Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8102e126 authored by Chris Wilson's avatar Chris Wilson
Browse files

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: default avatarHugh Dickins <hughd@google.com>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
[This is a candidate for stable, but needs minor porting to 2.6.37]
parent 1aad7ac0
Loading
Loading
Loading
Loading
+30 −13
Original line number Diff line number Diff line
@@ -1234,7 +1234,8 @@ static const struct drm_display_mode reported_modes[] = {
 * \return false if TV is disconnected.
 */
static int
intel_tv_detect_type (struct intel_tv *intel_tv)
intel_tv_detect_type (struct intel_tv *intel_tv,
		      struct drm_connector *connector)
{
	struct drm_encoder *encoder = &intel_tv->base.base;
	struct drm_device *dev = encoder->dev;
@@ -1245,11 +1246,13 @@ intel_tv_detect_type (struct intel_tv *intel_tv)
	int type;

	/* Disable TV interrupts around load detect or we'll recurse */
	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
		i915_disable_pipestat(dev_priv, 0,
				      PIPE_HOTPLUG_INTERRUPT_ENABLE |
				      PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
	}

	save_tv_dac = tv_dac = I915_READ(TV_DAC);
	save_tv_ctl = tv_ctl = I915_READ(TV_CTL);
@@ -1302,11 +1305,13 @@ intel_tv_detect_type (struct intel_tv *intel_tv)
	I915_WRITE(TV_CTL, save_tv_ctl);

	/* Restore interrupt config */
	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
		i915_enable_pipestat(dev_priv, 0,
				     PIPE_HOTPLUG_INTERRUPT_ENABLE |
				     PIPE_HOTPLUG_TV_INTERRUPT_ENABLE);
		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
	}

	return type;
}
@@ -1356,7 +1361,7 @@ intel_tv_detect(struct drm_connector *connector, bool force)
	drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);

	if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) {
		type = intel_tv_detect_type(intel_tv);
		type = intel_tv_detect_type(intel_tv, connector);
	} else if (force) {
		struct drm_crtc *crtc;
		int dpms_mode;
@@ -1364,7 +1369,7 @@ intel_tv_detect(struct drm_connector *connector, bool force)
		crtc = intel_get_load_detect_pipe(&intel_tv->base, connector,
						  &mode, &dpms_mode);
		if (crtc) {
			type = intel_tv_detect_type(intel_tv);
			type = intel_tv_detect_type(intel_tv, connector);
			intel_release_load_detect_pipe(&intel_tv->base, connector,
						       dpms_mode);
		} else
@@ -1658,6 +1663,18 @@ intel_tv_init(struct drm_device *dev)
	intel_encoder = &intel_tv->base;
	connector = &intel_connector->base;

	/* The documentation, for the older chipsets at least, recommend
	 * using a polling method rather than hotplug detection for TVs.
	 * This is because in order to perform the hotplug detection, the PLLs
	 * for the TV must be kept alive increasing power drain and starving
	 * bandwidth from other encoders. Notably for instance, it causes
	 * pipe underruns on Crestline when this encoder is supposedly idle.
	 *
	 * More recent chipsets favour HDMI rather than integrated S-Video.
	 */
	connector->polled =
		DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;

	drm_connector_init(dev, connector, &intel_tv_connector_funcs,
			   DRM_MODE_CONNECTOR_SVIDEO);