diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_tv.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_tv.c | 261 | 
1 files changed, 136 insertions, 125 deletions
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index dd6f84bf6c2..67c6c9a2eb1 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -902,6 +902,13 @@ intel_tv_mode_valid(struct drm_connector *connector,  } +static void +intel_tv_get_config(struct intel_encoder *encoder, +		    struct intel_crtc_config *pipe_config) +{ +	pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; +} +  static bool  intel_tv_compute_config(struct intel_encoder *encoder,  			struct intel_crtc_config *pipe_config) @@ -912,7 +919,7 @@ intel_tv_compute_config(struct intel_encoder *encoder,  	if (!tv_mode)  		return false; -	pipe_config->adjusted_mode.clock = tv_mode->clock; +	pipe_config->adjusted_mode.crtc_clock = tv_mode->clock;  	DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");  	pipe_config->pipe_bpp = 8*3; @@ -927,7 +934,86 @@ intel_tv_compute_config(struct intel_encoder *encoder,  	return true;  } -static void intel_tv_mode_set(struct intel_encoder *encoder) +static void +set_tv_mode_timings(struct drm_i915_private *dev_priv, +		    const struct tv_mode *tv_mode, +		    bool burst_ena) +{ +	u32 hctl1, hctl2, hctl3; +	u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7; + +	hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) | +		(tv_mode->htotal << TV_HTOTAL_SHIFT); + +	hctl2 = (tv_mode->hburst_start << 16) | +		(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT); + +	if (burst_ena) +		hctl2 |= TV_BURST_ENA; + +	hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) | +		(tv_mode->hblank_end << TV_HBLANK_END_SHIFT); + +	vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) | +		(tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) | +		(tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT); + +	vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) | +		(tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) | +		(tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT); + +	vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) | +		(tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) | +		(tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT); + +	if (tv_mode->veq_ena) +		vctl3 |= TV_EQUAL_ENA; + +	vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) | +		(tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT); + +	vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) | +		(tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT); + +	vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) | +		(tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT); + +	vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) | +		(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT); + +	I915_WRITE(TV_H_CTL_1, hctl1); +	I915_WRITE(TV_H_CTL_2, hctl2); +	I915_WRITE(TV_H_CTL_3, hctl3); +	I915_WRITE(TV_V_CTL_1, vctl1); +	I915_WRITE(TV_V_CTL_2, vctl2); +	I915_WRITE(TV_V_CTL_3, vctl3); +	I915_WRITE(TV_V_CTL_4, vctl4); +	I915_WRITE(TV_V_CTL_5, vctl5); +	I915_WRITE(TV_V_CTL_6, vctl6); +	I915_WRITE(TV_V_CTL_7, vctl7); +} + +static void set_color_conversion(struct drm_i915_private *dev_priv, +				 const struct color_conversion *color_conversion) +{ +	if (!color_conversion) +		return; + +	I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) | +		   color_conversion->gy); +	I915_WRITE(TV_CSC_Y2, (color_conversion->by << 16) | +		   color_conversion->ay); +	I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) | +		   color_conversion->gu); +	I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) | +		   color_conversion->au); +	I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) | +		   color_conversion->gv); +	I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) | +		   color_conversion->av); +} + +static void intel_tv_pre_enable(struct intel_encoder *encoder)  {  	struct drm_device *dev = encoder->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -935,14 +1021,13 @@ static void intel_tv_mode_set(struct intel_encoder *encoder)  	struct intel_tv *intel_tv = enc_to_tv(encoder);  	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);  	u32 tv_ctl; -	u32 hctl1, hctl2, hctl3; -	u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;  	u32 scctl1, scctl2, scctl3;  	int i, j;  	const struct video_levels *video_levels;  	const struct color_conversion *color_conversion;  	bool burst_ena; -	int pipe = intel_crtc->pipe; +	int xpos = 0x0, ypos = 0x0; +	unsigned int xsize, ysize;  	if (!tv_mode)  		return;	/* can't happen (mode_prepare prevents this) */ @@ -975,44 +1060,6 @@ static void intel_tv_mode_set(struct intel_encoder *encoder)  		burst_ena = tv_mode->burst_ena;  		break;  	} -	hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) | -		(tv_mode->htotal << TV_HTOTAL_SHIFT); - -	hctl2 = (tv_mode->hburst_start << 16) | -		(tv_mode->hburst_len << TV_HBURST_LEN_SHIFT); - -	if (burst_ena) -		hctl2 |= TV_BURST_ENA; - -	hctl3 = (tv_mode->hblank_start << TV_HBLANK_START_SHIFT) | -		(tv_mode->hblank_end << TV_HBLANK_END_SHIFT); - -	vctl1 = (tv_mode->nbr_end << TV_NBR_END_SHIFT) | -		(tv_mode->vi_end_f1 << TV_VI_END_F1_SHIFT) | -		(tv_mode->vi_end_f2 << TV_VI_END_F2_SHIFT); - -	vctl2 = (tv_mode->vsync_len << TV_VSYNC_LEN_SHIFT) | -		(tv_mode->vsync_start_f1 << TV_VSYNC_START_F1_SHIFT) | -		(tv_mode->vsync_start_f2 << TV_VSYNC_START_F2_SHIFT); - -	vctl3 = (tv_mode->veq_len << TV_VEQ_LEN_SHIFT) | -		(tv_mode->veq_start_f1 << TV_VEQ_START_F1_SHIFT) | -		(tv_mode->veq_start_f2 << TV_VEQ_START_F2_SHIFT); - -	if (tv_mode->veq_ena) -		vctl3 |= TV_EQUAL_ENA; - -	vctl4 = (tv_mode->vburst_start_f1 << TV_VBURST_START_F1_SHIFT) | -		(tv_mode->vburst_end_f1 << TV_VBURST_END_F1_SHIFT); - -	vctl5 = (tv_mode->vburst_start_f2 << TV_VBURST_START_F2_SHIFT) | -		(tv_mode->vburst_end_f2 << TV_VBURST_END_F2_SHIFT); - -	vctl6 = (tv_mode->vburst_start_f3 << TV_VBURST_START_F3_SHIFT) | -		(tv_mode->vburst_end_f3 << TV_VBURST_END_F3_SHIFT); - -	vctl7 = (tv_mode->vburst_start_f4 << TV_VBURST_START_F4_SHIFT) | -		(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);  	if (intel_crtc->pipe == 1)  		tv_ctl |= TV_ENC_PIPEB_SELECT; @@ -1044,37 +1091,16 @@ static void intel_tv_mode_set(struct intel_encoder *encoder)  		tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;  	/* Enable two fixes for the chips that need them. */ -	if (dev->pci_device < 0x2772) +	if (IS_I915GM(dev))  		tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX; -	I915_WRITE(TV_H_CTL_1, hctl1); -	I915_WRITE(TV_H_CTL_2, hctl2); -	I915_WRITE(TV_H_CTL_3, hctl3); -	I915_WRITE(TV_V_CTL_1, vctl1); -	I915_WRITE(TV_V_CTL_2, vctl2); -	I915_WRITE(TV_V_CTL_3, vctl3); -	I915_WRITE(TV_V_CTL_4, vctl4); -	I915_WRITE(TV_V_CTL_5, vctl5); -	I915_WRITE(TV_V_CTL_6, vctl6); -	I915_WRITE(TV_V_CTL_7, vctl7); +	set_tv_mode_timings(dev_priv, tv_mode, burst_ena); +  	I915_WRITE(TV_SC_CTL_1, scctl1);  	I915_WRITE(TV_SC_CTL_2, scctl2);  	I915_WRITE(TV_SC_CTL_3, scctl3); -	if (color_conversion) { -		I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) | -			   color_conversion->gy); -		I915_WRITE(TV_CSC_Y2, (color_conversion->by << 16) | -			   color_conversion->ay); -		I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) | -			   color_conversion->gu); -		I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) | -			   color_conversion->au); -		I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) | -			   color_conversion->gv); -		I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) | -			   color_conversion->av); -	} +	set_color_conversion(dev_priv, color_conversion);  	if (INTEL_INFO(dev)->gen >= 4)  		I915_WRITE(TV_CLR_KNOBS, 0x00404000); @@ -1085,46 +1111,25 @@ static void intel_tv_mode_set(struct intel_encoder *encoder)  		I915_WRITE(TV_CLR_LEVEL,  			   ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |  			    (video_levels->blank << TV_BLANK_LEVEL_SHIFT))); -	{ -		int pipeconf_reg = PIPECONF(pipe); -		int dspcntr_reg = DSPCNTR(intel_crtc->plane); -		int pipeconf = I915_READ(pipeconf_reg); -		int dspcntr = I915_READ(dspcntr_reg); -		int xpos = 0x0, ypos = 0x0; -		unsigned int xsize, ysize; -		/* Pipe must be off here */ -		I915_WRITE(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE); -		intel_flush_display_plane(dev_priv, intel_crtc->plane); - -		/* Wait for vblank for the disable to take effect */ -		if (IS_GEN2(dev)) -			intel_wait_for_vblank(dev, intel_crtc->pipe); - -		I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE); -		/* Wait for vblank for the disable to take effect. */ -		intel_wait_for_pipe_off(dev, intel_crtc->pipe); - -		/* Filter ctl must be set before TV_WIN_SIZE */ -		I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); -		xsize = tv_mode->hblank_start - tv_mode->hblank_end; -		if (tv_mode->progressive) -			ysize = tv_mode->nbr_end + 1; -		else -			ysize = 2*tv_mode->nbr_end + 1; - -		xpos += intel_tv->margin[TV_MARGIN_LEFT]; -		ypos += intel_tv->margin[TV_MARGIN_TOP]; -		xsize -= (intel_tv->margin[TV_MARGIN_LEFT] + -			  intel_tv->margin[TV_MARGIN_RIGHT]); -		ysize -= (intel_tv->margin[TV_MARGIN_TOP] + -			  intel_tv->margin[TV_MARGIN_BOTTOM]); -		I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos); -		I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize); - -		I915_WRITE(pipeconf_reg, pipeconf); -		I915_WRITE(dspcntr_reg, dspcntr); -		intel_flush_display_plane(dev_priv, intel_crtc->plane); -	} + +	assert_pipe_disabled(dev_priv, intel_crtc->pipe); + +	/* Filter ctl must be set before TV_WIN_SIZE */ +	I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); +	xsize = tv_mode->hblank_start - tv_mode->hblank_end; +	if (tv_mode->progressive) +		ysize = tv_mode->nbr_end + 1; +	else +		ysize = 2*tv_mode->nbr_end + 1; + +	xpos += intel_tv->margin[TV_MARGIN_LEFT]; +	ypos += intel_tv->margin[TV_MARGIN_TOP]; +	xsize -= (intel_tv->margin[TV_MARGIN_LEFT] + +		  intel_tv->margin[TV_MARGIN_RIGHT]); +	ysize -= (intel_tv->margin[TV_MARGIN_TOP] + +		  intel_tv->margin[TV_MARGIN_BOTTOM]); +	I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos); +	I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize);  	j = 0;  	for (i = 0; i < 60; i++) @@ -1182,8 +1187,8 @@ intel_tv_detect_type(struct intel_tv *intel_tv,  	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); +				      PIPE_HOTPLUG_INTERRUPT_STATUS | +				      PIPE_HOTPLUG_TV_INTERRUPT_STATUS);  		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);  	} @@ -1259,8 +1264,8 @@ intel_tv_detect_type(struct intel_tv *intel_tv,  	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); +				     PIPE_HOTPLUG_INTERRUPT_STATUS | +				     PIPE_HOTPLUG_TV_INTERRUPT_STATUS);  		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);  	} @@ -1309,17 +1314,18 @@ intel_tv_detect(struct drm_connector *connector, bool force)  	int type;  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n", -		      connector->base.id, drm_get_connector_name(connector), +		      connector->base.id, connector->name,  		      force);  	mode = reported_modes[0];  	if (force) {  		struct intel_load_detect_pipe tmp; +		struct drm_modeset_acquire_ctx ctx; -		if (intel_get_load_detect_pipe(connector, &mode, &tmp)) { +		if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {  			type = intel_tv_detect_type(intel_tv, connector); -			intel_release_load_detect_pipe(connector, &tmp); +			intel_release_load_detect_pipe(connector, &tmp, &ctx);  		} else  			return connector_status_unknown;  	} else @@ -1433,7 +1439,6 @@ intel_tv_get_modes(struct drm_connector *connector)  static void  intel_tv_destroy(struct drm_connector *connector)  { -	drm_sysfs_connector_remove(connector);  	drm_connector_cleanup(connector);  	kfree(connector);  } @@ -1518,7 +1523,7 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = {  static int tv_is_present_in_vbt(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; -	struct child_device_config *p_child; +	union child_device_config *p_child;  	int i, ret;  	if (!dev_priv->vbt.child_dev_num) @@ -1530,13 +1535,18 @@ static int tv_is_present_in_vbt(struct drm_device *dev)  		/*  		 * If the device type is not TV, continue.  		 */ -		if (p_child->device_type != DEVICE_TYPE_INT_TV && -			p_child->device_type != DEVICE_TYPE_TV) +		switch (p_child->old.device_type) { +		case DEVICE_TYPE_INT_TV: +		case DEVICE_TYPE_TV: +		case DEVICE_TYPE_TV_SVIDEO_COMPOSITE: +			break; +		default:  			continue; +		}  		/* Only when the addin_offset is non-zero, it is regarded  		 * as present.  		 */ -		if (p_child->addin_offset) { +		if (p_child->old.addin_offset) {  			ret = 1;  			break;  		} @@ -1590,12 +1600,12 @@ intel_tv_init(struct drm_device *dev)  	    (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)  		return; -	intel_tv = kzalloc(sizeof(struct intel_tv), GFP_KERNEL); +	intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL);  	if (!intel_tv) {  		return;  	} -	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); +	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);  	if (!intel_connector) {  		kfree(intel_tv);  		return; @@ -1622,18 +1632,19 @@ intel_tv_init(struct drm_device *dev)  			 DRM_MODE_ENCODER_TVDAC);  	intel_encoder->compute_config = intel_tv_compute_config; -	intel_encoder->mode_set = intel_tv_mode_set; +	intel_encoder->get_config = intel_tv_get_config; +	intel_encoder->pre_enable = intel_tv_pre_enable;  	intel_encoder->enable = intel_enable_tv;  	intel_encoder->disable = intel_disable_tv;  	intel_encoder->get_hw_state = intel_tv_get_hw_state;  	intel_connector->get_hw_state = intel_connector_get_hw_state; +	intel_connector->unregister = intel_connector_unregister;  	intel_connector_attach_encoder(intel_connector, intel_encoder);  	intel_encoder->type = INTEL_OUTPUT_TVOUT;  	intel_encoder->crtc_mask = (1 << 0) | (1 << 1); -	intel_encoder->cloneable = false; +	intel_encoder->cloneable = 0;  	intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1)); -	intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);  	intel_tv->type = DRM_MODE_CONNECTOR_Unknown;  	/* BIOS margin values */  | 
