[PATCH] ASoC: hdac_hda: add HDA patch loader support
HDA patch loader is supported by legacy HDA driver. Implement it on ASoC HDA driver, too.
Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Rander Wang rander.wang@intel.com --- sound/soc/codecs/hdac_hda.c | 28 ++++++++++++++++++++++++++++ sound/soc/codecs/hdac_hda.h | 4 ++++ sound/soc/intel/skylake/skl.c | 1 + sound/soc/sof/intel/hda-codec.c | 1 + 4 files changed, 34 insertions(+)
diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index be66853afbe2..8f5d97949d3d 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -7,6 +7,7 @@ * codec drivers using hdac_ext_bus_ops ops. */
+#include <linux/firmware.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/module.h> @@ -35,6 +36,13 @@ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ SNDRV_PCM_RATE_192000)
+#ifdef CONFIG_SND_HDA_PATCH_LOADER +static char *loadable_patch[SNDRV_CARDS]; + +module_param_array_named(patch, loadable_patch, charp, NULL, 0444); +MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface."); +#endif + static int hdac_hda_dai_open(struct snd_pcm_substream *substream, struct snd_soc_dai *dai); static void hdac_hda_dai_close(struct snd_pcm_substream *substream, @@ -423,6 +431,26 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) dev_err(&hdev->dev, "failed to create hda codec %d\n", ret); goto error_no_pm; } + +#ifdef CONFIG_SND_HDA_PATCH_LOADER + if (loadable_patch[hda_pvt->dev_index] && *loadable_patch[hda_pvt->dev_index]) { + dev_info(&hdev->dev, "Applying patch firmware '%s'\n", + loadable_patch[hda_pvt->dev_index]); + ret = request_firmware(&hda_pvt->fw, loadable_patch[hda_pvt->dev_index], + &hdev->dev); + if (ret < 0) + goto error_no_pm; + if (hda_pvt->fw) { + ret = snd_hda_load_patch(hcodec->bus, hda_pvt->fw->size, hda_pvt->fw->data); + if (ret < 0) { + dev_err(&hdev->dev, "failed to load hda patch %d\n", ret); + goto error_no_pm; + } + release_firmware(hda_pvt->fw); + hda_pvt->fw = NULL; + } + } +#endif /* * Overwrite type to HDA_DEV_ASOC since it is a ASoC driver * hda_codec.c will check this flag to determine if unregister diff --git a/sound/soc/codecs/hdac_hda.h b/sound/soc/codecs/hdac_hda.h index b65560981abb..b7a12aea8d32 100644 --- a/sound/soc/codecs/hdac_hda.h +++ b/sound/soc/codecs/hdac_hda.h @@ -26,6 +26,10 @@ struct hdac_hda_priv { struct hda_codec *codec; struct hdac_hda_pcm pcm[HDAC_DAI_ID_NUM]; bool need_display_power; + int dev_index; +#ifdef CONFIG_SND_HDA_PATCH_LOADER + const struct firmware *fw; +#endif };
struct hdac_ext_bus_ops *snd_soc_hdac_hda_get_ops(void); diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 77408a981b97..d753d393a428 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -736,6 +736,7 @@ static int probe_codec(struct hdac_bus *bus, int addr) return PTR_ERR(codec);
hda_codec->codec = codec; + hda_codec->dev_index = addr; dev_set_drvdata(&codec->core.dev, hda_codec);
/* use legacy bus only for HDA codecs, idisp uses ext bus */ diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 8a5e99a898ec..28ecbebb4b84 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -169,6 +169,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address) return ret;
hda_priv->codec = codec; + hda_priv->dev_index = address; dev_set_drvdata(&codec->core.dev, hda_priv);
if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) {
On Tue, 19 Sep 2023 10:32:09 +0200, Bard Liao wrote:
+#ifdef CONFIG_SND_HDA_PATCH_LOADER +static char *loadable_patch[SNDRV_CARDS];
Hm, this size looks wrong.
In the code later in this patch, dev_index points to the codec address, and it's basically irrelevant with SNDRV_CARDS. As SNDRV_CARDS might be 8 depending on the config, it can go beyond the array size, too. Use a different array size to match with the codec address ranges.
+module_param_array_named(patch, loadable_patch, charp, NULL, 0444); +MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface.");
Better to give a bit more description; when it's a codec address array, it can be non-zero, and user may wonder why it's not applied.
+#ifdef CONFIG_SND_HDA_PATCH_LOADER
- if (loadable_patch[hda_pvt->dev_index] && *loadable_patch[hda_pvt->dev_index]) {
dev_info(&hdev->dev, "Applying patch firmware '%s'\n",
loadable_patch[hda_pvt->dev_index]);
ret = request_firmware(&hda_pvt->fw, loadable_patch[hda_pvt->dev_index],
&hdev->dev);
if (ret < 0)
goto error_no_pm;
if (hda_pvt->fw) {
ret = snd_hda_load_patch(hcodec->bus, hda_pvt->fw->size, hda_pvt->fw->data);
if (ret < 0) {
dev_err(&hdev->dev, "failed to load hda patch %d\n", ret);
goto error_no_pm;
}
release_firmware(hda_pvt->fw);
hda_pvt->fw = NULL;
So the hda_pvt->fw is only for a temporary use, already released already here. Then...
--- a/sound/soc/codecs/hdac_hda.h +++ b/sound/soc/codecs/hdac_hda.h @@ -26,6 +26,10 @@ struct hdac_hda_priv { struct hda_codec *codec; struct hdac_hda_pcm pcm[HDAC_DAI_ID_NUM]; bool need_display_power;
- int dev_index;
+#ifdef CONFIG_SND_HDA_PATCH_LOADER
- const struct firmware *fw;
+#endif
... we don't have to add a new extra field, right?
thanks,
Takashi
-----Original Message----- From: Takashi Iwai tiwai@suse.de Sent: Tuesday, September 19, 2023 8:55 PM To: Bard Liao yung-chuan.liao@linux.intel.com Cc: broonie@kernel.org; alsa-devel@alsa-project.org; pierre- louis.bossart@linux.intel.com; Liao, Bard bard.liao@intel.com; peter.ujfalusi@linux.intel.com; kai.vehmanen@linux.intel.com Subject: Re: [PATCH] ASoC: hdac_hda: add HDA patch loader support
On Tue, 19 Sep 2023 10:32:09 +0200, Bard Liao wrote:
+#ifdef CONFIG_SND_HDA_PATCH_LOADER +static char *loadable_patch[SNDRV_CARDS];
Hm, this size looks wrong.
In the code later in this patch, dev_index points to the codec address, and it's basically irrelevant with SNDRV_CARDS. As SNDRV_CARDS might be 8 depending on the config, it can go beyond the array size, too. Use a different array size to match with the codec address ranges.
Thanks for pointing this out. Indeed, the array size is irrelevant with SNDRV_CARDS. I will change it to HDA_MAX_CODECS as it is the available number that we probe the codec.
+module_param_array_named(patch, loadable_patch, charp, NULL, 0444); +MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface.");
Better to give a bit more description; when it's a codec address array, it can be non-zero, and user may wonder why it's not applied.
Yes, I will do it.
+#ifdef CONFIG_SND_HDA_PATCH_LOADER
- if (loadable_patch[hda_pvt->dev_index] &&
*loadable_patch[hda_pvt->dev_index]) {
dev_info(&hdev->dev, "Applying patch firmware '%s'\n",
loadable_patch[hda_pvt->dev_index]);
ret = request_firmware(&hda_pvt->fw,
loadable_patch[hda_pvt->dev_index],
&hdev->dev);
if (ret < 0)
goto error_no_pm;
if (hda_pvt->fw) {
ret = snd_hda_load_patch(hcodec->bus, hda_pvt-
fw->size, hda_pvt->fw->data);
if (ret < 0) {
dev_err(&hdev->dev, "failed to load hda patch
%d\n", ret);
goto error_no_pm;
}
release_firmware(hda_pvt->fw);
hda_pvt->fw = NULL;
So the hda_pvt->fw is only for a temporary use, already released already here. Then...
--- a/sound/soc/codecs/hdac_hda.h +++ b/sound/soc/codecs/hdac_hda.h @@ -26,6 +26,10 @@ struct hdac_hda_priv { struct hda_codec *codec; struct hdac_hda_pcm pcm[HDAC_DAI_ID_NUM]; bool need_display_power;
- int dev_index;
+#ifdef CONFIG_SND_HDA_PATCH_LOADER
- const struct firmware *fw;
+#endif
... we don't have to add a new extra field, right?
Yes, I will remove it in the follow up patch.
Thanks, Bard
thanks,
Takashi
On Tue, 19 Sep 2023 16:32:09 +0800, Bard Liao wrote:
HDA patch loader is supported by legacy HDA driver. Implement it on ASoC HDA driver, too.
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: hdac_hda: add HDA patch loader support commit: 842a62a75e709b3efb5020a25a225fa51748c5f9
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (4)
-
Bard Liao
-
Liao, Bard
-
Mark Brown
-
Takashi Iwai