Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20325e8a authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2018-11-15' of...

Merge tag 'drm-intel-fixes-2018-11-15' of git://anongit.freedesktop.org/drm/drm-intel

 into drm-fixes

- Fix Bugzilla #108712: Fix incorrect EU count report from kernel
- Fix to account for scale factor when calculating initial phase on scaled output
- Avoid too trigger-happy HPD storm detection and fix a race and an OOPS for MST systems.
- Relocation race fix for Gen4/5
- A couple ICL fixes and dependencies for above Fixes:.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181115164709.GA13430@jlahtine-desk.ger.corp.intel.com
parents 9826b113 6e8adf6f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -474,7 +474,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)
			u8 eu_disabled_mask;
			u32 n_disabled;

			if (!(sseu->subslice_mask[ss] & BIT(ss)))
			if (!(sseu->subslice_mask[s] & BIT(ss)))
				/* skip disabled subslice */
				continue;

+42 −3
Original line number Diff line number Diff line
@@ -4850,8 +4850,31 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)
 * 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.
 *
 * Theory behind the formula (note that we ignore sub-pixel
 * source coordinates):
 * s = source sample position
 * d = destination sample position
 *
 * Downscaling 4:1:
 * -0.5
 * | 0.0
 * | |     1.5 (initial phase)
 * | |     |
 * v v     v
 * | s | s | s | s |
 * |       d       |
 *
 * Upscaling 1:4:
 * -0.5
 * | -0.375 (initial phase)
 * | |     0.0
 * | |     |
 * v v     v
 * |       s       |
 * | d | d | d | d |
 */
u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)
u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited)
{
	int phase = -0x8000;
	u16 trip = 0;
@@ -4859,6 +4882,15 @@ u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)
	if (chroma_cosited)
		phase += (sub - 1) * 0x8000 / sub;

	phase += scale / (2 * sub);

	/*
	 * Hardware initial phase limited to [-0.5:1.5].
	 * Since the max hardware scale factor is 3.0, we
	 * should never actually excdeed 1.0 here.
	 */
	WARN_ON(phase < -0x8000 || phase > 0x18000);

	if (phase < 0)
		phase = 0x10000 + phase;
	else
@@ -5067,13 +5099,20 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)

	if (crtc->config->pch_pfit.enabled) {
		u16 uv_rgb_hphase, uv_rgb_vphase;
		int pfit_w, pfit_h, hscale, vscale;
		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);
		pfit_w = (crtc->config->pch_pfit.size >> 16) & 0xFFFF;
		pfit_h = crtc->config->pch_pfit.size & 0xFFFF;

		hscale = (crtc->config->pipe_src_w << 16) / pfit_w;
		vscale = (crtc->config->pipe_src_h << 16) / pfit_h;

		uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);

		id = scaler_state->scaler_id;
		I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
+4 −4
Original line number Diff line number Diff line
@@ -452,6 +452,10 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
	if (!intel_connector)
		return NULL;

	intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
	intel_connector->mst_port = intel_dp;
	intel_connector->port = port;

	connector = &intel_connector->base;
	ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,
				 DRM_MODE_CONNECTOR_DisplayPort);
@@ -462,10 +466,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo

	drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs);

	intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
	intel_connector->mst_port = intel_dp;
	intel_connector->port = port;

	for_each_pipe(dev_priv, pipe) {
		struct drm_encoder *enc =
			&intel_dp->mst_encoders[pipe]->base.base;
+1 −1
Original line number Diff line number Diff line
@@ -1646,7 +1646,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
				  struct intel_crtc_state *crtc_state);

u16 skl_scaler_calc_phase(int sub, bool chroma_center);
u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(const struct intel_crtc_state *crtc_state,
		  u32 pixel_format);
+50 −20
Original line number Diff line number Diff line
@@ -228,7 +228,9 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
		drm_for_each_connector_iter(connector, &conn_iter) {
			struct intel_connector *intel_connector = to_intel_connector(connector);

			if (intel_connector->encoder->hpd_pin == pin) {
			/* Don't check MST ports, they don't have pins */
			if (!intel_connector->mst_port &&
			    intel_connector->encoder->hpd_pin == pin) {
				if (connector->polled != intel_connector->polled)
					DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
							 connector->name);
@@ -395,38 +397,55 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
	struct intel_encoder *encoder;
	bool storm_detected = false;
	bool queue_dig = false, queue_hp = false;
	u32 long_hpd_pulse_mask = 0;
	u32 short_hpd_pulse_mask = 0;
	enum hpd_pin pin;

	if (!pin_mask)
		return;

	spin_lock(&dev_priv->irq_lock);

	/*
	 * Determine whether ->hpd_pulse() exists for each pin, and
	 * whether we have a short or a long pulse. This is needed
	 * as each pin may have up to two encoders (HDMI and DP) and
	 * only the one of them (DP) will have ->hpd_pulse().
	 */
	for_each_intel_encoder(&dev_priv->drm, encoder) {
		enum hpd_pin pin = encoder->hpd_pin;
		bool has_hpd_pulse = intel_encoder_has_hpd_pulse(encoder);
		enum port port = encoder->port;
		bool long_hpd;

		pin = encoder->hpd_pin;
		if (!(BIT(pin) & pin_mask))
			continue;

		if (has_hpd_pulse) {
			bool long_hpd = long_mask & BIT(pin);
			enum port port = encoder->port;
		if (!has_hpd_pulse)
			continue;

		long_hpd = long_mask & BIT(pin);

		DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port),
				 long_hpd ? "long" : "short");
			/*
			 * For long HPD pulses we want to have the digital queue happen,
			 * but we still want HPD storm detection to function.
			 */
		queue_dig = true;

		if (long_hpd) {
				dev_priv->hotplug.long_port_mask |= (1 << port);
			long_hpd_pulse_mask |= BIT(pin);
			dev_priv->hotplug.long_port_mask |= BIT(port);
		} else {
				/* for short HPD just trigger the digital queue */
				dev_priv->hotplug.short_port_mask |= (1 << port);
				continue;
			short_hpd_pulse_mask |= BIT(pin);
			dev_priv->hotplug.short_port_mask |= BIT(port);
		}
	}

	/* Now process each pin just once */
	for_each_hpd_pin(pin) {
		bool long_hpd;

		if (!(BIT(pin) & pin_mask))
			continue;

		if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) {
			/*
			 * On GMCH platforms the interrupt mask bits only
@@ -442,11 +461,22 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
		if (dev_priv->hotplug.stats[pin].state != HPD_ENABLED)
			continue;

		if (!has_hpd_pulse) {
		/*
		 * Delegate to ->hpd_pulse() if one of the encoders for this
		 * pin has it, otherwise let the hotplug_work deal with this
		 * pin directly.
		 */
		if (((short_hpd_pulse_mask | long_hpd_pulse_mask) & BIT(pin))) {
			long_hpd = long_hpd_pulse_mask & BIT(pin);
		} else {
			dev_priv->hotplug.event_bits |= BIT(pin);
			long_hpd = true;
			queue_hp = true;
		}

		if (!long_hpd)
			continue;

		if (intel_hpd_irq_storm_detect(dev_priv, pin)) {
			dev_priv->hotplug.event_bits &= ~BIT(pin);
			storm_detected = true;
Loading