Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/i915/tv: Use polling rather than interrupt-based hotplug

The documentation recommends that we should use a polling method for TV
detection as this is more power efficient than the interrupt based
mechanism (as the encoder can be completely switched off). A secondary
effect is that leaving the hotplug enabled seems to be causing pipe
underruns as reported by Hugh Dickins on his Crestline.

Tested-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
[This is a candidate for stable, but needs minor porting to 2.6.37]

+30 -13
+30 -13
drivers/gpu/drm/i915/intel_tv.c
··· 1234 1234 * \return false if TV is disconnected. 1235 1235 */ 1236 1236 static int 1237 - intel_tv_detect_type (struct intel_tv *intel_tv) 1237 + intel_tv_detect_type (struct intel_tv *intel_tv, 1238 + struct drm_connector *connector) 1238 1239 { 1239 1240 struct drm_encoder *encoder = &intel_tv->base.base; 1240 1241 struct drm_device *dev = encoder->dev; ··· 1246 1245 int type; 1247 1246 1248 1247 /* Disable TV interrupts around load detect or we'll recurse */ 1249 - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 1250 - i915_disable_pipestat(dev_priv, 0, 1251 - PIPE_HOTPLUG_INTERRUPT_ENABLE | 1252 - PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); 1253 - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 1248 + if (connector->polled & DRM_CONNECTOR_POLL_HPD) { 1249 + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 1250 + i915_disable_pipestat(dev_priv, 0, 1251 + PIPE_HOTPLUG_INTERRUPT_ENABLE | 1252 + PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); 1253 + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 1254 + } 1254 1255 1255 1256 save_tv_dac = tv_dac = I915_READ(TV_DAC); 1256 1257 save_tv_ctl = tv_ctl = I915_READ(TV_CTL); ··· 1305 1302 I915_WRITE(TV_CTL, save_tv_ctl); 1306 1303 1307 1304 /* Restore interrupt config */ 1308 - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 1309 - i915_enable_pipestat(dev_priv, 0, 1310 - PIPE_HOTPLUG_INTERRUPT_ENABLE | 1311 - PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); 1312 - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 1305 + if (connector->polled & DRM_CONNECTOR_POLL_HPD) { 1306 + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 1307 + i915_enable_pipestat(dev_priv, 0, 1308 + PIPE_HOTPLUG_INTERRUPT_ENABLE | 1309 + PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); 1310 + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 1311 + } 1313 1312 1314 1313 return type; 1315 1314 } ··· 1361 1356 drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); 1362 1357 1363 1358 if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) { 1364 - type = intel_tv_detect_type(intel_tv); 1359 + type = intel_tv_detect_type(intel_tv, connector); 1365 1360 } else if (force) { 1366 1361 struct drm_crtc *crtc; 1367 1362 int dpms_mode; ··· 1369 1364 crtc = intel_get_load_detect_pipe(&intel_tv->base, connector, 1370 1365 &mode, &dpms_mode); 1371 1366 if (crtc) { 1372 - type = intel_tv_detect_type(intel_tv); 1367 + type = intel_tv_detect_type(intel_tv, connector); 1373 1368 intel_release_load_detect_pipe(&intel_tv->base, connector, 1374 1369 dpms_mode); 1375 1370 } else ··· 1662 1657 1663 1658 intel_encoder = &intel_tv->base; 1664 1659 connector = &intel_connector->base; 1660 + 1661 + /* The documentation, for the older chipsets at least, recommend 1662 + * using a polling method rather than hotplug detection for TVs. 1663 + * This is because in order to perform the hotplug detection, the PLLs 1664 + * for the TV must be kept alive increasing power drain and starving 1665 + * bandwidth from other encoders. Notably for instance, it causes 1666 + * pipe underruns on Crestline when this encoder is supposedly idle. 1667 + * 1668 + * More recent chipsets favour HDMI rather than integrated S-Video. 1669 + */ 1670 + connector->polled = 1671 + DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; 1665 1672 1666 1673 drm_connector_init(dev, connector, &intel_tv_connector_funcs, 1667 1674 DRM_MODE_CONNECTOR_SVIDEO);