summaryrefslogtreecommitdiffstats
path: root/firmware/target/hosted/sonynwz/power-nwz.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/sonynwz/power-nwz.c')
-rw-r--r--firmware/target/hosted/sonynwz/power-nwz.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/firmware/target/hosted/sonynwz/power-nwz.c b/firmware/target/hosted/sonynwz/power-nwz.c
new file mode 100644
index 0000000000..a5b19d6ead
--- /dev/null
+++ b/firmware/target/hosted/sonynwz/power-nwz.c
@@ -0,0 +1,208 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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);
+}