aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@bootlin.com>2019-08-19 15:25:15 -0400
committerMark Brown <broonie@kernel.org>2019-08-20 13:31:24 -0400
commitfb19739d7f688142b61d0fca476188c4fd9e937a (patch)
treed7538620d176ff99cf8b2927bf640cea63bf63f8 /sound
parent71137bcd0a9a778f9407a3bee46c62fcccee4f83 (diff)
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: 7d2993811a1e ("ASoC: sun4i-i2s: Add support for H3") Fixes: 21faaea1343f ("ASoC: sun4i-i2s: Add support for A83T") Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com> Link: https://lore.kernel.org/r/0b6665be216b3bd0e7bc43724818f05f3f8ee881.1566242458.git-series.maxime.ripard@bootlin.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/sunxi/sun4i-i2s.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 93ea627e2f1f..acfcdb26086a 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -152,6 +152,7 @@ struct sun4i_i2s_quirks {
152 struct reg_field field_fmt_bclk; 152 struct reg_field field_fmt_bclk;
153 struct reg_field field_fmt_lrclk; 153 struct reg_field field_fmt_lrclk;
154 154
155 unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
155 s8 (*get_sr)(const struct sun4i_i2s *, int); 156 s8 (*get_sr)(const struct sun4i_i2s *, int);
156 s8 (*get_wss)(const struct sun4i_i2s *, int); 157 s8 (*get_wss)(const struct sun4i_i2s *, int);
157 int (*set_chan_cfg)(const struct sun4i_i2s *, 158 int (*set_chan_cfg)(const struct sun4i_i2s *,
@@ -207,6 +208,16 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = {
207 /* TODO - extend divide ratio supported by newer SoCs */ 208 /* TODO - extend divide ratio supported by newer SoCs */
208}; 209};
209 210
211static unsigned long sun4i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s)
212{
213 return i2s->mclk_freq;
214}
215
216static unsigned long sun8i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s)
217{
218 return clk_get_rate(i2s->mod_clk);
219}
220
210static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s, 221static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s,
211 unsigned long parent_rate, 222 unsigned long parent_rate,
212 unsigned int sampling_rate, 223 unsigned int sampling_rate,
@@ -259,7 +270,7 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai,
259 unsigned int word_size) 270 unsigned int word_size)
260{ 271{
261 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); 272 struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
262 unsigned int oversample_rate, clk_rate; 273 unsigned int oversample_rate, clk_rate, bclk_parent_rate;
263 int bclk_div, mclk_div; 274 int bclk_div, mclk_div;
264 int ret; 275 int ret;
265 276
@@ -301,7 +312,8 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai,
301 return -EINVAL; 312 return -EINVAL;
302 } 313 }
303 314
304 bclk_div = sun4i_i2s_get_bclk_div(i2s, i2s->mclk_freq, 315 bclk_parent_rate = i2s->variant->get_bclk_parent_rate(i2s);
316 bclk_div = sun4i_i2s_get_bclk_div(i2s, bclk_parent_rate,
305 rate, word_size); 317 rate, word_size);
306 if (bclk_div < 0) { 318 if (bclk_div < 0) {
307 dev_err(dai->dev, "Unsupported BCLK divider: %d\n", bclk_div); 319 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 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 969 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
958 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), 970 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
959 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), 971 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
972 .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
960 .get_sr = sun4i_i2s_get_sr, 973 .get_sr = sun4i_i2s_get_sr,
961 .get_wss = sun4i_i2s_get_wss, 974 .get_wss = sun4i_i2s_get_wss,
962 .set_chan_cfg = sun4i_i2s_set_chan_cfg, 975 .set_chan_cfg = sun4i_i2s_set_chan_cfg,
@@ -972,6 +985,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
972 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 985 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
973 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), 986 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
974 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), 987 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
988 .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
975 .get_sr = sun4i_i2s_get_sr, 989 .get_sr = sun4i_i2s_get_sr,
976 .get_wss = sun4i_i2s_get_wss, 990 .get_wss = sun4i_i2s_get_wss,
977 .set_chan_cfg = sun4i_i2s_set_chan_cfg, 991 .set_chan_cfg = sun4i_i2s_set_chan_cfg,
@@ -987,6 +1001,7 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
987 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 1001 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
988 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), 1002 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
989 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), 1003 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
1004 .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate,
990 .get_sr = sun8i_i2s_get_sr_wss, 1005 .get_sr = sun8i_i2s_get_sr_wss,
991 .get_wss = sun8i_i2s_get_sr_wss, 1006 .get_wss = sun8i_i2s_get_sr_wss,
992 .set_chan_cfg = sun8i_i2s_set_chan_cfg, 1007 .set_chan_cfg = sun8i_i2s_set_chan_cfg,
@@ -1005,6 +1020,7 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
1005 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), 1020 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6),
1006 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), 1021 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
1007 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19), 1022 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19),
1023 .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate,
1008 .get_sr = sun8i_i2s_get_sr_wss, 1024 .get_sr = sun8i_i2s_get_sr_wss,
1009 .get_wss = sun8i_i2s_get_sr_wss, 1025 .get_wss = sun8i_i2s_get_sr_wss,
1010 .set_chan_cfg = sun8i_i2s_set_chan_cfg, 1026 .set_chan_cfg = sun8i_i2s_set_chan_cfg,
@@ -1020,6 +1036,7 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
1020 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), 1036 .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
1021 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), 1037 .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
1022 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), 1038 .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
1039 .get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
1023 .get_sr = sun4i_i2s_get_sr, 1040 .get_sr = sun4i_i2s_get_sr,
1024 .get_wss = sun4i_i2s_get_wss, 1041 .get_wss = sun4i_i2s_get_wss,
1025 .set_chan_cfg = sun4i_i2s_set_chan_cfg, 1042 .set_chan_cfg = sun4i_i2s_set_chan_cfg,