Commit c3d89fd7 authored by Mark Brown's avatar Mark Brown

Merge series "ASoC: add dailink .exit() callback" from Pierre-Louis Bossart...

Merge series "ASoC: add dailink .exit() callback" from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:

While looking at reboot issues and module load/unload tests, I found
out some resources allocated in the dailink .init() callback are not
properly released - there is no existing mechanism in the soc-core to
do so.

The addition of a dailink .exit() callback seems to be the simplest
solution overall. It can be argued that the existing machine platform
device .remove() callback can also perform the necessary cleanups,
however as shown in the last two examples this might require a loop to
identify components whereas the dailink .exit() already has all the
necessary information to revert the actions done in the .init() step.

Changes since RFC:
Better commit messages and explanations
rt5682 cases with snd_soc_component_set_jack() called in the .exit()

Fred Oh (2):
  ASoC: intel: sof_rt5682: move disabling jack to dai link's exit()
  ASoC: intel: cml_rt1011_rt5682: disable jack in dailink .exit()

Pierre-Louis Bossart (3):
  ASoC: soc-link: introduce exit() callback
  ASoC: Intel: bdw-rt5677: fix module load/unload issues
  ASoC: Intel: kbl-rt5660: use .exit() dailink callback to release gpiod

 include/sound/soc-link.h                   |  1 +
 include/sound/soc.h                        |  3 +++
 sound/soc/intel/boards/bdw-rt5677.c        | 18 ++++++++++++++--
 sound/soc/intel/boards/cml_rt1011_rt5682.c |  8 ++++++++
 sound/soc/intel/boards/kbl_rt5660.c        | 17 +++++++++++++--
 sound/soc/intel/boards/sof_rt5682.c        | 24 ++++++++--------------
 sound/soc/soc-core.c                       |  3 +++
 sound/soc/soc-link.c                       |  6 ++++++
 8 files changed, 60 insertions(+), 20 deletions(-)

base-commit: 39853b14
--
2.20.1
parents ee8a41cd 4fcc922c
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#define __SOC_LINK_H #define __SOC_LINK_H
int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd);
void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd);
int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params); struct snd_pcm_hw_params *params);
......
...@@ -799,6 +799,9 @@ struct snd_soc_dai_link { ...@@ -799,6 +799,9 @@ struct snd_soc_dai_link {
/* codec/machine specific init - e.g. add machine controls */ /* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_pcm_runtime *rtd); int (*init)(struct snd_soc_pcm_runtime *rtd);
/* codec/machine specific exit - dual of init() */
void (*exit)(struct snd_soc_pcm_runtime *rtd);
/* optional hw_params re-writing for BE and FE sync */ /* optional hw_params re-writing for BE and FE sync */
int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params); struct snd_pcm_hw_params *params);
......
...@@ -272,8 +272,8 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) ...@@ -272,8 +272,8 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
RT5677_CLK_SEL_SYS2); RT5677_CLK_SEL_SYS2);
/* Request rt5677 GPIO for headphone amp control */ /* Request rt5677 GPIO for headphone amp control */
bdw_rt5677->gpio_hp_en = devm_gpiod_get(component->dev, "headphone-enable", bdw_rt5677->gpio_hp_en = gpiod_get(component->dev, "headphone-enable",
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(bdw_rt5677->gpio_hp_en)) { if (IS_ERR(bdw_rt5677->gpio_hp_en)) {
dev_err(component->dev, "Can't find HP_AMP_SHDN_L gpio\n"); dev_err(component->dev, "Can't find HP_AMP_SHDN_L gpio\n");
return PTR_ERR(bdw_rt5677->gpio_hp_en); return PTR_ERR(bdw_rt5677->gpio_hp_en);
...@@ -307,6 +307,19 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) ...@@ -307,6 +307,19 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd)
return 0; return 0;
} }
static void bdw_rt5677_exit(struct snd_soc_pcm_runtime *rtd)
{
struct bdw_rt5677_priv *bdw_rt5677 =
snd_soc_card_get_drvdata(rtd->card);
/*
* The .exit() can be reached without going through the .init()
* so explicitly test if the gpiod is valid
*/
if (!IS_ERR_OR_NULL(bdw_rt5677->gpio_hp_en))
gpiod_put(bdw_rt5677->gpio_hp_en);
}
/* broadwell digital audio interface glue - connects codec <--> CPU */ /* broadwell digital audio interface glue - connects codec <--> CPU */
SND_SOC_DAILINK_DEF(dummy, SND_SOC_DAILINK_DEF(dummy,
DAILINK_COMP_ARRAY(COMP_DUMMY())); DAILINK_COMP_ARRAY(COMP_DUMMY()));
...@@ -372,6 +385,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { ...@@ -372,6 +385,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = {
.dpcm_playback = 1, .dpcm_playback = 1,
.dpcm_capture = 1, .dpcm_capture = 1,
.init = bdw_rt5677_init, .init = bdw_rt5677_init,
.exit = bdw_rt5677_exit,
#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) #if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL)
SND_SOC_DAILINK_REG(dummy, be, dummy), SND_SOC_DAILINK_REG(dummy, be, dummy),
#else #else
......
...@@ -161,6 +161,13 @@ static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -161,6 +161,13 @@ static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
return ret; return ret;
}; };
static void cml_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
snd_soc_component_set_jack(component, NULL, NULL);
}
static int cml_rt1011_spk_init(struct snd_soc_pcm_runtime *rtd) static int cml_rt1011_spk_init(struct snd_soc_pcm_runtime *rtd)
{ {
int ret = 0; int ret = 0;
...@@ -415,6 +422,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { ...@@ -415,6 +422,7 @@ static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = {
.name = "SSP0-Codec", .name = "SSP0-Codec",
.id = 0, .id = 0,
.init = cml_rt5682_codec_init, .init = cml_rt5682_codec_init,
.exit = cml_rt5682_codec_exit,
.ignore_pmdown_time = 1, .ignore_pmdown_time = 1,
.ops = &cml_rt5682_ops, .ops = &cml_rt5682_ops,
.dpcm_playback = 1, .dpcm_playback = 1,
......
...@@ -165,8 +165,8 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -165,8 +165,8 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd)
dev_warn(component->dev, "Failed to add driver gpios\n"); dev_warn(component->dev, "Failed to add driver gpios\n");
/* Request rt5660 GPIO for lineout mute control, return if fails */ /* Request rt5660 GPIO for lineout mute control, return if fails */
ctx->gpio_lo_mute = devm_gpiod_get(component->dev, "lineout-mute", ctx->gpio_lo_mute = gpiod_get(component->dev, "lineout-mute",
GPIOD_OUT_HIGH); GPIOD_OUT_HIGH);
if (IS_ERR(ctx->gpio_lo_mute)) { if (IS_ERR(ctx->gpio_lo_mute)) {
dev_err(component->dev, "Can't find GPIO_MUTE# gpio\n"); dev_err(component->dev, "Can't find GPIO_MUTE# gpio\n");
return PTR_ERR(ctx->gpio_lo_mute); return PTR_ERR(ctx->gpio_lo_mute);
...@@ -207,6 +207,18 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -207,6 +207,18 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd)
return 0; return 0;
} }
static void kabylake_rt5660_codec_exit(struct snd_soc_pcm_runtime *rtd)
{
struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
/*
* The .exit() can be reached without going through the .init()
* so explicitly test if the gpiod is valid
*/
if (!IS_ERR_OR_NULL(ctx->gpio_lo_mute))
gpiod_put(ctx->gpio_lo_mute);
}
static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device)
{ {
struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
...@@ -421,6 +433,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = { ...@@ -421,6 +433,7 @@ static struct snd_soc_dai_link kabylake_rt5660_dais[] = {
.id = 0, .id = 0,
.no_pcm = 1, .no_pcm = 1,
.init = kabylake_rt5660_codec_init, .init = kabylake_rt5660_codec_init,
.exit = kabylake_rt5660_codec_exit,
.dai_fmt = SND_SOC_DAIFMT_I2S | .dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAIFMT_CBS_CFS,
......
...@@ -206,6 +206,13 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -206,6 +206,13 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
return ret; return ret;
}; };
static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
snd_soc_component_set_jack(component, NULL, NULL);
}
static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
...@@ -525,6 +532,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, ...@@ -525,6 +532,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
links[id].platforms = platform_component; links[id].platforms = platform_component;
links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].num_platforms = ARRAY_SIZE(platform_component);
links[id].init = sof_rt5682_codec_init; links[id].init = sof_rt5682_codec_init;
links[id].exit = sof_rt5682_codec_exit;
links[id].ops = &sof_rt5682_ops; links[id].ops = &sof_rt5682_ops;
links[id].nonatomic = true; links[id].nonatomic = true;
links[id].dpcm_playback = 1; links[id].dpcm_playback = 1;
...@@ -786,21 +794,6 @@ static int sof_audio_probe(struct platform_device *pdev) ...@@ -786,21 +794,6 @@ static int sof_audio_probe(struct platform_device *pdev)
&sof_audio_card_rt5682); &sof_audio_card_rt5682);
} }
static int sof_rt5682_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct snd_soc_component *component = NULL;
for_each_card_components(card, component) {
if (!strcmp(component->name, rt5682_component[0].name)) {
snd_soc_component_set_jack(component, NULL, NULL);
break;
}
}
return 0;
}
static const struct platform_device_id board_ids[] = { static const struct platform_device_id board_ids[] = {
{ {
.name = "sof_rt5682", .name = "sof_rt5682",
...@@ -836,7 +829,6 @@ static const struct platform_device_id board_ids[] = { ...@@ -836,7 +829,6 @@ static const struct platform_device_id board_ids[] = {
static struct platform_driver sof_audio = { static struct platform_driver sof_audio = {
.probe = sof_audio_probe, .probe = sof_audio_probe,
.remove = sof_rt5682_remove,
.driver = { .driver = {
.name = "sof_rt5682", .name = "sof_rt5682",
.pm = &snd_soc_pm_ops, .pm = &snd_soc_pm_ops,
......
...@@ -945,6 +945,9 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, ...@@ -945,6 +945,9 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card,
{ {
lockdep_assert_held(&client_mutex); lockdep_assert_held(&client_mutex);
/* release machine specific resources */
snd_soc_link_exit(rtd);
/* /*
* Notify the machine driver for extra destruction * Notify the machine driver for extra destruction
*/ */
......
...@@ -40,6 +40,12 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd) ...@@ -40,6 +40,12 @@ int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd)
return soc_link_ret(rtd, ret); return soc_link_ret(rtd, ret);
} }
void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd)
{
if (rtd->dai_link->exit)
rtd->dai_link->exit(rtd);
}
int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment