mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
ASoC: rk3308_codec: using default gains on startup
We don't need to set gains when enable/disable ADC and DAC, keep gains at last time. And add hpout fade-in when enable DAC, and clean up a bit of coding style for gains. Change-Id: I2d8cdc1b0d87b55714177a1208a8f7a4e655a732 Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
This commit is contained in:
@@ -140,6 +140,10 @@ struct rk3308_codec_priv {
|
||||
int adc_path_state;
|
||||
int dac_path_state;
|
||||
|
||||
/* Only hpout do fade-in and fade-out */
|
||||
unsigned int hpout_l_dgain;
|
||||
unsigned int hpout_r_dgain;
|
||||
|
||||
bool enable_all_adcs;
|
||||
bool hp_plugged;
|
||||
struct delayed_work hpdet_work;
|
||||
@@ -175,6 +179,15 @@ static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_3_8_mic_gain_tlv,
|
||||
3, 3, TLV_DB_MINMAX_ITEM(2000, 2000),
|
||||
);
|
||||
|
||||
static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = {
|
||||
/* ALC AGC Group */
|
||||
SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Volume",
|
||||
@@ -448,16 +461,22 @@ static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = {
|
||||
0, rk3308_codec_dac_lineout_gain_tlv),
|
||||
|
||||
/* DAC HPOUT */
|
||||
SOC_SINGLE_TLV("DAC HPOUT Left Volume",
|
||||
RK3308_DAC_ANA_CON05,
|
||||
RK3308_DAC_L_HPOUT_GAIN_SFT,
|
||||
RK3308_DAC_L_HPOUT_GAIN_MAX,
|
||||
0, rk3308_codec_dac_hpout_gain_tlv),
|
||||
SOC_SINGLE_TLV("DAC HPOUT Right Volume",
|
||||
RK3308_DAC_ANA_CON06,
|
||||
RK3308_DAC_R_HPOUT_GAIN_SFT,
|
||||
RK3308_DAC_R_HPOUT_GAIN_MAX,
|
||||
0, rk3308_codec_dac_hpout_gain_tlv),
|
||||
SOC_SINGLE_EXT_TLV("DAC HPOUT Left Volume",
|
||||
RK3308_DAC_ANA_CON05,
|
||||
RK3308_DAC_L_HPOUT_GAIN_SFT,
|
||||
RK3308_DAC_L_HPOUT_GAIN_MAX,
|
||||
0,
|
||||
rk3308_codec_hpout_l_get_tlv,
|
||||
rk3308_codec_hpout_l_put_tlv,
|
||||
rk3308_codec_dac_hpout_gain_tlv),
|
||||
SOC_SINGLE_EXT_TLV("DAC HPOUT Right Volume",
|
||||
RK3308_DAC_ANA_CON06,
|
||||
RK3308_DAC_R_HPOUT_GAIN_SFT,
|
||||
RK3308_DAC_R_HPOUT_GAIN_MAX,
|
||||
0,
|
||||
rk3308_codec_hpout_r_get_tlv,
|
||||
rk3308_codec_hpout_r_put_tlv,
|
||||
rk3308_codec_dac_hpout_gain_tlv),
|
||||
|
||||
/* DAC HPMIX */
|
||||
SOC_SINGLE_RANGE_TLV("DAC HPMIX Left Volume",
|
||||
@@ -474,6 +493,54 @@ static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = {
|
||||
0, rk3308_codec_dac_hpmix_gain_tlv),
|
||||
};
|
||||
|
||||
static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
return snd_soc_get_volsw_range(kcontrol, ucontrol);
|
||||
}
|
||||
|
||||
static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int dgain = ucontrol->value.integer.value[0];
|
||||
|
||||
if (dgain > RK3308_DAC_L_HPOUT_GAIN_MAX) {
|
||||
dev_err(rk3308->plat_dev, "%s: invalid l_dgain: %d\n",
|
||||
__func__, dgain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rk3308->hpout_l_dgain = dgain;
|
||||
|
||||
return snd_soc_put_volsw_range(kcontrol, ucontrol);
|
||||
}
|
||||
|
||||
static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
return snd_soc_get_volsw_range(kcontrol, ucontrol);
|
||||
}
|
||||
|
||||
static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int dgain = ucontrol->value.integer.value[0];
|
||||
|
||||
if (dgain > RK3308_DAC_R_HPOUT_GAIN_MAX) {
|
||||
dev_err(rk3308->plat_dev, "%s: invalid r_dgain: %d\n",
|
||||
__func__, dgain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rk3308->hpout_r_dgain = dgain;
|
||||
|
||||
return snd_soc_put_volsw_range(kcontrol, ucontrol);
|
||||
}
|
||||
|
||||
static bool adc_for_each_grp(struct rk3308_codec_priv *rk3308,
|
||||
int type, int idx, u32 *grp)
|
||||
{
|
||||
@@ -901,6 +968,84 @@ static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3308_codec_digital_fadein(struct rk3308_codec_priv *rk3308)
|
||||
{
|
||||
unsigned int dgain, dgain_ref;
|
||||
|
||||
if (rk3308->hpout_l_dgain != rk3308->hpout_r_dgain) {
|
||||
pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n",
|
||||
rk3308->hpout_l_dgain, rk3308->hpout_r_dgain);
|
||||
dgain_ref = min(rk3308->hpout_l_dgain, rk3308->hpout_r_dgain);
|
||||
} else {
|
||||
dgain_ref = rk3308->hpout_l_dgain;
|
||||
}
|
||||
|
||||
/*
|
||||
* We'd better change the gain of the left and right channels
|
||||
* at the same time to avoid different listening
|
||||
*/
|
||||
for (dgain = RK3308_DAC_L_HPOUT_GAIN_NDB_39;
|
||||
dgain <= dgain_ref; dgain++) {
|
||||
/* Step 02 decrease dgains for de-pop */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05,
|
||||
RK3308_DAC_L_HPOUT_GAIN_MSK,
|
||||
dgain);
|
||||
|
||||
/* Step 02 decrease dgains for de-pop */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06,
|
||||
RK3308_DAC_R_HPOUT_GAIN_MSK,
|
||||
dgain);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3308_codec_digital_fadeout(struct rk3308_codec_priv *rk3308)
|
||||
{
|
||||
unsigned int l_dgain, r_dgain;
|
||||
|
||||
/*
|
||||
* Note. In the step2, adjusting the register step by step to
|
||||
* the appropriate value and taking 20ms as time step
|
||||
*/
|
||||
regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON05, &l_dgain);
|
||||
l_dgain &= RK3308_DAC_L_HPOUT_GAIN_MSK;
|
||||
|
||||
regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON06, &r_dgain);
|
||||
r_dgain &= RK3308_DAC_R_HPOUT_GAIN_MSK;
|
||||
|
||||
if (l_dgain != r_dgain) {
|
||||
pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n",
|
||||
l_dgain, r_dgain);
|
||||
l_dgain = min(l_dgain, r_dgain);
|
||||
}
|
||||
|
||||
/*
|
||||
* We'd better change the gain of the left and right channels
|
||||
* at the same time to avoid different listening
|
||||
*/
|
||||
while (l_dgain >= RK3308_DAC_L_HPOUT_GAIN_NDB_39) {
|
||||
/* Step 02 decrease dgains for de-pop */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05,
|
||||
RK3308_DAC_L_HPOUT_GAIN_MSK,
|
||||
l_dgain);
|
||||
|
||||
/* Step 02 decrease dgains for de-pop */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06,
|
||||
RK3308_DAC_R_HPOUT_GAIN_MSK,
|
||||
l_dgain);
|
||||
|
||||
usleep_range(200, 300); /* estimated value */
|
||||
|
||||
if (l_dgain == RK3308_DAC_L_HPOUT_GAIN_NDB_39)
|
||||
break;
|
||||
|
||||
l_dgain--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3308_codec_dac_lineout_enable(struct rk3308_codec_priv *rk3308)
|
||||
{
|
||||
/* Step 06 */
|
||||
@@ -1245,15 +1390,6 @@ static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308)
|
||||
|
||||
udelay(20);
|
||||
|
||||
/* Step 15 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12,
|
||||
RK3308_DAC_L_HPMIX_GAIN_MSK |
|
||||
RK3308_DAC_R_HPMIX_GAIN_MSK,
|
||||
RK3308_DAC_L_HPMIX_GAIN_NDB_6 |
|
||||
RK3308_DAC_R_HPMIX_GAIN_NDB_6);
|
||||
|
||||
udelay(20);
|
||||
|
||||
if (rk3308->dac_output == DAC_HPOUT ||
|
||||
rk3308->dac_output == DAC_LINEOUT_HPOUT) {
|
||||
/* Step 16 */
|
||||
@@ -1280,28 +1416,8 @@ static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308)
|
||||
if (rk3308->dac_output == DAC_HPOUT ||
|
||||
rk3308->dac_output == DAC_LINEOUT_HPOUT) {
|
||||
/* Step 18 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05,
|
||||
RK3308_DAC_L_HPOUT_GAIN_MSK,
|
||||
RK3308_DAC_L_HPOUT_GAIN_NDB_39);
|
||||
|
||||
/* Step 18 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06,
|
||||
RK3308_DAC_R_HPOUT_GAIN_MSK,
|
||||
RK3308_DAC_R_HPOUT_GAIN_NDB_39);
|
||||
|
||||
udelay(20);
|
||||
}
|
||||
|
||||
if (rk3308->dac_output == DAC_LINEOUT ||
|
||||
rk3308->dac_output == DAC_LINEOUT_HPOUT) {
|
||||
/* Step 19 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
|
||||
RK3308_DAC_L_LINEOUT_GAIN_MSK |
|
||||
RK3308_DAC_R_LINEOUT_GAIN_MSK,
|
||||
RK3308_DAC_L_LINEOUT_GAIN_NDB_6 |
|
||||
RK3308_DAC_R_LINEOUT_GAIN_NDB_6);
|
||||
|
||||
udelay(20);
|
||||
rk3308_codec_digital_fadein(rk3308);
|
||||
}
|
||||
|
||||
/* TODO: TRY TO TEST DRIVE STRENGTH */
|
||||
@@ -1309,61 +1425,11 @@ static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3308_codec_digital_fadeout(struct rk3308_codec_priv *rk3308)
|
||||
{
|
||||
unsigned int l_dgain, r_dgain;
|
||||
|
||||
/*
|
||||
* Note. In the step2, adjusting the register step by step to
|
||||
* the appropriate value and taking 20ms as time step
|
||||
*/
|
||||
regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON05, &l_dgain);
|
||||
l_dgain &= RK3308_DAC_L_HPOUT_GAIN_MSK;
|
||||
|
||||
regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON06, &r_dgain);
|
||||
r_dgain &= RK3308_DAC_R_HPOUT_GAIN_MSK;
|
||||
|
||||
if (l_dgain != r_dgain)
|
||||
pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n",
|
||||
l_dgain, r_dgain);
|
||||
|
||||
/*
|
||||
* We'd better change the gain of the left and right channels
|
||||
* at the same time to avoid different listening
|
||||
*/
|
||||
while (l_dgain >= RK3308_DAC_L_HPOUT_GAIN_NDB_39) {
|
||||
/* Step 02 decrease dgains for de-pop */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05,
|
||||
RK3308_DAC_L_HPOUT_GAIN_MSK,
|
||||
l_dgain);
|
||||
|
||||
/* Step 02 decrease dgains for de-pop */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06,
|
||||
RK3308_DAC_R_HPOUT_GAIN_MSK,
|
||||
r_dgain);
|
||||
|
||||
usleep_range(200, 300); /* estimated value */
|
||||
|
||||
if (l_dgain == RK3308_DAC_L_HPOUT_GAIN_NDB_39)
|
||||
break;
|
||||
|
||||
l_dgain--;
|
||||
r_dgain--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308)
|
||||
{
|
||||
/* Step 00, the min digital gain for mute */
|
||||
|
||||
/* Step 01 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
|
||||
RK3308_DAC_L_LINEOUT_GAIN_MSK |
|
||||
RK3308_DAC_R_LINEOUT_GAIN_MSK,
|
||||
RK3308_DAC_L_LINEOUT_GAIN_NDB_6 |
|
||||
RK3308_DAC_R_LINEOUT_GAIN_NDB_6);
|
||||
|
||||
/* Step 02 */
|
||||
rk3308_codec_digital_fadeout(rk3308);
|
||||
@@ -1477,13 +1543,6 @@ static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308)
|
||||
RK3308_DAC_L_HPMIX_INIT |
|
||||
RK3308_DAC_R_HPMIX_INIT);
|
||||
|
||||
/* Step 19 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12,
|
||||
RK3308_DAC_L_HPMIX_GAIN_MSK |
|
||||
RK3308_DAC_R_HPMIX_GAIN_MSK,
|
||||
RK3308_DAC_L_HPMIX_GAIN_NDB_6 |
|
||||
RK3308_DAC_R_HPMIX_GAIN_NDB_6);
|
||||
|
||||
/*
|
||||
* Note2. If the ACODEC_DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3]
|
||||
* is set to 0x1, add the steps from the section Disable ADC
|
||||
@@ -2078,7 +2137,6 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308,
|
||||
static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
int type)
|
||||
{
|
||||
unsigned int adc_aif1 = 0, adc_aif2 = 0;
|
||||
unsigned int agc_func_en;
|
||||
int idx, grp;
|
||||
|
||||
@@ -2216,24 +2274,8 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
}
|
||||
|
||||
/* vendor step 12 */
|
||||
adc_aif1 = RK3308_ADC_CH1_MIC_GAIN_0DB;
|
||||
adc_aif2 = RK3308_ADC_CH2_MIC_GAIN_0DB;
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON01(grp),
|
||||
RK3308_ADC_CH1_MIC_GAIN_MSK |
|
||||
RK3308_ADC_CH2_MIC_GAIN_MSK,
|
||||
adc_aif1 | adc_aif2);
|
||||
}
|
||||
|
||||
/* vendor step 13 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(grp),
|
||||
RK3308_ADC_CH1_ALC_GAIN_MSK,
|
||||
RK3308_ADC_CH1_ALC_GAIN_0DB);
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(grp),
|
||||
RK3308_ADC_CH2_ALC_GAIN_MSK,
|
||||
RK3308_ADC_CH2_ALC_GAIN_0DB);
|
||||
}
|
||||
|
||||
/* vendor step 14 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
@@ -2527,11 +2569,65 @@ static int rk3308_resume(struct snd_soc_codec *codec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3308_codec_default_gains(struct rk3308_codec_priv *rk3308)
|
||||
{
|
||||
int grp;
|
||||
|
||||
/* Prepare ADC gains */
|
||||
/* vendor step 12, set MIC PGA default gains */
|
||||
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON01(grp),
|
||||
RK3308_ADC_CH1_MIC_GAIN_MSK |
|
||||
RK3308_ADC_CH2_MIC_GAIN_MSK,
|
||||
RK3308_ADC_CH1_MIC_GAIN_0DB |
|
||||
RK3308_ADC_CH2_MIC_GAIN_0DB);
|
||||
}
|
||||
|
||||
/* vendor step 13, set ALC default gains */
|
||||
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(grp),
|
||||
RK3308_ADC_CH1_ALC_GAIN_MSK,
|
||||
RK3308_ADC_CH1_ALC_GAIN_0DB);
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(grp),
|
||||
RK3308_ADC_CH2_ALC_GAIN_MSK,
|
||||
RK3308_ADC_CH2_ALC_GAIN_0DB);
|
||||
}
|
||||
|
||||
/* Prepare DAC gains */
|
||||
/* Step 15, set HPMIX default gains */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12,
|
||||
RK3308_DAC_L_HPMIX_GAIN_MSK |
|
||||
RK3308_DAC_R_HPMIX_GAIN_MSK,
|
||||
RK3308_DAC_L_HPMIX_GAIN_NDB_6 |
|
||||
RK3308_DAC_R_HPMIX_GAIN_NDB_6);
|
||||
|
||||
/* Step 18, set HPOUT default gains */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05,
|
||||
RK3308_DAC_L_HPOUT_GAIN_MSK,
|
||||
RK3308_DAC_L_HPOUT_GAIN_NDB_39);
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06,
|
||||
RK3308_DAC_R_HPOUT_GAIN_MSK,
|
||||
RK3308_DAC_R_HPOUT_GAIN_NDB_39);
|
||||
|
||||
/* Using the same gain to HPOUT LR channels */
|
||||
rk3308->hpout_l_dgain = RK3308_DAC_L_HPOUT_GAIN_NDB_39;
|
||||
|
||||
/* Step 19, set LINEOUT default gains */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
|
||||
RK3308_DAC_L_LINEOUT_GAIN_MSK |
|
||||
RK3308_DAC_R_LINEOUT_GAIN_MSK,
|
||||
RK3308_DAC_L_LINEOUT_GAIN_NDB_6 |
|
||||
RK3308_DAC_R_LINEOUT_GAIN_NDB_6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3308_codec_prepare(struct rk3308_codec_priv *rk3308)
|
||||
{
|
||||
/* Clear registers for ADC and DAC */
|
||||
rk3308_codec_close_playback(rk3308);
|
||||
rk3308_codec_close_capture(rk3308);
|
||||
rk3308_codec_default_gains(rk3308);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user