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]
This commit is contained in:
Родитель
1aad7ac045
Коммит
8102e126c0
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче