Unverified Commit 842a62a7 authored by Bard Liao's avatar Bard Liao Committed by Mark Brown
Browse files

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: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarRander Wang <rander.wang@intel.com>
Link: https://lore.kernel.org/r/20230919083209.1919921-1-yung-chuan.liao@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 88e20c1f
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -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
+4 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -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) {