Re: [alsa-devel] [PATCH 1/1] ASoC: codecs: max98088: Combined DAI operations for DAI1 and DAI2.
Submitting again the patch what applied Peter's comments.
These added local variables and their initialization repeats. It may be better to put them in struct max98088_cdata[].
I got it. I will change register offset into struct max98088_cdata[].
DAI2 does not have an OSR bit in the _CLOCK register. In the combined function, this should be conditionally for DAI1 only.
I will fix it.
Thanks, Jin.
Combined DAI operations for DAI1 and DAI2. For this, added id into DAI runtime data to identify each DAI.
Signed-off-by: Jin Park jinyoungp@nvidia.com --- sound/soc/codecs/max98088.c | 278 +++++++++++-------------------------------- 1 files changed, 69 insertions(+), 209 deletions(-)
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index ac65a2d..3c0e4f7 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -36,6 +36,14 @@ struct max98088_cdata { unsigned int rate; unsigned int fmt; int eq_sel; + + unsigned short clkmode_reg; + unsigned short clk_reg; + unsigned short clkcfg_hi_reg; + unsigned short clkcfg_lo_reg; + unsigned short fmt_reg; + unsigned short play_lvl_reg; + unsigned short filters_reg; };
struct max98088_priv { @@ -1253,29 +1261,26 @@ static inline int rate_value(int rate, u8 *value) return -EINVAL; }
-static int max98088_dai1_hw_params(struct snd_pcm_substream *substream, +static int max98088_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_cdata *cdata; + struct max98088_cdata *cdata = &max98088->dai[dai->id - 1]; unsigned long long ni; unsigned int rate; - u8 regval; - - cdata = &max98088->dai[0]; + u8 val;
rate = params_rate(params);
switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, - M98088_DAI_WS, 0); + snd_soc_update_bits(codec, cdata->fmt_reg, M98088_DAI_WS, 0); break; case SNDRV_PCM_FORMAT_S24_LE: - snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, - M98088_DAI_WS, M98088_DAI_WS); + snd_soc_update_bits(codec, cdata->fmt_reg, M98088_DAI_WS, + M98088_DAI_WS); break; default: return -EINVAL; @@ -1283,16 +1288,14 @@ static int max98088_dai1_hw_params(struct snd_pcm_substream *substream,
snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0);
- if (rate_value(rate, ®val)) + if (rate_value(rate, &val)) return -EINVAL;
- snd_soc_update_bits(codec, M98088_REG_11_DAI1_CLKMODE, - M98088_CLKMODE_MASK, regval); + snd_soc_update_bits(codec, cdata->clkmode_reg, M98088_CLKMODE_MASK, val); cdata->rate = rate;
/* Configure NI when operating as master */ - if (snd_soc_read(codec, M98088_REG_14_DAI1_FORMAT) - & M98088_DAI_MAS) { + if (snd_soc_read(codec, cdata->fmt_reg) & M98088_DAI_MAS) { if (max98088->sysclk == 0) { dev_err(codec->dev, "Invalid system clock frequency\n"); return -EINVAL; @@ -1300,86 +1303,16 @@ static int max98088_dai1_hw_params(struct snd_pcm_substream *substream, ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) * (unsigned long long int)rate; do_div(ni, (unsigned long long int)max98088->sysclk); - snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI, - (ni >> 8) & 0x7F); - snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO, - ni & 0xFF); + snd_soc_write(codec, cdata->clkcfg_hi_reg, (ni >> 8) & 0x7F); + snd_soc_write(codec, cdata->clkcfg_lo_reg, ni & 0xFF); }
/* Update sample rate mode */ if (rate < 50000) - snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS, - M98088_DAI_DHF, 0); + snd_soc_update_bits(codec, cdata->filters_reg, M98088_DAI_DHF, 0); else - snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS, - M98088_DAI_DHF, M98088_DAI_DHF); - - snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, - M98088_SHDNRUN); - - return 0; -} - -static int max98088_dai2_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_cdata *cdata; - unsigned long long ni; - unsigned int rate; - u8 regval; - - cdata = &max98088->dai[1]; - - rate = params_rate(params); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, - M98088_DAI_WS, 0); - break; - case SNDRV_PCM_FORMAT_S24_LE: - snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, - M98088_DAI_WS, M98088_DAI_WS); - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); - - if (rate_value(rate, ®val)) - return -EINVAL; - - snd_soc_update_bits(codec, M98088_REG_19_DAI2_CLKMODE, - M98088_CLKMODE_MASK, regval); - cdata->rate = rate; - - /* Configure NI when operating as master */ - if (snd_soc_read(codec, M98088_REG_1C_DAI2_FORMAT) - & M98088_DAI_MAS) { - if (max98088->sysclk == 0) { - dev_err(codec->dev, "Invalid system clock frequency\n"); - return -EINVAL; - } - ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) - * (unsigned long long int)rate; - do_div(ni, (unsigned long long int)max98088->sysclk); - snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI, - (ni >> 8) & 0x7F); - snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO, - ni & 0xFF); - } - - /* Update sample rate mode */ - if (rate < 50000) - snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS, - M98088_DAI_DHF, 0); - else - snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS, - M98088_DAI_DHF, M98088_DAI_DHF); + snd_soc_update_bits(codec, cdata->filters_reg, M98088_DAI_DHF, + M98088_DAI_DHF);
snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, M98088_SHDNRUN); @@ -1423,16 +1356,13 @@ static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, return 0; }
-static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) +static int max98088_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_codec *codec = dai->codec; struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_cdata *cdata; - u8 reg15val; - u8 reg14val = 0; - - cdata = &max98088->dai[0]; + struct max98088_cdata *cdata = &max98088->dai[dai->id - 1]; + u8 clk_val; + u8 fmt_val = 0;
if (fmt != cdata->fmt) { cdata->fmt = fmt; @@ -1440,14 +1370,12 @@ static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai, switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* Slave mode PLL */ - snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI, - 0x80); - snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO, - 0x00); + snd_soc_write(codec, cdata->clkcfg_hi_reg, 0x80); + snd_soc_write(codec, cdata->clkcfg_lo_reg, 0x00); break; case SND_SOC_DAIFMT_CBM_CFM: /* Set to master mode */ - reg14val |= M98088_DAI_MAS; + fmt_val |= M98088_DAI_MAS; break; case SND_SOC_DAIFMT_CBS_CFM: case SND_SOC_DAIFMT_CBM_CFS: @@ -1458,7 +1386,7 @@ static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai,
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - reg14val |= M98088_DAI_DLY; + fmt_val |= M98088_DAI_DLY; break; case SND_SOC_DAIFMT_LEFT_J: break; @@ -1470,127 +1398,43 @@ static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai, case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_NB_IF: - reg14val |= M98088_DAI_WCI; + fmt_val |= M98088_DAI_WCI; break; case SND_SOC_DAIFMT_IB_NF: - reg14val |= M98088_DAI_BCI; + fmt_val |= M98088_DAI_BCI; break; case SND_SOC_DAIFMT_IB_IF: - reg14val |= M98088_DAI_BCI|M98088_DAI_WCI; + fmt_val |= M98088_DAI_BCI|M98088_DAI_WCI; break; default: return -EINVAL; }
- snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, + snd_soc_update_bits(codec, cdata->fmt_reg, M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | - M98088_DAI_WCI, reg14val); + M98088_DAI_WCI, fmt_val);
- reg15val = M98088_DAI_BSEL64; - if (max98088->digmic) - reg15val |= M98088_DAI_OSR64; - snd_soc_write(codec, M98088_REG_15_DAI1_CLOCK, reg15val); + clk_val = M98088_DAI_BSEL64; + if ((dai->id == 1) && max98088->digmic) + clk_val |= M98088_DAI_OSR64; + snd_soc_write(codec, cdata->clk_reg, clk_val); }
return 0; }
-static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) +static int max98088_dai_digital_mute(struct snd_soc_dai *dai, int mute) { - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_codec *codec = dai->codec; struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_cdata *cdata; - u8 reg1Cval = 0; - - cdata = &max98088->dai[1]; - - if (fmt != cdata->fmt) { - cdata->fmt = fmt; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* Slave mode PLL */ - snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI, - 0x80); - snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO, - 0x00); - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* Set to master mode */ - reg1Cval |= M98088_DAI_MAS; - break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - default: - dev_err(codec->dev, "Clock mode unsupported"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - reg1Cval |= M98088_DAI_DLY; - break; - case SND_SOC_DAIFMT_LEFT_J: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - reg1Cval |= M98088_DAI_WCI; - break; - case SND_SOC_DAIFMT_IB_NF: - reg1Cval |= M98088_DAI_BCI; - break; - case SND_SOC_DAIFMT_IB_IF: - reg1Cval |= M98088_DAI_BCI|M98088_DAI_WCI; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, - M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | - M98088_DAI_WCI, reg1Cval); - - snd_soc_write(codec, M98088_REG_1D_DAI2_CLOCK, - M98088_DAI_BSEL64); - } - - return 0; -} - -static int max98088_dai1_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int reg; - - if (mute) - reg = M98088_DAI_MUTE; - else - reg = 0; - - snd_soc_update_bits(codec, M98088_REG_2F_LVL_DAI1_PLAY, - M98088_DAI_MUTE_MASK, reg); - return 0; -} - -static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int reg; + struct max98088_cdata *cdata = &max98088->dai[dai->id - 1]; + int val = 0;
if (mute) - reg = M98088_DAI_MUTE; - else - reg = 0; + val = M98088_DAI_MUTE;
- snd_soc_update_bits(codec, M98088_REG_31_LVL_DAI2_PLAY, - M98088_DAI_MUTE_MASK, reg); + snd_soc_update_bits(codec, cdata->play_lvl_reg, M98088_DAI_MUTE_MASK, + val); return 0; }
@@ -1653,21 +1497,22 @@ static int max98088_set_bias_level(struct snd_soc_codec *codec,
static struct snd_soc_dai_ops max98088_dai1_ops = { .set_sysclk = max98088_dai_set_sysclk, - .set_fmt = max98088_dai1_set_fmt, - .hw_params = max98088_dai1_hw_params, - .digital_mute = max98088_dai1_digital_mute, + .set_fmt = max98088_dai_set_fmt, + .hw_params = max98088_dai_hw_params, + .digital_mute = max98088_dai_digital_mute, };
static struct snd_soc_dai_ops max98088_dai2_ops = { .set_sysclk = max98088_dai_set_sysclk, - .set_fmt = max98088_dai2_set_fmt, - .hw_params = max98088_dai2_hw_params, - .digital_mute = max98088_dai2_digital_mute, + .set_fmt = max98088_dai_set_fmt, + .hw_params = max98088_dai_hw_params, + .digital_mute = max98088_dai_digital_mute, };
static struct snd_soc_dai_driver max98088_dai[] = { { .name = "HiFi", + .id = 1, .playback = { .stream_name = "HiFi Playback", .channels_min = 1, @@ -1686,6 +1531,7 @@ static struct snd_soc_dai_driver max98088_dai[] = { }, { .name = "Aux", + .id = 2, .playback = { .stream_name = "Aux Playback", .channels_min = 1, @@ -1977,11 +1823,25 @@ static int max98088_probe(struct snd_soc_codec *codec) cdata->rate = (unsigned)-1; cdata->fmt = (unsigned)-1; cdata->eq_sel = 0; + cdata->clkmode_reg = M98088_REG_11_DAI1_CLKMODE; + cdata->clk_reg = M98088_REG_15_DAI1_CLOCK; + cdata->clkcfg_hi_reg = M98088_REG_12_DAI1_CLKCFG_HI; + cdata->clkcfg_lo_reg = M98088_REG_13_DAI1_CLKCFG_LO; + cdata->fmt_reg = M98088_REG_14_DAI1_FORMAT; + cdata->play_lvl_reg = M98088_REG_2F_LVL_DAI1_PLAY; + cdata->filters_reg = M98088_REG_18_DAI1_FILTERS;
cdata = &max98088->dai[1]; cdata->rate = (unsigned)-1; cdata->fmt = (unsigned)-1; cdata->eq_sel = 0; + cdata->clkmode_reg = M98088_REG_19_DAI2_CLKMODE; + cdata->clk_reg = M98088_REG_1D_DAI2_CLOCK; + cdata->clkcfg_hi_reg = M98088_REG_1A_DAI2_CLKCFG_HI; + cdata->clkcfg_lo_reg = M98088_REG_1B_DAI2_CLKCFG_LO; + cdata->fmt_reg = M98088_REG_1C_DAI2_FORMAT; + cdata->play_lvl_reg = M98088_REG_31_LVL_DAI2_PLAY; + cdata->filters_reg = M98088_REG_20_DAI2_FILTERS;
max98088->ina_state = 0; max98088->inb_state = 0; -- 1.7.1
participants (1)
-
Jinyoung Park