diff options
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 75 |
1 files changed, 55 insertions, 20 deletions
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 0cdf24673d48..4fbe27191de5 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
33 | #include <linux/pm_runtime.h> | 33 | #include <linux/pm_runtime.h> |
34 | #include <linux/clk.h> | 34 | #include <linux/clk.h> |
35 | #include <linux/gpio.h> | ||
35 | #include <video/omapdss.h> | 36 | #include <video/omapdss.h> |
36 | 37 | ||
37 | #include "ti_hdmi.h" | 38 | #include "ti_hdmi.h" |
@@ -61,6 +62,10 @@ static struct { | |||
61 | struct hdmi_ip_data ip_data; | 62 | struct hdmi_ip_data ip_data; |
62 | 63 | ||
63 | struct clk *sys_clk; | 64 | struct clk *sys_clk; |
65 | |||
66 | int ct_cp_hpd_gpio; | ||
67 | int ls_oe_gpio; | ||
68 | int hpd_gpio; | ||
64 | } hdmi; | 69 | } hdmi; |
65 | 70 | ||
66 | /* | 71 | /* |
@@ -314,12 +319,34 @@ static void hdmi_runtime_put(void) | |||
314 | 319 | ||
315 | static int __init hdmi_init_display(struct omap_dss_device *dssdev) | 320 | static int __init hdmi_init_display(struct omap_dss_device *dssdev) |
316 | { | 321 | { |
322 | int r; | ||
323 | |||
324 | struct gpio gpios[] = { | ||
325 | { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" }, | ||
326 | { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" }, | ||
327 | { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" }, | ||
328 | }; | ||
329 | |||
317 | DSSDBG("init_display\n"); | 330 | DSSDBG("init_display\n"); |
318 | 331 | ||
319 | dss_init_hdmi_ip_ops(&hdmi.ip_data); | 332 | dss_init_hdmi_ip_ops(&hdmi.ip_data); |
333 | |||
334 | r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); | ||
335 | if (r) | ||
336 | return r; | ||
337 | |||
320 | return 0; | 338 | return 0; |
321 | } | 339 | } |
322 | 340 | ||
341 | static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev) | ||
342 | { | ||
343 | DSSDBG("uninit_display\n"); | ||
344 | |||
345 | gpio_free(hdmi.ct_cp_hpd_gpio); | ||
346 | gpio_free(hdmi.ls_oe_gpio); | ||
347 | gpio_free(hdmi.hpd_gpio); | ||
348 | } | ||
349 | |||
323 | static const struct hdmi_config *hdmi_find_timing( | 350 | static const struct hdmi_config *hdmi_find_timing( |
324 | const struct hdmi_config *timings_arr, | 351 | const struct hdmi_config *timings_arr, |
325 | int len) | 352 | int len) |
@@ -462,9 +489,12 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
462 | struct omap_video_timings *p; | 489 | struct omap_video_timings *p; |
463 | unsigned long phy; | 490 | unsigned long phy; |
464 | 491 | ||
492 | gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); | ||
493 | gpio_set_value(hdmi.ls_oe_gpio, 1); | ||
494 | |||
465 | r = hdmi_runtime_get(); | 495 | r = hdmi_runtime_get(); |
466 | if (r) | 496 | if (r) |
467 | return r; | 497 | goto err_runtime_get; |
468 | 498 | ||
469 | dss_mgr_disable(dssdev->manager); | 499 | dss_mgr_disable(dssdev->manager); |
470 | 500 | ||
@@ -482,7 +512,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
482 | r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); | 512 | r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); |
483 | if (r) { | 513 | if (r) { |
484 | DSSDBG("Failed to lock PLL\n"); | 514 | DSSDBG("Failed to lock PLL\n"); |
485 | goto err; | 515 | goto err_pll_enable; |
486 | } | 516 | } |
487 | 517 | ||
488 | r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); | 518 | r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); |
@@ -526,8 +556,11 @@ err_vid_enable: | |||
526 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); | 556 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); |
527 | err_phy_enable: | 557 | err_phy_enable: |
528 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); | 558 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
529 | err: | 559 | err_pll_enable: |
530 | hdmi_runtime_put(); | 560 | hdmi_runtime_put(); |
561 | err_runtime_get: | ||
562 | gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); | ||
563 | gpio_set_value(hdmi.ls_oe_gpio, 0); | ||
531 | return -EIO; | 564 | return -EIO; |
532 | } | 565 | } |
533 | 566 | ||
@@ -539,6 +572,9 @@ static void hdmi_power_off(struct omap_dss_device *dssdev) | |||
539 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); | 572 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); |
540 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); | 573 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
541 | hdmi_runtime_put(); | 574 | hdmi_runtime_put(); |
575 | |||
576 | gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); | ||
577 | gpio_set_value(hdmi.ls_oe_gpio, 0); | ||
542 | } | 578 | } |
543 | 579 | ||
544 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 580 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, |
@@ -637,7 +673,6 @@ bool omapdss_hdmi_detect(void) | |||
637 | 673 | ||
638 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | 674 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) |
639 | { | 675 | { |
640 | struct omap_dss_hdmi_data *priv = dssdev->data; | ||
641 | int r = 0; | 676 | int r = 0; |
642 | 677 | ||
643 | DSSDBG("ENTER hdmi_display_enable\n"); | 678 | DSSDBG("ENTER hdmi_display_enable\n"); |
@@ -650,7 +685,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | |||
650 | goto err0; | 685 | goto err0; |
651 | } | 686 | } |
652 | 687 | ||
653 | hdmi.ip_data.hpd_gpio = priv->hpd_gpio; | 688 | hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio; |
654 | 689 | ||
655 | r = omap_dss_start_device(dssdev); | 690 | r = omap_dss_start_device(dssdev); |
656 | if (r) { | 691 | if (r) { |
@@ -658,26 +693,15 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | |||
658 | goto err0; | 693 | goto err0; |
659 | } | 694 | } |
660 | 695 | ||
661 | if (dssdev->platform_enable) { | ||
662 | r = dssdev->platform_enable(dssdev); | ||
663 | if (r) { | ||
664 | DSSERR("failed to enable GPIO's\n"); | ||
665 | goto err1; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | r = hdmi_power_on(dssdev); | 696 | r = hdmi_power_on(dssdev); |
670 | if (r) { | 697 | if (r) { |
671 | DSSERR("failed to power on device\n"); | 698 | DSSERR("failed to power on device\n"); |
672 | goto err2; | 699 | goto err1; |
673 | } | 700 | } |
674 | 701 | ||
675 | mutex_unlock(&hdmi.lock); | 702 | mutex_unlock(&hdmi.lock); |
676 | return 0; | 703 | return 0; |
677 | 704 | ||
678 | err2: | ||
679 | if (dssdev->platform_disable) | ||
680 | dssdev->platform_disable(dssdev); | ||
681 | err1: | 705 | err1: |
682 | omap_dss_stop_device(dssdev); | 706 | omap_dss_stop_device(dssdev); |
683 | err0: | 707 | err0: |
@@ -693,9 +717,6 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | |||
693 | 717 | ||
694 | hdmi_power_off(dssdev); | 718 | hdmi_power_off(dssdev); |
695 | 719 | ||
696 | if (dssdev->platform_disable) | ||
697 | dssdev->platform_disable(dssdev); | ||
698 | |||
699 | omap_dss_stop_device(dssdev); | 720 | omap_dss_stop_device(dssdev); |
700 | 721 | ||
701 | mutex_unlock(&hdmi.lock); | 722 | mutex_unlock(&hdmi.lock); |
@@ -873,10 +894,15 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev) | |||
873 | 894 | ||
874 | for (i = 0; i < pdata->num_devices; ++i) { | 895 | for (i = 0; i < pdata->num_devices; ++i) { |
875 | struct omap_dss_device *dssdev = pdata->devices[i]; | 896 | struct omap_dss_device *dssdev = pdata->devices[i]; |
897 | struct omap_dss_hdmi_data *priv = dssdev->data; | ||
876 | 898 | ||
877 | if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI) | 899 | if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI) |
878 | continue; | 900 | continue; |
879 | 901 | ||
902 | hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio; | ||
903 | hdmi.ls_oe_gpio = priv->ls_oe_gpio; | ||
904 | hdmi.hpd_gpio = priv->hpd_gpio; | ||
905 | |||
880 | r = hdmi_init_display(dssdev); | 906 | r = hdmi_init_display(dssdev); |
881 | if (r) { | 907 | if (r) { |
882 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | 908 | DSSERR("device %s init failed: %d\n", dssdev->name, r); |
@@ -938,8 +964,17 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) | |||
938 | return 0; | 964 | return 0; |
939 | } | 965 | } |
940 | 966 | ||
967 | static int __exit hdmi_remove_child(struct device *dev, void *data) | ||
968 | { | ||
969 | struct omap_dss_device *dssdev = to_dss_device(dev); | ||
970 | hdmi_uninit_display(dssdev); | ||
971 | return 0; | ||
972 | } | ||
973 | |||
941 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | 974 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) |
942 | { | 975 | { |
976 | device_for_each_child(&pdev->dev, NULL, hdmi_remove_child); | ||
977 | |||
943 | omap_dss_unregister_child_devices(&pdev->dev); | 978 | omap_dss_unregister_child_devices(&pdev->dev); |
944 | 979 | ||
945 | hdmi_panel_exit(); | 980 | hdmi_panel_exit(); |