aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-10-19 10:42:10 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-10-29 06:44:40 -0400
commitbb426fc96316b20876acc3289c5115f00918c2bb (patch)
tree43503e7c8023fb14123181567cb608f578a5c4ee /drivers/video
parent4e0397cfa78913f3da08c0aa8076b6b0a3b262a0 (diff)
OMAPDSS: HDMI: split power_on/off to two parts
There's currently just one power-on function for HDMI, which enables the IP and the video output. When reading EDID or detecting if a monitor is connected, we don't need the video output. Enabling the video output for these operations is not a big problem in itself, but the quick enable/disable cycles caused by the operations seem to cause sync lost errors from time to time. Also, this makes it possible to read the EDID before the full video path has been set up. This patch splits the hdmi_power_on into two parts, hdmi_power_on_core and hdmi_power_on_full. The "full" version does what hdmi_power_on does currently, and hdmi_power_on_core only enables the core IP. Similar changes are made for power_off. Note that these don't allow the HDMI IP to be first enabled, and later enable the video output, but the HDMI IP will first need to be powered off before calling the full version. So this is rather limited implementation, but it fills the needs for reading EDID. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Cc: Ricardo Neri <ricardo.neri@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/hdmi.c75
1 files changed, 46 insertions, 29 deletions
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 54931f14c09..1226044e550 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -500,12 +500,9 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
500 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); 500 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
501} 501}
502 502
503static int hdmi_power_on(struct omap_dss_device *dssdev) 503static int hdmi_power_on_core(struct omap_dss_device *dssdev)
504{ 504{
505 int r; 505 int r;
506 struct omap_video_timings *p;
507 struct omap_overlay_manager *mgr = dssdev->output->manager;
508 unsigned long phy;
509 506
510 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); 507 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
511 gpio_set_value(hdmi.ls_oe_gpio, 1); 508 gpio_set_value(hdmi.ls_oe_gpio, 1);
@@ -521,6 +518,46 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
521 if (r) 518 if (r)
522 goto err_runtime_get; 519 goto err_runtime_get;
523 520
521 /* Make selection of HDMI in DSS */
522 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
523
524 /* Select the dispc clock source as PRCM clock, to ensure that it is not
525 * DSI PLL source as the clock selected by DSI PLL might not be
526 * sufficient for the resolution selected / that can be changed
527 * dynamically by user. This can be moved to single location , say
528 * Boardfile.
529 */
530 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
531
532 return 0;
533
534err_runtime_get:
535 regulator_disable(hdmi.vdda_hdmi_dac_reg);
536err_vdac_enable:
537 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
538 gpio_set_value(hdmi.ls_oe_gpio, 0);
539 return r;
540}
541
542static void hdmi_power_off_core(struct omap_dss_device *dssdev)
543{
544 hdmi_runtime_put();
545 regulator_disable(hdmi.vdda_hdmi_dac_reg);
546 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
547 gpio_set_value(hdmi.ls_oe_gpio, 0);
548}
549
550static int hdmi_power_on_full(struct omap_dss_device *dssdev)
551{
552 int r;
553 struct omap_video_timings *p;
554 struct omap_overlay_manager *mgr = dssdev->output->manager;
555 unsigned long phy;
556
557 r = hdmi_power_on_core(dssdev);
558 if (r)
559 return r;
560
524 dss_mgr_disable(mgr); 561 dss_mgr_disable(mgr);
525 562
526 p = &hdmi.ip_data.cfg.timings; 563 p = &hdmi.ip_data.cfg.timings;
@@ -548,17 +585,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
548 585
549 hdmi.ip_data.ops->video_configure(&hdmi.ip_data); 586 hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
550 587
551 /* Make selection of HDMI in DSS */
552 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
553
554 /* Select the dispc clock source as PRCM clock, to ensure that it is not
555 * DSI PLL source as the clock selected by DSI PLL might not be
556 * sufficient for the resolution selected / that can be changed
557 * dynamically by user. This can be moved to single location , say
558 * Boardfile.
559 */
560 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
561
562 /* bypass TV gamma table */ 588 /* bypass TV gamma table */
563 dispc_enable_gamma_table(0); 589 dispc_enable_gamma_table(0);
564 590
@@ -582,16 +608,11 @@ err_vid_enable:
582err_phy_enable: 608err_phy_enable:
583 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 609 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
584err_pll_enable: 610err_pll_enable:
585 hdmi_runtime_put(); 611 hdmi_power_off_core(dssdev);
586err_runtime_get:
587 regulator_disable(hdmi.vdda_hdmi_dac_reg);
588err_vdac_enable:
589 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
590 gpio_set_value(hdmi.ls_oe_gpio, 0);
591 return -EIO; 612 return -EIO;
592} 613}
593 614
594static void hdmi_power_off(struct omap_dss_device *dssdev) 615static void hdmi_power_off_full(struct omap_dss_device *dssdev)
595{ 616{
596 struct omap_overlay_manager *mgr = dssdev->output->manager; 617 struct omap_overlay_manager *mgr = dssdev->output->manager;
597 618
@@ -600,12 +621,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
600 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 621 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
601 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 622 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
602 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 623 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
603 hdmi_runtime_put();
604 624
605 regulator_disable(hdmi.vdda_hdmi_dac_reg); 625 hdmi_power_off_core(dssdev);
606
607 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
608 gpio_set_value(hdmi.ls_oe_gpio, 0);
609} 626}
610 627
611int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 628int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -713,7 +730,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
713 goto err0; 730 goto err0;
714 } 731 }
715 732
716 r = hdmi_power_on(dssdev); 733 r = hdmi_power_on_full(dssdev);
717 if (r) { 734 if (r) {
718 DSSERR("failed to power on device\n"); 735 DSSERR("failed to power on device\n");
719 goto err1; 736 goto err1;
@@ -735,7 +752,7 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
735 752
736 mutex_lock(&hdmi.lock); 753 mutex_lock(&hdmi.lock);
737 754
738 hdmi_power_off(dssdev); 755 hdmi_power_off_full(dssdev);
739 756
740 omap_dss_stop_device(dssdev); 757 omap_dss_stop_device(dssdev);
741 758