1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2019 Intel Corporation 4 5 #include <linux/module.h> 6 #include <sound/pcm.h> 7 #include <sound/soc.h> 8 #include <sound/hda_codec.h> 9 #include <sound/hda_i915.h> 10 #include "../../codecs/hdac_hda.h" 11 12 #include "hda_dsp_common.h" 13 14 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 15 16 /* 17 * Search card topology and return PCM device number 18 * matching Nth playback HDMI device (zero-based index). 19 */ 20 static struct snd_pcm *hda_dsp_hdmi_pcm_handle(struct snd_soc_card *card, 21 int hdmi_idx) 22 { 23 struct snd_soc_pcm_runtime *rtd; 24 struct snd_pcm *spcm; 25 int i = 0; 26 27 for_each_card_rtds(card, rtd) { 28 /* ignore BE PCMs */ 29 if (rtd->dai_link && rtd->dai_link->no_pcm) 30 continue; 31 32 spcm = rtd->pcm; 33 34 /* ignore PCMs with no playback streams */ 35 if (!spcm || !spcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) 36 continue; 37 38 /* look for FE PCMs with name "HDMI x" */ 39 if (spcm && strstr(spcm->id, "HDMI")) { 40 if (i == hdmi_idx) 41 return rtd->pcm; 42 ++i; 43 } 44 } 45 46 return NULL; 47 } 48 49 /* 50 * Search card topology and register HDMI PCM related controls 51 * to codec driver. 52 */ 53 int hda_dsp_hdmi_build_controls(struct snd_soc_card *card, 54 struct snd_soc_component *comp) 55 { 56 struct hdac_hda_priv *hda_pvt; 57 struct hda_codec *hcodec; 58 struct snd_pcm *spcm; 59 struct hda_pcm *hpcm; 60 int err = 0, i = 0; 61 62 if (!comp) 63 return -EINVAL; 64 65 hda_pvt = snd_soc_component_get_drvdata(comp); 66 hcodec = hda_pvt->codec; 67 68 list_for_each_entry(hpcm, &hcodec->pcm_list_head, list) { 69 spcm = hda_dsp_hdmi_pcm_handle(card, i); 70 if (spcm) { 71 hpcm->pcm = spcm; 72 hpcm->device = spcm->device; 73 dev_dbg(card->dev, 74 "mapping HDMI converter %d to PCM %d (%p)\n", 75 i, hpcm->device, spcm); 76 } else { 77 hpcm->pcm = NULL; 78 hpcm->device = SNDRV_PCM_INVALID_DEVICE; 79 dev_warn(card->dev, 80 "%s: no PCM in topology for HDMI converter %d\n", 81 __func__, i); 82 } 83 i++; 84 } 85 snd_hdac_display_power(hcodec->core.bus, 86 HDA_CODEC_IDX_CONTROLLER, true); 87 err = snd_hda_codec_build_controls(hcodec); 88 if (err < 0) 89 dev_err(card->dev, "unable to create controls %d\n", err); 90 snd_hdac_display_power(hcodec->core.bus, 91 HDA_CODEC_IDX_CONTROLLER, false); 92 93 return err; 94 } 95 EXPORT_SYMBOL_NS(hda_dsp_hdmi_build_controls, "SND_SOC_INTEL_HDA_DSP_COMMON"); 96 97 #endif 98 99 MODULE_DESCRIPTION("ASoC Intel HDMI helpers"); 100 MODULE_LICENSE("GPL"); 101