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@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;
elsepcm->stream_tag[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
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) \