diff options
author | Dave Chapman <dave@dchapman.com> | 2006-02-05 17:16:34 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2006-02-05 17:16:34 +0000 |
commit | 465596b1639393ef320decced442537133ab09e8 (patch) | |
tree | 79c88e59c7ab15e2dab33caf045835b5a118a2e9 | |
parent | d16a8b8845ed496e9375c5dfac6da2011c9eb362 (diff) | |
download | rockbox-465596b1639393ef320decced442537133ab09e8.tar.gz rockbox-465596b1639393ef320decced442537133ab09e8.zip |
More iPod 3G code from Seven Le Mesle
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8582 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/drivers/ata.c | 33 | ||||
-rw-r--r-- | firmware/drivers/button.c | 139 | ||||
-rw-r--r-- | firmware/drivers/i2c-pp5002.c | 168 | ||||
-rw-r--r-- | firmware/drivers/pcf50605.c | 4 | ||||
-rw-r--r-- | firmware/drivers/power.c | 8 | ||||
-rw-r--r-- | firmware/drivers/serial.c | 6 | ||||
-rw-r--r-- | firmware/drivers/wm8731l.c | 268 |
7 files changed, 610 insertions, 16 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 3c79c1be8f..a5fb78d6bd 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -71,13 +71,20 @@ | |||
71 | #define SET_REG(reg,val) reg = ((val) << 8) | 71 | #define SET_REG(reg,val) reg = ((val) << 8) |
72 | #define SET_16BITREG(reg,val) reg = (val) | 72 | #define SET_16BITREG(reg,val) reg = (val) |
73 | 73 | ||
74 | #elif CONFIG_CPU == PP5020 | 74 | #elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) |
75 | 75 | ||
76 | /* don't use sh7034 assembler routines */ | 76 | /* don't use sh7034 assembler routines */ |
77 | #define PREFER_C_READING | 77 | #define PREFER_C_READING |
78 | #define PREFER_C_WRITING | 78 | #define PREFER_C_WRITING |
79 | 79 | ||
80 | #if (CONFIG_CPU == PP5002) | ||
81 | #define ATA_IOBASE 0xc00031e0 | ||
82 | #define ATA_CONTROL (*((volatile unsigned char*)(0xc00033f8))) | ||
83 | #elif (CONFIG_CPU == PP5020) | ||
80 | #define ATA_IOBASE 0xc30001e0 | 84 | #define ATA_IOBASE 0xc30001e0 |
85 | #define ATA_CONTROL (*((volatile unsigned char*)(0xc30003f8))) | ||
86 | #endif | ||
87 | |||
81 | #define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE))) | 88 | #define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE))) |
82 | #define ATA_ERROR (*((volatile unsigned char*)(ATA_IOBASE + 0x04))) | 89 | #define ATA_ERROR (*((volatile unsigned char*)(ATA_IOBASE + 0x04))) |
83 | #define ATA_NSECTOR (*((volatile unsigned char*)(ATA_IOBASE + 0x08))) | 90 | #define ATA_NSECTOR (*((volatile unsigned char*)(ATA_IOBASE + 0x08))) |
@@ -86,7 +93,6 @@ | |||
86 | #define ATA_HCYL (*((volatile unsigned char*)(ATA_IOBASE + 0x14))) | 93 | #define ATA_HCYL (*((volatile unsigned char*)(ATA_IOBASE + 0x14))) |
87 | #define ATA_SELECT (*((volatile unsigned char*)(ATA_IOBASE + 0x18))) | 94 | #define ATA_SELECT (*((volatile unsigned char*)(ATA_IOBASE + 0x18))) |
88 | #define ATA_COMMAND (*((volatile unsigned char*)(ATA_IOBASE + 0x1c))) | 95 | #define ATA_COMMAND (*((volatile unsigned char*)(ATA_IOBASE + 0x1c))) |
89 | #define ATA_CONTROL (*((volatile unsigned char*)(0xc30003f8))) | ||
90 | 96 | ||
91 | #define STATUS_BSY 0x80 | 97 | #define STATUS_BSY 0x80 |
92 | #define STATUS_RDY 0x40 | 98 | #define STATUS_RDY 0x40 |
@@ -928,6 +934,11 @@ extern void ata_flush(void) | |||
928 | 934 | ||
929 | static int check_registers(void) | 935 | static int check_registers(void) |
930 | { | 936 | { |
937 | #if (CONFIG_CPU == PP5002) | ||
938 | /* This fails on the PP5002, but the ATA driver still works. This | ||
939 | needs more investigation. */ | ||
940 | return 0; | ||
941 | #else | ||
931 | int i; | 942 | int i; |
932 | if ( ATA_STATUS & STATUS_BSY ) | 943 | if ( ATA_STATUS & STATUS_BSY ) |
933 | return -1; | 944 | return -1; |
@@ -939,13 +950,14 @@ static int check_registers(void) | |||
939 | SET_REG(ATA_HCYL, WRITE_PATTERN4); | 950 | SET_REG(ATA_HCYL, WRITE_PATTERN4); |
940 | 951 | ||
941 | if ((ATA_NSECTOR == READ_PATTERN1) && | 952 | if ((ATA_NSECTOR == READ_PATTERN1) && |
942 | (ATA_SECTOR == READ_PATTERN2) && | 953 | (ATA_SECTOR == READ_PATTERN2) && |
943 | (ATA_LCYL == READ_PATTERN3) && | 954 | (ATA_LCYL == READ_PATTERN3) && |
944 | (ATA_HCYL == READ_PATTERN4)) | 955 | (ATA_HCYL == READ_PATTERN4)) |
945 | return 0; | 956 | return 0; |
946 | } | 957 | } |
947 | 958 | ||
948 | return -2; | 959 | return -2; |
960 | #endif | ||
949 | } | 961 | } |
950 | 962 | ||
951 | static int freeze_lock(void) | 963 | static int freeze_lock(void) |
@@ -1254,7 +1266,7 @@ void ata_enable(bool on) | |||
1254 | (void)on; | 1266 | (void)on; |
1255 | #elif CONFIG_CPU == TCC730 | 1267 | #elif CONFIG_CPU == TCC730 |
1256 | 1268 | ||
1257 | #elif CONFIG_CPU == PP5020 | 1269 | #elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) |
1258 | /* TODO: Implement ata_enable() */ | 1270 | /* TODO: Implement ata_enable() */ |
1259 | (void)on; | 1271 | (void)on; |
1260 | #endif | 1272 | #endif |
@@ -1410,7 +1422,7 @@ int ata_init(void) | |||
1410 | #elif defined(IAUDIO_X5) | 1422 | #elif defined(IAUDIO_X5) |
1411 | /* X5 TODO */ | 1423 | /* X5 TODO */ |
1412 | bool coldstart = true; | 1424 | bool coldstart = true; |
1413 | #elif CONFIG_CPU == PP5020 | 1425 | #elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) |
1414 | bool coldstart = false; | 1426 | bool coldstart = false; |
1415 | /* TODO: Implement coldstart variable */ | 1427 | /* TODO: Implement coldstart variable */ |
1416 | #else | 1428 | #else |
@@ -1440,6 +1452,13 @@ int ata_init(void) | |||
1440 | or_l(0x00080000, &GPIO_FUNCTION); | 1452 | or_l(0x00080000, &GPIO_FUNCTION); |
1441 | 1453 | ||
1442 | /* FYI: The IDECONFIGx registers are set by set_cpu_frequency() */ | 1454 | /* FYI: The IDECONFIGx registers are set by set_cpu_frequency() */ |
1455 | #elif CONFIG_CPU == PP5002 | ||
1456 | /* From ipod-ide.c:ipod_ide_register() */ | ||
1457 | outl(inl(0xc0003024) | (1 << 7), 0xc0003024); | ||
1458 | outl(inl(0xc0003024) & ~(1<<2), 0xc0003024); | ||
1459 | |||
1460 | outl(0x10, 0xc0003000); | ||
1461 | outl(0x80002150, 0xc0003004); | ||
1443 | #elif CONFIG_CPU == PP5020 | 1462 | #elif CONFIG_CPU == PP5020 |
1444 | /* From ipod-ide.c:ipod_ide_register() */ | 1463 | /* From ipod-ide.c:ipod_ide_register() */ |
1445 | outl(inl(0xc3000028) | (1 << 5), 0xc3000028); | 1464 | outl(inl(0xc3000028) | (1 << 5), 0xc3000028); |
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 654852c516..5098cbe556 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c | |||
@@ -61,7 +61,8 @@ static bool flipped; /* buttons can be flipped to match the LCD flip */ | |||
61 | #define REPEAT_INTERVAL_FINISH 5 | 61 | #define REPEAT_INTERVAL_FINISH 5 |
62 | 62 | ||
63 | /* the power-off button and number of repeated keys before shutting off */ | 63 | /* the power-off button and number of repeated keys before shutting off */ |
64 | #if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) | 64 | #if (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) ||\ |
65 | (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) | ||
65 | #define POWEROFF_BUTTON BUTTON_PLAY | 66 | #define POWEROFF_BUTTON BUTTON_PLAY |
66 | #define POWEROFF_COUNT 40 | 67 | #define POWEROFF_COUNT 40 |
67 | #else | 68 | #else |
@@ -220,7 +221,132 @@ void ipod_4g_button_int(void) | |||
220 | CPU_HI_INT_EN = I2C_MASK; | 221 | CPU_HI_INT_EN = I2C_MASK; |
221 | } | 222 | } |
222 | #endif | 223 | #endif |
224 | #if CONFIG_KEYPAD == IPOD_3G_PAD | ||
225 | /* Variable to use for setting button status in interrupt handler */ | ||
226 | int int_btn = BUTTON_NONE; | ||
223 | 227 | ||
228 | /** | ||
229 | * | ||
230 | * | ||
231 | */ | ||
232 | void handle_scroll_wheel(int new_scroll, int was_hold, int reverse) | ||
233 | { | ||
234 | int wheel_keycode = BUTTON_NONE; | ||
235 | static int prev_scroll = -1; | ||
236 | static int scroll_state[4][4] = { | ||
237 | {0, 1, -1, 0}, | ||
238 | {-1, 0, 0, 1}, | ||
239 | {1, 0, 0, -1}, | ||
240 | {0, -1, 1, 0} | ||
241 | }; | ||
242 | |||
243 | if ( prev_scroll == -1 ) { | ||
244 | prev_scroll = new_scroll; | ||
245 | } | ||
246 | else if (!was_hold) { | ||
247 | switch (scroll_state[prev_scroll][new_scroll]) { | ||
248 | case 1: | ||
249 | if (reverse) { | ||
250 | /* 'r' keypress */ | ||
251 | wheel_keycode = BUTTON_SCROLL_FWD; | ||
252 | } | ||
253 | else { | ||
254 | /* 'l' keypress */ | ||
255 | wheel_keycode = BUTTON_SCROLL_BACK; | ||
256 | } | ||
257 | break; | ||
258 | case -1: | ||
259 | if (reverse) { | ||
260 | /* 'l' keypress */ | ||
261 | wheel_keycode = BUTTON_SCROLL_BACK; | ||
262 | } | ||
263 | else { | ||
264 | /* 'r' keypress */ | ||
265 | wheel_keycode = BUTTON_SCROLL_FWD; | ||
266 | break; | ||
267 | default: | ||
268 | /* only happens if we get out of sync */ | ||
269 | break; | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | if (wheel_keycode != BUTTON_NONE) | ||
274 | queue_post(&button_queue, wheel_keycode, NULL); | ||
275 | prev_scroll = new_scroll; | ||
276 | } | ||
277 | |||
278 | static int ipod_3g_button_read(void) | ||
279 | { | ||
280 | unsigned char source, state; | ||
281 | static int was_hold = 0; | ||
282 | int btn = BUTTON_NONE; | ||
283 | /* | ||
284 | * we need some delay for g3, cause hold generates several interrupts, | ||
285 | * some of them delayed | ||
286 | */ | ||
287 | udelay(250); | ||
288 | |||
289 | /* get source of interupts */ | ||
290 | source = inb(0xcf000040); | ||
291 | if (source) { | ||
292 | |||
293 | /* get current keypad status */ | ||
294 | state = inb(0xcf000030); | ||
295 | outb(~state, 0xcf000060); | ||
296 | |||
297 | if (was_hold && source == 0x40 && state == 0xbf) { | ||
298 | /* ack any active interrupts */ | ||
299 | outb(source, 0xcf000070); | ||
300 | return BUTTON_NONE; | ||
301 | } | ||
302 | was_hold = 0; | ||
303 | |||
304 | |||
305 | if ( source & 0x20 ) { | ||
306 | /* 3g hold switch is active low */ | ||
307 | btn |= BUTTON_HOLD; | ||
308 | was_hold = 1; | ||
309 | /* hold switch on 3g causes all outputs to go low */ | ||
310 | /* we shouldn't interpret these as key presses */ | ||
311 | goto done; | ||
312 | } | ||
313 | if (source & 0x1) { | ||
314 | btn |= BUTTON_RIGHT; | ||
315 | } | ||
316 | if (source & 0x2) { | ||
317 | btn |= BUTTON_SELECT; | ||
318 | } | ||
319 | if (source & 0x4) { | ||
320 | btn |= BUTTON_PLAY; | ||
321 | } | ||
322 | if (source & 0x8) { | ||
323 | btn |= BUTTON_LEFT; | ||
324 | } | ||
325 | if (source & 0x10) { | ||
326 | btn |= BUTTON_MENU; | ||
327 | } | ||
328 | |||
329 | if (source & 0xc0) { | ||
330 | handle_scroll_wheel((state & 0xc0) >> 6, was_hold, 0); | ||
331 | } | ||
332 | done: | ||
333 | |||
334 | /* ack any active interrupts */ | ||
335 | outb(source, 0xcf000070); | ||
336 | } | ||
337 | return btn; | ||
338 | } | ||
339 | |||
340 | void ipod_3g_button_int(void) | ||
341 | { | ||
342 | /** | ||
343 | * Theire is other things to do but for now ... | ||
344 | * TODO: implement this function in a better way | ||
345 | **/ | ||
346 | int_btn = ipod_3g_button_read(); | ||
347 | |||
348 | } | ||
349 | #endif | ||
224 | static void button_tick(void) | 350 | static void button_tick(void) |
225 | { | 351 | { |
226 | static int tick = 0; | 352 | static int tick = 0; |
@@ -404,8 +530,13 @@ void button_init(void) | |||
404 | GPIOA_INT_EN = 0x20; | 530 | GPIOA_INT_EN = 0x20; |
405 | CPU_INT_EN = 0x40000000; | 531 | CPU_INT_EN = 0x40000000; |
406 | CPU_HI_INT_EN = I2C_MASK; | 532 | CPU_HI_INT_EN = I2C_MASK; |
407 | #endif /* CONFIG_KEYPAD */ | ||
408 | 533 | ||
534 | #elif CONFIG_KEYPAD == IPOD_3G_PAD | ||
535 | outb(~inb(GPIOA_INPUT_VAL), GPIOA_INT_LEV); | ||
536 | outb(inb(GPIOA_INT_STAT), GPIOA_INT_CLR); | ||
537 | outb(0xff, GPIOA_INT_EN); | ||
538 | |||
539 | #endif /* CONFIG_KEYPAD */ | ||
409 | queue_init(&button_queue); | 540 | queue_init(&button_queue); |
410 | button_read(); | 541 | button_read(); |
411 | lastbtn = button_read(); | 542 | lastbtn = button_read(); |
@@ -418,7 +549,7 @@ void button_init(void) | |||
418 | } | 549 | } |
419 | 550 | ||
420 | #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ | 551 | #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ |
421 | #if (CONFIG_KEYPAD != IPOD_4G_PAD) | 552 | #if (CONFIG_KEYPAD != IPOD_3G_PAD) && (CONFIG_KEYPAD != IPOD_4G_PAD) |
422 | /* | 553 | /* |
423 | * helper function to swap UP/DOWN, LEFT/RIGHT (and F1/F3 for Recorder) | 554 | * helper function to swap UP/DOWN, LEFT/RIGHT (and F1/F3 for Recorder) |
424 | */ | 555 | */ |
@@ -883,7 +1014,7 @@ static int button_read(void) | |||
883 | if (data & 0x01) | 1014 | if (data & 0x01) |
884 | btn |= BUTTON_ON; | 1015 | btn |= BUTTON_ON; |
885 | 1016 | ||
886 | #elif CONFIG_KEYPAD == IPOD_4G_PAD | 1017 | #elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) |
887 | (void)data; | 1018 | (void)data; |
888 | /* The int_btn variable is set in the button interrupt handler */ | 1019 | /* The int_btn variable is set in the button interrupt handler */ |
889 | btn = int_btn; | 1020 | btn = int_btn; |
diff --git a/firmware/drivers/i2c-pp5002.c b/firmware/drivers/i2c-pp5002.c new file mode 100644 index 0000000000..dc26d8a5d9 --- /dev/null +++ b/firmware/drivers/i2c-pp5002.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * PP5002 I2C driver | ||
11 | * | ||
12 | * Based on code from the ipodlinux project - http://ipodlinux.org/ | ||
13 | * Adapted for Rockbox in January 2006 | ||
14 | * | ||
15 | * Original file: linux/arch/armnommu/mach-ipod/hardware.c | ||
16 | * | ||
17 | * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) | ||
18 | * | ||
19 | * All files in this archive are subject to the GNU General Public License. | ||
20 | * See the file COPYING in the source tree root for full license agreement. | ||
21 | * | ||
22 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
23 | * KIND, either express or implied. | ||
24 | * | ||
25 | ****************************************************************************/ | ||
26 | |||
27 | #include "cpu.h" | ||
28 | #include "kernel.h" | ||
29 | #include "logf.h" | ||
30 | #include "system.h" | ||
31 | #include "i2c-pp5002.h" | ||
32 | |||
33 | /* Local functions definitions */ | ||
34 | |||
35 | #define IPOD_I2C_BASE 0xc0008000 | ||
36 | #define IPOD_I2C_CTRL (IPOD_I2C_BASE+0x00) | ||
37 | #define IPOD_I2C_ADDR (IPOD_I2C_BASE+0x04) | ||
38 | #define IPOD_I2C_DATA0 (IPOD_I2C_BASE+0x0c) | ||
39 | #define IPOD_I2C_DATA1 (IPOD_I2C_BASE+0x10) | ||
40 | #define IPOD_I2C_DATA2 (IPOD_I2C_BASE+0x14) | ||
41 | #define IPOD_I2C_DATA3 (IPOD_I2C_BASE+0x18) | ||
42 | #define IPOD_I2C_STATUS (IPOD_I2C_BASE+0x1c) | ||
43 | |||
44 | /* IPOD_I2C_CTRL bit definitions */ | ||
45 | #define IPOD_I2C_SEND 0x80 | ||
46 | |||
47 | /* IPOD_I2C_STATUS bit definitions */ | ||
48 | #define IPOD_I2C_BUSY (1<<6) | ||
49 | |||
50 | #define POLL_TIMEOUT (HZ) | ||
51 | |||
52 | static int ipod_i2c_wait_not_busy(void) | ||
53 | { | ||
54 | unsigned long timeout; | ||
55 | timeout = current_tick + POLL_TIMEOUT; | ||
56 | while (TIME_BEFORE(current_tick, timeout)) { | ||
57 | if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) { | ||
58 | return 0; | ||
59 | } | ||
60 | yield(); | ||
61 | } | ||
62 | |||
63 | return -1; | ||
64 | } | ||
65 | |||
66 | |||
67 | /* Public functions */ | ||
68 | |||
69 | int ipod_i2c_read_byte(unsigned int addr, unsigned int *data) | ||
70 | { | ||
71 | if (ipod_i2c_wait_not_busy() < 0) | ||
72 | { | ||
73 | return -1; | ||
74 | } | ||
75 | |||
76 | /* clear top 15 bits, left shift 1, or in 0x1 for a read */ | ||
77 | outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR); | ||
78 | |||
79 | outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL); | ||
80 | |||
81 | outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); | ||
82 | |||
83 | if (ipod_i2c_wait_not_busy() < 0) | ||
84 | { | ||
85 | return -1; | ||
86 | } | ||
87 | |||
88 | if (data) | ||
89 | { | ||
90 | *data = inb(IPOD_I2C_DATA0); | ||
91 | } | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data) | ||
97 | { | ||
98 | int data_addr; | ||
99 | unsigned int i; | ||
100 | |||
101 | if (len < 1 || len > 4) | ||
102 | { | ||
103 | return -1; | ||
104 | } | ||
105 | |||
106 | if (ipod_i2c_wait_not_busy() < 0) | ||
107 | { | ||
108 | return -2; | ||
109 | } | ||
110 | |||
111 | /* clear top 15 bits, left shift 1 */ | ||
112 | outb((addr << 17) >> 16, IPOD_I2C_ADDR); | ||
113 | |||
114 | outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL); | ||
115 | |||
116 | data_addr = IPOD_I2C_DATA0; | ||
117 | for ( i = 0; i < len; i++ ) | ||
118 | { | ||
119 | outb(*data++, data_addr); | ||
120 | data_addr += 4; | ||
121 | } | ||
122 | |||
123 | outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL); | ||
124 | |||
125 | outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); | ||
126 | |||
127 | return 0x0; | ||
128 | } | ||
129 | |||
130 | int ipod_i2c_send_byte(unsigned int addr, int data0) | ||
131 | { | ||
132 | unsigned char data[1]; | ||
133 | |||
134 | data[0] = data0; | ||
135 | |||
136 | return ipod_i2c_send_bytes(addr, 1, data); | ||
137 | } | ||
138 | |||
139 | |||
140 | int i2c_readbyte(unsigned int dev_addr, int addr) | ||
141 | { | ||
142 | int data; | ||
143 | |||
144 | ipod_i2c_send_byte(dev_addr, addr); | ||
145 | ipod_i2c_read_byte(dev_addr, &data); | ||
146 | |||
147 | return data; | ||
148 | } | ||
149 | |||
150 | int ipod_i2c_send(unsigned int addr, int data0, int data1) | ||
151 | { | ||
152 | unsigned char data[2]; | ||
153 | |||
154 | data[0] = data0; | ||
155 | data[1] = data1; | ||
156 | |||
157 | return ipod_i2c_send_bytes(addr, 2, data); | ||
158 | } | ||
159 | |||
160 | void i2c_init(void) | ||
161 | { | ||
162 | /* From ipodlinux */ | ||
163 | |||
164 | outl(inl(0xcf005000) | 0x2, 0xcf005000); | ||
165 | |||
166 | outl(inl(0xcf005030) | (1<<8), 0xcf005030); | ||
167 | outl(inl(0xcf005030) & ~(1<<8), 0xcf005030); | ||
168 | } | ||
diff --git a/firmware/drivers/pcf50605.c b/firmware/drivers/pcf50605.c index d205f89882..122ba6ee38 100644 --- a/firmware/drivers/pcf50605.c +++ b/firmware/drivers/pcf50605.c | |||
@@ -24,7 +24,11 @@ | |||
24 | * | 24 | * |
25 | ****************************************************************************/ | 25 | ****************************************************************************/ |
26 | #include "config.h" | 26 | #include "config.h" |
27 | #if CONFIG_I2C == I2C_PP5020 | ||
27 | #include "i2c-pp5020.h" | 28 | #include "i2c-pp5020.h" |
29 | #elif CONFIG_I2C == I2C_PP5002 | ||
30 | #include "i2c-pp5002.h" | ||
31 | #endif | ||
28 | #include "rtc.h" | 32 | #include "rtc.h" |
29 | 33 | ||
30 | #define OOCS 0x01 | 34 | #define OOCS 0x01 |
diff --git a/firmware/drivers/power.c b/firmware/drivers/power.c index e91d8a25cc..2150040dd6 100644 --- a/firmware/drivers/power.c +++ b/firmware/drivers/power.c | |||
@@ -84,7 +84,7 @@ void power_init(void) | |||
84 | pcf50606_init(); | 84 | pcf50606_init(); |
85 | #endif | 85 | #endif |
86 | #endif | 86 | #endif |
87 | #elif CONFIG_CPU == PP5020 | 87 | #elif CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 |
88 | /* TODO: Implement power_init() */ | 88 | /* TODO: Implement power_init() */ |
89 | #else | 89 | #else |
90 | #ifdef HAVE_POWEROFF_ON_PB5 | 90 | #ifdef HAVE_POWEROFF_ON_PB5 |
@@ -181,7 +181,7 @@ void ide_power_enable(bool on) | |||
181 | or_l(0x80000000, &GPIO_OUT); | 181 | or_l(0x80000000, &GPIO_OUT); |
182 | #elif defined(IAUDIO_X5) | 182 | #elif defined(IAUDIO_X5) |
183 | /* X5 TODO */ | 183 | /* X5 TODO */ |
184 | #elif CONFIG_CPU == PP5020 | 184 | #elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) |
185 | /* We do nothing on the iPod */ | 185 | /* We do nothing on the iPod */ |
186 | #elif defined(GMINI_ARCH) | 186 | #elif defined(GMINI_ARCH) |
187 | if(on) | 187 | if(on) |
@@ -237,7 +237,7 @@ bool ide_powered(void) | |||
237 | return (GPIO_OUT & 0x80000000)?false:true; | 237 | return (GPIO_OUT & 0x80000000)?false:true; |
238 | #elif defined(IAUDIO_X5) | 238 | #elif defined(IAUDIO_X5) |
239 | return false; /* X5 TODO */ | 239 | return false; /* X5 TODO */ |
240 | #elif CONFIG_CPU == PP5020 | 240 | #elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) |
241 | /* pretend we are always powered - we don't turn it off on the ipod */ | 241 | /* pretend we are always powered - we don't turn it off on the ipod */ |
242 | return true; | 242 | return true; |
243 | #elif defined(GMINI_ARCH) | 243 | #elif defined(GMINI_ARCH) |
@@ -273,7 +273,7 @@ void power_off(void) | |||
273 | and_l(~0x00080000, &GPIO1_OUT); | 273 | and_l(~0x00080000, &GPIO1_OUT); |
274 | #elif defined(IAUDIO_X5) | 274 | #elif defined(IAUDIO_X5) |
275 | and_l(~0x00000008, &GPIO_OUT); | 275 | and_l(~0x00000008, &GPIO_OUT); |
276 | #elif CONFIG_CPU == PP5020 | 276 | #elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5002) |
277 | #ifndef BOOTLOADER | 277 | #ifndef BOOTLOADER |
278 | /* We don't turn off the ipod, we put it in a deep sleep */ | 278 | /* We don't turn off the ipod, we put it in a deep sleep */ |
279 | pcf50605_standby_mode(); | 279 | pcf50605_standby_mode(); |
diff --git a/firmware/drivers/serial.c b/firmware/drivers/serial.c index b491b13abb..8479da52f8 100644 --- a/firmware/drivers/serial.c +++ b/firmware/drivers/serial.c | |||
@@ -27,7 +27,11 @@ | |||
27 | #include "lcd.h" | 27 | #include "lcd.h" |
28 | #include "serial.h" | 28 | #include "serial.h" |
29 | 29 | ||
30 | #if (CONFIG_CPU != MCF5249) && (CONFIG_CPU != TCC730) && (CONFIG_CPU != PP5020) && (CONFIG_CPU != PNX0101) && (CONFIG_CPU != MCF5250) | 30 | |
31 | #if (CONFIG_CPU != MCF5249) && (CONFIG_CPU != TCC730) && \ | ||
32 | (CONFIG_CPU != PP5020) && (CONFIG_CPU != PNX0101) && \ | ||
33 | (CONFIG_CPU != PP5002) && (CONFIG_CPU != MCF5250) | ||
34 | |||
31 | /* FIX: this doesn't work on iRiver or Gmini or iPod yet */ | 35 | /* FIX: this doesn't work on iRiver or Gmini or iPod yet */ |
32 | /* iFP7xx has no remote */ | 36 | /* iFP7xx has no remote */ |
33 | 37 | ||
diff --git a/firmware/drivers/wm8731l.c b/firmware/drivers/wm8731l.c new file mode 100644 index 0000000000..d49e8f4476 --- /dev/null +++ b/firmware/drivers/wm8731l.c | |||
@@ -0,0 +1,268 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Driver for WM8731L audio codec | ||
11 | * | ||
12 | * Based on code from the ipodlinux project - http://ipodlinux.org/ | ||
13 | * Adapted for Rockbox in January 2006 | ||
14 | * | ||
15 | * Original file: linux/arch/armnommu/mach-ipod/audio.c | ||
16 | * | ||
17 | * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) | ||
18 | * | ||
19 | * All files in this archive are subject to the GNU General Public License. | ||
20 | * See the file COPYING in the source tree root for full license agreement. | ||
21 | * | ||
22 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
23 | * KIND, either express or implied. | ||
24 | * | ||
25 | ****************************************************************************/ | ||
26 | #include "lcd.h" | ||
27 | #include "cpu.h" | ||
28 | #include "kernel.h" | ||
29 | #include "thread.h" | ||
30 | #include "power.h" | ||
31 | #include "debug.h" | ||
32 | #include "system.h" | ||
33 | #include "sprintf.h" | ||
34 | #include "button.h" | ||
35 | #include "string.h" | ||
36 | #include "file.h" | ||
37 | #include "buffer.h" | ||
38 | #include "audio.h" | ||
39 | |||
40 | #include "i2c-pp5002.h" | ||
41 | #include "wm8731l.h" | ||
42 | #include "pcf50605.h" | ||
43 | |||
44 | void wm8731l_reset(void); | ||
45 | |||
46 | #define IPOD_PCM_LEVEL 0x65 /* -6dB */ | ||
47 | |||
48 | #define RESET (0x0f<<1) | ||
49 | #define PWRMGMT1 (0x19<<1) | ||
50 | #define PWRMGMT2 (0x1a<<1) | ||
51 | #define AINTFCE (0x07<<1) | ||
52 | #define LOUT1VOL (0x02<<1) | ||
53 | #define ROUT1VOL (0x03<<1) | ||
54 | #define LOUT2VOL (0x28<<1) | ||
55 | #define ROUT2VOL (0x29<<1) | ||
56 | |||
57 | int wm8731l_mute(int mute) | ||
58 | { | ||
59 | if (mute) | ||
60 | { | ||
61 | /* Set DACMU = 1 to soft-mute the audio DACs. */ | ||
62 | ipod_i2c_send(0x1a, 0xa, 0x8); | ||
63 | } else { | ||
64 | /* Set DACMU = 0 to soft-un-mute the audio DACs. */ | ||
65 | ipod_i2c_send(0x1a, 0xa, 0x0); | ||
66 | } | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | /** From ipodLinux **/ | ||
71 | static void codec_set_active(int active) | ||
72 | { | ||
73 | /* set active to 0x0 or 0x1 */ | ||
74 | if (active) { | ||
75 | ipod_i2c_send(0x1a, 0x12, 0x01); | ||
76 | } else { | ||
77 | ipod_i2c_send(0x1a, 0x12, 0x00); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit | ||
83 | */ | ||
84 | static void i2s_reset(void) | ||
85 | { | ||
86 | /* I2S device reset */ | ||
87 | outl(inl(0xcf005030) | 0x80, 0xcf005030); | ||
88 | outl(inl(0xcf005030) & ~0x80, 0xcf005030); | ||
89 | |||
90 | /* I2S controller enable */ | ||
91 | outl(inl(0xc0002500) | 0x1, 0xc0002500); | ||
92 | |||
93 | /* BIT.FORMAT [11:10] = I2S (default) */ | ||
94 | /* BIT.SIZE [9:8] = 24bit */ | ||
95 | /* FIFO.FORMAT = 24 bit LSB */ | ||
96 | |||
97 | /* reset DAC and ADC fifo */ | ||
98 | outl(inl(0xc000251c) | 0x30000, 0xc000251c); | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * Initialise the WM8975 for playback via headphone and line out. | ||
103 | * Note, I'm using the WM8750 datasheet as its apparently close. | ||
104 | */ | ||
105 | int wm8731l_init(void) { | ||
106 | /* reset I2C */ | ||
107 | i2c_init(); | ||
108 | |||
109 | /* device reset */ | ||
110 | outl(inl(0xcf005030) | 0x80, 0xcf005030); | ||
111 | outl(inl(0xcf005030) & ~0x80, 0xcf005030); | ||
112 | |||
113 | /* device enable */ | ||
114 | outl(inl(0xcf005000) | 0x80, 0xcf005000); | ||
115 | |||
116 | /* GPIO D06 enable for output */ | ||
117 | outl(inl(0xcf00000c) | 0x40, 0xcf00000c); | ||
118 | outl(inl(0xcf00001c) & ~0x40, 0xcf00001c); | ||
119 | /* bits 11,10 == 01 */ | ||
120 | outl(inl(0xcf004040) | 0x400, 0xcf004040); | ||
121 | outl(inl(0xcf004040) & ~0x800, 0xcf004040); | ||
122 | |||
123 | outl(inl(0xcf004048) & ~0x1, 0xcf004048); | ||
124 | |||
125 | outl(inl(0xcf000004) & ~0xf, 0xcf000004); | ||
126 | outl(inl(0xcf004044) & ~0xf, 0xcf004044); | ||
127 | |||
128 | /* C03 = 0 */ | ||
129 | outl(inl(0xcf000008) | 0x8, 0xcf000008); | ||
130 | outl(inl(0xcf000018) | 0x8, 0xcf000018); | ||
131 | outl(inl(0xcf000028) & ~0x8, 0xcf000028); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | /* Silently enable / disable audio output */ | ||
137 | void wm8731l_enable_output(bool enable) | ||
138 | { | ||
139 | if (enable) | ||
140 | { | ||
141 | /* reset the I2S controller into known state */ | ||
142 | i2s_reset(); | ||
143 | |||
144 | ipod_i2c_send(0x1a, 0x1e, 0x0); /*Reset*/ | ||
145 | |||
146 | codec_set_active(0x0); | ||
147 | |||
148 | /* DACSEL=1 */ | ||
149 | /* BYPASS=1 */ | ||
150 | ipod_i2c_send(0x1a, 0x8, 0x18); | ||
151 | |||
152 | /* set power register to POWEROFF=0 on OUTPD=0, DACPD=0 */ | ||
153 | ipod_i2c_send(0x1a, 0xc, 0x67); | ||
154 | |||
155 | /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */ | ||
156 | /* IWL=00(16 bit) FORMAT=10(I2S format) */ | ||
157 | ipod_i2c_send(0x1a, 0xe, 0x42); | ||
158 | |||
159 | wm8731l_set_sample_rate(WM8731L_44100HZ); | ||
160 | |||
161 | /* set the volume to -6dB */ | ||
162 | ipod_i2c_send(0x1a, 0x4, IPOD_PCM_LEVEL); | ||
163 | ipod_i2c_send(0x1a, 0x6 | 0x1, IPOD_PCM_LEVEL); | ||
164 | |||
165 | /* ACTIVE=1 */ | ||
166 | codec_set_active(1); | ||
167 | |||
168 | /* 5. Set DACMU = 0 to soft-un-mute the audio DACs. */ | ||
169 | ipod_i2c_send(0x1a, 0xa, 0x0); | ||
170 | |||
171 | wm8731l_mute(0); | ||
172 | } else { | ||
173 | wm8731l_mute(1); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | int wm8731l_set_master_vol(int vol_l, int vol_r) | ||
178 | { | ||
179 | /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ | ||
180 | /* 1111111 == +6dB */ | ||
181 | /* 1111001 == 0dB */ | ||
182 | /* 0110000 == -73dB */ | ||
183 | /* 0101111 == mute (0x2f) */ | ||
184 | if (vol_l == vol_r) { | ||
185 | ipod_i2c_send(0x1a, 0x4 | 0x1, vol_l); | ||
186 | } else { | ||
187 | ipod_i2c_send(0x1a, 0x4, vol_l); | ||
188 | ipod_i2c_send(0x1a, 0x6, vol_r); | ||
189 | } | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | int wm8975_set_mixer_vol(int channel1, int channel2) | ||
195 | { | ||
196 | (void)channel1; | ||
197 | (void)channel2; | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | void wm8731l_set_bass(int value) | ||
203 | { | ||
204 | (void)value; | ||
205 | } | ||
206 | |||
207 | void wm8731l_set_treble(int value) | ||
208 | { | ||
209 | (void)value; | ||
210 | } | ||
211 | |||
212 | /* Nice shutdown of WM8975 codec */ | ||
213 | void wm8731l_close(void) | ||
214 | { | ||
215 | /* set DACMU=1 DEEMPH=0 */ | ||
216 | ipod_i2c_send(0x1a, 0xa, 0x8); | ||
217 | |||
218 | /* ACTIVE=0 */ | ||
219 | codec_set_active(0x0); | ||
220 | |||
221 | /* line in mute left & right*/ | ||
222 | ipod_i2c_send(0x1a, 0x0 | 0x1, 0x80); | ||
223 | |||
224 | /* set DACSEL=0, MUTEMIC=1 */ | ||
225 | ipod_i2c_send(0x1a, 0x8, 0x2); | ||
226 | |||
227 | /* set POWEROFF=0 OUTPD=0 DACPD=1 */ | ||
228 | ipod_i2c_send(0x1a, 0xc, 0x6f); | ||
229 | |||
230 | /* set POWEROFF=1 OUTPD=1 DACPD=1 */ | ||
231 | ipod_i2c_send(0x1a, 0xc, 0xff); | ||
232 | } | ||
233 | |||
234 | /* Change the order of the noise shaper, 5th order is recommended above 32kHz */ | ||
235 | void wm8731l_set_nsorder(int order) | ||
236 | { | ||
237 | (void)order; | ||
238 | } | ||
239 | |||
240 | /* */ | ||
241 | void wm8731l_set_sample_rate(int sampling_control) | ||
242 | { | ||
243 | codec_set_active(0x0); | ||
244 | ipod_i2c_send(0x1a, 0x10, sampling_control); | ||
245 | codec_set_active(0x1); | ||
246 | } | ||
247 | |||
248 | void wm8731l_enable_recording(bool source_mic) | ||
249 | { | ||
250 | (void)source_mic; | ||
251 | } | ||
252 | |||
253 | void wm8731l_disable_recording(void) | ||
254 | { | ||
255 | |||
256 | } | ||
257 | |||
258 | void wm8731l_set_recvol(int left, int right, int type) | ||
259 | { | ||
260 | (void)left; | ||
261 | (void)right; | ||
262 | (void)type; | ||
263 | } | ||
264 | |||
265 | void wm8731l_set_monitor(int enable) | ||
266 | { | ||
267 | (void)enable; | ||
268 | } | ||