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

Commit 041df357 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-next-2014-10-24' of git://anongit.freedesktop.org/drm-intel into drm-next

- suspend/resume/freeze/thaw unification from Imre
- wa list improvements from Mika&Arun
- display pll precomputation from Ander Conselvan, this removed the last
  ->mode_set callbacks, a big step towards implementing atomic modesets
- more kerneldoc for the interrupt code
- 180 rotation for cursors (Ville&Sonika)
- ULT/ULX feature check macros cleaned up thanks to Damien
- piles and piles of fixes all over, bug team seems to work!

* tag 'drm-intel-next-2014-10-24' of git://anongit.freedesktop.org/drm-intel: (61 commits)
  drm/i915: Update DRIVER_DATE to 20141024
  drm/i915: add comments on what stage a given PM handler is called
  drm/i915: unify switcheroo and legacy suspend/resume handlers
  drm/i915: add poweroff_late handler
  drm/i915: sanitize suspend/resume helper function names
  drm/i915: unify S3 and S4 suspend/resume handlers
  drm/i915: disable/re-enable PCI device around S4 freeze/thaw
  drm/i915: enable output polling during S4 thaw
  drm/i915: check for GT faults in all resume handlers and driver load time
  drm/i915: remove unused restore_gtt_mappings optimization during suspend
  drm/i915: fix S4 suspend while switcheroo state is off
  drm/i915: vlv: fix switcheroo/legacy suspend/resume
  drm/i915: propagate error from legacy resume handler
  drm/i915: unify legacy S3 suspend and S4 freeze handlers
  drm/i915: factor out i915_drm_suspend_late
  drm/i915: Emit even number of dwords when emitting LRIs
  drm/i915: Add rotation support for cursor plane (v5)
  drm/i915: Correctly reject invalid flags for wait_ioctl
  drm/i915: use macros to assign mmio access functions
  drm/i915: only run hsw_power_well_post_enable when really needed
  ...
parents bbf0ef03 3eebaec6
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -3829,6 +3829,11 @@ int num_ioctls;</synopsis>
!Idrivers/gpu/drm/i915/intel_frontbuffer.c
!Fdrivers/gpu/drm/i915/intel_drv.h intel_frontbuffer_flip
!Fdrivers/gpu/drm/i915/i915_gem.c i915_gem_track_fb
      </sect2>
      <sect2>
        <title>Display FIFO Underrun Reporting</title>
!Pdrivers/gpu/drm/i915/intel_fifo_underrun.c fifo underrun handling
!Idrivers/gpu/drm/i915/intel_fifo_underrun.c
      </sect2>
      <sect2>
        <title>Plane Configuration</title>
+1 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ i915-y += intel_renderstate_gen6.o \
# modesetting core code
i915-y += intel_bios.o \
	  intel_display.o \
	  intel_fifo_underrun.o \
	  intel_frontbuffer.o \
	  intel_modes.o \
	  intel_overlay.o \
+27 −12
Original line number Diff line number Diff line
@@ -1848,6 +1848,8 @@ static int i915_execlists(struct seq_file *m, void *data)
	if (ret)
		return ret;

	intel_runtime_pm_get(dev_priv);

	for_each_ring(ring, dev_priv, ring_id) {
		struct intel_ctx_submit_request *head_req = NULL;
		int count = 0;
@@ -1899,6 +1901,7 @@ static int i915_execlists(struct seq_file *m, void *data)
		seq_putc(m, '\n');
	}

	intel_runtime_pm_put(dev_priv);
	mutex_unlock(&dev->struct_mutex);

	return 0;
@@ -2655,18 +2658,18 @@ static int i915_wa_registers(struct seq_file *m, void *unused)

	intel_runtime_pm_get(dev_priv);

	seq_printf(m, "Workarounds applied: %d\n", dev_priv->num_wa_regs);
	for (i = 0; i < dev_priv->num_wa_regs; ++i) {
		u32 addr, mask;
	seq_printf(m, "Workarounds applied: %d\n", dev_priv->workarounds.count);
	for (i = 0; i < dev_priv->workarounds.count; ++i) {
		u32 addr, mask, value, read;
		bool ok;

		addr = dev_priv->intel_wa_regs[i].addr;
		mask = dev_priv->intel_wa_regs[i].mask;
		dev_priv->intel_wa_regs[i].value = I915_READ(addr) | mask;
		if (dev_priv->intel_wa_regs[i].addr)
			seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n",
				   dev_priv->intel_wa_regs[i].addr,
				   dev_priv->intel_wa_regs[i].value,
				   dev_priv->intel_wa_regs[i].mask);
		addr = dev_priv->workarounds.reg[i].addr;
		mask = dev_priv->workarounds.reg[i].mask;
		value = dev_priv->workarounds.reg[i].value;
		read = I915_READ(addr);
		ok = (value & mask) == (read & mask);
		seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X, read: 0x%08x, status: %s\n",
			   addr, value, mask, read, ok ? "OK" : "FAIL");
	}

	intel_runtime_pm_put(dev_priv);
@@ -3255,6 +3258,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
	struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev,
									pipe));
	u32 val = 0; /* shut up gcc */
	int ret;

@@ -3290,6 +3295,14 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
		if (!pipe_crc->entries)
			return -ENOMEM;

		/*
		 * When IPS gets enabled, the pipe CRC changes. Since IPS gets
		 * enabled and disabled dynamically based on package C states,
		 * user space can't make reliable use of the CRCs, so let's just
		 * completely disable it.
		 */
		hsw_disable_ips(crtc);

		spin_lock_irq(&pipe_crc->lock);
		pipe_crc->head = 0;
		pipe_crc->tail = 0;
@@ -3328,6 +3341,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
			vlv_undo_pipe_scramble_reset(dev, pipe);
		else if (IS_HASWELL(dev) && pipe == PIPE_A)
			hsw_undo_trans_edp_pipe_A_crc_wa(dev);

		hsw_enable_ips(crtc);
	}

	return 0;
+7 −5
Original line number Diff line number Diff line
@@ -1275,12 +1275,12 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
		/* i915 resume handler doesn't set to D0 */
		pci_set_power_state(dev->pdev, PCI_D0);
		i915_resume(dev);
		i915_resume_legacy(dev);
		dev->switch_power_state = DRM_SWITCH_POWER_ON;
	} else {
		pr_err("switched off\n");
		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
		i915_suspend(dev, pmm);
		i915_suspend_legacy(dev, pmm);
		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
	}
}
@@ -1853,8 +1853,12 @@ int i915_driver_unload(struct drm_device *dev)

	acpi_video_unregister();

	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
	if (drm_core_check_feature(dev, DRIVER_MODESET))
		intel_fbdev_fini(dev);

	drm_vblank_cleanup(dev);

	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		intel_modeset_cleanup(dev);

		/*
@@ -1895,8 +1899,6 @@ int i915_driver_unload(struct drm_device *dev)
			i915_free_hws(dev);
	}

	drm_vblank_cleanup(dev);

	intel_teardown_gmbus(dev);
	intel_teardown_mchbar(dev);

+88 −122
Original line number Diff line number Diff line
@@ -463,7 +463,7 @@ void intel_detect_pch(struct drm_device *dev)
				dev_priv->pch_type = PCH_LPT;
				DRM_DEBUG_KMS("Found LynxPoint PCH\n");
				WARN_ON(!IS_HASWELL(dev));
				WARN_ON(IS_ULT(dev));
				WARN_ON(IS_HSW_ULT(dev));
			} else if (IS_BROADWELL(dev)) {
				dev_priv->pch_type = PCH_LPT;
				dev_priv->pch_id =
@@ -474,17 +474,15 @@ void intel_detect_pch(struct drm_device *dev)
				dev_priv->pch_type = PCH_LPT;
				DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
				WARN_ON(!IS_HASWELL(dev));
				WARN_ON(!IS_ULT(dev));
				WARN_ON(!IS_HSW_ULT(dev));
			} else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
				dev_priv->pch_type = PCH_SPT;
				DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
				WARN_ON(!IS_SKYLAKE(dev));
				WARN_ON(IS_ULT(dev));
			} else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
				dev_priv->pch_type = PCH_SPT;
				DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
				WARN_ON(!IS_SKYLAKE(dev));
				WARN_ON(!IS_ULT(dev));
			} else
				continue;

@@ -556,7 +554,7 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv);
static int intel_resume_prepare(struct drm_i915_private *dev_priv,
				bool rpm_resume);

static int i915_drm_freeze(struct drm_device *dev)
static int i915_drm_suspend(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_crtc *crtc;
@@ -632,7 +630,26 @@ static int i915_drm_freeze(struct drm_device *dev)
	return 0;
}

int i915_suspend(struct drm_device *dev, pm_message_t state)
static int i915_drm_suspend_late(struct drm_device *drm_dev)
{
	struct drm_i915_private *dev_priv = drm_dev->dev_private;
	int ret;

	ret = intel_suspend_complete(dev_priv);

	if (ret) {
		DRM_ERROR("Suspend complete failed: %d\n", ret);

		return ret;
	}

	pci_disable_device(drm_dev->pdev);
	pci_set_power_state(drm_dev->pdev, PCI_D3hot);

	return 0;
}

int i915_suspend_legacy(struct drm_device *dev, pm_message_t state)
{
	int error;

@@ -642,48 +659,25 @@ int i915_suspend(struct drm_device *dev, pm_message_t state)
		return -ENODEV;
	}

	if (state.event == PM_EVENT_PRETHAW)
		return 0;

	if (WARN_ON_ONCE(state.event != PM_EVENT_SUSPEND &&
			 state.event != PM_EVENT_FREEZE))
		return -EINVAL;

	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	error = i915_drm_freeze(dev);
	error = i915_drm_suspend(dev);
	if (error)
		return error;

	if (state.event == PM_EVENT_SUSPEND) {
		/* Shut down the device */
		pci_disable_device(dev->pdev);
		pci_set_power_state(dev->pdev, PCI_D3hot);
	}

	return 0;
	return i915_drm_suspend_late(dev);
}

static int i915_drm_thaw_early(struct drm_device *dev)
static int i915_drm_resume(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret;

	ret = intel_resume_prepare(dev_priv, false);
	if (ret)
		DRM_ERROR("Resume prepare failed: %d,Continuing resume\n", ret);

	intel_uncore_early_sanitize(dev, true);
	intel_uncore_sanitize(dev);
	intel_power_domains_init_hw(dev_priv);

	return ret;
}

static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	if (drm_core_check_feature(dev, DRIVER_MODESET) &&
	    restore_gtt_mappings) {
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		mutex_lock(&dev->struct_mutex);
		i915_gem_restore_gtt_mappings(dev);
		mutex_unlock(&dev->struct_mutex);
@@ -742,21 +736,15 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)

	intel_opregion_notify_adapter(dev, PCI_D0);

	return 0;
}

static int i915_drm_thaw(struct drm_device *dev)
{
	if (drm_core_check_feature(dev, DRIVER_MODESET))
		i915_check_and_clear_faults(dev);
	drm_kms_helper_poll_enable(dev);

	return __i915_drm_thaw(dev, true);
	return 0;
}

static int i915_resume_early(struct drm_device *dev)
static int i915_drm_resume_early(struct drm_device *dev)
{
	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret;

	/*
	 * We have a resume ordering issue with the snd-hda driver also
@@ -772,33 +760,29 @@ static int i915_resume_early(struct drm_device *dev)

	pci_set_master(dev->pdev);

	return i915_drm_thaw_early(dev);
}
	ret = intel_resume_prepare(dev_priv, false);
	if (ret)
		DRM_ERROR("Resume prepare failed: %d,Continuing resume\n", ret);

int i915_resume(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret;
	intel_uncore_early_sanitize(dev, true);
	intel_uncore_sanitize(dev);
	intel_power_domains_init_hw(dev_priv);

	/*
	 * Platforms with opregion should have sane BIOS, older ones (gen3 and
	 * earlier) need to restore the GTT mappings since the BIOS might clear
	 * all our scratch PTEs.
	 */
	ret = __i915_drm_thaw(dev, !dev_priv->opregion.header);
	if (ret)
	return ret;

	drm_kms_helper_poll_enable(dev);
	return 0;
}

static int i915_resume_legacy(struct drm_device *dev)
int i915_resume_legacy(struct drm_device *dev)
{
	i915_resume_early(dev);
	i915_resume(dev);
	int ret;

	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	ret = i915_drm_resume_early(dev);
	if (ret)
		return ret;

	return i915_drm_resume(dev);
}

/**
@@ -950,15 +934,13 @@ static int i915_pm_suspend(struct device *dev)
	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	return i915_drm_freeze(drm_dev);
	return i915_drm_suspend(drm_dev);
}

static int i915_pm_suspend_late(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	struct drm_i915_private *dev_priv = drm_dev->dev_private;
	int ret;

	/*
	 * We have a suspedn ordering issue with the snd-hda driver also
@@ -972,16 +954,7 @@ static int i915_pm_suspend_late(struct device *dev)
	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	ret = intel_suspend_complete(dev_priv);

	if (ret)
		DRM_ERROR("Suspend complete failed: %d\n", ret);
	else {
		pci_disable_device(pdev);
		pci_set_power_state(pdev, PCI_D3hot);
	}

	return ret;
	return i915_drm_suspend_late(drm_dev);
}

static int i915_pm_resume_early(struct device *dev)
@@ -989,52 +962,21 @@ static int i915_pm_resume_early(struct device *dev)
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);

	return i915_resume_early(drm_dev);
}

static int i915_pm_resume(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);

	return i915_resume(drm_dev);
}

static int i915_pm_freeze(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);

	if (!drm_dev || !drm_dev->dev_private) {
		dev_err(dev, "DRM not initialized, aborting suspend.\n");
		return -ENODEV;
	}

	return i915_drm_freeze(drm_dev);
}

static int i915_pm_thaw_early(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	return i915_drm_thaw_early(drm_dev);
	return i915_drm_resume_early(drm_dev);
}

static int i915_pm_thaw(struct device *dev)
static int i915_pm_resume(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);

	return i915_drm_thaw(drm_dev);
}

static int i915_pm_poweroff(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct drm_device *drm_dev = pci_get_drvdata(pdev);
	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	return i915_drm_freeze(drm_dev);
	return i915_drm_resume(drm_dev);
}

static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
@@ -1592,16 +1534,40 @@ static int intel_resume_prepare(struct drm_i915_private *dev_priv,
}

static const struct dev_pm_ops i915_pm_ops = {
	/*
	 * S0ix (via system suspend) and S3 event handlers [PMSG_SUSPEND,
	 * PMSG_RESUME]
	 */
	.suspend = i915_pm_suspend,
	.suspend_late = i915_pm_suspend_late,
	.resume_early = i915_pm_resume_early,
	.resume = i915_pm_resume,
	.freeze = i915_pm_freeze,
	.thaw_early = i915_pm_thaw_early,
	.thaw = i915_pm_thaw,
	.poweroff = i915_pm_poweroff,

	/*
	 * S4 event handlers
	 * @freeze, @freeze_late    : called (1) before creating the
	 *                            hibernation image [PMSG_FREEZE] and
	 *                            (2) after rebooting, before restoring
	 *                            the image [PMSG_QUIESCE]
	 * @thaw, @thaw_early       : called (1) after creating the hibernation
	 *                            image, before writing it [PMSG_THAW]
	 *                            and (2) after failing to create or
	 *                            restore the image [PMSG_RECOVER]
	 * @poweroff, @poweroff_late: called after writing the hibernation
	 *                            image, before rebooting [PMSG_HIBERNATE]
	 * @restore, @restore_early : called after rebooting and restoring the
	 *                            hibernation image [PMSG_RESTORE]
	 */
	.freeze = i915_pm_suspend,
	.freeze_late = i915_pm_suspend_late,
	.thaw_early = i915_pm_resume_early,
	.thaw = i915_pm_resume,
	.poweroff = i915_pm_suspend,
	.poweroff_late = i915_pm_suspend_late,
	.restore_early = i915_pm_resume_early,
	.restore = i915_pm_resume,

	/* S0ix (via runtime suspend) event handlers */
	.runtime_suspend = intel_runtime_suspend,
	.runtime_resume = intel_runtime_resume,
};
@@ -1643,7 +1609,7 @@ static struct drm_driver driver = {
	.set_busid = drm_pci_set_busid,

	/* Used in place of i915_pm_ops for non-DRIVER_MODESET */
	.suspend = i915_suspend,
	.suspend = i915_suspend_legacy,
	.resume = i915_resume_legacy,

	.device_is_agp = i915_driver_device_is_agp,
Loading