Commit fb180283 authored by Maxim Kochetkov's avatar Maxim Kochetkov Committed by Mark Brown

ASoC: codecs: max98090: Allow dsp_a mode

TDM mode for max98090 is dsp_a compatible with such limitations:
1) Up to four timeslots supported.
2) Only 16 bits timeslots supported.
3) Only 2 active timeslots (L/R) supported.

We want to setup TDM mode only when dsp_a mode is selected. So move
M98090_REG_TDM_FORMAT/M98090_REG_TDM_CONTROL registers setup from
max98090_set_tdm_slot() to the max98090_dai_set_fmt(). Also extend
max98090_set_tdm_slot() with all TDM limitations check.
Signed-off-by: default avatarMaxim Kochetkov <fido_max@inbox.ru>
Link: https://lore.kernel.org/r/Message-Id: <20230622142038.63388-1-fido_max@inbox.ru>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 82f76ac2
...@@ -1581,7 +1581,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, ...@@ -1581,7 +1581,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
struct snd_soc_component *component = codec_dai->component; struct snd_soc_component *component = codec_dai->component;
struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
struct max98090_cdata *cdata; struct max98090_cdata *cdata;
u8 regval; u8 regval, tdm_regval;
max98090->dai_fmt = fmt; max98090->dai_fmt = fmt;
cdata = &max98090->dai[0]; cdata = &max98090->dai[0];
...@@ -1590,6 +1590,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, ...@@ -1590,6 +1590,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
cdata->fmt = fmt; cdata->fmt = fmt;
regval = 0; regval = 0;
tdm_regval = 0;
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBC_CFC: case SND_SOC_DAIFMT_CBC_CFC:
/* Set to consumer mode PLL - MAS mode off */ /* Set to consumer mode PLL - MAS mode off */
...@@ -1635,7 +1636,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, ...@@ -1635,7 +1636,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
regval |= M98090_RJ_MASK; regval |= M98090_RJ_MASK;
break; break;
case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_A:
/* Not supported mode */ tdm_regval |= M98090_TDM_MASK;
break;
default: default:
dev_err(component->dev, "DAI format unsupported"); dev_err(component->dev, "DAI format unsupported");
return -EINVAL; return -EINVAL;
...@@ -1664,11 +1666,20 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, ...@@ -1664,11 +1666,20 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
* seen for the case of TDM mode. The remaining cases have * seen for the case of TDM mode. The remaining cases have
* normal logic. * normal logic.
*/ */
if (max98090->tdm_slots > 1) if (tdm_regval)
regval ^= M98090_BCI_MASK; regval ^= M98090_BCI_MASK;
snd_soc_component_write(component, snd_soc_component_write(component,
M98090_REG_INTERFACE_FORMAT, regval); M98090_REG_INTERFACE_FORMAT, regval);
regval = 0;
if (tdm_regval)
regval = max98090->tdm_lslot << M98090_TDM_SLOTL_SHIFT |
max98090->tdm_rslot << M98090_TDM_SLOTR_SHIFT |
0 << M98090_TDM_SLOTDLY_SHIFT;
snd_soc_component_write(component, M98090_REG_TDM_FORMAT, regval);
snd_soc_component_write(component, M98090_REG_TDM_CONTROL, tdm_regval);
} }
return 0; return 0;
...@@ -1679,33 +1690,22 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai, ...@@ -1679,33 +1690,22 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
{ {
struct snd_soc_component *component = codec_dai->component; struct snd_soc_component *component = codec_dai->component;
struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
struct max98090_cdata *cdata;
cdata = &max98090->dai[0];
if (slots < 0 || slots > 4) if (slots < 0 || slots > 4)
return -EINVAL; return -EINVAL;
max98090->tdm_slots = slots; if (slot_width != 16)
max98090->tdm_width = slot_width; return -EINVAL;
if (max98090->tdm_slots > 1) {
/* SLOTL SLOTR SLOTDLY */
snd_soc_component_write(component, M98090_REG_TDM_FORMAT,
0 << M98090_TDM_SLOTL_SHIFT |
1 << M98090_TDM_SLOTR_SHIFT |
0 << M98090_TDM_SLOTDLY_SHIFT);
/* FSW TDM */
snd_soc_component_update_bits(component, M98090_REG_TDM_CONTROL,
M98090_TDM_MASK,
M98090_TDM_MASK);
}
/* if (rx_mask != tx_mask)
* Normally advisable to set TDM first, but this permits either order return -EINVAL;
*/
cdata->fmt = 0; if (!rx_mask)
max98090_dai_set_fmt(codec_dai, max98090->dai_fmt); return -EINVAL;
max98090->tdm_slots = slots;
max98090->tdm_lslot = ffs(rx_mask) - 1;
max98090->tdm_rslot = fls(rx_mask) - 1;
return 0; return 0;
} }
...@@ -2408,6 +2408,9 @@ static int max98090_probe(struct snd_soc_component *component) ...@@ -2408,6 +2408,9 @@ static int max98090_probe(struct snd_soc_component *component)
max98090->pa1en = 0; max98090->pa1en = 0;
max98090->pa2en = 0; max98090->pa2en = 0;
max98090->tdm_lslot = 0;
max98090->tdm_rslot = 1;
ret = snd_soc_component_read(component, M98090_REG_REVISION_ID); ret = snd_soc_component_read(component, M98090_REG_REVISION_ID);
if (ret < 0) { if (ret < 0) {
dev_err(component->dev, "Failed to read device revision: %d\n", dev_err(component->dev, "Failed to read device revision: %d\n",
......
...@@ -1533,7 +1533,8 @@ struct max98090_priv { ...@@ -1533,7 +1533,8 @@ struct max98090_priv {
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
unsigned int dai_fmt; unsigned int dai_fmt;
int tdm_slots; int tdm_slots;
int tdm_width; int tdm_lslot;
int tdm_rslot;
u8 lin_state; u8 lin_state;
unsigned int pa1en; unsigned int pa1en;
unsigned int pa2en; unsigned int pa2en;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment