aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r--sound/soc/soc-core.c165
1 files changed, 104 insertions, 61 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 1cd149b9ce69..3f44150d8e30 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -113,6 +113,35 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
113} 113}
114#endif 114#endif
115 115
116static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
117{
118 struct snd_soc_pcm_runtime *rtd = substream->private_data;
119 struct snd_soc_device *socdev = rtd->socdev;
120 struct snd_soc_card *card = socdev->card;
121 struct snd_soc_dai_link *machine = rtd->dai;
122 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
123 struct snd_soc_dai *codec_dai = machine->codec_dai;
124 int ret;
125
126 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
127 machine->symmetric_rates) {
128 dev_dbg(card->dev, "Symmetry forces %dHz rate\n",
129 machine->rate);
130
131 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
132 SNDRV_PCM_HW_PARAM_RATE,
133 machine->rate,
134 machine->rate);
135 if (ret < 0) {
136 dev_err(card->dev,
137 "Unable to apply rate symmetry constraint: %d\n", ret);
138 return ret;
139 }
140 }
141
142 return 0;
143}
144
116/* 145/*
117 * Called by ALSA when a PCM substream is opened, the runtime->hw record is 146 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
118 * then initialized and any private data can be allocated. This also calls 147 * then initialized and any private data can be allocated. This also calls
@@ -221,6 +250,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
221 goto machine_err; 250 goto machine_err;
222 } 251 }
223 252
253 /* Symmetry only applies if we've already got an active stream. */
254 if (cpu_dai->active || codec_dai->active) {
255 ret = soc_pcm_apply_symmetry(substream);
256 if (ret != 0)
257 goto machine_err;
258 }
259
224 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); 260 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
225 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); 261 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
226 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, 262 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
@@ -263,7 +299,6 @@ static void close_delayed_work(struct work_struct *work)
263{ 299{
264 struct snd_soc_card *card = container_of(work, struct snd_soc_card, 300 struct snd_soc_card *card = container_of(work, struct snd_soc_card,
265 delayed_work.work); 301 delayed_work.work);
266 struct snd_soc_device *socdev = card->socdev;
267 struct snd_soc_codec *codec = card->codec; 302 struct snd_soc_codec *codec = card->codec;
268 struct snd_soc_dai *codec_dai; 303 struct snd_soc_dai *codec_dai;
269 int i; 304 int i;
@@ -279,27 +314,10 @@ static void close_delayed_work(struct work_struct *work)
279 314
280 /* are we waiting on this codec DAI stream */ 315 /* are we waiting on this codec DAI stream */
281 if (codec_dai->pop_wait == 1) { 316 if (codec_dai->pop_wait == 1) {
282
283 /* Reduce power if no longer active */
284 if (codec->active == 0) {
285 pr_debug("pop wq D1 %s %s\n", codec->name,
286 codec_dai->playback.stream_name);
287 snd_soc_dapm_set_bias_level(socdev,
288 SND_SOC_BIAS_PREPARE);
289 }
290
291 codec_dai->pop_wait = 0; 317 codec_dai->pop_wait = 0;
292 snd_soc_dapm_stream_event(codec, 318 snd_soc_dapm_stream_event(codec,
293 codec_dai->playback.stream_name, 319 codec_dai->playback.stream_name,
294 SND_SOC_DAPM_STREAM_STOP); 320 SND_SOC_DAPM_STREAM_STOP);
295
296 /* Fall into standby if no longer active */
297 if (codec->active == 0) {
298 pr_debug("pop wq D3 %s %s\n", codec->name,
299 codec_dai->playback.stream_name);
300 snd_soc_dapm_set_bias_level(socdev,
301 SND_SOC_BIAS_STANDBY);
302 }
303 } 321 }
304 } 322 }
305 mutex_unlock(&pcm_mutex); 323 mutex_unlock(&pcm_mutex);
@@ -363,10 +381,6 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
363 snd_soc_dapm_stream_event(codec, 381 snd_soc_dapm_stream_event(codec,
364 codec_dai->capture.stream_name, 382 codec_dai->capture.stream_name,
365 SND_SOC_DAPM_STREAM_STOP); 383 SND_SOC_DAPM_STREAM_STOP);
366
367 if (codec->active == 0 && codec_dai->pop_wait == 0)
368 snd_soc_dapm_set_bias_level(socdev,
369 SND_SOC_BIAS_STANDBY);
370 } 384 }
371 385
372 mutex_unlock(&pcm_mutex); 386 mutex_unlock(&pcm_mutex);
@@ -431,36 +445,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
431 cancel_delayed_work(&card->delayed_work); 445 cancel_delayed_work(&card->delayed_work);
432 } 446 }
433 447
434 /* do we need to power up codec */ 448 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
435 if (codec->bias_level != SND_SOC_BIAS_ON) { 449 snd_soc_dapm_stream_event(codec,
436 snd_soc_dapm_set_bias_level(socdev, 450 codec_dai->playback.stream_name,
437 SND_SOC_BIAS_PREPARE); 451 SND_SOC_DAPM_STREAM_START);
438 452 else
439 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 453 snd_soc_dapm_stream_event(codec,
440 snd_soc_dapm_stream_event(codec, 454 codec_dai->capture.stream_name,
441 codec_dai->playback.stream_name, 455 SND_SOC_DAPM_STREAM_START);
442 SND_SOC_DAPM_STREAM_START);
443 else
444 snd_soc_dapm_stream_event(codec,
445 codec_dai->capture.stream_name,
446 SND_SOC_DAPM_STREAM_START);
447
448 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
449 snd_soc_dai_digital_mute(codec_dai, 0);
450
451 } else {
452 /* codec already powered - power on widgets */
453 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
454 snd_soc_dapm_stream_event(codec,
455 codec_dai->playback.stream_name,
456 SND_SOC_DAPM_STREAM_START);
457 else
458 snd_soc_dapm_stream_event(codec,
459 codec_dai->capture.stream_name,
460 SND_SOC_DAPM_STREAM_START);
461 456
462 snd_soc_dai_digital_mute(codec_dai, 0); 457 snd_soc_dai_digital_mute(codec_dai, 0);
463 }
464 458
465out: 459out:
466 mutex_unlock(&pcm_mutex); 460 mutex_unlock(&pcm_mutex);
@@ -521,6 +515,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
521 } 515 }
522 } 516 }
523 517
518 machine->rate = params_rate(params);
519
524out: 520out:
525 mutex_unlock(&pcm_mutex); 521 mutex_unlock(&pcm_mutex);
526 return ret; 522 return ret;
@@ -632,6 +628,12 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
632 struct snd_soc_codec *codec = card->codec; 628 struct snd_soc_codec *codec = card->codec;
633 int i; 629 int i;
634 630
631 /* If the initialization of this soc device failed, there is no codec
632 * associated with it. Just bail out in this case.
633 */
634 if (!codec)
635 return 0;
636
635 /* Due to the resume being scheduled into a workqueue we could 637 /* Due to the resume being scheduled into a workqueue we could
636 * suspend before that's finished - wait for it to complete. 638 * suspend before that's finished - wait for it to complete.
637 */ 639 */
@@ -1334,6 +1336,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1334 return ret; 1336 return ret;
1335 } 1337 }
1336 1338
1339 codec->socdev = socdev;
1337 codec->card->dev = socdev->dev; 1340 codec->card->dev = socdev->dev;
1338 codec->card->private_data = codec; 1341 codec->card->private_data = codec;
1339 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); 1342 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
@@ -1744,7 +1747,7 @@ int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
1744{ 1747{
1745 int max = kcontrol->private_value; 1748 int max = kcontrol->private_value;
1746 1749
1747 if (max == 1) 1750 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
1748 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1751 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1749 else 1752 else
1750 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1753 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1774,7 +1777,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1774 unsigned int shift = mc->shift; 1777 unsigned int shift = mc->shift;
1775 unsigned int rshift = mc->rshift; 1778 unsigned int rshift = mc->rshift;
1776 1779
1777 if (max == 1) 1780 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
1778 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1781 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1779 else 1782 else
1780 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1783 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1881,7 +1884,7 @@ int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
1881 (struct soc_mixer_control *)kcontrol->private_value; 1884 (struct soc_mixer_control *)kcontrol->private_value;
1882 int max = mc->max; 1885 int max = mc->max;
1883 1886
1884 if (max == 1) 1887 if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
1885 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1888 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1886 else 1889 else
1887 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1890 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -2065,7 +2068,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2065int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 2068int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
2066 unsigned int freq, int dir) 2069 unsigned int freq, int dir)
2067{ 2070{
2068 if (dai->ops->set_sysclk) 2071 if (dai->ops && dai->ops->set_sysclk)
2069 return dai->ops->set_sysclk(dai, clk_id, freq, dir); 2072 return dai->ops->set_sysclk(dai, clk_id, freq, dir);
2070 else 2073 else
2071 return -EINVAL; 2074 return -EINVAL;
@@ -2085,7 +2088,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
2085int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, 2088int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
2086 int div_id, int div) 2089 int div_id, int div)
2087{ 2090{
2088 if (dai->ops->set_clkdiv) 2091 if (dai->ops && dai->ops->set_clkdiv)
2089 return dai->ops->set_clkdiv(dai, div_id, div); 2092 return dai->ops->set_clkdiv(dai, div_id, div);
2090 else 2093 else
2091 return -EINVAL; 2094 return -EINVAL;
@@ -2104,7 +2107,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
2104int snd_soc_dai_set_pll(struct snd_soc_dai *dai, 2107int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
2105 int pll_id, unsigned int freq_in, unsigned int freq_out) 2108 int pll_id, unsigned int freq_in, unsigned int freq_out)
2106{ 2109{
2107 if (dai->ops->set_pll) 2110 if (dai->ops && dai->ops->set_pll)
2108 return dai->ops->set_pll(dai, pll_id, freq_in, freq_out); 2111 return dai->ops->set_pll(dai, pll_id, freq_in, freq_out);
2109 else 2112 else
2110 return -EINVAL; 2113 return -EINVAL;
@@ -2120,7 +2123,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
2120 */ 2123 */
2121int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 2124int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2122{ 2125{
2123 if (dai->ops->set_fmt) 2126 if (dai->ops && dai->ops->set_fmt)
2124 return dai->ops->set_fmt(dai, fmt); 2127 return dai->ops->set_fmt(dai, fmt);
2125 else 2128 else
2126 return -EINVAL; 2129 return -EINVAL;
@@ -2139,7 +2142,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
2139int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 2142int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
2140 unsigned int mask, int slots) 2143 unsigned int mask, int slots)
2141{ 2144{
2142 if (dai->ops->set_sysclk) 2145 if (dai->ops && dai->ops->set_tdm_slot)
2143 return dai->ops->set_tdm_slot(dai, mask, slots); 2146 return dai->ops->set_tdm_slot(dai, mask, slots);
2144 else 2147 else
2145 return -EINVAL; 2148 return -EINVAL;
@@ -2155,7 +2158,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
2155 */ 2158 */
2156int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 2159int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
2157{ 2160{
2158 if (dai->ops->set_sysclk) 2161 if (dai->ops && dai->ops->set_tristate)
2159 return dai->ops->set_tristate(dai, tristate); 2162 return dai->ops->set_tristate(dai, tristate);
2160 else 2163 else
2161 return -EINVAL; 2164 return -EINVAL;
@@ -2171,7 +2174,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
2171 */ 2174 */
2172int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) 2175int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
2173{ 2176{
2174 if (dai->ops->digital_mute) 2177 if (dai->ops && dai->ops->digital_mute)
2175 return dai->ops->digital_mute(dai, mute); 2178 return dai->ops->digital_mute(dai, mute);
2176 else 2179 else
2177 return -EINVAL; 2180 return -EINVAL;
@@ -2352,6 +2355,39 @@ void snd_soc_unregister_platform(struct snd_soc_platform *platform)
2352} 2355}
2353EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); 2356EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
2354 2357
2358static u64 codec_format_map[] = {
2359 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE,
2360 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE,
2361 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE,
2362 SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE,
2363 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
2364 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE,
2365 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
2366 SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
2367 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE,
2368 SNDRV_PCM_FMTBIT_U20_3LE | SNDRV_PCM_FMTBIT_U20_3BE,
2369 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE,
2370 SNDRV_PCM_FMTBIT_U18_3LE | SNDRV_PCM_FMTBIT_U18_3BE,
2371 SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE,
2372 SNDRV_PCM_FMTBIT_FLOAT64_LE | SNDRV_PCM_FMTBIT_FLOAT64_BE,
2373 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
2374 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE,
2375};
2376
2377/* Fix up the DAI formats for endianness: codecs don't actually see
2378 * the endianness of the data but we're using the CPU format
2379 * definitions which do need to include endianness so we ensure that
2380 * codec DAIs always have both big and little endian variants set.
2381 */
2382static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
2383{
2384 int i;
2385
2386 for (i = 0; i < ARRAY_SIZE(codec_format_map); i++)
2387 if (stream->formats & codec_format_map[i])
2388 stream->formats |= codec_format_map[i];
2389}
2390
2355/** 2391/**
2356 * snd_soc_register_codec - Register a codec with the ASoC core 2392 * snd_soc_register_codec - Register a codec with the ASoC core
2357 * 2393 *
@@ -2359,6 +2395,8 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
2359 */ 2395 */
2360int snd_soc_register_codec(struct snd_soc_codec *codec) 2396int snd_soc_register_codec(struct snd_soc_codec *codec)
2361{ 2397{
2398 int i;
2399
2362 if (!codec->name) 2400 if (!codec->name)
2363 return -EINVAL; 2401 return -EINVAL;
2364 2402
@@ -2368,6 +2406,11 @@ int snd_soc_register_codec(struct snd_soc_codec *codec)
2368 2406
2369 INIT_LIST_HEAD(&codec->list); 2407 INIT_LIST_HEAD(&codec->list);
2370 2408
2409 for (i = 0; i < codec->num_dai; i++) {
2410 fixup_codec_formats(&codec->dai[i].playback);
2411 fixup_codec_formats(&codec->dai[i].capture);
2412 }
2413
2371 mutex_lock(&client_mutex); 2414 mutex_lock(&client_mutex);
2372 list_add(&codec->list, &codec_list); 2415 list_add(&codec->list, &codec_list);
2373 snd_soc_instantiate_cards(); 2416 snd_soc_instantiate_cards();