On 20 November 2019 15:24, Sebastian Reichel wrote:
This adds default clock/PLL configuration to the driver for usage with generic drivers like simple-card for usage with a fixed rate clock.
Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com
sound/soc/codecs/da7213.c | 75 ++++++++++++++++++++++++++++++++++++--- sound/soc/codecs/da7213.h | 2 ++ 2 files changed, 73 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 3e6ad996741b..ff1a936240be 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1156,6 +1156,7 @@ static int da7213_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component;
- struct da7213_priv *da7213 =
snd_soc_component_get_drvdata(component); u8 dai_ctrl = 0; u8 fs;
@@ -1181,33 +1182,43 @@ static int da7213_hw_params(struct snd_pcm_substream *substream, switch (params_rate(params)) { case 8000: fs = DA7213_SR_8000;
break; case 11025: fs = DA7213_SR_11025;da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000;
break; case 12000: fs = DA7213_SR_12000;da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800;
break; case 16000: fs = DA7213_SR_16000;da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000;
break; case 22050: fs = DA7213_SR_22050;da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000;
break; case 32000: fs = DA7213_SR_32000;da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800;
break; case 44100: fs = DA7213_SR_44100;da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000;
break; case 48000: fs = DA7213_SR_48000;da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800;
break; case 88200: fs = DA7213_SR_88200;da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000;
break; case 96000: fs = DA7213_SR_96000;da7213->out_rate = DA7213_PLL_FREQ_OUT_90316800;
break; default: return -EINVAL;da7213->out_rate = DA7213_PLL_FREQ_OUT_98304000;
@@ -1392,9 +1403,9 @@ static int da7213_set_component_sysclk(struct snd_soc_component *component, }
/* Supported PLL input frequencies are 32KHz, 5MHz - 54MHz. */ -static int da7213_set_component_pll(struct snd_soc_component *component,
int pll_id, int source,
unsigned int fref, unsigned int fout)
+static int _da7213_set_component_pll(struct snd_soc_component *component,
int pll_id, int source,
unsigned int fref, unsigned int fout)
{ struct da7213_priv *da7213 = snd_soc_component_get_drvdata(component);
@@ -1503,6 +1514,16 @@ static int da7213_set_component_pll(struct snd_soc_component *component, return 0; }
+static int da7213_set_component_pll(struct snd_soc_component *component,
int pll_id, int source,
unsigned int fref, unsigned int fout)
+{
- struct da7213_priv *da7213 =
snd_soc_component_get_drvdata(component);
- da7213->fixed_clk_auto_pll = false;
- return _da7213_set_component_pll(component, pll_id, source, fref,
fout); +}
/* DAI operations */ static const struct snd_soc_dai_ops da7213_dai_ops = { .hw_params = da7213_hw_params, @@ -1532,6 +1553,43 @@ static struct snd_soc_dai_driver da7213_dai = { .symmetric_rates = 1, };
+static int da7213_set_auto_pll(struct snd_soc_component *component, bool enable) +{
- struct da7213_priv *da7213 =
snd_soc_component_get_drvdata(component);
- int mode;
- if (!da7213->fixed_clk_auto_pll)
return 0;
- da7213->mclk_rate = clk_get_rate(da7213->mclk);
- if (enable)
mode = DA7213_SYSCLK_PLL;
- else
mode = DA7213_SYSCLK_MCLK;
If we're the clock slave, and we're using an MCLK that's not a harmonic then SRM is required to synchronise the PLL to the incoming WCLK signal. I assume simple sound card should allow for both master and slave modes? If so we'll need to do something here to determine this as well.
- switch (da7213->out_rate) {
- case DA7213_PLL_FREQ_OUT_90316800:
if (da7213->mclk_rate == 11289600 ||
da7213->mclk_rate == 22579200 ||
da7213->mclk_rate == 45158400)
mode = DA7213_SYSCLK_MCLK;
break;
- case DA7213_PLL_FREQ_OUT_98304000:
if (da7213->mclk_rate == 12288000 ||
da7213->mclk_rate == 24576000 ||
da7213->mclk_rate == 49152000)
mode = DA7213_SYSCLK_MCLK;
break;
- default:
return -1;
- }
- return _da7213_set_component_pll(component, 0, mode,
da7213->mclk_rate, da7213->out_rate);
+}
static int da7213_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { @@ -1551,6 +1609,8 @@ static int da7213_set_bias_level(struct snd_soc_component *component, "Failed to enable mclk\n"); return ret; }
da7213_set_auto_pll(component, true);
I've thought more about this and for the scenario where a machine driver controls the PLL through a DAPM widget associated with this codec (like some Intel boards do), then the PLL will be configured once here and then again when the relevant widget is called. I don't think that will matter but I will take a further look just in case this might cause some oddities.
} } break;
@@ -1562,8 +1622,10 @@ static int da7213_set_bias_level(struct snd_soc_component *component, DA7213_VMID_EN | DA7213_BIAS_EN); } else { /* Remove MCLK */
if (da7213->mclk)
if (da7213->mclk) {
da7213_set_auto_pll(component, false); clk_disable_unprepare(da7213->mclk);
} break; case SND_SOC_BIAS_OFF:}
@@ -1829,6 +1891,11 @@ static int da7213_probe(struct snd_soc_component *component) return PTR_ERR(da7213->mclk); else da7213->mclk = NULL;
} else {
/* Do automatic PLL handling assuming fixed clock until
* set_pll() has been called. This makes the codec usable
* with the simple-audio-card driver. */
da7213->fixed_clk_auto_pll = true;
}
return 0;
diff --git a/sound/soc/codecs/da7213.h b/sound/soc/codecs/da7213.h index 3890829dfb6e..97ccf0ddd2be 100644 --- a/sound/soc/codecs/da7213.h +++ b/sound/soc/codecs/da7213.h @@ -535,10 +535,12 @@ struct da7213_priv { struct regulator_bulk_data supplies[DA7213_NUM_SUPPLIES]; struct clk *mclk; unsigned int mclk_rate;
- unsigned int out_rate; int clk_src; bool master; bool alc_calib_auto; bool alc_en;
- bool fixed_clk_auto_pll; struct da7213_platform_data *pdata;
};
-- 2.24.0