aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2015-11-16 01:01:29 -0500
committerMark Brown <broonie@kernel.org>2015-11-16 08:18:28 -0500
commit35299f1779dbdcb61af4305904963b5bc9276eb9 (patch)
tree105ef88cc780786b639bc797dbe10db4361a52c0
parenta3af0c65836e714fa71dcaa0a81f6db83a212faa (diff)
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: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/ak4613.c90
1 files changed, 54 insertions, 36 deletions
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index 394c10ff049e..dab127603ff6 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -74,16 +74,6 @@
74#define DFS_DOUBLE_SPEED (1 << 2) 74#define DFS_DOUBLE_SPEED (1 << 2)
75#define DFS_QUAD_SPEED (2 << 2) 75#define DFS_QUAD_SPEED (2 << 2)
76 76
77struct ak4613_priv {
78 struct mutex lock;
79
80 unsigned int fmt;
81 u8 fmt_ctrl;
82 u8 oc;
83 u8 ic;
84 int cnt;
85};
86
87struct ak4613_formats { 77struct ak4613_formats {
88 unsigned int width; 78 unsigned int width;
89 unsigned int fmt; 79 unsigned int fmt;
@@ -94,6 +84,16 @@ struct ak4613_interface {
94 struct ak4613_formats playback; 84 struct ak4613_formats playback;
95}; 85};
96 86
87struct ak4613_priv {
88 struct mutex lock;
89 const struct ak4613_interface *iface;
90
91 unsigned int fmt;
92 u8 oc;
93 u8 ic;
94 int cnt;
95};
96
97/* 97/*
98 * Playback Volume 98 * Playback Volume
99 * 99 *
@@ -128,7 +128,7 @@ static const struct reg_default ak4613_reg[] = {
128 { 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0x00 }, 128 { 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0x00 },
129}; 129};
130 130
131#define AUDIO_IFACE_IDX_TO_VAL(i) (i << 3) 131#define AUDIO_IFACE_TO_VAL(fmts) ((fmts - ak4613_iface) << 3)
132#define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt } 132#define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt }
133static const struct ak4613_interface ak4613_iface[] = { 133static const struct ak4613_interface ak4613_iface[] = {
134 /* capture */ /* playback */ 134 /* capture */ /* playback */
@@ -242,7 +242,7 @@ static void ak4613_dai_shutdown(struct snd_pcm_substream *substream,
242 priv->cnt = 0; 242 priv->cnt = 0;
243 } 243 }
244 if (!priv->cnt) 244 if (!priv->cnt)
245 priv->fmt_ctrl = NO_FMT; 245 priv->iface = NULL;
246 mutex_unlock(&priv->lock); 246 mutex_unlock(&priv->lock);
247} 247}
248 248
@@ -267,13 +267,35 @@ static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
267 return 0; 267 return 0;
268} 268}
269 269
270static bool ak4613_dai_fmt_matching(const struct ak4613_interface *iface,
271 int is_play,
272 unsigned int fmt, unsigned int width)
273{
274 const struct ak4613_formats *fmts;
275
276 fmts = (is_play) ? &iface->playback : &iface->capture;
277
278 if (fmts->fmt != fmt)
279 return false;
280
281 if (fmt == SND_SOC_DAIFMT_RIGHT_J) {
282 if (fmts->width != width)
283 return false;
284 } else {
285 if (fmts->width < width)
286 return false;
287 }
288
289 return true;
290}
291
270static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, 292static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
271 struct snd_pcm_hw_params *params, 293 struct snd_pcm_hw_params *params,
272 struct snd_soc_dai *dai) 294 struct snd_soc_dai *dai)
273{ 295{
274 struct snd_soc_codec *codec = dai->codec; 296 struct snd_soc_codec *codec = dai->codec;
275 struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); 297 struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec);
276 const struct ak4613_formats *fmts; 298 const struct ak4613_interface *iface;
277 struct device *dev = codec->dev; 299 struct device *dev = codec->dev;
278 unsigned int width = params_width(params); 300 unsigned int width = params_width(params);
279 unsigned int fmt = priv->fmt; 301 unsigned int fmt = priv->fmt;
@@ -307,33 +329,27 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
307 * It doesn't support TDM at this point 329 * It doesn't support TDM at this point
308 */ 330 */
309 fmt_ctrl = NO_FMT; 331 fmt_ctrl = NO_FMT;
310 for (i = 0; i < ARRAY_SIZE(ak4613_iface); i++) { 332 ret = -EINVAL;
311 fmts = (is_play) ? &ak4613_iface[i].playback : 333 iface = NULL;
312 &ak4613_iface[i].capture;
313
314 if (fmts->fmt != fmt)
315 continue;
316 334
317 if (fmt == SND_SOC_DAIFMT_RIGHT_J) { 335 mutex_lock(&priv->lock);
318 if (fmts->width != width) 336 if (priv->iface) {
319 continue; 337 if (ak4613_dai_fmt_matching(priv->iface, is_play, fmt, width))
320 } else { 338 iface = priv->iface;
321 if (fmts->width < width) 339 } else {
340 for (i = ARRAY_SIZE(ak4613_iface); i >= 0; i--) {
341 if (!ak4613_dai_fmt_matching(ak4613_iface + i,
342 is_play,
343 fmt, width))
322 continue; 344 continue;
345 iface = ak4613_iface + i;
346 break;
323 } 347 }
324
325 fmt_ctrl = AUDIO_IFACE_IDX_TO_VAL(i);
326 break;
327 } 348 }
328 349
329 ret = -EINVAL; 350 if ((priv->iface == NULL) ||
330 if (fmt_ctrl == NO_FMT) 351 (priv->iface == iface)) {
331 goto hw_params_end; 352 priv->iface = iface;
332
333 mutex_lock(&priv->lock);
334 if ((priv->fmt_ctrl == NO_FMT) ||
335 (priv->fmt_ctrl == fmt_ctrl)) {
336 priv->fmt_ctrl = fmt_ctrl;
337 priv->cnt++; 353 priv->cnt++;
338 ret = 0; 354 ret = 0;
339 } 355 }
@@ -342,6 +358,8 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream,
342 if (ret < 0) 358 if (ret < 0)
343 goto hw_params_end; 359 goto hw_params_end;
344 360
361 fmt_ctrl = AUDIO_IFACE_TO_VAL(iface);
362
345 snd_soc_update_bits(codec, CTRL1, FMT_MASK, fmt_ctrl); 363 snd_soc_update_bits(codec, CTRL1, FMT_MASK, fmt_ctrl);
346 snd_soc_write(codec, CTRL2, ctrl2); 364 snd_soc_write(codec, CTRL2, ctrl2);
347 365
@@ -487,7 +505,7 @@ static int ak4613_i2c_probe(struct i2c_client *i2c,
487 505
488 ak4613_parse_of(priv, dev); 506 ak4613_parse_of(priv, dev);
489 507
490 priv->fmt_ctrl = NO_FMT; 508 priv->iface = NULL;
491 priv->cnt = 0; 509 priv->cnt = 0;
492 510
493 mutex_init(&priv->lock); 511 mutex_init(&priv->lock);