From 576ce4075bfa0f03e0e91a89eecc539b3b828b08 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 2 Nov 2018 16:18:21 +0100 Subject: ASoC: wm97xx: fix uninitialized regmap pointer problem gcc notices that without either the ac97 bus or the pdata, we never initialize the regmap pointer, which leads to an uninitialized variable access: sound/soc/codecs/wm9712.c: In function 'wm9712_soc_probe': sound/soc/codecs/wm9712.c:666:2: error: 'regmap' may be used uninitialized in this function [-Werror=maybe-uninitialized] Since that configuration is invalid, it's better to return an error here. I tried to avoid adding complexity to the conditions, and turned the #ifdef into a regular if(IS_ENABLED()) check for readability. This in turn requires moving some header file declarations out of an #ifdef. The same code is used in three drivers, all of which I'm changing the same way. Fixes: 2ed1a8e0ce8d ("ASoC: wm9712: add ac97 new bus support") Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown --- include/sound/soc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index f1dab1f4b194..5a8b84140f01 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -553,12 +553,12 @@ static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, } #endif -#ifdef CONFIG_SND_SOC_AC97_BUS struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component); struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component, unsigned int id, unsigned int id_mask); void snd_soc_free_ac97_component(struct snd_ac97 *ac97); +#ifdef CONFIG_SND_SOC_AC97_BUS int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, struct platform_device *pdev); -- cgit v1.2.3 From 8679284b37e9e2d529d60d1acc4133af4aa5dd34 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 1 Nov 2018 16:34:48 -0500 Subject: ASoC: acpi: define common interface for machine driver configuration The machine drivers may need information provided by the platform driver. Currently the information is passed using pdata specific to each plaform driver. This prevents other drivers, such as SOF, from reusing machine drivers directly. Add a new structure which contains the required fields. This proposal requires a bit more work on the platform side but this generic interface helps reuse code directly. Reviewed-by: Andy Shevchenko Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/soc-acpi.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'include') diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index e45b2330d16a..5154c6359609 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -37,6 +37,19 @@ snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], struct snd_soc_acpi_mach * snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines); +/** + * snd_soc_acpi_mach_params: interface for machine driver configuration + * + * @acpi_ipc_irq_index: used for BYT-CR detection + * @platform: string used for HDaudio codec support + * @codec_mask: used for HDAudio support + */ +struct snd_soc_acpi_mach_params { + u32 acpi_ipc_irq_index; + const char *platform; + u32 codec_mask; +}; + /** * snd_soc_acpi_mach: ACPI-based machine descriptor. Most of the fields are * related to the hardware, except for the firmware and topology file names. @@ -68,6 +81,7 @@ struct snd_soc_acpi_mach { struct snd_soc_acpi_mach * (*machine_quirk)(void *arg); const void *quirk_data; void *pdata; + struct snd_soc_acpi_mach_params mach_params; const char *sof_fw_filename; const char *sof_tplg_filename; const char *asoc_plat_name; -- cgit v1.2.3 From b92826fa8c5a423edf6c9e385b5d433c61375cc8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 16 Nov 2018 18:47:05 -0600 Subject: ASoC: Intel: fix interface for Chromebook machine drivers The changes for HDaudio overlooked the fact that the machine drivers used for Chromebooks rely on the dmic number information passed as pdata. Add dmic_num field to standard interface and use standard interface instead of SKL-specific one. Also clean-up pdata definition to remove fields that are no longer used. Fixes: 842bb5135f10 ('ASoC: Intel: use standard interface for Hdaudio machine driver') Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/soc-acpi.h | 1 + sound/soc/intel/boards/kbl_rt5663_max98927.c | 10 +++++----- sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 10 +++++----- sound/soc/intel/boards/skl_nau88l25_max98357a.c | 10 +++++----- sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 10 +++++----- sound/soc/intel/skylake/skl.c | 2 +- sound/soc/intel/skylake/skl.h | 3 --- 7 files changed, 22 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index 5154c6359609..266e64e3c24c 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -48,6 +48,7 @@ struct snd_soc_acpi_mach_params { u32 acpi_ipc_irq_index; const char *platform; u32 codec_mask; + u32 dmic_num; }; /** diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 6ea969c0a5fb..c2a96940f9f2 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -25,9 +25,9 @@ #include #include #include +#include #include "../../codecs/rt5663.h" #include "../../codecs/hdac_hdmi.h" -#include "../skylake/skl.h" #include #include #include @@ -969,7 +969,7 @@ static struct snd_soc_card kabylake_audio_card_rt5663 = { static int kabylake_audio_probe(struct platform_device *pdev) { struct kbl_rt5663_private *ctx; - struct skl_machine_pdata *pdata; + struct snd_soc_acpi_mach *mach; int ret; ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); @@ -984,9 +984,9 @@ static int kabylake_audio_probe(struct platform_device *pdev) kabylake_audio_card->dev = &pdev->dev; snd_soc_card_set_drvdata(kabylake_audio_card, ctx); - pdata = dev_get_drvdata(&pdev->dev); - if (pdata) - dmic_constraints = pdata->dmic_num == 2 ? + mach = dev_get_drvdata(&pdev->dev); + if (mach) + dmic_constraints = mach->mach_params.dmic_num == 2 ? &constraints_dmic_2ch : &constraints_dmic_channels; ctx->mclk = devm_clk_get(&pdev->dev, "ssp1_mclk"); diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index a737c915d46a..d7df307b406f 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -26,10 +26,10 @@ #include #include #include +#include #include "../../codecs/rt5514.h" #include "../../codecs/rt5663.h" #include "../../codecs/hdac_hdmi.h" -#include "../skylake/skl.h" #define KBL_REALTEK_CODEC_DAI "rt5663-aif" #define KBL_REALTEK_DMIC_CODEC_DAI "rt5514-aif1" @@ -648,7 +648,7 @@ static struct snd_soc_card kabylake_audio_card = { static int kabylake_audio_probe(struct platform_device *pdev) { struct kbl_codec_private *ctx; - struct skl_machine_pdata *pdata; + struct snd_soc_acpi_mach *mach; ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -659,9 +659,9 @@ static int kabylake_audio_probe(struct platform_device *pdev) kabylake_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&kabylake_audio_card, ctx); - pdata = dev_get_drvdata(&pdev->dev); - if (pdata) - dmic_constraints = pdata->dmic_num == 2 ? + mach = dev_get_drvdata(&pdev->dev); + if (mach) + dmic_constraints = mach->mach_params.dmic_num == 2 ? &constraints_dmic_2ch : &constraints_dmic_channels; return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card); diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index 552958ce736d..931890f9aa74 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -21,9 +21,9 @@ #include #include #include +#include #include "../../codecs/nau8825.h" #include "../../codecs/hdac_hdmi.h" -#include "../skylake/skl.h" #define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" #define SKL_MAXIM_CODEC_DAI "HiFi" @@ -641,7 +641,7 @@ static struct snd_soc_card skylake_audio_card = { static int skylake_audio_probe(struct platform_device *pdev) { struct skl_nau8825_private *ctx; - struct skl_machine_pdata *pdata; + struct snd_soc_acpi_mach *mach; ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -652,9 +652,9 @@ static int skylake_audio_probe(struct platform_device *pdev) skylake_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&skylake_audio_card, ctx); - pdata = dev_get_drvdata(&pdev->dev); - if (pdata) - dmic_constraints = pdata->dmic_num == 2 ? + mach = dev_get_drvdata(&pdev->dev); + if (mach) + dmic_constraints = mach->mach_params.dmic_num == 2 ? &constraints_dmic_2ch : &constraints_dmic_channels; return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card); diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index f985b30a1d0e..657c650766fc 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -23,11 +23,11 @@ #include #include #include +#include #include #include #include "../../codecs/nau8825.h" #include "../../codecs/hdac_hdmi.h" -#include "../skylake/skl.h" #define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" #define SKL_SSM_CODEC_DAI "ssm4567-hifi" @@ -694,7 +694,7 @@ static struct snd_soc_card skylake_audio_card = { static int skylake_audio_probe(struct platform_device *pdev) { struct skl_nau88125_private *ctx; - struct skl_machine_pdata *pdata; + struct snd_soc_acpi_mach *mach; ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -705,9 +705,9 @@ static int skylake_audio_probe(struct platform_device *pdev) skylake_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&skylake_audio_card, ctx); - pdata = dev_get_drvdata(&pdev->dev); - if (pdata) - dmic_constraints = pdata->dmic_num == 2 ? + mach = dev_get_drvdata(&pdev->dev); + if (mach) + dmic_constraints = mach->mach_params.dmic_num == 2 ? &constraints_dmic_2ch : &constraints_dmic_channels; return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card); diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index ebab04b51bc1..b66d66acbc35 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -515,7 +515,7 @@ static int skl_find_machine(struct skl *skl, void *driver_data) if (pdata) { skl->use_tplg_pcm = pdata->use_tplg_pcm; - pdata->dmic_num = skl_get_dmic_geo(skl); + mach->mach_params.dmic_num = skl_get_dmic_geo(skl); } return 0; diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 8d48cd7c56c8..85f8bb6687dc 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -119,10 +119,7 @@ struct skl_dma_params { }; struct skl_machine_pdata { - u32 dmic_num; bool use_tplg_pcm; /* use dais and dai links from topology */ - const char *platform; - u32 codec_mask; }; struct skl_dsp_ops { -- cgit v1.2.3 From a48bf02b35d9325eedb56ab531038511695a2734 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 21 Nov 2018 02:10:51 +0000 Subject: ASoC: simple-card-utils: tidyup asoc_simple_card_parse_convert() Current simple-card-utils has asoc_simple_card_parse_convert() to parse convert channel/rate for be_hw_params_fixup. But, it is parsing from top of node. If sound card had multi subnode, we need to parse it from each sub node. This patch tidyup asoc_simple_card_parse_convert() to allow parsing settings from each node. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 3 ++- sound/soc/generic/audio-graph-scu-card.c | 2 +- sound/soc/generic/simple-card-utils.c | 5 +++-- sound/soc/generic/simple-scu-card.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index fb0318f9b10f..d1f17172dce2 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -116,7 +116,8 @@ int asoc_simple_card_clean_reference(struct snd_soc_card *card); void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data, struct snd_pcm_hw_params *params); -void asoc_simple_card_parse_convert(struct device *dev, char *prefix, +void asoc_simple_card_parse_convert(struct device *dev, + struct device_node *np, char *prefix, struct asoc_simple_card_data *data); int asoc_simple_card_of_parse_routing(struct snd_soc_card *card, diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c index 2ba35bdd3b38..1f754933ea9f 100644 --- a/sound/soc/generic/audio-graph-scu-card.c +++ b/sound/soc/generic/audio-graph-scu-card.c @@ -204,7 +204,7 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) if (ret < 0) return ret; - asoc_simple_card_parse_convert(dev, NULL, &priv->adata); + asoc_simple_card_parse_convert(dev, node, NULL, &priv->adata); /* * it supports multi CPU, single CODEC only here diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index f3183a4718b3..a16373193b56 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -32,10 +32,11 @@ void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data, } EXPORT_SYMBOL_GPL(asoc_simple_card_convert_fixup); -void asoc_simple_card_parse_convert(struct device *dev, char *prefix, +void asoc_simple_card_parse_convert(struct device *dev, + struct device_node *np, + char *prefix, struct asoc_simple_card_data *data) { - struct device_node *np = dev->of_node; char prop[128]; if (!prefix) diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index 85b46f0eae0f..2d3ef6ebe863 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -202,7 +202,7 @@ static int asoc_simple_card_parse_of(struct simple_card_data *priv) if (ret < 0) return ret; - asoc_simple_card_parse_convert(dev, PREFIX, &priv->adata); + asoc_simple_card_parse_convert(dev, node, PREFIX, &priv->adata); /* find 1st codec */ np = of_get_child_by_name(node, PREFIX "codec"); -- cgit v1.2.3 From 33404f3f10beaf0d69d8765f5804b6fb3b305f0f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 21 Nov 2018 02:11:13 +0000 Subject: ASoC: simple_card_utils: remove "option" from asoc_simple_card_of_parse_routing() asoc_simple_card_of_parse_routing() had "option" parameter to consider error handling, but it is very pointless parameter. Let's remove it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 3 +-- sound/soc/generic/audio-graph-card.c | 2 +- sound/soc/generic/audio-graph-scu-card.c | 2 +- sound/soc/generic/simple-card-utils.c | 10 +++------- sound/soc/generic/simple-card.c | 2 +- sound/soc/generic/simple-scu-card.c | 2 +- 6 files changed, 8 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index d1f17172dce2..6d69ed2bd7b1 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -121,8 +121,7 @@ void asoc_simple_card_parse_convert(struct device *dev, struct asoc_simple_card_data *data); int asoc_simple_card_of_parse_routing(struct snd_soc_card *card, - char *prefix, - int optional); + char *prefix); int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card, char *prefix); diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 26eb6ff9b9f3..101c7da2df7c 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -238,7 +238,7 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) if (ret < 0) return ret; - ret = asoc_simple_card_of_parse_routing(card, NULL, 1); + ret = asoc_simple_card_of_parse_routing(card, NULL); if (ret < 0) return ret; diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c index 1f754933ea9f..c46947393f80 100644 --- a/sound/soc/generic/audio-graph-scu-card.c +++ b/sound/soc/generic/audio-graph-scu-card.c @@ -200,7 +200,7 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) * see simple-card */ - ret = asoc_simple_card_of_parse_routing(card, NULL, 0); + ret = asoc_simple_card_of_parse_routing(card, NULL); if (ret < 0) return ret; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index a16373193b56..c69ce1e563cd 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -417,8 +417,7 @@ int asoc_simple_card_clean_reference(struct snd_soc_card *card) EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference); int asoc_simple_card_of_parse_routing(struct snd_soc_card *card, - char *prefix, - int optional) + char *prefix) { struct device_node *node = card->dev->of_node; char prop[128]; @@ -428,11 +427,8 @@ int asoc_simple_card_of_parse_routing(struct snd_soc_card *card, snprintf(prop, sizeof(prop), "%s%s", prefix, "routing"); - if (!of_property_read_bool(node, prop)) { - if (optional) - return 0; - return -EINVAL; - } + if (!of_property_read_bool(node, prop)) + return 0; return snd_soc_of_parse_audio_routing(card, prop); } diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 5a3f59aa4ba5..ff3f9fa9ab5a 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -300,7 +300,7 @@ static int asoc_simple_card_parse_of(struct simple_card_data *priv) if (ret < 0) goto card_parse_end; - ret = asoc_simple_card_of_parse_routing(card, PREFIX, 1); + ret = asoc_simple_card_of_parse_routing(card, PREFIX); if (ret < 0) goto card_parse_end; diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index 2d3ef6ebe863..e650143eb532 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -198,7 +198,7 @@ static int asoc_simple_card_parse_of(struct simple_card_data *priv) if (ret < 0) return ret; - ret = asoc_simple_card_of_parse_routing(card, PREFIX, 0); + ret = asoc_simple_card_of_parse_routing(card, PREFIX); if (ret < 0) return ret; -- cgit v1.2.3 From 3b7103562c03cffb1a351f8c235b3bba2acd9e9b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 22 Nov 2018 00:55:09 +0000 Subject: ASoC: soc-core: add snd_soc_of_parse_node_prefix() Current ASoC has snd_soc_of_parse_audio_prefix() to get codec_conf settings from DT which is used to avoid DAI naming conflict when CPU/Codec matching. Currently, it is parsing from "top node", but, we want to parse from "each sub node" if sound card had multi cpus/codecs. This patch adds new snd_soc_of_parse_node_prefix() to allow parsing settings from selected node. It is keeping existing snd_soc_of_parse_audio_prefix() by using macro. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 6 +++++- sound/soc/soc-core.c | 11 +++++------ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 5a8b84140f01..93b7510e7f7d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1477,10 +1477,14 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np, unsigned int *rx_mask, unsigned int *slots, unsigned int *slot_width); -void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, +void snd_soc_of_parse_node_prefix(struct device_node *np, struct snd_soc_codec_conf *codec_conf, struct device_node *of_node, const char *propname); +#define snd_soc_of_parse_audio_prefix(card, conf, node, name) \ + snd_soc_of_parse_node_prefix((card)->dev->of_node, \ + (conf), (node), (name)) + int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6ddcf12bc030..012000de4bf0 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3484,12 +3484,11 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); -void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, - struct snd_soc_codec_conf *codec_conf, - struct device_node *of_node, - const char *propname) +void snd_soc_of_parse_node_prefix(struct device_node *np, + struct snd_soc_codec_conf *codec_conf, + struct device_node *of_node, + const char *propname) { - struct device_node *np = card->dev->of_node; const char *str; int ret; @@ -3502,7 +3501,7 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, codec_conf->of_node = of_node; codec_conf->name_prefix = str; } -EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix); +EXPORT_SYMBOL_GPL(snd_soc_of_parse_node_prefix); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname) -- cgit v1.2.3 From 33b2e1442aeaacabb4e29f8adb31469e87599b16 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 23 Nov 2018 13:13:03 +0900 Subject: ALSA: firewire-tascam: pick up data of state from tx isochronous pakcets Units of TASCAM FireWire series multiplex PCM frames and state of control surface into the same tx isochronous packets. One isochronous packet includes a part of the state in a quadlet data. An image of the state consists of 64 quadlet data. This commit demultiplexes the state from tx isochronous packets. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- include/uapi/sound/firewire.h | 2 ++ sound/firewire/tascam/amdtp-tascam.c | 17 ++++++++++++++++- sound/firewire/tascam/tascam.h | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index f0a547d86679..b9bc4bb1756b 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -88,4 +88,6 @@ struct snd_firewire_get_info { * Returns -EBUSY if the driver is already streaming. */ +#define SNDRV_FIREWIRE_TASCAM_STATE_COUNT 64 + #endif /* _UAPI_SOUND_FIREWIRE_H_INCLUDED */ diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index ab482423c165..516cb931fd5e 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -117,6 +117,21 @@ int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s, return amdtp_stream_add_pcm_hw_constraints(s, runtime); } +static void read_status_messages(struct amdtp_stream *s, + __be32 *buffer, unsigned int data_blocks) +{ + struct snd_tscm *tscm = container_of(s, struct snd_tscm, tx_stream); + int i; + + for (i = 0; i < data_blocks; i++) { + unsigned int index; + + index = be32_to_cpu(buffer[0]) % SNDRV_FIREWIRE_TASCAM_STATE_COUNT; + tscm->state[index] = buffer[s->data_block_quadlets - 1]; + buffer += s->data_block_quadlets; + } +} + static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffer, unsigned int data_blocks, @@ -128,7 +143,7 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, if (data_blocks > 0 && pcm) read_pcm_s32(s, pcm, buffer, data_blocks); - /* A place holder for control messages. */ + read_status_messages(s, buffer, data_blocks); return data_blocks; } diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index a5bd167eb5d9..c710496a99cf 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -89,6 +89,9 @@ struct snd_tscm { /* For MIDI message outgoing transactions. */ struct snd_fw_async_midi_port out_ports[TSCM_MIDI_OUT_PORT_MAX]; + + // A cache of status information in tx isoc packets. + __be32 state[SNDRV_FIREWIRE_TASCAM_STATE_COUNT]; }; #define TSCM_ADDR_BASE 0xffff00000000ull -- cgit v1.2.3 From 90e8ac5c9d446124a5b43a6f135bf67e060c0c9d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 23 Nov 2018 13:13:04 +0900 Subject: ALSA: firewire-tascam: add new hwdep ioctl command to get state image In a previous commit, ALSA firewire-tascam driver stores state image from tx isochronous packets. This image includes states of knob, fader, button of control surface, level of gain/volume of each physical inputs/outputs, and so on. It's useful for userspace applications to read whole of the image. This commit adds a unique ioctl command for ALSA hwdep interface for the purpose. For actual meaning of each bits in this image, please refer to discussion in alsa-devel[1]. [1] http://mailman.alsa-project.org/pipermail/alsa-devel/2018-October/140785.html Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- include/uapi/sound/firewire.h | 5 +++++ sound/firewire/tascam/tascam-hwdep.c | 10 ++++++++++ 2 files changed, 15 insertions(+) (limited to 'include') diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index b9bc4bb1756b..012f81bf4750 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -66,6 +66,7 @@ union snd_firewire_event { #define SNDRV_FIREWIRE_IOCTL_GET_INFO _IOR('H', 0xf8, struct snd_firewire_get_info) #define SNDRV_FIREWIRE_IOCTL_LOCK _IO('H', 0xf9) #define SNDRV_FIREWIRE_IOCTL_UNLOCK _IO('H', 0xfa) +#define SNDRV_FIREWIRE_IOCTL_TASCAM_STATE _IOR('H', 0xfb, struct snd_firewire_tascam_state) #define SNDRV_FIREWIRE_TYPE_DICE 1 #define SNDRV_FIREWIRE_TYPE_FIREWORKS 2 @@ -90,4 +91,8 @@ struct snd_firewire_get_info { #define SNDRV_FIREWIRE_TASCAM_STATE_COUNT 64 +struct snd_firewire_tascam_state { + __be32 data[SNDRV_FIREWIRE_TASCAM_STATE_COUNT]; +}; + #endif /* _UAPI_SOUND_FIREWIRE_H_INCLUDED */ diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 4e4c1e9020e8..a80397116c48 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -123,6 +123,14 @@ static int hwdep_unlock(struct snd_tscm *tscm) return err; } +static int tscm_hwdep_state(struct snd_tscm *tscm, void __user *arg) +{ + if (copy_to_user(arg, tscm->state, sizeof(tscm->state))) + return -EFAULT; + + return 0; +} + static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) { struct snd_tscm *tscm = hwdep->private_data; @@ -147,6 +155,8 @@ static int hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file, return hwdep_lock(tscm); case SNDRV_FIREWIRE_IOCTL_UNLOCK: return hwdep_unlock(tscm); + case SNDRV_FIREWIRE_IOCTL_TASCAM_STATE: + return tscm_hwdep_state(tscm, (void __user *)arg); default: return -ENOIOCTLCMD; } -- cgit v1.2.3 From d7167422433cdb61e58baee9c25543d0eba95c9d Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 23 Nov 2018 13:13:05 +0900 Subject: ALSA: firewire-tascam: queue events for change of control surface Units of TASCAM FireWire series transfer image of states of the unit in tx isochronous packets. Demultiplexing of the states from the packets is done in software interrupt context regardless of any process context. In a view of userspace applications, it needs to have notification mechanism to catch change of the states. This commit implements a queue to store events for the notification. The image of states includes fluctuating data such as level of gain/volume for physical input/output and position of knobs. Therefore the events are queued corresponding to some control features only. Furthermore, the queued events are planned to be consumed by userspace applications via ALSA hwdep interface. This commit suppresses event queueing when no applications open the hwdep interface. However, the queue is maintained in an optimistic scenario, thus without any care against overrrun. This is reasonable because target events are useless just to handle PCM frames. It starts queueing when an usespace application opens hwdep interface, thus it's expected to read the queued events steadily. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- include/uapi/sound/firewire.h | 6 ++++++ sound/firewire/tascam/amdtp-tascam.c | 34 +++++++++++++++++++++++++++++++++- sound/firewire/tascam/tascam-hwdep.c | 2 ++ sound/firewire/tascam/tascam.h | 6 ++++++ 4 files changed, 47 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index 012f81bf4750..bb067efb09c6 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -53,6 +53,12 @@ struct snd_firewire_event_motu_notification { __u32 message; /* MOTU-specific bits. */ }; +struct snd_firewire_tascam_change { + unsigned int index; + __be32 before; + __be32 after; +}; + union snd_firewire_event { struct snd_firewire_event_common common; struct snd_firewire_event_lock_status lock_status; diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 516cb931fd5e..0e8088c9ada9 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -121,13 +121,45 @@ static void read_status_messages(struct amdtp_stream *s, __be32 *buffer, unsigned int data_blocks) { struct snd_tscm *tscm = container_of(s, struct snd_tscm, tx_stream); + bool used = READ_ONCE(tscm->hwdep->used); int i; for (i = 0; i < data_blocks; i++) { unsigned int index; + __be32 before; + __be32 after; index = be32_to_cpu(buffer[0]) % SNDRV_FIREWIRE_TASCAM_STATE_COUNT; - tscm->state[index] = buffer[s->data_block_quadlets - 1]; + before = tscm->state[index]; + after = buffer[s->data_block_quadlets - 1]; + + if (used && index > 4 && index < 16) { + __be32 mask; + + if (index == 5) + mask = cpu_to_be32(~0x0000ffff); + else if (index == 6) + mask = cpu_to_be32(~0x0000ffff); + else if (index == 8) + mask = cpu_to_be32(~0x000f0f00); + else + mask = cpu_to_be32(~0x00000000); + + if ((before ^ after) & mask) { + struct snd_firewire_tascam_change *entry = + &tscm->queue[tscm->push_pos]; + + spin_lock_irq(&tscm->lock); + entry->index = index; + entry->before = before; + entry->after = after; + if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT) + tscm->push_pos = 0; + spin_unlock_irq(&tscm->lock); + } + } + + tscm->state[index] = after; buffer += s->data_block_quadlets; } } diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index a80397116c48..9afa827af05d 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -195,5 +195,7 @@ int snd_tscm_create_hwdep_device(struct snd_tscm *tscm) hwdep->private_data = tscm; hwdep->exclusive = true; + tscm->hwdep = hwdep; + return err; } diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index c710496a99cf..6a411ee0dcf1 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -62,6 +62,8 @@ struct snd_fw_async_midi_port { int consume_bytes; }; +#define SND_TSCM_QUEUE_COUNT 16 + struct snd_tscm { struct snd_card *card; struct fw_unit *unit; @@ -92,6 +94,10 @@ struct snd_tscm { // A cache of status information in tx isoc packets. __be32 state[SNDRV_FIREWIRE_TASCAM_STATE_COUNT]; + struct snd_hwdep *hwdep; + struct snd_firewire_tascam_change queue[SND_TSCM_QUEUE_COUNT]; + unsigned int pull_pos; + unsigned int push_pos; }; #define TSCM_ADDR_BASE 0xffff00000000ull -- cgit v1.2.3 From a8c0d13267a4151b2ff124cde6331ec28ed0d55e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Fri, 23 Nov 2018 13:13:07 +0900 Subject: ALSA: firewire-tascam: notify events of change of state for userspace applications In former commits, ALSA firewire-tascam driver queues events to notify change of state of control surface to userspace via ALSA hwdep interface. This commit implements actual notification of the events. The events are not governed by real time, thus no need to care underrun. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- include/uapi/sound/firewire.h | 7 ++++ sound/firewire/tascam/amdtp-tascam.c | 2 ++ sound/firewire/tascam/tascam-hwdep.c | 65 ++++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index bb067efb09c6..ae12826ed641 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -12,6 +12,7 @@ #define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e617475 #define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c #define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x64776479 +#define SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL 0x7473636d struct snd_firewire_event_common { unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */ @@ -59,12 +60,18 @@ struct snd_firewire_tascam_change { __be32 after; }; +struct snd_firewire_event_tascam_control { + unsigned int type; + struct snd_firewire_tascam_change changes[0]; +}; + union snd_firewire_event { struct snd_firewire_event_common common; struct snd_firewire_event_lock_status lock_status; struct snd_firewire_event_dice_notification dice_notification; struct snd_firewire_event_efw_response efw_response; struct snd_firewire_event_digi00x_message digi00x_message; + struct snd_firewire_event_tascam_control tascam_control; struct snd_firewire_event_motu_notification motu_notification; }; diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 0e8088c9ada9..a52d1f76c610 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -156,6 +156,8 @@ static void read_status_messages(struct amdtp_stream *s, if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT) tscm->push_pos = 0; spin_unlock_irq(&tscm->lock); + + wake_up(&tscm->hwdep_wait); } } diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 8f34cede2e9f..0414abf5daa8 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -35,6 +35,65 @@ static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf, return count; } +static long tscm_hwdep_read_queue(struct snd_tscm *tscm, char __user *buf, + long remained, loff_t *offset) +{ + char __user *pos = buf; + unsigned int type = SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL; + struct snd_firewire_tascam_change *entries = tscm->queue; + long count; + + // At least, one control event can be copied. + if (remained < sizeof(type) + sizeof(*entries)) { + spin_unlock_irq(&tscm->lock); + return -EINVAL; + } + + // Copy the type field later. + count = sizeof(type); + remained -= sizeof(type); + pos += sizeof(type); + + while (true) { + unsigned int head_pos; + unsigned int tail_pos; + unsigned int length; + + if (tscm->pull_pos == tscm->push_pos) + break; + else if (tscm->pull_pos < tscm->push_pos) + tail_pos = tscm->push_pos; + else + tail_pos = SND_TSCM_QUEUE_COUNT; + head_pos = tscm->pull_pos; + + length = (tail_pos - head_pos) * sizeof(*entries); + if (remained < length) + length = rounddown(remained, sizeof(*entries)); + if (length == 0) + break; + + spin_unlock_irq(&tscm->lock); + if (copy_to_user(pos, &entries[head_pos], length)) + return -EFAULT; + + spin_lock_irq(&tscm->lock); + + tscm->pull_pos = tail_pos % SND_TSCM_QUEUE_COUNT; + + count += length; + remained -= length; + pos += length; + } + + spin_unlock_irq(&tscm->lock); + + if (copy_to_user(buf, &type, sizeof(type))) + return -EFAULT; + + return count; +} + static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, loff_t *offset) { @@ -43,7 +102,7 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, spin_lock_irq(&tscm->lock); - while (!tscm->dev_lock_changed) { + while (!tscm->dev_lock_changed && tscm->push_pos == tscm->pull_pos) { prepare_to_wait(&tscm->hwdep_wait, &wait, TASK_INTERRUPTIBLE); spin_unlock_irq(&tscm->lock); schedule(); @@ -56,6 +115,8 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, // NOTE: The acquired lock should be released in callee side. if (tscm->dev_lock_changed) { count = tscm_hwdep_read_locked(tscm, buf, count, offset); + } else if (tscm->push_pos != tscm->pull_pos) { + count = tscm_hwdep_read_queue(tscm, buf, count, offset); } else { spin_unlock_irq(&tscm->lock); count = 0; @@ -73,7 +134,7 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_wait(file, &tscm->hwdep_wait, wait); spin_lock_irq(&tscm->lock); - if (tscm->dev_lock_changed) + if (tscm->dev_lock_changed || tscm->push_pos != tscm->pull_pos) events = EPOLLIN | EPOLLRDNORM; else events = 0; -- cgit v1.2.3 From 2708bccf9c6f142c3ef5a27f15d34febe751ce4c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 26 Nov 2018 01:21:22 +0000 Subject: ASoC: soc.h: makes snd_soc_of_parse_audio_prefix() inline commit 3b7103562c03c ("ASoC: soc-core: add snd_soc_of_parse_node_prefix()") maked snd_soc_of_parse_audio_prefix() as #define. But it'd be better to make this a static inline rather than a #define. It helps with error messages and type safety. This patch makes it inline. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/soc.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/sound/soc.h b/include/sound/soc.h index 93b7510e7f7d..66aafadcf5ef 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1481,9 +1481,15 @@ void snd_soc_of_parse_node_prefix(struct device_node *np, struct snd_soc_codec_conf *codec_conf, struct device_node *of_node, const char *propname); -#define snd_soc_of_parse_audio_prefix(card, conf, node, name) \ - snd_soc_of_parse_node_prefix((card)->dev->of_node, \ - (conf), (node), (name)) +static inline +void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, + struct snd_soc_codec_conf *codec_conf, + struct device_node *of_node, + const char *propname) +{ + snd_soc_of_parse_node_prefix(card->dev->of_node, + codec_conf, of_node, propname); +} int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); -- cgit v1.2.3 From faa2541f5b1afa8b6d777a73bc2f27d5c8c98695 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Nov 2018 17:47:44 +0100 Subject: leds: trigger: Introduce audio mute LED trigger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new LED trigger for coupling the audio mixer change with the LED on laptops or other devices. Currently there are two trigger types, "audio-mute" and "audio-micmute". The audio driver triggers the LED brightness change via ledtrig_audio_set() call with the proper type (either mute or mic-mute). OTOH, the consumers may call ledtrig_audio_get() for the initial brightness value that may have been set by the audio driver beforehand. This new stuff will be used by HD-audio codec driver and some platform drivers (thinkpad_acpi and dell-laptop, also upcoming huawei-wmi). Acked-by: Jacek Anaszewski Acked-by: Pavel Machek Acked-by: Pali Rohár Signed-off-by: Takashi Iwai --- drivers/leds/trigger/Kconfig | 7 ++++++ drivers/leds/trigger/Makefile | 1 + drivers/leds/trigger/ledtrig-audio.c | 44 ++++++++++++++++++++++++++++++++++++ include/linux/leds.h | 20 ++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 drivers/leds/trigger/ledtrig-audio.c (limited to 'include') diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index b76fc3cdc8f8..23cc85e2e0e5 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -136,4 +136,11 @@ config LEDS_TRIGGER_PATTERN which is a series of tuples, of brightness and duration (ms). If unsure, say N +config LEDS_TRIGGER_AUDIO + tristate "Audio Mute LED Trigger" + help + This allows LEDs to be controlled by audio drivers for following + the audio mute and mic-mute changes. + If unsure, say N + endif # LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 9bcb64ee8123..733a83e2a718 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o obj-$(CONFIG_LEDS_TRIGGER_PATTERN) += ledtrig-pattern.o +obj-$(CONFIG_LEDS_TRIGGER_AUDIO) += ledtrig-audio.o diff --git a/drivers/leds/trigger/ledtrig-audio.c b/drivers/leds/trigger/ledtrig-audio.c new file mode 100644 index 000000000000..f76621e88482 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-audio.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Audio Mute LED trigger +// + +#include +#include +#include + +static struct led_trigger *ledtrig_audio[NUM_AUDIO_LEDS]; +static enum led_brightness audio_state[NUM_AUDIO_LEDS]; + +enum led_brightness ledtrig_audio_get(enum led_audio type) +{ + return audio_state[type]; +} +EXPORT_SYMBOL_GPL(ledtrig_audio_get); + +void ledtrig_audio_set(enum led_audio type, enum led_brightness state) +{ + audio_state[type] = state; + led_trigger_event(ledtrig_audio[type], state); +} +EXPORT_SYMBOL_GPL(ledtrig_audio_set); + +static int __init ledtrig_audio_init(void) +{ + led_trigger_register_simple("audio-mute", + &ledtrig_audio[LED_AUDIO_MUTE]); + led_trigger_register_simple("audio-micmute", + &ledtrig_audio[LED_AUDIO_MICMUTE]); + return 0; +} +module_init(ledtrig_audio_init); + +static void __exit ledtrig_audio_exit(void) +{ + led_trigger_unregister_simple(ledtrig_audio[LED_AUDIO_MUTE]); + led_trigger_unregister_simple(ledtrig_audio[LED_AUDIO_MICMUTE]); +} +module_exit(ledtrig_audio_exit); + +MODULE_DESCRIPTION("LED trigger for audio mute control"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/leds.h b/include/linux/leds.h index 7393a316d9fa..580cbaef789a 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -487,4 +487,24 @@ struct led_pattern { int brightness; }; +enum led_audio { + LED_AUDIO_MUTE, /* master mute LED */ + LED_AUDIO_MICMUTE, /* mic mute LED */ + NUM_AUDIO_LEDS +}; + +#if IS_ENABLED(CONFIG_LEDS_TRIGGER_AUDIO) +enum led_brightness ledtrig_audio_get(enum led_audio type); +void ledtrig_audio_set(enum led_audio type, enum led_brightness state); +#else +static inline enum led_brightness ledtrig_audio_get(enum led_audio type) +{ + return LED_OFF; +} +static inline void ledtrig_audio_set(enum led_audio type, + enum led_brightness state) +{ +} +#endif + #endif /* __LINUX_LEDS_H_INCLUDED */ -- cgit v1.2.3 From bc184549853133303cf08d1f19477f9c87ef39fb Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 16 Nov 2018 15:41:41 +0200 Subject: ASoC: davinci-mcasp: Implement configurable dismod handling If the dismod is specified in the DT node, use the specified custom value to configure the drive on state of the inactive TX slots. If the dismod is not present or booted in legacy mode, the dismod is set to low as it was the original behavior. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- include/linux/platform_data/davinci_asp.h | 1 + sound/soc/davinci/davinci-mcasp.c | 19 ++++++++++++++++++- sound/soc/davinci/davinci-mcasp.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index 85ad68f9206a..7fe80f1c7e08 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -79,6 +79,7 @@ struct davinci_mcasp_pdata { /* McASP specific fields */ int tdm_slots; u8 op_mode; + u8 dismod; u8 num_serializer; u8 *serial_dir; u8 version; diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 0f3911be1c8e..40d3a916fb74 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -85,6 +85,7 @@ struct davinci_mcasp { u32 tdm_mask[2]; int slot_width; u8 op_mode; + u8 dismod; u8 num_serializer; u8 *serial_dir; u8 version; @@ -834,7 +835,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, if (mcasp->serial_dir[i] == TX_MODE && tx_ser < max_active_serializers) { mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), - DISMOD_LOW, DISMOD_MASK); + mcasp->dismod, DISMOD_MASK); set_bit(PIN_BIT_AXR(i), &mcasp->pdir); tx_ser++; } else if (mcasp->serial_dir[i] == RX_MODE && @@ -847,6 +848,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); } else if (mcasp->serial_dir[i] == TX_MODE) { /* Unused TX pins, clear PDIR */ + mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), + mcasp->dismod, DISMOD_MASK); clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); } } @@ -1709,6 +1712,7 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( if (pdev->dev.platform_data) { pdata = pdev->dev.platform_data; + pdata->dismod = DISMOD_LOW; return pdata; } else if (match) { pdata = devm_kmemdup(&pdev->dev, match->data, sizeof(*pdata), @@ -1798,6 +1802,18 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( if (ret >= 0) pdata->sram_size_capture = val; + ret = of_property_read_u32(np, "dismod", &val); + if (ret >= 0) { + if (val == 0 || val == 2 || val == 3) { + pdata->dismod = DISMOD_VAL(val); + } else { + dev_warn(&pdev->dev, "Invalid dismod value: %u\n", val); + pdata->dismod = DISMOD_LOW; + } + } else { + pdata->dismod = DISMOD_LOW; + } + return pdata; nodata: @@ -1973,6 +1989,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) mcasp->version = pdata->version; mcasp->txnumevt = pdata->txnumevt; mcasp->rxnumevt = pdata->rxnumevt; + mcasp->dismod = pdata->dismod; mcasp->dev = &pdev->dev; diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index acb024ab6a9d..5e4060d8fe56 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -209,6 +209,7 @@ #define DISMOD_3STATE (0x0) #define DISMOD_LOW (0x2 << 2) #define DISMOD_HIGH (0x3 << 2) +#define DISMOD_VAL(x) ((x) << 2) #define DISMOD_MASK DISMOD_HIGH #define TXSTATE BIT(4) #define RXSTATE BIT(5) -- cgit v1.2.3 From f783e128a6f1484d72ceab06d483ea32df0ce333 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Nov 2018 17:47:46 +0100 Subject: platform/x86: dell-laptop: Drop superfluous exported function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we've switched to the LED trigger for binding with HD-audio, we can drop the exported function as well as the whole linux/dell-led.h. Acked-by: Jacek Anaszewski Acked-by: Pavel Machek Acked-by: Andy Shevchenko Acked-by: Pali Rohár Signed-off-by: Takashi Iwai --- drivers/platform/x86/dell-laptop.c | 22 +++++----------------- include/linux/dell-led.h | 7 ------- 2 files changed, 5 insertions(+), 24 deletions(-) delete mode 100644 include/linux/dell-led.h (limited to 'include') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 0db2dbf7b0d1..fb071e6a5058 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include "dell-rbtn.h" @@ -2109,17 +2108,17 @@ static struct notifier_block dell_laptop_notifier = { .notifier_call = dell_laptop_notifier_call, }; -int dell_micmute_led_set(int state) +static int micmute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) { struct calling_interface_buffer buffer; struct calling_interface_token *token; + int state = brightness != LED_OFF; if (state == 0) token = dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE); - else if (state == 1) - token = dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE); else - return -EINVAL; + token = dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE); if (!token) return -ENODEV; @@ -2127,18 +2126,7 @@ int dell_micmute_led_set(int state) dell_fill_request(&buffer, token->location, token->value, 0, 0); dell_send_request(&buffer, CLASS_TOKEN_WRITE, SELECT_TOKEN_STD); - return state; -} -EXPORT_SYMBOL_GPL(dell_micmute_led_set); - -static int micmute_led_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - int state = brightness != LED_OFF; - int err; - - err = dell_micmute_led_set(state); - return err < 0 ? err : 0; + return 0; } static struct led_classdev micmute_led_cdev = { diff --git a/include/linux/dell-led.h b/include/linux/dell-led.h deleted file mode 100644 index 92521471517f..000000000000 --- a/include/linux/dell-led.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __DELL_LED_H__ -#define __DELL_LED_H__ - -int dell_micmute_led_set(int on); - -#endif -- cgit v1.2.3 From 9e908a180e6a90fa102d5d3f96ca86825f43e4fb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Nov 2018 17:47:47 +0100 Subject: platform/x86: thinkpad_acpi: Drop superfluous exported function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we've switched to the LED trigger for binding with HD-audio, we can drop the exported function as well as the whole linux/thinkpad_acpi.h. The own TPACPI_LED_MUTE and TPACPI_LED_MICMUTE definitions are replaced with the identical ones for LEDS, i.e. LED_AUDIO_MUTE and LED_AUDIO_MICMUTE, respectively. They are no longer needed as referred only locally. Acked-by: Jacek Anaszewski Acked-by: Pavel Machek Acked-by: Andy Shevchenko Acked-by: Henrique de Moraes Holschuh Acked-by: Pali Rohár Signed-off-by: Takashi Iwai --- drivers/platform/x86/thinkpad_acpi.c | 30 +++++++++++------------------- include/linux/thinkpad_acpi.h | 16 ---------------- 2 files changed, 11 insertions(+), 35 deletions(-) delete mode 100644 include/linux/thinkpad_acpi.h (limited to 'include') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 3d2c1f5f22e2..21ffb961585a 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -81,7 +81,6 @@ #include #include #include -#include #include #include #include @@ -9150,6 +9149,7 @@ static struct ibm_struct fan_driver_data = { * Mute LED subdriver */ +#define TPACPI_LED_MAX 2 struct tp_led_table { acpi_string name; @@ -9158,13 +9158,13 @@ struct tp_led_table { int state; }; -static struct tp_led_table led_tables[] = { - [TPACPI_LED_MUTE] = { +static struct tp_led_table led_tables[TPACPI_LED_MAX] = { + [LED_AUDIO_MUTE] = { .name = "SSMS", .on_value = 1, .off_value = 0, }, - [TPACPI_LED_MICMUTE] = { + [LED_AUDIO_MICMUTE] = { .name = "MMTS", .on_value = 2, .off_value = 0, @@ -9189,40 +9189,36 @@ static int mute_led_on_off(struct tp_led_table *t, bool state) return state; } -int tpacpi_led_set(int whichled, bool on) +static int tpacpi_led_set(int whichled, bool on) { struct tp_led_table *t; - if (whichled < 0 || whichled >= TPACPI_LED_MAX) - return -EINVAL; - t = &led_tables[whichled]; if (t->state < 0 || t->state == on) return t->state; return mute_led_on_off(t, on); } -EXPORT_SYMBOL_GPL(tpacpi_led_set); static int tpacpi_led_mute_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - return tpacpi_led_set(TPACPI_LED_MUTE, brightness != LED_OFF); + return tpacpi_led_set(LED_AUDIO_MUTE, brightness != LED_OFF); } static int tpacpi_led_micmute_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - return tpacpi_led_set(TPACPI_LED_MICMUTE, brightness != LED_OFF); + return tpacpi_led_set(LED_AUDIO_MICMUTE, brightness != LED_OFF); } -static struct led_classdev mute_led_cdev[] = { - [TPACPI_LED_MUTE] = { +static struct led_classdev mute_led_cdev[TPACPI_LED_MAX] = { + [LED_AUDIO_MUTE] = { .name = "platform::mute", .max_brightness = 1, .brightness_set_blocking = tpacpi_led_mute_set, .default_trigger = "audio-mute", }, - [TPACPI_LED_MICMUTE] = { + [LED_AUDIO_MICMUTE] = { .name = "platform::micmute", .max_brightness = 1, .brightness_set_blocking = tpacpi_led_micmute_set, @@ -9232,10 +9228,6 @@ static struct led_classdev mute_led_cdev[] = { static int mute_led_init(struct ibm_init_struct *iibm) { - static enum led_audio types[] = { - [TPACPI_LED_MUTE] = LED_AUDIO_MUTE, - [TPACPI_LED_MICMUTE] = LED_AUDIO_MICMUTE, - }; acpi_handle temp; int i, err; @@ -9246,7 +9238,7 @@ static int mute_led_init(struct ibm_init_struct *iibm) continue; } - mute_led_cdev[i].brightness = ledtrig_audio_get(types[i]); + mute_led_cdev[i].brightness = ledtrig_audio_get(i); err = led_classdev_register(&tpacpi_pdev->dev, &mute_led_cdev[i]); if (err < 0) { while (i--) { diff --git a/include/linux/thinkpad_acpi.h b/include/linux/thinkpad_acpi.h deleted file mode 100644 index 9fb317970c01..000000000000 --- a/include/linux/thinkpad_acpi.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __THINKPAD_ACPI_H__ -#define __THINKPAD_ACPI_H__ - -/* These two functions return 0 if success, or negative error code - (e g -ENODEV if no led present) */ - -enum { - TPACPI_LED_MUTE, - TPACPI_LED_MICMUTE, - TPACPI_LED_MAX, -}; - -int tpacpi_led_set(int whichled, bool on); - -#endif -- cgit v1.2.3 From 9923e9072d813e2efa591d01e6971e0833c38815 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 30 Nov 2018 18:54:37 -0600 Subject: ASoC: Intel: common: add ACPI matching tables for ICL Entry needed for ICL RVP w/ RT274 Signed-off-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- include/sound/soc-acpi-intel-match.h | 1 + sound/soc/intel/common/Makefile | 2 +- sound/soc/intel/common/soc-acpi-intel-icl-match.c | 32 +++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 sound/soc/intel/common/soc-acpi-intel-icl-match.c (limited to 'include') diff --git a/include/sound/soc-acpi-intel-match.h b/include/sound/soc-acpi-intel-match.h index f48f59e5b7b0..bb5e1e4ce8bf 100644 --- a/include/sound/soc-acpi-intel-match.h +++ b/include/sound/soc-acpi-intel-match.h @@ -24,6 +24,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[]; /* * generic table used for HDA codec-based platforms, possibly with diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index c1f50a079d34..56c81e20b5bf 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -7,7 +7,7 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m soc-acpi-intel-hsw-bdw-match.o \ soc-acpi-intel-skl-match.o soc-acpi-intel-kbl-match.o \ soc-acpi-intel-bxt-match.o soc-acpi-intel-glk-match.o \ - soc-acpi-intel-cnl-match.o \ + soc-acpi-intel-cnl-match.o soc-acpi-intel-icl-match.o \ soc-acpi-intel-hda-match.o obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c new file mode 100644 index 000000000000..33b441dca4d3 --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * soc-apci-intel-icl-match.c - tables and support for ICL ACPI enumeration. + * + * Copyright (c) 2018, Intel Corporation. + * + */ + +#include +#include +#include "../skylake/skl.h" + +static struct skl_machine_pdata icl_pdata = { + .use_tplg_pcm = true, +}; + +struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[] = { + { + .id = "INT34C2", + .drv_name = "icl_rt274", + .fw_filename = "intel/dsp_fw_icl.bin", + .pdata = &icl_pdata, + .sof_fw_filename = "intel/sof-icl.ri", + .sof_tplg_filename = "intel/sof-icl-rt274.tplg", + .asoc_plat_name = "0000:00:1f.3", + }, + {}, +}; +EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_icl_machines); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel Common ACPI Match module"); -- cgit v1.2.3 From 029d92c289bdad08ed08e61bf31b17cdc9ee61cf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 8 Dec 2018 17:31:49 +0100 Subject: ALSA: hda: Refactor display power management The current HD-audio code manages the DRM audio power via too complex redirections, and this seems even still unbalanced in a corner case as Intel DRM CI has been intermittently reporting. This patch is a big surgery for addressing the complexity and the possible unbalance. Basically the patch changes the display PM in the following ways: - Both HD-audio controller and codec drivers call a single helper, snd_hdac_display_power(). (Formerly, the display power control from a codec was done indirectly via link_power bus ops.) - snd_hdac_display_power() receives the codec address index. For turning on/off from the controller, pass HDA_CODEC_IDX_CONTROLLER. - snd_hdac_display_power() doesn't manage refcounts any longer, but keeps the power status in bitmap. If any of controller or codecs is turned on, the function updates the DRM power state via get_power() or put_power(). Also this refactor allows us more cleanup: - The link_power bus ops is dropped, so there is no longer indirect management, as mentioned in the above. - hdac_device link_power_control flag is moved to hda_codec display_power_control flag, as it's only for HDA legacy. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106525 Signed-off-by: Takashi Iwai --- include/sound/hda_codec.h | 1 + include/sound/hda_component.h | 10 ++++++++-- include/sound/hdaudio.h | 7 ++----- sound/hda/hdac_component.c | 35 ++++++++++++++++++++++------------- sound/hda/hdac_device.c | 17 ----------------- sound/pci/hda/hda_codec.c | 16 ++++++++++++---- sound/pci/hda/hda_controller.c | 11 ----------- sound/pci/hda/hda_intel.c | 22 ++++++++-------------- sound/pci/hda/patch_hdmi.c | 4 ++-- sound/soc/codecs/hdac_hdmi.c | 7 +++---- sound/soc/intel/skylake/skl.c | 10 +++++----- 11 files changed, 63 insertions(+), 77 deletions(-) (limited to 'include') diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 0d98bb9068b1..7fa48b100936 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -236,6 +236,7 @@ struct hda_codec { /* misc flags */ unsigned int in_freeing:1; /* being released */ unsigned int registered:1; /* codec was registered */ + unsigned int display_power_control:1; /* needs display power */ unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each * status change * (e.g. Realtek codecs) diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h index 78626cde7081..767c8d8a0230 100644 --- a/include/sound/hda_component.h +++ b/include/sound/hda_component.h @@ -5,10 +5,15 @@ #define __SOUND_HDA_COMPONENT_H #include +#include + +/* virtual idx for controller */ +#define HDA_CODEC_IDX_CONTROLLER HDA_MAX_CODECS #ifdef CONFIG_SND_HDA_COMPONENT int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); -int snd_hdac_display_power(struct hdac_bus *bus, bool enable); +int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, + bool enable); int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int dev_id, int rate); int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, @@ -25,7 +30,8 @@ static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) { return 0; } -static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable) +static inline int snd_hdac_display_power(struct hdac_bus *bus, + unsigned int idx, bool enable) { return 0; } diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index cd1773d0e08f..940e2b282133 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -79,7 +79,6 @@ struct hdac_device { /* misc flags */ atomic_t in_pm; /* suspend/resume being performed */ - bool link_power_control:1; /* sysfs */ struct hdac_widget_tree *widgets; @@ -237,8 +236,6 @@ struct hdac_bus_ops { /* get a response from the last command */ int (*get_response)(struct hdac_bus *bus, unsigned int addr, unsigned int *res); - /* control the link power */ - int (*link_power)(struct hdac_bus *bus, bool enable); }; /* @@ -363,7 +360,8 @@ struct hdac_bus { /* DRM component interface */ struct drm_audio_component *audio_component; - int drm_power_refcount; + long display_power_status; + bool display_power_active; /* parameters required for enhanced capabilities */ int num_streams; @@ -404,7 +402,6 @@ int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, unsigned int *res); int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus); -int snd_hdac_link_power(struct hdac_device *codec, bool enable); bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset); void snd_hdac_bus_stop_chip(struct hdac_bus *bus); diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c index 6e46a9c73aed..dd766414436b 100644 --- a/sound/hda/hdac_component.c +++ b/sound/hda/hdac_component.c @@ -54,38 +54,45 @@ EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); /** * snd_hdac_display_power - Power up / down the power refcount * @bus: HDA core bus + * @idx: HDA codec address, pass HDA_CODEC_IDX_CONTROLLER for controller * @enable: power up or down * - * This function is supposed to be used only by a HD-audio controller - * driver that needs the interaction with graphics driver. + * This function is used by either HD-audio controller or codec driver that + * needs the interaction with graphics driver. * - * This function manages a refcount and calls the get_power() and + * This function updates the power status, and calls the get_power() and * put_power() ops accordingly, toggling the codec wakeup, too. * * Returns zero for success or a negative error code. */ -int snd_hdac_display_power(struct hdac_bus *bus, bool enable) +int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) { struct drm_audio_component *acomp = bus->audio_component; - if (!acomp || !acomp->ops) - return -ENODEV; - dev_dbg(bus->dev, "display power %s\n", enable ? "enable" : "disable"); + if (enable) + set_bit(idx, &bus->display_power_status); + else + clear_bit(idx, &bus->display_power_status); - if (enable) { - if (!bus->drm_power_refcount++) { + if (!acomp || !acomp->ops) + return 0; + + if (bus->display_power_status) { + if (!bus->display_power_active) { if (acomp->ops->get_power) acomp->ops->get_power(acomp->dev); snd_hdac_set_codec_wakeup(bus, true); snd_hdac_set_codec_wakeup(bus, false); + bus->display_power_active = true; } } else { - WARN_ON(!bus->drm_power_refcount); - if (!--bus->drm_power_refcount) + if (bus->display_power_active) { if (acomp->ops->put_power) acomp->ops->put_power(acomp->dev); + bus->display_power_active = false; + } } return 0; @@ -321,10 +328,12 @@ int snd_hdac_acomp_exit(struct hdac_bus *bus) if (!acomp) return 0; - WARN_ON(bus->drm_power_refcount); - if (bus->drm_power_refcount > 0 && acomp->ops) + if (WARN_ON(bus->display_power_active) && acomp->ops) acomp->ops->put_power(acomp->dev); + bus->display_power_active = false; + bus->display_power_status = 0; + component_master_del(dev, &hdac_component_master_ops); bus->audio_component = NULL; diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index dbf02a3a8d2f..95b073ee4b32 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -622,23 +622,6 @@ int snd_hdac_power_down_pm(struct hdac_device *codec) EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm); #endif -/** - * snd_hdac_link_power - Enable/disable the link power for a codec - * @codec: the codec object - * @bool: enable or disable the link power - */ -int snd_hdac_link_power(struct hdac_device *codec, bool enable) -{ - if (!codec->link_power_control) - return 0; - - if (codec->bus->ops->link_power) - return codec->bus->ops->link_power(codec->bus, enable); - else - return -EINVAL; -} -EXPORT_SYMBOL_GPL(snd_hdac_link_power); - /* codec vendor labels */ struct hda_vendor_id { unsigned int id; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 0957813939e5..9f8d59e7e89f 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -36,6 +36,7 @@ #include "hda_beep.h" #include "hda_jack.h" #include +#include #define codec_in_pm(codec) snd_hdac_is_in_pm(&codec->core) #define hda_codec_is_power_on(codec) snd_hdac_is_power_on(&codec->core) @@ -799,6 +800,13 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) static unsigned int hda_set_power_state(struct hda_codec *codec, unsigned int power_state); +/* enable/disable display power per codec */ +static void codec_display_power(struct hda_codec *codec, bool enable) +{ + if (codec->display_power_control) + snd_hdac_display_power(&codec->bus->core, codec->addr, enable); +} + /* also called from hda_bind.c */ void snd_hda_codec_register(struct hda_codec *codec) { @@ -806,7 +814,7 @@ void snd_hda_codec_register(struct hda_codec *codec) return; if (device_is_registered(hda_codec_dev(codec))) { snd_hda_register_beep_device(codec); - snd_hdac_link_power(&codec->core, true); + codec_display_power(codec, true); pm_runtime_enable(hda_codec_dev(codec)); /* it was powered up in snd_hda_codec_new(), now all done */ snd_hda_power_down(codec); @@ -834,7 +842,7 @@ static int snd_hda_codec_dev_free(struct snd_device *device) codec->in_freeing = 1; snd_hdac_device_unregister(&codec->core); - snd_hdac_link_power(&codec->core, false); + codec_display_power(codec, false); put_device(hda_codec_dev(codec)); return 0; } @@ -2926,7 +2934,7 @@ static int hda_codec_runtime_suspend(struct device *dev) (codec_has_clkstop(codec) && codec_has_epss(codec) && (state & AC_PWRST_CLK_STOP_OK))) snd_hdac_codec_link_down(&codec->core); - snd_hdac_link_power(&codec->core, false); + codec_display_power(codec, false); return 0; } @@ -2934,7 +2942,7 @@ static int hda_codec_runtime_resume(struct device *dev) { struct hda_codec *codec = dev_to_hda_codec(dev); - snd_hdac_link_power(&codec->core, true); + codec_display_power(codec, true); snd_hdac_codec_link_up(&codec->core); hda_call_codec_resume(codec); pm_runtime_mark_last_busy(dev); diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index fe2506672a72..532e081f8b8a 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -989,20 +989,9 @@ static int azx_get_response(struct hdac_bus *bus, unsigned int addr, return azx_rirb_get_response(bus, addr, res); } -static int azx_link_power(struct hdac_bus *bus, bool enable) -{ - struct azx *chip = bus_to_azx(bus); - - if (chip->ops->link_power) - return chip->ops->link_power(chip, enable); - else - return -EINVAL; -} - static const struct hdac_bus_ops bus_core_ops = { .command = azx_send_cmd, .get_response = azx_get_response, - .link_power = azx_link_power, }; #ifdef CONFIG_SND_HDA_DSP_LOADER diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index cc06a323c817..9f67425d5039 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -667,13 +667,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) return 0; } -/* Enable/disable i915 display power for the link */ -static int azx_intel_link_power(struct azx *chip, bool enable) -{ - struct hdac_bus *bus = azx_bus(chip); - - return snd_hdac_display_power(bus, enable); -} +#define display_power(chip, enable) \ + snd_hdac_display_power(azx_bus(chip), HDA_CODEC_IDX_CONTROLLER, enable) /* * Check whether the current DMA position is acceptable for updating @@ -957,7 +952,7 @@ static void __azx_runtime_suspend(struct azx *chip) azx_clear_irq_pending(chip); if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && hda->need_i915_power) - snd_hdac_display_power(azx_bus(chip), false); + display_power(chip, false); } static void __azx_runtime_resume(struct azx *chip) @@ -968,7 +963,7 @@ static void __azx_runtime_resume(struct azx *chip) int status; if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { - snd_hdac_display_power(bus, true); + display_power(chip, true); if (hda->need_i915_power) snd_hdac_i915_set_bclk(bus); } @@ -989,7 +984,7 @@ static void __azx_runtime_resume(struct azx *chip) /* power down again for link-controlled chips */ if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && !hda->need_i915_power) - snd_hdac_display_power(bus, false); + display_power(chip, false); } #ifdef CONFIG_PM_SLEEP @@ -1355,7 +1350,7 @@ static int azx_free(struct azx *chip) if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { if (hda->need_i915_power) - snd_hdac_display_power(bus, false); + display_power(chip, false); } if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) snd_hdac_i915_exit(bus); @@ -2056,7 +2051,6 @@ static const struct hda_controller_ops pci_hda_ops = { .disable_msi_reset_irq = disable_msi_reset_irq, .pcm_mmap_prepare = pcm_mmap_prepare, .position_check = azx_position_check, - .link_power = azx_intel_link_power, }; static int azx_probe(struct pci_dev *pci, @@ -2239,7 +2233,7 @@ static int azx_probe_continue(struct azx *chip) if (CONTROLLER_IN_GPU(pci)) hda->need_i915_power = 1; - err = snd_hdac_display_power(bus, true); + err = display_power(chip, true); if (err < 0) { dev_err(chip->card->dev, "Cannot turn on display power on i915\n"); @@ -2295,7 +2289,7 @@ static int azx_probe_continue(struct azx *chip) out_free: if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && !hda->need_i915_power) - snd_hdac_display_power(bus, false); + display_power(chip, false); i915_power_fail: if (err < 0) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 67099cbb6be2..30fe4dbdb0ae 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2620,7 +2620,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) * can cover the codec power request, and so need not set this flag. */ if (!is_haswell(codec) && !is_broadwell(codec)) - codec->core.link_power_control = 1; + codec->display_power_control = 1; codec->patch_ops.set_power_state = haswell_set_power_state; codec->depop_delay = 0; @@ -2656,7 +2656,7 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) /* For Valleyview/Cherryview, only the display codec is in the display * power well and can use link_power ops to request/release the power. */ - codec->core.link_power_control = 1; + codec->display_power_control = 1; codec->depop_delay = 0; codec->auto_runtime_pm = 1; diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index e63d6e33df48..c3d551d2af7f 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -2031,14 +2031,13 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev) * Turned off in the runtime_suspend during the first explicit * pm_runtime_suspend call. */ - ret = snd_hdac_display_power(hdev->bus, true); + ret = snd_hdac_display_power(hdev->bus, hdev->addr, true); if (ret < 0) { dev_err(&hdev->dev, "Cannot turn on display power on i915 err: %d\n", ret); return ret; } - ret = hdac_hdmi_parse_and_map_nid(hdev, &hdmi_dais, &num_dais); if (ret < 0) { dev_err(&hdev->dev, @@ -2196,7 +2195,7 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) snd_hdac_ext_bus_link_put(bus, hlink); - err = snd_hdac_display_power(bus, false); + err = snd_hdac_display_power(bus, hdev->addr, false); if (err < 0) dev_err(dev, "Cannot turn off display power on i915\n"); @@ -2224,7 +2223,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev) snd_hdac_ext_bus_link_get(bus, hlink); - err = snd_hdac_display_power(bus, true); + err = snd_hdac_display_power(bus, hdev->addr, true); if (err < 0) { dev_err(dev, "Cannot turn on display power on i915\n"); return err; diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 7487f388e65d..64f8433ae921 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -334,7 +334,7 @@ static int skl_suspend(struct device *dev) } if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - ret = snd_hdac_display_power(bus, false); + ret = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); if (ret < 0) dev_err(bus->dev, "Cannot turn OFF display power on i915\n"); @@ -353,7 +353,7 @@ static int skl_resume(struct device *dev) /* Turned OFF in HDMI codec driver after codec reconfiguration */ if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - ret = snd_hdac_display_power(bus, true); + ret = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); if (ret < 0) { dev_err(bus->dev, "Cannot turn on display power on i915\n"); @@ -783,7 +783,7 @@ static int skl_i915_init(struct hdac_bus *bus) if (err < 0) return err; - err = snd_hdac_display_power(bus, true); + err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); if (err < 0) dev_err(bus->dev, "Cannot turn on display power on i915\n"); @@ -838,7 +838,7 @@ static void skl_probe_work(struct work_struct *work) snd_hdac_ext_bus_link_put(bus, hlink); if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - err = snd_hdac_display_power(bus, false); + err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); if (err < 0) { dev_err(bus->dev, "Cannot turn off display power on i915\n"); skl_machine_device_unregister(skl); @@ -855,7 +855,7 @@ static void skl_probe_work(struct work_struct *work) out_err: if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) - err = snd_hdac_display_power(bus, false); + err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); } /* -- cgit v1.2.3 From 4f799e734094f09feaae89ee75982fac84742c56 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 9 Dec 2018 10:04:25 +0100 Subject: ALSA: hda: Make snd_hdac_display_power() void function After the recent refactoring, snd_hdac_display_power() doesn't return any error, hence it can be defined to return void. This makes many error checks redundant and allows us to reduce them gracefully. Signed-off-by: Takashi Iwai --- include/sound/hda_component.h | 9 ++++----- sound/hda/hdac_component.c | 8 ++------ sound/pci/hda/hda_intel.c | 9 +-------- sound/soc/codecs/hdac_hdmi.c | 23 +++++------------------ sound/soc/intel/skylake/skl.c | 40 +++++++++++----------------------------- 5 files changed, 23 insertions(+), 66 deletions(-) (limited to 'include') diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h index 767c8d8a0230..2ec31b358950 100644 --- a/include/sound/hda_component.h +++ b/include/sound/hda_component.h @@ -12,8 +12,8 @@ #ifdef CONFIG_SND_HDA_COMPONENT int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); -int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, - bool enable); +void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, + bool enable); int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int dev_id, int rate); int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, @@ -30,10 +30,9 @@ static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) { return 0; } -static inline int snd_hdac_display_power(struct hdac_bus *bus, - unsigned int idx, bool enable) +static inline void snd_hdac_display_power(struct hdac_bus *bus, + unsigned int idx, bool enable) { - return 0; } static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int dev_id, int rate) diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c index dd766414436b..a6d37b9d6413 100644 --- a/sound/hda/hdac_component.c +++ b/sound/hda/hdac_component.c @@ -62,10 +62,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup); * * This function updates the power status, and calls the get_power() and * put_power() ops accordingly, toggling the codec wakeup, too. - * - * Returns zero for success or a negative error code. */ -int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) +void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) { struct drm_audio_component *acomp = bus->audio_component; @@ -77,7 +75,7 @@ int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) clear_bit(idx, &bus->display_power_status); if (!acomp || !acomp->ops) - return 0; + return; if (bus->display_power_status) { if (!bus->display_power_active) { @@ -94,8 +92,6 @@ int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable) bus->display_power_active = false; } } - - return 0; } EXPORT_SYMBOL_GPL(snd_hdac_display_power); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 5399d0180434..e784130ea4e0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2216,12 +2216,7 @@ static int azx_probe_continue(struct azx *chip) * this power. For other platforms, like Baytrail/Braswell, only the * display codec needs the power and it can be released after probe. */ - err = display_power(chip, true); - if (err < 0) { - dev_err(chip->card->dev, - "Cannot turn on display power on i915\n"); - goto i915_power_fail; - } + display_power(chip, true); err = azx_first_init(chip); if (err < 0) @@ -2271,8 +2266,6 @@ static int azx_probe_continue(struct azx *chip) out_free: if (err < 0 || !hda->need_i915_power) display_power(chip, false); - -i915_power_fail: if (err < 0) hda->init_failed = 1; complete_all(&hda->probe_wait); diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index c3d551d2af7f..552ed1968bc4 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -2031,13 +2031,8 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev) * Turned off in the runtime_suspend during the first explicit * pm_runtime_suspend call. */ - ret = snd_hdac_display_power(hdev->bus, hdev->addr, true); - if (ret < 0) { - dev_err(&hdev->dev, - "Cannot turn on display power on i915 err: %d\n", - ret); - return ret; - } + snd_hdac_display_power(hdev->bus, hdev->addr, true); + ret = hdac_hdmi_parse_and_map_nid(hdev, &hdmi_dais, &num_dais); if (ret < 0) { dev_err(&hdev->dev, @@ -2169,7 +2164,6 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) struct hdac_device *hdev = dev_to_hdac_dev(dev); struct hdac_bus *bus = hdev->bus; struct hdac_ext_link *hlink = NULL; - int err; dev_dbg(dev, "Enter: %s\n", __func__); @@ -2195,11 +2189,9 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) snd_hdac_ext_bus_link_put(bus, hlink); - err = snd_hdac_display_power(bus, hdev->addr, false); - if (err < 0) - dev_err(dev, "Cannot turn off display power on i915\n"); + snd_hdac_display_power(bus, hdev->addr, false); - return err; + return 0; } static int hdac_hdmi_runtime_resume(struct device *dev) @@ -2207,7 +2199,6 @@ static int hdac_hdmi_runtime_resume(struct device *dev) struct hdac_device *hdev = dev_to_hdac_dev(dev); struct hdac_bus *bus = hdev->bus; struct hdac_ext_link *hlink = NULL; - int err; dev_dbg(dev, "Enter: %s\n", __func__); @@ -2223,11 +2214,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev) snd_hdac_ext_bus_link_get(bus, hlink); - err = snd_hdac_display_power(bus, hdev->addr, true); - if (err < 0) { - dev_err(dev, "Cannot turn on display power on i915\n"); - return err; - } + snd_hdac_display_power(bus, hdev->addr, true); hdac_hdmi_skl_enable_all_pins(hdev); hdac_hdmi_skl_enable_dp12(hdev); diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 64f8433ae921..5c224a0e1c7a 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -311,7 +311,7 @@ static int skl_suspend(struct device *dev) struct pci_dev *pci = to_pci_dev(dev); struct hdac_bus *bus = pci_get_drvdata(pci); struct skl *skl = bus_to_skl(bus); - int ret = 0; + int ret; /* * Do not suspend if streams which are marked ignore suspend are @@ -333,14 +333,10 @@ static int skl_suspend(struct device *dev) skl->skl_sst->fw_loaded = false; } - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - ret = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); - if (ret < 0) - dev_err(bus->dev, - "Cannot turn OFF display power on i915\n"); - } + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); - return ret; + return 0; } static int skl_resume(struct device *dev) @@ -352,14 +348,8 @@ static int skl_resume(struct device *dev) int ret; /* Turned OFF in HDMI codec driver after codec reconfiguration */ - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - ret = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); - if (ret < 0) { - dev_err(bus->dev, - "Cannot turn on display power on i915\n"); - return ret; - } - } + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); /* * resume only when we are not in suspend active, otherwise need to @@ -783,11 +773,9 @@ static int skl_i915_init(struct hdac_bus *bus) if (err < 0) return err; - err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); - if (err < 0) - dev_err(bus->dev, "Cannot turn on display power on i915\n"); + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); - return err; + return 0; } static void skl_probe_work(struct work_struct *work) @@ -837,14 +825,8 @@ static void skl_probe_work(struct work_struct *work) list_for_each_entry(hlink, &bus->hlink_list, list) snd_hdac_ext_bus_link_put(bus, hlink); - if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { - err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); - if (err < 0) { - dev_err(bus->dev, "Cannot turn off display power on i915\n"); - skl_machine_device_unregister(skl); - return; - } - } + if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); /* configure PM */ pm_runtime_put_noidle(bus->dev); @@ -855,7 +837,7 @@ static void skl_probe_work(struct work_struct *work) out_err: if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) - err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); } /* -- cgit v1.2.3 From ba02eed9f300b6512181d526311d4e11aaa9714f Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 15 Nov 2018 18:13:20 +0000 Subject: ALSA: soc-compress: add support to snd_compr_set_runtime_buffer() Existing compress offload code allocates data buffers using simple kmalloc, however there are situations where these buffers have to be mapped in smmu. So provide a way to set the runtime buffer by the driver itself, simillar to what we do with pcm. This patch adds support to set runtime dma buffer on compressed stream. Signed-off-by: Srinivas Kandagatla Acked-by: Vinod Koul Signed-off-by: Mark Brown --- include/sound/compress_driver.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'include') diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index ea8c93bbb0e0..0cdc3999ecfa 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -23,6 +23,7 @@ struct snd_compr_ops; * struct snd_compr_runtime: runtime stream description * @state: stream state * @ops: pointer to DSP callbacks + * @dma_buffer_p: runtime dma buffer pointer * @buffer: pointer to kernel buffer, valid only when not in mmap mode or * DSP doesn't implement copy * @buffer_size: size of the above buffer @@ -37,6 +38,7 @@ struct snd_compr_ops; struct snd_compr_runtime { snd_pcm_state_t state; struct snd_compr_ops *ops; + struct snd_dma_buffer *dma_buffer_p; void *buffer; u64 buffer_size; u32 fragment_size; @@ -175,6 +177,23 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) wake_up(&stream->runtime->sleep); } +/** + * snd_compr_set_runtime_buffer - Set the Compress runtime buffer + * @substream: compress substream to set + * @bufp: the buffer information, NULL to clear + * + * Copy the buffer information to runtime buffer when @bufp is non-NULL. + * Otherwise it clears the current buffer information. + */ +static inline void snd_compr_set_runtime_buffer( + struct snd_compr_stream *substream, + struct snd_dma_buffer *bufp) +{ + struct snd_compr_runtime *runtime = substream->runtime; + + runtime->dma_buffer_p = bufp; +} + int snd_compr_stop_error(struct snd_compr_stream *stream, snd_pcm_state_t state); -- cgit v1.2.3 From 76119509d23cdd9fbc71585042b27b6511b44b4d Mon Sep 17 00:00:00 2001 From: Rohit kumar Date: Fri, 14 Dec 2018 17:59:26 +0530 Subject: ASoC: qdsp6: dt-bindings: Add q6afe display_port dt binding This patch adds bindings required for DISPLAY_PORT_RX port on AFE. Signed-off-by: Rohit kumar Acked-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- include/dt-bindings/sound/qcom,q6afe.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/dt-bindings/sound/qcom,q6afe.h b/include/dt-bindings/sound/qcom,q6afe.h index e2d3892240b8..1df06f8ad5c3 100644 --- a/include/dt-bindings/sound/qcom,q6afe.h +++ b/include/dt-bindings/sound/qcom,q6afe.h @@ -106,6 +106,7 @@ #define QUINARY_TDM_TX_6 101 #define QUINARY_TDM_RX_7 102 #define QUINARY_TDM_TX_7 103 +#define DISPLAY_PORT_RX 104 #endif /* __DT_BINDINGS_Q6_AFE_H__ */ -- cgit v1.2.3 From 18d43c9b88eb335440c5e769eb6c2d5bc908dc61 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Tue, 11 Dec 2018 15:30:27 -0600 Subject: ALSA: HDA: export process_unsol_events() The SOF implementation does not rely on the hdac_bus library, however for HDMI and HDaudio codec support it does need to deal with unsolicited events. Instead of re-inventing the wheel, export this symbol to reuse this part of the library directly. Signed-off-by: Keyon Jie Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 1 + sound/hda/hdac_bus.c | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 940e2b282133..f9b2b6330d27 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -387,6 +387,7 @@ void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec); void snd_hdac_bus_remove_device(struct hdac_bus *bus, struct hdac_device *codec); +void snd_hdac_bus_process_unsol_events(struct work_struct *work); static inline void snd_hdac_codec_link_up(struct hdac_device *codec) { diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 714a51721a31..012305177f68 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -9,8 +9,6 @@ #include #include "trace.h" -static void process_unsol_events(struct work_struct *work); - static const struct hdac_bus_ops default_ops = { .command = snd_hdac_bus_send_cmd, .get_response = snd_hdac_bus_get_response, @@ -37,7 +35,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, bus->io_ops = io_ops; INIT_LIST_HEAD(&bus->stream_list); INIT_LIST_HEAD(&bus->codec_list); - INIT_WORK(&bus->unsol_work, process_unsol_events); + INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events); spin_lock_init(&bus->reg_lock); mutex_init(&bus->cmd_mutex); bus->irq = -1; @@ -148,7 +146,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_queue_event); /* * process queued unsolicited events */ -static void process_unsol_events(struct work_struct *work) +void snd_hdac_bus_process_unsol_events(struct work_struct *work) { struct hdac_bus *bus = container_of(work, struct hdac_bus, unsol_work); struct hdac_device *codec; @@ -171,6 +169,7 @@ static void process_unsol_events(struct work_struct *work) drv->unsol_event(codec, res); } } +EXPORT_SYMBOL_GPL(snd_hdac_bus_process_unsol_events); /** * snd_hdac_bus_add_device - Add a codec to bus -- cgit v1.2.3 From d82b51c855a20eb456ac09f2f40ea98312373263 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Sat, 15 Dec 2018 14:07:23 -0600 Subject: ALSA: HD-Audio: SKL+: force HDaudio legacy or SKL+ driver selection For HDaudio and Skylake drivers, add module parameter "pci_binding" When pci_binding == 0 (AUTO), the PCI class/subclass info is used to select drivers based on the presence of the DSP. pci_binding == 1 (LEGACY) forces the use of the HDAudio legacy driver, even if the DSP is present. pci_binding == 2 (ASOC) forces the use of the ASOC driver. The information on the DSP presence is bypassed. The value for the module parameter needs to be identical for both drivers. This parameter is intended as a back-up solution if the automatic detection fails or when the DSP usage fails. Such cases should be reported on the alsa-devel mailing list for analysis. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 6 ++++++ sound/pci/hda/hda_intel.c | 26 ++++++++++++++++++++--- sound/soc/intel/skylake/skl.c | 48 +++++++++++++++++++++++++++++-------------- 3 files changed, 62 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index f9b2b6330d27..b4fa1c775251 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -98,6 +98,12 @@ enum { HDA_DEV_ASOC, }; +enum { + SND_SKL_PCI_BIND_AUTO, /* automatic selection based on pci class */ + SND_SKL_PCI_BIND_LEGACY,/* bind only with legacy driver */ + SND_SKL_PCI_BIND_ASOC /* bind only with ASoC driver */ +}; + /* direction */ enum { HDA_INPUT, HDA_OUTPUT diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2ec9c896ebc0..e42cc2230977 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -172,6 +172,9 @@ module_param_array(beep_mode, bool, NULL, 0444); MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " "(0=off, 1=on) (default=1)."); #endif +static int skl_pci_binding; +module_param_named(pci_binding, skl_pci_binding, int, 0444); +MODULE_PARM_DESC(pci_binding, "PCI binding (0=auto, 1=only legacy, 2=only asoc"); #ifdef CONFIG_PM static int param_set_xint(const char *val, const struct kernel_param *kp); @@ -2050,9 +2053,26 @@ static int azx_probe(struct pci_dev *pci, int err; /* check if this driver can be used on SKL+ Intel platforms */ - if ((pci_id->driver_data & AZX_DCAPS_INTEL_SHARED) && - pci->class != 0x040300) - return -ENODEV; + if (pci_id->driver_data & AZX_DCAPS_INTEL_SHARED) { + switch (skl_pci_binding) { + case SND_SKL_PCI_BIND_AUTO: + if (pci->class != 0x040300) { + dev_info(&pci->dev, "The DSP is enabled on this platform, aborting probe\n"); + return -ENODEV; + } + dev_info(&pci->dev, "No DSP detected, continuing HDaudio legacy probe\n"); + break; + case SND_SKL_PCI_BIND_LEGACY: + dev_info(&pci->dev, "Module parameter forced binding with HDaudio legacy, bypassed detection logic\n"); + break; + case SND_SKL_PCI_BIND_ASOC: + dev_info(&pci->dev, "Module parameter forced binding with SKL+ ASoC driver, aborting probe\n"); + return -ENODEV; + default: + dev_err(&pci->dev, "invalid value for skl_pci_binding module parameter, ignored\n"); + break; + } + } if (dev >= SNDRV_CARDS) return -ENODEV; diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 29d9b0eb83ea..60c94836bf5b 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -40,6 +40,9 @@ #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) #include "../../../soc/codecs/hdac_hda.h" #endif +static int skl_pci_binding; +module_param_named(pci_binding, skl_pci_binding, int, 0444); +MODULE_PARM_DESC(pci_binding, "PCI binding (0=auto, 1=only legacy, 2=only asoc"); /* * initialize the PCI registers @@ -896,21 +899,6 @@ static int skl_first_init(struct hdac_bus *bus) unsigned short gcap; int cp_streams, pb_streams, start_idx; - /* - * detect DSP by checking class/subclass/prog-id information - * class=04 subclass 03 prog-if 00: no DSP, legacy driver needs to be used - * class=04 subclass 01 prog-if 00: DSP is present (and may be required e.g. for DMIC or SSP support) - * class=04 subclass 03 prog-if 80: either of DSP or legacy mode can be used - */ - if (pci->class == 0x040300) { - dev_err(bus->dev, "The DSP is not enabled on this platform, aborting probe\n"); - return -ENODEV; - } else if (pci->class != 0x040100 && pci->class != 0x040380) { - dev_err(bus->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, aborting probe\n", pci->class); - return -ENODEV; - } - dev_info(bus->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); - err = pci_request_regions(pci, "Skylake HD audio"); if (err < 0) return err; @@ -984,6 +972,36 @@ static int skl_probe(struct pci_dev *pci, struct hdac_bus *bus = NULL; int err; + switch (skl_pci_binding) { + case SND_SKL_PCI_BIND_AUTO: + /* + * detect DSP by checking class/subclass/prog-id information + * class=04 subclass 03 prog-if 00: no DSP, use legacy driver + * class=04 subclass 01 prog-if 00: DSP is present + * (and may be required e.g. for DMIC or SSP support) + * class=04 subclass 03 prog-if 80: use DSP or legacy mode + */ + if (pci->class == 0x040300) { + dev_info(&pci->dev, "The DSP is not enabled on this platform, aborting probe\n"); + return -ENODEV; + } + if (pci->class != 0x040100 && pci->class != 0x040380) { + dev_err(&pci->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, aborting probe\n", pci->class); + return -ENODEV; + } + dev_info(&pci->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class); + break; + case SND_SKL_PCI_BIND_LEGACY: + dev_info(&pci->dev, "Module parameter forced binding with HDaudio legacy, aborting probe\n"); + return -ENODEV; + case SND_SKL_PCI_BIND_ASOC: + dev_info(&pci->dev, "Module parameter forced binding with SKL driver, bypassed detection logic\n"); + break; + default: + dev_err(&pci->dev, "invalid value for skl_pci_binding module parameter, ignored\n"); + break; + } + /* we use ext core ops, so provide NULL for ops here */ err = skl_create(pci, NULL, &skl); if (err < 0) -- cgit v1.2.3