[alsa-devel] [PATCH v3 03/10] ASoC: hdac_hda: add support for HDMI/DP as a HDA codec

Pierre-Louis Bossart pierre-louis.bossart at linux.intel.com
Tue Sep 10 22:36:36 CEST 2019



On 9/10/19 1:29 PM, Kai Vehmanen wrote:
> Handle all HDA codecs using same logic, including HDMI/DP.
> 
> Call to snd_hda_codec_build_controls() is delayed for HDMI/DP HDA
> devices. This is needed to discover the PCM device numbers as
> defined in topology.
> 
> Signed-off-by: Kai Vehmanen <kai.vehmanen at linux.intel.com>
> ---
>   sound/soc/codecs/hdac_hda.c | 95 ++++++++++++++++++++++++++++++++-----
>   sound/soc/codecs/hdac_hda.h | 12 ++++-
>   2 files changed, 94 insertions(+), 13 deletions(-)
> 
> diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c
> index 91242b6f8ea7..3d4362158b29 100644
> --- a/sound/soc/codecs/hdac_hda.c
> +++ b/sound/soc/codecs/hdac_hda.c
> @@ -16,11 +16,8 @@
>   #include <sound/hdaudio_ext.h>
>   #include <sound/hda_codec.h>
>   #include <sound/hda_register.h>
> -#include "hdac_hda.h"
>   
> -#define HDAC_ANALOG_DAI_ID		0
> -#define HDAC_DIGITAL_DAI_ID		1
> -#define HDAC_ALT_ANALOG_DAI_ID		2
> +#include "hdac_hda.h"
>   
>   #define STUB_FORMATS	(SNDRV_PCM_FMTBIT_S8 | \
>   			SNDRV_PCM_FMTBIT_U8 | \
> @@ -121,7 +118,46 @@ static struct snd_soc_dai_driver hdac_hda_dais[] = {
>   		.formats = STUB_FORMATS,
>   		.sig_bits = 24,
>   	},
> -}
> +},
> +{
> +	.id = HDAC_HDMI_0_DAI_ID,
> +	.name = "intel-hdmi-hifi1",
> +	.ops = &hdac_hda_dai_ops,
> +	.playback = {
> +		.stream_name    = "hifi1",
> +		.channels_min   = 1,
> +		.channels_max   = 16,

IIRC HDMI only deals with 8ch?

> +		.rates          = SNDRV_PCM_RATE_8000_192000,

And frequencies above 32kHz

> +		.formats        = STUB_FORMATS,
> +		.sig_bits = 24,
> +	},
> +},
> +{
> +	.id = HDAC_HDMI_1_DAI_ID,
> +	.name = "intel-hdmi-hifi2",
> +	.ops = &hdac_hda_dai_ops,
> +	.playback = {
> +		.stream_name    = "hifi2",
> +		.channels_min   = 1,
> +		.channels_max   = 16,
> +		.rates          = SNDRV_PCM_RATE_8000_192000,
> +		.formats        = STUB_FORMATS,
> +		.sig_bits = 24,
> +	},
> +},
> +{
> +	.id = HDAC_HDMI_2_DAI_ID,
> +	.name = "intel-hdmi-hifi3",
> +	.ops = &hdac_hda_dai_ops,
> +	.playback = {
> +		.stream_name    = "hifi3",
> +		.channels_min   = 1,
> +		.channels_max   = 16,
> +		.rates          = SNDRV_PCM_RATE_8000_192000,
> +		.formats        = STUB_FORMATS,
> +		.sig_bits = 24,
> +	},
> +},
>   
>   };
>   
> @@ -135,10 +171,11 @@ static int hdac_hda_dai_set_tdm_slot(struct snd_soc_dai *dai,
>   
>   	hda_pvt = snd_soc_component_get_drvdata(component);
>   	pcm = &hda_pvt->pcm[dai->id];
> +
>   	if (tx_mask)
> -		pcm[dai->id].stream_tag[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
> +		pcm->stream_tag[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
>   	else
> -		pcm[dai->id].stream_tag[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
> +		pcm->stream_tag[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
>   
>   	return 0;
>   }
> @@ -278,6 +315,12 @@ static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
>   	struct hda_pcm *cpcm;
>   	const char *pcm_name;
>   
> +	/*
> +	 * map DAI ID to the closest matching PCM name, using the naming
> +	 * scheme used by hda-codec snd_hda_gen_build_pcms() and for
> +	 * HDMI in hda_codec patch_hdmi.c)
> +	 */
> +
>   	switch (dai->id) {
>   	case HDAC_ANALOG_DAI_ID:
>   		pcm_name = "Analog";
> @@ -288,13 +331,22 @@ static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
>   	case HDAC_ALT_ANALOG_DAI_ID:
>   		pcm_name = "Alt Analog";
>   		break;
> +	case HDAC_HDMI_0_DAI_ID:
> +		pcm_name = "HDMI 0";
> +		break;
> +	case HDAC_HDMI_1_DAI_ID:
> +		pcm_name = "HDMI 1";
> +		break;
> +	case HDAC_HDMI_2_DAI_ID:
> +		pcm_name = "HDMI 2";
> +		break;
>   	default:
>   		dev_err(&hcodec->core.dev, "invalid dai id %d\n", dai->id);
>   		return NULL;
>   	}
>   
>   	list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
> -		if (strpbrk(cpcm->name, pcm_name))
> +		if (strstr(cpcm->name, pcm_name))
>   			return cpcm;
>   	}
>   
> @@ -302,6 +354,18 @@ static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
>   	return NULL;
>   }
>   
> +static bool is_hdmi_codec(struct hda_codec *hcodec)
> +{
> +	struct hda_pcm *cpcm;
> +
> +	list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
> +		if (cpcm->pcm_type == HDA_PCM_TYPE_HDMI)
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
>   static int hdac_hda_codec_probe(struct snd_soc_component *component)
>   {
>   	struct hdac_hda_priv *hda_pvt =
> @@ -366,16 +430,23 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
>   		dev_dbg(&hdev->dev, "no patch file found\n");
>   	}
>   
> +	/* configure codec for 1:1 PCM:DAI mapping */
> +	hcodec->mst_no_extra_pcms = 1;
> +
>   	ret = snd_hda_codec_parse_pcms(hcodec);
>   	if (ret < 0) {
>   		dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);
>   		goto error;
>   	}
>   
> -	ret = snd_hda_codec_build_controls(hcodec);
> -	if (ret < 0) {
> -		dev_err(&hdev->dev, "unable to create controls %d\n", ret);
> -		goto error;
> +	/* HDMI controls need to be created in machine drivers */
> +	if (!is_hdmi_codec(hcodec)) {
> +		ret = snd_hda_codec_build_controls(hcodec);
> +		if (ret < 0) {
> +			dev_err(&hdev->dev, "unable to create controls %d\n",
> +				ret);
> +			goto error;
> +		}
>   	}
>   
>   	hcodec->core.lazy_cache = true;
> diff --git a/sound/soc/codecs/hdac_hda.h b/sound/soc/codecs/hdac_hda.h
> index 6b1bd4f428e7..5d0979f6f215 100644
> --- a/sound/soc/codecs/hdac_hda.h
> +++ b/sound/soc/codecs/hdac_hda.h
> @@ -6,6 +6,16 @@
>   #ifndef __HDAC_HDA_H__
>   #define __HDAC_HDA_H__
>   
> +enum {
> +	HDAC_ANALOG_DAI_ID = 0,
> +	HDAC_DIGITAL_DAI_ID,
> +	HDAC_ALT_ANALOG_DAI_ID,
> +	HDAC_HDMI_0_DAI_ID,
> +	HDAC_HDMI_1_DAI_ID,
> +	HDAC_HDMI_2_DAI_ID,
> +	HDAC_LAST_DAI_ID = HDAC_HDMI_2_DAI_ID,
> +};
> +
>   struct hdac_hda_pcm {
>   	int stream_tag[2];
>   	unsigned int format_val[2];
> @@ -13,7 +23,7 @@ struct hdac_hda_pcm {
>   
>   struct hdac_hda_priv {
>   	struct hda_codec codec;
> -	struct hdac_hda_pcm pcm[2];
> +	struct hdac_hda_pcm pcm[HDAC_LAST_DAI_ID];
>   };
>   
>   #define hdac_to_hda_priv(_hdac) \
> 


More information about the Alsa-devel mailing list