118382eadSSubhransu S. Prusty /* 218382eadSSubhransu S. Prusty * hdac_hdmi.c - ASoc HDA-HDMI codec driver for Intel platforms 318382eadSSubhransu S. Prusty * 418382eadSSubhransu S. Prusty * Copyright (C) 2014-2015 Intel Corp 518382eadSSubhransu S. Prusty * Author: Samreen Nilofer <samreen.nilofer@intel.com> 618382eadSSubhransu S. Prusty * Subhransu S. Prusty <subhransu.s.prusty@intel.com> 718382eadSSubhransu S. Prusty * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 818382eadSSubhransu S. Prusty * 918382eadSSubhransu S. Prusty * This program is free software; you can redistribute it and/or modify 1018382eadSSubhransu S. Prusty * it under the terms of the GNU General Public License as published by 1118382eadSSubhransu S. Prusty * the Free Software Foundation; version 2 of the License. 1218382eadSSubhransu S. Prusty * 1318382eadSSubhransu S. Prusty * This program is distributed in the hope that it will be useful, but 1418382eadSSubhransu S. Prusty * WITHOUT ANY WARRANTY; without even the implied warranty of 1518382eadSSubhransu S. Prusty * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1618382eadSSubhransu S. Prusty * General Public License for more details. 1718382eadSSubhransu S. Prusty * 1818382eadSSubhransu S. Prusty * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1918382eadSSubhransu S. Prusty */ 2018382eadSSubhransu S. Prusty #include <linux/init.h> 2118382eadSSubhransu S. Prusty #include <linux/delay.h> 2218382eadSSubhransu S. Prusty #include <linux/module.h> 2318382eadSSubhransu S. Prusty #include <linux/pm_runtime.h> 24*a657f1d0SSubhransu S. Prusty #include <linux/hdmi.h> 2518382eadSSubhransu S. Prusty #include <sound/pcm_params.h> 2618382eadSSubhransu S. Prusty #include <sound/soc.h> 2718382eadSSubhransu S. Prusty #include <sound/hdaudio_ext.h> 2818382eadSSubhransu S. Prusty #include "../../hda/local.h" 2918382eadSSubhransu S. Prusty 30b0362adbSSubhransu S. Prusty #define AMP_OUT_MUTE 0xb080 31b0362adbSSubhransu S. Prusty #define AMP_OUT_UNMUTE 0xb000 3218382eadSSubhransu S. Prusty #define PIN_OUT (AC_PINCTL_OUT_EN) 33b0362adbSSubhransu S. Prusty 3418382eadSSubhransu S. Prusty #define HDA_MAX_CONNECTIONS 32 3518382eadSSubhransu S. Prusty 3618382eadSSubhransu S. Prusty struct hdac_hdmi_cvt_params { 3718382eadSSubhransu S. Prusty unsigned int channels_min; 3818382eadSSubhransu S. Prusty unsigned int channels_max; 3918382eadSSubhransu S. Prusty u32 rates; 4018382eadSSubhransu S. Prusty u64 formats; 4118382eadSSubhransu S. Prusty unsigned int maxbps; 4218382eadSSubhransu S. Prusty }; 4318382eadSSubhransu S. Prusty 4418382eadSSubhransu S. Prusty struct hdac_hdmi_cvt { 4518382eadSSubhransu S. Prusty hda_nid_t nid; 4618382eadSSubhransu S. Prusty struct hdac_hdmi_cvt_params params; 4718382eadSSubhransu S. Prusty }; 4818382eadSSubhransu S. Prusty 4918382eadSSubhransu S. Prusty struct hdac_hdmi_pin { 5018382eadSSubhransu S. Prusty hda_nid_t nid; 5118382eadSSubhransu S. Prusty int num_mux_nids; 5218382eadSSubhransu S. Prusty hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; 5318382eadSSubhransu S. Prusty }; 5418382eadSSubhransu S. Prusty 5518382eadSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map { 5618382eadSSubhransu S. Prusty int dai_id; 5718382eadSSubhransu S. Prusty struct hdac_hdmi_pin pin; 5818382eadSSubhransu S. Prusty struct hdac_hdmi_cvt cvt; 5918382eadSSubhransu S. Prusty }; 6018382eadSSubhransu S. Prusty 6118382eadSSubhransu S. Prusty struct hdac_hdmi_priv { 6218382eadSSubhransu S. Prusty hda_nid_t pin_nid[3]; 6318382eadSSubhransu S. Prusty hda_nid_t cvt_nid[3]; 6418382eadSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map dai_map[3]; 6518382eadSSubhransu S. Prusty }; 6618382eadSSubhransu S. Prusty 67e342ac08SSubhransu S. Prusty static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev) 68e342ac08SSubhransu S. Prusty { 69e342ac08SSubhransu S. Prusty struct hdac_device *hdac = container_of(dev, struct hdac_device, dev); 70e342ac08SSubhransu S. Prusty 71e342ac08SSubhransu S. Prusty return container_of(hdac, struct hdac_ext_device, hdac); 72e342ac08SSubhransu S. Prusty } 73e342ac08SSubhransu S. Prusty 74b0362adbSSubhransu S. Prusty static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac, 75b0362adbSSubhransu S. Prusty hda_nid_t cvt_nid, hda_nid_t pin_nid, 76b0362adbSSubhransu S. Prusty u32 stream_tag, int format) 77b0362adbSSubhransu S. Prusty { 78b0362adbSSubhransu S. Prusty unsigned int val; 79b0362adbSSubhransu S. Prusty 80b0362adbSSubhransu S. Prusty dev_dbg(&hdac->hdac.dev, "cvt nid %d pnid %d stream %d format 0x%x\n", 81b0362adbSSubhransu S. Prusty cvt_nid, pin_nid, stream_tag, format); 82b0362adbSSubhransu S. Prusty 83b0362adbSSubhransu S. Prusty val = (stream_tag << 4); 84b0362adbSSubhransu S. Prusty 85b0362adbSSubhransu S. Prusty snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0, 86b0362adbSSubhransu S. Prusty AC_VERB_SET_CHANNEL_STREAMID, val); 87b0362adbSSubhransu S. Prusty snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0, 88b0362adbSSubhransu S. Prusty AC_VERB_SET_STREAM_FORMAT, format); 89b0362adbSSubhransu S. Prusty 90b0362adbSSubhransu S. Prusty return 0; 91b0362adbSSubhransu S. Prusty } 92b0362adbSSubhransu S. Prusty 93*a657f1d0SSubhransu S. Prusty static void 94*a657f1d0SSubhransu S. Prusty hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid, 95*a657f1d0SSubhransu S. Prusty int packet_index, int byte_index) 96*a657f1d0SSubhransu S. Prusty { 97*a657f1d0SSubhransu S. Prusty int val; 98*a657f1d0SSubhransu S. Prusty 99*a657f1d0SSubhransu S. Prusty val = (packet_index << 5) | (byte_index & 0x1f); 100*a657f1d0SSubhransu S. Prusty 101*a657f1d0SSubhransu S. Prusty snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, 102*a657f1d0SSubhransu S. Prusty AC_VERB_SET_HDMI_DIP_INDEX, val); 103*a657f1d0SSubhransu S. Prusty } 104*a657f1d0SSubhransu S. Prusty 105*a657f1d0SSubhransu S. Prusty static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, 106*a657f1d0SSubhransu S. Prusty hda_nid_t cvt_nid, hda_nid_t pin_nid) 107*a657f1d0SSubhransu S. Prusty { 108*a657f1d0SSubhransu S. Prusty uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; 109*a657f1d0SSubhransu S. Prusty struct hdmi_audio_infoframe frame; 110*a657f1d0SSubhransu S. Prusty u8 *dip = (u8 *)&frame; 111*a657f1d0SSubhransu S. Prusty int ret; 112*a657f1d0SSubhransu S. Prusty int i; 113*a657f1d0SSubhransu S. Prusty 114*a657f1d0SSubhransu S. Prusty hdmi_audio_infoframe_init(&frame); 115*a657f1d0SSubhransu S. Prusty 116*a657f1d0SSubhransu S. Prusty /* Default stereo for now */ 117*a657f1d0SSubhransu S. Prusty frame.channels = 2; 118*a657f1d0SSubhransu S. Prusty 119*a657f1d0SSubhransu S. Prusty /* setup channel count */ 120*a657f1d0SSubhransu S. Prusty snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0, 121*a657f1d0SSubhransu S. Prusty AC_VERB_SET_CVT_CHAN_COUNT, frame.channels - 1); 122*a657f1d0SSubhransu S. Prusty 123*a657f1d0SSubhransu S. Prusty ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer)); 124*a657f1d0SSubhransu S. Prusty if (ret < 0) 125*a657f1d0SSubhransu S. Prusty return ret; 126*a657f1d0SSubhransu S. Prusty 127*a657f1d0SSubhransu S. Prusty /* stop infoframe transmission */ 128*a657f1d0SSubhransu S. Prusty hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); 129*a657f1d0SSubhransu S. Prusty snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, 130*a657f1d0SSubhransu S. Prusty AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_DISABLE); 131*a657f1d0SSubhransu S. Prusty 132*a657f1d0SSubhransu S. Prusty 133*a657f1d0SSubhransu S. Prusty /* Fill infoframe. Index auto-incremented */ 134*a657f1d0SSubhransu S. Prusty hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); 135*a657f1d0SSubhransu S. Prusty for (i = 0; i < sizeof(frame); i++) 136*a657f1d0SSubhransu S. Prusty snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, 137*a657f1d0SSubhransu S. Prusty AC_VERB_SET_HDMI_DIP_DATA, dip[i]); 138*a657f1d0SSubhransu S. Prusty 139*a657f1d0SSubhransu S. Prusty /* Start infoframe */ 140*a657f1d0SSubhransu S. Prusty hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); 141*a657f1d0SSubhransu S. Prusty snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, 142*a657f1d0SSubhransu S. Prusty AC_VERB_SET_HDMI_DIP_XMIT, AC_DIPXMIT_BEST); 143*a657f1d0SSubhransu S. Prusty 144*a657f1d0SSubhransu S. Prusty return 0; 145*a657f1d0SSubhransu S. Prusty } 146*a657f1d0SSubhransu S. Prusty 147b0362adbSSubhransu S. Prusty static void hdac_hdmi_set_power_state(struct hdac_ext_device *edev, 148b0362adbSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map *dai_map, unsigned int pwr_state) 149b0362adbSSubhransu S. Prusty { 150b0362adbSSubhransu S. Prusty /* Power up pin widget */ 151b0362adbSSubhransu S. Prusty if (!snd_hdac_check_power_state(&edev->hdac, dai_map->pin.nid, pwr_state)) 152b0362adbSSubhransu S. Prusty snd_hdac_codec_write(&edev->hdac, dai_map->pin.nid, 0, 153b0362adbSSubhransu S. Prusty AC_VERB_SET_POWER_STATE, pwr_state); 154b0362adbSSubhransu S. Prusty 155b0362adbSSubhransu S. Prusty /* Power up converter */ 156b0362adbSSubhransu S. Prusty if (!snd_hdac_check_power_state(&edev->hdac, dai_map->cvt.nid, pwr_state)) 157b0362adbSSubhransu S. Prusty snd_hdac_codec_write(&edev->hdac, dai_map->cvt.nid, 0, 158b0362adbSSubhransu S. Prusty AC_VERB_SET_POWER_STATE, pwr_state); 159b0362adbSSubhransu S. Prusty } 160b0362adbSSubhransu S. Prusty 161b0362adbSSubhransu S. Prusty static int hdac_hdmi_playback_prepare(struct snd_pcm_substream *substream, 162b0362adbSSubhransu S. Prusty struct snd_soc_dai *dai) 163b0362adbSSubhransu S. Prusty { 164b0362adbSSubhransu S. Prusty struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); 165b0362adbSSubhransu S. Prusty struct hdac_hdmi_priv *hdmi = hdac->private_data; 166b0362adbSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map *dai_map; 167b0362adbSSubhransu S. Prusty struct hdac_ext_dma_params *dd; 168*a657f1d0SSubhransu S. Prusty int ret; 169b0362adbSSubhransu S. Prusty 170b0362adbSSubhransu S. Prusty if (dai->id > 0) { 171b0362adbSSubhransu S. Prusty dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n"); 172b0362adbSSubhransu S. Prusty return -ENODEV; 173b0362adbSSubhransu S. Prusty } 174b0362adbSSubhransu S. Prusty 175b0362adbSSubhransu S. Prusty dai_map = &hdmi->dai_map[dai->id]; 176b0362adbSSubhransu S. Prusty 177b0362adbSSubhransu S. Prusty dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream); 178b0362adbSSubhransu S. Prusty dev_dbg(&hdac->hdac.dev, "stream tag from cpu dai %d format in cvt 0x%x\n", 179b0362adbSSubhransu S. Prusty dd->stream_tag, dd->format); 180b0362adbSSubhransu S. Prusty 181*a657f1d0SSubhransu S. Prusty ret = hdac_hdmi_setup_audio_infoframe(hdac, dai_map->cvt.nid, 182*a657f1d0SSubhransu S. Prusty dai_map->pin.nid); 183*a657f1d0SSubhransu S. Prusty if (ret < 0) 184*a657f1d0SSubhransu S. Prusty return ret; 185*a657f1d0SSubhransu S. Prusty 186b0362adbSSubhransu S. Prusty return hdac_hdmi_setup_stream(hdac, dai_map->cvt.nid, dai_map->pin.nid, 187b0362adbSSubhransu S. Prusty dd->stream_tag, dd->format); 188b0362adbSSubhransu S. Prusty } 189b0362adbSSubhransu S. Prusty 190b0362adbSSubhransu S. Prusty static int hdac_hdmi_set_hw_params(struct snd_pcm_substream *substream, 191b0362adbSSubhransu S. Prusty struct snd_pcm_hw_params *hparams, struct snd_soc_dai *dai) 192b0362adbSSubhransu S. Prusty { 193b0362adbSSubhransu S. Prusty struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); 194b0362adbSSubhransu S. Prusty struct hdac_ext_dma_params *dd; 195b0362adbSSubhransu S. Prusty 196b0362adbSSubhransu S. Prusty if (dai->id > 0) { 197b0362adbSSubhransu S. Prusty dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n"); 198b0362adbSSubhransu S. Prusty return -ENODEV; 199b0362adbSSubhransu S. Prusty } 200b0362adbSSubhransu S. Prusty 201b0362adbSSubhransu S. Prusty dd = kzalloc(sizeof(*dd), GFP_KERNEL); 202b0362adbSSubhransu S. Prusty dd->format = snd_hdac_calc_stream_format(params_rate(hparams), 203b0362adbSSubhransu S. Prusty params_channels(hparams), params_format(hparams), 204b0362adbSSubhransu S. Prusty 24, 0); 205b0362adbSSubhransu S. Prusty 206b0362adbSSubhransu S. Prusty snd_soc_dai_set_dma_data(dai, substream, (void *)dd); 207b0362adbSSubhransu S. Prusty 208b0362adbSSubhransu S. Prusty return 0; 209b0362adbSSubhransu S. Prusty } 210b0362adbSSubhransu S. Prusty 211b0362adbSSubhransu S. Prusty static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream, 212b0362adbSSubhransu S. Prusty struct snd_soc_dai *dai) 213b0362adbSSubhransu S. Prusty { 214b0362adbSSubhransu S. Prusty struct hdac_ext_device *edev = snd_soc_dai_get_drvdata(dai); 215b0362adbSSubhransu S. Prusty struct hdac_ext_dma_params *dd; 216b0362adbSSubhransu S. Prusty struct hdac_hdmi_priv *hdmi = edev->private_data; 217b0362adbSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map *dai_map; 218b0362adbSSubhransu S. Prusty 219b0362adbSSubhransu S. Prusty dai_map = &hdmi->dai_map[dai->id]; 220b0362adbSSubhransu S. Prusty 221b0362adbSSubhransu S. Prusty snd_hdac_codec_write(&edev->hdac, dai_map->cvt.nid, 0, 222b0362adbSSubhransu S. Prusty AC_VERB_SET_CHANNEL_STREAMID, 0); 223b0362adbSSubhransu S. Prusty snd_hdac_codec_write(&edev->hdac, dai_map->cvt.nid, 0, 224b0362adbSSubhransu S. Prusty AC_VERB_SET_STREAM_FORMAT, 0); 225b0362adbSSubhransu S. Prusty 226b0362adbSSubhransu S. Prusty dd = (struct hdac_ext_dma_params *)snd_soc_dai_get_dma_data(dai, substream); 227b0362adbSSubhransu S. Prusty snd_soc_dai_set_dma_data(dai, substream, NULL); 228b0362adbSSubhransu S. Prusty 229b0362adbSSubhransu S. Prusty kfree(dd); 230b0362adbSSubhransu S. Prusty 231b0362adbSSubhransu S. Prusty return 0; 232b0362adbSSubhransu S. Prusty } 233b0362adbSSubhransu S. Prusty 234b0362adbSSubhransu S. Prusty static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, 235b0362adbSSubhransu S. Prusty struct snd_soc_dai *dai) 236b0362adbSSubhransu S. Prusty { 237b0362adbSSubhransu S. Prusty struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); 238b0362adbSSubhransu S. Prusty struct hdac_hdmi_priv *hdmi = hdac->private_data; 239b0362adbSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map *dai_map; 240b0362adbSSubhransu S. Prusty int val; 241b0362adbSSubhransu S. Prusty 242b0362adbSSubhransu S. Prusty if (dai->id > 0) { 243b0362adbSSubhransu S. Prusty dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n"); 244b0362adbSSubhransu S. Prusty return -ENODEV; 245b0362adbSSubhransu S. Prusty } 246b0362adbSSubhransu S. Prusty 247b0362adbSSubhransu S. Prusty dai_map = &hdmi->dai_map[dai->id]; 248b0362adbSSubhransu S. Prusty 249b0362adbSSubhransu S. Prusty val = snd_hdac_codec_read(&hdac->hdac, dai_map->pin.nid, 0, 250b0362adbSSubhransu S. Prusty AC_VERB_GET_PIN_SENSE, 0); 251b0362adbSSubhransu S. Prusty dev_info(&hdac->hdac.dev, "Val for AC_VERB_GET_PIN_SENSE: %x\n", val); 252b0362adbSSubhransu S. Prusty 253b0362adbSSubhransu S. Prusty if ((!(val & AC_PINSENSE_PRESENCE)) || (!(val & AC_PINSENSE_ELDV))) { 254b0362adbSSubhransu S. Prusty dev_err(&hdac->hdac.dev, "Monitor presence invalid with val: %x\n", val); 255b0362adbSSubhransu S. Prusty return -ENODEV; 256b0362adbSSubhransu S. Prusty } 257b0362adbSSubhransu S. Prusty 258b0362adbSSubhransu S. Prusty hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0); 259b0362adbSSubhransu S. Prusty 260b0362adbSSubhransu S. Prusty snd_hdac_codec_write(&hdac->hdac, dai_map->pin.nid, 0, 261b0362adbSSubhransu S. Prusty AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 262b0362adbSSubhransu S. Prusty 263b0362adbSSubhransu S. Prusty snd_pcm_hw_constraint_step(substream->runtime, 0, 264b0362adbSSubhransu S. Prusty SNDRV_PCM_HW_PARAM_CHANNELS, 2); 265b0362adbSSubhransu S. Prusty 266b0362adbSSubhransu S. Prusty return 0; 267b0362adbSSubhransu S. Prusty } 268b0362adbSSubhransu S. Prusty 269b0362adbSSubhransu S. Prusty static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream, 270b0362adbSSubhransu S. Prusty struct snd_soc_dai *dai) 271b0362adbSSubhransu S. Prusty { 272b0362adbSSubhransu S. Prusty struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); 273b0362adbSSubhransu S. Prusty struct hdac_hdmi_priv *hdmi = hdac->private_data; 274b0362adbSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map *dai_map; 275b0362adbSSubhransu S. Prusty 276b0362adbSSubhransu S. Prusty dai_map = &hdmi->dai_map[dai->id]; 277b0362adbSSubhransu S. Prusty 278b0362adbSSubhransu S. Prusty hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D3); 279b0362adbSSubhransu S. Prusty 280b0362adbSSubhransu S. Prusty snd_hdac_codec_write(&hdac->hdac, dai_map->pin.nid, 0, 281b0362adbSSubhransu S. Prusty AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); 282b0362adbSSubhransu S. Prusty } 283b0362adbSSubhransu S. Prusty 28418382eadSSubhransu S. Prusty static int 28518382eadSSubhransu S. Prusty hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt) 28618382eadSSubhransu S. Prusty { 28718382eadSSubhransu S. Prusty int err; 28818382eadSSubhransu S. Prusty 28918382eadSSubhransu S. Prusty /* Only stereo supported as of now */ 29018382eadSSubhransu S. Prusty cvt->params.channels_min = cvt->params.channels_max = 2; 29118382eadSSubhransu S. Prusty 29218382eadSSubhransu S. Prusty err = snd_hdac_query_supported_pcm(hdac, cvt->nid, 29318382eadSSubhransu S. Prusty &cvt->params.rates, 29418382eadSSubhransu S. Prusty &cvt->params.formats, 29518382eadSSubhransu S. Prusty &cvt->params.maxbps); 29618382eadSSubhransu S. Prusty if (err < 0) 29718382eadSSubhransu S. Prusty dev_err(&hdac->dev, 29818382eadSSubhransu S. Prusty "Failed to query pcm params for nid %d: %d\n", 29918382eadSSubhransu S. Prusty cvt->nid, err); 30018382eadSSubhransu S. Prusty 30118382eadSSubhransu S. Prusty return err; 30218382eadSSubhransu S. Prusty } 30318382eadSSubhransu S. Prusty 30418382eadSSubhransu S. Prusty static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac, 30518382eadSSubhransu S. Prusty struct hdac_hdmi_pin *pin) 30618382eadSSubhransu S. Prusty { 30718382eadSSubhransu S. Prusty if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) { 30818382eadSSubhransu S. Prusty dev_warn(&hdac->hdac.dev, 30918382eadSSubhransu S. Prusty "HDMI: pin %d wcaps %#x does not support connection list\n", 31018382eadSSubhransu S. Prusty pin->nid, get_wcaps(&hdac->hdac, pin->nid)); 31118382eadSSubhransu S. Prusty return -EINVAL; 31218382eadSSubhransu S. Prusty } 31318382eadSSubhransu S. Prusty 31418382eadSSubhransu S. Prusty pin->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid, 31518382eadSSubhransu S. Prusty pin->mux_nids, HDA_MAX_CONNECTIONS); 31618382eadSSubhransu S. Prusty if (pin->num_mux_nids == 0) { 31718382eadSSubhransu S. Prusty dev_err(&hdac->hdac.dev, "No connections found\n"); 31818382eadSSubhransu S. Prusty return -ENODEV; 31918382eadSSubhransu S. Prusty } 32018382eadSSubhransu S. Prusty 32118382eadSSubhransu S. Prusty return pin->num_mux_nids; 32218382eadSSubhransu S. Prusty } 32318382eadSSubhransu S. Prusty 32418382eadSSubhransu S. Prusty static void hdac_hdmi_fill_widget_info(struct snd_soc_dapm_widget *w, 32518382eadSSubhransu S. Prusty enum snd_soc_dapm_type id, 32618382eadSSubhransu S. Prusty const char *wname, const char *stream) 32718382eadSSubhransu S. Prusty { 32818382eadSSubhransu S. Prusty w->id = id; 32918382eadSSubhransu S. Prusty w->name = wname; 33018382eadSSubhransu S. Prusty w->sname = stream; 33118382eadSSubhransu S. Prusty w->reg = SND_SOC_NOPM; 33218382eadSSubhransu S. Prusty w->shift = 0; 33318382eadSSubhransu S. Prusty w->kcontrol_news = NULL; 33418382eadSSubhransu S. Prusty w->num_kcontrols = 0; 33518382eadSSubhransu S. Prusty w->priv = NULL; 33618382eadSSubhransu S. Prusty } 33718382eadSSubhransu S. Prusty 33818382eadSSubhransu S. Prusty static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route, 33918382eadSSubhransu S. Prusty const char *sink, const char *control, const char *src) 34018382eadSSubhransu S. Prusty { 34118382eadSSubhransu S. Prusty route->sink = sink; 34218382eadSSubhransu S. Prusty route->source = src; 34318382eadSSubhransu S. Prusty route->control = control; 34418382eadSSubhransu S. Prusty route->connected = NULL; 34518382eadSSubhransu S. Prusty } 34618382eadSSubhransu S. Prusty 34718382eadSSubhransu S. Prusty static void create_fill_widget_route_map(struct snd_soc_dapm_context *dapm, 34818382eadSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map *dai_map) 34918382eadSSubhransu S. Prusty { 35018382eadSSubhransu S. Prusty struct snd_soc_dapm_route route[1]; 35118382eadSSubhransu S. Prusty struct snd_soc_dapm_widget widgets[2] = { {0} }; 35218382eadSSubhransu S. Prusty 35318382eadSSubhransu S. Prusty memset(&route, 0, sizeof(route)); 35418382eadSSubhransu S. Prusty 35518382eadSSubhransu S. Prusty hdac_hdmi_fill_widget_info(&widgets[0], snd_soc_dapm_output, 35618382eadSSubhransu S. Prusty "hif1 Output", NULL); 35718382eadSSubhransu S. Prusty hdac_hdmi_fill_widget_info(&widgets[1], snd_soc_dapm_aif_in, 35818382eadSSubhransu S. Prusty "Coverter 1", "hif1"); 35918382eadSSubhransu S. Prusty 36018382eadSSubhransu S. Prusty hdac_hdmi_fill_route(&route[0], "hif1 Output", NULL, "Coverter 1"); 36118382eadSSubhransu S. Prusty 36218382eadSSubhransu S. Prusty snd_soc_dapm_new_controls(dapm, widgets, ARRAY_SIZE(widgets)); 36318382eadSSubhransu S. Prusty snd_soc_dapm_add_routes(dapm, route, ARRAY_SIZE(route)); 36418382eadSSubhransu S. Prusty } 36518382eadSSubhransu S. Prusty 36618382eadSSubhransu S. Prusty static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev, 36718382eadSSubhransu S. Prusty struct hdac_hdmi_dai_pin_map *dai_map, 36818382eadSSubhransu S. Prusty hda_nid_t pin_nid, hda_nid_t cvt_nid, int dai_id) 36918382eadSSubhransu S. Prusty { 37018382eadSSubhransu S. Prusty int ret; 37118382eadSSubhransu S. Prusty 37218382eadSSubhransu S. Prusty dai_map->dai_id = dai_id; 37318382eadSSubhransu S. Prusty dai_map->pin.nid = pin_nid; 37418382eadSSubhransu S. Prusty 37518382eadSSubhransu S. Prusty ret = hdac_hdmi_query_pin_connlist(edev, &dai_map->pin); 37618382eadSSubhransu S. Prusty if (ret < 0) { 37718382eadSSubhransu S. Prusty dev_err(&edev->hdac.dev, 37818382eadSSubhransu S. Prusty "Error querying connection list: %d\n", ret); 37918382eadSSubhransu S. Prusty return ret; 38018382eadSSubhransu S. Prusty } 38118382eadSSubhransu S. Prusty 38218382eadSSubhransu S. Prusty dai_map->cvt.nid = cvt_nid; 38318382eadSSubhransu S. Prusty 38418382eadSSubhransu S. Prusty /* Enable out path for this pin widget */ 38518382eadSSubhransu S. Prusty snd_hdac_codec_write(&edev->hdac, pin_nid, 0, 38618382eadSSubhransu S. Prusty AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 38718382eadSSubhransu S. Prusty 38818382eadSSubhransu S. Prusty /* Enable transmission */ 38918382eadSSubhransu S. Prusty snd_hdac_codec_write(&edev->hdac, cvt_nid, 0, 39018382eadSSubhransu S. Prusty AC_VERB_SET_DIGI_CONVERT_1, 1); 39118382eadSSubhransu S. Prusty 39218382eadSSubhransu S. Prusty /* Category Code (CC) to zero */ 39318382eadSSubhransu S. Prusty snd_hdac_codec_write(&edev->hdac, cvt_nid, 0, 39418382eadSSubhransu S. Prusty AC_VERB_SET_DIGI_CONVERT_2, 0); 39518382eadSSubhransu S. Prusty 39618382eadSSubhransu S. Prusty snd_hdac_codec_write(&edev->hdac, pin_nid, 0, 39718382eadSSubhransu S. Prusty AC_VERB_SET_CONNECT_SEL, 0); 39818382eadSSubhransu S. Prusty 39918382eadSSubhransu S. Prusty return hdac_hdmi_query_cvt_params(&edev->hdac, &dai_map->cvt); 40018382eadSSubhransu S. Prusty } 40118382eadSSubhransu S. Prusty 40218382eadSSubhransu S. Prusty /* 40318382eadSSubhransu S. Prusty * Parse all nodes and store the cvt/pin nids in array 40418382eadSSubhransu S. Prusty * Add one time initialization for pin and cvt widgets 40518382eadSSubhransu S. Prusty */ 40618382eadSSubhransu S. Prusty static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev) 40718382eadSSubhransu S. Prusty { 40818382eadSSubhransu S. Prusty hda_nid_t nid; 40918382eadSSubhransu S. Prusty int i; 41018382eadSSubhransu S. Prusty struct hdac_device *hdac = &edev->hdac; 41118382eadSSubhransu S. Prusty struct hdac_hdmi_priv *hdmi = edev->private_data; 41218382eadSSubhransu S. Prusty int cvt_nid = 0, pin_nid = 0; 41318382eadSSubhransu S. Prusty 41418382eadSSubhransu S. Prusty hdac->num_nodes = snd_hdac_get_sub_nodes(hdac, hdac->afg, &nid); 41518382eadSSubhransu S. Prusty if (!nid || hdac->num_nodes < 0) { 41618382eadSSubhransu S. Prusty dev_warn(&hdac->dev, "HDMI: failed to get afg sub nodes\n"); 41718382eadSSubhransu S. Prusty return -EINVAL; 41818382eadSSubhransu S. Prusty } 41918382eadSSubhransu S. Prusty 42018382eadSSubhransu S. Prusty hdac->start_nid = nid; 42118382eadSSubhransu S. Prusty 42218382eadSSubhransu S. Prusty for (i = 0; i < hdac->num_nodes; i++, nid++) { 42318382eadSSubhransu S. Prusty unsigned int caps; 42418382eadSSubhransu S. Prusty unsigned int type; 42518382eadSSubhransu S. Prusty 42618382eadSSubhransu S. Prusty caps = get_wcaps(hdac, nid); 42718382eadSSubhransu S. Prusty type = get_wcaps_type(caps); 42818382eadSSubhransu S. Prusty 42918382eadSSubhransu S. Prusty if (!(caps & AC_WCAP_DIGITAL)) 43018382eadSSubhransu S. Prusty continue; 43118382eadSSubhransu S. Prusty 43218382eadSSubhransu S. Prusty switch (type) { 43318382eadSSubhransu S. Prusty 43418382eadSSubhransu S. Prusty case AC_WID_AUD_OUT: 43518382eadSSubhransu S. Prusty hdmi->cvt_nid[cvt_nid] = nid; 43618382eadSSubhransu S. Prusty cvt_nid++; 43718382eadSSubhransu S. Prusty break; 43818382eadSSubhransu S. Prusty 43918382eadSSubhransu S. Prusty case AC_WID_PIN: 44018382eadSSubhransu S. Prusty hdmi->pin_nid[pin_nid] = nid; 44118382eadSSubhransu S. Prusty pin_nid++; 44218382eadSSubhransu S. Prusty break; 44318382eadSSubhransu S. Prusty } 44418382eadSSubhransu S. Prusty } 44518382eadSSubhransu S. Prusty 44618382eadSSubhransu S. Prusty hdac->end_nid = nid; 44718382eadSSubhransu S. Prusty 44818382eadSSubhransu S. Prusty if (!pin_nid || !cvt_nid) 44918382eadSSubhransu S. Prusty return -EIO; 45018382eadSSubhransu S. Prusty 45118382eadSSubhransu S. Prusty /* 45218382eadSSubhransu S. Prusty * Currently on board only 1 pin and 1 converter is enabled for 45318382eadSSubhransu S. Prusty * simplification, more will be added eventually 45418382eadSSubhransu S. Prusty * So using fixed map for dai_id:pin:cvt 45518382eadSSubhransu S. Prusty */ 45618382eadSSubhransu S. Prusty return hdac_hdmi_init_dai_map(edev, &hdmi->dai_map[0], hdmi->pin_nid[0], 45718382eadSSubhransu S. Prusty hdmi->cvt_nid[0], 0); 45818382eadSSubhransu S. Prusty } 45918382eadSSubhransu S. Prusty 46018382eadSSubhransu S. Prusty static int hdmi_codec_probe(struct snd_soc_codec *codec) 46118382eadSSubhransu S. Prusty { 46218382eadSSubhransu S. Prusty struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); 46318382eadSSubhransu S. Prusty struct hdac_hdmi_priv *hdmi = edev->private_data; 46418382eadSSubhransu S. Prusty struct snd_soc_dapm_context *dapm = 46518382eadSSubhransu S. Prusty snd_soc_component_get_dapm(&codec->component); 46618382eadSSubhransu S. Prusty 46718382eadSSubhransu S. Prusty edev->scodec = codec; 46818382eadSSubhransu S. Prusty 46918382eadSSubhransu S. Prusty create_fill_widget_route_map(dapm, &hdmi->dai_map[0]); 47018382eadSSubhransu S. Prusty 47118382eadSSubhransu S. Prusty /* Imp: Store the card pointer in hda_codec */ 47218382eadSSubhransu S. Prusty edev->card = dapm->card->snd_card; 47318382eadSSubhransu S. Prusty 474e342ac08SSubhransu S. Prusty /* 475e342ac08SSubhransu S. Prusty * hdac_device core already sets the state to active and calls 476e342ac08SSubhransu S. Prusty * get_noresume. So enable runtime and set the device to suspend. 477e342ac08SSubhransu S. Prusty */ 478e342ac08SSubhransu S. Prusty pm_runtime_enable(&edev->hdac.dev); 479e342ac08SSubhransu S. Prusty pm_runtime_put(&edev->hdac.dev); 480e342ac08SSubhransu S. Prusty pm_runtime_suspend(&edev->hdac.dev); 481e342ac08SSubhransu S. Prusty 482e342ac08SSubhransu S. Prusty return 0; 483e342ac08SSubhransu S. Prusty } 484e342ac08SSubhransu S. Prusty 485e342ac08SSubhransu S. Prusty static int hdmi_codec_remove(struct snd_soc_codec *codec) 486e342ac08SSubhransu S. Prusty { 487e342ac08SSubhransu S. Prusty struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); 488e342ac08SSubhransu S. Prusty 489e342ac08SSubhransu S. Prusty pm_runtime_disable(&edev->hdac.dev); 49018382eadSSubhransu S. Prusty return 0; 49118382eadSSubhransu S. Prusty } 49218382eadSSubhransu S. Prusty 49318382eadSSubhransu S. Prusty static struct snd_soc_codec_driver hdmi_hda_codec = { 49418382eadSSubhransu S. Prusty .probe = hdmi_codec_probe, 495e342ac08SSubhransu S. Prusty .remove = hdmi_codec_remove, 49618382eadSSubhransu S. Prusty .idle_bias_off = true, 49718382eadSSubhransu S. Prusty }; 49818382eadSSubhransu S. Prusty 499b0362adbSSubhransu S. Prusty static struct snd_soc_dai_ops hdmi_dai_ops = { 500b0362adbSSubhransu S. Prusty .startup = hdac_hdmi_pcm_open, 501b0362adbSSubhransu S. Prusty .shutdown = hdac_hdmi_pcm_close, 502b0362adbSSubhransu S. Prusty .hw_params = hdac_hdmi_set_hw_params, 503b0362adbSSubhransu S. Prusty .prepare = hdac_hdmi_playback_prepare, 504b0362adbSSubhransu S. Prusty .hw_free = hdac_hdmi_playback_cleanup, 505b0362adbSSubhransu S. Prusty }; 506b0362adbSSubhransu S. Prusty 50718382eadSSubhransu S. Prusty static struct snd_soc_dai_driver hdmi_dais[] = { 50818382eadSSubhransu S. Prusty { .name = "intel-hdmi-hif1", 50918382eadSSubhransu S. Prusty .playback = { 51018382eadSSubhransu S. Prusty .stream_name = "hif1", 51118382eadSSubhransu S. Prusty .channels_min = 2, 51218382eadSSubhransu S. Prusty .channels_max = 2, 51318382eadSSubhransu S. Prusty .rates = SNDRV_PCM_RATE_32000 | 51418382eadSSubhransu S. Prusty SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 51518382eadSSubhransu S. Prusty SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | 51618382eadSSubhransu S. Prusty SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, 51718382eadSSubhransu S. Prusty .formats = SNDRV_PCM_FMTBIT_S16_LE | 51818382eadSSubhransu S. Prusty SNDRV_PCM_FMTBIT_S20_3LE | 51918382eadSSubhransu S. Prusty SNDRV_PCM_FMTBIT_S24_LE | 52018382eadSSubhransu S. Prusty SNDRV_PCM_FMTBIT_S32_LE, 52118382eadSSubhransu S. Prusty 52218382eadSSubhransu S. Prusty }, 523b0362adbSSubhransu S. Prusty .ops = &hdmi_dai_ops, 52418382eadSSubhransu S. Prusty }, 52518382eadSSubhransu S. Prusty }; 52618382eadSSubhransu S. Prusty 52718382eadSSubhransu S. Prusty static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) 52818382eadSSubhransu S. Prusty { 52918382eadSSubhransu S. Prusty struct hdac_device *codec = &edev->hdac; 53018382eadSSubhransu S. Prusty struct hdac_hdmi_priv *hdmi_priv; 53118382eadSSubhransu S. Prusty int ret = 0; 53218382eadSSubhransu S. Prusty 53318382eadSSubhransu S. Prusty hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL); 53418382eadSSubhransu S. Prusty if (hdmi_priv == NULL) 53518382eadSSubhransu S. Prusty return -ENOMEM; 53618382eadSSubhransu S. Prusty 53718382eadSSubhransu S. Prusty edev->private_data = hdmi_priv; 53818382eadSSubhransu S. Prusty 53918382eadSSubhransu S. Prusty dev_set_drvdata(&codec->dev, edev); 54018382eadSSubhransu S. Prusty 54118382eadSSubhransu S. Prusty ret = hdac_hdmi_parse_and_map_nid(edev); 54218382eadSSubhransu S. Prusty if (ret < 0) 54318382eadSSubhransu S. Prusty return ret; 54418382eadSSubhransu S. Prusty 54518382eadSSubhransu S. Prusty /* ASoC specific initialization */ 54618382eadSSubhransu S. Prusty return snd_soc_register_codec(&codec->dev, &hdmi_hda_codec, 54718382eadSSubhransu S. Prusty hdmi_dais, ARRAY_SIZE(hdmi_dais)); 54818382eadSSubhransu S. Prusty } 54918382eadSSubhransu S. Prusty 55018382eadSSubhransu S. Prusty static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) 55118382eadSSubhransu S. Prusty { 55218382eadSSubhransu S. Prusty snd_soc_unregister_codec(&edev->hdac.dev); 55318382eadSSubhransu S. Prusty 55418382eadSSubhransu S. Prusty return 0; 55518382eadSSubhransu S. Prusty } 55618382eadSSubhransu S. Prusty 557e342ac08SSubhransu S. Prusty #ifdef CONFIG_PM 558e342ac08SSubhransu S. Prusty static int hdac_hdmi_runtime_suspend(struct device *dev) 559e342ac08SSubhransu S. Prusty { 560e342ac08SSubhransu S. Prusty struct hdac_ext_device *edev = to_hda_ext_device(dev); 561e342ac08SSubhransu S. Prusty struct hdac_device *hdac = &edev->hdac; 562e342ac08SSubhransu S. Prusty 563e342ac08SSubhransu S. Prusty dev_dbg(dev, "Enter: %s\n", __func__); 564e342ac08SSubhransu S. Prusty 565e342ac08SSubhransu S. Prusty /* Power down afg */ 566e342ac08SSubhransu S. Prusty if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D3)) 567e342ac08SSubhransu S. Prusty snd_hdac_codec_write(hdac, hdac->afg, 0, 568e342ac08SSubhransu S. Prusty AC_VERB_SET_POWER_STATE, AC_PWRST_D3); 569e342ac08SSubhransu S. Prusty 570e342ac08SSubhransu S. Prusty return 0; 571e342ac08SSubhransu S. Prusty } 572e342ac08SSubhransu S. Prusty 573e342ac08SSubhransu S. Prusty static int hdac_hdmi_runtime_resume(struct device *dev) 574e342ac08SSubhransu S. Prusty { 575e342ac08SSubhransu S. Prusty struct hdac_ext_device *edev = to_hda_ext_device(dev); 576e342ac08SSubhransu S. Prusty struct hdac_device *hdac = &edev->hdac; 577e342ac08SSubhransu S. Prusty 578e342ac08SSubhransu S. Prusty dev_dbg(dev, "Enter: %s\n", __func__); 579e342ac08SSubhransu S. Prusty 580e342ac08SSubhransu S. Prusty /* Power up afg */ 581e342ac08SSubhransu S. Prusty if (!snd_hdac_check_power_state(hdac, hdac->afg, AC_PWRST_D0)) 582e342ac08SSubhransu S. Prusty snd_hdac_codec_write(hdac, hdac->afg, 0, 583e342ac08SSubhransu S. Prusty AC_VERB_SET_POWER_STATE, AC_PWRST_D0); 584e342ac08SSubhransu S. Prusty 585e342ac08SSubhransu S. Prusty return 0; 586e342ac08SSubhransu S. Prusty } 587e342ac08SSubhransu S. Prusty #else 588e342ac08SSubhransu S. Prusty #define hdac_hdmi_runtime_suspend NULL 589e342ac08SSubhransu S. Prusty #define hdac_hdmi_runtime_resume NULL 590e342ac08SSubhransu S. Prusty #endif 591e342ac08SSubhransu S. Prusty 592e342ac08SSubhransu S. Prusty static const struct dev_pm_ops hdac_hdmi_pm = { 593e342ac08SSubhransu S. Prusty SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL) 594e342ac08SSubhransu S. Prusty }; 595e342ac08SSubhransu S. Prusty 59618382eadSSubhransu S. Prusty static const struct hda_device_id hdmi_list[] = { 59718382eadSSubhransu S. Prusty HDA_CODEC_EXT_ENTRY(0x80862809, 0x100000, "Skylake HDMI", 0), 59818382eadSSubhransu S. Prusty {} 59918382eadSSubhransu S. Prusty }; 60018382eadSSubhransu S. Prusty 60118382eadSSubhransu S. Prusty MODULE_DEVICE_TABLE(hdaudio, hdmi_list); 60218382eadSSubhransu S. Prusty 60318382eadSSubhransu S. Prusty static struct hdac_ext_driver hdmi_driver = { 60418382eadSSubhransu S. Prusty . hdac = { 60518382eadSSubhransu S. Prusty .driver = { 60618382eadSSubhransu S. Prusty .name = "HDMI HDA Codec", 607e342ac08SSubhransu S. Prusty .pm = &hdac_hdmi_pm, 60818382eadSSubhransu S. Prusty }, 60918382eadSSubhransu S. Prusty .id_table = hdmi_list, 61018382eadSSubhransu S. Prusty }, 61118382eadSSubhransu S. Prusty .probe = hdac_hdmi_dev_probe, 61218382eadSSubhransu S. Prusty .remove = hdac_hdmi_dev_remove, 61318382eadSSubhransu S. Prusty }; 61418382eadSSubhransu S. Prusty 61518382eadSSubhransu S. Prusty static int __init hdmi_init(void) 61618382eadSSubhransu S. Prusty { 61718382eadSSubhransu S. Prusty return snd_hda_ext_driver_register(&hdmi_driver); 61818382eadSSubhransu S. Prusty } 61918382eadSSubhransu S. Prusty 62018382eadSSubhransu S. Prusty static void __exit hdmi_exit(void) 62118382eadSSubhransu S. Prusty { 62218382eadSSubhransu S. Prusty snd_hda_ext_driver_unregister(&hdmi_driver); 62318382eadSSubhransu S. Prusty } 62418382eadSSubhransu S. Prusty 62518382eadSSubhransu S. Prusty module_init(hdmi_init); 62618382eadSSubhransu S. Prusty module_exit(hdmi_exit); 62718382eadSSubhransu S. Prusty 62818382eadSSubhransu S. Prusty MODULE_LICENSE("GPL v2"); 62918382eadSSubhransu S. Prusty MODULE_DESCRIPTION("HDMI HD codec"); 63018382eadSSubhransu S. Prusty MODULE_AUTHOR("Samreen Nilofer<samreen.nilofer@intel.com>"); 63118382eadSSubhransu S. Prusty MODULE_AUTHOR("Subhransu S. Prusty<subhransu.s.prusty@intel.com>"); 632