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