Loading sound/soc/codecs/adau1373.c +237 −61 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ struct adau1373_dai { }; struct adau1373 { struct regmap *regmap; struct adau1373_dai dais[3]; }; Loading Loading @@ -73,7 +74,6 @@ struct adau1373 { #define ADAU1373_PLL_CTRL4(x) (0x2c + (x) * 7) #define ADAU1373_PLL_CTRL5(x) (0x2d + (x) * 7) #define ADAU1373_PLL_CTRL6(x) (0x2e + (x) * 7) #define ADAU1373_PLL_CTRL7(x) (0x2f + (x) * 7) #define ADAU1373_HEADDECT 0x36 #define ADAU1373_ADC_DAC_STATUS 0x37 #define ADAU1373_ADC_CTRL 0x3c Loading Loading @@ -152,37 +152,172 @@ struct adau1373 { #define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4 #define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2 static const uint8_t adau1373_default_regs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */ 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */ 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */ 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */ 0x00, 0x1f, 0x0f, 0x00, 0x00, static const struct reg_default adau1373_reg_defaults[] = { { ADAU1373_INPUT_MODE, 0x00 }, { ADAU1373_AINL_CTRL(0), 0x00 }, { ADAU1373_AINR_CTRL(0), 0x00 }, { ADAU1373_AINL_CTRL(1), 0x00 }, { ADAU1373_AINR_CTRL(1), 0x00 }, { ADAU1373_AINL_CTRL(2), 0x00 }, { ADAU1373_AINR_CTRL(2), 0x00 }, { ADAU1373_AINL_CTRL(3), 0x00 }, { ADAU1373_AINR_CTRL(3), 0x00 }, { ADAU1373_LLINE_OUT(0), 0x00 }, { ADAU1373_RLINE_OUT(0), 0x00 }, { ADAU1373_LLINE_OUT(1), 0x00 }, { ADAU1373_RLINE_OUT(1), 0x00 }, { ADAU1373_LSPK_OUT, 0x00 }, { ADAU1373_RSPK_OUT, 0x00 }, { ADAU1373_LHP_OUT, 0x00 }, { ADAU1373_RHP_OUT, 0x00 }, { ADAU1373_ADC_GAIN, 0x00 }, { ADAU1373_LADC_MIXER, 0x00 }, { ADAU1373_RADC_MIXER, 0x00 }, { ADAU1373_LLINE1_MIX, 0x00 }, { ADAU1373_RLINE1_MIX, 0x00 }, { ADAU1373_LLINE2_MIX, 0x00 }, { ADAU1373_RLINE2_MIX, 0x00 }, { ADAU1373_LSPK_MIX, 0x00 }, { ADAU1373_RSPK_MIX, 0x00 }, { ADAU1373_LHP_MIX, 0x00 }, { ADAU1373_RHP_MIX, 0x00 }, { ADAU1373_EP_MIX, 0x00 }, { ADAU1373_HP_CTRL, 0x00 }, { ADAU1373_HP_CTRL2, 0x00 }, { ADAU1373_LS_CTRL, 0x00 }, { ADAU1373_EP_CTRL, 0x00 }, { ADAU1373_MICBIAS_CTRL1, 0x00 }, { ADAU1373_MICBIAS_CTRL2, 0x00 }, { ADAU1373_OUTPUT_CTRL, 0x00 }, { ADAU1373_PWDN_CTRL1, 0x00 }, { ADAU1373_PWDN_CTRL2, 0x00 }, { ADAU1373_PWDN_CTRL3, 0x00 }, { ADAU1373_DPLL_CTRL(0), 0x00 }, { ADAU1373_PLL_CTRL1(0), 0x00 }, { ADAU1373_PLL_CTRL2(0), 0x00 }, { ADAU1373_PLL_CTRL3(0), 0x00 }, { ADAU1373_PLL_CTRL4(0), 0x00 }, { ADAU1373_PLL_CTRL5(0), 0x00 }, { ADAU1373_PLL_CTRL6(0), 0x02 }, { ADAU1373_DPLL_CTRL(1), 0x00 }, { ADAU1373_PLL_CTRL1(1), 0x00 }, { ADAU1373_PLL_CTRL2(1), 0x00 }, { ADAU1373_PLL_CTRL3(1), 0x00 }, { ADAU1373_PLL_CTRL4(1), 0x00 }, { ADAU1373_PLL_CTRL5(1), 0x00 }, { ADAU1373_PLL_CTRL6(1), 0x02 }, { ADAU1373_HEADDECT, 0x00 }, { ADAU1373_ADC_CTRL, 0x00 }, { ADAU1373_CLK_SRC_DIV(0), 0x00 }, { ADAU1373_CLK_SRC_DIV(1), 0x00 }, { ADAU1373_DAI(0), 0x0a }, { ADAU1373_DAI(1), 0x0a }, { ADAU1373_DAI(2), 0x0a }, { ADAU1373_BCLKDIV(0), 0x00 }, { ADAU1373_BCLKDIV(1), 0x00 }, { ADAU1373_BCLKDIV(2), 0x00 }, { ADAU1373_SRC_RATIOA(0), 0x00 }, { ADAU1373_SRC_RATIOB(0), 0x00 }, { ADAU1373_SRC_RATIOA(1), 0x00 }, { ADAU1373_SRC_RATIOB(1), 0x00 }, { ADAU1373_SRC_RATIOA(2), 0x00 }, { ADAU1373_SRC_RATIOB(2), 0x00 }, { ADAU1373_DEEMP_CTRL, 0x00 }, { ADAU1373_SRC_DAI_CTRL(0), 0x08 }, { ADAU1373_SRC_DAI_CTRL(1), 0x08 }, { ADAU1373_SRC_DAI_CTRL(2), 0x08 }, { ADAU1373_DIN_MIX_CTRL(0), 0x00 }, { ADAU1373_DIN_MIX_CTRL(1), 0x00 }, { ADAU1373_DIN_MIX_CTRL(2), 0x00 }, { ADAU1373_DIN_MIX_CTRL(3), 0x00 }, { ADAU1373_DIN_MIX_CTRL(4), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(0), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(1), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(2), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(3), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(4), 0x00 }, { ADAU1373_DAI_PBL_VOL(0), 0x00 }, { ADAU1373_DAI_PBR_VOL(0), 0x00 }, { ADAU1373_DAI_PBL_VOL(1), 0x00 }, { ADAU1373_DAI_PBR_VOL(1), 0x00 }, { ADAU1373_DAI_PBL_VOL(2), 0x00 }, { ADAU1373_DAI_PBR_VOL(2), 0x00 }, { ADAU1373_DAI_RECL_VOL(0), 0x00 }, { ADAU1373_DAI_RECR_VOL(0), 0x00 }, { ADAU1373_DAI_RECL_VOL(1), 0x00 }, { ADAU1373_DAI_RECR_VOL(1), 0x00 }, { ADAU1373_DAI_RECL_VOL(2), 0x00 }, { ADAU1373_DAI_RECR_VOL(2), 0x00 }, { ADAU1373_DAC1_PBL_VOL, 0x00 }, { ADAU1373_DAC1_PBR_VOL, 0x00 }, { ADAU1373_DAC2_PBL_VOL, 0x00 }, { ADAU1373_DAC2_PBR_VOL, 0x00 }, { ADAU1373_ADC_RECL_VOL, 0x00 }, { ADAU1373_ADC_RECR_VOL, 0x00 }, { ADAU1373_DMIC_RECL_VOL, 0x00 }, { ADAU1373_DMIC_RECR_VOL, 0x00 }, { ADAU1373_VOL_GAIN1, 0x00 }, { ADAU1373_VOL_GAIN2, 0x00 }, { ADAU1373_VOL_GAIN3, 0x00 }, { ADAU1373_HPF_CTRL, 0x00 }, { ADAU1373_BASS1, 0x00 }, { ADAU1373_BASS2, 0x00 }, { ADAU1373_DRC(0) + 0x0, 0x78 }, { ADAU1373_DRC(0) + 0x1, 0x18 }, { ADAU1373_DRC(0) + 0x2, 0x00 }, { ADAU1373_DRC(0) + 0x3, 0x00 }, { ADAU1373_DRC(0) + 0x4, 0x00 }, { ADAU1373_DRC(0) + 0x5, 0xc0 }, { ADAU1373_DRC(0) + 0x6, 0x00 }, { ADAU1373_DRC(0) + 0x7, 0x00 }, { ADAU1373_DRC(0) + 0x8, 0x00 }, { ADAU1373_DRC(0) + 0x9, 0xc0 }, { ADAU1373_DRC(0) + 0xa, 0x88 }, { ADAU1373_DRC(0) + 0xb, 0x7a }, { ADAU1373_DRC(0) + 0xc, 0xdf }, { ADAU1373_DRC(0) + 0xd, 0x20 }, { ADAU1373_DRC(0) + 0xe, 0x00 }, { ADAU1373_DRC(0) + 0xf, 0x00 }, { ADAU1373_DRC(1) + 0x0, 0x78 }, { ADAU1373_DRC(1) + 0x1, 0x18 }, { ADAU1373_DRC(1) + 0x2, 0x00 }, { ADAU1373_DRC(1) + 0x3, 0x00 }, { ADAU1373_DRC(1) + 0x4, 0x00 }, { ADAU1373_DRC(1) + 0x5, 0xc0 }, { ADAU1373_DRC(1) + 0x6, 0x00 }, { ADAU1373_DRC(1) + 0x7, 0x00 }, { ADAU1373_DRC(1) + 0x8, 0x00 }, { ADAU1373_DRC(1) + 0x9, 0xc0 }, { ADAU1373_DRC(1) + 0xa, 0x88 }, { ADAU1373_DRC(1) + 0xb, 0x7a }, { ADAU1373_DRC(1) + 0xc, 0xdf }, { ADAU1373_DRC(1) + 0xd, 0x20 }, { ADAU1373_DRC(1) + 0xe, 0x00 }, { ADAU1373_DRC(1) + 0xf, 0x00 }, { ADAU1373_DRC(2) + 0x0, 0x78 }, { ADAU1373_DRC(2) + 0x1, 0x18 }, { ADAU1373_DRC(2) + 0x2, 0x00 }, { ADAU1373_DRC(2) + 0x3, 0x00 }, { ADAU1373_DRC(2) + 0x4, 0x00 }, { ADAU1373_DRC(2) + 0x5, 0xc0 }, { ADAU1373_DRC(2) + 0x6, 0x00 }, { ADAU1373_DRC(2) + 0x7, 0x00 }, { ADAU1373_DRC(2) + 0x8, 0x00 }, { ADAU1373_DRC(2) + 0x9, 0xc0 }, { ADAU1373_DRC(2) + 0xa, 0x88 }, { ADAU1373_DRC(2) + 0xb, 0x7a }, { ADAU1373_DRC(2) + 0xc, 0xdf }, { ADAU1373_DRC(2) + 0xd, 0x20 }, { ADAU1373_DRC(2) + 0xe, 0x00 }, { ADAU1373_DRC(2) + 0xf, 0x00 }, { ADAU1373_3D_CTRL1, 0x00 }, { ADAU1373_3D_CTRL2, 0x00 }, { ADAU1373_FDSP_SEL1, 0x00 }, { ADAU1373_FDSP_SEL2, 0x00 }, { ADAU1373_FDSP_SEL2, 0x00 }, { ADAU1373_FDSP_SEL4, 0x00 }, { ADAU1373_DIGMICCTRL, 0x00 }, { ADAU1373_DIGEN, 0x00 }, }; static const unsigned int adau1373_out_tlv[] = { Loading Loading @@ -418,6 +553,7 @@ static int adau1373_pll_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); unsigned int pll_id = w->name[3] - '1'; unsigned int val; Loading @@ -426,7 +562,7 @@ static int adau1373_pll_event(struct snd_soc_dapm_widget *w, else val = 0; snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id), ADAU1373_PLL_CTRL6_PLL_EN, val); if (SND_SOC_DAPM_EVENT_ON(event)) Loading Loading @@ -938,7 +1074,7 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream, adau1373_dai->enable_src = (div != 0); snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id), regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id), ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK, (div << 2) | ADAU1373_BCLKDIV_64); Loading @@ -959,7 +1095,7 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), return regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id), ADAU1373_DAI_WLEN_MASK, ctrl); } Loading Loading @@ -1016,7 +1152,7 @@ static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id), ~ADAU1373_DAI_WLEN_MASK, ctrl); return 0; Loading @@ -1039,7 +1175,7 @@ static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai, adau1373_dai->sysclk = freq; adau1373_dai->clk_src = clk_id; snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id), regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id), ADAU1373_BCLKDIV_SOURCE, clk_id << 5); return 0; Loading Loading @@ -1120,6 +1256,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = { static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); unsigned int dpll_div = 0; unsigned int x, r, n, m, i, j, mode; Loading Loading @@ -1187,36 +1324,36 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, if (dpll_div) { dpll_div = 11 - dpll_div; snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id), ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0); } else { snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id), ADAU1373_PLL_CTRL6_DPLL_BYPASS, ADAU1373_PLL_CTRL6_DPLL_BYPASS); } snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id), regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id), (source << 4) | dpll_div); snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id), regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id), (r << 3) | (x << 1) | mode); /* Set sysclk to pll_rate / 4 */ snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); return 0; } static void adau1373_load_drc_settings(struct snd_soc_codec *codec, static void adau1373_load_drc_settings(struct adau1373 *adau1373, unsigned int nr, uint8_t *drc) { unsigned int i; for (i = 0; i < ADAU1373_DRC_SIZE; ++i) snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]); regmap_write(adau1373->regmap, ADAU1373_DRC(nr) + i, drc[i]); } static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias) Loading @@ -1235,13 +1372,14 @@ static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias) static int adau1373_probe(struct snd_soc_codec *codec) { struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); struct adau1373_platform_data *pdata = codec->dev->platform_data; bool lineout_differential = false; unsigned int val; int ret; int i; ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); if (ret) { dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); return ret; Loading @@ -1256,7 +1394,7 @@ static int adau1373_probe(struct snd_soc_codec *codec) return -EINVAL; for (i = 0; i < pdata->num_drc; ++i) { adau1373_load_drc_settings(codec, i, adau1373_load_drc_settings(adau1373, i, pdata->drc_setting[i]); } Loading @@ -1268,18 +1406,18 @@ static int adau1373_probe(struct snd_soc_codec *codec) if (pdata->input_differential[i]) val |= BIT(i); } snd_soc_write(codec, ADAU1373_INPUT_MODE, val); regmap_write(adau1373->regmap, ADAU1373_INPUT_MODE, val); val = 0; if (pdata->lineout_differential) val |= ADAU1373_OUTPUT_CTRL_LDIFF; if (pdata->lineout_ground_sense) val |= ADAU1373_OUTPUT_CTRL_LNFBEN; snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val); regmap_write(adau1373->regmap, ADAU1373_OUTPUT_CTRL, val); lineout_differential = pdata->lineout_differential; snd_soc_write(codec, ADAU1373_EP_CTRL, regmap_write(adau1373->regmap, ADAU1373_EP_CTRL, (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) | (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET)); } Loading @@ -1289,7 +1427,7 @@ static int adau1373_probe(struct snd_soc_codec *codec) ARRAY_SIZE(adau1373_lineout2_controls)); } snd_soc_write(codec, ADAU1373_ADC_CTRL, regmap_write(adau1373->regmap, ADAU1373_ADC_CTRL, ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT); return 0; Loading @@ -1298,17 +1436,19 @@ static int adau1373_probe(struct snd_soc_codec *codec) static int adau1373_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3, ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN); break; case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3, ADAU1373_PWDN_CTRL3_PWR_EN, 0); break; } Loading @@ -1324,17 +1464,49 @@ static int adau1373_remove(struct snd_soc_codec *codec) static int adau1373_suspend(struct snd_soc_codec *codec) { return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); int ret; ret = adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); regcache_cache_only(adau1373->regmap, true); return ret; } static int adau1373_resume(struct snd_soc_codec *codec) { struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); regcache_cache_only(adau1373->regmap, false); adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_cache_sync(codec); regcache_sync(adau1373->regmap); return 0; } static bool adau1373_register_volatile(struct device *dev, unsigned int reg) { switch (reg) { case ADAU1373_SOFT_RESET: case ADAU1373_ADC_DAC_STATUS: return true; default: return false; } } static const struct regmap_config adau1373_regmap_config = { .val_bits = 8, .reg_bits = 8, .volatile_reg = adau1373_register_volatile, .max_register = ADAU1373_SOFT_RESET, .cache_type = REGCACHE_RBTREE, .reg_defaults = adau1373_reg_defaults, .num_reg_defaults = ARRAY_SIZE(adau1373_reg_defaults), }; static struct snd_soc_codec_driver adau1373_codec_driver = { .probe = adau1373_probe, .remove = adau1373_remove, Loading @@ -1342,9 +1514,6 @@ static struct snd_soc_codec_driver adau1373_codec_driver = { .resume = adau1373_resume, .set_bias_level = adau1373_set_bias_level, .idle_bias_off = true, .reg_cache_size = ARRAY_SIZE(adau1373_default_regs), .reg_cache_default = adau1373_default_regs, .reg_word_size = sizeof(uint8_t), .set_pll = adau1373_set_pll, Loading @@ -1366,6 +1535,13 @@ static int adau1373_i2c_probe(struct i2c_client *client, if (!adau1373) return -ENOMEM; adau1373->regmap = devm_regmap_init_i2c(client, &adau1373_regmap_config); if (IS_ERR(adau1373->regmap)) return PTR_ERR(adau1373->regmap); regmap_write(adau1373->regmap, ADAU1373_SOFT_RESET, 0x00); dev_set_drvdata(&client->dev, adau1373); ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver, Loading Loading
sound/soc/codecs/adau1373.c +237 −61 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ struct adau1373_dai { }; struct adau1373 { struct regmap *regmap; struct adau1373_dai dais[3]; }; Loading Loading @@ -73,7 +74,6 @@ struct adau1373 { #define ADAU1373_PLL_CTRL4(x) (0x2c + (x) * 7) #define ADAU1373_PLL_CTRL5(x) (0x2d + (x) * 7) #define ADAU1373_PLL_CTRL6(x) (0x2e + (x) * 7) #define ADAU1373_PLL_CTRL7(x) (0x2f + (x) * 7) #define ADAU1373_HEADDECT 0x36 #define ADAU1373_ADC_DAC_STATUS 0x37 #define ADAU1373_ADC_CTRL 0x3c Loading Loading @@ -152,37 +152,172 @@ struct adau1373 { #define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4 #define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2 static const uint8_t adau1373_default_regs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */ 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */ 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */ 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */ 0x00, 0x1f, 0x0f, 0x00, 0x00, static const struct reg_default adau1373_reg_defaults[] = { { ADAU1373_INPUT_MODE, 0x00 }, { ADAU1373_AINL_CTRL(0), 0x00 }, { ADAU1373_AINR_CTRL(0), 0x00 }, { ADAU1373_AINL_CTRL(1), 0x00 }, { ADAU1373_AINR_CTRL(1), 0x00 }, { ADAU1373_AINL_CTRL(2), 0x00 }, { ADAU1373_AINR_CTRL(2), 0x00 }, { ADAU1373_AINL_CTRL(3), 0x00 }, { ADAU1373_AINR_CTRL(3), 0x00 }, { ADAU1373_LLINE_OUT(0), 0x00 }, { ADAU1373_RLINE_OUT(0), 0x00 }, { ADAU1373_LLINE_OUT(1), 0x00 }, { ADAU1373_RLINE_OUT(1), 0x00 }, { ADAU1373_LSPK_OUT, 0x00 }, { ADAU1373_RSPK_OUT, 0x00 }, { ADAU1373_LHP_OUT, 0x00 }, { ADAU1373_RHP_OUT, 0x00 }, { ADAU1373_ADC_GAIN, 0x00 }, { ADAU1373_LADC_MIXER, 0x00 }, { ADAU1373_RADC_MIXER, 0x00 }, { ADAU1373_LLINE1_MIX, 0x00 }, { ADAU1373_RLINE1_MIX, 0x00 }, { ADAU1373_LLINE2_MIX, 0x00 }, { ADAU1373_RLINE2_MIX, 0x00 }, { ADAU1373_LSPK_MIX, 0x00 }, { ADAU1373_RSPK_MIX, 0x00 }, { ADAU1373_LHP_MIX, 0x00 }, { ADAU1373_RHP_MIX, 0x00 }, { ADAU1373_EP_MIX, 0x00 }, { ADAU1373_HP_CTRL, 0x00 }, { ADAU1373_HP_CTRL2, 0x00 }, { ADAU1373_LS_CTRL, 0x00 }, { ADAU1373_EP_CTRL, 0x00 }, { ADAU1373_MICBIAS_CTRL1, 0x00 }, { ADAU1373_MICBIAS_CTRL2, 0x00 }, { ADAU1373_OUTPUT_CTRL, 0x00 }, { ADAU1373_PWDN_CTRL1, 0x00 }, { ADAU1373_PWDN_CTRL2, 0x00 }, { ADAU1373_PWDN_CTRL3, 0x00 }, { ADAU1373_DPLL_CTRL(0), 0x00 }, { ADAU1373_PLL_CTRL1(0), 0x00 }, { ADAU1373_PLL_CTRL2(0), 0x00 }, { ADAU1373_PLL_CTRL3(0), 0x00 }, { ADAU1373_PLL_CTRL4(0), 0x00 }, { ADAU1373_PLL_CTRL5(0), 0x00 }, { ADAU1373_PLL_CTRL6(0), 0x02 }, { ADAU1373_DPLL_CTRL(1), 0x00 }, { ADAU1373_PLL_CTRL1(1), 0x00 }, { ADAU1373_PLL_CTRL2(1), 0x00 }, { ADAU1373_PLL_CTRL3(1), 0x00 }, { ADAU1373_PLL_CTRL4(1), 0x00 }, { ADAU1373_PLL_CTRL5(1), 0x00 }, { ADAU1373_PLL_CTRL6(1), 0x02 }, { ADAU1373_HEADDECT, 0x00 }, { ADAU1373_ADC_CTRL, 0x00 }, { ADAU1373_CLK_SRC_DIV(0), 0x00 }, { ADAU1373_CLK_SRC_DIV(1), 0x00 }, { ADAU1373_DAI(0), 0x0a }, { ADAU1373_DAI(1), 0x0a }, { ADAU1373_DAI(2), 0x0a }, { ADAU1373_BCLKDIV(0), 0x00 }, { ADAU1373_BCLKDIV(1), 0x00 }, { ADAU1373_BCLKDIV(2), 0x00 }, { ADAU1373_SRC_RATIOA(0), 0x00 }, { ADAU1373_SRC_RATIOB(0), 0x00 }, { ADAU1373_SRC_RATIOA(1), 0x00 }, { ADAU1373_SRC_RATIOB(1), 0x00 }, { ADAU1373_SRC_RATIOA(2), 0x00 }, { ADAU1373_SRC_RATIOB(2), 0x00 }, { ADAU1373_DEEMP_CTRL, 0x00 }, { ADAU1373_SRC_DAI_CTRL(0), 0x08 }, { ADAU1373_SRC_DAI_CTRL(1), 0x08 }, { ADAU1373_SRC_DAI_CTRL(2), 0x08 }, { ADAU1373_DIN_MIX_CTRL(0), 0x00 }, { ADAU1373_DIN_MIX_CTRL(1), 0x00 }, { ADAU1373_DIN_MIX_CTRL(2), 0x00 }, { ADAU1373_DIN_MIX_CTRL(3), 0x00 }, { ADAU1373_DIN_MIX_CTRL(4), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(0), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(1), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(2), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(3), 0x00 }, { ADAU1373_DOUT_MIX_CTRL(4), 0x00 }, { ADAU1373_DAI_PBL_VOL(0), 0x00 }, { ADAU1373_DAI_PBR_VOL(0), 0x00 }, { ADAU1373_DAI_PBL_VOL(1), 0x00 }, { ADAU1373_DAI_PBR_VOL(1), 0x00 }, { ADAU1373_DAI_PBL_VOL(2), 0x00 }, { ADAU1373_DAI_PBR_VOL(2), 0x00 }, { ADAU1373_DAI_RECL_VOL(0), 0x00 }, { ADAU1373_DAI_RECR_VOL(0), 0x00 }, { ADAU1373_DAI_RECL_VOL(1), 0x00 }, { ADAU1373_DAI_RECR_VOL(1), 0x00 }, { ADAU1373_DAI_RECL_VOL(2), 0x00 }, { ADAU1373_DAI_RECR_VOL(2), 0x00 }, { ADAU1373_DAC1_PBL_VOL, 0x00 }, { ADAU1373_DAC1_PBR_VOL, 0x00 }, { ADAU1373_DAC2_PBL_VOL, 0x00 }, { ADAU1373_DAC2_PBR_VOL, 0x00 }, { ADAU1373_ADC_RECL_VOL, 0x00 }, { ADAU1373_ADC_RECR_VOL, 0x00 }, { ADAU1373_DMIC_RECL_VOL, 0x00 }, { ADAU1373_DMIC_RECR_VOL, 0x00 }, { ADAU1373_VOL_GAIN1, 0x00 }, { ADAU1373_VOL_GAIN2, 0x00 }, { ADAU1373_VOL_GAIN3, 0x00 }, { ADAU1373_HPF_CTRL, 0x00 }, { ADAU1373_BASS1, 0x00 }, { ADAU1373_BASS2, 0x00 }, { ADAU1373_DRC(0) + 0x0, 0x78 }, { ADAU1373_DRC(0) + 0x1, 0x18 }, { ADAU1373_DRC(0) + 0x2, 0x00 }, { ADAU1373_DRC(0) + 0x3, 0x00 }, { ADAU1373_DRC(0) + 0x4, 0x00 }, { ADAU1373_DRC(0) + 0x5, 0xc0 }, { ADAU1373_DRC(0) + 0x6, 0x00 }, { ADAU1373_DRC(0) + 0x7, 0x00 }, { ADAU1373_DRC(0) + 0x8, 0x00 }, { ADAU1373_DRC(0) + 0x9, 0xc0 }, { ADAU1373_DRC(0) + 0xa, 0x88 }, { ADAU1373_DRC(0) + 0xb, 0x7a }, { ADAU1373_DRC(0) + 0xc, 0xdf }, { ADAU1373_DRC(0) + 0xd, 0x20 }, { ADAU1373_DRC(0) + 0xe, 0x00 }, { ADAU1373_DRC(0) + 0xf, 0x00 }, { ADAU1373_DRC(1) + 0x0, 0x78 }, { ADAU1373_DRC(1) + 0x1, 0x18 }, { ADAU1373_DRC(1) + 0x2, 0x00 }, { ADAU1373_DRC(1) + 0x3, 0x00 }, { ADAU1373_DRC(1) + 0x4, 0x00 }, { ADAU1373_DRC(1) + 0x5, 0xc0 }, { ADAU1373_DRC(1) + 0x6, 0x00 }, { ADAU1373_DRC(1) + 0x7, 0x00 }, { ADAU1373_DRC(1) + 0x8, 0x00 }, { ADAU1373_DRC(1) + 0x9, 0xc0 }, { ADAU1373_DRC(1) + 0xa, 0x88 }, { ADAU1373_DRC(1) + 0xb, 0x7a }, { ADAU1373_DRC(1) + 0xc, 0xdf }, { ADAU1373_DRC(1) + 0xd, 0x20 }, { ADAU1373_DRC(1) + 0xe, 0x00 }, { ADAU1373_DRC(1) + 0xf, 0x00 }, { ADAU1373_DRC(2) + 0x0, 0x78 }, { ADAU1373_DRC(2) + 0x1, 0x18 }, { ADAU1373_DRC(2) + 0x2, 0x00 }, { ADAU1373_DRC(2) + 0x3, 0x00 }, { ADAU1373_DRC(2) + 0x4, 0x00 }, { ADAU1373_DRC(2) + 0x5, 0xc0 }, { ADAU1373_DRC(2) + 0x6, 0x00 }, { ADAU1373_DRC(2) + 0x7, 0x00 }, { ADAU1373_DRC(2) + 0x8, 0x00 }, { ADAU1373_DRC(2) + 0x9, 0xc0 }, { ADAU1373_DRC(2) + 0xa, 0x88 }, { ADAU1373_DRC(2) + 0xb, 0x7a }, { ADAU1373_DRC(2) + 0xc, 0xdf }, { ADAU1373_DRC(2) + 0xd, 0x20 }, { ADAU1373_DRC(2) + 0xe, 0x00 }, { ADAU1373_DRC(2) + 0xf, 0x00 }, { ADAU1373_3D_CTRL1, 0x00 }, { ADAU1373_3D_CTRL2, 0x00 }, { ADAU1373_FDSP_SEL1, 0x00 }, { ADAU1373_FDSP_SEL2, 0x00 }, { ADAU1373_FDSP_SEL2, 0x00 }, { ADAU1373_FDSP_SEL4, 0x00 }, { ADAU1373_DIGMICCTRL, 0x00 }, { ADAU1373_DIGEN, 0x00 }, }; static const unsigned int adau1373_out_tlv[] = { Loading Loading @@ -418,6 +553,7 @@ static int adau1373_pll_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); unsigned int pll_id = w->name[3] - '1'; unsigned int val; Loading @@ -426,7 +562,7 @@ static int adau1373_pll_event(struct snd_soc_dapm_widget *w, else val = 0; snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id), ADAU1373_PLL_CTRL6_PLL_EN, val); if (SND_SOC_DAPM_EVENT_ON(event)) Loading Loading @@ -938,7 +1074,7 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream, adau1373_dai->enable_src = (div != 0); snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id), regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id), ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK, (div << 2) | ADAU1373_BCLKDIV_64); Loading @@ -959,7 +1095,7 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), return regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id), ADAU1373_DAI_WLEN_MASK, ctrl); } Loading Loading @@ -1016,7 +1152,7 @@ static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id), ~ADAU1373_DAI_WLEN_MASK, ctrl); return 0; Loading @@ -1039,7 +1175,7 @@ static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai, adau1373_dai->sysclk = freq; adau1373_dai->clk_src = clk_id; snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id), regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id), ADAU1373_BCLKDIV_SOURCE, clk_id << 5); return 0; Loading Loading @@ -1120,6 +1256,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = { static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); unsigned int dpll_div = 0; unsigned int x, r, n, m, i, j, mode; Loading Loading @@ -1187,36 +1324,36 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, if (dpll_div) { dpll_div = 11 - dpll_div; snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id), ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0); } else { snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id), ADAU1373_PLL_CTRL6_DPLL_BYPASS, ADAU1373_PLL_CTRL6_DPLL_BYPASS); } snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id), regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id), (source << 4) | dpll_div); snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id), regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id), (r << 3) | (x << 1) | mode); /* Set sysclk to pll_rate / 4 */ snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); return 0; } static void adau1373_load_drc_settings(struct snd_soc_codec *codec, static void adau1373_load_drc_settings(struct adau1373 *adau1373, unsigned int nr, uint8_t *drc) { unsigned int i; for (i = 0; i < ADAU1373_DRC_SIZE; ++i) snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]); regmap_write(adau1373->regmap, ADAU1373_DRC(nr) + i, drc[i]); } static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias) Loading @@ -1235,13 +1372,14 @@ static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias) static int adau1373_probe(struct snd_soc_codec *codec) { struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); struct adau1373_platform_data *pdata = codec->dev->platform_data; bool lineout_differential = false; unsigned int val; int ret; int i; ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); if (ret) { dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); return ret; Loading @@ -1256,7 +1394,7 @@ static int adau1373_probe(struct snd_soc_codec *codec) return -EINVAL; for (i = 0; i < pdata->num_drc; ++i) { adau1373_load_drc_settings(codec, i, adau1373_load_drc_settings(adau1373, i, pdata->drc_setting[i]); } Loading @@ -1268,18 +1406,18 @@ static int adau1373_probe(struct snd_soc_codec *codec) if (pdata->input_differential[i]) val |= BIT(i); } snd_soc_write(codec, ADAU1373_INPUT_MODE, val); regmap_write(adau1373->regmap, ADAU1373_INPUT_MODE, val); val = 0; if (pdata->lineout_differential) val |= ADAU1373_OUTPUT_CTRL_LDIFF; if (pdata->lineout_ground_sense) val |= ADAU1373_OUTPUT_CTRL_LNFBEN; snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val); regmap_write(adau1373->regmap, ADAU1373_OUTPUT_CTRL, val); lineout_differential = pdata->lineout_differential; snd_soc_write(codec, ADAU1373_EP_CTRL, regmap_write(adau1373->regmap, ADAU1373_EP_CTRL, (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) | (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET)); } Loading @@ -1289,7 +1427,7 @@ static int adau1373_probe(struct snd_soc_codec *codec) ARRAY_SIZE(adau1373_lineout2_controls)); } snd_soc_write(codec, ADAU1373_ADC_CTRL, regmap_write(adau1373->regmap, ADAU1373_ADC_CTRL, ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT); return 0; Loading @@ -1298,17 +1436,19 @@ static int adau1373_probe(struct snd_soc_codec *codec) static int adau1373_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3, ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN); break; case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3, ADAU1373_PWDN_CTRL3_PWR_EN, 0); break; } Loading @@ -1324,17 +1464,49 @@ static int adau1373_remove(struct snd_soc_codec *codec) static int adau1373_suspend(struct snd_soc_codec *codec) { return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); int ret; ret = adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); regcache_cache_only(adau1373->regmap, true); return ret; } static int adau1373_resume(struct snd_soc_codec *codec) { struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); regcache_cache_only(adau1373->regmap, false); adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_cache_sync(codec); regcache_sync(adau1373->regmap); return 0; } static bool adau1373_register_volatile(struct device *dev, unsigned int reg) { switch (reg) { case ADAU1373_SOFT_RESET: case ADAU1373_ADC_DAC_STATUS: return true; default: return false; } } static const struct regmap_config adau1373_regmap_config = { .val_bits = 8, .reg_bits = 8, .volatile_reg = adau1373_register_volatile, .max_register = ADAU1373_SOFT_RESET, .cache_type = REGCACHE_RBTREE, .reg_defaults = adau1373_reg_defaults, .num_reg_defaults = ARRAY_SIZE(adau1373_reg_defaults), }; static struct snd_soc_codec_driver adau1373_codec_driver = { .probe = adau1373_probe, .remove = adau1373_remove, Loading @@ -1342,9 +1514,6 @@ static struct snd_soc_codec_driver adau1373_codec_driver = { .resume = adau1373_resume, .set_bias_level = adau1373_set_bias_level, .idle_bias_off = true, .reg_cache_size = ARRAY_SIZE(adau1373_default_regs), .reg_cache_default = adau1373_default_regs, .reg_word_size = sizeof(uint8_t), .set_pll = adau1373_set_pll, Loading @@ -1366,6 +1535,13 @@ static int adau1373_i2c_probe(struct i2c_client *client, if (!adau1373) return -ENOMEM; adau1373->regmap = devm_regmap_init_i2c(client, &adau1373_regmap_config); if (IS_ERR(adau1373->regmap)) return PTR_ERR(adau1373->regmap); regmap_write(adau1373->regmap, ADAU1373_SOFT_RESET, 0x00); dev_set_drvdata(&client->dev, adau1373); ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver, Loading