summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootloader/ipod.c4
-rw-r--r--firmware/drivers/button.c89
-rw-r--r--firmware/drivers/i2c-pp5020.c8
-rw-r--r--firmware/export/config.h2
-rw-r--r--firmware/system.c13
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