diff options
Diffstat (limited to 'sound/soc/codecs/hdmi-codec.c')
-rw-r--r-- | sound/soc/codecs/hdmi-codec.c | 79 |
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 | ||
27 | struct 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) | ||
33 | LIST_HEAD(hdmi_device_list); | ||
34 | |||
35 | #define DAI_NAME_SIZE 16 | ||
27 | struct hdmi_codec_priv { | 36 | struct 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 | ||
322 | static struct snd_soc_dai_driver hdmi_i2s_dai = { | 331 | static 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 | ||
336 | static const struct snd_soc_dai_driver hdmi_spdif_dai = { | 344 | static 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 | ||
356 | static 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 | |||
363 | static 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 | |||
349 | static struct snd_soc_codec_driver hdmi_codec = { | 377 | static 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 | ||
358 | static int hdmi_codec_probe(struct platform_device *pdev) | 389 | static 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); |