summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2010-04-29 13:14:43 +0000
committerMarcin Bukat <marcin.bukat@gmail.com>2010-04-29 13:14:43 +0000
commitc740af20e70ddc863c3a71f3b25e51b2a20b6795 (patch)
tree440c361a867739a24b87a2fc99916937abeff761
parent4c03e9a6f0f40cf8d0ffed0d2f35fafdab143738 (diff)
downloadrockbox-c740af20e70ddc863c3a71f3b25e51b2a20b6795.tar.gz
rockbox-c740af20e70ddc863c3a71f3b25e51b2a20b6795.zip
HD200 - add FM support.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25757 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/keymaps/keymap-mpio-hd200.c26
-rw-r--r--firmware/drivers/audio/wm8751.c175
-rw-r--r--firmware/export/wm8751.h114
-rw-r--r--firmware/target/coldfire/mpio/audio-mpio.c65
4 files changed, 371 insertions, 9 deletions
diff --git a/apps/keymaps/keymap-mpio-hd200.c b/apps/keymaps/keymap-mpio-hd200.c
index 95dec41d85..cf275888c0 100644
--- a/apps/keymaps/keymap-mpio-hd200.c
+++ b/apps/keymaps/keymap-mpio-hd200.c
@@ -149,6 +149,27 @@ static const struct button_mapping button_context_pitchscreen[] = {
149 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) 149 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
150}; /* button_context_pitchscreen */ 150}; /* button_context_pitchscreen */
151 151
152static const struct button_mapping button_context_radio[] = {
153 { ACTION_FM_MENU, BUTTON_SELECT | BUTTON_REPEAT, BUTTON_NONE },
154 { ACTION_FM_PRESET, BUTTON_SELECT | BUTTON_REL, BUTTON_SELECT },
155 { ACTION_FM_MODE, BUTTON_SELECT, BUTTON_NONE },
156 { ACTION_FM_STOP, BUTTON_PLAY | BUTTON_REPEAT, BUTTON_PLAY },
157 { ACTION_FM_EXIT, BUTTON_REC | BUTTON_REL, BUTTON_REC },
158 { ACTION_FM_PLAY, BUTTON_PLAY | BUTTON_REL, BUTTON_PLAY },
159 { ACTION_FM_QUICKSCREEN, BUTTON_REC|BUTTON_REPEAT, BUTTON_REC },
160 { ACTION_SETTINGS_INC, BUTTON_VOL_UP, BUTTON_NONE },
161 { ACTION_SETTINGS_INCREPEAT, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
162 { ACTION_SETTINGS_DEC, BUTTON_VOL_DOWN, BUTTON_NONE },
163 { ACTION_SETTINGS_DECREPEAT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
164 { ACTION_STD_NEXT, BUTTON_NEXT, BUTTON_NONE },
165 { ACTION_STD_NEXTREPEAT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
166 { ACTION_STD_PREV, BUTTON_PREV, BUTTON_NONE },
167 { ACTION_STD_PREVREPEAT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
168
169 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS)
170
171};
172
152const struct button_mapping* get_context_mapping(int context) 173const struct button_mapping* get_context_mapping(int context)
153{ 174{
154 switch (context) 175 switch (context)
@@ -157,7 +178,10 @@ const struct button_mapping* get_context_mapping(int context)
157 return button_context_standard; 178 return button_context_standard;
158 case CONTEXT_WPS: 179 case CONTEXT_WPS:
159 return button_context_wps; 180 return button_context_wps;
160 181#if CONFIG_TUNER
182 case CONTEXT_FM:
183 return button_context_radio;
184#endif
161 case CONTEXT_TREE: 185 case CONTEXT_TREE:
162 case CONTEXT_LIST: 186 case CONTEXT_LIST:
163 case CONTEXT_MAINMENU: 187 case CONTEXT_MAINMENU:
diff --git a/firmware/drivers/audio/wm8751.c b/firmware/drivers/audio/wm8751.c
index ffe7f20bba..18441826d4 100644
--- a/firmware/drivers/audio/wm8751.c
+++ b/firmware/drivers/audio/wm8751.c
@@ -99,6 +99,18 @@ static int adaptivebass2hw(int value)
99} 99}
100#endif 100#endif
101 101
102#if defined(HAVE_WM8750)
103static int recvol2hw(int value)
104{
105/* convert tenth of dB of input volume (-172...300) to input register value */
106 /* +30dB to -17.25 0.75dB step 6 bits */
107 /* 111111 == +30dB (0x3f) */
108 /* 010111 == 0dB (0x17) */
109 /* 000000 == -17.25dB */
110
111 return (3*(value/10 - 0x17))/4;
112}
113#endif
102static void audiohw_mute(bool mute) 114static void audiohw_mute(bool mute)
103{ 115{
104 /* Mute: Set DACMU = 1 to soft-mute the audio DACs. */ 116 /* Mute: Set DACMU = 1 to soft-mute the audio DACs. */
@@ -268,3 +280,166 @@ void audiohw_set_frequency(int fsel)
268 wmcodec_write(CLOCKING, srctrl_table[fsel]); 280 wmcodec_write(CLOCKING, srctrl_table[fsel]);
269#endif 281#endif
270} 282}
283
284#if defined(HAVE_WM8750)
285void audiohw_set_recsrc(int source, bool recording)
286{
287 /* INPUT1 - FM radio
288 * INPUT2 - Line-in
289 * INPUT3 - MIC
290 *
291 * if recording == false we use analog bypass from input
292 * turn off ADC, PGA to save power
293 * turn on output buffer(s)
294 *
295 * if recording == true we route input signal to PGA
296 * and monitoring picks up signal after PGA in analog domain
297 * turn on ADC, PGA, DAC, output buffer(s)
298 */
299
300 switch(source)
301 {
302 case AUDIO_SRC_PLAYBACK:
303 /* mute PGA, disable all audio paths but DAC and output stage*/
304 wmcodec_write(LINVOL, LINVOL_LINMUTE | LINVOL_LINVOL(23)); /* 0dB */
305 wmcodec_write(RINVOL, RINVOL_RINMUTE | RINVOL_RINVOL(23)); /* 0dB */
306 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K);
307 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
308 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
309
310 /* route DAC signal to output mixer */
311 wmcodec_write(LEFTMIX1, LEFTMIX1_LD2LO);
312 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RD2RO);
313
314 /* unmute DAC */
315 audiohw_mute(false);
316 break;
317
318 case AUDIO_SRC_FMRADIO:
319 if(recording)
320 {
321 /* Set input volume to PGA */
322 wmcodec_write(LINVOL, LINVOL_LINVOL(23));
323 wmcodec_write(RINVOL, RINVOL_RINVOL(23));
324
325 /* Turn on PGA and ADC */
326 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K |
327 PWRMGMT1_AINL | PWRMGMT1_AINR |
328 PWRMGMT1_ADCL | PWRMGMT1_ADCR);
329
330 /* Setup input source for PGA as INPUT1
331 * MICBOOST disabled
332 */
333 wmcodec_write(ADCL, ADCL_LINSEL_LINPUT1 | ADCL_LMICBOOST_DISABLED);
334 wmcodec_write(ADCR, ADCR_RINSEL_RINPUT1 | ADCR_RMICBOOST_DISABLED);
335
336 /* setup output digital data
337 * default is LADC -> LDATA, RADC -> RDATA
338 * so we don't touch this
339 */
340
341 /* power up DAC and output stage */
342 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
343 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
344
345 /* analog monitor */
346 wmcodec_write(LEFTMIX1, LEFTMIX1_LMIXSEL_ADCLIN |
347 LEFTMIX1_LD2LO);
348 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RMIXSEL_ADCRIN |
349 RIGHTMIX2_RD2RO);
350 }
351 else
352 {
353
354 /* turn off ADC, PGA */
355 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K);
356
357 /* turn on DAC and output stage */
358 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
359 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
360
361 /* setup monitor mode by routing input signal to outmix
362 * at 0dB volume
363 */
364 wmcodec_write(LEFTMIX1, LEFTMIX1_LI2LO | LEFTMIX1_LMIXSEL_LINPUT1 |
365 LEFTMIX1_LI2LOVOL(0x20) | LEFTMIX1_LD2LO);
366 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RI2RO | RIGHTMIX2_RMIXSEL_RINPUT1 |
367 RIGHTMIX2_RI2ROVOL(0x20) | RIGHTMIX2_RD2RO);
368 }
369 break;
370
371 case AUDIO_SRC_LINEIN:
372 /* Set input volume to PGA */
373 wmcodec_write(LINVOL, LINVOL_LINVOL(23));
374 wmcodec_write(RINVOL, RINVOL_RINVOL(23));
375
376 /* Turn on PGA, ADC, DAC */
377 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K |
378 PWRMGMT1_AINL | PWRMGMT1_AINR |
379 PWRMGMT1_ADCL | PWRMGMT1_ADCR);
380
381 /* turn on DAC and output stage */
382 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
383 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
384
385 /* Setup input source for PGA as INPUT2
386 * MICBOOST disabled
387 */
388 wmcodec_write(ADCL, ADCL_LINSEL_LINPUT2 | ADCL_LMICBOOST_DISABLED);
389 wmcodec_write(ADCR, ADCR_RINSEL_RINPUT2 | ADCR_RMICBOOST_DISABLED);
390
391 /* setup output digital data
392 * default is LADC -> LDATA, RADC -> RDATA
393 * so we don't touch this
394 */
395
396 /* digital monitor */
397 wmcodec_write(LEFTMIX1, LEFTMIX1_LMIXSEL_ADCLIN |
398 LEFTMIX1_LD2LO);
399 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RMIXSEL_ADCRIN |
400 RIGHTMIX2_RD2RO);
401 break;
402
403 case AUDIO_SRC_MIC:
404 /* Set input volume to PGA */
405 wmcodec_write(LINVOL, LINVOL_LINVOL(23));
406 wmcodec_write(RINVOL, RINVOL_RINVOL(23));
407
408 /* Turn on PGA and ADC, turn off DAC */
409 wmcodec_write(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_50K |
410 PWRMGMT1_AINL | PWRMGMT1_AINR |
411 PWRMGMT1_ADCL | PWRMGMT1_ADCR);
412
413 /* turn on DAC and output stage */
414 wmcodec_write(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR |
415 PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
416
417 /* Setup input source for PGA as INPUT3
418 * MICBOOST disabled
419 */
420 wmcodec_write(ADCL, ADCL_LINSEL_LINPUT3 | ADCL_LMICBOOST_DISABLED);
421 wmcodec_write(ADCR, ADCR_RINSEL_RINPUT3 | ADCR_RMICBOOST_DISABLED);
422
423 /* setup output digital data
424 * default is LADC -> LDATA, RADC -> RDATA
425 * so we don't touch this
426 */
427
428 /* analog monitor */
429 wmcodec_write(LEFTMIX1, LEFTMIX1_LMIXSEL_ADCLIN |
430 LEFTMIX1_LD2LO);
431 wmcodec_write(RIGHTMIX2, RIGHTMIX2_RMIXSEL_ADCRIN |
432 RIGHTMIX2_RD2RO);
433 break;
434
435 } /* switch(source) */
436}
437
438/* Setup PGA gain */
439void audiohw_set_recvol(int left, int right, int type)
440{
441 (void)type;
442 wmcodec_write(LINVOL, LINVOL_LINVOL(recvol2hw(left)));
443 wmcodec_write(RINVOL, RINVOL_RINVOL(recvol2hw(right)));
444}
445#endif
diff --git a/firmware/export/wm8751.h b/firmware/export/wm8751.h
index c171642853..fb7532bfd8 100644
--- a/firmware/export/wm8751.h
+++ b/firmware/export/wm8751.h
@@ -31,11 +31,28 @@ extern int tenthdb2master(int db);
31 31
32extern void audiohw_set_master_vol(int vol_l, int vol_r); 32extern void audiohw_set_master_vol(int vol_l, int vol_r);
33extern void audiohw_set_lineout_vol(int vol_l, int vol_r); 33extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
34#if defined(HAVE_WM8750)
35void audiohw_set_recsrc(int source, bool recording);
36#endif
34 37
35/* Register addresses and bits */ 38/* Register addresses and bits */
36#define OUTPUT_MUTED 0x2f 39#define OUTPUT_MUTED 0x2f
37#define OUTPUT_0DB 0x79 40#define OUTPUT_0DB 0x79
38 41
42#if defined(HAVE_WM8750)
43#define LINVOL 0x00
44#define LINVOL_LINVOL(x) ((x) & 0x3f)
45#define LINVOL_LIZC (1 << 6)
46#define LINVOL_LINMUTE (1 << 7)
47#define LINVOL_LIVU (1 << 8)
48
49#define RINVOL 0x01
50#define RINVOL_RINVOL(x) ((x) & 0x3f)
51#define RINVOL_RIZC (1 << 6)
52#define RINVOL_RINMUTE (1 << 7)
53#define RINVOL_RIVU (1 << 8)
54#endif
55
39#define LOUT1 0x02 56#define LOUT1 0x02
40#define LOUT1_LOUT1VOL_MASK (0x07f << 0) 57#define LOUT1_LOUT1VOL_MASK (0x07f << 0)
41#define LOUT1_LOUT1VOL(x) ((x) & 0x7f) 58#define LOUT1_LOUT1VOL(x) ((x) & 0x7f)
@@ -98,7 +115,7 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
98#define RESET 0x0f 115#define RESET 0x0f
99#define RESET_RESET 0x000 116#define RESET_RESET 0x000
100 117
101/* WM8750 only */ 118#if defined(HAVE_WM8750)
102#define ENHANCE_3D 0x10 119#define ENHANCE_3D 0x10
103#define ENHANCE_3D_3DEN (1 << 0) 120#define ENHANCE_3D_3DEN (1 << 0)
104#define ENHANCE_3D_DEPTH(x) (((x) & 0xf) << 1) 121#define ENHANCE_3D_DEPTH(x) (((x) & 0xf) << 1)
@@ -107,6 +124,30 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
107#define ENHANCE_3D_MODE3D_PLAYBACK (1 << 7) 124#define ENHANCE_3D_MODE3D_PLAYBACK (1 << 7)
108#define ENHANCE_3D_MODE3D_RECORD (0 << 7) 125#define ENHANCE_3D_MODE3D_RECORD (0 << 7)
109 126
127#define ALC1 0x11
128#define ALC1_ALCL(x) ((x) & (0x0f))
129#define ALC1_MAXGAIN(x) ((x) & (0x07 << 4))
130#define ALC1_ALCSEL_DISABLED (0 << 7)
131#define ALC1_ALCSEL_RIGHT (1 << 7)
132#define ALC1_ALCSEL_LEFT (2 << 7)
133#define ALC1_ALCSEL_STEREO (3 << 7)
134
135#define ALC2 0x12
136#define ALC2_HLD(x) ((x) & 0x0f)
137#define ALC2_ALCZC (1 << 7)
138
139#define ALC3 0x13
140#define ALC3_ATK(x) ((x) & 0x0f)
141#define ALC3_DCY(x) ((x) & (0x0f << 4))
142
143#define NGAT 0x14
144#define NGAT_NGAT (1 << 0)
145#define NGAT_NGG_CONST (0 << 1)
146#define NGAT_NGG_MUTEADC (1 << 1)
147#define NGAT_NGG(x) ((x) & (0x3 << 1))
148#define NGAT_NGTH(x) ((x) & (0x1f << 3))
149#endif
150
110#define ADDITIONAL1 0x17 151#define ADDITIONAL1 0x17
111#define ADDITIONAL1_TOEN (1 << 0) 152#define ADDITIONAL1_TOEN (1 << 0)
112#define ADDITIONAL1_DACINV (1 << 1) 153#define ADDITIONAL1_DACINV (1 << 1)
@@ -136,6 +177,13 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
136 177
137#define PWRMGMT1 0x19 178#define PWRMGMT1 0x19
138#define PWRMGMT1_DIGENB (1 << 0) 179#define PWRMGMT1_DIGENB (1 << 0)
180#if defined(HAVE_WM8750)
181#define PWRMGMT1_MICBIAS (1 << 1)
182#define PWRMGMT1_ADCR (1 << 2)
183#define PWRMGMT1_ADCL (1 << 3)
184#define PWRMGMT1_AINR (1 << 4)
185#define PWRMGMT1_AINL (1 << 5)
186#endif
139#define PWRMGMT1_VREF (1 << 6) 187#define PWRMGMT1_VREF (1 << 6)
140#define PWRMGMT1_VMIDSEL_DISABLED (0 << 7) 188#define PWRMGMT1_VMIDSEL_DISABLED (0 << 7)
141#define PWRMGMT1_VMIDSEL_50K (1 << 7) 189#define PWRMGMT1_VMIDSEL_50K (1 << 7)
@@ -158,7 +206,48 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
158#define ADDITIONAL3_HPFLREN (1 << 5) 206#define ADDITIONAL3_HPFLREN (1 << 5)
159#define ADDITIONAL3_VROI (1 << 6) 207#define ADDITIONAL3_VROI (1 << 6)
160 208
209#if defined(HAVE_WM8750)
210#define ADCIM 0x1f
211#define ADCIM_LDCM (1 << 4)
212#define ADCIM_RDCM (1 << 5)
213#define ADCIM_MONOMIX_STEREO (0 << 6)
214#define ADCIM_MONOMIX_AMONOL (1 << 6)
215#define ADCIM_MONOMIX_AMONOR (2 << 6)
216#define ADCIM_MONOMIX_DMONO (3 << 6)
217#define ADCIM_MONOMIX(x) ((x) & (0x3 << 6))
218#define ADCIM_DS (1 << 8)
219
220#define ADCL 0x20
221#define ADCL_LMICBOOST_DISABLED (0 << 4)
222#define ADCL_LMICBOOST_13DB (1 << 4)
223#define ADCL_LMICBOOST_20DB (2 << 4)
224#define ADCL_LMICBOOST_29DB (3 << 4)
225#define ADCL_LMICBOOST(x) ((x) & (0x3 << 7))
226#define ADCL_LINSEL_LINPUT1 (0 << 6)
227#define ADCL_LINSEL_LINPUT2 (1 << 6)
228#define ADCL_LINSEL_LINPUT3 (2 << 6)
229#define ADCL_LINSEL_DIFF (3 << 6)
230
231#define ADCR 0x21
232#define ADCR_RMICBOOST_DISABLED (0 << 4)
233#define ADCR_RMICBOOST_13DB (1 << 4)
234#define ADCR_RMICBOOST_20DB (2 << 4)
235#define ADCR_RMICBOOST_29DB (3 << 4)
236#define ADCR_RMICBOOST(x) ((x) & (0x3 << 7))
237#define ADCR_RINSEL_RINPUT1 (0 << 6)
238#define ADCR_RINSEL_RINPUT2 (1 << 6)
239#define ADCR_RINSEL_RINPUT3 (2 << 6)
240#define ADCR_RINSEL_DIFF (3 << 6)
241#endif
242
161#define LEFTMIX1 0x22 243#define LEFTMIX1 0x22
244#if defined(HAVE_WM8750)
245#define LEFTMIX1_LMIXSEL_LINPUT1 (0 << 0)
246#define LEFTMIX1_LMIXSEL_LINPUT2 (1 << 0)
247#define LEFTMIX1_LMIXSEL_LINPUT3 (2 << 0)
248#define LEFTMIX1_LMIXSEL_ADCLIN (3 << 0)
249#define LEFTMIX1_LMIXSEL_DIFF (4 << 0)
250#endif
162#define LEFTMIX1_LI2LO_DEFAULT (5 << 4) 251#define LEFTMIX1_LI2LO_DEFAULT (5 << 4)
163#define LEFTMIX1_LI2LOVOL(x) ((x) & (0x7 << 4)) 252#define LEFTMIX1_LI2LOVOL(x) ((x) & (0x7 << 4))
164#define LEFTMIX1_LI2LO (1 << 7) 253#define LEFTMIX1_LI2LO (1 << 7)
@@ -167,16 +256,39 @@ extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
167#define LEFTMIX2 0x23 256#define LEFTMIX2 0x23
168#define LEFTMIX2_MI2LO_DEFAULT (5 << 4) 257#define LEFTMIX2_MI2LO_DEFAULT (5 << 4)
169#define LEFTMIX2_MI2LOVOL(x) ((x) & (0x7 << 4)) 258#define LEFTMIX2_MI2LOVOL(x) ((x) & (0x7 << 4))
259#if defined(HAVE_WM8750)
260#define LEFTMIX2_RI2LO (1 << 7)
261#elif defined(HAVE_WM8751)
170#define LEFTMIX2_MI2LO (1 << 7) 262#define LEFTMIX2_MI2LO (1 << 7)
263#endif
171#define LEFTMIX2_RD2LO (1 << 8) 264#define LEFTMIX2_RD2LO (1 << 8)
172 265
173#define RIGHTMIX1 0x24 266#define RIGHTMIX1 0x24
267#if defined(HAVE_WM8750)
268#define RIGHTMIX1_RMIXSEL_RINPUT1 (0 << 0)
269#define RIGHTMIX1_RMIXSEL_RINPUT2 (1 << 0)
270#define RIGHTMIX1_RMIXSEL_RINPUT3 (2 << 0)
271#define RIGHTMIX1_RMIXSEL_ADCRIN (3 << 0)
272#define RIGHTMIX1_RMIXSEL_DIFF (4 << 0)
273#define RIGHTMIX1_LI2RO_DEFAULT (5 << 4)
274#define RIGHTMIX1_LI2ROVOL(x) ((x) & (0x7 << 4))
275#define RIGHTMIX1_LI2RO (1 << 7)
276#define RIGHTMIX1_LD2RO (1 << 8)
277#elif defined(HAVE_WM8751)
174#define RIGHTMIX1_MI2RO_DEFAULT (5 << 4) 278#define RIGHTMIX1_MI2RO_DEFAULT (5 << 4)
175#define RIGHTMIX1_MI2ROVOL(x) ((x) & (0x7 << 4)) 279#define RIGHTMIX1_MI2ROVOL(x) ((x) & (0x7 << 4))
176#define RIGHTMIX1_MI2RO (1 << 7) 280#define RIGHTMIX1_MI2RO (1 << 7)
177#define RIGHTMIX1_LD2RO (1 << 8) 281#define RIGHTMIX1_LD2RO (1 << 8)
282#endif
178 283
179#define RIGHTMIX2 0x25 284#define RIGHTMIX2 0x25
285#if defined(HAVE_WM8750)
286#define RIGHTMIX2_RMIXSEL_RINPUT1 (0 << 0)
287#define RIGHTMIX2_RMIXSEL_RINPUT2 (1 << 0)
288#define RIGHTMIX2_RMIXSEL_RINPUT3 (2 << 0)
289#define RIGHTMIX2_RMIXSEL_ADCRIN (3 << 0)
290#define RIGHTMIX2_RMIXSEL_DIFF (4 << 0)
291#endif
180#define RIGHTMIX2_RI2RO_DEFAULT (5 << 4) 292#define RIGHTMIX2_RI2RO_DEFAULT (5 << 4)
181#define RIGHTMIX2_RI2ROVOL(x) ((x) & (0x7 << 4)) 293#define RIGHTMIX2_RI2ROVOL(x) ((x) & (0x7 << 4))
182#define RIGHTMIX2_RI2RO (1 << 7) 294#define RIGHTMIX2_RI2RO (1 << 7)
diff --git a/firmware/target/coldfire/mpio/audio-mpio.c b/firmware/target/coldfire/mpio/audio-mpio.c
index 28c6419171..217881547e 100644
--- a/firmware/target/coldfire/mpio/audio-mpio.c
+++ b/firmware/target/coldfire/mpio/audio-mpio.c
@@ -23,27 +23,78 @@
23#include "audio.h" 23#include "audio.h"
24#include "sound.h" 24#include "sound.h"
25 25
26static inline void enable_mclk(bool enable)
27{
28 if(enable)
29 and_l(~(1<<10), &GPIO1_FUNCTION);
30 else
31 or_l((1<<10), &GPIO1_FUNCTION);
32}
33
26void audio_set_output_source(int source) 34void audio_set_output_source(int source)
27{ 35{
36 static const unsigned char txsrc_select[AUDIO_NUM_SOURCES+1] =
37 {
38 [AUDIO_SRC_PLAYBACK+1] = 3, /* PDOR3 */
39 [AUDIO_SRC_MIC+1] = 4, /* IIS1 RcvData */
40 [AUDIO_SRC_LINEIN+1] = 4, /* IIS1 RcvData */
41 [AUDIO_SRC_FMRADIO+1] = 4, /* IIS1 RcvData */
42 };
28 43
29 (void)source;
30 int level = set_irq_level(DMA_IRQ_LEVEL); 44 int level = set_irq_level(DMA_IRQ_LEVEL);
31 45
32 /* PDOR3 */ 46 if ((unsigned)source >= AUDIO_NUM_SOURCES)
33 IIS2CONFIG = (IIS2CONFIG & ~(7 << 8)) | (3 << 8); 47 source = AUDIO_SRC_PLAYBACK;
48
49 IIS2CONFIG = (IIS2CONFIG & ~(7 << 8)) | (txsrc_select[source+1] << 8);
34 50
35 restore_irq(level); 51 restore_irq(level);
36} 52}
37 53
38void audio_input_mux(int source, unsigned flags) 54void audio_input_mux(int source, unsigned flags)
39{ 55{
40 (void)source; 56 /* Prevent pops from unneeded switching */
41 (void)flags; 57 static int last_source = AUDIO_SRC_PLAYBACK;
58 bool recording = flags & SRCF_RECORDING;
59 static bool last_recording = false;
42 60
43 switch(source) 61 switch(source)
44 { 62 {
63 default:
64 /* playback - no recording */
65 source = AUDIO_SRC_PLAYBACK;
66
67 case AUDIO_SRC_PLAYBACK:
68 if (source != last_source)
69 {
70 audiohw_set_recsrc(source,false);
71 coldfire_set_dataincontrol(0);
72 }
73 break;
74
75 case AUDIO_SRC_MIC:
76 case AUDIO_SRC_LINEIN:
77 /* recording only */
78 if (source != last_source)
79 {
80 audiohw_set_recsrc(source,true);
81 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
82 coldfire_set_dataincontrol((3 << 14) | (4 << 3));
83 }
84 break;
85
45 case AUDIO_SRC_FMRADIO: 86 case AUDIO_SRC_FMRADIO:
46 break; 87 if (source == last_source && recording == last_recording)
88 break;
89
90 last_recording = recording;
91
92 /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */
93 coldfire_set_dataincontrol(recording ?
94 ((3 << 14) | (4 << 3)) : 0);
95 audiohw_set_recsrc(source, recording);
96 break;
47 } 97 }
48 /* empty stub */ 98
99 last_source = source;
49} 100}