diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 818 | 
1 files changed, 541 insertions, 277 deletions
| diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2cc6faa1daa8..d2951096bca0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1022,7 +1022,7 @@ bool intel_crtc_active(struct intel_crtc *crtc)  	 * We can ditch the adjusted_mode.crtc_clock check as soon  	 * as Haswell has gained clock readout/fastboot support.  	 * -	 * We can ditch the crtc->primary->fb check as soon as we can +	 * We can ditch the crtc->primary->state->fb check as soon as we can  	 * properly reconstruct framebuffers.  	 *  	 * FIXME: The intel_crtc->active here should be switched to @@ -1202,7 +1202,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe)  {  	i915_reg_t pp_reg;  	u32 val; -	enum pipe panel_pipe = PIPE_A; +	enum pipe panel_pipe = INVALID_PIPE;  	bool locked = true;  	if (WARN_ON(HAS_DDI(dev_priv))) @@ -1214,18 +1214,35 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe)  		pp_reg = PP_CONTROL(0);  		port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK; -		if (port_sel == PANEL_PORT_SELECT_LVDS && -		    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) -			panel_pipe = PIPE_B; -		/* XXX: else fix for eDP */ +		switch (port_sel) { +		case PANEL_PORT_SELECT_LVDS: +			intel_lvds_port_enabled(dev_priv, PCH_LVDS, &panel_pipe); +			break; +		case PANEL_PORT_SELECT_DPA: +			intel_dp_port_enabled(dev_priv, DP_A, PORT_A, &panel_pipe); +			break; +		case PANEL_PORT_SELECT_DPC: +			intel_dp_port_enabled(dev_priv, PCH_DP_C, PORT_C, &panel_pipe); +			break; +		case PANEL_PORT_SELECT_DPD: +			intel_dp_port_enabled(dev_priv, PCH_DP_D, PORT_D, &panel_pipe); +			break; +		default: +			MISSING_CASE(port_sel); +			break; +		}  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {  		/* presumably write lock depends on pipe, not port select */  		pp_reg = PP_CONTROL(pipe);  		panel_pipe = pipe;  	} else { +		u32 port_sel; +  		pp_reg = PP_CONTROL(0); -		if (I915_READ(LVDS) & LVDS_PIPEB_SELECT) -			panel_pipe = PIPE_B; +		port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK; + +		WARN_ON(port_sel != PANEL_PORT_SELECT_LVDS); +		intel_lvds_port_enabled(dev_priv, LVDS, &panel_pipe);  	}  	val = I915_READ(pp_reg); @@ -1267,7 +1284,10 @@ void assert_pipe(struct drm_i915_private *dev_priv,  static void assert_plane(struct intel_plane *plane, bool state)  { -	bool cur_state = plane->get_hw_state(plane); +	enum pipe pipe; +	bool cur_state; + +	cur_state = plane->get_hw_state(plane, &pipe);  	I915_STATE_WARN(cur_state != state,  			"%s assertion failure (expected %s, current %s)\n", @@ -1305,125 +1325,64 @@ void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,  	     pipe_name(pipe));  } -static bool dp_pipe_enabled(struct drm_i915_private *dev_priv, -			    enum pipe pipe, u32 port_sel, u32 val) -{ -	if ((val & DP_PORT_EN) == 0) -		return false; - -	if (HAS_PCH_CPT(dev_priv)) { -		u32 trans_dp_ctl = I915_READ(TRANS_DP_CTL(pipe)); -		if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel) -			return false; -	} else if (IS_CHERRYVIEW(dev_priv)) { -		if ((val & DP_PIPE_MASK_CHV) != DP_PIPE_SELECT_CHV(pipe)) -			return false; -	} else { -		if ((val & DP_PIPE_MASK) != (pipe << 30)) -			return false; -	} -	return true; -} - -static bool hdmi_pipe_enabled(struct drm_i915_private *dev_priv, -			      enum pipe pipe, u32 val) +static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, +				   enum pipe pipe, enum port port, +				   i915_reg_t dp_reg)  { -	if ((val & SDVO_ENABLE) == 0) -		return false; - -	if (HAS_PCH_CPT(dev_priv)) { -		if ((val & SDVO_PIPE_SEL_MASK_CPT) != SDVO_PIPE_SEL_CPT(pipe)) -			return false; -	} else if (IS_CHERRYVIEW(dev_priv)) { -		if ((val & SDVO_PIPE_SEL_MASK_CHV) != SDVO_PIPE_SEL_CHV(pipe)) -			return false; -	} else { -		if ((val & SDVO_PIPE_SEL_MASK) != SDVO_PIPE_SEL(pipe)) -			return false; -	} -	return true; -} +	enum pipe port_pipe; +	bool state; -static bool lvds_pipe_enabled(struct drm_i915_private *dev_priv, -			      enum pipe pipe, u32 val) -{ -	if ((val & LVDS_PORT_EN) == 0) -		return false; +	state = intel_dp_port_enabled(dev_priv, dp_reg, port, &port_pipe); -	if (HAS_PCH_CPT(dev_priv)) { -		if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe)) -			return false; -	} else { -		if ((val & LVDS_PIPE_MASK) != LVDS_PIPE(pipe)) -			return false; -	} -	return true; -} +	I915_STATE_WARN(state && port_pipe == pipe, +			"PCH DP %c enabled on transcoder %c, should be disabled\n", +			port_name(port), pipe_name(pipe)); -static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv, -			      enum pipe pipe, u32 val) -{ -	if ((val & ADPA_DAC_ENABLE) == 0) -		return false; -	if (HAS_PCH_CPT(dev_priv)) { -		if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe)) -			return false; -	} else { -		if ((val & ADPA_PIPE_SELECT_MASK) != ADPA_PIPE_SELECT(pipe)) -			return false; -	} -	return true; +	I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, +			"IBX PCH DP %c still using transcoder B\n", +			port_name(port));  } -static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, -				   enum pipe pipe, i915_reg_t reg, -				   u32 port_sel) +static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, +				     enum pipe pipe, enum port port, +				     i915_reg_t hdmi_reg)  { -	u32 val = I915_READ(reg); -	I915_STATE_WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), -	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", -	     i915_mmio_reg_offset(reg), pipe_name(pipe)); +	enum pipe port_pipe; +	bool state; -	I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && (val & DP_PORT_EN) == 0 -	     && (val & DP_PIPEB_SELECT), -	     "IBX PCH dp port still using transcoder B\n"); -} +	state = intel_sdvo_port_enabled(dev_priv, hdmi_reg, &port_pipe); -static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, -				     enum pipe pipe, i915_reg_t reg) -{ -	u32 val = I915_READ(reg); -	I915_STATE_WARN(hdmi_pipe_enabled(dev_priv, pipe, val), -	     "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", -	     i915_mmio_reg_offset(reg), pipe_name(pipe)); +	I915_STATE_WARN(state && port_pipe == pipe, +			"PCH HDMI %c enabled on transcoder %c, should be disabled\n", +			port_name(port), pipe_name(pipe)); -	I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && (val & SDVO_ENABLE) == 0 -	     && (val & SDVO_PIPE_B_SELECT), -	     "IBX PCH hdmi port still using transcoder B\n"); +	I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, +			"IBX PCH HDMI %c still using transcoder B\n", +			port_name(port));  }  static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,  				      enum pipe pipe)  { -	u32 val; +	enum pipe port_pipe; -	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B); -	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C); -	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D); +	assert_pch_dp_disabled(dev_priv, pipe, PORT_B, PCH_DP_B); +	assert_pch_dp_disabled(dev_priv, pipe, PORT_C, PCH_DP_C); +	assert_pch_dp_disabled(dev_priv, pipe, PORT_D, PCH_DP_D); -	val = I915_READ(PCH_ADPA); -	I915_STATE_WARN(adpa_pipe_enabled(dev_priv, pipe, val), -	     "PCH VGA enabled on transcoder %c, should be disabled\n", -	     pipe_name(pipe)); +	I915_STATE_WARN(intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) && +			port_pipe == pipe, +			"PCH VGA enabled on transcoder %c, should be disabled\n", +			pipe_name(pipe)); -	val = I915_READ(PCH_LVDS); -	I915_STATE_WARN(lvds_pipe_enabled(dev_priv, pipe, val), -	     "PCH LVDS enabled on transcoder %c, should be disabled\n", -	     pipe_name(pipe)); +	I915_STATE_WARN(intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) && +			port_pipe == pipe, +			"PCH LVDS enabled on transcoder %c, should be disabled\n", +			pipe_name(pipe)); -	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIB); -	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMIC); -	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID); +	assert_pch_hdmi_disabled(dev_priv, pipe, PORT_B, PCH_HDMIB); +	assert_pch_hdmi_disabled(dev_priv, pipe, PORT_C, PCH_HDMIC); +	assert_pch_hdmi_disabled(dev_priv, pipe, PORT_D, PCH_HDMID);  }  static void _vlv_enable_pll(struct intel_crtc *crtc, @@ -2521,6 +2480,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,  {  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);  	struct intel_rotation_info *rot_info = &intel_fb->rot_info; +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);  	u32 gtt_offset_rotated = 0;  	unsigned int max_size = 0;  	int i, num_planes = fb->format->num_planes; @@ -2585,7 +2545,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,  		 * fb layout agrees with the fence layout. We already check that the  		 * fb stride matches the fence stride elsewhere.  		 */ -		if (i == 0 && i915_gem_object_is_tiled(intel_fb->obj) && +		if (i == 0 && i915_gem_object_is_tiled(obj) &&  		    (x + width) * cpp > fb->pitches[i]) {  			DRM_DEBUG_KMS("bad fb plane %d offset: 0x%x\n",  				      i, fb->offsets[i]); @@ -2670,9 +2630,9 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,  		max_size = max(max_size, offset + size);  	} -	if (max_size * tile_size > intel_fb->obj->base.size) { +	if (max_size * tile_size > obj->base.size) {  		DRM_DEBUG_KMS("fb too big for bo (need %u bytes, have %zu bytes)\n", -			      max_size * tile_size, intel_fb->obj->base.size); +			      max_size * tile_size, obj->base.size);  		return -EINVAL;  	} @@ -2796,10 +2756,10 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state,  	/* FIXME pre-g4x don't work like this */  	if (visible) { -		crtc_state->base.plane_mask |= BIT(drm_plane_index(&plane->base)); +		crtc_state->base.plane_mask |= drm_plane_mask(&plane->base);  		crtc_state->active_planes |= BIT(plane->id);  	} else { -		crtc_state->base.plane_mask &= ~BIT(drm_plane_index(&plane->base)); +		crtc_state->base.plane_mask &= ~drm_plane_mask(&plane->base);  		crtc_state->active_planes &= ~BIT(plane->id);  	} @@ -2922,9 +2882,8 @@ valid_fb:  	if (i915_gem_object_is_tiled(obj))  		dev_priv->preserve_bios_swizzle = true; -	drm_framebuffer_get(fb); -	primary->fb = primary->state->fb = fb; -	primary->crtc = primary->state->crtc = &intel_crtc->base; +	plane_state->fb = fb; +	plane_state->crtc = &intel_crtc->base;  	intel_set_plane_visible(to_intel_crtc_state(crtc_state),  				to_intel_plane_state(plane_state), @@ -3029,6 +2988,7 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state,  	int w = drm_rect_width(&plane_state->base.src) >> 16;  	int h = drm_rect_height(&plane_state->base.src) >> 16;  	int dst_x = plane_state->base.dst.x1; +	int dst_w = drm_rect_width(&plane_state->base.dst);  	int pipe_src_w = crtc_state->pipe_src_w;  	int max_width = skl_max_plane_width(fb, 0, rotation);  	int max_height = 4096; @@ -3050,10 +3010,10 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state,  	 * screen may cause FIFO underflow and display corruption.  	 */  	if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && -	    (dst_x + w < 4 || dst_x > pipe_src_w - 4)) { +	    (dst_x + dst_w < 4 || dst_x > pipe_src_w - 4)) {  		DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n", -			      dst_x + w < 4 ? "end" : "start", -			      dst_x + w < 4 ? dst_x + w : dst_x, +			      dst_x + dst_w < 4 ? "end" : "start", +			      dst_x + dst_w < 4 ? dst_x + dst_w : dst_x,  			      4, pipe_src_w - 4);  		return -ERANGE;  	} @@ -3430,24 +3390,33 @@ static void i9xx_disable_plane(struct intel_plane *plane,  	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);  } -static bool i9xx_plane_get_hw_state(struct intel_plane *plane) +static bool i9xx_plane_get_hw_state(struct intel_plane *plane, +				    enum pipe *pipe)  {  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);  	enum intel_display_power_domain power_domain;  	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; -	enum pipe pipe = plane->pipe;  	bool ret; +	u32 val;  	/*  	 * Not 100% correct for planes that can move between pipes,  	 * but that's only the case for gen2-4 which don't have any  	 * display power wells.  	 */ -	power_domain = POWER_DOMAIN_PIPE(pipe); +	power_domain = POWER_DOMAIN_PIPE(plane->pipe);  	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))  		return false; -	ret = I915_READ(DSPCNTR(i9xx_plane)) & DISPLAY_PLANE_ENABLE; +	val = I915_READ(DSPCNTR(i9xx_plane)); + +	ret = val & DISPLAY_PLANE_ENABLE; + +	if (INTEL_GEN(dev_priv) >= 5) +		*pipe = plane->pipe; +	else +		*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> +			DISPPLANE_SEL_PIPE_SHIFT;  	intel_display_power_put(dev_priv, power_domain); @@ -3689,7 +3658,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,  	plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;  	plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format); -	if (intel_format_is_yuv(fb->format->format)) { +	if (fb->format->is_yuv) {  		if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)  			plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;  		else @@ -4631,20 +4600,33 @@ static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)  	}  } -/* Return which DP Port should be selected for Transcoder DP control */ -static enum port -intel_trans_dp_port_sel(struct intel_crtc *crtc) +/* + * Finds the encoder associated with the given CRTC. This can only be + * used when we know that the CRTC isn't feeding multiple encoders! + */ +static struct intel_encoder * +intel_get_crtc_new_encoder(const struct intel_atomic_state *state, +			   const struct intel_crtc_state *crtc_state)  { -	struct drm_device *dev = crtc->base.dev; -	struct intel_encoder *encoder; +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); +	const struct drm_connector_state *connector_state; +	const struct drm_connector *connector; +	struct intel_encoder *encoder = NULL; +	int num_encoders = 0; +	int i; + +	for_each_new_connector_in_state(&state->base, connector, connector_state, i) { +		if (connector_state->crtc != &crtc->base) +			continue; -	for_each_encoder_on_crtc(dev, &crtc->base, encoder) { -		if (encoder->type == INTEL_OUTPUT_DP || -		    encoder->type == INTEL_OUTPUT_EDP) -			return encoder->port; +		encoder = to_intel_encoder(connector_state->best_encoder); +		num_encoders++;  	} -	return -1; +	WARN(num_encoders != 1, "%d encoders for pipe %c\n", +	     num_encoders, pipe_name(crtc->pipe)); + +	return encoder;  }  /* @@ -4655,7 +4637,8 @@ intel_trans_dp_port_sel(struct intel_crtc *crtc)   *   - DP transcoding bits   *   - transcoder   */ -static void ironlake_pch_enable(const struct intel_crtc_state *crtc_state) +static void ironlake_pch_enable(const struct intel_atomic_state *state, +				const struct intel_crtc_state *crtc_state)  {  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);  	struct drm_device *dev = crtc->base.dev; @@ -4714,6 +4697,8 @@ static void ironlake_pch_enable(const struct intel_crtc_state *crtc_state)  			&crtc_state->base.adjusted_mode;  		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;  		i915_reg_t reg = TRANS_DP_CTL(pipe); +		enum port port; +  		temp = I915_READ(reg);  		temp &= ~(TRANS_DP_PORT_SEL_MASK |  			  TRANS_DP_SYNC_MASK | @@ -4726,19 +4711,9 @@ static void ironlake_pch_enable(const struct intel_crtc_state *crtc_state)  		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)  			temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; -		switch (intel_trans_dp_port_sel(crtc)) { -		case PORT_B: -			temp |= TRANS_DP_PORT_SEL_B; -			break; -		case PORT_C: -			temp |= TRANS_DP_PORT_SEL_C; -			break; -		case PORT_D: -			temp |= TRANS_DP_PORT_SEL_D; -			break; -		default: -			BUG(); -		} +		port = intel_get_crtc_new_encoder(state, crtc_state)->port; +		WARN_ON(port < PORT_B || port > PORT_D); +		temp |= TRANS_DP_PORT_SEL(port);  		I915_WRITE(reg, temp);  	} @@ -4746,7 +4721,8 @@ static void ironlake_pch_enable(const struct intel_crtc_state *crtc_state)  	ironlake_enable_pch_transcoder(dev_priv, pipe);  } -static void lpt_pch_enable(const struct intel_crtc_state *crtc_state) +static void lpt_pch_enable(const struct intel_atomic_state *state, +			   const struct intel_crtc_state *crtc_state)  {  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -4776,6 +4752,39 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)  	}  } +/* + * The hardware phase 0.0 refers to the center of the pixel. + * We want to start from the top/left edge which is phase + * -0.5. That matches how the hardware calculates the scaling + * factors (from top-left of the first pixel to bottom-right + * of the last pixel, as opposed to the pixel centers). + * + * For 4:2:0 subsampled chroma planes we obviously have to + * adjust that so that the chroma sample position lands in + * the right spot. + * + * Note that for packed YCbCr 4:2:2 formats there is no way to + * control chroma siting. The hardware simply replicates the + * chroma samples for both of the luma samples, and thus we don't + * actually get the expected MPEG2 chroma siting convention :( + * The same behaviour is observed on pre-SKL platforms as well. + */ +u16 skl_scaler_calc_phase(int sub, bool chroma_cosited) +{ +	int phase = -0x8000; +	u16 trip = 0; + +	if (chroma_cosited) +		phase += (sub - 1) * 0x8000 / sub; + +	if (phase < 0) +		phase = 0x10000 + phase; +	else +		trip = PS_PHASE_TRIP; + +	return ((phase >> 2) & PS_PHASE_MASK) | trip; +} +  static int  skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,  		  unsigned int scaler_user, int *scaler_id, @@ -4975,14 +4984,22 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)  		&crtc->config->scaler_state;  	if (crtc->config->pch_pfit.enabled) { +		u16 uv_rgb_hphase, uv_rgb_vphase;  		int id;  		if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))  			return; +		uv_rgb_hphase = skl_scaler_calc_phase(1, false); +		uv_rgb_vphase = skl_scaler_calc_phase(1, false); +  		id = scaler_state->scaler_id;  		I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |  			PS_FILTER_MEDIUM | scaler_state->scalers[id].mode); +		I915_WRITE_FW(SKL_PS_VPHASE(pipe, id), +			      PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_vphase)); +		I915_WRITE_FW(SKL_PS_HPHASE(pipe, id), +			      PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_hphase));  		I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);  		I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);  	} @@ -5062,10 +5079,14 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state)  		mutex_lock(&dev_priv->pcu_lock);  		WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));  		mutex_unlock(&dev_priv->pcu_lock); -		/* wait for pcode to finish disabling IPS, which may take up to 42ms */ +		/* +		 * Wait for PCODE to finish disabling IPS. The BSpec specified +		 * 42ms timeout value leads to occasional timeouts so use 100ms +		 * instead. +		 */  		if (intel_wait_for_register(dev_priv,  					    IPS_CTL, IPS_ENABLE, 0, -					    42)) +					    100))  			DRM_ERROR("Timed out waiting for IPS disable\n");  	} else {  		I915_WRITE(IPS_CTL, 0); @@ -5501,10 +5522,8 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,  	 *  	 * Spurious PCH underruns also occur during PCH enabling.  	 */ -	if (intel_crtc->config->has_pch_encoder || IS_GEN5(dev_priv)) -		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); -	if (intel_crtc->config->has_pch_encoder) -		intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); +	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); +	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);  	if (intel_crtc->config->has_pch_encoder)  		intel_prepare_shared_dpll(intel_crtc); @@ -5549,7 +5568,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,  	intel_enable_pipe(pipe_config);  	if (intel_crtc->config->has_pch_encoder) -		ironlake_pch_enable(pipe_config); +		ironlake_pch_enable(old_intel_state, pipe_config);  	assert_vblank_disabled(crtc);  	drm_crtc_vblank_on(crtc); @@ -5559,9 +5578,16 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,  	if (HAS_PCH_CPT(dev_priv))  		cpt_verify_modeset(dev, intel_crtc->pipe); -	/* Must wait for vblank to avoid spurious PCH FIFO underruns */ -	if (intel_crtc->config->has_pch_encoder) +	/* +	 * Must wait for vblank to avoid spurious PCH FIFO underruns. +	 * And a second vblank wait is needed at least on ILK with +	 * some interlaced HDMI modes. Let's do the double wait always +	 * in case there are more corner cases we don't know about. +	 */ +	if (intel_crtc->config->has_pch_encoder) {  		intel_wait_for_vblank(dev_priv, pipe); +		intel_wait_for_vblank(dev_priv, pipe); +	}  	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);  	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);  } @@ -5611,6 +5637,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,  	struct intel_atomic_state *old_intel_state =  		to_intel_atomic_state(old_state);  	bool psl_clkgate_wa; +	u32 pipe_chicken;  	if (WARN_ON(intel_crtc->active))  		return; @@ -5623,6 +5650,8 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,  	if (INTEL_GEN(dev_priv) >= 11)  		icl_map_plls_to_ports(crtc, pipe_config, old_state); +	intel_encoders_pre_enable(crtc, pipe_config, old_state); +  	if (intel_crtc_has_dp_encoder(intel_crtc->config))  		intel_dp_set_m_n(intel_crtc, M1_N1); @@ -5651,11 +5680,6 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,  	intel_crtc->active = true; -	intel_encoders_pre_enable(crtc, pipe_config, old_state); - -	if (!transcoder_is_dsi(cpu_transcoder)) -		intel_ddi_enable_pipe_clock(pipe_config); -  	/* Display WA #1180: WaDisableScalarClockGating: glk, cnl */  	psl_clkgate_wa = (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&  			 intel_crtc->config->pch_pfit.enabled; @@ -5673,6 +5697,17 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,  	 */  	intel_color_load_luts(&pipe_config->base); +	/* +	 * Display WA #1153: enable hardware to bypass the alpha math +	 * and rounding for per-pixel values 00 and 0xff +	 */ +	if (INTEL_GEN(dev_priv) >= 11) { +		pipe_chicken = I915_READ(PIPE_CHICKEN(pipe)); +		if (!(pipe_chicken & PER_PIXEL_ALPHA_BYPASS_EN)) +			I915_WRITE_FW(PIPE_CHICKEN(pipe), +				      pipe_chicken | PER_PIXEL_ALPHA_BYPASS_EN); +	} +  	intel_ddi_set_pipe_settings(pipe_config);  	if (!transcoder_is_dsi(cpu_transcoder))  		intel_ddi_enable_transcoder_func(pipe_config); @@ -5688,7 +5723,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,  		intel_enable_pipe(pipe_config);  	if (intel_crtc->config->has_pch_encoder) -		lpt_pch_enable(pipe_config); +		lpt_pch_enable(old_intel_state, pipe_config);  	if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST))  		intel_ddi_set_vc_payload_alloc(pipe_config, true); @@ -5741,10 +5776,8 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state,  	 * pipe is already disabled, but FDI RX/TX is still enabled.  	 * Happens at least with VGA+HDMI cloning. Suppress them.  	 */ -	if (intel_crtc->config->has_pch_encoder) { -		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); -		intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); -	} +	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); +	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);  	intel_encoders_disable(crtc, old_crtc_state, old_state); @@ -5794,7 +5827,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,  	struct drm_crtc *crtc = old_crtc_state->base.crtc;  	struct drm_i915_private *dev_priv = to_i915(crtc->dev);  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; +	enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;  	intel_encoders_disable(crtc, old_crtc_state, old_state); @@ -5805,20 +5838,17 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,  	if (!transcoder_is_dsi(cpu_transcoder))  		intel_disable_pipe(old_crtc_state); -	if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST)) -		intel_ddi_set_vc_payload_alloc(intel_crtc->config, false); +	if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) +		intel_ddi_set_vc_payload_alloc(old_crtc_state, false);  	if (!transcoder_is_dsi(cpu_transcoder)) -		intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder); +		intel_ddi_disable_transcoder_func(old_crtc_state);  	if (INTEL_GEN(dev_priv) >= 9)  		skylake_scaler_disable(intel_crtc);  	else  		ironlake_pfit_disable(intel_crtc, false); -	if (!transcoder_is_dsi(cpu_transcoder)) -		intel_ddi_disable_pipe_clock(intel_crtc->config); -  	intel_encoders_post_disable(crtc, old_crtc_state, old_state);  	if (INTEL_GEN(dev_priv) >= 11) @@ -5849,6 +5879,22 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)  	I915_WRITE(BCLRPAT(crtc->pipe), 0);  } +bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port) +{ +	if (IS_ICELAKE(dev_priv)) +		return port >= PORT_C && port <= PORT_F; + +	return false; +} + +enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port) +{ +	if (!intel_port_is_tc(dev_priv, port)) +		return PORT_TC_NONE; + +	return port - PORT_C; +} +  enum intel_display_power_domain intel_port_to_power_domain(enum port port)  {  	switch (port) { @@ -7675,16 +7721,18 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,  	struct drm_i915_private *dev_priv = to_i915(dev);  	struct intel_plane *plane = to_intel_plane(crtc->base.primary);  	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; -	enum pipe pipe = crtc->pipe; +	enum pipe pipe;  	u32 val, base, offset;  	int fourcc, pixel_format;  	unsigned int aligned_height;  	struct drm_framebuffer *fb;  	struct intel_framebuffer *intel_fb; -	if (!plane->get_hw_state(plane)) +	if (!plane->get_hw_state(plane, &pipe))  		return; +	WARN_ON(pipe != crtc->pipe); +  	intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);  	if (!intel_fb) {  		DRM_DEBUG_KMS("failed to alloc fb\n"); @@ -8705,16 +8753,18 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,  	struct drm_i915_private *dev_priv = to_i915(dev);  	struct intel_plane *plane = to_intel_plane(crtc->base.primary);  	enum plane_id plane_id = plane->id; -	enum pipe pipe = crtc->pipe; +	enum pipe pipe;  	u32 val, base, offset, stride_mult, tiling, alpha;  	int fourcc, pixel_format;  	unsigned int aligned_height;  	struct drm_framebuffer *fb;  	struct intel_framebuffer *intel_fb; -	if (!plane->get_hw_state(plane)) +	if (!plane->get_hw_state(plane, &pipe))  		return; +	WARN_ON(pipe != crtc->pipe); +  	intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);  	if (!intel_fb) {  		DRM_DEBUG_KMS("failed to alloc fb\n"); @@ -9142,9 +9192,12 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)  static int haswell_crtc_compute_clock(struct intel_crtc *crtc,  				      struct intel_crtc_state *crtc_state)  { +	struct intel_atomic_state *state = +		to_intel_atomic_state(crtc_state->base.state); +  	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) {  		struct intel_encoder *encoder = -			intel_ddi_get_crtc_new_encoder(crtc_state); +			intel_get_crtc_new_encoder(state, crtc_state);  		if (!intel_get_shared_dpll(crtc, crtc_state, encoder)) {  			DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", @@ -9172,6 +9225,44 @@ static void cannonlake_get_ddi_pll(struct drm_i915_private *dev_priv,  	pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);  } +static void icelake_get_ddi_pll(struct drm_i915_private *dev_priv, +				enum port port, +				struct intel_crtc_state *pipe_config) +{ +	enum intel_dpll_id id; +	u32 temp; + +	/* TODO: TBT pll not implemented. */ +	switch (port) { +	case PORT_A: +	case PORT_B: +		temp = I915_READ(DPCLKA_CFGCR0_ICL) & +		       DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); +		id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port); + +		if (WARN_ON(id != DPLL_ID_ICL_DPLL0 && id != DPLL_ID_ICL_DPLL1)) +			return; +		break; +	case PORT_C: +		id = DPLL_ID_ICL_MGPLL1; +		break; +	case PORT_D: +		id = DPLL_ID_ICL_MGPLL2; +		break; +	case PORT_E: +		id = DPLL_ID_ICL_MGPLL3; +		break; +	case PORT_F: +		id = DPLL_ID_ICL_MGPLL4; +		break; +	default: +		MISSING_CASE(port); +		return; +	} + +	pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); +} +  static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv,  				enum port port,  				struct intel_crtc_state *pipe_config) @@ -9273,6 +9364,7 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,  		switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {  		default:  			WARN(1, "unknown pipe linked to edp transcoder\n"); +			/* fall through */  		case TRANS_DDI_EDP_INPUT_A_ONOFF:  		case TRANS_DDI_EDP_INPUT_A_ON:  			trans_edp_pipe = PIPE_A; @@ -9328,7 +9420,7 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,  		 * registers/MIPI[BXT]. We can break out here early, since we  		 * need the same DSI PLL to be enabled for both DSI ports.  		 */ -		if (!intel_dsi_pll_is_enabled(dev_priv)) +		if (!bxt_dsi_pll_is_enabled(dev_priv))  			break;  		/* XXX: this works for video mode only */ @@ -9359,7 +9451,9 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,  	port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT; -	if (IS_CANNONLAKE(dev_priv)) +	if (IS_ICELAKE(dev_priv)) +		icelake_get_ddi_pll(dev_priv, port, pipe_config); +	else if (IS_CANNONLAKE(dev_priv))  		cannonlake_get_ddi_pll(dev_priv, port, pipe_config);  	else if (IS_GEN9_BC(dev_priv))  		skylake_get_ddi_pll(dev_priv, port, pipe_config); @@ -9692,7 +9786,8 @@ static void i845_disable_cursor(struct intel_plane *plane,  	i845_update_cursor(plane, NULL, NULL);  } -static bool i845_cursor_get_hw_state(struct intel_plane *plane) +static bool i845_cursor_get_hw_state(struct intel_plane *plane, +				     enum pipe *pipe)  {  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);  	enum intel_display_power_domain power_domain; @@ -9704,6 +9799,8 @@ static bool i845_cursor_get_hw_state(struct intel_plane *plane)  	ret = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE; +	*pipe = PIPE_A; +  	intel_display_power_put(dev_priv, power_domain);  	return ret; @@ -9715,25 +9812,30 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,  	struct drm_i915_private *dev_priv =  		to_i915(plane_state->base.plane->dev);  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); -	u32 cntl; +	u32 cntl = 0; -	cntl = MCURSOR_GAMMA_ENABLE; +	if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) +		cntl |= MCURSOR_TRICKLE_FEED_DISABLE; -	if (HAS_DDI(dev_priv)) -		cntl |= CURSOR_PIPE_CSC_ENABLE; +	if (INTEL_GEN(dev_priv) <= 10) { +		cntl |= MCURSOR_GAMMA_ENABLE; + +		if (HAS_DDI(dev_priv)) +			cntl |= MCURSOR_PIPE_CSC_ENABLE; +	}  	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))  		cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);  	switch (plane_state->base.crtc_w) {  	case 64: -		cntl |= CURSOR_MODE_64_ARGB_AX; +		cntl |= MCURSOR_MODE_64_ARGB_AX;  		break;  	case 128: -		cntl |= CURSOR_MODE_128_ARGB_AX; +		cntl |= MCURSOR_MODE_128_ARGB_AX;  		break;  	case 256: -		cntl |= CURSOR_MODE_256_ARGB_AX; +		cntl |= MCURSOR_MODE_256_ARGB_AX;  		break;  	default:  		MISSING_CASE(plane_state->base.crtc_w); @@ -9741,7 +9843,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,  	}  	if (plane_state->base.rotation & DRM_MODE_ROTATE_180) -		cntl |= CURSOR_ROTATE_180; +		cntl |= MCURSOR_ROTATE_180;  	return cntl;  } @@ -9903,23 +10005,32 @@ static void i9xx_disable_cursor(struct intel_plane *plane,  	i9xx_update_cursor(plane, NULL, NULL);  } -static bool i9xx_cursor_get_hw_state(struct intel_plane *plane) +static bool i9xx_cursor_get_hw_state(struct intel_plane *plane, +				     enum pipe *pipe)  {  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);  	enum intel_display_power_domain power_domain; -	enum pipe pipe = plane->pipe;  	bool ret; +	u32 val;  	/*  	 * Not 100% correct for planes that can move between pipes,  	 * but that's only the case for gen2-3 which don't have any  	 * display power wells.  	 */ -	power_domain = POWER_DOMAIN_PIPE(pipe); +	power_domain = POWER_DOMAIN_PIPE(plane->pipe);  	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))  		return false; -	ret = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; +	val = I915_READ(CURCNTR(plane->pipe)); + +	ret = val & MCURSOR_MODE; + +	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) +		*pipe = plane->pipe; +	else +		*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >> +			MCURSOR_PIPE_SELECT_SHIFT;  	intel_display_power_put(dev_priv, power_domain); @@ -10631,7 +10742,7 @@ static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)  	drm_connector_list_iter_begin(dev, &conn_iter);  	for_each_intel_connector_iter(connector, &conn_iter) {  		if (connector->base.state->crtc) -			drm_connector_unreference(&connector->base); +			drm_connector_put(&connector->base);  		if (connector->base.encoder) {  			connector->base.state->best_encoder = @@ -10639,7 +10750,7 @@ static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)  			connector->base.state->crtc =  				connector->base.encoder->crtc; -			drm_connector_reference(&connector->base); +			drm_connector_get(&connector->base);  		} else {  			connector->base.state->best_encoder = NULL;  			connector->base.state->crtc = NULL; @@ -10918,6 +11029,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)  		case INTEL_OUTPUT_DDI:  			if (WARN_ON(!HAS_DDI(to_i915(dev))))  				break; +			/* else: fall through */  		case INTEL_OUTPUT_DP:  		case INTEL_OUTPUT_HDMI:  		case INTEL_OUTPUT_EDP: @@ -11791,7 +11903,7 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,  			 struct drm_crtc_state *new_state)  {  	struct intel_dpll_hw_state dpll_hw_state; -	unsigned crtc_mask; +	unsigned int crtc_mask;  	bool active;  	memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); @@ -11818,7 +11930,7 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,  		return;  	} -	crtc_mask = 1 << drm_crtc_index(crtc); +	crtc_mask = drm_crtc_mask(crtc);  	if (new_state->active)  		I915_STATE_WARN(!(pll->active_mask & crtc_mask), @@ -11853,7 +11965,7 @@ verify_shared_dpll_state(struct drm_device *dev, struct drm_crtc *crtc,  	if (old_state->shared_dpll &&  	    old_state->shared_dpll != new_state->shared_dpll) { -		unsigned crtc_mask = 1 << drm_crtc_index(crtc); +		unsigned int crtc_mask = drm_crtc_mask(crtc);  		struct intel_shared_dpll *pll = old_state->shared_dpll;  		I915_STATE_WARN(pll->active_mask & crtc_mask, @@ -12449,6 +12561,19 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat  	finish_wait(&dev_priv->gpu_error.wait_queue, &wait_reset);  } +static void intel_atomic_cleanup_work(struct work_struct *work) +{ +	struct drm_atomic_state *state = +		container_of(work, struct drm_atomic_state, commit_work); +	struct drm_i915_private *i915 = to_i915(state->dev); + +	drm_atomic_helper_cleanup_planes(&i915->drm, state); +	drm_atomic_helper_commit_cleanup_done(state); +	drm_atomic_state_put(state); + +	intel_atomic_helper_free_state(i915); +} +  static void intel_atomic_commit_tail(struct drm_atomic_state *state)  {  	struct drm_device *dev = state->dev; @@ -12609,13 +12734,16 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)  		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);  	} -	drm_atomic_helper_cleanup_planes(dev, state); - -	drm_atomic_helper_commit_cleanup_done(state); - -	drm_atomic_state_put(state); - -	intel_atomic_helper_free_state(dev_priv); +	/* +	 * Defer the cleanup of the old state to a separate worker to not +	 * impede the current task (userspace for blocking modesets) that +	 * are executed inline. For out-of-line asynchronous modesets/flips, +	 * deferring to a new worker seems overkill, but we would place a +	 * schedule point (cond_resched()) here anyway to keep latencies +	 * down. +	 */ +	INIT_WORK(&state->commit_work, intel_atomic_cleanup_work); +	schedule_work(&state->commit_work);  }  static void intel_atomic_commit_work(struct work_struct *work) @@ -12981,6 +13109,19 @@ intel_prepare_plane_fb(struct drm_plane *plane,  		add_rps_boost_after_vblank(new_state->crtc, new_state->fence);  	} +	/* +	 * We declare pageflips to be interactive and so merit a small bias +	 * towards upclocking to deliver the frame on time. By only changing +	 * the RPS thresholds to sample more regularly and aim for higher +	 * clocks we can hopefully deliver low power workloads (like kodi) +	 * that are not quite steady state without resorting to forcing +	 * maximum clocks following a vblank miss (see do_rps_boost()). +	 */ +	if (!intel_state->rps_interactive) { +		intel_rps_mark_interactive(dev_priv, true); +		intel_state->rps_interactive = true; +	} +  	return 0;  } @@ -12997,8 +13138,15 @@ void  intel_cleanup_plane_fb(struct drm_plane *plane,  		       struct drm_plane_state *old_state)  { +	struct intel_atomic_state *intel_state = +		to_intel_atomic_state(old_state->state);  	struct drm_i915_private *dev_priv = to_i915(plane->dev); +	if (intel_state->rps_interactive) { +		intel_rps_mark_interactive(dev_priv, false); +		intel_state->rps_interactive = false; +	} +  	/* Should only be called after a successful intel_prepare_plane_fb()! */  	mutex_lock(&dev_priv->drm.struct_mutex);  	intel_plane_unpin_fb(to_intel_plane_state(old_state)); @@ -13181,8 +13329,17 @@ void intel_plane_destroy(struct drm_plane *plane)  	kfree(to_intel_plane(plane));  } -static bool i8xx_mod_supported(uint32_t format, uint64_t modifier) +static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane, +					    u32 format, u64 modifier)  { +	switch (modifier) { +	case DRM_FORMAT_MOD_LINEAR: +	case I915_FORMAT_MOD_X_TILED: +		break; +	default: +		return false; +	} +  	switch (format) {  	case DRM_FORMAT_C8:  	case DRM_FORMAT_RGB565: @@ -13195,8 +13352,17 @@ static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)  	}  } -static bool i965_mod_supported(uint32_t format, uint64_t modifier) +static bool i965_plane_format_mod_supported(struct drm_plane *_plane, +					    u32 format, u64 modifier)  { +	switch (modifier) { +	case DRM_FORMAT_MOD_LINEAR: +	case I915_FORMAT_MOD_X_TILED: +		break; +	default: +		return false; +	} +  	switch (format) {  	case DRM_FORMAT_C8:  	case DRM_FORMAT_RGB565: @@ -13211,8 +13377,26 @@ static bool i965_mod_supported(uint32_t format, uint64_t modifier)  	}  } -static bool skl_mod_supported(uint32_t format, uint64_t modifier) +static bool skl_plane_format_mod_supported(struct drm_plane *_plane, +					   u32 format, u64 modifier)  { +	struct intel_plane *plane = to_intel_plane(_plane); + +	switch (modifier) { +	case DRM_FORMAT_MOD_LINEAR: +	case I915_FORMAT_MOD_X_TILED: +	case I915_FORMAT_MOD_Y_TILED: +	case I915_FORMAT_MOD_Yf_TILED: +		break; +	case I915_FORMAT_MOD_Y_TILED_CCS: +	case I915_FORMAT_MOD_Yf_TILED_CCS: +		if (!plane->has_ccs) +			return false; +		break; +	default: +		return false; +	} +  	switch (format) {  	case DRM_FORMAT_XRGB8888:  	case DRM_FORMAT_XBGR8888: @@ -13244,38 +13428,36 @@ static bool skl_mod_supported(uint32_t format, uint64_t modifier)  	}  } -static bool intel_primary_plane_format_mod_supported(struct drm_plane *plane, -						     uint32_t format, -						     uint64_t modifier) +static bool intel_cursor_format_mod_supported(struct drm_plane *_plane, +					      u32 format, u64 modifier)  { -	struct drm_i915_private *dev_priv = to_i915(plane->dev); - -	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID)) -		return false; - -	if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL && -	    modifier != DRM_FORMAT_MOD_LINEAR) -		return false; - -	if (INTEL_GEN(dev_priv) >= 9) -		return skl_mod_supported(format, modifier); -	else if (INTEL_GEN(dev_priv) >= 4) -		return i965_mod_supported(format, modifier); -	else -		return i8xx_mod_supported(format, modifier); +	return modifier == DRM_FORMAT_MOD_LINEAR && +		format == DRM_FORMAT_ARGB8888;  } -static bool intel_cursor_plane_format_mod_supported(struct drm_plane *plane, -						    uint32_t format, -						    uint64_t modifier) -{ -	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID)) -		return false; +static struct drm_plane_funcs skl_plane_funcs = { +	.update_plane = drm_atomic_helper_update_plane, +	.disable_plane = drm_atomic_helper_disable_plane, +	.destroy = intel_plane_destroy, +	.atomic_get_property = intel_plane_atomic_get_property, +	.atomic_set_property = intel_plane_atomic_set_property, +	.atomic_duplicate_state = intel_plane_duplicate_state, +	.atomic_destroy_state = intel_plane_destroy_state, +	.format_mod_supported = skl_plane_format_mod_supported, +}; -	return modifier == DRM_FORMAT_MOD_LINEAR && format == DRM_FORMAT_ARGB8888; -} +static struct drm_plane_funcs i965_plane_funcs = { +	.update_plane = drm_atomic_helper_update_plane, +	.disable_plane = drm_atomic_helper_disable_plane, +	.destroy = intel_plane_destroy, +	.atomic_get_property = intel_plane_atomic_get_property, +	.atomic_set_property = intel_plane_atomic_set_property, +	.atomic_duplicate_state = intel_plane_duplicate_state, +	.atomic_destroy_state = intel_plane_destroy_state, +	.format_mod_supported = i965_plane_format_mod_supported, +}; -static struct drm_plane_funcs intel_plane_funcs = { +static struct drm_plane_funcs i8xx_plane_funcs = {  	.update_plane = drm_atomic_helper_update_plane,  	.disable_plane = drm_atomic_helper_disable_plane,  	.destroy = intel_plane_destroy, @@ -13283,7 +13465,7 @@ static struct drm_plane_funcs intel_plane_funcs = {  	.atomic_set_property = intel_plane_atomic_set_property,  	.atomic_duplicate_state = intel_plane_duplicate_state,  	.atomic_destroy_state = intel_plane_destroy_state, -	.format_mod_supported = intel_primary_plane_format_mod_supported, +	.format_mod_supported = i8xx_plane_format_mod_supported,  };  static int @@ -13408,7 +13590,7 @@ static const struct drm_plane_funcs intel_cursor_plane_funcs = {  	.atomic_set_property = intel_plane_atomic_set_property,  	.atomic_duplicate_state = intel_plane_duplicate_state,  	.atomic_destroy_state = intel_plane_destroy_state, -	.format_mod_supported = intel_cursor_plane_format_mod_supported, +	.format_mod_supported = intel_cursor_format_mod_supported,  };  static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv, @@ -13466,6 +13648,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)  {  	struct intel_plane *primary = NULL;  	struct intel_plane_state *state = NULL; +	const struct drm_plane_funcs *plane_funcs;  	const uint32_t *intel_primary_formats;  	unsigned int supported_rotations;  	unsigned int num_formats; @@ -13521,6 +13704,9 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)  	primary->check_plane = intel_check_primary_plane;  	if (INTEL_GEN(dev_priv) >= 9) { +		primary->has_ccs = skl_plane_has_ccs(dev_priv, pipe, +						     PLANE_PRIMARY); +  		if (skl_plane_has_planar(dev_priv, pipe, PLANE_PRIMARY)) {  			intel_primary_formats = skl_pri_planar_formats;  			num_formats = ARRAY_SIZE(skl_pri_planar_formats); @@ -13529,7 +13715,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)  			num_formats = ARRAY_SIZE(skl_primary_formats);  		} -		if (skl_plane_has_ccs(dev_priv, pipe, PLANE_PRIMARY)) +		if (primary->has_ccs)  			modifiers = skl_format_modifiers_ccs;  		else  			modifiers = skl_format_modifiers_noccs; @@ -13537,6 +13723,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)  		primary->update_plane = skl_update_plane;  		primary->disable_plane = skl_disable_plane;  		primary->get_hw_state = skl_plane_get_hw_state; + +		plane_funcs = &skl_plane_funcs;  	} else if (INTEL_GEN(dev_priv) >= 4) {  		intel_primary_formats = i965_primary_formats;  		num_formats = ARRAY_SIZE(i965_primary_formats); @@ -13545,6 +13733,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)  		primary->update_plane = i9xx_update_plane;  		primary->disable_plane = i9xx_disable_plane;  		primary->get_hw_state = i9xx_plane_get_hw_state; + +		plane_funcs = &i965_plane_funcs;  	} else {  		intel_primary_formats = i8xx_primary_formats;  		num_formats = ARRAY_SIZE(i8xx_primary_formats); @@ -13553,25 +13743,27 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)  		primary->update_plane = i9xx_update_plane;  		primary->disable_plane = i9xx_disable_plane;  		primary->get_hw_state = i9xx_plane_get_hw_state; + +		plane_funcs = &i8xx_plane_funcs;  	}  	if (INTEL_GEN(dev_priv) >= 9)  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base, -					       0, &intel_plane_funcs, +					       0, plane_funcs,  					       intel_primary_formats, num_formats,  					       modifiers,  					       DRM_PLANE_TYPE_PRIMARY,  					       "plane 1%c", pipe_name(pipe));  	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base, -					       0, &intel_plane_funcs, +					       0, plane_funcs,  					       intel_primary_formats, num_formats,  					       modifiers,  					       DRM_PLANE_TYPE_PRIMARY,  					       "primary %c", pipe_name(pipe));  	else  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base, -					       0, &intel_plane_funcs, +					       0, plane_funcs,  					       intel_primary_formats, num_formats,  					       modifiers,  					       DRM_PLANE_TYPE_PRIMARY, @@ -13951,7 +14143,14 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)  	if (intel_crt_present(dev_priv))  		intel_crt_init(dev_priv); -	if (IS_GEN9_LP(dev_priv)) { +	if (IS_ICELAKE(dev_priv)) { +		intel_ddi_init(dev_priv, PORT_A); +		intel_ddi_init(dev_priv, PORT_B); +		intel_ddi_init(dev_priv, PORT_C); +		intel_ddi_init(dev_priv, PORT_D); +		intel_ddi_init(dev_priv, PORT_E); +		intel_ddi_init(dev_priv, PORT_F); +	} else if (IS_GEN9_LP(dev_priv)) {  		/*  		 * FIXME: Broxton doesn't support port detection via the  		 * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to @@ -13961,7 +14160,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)  		intel_ddi_init(dev_priv, PORT_B);  		intel_ddi_init(dev_priv, PORT_C); -		intel_dsi_init(dev_priv); +		vlv_dsi_init(dev_priv);  	} else if (HAS_DDI(dev_priv)) {  		int found; @@ -14067,7 +14266,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)  				intel_hdmi_init(dev_priv, CHV_HDMID, PORT_D);  		} -		intel_dsi_init(dev_priv); +		vlv_dsi_init(dev_priv);  	} else if (!IS_GEN2(dev_priv) && !IS_PINEVIEW(dev_priv)) {  		bool found = false; @@ -14124,14 +14323,15 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)  static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)  {  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);  	drm_framebuffer_cleanup(fb); -	i915_gem_object_lock(intel_fb->obj); -	WARN_ON(!intel_fb->obj->framebuffer_references--); -	i915_gem_object_unlock(intel_fb->obj); +	i915_gem_object_lock(obj); +	WARN_ON(!obj->framebuffer_references--); +	i915_gem_object_unlock(obj); -	i915_gem_object_put(intel_fb->obj); +	i915_gem_object_put(obj);  	kfree(intel_fb);  } @@ -14140,8 +14340,7 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,  						struct drm_file *file,  						unsigned int *handle)  { -	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); -	struct drm_i915_gem_object *obj = intel_fb->obj; +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);  	if (obj->userptr.mm) {  		DRM_DEBUG("attempting to use a userptr for a framebuffer, denied\n"); @@ -14349,11 +14548,6 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  		}  		break;  	case DRM_FORMAT_NV12: -		if (mode_cmd->modifier[0] == I915_FORMAT_MOD_Y_TILED_CCS || -		    mode_cmd->modifier[0] == I915_FORMAT_MOD_Yf_TILED_CCS) { -			DRM_DEBUG_KMS("RC not to be enabled with NV12\n"); -			goto err; -		}  		if (INTEL_GEN(dev_priv) < 9 || IS_SKYLAKE(dev_priv) ||  		    IS_BROXTON(dev_priv)) {  			DRM_DEBUG_KMS("unsupported pixel format: %s\n", @@ -14411,9 +14605,9 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  				      i, fb->pitches[i], stride_alignment);  			goto err;  		} -	} -	intel_fb->obj = obj; +		fb->obj[i] = &obj->base; +	}  	ret = intel_fill_fb_info(dev_priv, fb);  	if (ret) @@ -14469,6 +14663,10 @@ static enum drm_mode_status  intel_mode_valid(struct drm_device *dev,  		 const struct drm_display_mode *mode)  { +	struct drm_i915_private *dev_priv = to_i915(dev); +	int hdisplay_max, htotal_max; +	int vdisplay_max, vtotal_max; +  	/*  	 * Can't reject DBLSCAN here because Xorg ddxen can add piles  	 * of DBLSCAN modes to the output's mode list when they detect @@ -14498,6 +14696,36 @@ intel_mode_valid(struct drm_device *dev,  			   DRM_MODE_FLAG_CLKDIV2))  		return MODE_BAD; +	if (INTEL_GEN(dev_priv) >= 9 || +	    IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) { +		hdisplay_max = 8192; /* FDI max 4096 handled elsewhere */ +		vdisplay_max = 4096; +		htotal_max = 8192; +		vtotal_max = 8192; +	} else if (INTEL_GEN(dev_priv) >= 3) { +		hdisplay_max = 4096; +		vdisplay_max = 4096; +		htotal_max = 8192; +		vtotal_max = 8192; +	} else { +		hdisplay_max = 2048; +		vdisplay_max = 2048; +		htotal_max = 4096; +		vtotal_max = 4096; +	} + +	if (mode->hdisplay > hdisplay_max || +	    mode->hsync_start > htotal_max || +	    mode->hsync_end > htotal_max || +	    mode->htotal > htotal_max) +		return MODE_H_ILLEGAL; + +	if (mode->vdisplay > vdisplay_max || +	    mode->vsync_start > vtotal_max || +	    mode->vsync_end > vtotal_max || +	    mode->vtotal > vtotal_max) +		return MODE_V_ILLEGAL; +  	return MODE_OK;  } @@ -14646,6 +14874,18 @@ static void quirk_increase_t12_delay(struct drm_device *dev)  	DRM_INFO("Applying T12 delay quirk\n");  } +/* + * GeminiLake NUC HDMI outputs require additional off time + * this allows the onboard retimer to correctly sync to signal + */ +static void quirk_increase_ddi_disabled_time(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = to_i915(dev); + +	dev_priv->quirks |= QUIRK_INCREASE_DDI_DISABLED_TIME; +	DRM_INFO("Applying Increase DDI Disabled quirk\n"); +} +  struct intel_quirk {  	int device;  	int subsystem_vendor; @@ -14732,6 +14972,13 @@ static struct intel_quirk intel_quirks[] = {  	/* Toshiba Satellite P50-C-18C */  	{ 0x191B, 0x1179, 0xF840, quirk_increase_t12_delay }, + +	/* GeminiLake NUC */ +	{ 0x3185, 0x8086, 0x2072, quirk_increase_ddi_disabled_time }, +	{ 0x3184, 0x8086, 0x2072, quirk_increase_ddi_disabled_time }, +	/* ASRock ITX*/ +	{ 0x3185, 0x1849, 0x2212, quirk_increase_ddi_disabled_time }, +	{ 0x3184, 0x1849, 0x2212, quirk_increase_ddi_disabled_time },  };  static void intel_init_quirks(struct drm_device *dev) @@ -14936,6 +15183,7 @@ int intel_modeset_init(struct drm_device *dev)  		}  	} +	/* maximum framebuffer dimensions */  	if (IS_GEN2(dev_priv)) {  		dev->mode_config.max_width = 2048;  		dev->mode_config.max_height = 2048; @@ -14951,11 +15199,11 @@ int intel_modeset_init(struct drm_device *dev)  		dev->mode_config.cursor_width = IS_I845G(dev_priv) ? 64 : 512;  		dev->mode_config.cursor_height = 1023;  	} else if (IS_GEN2(dev_priv)) { -		dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH; -		dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT; +		dev->mode_config.cursor_width = 64; +		dev->mode_config.cursor_height = 64;  	} else { -		dev->mode_config.cursor_width = MAX_CURSOR_WIDTH; -		dev->mode_config.cursor_height = MAX_CURSOR_HEIGHT; +		dev->mode_config.cursor_width = 256; +		dev->mode_config.cursor_height = 256;  	}  	dev->mode_config.fb_base = ggtt->gmadr.start; @@ -15105,8 +15353,8 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)  	WARN_ON(I915_READ(DSPCNTR(PLANE_A)) & DISPLAY_PLANE_ENABLE);  	WARN_ON(I915_READ(DSPCNTR(PLANE_B)) & DISPLAY_PLANE_ENABLE);  	WARN_ON(I915_READ(DSPCNTR(PLANE_C)) & DISPLAY_PLANE_ENABLE); -	WARN_ON(I915_READ(CURCNTR(PIPE_A)) & CURSOR_MODE); -	WARN_ON(I915_READ(CURCNTR(PIPE_B)) & CURSOR_MODE); +	WARN_ON(I915_READ(CURCNTR(PIPE_A)) & MCURSOR_MODE); +	WARN_ON(I915_READ(CURCNTR(PIPE_B)) & MCURSOR_MODE);  	I915_WRITE(PIPECONF(pipe), 0);  	POSTING_READ(PIPECONF(pipe)); @@ -15120,12 +15368,12 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)  static bool intel_plane_mapping_ok(struct intel_crtc *crtc,  				   struct intel_plane *plane)  { -	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); -	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; -	u32 val = I915_READ(DSPCNTR(i9xx_plane)); +	enum pipe pipe; -	return (val & DISPLAY_PLANE_ENABLE) == 0 || -		(val & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE(crtc->pipe); +	if (!plane->get_hw_state(plane, &pipe)) +		return true; + +	return pipe == crtc->pipe;  }  static void @@ -15284,6 +15532,9 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)  		connector->base.dpms = DRM_MODE_DPMS_OFF;  		connector->base.encoder = NULL;  	} + +	/* notify opregion of the sanitized encoder state */ +	intel_opregion_notify_encoder(encoder, connector && has_active_crtc);  }  void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv) @@ -15324,7 +15575,10 @@ static void readout_plane_state(struct intel_crtc *crtc)  	for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {  		struct intel_plane_state *plane_state =  			to_intel_plane_state(plane->base.state); -		bool visible = plane->get_hw_state(plane); +		enum pipe pipe; +		bool visible; + +		visible = plane->get_hw_state(plane, &pipe);  		intel_set_plane_visible(crtc_state, plane_state, visible);  	} @@ -15423,9 +15677,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)  				 * rely on the connector_mask being accurate.  				 */  				encoder->base.crtc->state->connector_mask |= -					1 << drm_connector_index(&connector->base); +					drm_connector_mask(&connector->base);  				encoder->base.crtc->state->encoder_mask |= -					1 << drm_encoder_index(&encoder->base); +					drm_encoder_mask(&encoder->base);  			}  		} else { @@ -15491,11 +15745,20 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)  	for_each_intel_encoder(&dev_priv->drm, encoder) {  		u64 get_domains;  		enum intel_display_power_domain domain; +		struct intel_crtc_state *crtc_state;  		if (!encoder->get_power_domains)  			continue; -		get_domains = encoder->get_power_domains(encoder); +		/* +		 * MST-primary and inactive encoders don't have a crtc state +		 * and neither of these require any power domain references. +		 */ +		if (!encoder->base.crtc) +			continue; + +		crtc_state = to_intel_crtc_state(encoder->base.crtc->state); +		get_domains = encoder->get_power_domains(encoder, crtc_state);  		for_each_power_domain(domain, get_domains)  			intel_display_power_get(dev_priv, domain);  	} @@ -15671,6 +15934,8 @@ void intel_modeset_cleanup(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = to_i915(dev); +	flush_workqueue(dev_priv->modeset_wq); +  	flush_work(&dev_priv->atomic_helper.free_work);  	WARN_ON(!llist_empty(&dev_priv->atomic_helper.free_list)); @@ -15714,8 +15979,7 @@ void intel_connector_attach_encoder(struct intel_connector *connector,  				    struct intel_encoder *encoder)  {  	connector->encoder = encoder; -	drm_mode_connector_attach_encoder(&connector->base, -					  &encoder->base); +	drm_connector_attach_encoder(&connector->base, &encoder->base);  }  /* |