diff options
author | Liam Girdwood <lrg@ti.com> | 2011-07-24 15:59:43 -0400 |
---|---|---|
committer | Paolo Pisati <paolo.pisati@canonical.com> | 2012-08-17 04:18:25 -0400 |
commit | d4363e11fe690f28ef3043c3e913839a34d22030 (patch) | |
tree | b70e0d7e8f2c33639d04ff07d9e7133fb44f47ba | |
parent | 47ab6540593de31edf24ec22220b26e642651f02 (diff) |
Subject: [PATCH 071/104] ASoC: dsp - Add DSP support to core ASoC API/structures
Export inline DAI PCM operations to allow DSP core to individually call BE PCM
operations and ....
Allow machine drivers to specifify DSP FE and BE DAI links.
Add FE and BE state information to PCM rtd.
TODO: split out this into smaller patches.
Signed-off-by: Liam Girdwood <lrg@ti.com>
-rw-r--r-- | include/sound/soc-dai.h | 94 | ||||
-rw-r--r-- | include/sound/soc.h | 38 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 2 |
3 files changed, 133 insertions, 1 deletions
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 5ad5f3a50c6..f298f67b954 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h | |||
@@ -281,4 +281,98 @@ static inline void *snd_soc_dai_get_drvdata(struct snd_soc_dai *dai) | |||
281 | return dev_get_drvdata(dai->dev); | 281 | return dev_get_drvdata(dai->dev); |
282 | } | 282 | } |
283 | 283 | ||
284 | /* Backend DAI PCM ops */ | ||
285 | static inline int snd_soc_dai_startup(struct snd_pcm_substream *substream, | ||
286 | struct snd_soc_dai *dai) | ||
287 | { | ||
288 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
289 | int ret = 0; | ||
290 | |||
291 | mutex_lock(&rtd->pcm_mutex); | ||
292 | |||
293 | if (dai->driver->ops->startup) | ||
294 | ret = dai->driver->ops->startup(substream, dai); | ||
295 | |||
296 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
297 | dai->playback_active++; | ||
298 | else | ||
299 | dai->capture_active++; | ||
300 | |||
301 | dai->active++; | ||
302 | |||
303 | mutex_unlock(&rtd->pcm_mutex); | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | static inline void snd_soc_dai_shutdown(struct snd_pcm_substream *substream, | ||
308 | struct snd_soc_dai *dai) | ||
309 | { | ||
310 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
311 | |||
312 | mutex_lock(&rtd->pcm_mutex); | ||
313 | |||
314 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
315 | dai->playback_active--; | ||
316 | else | ||
317 | dai->capture_active--; | ||
318 | |||
319 | dai->active--; | ||
320 | |||
321 | if (dai->driver->ops->shutdown) | ||
322 | dai->driver->ops->shutdown(substream, dai); | ||
323 | mutex_unlock(&rtd->pcm_mutex); | ||
324 | } | ||
325 | |||
326 | static inline int snd_soc_dai_hw_params(struct snd_pcm_substream * substream, | ||
327 | struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai) | ||
328 | { | ||
329 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
330 | int ret = 0; | ||
331 | |||
332 | mutex_lock(&rtd->pcm_mutex); | ||
333 | |||
334 | if (dai->driver->ops->hw_params) | ||
335 | ret = dai->driver->ops->hw_params(substream, hw_params, dai); | ||
336 | |||
337 | mutex_unlock(&rtd->pcm_mutex); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static inline int snd_soc_dai_hw_free(struct snd_pcm_substream *substream, | ||
342 | struct snd_soc_dai *dai) | ||
343 | { | ||
344 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
345 | int ret = 0; | ||
346 | |||
347 | mutex_lock(&rtd->pcm_mutex); | ||
348 | |||
349 | if (dai->driver->ops->hw_free) | ||
350 | ret = dai->driver->ops->hw_free(substream, dai); | ||
351 | |||
352 | mutex_unlock(&rtd->pcm_mutex); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | static inline int snd_soc_dai_prepare(struct snd_pcm_substream *substream, | ||
357 | struct snd_soc_dai *dai) | ||
358 | { | ||
359 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
360 | int ret = 0; | ||
361 | |||
362 | mutex_lock(&rtd->pcm_mutex); | ||
363 | |||
364 | if (dai->driver->ops->prepare) | ||
365 | ret = dai->driver->ops->prepare(substream, dai); | ||
366 | |||
367 | mutex_unlock(&rtd->pcm_mutex); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | static inline int snd_soc_dai_trigger(struct snd_pcm_substream *substream, | ||
372 | int cmd, struct snd_soc_dai *dai) | ||
373 | { | ||
374 | if (dai->driver->ops->trigger) | ||
375 | return dai->driver->ops->trigger(substream, cmd, dai); | ||
376 | return 0; | ||
377 | } | ||
284 | #endif | 378 | #endif |
diff --git a/include/sound/soc.h b/include/sound/soc.h index e52a2fae146..1f661a760ae 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -247,6 +247,7 @@ struct snd_soc_jack; | |||
247 | struct snd_soc_jack_zone; | 247 | struct snd_soc_jack_zone; |
248 | struct snd_soc_jack_pin; | 248 | struct snd_soc_jack_pin; |
249 | struct snd_soc_cache_ops; | 249 | struct snd_soc_cache_ops; |
250 | struct snd_soc_dsp_link; | ||
250 | #include <sound/soc-dapm.h> | 251 | #include <sound/soc-dapm.h> |
251 | 252 | ||
252 | #ifdef CONFIG_GPIOLIB | 253 | #ifdef CONFIG_GPIOLIB |
@@ -317,6 +318,11 @@ int snd_soc_platform_read(struct snd_soc_platform *platform, | |||
317 | int snd_soc_platform_write(struct snd_soc_platform *platform, | 318 | int snd_soc_platform_write(struct snd_soc_platform *platform, |
318 | unsigned int reg, unsigned int val); | 319 | unsigned int reg, unsigned int val); |
319 | 320 | ||
321 | struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, | ||
322 | const char *dai_link, int stream); | ||
323 | struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, | ||
324 | const char *dai_link); | ||
325 | |||
320 | /* Utility functions to get clock rates from various things */ | 326 | /* Utility functions to get clock rates from various things */ |
321 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); | 327 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); |
322 | int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); | 328 | int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); |
@@ -701,15 +707,29 @@ struct snd_soc_dai_link { | |||
701 | const char *cpu_dai_name; | 707 | const char *cpu_dai_name; |
702 | const char *codec_dai_name; | 708 | const char *codec_dai_name; |
703 | 709 | ||
710 | struct snd_soc_dsp_link *dsp_link; | ||
711 | |||
704 | /* Keep DAI active over suspend */ | 712 | /* Keep DAI active over suspend */ |
705 | unsigned int ignore_suspend:1; | 713 | unsigned int ignore_suspend:1; |
706 | 714 | ||
707 | /* Symmetry requirements */ | 715 | /* Symmetry requirements */ |
708 | unsigned int symmetric_rates:1; | 716 | unsigned int symmetric_rates:1; |
717 | /* No PCM created for this DAI link */ | ||
718 | unsigned int no_pcm:1; | ||
719 | /* This DAI link can change CODEC and platform at runtime*/ | ||
720 | unsigned int dynamic:1; | ||
721 | /* This DAI link has no codec side driver*/ | ||
722 | unsigned int no_codec:1; | ||
723 | /* This DAI has a Backend ID */ | ||
724 | unsigned int be_id; | ||
709 | 725 | ||
710 | /* codec/machine specific init - e.g. add machine controls */ | 726 | /* codec/machine specific init - e.g. add machine controls */ |
711 | int (*init)(struct snd_soc_pcm_runtime *rtd); | 727 | int (*init)(struct snd_soc_pcm_runtime *rtd); |
712 | 728 | ||
729 | /* hw_params re-writing for BE and FE sync */ | ||
730 | int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, | ||
731 | struct snd_pcm_hw_params *params); | ||
732 | |||
713 | /* machine stream operations */ | 733 | /* machine stream operations */ |
714 | struct snd_soc_ops *ops; | 734 | struct snd_soc_ops *ops; |
715 | }; | 735 | }; |
@@ -749,6 +769,7 @@ struct snd_soc_card { | |||
749 | 769 | ||
750 | struct list_head list; | 770 | struct list_head list; |
751 | struct mutex mutex; | 771 | struct mutex mutex; |
772 | struct mutex dsp_mutex; | ||
752 | 773 | ||
753 | bool instantiated; | 774 | bool instantiated; |
754 | 775 | ||
@@ -826,6 +847,16 @@ struct snd_soc_card { | |||
826 | void *drvdata; | 847 | void *drvdata; |
827 | }; | 848 | }; |
828 | 849 | ||
850 | /* DSP runtime data */ | ||
851 | struct snd_soc_dsp_runtime { | ||
852 | struct list_head be_clients; | ||
853 | struct list_head fe_clients; | ||
854 | int users; | ||
855 | struct snd_pcm_runtime *runtime; | ||
856 | struct snd_pcm_hw_params params; | ||
857 | int runtime_update; | ||
858 | }; | ||
859 | |||
829 | /* SoC machine DAI configuration, glues a codec and cpu DAI together */ | 860 | /* SoC machine DAI configuration, glues a codec and cpu DAI together */ |
830 | struct snd_soc_pcm_runtime { | 861 | struct snd_soc_pcm_runtime { |
831 | struct device dev; | 862 | struct device dev; |
@@ -838,6 +869,9 @@ struct snd_soc_pcm_runtime { | |||
838 | unsigned int complete:1; | 869 | unsigned int complete:1; |
839 | unsigned int dev_registered:1; | 870 | unsigned int dev_registered:1; |
840 | 871 | ||
872 | /* DSP runtime data */ | ||
873 | struct snd_soc_dsp_runtime dsp[2]; | ||
874 | |||
841 | /* Symmetry data - only valid if symmetry is being enforced */ | 875 | /* Symmetry data - only valid if symmetry is being enforced */ |
842 | unsigned int rate; | 876 | unsigned int rate; |
843 | long pmdown_time; | 877 | long pmdown_time; |
@@ -850,6 +884,10 @@ struct snd_soc_pcm_runtime { | |||
850 | struct snd_soc_dai *cpu_dai; | 884 | struct snd_soc_dai *cpu_dai; |
851 | 885 | ||
852 | struct delayed_work delayed_work; | 886 | struct delayed_work delayed_work; |
887 | |||
888 | #ifdef CONFIG_DEBUG_FS | ||
889 | struct dentry *debugfs_dsp_root; | ||
890 | #endif | ||
853 | }; | 891 | }; |
854 | 892 | ||
855 | /* mixer control */ | 893 | /* mixer control */ |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 726d24076e8..b46b8178eb6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -782,7 +782,7 @@ find_codec: | |||
782 | 782 | ||
783 | /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/ | 783 | /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/ |
784 | list_for_each_entry(codec_dai, &dai_list, list) { | 784 | list_for_each_entry(codec_dai, &dai_list, list) { |
785 | if (codec->dev == codec_dai->dev && | 785 | if ((codec->dev == codec_dai->dev || codec->driver == &null_codec_drv) && |
786 | !strcmp(codec_dai->name, dai_link->codec_dai_name)) { | 786 | !strcmp(codec_dai->name, dai_link->codec_dai_name)) { |
787 | rtd->codec_dai = codec_dai; | 787 | rtd->codec_dai = codec_dai; |
788 | goto find_platform; | 788 | goto find_platform; |