[alsa-devel] [PATCH] ASoC: ak4613: tidyup CTRL1 value selection method

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Mon Nov 16 07:01:29 CET 2015


From: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>

Current CTRL1 selection method didn't care about simultaneous
playback / capture. This patch tidyup it.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
---
 sound/soc/codecs/ak4613.c | 90 ++++++++++++++++++++++++++++-------------------
 1 file changed, 54 insertions(+), 36 deletions(-)

diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index 394c10f..dab1276 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -74,16 +74,6 @@
 #define DFS_DOUBLE_SPEED	(1 << 2)
 #define DFS_QUAD_SPEED		(2 << 2)
 
-struct ak4613_priv {
-	struct mutex lock;
-
-	unsigned int fmt;
-	u8 fmt_ctrl;
-	u8 oc;
-	u8 ic;
-	int cnt;
-};
-
 struct ak4613_formats {
 	unsigned int width;
 	unsigned int fmt;
@@ -94,6 +84,16 @@ struct ak4613_interface {
 	struct ak4613_formats playback;
 };
 
+struct ak4613_priv {
+	struct mutex lock;
+	const struct ak4613_interface *iface;
+
+	unsigned int fmt;
+	u8 oc;
+	u8 ic;
+	int cnt;
+};
+
 /*
  * Playback Volume
  *
@@ -128,7 +128,7 @@ static const struct reg_default ak4613_reg[] = {
 	{ 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0x00 },
 };
 
-#define AUDIO_IFACE_IDX_TO_VAL(i) (i << 3)
+#define AUDIO_IFACE_TO_VAL(fmts) ((fmts - ak4613_iface) << 3)
 #define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt }
 static const struct ak4613_interface ak4613_iface[] = {
 	/* capture */				/* playback */
@@ -242,7 +242,7 @@ static void ak4613_dai_shutdown(struct snd_pcm_substream *substream,
 		priv->cnt = 0;
 	}
 	if (!priv->cnt)
-		priv->fmt_ctrl = NO_FMT;
+		priv->iface = NULL;
 	mutex_unlock(&priv->lock);
 }
 
@@ -267,13 +267,35 @@ static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	return 0;
 }
 
+static bool ak4613_dai_fmt_matching(const struct ak4613_interface *iface,
+				    int is_play,
+				    unsigned int fmt, unsigned int width)
+{
+	const struct ak4613_formats *fmts;
+
+	fmts = (is_play) ? &iface->playback : &iface->capture;
+
+	if (fmts->fmt != fmt)
+		return false;
+
+	if (fmt == SND_SOC_DAIFMT_RIGHT_J) {
+		if (fmts->width != width)
+			return false;
+	} else {
+		if (fmts->width < width)
+			return false;
+	}
+
+	return true;
+}
+
 static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params,
 				struct snd_soc_dai *dai)
 {
 	struct snd_soc_codec *codec = dai->codec;
 	struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec);
-	const struct ak4613_formats *fmts;
+	const struct ak4613_interface *iface;
 	struct device *dev = codec->dev;
 	unsigned int width = params_width(params);
 	unsigned int fmt = priv->fmt;
@@ -307,33 +329,27 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
 	 * It doesn't support TDM at this point
 	 */
 	fmt_ctrl = NO_FMT;
-	for (i = 0; i < ARRAY_SIZE(ak4613_iface); i++) {
-		fmts = (is_play) ?	&ak4613_iface[i].playback :
-					&ak4613_iface[i].capture;
-
-		if (fmts->fmt != fmt)
-			continue;
+	ret = -EINVAL;
+	iface = NULL;
 
-		if (fmt == SND_SOC_DAIFMT_RIGHT_J) {
-			if (fmts->width != width)
-				continue;
-		} else {
-			if (fmts->width < width)
+	mutex_lock(&priv->lock);
+	if (priv->iface) {
+		if (ak4613_dai_fmt_matching(priv->iface, is_play, fmt, width))
+			iface = priv->iface;
+	} else {
+		for (i = ARRAY_SIZE(ak4613_iface); i >= 0; i--) {
+			if (!ak4613_dai_fmt_matching(ak4613_iface + i,
+						     is_play,
+						     fmt, width))
 				continue;
+			iface = ak4613_iface + i;
+			break;
 		}
-
-		fmt_ctrl = AUDIO_IFACE_IDX_TO_VAL(i);
-		break;
 	}
 
-	ret = -EINVAL;
-	if (fmt_ctrl == NO_FMT)
-		goto hw_params_end;
-
-	mutex_lock(&priv->lock);
-	if ((priv->fmt_ctrl == NO_FMT) ||
-	    (priv->fmt_ctrl == fmt_ctrl)) {
-		priv->fmt_ctrl = fmt_ctrl;
+	if ((priv->iface == NULL) ||
+	    (priv->iface == iface)) {
+		priv->iface = iface;
 		priv->cnt++;
 		ret = 0;
 	}
@@ -342,6 +358,8 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
 	if (ret < 0)
 		goto hw_params_end;
 
+	fmt_ctrl = AUDIO_IFACE_TO_VAL(iface);
+
 	snd_soc_update_bits(codec, CTRL1, FMT_MASK, fmt_ctrl);
 	snd_soc_write(codec, CTRL2, ctrl2);
 
@@ -487,7 +505,7 @@ static int ak4613_i2c_probe(struct i2c_client *i2c,
 
 	ak4613_parse_of(priv, dev);
 
-	priv->fmt_ctrl		= NO_FMT;
+	priv->iface		= NULL;
 	priv->cnt		= 0;
 
 	mutex_init(&priv->lock);
-- 
1.9.1



More information about the Alsa-devel mailing list