diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2015-11-16 01:01:29 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-11-16 08:18:28 -0500 |
commit | 35299f1779dbdcb61af4305904963b5bc9276eb9 (patch) | |
tree | 105ef88cc780786b639bc797dbe10db4361a52c0 | |
parent | a3af0c65836e714fa71dcaa0a81f6db83a212faa (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.c | 90 |
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 | ||
77 | struct 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 | |||
87 | struct ak4613_formats { | 77 | struct 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 | ||
87 | struct 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 } |
133 | static const struct ak4613_interface ak4613_iface[] = { | 133 | static 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 | ||
270 | static 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 | |||
270 | static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, | 292 | static 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); |