diff options
author | Marcin Bukat <marcin.bukat@gmail.com> | 2011-03-14 23:06:33 +0000 |
---|---|---|
committer | Marcin Bukat <marcin.bukat@gmail.com> | 2011-03-14 23:06:33 +0000 |
commit | ae68278c8d3c253b2417439b0176f97476f8caa4 (patch) | |
tree | e77982e35bc3d4e5124295d7f4e6f8608dd96392 | |
parent | 9c41252d771e8b1d114ca023aaa837c99782a3c3 (diff) | |
download | rockbox-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.c | 121 | ||||
-rw-r--r-- | firmware/sound.c | 3 |
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 | ||
34 | const struct sound_settings_info audiohw_settings[] = { | 34 | const 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 | ||
61 | static int prescaler = 0; | ||
62 | |||
63 | static uint16_t wmcodec_regs[WM_NUM_REGS] = | 58 | static 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 */ | ||
106 | static int prescalertone = 0; | ||
107 | static int prescaler3d = 0; | ||
108 | |||
110 | static void wmcodec_set_reg(unsigned int reg, unsigned int val) | 109 | static 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 | ||
164 | static 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 |
174 | void audiohw_set_bass_cutoff(int val) | 163 | void 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 | ||
192 | int 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 | |||
203 | static void audiohw_mute(bool mute) | 216 | static 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) | |||
359 | void audiohw_set_bass(int value) | 368 | void 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 | ||
370 | void audiohw_set_treble(int value) | 375 | void 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 | ||
376 | void audiohw_set_prescaler(int value) | 381 | static 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 | ||
392 | void 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 */ |
385 | void audiohw_close(void) | 399 | void 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 */ |
425 | void audiohw_set_depth_3d(int val) | 439 | void 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 | ||
443 | static void audiohw_set_ngat(int ngath, int type, bool enable) | 463 | static 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 | ||
478 | void audiohw_set_recsrc(int source, bool recording) | 499 | void 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) |
673 | int sound_val2phys(int setting, int value) | 674 | int 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) |