1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2019 Intel Corporation. All rights reserved. 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 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 spcm = rtd->pcm ? 29 rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].pcm : NULL; 30 if (spcm && strstr(spcm->id, "HDMI")) { 31 if (i == hdmi_idx) 32 return rtd->pcm; 33 ++i; 34 } 35 } 36 37 return NULL; 38 } 39 40 /* 41 * Search card topology and register HDMI PCM related controls 42 * to codec driver. 43 */ 44 int hda_dsp_hdmi_build_controls(struct snd_soc_card *card, 45 struct snd_soc_component *comp) 46 { 47 struct hdac_hda_priv *hda_pvt; 48 struct hda_codec *hcodec; 49 struct snd_pcm *spcm; 50 struct hda_pcm *hpcm; 51 int err = 0, i = 0; 52 53 if (!comp) 54 return -EINVAL; 55 56 hda_pvt = snd_soc_component_get_drvdata(comp); 57 hcodec = &hda_pvt->codec; 58 59 list_for_each_entry(hpcm, &hcodec->pcm_list_head, list) { 60 spcm = hda_dsp_hdmi_pcm_handle(card, i); 61 if (spcm) { 62 hpcm->pcm = spcm; 63 hpcm->device = spcm->device; 64 dev_dbg(card->dev, 65 "mapping HDMI converter %d to PCM %d (%p)\n", 66 i, hpcm->device, spcm); 67 } else { 68 hpcm->pcm = NULL; 69 hpcm->device = SNDRV_PCM_INVALID_DEVICE; 70 dev_warn(card->dev, 71 "%s: no PCM in topology for HDMI converter %d\n", 72 __func__, i); 73 } 74 i++; 75 } 76 snd_hdac_display_power(hcodec->core.bus, 77 HDA_CODEC_IDX_CONTROLLER, true); 78 err = snd_hda_codec_build_controls(hcodec); 79 if (err < 0) 80 dev_err(card->dev, "unable to create controls %d\n", err); 81 snd_hdac_display_power(hcodec->core.bus, 82 HDA_CODEC_IDX_CONTROLLER, false); 83 84 return err; 85 } 86 EXPORT_SYMBOL_NS(hda_dsp_hdmi_build_controls, SND_SOC_INTEL_HDA_DSP_COMMON); 87 88 #endif 89 90 MODULE_DESCRIPTION("ASoC Intel HDMI helpers"); 91 MODULE_LICENSE("GPL"); 92