Skip to content

Commit 608b8c3

Browse files
kv2019ibroonie
authored andcommitted
ASoC: hdac_hda: add support for HDMI/DP as a HDA codec
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 <[email protected]> Reviewed-by: Takashi Iwai <[email protected]> Reviewed-by: Pierre-Louis Bossart <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 2a2edfb commit 608b8c3

File tree

2 files changed

+114
-13
lines changed

2 files changed

+114
-13
lines changed

sound/soc/codecs/hdac_hda.c

Lines changed: 102 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@
1414
#include <sound/pcm_params.h>
1515
#include <sound/soc.h>
1616
#include <sound/hdaudio_ext.h>
17+
#include <sound/hda_i915.h>
1718
#include <sound/hda_codec.h>
1819
#include <sound/hda_register.h>
19-
#include "hdac_hda.h"
2020

21-
#define HDAC_ANALOG_DAI_ID 0
22-
#define HDAC_DIGITAL_DAI_ID 1
23-
#define HDAC_ALT_ANALOG_DAI_ID 2
21+
#include "hdac_hda.h"
2422

2523
#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
2624
SNDRV_PCM_FMTBIT_U8 | \
@@ -32,6 +30,11 @@
3230
SNDRV_PCM_FMTBIT_U32_LE | \
3331
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
3432

33+
#define STUB_HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
34+
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
35+
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
36+
SNDRV_PCM_RATE_192000)
37+
3538
static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
3639
struct snd_soc_dai *dai);
3740
static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
@@ -121,7 +124,46 @@ static struct snd_soc_dai_driver hdac_hda_dais[] = {
121124
.formats = STUB_FORMATS,
122125
.sig_bits = 24,
123126
},
124-
}
127+
},
128+
{
129+
.id = HDAC_HDMI_0_DAI_ID,
130+
.name = "intel-hdmi-hifi1",
131+
.ops = &hdac_hda_dai_ops,
132+
.playback = {
133+
.stream_name = "hifi1",
134+
.channels_min = 1,
135+
.channels_max = 32,
136+
.rates = STUB_HDMI_RATES,
137+
.formats = STUB_FORMATS,
138+
.sig_bits = 24,
139+
},
140+
},
141+
{
142+
.id = HDAC_HDMI_1_DAI_ID,
143+
.name = "intel-hdmi-hifi2",
144+
.ops = &hdac_hda_dai_ops,
145+
.playback = {
146+
.stream_name = "hifi2",
147+
.channels_min = 1,
148+
.channels_max = 32,
149+
.rates = STUB_HDMI_RATES,
150+
.formats = STUB_FORMATS,
151+
.sig_bits = 24,
152+
},
153+
},
154+
{
155+
.id = HDAC_HDMI_2_DAI_ID,
156+
.name = "intel-hdmi-hifi3",
157+
.ops = &hdac_hda_dai_ops,
158+
.playback = {
159+
.stream_name = "hifi3",
160+
.channels_min = 1,
161+
.channels_max = 32,
162+
.rates = STUB_HDMI_RATES,
163+
.formats = STUB_FORMATS,
164+
.sig_bits = 24,
165+
},
166+
},
125167

126168
};
127169

@@ -135,10 +177,11 @@ static int hdac_hda_dai_set_tdm_slot(struct snd_soc_dai *dai,
135177

136178
hda_pvt = snd_soc_component_get_drvdata(component);
137179
pcm = &hda_pvt->pcm[dai->id];
180+
138181
if (tx_mask)
139-
pcm[dai->id].stream_tag[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
182+
pcm->stream_tag[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
140183
else
141-
pcm[dai->id].stream_tag[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
184+
pcm->stream_tag[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
142185

143186
return 0;
144187
}
@@ -278,6 +321,12 @@ static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
278321
struct hda_pcm *cpcm;
279322
const char *pcm_name;
280323

324+
/*
325+
* map DAI ID to the closest matching PCM name, using the naming
326+
* scheme used by hda-codec snd_hda_gen_build_pcms() and for
327+
* HDMI in hda_codec patch_hdmi.c)
328+
*/
329+
281330
switch (dai->id) {
282331
case HDAC_ANALOG_DAI_ID:
283332
pcm_name = "Analog";
@@ -288,20 +337,41 @@ static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
288337
case HDAC_ALT_ANALOG_DAI_ID:
289338
pcm_name = "Alt Analog";
290339
break;
340+
case HDAC_HDMI_0_DAI_ID:
341+
pcm_name = "HDMI 0";
342+
break;
343+
case HDAC_HDMI_1_DAI_ID:
344+
pcm_name = "HDMI 1";
345+
break;
346+
case HDAC_HDMI_2_DAI_ID:
347+
pcm_name = "HDMI 2";
348+
break;
291349
default:
292350
dev_err(&hcodec->core.dev, "invalid dai id %d\n", dai->id);
293351
return NULL;
294352
}
295353

296354
list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
297-
if (strpbrk(cpcm->name, pcm_name))
355+
if (strstr(cpcm->name, pcm_name))
298356
return cpcm;
299357
}
300358

301359
dev_err(&hcodec->core.dev, "didn't find PCM for DAI %s\n", dai->name);
302360
return NULL;
303361
}
304362

363+
static bool is_hdmi_codec(struct hda_codec *hcodec)
364+
{
365+
struct hda_pcm *cpcm;
366+
367+
list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
368+
if (cpcm->pcm_type == HDA_PCM_TYPE_HDMI)
369+
return true;
370+
}
371+
372+
return false;
373+
}
374+
305375
static int hdac_hda_codec_probe(struct snd_soc_component *component)
306376
{
307377
struct hdac_hda_priv *hda_pvt =
@@ -322,6 +392,15 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
322392

323393
snd_hdac_ext_bus_link_get(hdev->bus, hlink);
324394

395+
/*
396+
* Ensure any HDA display is powered at codec probe.
397+
* After snd_hda_codec_device_new(), display power is
398+
* managed by runtime PM.
399+
*/
400+
if (hda_pvt->need_display_power)
401+
snd_hdac_display_power(hdev->bus,
402+
HDA_CODEC_IDX_CONTROLLER, true);
403+
325404
ret = snd_hda_codec_device_new(hcodec->bus, component->card->snd_card,
326405
hdev->addr, hcodec);
327406
if (ret < 0) {
@@ -366,20 +445,31 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
366445
dev_dbg(&hdev->dev, "no patch file found\n");
367446
}
368447

448+
/* configure codec for 1:1 PCM:DAI mapping */
449+
hcodec->mst_no_extra_pcms = 1;
450+
369451
ret = snd_hda_codec_parse_pcms(hcodec);
370452
if (ret < 0) {
371453
dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);
372454
goto error;
373455
}
374456

375-
ret = snd_hda_codec_build_controls(hcodec);
376-
if (ret < 0) {
377-
dev_err(&hdev->dev, "unable to create controls %d\n", ret);
378-
goto error;
457+
/* HDMI controls need to be created in machine drivers */
458+
if (!is_hdmi_codec(hcodec)) {
459+
ret = snd_hda_codec_build_controls(hcodec);
460+
if (ret < 0) {
461+
dev_err(&hdev->dev, "unable to create controls %d\n",
462+
ret);
463+
goto error;
464+
}
379465
}
380466

381467
hcodec->core.lazy_cache = true;
382468

469+
if (hda_pvt->need_display_power)
470+
snd_hdac_display_power(hdev->bus,
471+
HDA_CODEC_IDX_CONTROLLER, false);
472+
383473
/*
384474
* hdac_device core already sets the state to active and calls
385475
* get_noresume. So enable runtime and set the device to suspend.

sound/soc/codecs/hdac_hda.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,25 @@
66
#ifndef __HDAC_HDA_H__
77
#define __HDAC_HDA_H__
88

9+
enum {
10+
HDAC_ANALOG_DAI_ID = 0,
11+
HDAC_DIGITAL_DAI_ID,
12+
HDAC_ALT_ANALOG_DAI_ID,
13+
HDAC_HDMI_0_DAI_ID,
14+
HDAC_HDMI_1_DAI_ID,
15+
HDAC_HDMI_2_DAI_ID,
16+
HDAC_LAST_DAI_ID = HDAC_HDMI_2_DAI_ID,
17+
};
18+
919
struct hdac_hda_pcm {
1020
int stream_tag[2];
1121
unsigned int format_val[2];
1222
};
1323

1424
struct hdac_hda_priv {
1525
struct hda_codec codec;
16-
struct hdac_hda_pcm pcm[2];
26+
struct hdac_hda_pcm pcm[HDAC_LAST_DAI_ID];
27+
bool need_display_power;
1728
};
1829

1930
#define hdac_to_hda_priv(_hdac) \

0 commit comments

Comments
 (0)