From: Marcus Cooper <codekipper@xxxxxxxxx> Newer SoCs like the H6 have the channel select bits in a different positions than what is on the H3. As we will eventually add multi- channel support then create function calls as opposed to regmap fields to add support for different devices. Signed-off-by: Marcus Cooper <codekipper@xxxxxxxxx> --- sound/soc/sunxi/sun4i-i2s.c | 68 ++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 8d28a386872f..19988d61a085 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -120,6 +120,8 @@ #define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12) #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) #define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4) +#define SUN8I_I2S_TX_CHAN_SEL_MASK GENMASK(2, 0) +#define SUN8I_I2S_TX_CHAN_SEL(chan) (chan - 1) #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 @@ -161,6 +163,8 @@ struct sun4i_i2s_quirks { void (*set_rxchanoffset)(const struct sun4i_i2s *); void (*set_txchanen)(const struct sun4i_i2s *, int, int); void (*set_rxchanen)(const struct sun4i_i2s *, int); + void (*set_txchansel)(const struct sun4i_i2s *, int, int); + void (*set_rxchansel)(const struct sun4i_i2s *, int); }; struct sun4i_i2s { @@ -405,12 +409,8 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210); /* Configure the channels */ - regmap_update_bits(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG, - SUN4I_I2S_CHAN_SEL_MASK, - SUN4I_I2S_CHAN_SEL(channels)); - regmap_update_bits(i2s->regmap, SUN4I_I2S_RX_CHAN_SEL_REG, - SUN4I_I2S_CHAN_SEL_MASK, - SUN4I_I2S_CHAN_SEL(channels)); + i2s->variant->set_txchansel(i2s, 0, channels); + i2s->variant->set_rxchansel(i2s, channels); return 0; } @@ -430,12 +430,8 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210); /* Configure the channels */ - regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, - SUN4I_I2S_CHAN_SEL_MASK, - SUN4I_I2S_CHAN_SEL(channels)); - regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG, - SUN4I_I2S_CHAN_SEL_MASK, - SUN4I_I2S_CHAN_SEL(channels)); + i2s->variant->set_txchansel(i2s, 0, channels); + i2s->variant->set_rxchansel(i2s, channels); regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG, SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK, @@ -504,6 +500,40 @@ static void sun8i_i2s_set_rxchanen(const struct sun4i_i2s *i2s, int channel) SUN8I_I2S_TX_CHAN_EN(channel)); } +static void sun4i_i2s_set_txchansel(const struct sun4i_i2s *i2s, int output, + int channel) +{ + if (output == 0) + regmap_write(i2s->regmap, + SUN4I_I2S_TX_CHAN_SEL_REG, + SUN4I_I2S_CHAN_SEL(channel)); +} + +static void sun8i_i2s_set_txchansel(const struct sun4i_i2s *i2s, int output, + int channel) +{ + if (output >= 0 && output < 4) + regmap_update_bits(i2s->regmap, + SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4), + SUN8I_I2S_TX_CHAN_SEL_MASK, + SUN8I_I2S_TX_CHAN_SEL(channel)); +} + +static void sun4i_i2s_set_rxchansel(const struct sun4i_i2s *i2s, int channel) +{ + regmap_write(i2s->regmap, + SUN4I_I2S_RX_CHAN_SEL_REG, + SUN4I_I2S_CHAN_SEL(channel)); +} + +static void sun8i_i2s_set_rxchansel(const struct sun4i_i2s *i2s, int channel) +{ + regmap_update_bits(i2s->regmap, + SUN8I_I2S_RX_CHAN_SEL_REG, + SUN8I_I2S_TX_CHAN_SEL_MASK, + SUN8I_I2S_TX_CHAN_SEL(channel)); +} + static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -528,6 +558,10 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, return ret; } + /* Configure the channels */ + i2s->variant->set_txchansel(i2s, 0, channels); + i2s->variant->set_rxchansel(i2s, channels); + if (i2s->variant->set_txchanen) i2s->variant->set_txchanen(i2s, 0, channels); @@ -1118,6 +1152,8 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { .get_wss = sun4i_i2s_get_wss, .set_chan_cfg = sun4i_i2s_set_chan_cfg, .set_fmt = sun4i_i2s_set_soc_fmt, + .set_txchansel = sun4i_i2s_set_txchansel, + .set_rxchansel = sun4i_i2s_set_rxchansel, }; static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { @@ -1136,6 +1172,8 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { .get_wss = sun4i_i2s_get_wss, .set_chan_cfg = sun4i_i2s_set_chan_cfg, .set_fmt = sun4i_i2s_set_soc_fmt, + .set_txchansel = sun4i_i2s_set_txchansel, + .set_rxchansel = sun4i_i2s_set_rxchansel, }; /* @@ -1159,6 +1197,8 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { .get_wss = sun4i_i2s_get_wss, .set_chan_cfg = sun4i_i2s_set_chan_cfg, .set_fmt = sun4i_i2s_set_soc_fmt, + .set_txchansel = sun4i_i2s_set_txchansel, + .set_rxchansel = sun4i_i2s_set_rxchansel, }; static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { @@ -1181,6 +1221,8 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { .set_rxchanoffset = sun8i_i2s_set_rxchanoffset, .set_txchanen = sun8i_i2s_set_txchanen, .set_rxchanen = sun8i_i2s_set_rxchanen, + .set_txchansel = sun8i_i2s_set_txchansel, + .set_rxchansel = sun8i_i2s_set_rxchansel, }; static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { @@ -1199,6 +1241,8 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { .get_wss = sun4i_i2s_get_wss, .set_chan_cfg = sun4i_i2s_set_chan_cfg, .set_fmt = sun4i_i2s_set_soc_fmt, + .set_txchansel = sun4i_i2s_set_txchansel, + .set_rxchansel = sun4i_i2s_set_rxchansel, }; static int sun4i_i2s_init_regmap_fields(struct device *dev, -- 2.23.0 _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx https://mailman.alsa-project.org/mailman/listinfo/alsa-devel