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

Commit 20a984c2 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2014-08-21' of git://anongit.freedesktop.org/drm-intel

Display fixes from Ville and Imre, all cc: stable.

* tag 'drm-intel-fixes-2014-08-21' of git://anongit.freedesktop.org/drm-intel:
  drm/i915: don't try to retrain a DP link on an inactive CRTC
  drm/i915: make sure VDD is turned off during system suspend
  drm/i915: cancel hotplug and dig_port work during suspend and unload
  drm/i915: fix HPD IRQ reenable work cancelation
  drm/i915: take display port power domain in DP HPD handler
  drm/i915: Don't try to enable cursor from setplane when crtc is disabled
  drm/i915: Skip load detect when intel_crtc->new_enable==true
  drm/i915: Fix locking for intel_enable_pipe_a()
parents c3735aeb 1a125d8a
Loading
Loading
Loading
Loading
+33 −0
Original line number Original line Diff line number Diff line
@@ -494,6 +494,36 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
	return true;
	return true;
}
}


void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
{
	spin_lock_irq(&dev_priv->irq_lock);

	dev_priv->long_hpd_port_mask = 0;
	dev_priv->short_hpd_port_mask = 0;
	dev_priv->hpd_event_bits = 0;

	spin_unlock_irq(&dev_priv->irq_lock);

	cancel_work_sync(&dev_priv->dig_port_work);
	cancel_work_sync(&dev_priv->hotplug_work);
	cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
}

static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
{
	struct drm_device *dev = dev_priv->dev;
	struct drm_encoder *encoder;

	drm_modeset_lock_all(dev);
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		struct intel_encoder *intel_encoder = to_intel_encoder(encoder);

		if (intel_encoder->suspend)
			intel_encoder->suspend(intel_encoder);
	}
	drm_modeset_unlock_all(dev);
}

static int i915_drm_freeze(struct drm_device *dev)
static int i915_drm_freeze(struct drm_device *dev)
{
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -538,6 +568,9 @@ static int i915_drm_freeze(struct drm_device *dev)
		flush_delayed_work(&dev_priv->rps.delayed_resume_work);
		flush_delayed_work(&dev_priv->rps.delayed_resume_work);


		intel_runtime_pm_disable_interrupts(dev);
		intel_runtime_pm_disable_interrupts(dev);
		intel_hpd_cancel_work(dev_priv);

		intel_suspend_encoders(dev_priv);


		intel_suspend_gt_powersave(dev);
		intel_suspend_gt_powersave(dev);


+2 −1
Original line number Original line Diff line number Diff line
@@ -1458,7 +1458,7 @@ struct drm_i915_private {
		} hpd_mark;
		} hpd_mark;
	} hpd_stats[HPD_NUM_PINS];
	} hpd_stats[HPD_NUM_PINS];
	u32 hpd_event_bits;
	u32 hpd_event_bits;
	struct timer_list hotplug_reenable_timer;
	struct delayed_work hotplug_reenable_work;


	struct i915_fbc fbc;
	struct i915_fbc fbc;
	struct i915_drrs drrs;
	struct i915_drrs drrs;
@@ -2178,6 +2178,7 @@ extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);


extern void intel_console_resume(struct work_struct *work);
extern void intel_console_resume(struct work_struct *work);


+12 −21
Original line number Original line Diff line number Diff line
@@ -1189,8 +1189,8 @@ static void i915_hotplug_work_func(struct work_struct *work)
	  * some connectors */
	  * some connectors */
	if (hpd_disabled) {
	if (hpd_disabled) {
		drm_kms_helper_poll_enable(dev);
		drm_kms_helper_poll_enable(dev);
		mod_timer(&dev_priv->hotplug_reenable_timer,
		mod_delayed_work(system_wq, &dev_priv->hotplug_reenable_work,
			  jiffies + msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
				 msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
	}
	}


	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@@ -1213,11 +1213,6 @@ static void i915_hotplug_work_func(struct work_struct *work)
		drm_kms_helper_hotplug_event(dev);
		drm_kms_helper_hotplug_event(dev);
}
}


static void intel_hpd_irq_uninstall(struct drm_i915_private *dev_priv)
{
	del_timer_sync(&dev_priv->hotplug_reenable_timer);
}

static void ironlake_rps_change_irq_handler(struct drm_device *dev)
static void ironlake_rps_change_irq_handler(struct drm_device *dev)
{
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3892,8 +3887,6 @@ static void gen8_irq_uninstall(struct drm_device *dev)
	if (!dev_priv)
	if (!dev_priv)
		return;
		return;


	intel_hpd_irq_uninstall(dev_priv);

	gen8_irq_reset(dev);
	gen8_irq_reset(dev);
}
}


@@ -3908,8 +3901,6 @@ static void valleyview_irq_uninstall(struct drm_device *dev)


	I915_WRITE(VLV_MASTER_IER, 0);
	I915_WRITE(VLV_MASTER_IER, 0);


	intel_hpd_irq_uninstall(dev_priv);

	for_each_pipe(pipe)
	for_each_pipe(pipe)
		I915_WRITE(PIPESTAT(pipe), 0xffff);
		I915_WRITE(PIPESTAT(pipe), 0xffff);


@@ -3988,8 +3979,6 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
	if (!dev_priv)
	if (!dev_priv)
		return;
		return;


	intel_hpd_irq_uninstall(dev_priv);

	ironlake_irq_reset(dev);
	ironlake_irq_reset(dev);
}
}


@@ -4360,8 +4349,6 @@ static void i915_irq_uninstall(struct drm_device * dev)
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_private *dev_priv = dev->dev_private;
	int pipe;
	int pipe;


	intel_hpd_irq_uninstall(dev_priv);

	if (I915_HAS_HOTPLUG(dev)) {
	if (I915_HAS_HOTPLUG(dev)) {
		I915_WRITE(PORT_HOTPLUG_EN, 0);
		I915_WRITE(PORT_HOTPLUG_EN, 0);
		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
@@ -4598,8 +4585,6 @@ static void i965_irq_uninstall(struct drm_device * dev)
	if (!dev_priv)
	if (!dev_priv)
		return;
		return;


	intel_hpd_irq_uninstall(dev_priv);

	I915_WRITE(PORT_HOTPLUG_EN, 0);
	I915_WRITE(PORT_HOTPLUG_EN, 0);
	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));


@@ -4615,14 +4600,18 @@ static void i965_irq_uninstall(struct drm_device * dev)
	I915_WRITE(IIR, I915_READ(IIR));
	I915_WRITE(IIR, I915_READ(IIR));
}
}


static void intel_hpd_irq_reenable(unsigned long data)
static void intel_hpd_irq_reenable(struct work_struct *work)
{
{
	struct drm_i915_private *dev_priv = (struct drm_i915_private *)data;
	struct drm_i915_private *dev_priv =
		container_of(work, typeof(*dev_priv),
			     hotplug_reenable_work.work);
	struct drm_device *dev = dev_priv->dev;
	struct drm_device *dev = dev_priv->dev;
	struct drm_mode_config *mode_config = &dev->mode_config;
	struct drm_mode_config *mode_config = &dev->mode_config;
	unsigned long irqflags;
	unsigned long irqflags;
	int i;
	int i;


	intel_runtime_pm_get(dev_priv);

	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
	for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) {
	for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) {
		struct drm_connector *connector;
		struct drm_connector *connector;
@@ -4648,6 +4637,8 @@ static void intel_hpd_irq_reenable(unsigned long data)
	if (dev_priv->display.hpd_irq_setup)
	if (dev_priv->display.hpd_irq_setup)
		dev_priv->display.hpd_irq_setup(dev);
		dev_priv->display.hpd_irq_setup(dev);
	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);

	intel_runtime_pm_put(dev_priv);
}
}


void intel_irq_init(struct drm_device *dev)
void intel_irq_init(struct drm_device *dev)
@@ -4670,8 +4661,8 @@ void intel_irq_init(struct drm_device *dev)
	setup_timer(&dev_priv->gpu_error.hangcheck_timer,
	setup_timer(&dev_priv->gpu_error.hangcheck_timer,
		    i915_hangcheck_elapsed,
		    i915_hangcheck_elapsed,
		    (unsigned long) dev);
		    (unsigned long) dev);
	setup_timer(&dev_priv->hotplug_reenable_timer, intel_hpd_irq_reenable,
	INIT_DELAYED_WORK(&dev_priv->hotplug_reenable_work,
		    (unsigned long) dev_priv);
			  intel_hpd_irq_reenable);


	pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
	pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);


+6 −1
Original line number Original line Diff line number Diff line
@@ -699,16 +699,21 @@ intel_crt_detect(struct drm_connector *connector, bool force)
		goto out;
		goto out;
	}
	}


	drm_modeset_acquire_init(&ctx, 0);

	/* for pre-945g platforms use load detect */
	/* for pre-945g platforms use load detect */
	if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
	if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
		if (intel_crt_detect_ddc(connector))
		if (intel_crt_detect_ddc(connector))
			status = connector_status_connected;
			status = connector_status_connected;
		else
		else
			status = intel_crt_load_detect(crt);
			status = intel_crt_load_detect(crt);
		intel_release_load_detect_pipe(connector, &tmp, &ctx);
		intel_release_load_detect_pipe(connector, &tmp);
	} else
	} else
		status = connector_status_unknown;
		status = connector_status_unknown;


	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);

out:
out:
	intel_display_power_put(dev_priv, power_domain);
	intel_display_power_put(dev_priv, power_domain);
	return status;
	return status;
+15 −24
Original line number Original line Diff line number Diff line
@@ -8462,8 +8462,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
		      connector->base.id, connector->name,
		      connector->base.id, connector->name,
		      encoder->base.id, encoder->name);
		      encoder->base.id, encoder->name);


	drm_modeset_acquire_init(ctx, 0);

retry:
retry:
	ret = drm_modeset_lock(&config->connection_mutex, ctx);
	ret = drm_modeset_lock(&config->connection_mutex, ctx);
	if (ret)
	if (ret)
@@ -8502,11 +8500,15 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
		i++;
		i++;
		if (!(encoder->possible_crtcs & (1 << i)))
		if (!(encoder->possible_crtcs & (1 << i)))
			continue;
			continue;
		if (!possible_crtc->enabled) {
		if (possible_crtc->enabled)
			continue;
		/* This can occur when applying the pipe A quirk on resume. */
		if (to_intel_crtc(possible_crtc)->new_enabled)
			continue;

		crtc = possible_crtc;
		crtc = possible_crtc;
		break;
		break;
	}
	}
	}


	/*
	/*
	 * If we didn't find an unused CRTC, don't use any.
	 * If we didn't find an unused CRTC, don't use any.
@@ -8574,15 +8576,11 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
		goto retry;
		goto retry;
	}
	}


	drm_modeset_drop_locks(ctx);
	drm_modeset_acquire_fini(ctx);

	return false;
	return false;
}
}


void intel_release_load_detect_pipe(struct drm_connector *connector,
void intel_release_load_detect_pipe(struct drm_connector *connector,
				    struct intel_load_detect_pipe *old,
				    struct intel_load_detect_pipe *old)
				    struct drm_modeset_acquire_ctx *ctx)
{
{
	struct intel_encoder *intel_encoder =
	struct intel_encoder *intel_encoder =
		intel_attached_encoder(connector);
		intel_attached_encoder(connector);
@@ -8606,17 +8604,12 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
			drm_framebuffer_unreference(old->release_fb);
			drm_framebuffer_unreference(old->release_fb);
		}
		}


		goto unlock;
		return;
		return;
	}
	}


	/* Switch crtc and encoder back off if necessary */
	/* Switch crtc and encoder back off if necessary */
	if (old->dpms_mode != DRM_MODE_DPMS_ON)
	if (old->dpms_mode != DRM_MODE_DPMS_ON)
		connector->funcs->dpms(connector, old->dpms_mode);
		connector->funcs->dpms(connector, old->dpms_mode);

unlock:
	drm_modeset_drop_locks(ctx);
	drm_modeset_acquire_fini(ctx);
}
}


static int i9xx_pll_refclk(struct drm_device *dev,
static int i9xx_pll_refclk(struct drm_device *dev,
@@ -11700,8 +11693,8 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
	};
	};
	const struct drm_rect clip = {
	const struct drm_rect clip = {
		/* integer pixels */
		/* integer pixels */
		.x2 = intel_crtc->config.pipe_src_w,
		.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
		.y2 = intel_crtc->config.pipe_src_h,
		.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
	};
	};
	bool visible;
	bool visible;
	int ret;
	int ret;
@@ -12659,7 +12652,7 @@ static void intel_enable_pipe_a(struct drm_device *dev)
	struct intel_connector *connector;
	struct intel_connector *connector;
	struct drm_connector *crt = NULL;
	struct drm_connector *crt = NULL;
	struct intel_load_detect_pipe load_detect_temp;
	struct intel_load_detect_pipe load_detect_temp;
	struct drm_modeset_acquire_ctx ctx;
	struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;


	/* We can't just switch on the pipe A, we need to set things up with a
	/* We can't just switch on the pipe A, we need to set things up with a
	 * proper mode and output configuration. As a gross hack, enable pipe A
	 * proper mode and output configuration. As a gross hack, enable pipe A
@@ -12676,10 +12669,8 @@ static void intel_enable_pipe_a(struct drm_device *dev)
	if (!crt)
	if (!crt)
		return;
		return;


	if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, &ctx))
	if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx))
		intel_release_load_detect_pipe(crt, &load_detect_temp, &ctx);
		intel_release_load_detect_pipe(crt, &load_detect_temp);


}
}


static bool
static bool
@@ -13112,7 +13103,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
	 * experience fancy races otherwise.
	 * experience fancy races otherwise.
	 */
	 */
	drm_irq_uninstall(dev);
	drm_irq_uninstall(dev);
	cancel_work_sync(&dev_priv->hotplug_work);
	intel_hpd_cancel_work(dev_priv);
	dev_priv->pm._irqs_disabled = true;
	dev_priv->pm._irqs_disabled = true;


	/*
	/*
Loading