[RFC] drm/msm/hdmi: spurious hpd disconnect workaround
Rob Clark
robdclark at gmail.com
Wed Jan 21 12:43:16 PST 2015
On some (well, maybe just one) HDMI monitor I get a spurious disconnect
in the process of lighting up the display. A low-pass filter on HPD
events, in the form of leaving the HPD irq disabled for 100ms after the
previous HPD irq, seems to do a good job of working around the issue.
A somewhat simpler solution is just msleep(100) in the hotplug worker.
But AFAIU that will interfere with the pending HDCP support, if HDCP
requires guarantees about detecting disconnect in a timely fashion.
Signed-off-by: Rob Clark <robdclark at gmail.com>
---
drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
index bc20e9b..f481f54 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
@@ -24,6 +24,7 @@ struct hdmi_connector {
struct drm_connector base;
struct hdmi *hdmi;
struct work_struct hpd_work;
+ struct timer_list hotplug_timer;
};
#define to_hdmi_connector(x) container_of(x, struct hdmi_connector, base)
@@ -228,11 +229,25 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector)
}
static void
+hotplug_timer(unsigned long data)
+{
+ struct hdmi *hdmi = (struct hdmi *)data;
+ uint32_t hpd_int_ctrl;
+
+ /* re-enable HPD irq: */
+ hpd_int_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_INT_CTRL);
+ hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_EN;
+ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
+}
+
+static void
hotplug_work(struct work_struct *work)
{
struct hdmi_connector *hdmi_connector =
container_of(work, struct hdmi_connector, hpd_work);
struct drm_connector *connector = &hdmi_connector->base;
+ mod_timer(&hdmi_connector->hotplug_timer,
+ round_jiffies_up(jiffies + msecs_to_jiffies(100)));
drm_helper_hpd_irq_event(connector->dev);
}
@@ -258,7 +273,7 @@ void hdmi_connector_irq(struct drm_connector *connector)
DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl);
/* detect disconnect if we are connected or visa versa: */
- hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN;
+ hpd_int_ctrl = 0;
if (!detected)
hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
@@ -416,6 +431,8 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
hdmi_connector->hdmi = hdmi;
INIT_WORK(&hdmi_connector->hpd_work, hotplug_work);
+ setup_timer(&hdmi_connector->hotplug_timer, hotplug_timer,
+ (unsigned long)hdmi);
connector = &hdmi_connector->base;
--
2.1.0
More information about the dri-devel
mailing list