[Intel-gfx] [PATCH] drm/i915: crt load pipe detection sync up with 2D driver

Eric Anholt eric at anholt.net
Fri May 22 21:15:59 CEST 2009


On Fri, 2009-05-22 at 17:50 +0800, Ma Ling wrote:
> Two approaches for VGA detections: hot plug detection for 945G onwards
> and load pipe detection for Pre-945G. load pipe detection will get one free
> pipe ,and set border color as red and blue, then check CRT status by
> swf register.
> 
> Signed-off-by: Ma Ling <ling.ma at intel.com>
> ---
>  drivers/gpu/drm/i915/intel_crt.c |  164 ++++++++++++++++++++++++++++++++++++--
>  1 files changed, 157 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 19148c3..60f979f 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -198,22 +198,172 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
>  	return intel_ddc_probe(intel_output);
>  }
>  
> +static enum drm_connector_status
> +intel_crt_load_detect(struct drm_crtc *crtc, struct intel_output *intel_output)
> +{
> +	struct drm_encoder *encoder = &intel_output->enc;
> +	struct drm_device *dev = encoder->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	uint32_t pipe = intel_crtc->pipe;
> +	uint32_t save_bclrpat;
> +	uint32_t save_vtotal;
> +	uint32_t vtotal, vactive;
> +	uint32_t vsample;
> +	uint32_t vblank, vblank_start, vblank_end;
> +	uint32_t dsl;
> +	uint32_t bclrpat_reg;
> +	uint32_t vtotal_reg;
> +	uint32_t vblank_reg;
> +	uint32_t vsync_reg;
> +	uint32_t pipeconf_reg;
> +	uint32_t pipe_dsl_reg;
> +	uint8_t	st00;
> +	enum drm_connector_status status;
> +
> +	if (pipe == 0) {
> +		bclrpat_reg = BCLRPAT_A;
> +		vtotal_reg = VTOTAL_A;
> +		vblank_reg = VBLANK_A;
> +		vsync_reg = VSYNC_A;
> +		pipeconf_reg = PIPEACONF;
> +		/* Display Scan Line for PIPE A */
> +		pipe_dsl_reg = 0x70000;
> +	} else {
> +		bclrpat_reg = BCLRPAT_B;
> +		vtotal_reg = VTOTAL_B;
> +		vblank_reg = VBLANK_B;
> +		vsync_reg = VSYNC_B;
> +		pipeconf_reg = PIPEBCONF;
> +		/* Display Scan Line for PIPE B */
> +		pipe_dsl_reg = 0x71000;

Register definitions go in the register header.

> +	}
> +
> +	save_bclrpat = I915_READ(bclrpat_reg);
> +	save_vtotal = I915_READ(vtotal_reg);
> +	vblank = I915_READ(vblank_reg);
> +
> +	vtotal = ((save_vtotal >> 16) & 0xfff) + 1;
> +	vactive = (save_vtotal & 0x7ff) + 1;
> +
> +	vblank_start = (vblank & 0xfff) + 1;
> +	vblank_end = ((vblank >> 16) & 0xfff) + 1;
> +
> +	/* Set the border color to purple. */
> +	I915_WRITE(bclrpat_reg, 0x500050);
> +
> +	if (IS_I9XX(dev)) {
> +		uint32_t pipeconf = I915_READ(pipeconf_reg);
> +		I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
> +		/* Wait for next Vblank to substitue
> +		 * border color for Color info */
> +		intel_wait_for_vblank(dev);
> +		st00 = I915_READ8(VGA_MSR_WRITE);
> +		status  = ((st00 & (1 << 4)) != 0) ?
> +			connector_status_connected :
> +			connector_status_disconnected;
> +
> +		I915_WRITE(pipeconf_reg, pipeconf);
> +	} else {
> +		bool restore_vblank = false;
> +		int count, detect;
> +
> +		/*
> +		* If there isn't any border, add some.
> +		* Yes, this will flicker
> +		*/
> +		if (vblank_start <= vactive && vblank_end >= vtotal) {
> +			uint32_t  vsync = I915_READ(vsync_reg);
> +			uint32_t  vsync_start = (vsync & 0xffff) + 1;
> +
> +			vblank_start = vsync_start;
> +			I915_WRITE(vblank_reg,
> +				(vblank_start - 1) |
> +				((vblank_end - 1) << 16));
> +			restore_vblank = true;
> +		}
> +		/* sample in the vertical border, selecting the larger one */
> +		if (vblank_start - vactive >= vtotal - vblank_end)
> +			vsample = (vblank_start + vactive) >> 1;
> +		else
> +			vsample = (vtotal + vblank_end) >> 1;
> +
> +		/*
> +		 * Wait for the border to be displayed
> +		 */
> +		while (I915_READ(pipe_dsl_reg) >= vactive)
> +			;
> +		while ((dsl = I915_READ(pipe_dsl_reg)) <= vsample)
> +			;
> +		/*
> +		 * Watch ST00 for an entire scanline
> +		 */
> +		detect = 0;
> +		count = 0;
> +		do {
> +			count++;
> +			/* Read the ST00 VGA status register */
> +			st00 = I915_READ8(VGA_MSR_WRITE);
> +			if (st00 & (1 << 4))
> +				detect++;
> +		} while ((I915_READ(pipe_dsl_reg) == dsl));
> +
> +		/* restore vblank if necessary */
> +		if (restore_vblank)
> +			I915_WRITE(vblank_reg, vblank);
> +		/*
> +		 * If more than 3/4 of the scanline detected a monitor,
> +		 * then it is assumed to be present. This works even on i830,
> +		 * where there isn't any way to force the border color across
> +		 * the screen
> +		 */
> +		status = detect * 4 > count * 3 ?
> +			 connector_status_connected :
> +			 connector_status_disconnected;
> +	}
> +
> +	/* Restore previous settings */
> +	I915_WRITE(bclrpat_reg, save_bclrpat);
> +
> +	return status;
> +}
> +
>  static enum drm_connector_status intel_crt_detect(struct drm_connector *connector)
>  {
>  	struct drm_device *dev = connector->dev;
> +	struct intel_output *intel_output = to_intel_output(connector);
> +	struct drm_encoder *encoder = &intel_output->enc;
> +	struct drm_crtc *crtc;
> +	int dpms_mode;
> +	enum drm_connector_status status = connector_status_disconnected;
>  
>  	if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
>  		if (intel_crt_detect_hotplug(connector))
> -			return connector_status_connected;
> -		else
> -			return connector_status_disconnected;
> +			status = connector_status_connected;
> +
> +		goto end;
> +	}
> +
> +	if (intel_crt_detect_ddc(connector)) {
> +		status = connector_status_connected;
> +		goto end;
>  	}
>  
> -	if (intel_crt_detect_ddc(connector))
> -		return connector_status_connected;
> +	/* for pre-945g platforms use load detect */
> +	if (encoder->crtc && encoder->crtc->enabled) {
> +		status = intel_crt_load_detect(encoder->crtc, intel_output);
> +	} else {
> +		crtc = intel_get_load_detect_pipe(intel_output,
> +						  NULL, &dpms_mode);
> +		if (crtc) {
> +			status = intel_crt_load_detect(crtc, intel_output);
> +			intel_release_load_detect_pipe(intel_output, dpms_mode);
> +		} else
> +			status = connector_status_unknown;
> +	}
>  
> -	/* TODO use load detect */
> -	return connector_status_unknown;
> +end:
> +	return status;
>  }

If there's no other teardown, please replace these gotos to the return
with just returns.

-- 
Eric Anholt
eric at anholt.net                         eric.anholt at intel.com


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20090522/d0094eed/attachment.sig>


More information about the Intel-gfx mailing list