aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/hdmi_panel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/hdmi_panel.c')
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index aafe636..9e2cfc3 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -139,6 +139,8 @@ static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+ hdmi_panel_hpd_handler(0);
+
omapdss_hdmi_display_disable(dssdev);
err:
mutex_unlock(&hdmi.hdmi_lock);
@@ -194,23 +196,41 @@ static void hdmi_hotplug_detect_worker(struct work_struct *work)
if (dssdev == NULL)
return;
+ mutex_lock(&hdmi.hdmi_lock);
if (state == HPD_STATE_OFF) {
switch_set_state(&hdmi.hpd_switch, 0);
- dssdev->driver->disable(dssdev);
- return;
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+ mutex_unlock(&hdmi.hdmi_lock);
+ dssdev->driver->disable(dssdev);
+ mutex_lock(&hdmi.hdmi_lock);
+ }
+ goto done;
} else {
if (state == HPD_STATE_START) {
+ mutex_unlock(&hdmi.hdmi_lock);
dssdev->driver->enable(dssdev);
+ mutex_lock(&hdmi.hdmi_lock);
+ } else if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
+ hdmi.hpd_switch.state) {
+ /* powered down after enable - skip EDID read */
+ goto done;
} else if (hdmi_read_edid(&dssdev->panel.timings)) {
+ /* get monspecs from edid */
+ hdmi_get_monspecs(&dssdev->panel.monspecs);
+ pr_info("panel size %d by %d\n",
+ dssdev->panel.monspecs.max_x,
+ dssdev->panel.monspecs.max_y);
switch_set_state(&hdmi.hpd_switch, 1);
- return;
+ goto done;
} else if (state == HPD_STATE_EDID_TRYLAST){
pr_info("Failed to read EDID after %d times. Giving up.", state - HPD_STATE_START);
- return;
+ goto done;
}
if (atomic_add_unless(&d->state, 1, HPD_STATE_OFF))
queue_delayed_work(my_workq, &d->dwork, msecs_to_jiffies(60));
}
+done:
+ mutex_unlock(&hdmi.hdmi_lock);
}
int hdmi_panel_hpd_handler(int hpd)
@@ -265,6 +285,16 @@ err:
return r;
}
+static int hdmi_get_modedb(struct omap_dss_device *dssdev,
+ struct fb_videomode *modedb, int modedb_len)
+{
+ struct fb_monspecs *specs = &dssdev->panel.monspecs;
+ if (specs->modedb_len < modedb_len)
+ modedb_len = specs->modedb_len;
+ memcpy(modedb, specs->modedb, sizeof(*modedb) * modedb_len);
+ return modedb_len;
+}
+
static struct omap_dss_driver hdmi_driver = {
.probe = hdmi_panel_probe,
.remove = hdmi_panel_remove,
@@ -275,6 +305,8 @@ static struct omap_dss_driver hdmi_driver = {
.get_timings = hdmi_get_timings,
.set_timings = hdmi_set_timings,
.check_timings = hdmi_check_timings,
+ .get_modedb = hdmi_get_modedb,
+ .set_mode = omapdss_hdmi_display_set_mode,
.driver = {
.name = "hdmi_panel",
.owner = THIS_MODULE,