From 285079138b0baa5cf03221f8abcdaaec8e35f112 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Mon, 27 Feb 2006 12:35:05 +0000 Subject: [PATCH] Patch #3060 from Andrew Scott - iPod mini button driver git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8857 a1c6a512-1295-4272-9138-f99709370657 --- bootloader/ipod.c | 4 ++ firmware/drivers/button.c | 89 ++++++++++++++++++++++++++++++++++- firmware/drivers/i2c-pp5020.c | 8 ++++ firmware/export/config.h | 2 +- firmware/system.c | 13 +++++ 5 files changed, 113 insertions(+), 3 deletions(-) diff --git a/bootloader/ipod.c b/bootloader/ipod.c index f62fa265a5..793253a0ca 100644 --- a/bootloader/ipod.c +++ b/bootloader/ipod.c @@ -193,7 +193,11 @@ static int key_pressed(void) unsigned char state; #if CONFIG_KEYPAD == IPOD_4G_PAD +#if defined(APPLE_IPODMINI) + state = GPIOA_INPUT_VAL & 0x3f; +#else state = opto_keypad_read(); +#endif if ((state & 0x4) == 0) return BUTTON_LEFT; if ((state & 0x10) == 0) return BUTTON_MENU; if ((state & 0x8) == 0) return BUTTON_PLAY; diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index d5855506fc..0b41fb10fe 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c @@ -87,7 +87,9 @@ static bool remote_button_hold_only(void); #if CONFIG_KEYPAD == IPOD_4G_PAD /* Variable to use for setting button status in interrupt handler */ int int_btn = BUTTON_NONE; +#endif +#if (CONFIG_KEYPAD == IPOD_4G_PAD) && (!defined(APPLE_IPODMINI)) static void opto_i2c_init(void) { int i, curr_value; @@ -240,7 +242,7 @@ void ipod_4g_button_int(void) CPU_HI_INT_EN = I2C_MASK; } #endif -#if CONFIG_KEYPAD == IPOD_3G_PAD +#if (CONFIG_KEYPAD == IPOD_3G_PAD) || (defined(APPLE_IPODMINI)) /** * * @@ -291,7 +293,68 @@ void handle_scroll_wheel(int new_scroll, int was_hold, int reverse) queue_post(&button_queue, wheel_keycode, NULL); prev_scroll = new_scroll; } +#endif +#if (CONFIG_KEYPAD == IPOD_4G_PAD) && (defined(APPLE_IPODMINI)) +static int ipod_mini_button_read(void) +{ + unsigned char source, wheel_source, state, wheel_state; + int btn = BUTTON_NONE; + /* + * we need some delay for mini, cause hold generates several interrupts, + * some of them delayed + */ + udelay(250); + + /* get source(s) of interupt */ + source = GPIOA_INT_STAT & 0x3f; + wheel_source = GPIOB_INT_STAT & 0x30; + + if (source == 0 && wheel_source == 0) { + return BUTTON_NONE; /* not for us */ + } + + /* get current keypad & wheel status */ + state = GPIOA_INPUT_VAL & 0x3f; + wheel_state = GPIOB_INPUT_VAL & 0x30; + + /* toggle interrupt level */ + GPIOA_INT_LEV = ~state; + GPIOB_INT_LEV = ~wheel_state; + + if (source & 0x1) + btn |= BUTTON_SELECT; + if (source & 0x2) + btn |= BUTTON_MENU; + if (source & 0x4) + btn |= BUTTON_PLAY; + if (source & 0x8) + btn |= BUTTON_RIGHT; + if (source & 0x10) + btn |= BUTTON_LEFT; + + if (wheel_source & 0x30) { + handle_scroll_wheel((wheel_state & 0x30) >> 4, 0, 1); + } + + /* ack any active interrupts */ + if (source) + GPIOA_INT_CLR = source; + if (wheel_source) + GPIOB_INT_CLR = wheel_source; + + return btn; +} + +void ipod_mini_button_int(void) +{ + CPU_HI_INT_CLR = GPIO_MASK; + int_btn = ipod_mini_button_read(); + //CPU_INT_EN = 0x40000000; + CPU_HI_INT_EN = GPIO_MASK; +} +#endif +#if CONFIG_KEYPAD == IPOD_3G_PAD static int ipod_3g_button_read(void) { unsigned char source, state; @@ -541,7 +604,7 @@ void button_init(void) /* nothing to initialize here */ #elif CONFIG_KEYPAD == GMINI100_PAD /* nothing to initialize here */ -#elif CONFIG_KEYPAD == IPOD_4G_PAD +#elif (CONFIG_KEYPAD == IPOD_4G_PAD) && (!defined(APPLE_IPODMINI)) opto_i2c_init(); /* hold button - enable as input */ GPIOA_ENABLE |= 0x20; @@ -551,9 +614,31 @@ void button_init(void) GPIOA_INT_CLR = GPIOA_INT_STAT & 0x20; /* enable interrupts */ GPIOA_INT_EN = 0x20; + /* unmask interrupt */ CPU_INT_EN = 0x40000000; CPU_HI_INT_EN = I2C_MASK; +#elif (CONFIG_KEYPAD == IPOD_4G_PAD) && (defined(APPLE_IPODMINI)) + /* iPod Mini G1 */ + /* buttons - enable as input */ + GPIOA_ENABLE |= 0x3f; + GPIOA_OUTPUT_EN &= ~0x3f; + /* scroll wheel- enable as input */ + GPIOB_ENABLE |= 0x30; /* port b 4,5 */ + GPIOB_OUTPUT_EN &= ~0x30; /* port b 4,5 */ + /* buttons - set interrupt levels */ + GPIOA_INT_LEV = ~(GPIOA_INPUT_VAL & 0x3f); + GPIOA_INT_CLR = GPIOA_INT_STAT & 0x3f; + /* scroll wheel - set interrupt levels */ + GPIOB_INT_LEV = ~(GPIOB_INPUT_VAL & 0x3f); + GPIOB_INT_CLR = GPIOB_INT_STAT & 0x3f; + /* enable interrupts */ + GPIOA_INT_EN = 0x3f; + GPIOB_INT_EN = 0x30; + /* unmask interrupt */ + CPU_INT_EN = 0x40000000; + CPU_HI_INT_EN = GPIO_MASK; + #elif CONFIG_KEYPAD == IPOD_3G_PAD GPIOA_INT_LEV = ~GPIOA_INPUT_VAL; GPIOA_INT_CLR = GPIOA_INT_STAT; diff --git a/firmware/drivers/i2c-pp5020.c b/firmware/drivers/i2c-pp5020.c index fccaffc571..9f26d3be6e 100644 --- a/firmware/drivers/i2c-pp5020.c +++ b/firmware/drivers/i2c-pp5020.c @@ -161,6 +161,14 @@ void i2c_init(void) { /* From ipodlinux */ +#if defined(APPLE_IPODMINI) + /* GPIO port C disable port 0x10 */ + GPIOC_ENABLE &= ~0x10; + + /* GPIO port C disable port 0x20 */ + GPIOC_ENABLE &= ~0x20; +#endif + outl(inl(0x6000600c) | 0x1000, 0x6000600c); /* enable 12 */ outl(inl(0x60006004) | 0x1000, 0x60006004); /* start reset 12 */ outl(inl(0x60006004) & ~0x1000, 0x60006004); /* end reset 12 */ diff --git a/firmware/export/config.h b/firmware/export/config.h index 1557accde5..20ca7aa5c6 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -123,7 +123,7 @@ /* CONFIG_RTC */ #define RTC_M41ST84W 1 /* Archos Recorder */ -#define RTC_PCF50605 2 /* iPod 3G and 4G*/ +#define RTC_PCF50605 2 /* iPod 3G, 4G & Mini */ #define RTC_PCF50606 3 /* iriver H300 */ #define RTC_S3C2440 4 diff --git a/firmware/system.c b/firmware/system.c index 79004f8284..fa07f6364e 100644 --- a/firmware/system.c +++ b/firmware/system.c @@ -1140,6 +1140,18 @@ unsigned int ipod_hw_rev; #ifndef BOOTLOADER extern void TIMER1(void); + +#if defined(APPLE_IPODMINI) +extern void ipod_mini_button_int(void); + +void irq(void) +{ + if (CPU_INT_STAT & TIMER1_MASK) + TIMER1(); + else if (CPU_HI_INT_STAT & GPIO_MASK) + ipod_mini_button_int(); +} +#else extern void ipod_4g_button_int(void); void irq(void) @@ -1150,6 +1162,7 @@ void irq(void) ipod_4g_button_int(); } #endif +#endif /* BOOTLOADER */ /* TODO: The following two function have been lifted straight from IPL, and hence have a lot of numeric addresses used straight. I'd like to use