summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2006-02-26 15:59:46 +0000
committerDave Chapman <dave@dchapman.com>2006-02-26 15:59:46 +0000
commit2f76763d73c7be641cd55c30ff15f6ff9dda5fe0 (patch)
tree29179e6843bf4de0bdedf9ed40e07cfb520bdad8 /firmware
parent4b9fbd168713e572f9a73a7bacaa850e8c961994 (diff)
downloadrockbox-2f76763d73c7be641cd55c30ff15f6ff9dda5fe0.tar.gz
rockbox-2f76763d73c7be641cd55c30ff15f6ff9dda5fe0.zip
iPod 3G - initial (completely untested) attempt at audio support
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8847 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/drivers/wm8731l.c106
-rw-r--r--firmware/export/config-ipod3g.h2
-rw-r--r--firmware/export/wm8731l.h36
-rw-r--r--firmware/pcm_playback.c76
-rw-r--r--firmware/sound.c54
-rw-r--r--firmware/system.c4
7 files changed, 184 insertions, 96 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 4c6fbd7c2a..23c3a6dddc 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -180,7 +180,7 @@ drivers/uda1380.c
180drivers/wm8975.c 180drivers/wm8975.c
181#elif defined(HAVE_WM8758) && !defined(SIMULATOR) 181#elif defined(HAVE_WM8758) && !defined(SIMULATOR)
182drivers/wm8758.c 182drivers/wm8758.c
183#elif defined(HAVE_WM8731L) && !defined(SIMULATOR) 183#elif defined(HAVE_WM8731) && !defined(SIMULATOR)
184drivers/wm8731l.c 184drivers/wm8731l.c
185#elif defined(HAVE_TLV320) && !defined(SIMULATOR) 185#elif defined(HAVE_TLV320) && !defined(SIMULATOR)
186drivers/tlv320.c 186drivers/tlv320.c
diff --git a/firmware/drivers/wm8731l.c b/firmware/drivers/wm8731l.c
index d49e8f4476..990ad0ebbc 100644
--- a/firmware/drivers/wm8731l.c
+++ b/firmware/drivers/wm8731l.c
@@ -41,40 +41,46 @@
41#include "wm8731l.h" 41#include "wm8731l.h"
42#include "pcf50605.h" 42#include "pcf50605.h"
43 43
44void wm8731l_reset(void);
45
46#define IPOD_PCM_LEVEL 0x65 /* -6dB */ 44#define IPOD_PCM_LEVEL 0x65 /* -6dB */
47 45
48#define RESET (0x0f<<1) 46#define LINVOL 0x00
49#define PWRMGMT1 (0x19<<1) 47#define RINVOL 0x01
50#define PWRMGMT2 (0x1a<<1) 48#define LOUTVOL 0x02
51#define AINTFCE (0x07<<1) 49#define ROUTVOL 0x03
52#define LOUT1VOL (0x02<<1) 50#define DACCTRL 0x05
53#define ROUT1VOL (0x03<<1) 51#define PWRMGMT 0x06
54#define LOUT2VOL (0x28<<1) 52#define AINTFCE 0x07
55#define ROUT2VOL (0x29<<1) 53#define SAMPCTRL 0x08
54#define ACTIVECTRL 0x09
55#define RESET 0x0f
56
57void wm8731_write(int reg, int data)
58{
59 ipod_i2c_send(0x1a, (reg<<1) | ((data&0x100)>>8),data&0xff);
60}
56 61
57int wm8731l_mute(int mute) 62int wmcodec_mute(int mute)
58{ 63{
59 if (mute) 64 if (mute)
60 { 65 {
61 /* Set DACMU = 1 to soft-mute the audio DACs. */ 66 /* Set DACMU = 1 to soft-mute the audio DACs. */
62 ipod_i2c_send(0x1a, 0xa, 0x8); 67 wm8731_write(DACCTRL, 0x8);
63 } else { 68 } else {
64 /* Set DACMU = 0 to soft-un-mute the audio DACs. */ 69 /* Set DACMU = 0 to soft-un-mute the audio DACs. */
65 ipod_i2c_send(0x1a, 0xa, 0x0); 70 wm8731_write(DACCTRL, 0x0);
66 } 71 }
67 72
68 return 0; 73 return 0;
69} 74}
75
70/** From ipodLinux **/ 76/** From ipodLinux **/
71static void codec_set_active(int active) 77static void codec_set_active(int active)
72{ 78{
73 /* set active to 0x0 or 0x1 */ 79 /* set active to 0x0 or 0x1 */
74 if (active) { 80 if (active) {
75 ipod_i2c_send(0x1a, 0x12, 0x01); 81 wm8731_write(ACTIVECTRL, 0x01);
76 } else { 82 } else {
77 ipod_i2c_send(0x1a, 0x12, 0x00); 83 wm8731_write(ACTIVECTRL, 0x00);
78 } 84 }
79} 85}
80 86
@@ -102,7 +108,7 @@ static void i2s_reset(void)
102 * Initialise the WM8975 for playback via headphone and line out. 108 * Initialise the WM8975 for playback via headphone and line out.
103 * Note, I'm using the WM8750 datasheet as its apparently close. 109 * Note, I'm using the WM8750 datasheet as its apparently close.
104 */ 110 */
105int wm8731l_init(void) { 111int wmcodec_init(void) {
106 /* reset I2C */ 112 /* reset I2C */
107 i2c_init(); 113 i2c_init();
108 114
@@ -134,64 +140,61 @@ int wm8731l_init(void) {
134} 140}
135 141
136/* Silently enable / disable audio output */ 142/* Silently enable / disable audio output */
137void wm8731l_enable_output(bool enable) 143void wmcodec_enable_output(bool enable)
138{ 144{
139 if (enable) 145 if (enable)
140 { 146 {
141 /* reset the I2S controller into known state */ 147 /* reset the I2S controller into known state */
142 i2s_reset(); 148 i2s_reset();
143 149
144 ipod_i2c_send(0x1a, 0x1e, 0x0); /*Reset*/ 150 wm8731_write(RESET, 0x0); /*Reset*/
145 151
146 codec_set_active(0x0); 152 codec_set_active(0x0);
147 153
148 /* DACSEL=1 */ 154 /* DACSEL=1 */
149 /* BYPASS=1 */ 155 /* BYPASS=1 */
150 ipod_i2c_send(0x1a, 0x8, 0x18); 156 wm8731_write(0x4, 0x18);
151 157
152 /* set power register to POWEROFF=0 on OUTPD=0, DACPD=0 */ 158 /* set power register to POWEROFF=0 on OUTPD=0, DACPD=0 */
153 ipod_i2c_send(0x1a, 0xc, 0x67); 159 wm8731_write(PWRMGMT, 0x67);
154 160
155 /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */ 161 /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */
156 /* IWL=00(16 bit) FORMAT=10(I2S format) */ 162 /* IWL=00(16 bit) FORMAT=10(I2S format) */
157 ipod_i2c_send(0x1a, 0xe, 0x42); 163 wm8731_write(AINTFCE, 0x42);
158 164
159 wm8731l_set_sample_rate(WM8731L_44100HZ); 165 wmcodec_set_sample_rate(WM8731L_44100HZ);
160 166
161 /* set the volume to -6dB */ 167 /* set the volume to -6dB */
162 ipod_i2c_send(0x1a, 0x4, IPOD_PCM_LEVEL); 168 wm8731_write(LOUTVOL, IPOD_PCM_LEVEL);
163 ipod_i2c_send(0x1a, 0x6 | 0x1, IPOD_PCM_LEVEL); 169 wm8731_write(ROUTVOL, 0x100 | IPOD_PCM_LEVEL);
164 170
165 /* ACTIVE=1 */ 171 /* ACTIVE=1 */
166 codec_set_active(1); 172 codec_set_active(1);
167 173
168 /* 5. Set DACMU = 0 to soft-un-mute the audio DACs. */ 174 /* 5. Set DACMU = 0 to soft-un-mute the audio DACs. */
169 ipod_i2c_send(0x1a, 0xa, 0x0); 175 wm8731_write(DACCTRL, 0x0);
170 176
171 wm8731l_mute(0); 177 wmcodec_mute(0);
172 } else { 178 } else {
173 wm8731l_mute(1); 179 wmcodec_mute(1);
174 } 180 }
175} 181}
176 182
177int wm8731l_set_master_vol(int vol_l, int vol_r) 183int wmcodec_set_master_vol(int vol_l, int vol_r)
178{ 184{
179 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ 185 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
180 /* 1111111 == +6dB */ 186 /* 1111111 == +6dB */
181 /* 1111001 == 0dB */ 187 /* 1111001 == 0dB */
182 /* 0110000 == -73dB */ 188 /* 0110000 == -73dB */
183 /* 0101111 == mute (0x2f) */ 189 /* 0101111 == mute (0x2f) */
184 if (vol_l == vol_r) { 190
185 ipod_i2c_send(0x1a, 0x4 | 0x1, vol_l); 191 wm8731_write(LOUTVOL, vol_l);
186 } else { 192 wm8731_write(ROUTVOL, vol_r);
187 ipod_i2c_send(0x1a, 0x4, vol_l);
188 ipod_i2c_send(0x1a, 0x6, vol_r);
189 }
190 193
191 return 0; 194 return 0;
192} 195}
193 196
194int wm8975_set_mixer_vol(int channel1, int channel2) 197int wmcodec_set_mixer_vol(int channel1, int channel2)
195{ 198{
196 (void)channel1; 199 (void)channel1;
197 (void)channel2; 200 (void)channel2;
@@ -199,70 +202,69 @@ int wm8975_set_mixer_vol(int channel1, int channel2)
199 return 0; 202 return 0;
200} 203}
201 204
202void wm8731l_set_bass(int value) 205void wmcodec_set_bass(int value)
203{ 206{
204 (void)value; 207 (void)value;
205} 208}
206 209
207void wm8731l_set_treble(int value) 210void wmcodec_set_treble(int value)
208{ 211{
209 (void)value; 212 (void)value;
210} 213}
211 214
212/* Nice shutdown of WM8975 codec */ 215/* Nice shutdown of WM8731 codec */
213void wm8731l_close(void) 216void wmcodec_close(void)
214{ 217{
215 /* set DACMU=1 DEEMPH=0 */ 218 /* set DACMU=1 DEEMPH=0 */
216 ipod_i2c_send(0x1a, 0xa, 0x8); 219 wm8731_write(DACCTRL, 0x8);
217 220
218 /* ACTIVE=0 */ 221 /* ACTIVE=0 */
219 codec_set_active(0x0); 222 codec_set_active(0x0);
220 223
221 /* line in mute left & right*/ 224 /* line in mute left & right*/
222 ipod_i2c_send(0x1a, 0x0 | 0x1, 0x80); 225 wm8731_write(LINVOL, 0x100 | 0x80);
223 226
224 /* set DACSEL=0, MUTEMIC=1 */ 227 /* set DACSEL=0, MUTEMIC=1 */
225 ipod_i2c_send(0x1a, 0x8, 0x2); 228 wm8731_write(0x4, 0x2);
226 229
227 /* set POWEROFF=0 OUTPD=0 DACPD=1 */ 230 /* set POWEROFF=0 OUTPD=0 DACPD=1 */
228 ipod_i2c_send(0x1a, 0xc, 0x6f); 231 wm8731_write(PWRMGMT, 0x6f);
229 232
230 /* set POWEROFF=1 OUTPD=1 DACPD=1 */ 233 /* set POWEROFF=1 OUTPD=1 DACPD=1 */
231 ipod_i2c_send(0x1a, 0xc, 0xff); 234 wm8731_write(PWRMGMT, 0xff);
232} 235}
233 236
234/* Change the order of the noise shaper, 5th order is recommended above 32kHz */ 237/* Change the order of the noise shaper, 5th order is recommended above 32kHz */
235void wm8731l_set_nsorder(int order) 238void wmcodec_set_nsorder(int order)
236{ 239{
237 (void)order; 240 (void)order;
238} 241}
239 242
240/* */ 243void wmcodec_set_sample_rate(int sampling_control)
241void wm8731l_set_sample_rate(int sampling_control)
242{ 244{
243 codec_set_active(0x0); 245 codec_set_active(0x0);
244 ipod_i2c_send(0x1a, 0x10, sampling_control); 246 wm8731_write(SAMPCTRL, sampling_control);
245 codec_set_active(0x1); 247 codec_set_active(0x1);
246} 248}
247 249
248void wm8731l_enable_recording(bool source_mic) 250void wmcodec_enable_recording(bool source_mic)
249{ 251{
250 (void)source_mic; 252 (void)source_mic;
251} 253}
252 254
253void wm8731l_disable_recording(void) 255void wmcodec_disable_recording(void)
254{ 256{
255 257
256} 258}
257 259
258void wm8731l_set_recvol(int left, int right, int type) 260void wmcodec_set_recvol(int left, int right, int type)
259{ 261{
260 (void)left; 262 (void)left;
261 (void)right; 263 (void)right;
262 (void)type; 264 (void)type;
263} 265}
264 266
265void wm8731l_set_monitor(int enable) 267void wmcodec_set_monitor(int enable)
266{ 268{
267 (void)enable; 269 (void)enable;
268} 270}
diff --git a/firmware/export/config-ipod3g.h b/firmware/export/config-ipod3g.h
index e809afa6c9..072d6027fc 100644
--- a/firmware/export/config-ipod3g.h
+++ b/firmware/export/config-ipod3g.h
@@ -41,7 +41,7 @@
41#define PLUGIN_BUFFER_SIZE 0x80000 41#define PLUGIN_BUFFER_SIZE 0x80000
42 42
43/* Define this if you have the WM8731L audio codec */ 43/* Define this if you have the WM8731L audio codec */
44#define HAVE_WM8731L 44#define HAVE_WM8731
45 45
46/* Define this for LCD backlight available */ 46/* Define this for LCD backlight available */
47#define CONFIG_BACKLIGHT BL_IPOD3G /* port controlled */ 47#define CONFIG_BACKLIGHT BL_IPOD3G /* port controlled */
diff --git a/firmware/export/wm8731l.h b/firmware/export/wm8731l.h
index 6ed845c714..d384976226 100644
--- a/firmware/export/wm8731l.h
+++ b/firmware/export/wm8731l.h
@@ -20,31 +20,25 @@
20#ifndef _WM8731L_H 20#ifndef _WM8731L_H
21#define _WM8731L_H 21#define _WM8731L_H
22 22
23extern void wm8731l_reset(void); 23extern void wmcodec_reset(void);
24extern int wm8731l_init(void); 24extern int wmcodec_init(void);
25extern void wm8731l_enable_output(bool enable); 25extern void wmcodec_enable_output(bool enable);
26extern int wm8731l_set_master_vol(int vol_l, int vol_r); 26extern int wmcodec_set_master_vol(int vol_l, int vol_r);
27extern int wm8731l_set_mixer_vol(int channel1, int channel2); 27extern int wmcodec_set_mixer_vol(int channel1, int channel2);
28extern void wm8731l_set_bass(int value); 28extern void wmcodec_set_bass(int value);
29extern void wm8731l_set_treble(int value); 29extern void wmcodec_set_treble(int value);
30extern int wm8731l_mute(int mute); 30extern int wmcodec_mute(int mute);
31extern void wm8731l_close(void); 31extern void wmcodec_close(void);
32extern void wm8731l_set_nsorder(int order); 32extern void wmcodec_set_nsorder(int order);
33extern void wm8731l_set_sample_rate(int sampling_control); 33extern void wmcodec_set_sample_rate(int sampling_control);
34 34
35extern void wm8731l_enable_recording(bool source_mic); 35extern void wmcodec_enable_recording(bool source_mic);
36extern void wm8731l_disable_recording(void); 36extern void wmcodec_disable_recording(void);
37extern void wm8731l_set_recvol(int left, int right, int type); 37extern void wmcodec_set_recvol(int left, int right, int type);
38extern void wm8731l_set_monitor(int enable); 38extern void wmcodec_set_monitor(int enable);
39 39
40/* Register settings for the supported samplerates: */ 40/* Register settings for the supported samplerates: */
41#define WM8731L_8000HZ 0x4d 41#define WM8731L_8000HZ 0x4d
42/*
43 IpodLinux don't seem to support those sampling rate with the wm8731L chip
44#define WM8975_16000HZ 0x55
45#define WM8975_22050HZ 0x77
46#define WM8975_24000HZ 0x79
47*/
48#define WM8731L_32000HZ 0x59 42#define WM8731L_32000HZ 0x59
49#define WM8731L_44100HZ 0x63 43#define WM8731L_44100HZ 0x63
50#define WM8731L_48000HZ 0x41 44#define WM8731L_48000HZ 0x41
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index a9d9ecd9e6..af642e4d43 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -31,7 +31,7 @@
31#include "wm8758.h" 31#include "wm8758.h"
32#elif defined(HAVE_TLV320) 32#elif defined(HAVE_TLV320)
33#include "tlv320.h" 33#include "tlv320.h"
34#elif defined(HAVE_WM8731L) 34#elif defined(HAVE_WM8731)
35#include "wm8731l.h" 35#include "wm8731l.h"
36#endif 36#endif
37#include "system.h" 37#include "system.h"
@@ -314,13 +314,17 @@ void pcm_init(void)
314 dma_stop(); 314 dma_stop();
315} 315}
316 316
317#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) 317#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
318 318
319/* We need to unify this code with the uda1380 code as much as possible, but 319/* We need to unify this code with the uda1380 code as much as possible, but
320 we will keep it separate during early development. 320 we will keep it separate during early development.
321*/ 321*/
322 322
323#if CONFIG_CPU == PP5020
323#define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x3f0000) >> 16) 324#define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x3f0000) >> 16)
325#elif CONFIG_CPU == PP5002
326#define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x7800000) >> 23)
327#endif
324 328
325static bool pcm_playing; 329static bool pcm_playing;
326static bool pcm_paused; 330static bool pcm_paused;
@@ -329,6 +333,8 @@ static int pcm_freq = 0x6; /* 44.1 is default */
329unsigned short* p IBSS_ATTR; 333unsigned short* p IBSS_ATTR;
330long p_size IBSS_ATTR; 334long p_size IBSS_ATTR;
331 335
336#define PP5002_DMA_OUT_MASK (1 << DMA_OUT_IRQ)
337
332static void dma_start(const void *addr, size_t size) 338static void dma_start(const void *addr, size_t size)
333{ 339{
334 p=(unsigned short*)addr; 340 p=(unsigned short*)addr;
@@ -336,22 +342,36 @@ static void dma_start(const void *addr, size_t size)
336 342
337 pcm_playing = true; 343 pcm_playing = true;
338 344
345#if CONFIG_CPU == PP5020
339 /* setup I2S interrupt for FIQ */ 346 /* setup I2S interrupt for FIQ */
340 outl(inl(0x6000402c) | I2S_MASK, 0x6000402c); 347 outl(inl(0x6000402c) | I2S_MASK, 0x6000402c);
341 outl(I2S_MASK, 0x60004024); 348 outl(I2S_MASK, 0x60004024);
349#else
350 /* setup I2S interrupt for FIQ */
351 outl(inl(0xcf00103c) | PP5002_DMA_OUT_MASK, 0xcf00103c);
352 outl(PP5002_DMA_OUT_MASK, 0xcf001034);
353#endif
342 354
343 /* Clear the FIQ disable bit in cpsr_c */ 355 /* Clear the FIQ disable bit in cpsr_c */
344 enable_fiq(); 356 enable_fiq();
345 357
346 /* Enable playback FIFO */ 358 /* Enable playback FIFO */
359#if CONFIG_CPU == PP5020
347 IISCONFIG |= 0x20000000; 360 IISCONFIG |= 0x20000000;
361#elif CONFIG_CPU == PP5002
362 IISCONFIG |= 0x4;
363#endif
348 364
349 /* Fill the FIFO - we assume there are enough bytes in the pcm buffer to 365 /* Fill the FIFO - we assume there are enough bytes in the pcm buffer to
350 fill the 32-byte FIFO. */ 366 fill the 32-byte FIFO. */
351 while (p_size > 0) { 367 while (p_size > 0) {
352 if (FIFO_FREE_COUNT < 2) { 368 if (FIFO_FREE_COUNT < 2) {
353 /* Enable interrupt */ 369 /* Enable interrupt */
370#if CONFIG_CPU == PP5020
354 IISCONFIG |= 0x2; 371 IISCONFIG |= 0x2;
372#elif CONFIG_CPU == PP5002
373 IISFIFO_CFG &= ~(1<<9);
374#endif
355 return; 375 return;
356 } 376 }
357 377
@@ -366,12 +386,23 @@ static void dma_stop(void)
366{ 386{
367 pcm_playing = false; 387 pcm_playing = false;
368 388
389#if CONFIG_CPU == PP5020
390
369 /* Disable playback FIFO */ 391 /* Disable playback FIFO */
370 IISCONFIG &= ~0x20000000; 392 IISCONFIG &= ~0x20000000;
371 393
372 /* Disable the interrupt */ 394 /* Disable the interrupt */
373 IISCONFIG &= ~0x2; 395 IISCONFIG &= ~0x2;
374 396
397#elif CONFIG_CPU == PP5002
398
399 /* Disable playback FIFO */
400 IISCONFIG &= ~0x4;
401
402 /* Disable the interrupt */
403 IISFIFO_CFG &= ~(1<<9);
404#endif
405
375 disable_fiq(); 406 disable_fiq();
376 407
377 pcm_paused = false; 408 pcm_paused = false;
@@ -438,14 +469,22 @@ void pcm_play_pause(bool play)
438 enable_fiq(); 469 enable_fiq();
439 470
440 /* Enable playback FIFO */ 471 /* Enable playback FIFO */
472#if CONFIG_CPU == PP5020
441 IISCONFIG |= 0x20000000; 473 IISCONFIG |= 0x20000000;
474#elif CONFIG_CPU == PP5002
475 IISCONFIG |= 0x4;
476#endif
442 477
443 /* Fill the FIFO - we assume there are enough bytes in the 478 /* Fill the FIFO - we assume there are enough bytes in the
444 pcm buffer to fill the 32-byte FIFO. */ 479 pcm buffer to fill the 32-byte FIFO. */
445 while (p_size > 0) { 480 while (p_size > 0) {
446 if (FIFO_FREE_COUNT < 2) { 481 if (FIFO_FREE_COUNT < 2) {
447 /* Enable interrupt */ 482 /* Enable interrupt */
483#if CONFIG_CPU == PP5020
448 IISCONFIG |= 0x2; 484 IISCONFIG |= 0x2;
485#elif CONFIG_CPU == PP5002
486 IISFIFO_CFG &= ~(1<<9);
487#endif
449 return; 488 return;
450 } 489 }
451 490
@@ -473,12 +512,23 @@ void pcm_play_pause(bool play)
473 { 512 {
474 logf("pause"); 513 logf("pause");
475 514
515#if CONFIG_CPU == PP5020
516
476 /* Disable the interrupt */ 517 /* Disable the interrupt */
477 IISCONFIG &= ~0x2; 518 IISCONFIG &= ~0x2;
478 519
479 /* Disable playback FIFO */ 520 /* Disable playback FIFO */
480 IISCONFIG &= ~0x20000000; 521 IISCONFIG &= ~0x20000000;
481 522
523#elif CONFIG_CPU == PP5002
524
525 /* Disable the interrupt */
526 IISFIFO_CFG &= ~(1<<9);
527
528 /* Disable playback FIFO */
529 IISCONFIG &= ~0x4;
530#endif
531
482 disable_fiq(); 532 disable_fiq();
483 } 533 }
484 pcm_paused = !play; 534 pcm_paused = !play;
@@ -500,7 +550,7 @@ bool pcm_is_playing(void)
500 actually needs to do so when calling callback_for_more. C version is still 550 actually needs to do so when calling callback_for_more. C version is still
501 included below for reference. 551 included below for reference.
502 */ 552 */
503#if 1 553#if CONFIG_CPU == PP5020
504void fiq(void) ICODE_ATTR __attribute__((naked)); 554void fiq(void) ICODE_ATTR __attribute__((naked));
505void fiq(void) 555void fiq(void)
506{ 556{
@@ -579,13 +629,22 @@ void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
579void fiq(void) 629void fiq(void)
580{ 630{
581 /* Clear interrupt */ 631 /* Clear interrupt */
632#if CONFIG_CPU == PP5020
582 IISCONFIG &= ~0x2; 633 IISCONFIG &= ~0x2;
634#elif CONFIG_CPU == PP5002
635 inl(0xcf001040);
636 IISFIFO_CFG &= ~(1<<9);
637#endif
583 638
584 do { 639 do {
585 while (p_size) { 640 while (p_size) {
586 if (FIFO_FREE_COUNT < 2) { 641 if (FIFO_FREE_COUNT < 2) {
587 /* Enable interrupt */ 642 /* Enable interrupt */
643#if CONFIG_CPU == PP5020
588 IISCONFIG |= 0x2; 644 IISCONFIG |= 0x2;
645#elif CONFIG_CPU == PP5002
646 IISFIFO_CFG &= ~(1<<9);
647#endif
589 return; 648 return;
590 } 649 }
591 650
@@ -625,9 +684,9 @@ void pcm_init(void)
625 dma_stop(); 684 dma_stop();
626} 685}
627 686
628#elif (CONFIG_CPU == PNX0101) || (CONFIG_CPU == PP5002) 687#elif (CONFIG_CPU == PNX0101)
629 688
630/* TODO: Implement for iFP7xx and iPod 3G 689/* TODO: Implement for iFP7xx
631 For now, just implement some dummy functions. 690 For now, just implement some dummy functions.
632*/ 691*/
633 692
@@ -686,7 +745,7 @@ size_t pcm_get_bytes_waiting(void)
686 745
687#endif 746#endif
688 747
689#if (CONFIG_CPU != PNX0101) && (CONFIG_CPU != PP5002) 748#if (CONFIG_CPU != PNX0101)
690/* 749/*
691 * This function goes directly into the DMA buffer to calculate the left and 750 * This function goes directly into the DMA buffer to calculate the left and
692 * right peak values. To avoid missing peaks it tries to look forward two full 751 * right peak values. To avoid missing peaks it tries to look forward two full
@@ -704,12 +763,9 @@ void pcm_calculate_peaks(int *left, int *right)
704#ifdef HAVE_UDA1380 763#ifdef HAVE_UDA1380
705 long samples = (BCR0 & 0xffffff) / 4; 764 long samples = (BCR0 & 0xffffff) / 4;
706 short *addr = (short *) (SAR0 & ~3); 765 short *addr = (short *) (SAR0 & ~3);
707#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) 766#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
708 long samples = p_size / 4; 767 long samples = p_size / 4;
709 short *addr = p; 768 short *addr = p;
710#elif defined(HAVE_WM8731L)
711 long samples = next_size / 4;
712 short *addr = (short *)next_start;
713#elif defined(HAVE_TLV320) 769#elif defined(HAVE_TLV320)
714 long samples = 4; /* TODO X5 */ 770 long samples = 4; /* TODO X5 */
715 short *addr = NULL; 771 short *addr = NULL;
diff --git a/firmware/sound.c b/firmware/sound.c
index a039cca609..f1c9ff79e7 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -30,6 +30,8 @@
30#include "wm8975.h" 30#include "wm8975.h"
31#elif defined(HAVE_WM8758) 31#elif defined(HAVE_WM8758)
32#include "wm8758.h" 32#include "wm8758.h"
33#elif defined(HAVE_WM8731)
34#include "wm8731l.h"
33#elif defined(HAVE_TLV320) 35#elif defined(HAVE_TLV320)
34#include "tlv320.h" 36#include "tlv320.h"
35#endif 37#endif
@@ -77,6 +79,10 @@ static const struct sound_settings_info sound_settings_table[] = {
77 [SOUND_VOLUME] = {"dB", 0, 1, -57, 6, -25, sound_set_volume}, 79 [SOUND_VOLUME] = {"dB", 0, 1, -57, 6, -25, sound_set_volume},
78 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass}, 80 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
79 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble}, 81 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
82#elif defined(HAVE_WM8731)
83 [SOUND_VOLUME] = {"dB", 0, 1, -73, 6, -25, sound_set_volume},
84 [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0, sound_set_bass},
85 [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0, sound_set_treble},
80#else /* MAS3507D */ 86#else /* MAS3507D */
81 [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18, sound_set_volume}, 87 [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18, sound_set_volume},
82 [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7, sound_set_bass}, 88 [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7, sound_set_bass},
@@ -350,10 +356,44 @@ static int tenthdb2mixer(int db)
350 return -db * 2 / 5; 356 return -db * 2 / 5;
351} 357}
352 358
359#elif defined(HAVE_WM8731)
360/* volume/balance/treble/bass interdependency */
361#define VOLUME_MIN -730
362#define VOLUME_MAX 60
363
364/* convert tenth of dB volume (-730..60) to master volume register value */
365static int tenthdb2master(int db)
366{
367 /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
368 /* 1111111 == +6dB (0x7f) */
369 /* 1111001 == 0dB (0x79) */
370 /* 0110000 == -73dB (0x30 */
371 /* 0101111 == mute (0x2f) */
372
373 if (db <= -570) {
374 return 0x0;
375 } else {
376 return((db/10)+57);
377 }
378}
379
380/* convert tenth of dB volume (-780..0) to mixer volume register value */
381static int tenthdb2mixer(int db)
382{
383 if (db < -660) /* 1.5 dB steps */
384 return (2640 - db) / 15;
385 else if (db < -600) /* 0.75 dB steps */
386 return (990 - db) * 2 / 15;
387 else if (db < -460) /* 0.5 dB steps */
388 return (460 - db) / 5;
389 else /* 0.25 dB steps */
390 return -db * 2 / 5;
391}
392
353#endif 393#endif
354 394
355#if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || \ 395#if (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || \
356 defined HAVE_WM8975 || defined HAVE_WM8758 396 defined HAVE_WM8975 || defined HAVE_WM8758 || defined(HAVE_WM8731)
357 /* volume/balance/treble/bass interdependency main part */ 397 /* volume/balance/treble/bass interdependency main part */
358#define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN) 398#define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
359 399
@@ -383,7 +423,7 @@ static void set_prescaled_volume(void)
383 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]); 423 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
384#elif defined(HAVE_UDA1380) 424#elif defined(HAVE_UDA1380)
385 uda1380_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale)); 425 uda1380_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale));
386#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) 426#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
387 wmcodec_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale)); 427 wmcodec_set_mixer_vol(tenthdb2mixer(-prescale), tenthdb2mixer(-prescale));
388#endif 428#endif
389 429
@@ -409,7 +449,7 @@ static void set_prescaled_volume(void)
409 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false); 449 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
410#elif defined(HAVE_UDA1380) 450#elif defined(HAVE_UDA1380)
411 uda1380_set_master_vol(tenthdb2master(l), tenthdb2master(r)); 451 uda1380_set_master_vol(tenthdb2master(l), tenthdb2master(r));
412#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) 452#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
413 wmcodec_set_master_vol(tenthdb2master(l), tenthdb2master(r)); 453 wmcodec_set_master_vol(tenthdb2master(l), tenthdb2master(r));
414#endif 454#endif
415} 455}
@@ -511,7 +551,7 @@ void sound_set_volume(int value)
511 unsigned tmp = ((unsigned)(value + 115) & 0xff) << 8; 551 unsigned tmp = ((unsigned)(value + 115) & 0xff) << 8;
512 mas_codec_writereg(0x10, tmp); 552 mas_codec_writereg(0x10, tmp);
513#elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || \ 553#elif (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 || \
514 defined HAVE_WM8975 || defined HAVE_WM8758 554 defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731
515 current_volume = value * 10; /* tenth of dB */ 555 current_volume = value * 10; /* tenth of dB */
516 set_prescaled_volume(); 556 set_prescaled_volume();
517#elif CONFIG_CPU == PNX0101 557#elif CONFIG_CPU == PNX0101
@@ -528,7 +568,7 @@ void sound_set_balance(int value)
528 unsigned tmp = ((unsigned)(value * 127 / 100) & 0xff) << 8; 568 unsigned tmp = ((unsigned)(value * 127 / 100) & 0xff) << 8;
529 mas_codec_writereg(0x11, tmp); 569 mas_codec_writereg(0x11, tmp);
530#elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 || \ 570#elif CONFIG_CODEC == MAS3507D || defined HAVE_UDA1380 || \
531 defined HAVE_WM8975 || defined HAVE_WM8758 571 defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731
532 current_balance = value * VOLUME_RANGE / 100; /* tenth of dB */ 572 current_balance = value * VOLUME_RANGE / 100; /* tenth of dB */
533 set_prescaled_volume(); 573 set_prescaled_volume();
534#elif CONFIG_CPU == PNX0101 574#elif CONFIG_CPU == PNX0101
@@ -552,7 +592,7 @@ void sound_set_bass(int value)
552 uda1380_set_bass(value >> 1); 592 uda1380_set_bass(value >> 1);
553 current_bass = value * 10; 593 current_bass = value * 10;
554 set_prescaled_volume(); 594 set_prescaled_volume();
555#elif defined HAVE_WM8975 || defined HAVE_WM8758 595#elif defined HAVE_WM8975 || defined HAVE_WM8758 || defined HAVE_WM8731
556 current_bass = value * 10; 596 current_bass = value * 10;
557 wmcodec_set_bass(value); 597 wmcodec_set_bass(value);
558 set_prescaled_volume(); 598 set_prescaled_volume();
@@ -577,7 +617,7 @@ void sound_set_treble(int value)
577 uda1380_set_treble(value >> 1); 617 uda1380_set_treble(value >> 1);
578 current_treble = value * 10; 618 current_treble = value * 10;
579 set_prescaled_volume(); 619 set_prescaled_volume();
580#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) 620#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731)
581 wmcodec_set_treble(value); 621 wmcodec_set_treble(value);
582 current_treble = value * 10; 622 current_treble = value * 10;
583 set_prescaled_volume(); 623 set_prescaled_volume();
diff --git a/firmware/system.c b/firmware/system.c
index b47d983595..79004f8284 100644
--- a/firmware/system.c
+++ b/firmware/system.c
@@ -1237,10 +1237,6 @@ void irq(void)
1237 TIMER1(); 1237 TIMER1();
1238} 1238}
1239 1239
1240void fiq(void)
1241{
1242 /** TODO: implement this function **/
1243}
1244#endif 1240#endif
1245 1241
1246/* TODO: The following two function have been lifted straight from IPL, and 1242/* TODO: The following two function have been lifted straight from IPL, and