mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-20 13:47:56 +07:00
ASoC: sun4i-i2s: Fix the MCLK and BCLK dividers on newer SoCs
From: Marcus Cooper <codekipper@gmail.com> 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 <codekipper@gmail.com> [Maxime: Fix the commit log, use a field in the quirk structure] Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com> Link: https://lore.kernel.org/r/0e5b4abf06cd3202354315201c6af44caeb20236.1566242458.git-series.maxime.ripard@bootlin.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
fb19739d7f
commit
c1d3a921d7
@ -129,8 +129,6 @@ struct sun4i_i2s;
|
||||
* @has_fmt_set_lrck_period: SoC requires lrclk period to be set.
|
||||
* @reg_offset_txdata: offset of the tx fifo.
|
||||
* @sun4i_i2s_regmap: regmap config to use.
|
||||
* @mclk_offset: Value by which mclkdiv needs to be adjusted.
|
||||
* @bclk_offset: Value by which bclkdiv needs to be adjusted.
|
||||
* @field_clkdiv_mclk_en: regmap field to enable mclk output.
|
||||
* @field_fmt_wss: regmap field to set word select size.
|
||||
* @field_fmt_sr: regmap field to set sample resolution.
|
||||
@ -142,8 +140,6 @@ struct sun4i_i2s_quirks {
|
||||
bool has_fmt_set_lrck_period;
|
||||
unsigned int reg_offset_txdata; /* TX FIFO */
|
||||
const struct regmap_config *sun4i_i2s_regmap;
|
||||
unsigned int mclk_offset;
|
||||
unsigned int bclk_offset;
|
||||
|
||||
/* Register fields for i2s */
|
||||
struct reg_field field_clkdiv_mclk_en;
|
||||
@ -152,6 +148,11 @@ struct sun4i_i2s_quirks {
|
||||
struct reg_field field_fmt_bclk;
|
||||
struct reg_field field_fmt_lrclk;
|
||||
|
||||
const struct sun4i_i2s_clk_div *bclk_dividers;
|
||||
unsigned int num_bclk_dividers;
|
||||
const struct sun4i_i2s_clk_div *mclk_dividers;
|
||||
unsigned int num_mclk_dividers;
|
||||
|
||||
unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
|
||||
s8 (*get_sr)(const struct sun4i_i2s *, int);
|
||||
s8 (*get_wss)(const struct sun4i_i2s *, int);
|
||||
@ -208,6 +209,24 @@ static const struct sun4i_i2s_clk_div sun4i_i2s_mclk_div[] = {
|
||||
/* TODO - extend divide ratio supported by newer SoCs */
|
||||
};
|
||||
|
||||
static const struct sun4i_i2s_clk_div sun8i_i2s_clk_div[] = {
|
||||
{ .div = 1, .val = 1 },
|
||||
{ .div = 2, .val = 2 },
|
||||
{ .div = 4, .val = 3 },
|
||||
{ .div = 6, .val = 4 },
|
||||
{ .div = 8, .val = 5 },
|
||||
{ .div = 12, .val = 6 },
|
||||
{ .div = 16, .val = 7 },
|
||||
{ .div = 24, .val = 8 },
|
||||
{ .div = 32, .val = 9 },
|
||||
{ .div = 48, .val = 10 },
|
||||
{ .div = 64, .val = 11 },
|
||||
{ .div = 96, .val = 12 },
|
||||
{ .div = 128, .val = 13 },
|
||||
{ .div = 176, .val = 14 },
|
||||
{ .div = 192, .val = 15 },
|
||||
};
|
||||
|
||||
static unsigned long sun4i_i2s_get_bclk_parent_rate(const struct sun4i_i2s *i2s)
|
||||
{
|
||||
return i2s->mclk_freq;
|
||||
@ -223,11 +242,12 @@ static int sun4i_i2s_get_bclk_div(struct sun4i_i2s *i2s,
|
||||
unsigned int sampling_rate,
|
||||
unsigned int word_size)
|
||||
{
|
||||
const struct sun4i_i2s_clk_div *dividers = i2s->variant->bclk_dividers;
|
||||
int div = parent_rate / sampling_rate / word_size / 2;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sun4i_i2s_bclk_div); i++) {
|
||||
const struct sun4i_i2s_clk_div *bdiv = &sun4i_i2s_bclk_div[i];
|
||||
for (i = 0; i < i2s->variant->num_bclk_dividers; i++) {
|
||||
const struct sun4i_i2s_clk_div *bdiv = ÷rs[i];
|
||||
|
||||
if (bdiv->div == div)
|
||||
return bdiv->val;
|
||||
@ -240,11 +260,12 @@ static int sun4i_i2s_get_mclk_div(struct sun4i_i2s *i2s,
|
||||
unsigned long parent_rate,
|
||||
unsigned long mclk_rate)
|
||||
{
|
||||
const struct sun4i_i2s_clk_div *dividers = i2s->variant->mclk_dividers;
|
||||
int div = parent_rate / mclk_rate;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sun4i_i2s_mclk_div); i++) {
|
||||
const struct sun4i_i2s_clk_div *mdiv = &sun4i_i2s_mclk_div[i];
|
||||
for (i = 0; i < i2s->variant->num_mclk_dividers; i++) {
|
||||
const struct sun4i_i2s_clk_div *mdiv = ÷rs[i];
|
||||
|
||||
if (mdiv->div == div)
|
||||
return mdiv->val;
|
||||
@ -326,10 +347,6 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Adjust the clock division values if needed */
|
||||
bclk_div += i2s->variant->bclk_offset;
|
||||
mclk_div += i2s->variant->mclk_offset;
|
||||
|
||||
regmap_write(i2s->regmap, SUN4I_I2S_CLK_DIV_REG,
|
||||
SUN4I_I2S_CLK_DIV_BCLK(bclk_div) |
|
||||
SUN4I_I2S_CLK_DIV_MCLK(mclk_div));
|
||||
@ -969,6 +986,10 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
|
||||
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
|
||||
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
|
||||
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
|
||||
.bclk_dividers = sun4i_i2s_bclk_div,
|
||||
.num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div),
|
||||
.mclk_dividers = sun4i_i2s_mclk_div,
|
||||
.num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div),
|
||||
.get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
|
||||
.get_sr = sun4i_i2s_get_sr,
|
||||
.get_wss = sun4i_i2s_get_wss,
|
||||
@ -985,6 +1006,10 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
|
||||
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
|
||||
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
|
||||
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
|
||||
.bclk_dividers = sun4i_i2s_bclk_div,
|
||||
.num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div),
|
||||
.mclk_dividers = sun4i_i2s_mclk_div,
|
||||
.num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div),
|
||||
.get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
|
||||
.get_sr = sun4i_i2s_get_sr,
|
||||
.get_wss = sun4i_i2s_get_wss,
|
||||
@ -1001,6 +1026,10 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
|
||||
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
|
||||
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
|
||||
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
|
||||
.bclk_dividers = sun8i_i2s_clk_div,
|
||||
.num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
|
||||
.mclk_dividers = sun8i_i2s_clk_div,
|
||||
.num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
|
||||
.get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate,
|
||||
.get_sr = sun8i_i2s_get_sr_wss,
|
||||
.get_wss = sun8i_i2s_get_sr_wss,
|
||||
@ -1012,14 +1041,16 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
|
||||
.has_reset = true,
|
||||
.reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
|
||||
.sun4i_i2s_regmap = &sun8i_i2s_regmap_config,
|
||||
.mclk_offset = 1,
|
||||
.bclk_offset = 2,
|
||||
.has_fmt_set_lrck_period = true,
|
||||
.field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
|
||||
.field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2),
|
||||
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6),
|
||||
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
|
||||
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 19, 19),
|
||||
.bclk_dividers = sun8i_i2s_clk_div,
|
||||
.num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
|
||||
.mclk_dividers = sun8i_i2s_clk_div,
|
||||
.num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
|
||||
.get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate,
|
||||
.get_sr = sun8i_i2s_get_sr_wss,
|
||||
.get_wss = sun8i_i2s_get_sr_wss,
|
||||
@ -1036,6 +1067,10 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
|
||||
.field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5),
|
||||
.field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6),
|
||||
.field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7),
|
||||
.bclk_dividers = sun4i_i2s_bclk_div,
|
||||
.num_bclk_dividers = ARRAY_SIZE(sun4i_i2s_bclk_div),
|
||||
.mclk_dividers = sun4i_i2s_mclk_div,
|
||||
.num_mclk_dividers = ARRAY_SIZE(sun4i_i2s_mclk_div),
|
||||
.get_bclk_parent_rate = sun4i_i2s_get_bclk_parent_rate,
|
||||
.get_sr = sun4i_i2s_get_sr,
|
||||
.get_wss = sun4i_i2s_get_wss,
|
||||
|
Loading…
Reference in New Issue
Block a user