From 1fa5d49380a412aa909446d2afeb6c3894e392c6 Mon Sep 17 00:00:00 2001 From: Michael Sparmann Date: Thu, 8 Oct 2009 20:56:51 +0000 Subject: Implemented iPod Nano 2G power_off() git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23014 a1c6a512-1295-4272-9138-f99709370657 --- .../target/arm/s5l8700/ipodnano2g/lcd-nano2g.c | 27 ++++++++++++++ .../target/arm/s5l8700/ipodnano2g/pmu-nano2g.c | 42 +++++++++++++++------- .../target/arm/s5l8700/ipodnano2g/pmu-target.h | 1 + .../target/arm/s5l8700/ipodnano2g/power-nano2g.c | 28 ++++++++++----- 4 files changed, 77 insertions(+), 21 deletions(-) (limited to 'firmware/target/arm/s5l8700') diff --git a/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c index 07a92a970d..76e35ead30 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c +++ b/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c @@ -35,6 +35,10 @@ /* LCD type 0 register defines */ #define R_ENTRY_MODE 0x03 +#define R_DISPLAY_CONTROL_1 0x07 +#define R_POWER_CONTROL_1 0x10 +#define R_POWER_CONTROL_2 0x12 +#define R_POWER_CONTROL_3 0x13 #define R_HORIZ_GRAM_ADDR_SET 0x20 #define R_VERT_GRAM_ADDR_SET 0x21 #define R_WRITE_DATA_TO_GRAM 0x22 @@ -46,6 +50,8 @@ /* LCD type 1 register defines */ +#define R_SLEEP_IN 0x10 +#define R_DISPLAY_OFF 0x28 #define R_COLUMN_ADDR_SET 0x2a #define R_ROW_ADDR_SET 0x2b #define R_MEMORY_WRITE 0x2c @@ -122,6 +128,27 @@ void lcd_set_flip(bool yesno) void lcd_off(void) { + if (lcd_type == 0) + { + s5l_lcd_write_cmd_data(R_DISPLAY_CONTROL_1, 0x232); + s5l_lcd_write_cmd_data(R_POWER_CONTROL_3, 0x1137); + s5l_lcd_write_cmd_data(R_DISPLAY_CONTROL_1, 0x201); + s5l_lcd_write_cmd_data(R_POWER_CONTROL_3, 0x137); + s5l_lcd_write_cmd_data(R_DISPLAY_CONTROL_1, 0x200); + s5l_lcd_write_cmd_data(R_POWER_CONTROL_1, 0x680); + s5l_lcd_write_cmd_data(R_POWER_CONTROL_2, 0x160); + s5l_lcd_write_cmd_data(R_POWER_CONTROL_3, 0x127); + s5l_lcd_write_cmd_data(R_POWER_CONTROL_1, 0x600); + } + else + { + s5l_lcd_write_cmd(R_DISPLAY_OFF); + s5l_lcd_write_data(0); + s5l_lcd_write_data(0); + s5l_lcd_write_cmd(R_SLEEP_IN); + s5l_lcd_write_data(0); + s5l_lcd_write_data(0); + } } void lcd_on(void) diff --git a/firmware/target/arm/s5l8700/ipodnano2g/pmu-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/pmu-nano2g.c index 7a6407e809..4dd295c21a 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/pmu-nano2g.c +++ b/firmware/target/arm/s5l8700/ipodnano2g/pmu-nano2g.c @@ -24,30 +24,30 @@ #include "i2c-s5l8700.h" static struct mutex pmu_adc_mutex; -int pmu_initialized; +int pmu_initialized = 0; -unsigned char pmu_read(int address) +void pmu_read_multiple(int address, int count, unsigned char* buffer) { - unsigned char tmp; - - i2c_read(0xe6, address, 1, &tmp); - - return tmp; + i2c_read(0xe6, address, count, buffer); } -void pmu_write(int address, unsigned char val) +void pmu_write_multiple(int address, int count, unsigned char* buffer) { - i2c_write(0xe6, address, 1, &val); + i2c_write(0xe6, address, count, buffer); } -void pmu_read_multiple(int address, int count, unsigned char* buffer) +unsigned char pmu_read(int address) { - i2c_read(0xe6, address, count, buffer); + unsigned char tmp; + + pmu_read_multiple(address, 1, &tmp); + + return tmp; } -void pmu_write_multiple(int address, int count, unsigned char* buffer) +void pmu_write(int address, unsigned char val) { - i2c_write(0xe6, address, count, buffer); + pmu_write_multiple(address, 1, &val); } void pmu_init(void) @@ -88,3 +88,19 @@ int pmu_read_battery_current(void) mutex_unlock(&pmu_adc_mutex); return milliamps; } + +void pmu_switch_power(int gate, int onoff) +{ + if (gate < 4) + { + unsigned char newval = pmu_read(0x3B) & ~(1 << (2 * gate)); + if (onoff) newval |= 1 << (2 * gate); + pmu_write(0x3B, newval); + } + else if (gate < 7) + { + unsigned char newval = pmu_read(0x3C) & ~(1 << (2 * (gate - 4))); + if (onoff) newval |= 1 << (2 * (gate - 4)); + pmu_write(0x3C, newval); + } +} \ No newline at end of file diff --git a/firmware/target/arm/s5l8700/ipodnano2g/pmu-target.h b/firmware/target/arm/s5l8700/ipodnano2g/pmu-target.h index 7ddfc631fc..43b0f54308 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/pmu-target.h +++ b/firmware/target/arm/s5l8700/ipodnano2g/pmu-target.h @@ -31,5 +31,6 @@ void pmu_write_multiple(int address, int count, unsigned char* buffer); int pmu_read_battery_voltage(void); int pmu_read_battery_current(void); void pmu_init(void); +void pmu_switch_power(int gate, int onoff); #endif diff --git a/firmware/target/arm/s5l8700/ipodnano2g/power-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/power-nano2g.c index fbd5157fb0..31f23ff9ff 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/power-nano2g.c +++ b/firmware/target/arm/s5l8700/ipodnano2g/power-nano2g.c @@ -26,20 +26,32 @@ #include "ftl-target.h" #include #include "panic.h" +#include "pmu-target.h" +#include "lcd.h" -/* Power handling for S5L8700 based Meizu players - - The M3 and M6 players appear to use the same pins for power, USB detection - and charging status. -*/ - void power_off(void) { if (ftl_sync() != 0) panicf("Failed to unmount flash!"); - /* TODO: Really power-off */ - panicf("Poweroff not implemented yet."); + pmu_write(0x2b, 0); /* Kill the backlight, instantly. */ + pmu_write(0x29, 0); + + lcd_off(); + + pmu_switch_power(0, 0); + pmu_switch_power(2, 0); + pmu_switch_power(3, 0); + pmu_switch_power(4, 0); + pmu_switch_power(6, 0); + pmu_switch_power(7, 0); + + pmu_write(0x36, pmu_read(0x36) & 0xF0); + pmu_write(0x34, pmu_read(0x34) & 0xF0); + pmu_write(0xD, pmu_read(0xD) | 0x40); + pmu_write(0xD, pmu_read(0xD) | 0x02); + pmu_write(0xC, 1); + while(1); } -- cgit v1.2.3