Skip to content

Commit c1d3a92

Browse files
mripardbroonie
authored andcommitted
ASoC: sun4i-i2s: Fix the MCLK and BCLK dividers on newer SoCs
From: Marcus Cooper <[email protected]> The clock division dividers have changed between the older (A10/A31) and newer (H3, A64, etc) SoCs. While this was addressed through an offset on some SoCs, it was missing some dividers as well, so the support wasn't perfect. Let's introduce a pointer in the quirk structure for the divider calculation functions to use so we can have the proper range now. Signed-off-by: Marcus Cooper <[email protected]> [Maxime: Fix the commit log, use a field in the quirk structure] Signed-off-by: Maxime Ripard <[email protected]> Link: https://lore.kernel.org/r/0e5b4abf06cd3202354315201c6af44caeb20236.1566242458.git-series.maxime.ripard@bootlin.com Signed-off-by: Mark Brown <[email protected]>
1 parent fb19739 commit c1d3a92

File tree

1 file changed

+49
-14
lines changed

1 file changed

+49
-14
lines changed

sound/soc/sunxi/sun4i-i2s.c

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,6 @@ struct sun4i_i2s;
129129
* @has_fmt_set_lrck_period: SoC requires lrclk period to be set.
130130
* @reg_offset_txdata: offset of the tx fifo.
131131
* @sun4i_i2s_regmap: regmap config to use.
132-
* @mclk_offset: Value by which mclkdiv needs to be adjusted.
133-
* @bclk_offset: Value by which bclkdiv needs to be adjusted.
134132
* @field_clkdiv_mclk_en: regmap field to enable mclk output.
135133
* @field_fmt_wss: regmap field to set word select size.
136134
* @field_fmt_sr: regmap field to set sample resolution.
@@ -142,8 +140,6 @@ struct sun4i_i2s_quirks {
142140
bool has_fmt_set_lrck_period;
143141
unsigned int reg_offset_txdata; /* TX FIFO */
144142
const struct regmap_config *sun4i_i2s_regmap;
145-
unsigned int mclk_offset;
146-
unsigned int bclk_offset;
147143

148144
/* Register fields for i2s */
149145
struct reg_field field_clkdiv_mclk_en;
@@ -152,6 +148,11 @@ struct sun4i_i2s_quirks {
152148
struct reg_field field_fmt_bclk;
153149
struct reg_field field_fmt_lrclk;
154150

151+
const struct sun4i_i2s_clk_div *bclk_dividers;
152+
unsigned int num_bclk_dividers;
153+
const struct sun4i_i2s_clk_div *mclk_dividers;
154+
unsigned int num_mclk_dividers;
155+
155156
unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
156157
s8 (*get_sr)(const struct sun4i_i2s *, int);
157158
s8 (*get_wss)(const struct sun4i_i2s *, int);
@@ -208,6 +209,24 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = {
208209
/* TODO - extend divide ratio supported by newer SoCs */
209210
};
210211

212+
static const struct sun4i_i2s_clk_div sun8i_i2s_clk_div[] = {
213+
{ .div = 1, .val = 1 },
214+
{ .div = 2, .val = 2 },
215+
{ .div = 4, .val = 3 },
216+
{ .div = 6, .val = 4 },
217+
{ .div = 8, .val = 5 },
218+
{ .div = 12, .val = 6 },
219+
{ .div = 16, .val = 7 },
220+
{ .div = 24, .val = 8 },
221+
{ .div = 32, .val = 9 },
222+
{ .div = 48, .val = 10 },
223+
{ .div = 64, .val = 11 },
224+
{ .div = 96, .val = 12 },
225+
{ .div = 128, .val = 13 },
226+
{ .div = 176, .val = 14 },
227+
{ .div = 192, .val = 15 },
228+
};
229+
211230
static unsigned long sun4i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s)
212231
{
213232
return i2s->mclk_freq;
@@ -223,11 +242,12 @@ static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s,
223242
unsigned int sampling_rate,
224243
unsigned int word_size)
225244
{
245+
const struct sun4i_i2s_clk_div *dividers = i2s->variant->bclk_dividers;
226246
int div = parent_rate / sampling_rate / word_size / 2;
227247
int i;
228248

229-
for (i = 0; i < ARRAY_SIZE(sun4i_i2s_bclk_div); i++) {
230-
const struct sun4i_i2s_clk_div *bdiv = &sun4i_i2s_bclk_div[i];
249+
for (i = 0; i < i2s->variant->num_bclk_dividers; i++) {
250+
const struct sun4i_i2s_clk_div *bdiv = &dividers[i];
231251

232252
if (bdiv->div == div)
233253
return bdiv->val;
@@ -240,11 +260,12 @@ static int sun4i_i2s_get_mclk_div(struct sun4i_i2s *i2s,
240260
unsigned long parent_rate,
241261
unsigned long mclk_rate)
242262
{
263+
const struct sun4i_i2s_clk_div *dividers = i2s->variant->mclk_dividers;
243264
int div = parent_rate / mclk_rate;
244265
int i;
245266

246-
for (i = 0; i < ARRAY_SIZE(sun4i_i2s_mclk_div); i++) {
247-
const struct sun4i_i2s_clk_div *mdiv = &sun4i_i2s_mclk_div[i];
267+
for (i = 0; i < i2s->variant->num_mclk_dividers; i++) {
268+
const struct sun4i_i2s_clk_div *mdiv = &dividers[i];
248269

249270
if (mdiv->div == div)
250271
return mdiv->val;
@@ -326,10 +347,6 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai,
326347
return -EINVAL;
327348
}
328349

329-
/* Adjust the clock division values if needed */
330-
bclk_div += i2s->variant->bclk_offset;
331-
mclk_div += i2s->variant->mclk_offset;
332-
333350
regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG,
334351
SUN4I_I2S_CLK_DIV_BCLK(bclk_div) |
335352
SUN4I_I2S_CLK_DIV_MCLK(mclk_div));
@@ -969,6 +986,10 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
969986
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
970987
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
971988
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
989+
.bclk_dividers = sun4i_i2s_bclk_div,
990+
.num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div),
991+
.mclk_dividers = sun4i_i2s_mclk_div,
992+
.num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div),
972993
.get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
973994
.get_sr = sun4i_i2s_get_sr,
974995
.get_wss = sun4i_i2s_get_wss,
@@ -985,6 +1006,10 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
9851006
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
9861007
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
9871008
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
1009+
.bclk_dividers = sun4i_i2s_bclk_div,
1010+
.num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div),
1011+
.mclk_dividers = sun4i_i2s_mclk_div,
1012+
.num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div),
9881013
.get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
9891014
.get_sr = sun4i_i2s_get_sr,
9901015
.get_wss = sun4i_i2s_get_wss,
@@ -1001,6 +1026,10 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
10011026
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
10021027
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
10031028
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
1029+
.bclk_dividers = sun8i_i2s_clk_div,
1030+
.num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
1031+
.mclk_dividers = sun8i_i2s_clk_div,
1032+
.num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
10041033
.get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate,
10051034
.get_sr = sun8i_i2s_get_sr_wss,
10061035
.get_wss = sun8i_i2s_get_sr_wss,
@@ -1012,14 +1041,16 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
10121041
.has_reset = true,
10131042
.reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
10141043
.sun4i_i2s_regmap = &sun8i_i2s_regmap_config,
1015-
.mclk_offset = 1,
1016-
.bclk_offset = 2,
10171044
.has_fmt_set_lrck_period = true,
10181045
.field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
10191046
.field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2),
10201047
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6),
10211048
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
10221049
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19),
1050+
.bclk_dividers = sun8i_i2s_clk_div,
1051+
.num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
1052+
.mclk_dividers = sun8i_i2s_clk_div,
1053+
.num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
10231054
.get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate,
10241055
.get_sr = sun8i_i2s_get_sr_wss,
10251056
.get_wss = sun8i_i2s_get_sr_wss,
@@ -1036,6 +1067,10 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
10361067
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
10371068
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
10381069
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
1070+
.bclk_dividers = sun4i_i2s_bclk_div,
1071+
.num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div),
1072+
.mclk_dividers = sun4i_i2s_mclk_div,
1073+
.num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div),
10391074
.get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
10401075
.get_sr = sun4i_i2s_get_sr,
10411076
.get_wss = sun4i_i2s_get_wss,

0 commit comments

Comments
 (0)