mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
ASoC: rk3308_codec: operate loopback ADCs during LINEOUT
We need to operate loopback ADCs during LINEOUT enable or disable that it make ensure enable ADCs more smoothly. Therefore, we don't need to reset loopback ADCs in rk3308_codec_loopback_work(), and separete reinit-mics from adc_ana_enable(). Change-Id: Id26dd5ad00c527be47a706df58c435f12d46c281 Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
This commit is contained in:
@@ -53,6 +53,7 @@
|
||||
|
||||
#define CODEC_DRV_NAME "rk3308-acodec"
|
||||
|
||||
#define ADC_GRP_SKIP_MAGIC 0x1001
|
||||
#define ADC_LR_GROUP_MAX 4
|
||||
#define ADC_STABLE_MS 20
|
||||
#define DEBUG_POP_ALWAYS 0
|
||||
@@ -159,6 +160,7 @@ struct rk3308_codec_priv {
|
||||
|
||||
bool enable_all_adcs;
|
||||
bool hp_plugged;
|
||||
bool loopback_dacs_enabled;
|
||||
bool no_deep_low_power;
|
||||
struct delayed_work hpdet_work;
|
||||
struct delayed_work loopback_work;
|
||||
@@ -571,7 +573,18 @@ static bool adc_for_each_grp(struct rk3308_codec_priv *rk3308,
|
||||
if (idx >= max_grps)
|
||||
return false;
|
||||
|
||||
*grp = rk3308->i2s_sdis[idx];
|
||||
if ((!rk3308->loopback_dacs_enabled) &&
|
||||
has_loopback(rk3308->loopback_grp) &&
|
||||
rk3308->loopback_grp == idx) {
|
||||
/*
|
||||
* Ths loopback DACs are closed, and specify the
|
||||
* loopback ADCs.
|
||||
*/
|
||||
*grp = ADC_GRP_SKIP_MAGIC;
|
||||
} else {
|
||||
*grp = rk3308->i2s_sdis[idx];
|
||||
}
|
||||
|
||||
dev_dbg(rk3308->plat_dev,
|
||||
"ADC_TYPE_NORMAL, idx: %d, get grp: %d\n",
|
||||
idx, *grp);
|
||||
@@ -1994,6 +2007,9 @@ static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308, int type)
|
||||
* These values are estimated
|
||||
*/
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(grp),
|
||||
RK3308_AGC_LO_8BITS_AGC_MAX_MSK,
|
||||
0x26);
|
||||
@@ -2029,6 +2045,9 @@ static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308, int type)
|
||||
* By default is 44.1KHz for sample.
|
||||
*/
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON04(grp),
|
||||
RK3308_AGC_APPROX_RATE_MSK,
|
||||
RK3308_AGC_APPROX_RATE_44_1K);
|
||||
@@ -2041,6 +2060,9 @@ static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308, int type)
|
||||
#if ENABLE_AGC
|
||||
/* 3. Set ACODEC_ALC_DIG_CON9[6] to 0x1, to enable the ALC module */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp),
|
||||
RK3308_AGC_FUNC_SEL_MSK,
|
||||
RK3308_AGC_FUNC_SEL_EN);
|
||||
@@ -2056,6 +2078,9 @@ static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308, int type)
|
||||
* to 0x3, to enable the ALC module to control the gain of PGA.
|
||||
*/
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp),
|
||||
RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK |
|
||||
RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK,
|
||||
@@ -2114,6 +2139,9 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308,
|
||||
int idx, grp;
|
||||
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
/* vendor step 1 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
|
||||
RK3308_ADC_CH1_ADC_WORK |
|
||||
@@ -2123,6 +2151,9 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308,
|
||||
}
|
||||
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
/* vendor step 2 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
|
||||
RK3308_ADC_CH1_ALC_WORK |
|
||||
@@ -2132,6 +2163,9 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308,
|
||||
}
|
||||
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
/* vendor step 3 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
|
||||
RK3308_ADC_CH1_MIC_WORK |
|
||||
@@ -2143,6 +2177,9 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308,
|
||||
usleep_range(200, 250); /* estimated value */
|
||||
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
/* vendor step 1 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
|
||||
RK3308_ADC_CH1_ADC_WORK |
|
||||
@@ -2152,6 +2189,9 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308,
|
||||
}
|
||||
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
/* vendor step 2 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
|
||||
RK3308_ADC_CH1_ALC_WORK |
|
||||
@@ -2161,6 +2201,9 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308,
|
||||
}
|
||||
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
/* vendor step 3 */
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
|
||||
RK3308_ADC_CH1_MIC_WORK |
|
||||
@@ -2195,7 +2238,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
/* Keep other ADCs as MIC-IN */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
/* The groups without line-in are >= 1 */
|
||||
if (grp < 1)
|
||||
if (grp < 1 || grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap,
|
||||
@@ -2207,6 +2250,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
}
|
||||
} else {
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap,
|
||||
RK3308_ADC_ANA_CON07(grp),
|
||||
RK3308_ADC_CH1_IN_SEL_MSK |
|
||||
@@ -2222,6 +2268,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
* buffer, and to end the initialization of MIC
|
||||
*/
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
|
||||
RK3308_ADC_CH1_MIC_UNMUTE |
|
||||
RK3308_ADC_CH2_MIC_UNMUTE,
|
||||
@@ -2234,6 +2283,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
* of audio
|
||||
*/
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp),
|
||||
RK3308_ADC_CURRENT_MSK,
|
||||
RK3308_ADC_CURRENT_EN);
|
||||
@@ -2241,6 +2293,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
|
||||
/* vendor step 4*/
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
|
||||
RK3308_ADC_CH1_BUF_REF_EN |
|
||||
RK3308_ADC_CH2_BUF_REF_EN,
|
||||
@@ -2250,6 +2305,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
|
||||
/* vendor step 5 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
|
||||
RK3308_ADC_CH1_MIC_EN |
|
||||
RK3308_ADC_CH2_MIC_EN,
|
||||
@@ -2259,6 +2317,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
|
||||
/* vendor step 6 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
|
||||
RK3308_ADC_CH1_ALC_EN |
|
||||
RK3308_ADC_CH2_ALC_EN,
|
||||
@@ -2268,6 +2329,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
|
||||
/* vendor step 7 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
|
||||
RK3308_ADC_CH1_CLK_EN |
|
||||
RK3308_ADC_CH2_CLK_EN,
|
||||
@@ -2277,6 +2341,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
|
||||
/* vendor step 8 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
|
||||
RK3308_ADC_CH1_ADC_EN |
|
||||
RK3308_ADC_CH2_ADC_EN,
|
||||
@@ -2286,6 +2353,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
|
||||
/* vendor step 9 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
|
||||
RK3308_ADC_CH1_ADC_WORK |
|
||||
RK3308_ADC_CH2_ADC_WORK,
|
||||
@@ -2295,6 +2365,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
|
||||
/* vendor step 10 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
|
||||
RK3308_ADC_CH1_ALC_WORK |
|
||||
RK3308_ADC_CH2_ALC_WORK,
|
||||
@@ -2304,6 +2377,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
|
||||
/* vendor step 11 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
|
||||
RK3308_ADC_CH1_MIC_WORK |
|
||||
RK3308_ADC_CH2_MIC_WORK,
|
||||
@@ -2317,6 +2393,9 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
|
||||
/* vendor step 14 */
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
if (grp == ADC_GRP_SKIP_MAGIC)
|
||||
continue;
|
||||
|
||||
regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp),
|
||||
&agc_func_en);
|
||||
if (rk3308->adc_zerocross ||
|
||||
@@ -2337,11 +2416,6 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308,
|
||||
}
|
||||
}
|
||||
|
||||
/* vendor step 15, re-init mic */
|
||||
rk3308_codec_adc_reinit_mics(rk3308, type);
|
||||
|
||||
/* vendor step 16 Begin recording */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2448,6 +2522,7 @@ static int rk3308_codec_open_capture(struct rk3308_codec_priv *rk3308)
|
||||
|
||||
rk3308_codec_alc_enable(rk3308, type);
|
||||
rk3308_codec_adc_ana_enable(rk3308, type);
|
||||
rk3308_codec_adc_reinit_mics(rk3308, type);
|
||||
|
||||
if (rk3308->adc_grp0_using_linein) {
|
||||
regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(0),
|
||||
@@ -2621,6 +2696,10 @@ static int rk3308_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec);
|
||||
struct snd_pcm_str *playback_str =
|
||||
&substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK];
|
||||
int type = ADC_TYPE_LOOPBACK;
|
||||
int idx, grp;
|
||||
int ret;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
@@ -2634,6 +2713,33 @@ static int rk3308_hw_params(struct snd_pcm_substream *substream,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Check the DACs are opened */
|
||||
if (playback_str->substream_opened) {
|
||||
rk3308->loopback_dacs_enabled = true;
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
regmap_update_bits(rk3308->regmap,
|
||||
RK3308_ADC_DIG_CON03(grp),
|
||||
RK3308_ADC_L_CH_BIST_MSK,
|
||||
RK3308_ADC_L_CH_NORMAL_LEFT);
|
||||
regmap_update_bits(rk3308->regmap,
|
||||
RK3308_ADC_DIG_CON03(grp),
|
||||
RK3308_ADC_R_CH_BIST_MSK,
|
||||
RK3308_ADC_R_CH_NORMAL_RIGHT);
|
||||
}
|
||||
} else {
|
||||
rk3308->loopback_dacs_enabled = false;
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
regmap_update_bits(rk3308->regmap,
|
||||
RK3308_ADC_DIG_CON03(grp),
|
||||
RK3308_ADC_L_CH_BIST_MSK,
|
||||
RK3308_ADC_L_CH_BIST_SINE);
|
||||
regmap_update_bits(rk3308->regmap,
|
||||
RK3308_ADC_DIG_CON03(grp),
|
||||
RK3308_ADC_R_CH_BIST_MSK,
|
||||
RK3308_ADC_R_CH_BIST_SINE);
|
||||
}
|
||||
}
|
||||
|
||||
rk3308_codec_open_capture(rk3308);
|
||||
rk3308_codec_adc_dig_config(rk3308, params);
|
||||
}
|
||||
@@ -2646,18 +2752,38 @@ static int rk3308_pcm_trigger(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct snd_soc_codec *codec = dai->codec;
|
||||
struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec);
|
||||
int type = ADC_TYPE_LOOPBACK;
|
||||
int idx, grp;
|
||||
|
||||
if (has_loopback(rk3308->loopback_grp) &&
|
||||
rk3308->dac_output == DAC_LINEOUT &&
|
||||
substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
|
||||
cmd == SNDRV_PCM_TRIGGER_START) {
|
||||
struct snd_pcm_str *capture_str =
|
||||
&substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
|
||||
substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (cmd == SNDRV_PCM_TRIGGER_START) {
|
||||
struct snd_pcm_str *capture_str =
|
||||
&substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
|
||||
|
||||
if (capture_str->substream_opened)
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&rk3308->loopback_work,
|
||||
msecs_to_jiffies(LOOPBACK_HANDLE_MS));
|
||||
if (capture_str->substream_opened)
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&rk3308->loopback_work,
|
||||
msecs_to_jiffies(LOOPBACK_HANDLE_MS));
|
||||
} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
|
||||
/*
|
||||
* Switch to dummy bist mode to kick the glitch during disable
|
||||
* ADCs and keep zero input data
|
||||
*/
|
||||
for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) {
|
||||
regmap_update_bits(rk3308->regmap,
|
||||
RK3308_ADC_DIG_CON03(grp),
|
||||
RK3308_ADC_L_CH_BIST_MSK,
|
||||
RK3308_ADC_L_CH_BIST_SINE);
|
||||
regmap_update_bits(rk3308->regmap,
|
||||
RK3308_ADC_DIG_CON03(grp),
|
||||
RK3308_ADC_R_CH_BIST_MSK,
|
||||
RK3308_ADC_R_CH_BIST_SINE);
|
||||
}
|
||||
rk3308_codec_alc_disable(rk3308, ADC_TYPE_LOOPBACK);
|
||||
rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_LOOPBACK);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2950,10 +3076,7 @@ static void rk3308_codec_loopback_work(struct work_struct *work)
|
||||
int type = ADC_TYPE_LOOPBACK;
|
||||
int idx, grp;
|
||||
|
||||
/* Reset ADC quickly */
|
||||
rk3308_codec_alc_disable(rk3308, type);
|
||||
rk3308_codec_adc_ana_disable(rk3308, type);
|
||||
|
||||
/* Prepare loopback ADCs */
|
||||
rk3308_codec_alc_enable(rk3308, type);
|
||||
rk3308_codec_adc_ana_enable(rk3308, type);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user