diff options
-rw-r--r-- | drivers/video/fbdev/omap2/dss/hdmi4.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c index 33ed4109f7bc..e76cc5fb8430 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi4.c +++ b/drivers/video/fbdev/omap2/dss/hdmi4.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | #include <video/omapdss.h> | 35 | #include <video/omapdss.h> |
36 | #include <sound/omap-hdmi-audio.h> | ||
36 | 37 | ||
37 | #include "hdmi4_core.h" | 38 | #include "hdmi4_core.h" |
38 | #include "dss.h" | 39 | #include "dss.h" |
@@ -340,6 +341,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev) | |||
340 | goto err0; | 341 | goto err0; |
341 | } | 342 | } |
342 | 343 | ||
344 | hdmi.display_enabled = true; | ||
345 | |||
343 | mutex_unlock(&hdmi.lock); | 346 | mutex_unlock(&hdmi.lock); |
344 | return 0; | 347 | return 0; |
345 | 348 | ||
@@ -354,8 +357,13 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev) | |||
354 | 357 | ||
355 | mutex_lock(&hdmi.lock); | 358 | mutex_lock(&hdmi.lock); |
356 | 359 | ||
360 | if (hdmi.audio_pdev && hdmi.audio_abort_cb) | ||
361 | hdmi.audio_abort_cb(&hdmi.audio_pdev->dev); | ||
362 | |||
357 | hdmi_power_off_full(dssdev); | 363 | hdmi_power_off_full(dssdev); |
358 | 364 | ||
365 | hdmi.display_enabled = false; | ||
366 | |||
359 | mutex_unlock(&hdmi.lock); | 367 | mutex_unlock(&hdmi.lock); |
360 | } | 368 | } |
361 | 369 | ||
@@ -531,6 +539,112 @@ err: | |||
531 | return r; | 539 | return r; |
532 | } | 540 | } |
533 | 541 | ||
542 | /* Audio callbacks */ | ||
543 | static int hdmi_audio_startup(struct device *dev, | ||
544 | void (*abort_cb)(struct device *dev)) | ||
545 | { | ||
546 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
547 | int ret = 0; | ||
548 | |||
549 | mutex_lock(&hd->lock); | ||
550 | |||
551 | if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { | ||
552 | ret = -EPERM; | ||
553 | goto out; | ||
554 | } | ||
555 | |||
556 | hd->audio_abort_cb = abort_cb; | ||
557 | |||
558 | out: | ||
559 | mutex_unlock(&hd->lock); | ||
560 | |||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | static int hdmi_audio_shutdown(struct device *dev) | ||
565 | { | ||
566 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
567 | |||
568 | mutex_lock(&hd->lock); | ||
569 | hd->audio_abort_cb = NULL; | ||
570 | mutex_unlock(&hd->lock); | ||
571 | |||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | static int hdmi_audio_start(struct device *dev) | ||
576 | { | ||
577 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
578 | |||
579 | WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); | ||
580 | WARN_ON(!hd->display_enabled); | ||
581 | |||
582 | hdmi_wp_audio_enable(&hd->wp, true); | ||
583 | hdmi4_audio_start(&hd->core, &hd->wp); | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | static void hdmi_audio_stop(struct device *dev) | ||
589 | { | ||
590 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
591 | |||
592 | WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); | ||
593 | WARN_ON(!hd->display_enabled); | ||
594 | |||
595 | hdmi4_audio_stop(&hd->core, &hd->wp); | ||
596 | hdmi_wp_audio_enable(&hd->wp, false); | ||
597 | } | ||
598 | |||
599 | static int hdmi_audio_config(struct device *dev, | ||
600 | struct omap_dss_audio *dss_audio) | ||
601 | { | ||
602 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
603 | int ret; | ||
604 | |||
605 | mutex_lock(&hd->lock); | ||
606 | |||
607 | if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { | ||
608 | ret = -EPERM; | ||
609 | goto out; | ||
610 | } | ||
611 | |||
612 | ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio, | ||
613 | hd->cfg.timings.pixelclock); | ||
614 | |||
615 | out: | ||
616 | mutex_unlock(&hd->lock); | ||
617 | |||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | static const struct omap_hdmi_audio_ops hdmi_audio_ops = { | ||
622 | .audio_startup = hdmi_audio_startup, | ||
623 | .audio_shutdown = hdmi_audio_shutdown, | ||
624 | .audio_start = hdmi_audio_start, | ||
625 | .audio_stop = hdmi_audio_stop, | ||
626 | .audio_config = hdmi_audio_config, | ||
627 | }; | ||
628 | |||
629 | static int hdmi_audio_register(struct device *dev) | ||
630 | { | ||
631 | struct omap_hdmi_audio_pdata pdata = { | ||
632 | .dev = dev, | ||
633 | .dss_version = omapdss_get_version(), | ||
634 | .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp), | ||
635 | .ops = &hdmi_audio_ops, | ||
636 | }; | ||
637 | |||
638 | hdmi.audio_pdev = platform_device_register_data( | ||
639 | dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO, | ||
640 | &pdata, sizeof(pdata)); | ||
641 | |||
642 | if (IS_ERR(hdmi.audio_pdev)) | ||
643 | return PTR_ERR(hdmi.audio_pdev); | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | |||
534 | /* HDMI HW IP initialisation */ | 648 | /* HDMI HW IP initialisation */ |
535 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | 649 | static int omapdss_hdmihw_probe(struct platform_device *pdev) |
536 | { | 650 | { |
@@ -583,6 +697,14 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) | |||
583 | 697 | ||
584 | hdmi_init_output(pdev); | 698 | hdmi_init_output(pdev); |
585 | 699 | ||
700 | r = hdmi_audio_register(&pdev->dev); | ||
701 | if (r) { | ||
702 | DSSERR("Registering HDMI audio failed\n"); | ||
703 | hdmi_uninit_output(pdev); | ||
704 | pm_runtime_disable(&pdev->dev); | ||
705 | return r; | ||
706 | } | ||
707 | |||
586 | dss_debugfs_create_file("hdmi", hdmi_dump_regs); | 708 | dss_debugfs_create_file("hdmi", hdmi_dump_regs); |
587 | 709 | ||
588 | return 0; | 710 | return 0; |
@@ -593,6 +715,9 @@ err: | |||
593 | 715 | ||
594 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | 716 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) |
595 | { | 717 | { |
718 | if (hdmi.audio_pdev) | ||
719 | platform_device_unregister(hdmi.audio_pdev); | ||
720 | |||
596 | hdmi_uninit_output(pdev); | 721 | hdmi_uninit_output(pdev); |
597 | 722 | ||
598 | hdmi_pll_uninit(&hdmi.pll); | 723 | hdmi_pll_uninit(&hdmi.pll); |