struct drm_device *dev = output->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = output->driver_private;
+ u32 pipeastat, pipeastat_save;
u32 tv_ctl, save_tv_ctl;
u32 tv_dac, save_tv_dac;
int type = ConnectorUnknown;
tv_dac = I915_READ(TV_DAC);
+
+ /* Disable TV interrupts around load detect or we'll recurse */
+ pipeastat = I915_READ(I915REG_PIPEASTAT);
+ pipeastat_save = pipeastat;
+ pipeastat &= ~I915_HOTPLUG_INTERRUPT_ENABLE;
+ pipeastat &= ~I915_HOTPLUG_TV_INTERRUPT_ENABLE;
+ I915_WRITE(I915REG_PIPEASTAT, pipeastat | I915_HOTPLUG_TV_CLEAR |
+ I915_HOTPLUG_CLEAR);
+
/*
* Detect TV by polling)
*/
type = -1;
}
+ /* Restore interrupt config */
+ I915_WRITE(I915REG_PIPEASTAT, pipeastat_save | I915_HOTPLUG_TV_CLEAR |
+ I915_HOTPLUG_CLEAR);
+
return type;
}
mode = reported_modes[0];
drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
- crtc = intel_get_load_detect_pipe(output, &mode, &dpms_mode);
- if (crtc) {
- type = intel_tv_detect_type(crtc, output);
- intel_release_load_detect_pipe(output, dpms_mode);
+ if (output->crtc) {
+ type = intel_tv_detect_type(output->crtc, output);
+ } else {
+ crtc = intel_get_load_detect_pipe(output, &mode, &dpms_mode);
+ if (crtc) {
+ type = intel_tv_detect_type(crtc, output);
+ intel_release_load_detect_pipe(output, dpms_mode);
+ } else
+ type = -1;
}
if (type != tv_priv->type) {
if (iout == 0)
goto unlock;
- /* may need to I915_WRITE(TVDAC, 1<<31) to ack the interrupt */
status = output->funcs->detect(output);
drm_hotplug_stage_two(dev, output,
status == output_status_connected ? 1 : 0);
struct drm_i915_master_private *master_priv;
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
u32 iir;
- u32 pipea_stats, pipeb_stats;
+ u32 pipea_stats = 0, pipeb_stats, tvdac;
int hotplug = 0;
int vblank = 0;
}
/* This is a global event, and not a pipe A event */
- if ((pipea_stats & I915_HOTPLUG_INTERRUPT_STATUS) ||
- (pipea_stats & I915_HOTPLUG_TV_INTERRUPT_STATUS))
+ if (pipea_stats & I915_HOTPLUG_INTERRUPT_STATUS)
hotplug = 1;
+ if (pipea_stats & I915_HOTPLUG_TV_INTERRUPT_STATUS) {
+ hotplug = 1;
+ /* Toggle hotplug detection to clear hotplug status */
+ tvdac = I915_READ(TV_DAC);
+ I915_WRITE(TV_DAC, tvdac & ~TVDAC_STATE_CHG_EN);
+ I915_WRITE(TV_DAC, tvdac | TVDAC_STATE_CHG_EN);
+ }
+
I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
}
I915_WRITE(SDVOB, I915_READ(SDVOB) | SDVO_INTERRUPT_ENABLE);
I915_WRITE(SDVOC, I915_READ(SDVOC) | SDVO_INTERRUPT_ENABLE);
+
+ /* TV */
+ I915_WRITE(TV_DAC, I915_READ(TV_DAC) | TVDAC_STATE_CHG_EN);
} else {
/* DVO ???? */
}