[alsa-devel] [PATCH v3 0/3][RFC] ASoC: Component has suspend/resume support
Hi Mark, Lars-Peter
These patches are v3+RFC of Component level suspend/resume support.
I'm waiting Vinod's cleanup patch which will remove "codec_dev_list" from Intel drivers. But until then, I would like to get review about v3 patch. This v3 patch-set is still modifing Intel's driver at this point, but final/official v3 patchset will doesn't have it, because it will be based on Vinod's cleanup patch.
Kuninori Morimoto (3): ASoC: core: replace codec_dev_list to component_dev_list on Card ASoC: core: replace aux_comp_list to component_dev_list ASoC: add Component level suspend/resume
include/sound/soc.h | 16 +++--- sound/soc/intel/boards/broadwell.c | 16 +++--- sound/soc/intel/boards/cht_bsw_rt5672.c | 16 +++--- sound/soc/soc-core.c | 90 ++++++++++++++++++++------------- 4 files changed, 85 insertions(+), 53 deletions(-)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Current Card has Codec list (= codec_dev_list), but Codec will be removed in the future. Because of this reason, this patch adds new Component list in Card, and replace Codec list.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v2 -> v3
- focusing to codec_dev_list / component_dev_list only
include/sound/soc.h | 6 +++--- sound/soc/intel/boards/broadwell.c | 16 ++++++++++------ sound/soc/intel/boards/cht_bsw_rt5672.c | 16 ++++++++++------ sound/soc/soc-core.c | 28 ++++++++++++++++------------ 4 files changed, 39 insertions(+), 27 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 1ed9371..b5544e2 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -810,6 +810,7 @@ struct snd_soc_component {
struct list_head list; struct list_head list_aux; /* for auxiliary component of the card */ + struct list_head card_list;
struct snd_soc_dai_driver *dai_drv; int num_dai; @@ -868,7 +869,6 @@ struct snd_soc_codec { const struct snd_soc_codec_driver *driver;
struct list_head list; - struct list_head card_list;
/* runtime */ unsigned int cache_bypass:1; /* Suppress access to the cache */ @@ -1170,7 +1170,7 @@ struct snd_soc_card { struct work_struct deferred_resume_work;
/* lists of probed devices belonging to this card */ - struct list_head codec_dev_list; + struct list_head component_dev_list;
struct list_head widgets; struct list_head paths; @@ -1540,11 +1540,11 @@ static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platfo
static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) { - INIT_LIST_HEAD(&card->codec_dev_list); INIT_LIST_HEAD(&card->widgets); INIT_LIST_HEAD(&card->paths); INIT_LIST_HEAD(&card->dapm_list); INIT_LIST_HEAD(&card->aux_comp_list); + INIT_LIST_HEAD(&card->component_dev_list); }
static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 7486a00..80f3a2d 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -220,10 +220,12 @@ static int broadwell_rtd_init(struct snd_soc_pcm_runtime *rtd) };
static int broadwell_suspend(struct snd_soc_card *card){ - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-INT343A:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-INT343A:00")) { dev_dbg(codec->dev, "disabling jack detect before going to suspend.\n"); rt286_mic_detect(codec, NULL); break; @@ -233,10 +235,12 @@ static int broadwell_suspend(struct snd_soc_card *card){ }
static int broadwell_resume(struct snd_soc_card *card){ - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-INT343A:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-INT343A:00")) { dev_dbg(codec->dev, "enabling jack detect for resume.\n"); rt286_mic_detect(codec, &broadwell_headset); break; diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index df9d254..dfae9cf 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -292,10 +292,12 @@ static int cht_aif1_startup(struct snd_pcm_substream *substream)
static int cht_suspend_pre(struct snd_soc_card *card) { - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-10EC5670:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-10EC5670:00")) { dev_dbg(codec->dev, "disabling jack detect before going to suspend.\n"); rt5670_jack_suspend(codec); break; @@ -306,10 +308,12 @@ static int cht_suspend_pre(struct snd_soc_card *card)
static int cht_resume_post(struct snd_soc_card *card) { - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-10EC5670:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-10EC5670:00")) { dev_dbg(codec->dev, "enabling jack detect for resume.\n"); rt5670_jack_resume(codec); break; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c0bbcd9..d204bb7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -626,7 +626,7 @@ static void codec2codec_close_delayed_work(struct work_struct *work) int snd_soc_suspend(struct device *dev) { struct snd_soc_card *card = dev_get_drvdata(dev); - struct snd_soc_codec *codec; + struct snd_soc_component *component; struct snd_soc_pcm_runtime *rtd; int i;
@@ -703,8 +703,12 @@ int snd_soc_suspend(struct device *dev) snd_soc_dapm_sync(&card->dapm);
/* suspend all CODECs */ - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + list_for_each_entry(component, &card->component_dev_list, card_list) { + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + if (!codec) + continue;
/* If there are paths active then the CODEC will be held with * bias _ON and should not be suspended. */ @@ -768,7 +772,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 snd_soc_pcm_runtime *rtd; - struct snd_soc_codec *codec; + struct snd_soc_component *component; int i;
/* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, @@ -794,7 +798,12 @@ static void soc_resume_deferred(struct work_struct *work) cpu_dai->driver->resume(cpu_dai); }
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { + list_for_each_entry(component, &card->component_dev_list, card_list) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + if (!codec) + continue; + if (codec->suspended) { if (codec->driver->resume) codec->driver->resume(codec); @@ -1072,9 +1081,7 @@ static void soc_remove_component(struct snd_soc_component *component) if (!component->card) return;
- /* This is a HACK and will be removed soon */ - if (component->codec) - list_del(&component->codec->card_list); + list_del(&component->card_list);
if (component->remove) component->remove(component); @@ -1443,10 +1450,7 @@ static int soc_probe_component(struct snd_soc_card *card, component->num_dapm_routes);
list_add(&dapm->list, &card->dapm_list); - - /* This is a HACK and will be removed soon */ - if (component->codec) - list_add(&component->codec->card_list, &card->codec_dev_list); + list_add(&component->card_list, &card->component_dev_list);
return 0;
The patch
ASoC: core: replace codec_dev_list to component_dev_list on Card
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From d9fc40639dc1b87915426d2ef489a591b0fd650b Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Wed, 30 Nov 2016 06:22:36 +0000 Subject: [PATCH] ASoC: core: replace codec_dev_list to component_dev_list on Card
Current Card has Codec list (= codec_dev_list), but Codec will be removed in the future. Because of this reason, this patch adds new Component list in Card, and replace Codec list.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org --- include/sound/soc.h | 6 +++--- sound/soc/intel/boards/broadwell.c | 16 ++++++++++------ sound/soc/intel/boards/cht_bsw_rt5672.c | 16 ++++++++++------ sound/soc/soc-core.c | 28 ++++++++++++++++------------ 4 files changed, 39 insertions(+), 27 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 1ed9371ece0d..b5544e2287b8 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -810,6 +810,7 @@ struct snd_soc_component {
struct list_head list; struct list_head list_aux; /* for auxiliary component of the card */ + struct list_head card_list;
struct snd_soc_dai_driver *dai_drv; int num_dai; @@ -868,7 +869,6 @@ struct snd_soc_codec { const struct snd_soc_codec_driver *driver;
struct list_head list; - struct list_head card_list;
/* runtime */ unsigned int cache_bypass:1; /* Suppress access to the cache */ @@ -1170,7 +1170,7 @@ struct snd_soc_card { struct work_struct deferred_resume_work;
/* lists of probed devices belonging to this card */ - struct list_head codec_dev_list; + struct list_head component_dev_list;
struct list_head widgets; struct list_head paths; @@ -1540,11 +1540,11 @@ static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platfo
static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) { - INIT_LIST_HEAD(&card->codec_dev_list); INIT_LIST_HEAD(&card->widgets); INIT_LIST_HEAD(&card->paths); INIT_LIST_HEAD(&card->dapm_list); INIT_LIST_HEAD(&card->aux_comp_list); + INIT_LIST_HEAD(&card->component_dev_list); }
static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 7486a0022fde..80f3a2d95737 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -220,10 +220,12 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { };
static int broadwell_suspend(struct snd_soc_card *card){ - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-INT343A:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-INT343A:00")) { dev_dbg(codec->dev, "disabling jack detect before going to suspend.\n"); rt286_mic_detect(codec, NULL); break; @@ -233,10 +235,12 @@ static int broadwell_suspend(struct snd_soc_card *card){ }
static int broadwell_resume(struct snd_soc_card *card){ - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-INT343A:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-INT343A:00")) { dev_dbg(codec->dev, "enabling jack detect for resume.\n"); rt286_mic_detect(codec, &broadwell_headset); break; diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index df9d254baa18..dfae9cfa0ac6 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -292,10 +292,12 @@ static struct snd_soc_dai_link cht_dailink[] = {
static int cht_suspend_pre(struct snd_soc_card *card) { - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-10EC5670:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-10EC5670:00")) { dev_dbg(codec->dev, "disabling jack detect before going to suspend.\n"); rt5670_jack_suspend(codec); break; @@ -306,10 +308,12 @@ static int cht_suspend_pre(struct snd_soc_card *card)
static int cht_resume_post(struct snd_soc_card *card) { - struct snd_soc_codec *codec; + struct snd_soc_component *component; + + list_for_each_entry(component, &card->component_dev_list, card_list) { + if (!strcmp(component->name, "i2c-10EC5670:00")) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { - if (!strcmp(codec->component.name, "i2c-10EC5670:00")) { dev_dbg(codec->dev, "enabling jack detect for resume.\n"); rt5670_jack_resume(codec); break; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c0bbcd903261..d204bb772f00 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -626,7 +626,7 @@ static void codec2codec_close_delayed_work(struct work_struct *work) int snd_soc_suspend(struct device *dev) { struct snd_soc_card *card = dev_get_drvdata(dev); - struct snd_soc_codec *codec; + struct snd_soc_component *component; struct snd_soc_pcm_runtime *rtd; int i;
@@ -703,8 +703,12 @@ int snd_soc_suspend(struct device *dev) snd_soc_dapm_sync(&card->dapm);
/* suspend all CODECs */ - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + list_for_each_entry(component, &card->component_dev_list, card_list) { + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + if (!codec) + continue;
/* If there are paths active then the CODEC will be held with * bias _ON and should not be suspended. */ @@ -768,7 +772,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 snd_soc_pcm_runtime *rtd; - struct snd_soc_codec *codec; + struct snd_soc_component *component; int i;
/* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, @@ -794,7 +798,12 @@ static void soc_resume_deferred(struct work_struct *work) cpu_dai->driver->resume(cpu_dai); }
- list_for_each_entry(codec, &card->codec_dev_list, card_list) { + list_for_each_entry(component, &card->component_dev_list, card_list) { + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + if (!codec) + continue; + if (codec->suspended) { if (codec->driver->resume) codec->driver->resume(codec); @@ -1072,9 +1081,7 @@ static void soc_remove_component(struct snd_soc_component *component) if (!component->card) return;
- /* This is a HACK and will be removed soon */ - if (component->codec) - list_del(&component->codec->card_list); + list_del(&component->card_list);
if (component->remove) component->remove(component); @@ -1443,10 +1450,7 @@ static int soc_probe_component(struct snd_soc_card *card, component->num_dapm_routes);
list_add(&dapm->list, &card->dapm_list); - - /* This is a HACK and will be removed soon */ - if (component->codec) - list_add(&component->codec->card_list, &card->codec_dev_list); + list_add(&component->card_list, &card->component_dev_list);
return 0;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Now, Card has component_dev_list, we can replace aux_comp_list to component_dev_list with new auxiliary flags
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v2 -> v3
- focusing to auxiliary only
include/sound/soc.h | 4 +--- sound/soc/soc-core.c | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index b5544e2..0bd57b7 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -807,9 +807,9 @@ struct snd_soc_component {
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ unsigned int registered_as_component:1; + unsigned int auxiliary:1; /* for auxiliary component of the card */
struct list_head list; - struct list_head list_aux; /* for auxiliary component of the card */ struct list_head card_list;
struct snd_soc_dai_driver *dai_drv; @@ -1148,7 +1148,6 @@ struct snd_soc_card { */ struct snd_soc_aux_dev *aux_dev; int num_aux_devs; - struct list_head aux_comp_list;
const struct snd_kcontrol_new *controls; int num_controls; @@ -1543,7 +1542,6 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) INIT_LIST_HEAD(&card->widgets); INIT_LIST_HEAD(&card->paths); INIT_LIST_HEAD(&card->dapm_list); - INIT_LIST_HEAD(&card->aux_comp_list); INIT_LIST_HEAD(&card->component_dev_list); }
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d204bb7..ba8e000 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1710,7 +1710,8 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) }
component->init = aux_dev->init; - list_add(&component->list_aux, &card->aux_comp_list); + component->auxiliary = 1; + return 0;
err_defer: @@ -1726,7 +1727,10 @@ static int soc_probe_aux_devices(struct snd_soc_card *card)
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { - list_for_each_entry(comp, &card->aux_comp_list, list_aux) { + list_for_each_entry(comp, &card->component_dev_list, card_list) { + if (!comp->auxiliary) + continue; + if (comp->driver->probe_order == order) { ret = soc_probe_component(card, comp); if (ret < 0) { @@ -1750,11 +1754,14 @@ static void soc_remove_aux_devices(struct snd_soc_card *card) for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { list_for_each_entry_safe(comp, _comp, - &card->aux_comp_list, list_aux) { + &card->component_dev_list, card_list) { + + if (!comp->auxiliary) + continue; + if (comp->driver->remove_order == order) { soc_remove_component(comp); - /* remove it from the card's aux_comp_list */ - list_del(&comp->list_aux); + comp->auxiliary = 0; } } }
The patch
ASoC: core: replace aux_comp_list to component_dev_list
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 1a653aa44725668590b36bbe2d7fe4736a69f055 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Wed, 30 Nov 2016 06:22:55 +0000 Subject: [PATCH] ASoC: core: replace aux_comp_list to component_dev_list
Now, Card has component_dev_list, we can replace aux_comp_list to component_dev_list with new auxiliary flags
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org --- include/sound/soc.h | 4 +--- sound/soc/soc-core.c | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index b5544e2287b8..0bd57b77d010 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -807,9 +807,9 @@ struct snd_soc_component {
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ unsigned int registered_as_component:1; + unsigned int auxiliary:1; /* for auxiliary component of the card */
struct list_head list; - struct list_head list_aux; /* for auxiliary component of the card */ struct list_head card_list;
struct snd_soc_dai_driver *dai_drv; @@ -1148,7 +1148,6 @@ struct snd_soc_card { */ struct snd_soc_aux_dev *aux_dev; int num_aux_devs; - struct list_head aux_comp_list;
const struct snd_kcontrol_new *controls; int num_controls; @@ -1543,7 +1542,6 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) INIT_LIST_HEAD(&card->widgets); INIT_LIST_HEAD(&card->paths); INIT_LIST_HEAD(&card->dapm_list); - INIT_LIST_HEAD(&card->aux_comp_list); INIT_LIST_HEAD(&card->component_dev_list); }
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d204bb772f00..ba8e000faaf1 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1710,7 +1710,8 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) }
component->init = aux_dev->init; - list_add(&component->list_aux, &card->aux_comp_list); + component->auxiliary = 1; + return 0;
err_defer: @@ -1726,7 +1727,10 @@ static int soc_probe_aux_devices(struct snd_soc_card *card)
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { - list_for_each_entry(comp, &card->aux_comp_list, list_aux) { + list_for_each_entry(comp, &card->component_dev_list, card_list) { + if (!comp->auxiliary) + continue; + if (comp->driver->probe_order == order) { ret = soc_probe_component(card, comp); if (ret < 0) { @@ -1750,11 +1754,14 @@ static void soc_remove_aux_devices(struct snd_soc_card *card) for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { list_for_each_entry_safe(comp, _comp, - &card->aux_comp_list, list_aux) { + &card->component_dev_list, card_list) { + + if (!comp->auxiliary) + continue; + if (comp->driver->remove_order == order) { soc_remove_component(comp); - /* remove it from the card's aux_comp_list */ - list_del(&comp->list_aux); + comp->auxiliary = 0; } } }
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
In current ALSA SoC, Codec only has suspend/resume feature, but it should be supported on Component level. This patch adds it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v2 -> v3
- focusing to suspend/resume only
include/sound/soc.h | 6 ++++- sound/soc/soc-core.c | 63 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 27 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 0bd57b7..13cc64e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -782,6 +782,8 @@ struct snd_soc_component_driver {
int (*probe)(struct snd_soc_component *); void (*remove)(struct snd_soc_component *); + int (*suspend)(struct snd_soc_component *); + int (*resume)(struct snd_soc_component *);
/* DT */ int (*of_xlate_dai_name)(struct snd_soc_component *component, @@ -808,6 +810,7 @@ struct snd_soc_component { unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ unsigned int registered_as_component:1; unsigned int auxiliary:1; /* for auxiliary component of the card */ + unsigned int suspended:1; /* is in suspend PM state */
struct list_head list; struct list_head card_list; @@ -853,6 +856,8 @@ struct snd_soc_component {
int (*probe)(struct snd_soc_component *); void (*remove)(struct snd_soc_component *); + int (*suspend)(struct snd_soc_component *); + int (*resume)(struct snd_soc_component *);
/* machine specific init */ int (*init)(struct snd_soc_component *component); @@ -872,7 +877,6 @@ struct snd_soc_codec {
/* runtime */ unsigned int cache_bypass:1; /* Suppress access to the cache */ - unsigned int suspended:1; /* Codec is in suspend PM state */ unsigned int cache_init:1; /* codec cache has been initialized */
/* codec IO */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ba8e000..f35ec5b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -702,43 +702,39 @@ int snd_soc_suspend(struct device *dev) dapm_mark_endpoints_dirty(card); snd_soc_dapm_sync(&card->dapm);
- /* suspend all CODECs */ + /* suspend all COMPONENTs */ list_for_each_entry(component, &card->component_dev_list, card_list) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- if (!codec) - continue; - - /* If there are paths active then the CODEC will be held with + /* If there are paths active then the COMPONENT will be held with * bias _ON and should not be suspended. */ - if (!codec->suspended) { + if (!component->suspended) { switch (snd_soc_dapm_get_bias_level(dapm)) { case SND_SOC_BIAS_STANDBY: /* - * If the CODEC is capable of idle + * If the COMPONENT is capable of idle * bias off then being in STANDBY * means it's doing something, * otherwise fall through. */ if (dapm->idle_bias_off) { - dev_dbg(codec->dev, + dev_dbg(component->dev, "ASoC: idle_bias_off CODEC on over suspend\n"); break; }
case SND_SOC_BIAS_OFF: - if (codec->driver->suspend) - codec->driver->suspend(codec); - codec->suspended = 1; - if (codec->component.regmap) - regcache_mark_dirty(codec->component.regmap); + if (component->suspend) + component->suspend(component); + component->suspended = 1; + if (component->regmap) + regcache_mark_dirty(component->regmap); /* deactivate pins to sleep state */ - pinctrl_pm_select_sleep_state(codec->dev); + pinctrl_pm_select_sleep_state(component->dev); break; default: - dev_dbg(codec->dev, - "ASoC: CODEC is on over suspend\n"); + dev_dbg(component->dev, + "ASoC: COMPONENT is on over suspend\n"); break; } } @@ -799,15 +795,10 @@ static void soc_resume_deferred(struct work_struct *work) }
list_for_each_entry(component, &card->component_dev_list, card_list) { - struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - - if (!codec) - continue; - - if (codec->suspended) { - if (codec->driver->resume) - codec->driver->resume(codec); - codec->suspended = 0; + if (component->suspended) { + if (component->resume) + component->resume(component); + component->suspended = 0; } }
@@ -2937,6 +2928,8 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, component->driver = driver; component->probe = component->driver->probe; component->remove = component->driver->remove; + component->suspend = component->driver->suspend; + component->resume = component->driver->resume;
dapm = &component->dapm; dapm->dev = dev; @@ -3286,6 +3279,20 @@ static void snd_soc_codec_drv_remove(struct snd_soc_component *component) codec->driver->remove(codec); }
+static int snd_soc_codec_drv_suspend(struct snd_soc_component *component) +{ + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + return codec->driver->suspend(codec); +} + +static int snd_soc_codec_drv_resume(struct snd_soc_component *component) +{ + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + return codec->driver->resume(codec); +} + static int snd_soc_codec_drv_write(struct snd_soc_component *component, unsigned int reg, unsigned int val) { @@ -3347,6 +3354,10 @@ int snd_soc_register_codec(struct device *dev, codec->component.probe = snd_soc_codec_drv_probe; if (codec_drv->remove) codec->component.remove = snd_soc_codec_drv_remove; + if (codec_drv->suspend) + codec->component.suspend = snd_soc_codec_drv_suspend; + if (codec_drv->resume) + codec->component.resume = snd_soc_codec_drv_resume; if (codec_drv->write) codec->component.write = snd_soc_codec_drv_write; if (codec_drv->read)
The patch
ASoC: add Component level suspend/resume
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 9178feb4538e055bf22be44c38b90cc31d2baf99 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Wed, 30 Nov 2016 06:23:13 +0000 Subject: [PATCH] ASoC: add Component level suspend/resume
In current ALSA SoC, Codec only has suspend/resume feature, but it should be supported on Component level. This patch adds it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org --- include/sound/soc.h | 6 ++++- sound/soc/soc-core.c | 63 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 27 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 0bd57b77d010..13cc64e5bb77 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -782,6 +782,8 @@ struct snd_soc_component_driver {
int (*probe)(struct snd_soc_component *); void (*remove)(struct snd_soc_component *); + int (*suspend)(struct snd_soc_component *); + int (*resume)(struct snd_soc_component *);
/* DT */ int (*of_xlate_dai_name)(struct snd_soc_component *component, @@ -808,6 +810,7 @@ struct snd_soc_component { unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ unsigned int registered_as_component:1; unsigned int auxiliary:1; /* for auxiliary component of the card */ + unsigned int suspended:1; /* is in suspend PM state */
struct list_head list; struct list_head card_list; @@ -853,6 +856,8 @@ struct snd_soc_component {
int (*probe)(struct snd_soc_component *); void (*remove)(struct snd_soc_component *); + int (*suspend)(struct snd_soc_component *); + int (*resume)(struct snd_soc_component *);
/* machine specific init */ int (*init)(struct snd_soc_component *component); @@ -872,7 +877,6 @@ struct snd_soc_codec {
/* runtime */ unsigned int cache_bypass:1; /* Suppress access to the cache */ - unsigned int suspended:1; /* Codec is in suspend PM state */ unsigned int cache_init:1; /* codec cache has been initialized */
/* codec IO */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ba8e000faaf1..f35ec5bf3b78 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -702,43 +702,39 @@ int snd_soc_suspend(struct device *dev) dapm_mark_endpoints_dirty(card); snd_soc_dapm_sync(&card->dapm);
- /* suspend all CODECs */ + /* suspend all COMPONENTs */ list_for_each_entry(component, &card->component_dev_list, card_list) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
- if (!codec) - continue; - - /* If there are paths active then the CODEC will be held with + /* If there are paths active then the COMPONENT will be held with * bias _ON and should not be suspended. */ - if (!codec->suspended) { + if (!component->suspended) { switch (snd_soc_dapm_get_bias_level(dapm)) { case SND_SOC_BIAS_STANDBY: /* - * If the CODEC is capable of idle + * If the COMPONENT is capable of idle * bias off then being in STANDBY * means it's doing something, * otherwise fall through. */ if (dapm->idle_bias_off) { - dev_dbg(codec->dev, + dev_dbg(component->dev, "ASoC: idle_bias_off CODEC on over suspend\n"); break; }
case SND_SOC_BIAS_OFF: - if (codec->driver->suspend) - codec->driver->suspend(codec); - codec->suspended = 1; - if (codec->component.regmap) - regcache_mark_dirty(codec->component.regmap); + if (component->suspend) + component->suspend(component); + component->suspended = 1; + if (component->regmap) + regcache_mark_dirty(component->regmap); /* deactivate pins to sleep state */ - pinctrl_pm_select_sleep_state(codec->dev); + pinctrl_pm_select_sleep_state(component->dev); break; default: - dev_dbg(codec->dev, - "ASoC: CODEC is on over suspend\n"); + dev_dbg(component->dev, + "ASoC: COMPONENT is on over suspend\n"); break; } } @@ -799,15 +795,10 @@ static void soc_resume_deferred(struct work_struct *work) }
list_for_each_entry(component, &card->component_dev_list, card_list) { - struct snd_soc_codec *codec = snd_soc_component_to_codec(component); - - if (!codec) - continue; - - if (codec->suspended) { - if (codec->driver->resume) - codec->driver->resume(codec); - codec->suspended = 0; + if (component->suspended) { + if (component->resume) + component->resume(component); + component->suspended = 0; } }
@@ -2937,6 +2928,8 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, component->driver = driver; component->probe = component->driver->probe; component->remove = component->driver->remove; + component->suspend = component->driver->suspend; + component->resume = component->driver->resume;
dapm = &component->dapm; dapm->dev = dev; @@ -3286,6 +3279,20 @@ static void snd_soc_codec_drv_remove(struct snd_soc_component *component) codec->driver->remove(codec); }
+static int snd_soc_codec_drv_suspend(struct snd_soc_component *component) +{ + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + return codec->driver->suspend(codec); +} + +static int snd_soc_codec_drv_resume(struct snd_soc_component *component) +{ + struct snd_soc_codec *codec = snd_soc_component_to_codec(component); + + return codec->driver->resume(codec); +} + static int snd_soc_codec_drv_write(struct snd_soc_component *component, unsigned int reg, unsigned int val) { @@ -3347,6 +3354,10 @@ int snd_soc_register_codec(struct device *dev, codec->component.probe = snd_soc_codec_drv_probe; if (codec_drv->remove) codec->component.remove = snd_soc_codec_drv_remove; + if (codec_drv->suspend) + codec->component.suspend = snd_soc_codec_drv_suspend; + if (codec_drv->resume) + codec->component.resume = snd_soc_codec_drv_resume; if (codec_drv->write) codec->component.write = snd_soc_codec_drv_write; if (codec_drv->read)
Hi Mark, Lars-Peter
These patches are v3+RFC of Component level suspend/resume support.
I'm waiting Vinod's cleanup patch which will remove "codec_dev_list" from Intel drivers. But until then, I would like to get review about v3 patch. This v3 patch-set is still modifing Intel's driver at this point, but final/official v3 patchset will doesn't have it, because it will be based on Vinod's cleanup patch.
Kuninori Morimoto (3): ASoC: core: replace codec_dev_list to component_dev_list on Card ASoC: core: replace aux_comp_list to component_dev_list ASoC: add Component level suspend/resume
include/sound/soc.h | 16 +++--- sound/soc/intel/boards/broadwell.c | 16 +++--- sound/soc/intel/boards/cht_bsw_rt5672.c | 16 +++--- sound/soc/soc-core.c | 90 ++++++++++++++++++++------------- 4 files changed, 85 insertions(+), 53 deletions(-)
If Vinod's intel side fixup patch takes long term, is it possible to have chance first to these patches ?
participants (2)
-
Kuninori Morimoto
-
Mark Brown