xref: /openbmc/linux/sound/soc/codecs/hdac_hdmi.c (revision 18382ead3640b5aab9bf4545249d84b51bbcba49)
1*18382eadSSubhransu S. Prusty /*
2*18382eadSSubhransu S. Prusty  *  hdac_hdmi.c - ASoc HDA-HDMI codec driver for Intel platforms
3*18382eadSSubhransu S. Prusty  *
4*18382eadSSubhransu S. Prusty  *  Copyright (C) 2014-2015 Intel Corp
5*18382eadSSubhransu S. Prusty  *  Author: Samreen Nilofer <samreen.nilofer@intel.com>
6*18382eadSSubhransu S. Prusty  *	    Subhransu S. Prusty <subhransu.s.prusty@intel.com>
7*18382eadSSubhransu S. Prusty  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8*18382eadSSubhransu S. Prusty  *
9*18382eadSSubhransu S. Prusty  *  This program is free software; you can redistribute it and/or modify
10*18382eadSSubhransu S. Prusty  *  it under the terms of the GNU General Public License as published by
11*18382eadSSubhransu S. Prusty  *  the Free Software Foundation; version 2 of the License.
12*18382eadSSubhransu S. Prusty  *
13*18382eadSSubhransu S. Prusty  *  This program is distributed in the hope that it will be useful, but
14*18382eadSSubhransu S. Prusty  *  WITHOUT ANY WARRANTY; without even the implied warranty of
15*18382eadSSubhransu S. Prusty  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*18382eadSSubhransu S. Prusty  *  General Public License for more details.
17*18382eadSSubhransu S. Prusty  *
18*18382eadSSubhransu S. Prusty  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19*18382eadSSubhransu S. Prusty  */
20*18382eadSSubhransu S. Prusty #include <linux/init.h>
21*18382eadSSubhransu S. Prusty #include <linux/delay.h>
22*18382eadSSubhransu S. Prusty #include <linux/module.h>
23*18382eadSSubhransu S. Prusty #include <linux/pm_runtime.h>
24*18382eadSSubhransu S. Prusty #include <sound/pcm_params.h>
25*18382eadSSubhransu S. Prusty #include <sound/soc.h>
26*18382eadSSubhransu S. Prusty #include <sound/hdaudio_ext.h>
27*18382eadSSubhransu S. Prusty #include "../../hda/local.h"
28*18382eadSSubhransu S. Prusty 
29*18382eadSSubhransu S. Prusty #define PIN_OUT			(AC_PINCTL_OUT_EN)
30*18382eadSSubhransu S. Prusty #define HDA_MAX_CONNECTIONS     32
31*18382eadSSubhransu S. Prusty 
32*18382eadSSubhransu S. Prusty struct hdac_hdmi_cvt_params {
33*18382eadSSubhransu S. Prusty 	unsigned int channels_min;
34*18382eadSSubhransu S. Prusty 	unsigned int channels_max;
35*18382eadSSubhransu S. Prusty 	u32 rates;
36*18382eadSSubhransu S. Prusty 	u64 formats;
37*18382eadSSubhransu S. Prusty 	unsigned int maxbps;
38*18382eadSSubhransu S. Prusty };
39*18382eadSSubhransu S. Prusty 
40*18382eadSSubhransu S. Prusty struct hdac_hdmi_cvt {
41*18382eadSSubhransu S. Prusty 	hda_nid_t nid;
42*18382eadSSubhransu S. Prusty 	struct hdac_hdmi_cvt_params params;
43*18382eadSSubhransu S. Prusty };
44*18382eadSSubhransu S. Prusty 
45*18382eadSSubhransu S. Prusty struct hdac_hdmi_pin {
46*18382eadSSubhransu S. Prusty 	hda_nid_t nid;
47*18382eadSSubhransu S. Prusty 	int num_mux_nids;
48*18382eadSSubhransu S. Prusty 	hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
49*18382eadSSubhransu S. Prusty };
50*18382eadSSubhransu S. Prusty 
51*18382eadSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map {
52*18382eadSSubhransu S. Prusty 	int dai_id;
53*18382eadSSubhransu S. Prusty 	struct hdac_hdmi_pin pin;
54*18382eadSSubhransu S. Prusty 	struct hdac_hdmi_cvt cvt;
55*18382eadSSubhransu S. Prusty };
56*18382eadSSubhransu S. Prusty 
57*18382eadSSubhransu S. Prusty struct hdac_hdmi_priv {
58*18382eadSSubhransu S. Prusty 	hda_nid_t pin_nid[3];
59*18382eadSSubhransu S. Prusty 	hda_nid_t cvt_nid[3];
60*18382eadSSubhransu S. Prusty 	struct hdac_hdmi_dai_pin_map dai_map[3];
61*18382eadSSubhransu S. Prusty };
62*18382eadSSubhransu S. Prusty 
63*18382eadSSubhransu S. Prusty static int
64*18382eadSSubhransu S. Prusty hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt)
65*18382eadSSubhransu S. Prusty {
66*18382eadSSubhransu S. Prusty 	int err;
67*18382eadSSubhransu S. Prusty 
68*18382eadSSubhransu S. Prusty 	/* Only stereo supported as of now */
69*18382eadSSubhransu S. Prusty 	cvt->params.channels_min = cvt->params.channels_max = 2;
70*18382eadSSubhransu S. Prusty 
71*18382eadSSubhransu S. Prusty 	err = snd_hdac_query_supported_pcm(hdac, cvt->nid,
72*18382eadSSubhransu S. Prusty 			&cvt->params.rates,
73*18382eadSSubhransu S. Prusty 			&cvt->params.formats,
74*18382eadSSubhransu S. Prusty 			&cvt->params.maxbps);
75*18382eadSSubhransu S. Prusty 	if (err < 0)
76*18382eadSSubhransu S. Prusty 		dev_err(&hdac->dev,
77*18382eadSSubhransu S. Prusty 			"Failed to query pcm params for nid %d: %d\n",
78*18382eadSSubhransu S. Prusty 			cvt->nid, err);
79*18382eadSSubhransu S. Prusty 
80*18382eadSSubhransu S. Prusty 	return err;
81*18382eadSSubhransu S. Prusty }
82*18382eadSSubhransu S. Prusty 
83*18382eadSSubhransu S. Prusty static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac,
84*18382eadSSubhransu S. Prusty 					struct hdac_hdmi_pin *pin)
85*18382eadSSubhransu S. Prusty {
86*18382eadSSubhransu S. Prusty 	if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) {
87*18382eadSSubhransu S. Prusty 		dev_warn(&hdac->hdac.dev,
88*18382eadSSubhransu S. Prusty 			"HDMI: pin %d wcaps %#x does not support connection list\n",
89*18382eadSSubhransu S. Prusty 			pin->nid, get_wcaps(&hdac->hdac, pin->nid));
90*18382eadSSubhransu S. Prusty 		return -EINVAL;
91*18382eadSSubhransu S. Prusty 	}
92*18382eadSSubhransu S. Prusty 
93*18382eadSSubhransu S. Prusty 	pin->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid,
94*18382eadSSubhransu S. Prusty 			pin->mux_nids, HDA_MAX_CONNECTIONS);
95*18382eadSSubhransu S. Prusty 	if (pin->num_mux_nids == 0) {
96*18382eadSSubhransu S. Prusty 		dev_err(&hdac->hdac.dev, "No connections found\n");
97*18382eadSSubhransu S. Prusty 		return -ENODEV;
98*18382eadSSubhransu S. Prusty 	}
99*18382eadSSubhransu S. Prusty 
100*18382eadSSubhransu S. Prusty 	return pin->num_mux_nids;
101*18382eadSSubhransu S. Prusty }
102*18382eadSSubhransu S. Prusty 
103*18382eadSSubhransu S. Prusty static void hdac_hdmi_fill_widget_info(struct snd_soc_dapm_widget *w,
104*18382eadSSubhransu S. Prusty 				enum snd_soc_dapm_type id,
105*18382eadSSubhransu S. Prusty 				const char *wname, const char *stream)
106*18382eadSSubhransu S. Prusty {
107*18382eadSSubhransu S. Prusty 	w->id = id;
108*18382eadSSubhransu S. Prusty 	w->name = wname;
109*18382eadSSubhransu S. Prusty 	w->sname = stream;
110*18382eadSSubhransu S. Prusty 	w->reg = SND_SOC_NOPM;
111*18382eadSSubhransu S. Prusty 	w->shift = 0;
112*18382eadSSubhransu S. Prusty 	w->kcontrol_news = NULL;
113*18382eadSSubhransu S. Prusty 	w->num_kcontrols = 0;
114*18382eadSSubhransu S. Prusty 	w->priv = NULL;
115*18382eadSSubhransu S. Prusty }
116*18382eadSSubhransu S. Prusty 
117*18382eadSSubhransu S. Prusty static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route,
118*18382eadSSubhransu S. Prusty 		const char *sink, const char *control, const char *src)
119*18382eadSSubhransu S. Prusty {
120*18382eadSSubhransu S. Prusty 	route->sink = sink;
121*18382eadSSubhransu S. Prusty 	route->source = src;
122*18382eadSSubhransu S. Prusty 	route->control = control;
123*18382eadSSubhransu S. Prusty 	route->connected = NULL;
124*18382eadSSubhransu S. Prusty }
125*18382eadSSubhransu S. Prusty 
126*18382eadSSubhransu S. Prusty static void create_fill_widget_route_map(struct snd_soc_dapm_context *dapm,
127*18382eadSSubhransu S. Prusty 					struct hdac_hdmi_dai_pin_map *dai_map)
128*18382eadSSubhransu S. Prusty {
129*18382eadSSubhransu S. Prusty 	struct snd_soc_dapm_route route[1];
130*18382eadSSubhransu S. Prusty 	struct snd_soc_dapm_widget widgets[2] = { {0} };
131*18382eadSSubhransu S. Prusty 
132*18382eadSSubhransu S. Prusty 	memset(&route, 0, sizeof(route));
133*18382eadSSubhransu S. Prusty 
134*18382eadSSubhransu S. Prusty 	hdac_hdmi_fill_widget_info(&widgets[0], snd_soc_dapm_output,
135*18382eadSSubhransu S. Prusty 			"hif1 Output", NULL);
136*18382eadSSubhransu S. Prusty 	hdac_hdmi_fill_widget_info(&widgets[1], snd_soc_dapm_aif_in,
137*18382eadSSubhransu S. Prusty 			"Coverter 1", "hif1");
138*18382eadSSubhransu S. Prusty 
139*18382eadSSubhransu S. Prusty 	hdac_hdmi_fill_route(&route[0], "hif1 Output", NULL, "Coverter 1");
140*18382eadSSubhransu S. Prusty 
141*18382eadSSubhransu S. Prusty 	snd_soc_dapm_new_controls(dapm, widgets, ARRAY_SIZE(widgets));
142*18382eadSSubhransu S. Prusty 	snd_soc_dapm_add_routes(dapm, route, ARRAY_SIZE(route));
143*18382eadSSubhransu S. Prusty }
144*18382eadSSubhransu S. Prusty 
145*18382eadSSubhransu S. Prusty static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev,
146*18382eadSSubhransu S. Prusty 			struct hdac_hdmi_dai_pin_map *dai_map,
147*18382eadSSubhransu S. Prusty 			hda_nid_t pin_nid, hda_nid_t cvt_nid, int dai_id)
148*18382eadSSubhransu S. Prusty {
149*18382eadSSubhransu S. Prusty 	int ret;
150*18382eadSSubhransu S. Prusty 
151*18382eadSSubhransu S. Prusty 	dai_map->dai_id = dai_id;
152*18382eadSSubhransu S. Prusty 	dai_map->pin.nid = pin_nid;
153*18382eadSSubhransu S. Prusty 
154*18382eadSSubhransu S. Prusty 	ret = hdac_hdmi_query_pin_connlist(edev, &dai_map->pin);
155*18382eadSSubhransu S. Prusty 	if (ret < 0) {
156*18382eadSSubhransu S. Prusty 		dev_err(&edev->hdac.dev,
157*18382eadSSubhransu S. Prusty 			"Error querying connection list: %d\n", ret);
158*18382eadSSubhransu S. Prusty 		return ret;
159*18382eadSSubhransu S. Prusty 	}
160*18382eadSSubhransu S. Prusty 
161*18382eadSSubhransu S. Prusty 	dai_map->cvt.nid = cvt_nid;
162*18382eadSSubhransu S. Prusty 
163*18382eadSSubhransu S. Prusty 	/* Enable out path for this pin widget */
164*18382eadSSubhransu S. Prusty 	snd_hdac_codec_write(&edev->hdac, pin_nid, 0,
165*18382eadSSubhransu S. Prusty 			AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
166*18382eadSSubhransu S. Prusty 
167*18382eadSSubhransu S. Prusty 	/* Enable transmission */
168*18382eadSSubhransu S. Prusty 	snd_hdac_codec_write(&edev->hdac, cvt_nid, 0,
169*18382eadSSubhransu S. Prusty 			AC_VERB_SET_DIGI_CONVERT_1, 1);
170*18382eadSSubhransu S. Prusty 
171*18382eadSSubhransu S. Prusty 	/* Category Code (CC) to zero */
172*18382eadSSubhransu S. Prusty 	snd_hdac_codec_write(&edev->hdac, cvt_nid, 0,
173*18382eadSSubhransu S. Prusty 			AC_VERB_SET_DIGI_CONVERT_2, 0);
174*18382eadSSubhransu S. Prusty 
175*18382eadSSubhransu S. Prusty 	snd_hdac_codec_write(&edev->hdac, pin_nid, 0,
176*18382eadSSubhransu S. Prusty 			AC_VERB_SET_CONNECT_SEL, 0);
177*18382eadSSubhransu S. Prusty 
178*18382eadSSubhransu S. Prusty 	return hdac_hdmi_query_cvt_params(&edev->hdac, &dai_map->cvt);
179*18382eadSSubhransu S. Prusty }
180*18382eadSSubhransu S. Prusty 
181*18382eadSSubhransu S. Prusty /*
182*18382eadSSubhransu S. Prusty  * Parse all nodes and store the cvt/pin nids in array
183*18382eadSSubhransu S. Prusty  * Add one time initialization for pin and cvt widgets
184*18382eadSSubhransu S. Prusty  */
185*18382eadSSubhransu S. Prusty static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
186*18382eadSSubhransu S. Prusty {
187*18382eadSSubhransu S. Prusty 	hda_nid_t nid;
188*18382eadSSubhransu S. Prusty 	int i;
189*18382eadSSubhransu S. Prusty 	struct hdac_device *hdac = &edev->hdac;
190*18382eadSSubhransu S. Prusty 	struct hdac_hdmi_priv *hdmi = edev->private_data;
191*18382eadSSubhransu S. Prusty 	int cvt_nid = 0, pin_nid = 0;
192*18382eadSSubhransu S. Prusty 
193*18382eadSSubhransu S. Prusty 	hdac->num_nodes = snd_hdac_get_sub_nodes(hdac, hdac->afg, &nid);
194*18382eadSSubhransu S. Prusty 	if (!nid || hdac->num_nodes < 0) {
195*18382eadSSubhransu S. Prusty 		dev_warn(&hdac->dev, "HDMI: failed to get afg sub nodes\n");
196*18382eadSSubhransu S. Prusty 		return -EINVAL;
197*18382eadSSubhransu S. Prusty 	}
198*18382eadSSubhransu S. Prusty 
199*18382eadSSubhransu S. Prusty 	hdac->start_nid = nid;
200*18382eadSSubhransu S. Prusty 
201*18382eadSSubhransu S. Prusty 	for (i = 0; i < hdac->num_nodes; i++, nid++) {
202*18382eadSSubhransu S. Prusty 		unsigned int caps;
203*18382eadSSubhransu S. Prusty 		unsigned int type;
204*18382eadSSubhransu S. Prusty 
205*18382eadSSubhransu S. Prusty 		caps = get_wcaps(hdac, nid);
206*18382eadSSubhransu S. Prusty 		type = get_wcaps_type(caps);
207*18382eadSSubhransu S. Prusty 
208*18382eadSSubhransu S. Prusty 		if (!(caps & AC_WCAP_DIGITAL))
209*18382eadSSubhransu S. Prusty 			continue;
210*18382eadSSubhransu S. Prusty 
211*18382eadSSubhransu S. Prusty 		switch (type) {
212*18382eadSSubhransu S. Prusty 
213*18382eadSSubhransu S. Prusty 		case AC_WID_AUD_OUT:
214*18382eadSSubhransu S. Prusty 			hdmi->cvt_nid[cvt_nid] = nid;
215*18382eadSSubhransu S. Prusty 			cvt_nid++;
216*18382eadSSubhransu S. Prusty 			break;
217*18382eadSSubhransu S. Prusty 
218*18382eadSSubhransu S. Prusty 		case AC_WID_PIN:
219*18382eadSSubhransu S. Prusty 			hdmi->pin_nid[pin_nid] = nid;
220*18382eadSSubhransu S. Prusty 			pin_nid++;
221*18382eadSSubhransu S. Prusty 			break;
222*18382eadSSubhransu S. Prusty 		}
223*18382eadSSubhransu S. Prusty 	}
224*18382eadSSubhransu S. Prusty 
225*18382eadSSubhransu S. Prusty 	hdac->end_nid = nid;
226*18382eadSSubhransu S. Prusty 
227*18382eadSSubhransu S. Prusty 	if (!pin_nid || !cvt_nid)
228*18382eadSSubhransu S. Prusty 		return -EIO;
229*18382eadSSubhransu S. Prusty 
230*18382eadSSubhransu S. Prusty 	/*
231*18382eadSSubhransu S. Prusty 	 * Currently on board only 1 pin and 1 converter is enabled for
232*18382eadSSubhransu S. Prusty 	 * simplification, more will be added eventually
233*18382eadSSubhransu S. Prusty 	 * So using fixed map for dai_id:pin:cvt
234*18382eadSSubhransu S. Prusty 	 */
235*18382eadSSubhransu S. Prusty 	return hdac_hdmi_init_dai_map(edev, &hdmi->dai_map[0], hdmi->pin_nid[0],
236*18382eadSSubhransu S. Prusty 			hdmi->cvt_nid[0], 0);
237*18382eadSSubhransu S. Prusty }
238*18382eadSSubhransu S. Prusty 
239*18382eadSSubhransu S. Prusty static int hdmi_codec_probe(struct snd_soc_codec *codec)
240*18382eadSSubhransu S. Prusty {
241*18382eadSSubhransu S. Prusty 	struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
242*18382eadSSubhransu S. Prusty 	struct hdac_hdmi_priv *hdmi = edev->private_data;
243*18382eadSSubhransu S. Prusty 	struct snd_soc_dapm_context *dapm =
244*18382eadSSubhransu S. Prusty 		snd_soc_component_get_dapm(&codec->component);
245*18382eadSSubhransu S. Prusty 
246*18382eadSSubhransu S. Prusty 	edev->scodec = codec;
247*18382eadSSubhransu S. Prusty 
248*18382eadSSubhransu S. Prusty 	create_fill_widget_route_map(dapm, &hdmi->dai_map[0]);
249*18382eadSSubhransu S. Prusty 
250*18382eadSSubhransu S. Prusty 	/* Imp: Store the card pointer in hda_codec */
251*18382eadSSubhransu S. Prusty 	edev->card = dapm->card->snd_card;
252*18382eadSSubhransu S. Prusty 
253*18382eadSSubhransu S. Prusty 	return 0;
254*18382eadSSubhransu S. Prusty }
255*18382eadSSubhransu S. Prusty 
256*18382eadSSubhransu S. Prusty static struct snd_soc_codec_driver hdmi_hda_codec = {
257*18382eadSSubhransu S. Prusty 	.probe		= hdmi_codec_probe,
258*18382eadSSubhransu S. Prusty 	.idle_bias_off	= true,
259*18382eadSSubhransu S. Prusty };
260*18382eadSSubhransu S. Prusty 
261*18382eadSSubhransu S. Prusty static struct snd_soc_dai_driver hdmi_dais[] = {
262*18382eadSSubhransu S. Prusty 	{	.name = "intel-hdmi-hif1",
263*18382eadSSubhransu S. Prusty 		.playback = {
264*18382eadSSubhransu S. Prusty 			.stream_name = "hif1",
265*18382eadSSubhransu S. Prusty 			.channels_min = 2,
266*18382eadSSubhransu S. Prusty 			.channels_max = 2,
267*18382eadSSubhransu S. Prusty 			.rates = SNDRV_PCM_RATE_32000 |
268*18382eadSSubhransu S. Prusty 				SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
269*18382eadSSubhransu S. Prusty 				SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
270*18382eadSSubhransu S. Prusty 				SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
271*18382eadSSubhransu S. Prusty 			.formats = SNDRV_PCM_FMTBIT_S16_LE |
272*18382eadSSubhransu S. Prusty 				SNDRV_PCM_FMTBIT_S20_3LE |
273*18382eadSSubhransu S. Prusty 				SNDRV_PCM_FMTBIT_S24_LE |
274*18382eadSSubhransu S. Prusty 				SNDRV_PCM_FMTBIT_S32_LE,
275*18382eadSSubhransu S. Prusty 
276*18382eadSSubhransu S. Prusty 		},
277*18382eadSSubhransu S. Prusty 	},
278*18382eadSSubhransu S. Prusty };
279*18382eadSSubhransu S. Prusty 
280*18382eadSSubhransu S. Prusty static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
281*18382eadSSubhransu S. Prusty {
282*18382eadSSubhransu S. Prusty 	struct hdac_device *codec = &edev->hdac;
283*18382eadSSubhransu S. Prusty 	struct hdac_hdmi_priv *hdmi_priv;
284*18382eadSSubhransu S. Prusty 	int ret = 0;
285*18382eadSSubhransu S. Prusty 
286*18382eadSSubhransu S. Prusty 	hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL);
287*18382eadSSubhransu S. Prusty 	if (hdmi_priv == NULL)
288*18382eadSSubhransu S. Prusty 		return -ENOMEM;
289*18382eadSSubhransu S. Prusty 
290*18382eadSSubhransu S. Prusty 	edev->private_data = hdmi_priv;
291*18382eadSSubhransu S. Prusty 
292*18382eadSSubhransu S. Prusty 	dev_set_drvdata(&codec->dev, edev);
293*18382eadSSubhransu S. Prusty 
294*18382eadSSubhransu S. Prusty 	ret = hdac_hdmi_parse_and_map_nid(edev);
295*18382eadSSubhransu S. Prusty 	if (ret < 0)
296*18382eadSSubhransu S. Prusty 		return ret;
297*18382eadSSubhransu S. Prusty 
298*18382eadSSubhransu S. Prusty 	/* ASoC specific initialization */
299*18382eadSSubhransu S. Prusty 	return snd_soc_register_codec(&codec->dev, &hdmi_hda_codec,
300*18382eadSSubhransu S. Prusty 			hdmi_dais, ARRAY_SIZE(hdmi_dais));
301*18382eadSSubhransu S. Prusty }
302*18382eadSSubhransu S. Prusty 
303*18382eadSSubhransu S. Prusty static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)
304*18382eadSSubhransu S. Prusty {
305*18382eadSSubhransu S. Prusty 	snd_soc_unregister_codec(&edev->hdac.dev);
306*18382eadSSubhransu S. Prusty 
307*18382eadSSubhransu S. Prusty 	return 0;
308*18382eadSSubhransu S. Prusty }
309*18382eadSSubhransu S. Prusty 
310*18382eadSSubhransu S. Prusty static const struct hda_device_id hdmi_list[] = {
311*18382eadSSubhransu S. Prusty 	HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0),
312*18382eadSSubhransu S. Prusty 	{}
313*18382eadSSubhransu S. Prusty };
314*18382eadSSubhransu S. Prusty 
315*18382eadSSubhransu S. Prusty MODULE_DEVICE_TABLE(hdaudio, hdmi_list);
316*18382eadSSubhransu S. Prusty 
317*18382eadSSubhransu S. Prusty static struct hdac_ext_driver hdmi_driver = {
318*18382eadSSubhransu S. Prusty 	. hdac = {
319*18382eadSSubhransu S. Prusty 		.driver = {
320*18382eadSSubhransu S. Prusty 			.name   = "HDMI HDA Codec",
321*18382eadSSubhransu S. Prusty 		},
322*18382eadSSubhransu S. Prusty 		.id_table       = hdmi_list,
323*18382eadSSubhransu S. Prusty 	},
324*18382eadSSubhransu S. Prusty 	.probe          = hdac_hdmi_dev_probe,
325*18382eadSSubhransu S. Prusty 	.remove         = hdac_hdmi_dev_remove,
326*18382eadSSubhransu S. Prusty };
327*18382eadSSubhransu S. Prusty 
328*18382eadSSubhransu S. Prusty static int __init hdmi_init(void)
329*18382eadSSubhransu S. Prusty {
330*18382eadSSubhransu S. Prusty 	return snd_hda_ext_driver_register(&hdmi_driver);
331*18382eadSSubhransu S. Prusty }
332*18382eadSSubhransu S. Prusty 
333*18382eadSSubhransu S. Prusty static void __exit hdmi_exit(void)
334*18382eadSSubhransu S. Prusty {
335*18382eadSSubhransu S. Prusty 	snd_hda_ext_driver_unregister(&hdmi_driver);
336*18382eadSSubhransu S. Prusty }
337*18382eadSSubhransu S. Prusty 
338*18382eadSSubhransu S. Prusty module_init(hdmi_init);
339*18382eadSSubhransu S. Prusty module_exit(hdmi_exit);
340*18382eadSSubhransu S. Prusty 
341*18382eadSSubhransu S. Prusty MODULE_LICENSE("GPL v2");
342*18382eadSSubhransu S. Prusty MODULE_DESCRIPTION("HDMI HD codec");
343*18382eadSSubhransu S. Prusty MODULE_AUTHOR("Samreen Nilofer<samreen.nilofer@intel.com>");
344*18382eadSSubhransu S. Prusty MODULE_AUTHOR("Subhransu S. Prusty<subhransu.s.prusty@intel.com>");
345