ASoC: rk3308_codec: fix the failed loopback

If the capture running, we need to reset the ADCs quickly
when the LINEOUT startup.

Change-Id: I60eb1200961193cab39273da8c1a12a405c7f69b
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
This commit is contained in:
Xing Zheng
2018-05-28 16:36:22 +08:00
committed by Tao Huang
parent 74cdadd0b0
commit 9b9cee02e5

View File

@@ -57,6 +57,8 @@
#define DEBUG_POP_ALWAYS 0
#define ENABLE_AGC 0
#define HPDET_POLL_MS 2000
#define LOOPBACK_NO_USE -1
#define LOOPBACK_HANDLE_MS 100
enum {
ADC_GRP0_MICIN = 0,
@@ -84,6 +86,7 @@ struct rk3308_codec_priv {
struct clk *mclk_tx;
struct gpio_desc *hp_ctl_gpio;
struct gpio_desc *spk_ctl_gpio;
struct snd_soc_codec *codec;
struct snd_soc_jack *hpdet_jack;
int irq;
/*
@@ -101,8 +104,15 @@ struct rk3308_codec_priv {
int dac_output;
int dac_path_state;
int grp_min;
int grp_max;
/* The ADC group which is used for loop back */
int loopback_grp;
bool hp_plugged;
struct delayed_work hpdet_work;
struct delayed_work loopback_work;
#if defined(CONFIG_DEBUG_FS)
struct dentry *dbg_codec;
@@ -615,7 +625,7 @@ static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai,
RK3308_ADC_DIG_WORK,
RK3308_ADC_DIG_RESET);
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp),
RK3308_ADC_I2S_LRC_POL_MSK |
RK3308_ADC_I2S_MODE_MSK,
@@ -634,7 +644,7 @@ static int rk3308_set_dai_fmt(struct snd_soc_dai *codec_dai,
RK3308_ADC_DIG_WORK);
/* Enable high pass filter and cut-off 20Hz for ADCs */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON04(grp),
RK3308_ADC_HPF_PATH_MSK,
RK3308_ADC_HPF_PATH_EN);
@@ -789,7 +799,6 @@ static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
else if (rk3308->dac_output == DAC_HPOUT)
rk3308_headphone_ctl(rk3308, 1);
#endif
for (dgain = 0x7; dgain >= 0x2; dgain--) {
/*
* Keep the min -> max digital CIC interpolation
@@ -1561,6 +1570,19 @@ static int check_micbias(int micbias)
return -EINVAL;
}
static bool has_loopback(int loopback_grp)
{
switch (loopback_grp) {
case 0:
case 1:
case 2:
case 3:
return true;
}
return false;
}
static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308,
int micbias)
{
@@ -1652,7 +1674,7 @@ static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308)
*
* These values are estimated
*/
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON05(grp),
RK3308_AGC_LO_8BITS_AGC_MAX_MSK,
0x26);
@@ -1687,7 +1709,7 @@ static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308)
*
* By default is 44.1KHz for sample.
*/
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON04(grp),
RK3308_AGC_APPROX_RATE_MSK,
RK3308_AGC_APPROX_RATE_44_1K);
@@ -1699,7 +1721,7 @@ static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308)
#if ENABLE_AGC
/* 3. Set ACODEC_ALC_DIG_CON9[6] to 0x1, to enable the ALC module */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp),
RK3308_AGC_FUNC_SEL_MSK,
RK3308_AGC_FUNC_SEL_EN);
@@ -1714,7 +1736,7 @@ static int rk3308_codec_alc_enable(struct rk3308_codec_priv *rk3308)
* (ACODEC_ADC_ANA_CON11+0x80)[1:0] and (ACODEC_ADC_ANA_CON11+0xc0)[1:0]
* to 0x3, to enable the ALC module to control the gain of PGA.
*/
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp),
RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK |
RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK,
@@ -1736,7 +1758,7 @@ static int rk3308_codec_alc_disable(struct rk3308_codec_priv *rk3308)
{
int grp;
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/*
* 1. Set ACODEC_ALC_DIG_CON9[6] to 0x0, to disable the ALC
* module, then the ALC output gain will keep to the last value
@@ -1749,7 +1771,7 @@ static int rk3308_codec_alc_disable(struct rk3308_codec_priv *rk3308)
RK3308_AGC_FUNC_SEL_DIS);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/*
* 2. Set ACODEC_ADC_ANA_CON11[1:0], (ACODEC_ADC_ANA_CON11+0x40)
* [1:0], (ACODEC_ADC_ANA_CON11+0x80)[1:0] and
@@ -1770,7 +1792,7 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308)
{
int grp;
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 1 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
RK3308_ADC_CH1_ADC_WORK |
@@ -1779,7 +1801,7 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_ADC_INIT);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 2 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
RK3308_ADC_CH1_ALC_WORK |
@@ -1788,7 +1810,7 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_ALC_INIT);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 3 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
RK3308_ADC_CH1_MIC_WORK |
@@ -1797,9 +1819,9 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_MIC_INIT);
}
usleep_range(200, 250); /* estimated value */
usleep_range(200, 250); /* estimated value */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 1 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
RK3308_ADC_CH1_ADC_WORK |
@@ -1808,7 +1830,7 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_ADC_WORK);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 2 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
RK3308_ADC_CH1_ALC_WORK |
@@ -1817,7 +1839,7 @@ static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_ALC_WORK);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 3 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
RK3308_ADC_CH1_MIC_WORK |
@@ -1859,7 +1881,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_IN_MIC);
}
} else {
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap,
RK3308_ADC_ANA_CON07(grp),
RK3308_ADC_CH1_IN_SEL_MSK |
@@ -1884,14 +1906,14 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
* 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source
* of audio
*/
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp),
RK3308_ADC_CURRENT_MSK,
RK3308_ADC_CURRENT_EN);
}
/* vendor step 4*/
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
RK3308_ADC_CH1_BUF_REF_EN |
RK3308_ADC_CH2_BUF_REF_EN,
@@ -1900,7 +1922,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
}
/* vendor step 5 */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
RK3308_ADC_CH1_MIC_EN |
RK3308_ADC_CH2_MIC_EN,
@@ -1909,7 +1931,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
}
/* vendor step 6 */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
RK3308_ADC_CH1_ALC_EN |
RK3308_ADC_CH2_ALC_EN,
@@ -1918,7 +1940,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
}
/* vendor step 7 */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
RK3308_ADC_CH1_CLK_EN |
RK3308_ADC_CH2_CLK_EN,
@@ -1927,7 +1949,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
}
/* vendor step 8 */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
RK3308_ADC_CH1_ADC_EN |
RK3308_ADC_CH2_ADC_EN,
@@ -1936,7 +1958,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
}
/* vendor step 9 */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
RK3308_ADC_CH1_ADC_WORK |
RK3308_ADC_CH2_ADC_WORK,
@@ -1945,7 +1967,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
}
/* vendor step 10 */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
RK3308_ADC_CH1_ALC_WORK |
RK3308_ADC_CH2_ALC_WORK,
@@ -1954,7 +1976,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
}
/* vendor step 11 */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
RK3308_ADC_CH1_MIC_WORK |
RK3308_ADC_CH2_MIC_WORK,
@@ -1965,7 +1987,7 @@ 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 (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON01(grp),
RK3308_ADC_CH1_MIC_GAIN_MSK |
RK3308_ADC_CH2_MIC_GAIN_MSK,
@@ -1973,7 +1995,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
}
/* vendor step 13 */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(grp),
RK3308_ADC_CH1_ALC_GAIN_MSK,
RK3308_ADC_CH1_ALC_GAIN_0DB);
@@ -1983,7 +2005,7 @@ static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308)
}
/* vendor step 14 */
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp),
&agc_func_en);
if (rk3308->adc_zerocross ||
@@ -2016,7 +2038,7 @@ static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308)
{
int grp;
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 1 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
RK3308_ADC_CH1_ZEROCROSS_DET_EN |
@@ -2025,7 +2047,7 @@ static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_ZEROCROSS_DET_DIS);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 2 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
RK3308_ADC_CH1_ADC_EN |
@@ -2034,7 +2056,7 @@ static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_ADC_DIS);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 3 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
RK3308_ADC_CH1_CLK_EN |
@@ -2043,7 +2065,7 @@ static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_CLK_DIS);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 4 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
RK3308_ADC_CH1_ALC_EN |
@@ -2052,7 +2074,7 @@ static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_ALC_DIS);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 5 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
RK3308_ADC_CH1_MIC_EN |
@@ -2061,7 +2083,7 @@ static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_MIC_DIS);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 6 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
RK3308_ADC_CH1_BUF_REF_EN |
@@ -2070,14 +2092,14 @@ static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_BUF_REF_DIS);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 7 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp),
RK3308_ADC_CURRENT_MSK,
RK3308_ADC_CURRENT_DIS);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 8 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp),
RK3308_ADC_CH1_ADC_WORK |
@@ -2086,7 +2108,7 @@ static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_ADC_INIT);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 9 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp),
RK3308_ADC_CH1_ALC_WORK |
@@ -2095,7 +2117,7 @@ static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308)
RK3308_ADC_CH2_ALC_INIT);
}
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
/* vendor step 10 */
regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
RK3308_ADC_CH1_MIC_WORK |
@@ -2123,7 +2145,7 @@ static int rk3308_codec_open_capture(struct snd_soc_codec *codec)
RK3308_ADC_R_CH_BIST_MSK,
RK3308_ADC_R_CH_NORMAL_LEFT);
} else {
for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
for (grp = rk3308->grp_min; grp < rk3308->grp_max; grp++) {
regmap_update_bits(rk3308->regmap,
RK3308_ADC_DIG_CON03(grp),
RK3308_ADC_L_CH_BIST_MSK,
@@ -2168,6 +2190,28 @@ static int rk3308_codec_close_playback(struct snd_soc_codec *codec)
return 0;
}
static int rk3308_pcm_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec);
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];
if (capture_str->substream_opened)
queue_delayed_work(system_power_efficient_wq,
&rk3308->loopback_work,
msecs_to_jiffies(LOOPBACK_HANDLE_MS));
}
return 0;
}
static int rk3308_pcm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -2205,6 +2249,7 @@ static struct snd_soc_dai_ops rk3308_dai_ops = {
.hw_params = rk3308_hw_params,
.set_fmt = rk3308_set_dai_fmt,
.mute_stream = rk3308_mute_stream,
.trigger = rk3308_pcm_trigger,
.startup = rk3308_pcm_startup,
.shutdown = rk3308_pcm_shutdown,
};
@@ -2264,6 +2309,7 @@ static int rk3308_probe(struct snd_soc_codec *codec)
{
struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec);
rk3308->codec = codec;
rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE);
rk3308_codec_reset(codec);
@@ -2369,6 +2415,21 @@ static void rk3308_codec_hpdetect_work(struct work_struct *work)
enable_irq(rk3308->irq);
}
static void rk3308_codec_loopback_work(struct work_struct *work)
{
struct rk3308_codec_priv *rk3308 =
container_of(work, struct rk3308_codec_priv, loopback_work.work);
rk3308->grp_min = rk3308->loopback_grp;
rk3308->grp_max = rk3308->loopback_grp + 1;
rk3308_codec_close_capture(rk3308->codec);
rk3308_codec_open_capture(rk3308->codec);
rk3308->grp_min = 0;
rk3308->grp_max = ADC_LR_GROUP_MAX;
}
static irqreturn_t rk3308_codec_hpdet_isr(int irq, void *data)
{
struct rk3308_codec_priv *rk3308 = data;
@@ -2784,6 +2845,19 @@ static int rk3308_platform_probe(struct platform_device *pdev)
return ret;
}
rk3308->loopback_grp = LOOPBACK_NO_USE;
ret = of_property_read_u32(np, "rockchip,loopback-grp",
&rk3308->loopback_grp);
/*
* If there is no loopback on some board, the -EINVAL indicates that
* we don't need add the node, and it is not an error.
*/
if (ret < 0 && ret != -EINVAL) {
dev_err(&pdev->dev, "Failed to read loopback property: %d\n",
ret);
return ret;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) {
@@ -2807,6 +2881,7 @@ static int rk3308_platform_probe(struct platform_device *pdev)
}
INIT_DELAYED_WORK(&rk3308->hpdet_work, rk3308_codec_hpdetect_work);
INIT_DELAYED_WORK(&rk3308->loopback_work, rk3308_codec_loopback_work);
ret = devm_request_irq(&pdev->dev, rk3308->irq,
rk3308_codec_hpdet_isr,
@@ -2821,6 +2896,8 @@ static int rk3308_platform_probe(struct platform_device *pdev)
rk3308->adc_grp0_using_linein = ADC_GRP0_MICIN;
rk3308->dac_output = DAC_LINEOUT;
rk3308->adc_zerocross = 1;
rk3308->grp_min = 0;
rk3308->grp_max = ADC_LR_GROUP_MAX;
platform_set_drvdata(pdev, rk3308);