[alsa-devel] [RFC PATCH v2 2/6] ASoC: Intel: skl-hda-dsp-generic: use snd-hda-codec-hdmi

Pierre-Louis Bossart pierre-louis.bossart at linux.intel.com
Fri Sep 6 17:10:24 CEST 2019


On 9/6/19 9:29 AM, Kai Vehmanen wrote:
> Add support for using snd-hda-codec-hdmi driver for HDMI/DP
> instead of ASoC hdac-hdmi. This is aligned with how other
> HDA codecs are already handled.
> 
> When snd-hda-codec-hdmi is used, the PCM device numbers are
> parsed from card topology and passed to the codec driver.
> This needs to be done at runtime as topology changes may
> affect PCM device allocation.
> 
> Signed-off-by: Kai Vehmanen <kai.vehmanen at linux.intel.com>
> ---
>   sound/soc/intel/boards/skl_hda_dsp_common.c  | 26 +++++++-
>   sound/soc/intel/boards/skl_hda_dsp_common.h  | 69 ++++++++++++++++++++
>   sound/soc/intel/boards/skl_hda_dsp_generic.c |  7 --
>   3 files changed, 94 insertions(+), 8 deletions(-)
> 
> diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c
> index 55fd82e05e2c..23784178015b 100644
> --- a/sound/soc/intel/boards/skl_hda_dsp_common.c
> +++ b/sound/soc/intel/boards/skl_hda_dsp_common.c
> @@ -14,6 +14,9 @@
>   #include "../../codecs/hdac_hdmi.h"
>   #include "skl_hda_dsp_common.h"
>   
> +#include <sound/hda_codec.h>
> +#include "../../codecs/hdac_hda.h"
> +
>   #define NAME_SIZE	32
>   
>   int skl_hda_hdmi_add_pcm(struct snd_soc_card *card, int device)
> @@ -133,17 +136,38 @@ int skl_hda_hdmi_jack_init(struct snd_soc_card *card)
>   	struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
>   	struct snd_soc_component *component = NULL;
>   	struct skl_hda_hdmi_pcm *pcm;
> +	const char *modname;
> +	int use_common_codec = 0;
>   	char jack_name[NAME_SIZE];
>   	int err;
>   
> +	/*
> +	 * Detect whether this machine driver is used with SOF and
> +	 * alter behaviour based on which HDMI codec driver has
> +	 * been selected.
> +	 */
> +	if (!strncmp(card->name, "sof-skl_hda_card", 16)) {
> +		for_each_card_components(card, component) {
> +			modname = module_name(component->dev->driver->owner);
> +			if (!strncmp(component->name, "ehdaudio0D2", 11) &&
> +			    !strncmp(modname, "snd_hda_codec_hdmi", 18))
> +				use_common_codec = 1;
> +		}
> +	}

yuk. I am not a big fan of this...

It seems that we could pass information from the SOF side to the machine 
driver using the mach_params argument. we already pass the codec_mask 
and other fields, it wouldn't be too hard to reclaim a field or extend 
the structure to pass the information.

> +
> +	if (use_common_codec)
> +		return skl_hda_hdmi_build_controls(card);
> +
>   	list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
> +		if (!pcm)
> +			continue;
> +
>   		component = pcm->codec_dai->component;
>   		snprintf(jack_name, sizeof(jack_name),
>   			 "HDMI/DP, pcm=%d Jack", pcm->device);
>   		err = snd_soc_card_jack_new(card, jack_name,
>   					    SND_JACK_AVOUT, &pcm->hdmi_jack,
>   					    NULL, 0);
> -
>   		if (err)
>   			return err;
>   
> diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h
> index daa582e513b2..5438631be565 100644
> --- a/sound/soc/intel/boards/skl_hda_dsp_common.h
> +++ b/sound/soc/intel/boards/skl_hda_dsp_common.h
> @@ -14,6 +14,8 @@
>   #include <linux/platform_device.h>
>   #include <sound/core.h>
>   #include <sound/jack.h>
> +#include <sound/hda_codec.h>
> +#include "../../codecs/hdac_hda.h"
>   
>   #define HDA_DSP_MAX_BE_DAI_LINKS 7
>   
> @@ -35,4 +37,71 @@ extern struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS];
>   int skl_hda_hdmi_jack_init(struct snd_soc_card *card);
>   int skl_hda_hdmi_add_pcm(struct snd_soc_card *card, int device);
>   
> +/*
> + * Search card topology and return PCM device number
> + * matching Nth HDMI device (zero-based index).
> + */
> +static inline struct snd_pcm *skl_hda_hdmi_pcm_handle(struct snd_soc_card *card,
> +						      int hdmi_idx)
> +{
> +	struct snd_soc_pcm_runtime *rtd;
> +	int i = 0;
> +	struct snd_pcm *spcm;
> +
> +	for_each_card_rtds(card, rtd) {
> +		spcm = rtd->pcm ?
> +			rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].pcm : 0;
> +		if (spcm && strstr(spcm->id, "HDMI")) {
> +			if (i == hdmi_idx)
> +				return rtd->pcm;
> +			++i;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Search card topology and register HDMI PCM related controls
> + * to codec driver.
> + */
> +static inline int skl_hda_hdmi_build_controls(struct snd_soc_card *card)
> +{
> +	struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
> +	struct snd_soc_component *component;
> +	struct hdac_hda_priv *hda_pvt;
> +	struct skl_hda_hdmi_pcm *pcm;
> +	struct hda_codec *hcodec;
> +	struct snd_pcm *spcm;
> +	struct hda_pcm *hpcm;
> +	int err = 0, i = 0;
> +
> +	pcm = list_first_entry(&ctx->hdmi_pcm_list, struct skl_hda_hdmi_pcm,
> +			       head);
> +	component = pcm->codec_dai->component;
> +	if (!component)
> +		return -EINVAL;
> +
> +	hda_pvt = snd_soc_component_get_drvdata(component);
> +	hcodec = &hda_pvt->codec;
> +
> +	list_for_each_entry(hpcm, &hcodec->pcm_list_head, list) {
> +		spcm = skl_hda_hdmi_pcm_handle(card, i);
> +		if (spcm) {
> +			hpcm->pcm = spcm;
> +			hpcm->device = spcm->device;
> +			dev_dbg(card->dev,
> +				"%s: mapping HDMI converter %d to PCM %d (%p)\n",
> +				__func__, i, hpcm->device, spcm);
> +		}
> +		i++;
> +	}
> +
> +	err = snd_hda_codec_build_controls(hcodec);
> +	if (err < 0)
> +		dev_err(card->dev, "unable to create controls %d\n", err);
> +
> +	return err;
> +}
> +
>   #endif /* __SOUND_SOC_HDA_DSP_COMMON_H */
> diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c
> index 9ed68eb4f058..9b6f8cc87f99 100644
> --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c
> +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c
> @@ -26,13 +26,6 @@ static const struct snd_soc_dapm_widget skl_hda_widgets[] = {
>   };
>   
>   static const struct snd_soc_dapm_route skl_hda_map[] = {
> -	{ "hifi3", NULL, "iDisp3 Tx"},
> -	{ "iDisp3 Tx", NULL, "iDisp3_out"},
> -	{ "hifi2", NULL, "iDisp2 Tx"},
> -	{ "iDisp2 Tx", NULL, "iDisp2_out"},
> -	{ "hifi1", NULL, "iDisp1 Tx"},
> -	{ "iDisp1 Tx", NULL, "iDisp1_out"},
> -
>   	{ "Analog Out", NULL, "Codec Output Pin1" },
>   	{ "Digital Out", NULL, "Codec Output Pin2" },
>   	{ "Alt Analog Out", NULL, "Codec Output Pin3" },
> 



More information about the Alsa-devel mailing list