summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-12-12 11:01:07 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-12-12 11:01:07 +0000
commite69d567d9ebf7d236ff9663b11ac396cc71dcd75 (patch)
tree093b9d1bc979d79be1fcd0daac1d8daf8ac55503 /firmware
parent0ad97d13fc52b28de566dc0ddaf7245583eec2cc (diff)
downloadrockbox-e69d567d9ebf7d236ff9663b11ac396cc71dcd75.tar.gz
rockbox-e69d567d9ebf7d236ff9663b11ac396cc71dcd75.zip
Bring consistency to pcm implementation and samplerate handling. Less low-level duplication. A small test_sampr fix so it works on coldfire again.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19400 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/audio/as3514.c4
-rw-r--r--firmware/drivers/audio/tlv320.c16
-rw-r--r--firmware/drivers/audio/tsc2100.c6
-rw-r--r--firmware/drivers/audio/uda1380.c35
-rw-r--r--firmware/drivers/audio/wm8731.c39
-rw-r--r--firmware/drivers/audio/wm8751.c14
-rw-r--r--firmware/drivers/audio/wm8758.c6
-rw-r--r--firmware/drivers/audio/wm8975.c6
-rw-r--r--firmware/drivers/audio/wm8978.c24
-rw-r--r--firmware/drivers/audio/wm8985.c6
-rw-r--r--firmware/export/as3514.h2
-rw-r--r--firmware/export/config-gigabeat.h6
-rw-r--r--firmware/export/config-mrobe100.h1
-rw-r--r--firmware/export/pcm.h6
-rw-r--r--firmware/export/pp5002.h56
-rw-r--r--firmware/export/pp5020.h3
-rw-r--r--firmware/export/tlv320.h2
-rw-r--r--firmware/export/uda1380.h4
-rw-r--r--firmware/export/wm8731.h2
-rw-r--r--firmware/export/wm8758.h2
-rw-r--r--firmware/export/wm8975.h2
-rw-r--r--firmware/export/wm8978.h2
-rw-r--r--firmware/pcm.c68
-rw-r--r--firmware/target/arm/as3525/pcm-as3525.c11
-rw-r--r--firmware/target/arm/audio-pp.c18
-rw-r--r--firmware/target/arm/i2s-pp.c14
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c75
-rw-r--r--firmware/target/arm/pcm-pp.c56
-rw-r--r--firmware/target/arm/pcm-telechips.c13
-rw-r--r--firmware/target/arm/pnx0101/pcm-pnx0101.c13
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c59
-rw-r--r--firmware/target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c33
-rw-r--r--[-rwxr-xr-x]firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c8
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c101
-rw-r--r--firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c7
35 files changed, 307 insertions, 413 deletions
diff --git a/firmware/drivers/audio/as3514.c b/firmware/drivers/audio/as3514.c
index 825cf51655..551a9df9b7 100644
--- a/firmware/drivers/audio/as3514.c
+++ b/firmware/drivers/audio/as3514.c
@@ -290,9 +290,9 @@ void audiohw_close(void)
290 sleep(HZ/4); 290 sleep(HZ/4);
291} 291}
292 292
293void audiohw_set_sample_rate(int sampling_control) 293void audiohw_set_frequency(int fsel)
294{ 294{
295 (void)sampling_control; 295 (void)fsel;
296} 296}
297 297
298#if defined(HAVE_RECORDING) 298#if defined(HAVE_RECORDING)
diff --git a/firmware/drivers/audio/tlv320.c b/firmware/drivers/audio/tlv320.c
index b2c5be8e61..c85627e683 100644
--- a/firmware/drivers/audio/tlv320.c
+++ b/firmware/drivers/audio/tlv320.c
@@ -152,21 +152,21 @@ void audiohw_postinit(void)
152 * 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default) 152 * 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default)
153 * 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2 153 * 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2
154 */ 154 */
155void audiohw_set_frequency(unsigned fsel) 155void audiohw_set_frequency(int fsel)
156{ 156{
157 /* All rates available for 11.2896MHz besides 8.021 */ 157 /* All rates available for 11.2896MHz besides 8.021 */
158 unsigned char values_src[3] = 158 static const unsigned char values_src[HW_NUM_FREQ] =
159 { 159 {
160 /* Fs: */ 160 [HW_FREQ_11] = (0x8 << 2) | SRC_CLKIN,
161 (0x8 << 2) | SRC_CLKIN, /* 11025, 22050 */ 161 [HW_FREQ_22] = (0x8 << 2) | SRC_CLKIN,
162 (0x8 << 2), /* 44100 */ 162 [HW_FREQ_44] = (0x8 << 2),
163 (0xf << 2), /* 88200 */ 163 [HW_FREQ_88] = (0xf << 2),
164 }; 164 };
165 165
166 unsigned value_dap, value_pc; 166 unsigned value_dap, value_pc;
167 167
168 if (fsel >= ARRAYLEN(values_src)) 168 if ((unsigned)fsel >= HW_NUM_FREQ)
169 fsel = 1; 169 fsel = HW_FREQ_DEFAULT;
170 170
171 /* Temporarily turn off the DAC and ADC before switching sample 171 /* Temporarily turn off the DAC and ADC before switching sample
172 rates or they don't choose their filters correctly */ 172 rates or they don't choose their filters correctly */
diff --git a/firmware/drivers/audio/tsc2100.c b/firmware/drivers/audio/tsc2100.c
index e0e2c53e69..11f30a8560 100644
--- a/firmware/drivers/audio/tsc2100.c
+++ b/firmware/drivers/audio/tsc2100.c
@@ -130,7 +130,7 @@ void audiohw_close(void)
130 130
131} 131}
132 132
133void audiohw_set_sample_rate(int sampling_control) 133void audiohw_set_frequency(int fsel)
134{ 134
135 (void)sampling_control; 135 (void)fsel;
136} 136}
diff --git a/firmware/drivers/audio/uda1380.c b/firmware/drivers/audio/uda1380.c
index a0e7ef56d8..efe02caca8 100644
--- a/firmware/drivers/audio/uda1380.c
+++ b/firmware/drivers/audio/uda1380.c
@@ -218,23 +218,38 @@ static void reset(void)
218 * 11025: 0 = 6.25 to 12.5 MCLK/2 SCLK, LRCK: Audio Clk / 16 218 * 11025: 0 = 6.25 to 12.5 MCLK/2 SCLK, LRCK: Audio Clk / 16
219 * 22050: 1 = 12.5 to 25 MCLK/2 SCLK, LRCK: Audio Clk / 8 219 * 22050: 1 = 12.5 to 25 MCLK/2 SCLK, LRCK: Audio Clk / 8
220 * 44100: 2 = 25 to 50 MCLK SCLK, LRCK: Audio Clk / 4 (default) 220 * 44100: 2 = 25 to 50 MCLK SCLK, LRCK: Audio Clk / 4 (default)
221 * 88200: 3 = 50 to 100 MCLK SCLK, LRCK: Audio Clk / 2 <= TODO: Needs WSPLL 221 * 88200: 3 = 50 to 100 MCLK SCLK, LRCK: Audio Clk / 2
222 */ 222 */
223void audiohw_set_frequency(unsigned fsel) 223void audiohw_set_frequency(int fsel)
224{ 224{
225 static const unsigned short values_reg[4][2] = 225 static const unsigned short values_reg[HW_NUM_FREQ][2] =
226 { 226 {
227 /* Fs: */ 227 [HW_FREQ_11] = /* Fs: */
228 { 0, WSPLL_625_125 | SYSCLK_512FS }, /* 11025 */ 228 {
229 { 0, WSPLL_125_25 | SYSCLK_256FS }, /* 22050 */ 229 0,
230 { MIX_CTL_SEL_NS, WSPLL_25_50 | SYSCLK_256FS }, /* 44100 */ 230 WSPLL_625_125 | SYSCLK_512FS
231 { MIX_CTL_SEL_NS, WSPLL_50_100 | SYSCLK_256FS }, /* 88200 */ 231 },
232 [HW_FREQ_22] =
233 {
234 0,
235 WSPLL_125_25 | SYSCLK_256FS
236 },
237 [HW_FREQ_44] =
238 {
239 MIX_CTL_SEL_NS,
240 WSPLL_25_50 | SYSCLK_256FS
241 },
242 [HW_FREQ_88] =
243 {
244 MIX_CTL_SEL_NS,
245 WSPLL_50_100 | SYSCLK_256FS
246 },
232 }; 247 };
233 248
234 const unsigned short *ent; 249 const unsigned short *ent;
235 250
236 if (fsel >= ARRAYLEN(values_reg)) 251 if ((unsigned)fsel >= HW_NUM_FREQ)
237 fsel = 2; 252 fsel = HW_FREQ_DEFAULT;
238 253
239 ent = values_reg[fsel]; 254 ent = values_reg[fsel];
240 255
diff --git a/firmware/drivers/audio/wm8731.c b/firmware/drivers/audio/wm8731.c
index c065de620a..2b74d718b0 100644
--- a/firmware/drivers/audio/wm8731.c
+++ b/firmware/drivers/audio/wm8731.c
@@ -224,35 +224,24 @@ void audiohw_close(void)
224 /* 2) Remove the WM codec supplies. */ 224 /* 2) Remove the WM codec supplies. */
225} 225}
226 226
227void audiohw_set_sample_rate(int sampling_control) 227void audiohw_set_frequency(int fsel)
228{ 228{
229 int rate; 229 /* For 24MHz MCLK */
230 230 static const unsigned char srctrl_table[HW_NUM_FREQ] =
231 switch(sampling_control)
232 { 231 {
233 case SAMPR_96: 232 [HW_FREQ_8] = WMC_USB24_8000HZ,
234 rate = WMC_USB24_96000HZ; 233 [HW_FREQ_32] = WMC_USB24_32000HZ,
235 break; 234 [HW_FREQ_44] = WMC_USB24_44100HZ,
236 case SAMPR_88: 235 [HW_FREQ_48] = WMC_USB24_48000HZ,
237 rate = WMC_USB24_88200HZ; 236 [HW_FREQ_88] = WMC_USB24_88200HZ,
238 break; 237 [HW_FREQ_96] = WMC_USB24_96000HZ,
239 case SAMPR_48: 238 };
240 rate = WMC_USB24_48000HZ; 239
241 break; 240 if ((unsigned)fsel >= HW_NUM_FREQ)
242 default: 241 fsel = HW_FREQ_DEFAULT;
243 case SAMPR_44:
244 rate = WMC_USB24_44100HZ;
245 break;
246 case SAMPR_32:
247 rate = WMC_USB24_32000HZ;
248 break;
249 case SAMPR_8:
250 rate = WMC_USB24_8000HZ;
251 break;
252 }
253 242
254 codec_set_active(false); 243 codec_set_active(false);
255 wmc_write(SAMPCTRL, rate); 244 wmc_write(SAMPCTRL, srctrl_table[fsel]);
256 codec_set_active(true); 245 codec_set_active(true);
257} 246}
258 247
diff --git a/firmware/drivers/audio/wm8751.c b/firmware/drivers/audio/wm8751.c
index 2e0eb06dbf..79c7396629 100644
--- a/firmware/drivers/audio/wm8751.c
+++ b/firmware/drivers/audio/wm8751.c
@@ -229,8 +229,18 @@ void audiohw_close(void)
229 wmcodec_write(PWRMGMT1, 0x0); 229 wmcodec_write(PWRMGMT1, 0x0);
230} 230}
231 231
232/* Note: Disable output before calling this function */
233void audiohw_set_frequency(int fsel) 232void audiohw_set_frequency(int fsel)
234{ 233{
235 wmcodec_write(CLOCKING, fsel); 234 static const unsigned char srctrl_table[HW_NUM_FREQ] =
235 {
236 HW_HAVE_11_([HW_FREQ_11] = CODEC_SRCTRL_11025HZ,)
237 HW_HAVE_22_([HW_FREQ_22] = CODEC_SRCTRL_22050HZ,)
238 HW_HAVE_44_([HW_FREQ_44] = CODEC_SRCTRL_44100HZ,)
239 HW_HAVE_88_([HW_FREQ_88] = CODEC_SRCTRL_88200HZ,)
240 };
241
242 if ((unsigned)fsel >= HW_NUM_FREQ)
243 fsel = HW_FREQ_DEFAULT;
244
245 wmcodec_write(CLOCKING, srctrl_table[fsel]);
236} 246}
diff --git a/firmware/drivers/audio/wm8758.c b/firmware/drivers/audio/wm8758.c
index 8ebfbe8e26..defc415f98 100644
--- a/firmware/drivers/audio/wm8758.c
+++ b/firmware/drivers/audio/wm8758.c
@@ -107,7 +107,7 @@ void audiohw_preinit(void)
107 wmcodec_write(OUTCTRL, OUTCTRL_VROI); 107 wmcodec_write(OUTCTRL, OUTCTRL_VROI);
108 wmcodec_write(CLKCTRL, CLKCTRL_MS); /* WM8758 is clock master */ 108 wmcodec_write(CLKCTRL, CLKCTRL_MS); /* WM8758 is clock master */
109 109
110 audiohw_set_sample_rate(WM8758_44100HZ); 110 audiohw_set_sample_rate(HW_FREQ_44);
111 111
112 wmcodec_write(LOUTMIX, LOUTMIX_DACL2LMIX); 112 wmcodec_write(LOUTMIX, LOUTMIX_DACL2LMIX);
113 wmcodec_write(ROUTMIX, ROUTMIX_DACR2RMIX); 113 wmcodec_write(ROUTMIX, ROUTMIX_DACR2RMIX);
@@ -170,10 +170,10 @@ void audiohw_close(void)
170} 170}
171 171
172/* Note: Disable output before calling this function */ 172/* Note: Disable output before calling this function */
173void audiohw_set_sample_rate(int sampling_control) 173void audiohw_set_frequency(int fsel)
174{ 174{
175 /**** We force 44.1KHz for now. ****/ 175 /**** We force 44.1KHz for now. ****/
176 (void)sampling_control; 176 (void)fsel;
177 177
178 /* setup PLL for MHZ=11.2896 */ 178 /* setup PLL for MHZ=11.2896 */
179 wmcodec_write(PLLN, PLLN_PLLPRESCALE | 0x7); 179 wmcodec_write(PLLN, PLLN_PLLPRESCALE | 0x7);
diff --git a/firmware/drivers/audio/wm8975.c b/firmware/drivers/audio/wm8975.c
index aa519e8819..f14890db74 100644
--- a/firmware/drivers/audio/wm8975.c
+++ b/firmware/drivers/audio/wm8975.c
@@ -145,7 +145,7 @@ void audiohw_preinit(void)
145 145
146 wm8975_write(DAPCTRL, wm8975_regs[DAPCTRL] ); 146 wm8975_write(DAPCTRL, wm8975_regs[DAPCTRL] );
147 147
148 audiohw_set_sample_rate(WM8975_44100HZ); 148 wmcodec_write(SAMPCTRL, WM8975_44100HZ);
149 149
150 /* set the volume to -6dB */ 150 /* set the volume to -6dB */
151 wmcodec_write(LOUT1VOL, LOUT1VOL_LO1ZC | IPOD_PCM_LEVEL); 151 wmcodec_write(LOUT1VOL, LOUT1VOL_LO1ZC | IPOD_PCM_LEVEL);
@@ -224,9 +224,9 @@ void audiohw_close(void)
224} 224}
225 225
226/* Note: Disable output before calling this function */ 226/* Note: Disable output before calling this function */
227void audiohw_set_sample_rate(int sampling_control) 227void audiohw_set_frequency(int fsel)
228{ 228{
229 wmcodec_write(SAMPCTRL, sampling_control); 229 (void)fsel;
230} 230}
231 231
232#ifdef HAVE_RECORDING 232#ifdef HAVE_RECORDING
diff --git a/firmware/drivers/audio/wm8978.c b/firmware/drivers/audio/wm8978.c
index 6a7c974f43..d8bf05063f 100644
--- a/firmware/drivers/audio/wm8978.c
+++ b/firmware/drivers/audio/wm8978.c
@@ -363,9 +363,9 @@ void audiohw_mute(bool mute)
363 } 363 }
364} 364}
365 365
366void audiohw_set_frequency(int sampling_control) 366void audiohw_set_frequency(int fsel)
367{ 367{
368 /* For 16.9344MHz MCLK */ 368 /* For 16.9344MHz MCLK, codec as master. */
369 static const struct 369 static const struct
370 { 370 {
371 uint32_t plln : 8; 371 uint32_t plln : 8;
@@ -374,7 +374,7 @@ void audiohw_set_frequency(int sampling_control)
374 uint32_t pllk3 : 9; 374 uint32_t pllk3 : 9;
375 unsigned char mclkdiv; 375 unsigned char mclkdiv;
376 unsigned char filter; 376 unsigned char filter;
377 } sctrl_table[HW_NUM_FREQ] = 377 } srctrl_table[HW_NUM_FREQ] =
378 { 378 {
379 [HW_FREQ_8] = /* PLL = 65.536MHz */ 379 [HW_FREQ_8] = /* PLL = 65.536MHz */
380 { 380 {
@@ -450,16 +450,14 @@ void audiohw_set_frequency(int sampling_control)
450 unsigned int plln; 450 unsigned int plln;
451 unsigned int mclkdiv; 451 unsigned int mclkdiv;
452 452
453 if ((unsigned)sampling_control >= ARRAYLEN(sctrl_table)) 453 if ((unsigned)fsel >= HW_NUM_FREQ)
454 sampling_control = HW_FREQ_DEFAULT; 454 fsel = HW_FREQ_DEFAULT;
455
456 455
457 /* Setup filters. */ 456 /* Setup filters. */
458 wmc_write(WMC_ADDITIONAL_CTRL, 457 wmc_write(WMC_ADDITIONAL_CTRL, srctrl_table[fsel].filter);
459 sctrl_table[sampling_control].filter);
460 458
461 plln = sctrl_table[sampling_control].plln; 459 plln = srctrl_table[fsel].plln;
462 mclkdiv = sctrl_table[sampling_control].mclkdiv; 460 mclkdiv = srctrl_table[fsel].mclkdiv;
463 461
464 if (plln != 0) 462 if (plln != 0)
465 { 463 {
@@ -467,9 +465,9 @@ void audiohw_set_frequency(int sampling_control)
467 465
468 /* Program PLL. */ 466 /* Program PLL. */
469 wmc_write(WMC_PLL_N, plln); 467 wmc_write(WMC_PLL_N, plln);
470 wmc_write(WMC_PLL_K1, sctrl_table[sampling_control].pllk1); 468 wmc_write(WMC_PLL_K1, srctrl_table[fsel].pllk1);
471 wmc_write(WMC_PLL_K2, sctrl_table[sampling_control].pllk2); 469 wmc_write(WMC_PLL_K2, srctrl_table[fsel].pllk2);
472 wmc_write(WMC_PLL_K3, sctrl_table[sampling_control].pllk3); 470 wmc_write(WMC_PLL_K3, srctrl_table[fsel].pllk3);
473 471
474 /* Turn on PLL. */ 472 /* Turn on PLL. */
475 wmc_set(WMC_POWER_MANAGEMENT1, WMC_PLLEN); 473 wmc_set(WMC_POWER_MANAGEMENT1, WMC_PLLEN);
diff --git a/firmware/drivers/audio/wm8985.c b/firmware/drivers/audio/wm8985.c
index 0467e3718a..f7b2e510ae 100644
--- a/firmware/drivers/audio/wm8985.c
+++ b/firmware/drivers/audio/wm8985.c
@@ -235,12 +235,12 @@ void audiohw_close(void)
235} 235}
236 236
237/* Note: Disable output before calling this function */ 237/* Note: Disable output before calling this function */
238void audiohw_set_sample_rate(int sampling_control) 238void audiohw_set_sample_rate(int fsel)
239{ 239{
240 /* Currently the WM8985 acts as slave to the SoC I2S controller, so no 240 /* Currently the WM8985 acts as slave to the SoC I2S controller, so no
241 setup is needed here. This seems to be in contrast to every other WM 241 setup is needed here. This seems to be in contrast to every other WM
242 driver in Rockbox, so this may need to change in the future. */ 242 driver in Rockbox, so this may need to change in the future. */
243 (void)sampling_control; 243 (void)fsel;
244} 244}
245 245
246#ifdef HAVE_RECORDING 246#ifdef HAVE_RECORDING
@@ -261,7 +261,7 @@ void audiohw_enable_recording(bool source_mic)
261 261
262 /* The iPod can handle multiple frequencies, but fix at 44.1KHz 262 /* The iPod can handle multiple frequencies, but fix at 44.1KHz
263 for now */ 263 for now */
264 audiohw_set_sample_rate(WM8985_44100HZ); 264 audiohw_set_frequency(HW_FREQ_DEFAULT);
265 265
266 wmcodec_write(INCTRL,0x44); /* Connect L2 and R2 inputs */ 266 wmcodec_write(INCTRL,0x44); /* Connect L2 and R2 inputs */
267 267
diff --git a/firmware/export/as3514.h b/firmware/export/as3514.h
index af4615a15e..07aa0ebfe2 100644
--- a/firmware/export/as3514.h
+++ b/firmware/export/as3514.h
@@ -26,7 +26,7 @@ extern int tenthdb2master(int db);
26 26
27extern void audiohw_set_master_vol(int vol_l, int vol_r); 27extern void audiohw_set_master_vol(int vol_l, int vol_r);
28extern void audiohw_set_lineout_vol(int vol_l, int vol_r); 28extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
29extern void audiohw_set_sample_rate(int sampling_control); 29extern void audiohw_set_frequency(int fsel);
30 30
31/* Register Descriptions */ 31/* Register Descriptions */
32#define AS3514_LINE_OUT_R 0x00 32#define AS3514_LINE_OUT_R 0x00
diff --git a/firmware/export/config-gigabeat.h b/firmware/export/config-gigabeat.h
index 664befd54e..708c17fd8a 100644
--- a/firmware/export/config-gigabeat.h
+++ b/firmware/export/config-gigabeat.h
@@ -105,6 +105,12 @@
105#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \ 105#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \
106 SAMPR_CAP_11) 106 SAMPR_CAP_11)
107 107
108/* All exact rates for 16.9344MHz clock */
109#define CODEC_SRCTRL_11025HZ (0x19 << 1)
110#define CODEC_SRCTRL_22050HZ (0x1b << 1)
111#define CODEC_SRCTRL_44100HZ (0x11 << 1)
112#define CODEC_SRCTRL_88200HZ (0x1f << 1)
113
108#define HAVE_HEADPHONE_DETECTION 114#define HAVE_HEADPHONE_DETECTION
109 115
110#define BATTERY_CAPACITY_DEFAULT 2000 /* default battery capacity */ 116#define BATTERY_CAPACITY_DEFAULT 2000 /* default battery capacity */
diff --git a/firmware/export/config-mrobe100.h b/firmware/export/config-mrobe100.h
index 051f15824f..4ade179c04 100644
--- a/firmware/export/config-mrobe100.h
+++ b/firmware/export/config-mrobe100.h
@@ -58,6 +58,7 @@
58 58
59/* Wolfsom audio codec */ 59/* Wolfsom audio codec */
60#define HAVE_WM8751 60#define HAVE_WM8751
61#define CODEC_SRCTRL_44100HZ (0x40|(0x11 << 1)|1)
61 62
62#define AB_REPEAT_ENABLE 1 63#define AB_REPEAT_ENABLE 1
63 64
diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h
index 1660f0670d..ac8ddb1b3c 100644
--- a/firmware/export/pcm.h
+++ b/firmware/export/pcm.h
@@ -57,7 +57,7 @@ typedef int (*pcm_more_callback_type2)(int status);
57/* set the pcm frequency - use values in hw_sampr_list 57/* set the pcm frequency - use values in hw_sampr_list
58 * use -1 for the default frequency 58 * use -1 for the default frequency
59 */ 59 */
60void pcm_set_frequency(unsigned int frequency); 60void pcm_set_frequency(unsigned int samplerate);
61/* apply settings to hardware immediately */ 61/* apply settings to hardware immediately */
62void pcm_apply_settings(void); 62void pcm_apply_settings(void);
63 63
@@ -87,6 +87,8 @@ bool pcm_is_playing(void);
87 specific portion **/ 87 specific portion **/
88 88
89extern unsigned long pcm_curr_sampr; 89extern unsigned long pcm_curr_sampr;
90extern unsigned long pcm_sampr;
91extern int pcm_fsel;
90 92
91/* the registered callback function to ask for more mp3 data */ 93/* the registered callback function to ask for more mp3 data */
92extern volatile pcm_more_callback_type pcm_callback_for_more; 94extern volatile pcm_more_callback_type pcm_callback_for_more;
@@ -102,6 +104,8 @@ void pcm_play_dma_pause(bool pause);
102void pcm_play_dma_stopped_callback(void); 104void pcm_play_dma_stopped_callback(void);
103const void * pcm_play_dma_get_peak_buffer(int *count); 105const void * pcm_play_dma_get_peak_buffer(int *count);
104 106
107void pcm_dma_apply_settings(void);
108
105#ifdef HAVE_RECORDING 109#ifdef HAVE_RECORDING
106 110
107/** RAW PCM recording routines **/ 111/** RAW PCM recording routines **/
diff --git a/firmware/export/pp5002.h b/firmware/export/pp5002.h
index b235a2154b..9fab86bf21 100644
--- a/firmware/export/pp5002.h
+++ b/firmware/export/pp5002.h
@@ -34,19 +34,64 @@
34#define LCD1_BUSY_MASK 0x8000 34#define LCD1_BUSY_MASK 0x8000
35 35
36/* I2S controller */ 36/* I2S controller */
37
38/* FIFO slot bits 7-0 are not implemented and so use of packed samples
39 * appears to be impossible. */
37#define IISCONFIG (*(volatile unsigned long *)(0xc0002500)) 40#define IISCONFIG (*(volatile unsigned long *)(0xc0002500))
38#define IISFIFO_CFG (*(volatile unsigned long *)(0xc000251c)) 41#define IISFIFO_CFG (*(volatile unsigned long *)(0xc000251c))
39#define IISFIFO_WR (*(volatile unsigned long *)(0xc0002540)) 42#define IISFIFO_WR (*(volatile unsigned long *)(0xc0002540))
40#define IISFIFO_RD (*(volatile unsigned long *)(0xc0002580)) 43#define IISFIFO_RD (*(volatile unsigned long *)(0xc0002580))
41 44
42/* IISCONFIG bits: */ 45/**
46 * IISCONFIG bits:
47 * | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 |
48 * | | | | | | | | |
49 * | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
50 * | | | | | | | | |
51 * | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 |
52 * | | | | | | | | |
53 * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
54 * | rw | rw | rw | MS | rw |TXFENB# | rw | ENB |
55 *
56 * # No effect observed on iPod 3g
57 */
58#define IIS_ENABLE (1 << 0)
43#define IIS_TXFIFOEN (1 << 2) 59#define IIS_TXFIFOEN (1 << 2)
44#define IIS_TX_FREE_MASK (0xf << 23) 60#define IIS_MASTER (1 << 4)
61
62/**
63 * IISFIFO_CFG bits:
64 * | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 |
65 * | | RXFull[3:0]$ | TXFree[3:1] >
66 * | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
67 * >TXFre[0]| | | | | | RXCLR | TXCLR |
68 * | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 |
69 * | rw | rw | rw | rw | rw | rw | IRQTX | rw |
70 * | 7* | 6* | 5* | 4* | 3 | 2 | 1 | 0 |
71 * |RXEMPTY | RXSAFE | RXDNGR | RXFULL | TXFULL | TXSAFE | TXDNGR |TXEMPTY |
72 *
73 * $Could be RXFree
74 * *Meaning isn't certain yet.
75 * More concerted recording work will reveal.
76 */
77#define IIS_IRQTX_REG IISFIFO_CFG
78#define IIS_IRQRX_REG IISFIFO_CFG
79
80#define IIS_RX_FULL_MASK (0xf << 27)
81#define IIS_RX_FULL_COUNT ((IISFIFO_CFG & IIS_RX_FULL_MASK) >> 27)
82#define IIS_TX_FREE_MASK (0xf << 23) /* 0xf = 16 or 15 free */
45#define IIS_TX_FREE_COUNT ((IISFIFO_CFG & IIS_TX_FREE_MASK) >> 23) 83#define IIS_TX_FREE_COUNT ((IISFIFO_CFG & IIS_TX_FREE_MASK) >> 23)
84#define IIS_TX_IS_EMPTY ((IISFIFO_CFG & IIS_TXEMPTY) != 0)
85
86#define IIS_RXCLR (1 << 17) /* Resets *could* be reversed */
87#define IIS_TXCLR (1 << 16)
88#define IIS_IRQTX (1 << 9)
89#define IIS_TXFULL (1 << 3) /* All slots occupied */
90#define IIS_TXSAFE (1 << 2) /* FIFO >= 3/4 full */
91#define IIS_TXDANGER (1 << 1) /* FIFO <= 1/4 full */
92#define IIS_TXEMPTY (1 << 0) /* No samples in FIFO */
46 93
47/* IISFIFO_CFG bits: */ 94#define IIS_RXEMPTY (1 << 4) /* FIFO is empty */
48#define IIS_IRQTX_REG IISFIFO_CFG
49#define IIS_IRQTX (1 << 9)
50 95
51#define IDE_BASE 0xc0003000 96#define IDE_BASE 0xc0003000
52 97
@@ -184,6 +229,7 @@
184#define DEV_RS (*(volatile unsigned long *)(0xcf005030)) 229#define DEV_RS (*(volatile unsigned long *)(0xcf005030))
185 230
186#define DEV_I2C (1<<8) 231#define DEV_I2C (1<<8)
232#define DEV_I2S (1<<7)
187#define DEV_USB 0x400000 233#define DEV_USB 0x400000
188 234
189#define CLOCK_ENABLE (*(volatile unsigned long *)(0xcf005008)) 235#define CLOCK_ENABLE (*(volatile unsigned long *)(0xcf005008))
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h
index 908fed0087..b4919a219e 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -431,6 +431,9 @@
431#define IIS_TX_FREE_COUNT \ 431#define IIS_TX_FREE_COUNT \
432 ((IISFIFO_CFG & IIS_TX_FREE_MASK) >> 16) 432 ((IISFIFO_CFG & IIS_TX_FREE_MASK) >> 16)
433 433
434#define IIS_TX_IS_EMPTY \
435 ((IISFIFO_CFG & IIS_TX_FREE_MASK) >= (16 << 16))
436
434#define IIS_RXCLR (1 << 12) 437#define IIS_RXCLR (1 << 12)
435#define IIS_TXCLR (1 << 8) 438#define IIS_TXCLR (1 << 8)
436/* Number of slots */ 439/* Number of slots */
diff --git a/firmware/export/tlv320.h b/firmware/export/tlv320.h
index 91c4a67623..171223f5bb 100644
--- a/firmware/export/tlv320.h
+++ b/firmware/export/tlv320.h
@@ -38,7 +38,7 @@ extern int tenthdb2master(int db);
38 * 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default) 38 * 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default)
39 * 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2 39 * 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2
40 */ 40 */
41extern void audiohw_set_frequency(unsigned fsel); 41extern void audiohw_set_frequency(int fsel);
42extern void audiohw_set_headphone_vol(int vol_l, int vol_r); 42extern void audiohw_set_headphone_vol(int vol_l, int vol_r);
43 43
44#define HEADPHONE_MUTE 0x30 /* 0110000 = -73db */ 44#define HEADPHONE_MUTE 0x30 /* 0110000 = -73db */
diff --git a/firmware/export/uda1380.h b/firmware/export/uda1380.h
index 26b13a968f..af2b579a60 100644
--- a/firmware/export/uda1380.h
+++ b/firmware/export/uda1380.h
@@ -36,6 +36,8 @@ extern void audiohw_set_mixer_vol(int channel1, int channel2);
36 36
37/** 37/**
38 * Sets frequency settings for DAC and ADC relative to MCLK 38 * Sets frequency settings for DAC and ADC relative to MCLK
39 * For Coldfire IIS dividers, 11.2896MHz, codec as slave with
40 * PLL enabled.
39 * 41 *
40 * Selection for frequency ranges: 42 * Selection for frequency ranges:
41 * Fs: range: with: 43 * Fs: range: with:
@@ -44,7 +46,7 @@ extern void audiohw_set_mixer_vol(int channel1, int channel2);
44 * 44100: 2 = 25 to 50 SCLK, LRCK: Audio Clk / 4 (default) 46 * 44100: 2 = 25 to 50 SCLK, LRCK: Audio Clk / 4 (default)
45 * 88200: 3 = 50 to 100 SCLK, LRCK: Audio Clk / 2 47 * 88200: 3 = 50 to 100 SCLK, LRCK: Audio Clk / 2
46 */ 48 */
47extern void audiohw_set_frequency(unsigned fsel); 49extern void audiohw_set_frequency(int fsel);
48 50
49#define UDA1380_ADDR 0x30 51#define UDA1380_ADDR 0x30
50 52
diff --git a/firmware/export/wm8731.h b/firmware/export/wm8731.h
index 9d5b61833f..512ef9ff3f 100644
--- a/firmware/export/wm8731.h
+++ b/firmware/export/wm8731.h
@@ -31,7 +31,7 @@
31extern int tenthdb2master(int db); 31extern int tenthdb2master(int db);
32 32
33extern void audiohw_set_master_vol(int vol_l, int vol_r); 33extern void audiohw_set_master_vol(int vol_l, int vol_r);
34extern void audiohw_set_sample_rate(int sampling_control); 34extern void audiohw_set_frequency(int fsel);
35 35
36/* Common register bits */ 36/* Common register bits */
37#ifdef HAVE_WM8731 37#ifdef HAVE_WM8731
diff --git a/firmware/export/wm8758.h b/firmware/export/wm8758.h
index c094b1296a..493d18b753 100644
--- a/firmware/export/wm8758.h
+++ b/firmware/export/wm8758.h
@@ -34,7 +34,7 @@ extern int tenthdb2mixer(int db);
34extern void audiohw_set_master_vol(int vol_l, int vol_r); 34extern void audiohw_set_master_vol(int vol_l, int vol_r);
35extern void audiohw_set_lineout_vol(int vol_l, int vol_r); 35extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
36extern void audiohw_set_mixer_vol(int channel1, int channel2); 36extern void audiohw_set_mixer_vol(int channel1, int channel2);
37extern void audiohw_set_sample_rate(int sampling_control); 37extern void audiohw_set_frequency(int fsel);
38 38
39#define RESET 0x00 39#define RESET 0x00
40#define RESET_RESET 0x0 40#define RESET_RESET 0x0
diff --git a/firmware/export/wm8975.h b/firmware/export/wm8975.h
index e2e443213a..aeec33e3d8 100644
--- a/firmware/export/wm8975.h
+++ b/firmware/export/wm8975.h
@@ -32,7 +32,7 @@ extern int tenthdb2master(int db);
32 32
33extern void audiohw_set_master_vol(int vol_l, int vol_r); 33extern void audiohw_set_master_vol(int vol_l, int vol_r);
34extern void audiohw_set_lineout_vol(int vol_l, int vol_r); 34extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
35extern void audiohw_set_sample_rate(int sampling_control); 35extern void audiohw_set_frequency(int fsel);
36 36
37/* Register addresses and bits */ 37/* Register addresses and bits */
38 38
diff --git a/firmware/export/wm8978.h b/firmware/export/wm8978.h
index 9c54ae354d..f444c96a29 100644
--- a/firmware/export/wm8978.h
+++ b/firmware/export/wm8978.h
@@ -28,7 +28,7 @@
28 28
29int tenthdb2master(int db); 29int tenthdb2master(int db);
30void audiohw_set_headphone_vol(int vol_l, int vol_r); 30void audiohw_set_headphone_vol(int vol_l, int vol_r);
31void audiohw_set_frequency(int sampling_control); 31void audiohw_set_frequency(int fsel);
32 32
33void wmc_set(unsigned int reg, unsigned int bits); 33void wmc_set(unsigned int reg, unsigned int bits);
34void wmc_clear(unsigned int reg, unsigned int bits); 34void wmc_clear(unsigned int reg, unsigned int bits);
diff --git a/firmware/pcm.c b/firmware/pcm.c
index ddf5095725..ea451a0b9f 100644
--- a/firmware/pcm.c
+++ b/firmware/pcm.c
@@ -24,6 +24,7 @@
24#include "logf.h" 24#include "logf.h"
25#include "audio.h" 25#include "audio.h"
26#include "sound.h" 26#include "sound.h"
27#include "general.h"
27 28
28/** 29/**
29 * Aspects implemented in the target-specific portion: 30 * Aspects implemented in the target-specific portion:
@@ -42,11 +43,17 @@
42 * pcm_play_dma_pause 43 * pcm_play_dma_pause
43 * pcm_play_dma_get_peak_buffer 44 * pcm_play_dma_get_peak_buffer
44 * Data Read/Written within TSP - 45 * Data Read/Written within TSP -
45 * pcm_curr_sampr (RW) 46 * pcm_sampr (R)
47 * pcm_fsel (R)
48 * pcm_curr_sampr (R)
46 * pcm_callback_for_more (R) 49 * pcm_callback_for_more (R)
47 * pcm_playing (R) 50 * pcm_playing (R)
48 * pcm_paused (R) 51 * pcm_paused (R)
49 * 52 *
53 * ==Playback/Recording==
54 * Semi-private -
55 * pcm_dma_apply_settings
56 *
50 * ==Recording== 57 * ==Recording==
51 * Public - 58 * Public -
52 * pcm_rec_lock 59 * pcm_rec_lock
@@ -76,6 +83,10 @@ volatile bool pcm_playing SHAREDBSS_ATTR = false;
76volatile bool pcm_paused SHAREDBSS_ATTR = false; 83volatile bool pcm_paused SHAREDBSS_ATTR = false;
77/* samplerate of currently playing audio - undefined if stopped */ 84/* samplerate of currently playing audio - undefined if stopped */
78unsigned long pcm_curr_sampr SHAREDBSS_ATTR = 0; 85unsigned long pcm_curr_sampr SHAREDBSS_ATTR = 0;
86/* samplerate waiting to be set */
87unsigned long pcm_sampr SHAREDBSS_ATTR = HW_SAMPR_DEFAULT;
88/* samplerate frequency selection index */
89int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
79 90
80/** 91/**
81 * Do peak calculation using distance squared from axis and save a lot 92 * Do peak calculation using distance squared from axis and save a lot
@@ -179,6 +190,8 @@ void pcm_init(void)
179 190
180 pcm_play_dma_stopped_callback(); 191 pcm_play_dma_stopped_callback();
181 192
193 pcm_set_frequency(HW_SAMPR_DEFAULT);
194
182 logf(" pcm_play_dma_init"); 195 logf(" pcm_play_dma_init");
183 pcm_play_dma_init(); 196 pcm_play_dma_init();
184} 197}
@@ -221,6 +234,8 @@ void pcm_play_data(pcm_more_callback_type get_more,
221 234
222 pcm_callback_for_more = get_more; 235 pcm_callback_for_more = get_more;
223 236
237 pcm_apply_settings();
238
224 logf(" pcm_play_data_start"); 239 logf(" pcm_play_data_start");
225 pcm_play_data_start(start, size); 240 pcm_play_data_start(start, size);
226 241
@@ -241,16 +256,21 @@ void pcm_play_pause(bool play)
241 pcm_play_dma_pause(true); 256 pcm_play_dma_pause(true);
242 pcm_paused = true; 257 pcm_paused = true;
243 } 258 }
244 else if (pcm_get_bytes_waiting() > 0)
245 {
246 logf(" pcm_play_dma_pause");
247 pcm_play_dma_pause(false);
248 pcm_paused = false;
249 }
250 else 259 else
251 { 260 {
252 logf(" pcm_play_dma_start: no data"); 261 pcm_apply_settings();
253 pcm_play_data_start(NULL, 0); 262
263 if (pcm_get_bytes_waiting() > 0)
264 {
265 logf(" pcm_play_dma_pause");
266 pcm_play_dma_pause(false);
267 pcm_paused = false;
268 }
269 else
270 {
271 logf(" pcm_play_dma_start: no data");
272 pcm_play_data_start(NULL, 0);
273 }
254 } 274 }
255 } 275 }
256 else 276 else
@@ -290,6 +310,35 @@ void pcm_play_dma_stopped_callback(void)
290 310
291/**/ 311/**/
292 312
313/* set frequency next frequency used by the audio hardware -
314 * what pcm_apply_settings will set */
315void pcm_set_frequency(unsigned int samplerate)
316{
317 logf("pcm_set_frequency");
318
319 int index = round_value_to_list32(samplerate, hw_freq_sampr,
320 HW_NUM_FREQ, false);
321
322 if (samplerate != hw_freq_sampr[index])
323 index = HW_FREQ_DEFAULT; /* Invalid = default */
324
325 pcm_sampr = hw_freq_sampr[index];
326 pcm_fsel = index;
327}
328
329/* apply pcm settings to the hardware */
330void pcm_apply_settings(void)
331{
332 logf("pcm_apply_settings");
333
334 if (pcm_sampr != pcm_curr_sampr)
335 {
336 logf(" pcm_dma_apply_settings");
337 pcm_dma_apply_settings();
338 pcm_curr_sampr = pcm_sampr;
339 }
340}
341
293bool pcm_is_playing(void) 342bool pcm_is_playing(void)
294{ 343{
295 return pcm_playing; 344 return pcm_playing;
@@ -411,6 +460,7 @@ void pcm_record_data(pcm_more_callback_type2 more_ready,
411 pcm_callback_more_ready = more_ready; 460 pcm_callback_more_ready = more_ready;
412 461
413 logf(" pcm_rec_dma_start"); 462 logf(" pcm_rec_dma_start");
463 pcm_apply_settings();
414 pcm_rec_dma_start(start, size); 464 pcm_rec_dma_start(start, size);
415 pcm_recording = true; 465 pcm_recording = true;
416 466
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c
index d47f80ae77..fe694e0967 100644
--- a/firmware/target/arm/as3525/pcm-as3525.c
+++ b/firmware/target/arm/as3525/pcm-as3525.c
@@ -138,8 +138,10 @@ void pcm_postinit(void)
138 pcm_apply_settings(); 138 pcm_apply_settings();
139} 139}
140 140
141void pcm_set_frequency(unsigned int frequency) 141void pcm_dma_apply_settings(void)
142{ 142{
143 unsigned long frequency = pcm_sampr;
144
143 const int divider = (((AS3525_PLLA_FREQ/128) + (frequency/2)) / frequency) - 1; 145 const int divider = (((AS3525_PLLA_FREQ/128) + (frequency/2)) / frequency) - 1;
144 if(divider < 0 || divider > 511) 146 if(divider < 0 || divider > 511)
145 panicf("unsupported frequency %d", frequency); 147 panicf("unsupported frequency %d", frequency);
@@ -147,13 +149,6 @@ void pcm_set_frequency(unsigned int frequency)
147 CGU_AUDIO &= ~(((511 ^ divider) << 2) /* I2SOUT */ 149 CGU_AUDIO &= ~(((511 ^ divider) << 2) /* I2SOUT */
148 /*| ((511 ^ divider) << 14) */ /* I2SIN */ 150 /*| ((511 ^ divider) << 14) */ /* I2SIN */
149 ); 151 );
150
151 pcm_curr_sampr = frequency;
152}
153
154void pcm_apply_settings(void)
155{
156 pcm_set_frequency(HW_SAMPR_DEFAULT);
157} 152}
158 153
159size_t pcm_get_bytes_waiting(void) 154size_t pcm_get_bytes_waiting(void)
diff --git a/firmware/target/arm/audio-pp.c b/firmware/target/arm/audio-pp.c
index ba52118e0f..b170518af4 100644
--- a/firmware/target/arm/audio-pp.c
+++ b/firmware/target/arm/audio-pp.c
@@ -40,6 +40,23 @@ void audio_input_mux(int source, unsigned flags)
40 static bool last_recording = false; 40 static bool last_recording = false;
41#endif 41#endif
42 42
43#if defined(IPOD_COLOR) || defined (IPOD_4G)
44 /* The usual magic from IPL - I'm guessing this configures the headphone
45 socket to be input or output. */
46 if (recording && source != AUDIO_SRC_PLAYBACK)
47 {
48 /* input */
49 GPIO_CLEAR_BITWISE(GPIOI_OUTPUT_VAL, 0x40);
50 GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_VAL, 0x04);
51 }
52 else
53 {
54 /* output */
55 GPIO_SET_BITWISE(GPIOI_OUTPUT_VAL, 0x40);
56 GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x04);
57 }
58#endif /* IPOD_COLOR || IPOD_4G */
59
43 switch (source) 60 switch (source)
44 { 61 {
45 default: /* playback - no recording */ 62 default: /* playback - no recording */
@@ -109,4 +126,3 @@ void audio_input_mux(int source, unsigned flags)
109 last_source = source; 126 last_source = source;
110} /* audio_input_mux */ 127} /* audio_input_mux */
111#endif /* INPUT_SRC_CAPS != 0 */ 128#endif /* INPUT_SRC_CAPS != 0 */
112
diff --git a/firmware/target/arm/i2s-pp.c b/firmware/target/arm/i2s-pp.c
index c96a559a8a..81c1fa1265 100644
--- a/firmware/target/arm/i2s-pp.c
+++ b/firmware/target/arm/i2s-pp.c
@@ -25,28 +25,22 @@
25 * KIND, either express or implied. 25 * KIND, either express or implied.
26 * 26 *
27 ****************************************************************************/ 27 ****************************************************************************/
28
29#include "system.h" 28#include "system.h"
30#include "cpu.h" 29#include "cpu.h"
31#include "i2s.h" 30#include "i2s.h"
32 31
33/* TODO: Add in PP5002 defs */
34#if CONFIG_CPU == PP5002 32#if CONFIG_CPU == PP5002
35void i2s_reset(void) 33void i2s_reset(void)
36{ 34{
37 /* I2S device reset */ 35 /* I2S device reset */
38 DEV_RS |= 0x80; 36 DEV_RS |= DEV_I2S;
39 DEV_RS &= ~0x80; 37 DEV_RS &= ~DEV_I2S;
40 38
41 /* I2S controller enable */ 39 /* I2S controller enable */
42 IISCONFIG |= 1; 40 IISCONFIG |= IIS_ENABLE;
43
44 /* BIT.FORMAT [11:10] = I2S (default) */
45 /* BIT.SIZE [9:8] = 24bit */
46 /* FIFO.FORMAT = 24 bit LSB */
47 41
48 /* reset DAC and ADC fifo */ 42 /* reset DAC and ADC fifo */
49 IISFIFO_CFG |= 0x30000; 43 IISFIFO_CFG |= IIS_RXCLR | IIS_TXCLR;
50} 44}
51#else /* PP502X */ 45#else /* PP502X */
52 46
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
index 99aa66a781..48f7f608d9 100644
--- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
@@ -37,9 +37,6 @@ struct dma_data
37 int state; 37 int state;
38}; 38};
39 39
40static unsigned long pcm_freq; /* 44.1 is default */
41static int sr_ctrl;
42
43static struct dma_data dma_play_data = 40static struct dma_data dma_play_data =
44{ 41{
45 /* Initialize to a locked, stopped state */ 42 /* Initialize to a locked, stopped state */
@@ -67,15 +64,6 @@ void pcm_play_unlock(void)
67 } 64 }
68} 65}
69 66
70static void _pcm_apply_settings(void)
71{
72 if (pcm_freq != pcm_curr_sampr)
73 {
74 pcm_curr_sampr = pcm_freq;
75 audiohw_set_frequency(sr_ctrl);
76 }
77}
78
79static void __attribute__((interrupt("IRQ"))) SSI1_HANDLER(void) 67static void __attribute__((interrupt("IRQ"))) SSI1_HANDLER(void)
80{ 68{
81 register pcm_more_callback_type get_more; 69 register pcm_more_callback_type get_more;
@@ -109,19 +97,9 @@ static void __attribute__((interrupt("IRQ"))) SSI1_HANDLER(void)
109 pcm_play_dma_stopped_callback(); 97 pcm_play_dma_stopped_callback();
110} 98}
111 99
112void pcm_apply_settings(void) 100void pcm_dma_apply_settings(void)
113{ 101{
114 pcm_play_lock(); 102 audiohw_set_frequency(pcm_fsel);
115#ifdef HAVE_RECORDING
116 pcm_rec_lock();
117#endif
118
119 _pcm_apply_settings();
120
121#ifdef HAVE_RECORDING
122 pcm_rec_unlock();
123#endif
124 pcm_play_unlock();
125} 103}
126 104
127void pcm_play_dma_init(void) 105void pcm_play_dma_init(void)
@@ -214,7 +192,6 @@ void pcm_play_dma_init(void)
214 /* Enable SSI2 (codec clock) */ 192 /* Enable SSI2 (codec clock) */
215 SSI_SCR2 |= SSI_SCR_SSIEN; 193 SSI_SCR2 |= SSI_SCR_SSIEN;
216 194
217 pcm_set_frequency(HW_SAMPR_DEFAULT);
218 audiohw_init(); 195 audiohw_init();
219} 196}
220 197
@@ -230,7 +207,7 @@ static void play_start_pcm(void)
230 SSI_SCR1 &= ~SSI_SCR_TE; 207 SSI_SCR1 &= ~SSI_SCR_TE;
231 208
232 /* Apply new settings */ 209 /* Apply new settings */
233 _pcm_apply_settings(); 210 pcm_apply_settings();
234 211
235 /* Enable interrupt on unlock */ 212 /* Enable interrupt on unlock */
236 dma_play_data.state = 1; 213 dma_play_data.state = 1;
@@ -296,52 +273,6 @@ void pcm_play_dma_pause(bool pause)
296 } 273 }
297} 274}
298 275
299/* Set the pcm frequency hardware will use when play is next started or
300 when pcm_apply_settings is called. Do not apply the setting to the
301 hardware here but simply cache it. */
302void pcm_set_frequency(unsigned int frequency)
303{
304 int index;
305
306 switch (frequency)
307 {
308 case SAMPR_48:
309 index = HW_FREQ_48;
310 break;
311 case SAMPR_44:
312 index = HW_FREQ_44;
313 break;
314 case SAMPR_32:
315 index = HW_FREQ_32;
316 break;
317 case SAMPR_24:
318 index = HW_FREQ_24;
319 break;
320 case SAMPR_22:
321 index = HW_FREQ_22;
322 break;
323 case SAMPR_16:
324 index = HW_FREQ_16;
325 break;
326 case SAMPR_12:
327 index = HW_FREQ_12;
328 break;
329 case SAMPR_11:
330 index = HW_FREQ_11;
331 break;
332 case SAMPR_8:
333 index = HW_FREQ_8;
334 break;
335 default:
336 /* Invalid = default */
337 frequency = HW_SAMPR_DEFAULT;
338 index = HW_FREQ_DEFAULT;
339 }
340
341 pcm_freq = frequency;
342 sr_ctrl = index;
343}
344
345/* Return the number of bytes waiting - full L-R sample pairs only */ 276/* Return the number of bytes waiting - full L-R sample pairs only */
346size_t pcm_get_bytes_waiting(void) 277size_t pcm_get_bytes_waiting(void)
347{ 278{
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index deaa20b6be..e00b1d7e75 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -25,10 +25,7 @@
25#include "audio.h" 25#include "audio.h"
26#include "sound.h" 26#include "sound.h"
27#include "pcm.h" 27#include "pcm.h"
28 28#include "pcm_sampr.h"
29#ifdef HAVE_WM8751
30#define MROBE100_44100HZ (0x40|(0x11 << 1)|1)
31#endif
32 29
33/** DMA **/ 30/** DMA **/
34 31
@@ -87,36 +84,9 @@ static struct dma_data dma_play_data SHAREDBSS_ATTR =
87 .state = 0 84 .state = 0
88}; 85};
89 86
90static unsigned long pcm_freq SHAREDDATA_ATTR = HW_SAMPR_DEFAULT; /* 44.1 is default */ 87void pcm_dma_apply_settings(void)
91#ifdef HAVE_WM8751
92/* Samplerate control for audio codec */
93static int sr_ctrl = MROBE100_44100HZ;
94#endif
95
96void pcm_set_frequency(unsigned int frequency)
97{
98#if defined(HAVE_WM8731) || defined(HAVE_WM8721)
99 pcm_freq = frequency;
100#else
101 (void)frequency;
102 pcm_freq = HW_SAMPR_DEFAULT;
103#endif
104#ifdef HAVE_WM8751
105 sr_ctrl = MROBE100_44100HZ;
106#endif
107}
108
109void pcm_apply_settings(void)
110{ 88{
111#ifdef HAVE_WM8751 89 audiohw_set_frequency(pcm_fsel);
112 audiohw_set_frequency(sr_ctrl);
113#endif
114
115#if defined(HAVE_WM8711) || defined(HAVE_WM8721) \
116 || defined(HAVE_WM8731)
117 audiohw_set_sample_rate(pcm_freq);
118#endif
119 pcm_curr_sampr = pcm_freq;
120} 90}
121 91
122/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by 92/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by
@@ -330,9 +300,7 @@ static void play_stop_pcm(void)
330 IIS_IRQTX_REG &= ~IIS_IRQTX; 300 IIS_IRQTX_REG &= ~IIS_IRQTX;
331 301
332 /* Wait for FIFO to empty */ 302 /* Wait for FIFO to empty */
333#ifdef CPU_PP502x 303 while (!IIS_TX_IS_EMPTY);
334 while (IIS_TX_FREE_COUNT < 16);
335#endif
336 304
337 dma_play_data.state = 0; 305 dma_play_data.state = 0;
338} 306}
@@ -397,8 +365,6 @@ void pcm_play_dma_init(void)
397 : [iiscfg]"r"(iiscfg), [dmapd]"r"(dmapd) 365 : [iiscfg]"r"(iiscfg), [dmapd]"r"(dmapd)
398 : "r2"); 366 : "r2");
399 367
400 pcm_set_frequency(SAMPR_44);
401
402 /* Initialize default register values. */ 368 /* Initialize default register values. */
403 audiohw_init(); 369 audiohw_init();
404 370
@@ -620,24 +586,10 @@ void pcm_rec_dma_start(void *addr, size_t size)
620void pcm_rec_dma_close(void) 586void pcm_rec_dma_close(void)
621{ 587{
622 pcm_rec_dma_stop(); 588 pcm_rec_dma_stop();
623
624#if defined(IPOD_COLOR) || defined (IPOD_4G)
625 /* The usual magic from IPL - I'm guessing this configures the headphone
626 socket to be input or output - in this case, output. */
627 GPIO_SET_BITWISE(GPIOI_OUTPUT_VAL, 0x40);
628 GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x04);
629#endif
630} /* pcm_close_recording */ 589} /* pcm_close_recording */
631 590
632void pcm_rec_dma_init(void) 591void pcm_rec_dma_init(void)
633{ 592{
634#if defined(IPOD_COLOR) || defined (IPOD_4G)
635 /* The usual magic from IPL - I'm guessing this configures the headphone
636 socket to be input or output - in this case, input. */
637 GPIO_CLEAR_BITWISE(GPIOI_OUTPUT_VAL, 0x40);
638 GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_VAL, 0x04);
639#endif
640
641 pcm_rec_dma_stop(); 593 pcm_rec_dma_stop();
642} /* pcm_init */ 594} /* pcm_init */
643 595
diff --git a/firmware/target/arm/pcm-telechips.c b/firmware/target/arm/pcm-telechips.c
index affad01c76..a4dc63fc56 100644
--- a/firmware/target/arm/pcm-telechips.c
+++ b/firmware/target/arm/pcm-telechips.c
@@ -58,7 +58,7 @@ struct dma_data dma_play_data SHAREDBSS_ATTR =
58 .state = 0 58 .state = 0
59}; 59};
60 60
61static unsigned long pcm_freq SHAREDDATA_ATTR = HW_SAMPR_DEFAULT; /* 44.1 is default */ 61static unsigned long pcm_sampr SHAREDDATA_ATTR = HW_SAMPR_DEFAULT; /* 44.1 is default */
62 62
63void pcm_postinit(void) 63void pcm_postinit(void)
64{ 64{
@@ -102,8 +102,6 @@ void pcm_play_dma_init(void)
102 /* Set DAI interrupts as FIQs */ 102 /* Set DAI interrupts as FIQs */
103 IRQSEL = ~(DAI_RX_IRQ_MASK | DAI_TX_IRQ_MASK); 103 IRQSEL = ~(DAI_RX_IRQ_MASK | DAI_TX_IRQ_MASK);
104 104
105 pcm_set_frequency(SAMPR_44);
106
107 /* Initialize default register values. */ 105 /* Initialize default register values. */
108 audiohw_init(); 106 audiohw_init();
109 107
@@ -113,15 +111,8 @@ void pcm_play_dma_init(void)
113#endif 111#endif
114} 112}
115 113
116void pcm_apply_settings(void) 114void pcm_dma_apply_settings(void)
117{
118 pcm_curr_sampr = pcm_freq;
119}
120
121void pcm_set_frequency(unsigned int frequency)
122{ 115{
123 (void) frequency;
124 pcm_freq = HW_SAMPR_DEFAULT;
125} 116}
126 117
127static void play_start_pcm(void) 118static void play_start_pcm(void)
diff --git a/firmware/target/arm/pnx0101/pcm-pnx0101.c b/firmware/target/arm/pnx0101/pcm-pnx0101.c
index 4f90c5f829..20fca48039 100644
--- a/firmware/target/arm/pnx0101/pcm-pnx0101.c
+++ b/firmware/target/arm/pnx0101/pcm-pnx0101.c
@@ -27,7 +27,7 @@
27short __attribute__((section(".dmabuf"))) dma_buf_left[DMA_BUF_SAMPLES]; 27short __attribute__((section(".dmabuf"))) dma_buf_left[DMA_BUF_SAMPLES];
28short __attribute__((section(".dmabuf"))) dma_buf_right[DMA_BUF_SAMPLES]; 28short __attribute__((section(".dmabuf"))) dma_buf_right[DMA_BUF_SAMPLES];
29 29
30static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */ 30static int pcm_sampr = HW_SAMPR_DEFAULT; /* 44.1 is default */
31 31
32unsigned short* p IBSS_ATTR; 32unsigned short* p IBSS_ATTR;
33size_t p_size IBSS_ATTR; 33size_t p_size IBSS_ATTR;
@@ -147,8 +147,6 @@ void pcm_init(void)
147{ 147{
148 int i; 148 int i;
149 149
150 pcm_set_frequency(HW_SAMPR_DEFAULT);
151
152 memset(dma_buf_left, 0, sizeof(dma_buf_left)); 150 memset(dma_buf_left, 0, sizeof(dma_buf_left));
153 memset(dma_buf_right, 0, sizeof(dma_buf_right)); 151 memset(dma_buf_right, 0, sizeof(dma_buf_right));
154 152
@@ -193,15 +191,8 @@ void pcm_postinit(void)
193 pcm_apply_settings(); 191 pcm_apply_settings();
194} 192}
195 193
196void pcm_set_frequency(unsigned int frequency) 194void pcm_dma_apply_settings(void)
197{
198 (void)frequency;
199 pcm_freq = HW_SAMPR_DEFAULT;
200}
201
202void pcm_apply_settings(void)
203{ 195{
204 pcm_curr_sampr = pcm_freq;
205} 196}
206 197
207size_t pcm_get_bytes_waiting(void) 198size_t pcm_get_bytes_waiting(void)
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
index 14fbcd5cfe..315fc3bf0f 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
@@ -26,12 +26,6 @@
26#include "sound.h" 26#include "sound.h"
27#include "file.h" 27#include "file.h"
28 28
29/* All exact rates for 16.9344MHz clock */
30#define GIGABEAT_11025HZ (0x19 << 1)
31#define GIGABEAT_22050HZ (0x1b << 1)
32#define GIGABEAT_44100HZ (0x11 << 1)
33#define GIGABEAT_88200HZ (0x1f << 1)
34
35/* PCM interrupt routine lockout */ 29/* PCM interrupt routine lockout */
36static struct 30static struct
37{ 31{
@@ -43,11 +37,6 @@ static struct
43 .state = 0, 37 .state = 0,
44}; 38};
45 39
46/* Last samplerate set by pcm_set_frequency */
47static unsigned long pcm_freq = 0; /* 44.1 is default */
48/* Samplerate control for audio codec */
49static int sr_ctrl = 0;
50
51#define FIFO_COUNT ((IISFCON >> 6) & 0x3F) 40#define FIFO_COUNT ((IISFCON >> 6) & 0x3F)
52 41
53/* Setup for the DMA controller */ 42/* Setup for the DMA controller */
@@ -57,22 +46,6 @@ static int sr_ctrl = 0;
57/* Get more data from the callback and top off the FIFO */ 46/* Get more data from the callback and top off the FIFO */
58void fiq_handler(void) __attribute__((interrupt ("FIQ"))); 47void fiq_handler(void) __attribute__((interrupt ("FIQ")));
59 48
60static void _pcm_apply_settings(void)
61{
62 if (pcm_freq != pcm_curr_sampr)
63 {
64 pcm_curr_sampr = pcm_freq;
65 audiohw_set_frequency(sr_ctrl);
66 }
67}
68
69void pcm_apply_settings(void)
70{
71 int status = disable_fiq_save();
72 _pcm_apply_settings();
73 restore_fiq(status);
74}
75
76/* Mask the DMA interrupt */ 49/* Mask the DMA interrupt */
77void pcm_play_lock(void) 50void pcm_play_lock(void)
78{ 51{
@@ -89,8 +62,6 @@ void pcm_play_unlock(void)
89 62
90void pcm_play_dma_init(void) 63void pcm_play_dma_init(void)
91{ 64{
92 pcm_set_frequency(SAMPR_44);
93
94 /* There seem to be problems when changing the IIS interface configuration 65 /* There seem to be problems when changing the IIS interface configuration
95 * when a clock is not present. 66 * when a clock is not present.
96 */ 67 */
@@ -128,13 +99,18 @@ void pcm_postinit(void)
128 pcm_apply_settings(); 99 pcm_apply_settings();
129} 100}
130 101
102void pcm_dma_apply_settings(void)
103{
104 audiohw_set_frequency(pcm_fsel);
105}
106
131/* Connect the DMA and start filling the FIFO */ 107/* Connect the DMA and start filling the FIFO */
132static void play_start_pcm(void) 108static void play_start_pcm(void)
133{ 109{
134 /* clear pending DMA interrupt */ 110 /* clear pending DMA interrupt */
135 SRCPND = DMA2_MASK; 111 SRCPND = DMA2_MASK;
136 112
137 _pcm_apply_settings(); 113 pcm_apply_settings();
138 114
139 /* Flush any pending writes */ 115 /* Flush any pending writes */
140 clean_dcache_range((void*)DISRC2, (DCON2 & 0xFFFFF) * 2); 116 clean_dcache_range((void*)DISRC2, (DCON2 & 0xFFFFF) * 2);
@@ -272,29 +248,6 @@ void fiq_handler(void)
272 } 248 }
273} 249}
274 250
275void pcm_set_frequency(unsigned int frequency)
276{
277 switch(frequency)
278 {
279 case SAMPR_11:
280 sr_ctrl = GIGABEAT_11025HZ;
281 break;
282 case SAMPR_22:
283 sr_ctrl = GIGABEAT_22050HZ;
284 break;
285 default:
286 frequency = SAMPR_44;
287 case SAMPR_44:
288 sr_ctrl = GIGABEAT_44100HZ;
289 break;
290 case SAMPR_88:
291 sr_ctrl = GIGABEAT_88200HZ;
292 break;
293 }
294
295 pcm_freq = frequency;
296}
297
298size_t pcm_get_bytes_waiting(void) 251size_t pcm_get_bytes_waiting(void)
299{ 252{
300 /* lie a little and only return full pairs */ 253 /* lie a little and only return full pairs */
diff --git a/firmware/target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c
index 34425fa63d..d8c953bbce 100644
--- a/firmware/target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c
+++ b/firmware/target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c
@@ -28,6 +28,8 @@
28#include "audiohw.h" 28#include "audiohw.h"
29#include "dsp-target.h" 29#include "dsp-target.h"
30 30
31static int pcm_fsel = HW_FREQ_DEFAULT;
32
31void pcm_play_dma_init(void) 33void pcm_play_dma_init(void)
32{ 34{
33 IO_CLK_O1DIV = 3; 35 IO_CLK_O1DIV = 3;
@@ -37,7 +39,7 @@ void pcm_play_dma_init(void)
37 39
38 audiohw_init(); 40 audiohw_init();
39 41
40 audiohw_set_frequency(1); 42 audiohw_set_frequency(HW_FREQ_DEFAULT);
41 43
42 /* init DSP */ 44 /* init DSP */
43 dsp_init(); 45 dsp_init();
@@ -46,42 +48,21 @@ void pcm_play_dma_init(void)
46void pcm_postinit(void) 48void pcm_postinit(void)
47{ 49{
48 audiohw_postinit(); 50 audiohw_postinit();
51 pcm_apply_settings();
52
49 /* wake DSP */ 53 /* wake DSP */
50 dsp_wake(); 54 dsp_wake();
51} 55}
52 56
53/* set frequency used by the audio hardware */
54void pcm_set_frequency(unsigned int frequency)
55{
56 int index;
57
58 switch(frequency)
59 {
60 case SAMPR_11:
61 case SAMPR_22:
62 index = 0;
63 break;
64 default:
65 case SAMPR_44:
66 index = 1;
67 break;
68 case SAMPR_88:
69 index = 2;
70 break;
71 }
72
73 audiohw_set_frequency(index);
74} /* pcm_set_frequency */
75
76const void * pcm_play_dma_get_peak_buffer(int *count) 57const void * pcm_play_dma_get_peak_buffer(int *count)
77{ 58{
78 (void) count; 59 (void) count;
79 return 0; 60 return 0;
80} 61}
81 62
82void pcm_apply_settings(void) 63void pcm_dma_apply_settings(void)
83{ 64{
84 65 audiohw_set_frequency(pcm_fsel);
85} 66}
86 67
87void pcm_play_dma_start(const void *addr, size_t size) 68void pcm_play_dma_start(const void *addr, size_t size)
diff --git a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
index 2f0e40757b..4c9cc337a5 100755..100644
--- a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
+++ b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
@@ -41,14 +41,8 @@ void pcm_play_dma_init(void)
41 41
42} 42}
43 43
44void pcm_apply_settings(void) 44void pcm_dma_apply_settings(void)
45{ 45{
46
47}
48
49void pcm_set_frequency(unsigned int frequency)
50{
51 (void) frequency;
52} 46}
53 47
54void pcm_play_dma_start(const void *addr, size_t size) 48void pcm_play_dma_start(const void *addr, size_t size)
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c
index 35b3ecae9c..914947a98e 100644
--- a/firmware/target/coldfire/pcm-coldfire.c
+++ b/firmware/target/coldfire/pcm-coldfire.c
@@ -69,66 +69,43 @@ static void iis_play_reset_if_playback(bool if_playback)
69/** Sample rates **/ 69/** Sample rates **/
70#define FPARM_CLOCKSEL 0 70#define FPARM_CLOCKSEL 0
71#define FPARM_CLSEL 1 71#define FPARM_CLSEL 1
72#define FPARM_FSEL 2
73#if CONFIG_CPU == MCF5249 && defined(HAVE_UDA1380) 72#if CONFIG_CPU == MCF5249 && defined(HAVE_UDA1380)
74static const unsigned char pcm_freq_parms[HW_NUM_FREQ][3] = 73static const unsigned char pcm_freq_parms[HW_NUM_FREQ][2] =
75{ 74{
76 [HW_FREQ_88] = { 0x0c, 0x01, 0x03 }, 75 [HW_FREQ_88] = { 0x0c, 0x01 },
77 [HW_FREQ_44] = { 0x06, 0x01, 0x02 }, 76 [HW_FREQ_44] = { 0x06, 0x01 },
78 [HW_FREQ_22] = { 0x04, 0x02, 0x01 }, 77 [HW_FREQ_22] = { 0x04, 0x02 },
79 [HW_FREQ_11] = { 0x02, 0x02, 0x00 }, 78 [HW_FREQ_11] = { 0x02, 0x02 },
80}; 79};
81#endif 80#endif
82 81
83#if (CONFIG_CPU == MCF5250 || CONFIG_CPU == MCF5249) && defined(HAVE_TLV320) 82#if (CONFIG_CPU == MCF5250 || CONFIG_CPU == MCF5249) && defined(HAVE_TLV320)
84static const unsigned char pcm_freq_parms[HW_NUM_FREQ][3] = 83static const unsigned char pcm_freq_parms[HW_NUM_FREQ][2] =
85{ 84{
86 [HW_FREQ_88] = { 0x0c, 0x01, 0x02 }, 85 [HW_FREQ_88] = { 0x0c, 0x01 },
87 [HW_FREQ_44] = { 0x06, 0x01, 0x01 }, 86 [HW_FREQ_44] = { 0x06, 0x01 },
88 [HW_FREQ_22] = { 0x04, 0x01, 0x00 }, 87 [HW_FREQ_22] = { 0x04, 0x01 },
89 [HW_FREQ_11] = { 0x02, 0x02, 0x00 }, 88 [HW_FREQ_11] = { 0x02, 0x02 },
90}; 89};
91#endif 90#endif
92 91
93static unsigned long pcm_freq = 0; /* 44.1 is default */ 92static const unsigned char *freq_ent;
94static const unsigned char *freq_ent = pcm_freq_parms[HW_FREQ_DEFAULT];
95
96/* set frequency used by the audio hardware */
97void pcm_set_frequency(unsigned int frequency)
98{
99 int index;
100
101 switch(frequency)
102 {
103 case SAMPR_11:
104 index = HW_FREQ_11;
105 break;
106 case SAMPR_22:
107 index = HW_FREQ_22;
108 break;
109 default:
110 case SAMPR_44:
111 index = HW_FREQ_44;
112 break;
113 case SAMPR_88:
114 index = HW_FREQ_88;
115 break;
116 }
117
118 /* remember table entry and rate */
119 freq_ent = pcm_freq_parms[index];
120 pcm_freq = hw_freq_sampr[index];
121} /* pcm_set_frequency */
122 93
123/* apply audio settings */ 94/* apply audio settings */
124static bool _pcm_apply_settings(bool clear_reset) 95static bool _pcm_dma_apply_settings(bool clear_reset)
125{ 96{
126 bool did_reset = false; 97 bool did_reset = false;
127 unsigned long iis_play_defparm = IIS_PLAY_DEFPARM; 98 unsigned long iis_play_defparm;
99
100 int level = set_irq_level(DMA_IRQ_LEVEL);
101
102 /* remember table entry */
103 freq_ent = pcm_freq_parms[pcm_fsel];
128 104
129 if (pcm_freq != pcm_curr_sampr) 105 iis_play_defparm = IIS_PLAY_DEFPARM;
106
107 if (pcm_sampr != pcm_curr_sampr)
130 { 108 {
131 pcm_curr_sampr = pcm_freq;
132 /* Reprogramming bits 15-12 requires FIFO to be in a reset 109 /* Reprogramming bits 15-12 requires FIFO to be in a reset
133 condition - Users Manual 17-8, Note 11 */ 110 condition - Users Manual 17-8, Note 11 */
134 or_l(IIS_FIFO_RESET, &IIS_PLAY); 111 or_l(IIS_FIFO_RESET, &IIS_PLAY);
@@ -136,8 +113,8 @@ static bool _pcm_apply_settings(bool clear_reset)
136 or starting recording will sound absolutely awful once in 113 or starting recording will sound absolutely awful once in
137 awhile - audiohw_set_frequency then coldfire_set_pllcr_audio_bits 114 awhile - audiohw_set_frequency then coldfire_set_pllcr_audio_bits
138 */ 115 */
139 SET_IIS_PLAY(iis_play_defparm | IIS_FIFO_RESET); 116 SET_IIS_PLAY(IIS_PLAY_DEFPARM | IIS_FIFO_RESET);
140 audiohw_set_frequency(freq_ent[FPARM_FSEL]); 117 audiohw_set_frequency(pcm_fsel);
141 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM); 118 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM);
142 did_reset = true; 119 did_reset = true;
143 } 120 }
@@ -147,26 +124,21 @@ static bool _pcm_apply_settings(bool clear_reset)
147 be cleared. If the frequency didn't change, it was never altered and 124 be cleared. If the frequency didn't change, it was never altered and
148 the reset flag can just be removed or no action taken. */ 125 the reset flag can just be removed or no action taken. */
149 if (clear_reset) 126 if (clear_reset)
150 SET_IIS_PLAY(iis_play_defparm & ~IIS_FIFO_RESET); 127 SET_IIS_PLAY(IIS_PLAY_DEFPARM & ~IIS_FIFO_RESET);
128
129 restore_irq(level);
130
151#if 0 131#if 0
152 logf("IISPLAY: %08X", IIS_PLAY); 132 logf("IISPLAY: %08X", IIS_PLAY);
153#endif 133#endif
154 134
155 return did_reset; 135 return did_reset;
156} /* _pcm_apply_settings */ 136} /* _pcm_dma_apply_settings */
157
158/* apply audio setting with all DMA interrupts disabled */
159static void _pcm_apply_settings_irq_lock(bool clear_reset)
160{
161 int level = set_irq_level(DMA_IRQ_LEVEL);
162 _pcm_apply_settings(clear_reset);
163 restore_irq(level);
164}
165 137
166/* This clears the reset bit to enable monitoring immediately if monitoring 138/* This clears the reset bit to enable monitoring immediately if monitoring
167 recording sources or always if playback is in progress - we might be 139 recording sources or always if playback is in progress - we might be
168 switching samplerates on the fly */ 140 switching samplerates on the fly */
169void pcm_apply_settings(void) 141void pcm_dma_apply_settings(void)
170{ 142{
171 int level = set_irq_level(DMA_IRQ_LEVEL); 143 int level = set_irq_level(DMA_IRQ_LEVEL);
172 bool pbm = is_playback_monitoring(); 144 bool pbm = is_playback_monitoring();
@@ -174,14 +146,16 @@ void pcm_apply_settings(void)
174 146
175 /* Clear reset if not playback monitoring or peripheral request is 147 /* Clear reset if not playback monitoring or peripheral request is
176 active and playback monitoring */ 148 active and playback monitoring */
177 if (_pcm_apply_settings(!pbm || kick) && kick) 149 if (_pcm_dma_apply_settings(!pbm || kick) && kick)
178 PDOR3 = 0; /* Kick FIFO out of reset by writing to it */ 150 PDOR3 = 0; /* Kick FIFO out of reset by writing to it */
179 151
180 restore_irq(level); 152 restore_irq(level);
181} /* pcm_apply_settings */ 153} /* pcm_dma_apply_settings */
182 154
183void pcm_play_dma_init(void) 155void pcm_play_dma_init(void)
184{ 156{
157 freq_ent = pcm_freq_parms[pcm_fsel];
158
185 AUDIOGLOB = (1 << 8) /* IIS1 fifo auto sync */ 159 AUDIOGLOB = (1 << 8) /* IIS1 fifo auto sync */
186 | (1 << 7) /* PDIR2 fifo auto sync */ 160 | (1 << 7) /* PDIR2 fifo auto sync */
187#ifdef HAVE_SPDIF_OUT 161#ifdef HAVE_SPDIF_OUT
@@ -200,7 +174,6 @@ void pcm_play_dma_init(void)
200 other settings. */ 174 other settings. */
201 or_l(IIS_FIFO_RESET, &IIS_PLAY); 175 or_l(IIS_FIFO_RESET, &IIS_PLAY);
202 SET_IIS_PLAY(IIS_PLAY_DEFPARM | IIS_FIFO_RESET); 176 SET_IIS_PLAY(IIS_PLAY_DEFPARM | IIS_FIFO_RESET);
203 pcm_set_frequency(HW_FREQ_DEFAULT);
204 audio_set_output_source(AUDIO_SRC_PLAYBACK); 177 audio_set_output_source(AUDIO_SRC_PLAYBACK);
205 178
206 /* Initialize default register values. */ 179 /* Initialize default register values. */
@@ -208,7 +181,7 @@ void pcm_play_dma_init(void)
208 181
209 audio_input_mux(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); 182 audio_input_mux(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
210 183
211 audiohw_set_frequency(freq_ent[FPARM_FSEL]); 184 audiohw_set_frequency(pcm_fsel);
212 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM); 185 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM);
213 186
214#if defined(HAVE_SPDIF_REC) || defined(HAVE_SPDIF_OUT) 187#if defined(HAVE_SPDIF_REC) || defined(HAVE_SPDIF_OUT)
@@ -264,7 +237,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
264 BCR0 = (unsigned long)size; /* Bytes to transfer */ 237 BCR0 = (unsigned long)size; /* Bytes to transfer */
265 238
266 /* Enable the FIFO and force one write to it */ 239 /* Enable the FIFO and force one write to it */
267 _pcm_apply_settings_irq_lock(is_playback_monitoring()); 240 _pcm_dma_apply_settings(is_playback_monitoring());
268 241
269 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | 242 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA |
270 DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) | DMA_START; 243 DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) | DMA_START;
@@ -299,7 +272,7 @@ void pcm_play_dma_pause(bool pause)
299 { 272 {
300 /* restart playback on current buffer */ 273 /* restart playback on current buffer */
301 /* Enable the FIFO and force one write to it */ 274 /* Enable the FIFO and force one write to it */
302 _pcm_apply_settings_irq_lock(is_playback_monitoring()); 275 _pcm_dma_apply_settings(is_playback_monitoring());
303 or_l(DMA_EEXT | DMA_START, &DCR0); 276 or_l(DMA_EEXT | DMA_START, &DCR0);
304 dma_play_lock.state = (1 << 14); 277 dma_play_lock.state = (1 << 14);
305 } 278 }
@@ -403,7 +376,7 @@ void pcm_rec_dma_start(void *addr, size_t size)
403 and_l(~PDIR2_FIFO_RESET, &DATAINCONTROL); 376 and_l(~PDIR2_FIFO_RESET, &DATAINCONTROL);
404 /* Clear TX FIFO reset bit if the source is not set to monitor playback 377 /* Clear TX FIFO reset bit if the source is not set to monitor playback
405 otherwise maintain independence between playback and recording. */ 378 otherwise maintain independence between playback and recording. */
406 _pcm_apply_settings_irq_lock(!is_playback_monitoring()); 379 _pcm_dma_apply_settings(!is_playback_monitoring());
407 380
408 /* Start the DMA transfer.. */ 381 /* Start the DMA transfer.. */
409#ifdef HAVE_SPDIF_REC 382#ifdef HAVE_SPDIF_REC
diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
index e4d9127c21..2d3aa45d08 100644
--- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
@@ -58,14 +58,13 @@ void pcm_play_dma_init(void)
58 audiohw_init(); 58 audiohw_init();
59} 59}
60 60
61void pcm_set_frequency(unsigned int frequency) 61void pcm_dma_apply_settings(void)
62{ 62{
63 (void) frequency;
64 /* TODO */ 63 /* TODO */
65 64
66 /* 65 /*
67 __i2s_set_oss_sample_size(frequency); 66 __i2s_set_oss_sample_size(pcm_sampr);
68 i2s_codec_set_samplerate(frequency); 67 i2s_codec_set_samplerate(pcm_sampr);
69 */ 68 */
70} 69}
71 70