[alsa-devel] [RFC don't apply] ASoC: Add support for optional auxiliary dailess codecs
Liam Girdwood
lrg at slimlogic.co.uk
Thu Nov 25 20:18:23 CET 2010
Hi Jarkko,
Sorry, didn't get a chance to discuss on IRC but I have some comments
below :-
On Thu, 2010-11-25 at 17:47 +0200, Jarkko Nikula wrote:
> This makes possible to register auxiliary dailess codecs in a machine
> driver. Term dailess is used here for amplifiers and codecs without DAI or
> DAI being unused.
>
> Dailess auxiliary codecs are kept in struct snd_soc_aux_dev and those codecs
> are probed after initializing the DAI links. There are no major differences
> between DAI link codecs and dailess codecs in ASoC core point of view. DAPM
> handles them equally and sysfs and debugfs directories for dailess codecs
> are similar except the pmdown_time node is not created.
>
> Only suspend and resume functions are modified to traverse all probed codecs
> instead of DAI link codecs.
>
> Example below shows a dailess codec registration.
>
> struct snd_soc_aux_dev foo_aux_dev[] = {
> {
> .name = "Amp",
> .codec_name = "codec.2",
> .init = foo_init2,
> },
> };
>
> static struct snd_soc_card card = {
> ...
> .aux_dev = foo_aux_dev,
> .num_aux_devs = ARRAY_SIZE(foo_aux_dev),
> };
>
> Signed-off-by: Jarkko Nikula <jhnikula at gmail.com>
> ---
> Idea sharing version, not to be applied. Needs at least cross-device DAPM
> to be usuful and e.g. soc_probe_dai_link and soc_probe_aux_dev share a lot
> of same code.
>
> I'm not entirely sure of reusing struct snd_soc_pcm_runtime but having some
> common struct on top of it for registering the sysfs nodes and passing to
> snd_soc_dapm_sys_add didn't sound clear either.
> Anyway suspend/resume is working with this version and doesn't need any other
> modifications to soc_suspend/soc_resume than traversing through the registered
> codecs instead of doing bunch of rtd->dailess etc hacks there.
> ---
> include/sound/soc.h | 17 ++++++
> sound/soc/soc-core.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 166 insertions(+), 6 deletions(-)
>
> diff --git a/include/sound/soc.h b/include/sound/soc.h
> index 346c59e..c62225e 100644
> --- a/include/sound/soc.h
> +++ b/include/sound/soc.h
> @@ -583,6 +583,14 @@ struct snd_soc_prefix_map {
> const char *name_prefix;
> };
>
> +struct snd_soc_aux_dev {
> + const char *name; /* Codec name */
> + const char *codec_name; /* for multi-codec */
> +
> + /* codec/machine specific init - e.g. add machine controls */
> + int (*init)(struct snd_soc_dapm_context *dapm);
> +};
> +
> /* SoC card */
> struct snd_soc_card {
> const char *name;
> @@ -624,6 +632,15 @@ struct snd_soc_card {
> struct snd_soc_prefix_map *prefix_map;
> int num_prefixes;
>
> + /*
> + * optional auxiliary devices such as amplifiers or codecs with DAI
> + * link unused
> + */
> + struct snd_soc_aux_dev *aux_dev;
> + int num_aux_devs;
> + struct snd_soc_pcm_runtime *rtd_aux;
> + int num_aux_rtd;
> +
Could we not just make this a new component type and have a list of aux
devices ?
>
> /* lists of probed devices belonging to this card */
> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
> index b0e1aea..d7fc3a6 100644
> --- a/sound/soc/soc-core.c
> +++ b/sound/soc/soc-core.c
> @@ -986,6 +986,7 @@ static int soc_suspend(struct device *dev)
> {
> struct platform_device *pdev = to_platform_device(dev);
> struct snd_soc_card *card = platform_get_drvdata(pdev);
> + struct snd_soc_codec *codec;
> int i;
>
> /* If the initialization of this soc device failed, there is no codec
> @@ -1064,8 +1065,7 @@ static int soc_suspend(struct device *dev)
> }
>
> /* suspend all CODECs */
> - for (i = 0; i < card->num_rtd; i++) {
> - struct snd_soc_codec *codec = card->rtd[i].codec;
> + list_for_each_entry(codec, &card->codec_dev_list, card_list) {
> /* If there are paths active then the CODEC will be held with
> * bias _ON and should not be suspended. */
> if (!codec->suspended && codec->driver->suspend) {
> @@ -1106,6 +1106,7 @@ static void soc_resume_deferred(struct work_struct *work)
> struct snd_soc_card *card =
> container_of(work, struct snd_soc_card, deferred_resume_work);
> struct platform_device *pdev = to_platform_device(card->dev);
> + struct snd_soc_codec *codec;
> int i;
>
> /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
> @@ -1131,8 +1132,7 @@ static void soc_resume_deferred(struct work_struct *work)
> cpu_dai->driver->resume(cpu_dai);
> }
>
> - for (i = 0; i < card->num_rtd; i++) {
> - struct snd_soc_codec *codec = card->rtd[i].codec;
> + list_for_each_entry(codec, &card->codec_dev_list, card_list) {
> /* If the CODEC was idle over suspend then it will have been
> * left with bias OFF or STANDBY and suspended so we must now
> * resume. Otherwise the suspend was suppressed.
> @@ -1604,6 +1604,130 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
> }
> #endif
>
> +static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
> +{
> + struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
> + struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num];
> + struct snd_soc_codec *codec;
> + const char *temp;
> + int ret = 0;
> +
> + /* find CODEC from registered CODECs*/
> + list_for_each_entry(codec, &codec_list, list) {
> + if (!strcmp(codec->name, aux_dev->codec_name)) {
> + if (codec->probed) {
> + dev_err(codec->dev,
> + "asoc: codec already probed");
> + ret = -EBUSY;
> + goto out;
> + }
> + break;
> + }
> + }
> +
Why do aux devices need to be coupled with CODECs here ?
Thanks
Liam
--
Freelance Developer, SlimLogic Ltd
ASoC and Voltage Regulator Maintainer.
http://www.slimlogic.co.uk
More information about the Alsa-devel
mailing list