diff options
Diffstat (limited to 'drivers/video/omap2/dss/hdmi_panel.c')
-rw-r--r-- | drivers/video/omap2/dss/hdmi_panel.c | 40 |
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, |