[PATCH 1/9] ASoC: sun4i-i2s: Add quirk to handle fixed WSS

Vasily Khoruzhick anarsoul at gmail.com
Sun Dec 3 12:41:49 PST 2017


I2S for audio codec on sun50i-A64 always uses fixed word select size value,
no matter what is sample width. Add quirk to support that.

Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
---
 sound/soc/sunxi/sun4i-i2s.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 04f92583a969..54c16eb64713 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -132,6 +132,8 @@
  * @mclk_offset: Value by which mclkdiv needs to be adjusted.
  * @bclk_offset: Value by which bclkdiv needs to be adjusted.
  * @fmt_offset: Value by which wss and sr needs to be adjusted.
+ * @fixed_wss: Hardcoded 'word select size' value needs to be used
+ * @wss_value: Value to be used as WSS if fixed_wss is set
  * @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.
@@ -150,11 +152,13 @@ struct sun4i_i2s_quirks {
 	bool				has_chcfg;
 	bool				has_chsel_tx_chen;
 	bool				has_chsel_offset;
+	bool				fixed_wss;
 	unsigned int			reg_offset_txdata;	/* TX FIFO */
 	const struct regmap_config	*sun4i_i2s_regmap;
 	unsigned int			mclk_offset;
 	unsigned int			bclk_offset;
 	unsigned int			fmt_offset;
+	unsigned int			wss_value;
 
 	/* Register fields for i2s */
 	struct reg_field		field_clkdiv_mclk_en;
@@ -345,7 +349,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
 			       struct snd_soc_dai *dai)
 {
 	struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-	int sr, wss, channels;
+	int sr, wss, channels, pwidth;
 	u32 width;
 
 	channels = params_channels(params);
@@ -386,7 +390,8 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
 	}
 	i2s->playback_dma_data.addr_width = width;
 
-	switch (params_width(params)) {
+	pwidth = params_width(params);
+	switch (pwidth) {
 	case 16:
 		sr = 0;
 		wss = 0;
@@ -396,13 +401,30 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
+	if (i2s->variant->fixed_wss) {
+		wss = i2s->variant->wss_value;
+		switch (wss) {
+		case 0:
+			pwidth = 16;
+			break;
+		case 1:
+			pwidth = 20;
+			break;
+		case 2:
+			pwidth = 24;
+			break;
+		case 3:
+			pwidth = 32;
+			break;
+		}
+	}
+
 	regmap_field_write(i2s->field_fmt_wss,
 			   wss + i2s->variant->fmt_offset);
 	regmap_field_write(i2s->field_fmt_sr,
 			   sr + i2s->variant->fmt_offset);
 
-	return sun4i_i2s_set_clk_rate(i2s, params_rate(params),
-				      params_width(params));
+	return sun4i_i2s_set_clk_rate(i2s, params_rate(params), pwidth);
 }
 
 static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-- 
2.15.0




More information about the linux-arm-kernel mailing list