diff options
author | Jyri Sarha <jsarha@ti.com> | 2014-05-23 09:20:46 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-12-01 04:09:53 -0500 |
commit | 45302d7e1bef631acd946a6f296deb9c709dc5af (patch) | |
tree | 3627a24c286e4683a2f75fe74c20456344d75140 | |
parent | 274a1e8b2bc9667bc94fd1d3232a4c8732fcbf26 (diff) |
OMAPDSS: hdmi5: Register ASoC platform device for omap hdmi audio
Implements callbacks for OMAP HDMI audio platform driver and registers
it in probe function. Unregistering is done in remove function.
Signed-off-by: Jyri Sarha <jsarha@ti.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r-- | drivers/video/fbdev/omap2/dss/hdmi5.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5.c b/drivers/video/fbdev/omap2/dss/hdmi5.c index b482de33d440..84736667e528 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi5.c +++ b/drivers/video/fbdev/omap2/dss/hdmi5.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/gpio.h> | 38 | #include <linux/gpio.h> |
39 | #include <linux/regulator/consumer.h> | 39 | #include <linux/regulator/consumer.h> |
40 | #include <video/omapdss.h> | 40 | #include <video/omapdss.h> |
41 | #include <sound/omap-hdmi-audio.h> | ||
41 | 42 | ||
42 | #include "hdmi5_core.h" | 43 | #include "hdmi5_core.h" |
43 | #include "dss.h" | 44 | #include "dss.h" |
@@ -368,6 +369,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev) | |||
368 | goto err0; | 369 | goto err0; |
369 | } | 370 | } |
370 | 371 | ||
372 | hdmi.display_enabled = true; | ||
373 | |||
371 | mutex_unlock(&hdmi.lock); | 374 | mutex_unlock(&hdmi.lock); |
372 | return 0; | 375 | return 0; |
373 | 376 | ||
@@ -382,8 +385,13 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev) | |||
382 | 385 | ||
383 | mutex_lock(&hdmi.lock); | 386 | mutex_lock(&hdmi.lock); |
384 | 387 | ||
388 | if (hdmi.audio_pdev && hdmi.audio_abort_cb) | ||
389 | hdmi.audio_abort_cb(&hdmi.audio_pdev->dev); | ||
390 | |||
385 | hdmi_power_off_full(dssdev); | 391 | hdmi_power_off_full(dssdev); |
386 | 392 | ||
393 | hdmi.display_enabled = false; | ||
394 | |||
387 | mutex_unlock(&hdmi.lock); | 395 | mutex_unlock(&hdmi.lock); |
388 | } | 396 | } |
389 | 397 | ||
@@ -559,6 +567,112 @@ err: | |||
559 | return r; | 567 | return r; |
560 | } | 568 | } |
561 | 569 | ||
570 | /* Audio callbacks */ | ||
571 | static int hdmi_audio_startup(struct device *dev, | ||
572 | void (*abort_cb)(struct device *dev)) | ||
573 | { | ||
574 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
575 | int ret = 0; | ||
576 | |||
577 | mutex_lock(&hd->lock); | ||
578 | |||
579 | if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { | ||
580 | ret = -EPERM; | ||
581 | goto out; | ||
582 | } | ||
583 | |||
584 | hd->audio_abort_cb = abort_cb; | ||
585 | |||
586 | out: | ||
587 | mutex_unlock(&hd->lock); | ||
588 | |||
589 | return ret; | ||
590 | } | ||
591 | |||
592 | static int hdmi_audio_shutdown(struct device *dev) | ||
593 | { | ||
594 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
595 | |||
596 | mutex_lock(&hd->lock); | ||
597 | hd->audio_abort_cb = NULL; | ||
598 | mutex_unlock(&hd->lock); | ||
599 | |||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int hdmi_audio_start(struct device *dev) | ||
604 | { | ||
605 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
606 | |||
607 | WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); | ||
608 | WARN_ON(!hd->display_enabled); | ||
609 | |||
610 | hdmi_wp_audio_enable(&hd->wp, true); | ||
611 | hdmi_wp_audio_core_req_enable(&hd->wp, true); | ||
612 | |||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | static void hdmi_audio_stop(struct device *dev) | ||
617 | { | ||
618 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
619 | |||
620 | WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); | ||
621 | WARN_ON(!hd->display_enabled); | ||
622 | |||
623 | hdmi_wp_audio_core_req_enable(&hd->wp, false); | ||
624 | hdmi_wp_audio_enable(&hd->wp, false); | ||
625 | } | ||
626 | |||
627 | static int hdmi_audio_config(struct device *dev, | ||
628 | struct omap_dss_audio *dss_audio) | ||
629 | { | ||
630 | struct omap_hdmi *hd = dev_get_drvdata(dev); | ||
631 | int ret; | ||
632 | |||
633 | mutex_lock(&hd->lock); | ||
634 | |||
635 | if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { | ||
636 | ret = -EPERM; | ||
637 | goto out; | ||
638 | } | ||
639 | |||
640 | ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio, | ||
641 | hd->cfg.timings.pixelclock); | ||
642 | |||
643 | out: | ||
644 | mutex_unlock(&hd->lock); | ||
645 | |||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | static const struct omap_hdmi_audio_ops hdmi_audio_ops = { | ||
650 | .audio_startup = hdmi_audio_startup, | ||
651 | .audio_shutdown = hdmi_audio_shutdown, | ||
652 | .audio_start = hdmi_audio_start, | ||
653 | .audio_stop = hdmi_audio_stop, | ||
654 | .audio_config = hdmi_audio_config, | ||
655 | }; | ||
656 | |||
657 | static int hdmi_audio_register(struct device *dev) | ||
658 | { | ||
659 | struct omap_hdmi_audio_pdata pdata = { | ||
660 | .dev = dev, | ||
661 | .dss_version = omapdss_get_version(), | ||
662 | .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp), | ||
663 | .ops = &hdmi_audio_ops, | ||
664 | }; | ||
665 | |||
666 | hdmi.audio_pdev = platform_device_register_data( | ||
667 | dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO, | ||
668 | &pdata, sizeof(pdata)); | ||
669 | |||
670 | if (IS_ERR(hdmi.audio_pdev)) | ||
671 | return PTR_ERR(hdmi.audio_pdev); | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | |||
562 | /* HDMI HW IP initialisation */ | 676 | /* HDMI HW IP initialisation */ |
563 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | 677 | static int omapdss_hdmihw_probe(struct platform_device *pdev) |
564 | { | 678 | { |
@@ -611,6 +725,14 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) | |||
611 | 725 | ||
612 | hdmi_init_output(pdev); | 726 | hdmi_init_output(pdev); |
613 | 727 | ||
728 | r = hdmi_audio_register(&pdev->dev); | ||
729 | if (r) { | ||
730 | DSSERR("Registering HDMI audio failed %d\n", r); | ||
731 | hdmi_uninit_output(pdev); | ||
732 | pm_runtime_disable(&pdev->dev); | ||
733 | return r; | ||
734 | } | ||
735 | |||
614 | dss_debugfs_create_file("hdmi", hdmi_dump_regs); | 736 | dss_debugfs_create_file("hdmi", hdmi_dump_regs); |
615 | 737 | ||
616 | return 0; | 738 | return 0; |
@@ -621,6 +743,9 @@ err: | |||
621 | 743 | ||
622 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | 744 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) |
623 | { | 745 | { |
746 | if (hdmi.audio_pdev) | ||
747 | platform_device_unregister(hdmi.audio_pdev); | ||
748 | |||
624 | hdmi_uninit_output(pdev); | 749 | hdmi_uninit_output(pdev); |
625 | 750 | ||
626 | hdmi_pll_uninit(&hdmi.pll); | 751 | hdmi_pll_uninit(&hdmi.pll); |