18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// Copyright(c) 2019 Intel Corporation. All rights reserved.
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <sound/pcm.h>
68c2ecf20Sopenharmony_ci#include <sound/soc.h>
78c2ecf20Sopenharmony_ci#include <sound/hda_codec.h>
88c2ecf20Sopenharmony_ci#include <sound/hda_i915.h>
98c2ecf20Sopenharmony_ci#include "../../codecs/hdac_hda.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include "hda_dsp_common.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/*
168c2ecf20Sopenharmony_ci * Search card topology and return PCM device number
178c2ecf20Sopenharmony_ci * matching Nth HDMI device (zero-based index).
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_cistatic struct snd_pcm *hda_dsp_hdmi_pcm_handle(struct snd_soc_card *card,
208c2ecf20Sopenharmony_ci					       int hdmi_idx)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd;
238c2ecf20Sopenharmony_ci	struct snd_pcm *spcm;
248c2ecf20Sopenharmony_ci	int i = 0;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	for_each_card_rtds(card, rtd) {
278c2ecf20Sopenharmony_ci		spcm = rtd->pcm ?
288c2ecf20Sopenharmony_ci			rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].pcm : NULL;
298c2ecf20Sopenharmony_ci		if (spcm && strstr(spcm->id, "HDMI")) {
308c2ecf20Sopenharmony_ci			if (i == hdmi_idx)
318c2ecf20Sopenharmony_ci				return rtd->pcm;
328c2ecf20Sopenharmony_ci			++i;
338c2ecf20Sopenharmony_ci		}
348c2ecf20Sopenharmony_ci	}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	return NULL;
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/*
408c2ecf20Sopenharmony_ci * Search card topology and register HDMI PCM related controls
418c2ecf20Sopenharmony_ci * to codec driver.
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_ciint hda_dsp_hdmi_build_controls(struct snd_soc_card *card,
448c2ecf20Sopenharmony_ci				struct snd_soc_component *comp)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	struct hdac_hda_priv *hda_pvt;
478c2ecf20Sopenharmony_ci	struct hda_codec *hcodec;
488c2ecf20Sopenharmony_ci	struct snd_pcm *spcm;
498c2ecf20Sopenharmony_ci	struct hda_pcm *hpcm;
508c2ecf20Sopenharmony_ci	int err = 0, i = 0;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	if (!comp)
538c2ecf20Sopenharmony_ci		return -EINVAL;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	hda_pvt = snd_soc_component_get_drvdata(comp);
568c2ecf20Sopenharmony_ci	hcodec = &hda_pvt->codec;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	list_for_each_entry(hpcm, &hcodec->pcm_list_head, list) {
598c2ecf20Sopenharmony_ci		spcm = hda_dsp_hdmi_pcm_handle(card, i);
608c2ecf20Sopenharmony_ci		if (spcm) {
618c2ecf20Sopenharmony_ci			hpcm->pcm = spcm;
628c2ecf20Sopenharmony_ci			hpcm->device = spcm->device;
638c2ecf20Sopenharmony_ci			dev_dbg(card->dev,
648c2ecf20Sopenharmony_ci				"%s: mapping HDMI converter %d to PCM %d (%p)\n",
658c2ecf20Sopenharmony_ci				__func__, i, hpcm->device, spcm);
668c2ecf20Sopenharmony_ci		} else {
678c2ecf20Sopenharmony_ci			hpcm->pcm = NULL;
688c2ecf20Sopenharmony_ci			hpcm->device = SNDRV_PCM_INVALID_DEVICE;
698c2ecf20Sopenharmony_ci			dev_warn(card->dev,
708c2ecf20Sopenharmony_ci				 "%s: no PCM in topology for HDMI converter %d\n\n",
718c2ecf20Sopenharmony_ci				 __func__, i);
728c2ecf20Sopenharmony_ci		}
738c2ecf20Sopenharmony_ci		i++;
748c2ecf20Sopenharmony_ci	}
758c2ecf20Sopenharmony_ci	snd_hdac_display_power(hcodec->core.bus,
768c2ecf20Sopenharmony_ci			       HDA_CODEC_IDX_CONTROLLER, true);
778c2ecf20Sopenharmony_ci	err = snd_hda_codec_build_controls(hcodec);
788c2ecf20Sopenharmony_ci	if (err < 0)
798c2ecf20Sopenharmony_ci		dev_err(card->dev, "unable to create controls %d\n", err);
808c2ecf20Sopenharmony_ci	snd_hdac_display_power(hcodec->core.bus,
818c2ecf20Sopenharmony_ci			       HDA_CODEC_IDX_CONTROLLER, false);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	return err;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#endif
87