summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2011-03-14 23:06:33 +0000
committerMarcin Bukat <marcin.bukat@gmail.com>2011-03-14 23:06:33 +0000
commitae68278c8d3c253b2417439b0176f97476f8caa4 (patch)
treee77982e35bc3d4e5124295d7f4e6f8608dd96392
parent9c41252d771e8b1d114ca023aaa837c99782a3c3 (diff)
downloadrockbox-ae68278c8d3c253b2417439b0176f97476f8caa4.tar.gz
rockbox-ae68278c8d3c253b2417439b0176f97476f8caa4.zip
WM8750/51 driver:
1) Set prescaler correctly when 3d enhancement in use. 2) Implement sound_val2phys so gains in recording screen are correct. 3) Minor cleanups. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29588 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/audio/wm8751.c121
-rw-r--r--firmware/sound.c3
2 files changed, 74 insertions, 50 deletions
diff --git a/firmware/drivers/audio/wm8751.c b/firmware/drivers/audio/wm8751.c
index b9d41c7b32..02a04a3802 100644
--- a/firmware/drivers/audio/wm8751.c
+++ b/firmware/drivers/audio/wm8751.c
@@ -33,19 +33,16 @@
33 33
34const struct sound_settings_info audiohw_settings[] = { 34const struct sound_settings_info audiohw_settings[] = {
35 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25}, 35 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25},
36#ifdef USE_ADAPTIVE_BASS
37 [SOUND_BASS] = {"", 0, 1, 0, 15, 0},
38#else
39 [SOUND_BASS] = {"dB", 1, 15, -60, 90, 0}, 36 [SOUND_BASS] = {"dB", 1, 15, -60, 90, 0},
40#endif
41 [SOUND_TREBLE] = {"dB", 1, 15, -60, 90, 0}, 37 [SOUND_TREBLE] = {"dB", 1, 15, -60, 90, 0},
42 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, 38 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
43 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, 39 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
44 [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, 40 [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
45#ifdef HAVE_RECORDING 41#ifdef HAVE_RECORDING
46 [SOUND_LEFT_GAIN] = {"dB", 1, 50,-970, 300, 0}, 42 /* -97.0dB to 30.0dB in 0.5dB increments */
47 [SOUND_RIGHT_GAIN] = {"dB", 1, 50,-970, 300, 0}, 43 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-194, 60, 0},
48 [SOUND_MIC_GAIN] = {"dB", 1, 50,-970, 300, 0}, 44 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-194, 60, 0},
45 [SOUND_MIC_GAIN] = {"dB", 1, 1,-194, 60, 60},
49#endif 46#endif
50#ifdef AUDIOHW_HAVE_BASS_CUTOFF 47#ifdef AUDIOHW_HAVE_BASS_CUTOFF
51 [SOUND_BASS_CUTOFF] = {"Hz", 0, 70, 130, 200, 200}, 48 [SOUND_BASS_CUTOFF] = {"Hz", 0, 70, 130, 200, 200},
@@ -54,12 +51,10 @@ const struct sound_settings_info audiohw_settings[] = {
54 [SOUND_TREBLE_CUTOFF] = {"kHz",0, 4, 4, 8, 4}, 51 [SOUND_TREBLE_CUTOFF] = {"kHz",0, 4, 4, 8, 4},
55#endif 52#endif
56#ifdef AUDIOHW_HAVE_DEPTH_3D 53#ifdef AUDIOHW_HAVE_DEPTH_3D
57 [SOUND_DEPTH_3D] = {"", 0, 1, -1, 15, -1}, 54 [SOUND_DEPTH_3D] = {"%", 0, 1, 0, 15, 0},
58#endif 55#endif
59}; 56};
60 57
61static int prescaler = 0;
62
63static uint16_t wmcodec_regs[WM_NUM_REGS] = 58static uint16_t wmcodec_regs[WM_NUM_REGS] =
64{ 59{
65 [0 ... WM_NUM_REGS-1] = 0x200, /* set invalid data in gaps */ 60 [0 ... WM_NUM_REGS-1] = 0x200, /* set invalid data in gaps */
@@ -107,6 +102,10 @@ static uint16_t wmcodec_regs[WM_NUM_REGS] =
107 [MONOOUT] = 0x079 102 [MONOOUT] = 0x079
108}; 103};
109 104
105/* global prescaler vars */
106static int prescalertone = 0;
107static int prescaler3d = 0;
108
110static void wmcodec_set_reg(unsigned int reg, unsigned int val) 109static void wmcodec_set_reg(unsigned int reg, unsigned int val)
111{ 110{
112 if (reg >= WM_NUM_REGS || (wmcodec_regs[reg] & 0x200)) 111 if (reg >= WM_NUM_REGS || (wmcodec_regs[reg] & 0x200))
@@ -160,16 +159,6 @@ static int tone_tenthdb2hw(int value)
160 return value; 159 return value;
161} 160}
162 161
163#ifdef USE_ADAPTIVE_BASS
164static int adaptivebass2hw(int value)
165{
166 /* 0 to 15 step 1 - step -1 0 = off is a 15 in the register */
167 value = 15 - value;
168
169 return value;
170}
171#endif
172
173#ifdef AUDIOHW_HAVE_BASS_CUTOFF 162#ifdef AUDIOHW_HAVE_BASS_CUTOFF
174void audiohw_set_bass_cutoff(int val) 163void audiohw_set_bass_cutoff(int val)
175{ 164{
@@ -200,14 +189,38 @@ static int recvol2hw(int value)
200} 189}
201#endif 190#endif
202 191
192int sound_val2phys(int setting, int value)
193{
194 int result;
195
196 switch (setting)
197 {
198#ifdef HAVE_RECORDING
199 case SOUND_LEFT_GAIN:
200 case SOUND_RIGHT_GAIN:
201 case SOUND_MIC_GAIN:
202 result = value * 5;
203 break;
204#endif
205 case SOUND_DEPTH_3D:
206 result = (100 * value + 8) / 15;
207 break;
208
209 default:
210 result = value;
211 }
212
213 return result;
214}
215
203static void audiohw_mute(bool mute) 216static void audiohw_mute(bool mute)
204{ 217{
205 /* Mute: Set DACMU = 1 to soft-mute the audio DACs. */ 218 /* Mute: Set DACMU = 1 to soft-mute the audio DACs. */
206 /* Unmute: Set DACMU = 0 to soft-un-mute the audio DACs. */ 219 /* Unmute: Set DACMU = 0 to soft-un-mute the audio DACs. */
207 if (mute) 220 if (mute)
208 wmcodec_set_bits(DACCTRL,DACCTRL_DACMU); 221 wmcodec_set_bits(DACCTRL, DACCTRL_DACMU);
209 else 222 else
210 wmcodec_clear_bits(DACCTRL,DACCTRL_DACMU); 223 wmcodec_clear_bits(DACCTRL, DACCTRL_DACMU);
211} 224}
212 225
213/* Reset and power up the WM8751 */ 226/* Reset and power up the WM8751 */
@@ -243,7 +256,7 @@ void audiohw_preinit(void)
243 wmcodec_set_bits(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_5K); 256 wmcodec_set_bits(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_5K);
244 257
245#ifdef CODEC_SLAVE 258#ifdef CODEC_SLAVE
246 wmcodec_set_bits(AINTFCE,AINTFCE_WL_16|AINTFCE_FORMAT_I2S); 259 wmcodec_set_bits(AINTFCE,AINTFCE_WL_16 | AINTFCE_FORMAT_I2S);
247#else 260#else
248 /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */ 261 /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */
249 /* IWL=00(16 bit) FORMAT=10(I2S format) */ 262 /* IWL=00(16 bit) FORMAT=10(I2S format) */
@@ -261,25 +274,21 @@ void audiohw_postinit(void)
261 /* From app notes: allow Vref to stabilize to reduce clicks */ 274 /* From app notes: allow Vref to stabilize to reduce clicks */
262 sleep(HZ); 275 sleep(HZ);
263 276
264
265#ifdef AUDIOHW_HAVE_DEPTH_3D 277#ifdef AUDIOHW_HAVE_DEPTH_3D
266 wmcodec_set_bits(ENHANCE_3D, ENHANCE_3D_MODE3D_PLAYBACK); 278 wmcodec_set_bits(ENHANCE_3D, ENHANCE_3D_MODE3D_PLAYBACK);
267#endif 279#endif
268 280
269#ifdef USE_ADAPTIVE_BASS
270 wmcodec_set_bits(BASSCTRL, BASSCTRL_BB);
271#endif
272
273 /* 3. Enable DACs as required. */ 281 /* 3. Enable DACs as required. */
274 wmcodec_set_bits(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR); 282 wmcodec_set_bits(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR);
275 283
276 /* 4. Enable line and / or headphone output buffers as required. */ 284 /* 4. Enable line and / or headphone output buffers as required. */
277#if defined(MROBE_100) || defined(MPIO_HD200) 285#if defined(GIGABEATFX)
278 /* power-up output stage */ 286 /* headphones + line-out */
279 wmcodec_set_bits(PWRMGMT2, PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
280#else
281 wmcodec_set_bits(PWRMGMT2, PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1 | 287 wmcodec_set_bits(PWRMGMT2, PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1 |
282 PWRMGMT2_LOUT2 | PWRMGMT2_ROUT2); 288 PWRMGMT2_LOUT2 | PWRMGMT2_ROUT2);
289#else
290 /* headphones */
291 wmcodec_set_bits(PWRMGMT2, PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
283#endif 292#endif
284 293
285 /* Full -0dB on the DACS */ 294 /* Full -0dB on the DACS */
@@ -359,12 +368,8 @@ void audiohw_set_lineout_vol(int vol_l, int vol_r)
359void audiohw_set_bass(int value) 368void audiohw_set_bass(int value)
360{ 369{
361 wmcodec_set_masked(BASSCTRL, 370 wmcodec_set_masked(BASSCTRL,
362 371 BASSCTRL_BASS(tone_tenthdb2hw(value)),
363#ifdef USE_ADAPTIVE_BASS 372 BASSCTRL_BASS_MASK);
364 BASSCTRL_BASS(adaptivebass2hw(value)),BASSCTRL_BASS_MASK);
365#else
366 BASSCTRL_BASS(tone_tenthdb2hw(value)),BASSCTRL_BASS_MASK);
367#endif
368} 373}
369 374
370void audiohw_set_treble(int value) 375void audiohw_set_treble(int value)
@@ -373,14 +378,23 @@ void audiohw_set_treble(int value)
373 TREBCTRL_TREB_MASK); 378 TREBCTRL_TREB_MASK);
374} 379}
375 380
376void audiohw_set_prescaler(int value) 381static void sync_prescaler(void)
377{ 382{
378 prescaler = 3 * value / 15; 383 int prescaler;
384 prescaler = prescalertone + prescaler3d;
385
386 /* attenuate in 0.5dB steps (0dB - -127dB) */
379 wmcodec_set_reg(LEFTGAIN, 0xff - (prescaler & LEFTGAIN_LDACVOL)); 387 wmcodec_set_reg(LEFTGAIN, 0xff - (prescaler & LEFTGAIN_LDACVOL));
380 wmcodec_set_reg(RIGHTGAIN, RIGHTGAIN_RDVU | 388 wmcodec_set_reg(RIGHTGAIN, RIGHTGAIN_RDVU |
381 (0xff - (prescaler & RIGHTGAIN_RDACVOL))); 389 (0xff - (prescaler & RIGHTGAIN_RDACVOL)));
382} 390}
383 391
392void audiohw_set_prescaler(int value)
393{
394 prescalertone = 3 * value / 15; /* value in tdB */
395 sync_prescaler();
396}
397
384/* Nice shutdown of WM8751 codec */ 398/* Nice shutdown of WM8751 codec */
385void audiohw_close(void) 399void audiohw_close(void)
386{ 400{
@@ -424,11 +438,9 @@ void audiohw_set_frequency(int fsel)
424/* Set the depth of the 3D effect */ 438/* Set the depth of the 3D effect */
425void audiohw_set_depth_3d(int val) 439void audiohw_set_depth_3d(int val)
426{ 440{
427 if (val >= 0) 441 if (val > 0)
428 { 442 {
429 if ( !(wmcodec_regs[ENHANCE_3D] & ENHANCE_3D_3DEN) ) 443 wmcodec_set_bits(ENHANCE_3D, ENHANCE_3D_3DEN);
430 wmcodec_set_bits(ENHANCE_3D, ENHANCE_3D_3DEN);
431
432 wmcodec_set_masked(ENHANCE_3D, ENHANCE_3D_DEPTH(val), 444 wmcodec_set_masked(ENHANCE_3D, ENHANCE_3D_DEPTH(val),
433 ENHANCE_3D_DEPTH_MASK); 445 ENHANCE_3D_DEPTH_MASK);
434 } 446 }
@@ -436,10 +448,18 @@ void audiohw_set_depth_3d(int val)
436 { 448 {
437 wmcodec_clear_bits(ENHANCE_3D, ENHANCE_3D_3DEN); 449 wmcodec_clear_bits(ENHANCE_3D, ENHANCE_3D_3DEN);
438 } 450 }
451
452 /* -4 dB @ full setting
453 * this gives approximately constant volume on setting change
454 * and prevents clipping (at least on my HD300)
455 */
456 prescaler3d = 8*val / 15;
457 sync_prescaler();
439} 458}
440#endif 459#endif
441 460
442#ifdef HAVE_RECORDING 461#ifdef HAVE_RECORDING
462#if 0
443static void audiohw_set_ngat(int ngath, int type, bool enable) 463static void audiohw_set_ngat(int ngath, int type, bool enable)
444{ 464{
445 /* This function controls Noise gate function 465 /* This function controls Noise gate function
@@ -474,6 +494,7 @@ static void audiohw_set_alc(unsigned char level, /* signal level at ADC */
474 wmcodec_set_masked(ALC1, ALC1_ALCSEL_DISABLED, ALC1_ALCSEL_MASK); 494 wmcodec_set_masked(ALC1, ALC1_ALCSEL_DISABLED, ALC1_ALCSEL_MASK);
475 } 495 }
476} 496}
497#endif
477 498
478void audiohw_set_recsrc(int source, bool recording) 499void audiohw_set_recsrc(int source, bool recording)
479{ 500{
@@ -529,8 +550,10 @@ void audiohw_set_recsrc(int source, bool recording)
529 wmcodec_set_masked(ADCR, ADCR_RINSEL_RINPUT1, ADCR_RINSEL_MASK); 550 wmcodec_set_masked(ADCR, ADCR_RINSEL_RINPUT1, ADCR_RINSEL_MASK);
530 551
531 /* turn off ALC and NGAT as OF do */ 552 /* turn off ALC and NGAT as OF do */
553 /*
532 audiohw_set_alc(0x00, false, 0x00, 0x00, 0x00, false); 554 audiohw_set_alc(0x00, false, 0x00, 0x00, 0x00, false);
533 audiohw_set_ngat(0x00, 0x00, false); 555 audiohw_set_ngat(0x00, 0x00, false);
556 */
534 557
535 /* setup output digital data 558 /* setup output digital data
536 * default is LADC -> LDATA, RADC -> RDATA 559 * default is LADC -> LDATA, RADC -> RDATA
@@ -596,9 +619,9 @@ void audiohw_set_recsrc(int source, bool recording)
596 619
597 /* setup ALC and NGAT as OF do */ 620 /* setup ALC and NGAT as OF do */
598 /* level, zc, hold, decay, attack, enable */ 621 /* level, zc, hold, decay, attack, enable */
599 audiohw_set_alc(0x0b, true, 0x00, 0x03, 0x02, true); 622 /* audiohw_set_alc(0x0b, true, 0x00, 0x03, 0x02, true); */
600 /* ngath, type, enable */ 623 /* ngath, type, enable */
601 audiohw_set_ngat(0x08, 0x02, true); 624 /* audiohw_set_ngat(0x08, 0x02, true); */
602 625
603 /* setup output digital data 626 /* setup output digital data
604 * default is LADC -> LDATA, RADC -> RDATA 627 * default is LADC -> LDATA, RADC -> RDATA
@@ -634,9 +657,9 @@ void audiohw_set_recsrc(int source, bool recording)
634 657
635 /* setup ALC and NGAT as OF do */ 658 /* setup ALC and NGAT as OF do */
636 /* level, zc, hold, decay, attack, enable */ 659 /* level, zc, hold, decay, attack, enable */
637 audiohw_set_alc(0x0f, false, 0x00, 0x05, 0x02, true); 660 /* audiohw_set_alc(0x0f, false, 0x00, 0x05, 0x02, true); */
638 /* ngath, type, enable */ 661 /* ngath, type, enable */
639 audiohw_set_ngat(0x1f, 0x00, true); 662 /* audiohw_set_ngat(0x1f, 0x00, true); */
640 663
641 /* setup output digital data 664 /* setup output digital data
642 * default is LADC -> LDATA, RADC -> RDATA 665 * default is LADC -> LDATA, RADC -> RDATA
diff --git a/firmware/sound.c b/firmware/sound.c
index efdcb19987..658a732a15 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -669,6 +669,7 @@ void sound_set(int setting, int value)
669 && !defined(HAVE_WM8758) && !defined(HAVE_TSC2100) \ 669 && !defined(HAVE_WM8758) && !defined(HAVE_TSC2100) \
670 && !defined (HAVE_WM8711) && !defined (HAVE_WM8721) \ 670 && !defined (HAVE_WM8711) && !defined (HAVE_WM8721) \
671 && !defined (HAVE_WM8731) && !defined (HAVE_WM8978) \ 671 && !defined (HAVE_WM8731) && !defined (HAVE_WM8978) \
672 && !defined (HAVE_WM8750) && !defined (HAVE_WM8751) \
672 && !defined(HAVE_AK4537)) || (CONFIG_PLATFORM & PLATFORM_HOSTED) 673 && !defined(HAVE_AK4537)) || (CONFIG_PLATFORM & PLATFORM_HOSTED)
673int sound_val2phys(int setting, int value) 674int sound_val2phys(int setting, int value)
674{ 675{
@@ -748,7 +749,7 @@ int sound_val2phys(int setting, int value)
748 } 749 }
749 750
750 return result; 751 return result;
751#elif defined(HAVE_WM8978) 752#elif defined(HAVE_WM8978) || defined(HAVE_WM8750) || defined(HAVE_WM8751)
752 int result; 753 int result;
753 754
754 switch (setting) 755 switch (setting)