1 /* 2 * ALSA SoC codec for HDMI encoder drivers 3 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ 4 * Author: Jyri Sarha <jsarha@ti.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * version 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 */ 15 #include <linux/module.h> 16 #include <linux/string.h> 17 #include <sound/core.h> 18 #include <sound/pcm.h> 19 #include <sound/pcm_params.h> 20 #include <sound/soc.h> 21 #include <sound/pcm_drm_eld.h> 22 #include <sound/hdmi-codec.h> 23 #include <sound/pcm_iec958.h> 24 25 #include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */ 26 27 struct hdmi_codec_priv { 28 struct hdmi_codec_pdata hcd; 29 struct snd_soc_dai_driver *daidrv; 30 struct hdmi_codec_daifmt daifmt[2]; 31 struct mutex current_stream_lock; 32 struct snd_pcm_substream *current_stream; 33 struct snd_pcm_hw_constraint_list ratec; 34 uint8_t eld[MAX_ELD_BYTES]; 35 }; 36 37 static const struct snd_soc_dapm_widget hdmi_widgets[] = { 38 SND_SOC_DAPM_OUTPUT("TX"), 39 }; 40 41 static const struct snd_soc_dapm_route hdmi_routes[] = { 42 { "TX", NULL, "Playback" }, 43 }; 44 45 enum { 46 DAI_ID_I2S = 0, 47 DAI_ID_SPDIF, 48 }; 49 50 static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, 51 struct snd_ctl_elem_info *uinfo) 52 { 53 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 54 struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component); 55 56 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 57 uinfo->count = sizeof(hcp->eld); 58 59 return 0; 60 } 61 62 static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, 63 struct snd_ctl_elem_value *ucontrol) 64 { 65 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 66 struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component); 67 68 memcpy(ucontrol->value.bytes.data, hcp->eld, sizeof(hcp->eld)); 69 70 return 0; 71 } 72 73 static const struct snd_kcontrol_new hdmi_controls[] = { 74 { 75 .access = SNDRV_CTL_ELEM_ACCESS_READ | 76 SNDRV_CTL_ELEM_ACCESS_VOLATILE, 77 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 78 .name = "ELD", 79 .info = hdmi_eld_ctl_info, 80 .get = hdmi_eld_ctl_get, 81 }, 82 }; 83 84 static int hdmi_codec_new_stream(struct snd_pcm_substream *substream, 85 struct snd_soc_dai *dai) 86 { 87 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); 88 int ret = 0; 89 90 mutex_lock(&hcp->current_stream_lock); 91 if (!hcp->current_stream) { 92 hcp->current_stream = substream; 93 } else if (hcp->current_stream != substream) { 94 dev_err(dai->dev, "Only one simultaneous stream supported!\n"); 95 ret = -EINVAL; 96 } 97 mutex_unlock(&hcp->current_stream_lock); 98 99 return ret; 100 } 101 102 static int hdmi_codec_startup(struct snd_pcm_substream *substream, 103 struct snd_soc_dai *dai) 104 { 105 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); 106 int ret = 0; 107 108 dev_dbg(dai->dev, "%s()\n", __func__); 109 110 ret = hdmi_codec_new_stream(substream, dai); 111 if (ret) 112 return ret; 113 114 if (hcp->hcd.ops->audio_startup) { 115 ret = hcp->hcd.ops->audio_startup(dai->dev->parent, hcp->hcd.data); 116 if (ret) { 117 mutex_lock(&hcp->current_stream_lock); 118 hcp->current_stream = NULL; 119 mutex_unlock(&hcp->current_stream_lock); 120 return ret; 121 } 122 } 123 124 if (hcp->hcd.ops->get_eld) { 125 ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->hcd.data, 126 hcp->eld, sizeof(hcp->eld)); 127 128 if (!ret) { 129 ret = snd_pcm_hw_constraint_eld(substream->runtime, 130 hcp->eld); 131 if (ret) 132 return ret; 133 } 134 } 135 return 0; 136 } 137 138 static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, 139 struct snd_soc_dai *dai) 140 { 141 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); 142 143 dev_dbg(dai->dev, "%s()\n", __func__); 144 145 WARN_ON(hcp->current_stream != substream); 146 147 hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data); 148 149 mutex_lock(&hcp->current_stream_lock); 150 hcp->current_stream = NULL; 151 mutex_unlock(&hcp->current_stream_lock); 152 } 153 154 static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, 155 struct snd_pcm_hw_params *params, 156 struct snd_soc_dai *dai) 157 { 158 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); 159 struct hdmi_codec_params hp = { 160 .iec = { 161 .status = { 0 }, 162 .subcode = { 0 }, 163 .pad = 0, 164 .dig_subframe = { 0 }, 165 } 166 }; 167 int ret; 168 169 dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__, 170 params_width(params), params_rate(params), 171 params_channels(params)); 172 173 if (params_width(params) > 24) 174 params->msbits = 24; 175 176 ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status, 177 sizeof(hp.iec.status)); 178 if (ret < 0) { 179 dev_err(dai->dev, "Creating IEC958 channel status failed %d\n", 180 ret); 181 return ret; 182 } 183 184 ret = hdmi_codec_new_stream(substream, dai); 185 if (ret) 186 return ret; 187 188 hdmi_audio_infoframe_init(&hp.cea); 189 hp.cea.channels = params_channels(params); 190 hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; 191 hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; 192 hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; 193 194 hp.sample_width = params_width(params); 195 hp.sample_rate = params_rate(params); 196 hp.channels = params_channels(params); 197 198 return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data, 199 &hcp->daifmt[dai->id], &hp); 200 } 201 202 static int hdmi_codec_set_fmt(struct snd_soc_dai *dai, 203 unsigned int fmt) 204 { 205 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); 206 struct hdmi_codec_daifmt cf = { 0 }; 207 int ret = 0; 208 209 dev_dbg(dai->dev, "%s()\n", __func__); 210 211 if (dai->id == DAI_ID_SPDIF) { 212 cf.fmt = HDMI_SPDIF; 213 } else { 214 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 215 case SND_SOC_DAIFMT_CBM_CFM: 216 cf.bit_clk_master = 1; 217 cf.frame_clk_master = 1; 218 break; 219 case SND_SOC_DAIFMT_CBS_CFM: 220 cf.frame_clk_master = 1; 221 break; 222 case SND_SOC_DAIFMT_CBM_CFS: 223 cf.bit_clk_master = 1; 224 break; 225 case SND_SOC_DAIFMT_CBS_CFS: 226 break; 227 default: 228 return -EINVAL; 229 } 230 231 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 232 case SND_SOC_DAIFMT_NB_NF: 233 break; 234 case SND_SOC_DAIFMT_NB_IF: 235 cf.frame_clk_inv = 1; 236 break; 237 case SND_SOC_DAIFMT_IB_NF: 238 cf.bit_clk_inv = 1; 239 break; 240 case SND_SOC_DAIFMT_IB_IF: 241 cf.frame_clk_inv = 1; 242 cf.bit_clk_inv = 1; 243 break; 244 } 245 246 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 247 case SND_SOC_DAIFMT_I2S: 248 cf.fmt = HDMI_I2S; 249 break; 250 case SND_SOC_DAIFMT_DSP_A: 251 cf.fmt = HDMI_DSP_A; 252 break; 253 case SND_SOC_DAIFMT_DSP_B: 254 cf.fmt = HDMI_DSP_B; 255 break; 256 case SND_SOC_DAIFMT_RIGHT_J: 257 cf.fmt = HDMI_RIGHT_J; 258 break; 259 case SND_SOC_DAIFMT_LEFT_J: 260 cf.fmt = HDMI_LEFT_J; 261 break; 262 case SND_SOC_DAIFMT_AC97: 263 cf.fmt = HDMI_AC97; 264 break; 265 default: 266 dev_err(dai->dev, "Invalid DAI interface format\n"); 267 return -EINVAL; 268 } 269 } 270 271 hcp->daifmt[dai->id] = cf; 272 273 return ret; 274 } 275 276 static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute) 277 { 278 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); 279 280 dev_dbg(dai->dev, "%s()\n", __func__); 281 282 if (hcp->hcd.ops->digital_mute) 283 return hcp->hcd.ops->digital_mute(dai->dev->parent, 284 hcp->hcd.data, mute); 285 286 return 0; 287 } 288 289 static const struct snd_soc_dai_ops hdmi_dai_ops = { 290 .startup = hdmi_codec_startup, 291 .shutdown = hdmi_codec_shutdown, 292 .hw_params = hdmi_codec_hw_params, 293 .set_fmt = hdmi_codec_set_fmt, 294 .digital_mute = hdmi_codec_digital_mute, 295 }; 296 297 298 #define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ 299 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ 300 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ 301 SNDRV_PCM_RATE_192000) 302 303 #define SPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ 304 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\ 305 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\ 306 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) 307 308 /* 309 * This list is only for formats allowed on the I2S bus. So there is 310 * some formats listed that are not supported by HDMI interface. For 311 * instance allowing the 32-bit formats enables 24-precision with CPU 312 * DAIs that do not support 24-bit formats. If the extra formats cause 313 * problems, we should add the video side driver an option to disable 314 * them. 315 */ 316 #define I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ 317 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\ 318 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\ 319 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ 320 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) 321 322 static struct snd_soc_dai_driver hdmi_i2s_dai = { 323 .name = "i2s-hifi", 324 .id = DAI_ID_I2S, 325 .playback = { 326 .stream_name = "Playback", 327 .channels_min = 2, 328 .channels_max = 8, 329 .rates = HDMI_RATES, 330 .formats = I2S_FORMATS, 331 .sig_bits = 24, 332 }, 333 .ops = &hdmi_dai_ops, 334 }; 335 336 static const struct snd_soc_dai_driver hdmi_spdif_dai = { 337 .name = "spdif-hifi", 338 .id = DAI_ID_SPDIF, 339 .playback = { 340 .stream_name = "Playback", 341 .channels_min = 2, 342 .channels_max = 2, 343 .rates = HDMI_RATES, 344 .formats = SPDIF_FORMATS, 345 }, 346 .ops = &hdmi_dai_ops, 347 }; 348 349 static struct snd_soc_codec_driver hdmi_codec = { 350 .controls = hdmi_controls, 351 .num_controls = ARRAY_SIZE(hdmi_controls), 352 .dapm_widgets = hdmi_widgets, 353 .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), 354 .dapm_routes = hdmi_routes, 355 .num_dapm_routes = ARRAY_SIZE(hdmi_routes), 356 }; 357 358 static int hdmi_codec_probe(struct platform_device *pdev) 359 { 360 struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; 361 struct device *dev = &pdev->dev; 362 struct hdmi_codec_priv *hcp; 363 int dai_count, i = 0; 364 int ret; 365 366 dev_dbg(dev, "%s()\n", __func__); 367 368 if (!hcd) { 369 dev_err(dev, "%s: No plalform data\n", __func__); 370 return -EINVAL; 371 } 372 373 dai_count = hcd->i2s + hcd->spdif; 374 if (dai_count < 1 || !hcd->ops || !hcd->ops->hw_params || 375 !hcd->ops->audio_shutdown) { 376 dev_err(dev, "%s: Invalid parameters\n", __func__); 377 return -EINVAL; 378 } 379 380 hcp = devm_kzalloc(dev, sizeof(*hcp), GFP_KERNEL); 381 if (!hcp) 382 return -ENOMEM; 383 384 hcp->hcd = *hcd; 385 mutex_init(&hcp->current_stream_lock); 386 387 hcp->daidrv = devm_kzalloc(dev, dai_count * sizeof(*hcp->daidrv), 388 GFP_KERNEL); 389 if (!hcp->daidrv) 390 return -ENOMEM; 391 392 if (hcd->i2s) { 393 hcp->daidrv[i] = hdmi_i2s_dai; 394 hcp->daidrv[i].playback.channels_max = 395 hcd->max_i2s_channels; 396 i++; 397 } 398 399 if (hcd->spdif) 400 hcp->daidrv[i] = hdmi_spdif_dai; 401 402 ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv, 403 dai_count); 404 if (ret) { 405 dev_err(dev, "%s: snd_soc_register_codec() failed (%d)\n", 406 __func__, ret); 407 return ret; 408 } 409 410 dev_set_drvdata(dev, hcp); 411 return 0; 412 } 413 414 static int hdmi_codec_remove(struct platform_device *pdev) 415 { 416 snd_soc_unregister_codec(&pdev->dev); 417 return 0; 418 } 419 420 static struct platform_driver hdmi_codec_driver = { 421 .driver = { 422 .name = HDMI_CODEC_DRV_NAME, 423 }, 424 .probe = hdmi_codec_probe, 425 .remove = hdmi_codec_remove, 426 }; 427 428 module_platform_driver(hdmi_codec_driver); 429 430 MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>"); 431 MODULE_DESCRIPTION("HDMI Audio Codec Driver"); 432 MODULE_LICENSE("GPL"); 433 MODULE_ALIAS("platform:" HDMI_CODEC_DRV_NAME); 434