summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2006-02-05 17:16:34 +0000
committerDave Chapman <dave@dchapman.com>2006-02-05 17:16:34 +0000
commit465596b1639393ef320decced442537133ab09e8 (patch)
tree79c88e59c7ab15e2dab33caf045835b5a118a2e9
parentd16a8b8845ed496e9375c5dfac6da2011c9eb362 (diff)
downloadrockbox-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.c33
-rw-r--r--firmware/drivers/button.c139
-rw-r--r--firmware/drivers/i2c-pp5002.c168
-rw-r--r--firmware/drivers/pcf50605.c4
-rw-r--r--firmware/drivers/power.c8
-rw-r--r--firmware/drivers/serial.c6
-rw-r--r--firmware/drivers/wm8731l.c268
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
929static int check_registers(void) 935static 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
951static int freeze_lock(void) 963static 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 */
226int int_btn = BUTTON_NONE;
223 227
228/**
229 *
230 *
231 */
232void 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
278static int ipod_3g_button_read(void)
279{
280 unsigned char source, state;
281 static int was_hold = 0;
282int 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
340void 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
224static void button_tick(void) 350static 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
52static 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
69int 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
96int 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
130int 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
140int 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
150int 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
160void 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
44void 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
57int 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 **/
71static 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 */
84static 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 */
105int 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 */
137void 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
177int 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
194int wm8975_set_mixer_vol(int channel1, int channel2)
195{
196 (void)channel1;
197 (void)channel2;
198
199 return 0;
200}
201
202void wm8731l_set_bass(int value)
203{
204 (void)value;
205}
206
207void wm8731l_set_treble(int value)
208{
209 (void)value;
210}
211
212/* Nice shutdown of WM8975 codec */
213void 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 */
235void wm8731l_set_nsorder(int order)
236{
237 (void)order;
238}
239
240/* */
241void 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
248void wm8731l_enable_recording(bool source_mic)
249{
250 (void)source_mic;
251}
252
253void wm8731l_disable_recording(void)
254{
255
256}
257
258void wm8731l_set_recvol(int left, int right, int type)
259{
260 (void)left;
261 (void)right;
262 (void)type;
263}
264
265void wm8731l_set_monitor(int enable)
266{
267 (void)enable;
268}