aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/omap2/dss/hdmi.c234
-rw-r--r--include/video/omapdss.h44
2 files changed, 267 insertions, 11 deletions
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 2b0a2aac8aed..44a885b92825 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -70,6 +70,8 @@ static struct {
70 int ls_oe_gpio; 70 int ls_oe_gpio;
71 int hpd_gpio; 71 int hpd_gpio;
72 72
73 bool core_enabled;
74
73 struct omap_dss_device output; 75 struct omap_dss_device output;
74} hdmi; 76} hdmi;
75 77
@@ -515,8 +517,10 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
515{ 517{
516 int r; 518 int r;
517 519
518 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1); 520 if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
519 gpio_set_value(hdmi.ls_oe_gpio, 1); 521 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
522 if (gpio_is_valid(hdmi.ls_oe_gpio))
523 gpio_set_value(hdmi.ls_oe_gpio, 1);
520 524
521 /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */ 525 /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
522 udelay(300); 526 udelay(300);
@@ -532,22 +536,30 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
532 /* Make selection of HDMI in DSS */ 536 /* Make selection of HDMI in DSS */
533 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); 537 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
534 538
539 hdmi.core_enabled = true;
540
535 return 0; 541 return 0;
536 542
537err_runtime_get: 543err_runtime_get:
538 regulator_disable(hdmi.vdda_hdmi_dac_reg); 544 regulator_disable(hdmi.vdda_hdmi_dac_reg);
539err_vdac_enable: 545err_vdac_enable:
540 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); 546 if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
541 gpio_set_value(hdmi.ls_oe_gpio, 0); 547 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
548 if (gpio_is_valid(hdmi.ls_oe_gpio))
549 gpio_set_value(hdmi.ls_oe_gpio, 0);
542 return r; 550 return r;
543} 551}
544 552
545static void hdmi_power_off_core(struct omap_dss_device *dssdev) 553static void hdmi_power_off_core(struct omap_dss_device *dssdev)
546{ 554{
555 hdmi.core_enabled = false;
556
547 hdmi_runtime_put(); 557 hdmi_runtime_put();
548 regulator_disable(hdmi.vdda_hdmi_dac_reg); 558 regulator_disable(hdmi.vdda_hdmi_dac_reg);
549 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0); 559 if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
550 gpio_set_value(hdmi.ls_oe_gpio, 0); 560 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
561 if (gpio_is_valid(hdmi.ls_oe_gpio))
562 gpio_set_value(hdmi.ls_oe_gpio, 0);
551} 563}
552 564
553static int hdmi_power_on_full(struct omap_dss_device *dssdev) 565static int hdmi_power_on_full(struct omap_dss_device *dssdev)
@@ -662,6 +674,18 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
662 mutex_unlock(&hdmi.lock); 674 mutex_unlock(&hdmi.lock);
663} 675}
664 676
677static void omapdss_hdmi_display_get_timings(struct omap_dss_device *dssdev,
678 struct omap_video_timings *timings)
679{
680 const struct hdmi_config *cfg;
681
682 cfg = hdmi_get_timings();
683 if (cfg == NULL)
684 cfg = &vesa_timings[0];
685
686 memcpy(timings, &cfg->timings, sizeof(cfg->timings));
687}
688
665static void hdmi_dump_regs(struct seq_file *s) 689static void hdmi_dump_regs(struct seq_file *s)
666{ 690{
667 mutex_lock(&hdmi.lock); 691 mutex_lock(&hdmi.lock);
@@ -1025,6 +1049,199 @@ static int hdmi_probe_pdata(struct platform_device *pdev)
1025 return 0; 1049 return 0;
1026} 1050}
1027 1051
1052static int hdmi_connect(struct omap_dss_device *dssdev,
1053 struct omap_dss_device *dst)
1054{
1055 struct omap_overlay_manager *mgr;
1056 int r;
1057
1058 dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
1059
1060 r = hdmi_init_regulator();
1061 if (r)
1062 return r;
1063
1064 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
1065 if (!mgr)
1066 return -ENODEV;
1067
1068 r = dss_mgr_connect(mgr, dssdev);
1069 if (r)
1070 return r;
1071
1072 r = omapdss_output_set_device(dssdev, dst);
1073 if (r) {
1074 DSSERR("failed to connect output to new device: %s\n",
1075 dst->name);
1076 dss_mgr_disconnect(mgr, dssdev);
1077 return r;
1078 }
1079
1080 return 0;
1081}
1082
1083static void hdmi_disconnect(struct omap_dss_device *dssdev,
1084 struct omap_dss_device *dst)
1085{
1086 WARN_ON(dst != dssdev->device);
1087
1088 if (dst != dssdev->device)
1089 return;
1090
1091 omapdss_output_unset_device(dssdev);
1092
1093 if (dssdev->manager)
1094 dss_mgr_disconnect(dssdev->manager, dssdev);
1095}
1096
1097static int hdmi_read_edid(struct omap_dss_device *dssdev,
1098 u8 *edid, int len)
1099{
1100 bool need_enable;
1101 int r;
1102
1103 need_enable = hdmi.core_enabled == false;
1104
1105 if (need_enable) {
1106 r = omapdss_hdmi_core_enable(dssdev);
1107 if (r)
1108 return r;
1109 }
1110
1111 r = omapdss_hdmi_read_edid(edid, len);
1112
1113 if (need_enable)
1114 omapdss_hdmi_core_disable(dssdev);
1115
1116 return r;
1117}
1118
1119#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
1120static int omapdss_hdmi_audio_enable(struct omap_dss_device *dssdev)
1121{
1122 int r;
1123
1124 mutex_lock(&hdmi.lock);
1125
1126 if (!hdmi_mode_has_audio()) {
1127 r = -EPERM;
1128 goto err;
1129 }
1130
1131 r = hdmi_audio_enable();
1132 if (r)
1133 goto err;
1134
1135 mutex_unlock(&hdmi.lock);
1136 return 0;
1137
1138err:
1139 mutex_unlock(&hdmi.lock);
1140 return r;
1141}
1142
1143static void omapdss_hdmi_audio_disable(struct omap_dss_device *dssdev)
1144{
1145 hdmi_audio_disable();
1146}
1147
1148static int omapdss_hdmi_audio_start(struct omap_dss_device *dssdev)
1149{
1150 return hdmi_audio_start();
1151}
1152
1153static void omapdss_hdmi_audio_stop(struct omap_dss_device *dssdev)
1154{
1155 hdmi_audio_stop();
1156}
1157
1158static bool omapdss_hdmi_audio_supported(struct omap_dss_device *dssdev)
1159{
1160 bool r;
1161
1162 mutex_lock(&hdmi.lock);
1163
1164 r = hdmi_mode_has_audio();
1165
1166 mutex_unlock(&hdmi.lock);
1167 return r;
1168}
1169
1170static int omapdss_hdmi_audio_config(struct omap_dss_device *dssdev,
1171 struct omap_dss_audio *audio)
1172{
1173 int r;
1174
1175 mutex_lock(&hdmi.lock);
1176
1177 if (!hdmi_mode_has_audio()) {
1178 r = -EPERM;
1179 goto err;
1180 }
1181
1182 r = hdmi_audio_config(audio);
1183 if (r)
1184 goto err;
1185
1186 mutex_unlock(&hdmi.lock);
1187 return 0;
1188
1189err:
1190 mutex_unlock(&hdmi.lock);
1191 return r;
1192}
1193#else
1194static int omapdss_hdmi_audio_enable(struct omap_dss_device *dssdev)
1195{
1196 return -EPERM;
1197}
1198
1199static void omapdss_hdmi_audio_disable(struct omap_dss_device *dssdev)
1200{
1201}
1202
1203static int omapdss_hdmi_audio_start(struct omap_dss_device *dssdev)
1204{
1205 return -EPERM;
1206}
1207
1208static void omapdss_hdmi_audio_stop(struct omap_dss_device *dssdev)
1209{
1210}
1211
1212static bool omapdss_hdmi_audio_supported(struct omap_dss_device *dssdev)
1213{
1214 return false;
1215}
1216
1217static int omapdss_hdmi_audio_config(struct omap_dss_device *dssdev,
1218 struct omap_dss_audio *audio)
1219{
1220 return -EPERM;
1221}
1222#endif
1223
1224static const struct omapdss_hdmi_ops hdmi_ops = {
1225 .connect = hdmi_connect,
1226 .disconnect = hdmi_disconnect,
1227
1228 .enable = omapdss_hdmi_display_enable,
1229 .disable = omapdss_hdmi_display_disable,
1230
1231 .check_timings = omapdss_hdmi_display_check_timing,
1232 .set_timings = omapdss_hdmi_display_set_timing,
1233 .get_timings = omapdss_hdmi_display_get_timings,
1234
1235 .read_edid = hdmi_read_edid,
1236
1237 .audio_enable = omapdss_hdmi_audio_enable,
1238 .audio_disable = omapdss_hdmi_audio_disable,
1239 .audio_start = omapdss_hdmi_audio_start,
1240 .audio_stop = omapdss_hdmi_audio_stop,
1241 .audio_supported = omapdss_hdmi_audio_supported,
1242 .audio_config = omapdss_hdmi_audio_config,
1243};
1244
1028static void hdmi_init_output(struct platform_device *pdev) 1245static void hdmi_init_output(struct platform_device *pdev)
1029{ 1246{
1030 struct omap_dss_device *out = &hdmi.output; 1247 struct omap_dss_device *out = &hdmi.output;
@@ -1034,6 +1251,7 @@ static void hdmi_init_output(struct platform_device *pdev)
1034 out->output_type = OMAP_DISPLAY_TYPE_HDMI; 1251 out->output_type = OMAP_DISPLAY_TYPE_HDMI;
1035 out->name = "hdmi.0"; 1252 out->name = "hdmi.0";
1036 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; 1253 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
1254 out->ops.hdmi = &hdmi_ops;
1037 out->owner = THIS_MODULE; 1255 out->owner = THIS_MODULE;
1038 1256
1039 omapdss_register_output(out); 1257 omapdss_register_output(out);
@@ -1083,6 +1301,10 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
1083 hdmi.ip_data.pll_offset = HDMI_PLLCTRL; 1301 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1084 hdmi.ip_data.phy_offset = HDMI_PHY; 1302 hdmi.ip_data.phy_offset = HDMI_PHY;
1085 1303
1304 hdmi.ct_cp_hpd_gpio = -1;
1305 hdmi.ls_oe_gpio = -1;
1306 hdmi.hpd_gpio = -1;
1307
1086 hdmi_init_output(pdev); 1308 hdmi_init_output(pdev);
1087 1309
1088 r = hdmi_panel_init(); 1310 r = hdmi_panel_init();
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index adb103633bd1..709e8015f324 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -172,6 +172,11 @@ enum omap_dss_audio_state {
172 OMAP_DSS_AUDIO_PLAYING, 172 OMAP_DSS_AUDIO_PLAYING,
173}; 173};
174 174
175struct omap_dss_audio {
176 struct snd_aes_iec958 *iec;
177 struct snd_cea_861_aud_if *cea;
178};
179
175enum omap_dss_rotation_type { 180enum omap_dss_rotation_type {
176 OMAP_DSS_ROT_DMA = 1 << 0, 181 OMAP_DSS_ROT_DMA = 1 << 0,
177 OMAP_DSS_ROT_VRFB = 1 << 1, 182 OMAP_DSS_ROT_VRFB = 1 << 1,
@@ -653,6 +658,39 @@ struct omapdss_atv_ops {
653 u32 (*get_wss)(struct omap_dss_device *dssdev); 658 u32 (*get_wss)(struct omap_dss_device *dssdev);
654}; 659};
655 660
661struct omapdss_hdmi_ops {
662 int (*connect)(struct omap_dss_device *dssdev,
663 struct omap_dss_device *dst);
664 void (*disconnect)(struct omap_dss_device *dssdev,
665 struct omap_dss_device *dst);
666
667 int (*enable)(struct omap_dss_device *dssdev);
668 void (*disable)(struct omap_dss_device *dssdev);
669
670 int (*check_timings)(struct omap_dss_device *dssdev,
671 struct omap_video_timings *timings);
672 void (*set_timings)(struct omap_dss_device *dssdev,
673 struct omap_video_timings *timings);
674 void (*get_timings)(struct omap_dss_device *dssdev,
675 struct omap_video_timings *timings);
676
677 int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
678 bool (*detect)(struct omap_dss_device *dssdev);
679
680 /*
681 * Note: These functions might sleep. Do not call while
682 * holding a spinlock/readlock.
683 */
684 int (*audio_enable)(struct omap_dss_device *dssdev);
685 void (*audio_disable)(struct omap_dss_device *dssdev);
686 bool (*audio_supported)(struct omap_dss_device *dssdev);
687 int (*audio_config)(struct omap_dss_device *dssdev,
688 struct omap_dss_audio *audio);
689 /* Note: These functions may not sleep */
690 int (*audio_start)(struct omap_dss_device *dssdev);
691 void (*audio_stop)(struct omap_dss_device *dssdev);
692};
693
656struct omap_dss_device { 694struct omap_dss_device {
657 /* old device, to be removed */ 695 /* old device, to be removed */
658 struct device old_dev; 696 struct device old_dev;
@@ -722,6 +760,7 @@ struct omap_dss_device {
722 const struct omapdss_dpi_ops *dpi; 760 const struct omapdss_dpi_ops *dpi;
723 const struct omapdss_sdi_ops *sdi; 761 const struct omapdss_sdi_ops *sdi;
724 const struct omapdss_dvi_ops *dvi; 762 const struct omapdss_dvi_ops *dvi;
763 const struct omapdss_hdmi_ops *hdmi;
725 const struct omapdss_atv_ops *atv; 764 const struct omapdss_atv_ops *atv;
726 } ops; 765 } ops;
727 766
@@ -759,11 +798,6 @@ struct omap_dss_hdmi_data
759 int hpd_gpio; 798 int hpd_gpio;
760}; 799};
761 800
762struct omap_dss_audio {
763 struct snd_aes_iec958 *iec;
764 struct snd_cea_861_aud_if *cea;
765};
766
767struct omap_dss_driver { 801struct omap_dss_driver {
768 struct device_driver driver; 802 struct device_driver driver;
769 803