Commit fb19739d authored by Maxime Ripard's avatar Maxime Ripard Committed by Mark Brown

ASoC: sun4i-i2s: Use module clock as BCLK parent on newer SoCs

On the first generation of Allwinner SoCs (A10-A31), the i2s controller was
using the MCLK as BCLK parent. However, this changed since the introduction
of the A83t and BCLK now uses the module clock as its parent.

Let's introduce a hook to get the parent rate and use that in our divider
calculations.

Fixes: 7d299381 ("ASoC: sun4i-i2s: Add support for H3")
Fixes: 21faaea1 ("ASoC: sun4i-i2s: Add support for A83T")
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@bootlin.com>
Link: https://lore.kernel.org/r/0b6665be216b3bd0e7bc43724818f05f3f8ee881.1566242458.git-series.maxime.ripard@bootlin.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 71137bcd
...@@ -152,6 +152,7 @@ struct sun4i_i2s_quirks { ...@@ -152,6 +152,7 @@ struct sun4i_i2s_quirks {
struct reg_field field_fmt_bclk; struct reg_field field_fmt_bclk;
struct reg_field field_fmt_lrclk; struct reg_field field_fmt_lrclk;
unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
s8 (*get_sr)(const struct sun4i_i2s *, int); s8 (*get_sr)(const struct sun4i_i2s *, int);
s8 (*get_wss)(const struct sun4i_i2s *, int); s8 (*get_wss)(const struct sun4i_i2s *, int);
int (*set_chan_cfg)(const struct sun4i_i2s *, int (*set_chan_cfg)(const struct sun4i_i2s *,
...@@ -207,6 +208,16 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = { ...@@ -207,6 +208,16 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = {
/* TODO - extend divide ratio supported by newer SoCs */ /* TODO - extend divide ratio supported by newer SoCs */
}; };
static unsigned long sun4i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s)
{
return i2s->mclk_freq;
}
static unsigned long sun8i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s)
{
return clk_get_rate(i2s->mod_clk);
}
static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s, static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s,
unsigned long parent_rate, unsigned long parent_rate,
unsigned int sampling_rate, unsigned int sampling_rate,
...@@ -259,7 +270,7 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, ...@@ -259,7 +270,7 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai,
unsigned int word_size) unsigned int word_size)
{ {
struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
unsigned int oversample_rate, clk_rate; unsigned int oversample_rate, clk_rate, bclk_parent_rate;
int bclk_div, mclk_div; int bclk_div, mclk_div;
int ret; int ret;
...@@ -301,7 +312,8 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, ...@@ -301,7 +312,8 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai,
return -EINVAL; return -EINVAL;
} }
bclk_div = sun4i_i2s_get_bclk_div(i2s, i2s->mclk_freq, bclk_parent_rate = i2s->variant->get_bclk_parent_rate(i2s);
bclk_div = sun4i_i2s_get_bclk_div(i2s, bclk_parent_rate,
rate, word_size); rate, word_size);
if (bclk_div < 0) { if (bclk_div < 0) {
dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div); dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div);
...@@ -957,6 +969,7 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { ...@@ -957,6 +969,7 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
.get_sr = sun4i_i2s_get_sr, .get_sr = sun4i_i2s_get_sr,
.get_wss = sun4i_i2s_get_wss, .get_wss = sun4i_i2s_get_wss,
.set_chan_cfg = sun4i_i2s_set_chan_cfg, .set_chan_cfg = sun4i_i2s_set_chan_cfg,
...@@ -972,6 +985,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { ...@@ -972,6 +985,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
.get_sr = sun4i_i2s_get_sr, .get_sr = sun4i_i2s_get_sr,
.get_wss = sun4i_i2s_get_wss, .get_wss = sun4i_i2s_get_wss,
.set_chan_cfg = sun4i_i2s_set_chan_cfg, .set_chan_cfg = sun4i_i2s_set_chan_cfg,
...@@ -987,6 +1001,7 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { ...@@ -987,6 +1001,7 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate,
.get_sr = sun8i_i2s_get_sr_wss, .get_sr = sun8i_i2s_get_sr_wss,
.get_wss = sun8i_i2s_get_sr_wss, .get_wss = sun8i_i2s_get_sr_wss,
.set_chan_cfg = sun8i_i2s_set_chan_cfg, .set_chan_cfg = sun8i_i2s_set_chan_cfg,
...@@ -1005,6 +1020,7 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { ...@@ -1005,6 +1020,7 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19), .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19),
.get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate,
.get_sr = sun8i_i2s_get_sr_wss, .get_sr = sun8i_i2s_get_sr_wss,
.get_wss = sun8i_i2s_get_sr_wss, .get_wss = sun8i_i2s_get_sr_wss,
.set_chan_cfg = sun8i_i2s_set_chan_cfg, .set_chan_cfg = sun8i_i2s_set_chan_cfg,
...@@ -1020,6 +1036,7 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { ...@@ -1020,6 +1036,7 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
.get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
.get_sr = sun4i_i2s_get_sr, .get_sr = sun4i_i2s_get_sr,
.get_wss = sun4i_i2s_get_wss, .get_wss = sun4i_i2s_get_wss,
.set_chan_cfg = sun4i_i2s_set_chan_cfg, .set_chan_cfg = sun4i_i2s_set_chan_cfg,
......
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