aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Farnsworth <simon.farnsworth@onelan.co.uk>2011-09-21 12:13:30 -0400
committerKeith Packard <keithp@keithp.com>2011-09-21 17:55:51 -0400
commitcc68c81aed7d892deaf12d720d5455208e94cd0a (patch)
tree1f2e593274a7437846ff4fa59fb8c50232c27b7c
parent7cd015a0a37265e23bbdce7ce8f7e00507abe9ed (diff)
drm/i915: Enable SDVO hotplug interrupts for HDMI and DVI
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. Note that this is only tested on single-function DVI-D SDVOs, on two platforms (965GME and 945GSE), and has not been checked against a specification document. With lots of help from Adam Jackson <ajax@redhat.com> on IRC. Signed-off-by: Simon Farnsworth <simon.farnsworth@onelan.co.uk> Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h3
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c88
2 files changed, 29 insertions, 62 deletions
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0b2ee9d39980..fe1099d8817e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -337,9 +337,6 @@ extern void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
337 struct drm_connector *connector, 337 struct drm_connector *connector,
338 struct intel_load_detect_pipe *old); 338 struct intel_load_detect_pipe *old);
339 339
340extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB);
341extern int intel_sdvo_supports_hotplug(struct drm_connector *connector);
342extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable);
343extern void intelfb_restore(void); 340extern void intelfb_restore(void);
344extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, 341extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
345 u16 blue, int regno); 342 u16 blue, int regno);
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 30fe554d8936..6348c499616f 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -92,6 +92,11 @@ struct intel_sdvo {
92 */ 92 */
93 uint16_t attached_output; 93 uint16_t attached_output;
94 94
95 /*
96 * Hotplug activation bits for this device
97 */
98 uint8_t hotplug_active[2];
99
95 /** 100 /**
96 * This is used to select the color range of RBG outputs in HDMI mode. 101 * This is used to select the color range of RBG outputs in HDMI mode.
97 * It is only valid when using TMDS encoding and 8 bit per color mode. 102 * It is only valid when using TMDS encoding and 8 bit per color mode.
@@ -1208,74 +1213,20 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
1208 return true; 1213 return true;
1209} 1214}
1210 1215
1211/* No use! */ 1216static int intel_sdvo_supports_hotplug(struct intel_sdvo *intel_sdvo)
1212#if 0
1213struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB)
1214{
1215 struct drm_connector *connector = NULL;
1216 struct intel_sdvo *iout = NULL;
1217 struct intel_sdvo *sdvo;
1218
1219 /* find the sdvo connector */
1220 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1221 iout = to_intel_sdvo(connector);
1222
1223 if (iout->type != INTEL_OUTPUT_SDVO)
1224 continue;
1225
1226 sdvo = iout->dev_priv;
1227
1228 if (sdvo->sdvo_reg == SDVOB && sdvoB)
1229 return connector;
1230
1231 if (sdvo->sdvo_reg == SDVOC && !sdvoB)
1232 return connector;
1233
1234 }
1235
1236 return NULL;
1237}
1238
1239int intel_sdvo_supports_hotplug(struct drm_connector *connector)
1240{ 1217{
1241 u8 response[2]; 1218 u8 response[2];
1242 u8 status;
1243 struct intel_sdvo *intel_sdvo;
1244 DRM_DEBUG_KMS("\n");
1245
1246 if (!connector)
1247 return 0;
1248
1249 intel_sdvo = to_intel_sdvo(connector);
1250 1219
1251 return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, 1220 return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
1252 &response, 2) && response[0]; 1221 &response, 2) && response[0];
1253} 1222}
1254 1223
1255void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) 1224static void intel_sdvo_enable_hotplug(struct intel_encoder *encoder)
1256{ 1225{
1257 u8 response[2]; 1226 struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
1258 u8 status;
1259 struct intel_sdvo *intel_sdvo = to_intel_sdvo(connector);
1260
1261 intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
1262 intel_sdvo_read_response(intel_sdvo, &response, 2);
1263
1264 if (on) {
1265 intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
1266 status = intel_sdvo_read_response(intel_sdvo, &response, 2);
1267
1268 intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
1269 } else {
1270 response[0] = 0;
1271 response[1] = 0;
1272 intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
1273 }
1274 1227
1275 intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); 1228 intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &intel_sdvo->hotplug_active, 2);
1276 intel_sdvo_read_response(intel_sdvo, &response, 2);
1277} 1229}
1278#endif
1279 1230
1280static bool 1231static bool
1281intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) 1232intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
@@ -2045,6 +1996,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
2045{ 1996{
2046 struct drm_encoder *encoder = &intel_sdvo->base.base; 1997 struct drm_encoder *encoder = &intel_sdvo->base.base;
2047 struct drm_connector *connector; 1998 struct drm_connector *connector;
1999 struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
2048 struct intel_connector *intel_connector; 2000 struct intel_connector *intel_connector;
2049 struct intel_sdvo_connector *intel_sdvo_connector; 2001 struct intel_sdvo_connector *intel_sdvo_connector;
2050 2002
@@ -2062,7 +2014,17 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
2062 2014
2063 intel_connector = &intel_sdvo_connector->base; 2015 intel_connector = &intel_sdvo_connector->base;
2064 connector = &intel_connector->base; 2016 connector = &intel_connector->base;
2065 connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; 2017 if (intel_sdvo_supports_hotplug(intel_sdvo) & (1 << device)) {
2018 connector->polled = DRM_CONNECTOR_POLL_HPD;
2019 intel_sdvo->hotplug_active[0] |= 1 << device;
2020 /* Some SDVO devices have one-shot hotplug interrupts.
2021 * Ensure that they get re-enabled when an interrupt happens.
2022 */
2023 intel_encoder->hot_plug = intel_sdvo_enable_hotplug;
2024 intel_sdvo_enable_hotplug(intel_encoder);
2025 }
2026 else
2027 connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
2066 encoder->encoder_type = DRM_MODE_ENCODER_TMDS; 2028 encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
2067 connector->connector_type = DRM_MODE_CONNECTOR_DVID; 2029 connector->connector_type = DRM_MODE_CONNECTOR_DVID;
2068 2030
@@ -2569,6 +2531,14 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
2569 if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) 2531 if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
2570 goto err; 2532 goto err;
2571 2533
2534 /* Set up hotplug command - note paranoia about contents of reply.
2535 * We assume that the hardware is in a sane state, and only touch
2536 * the bits we think we understand.
2537 */
2538 intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG,
2539 &intel_sdvo->hotplug_active, 2);
2540 intel_sdvo->hotplug_active[0] &= ~0x3;
2541
2572 if (intel_sdvo_output_setup(intel_sdvo, 2542 if (intel_sdvo_output_setup(intel_sdvo,
2573 intel_sdvo->caps.output_flags) != true) { 2543 intel_sdvo->caps.output_flags) != true) {
2574 DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", 2544 DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",