Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35299f17 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

ASoC: ak4613: tidyup CTRL1 value selection method



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

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent a3af0c65
Loading
Loading
Loading
Loading
+54 −36
Original line number Diff line number Diff line
@@ -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;
	mutex_lock(&priv->lock);
	if (priv->iface) {
		if (ak4613_dai_fmt_matching(priv->iface, is_play, fmt, width))
			iface = priv->iface;
	} else {
			if (fmts->width < width)
		for (i = ARRAY_SIZE(ak4613_iface); i >= 0; i--) {
			if (!ak4613_dai_fmt_matching(ak4613_iface + i,
						     is_play,
						     fmt, width))
				continue;
		}

		fmt_ctrl = AUDIO_IFACE_IDX_TO_VAL(i);
			iface = ak4613_iface + 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);