rockbox/firmware/target/hosted/sonynwz/power-nwz.c
Amaury Pouly 1d121e8c08 Initial commit for the Sony NWZ linux port
SUPPORTED SERIES:
- NWZ-E450
- NWZ-E460
- NWZ-E470
- NWZ-E580
- NWZ-A10

NOTES:
- bootloader makefile convert an extra font to be installed alongside the bootloader
  since sysfont is way too small
- the toolsicon bitmap comes from the Oxygen iconset
- touchscreen driver is untested

TODO:
- implement audio routing driver (pcm is handled by pcm-alsa)
- fix playback: it crashes on illegal instruction in DEBUG builds
- find out why the browser starts at / instead of /contents
- implement radio support
- implement return to OF for usb handling
- calibrate battery curve (NB: of can report a battery level on a 0-5 scale but
  probabl don't want to use that ?)
- implement simulator build (we need a nice image of the player)
- figure out if we can detect jack removal

POTENTIAL TODOS:
- try to build a usb serial gadget and gdbserver

Change-Id: Ic77d71e0651355d47cc4e423a40fb64a60c69a80
2017-09-05 21:42:12 +02:00

208 lines
5 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2016 Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "system.h"
#include "power-nwz.h"
#include "button-target.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/reboot.h>
static int power_fd = -1; /* file descriptor */
void power_init(void)
{
power_fd = open(NWZ_POWER_DEV, O_RDWR);
}
void power_close(void)
{
close(power_fd);
}
int nwz_power_get_status(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_STATUS, &status) < 0)
return -1;
return status;
}
static int nwz_power_adval_to_mv(int adval, int ad_base)
{
if(adval == -1)
return -1;
/* the AD base corresponds to the millivolt value if adval was 255 */
return (adval * ad_base) / 255;
}
int nwz_power_get_vbus_adval(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_VBUS_ADVAL, &status) < 0)
return -1;
return status;
}
int nwz_power_get_vbus_voltage(void)
{
return nwz_power_adval_to_mv(nwz_power_get_vbus_adval(), NWZ_POWER_AD_BASE_VBUS);
}
int nwz_power_get_vbus_limit(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_VBUS_LIMIT, &status) < 0)
return -1;
return status;
}
int nwz_power_get_charge_switch(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_CHARGE_SWITCH, &status) < 0)
return -1;
return status;
}
int nwz_power_get_charge_current(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_CHARGE_CURRENT, &status) < 0)
return -1;
return status;
}
int nwz_power_get_battery_gauge(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_BAT_GAUGE, &status) < 0)
return -1;
return status;
}
int nwz_power_get_battery_adval(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_BAT_ADVAL, &status) < 0)
return -1;
return status;
}
int nwz_power_get_battery_voltage(void)
{
return nwz_power_adval_to_mv(nwz_power_get_battery_adval(), NWZ_POWER_AD_BASE_VBAT);
}
int nwz_power_get_vbat_adval(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_VBAT_ADVAL, &status) < 0)
return -1;
return status;
}
int nwz_power_get_vbat_voltage(void)
{
return nwz_power_adval_to_mv(nwz_power_get_vbat_adval(), NWZ_POWER_AD_BASE_VBAT);
}
int nwz_power_get_sample_count(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_SAMPLE_COUNT, &status) < 0)
return -1;
return status;
}
int nwz_power_get_vsys_adval(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_VSYS_ADVAL, &status) < 0)
return -1;
return status;
}
int nwz_power_get_vsys_voltage(void)
{
return nwz_power_adval_to_mv(nwz_power_get_vsys_adval(), NWZ_POWER_AD_BASE_VSYS);
}
int nwz_power_get_acc_charge_mode(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_GET_ACCESSARY_CHARGE_MODE, &status) < 0)
return -1;
return status;
}
int nwz_power_is_fully_charged(void)
{
int status;
if(ioctl(power_fd, NWZ_POWER_IS_FULLY_CHARGED, &status) < 0)
return -1;
return status;
}
static int write_string_to_file(const char *file, const char *msg)
{
int fd = open(file, O_WRONLY);
if(fd < 0)
return -1;
const int len = strlen(msg);
int res = write(fd, msg, len);
close(fd);
return res == len ? 0 : -1;
}
int do_nwz_power_suspend(void)
{
/* older devices use /proc/pm, while the new one use the standard sys file */
if(write_string_to_file("/proc/pm", "S3") == 0)
return 0;
return write_string_to_file("/sys/power/state", "mem");
}
int nwz_power_suspend(void)
{
int ret = do_nwz_power_suspend();
/* the button driver tracks button status using events, but the kernel does
* not generate an event if a key is changed during suspend, so make sure we
* reload as much information as possible */
nwz_button_reload_after_suspend();
return ret;
}
int nwz_power_shutdown(void)
{
sync(); /* man page advises to sync to avoid data loss */
return reboot(RB_POWER_OFF);
}
int nwz_power_restart(void)
{
sync(); /* man page advises to sync to avoid data loss */
return reboot(RB_AUTOBOOT);
}