aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/hdmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/hdmi.c')
-rw-r--r--drivers/video/omap2/dss/hdmi.c159
1 files changed, 114 insertions, 45 deletions
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 0d6d7213a858..769d0828581c 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -60,6 +60,7 @@
60static struct { 60static struct {
61 struct mutex lock; 61 struct mutex lock;
62 struct platform_device *pdev; 62 struct platform_device *pdev;
63
63 struct hdmi_ip_data ip_data; 64 struct hdmi_ip_data ip_data;
64 65
65 struct clk *sys_clk; 66 struct clk *sys_clk;
@@ -295,6 +296,12 @@ static const struct hdmi_config vesa_timings[] = {
295 false, }, 296 false, },
296 { 0x55, HDMI_DVI }, 297 { 0x55, HDMI_DVI },
297 }, 298 },
299 {
300 { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
301 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
302 false, },
303 { 0x44, HDMI_DVI },
304 },
298}; 305};
299 306
300static int hdmi_runtime_get(void) 307static int hdmi_runtime_get(void)
@@ -323,7 +330,6 @@ static void hdmi_runtime_put(void)
323 330
324static int __init hdmi_init_display(struct omap_dss_device *dssdev) 331static int __init hdmi_init_display(struct omap_dss_device *dssdev)
325{ 332{
326 struct omap_dss_board_info *pdata = hdmi.pdev->dev.platform_data;
327 int r; 333 int r;
328 334
329 struct gpio gpios[] = { 335 struct gpio gpios[] = {
@@ -334,13 +340,17 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
334 340
335 DSSDBG("init_display\n"); 341 DSSDBG("init_display\n");
336 342
337 dss_init_hdmi_ip_ops(&hdmi.ip_data, pdata->version); 343 dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
338 344
339 if (hdmi.vdda_hdmi_dac_reg == NULL) { 345 if (hdmi.vdda_hdmi_dac_reg == NULL) {
340 struct regulator *reg; 346 struct regulator *reg;
341 347
342 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); 348 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
343 349
350 /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
351 if (IS_ERR(reg))
352 reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
353
344 if (IS_ERR(reg)) { 354 if (IS_ERR(reg)) {
345 DSSERR("can't get VDDA_HDMI_DAC regulator\n"); 355 DSSERR("can't get VDDA_HDMI_DAC regulator\n");
346 return PTR_ERR(reg); 356 return PTR_ERR(reg);
@@ -356,7 +366,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
356 return 0; 366 return 0;
357} 367}
358 368
359static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev) 369static void hdmi_uninit_display(struct omap_dss_device *dssdev)
360{ 370{
361 DSSDBG("uninit_display\n"); 371 DSSDBG("uninit_display\n");
362 372
@@ -399,7 +409,8 @@ static bool hdmi_timings_compare(struct omap_video_timings *timing1,
399{ 409{
400 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; 410 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
401 411
402 if ((timing2->pixel_clock == timing1->pixel_clock) && 412 if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
413 DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
403 (timing2->x_res == timing1->x_res) && 414 (timing2->x_res == timing1->x_res) &&
404 (timing2->y_res == timing1->y_res)) { 415 (timing2->y_res == timing1->y_res)) {
405 416
@@ -501,12 +512,9 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
501 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); 512 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
502} 513}
503 514
504static int hdmi_power_on(struct omap_dss_device *dssdev) 515static int hdmi_power_on_core(struct omap_dss_device *dssdev)
505{ 516{
506 int r; 517 int r;
507 struct omap_video_timings *p;
508 struct omap_overlay_manager *mgr = dssdev->output->manager;
509 unsigned long phy;
510 518
511 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); 519 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
512 gpio_set_value(hdmi.ls_oe_gpio, 1); 520 gpio_set_value(hdmi.ls_oe_gpio, 1);
@@ -522,6 +530,38 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
522 if (r) 530 if (r)
523 goto err_runtime_get; 531 goto err_runtime_get;
524 532
533 /* Make selection of HDMI in DSS */
534 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
535
536 return 0;
537
538err_runtime_get:
539 regulator_disable(hdmi.vdda_hdmi_dac_reg);
540err_vdac_enable:
541 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
542 gpio_set_value(hdmi.ls_oe_gpio, 0);
543 return r;
544}
545
546static void hdmi_power_off_core(struct omap_dss_device *dssdev)
547{
548 hdmi_runtime_put();
549 regulator_disable(hdmi.vdda_hdmi_dac_reg);
550 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
551 gpio_set_value(hdmi.ls_oe_gpio, 0);
552}
553
554static int hdmi_power_on_full(struct omap_dss_device *dssdev)
555{
556 int r;
557 struct omap_video_timings *p;
558 struct omap_overlay_manager *mgr = dssdev->output->manager;
559 unsigned long phy;
560
561 r = hdmi_power_on_core(dssdev);
562 if (r)
563 return r;
564
525 dss_mgr_disable(mgr); 565 dss_mgr_disable(mgr);
526 566
527 p = &hdmi.ip_data.cfg.timings; 567 p = &hdmi.ip_data.cfg.timings;
@@ -549,17 +589,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
549 589
550 hdmi.ip_data.ops->video_configure(&hdmi.ip_data); 590 hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
551 591
552 /* Make selection of HDMI in DSS */
553 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
554
555 /* Select the dispc clock source as PRCM clock, to ensure that it is not
556 * DSI PLL source as the clock selected by DSI PLL might not be
557 * sufficient for the resolution selected / that can be changed
558 * dynamically by user. This can be moved to single location , say
559 * Boardfile.
560 */
561 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
562
563 /* bypass TV gamma table */ 592 /* bypass TV gamma table */
564 dispc_enable_gamma_table(0); 593 dispc_enable_gamma_table(0);
565 594
@@ -583,16 +612,11 @@ err_vid_enable:
583err_phy_enable: 612err_phy_enable:
584 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 613 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
585err_pll_enable: 614err_pll_enable:
586 hdmi_runtime_put(); 615 hdmi_power_off_core(dssdev);
587err_runtime_get:
588 regulator_disable(hdmi.vdda_hdmi_dac_reg);
589err_vdac_enable:
590 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
591 gpio_set_value(hdmi.ls_oe_gpio, 0);
592 return -EIO; 616 return -EIO;
593} 617}
594 618
595static void hdmi_power_off(struct omap_dss_device *dssdev) 619static void hdmi_power_off_full(struct omap_dss_device *dssdev)
596{ 620{
597 struct omap_overlay_manager *mgr = dssdev->output->manager; 621 struct omap_overlay_manager *mgr = dssdev->output->manager;
598 622
@@ -601,12 +625,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
601 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 625 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
602 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 626 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
603 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 627 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
604 hdmi_runtime_put();
605
606 regulator_disable(hdmi.vdda_hdmi_dac_reg);
607 628
608 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); 629 hdmi_power_off_core(dssdev);
609 gpio_set_value(hdmi.ls_oe_gpio, 0);
610} 630}
611 631
612int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 632int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -716,7 +736,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
716 goto err0; 736 goto err0;
717 } 737 }
718 738
719 r = hdmi_power_on(dssdev); 739 r = hdmi_power_on_full(dssdev);
720 if (r) { 740 if (r) {
721 DSSERR("failed to power on device\n"); 741 DSSERR("failed to power on device\n");
722 goto err1; 742 goto err1;
@@ -738,13 +758,48 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
738 758
739 mutex_lock(&hdmi.lock); 759 mutex_lock(&hdmi.lock);
740 760
741 hdmi_power_off(dssdev); 761 hdmi_power_off_full(dssdev);
742 762
743 omap_dss_stop_device(dssdev); 763 omap_dss_stop_device(dssdev);
744 764
745 mutex_unlock(&hdmi.lock); 765 mutex_unlock(&hdmi.lock);
746} 766}
747 767
768int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
769{
770 int r = 0;
771
772 DSSDBG("ENTER omapdss_hdmi_core_enable\n");
773
774 mutex_lock(&hdmi.lock);
775
776 hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
777
778 r = hdmi_power_on_core(dssdev);
779 if (r) {
780 DSSERR("failed to power on device\n");
781 goto err0;
782 }
783
784 mutex_unlock(&hdmi.lock);
785 return 0;
786
787err0:
788 mutex_unlock(&hdmi.lock);
789 return r;
790}
791
792void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
793{
794 DSSDBG("Enter omapdss_hdmi_core_disable\n");
795
796 mutex_lock(&hdmi.lock);
797
798 hdmi_power_off_core(dssdev);
799
800 mutex_unlock(&hdmi.lock);
801}
802
748static int hdmi_get_clocks(struct platform_device *pdev) 803static int hdmi_get_clocks(struct platform_device *pdev)
749{ 804{
750 struct clk *clk; 805 struct clk *clk;
@@ -913,7 +968,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
913static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev) 968static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
914{ 969{
915 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 970 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
916 const char *def_disp_name = dss_get_default_display_name(); 971 const char *def_disp_name = omapdss_get_default_display_name();
917 struct omap_dss_device *def_dssdev; 972 struct omap_dss_device *def_dssdev;
918 int i; 973 int i;
919 974
@@ -971,9 +1026,19 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
971 return; 1026 return;
972 } 1027 }
973 1028
1029 r = omapdss_output_set_device(&hdmi.output, dssdev);
1030 if (r) {
1031 DSSERR("failed to connect output to new device: %s\n",
1032 dssdev->name);
1033 dss_put_device(dssdev);
1034 return;
1035 }
1036
974 r = dss_add_device(dssdev); 1037 r = dss_add_device(dssdev);
975 if (r) { 1038 if (r) {
976 DSSERR("device %s register failed: %d\n", dssdev->name, r); 1039 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1040 omapdss_output_unset_device(&hdmi.output);
1041 hdmi_uninit_display(dssdev);
977 dss_put_device(dssdev); 1042 dss_put_device(dssdev);
978 return; 1043 return;
979 } 1044 }
@@ -1000,22 +1065,22 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev)
1000/* HDMI HW IP initialisation */ 1065/* HDMI HW IP initialisation */
1001static int __init omapdss_hdmihw_probe(struct platform_device *pdev) 1066static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
1002{ 1067{
1003 struct resource *hdmi_mem; 1068 struct resource *res;
1004 int r; 1069 int r;
1005 1070
1006 hdmi.pdev = pdev; 1071 hdmi.pdev = pdev;
1007 1072
1008 mutex_init(&hdmi.lock); 1073 mutex_init(&hdmi.lock);
1074 mutex_init(&hdmi.ip_data.lock);
1009 1075
1010 hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); 1076 res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
1011 if (!hdmi_mem) { 1077 if (!res) {
1012 DSSERR("can't get IORESOURCE_MEM HDMI\n"); 1078 DSSERR("can't get IORESOURCE_MEM HDMI\n");
1013 return -EINVAL; 1079 return -EINVAL;
1014 } 1080 }
1015 1081
1016 /* Base address taken from platform */ 1082 /* Base address taken from platform */
1017 hdmi.ip_data.base_wp = ioremap(hdmi_mem->start, 1083 hdmi.ip_data.base_wp = devm_request_and_ioremap(&pdev->dev, res);
1018 resource_size(hdmi_mem));
1019 if (!hdmi.ip_data.base_wp) { 1084 if (!hdmi.ip_data.base_wp) {
1020 DSSERR("can't ioremap WP\n"); 1085 DSSERR("can't ioremap WP\n");
1021 return -ENOMEM; 1086 return -ENOMEM;
@@ -1023,7 +1088,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
1023 1088
1024 r = hdmi_get_clocks(pdev); 1089 r = hdmi_get_clocks(pdev);
1025 if (r) { 1090 if (r) {
1026 iounmap(hdmi.ip_data.base_wp); 1091 DSSERR("can't get clocks\n");
1027 return r; 1092 return r;
1028 } 1093 }
1029 1094
@@ -1034,9 +1099,11 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
1034 hdmi.ip_data.pll_offset = HDMI_PLLCTRL; 1099 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1035 hdmi.ip_data.phy_offset = HDMI_PHY; 1100 hdmi.ip_data.phy_offset = HDMI_PHY;
1036 1101
1037 mutex_init(&hdmi.ip_data.lock); 1102 r = hdmi_panel_init();
1038 1103 if (r) {
1039 hdmi_panel_init(); 1104 DSSERR("can't init panel\n");
1105 goto err_panel_init;
1106 }
1040 1107
1041 dss_debugfs_create_file("hdmi", hdmi_dump_regs); 1108 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
1042 1109
@@ -1045,6 +1112,10 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
1045 hdmi_probe_pdata(pdev); 1112 hdmi_probe_pdata(pdev);
1046 1113
1047 return 0; 1114 return 0;
1115
1116err_panel_init:
1117 hdmi_put_clocks();
1118 return r;
1048} 1119}
1049 1120
1050static int __exit hdmi_remove_child(struct device *dev, void *data) 1121static int __exit hdmi_remove_child(struct device *dev, void *data)
@@ -1068,8 +1139,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
1068 1139
1069 hdmi_put_clocks(); 1140 hdmi_put_clocks();
1070 1141
1071 iounmap(hdmi.ip_data.base_wp);
1072
1073 return 0; 1142 return 0;
1074} 1143}
1075 1144