From patchwork Wed Aug 17 09:52:21 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Farnsworth X-Patchwork-Id: 1073782 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p7HBoWpB024208 for ; Wed, 17 Aug 2011 11:50:53 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4A0BB9F5EC for ; Wed, 17 Aug 2011 04:50:32 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Wed, 17 Aug 2011 11:50:53 +0000 (UTC) X-Greylist: delayed 6805 seconds by postgrey-1.31 at gabe; Wed, 17 Aug 2011 04:45:52 PDT Received: from claranet-outbound-smtp03.uk.clara.net (claranet-outbound-smtp03.uk.clara.net [195.8.89.36]) by gabe.freedesktop.org (Postfix) with ESMTP id 86414A028B for ; Wed, 17 Aug 2011 04:45:52 -0700 (PDT) Received: from 110.100.155.90.in-addr.arpa ([90.155.100.110]:43495 helo=f12simon.office.onelan.co.uk) by relay03.mail.eu.clara.net (relay.clara.net [213.253.3.43]:1025) with esmtpa (authdaemon_plain:simon.farnsworth@onelan.co.uk) id 1QtcnQ-0006ET-AZ (return-path ); Wed, 17 Aug 2011 09:52:24 +0000 From: Simon Farnsworth To: "intel-gfx@lists.freedesktop.org" Date: Wed, 17 Aug 2011 10:52:21 +0100 Message-Id: <1313574741-31193-1-git-send-email-simon.farnsworth@onelan.co.uk> X-Mailer: git-send-email 1.7.6 Subject: [Intel-gfx] [PATCH] i915: Enable SDVO hotplug interrupts for HDMI and DVI X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org I was seeing a nasty 5 frame glitch every 10 seconds, caused by the poll for connection on DVI attached by SDVO. As my SDVO DVI supports hotplug detect interrupts, the fix is to enable them, and hook them in to the various bits of driver infrastructure so that they work reliably. With lots of help from Adam Jackson on IRC. Signed-off-by: Simon Farnsworth --- I'm not entirely confident that I'm treating the result of SDVO_CMD_GET_HOT_PLUG_SUPPORT correctly for multifunction SDVO devices. I've assumed it's a bitmask, but I have no documents to tell me that that's right. Review from someone who understands SDVO would be appreciated. Note that I've only wired up hotplug fully for SDVO TMDS outputs. While we will get hotplug interrupts for other SDVO types, we won't do anything with them; if someone with another SDVO type wants to wire it up and test it, look at how intel_sdvo_dvi_init sets connector->polled. However, this does work well for my hardware, which is all single-function SDVO DVI-D ports, both on Atom N270 and 965GME. drivers/gpu/drm/i915/intel_drv.h | 3 -- drivers/gpu/drm/i915/intel_sdvo.c | 43 ++++++++++++++++++------------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7b330e7..94bb596 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -336,9 +336,6 @@ extern void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_connector *connector, struct intel_load_detect_pipe *old); -extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB); -extern int intel_sdvo_supports_hotplug(struct drm_connector *connector); -extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable); extern void intelfb_restore(void); extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 30fe554..9404388 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1235,47 +1235,38 @@ struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB) return NULL; } +#endif -int intel_sdvo_supports_hotplug(struct drm_connector *connector) +static int intel_sdvo_supports_hotplug(struct intel_sdvo *intel_sdvo) { u8 response[2]; - u8 status; - struct intel_sdvo *intel_sdvo; - DRM_DEBUG_KMS("\n"); - - if (!connector) - return 0; - - intel_sdvo = to_intel_sdvo(connector); return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, &response, 2) && response[0]; } -void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) +static void intel_sdvo_set_hotplug(struct intel_sdvo *intel_sdvo) { u8 response[2]; u8 status; - struct intel_sdvo *intel_sdvo = to_intel_sdvo(connector); intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); intel_sdvo_read_response(intel_sdvo, &response, 2); - if (on) { - intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0); - status = intel_sdvo_read_response(intel_sdvo, &response, 2); + intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0); + status = intel_sdvo_read_response(intel_sdvo, &response, 2); - intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); - } else { - response[0] = 0; - response[1] = 0; - intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); - } + intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); intel_sdvo_read_response(intel_sdvo, &response, 2); } -#endif + +void intel_sdvo_do_hotplug(struct intel_encoder *encoder) +{ + struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base); + intel_sdvo_set_hotplug(intel_sdvo); +} static bool intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) @@ -2062,7 +2053,10 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) intel_connector = &intel_sdvo_connector->base; connector = &intel_connector->base; - connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; + if (intel_sdvo_supports_hotplug(intel_sdvo) & (1 << device)) + connector->polled = DRM_CONNECTOR_POLL_HPD; + else + connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; encoder->encoder_type = DRM_MODE_ENCODER_TMDS; connector->connector_type = DRM_MODE_CONNECTOR_DVID; @@ -2587,6 +2581,11 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) &intel_sdvo->pixel_clock_max)) goto err; + if (intel_sdvo_supports_hotplug(intel_sdvo)) { + intel_encoder->hot_plug = intel_sdvo_do_hotplug; + intel_sdvo_set_hotplug(intel_sdvo); + } + DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " "clock range %dMHz - %dMHz, " "input 1: %c, input 2: %c, "