1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2020 Intel Corporation
3 
4 /*
5  *  sof_sdw_hdmi - Helpers to handle HDMI from generic machine driver
6  */
7 
8 #include <linux/device.h>
9 #include <linux/errno.h>
10 #include <linux/kernel.h>
11 #include <linux/list.h>
12 #include <sound/soc.h>
13 #include <sound/soc-acpi.h>
14 #include <sound/jack.h>
15 #include "sof_sdw_common.h"
16 #include "../../codecs/hdac_hdmi.h"
17 #include "hda_dsp_common.h"
18 
19 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
20 static struct snd_soc_jack hdmi[MAX_HDMI_NUM];
21 
22 struct hdmi_pcm {
23 	struct list_head head;
24 	struct snd_soc_dai *codec_dai;
25 	int device;
26 };
27 
28 int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd)
29 {
30 	struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
31 	struct snd_soc_dai *dai = rtd->codec_dai;
32 	struct hdmi_pcm *pcm;
33 
34 	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
35 	if (!pcm)
36 		return -ENOMEM;
37 
38 	/* dai_link id is 1:1 mapped to the PCM device */
39 	pcm->device = rtd->dai_link->id;
40 	pcm->codec_dai = dai;
41 
42 	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
43 
44 	return 0;
45 }
46 
47 #define NAME_SIZE	32
48 int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card)
49 {
50 	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
51 	struct hdmi_pcm *pcm;
52 	struct snd_soc_component *component = NULL;
53 	int err, i = 0;
54 	char jack_name[NAME_SIZE];
55 
56 	pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm,
57 			       head);
58 	component = pcm->codec_dai->component;
59 
60 	if (ctx->common_hdmi_codec_drv)
61 		return hda_dsp_hdmi_build_controls(card, component);
62 
63 	list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
64 		component = pcm->codec_dai->component;
65 		snprintf(jack_name, sizeof(jack_name),
66 			 "HDMI/DP, pcm=%d Jack", pcm->device);
67 		err = snd_soc_card_jack_new(card, jack_name,
68 					    SND_JACK_AVOUT, &hdmi[i],
69 					    NULL, 0);
70 
71 		if (err)
72 			return err;
73 
74 		err = snd_jack_add_new_kctl(hdmi[i].jack,
75 					    jack_name, SND_JACK_AVOUT);
76 		if (err)
77 			dev_warn(component->dev, "failed creating Jack kctl\n");
78 
79 		err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
80 					  &hdmi[i]);
81 		if (err < 0)
82 			return err;
83 
84 		i++;
85 	}
86 
87 	if (!component)
88 		return -EINVAL;
89 
90 	return hdac_hdmi_jack_port_init(component, &card->dapm);
91 }
92 #else
93 int hdmi_card_late_probe(struct snd_soc_card *card)
94 {
95 	return 0;
96 }
97 #endif
98