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
This commit is contained in:
Marcin Bukat 2011-03-14 23:06:33 +00:00
parent 9c41252d77
commit ae68278c8d
2 changed files with 75 additions and 51 deletions

View file

@ -33,19 +33,16 @@
const struct sound_settings_info audiohw_settings[] = {
[SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25},
#ifdef USE_ADAPTIVE_BASS
[SOUND_BASS] = {"", 0, 1, 0, 15, 0},
#else
[SOUND_BASS] = {"dB", 1, 15, -60, 90, 0},
#endif
[SOUND_TREBLE] = {"dB", 1, 15, -60, 90, 0},
[SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
[SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
[SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
#ifdef HAVE_RECORDING
[SOUND_LEFT_GAIN] = {"dB", 1, 50,-970, 300, 0},
[SOUND_RIGHT_GAIN] = {"dB", 1, 50,-970, 300, 0},
[SOUND_MIC_GAIN] = {"dB", 1, 50,-970, 300, 0},
/* -97.0dB to 30.0dB in 0.5dB increments */
[SOUND_LEFT_GAIN] = {"dB", 1, 1,-194, 60, 0},
[SOUND_RIGHT_GAIN] = {"dB", 1, 1,-194, 60, 0},
[SOUND_MIC_GAIN] = {"dB", 1, 1,-194, 60, 60},
#endif
#ifdef AUDIOHW_HAVE_BASS_CUTOFF
[SOUND_BASS_CUTOFF] = {"Hz", 0, 70, 130, 200, 200},
@ -54,12 +51,10 @@ const struct sound_settings_info audiohw_settings[] = {
[SOUND_TREBLE_CUTOFF] = {"kHz",0, 4, 4, 8, 4},
#endif
#ifdef AUDIOHW_HAVE_DEPTH_3D
[SOUND_DEPTH_3D] = {"", 0, 1, -1, 15, -1},
[SOUND_DEPTH_3D] = {"%", 0, 1, 0, 15, 0},
#endif
};
static int prescaler = 0;
static uint16_t wmcodec_regs[WM_NUM_REGS] =
{
[0 ... WM_NUM_REGS-1] = 0x200, /* set invalid data in gaps */
@ -107,6 +102,10 @@ static uint16_t wmcodec_regs[WM_NUM_REGS] =
[MONOOUT] = 0x079
};
/* global prescaler vars */
static int prescalertone = 0;
static int prescaler3d = 0;
static void wmcodec_set_reg(unsigned int reg, unsigned int val)
{
if (reg >= WM_NUM_REGS || (wmcodec_regs[reg] & 0x200))
@ -160,16 +159,6 @@ static int tone_tenthdb2hw(int value)
return value;
}
#ifdef USE_ADAPTIVE_BASS
static int adaptivebass2hw(int value)
{
/* 0 to 15 step 1 - step -1 0 = off is a 15 in the register */
value = 15 - value;
return value;
}
#endif
#ifdef AUDIOHW_HAVE_BASS_CUTOFF
void audiohw_set_bass_cutoff(int val)
{
@ -200,14 +189,38 @@ static int recvol2hw(int value)
}
#endif
int sound_val2phys(int setting, int value)
{
int result;
switch (setting)
{
#ifdef HAVE_RECORDING
case SOUND_LEFT_GAIN:
case SOUND_RIGHT_GAIN:
case SOUND_MIC_GAIN:
result = value * 5;
break;
#endif
case SOUND_DEPTH_3D:
result = (100 * value + 8) / 15;
break;
default:
result = value;
}
return result;
}
static void audiohw_mute(bool mute)
{
/* Mute: Set DACMU = 1 to soft-mute the audio DACs. */
/* Unmute: Set DACMU = 0 to soft-un-mute the audio DACs. */
if (mute)
wmcodec_set_bits(DACCTRL,DACCTRL_DACMU);
wmcodec_set_bits(DACCTRL, DACCTRL_DACMU);
else
wmcodec_clear_bits(DACCTRL,DACCTRL_DACMU);
wmcodec_clear_bits(DACCTRL, DACCTRL_DACMU);
}
/* Reset and power up the WM8751 */
@ -243,7 +256,7 @@ void audiohw_preinit(void)
wmcodec_set_bits(PWRMGMT1, PWRMGMT1_VREF | PWRMGMT1_VMIDSEL_5K);
#ifdef CODEC_SLAVE
wmcodec_set_bits(AINTFCE,AINTFCE_WL_16|AINTFCE_FORMAT_I2S);
wmcodec_set_bits(AINTFCE,AINTFCE_WL_16 | AINTFCE_FORMAT_I2S);
#else
/* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */
/* IWL=00(16 bit) FORMAT=10(I2S format) */
@ -261,25 +274,21 @@ void audiohw_postinit(void)
/* From app notes: allow Vref to stabilize to reduce clicks */
sleep(HZ);
#ifdef AUDIOHW_HAVE_DEPTH_3D
wmcodec_set_bits(ENHANCE_3D, ENHANCE_3D_MODE3D_PLAYBACK);
#endif
#ifdef USE_ADAPTIVE_BASS
wmcodec_set_bits(BASSCTRL, BASSCTRL_BB);
#endif
/* 3. Enable DACs as required. */
wmcodec_set_bits(PWRMGMT2, PWRMGMT2_DACL | PWRMGMT2_DACR);
/* 4. Enable line and / or headphone output buffers as required. */
#if defined(MROBE_100) || defined(MPIO_HD200)
/* power-up output stage */
wmcodec_set_bits(PWRMGMT2, PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
#else
#if defined(GIGABEATFX)
/* headphones + line-out */
wmcodec_set_bits(PWRMGMT2, PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1 |
PWRMGMT2_LOUT2 | PWRMGMT2_ROUT2);
#else
/* headphones */
wmcodec_set_bits(PWRMGMT2, PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1);
#endif
/* Full -0dB on the DACS */
@ -359,12 +368,8 @@ void audiohw_set_lineout_vol(int vol_l, int vol_r)
void audiohw_set_bass(int value)
{
wmcodec_set_masked(BASSCTRL,
#ifdef USE_ADAPTIVE_BASS
BASSCTRL_BASS(adaptivebass2hw(value)),BASSCTRL_BASS_MASK);
#else
BASSCTRL_BASS(tone_tenthdb2hw(value)),BASSCTRL_BASS_MASK);
#endif
BASSCTRL_BASS(tone_tenthdb2hw(value)),
BASSCTRL_BASS_MASK);
}
void audiohw_set_treble(int value)
@ -373,12 +378,21 @@ void audiohw_set_treble(int value)
TREBCTRL_TREB_MASK);
}
static void sync_prescaler(void)
{
int prescaler;
prescaler = prescalertone + prescaler3d;
/* attenuate in 0.5dB steps (0dB - -127dB) */
wmcodec_set_reg(LEFTGAIN, 0xff - (prescaler & LEFTGAIN_LDACVOL));
wmcodec_set_reg(RIGHTGAIN, RIGHTGAIN_RDVU |
(0xff - (prescaler & RIGHTGAIN_RDACVOL)));
}
void audiohw_set_prescaler(int value)
{
prescaler = 3 * value / 15;
wmcodec_set_reg(LEFTGAIN, 0xff - (prescaler & LEFTGAIN_LDACVOL));
wmcodec_set_reg(RIGHTGAIN, RIGHTGAIN_RDVU |
(0xff - (prescaler & RIGHTGAIN_RDACVOL)));
prescalertone = 3 * value / 15; /* value in tdB */
sync_prescaler();
}
/* Nice shutdown of WM8751 codec */
@ -424,11 +438,9 @@ void audiohw_set_frequency(int fsel)
/* Set the depth of the 3D effect */
void audiohw_set_depth_3d(int val)
{
if (val >= 0)
if (val > 0)
{
if ( !(wmcodec_regs[ENHANCE_3D] & ENHANCE_3D_3DEN) )
wmcodec_set_bits(ENHANCE_3D, ENHANCE_3D_3DEN);
wmcodec_set_bits(ENHANCE_3D, ENHANCE_3D_3DEN);
wmcodec_set_masked(ENHANCE_3D, ENHANCE_3D_DEPTH(val),
ENHANCE_3D_DEPTH_MASK);
}
@ -436,10 +448,18 @@ void audiohw_set_depth_3d(int val)
{
wmcodec_clear_bits(ENHANCE_3D, ENHANCE_3D_3DEN);
}
/* -4 dB @ full setting
* this gives approximately constant volume on setting change
* and prevents clipping (at least on my HD300)
*/
prescaler3d = 8*val / 15;
sync_prescaler();
}
#endif
#ifdef HAVE_RECORDING
#if 0
static void audiohw_set_ngat(int ngath, int type, bool enable)
{
/* This function controls Noise gate function
@ -474,6 +494,7 @@ static void audiohw_set_alc(unsigned char level, /* signal level at ADC */
wmcodec_set_masked(ALC1, ALC1_ALCSEL_DISABLED, ALC1_ALCSEL_MASK);
}
}
#endif
void audiohw_set_recsrc(int source, bool recording)
{
@ -529,8 +550,10 @@ void audiohw_set_recsrc(int source, bool recording)
wmcodec_set_masked(ADCR, ADCR_RINSEL_RINPUT1, ADCR_RINSEL_MASK);
/* turn off ALC and NGAT as OF do */
/*
audiohw_set_alc(0x00, false, 0x00, 0x00, 0x00, false);
audiohw_set_ngat(0x00, 0x00, false);
*/
/* setup output digital data
* default is LADC -> LDATA, RADC -> RDATA
@ -596,9 +619,9 @@ void audiohw_set_recsrc(int source, bool recording)
/* setup ALC and NGAT as OF do */
/* level, zc, hold, decay, attack, enable */
audiohw_set_alc(0x0b, true, 0x00, 0x03, 0x02, true);
/* audiohw_set_alc(0x0b, true, 0x00, 0x03, 0x02, true); */
/* ngath, type, enable */
audiohw_set_ngat(0x08, 0x02, true);
/* audiohw_set_ngat(0x08, 0x02, true); */
/* setup output digital data
* default is LADC -> LDATA, RADC -> RDATA
@ -634,9 +657,9 @@ void audiohw_set_recsrc(int source, bool recording)
/* setup ALC and NGAT as OF do */
/* level, zc, hold, decay, attack, enable */
audiohw_set_alc(0x0f, false, 0x00, 0x05, 0x02, true);
/* audiohw_set_alc(0x0f, false, 0x00, 0x05, 0x02, true); */
/* ngath, type, enable */
audiohw_set_ngat(0x1f, 0x00, true);
/* audiohw_set_ngat(0x1f, 0x00, true); */
/* setup output digital data
* default is LADC -> LDATA, RADC -> RDATA

View file

@ -669,6 +669,7 @@ void sound_set(int setting, int value)
&& !defined(HAVE_WM8758) && !defined(HAVE_TSC2100) \
&& !defined (HAVE_WM8711) && !defined (HAVE_WM8721) \
&& !defined (HAVE_WM8731) && !defined (HAVE_WM8978) \
&& !defined (HAVE_WM8750) && !defined (HAVE_WM8751) \
&& !defined(HAVE_AK4537)) || (CONFIG_PLATFORM & PLATFORM_HOSTED)
int sound_val2phys(int setting, int value)
{
@ -748,7 +749,7 @@ int sound_val2phys(int setting, int value)
}
return result;
#elif defined(HAVE_WM8978)
#elif defined(HAVE_WM8978) || defined(HAVE_WM8750) || defined(HAVE_WM8751)
int result;
switch (setting)