diff mbox series

ASoC: hdac_hda: add HDA patch loader support

Message ID 20230919083209.1919921-1-yung-chuan.liao@linux.intel.com (mailing list archive)
State Accepted
Commit 842a62a75e709b3efb5020a25a225fa51748c5f9
Headers show
Series ASoC: hdac_hda: add HDA patch loader support | expand

Commit Message

Bard Liao Sept. 19, 2023, 8:32 a.m. UTC
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(+)

Comments

Takashi Iwai Sept. 19, 2023, 12:55 p.m. UTC | #1
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
Mark Brown Sept. 19, 2023, 4:59 p.m. UTC | #2
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
Liao, Bard Sept. 20, 2023, 8:10 a.m. UTC | #3
> -----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
diff mbox series

Patch

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) {