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

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
...@@ -74,16 +74,6 @@ ...@@ -74,16 +74,6 @@
#define DFS_DOUBLE_SPEED (1 << 2) #define DFS_DOUBLE_SPEED (1 << 2)
#define DFS_QUAD_SPEED (2 << 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 { struct ak4613_formats {
unsigned int width; unsigned int width;
unsigned int fmt; unsigned int fmt;
...@@ -94,6 +84,16 @@ struct ak4613_interface { ...@@ -94,6 +84,16 @@ struct ak4613_interface {
struct ak4613_formats playback; 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 * Playback Volume
* *
...@@ -128,7 +128,7 @@ static const struct reg_default ak4613_reg[] = { ...@@ -128,7 +128,7 @@ static const struct reg_default ak4613_reg[] = {
{ 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0x00 }, { 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 } #define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt }
static const struct ak4613_interface ak4613_iface[] = { static const struct ak4613_interface ak4613_iface[] = {
/* capture */ /* playback */ /* capture */ /* playback */
...@@ -242,7 +242,7 @@ static void ak4613_dai_shutdown(struct snd_pcm_substream *substream, ...@@ -242,7 +242,7 @@ static void ak4613_dai_shutdown(struct snd_pcm_substream *substream,
priv->cnt = 0; priv->cnt = 0;
} }
if (!priv->cnt) if (!priv->cnt)
priv->fmt_ctrl = NO_FMT; priv->iface = NULL;
mutex_unlock(&priv->lock); mutex_unlock(&priv->lock);
} }
...@@ -267,13 +267,35 @@ static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ...@@ -267,13 +267,35 @@ static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0; 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, static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct ak4613_priv *priv = snd_soc_codec_get_drvdata(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; struct device *dev = codec->dev;
unsigned int width = params_width(params); unsigned int width = params_width(params);
unsigned int fmt = priv->fmt; unsigned int fmt = priv->fmt;
...@@ -307,33 +329,27 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -307,33 +329,27 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
* It doesn't support TDM at this point * It doesn't support TDM at this point
*/ */
fmt_ctrl = NO_FMT; fmt_ctrl = NO_FMT;
for (i = 0; i < ARRAY_SIZE(ak4613_iface); i++) { ret = -EINVAL;
fmts = (is_play) ? &ak4613_iface[i].playback : iface = NULL;
&ak4613_iface[i].capture;
if (fmts->fmt != fmt)
continue;
if (fmt == SND_SOC_DAIFMT_RIGHT_J) { mutex_lock(&priv->lock);
if (fmts->width != width) if (priv->iface) {
continue; if (ak4613_dai_fmt_matching(priv->iface, is_play, fmt, width))
iface = priv->iface;
} else { } 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; continue;
} iface = ak4613_iface + i;
fmt_ctrl = AUDIO_IFACE_IDX_TO_VAL(i);
break; break;
} }
}
ret = -EINVAL; if ((priv->iface == NULL) ||
if (fmt_ctrl == NO_FMT) (priv->iface == iface)) {
goto hw_params_end; priv->iface = iface;
mutex_lock(&priv->lock);
if ((priv->fmt_ctrl == NO_FMT) ||
(priv->fmt_ctrl == fmt_ctrl)) {
priv->fmt_ctrl = fmt_ctrl;
priv->cnt++; priv->cnt++;
ret = 0; ret = 0;
} }
...@@ -342,6 +358,8 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -342,6 +358,8 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
if (ret < 0) if (ret < 0)
goto hw_params_end; goto hw_params_end;
fmt_ctrl = AUDIO_IFACE_TO_VAL(iface);
snd_soc_update_bits(codec, CTRL1, FMT_MASK, fmt_ctrl); snd_soc_update_bits(codec, CTRL1, FMT_MASK, fmt_ctrl);
snd_soc_write(codec, CTRL2, ctrl2); snd_soc_write(codec, CTRL2, ctrl2);
...@@ -487,7 +505,7 @@ static int ak4613_i2c_probe(struct i2c_client *i2c, ...@@ -487,7 +505,7 @@ static int ak4613_i2c_probe(struct i2c_client *i2c,
ak4613_parse_of(priv, dev); ak4613_parse_of(priv, dev);
priv->fmt_ctrl = NO_FMT; priv->iface = NULL;
priv->cnt = 0; priv->cnt = 0;
mutex_init(&priv->lock); mutex_init(&priv->lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment