aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/hdmi-codec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/hdmi-codec.c')
-rw-r--r--sound/soc/codecs/hdmi-codec.c79
1 files changed, 70 insertions, 9 deletions
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index f27d115626db..b904492d7744 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -24,6 +24,15 @@
24 24
25#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */ 25#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */
26 26
27struct hdmi_device {
28 struct device *dev;
29 struct list_head list;
30 int cnt;
31};
32#define pos_to_hdmi_device(pos) container_of((pos), struct hdmi_device, list)
33LIST_HEAD(hdmi_device_list);
34
35#define DAI_NAME_SIZE 16
27struct hdmi_codec_priv { 36struct hdmi_codec_priv {
28 struct hdmi_codec_pdata hcd; 37 struct hdmi_codec_pdata hcd;
29 struct snd_soc_dai_driver *daidrv; 38 struct snd_soc_dai_driver *daidrv;
@@ -320,7 +329,6 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = {
320 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) 329 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
321 330
322static struct snd_soc_dai_driver hdmi_i2s_dai = { 331static struct snd_soc_dai_driver hdmi_i2s_dai = {
323 .name = "i2s-hifi",
324 .id = DAI_ID_I2S, 332 .id = DAI_ID_I2S,
325 .playback = { 333 .playback = {
326 .stream_name = "Playback", 334 .stream_name = "Playback",
@@ -334,7 +342,6 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = {
334}; 342};
335 343
336static const struct snd_soc_dai_driver hdmi_spdif_dai = { 344static const struct snd_soc_dai_driver hdmi_spdif_dai = {
337 .name = "spdif-hifi",
338 .id = DAI_ID_SPDIF, 345 .id = DAI_ID_SPDIF,
339 .playback = { 346 .playback = {
340 .stream_name = "Playback", 347 .stream_name = "Playback",
@@ -346,13 +353,37 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = {
346 .ops = &hdmi_dai_ops, 353 .ops = &hdmi_dai_ops,
347}; 354};
348 355
356static char hdmi_dai_name[][DAI_NAME_SIZE] = {
357 "hdmi-hifi.0",
358 "hdmi-hifi.1",
359 "hdmi-hifi.2",
360 "hdmi-hifi.3",
361};
362
363static int hdmi_of_xlate_dai_name(struct snd_soc_component *component,
364 struct of_phandle_args *args,
365 const char **dai_name)
366{
367 int id = args->args[0];
368
369 if (id < ARRAY_SIZE(hdmi_dai_name)) {
370 *dai_name = hdmi_dai_name[id];
371 return 0;
372 }
373
374 return -EAGAIN;
375}
376
349static struct snd_soc_codec_driver hdmi_codec = { 377static struct snd_soc_codec_driver hdmi_codec = {
350 .controls = hdmi_controls, 378 .component_driver = {
351 .num_controls = ARRAY_SIZE(hdmi_controls), 379 .controls = hdmi_controls,
352 .dapm_widgets = hdmi_widgets, 380 .num_controls = ARRAY_SIZE(hdmi_controls),
353 .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), 381 .dapm_widgets = hdmi_widgets,
354 .dapm_routes = hdmi_routes, 382 .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
355 .num_dapm_routes = ARRAY_SIZE(hdmi_routes), 383 .dapm_routes = hdmi_routes,
384 .num_dapm_routes = ARRAY_SIZE(hdmi_routes),
385 .of_xlate_dai_name = hdmi_of_xlate_dai_name,
386 },
356}; 387};
357 388
358static int hdmi_codec_probe(struct platform_device *pdev) 389static int hdmi_codec_probe(struct platform_device *pdev)
@@ -360,6 +391,8 @@ static int hdmi_codec_probe(struct platform_device *pdev)
360 struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; 391 struct hdmi_codec_pdata *hcd = pdev->dev.platform_data;
361 struct device *dev = &pdev->dev; 392 struct device *dev = &pdev->dev;
362 struct hdmi_codec_priv *hcp; 393 struct hdmi_codec_priv *hcp;
394 struct hdmi_device *hd;
395 struct list_head *pos;
363 int dai_count, i = 0; 396 int dai_count, i = 0;
364 int ret; 397 int ret;
365 398
@@ -381,6 +414,31 @@ static int hdmi_codec_probe(struct platform_device *pdev)
381 if (!hcp) 414 if (!hcp)
382 return -ENOMEM; 415 return -ENOMEM;
383 416
417 hd = NULL;
418 list_for_each(pos, &hdmi_device_list) {
419 struct hdmi_device *tmp = pos_to_hdmi_device(pos);
420
421 if (tmp->dev == dev->parent) {
422 hd = tmp;
423 break;
424 }
425 }
426
427 if (!hd) {
428 hd = devm_kzalloc(dev, sizeof(*hd), GFP_KERNEL);
429 if (!hd)
430 return -ENOMEM;
431
432 hd->dev = dev->parent;
433
434 list_add_tail(&hd->list, &hdmi_device_list);
435 }
436
437 if (hd->cnt >= ARRAY_SIZE(hdmi_dai_name)) {
438 dev_err(dev, "too many hdmi codec are deteced\n");
439 return -EINVAL;
440 }
441
384 hcp->hcd = *hcd; 442 hcp->hcd = *hcd;
385 mutex_init(&hcp->current_stream_lock); 443 mutex_init(&hcp->current_stream_lock);
386 444
@@ -393,11 +451,14 @@ static int hdmi_codec_probe(struct platform_device *pdev)
393 hcp->daidrv[i] = hdmi_i2s_dai; 451 hcp->daidrv[i] = hdmi_i2s_dai;
394 hcp->daidrv[i].playback.channels_max = 452 hcp->daidrv[i].playback.channels_max =
395 hcd->max_i2s_channels; 453 hcd->max_i2s_channels;
454 hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++];
396 i++; 455 i++;
397 } 456 }
398 457
399 if (hcd->spdif) 458 if (hcd->spdif) {
400 hcp->daidrv[i] = hdmi_spdif_dai; 459 hcp->daidrv[i] = hdmi_spdif_dai;
460 hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++];
461 }
401 462
402 ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv, 463 ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv,
403 dai_count); 464 dai_count);