diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 135 | 
1 files changed, 75 insertions, 60 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 9ba0aaed7ee..2ee9821b9d9 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -36,10 +36,15 @@  #include <drm/i915_drm.h>  #include "i915_drv.h" +static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi) +{ +	return hdmi_to_dig_port(intel_hdmi)->base.base.dev; +} +  static void  assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)  { -	struct drm_device *dev = intel_hdmi->base.base.dev; +	struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi);  	struct drm_i915_private *dev_priv = dev->dev_private;  	uint32_t enabled_bits; @@ -51,13 +56,14 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)  struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)  { -	return container_of(encoder, struct intel_hdmi, base.base); +	struct intel_digital_port *intel_dig_port = +		container_of(encoder, struct intel_digital_port, base.base); +	return &intel_dig_port->hdmi;  }  static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)  { -	return container_of(intel_attached_encoder(connector), -			    struct intel_hdmi, base); +	return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base);  }  void intel_dip_infoframe_csum(struct dip_infoframe *frame) @@ -334,6 +340,8 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)  		avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2; +	avi_if.body.avi.VIC = drm_mode_cea_vic(adjusted_mode); +  	intel_set_infoframe(encoder, &avi_if);  } @@ -754,16 +762,16 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector,  	return MODE_OK;  } -static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, -				  const struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) +bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, +			   const struct drm_display_mode *mode, +			   struct drm_display_mode *adjusted_mode)  {  	return true;  }  static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi)  { -	struct drm_device *dev = intel_hdmi->base.base.dev; +	struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi);  	struct drm_i915_private *dev_priv = dev->dev_private;  	uint32_t bit; @@ -786,6 +794,9 @@ static enum drm_connector_status  intel_hdmi_detect(struct drm_connector *connector, bool force)  {  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); +	struct intel_digital_port *intel_dig_port = +		hdmi_to_dig_port(intel_hdmi); +	struct intel_encoder *intel_encoder = &intel_dig_port->base;  	struct drm_i915_private *dev_priv = connector->dev->dev_private;  	struct edid *edid;  	enum drm_connector_status status = connector_status_disconnected; @@ -814,6 +825,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)  		if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO)  			intel_hdmi->has_audio =  				(intel_hdmi->force_audio == HDMI_AUDIO_ON); +		intel_encoder->type = INTEL_OUTPUT_HDMI;  	}  	return status; @@ -859,10 +871,12 @@ intel_hdmi_set_property(struct drm_connector *connector,  			uint64_t val)  {  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); +	struct intel_digital_port *intel_dig_port = +		hdmi_to_dig_port(intel_hdmi);  	struct drm_i915_private *dev_priv = connector->dev->dev_private;  	int ret; -	ret = drm_connector_property_set_value(connector, property, val); +	ret = drm_object_property_set_value(&connector->base, property, val);  	if (ret)  		return ret; @@ -898,8 +912,8 @@ intel_hdmi_set_property(struct drm_connector *connector,  	return -EINVAL;  done: -	if (intel_hdmi->base.base.crtc) { -		struct drm_crtc *crtc = intel_hdmi->base.base.crtc; +	if (intel_dig_port->base.base.crtc) { +		struct drm_crtc *crtc = intel_dig_port->base.base.crtc;  		intel_set_mode(crtc, &crtc->mode,  			       crtc->x, crtc->y, crtc->fb);  	} @@ -914,12 +928,6 @@ static void intel_hdmi_destroy(struct drm_connector *connector)  	kfree(connector);  } -static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = { -	.mode_fixup = intel_hdmi_mode_fixup, -	.mode_set = intel_ddi_mode_set, -	.disable = intel_encoder_noop, -}; -  static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {  	.mode_fixup = intel_hdmi_mode_fixup,  	.mode_set = intel_hdmi_mode_set, @@ -951,43 +959,24 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c  	intel_attach_broadcast_rgb_property(connector);  } -void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port) +void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, +			       struct intel_connector *intel_connector)  { +	struct drm_connector *connector = &intel_connector->base; +	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; +	struct intel_encoder *intel_encoder = &intel_dig_port->base; +	struct drm_device *dev = intel_encoder->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; -	struct drm_connector *connector; -	struct intel_encoder *intel_encoder; -	struct intel_connector *intel_connector; -	struct intel_hdmi *intel_hdmi; - -	intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); -	if (!intel_hdmi) -		return; - -	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); -	if (!intel_connector) { -		kfree(intel_hdmi); -		return; -	} - -	intel_encoder = &intel_hdmi->base; -	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, -			 DRM_MODE_ENCODER_TMDS); +	enum port port = intel_dig_port->port; -	connector = &intel_connector->base;  	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,  			   DRM_MODE_CONNECTOR_HDMIA);  	drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); -	intel_encoder->type = INTEL_OUTPUT_HDMI; -  	connector->polled = DRM_CONNECTOR_POLL_HPD;  	connector->interlace_allowed = 1;  	connector->doublescan_allowed = 0; -	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); -	intel_encoder->cloneable = false; - -	intel_hdmi->ddi_port = port;  	switch (port) {  	case PORT_B:  		intel_hdmi->ddc_bus = GMBUS_PORT_DPB; @@ -1007,8 +996,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)  		BUG();  	} -	intel_hdmi->sdvox_reg = sdvox_reg; -  	if (!HAS_PCH_SPLIT(dev)) {  		intel_hdmi->write_infoframe = g4x_write_infoframe;  		intel_hdmi->set_infoframes = g4x_set_infoframes; @@ -1026,21 +1013,10 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)  		intel_hdmi->set_infoframes = cpt_set_infoframes;  	} -	if (IS_HASWELL(dev)) { -		intel_encoder->enable = intel_enable_ddi; -		intel_encoder->disable = intel_disable_ddi; -		intel_encoder->get_hw_state = intel_ddi_get_hw_state; -		drm_encoder_helper_add(&intel_encoder->base, -				       &intel_hdmi_helper_funcs_hsw); -	} else { -		intel_encoder->enable = intel_enable_hdmi; -		intel_encoder->disable = intel_disable_hdmi; -		intel_encoder->get_hw_state = intel_hdmi_get_hw_state; -		drm_encoder_helper_add(&intel_encoder->base, -				       &intel_hdmi_helper_funcs); -	} -	intel_connector->get_hw_state = intel_connector_get_hw_state; - +	if (IS_HASWELL(dev)) +		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; +	else +		intel_connector->get_hw_state = intel_connector_get_hw_state;  	intel_hdmi_add_properties(intel_hdmi, connector); @@ -1056,3 +1032,42 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)  		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);  	}  } + +void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port) +{ +	struct intel_digital_port *intel_dig_port; +	struct intel_encoder *intel_encoder; +	struct drm_encoder *encoder; +	struct intel_connector *intel_connector; + +	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); +	if (!intel_dig_port) +		return; + +	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); +	if (!intel_connector) { +		kfree(intel_dig_port); +		return; +	} + +	intel_encoder = &intel_dig_port->base; +	encoder = &intel_encoder->base; + +	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, +			 DRM_MODE_ENCODER_TMDS); +	drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); + +	intel_encoder->enable = intel_enable_hdmi; +	intel_encoder->disable = intel_disable_hdmi; +	intel_encoder->get_hw_state = intel_hdmi_get_hw_state; + +	intel_encoder->type = INTEL_OUTPUT_HDMI; +	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); +	intel_encoder->cloneable = false; + +	intel_dig_port->port = port; +	intel_dig_port->hdmi.sdvox_reg = sdvox_reg; +	intel_dig_port->dp.output_reg = 0; + +	intel_hdmi_init_connector(intel_dig_port, intel_connector); +}  |