“e7cfbea9cb7a02ea29fdae5d39c9e3d09102c4d5”上不存在“...include/git@gitcode.net:openharmony/kernel_linux.git”
提交 041df357 编写于 作者: D Dave Airlie

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
  ...
...@@ -3829,6 +3829,11 @@ int num_ioctls;</synopsis> ...@@ -3829,6 +3829,11 @@ int num_ioctls;</synopsis>
!Idrivers/gpu/drm/i915/intel_frontbuffer.c !Idrivers/gpu/drm/i915/intel_frontbuffer.c
!Fdrivers/gpu/drm/i915/intel_drv.h intel_frontbuffer_flip !Fdrivers/gpu/drm/i915/intel_drv.h intel_frontbuffer_flip
!Fdrivers/gpu/drm/i915/i915_gem.c i915_gem_track_fb !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>
<sect2> <sect2>
<title>Plane Configuration</title> <title>Plane Configuration</title>
......
...@@ -45,6 +45,7 @@ i915-y += intel_renderstate_gen6.o \ ...@@ -45,6 +45,7 @@ i915-y += intel_renderstate_gen6.o \
# modesetting core code # modesetting core code
i915-y += intel_bios.o \ i915-y += intel_bios.o \
intel_display.o \ intel_display.o \
intel_fifo_underrun.o \
intel_frontbuffer.o \ intel_frontbuffer.o \
intel_modes.o \ intel_modes.o \
intel_overlay.o \ intel_overlay.o \
......
...@@ -1848,6 +1848,8 @@ static int i915_execlists(struct seq_file *m, void *data) ...@@ -1848,6 +1848,8 @@ static int i915_execlists(struct seq_file *m, void *data)
if (ret) if (ret)
return ret; return ret;
intel_runtime_pm_get(dev_priv);
for_each_ring(ring, dev_priv, ring_id) { for_each_ring(ring, dev_priv, ring_id) {
struct intel_ctx_submit_request *head_req = NULL; struct intel_ctx_submit_request *head_req = NULL;
int count = 0; int count = 0;
...@@ -1899,6 +1901,7 @@ static int i915_execlists(struct seq_file *m, void *data) ...@@ -1899,6 +1901,7 @@ static int i915_execlists(struct seq_file *m, void *data)
seq_putc(m, '\n'); seq_putc(m, '\n');
} }
intel_runtime_pm_put(dev_priv);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return 0; return 0;
...@@ -2655,18 +2658,18 @@ static int i915_wa_registers(struct seq_file *m, void *unused) ...@@ -2655,18 +2658,18 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
intel_runtime_pm_get(dev_priv); intel_runtime_pm_get(dev_priv);
seq_printf(m, "Workarounds applied: %d\n", dev_priv->num_wa_regs); seq_printf(m, "Workarounds applied: %d\n", dev_priv->workarounds.count);
for (i = 0; i < dev_priv->num_wa_regs; ++i) { for (i = 0; i < dev_priv->workarounds.count; ++i) {
u32 addr, mask; u32 addr, mask, value, read;
bool ok;
addr = dev_priv->intel_wa_regs[i].addr;
mask = dev_priv->intel_wa_regs[i].mask; addr = dev_priv->workarounds.reg[i].addr;
dev_priv->intel_wa_regs[i].value = I915_READ(addr) | mask; mask = dev_priv->workarounds.reg[i].mask;
if (dev_priv->intel_wa_regs[i].addr) value = dev_priv->workarounds.reg[i].value;
seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n", read = I915_READ(addr);
dev_priv->intel_wa_regs[i].addr, ok = (value & mask) == (read & mask);
dev_priv->intel_wa_regs[i].value, seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X, read: 0x%08x, status: %s\n",
dev_priv->intel_wa_regs[i].mask); addr, value, mask, read, ok ? "OK" : "FAIL");
} }
intel_runtime_pm_put(dev_priv); intel_runtime_pm_put(dev_priv);
...@@ -3255,6 +3258,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, ...@@ -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 drm_i915_private *dev_priv = dev->dev_private;
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; 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 */ u32 val = 0; /* shut up gcc */
int ret; int ret;
...@@ -3290,6 +3295,14 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, ...@@ -3290,6 +3295,14 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
if (!pipe_crc->entries) if (!pipe_crc->entries)
return -ENOMEM; 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); spin_lock_irq(&pipe_crc->lock);
pipe_crc->head = 0; pipe_crc->head = 0;
pipe_crc->tail = 0; pipe_crc->tail = 0;
...@@ -3328,6 +3341,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, ...@@ -3328,6 +3341,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
vlv_undo_pipe_scramble_reset(dev, pipe); vlv_undo_pipe_scramble_reset(dev, pipe);
else if (IS_HASWELL(dev) && pipe == PIPE_A) else if (IS_HASWELL(dev) && pipe == PIPE_A)
hsw_undo_trans_edp_pipe_A_crc_wa(dev); hsw_undo_trans_edp_pipe_A_crc_wa(dev);
hsw_enable_ips(crtc);
} }
return 0; return 0;
......
...@@ -1275,12 +1275,12 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_ ...@@ -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; dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
/* i915 resume handler doesn't set to D0 */ /* i915 resume handler doesn't set to D0 */
pci_set_power_state(dev->pdev, PCI_D0); pci_set_power_state(dev->pdev, PCI_D0);
i915_resume(dev); i915_resume_legacy(dev);
dev->switch_power_state = DRM_SWITCH_POWER_ON; dev->switch_power_state = DRM_SWITCH_POWER_ON;
} else { } else {
pr_err("switched off\n"); pr_err("switched off\n");
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; 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; dev->switch_power_state = DRM_SWITCH_POWER_OFF;
} }
} }
...@@ -1853,8 +1853,12 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1853,8 +1853,12 @@ int i915_driver_unload(struct drm_device *dev)
acpi_video_unregister(); acpi_video_unregister();
if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (drm_core_check_feature(dev, DRIVER_MODESET))
intel_fbdev_fini(dev); intel_fbdev_fini(dev);
drm_vblank_cleanup(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_modeset_cleanup(dev); intel_modeset_cleanup(dev);
/* /*
...@@ -1895,8 +1899,6 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -1895,8 +1899,6 @@ int i915_driver_unload(struct drm_device *dev)
i915_free_hws(dev); i915_free_hws(dev);
} }
drm_vblank_cleanup(dev);
intel_teardown_gmbus(dev); intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev); intel_teardown_mchbar(dev);
......
...@@ -463,7 +463,7 @@ void intel_detect_pch(struct drm_device *dev) ...@@ -463,7 +463,7 @@ void intel_detect_pch(struct drm_device *dev)
dev_priv->pch_type = PCH_LPT; dev_priv->pch_type = PCH_LPT;
DRM_DEBUG_KMS("Found LynxPoint PCH\n"); DRM_DEBUG_KMS("Found LynxPoint PCH\n");
WARN_ON(!IS_HASWELL(dev)); WARN_ON(!IS_HASWELL(dev));
WARN_ON(IS_ULT(dev)); WARN_ON(IS_HSW_ULT(dev));
} else if (IS_BROADWELL(dev)) { } else if (IS_BROADWELL(dev)) {
dev_priv->pch_type = PCH_LPT; dev_priv->pch_type = PCH_LPT;
dev_priv->pch_id = dev_priv->pch_id =
...@@ -474,17 +474,15 @@ void intel_detect_pch(struct drm_device *dev) ...@@ -474,17 +474,15 @@ void intel_detect_pch(struct drm_device *dev)
dev_priv->pch_type = PCH_LPT; dev_priv->pch_type = PCH_LPT;
DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
WARN_ON(!IS_HASWELL(dev)); 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) { } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_SPT; dev_priv->pch_type = PCH_SPT;
DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
WARN_ON(!IS_SKYLAKE(dev)); WARN_ON(!IS_SKYLAKE(dev));
WARN_ON(IS_ULT(dev));
} else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) { } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
dev_priv->pch_type = PCH_SPT; dev_priv->pch_type = PCH_SPT;
DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
WARN_ON(!IS_SKYLAKE(dev)); WARN_ON(!IS_SKYLAKE(dev));
WARN_ON(!IS_ULT(dev));
} else } else
continue; continue;
...@@ -556,7 +554,7 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv); ...@@ -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, static int intel_resume_prepare(struct drm_i915_private *dev_priv,
bool rpm_resume); 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_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc; struct drm_crtc *crtc;
...@@ -632,7 +630,26 @@ static int i915_drm_freeze(struct drm_device *dev) ...@@ -632,7 +630,26 @@ static int i915_drm_freeze(struct drm_device *dev)
return 0; 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; int error;
...@@ -642,48 +659,25 @@ int i915_suspend(struct drm_device *dev, pm_message_t state) ...@@ -642,48 +659,25 @@ int i915_suspend(struct drm_device *dev, pm_message_t state)
return -ENODEV; return -ENODEV;
} }
if (state.event == PM_EVENT_PRETHAW) if (WARN_ON_ONCE(state.event != PM_EVENT_SUSPEND &&
return 0; state.event != PM_EVENT_FREEZE))
return -EINVAL;
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0; return 0;
error = i915_drm_freeze(dev); error = i915_drm_suspend(dev);
if (error) if (error)
return error; return error;
if (state.event == PM_EVENT_SUSPEND) { return i915_drm_suspend_late(dev);
/* Shut down the device */
pci_disable_device(dev->pdev);
pci_set_power_state(dev->pdev, PCI_D3hot);
}
return 0;
} }
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; 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; if (drm_core_check_feature(dev, DRIVER_MODESET)) {
}
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) {
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
i915_gem_restore_gtt_mappings(dev); i915_gem_restore_gtt_mappings(dev);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
...@@ -742,21 +736,15 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) ...@@ -742,21 +736,15 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
intel_opregion_notify_adapter(dev, PCI_D0); intel_opregion_notify_adapter(dev, PCI_D0);
return 0; drm_kms_helper_poll_enable(dev);
}
static int i915_drm_thaw(struct drm_device *dev)
{
if (drm_core_check_feature(dev, DRIVER_MODESET))
i915_check_and_clear_faults(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) struct drm_i915_private *dev_priv = dev->dev_private;
return 0; int ret;
/* /*
* We have a resume ordering issue with the snd-hda driver also * 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) ...@@ -772,33 +760,29 @@ static int i915_resume_early(struct drm_device *dev)
pci_set_master(dev->pdev); 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);
intel_uncore_early_sanitize(dev, true);
intel_uncore_sanitize(dev);
intel_power_domains_init_hw(dev_priv);
return ret;
} }
int i915_resume(struct drm_device *dev) int i915_resume_legacy(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private;
int ret; int ret;
/* if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
* Platforms with opregion should have sane BIOS, older ones (gen3 and return 0;
* earlier) need to restore the GTT mappings since the BIOS might clear
* all our scratch PTEs. ret = i915_drm_resume_early(dev);
*/
ret = __i915_drm_thaw(dev, !dev_priv->opregion.header);
if (ret) if (ret)
return ret; return ret;
drm_kms_helper_poll_enable(dev); return i915_drm_resume(dev);
return 0;
}
static int i915_resume_legacy(struct drm_device *dev)
{
i915_resume_early(dev);
i915_resume(dev);
return 0;
} }
/** /**
...@@ -950,15 +934,13 @@ static int i915_pm_suspend(struct device *dev) ...@@ -950,15 +934,13 @@ static int i915_pm_suspend(struct device *dev)
if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0; return 0;
return i915_drm_freeze(drm_dev); return i915_drm_suspend(drm_dev);
} }
static int i915_pm_suspend_late(struct device *dev) static int i915_pm_suspend_late(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev); 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 * 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) ...@@ -972,16 +954,7 @@ static int i915_pm_suspend_late(struct device *dev)
if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0; return 0;
ret = intel_suspend_complete(dev_priv); return i915_drm_suspend_late(drm_dev);
if (ret)
DRM_ERROR("Suspend complete failed: %d\n", ret);
else {
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
}
return ret;
} }
static int i915_pm_resume_early(struct device *dev) static int i915_pm_resume_early(struct device *dev)
...@@ -989,52 +962,21 @@ 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 pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev); struct drm_device *drm_dev = pci_get_drvdata(pdev);
return i915_resume_early(drm_dev); if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
} return 0;
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);
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 pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev); struct drm_device *drm_dev = pci_get_drvdata(pdev);
return i915_drm_thaw(drm_dev); if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
} return 0;
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);
return i915_drm_freeze(drm_dev); return i915_drm_resume(drm_dev);
} }
static int hsw_suspend_complete(struct drm_i915_private *dev_priv) 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, ...@@ -1592,16 +1534,40 @@ static int intel_resume_prepare(struct drm_i915_private *dev_priv,
} }
static const struct dev_pm_ops i915_pm_ops = { 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 = i915_pm_suspend,
.suspend_late = i915_pm_suspend_late, .suspend_late = i915_pm_suspend_late,
.resume_early = i915_pm_resume_early, .resume_early = i915_pm_resume_early,
.resume = i915_pm_resume, .resume = i915_pm_resume,
.freeze = i915_pm_freeze,
.thaw_early = i915_pm_thaw_early, /*
.thaw = i915_pm_thaw, * S4 event handlers
.poweroff = i915_pm_poweroff, * @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_early = i915_pm_resume_early,
.restore = i915_pm_resume, .restore = i915_pm_resume,
/* S0ix (via runtime suspend) event handlers */
.runtime_suspend = intel_runtime_suspend, .runtime_suspend = intel_runtime_suspend,
.runtime_resume = intel_runtime_resume, .runtime_resume = intel_runtime_resume,
}; };
...@@ -1643,7 +1609,7 @@ static struct drm_driver driver = { ...@@ -1643,7 +1609,7 @@ static struct drm_driver driver = {
.set_busid = drm_pci_set_busid, .set_busid = drm_pci_set_busid,
/* Used in place of i915_pm_ops for non-DRIVER_MODESET */ /* Used in place of i915_pm_ops for non-DRIVER_MODESET */
.suspend = i915_suspend, .suspend = i915_suspend_legacy,
.resume = i915_resume_legacy, .resume = i915_resume_legacy,
.device_is_agp = i915_driver_device_is_agp, .device_is_agp = i915_driver_device_is_agp,
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
#define DRIVER_NAME "i915" #define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics" #define DRIVER_DESC "Intel Graphics"
#define DRIVER_DATE "20141003" #define DRIVER_DATE "20141024"
enum pipe { enum pipe {
INVALID_PIPE = -1, INVALID_PIPE = -1,
...@@ -460,7 +460,7 @@ struct drm_i915_display_funcs { ...@@ -460,7 +460,7 @@ struct drm_i915_display_funcs {
* Returns true on success, false on failure. * Returns true on success, false on failure.
*/ */
bool (*find_dpll)(const struct intel_limit *limit, bool (*find_dpll)(const struct intel_limit *limit,
struct drm_crtc *crtc, struct intel_crtc *crtc,
int target, int refclk, int target, int refclk,
struct dpll *match_clock, struct dpll *match_clock,
struct dpll *best_clock); struct dpll *best_clock);
...@@ -476,7 +476,7 @@ struct drm_i915_display_funcs { ...@@ -476,7 +476,7 @@ struct drm_i915_display_funcs {
struct intel_crtc_config *); struct intel_crtc_config *);
void (*get_plane_config)(struct intel_crtc *, void (*get_plane_config)(struct intel_crtc *,
struct intel_plane_config *); struct intel_plane_config *);
int (*crtc_mode_set)(struct drm_crtc *crtc, int (*crtc_mode_set)(struct intel_crtc *crtc,
int x, int y, int x, int y,
struct drm_framebuffer *old_fb); struct drm_framebuffer *old_fb);
void (*crtc_enable)(struct drm_crtc *crtc); void (*crtc_enable)(struct drm_crtc *crtc);
...@@ -1448,6 +1448,20 @@ struct i915_frontbuffer_tracking { ...@@ -1448,6 +1448,20 @@ struct i915_frontbuffer_tracking {
unsigned flip_bits; unsigned flip_bits;
}; };
struct i915_wa_reg {
u32 addr;
u32 value;
/* bitmask representing WA bits */
u32 mask;
};
#define I915_MAX_WA_REGS 16
struct i915_workarounds {
struct i915_wa_reg reg[I915_MAX_WA_REGS];
u32 count;
};
struct drm_i915_private { struct drm_i915_private {
struct drm_device *dev; struct drm_device *dev;
struct kmem_cache *slab; struct kmem_cache *slab;
...@@ -1527,6 +1541,8 @@ struct drm_i915_private { ...@@ -1527,6 +1541,8 @@ struct drm_i915_private {
struct intel_opregion opregion; struct intel_opregion opregion;
struct intel_vbt_data vbt; struct intel_vbt_data vbt;
bool preserve_bios_swizzle;
/* overlay */ /* overlay */
struct intel_overlay *overlay; struct intel_overlay *overlay;
...@@ -1590,19 +1606,7 @@ struct drm_i915_private { ...@@ -1590,19 +1606,7 @@ struct drm_i915_private {
struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
int dpio_phy_iosf_port[I915_NUM_PHYS_VLV]; int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
/* struct i915_workarounds workarounds;
* workarounds are currently applied at different places and
* changes are being done to consolidate them so exact count is
* not clear at this point, use a max value for now.
*/
#define I915_MAX_WA_REGS 16
struct {
u32 addr;
u32 value;
/* bitmask representing WA bits */
u32 mask;
} intel_wa_regs[I915_MAX_WA_REGS];
u32 num_wa_regs;
/* Reclocking support */ /* Reclocking support */
bool render_reclock_avail; bool render_reclock_avail;
...@@ -2107,7 +2111,6 @@ struct drm_i915_cmd_table { ...@@ -2107,7 +2111,6 @@ struct drm_i915_cmd_table {
(INTEL_DEVID(dev) & 0x00F0) == 0x0020) (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
#define IS_HSW_ULT(dev) (IS_HASWELL(dev) && \ #define IS_HSW_ULT(dev) (IS_HASWELL(dev) && \
(INTEL_DEVID(dev) & 0xFF00) == 0x0A00) (INTEL_DEVID(dev) & 0xFF00) == 0x0A00)
#define IS_ULT(dev) (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
#define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ #define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \
(INTEL_DEVID(dev) & 0x00F0) == 0x0020) (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
/* ULX machines are also considered ULT. */ /* ULX machines are also considered ULT. */
...@@ -2141,7 +2144,7 @@ struct drm_i915_cmd_table { ...@@ -2141,7 +2144,7 @@ struct drm_i915_cmd_table {
#define HAS_VEBOX(dev) (INTEL_INFO(dev)->ring_mask & VEBOX_RING) #define HAS_VEBOX(dev) (INTEL_INFO(dev)->ring_mask & VEBOX_RING)
#define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc)
#define HAS_WT(dev) ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \ #define HAS_WT(dev) ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \
to_i915(dev)->ellc_size) __I915__(dev)->ellc_size)
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6)
...@@ -2178,13 +2181,15 @@ struct drm_i915_cmd_table { ...@@ -2178,13 +2181,15 @@ struct drm_i915_cmd_table {
#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
#define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) #define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
#define HAS_IPS(dev) (IS_ULT(dev) || IS_BROADWELL(dev)) #define HAS_IPS(dev) (IS_HSW_ULT(dev) || IS_BROADWELL(dev))
#define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi)
#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) #define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev))
#define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \ #define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \
IS_BROADWELL(dev) || IS_VALLEYVIEW(dev)) IS_BROADWELL(dev) || IS_VALLEYVIEW(dev))
#define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6)
#define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
#define INTEL_PCH_DEVICE_ID_MASK 0xff00 #define INTEL_PCH_DEVICE_ID_MASK 0xff00
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 #define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
...@@ -2195,7 +2200,7 @@ struct drm_i915_cmd_table { ...@@ -2195,7 +2200,7 @@ struct drm_i915_cmd_table {
#define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100 #define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100
#define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00 #define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00
#define INTEL_PCH_TYPE(dev) (to_i915(dev)->pch_type) #define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type)
#define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT) #define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT)
#define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT)
#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
...@@ -2216,8 +2221,8 @@ struct drm_i915_cmd_table { ...@@ -2216,8 +2221,8 @@ struct drm_i915_cmd_table {
extern const struct drm_ioctl_desc i915_ioctls[]; extern const struct drm_ioctl_desc i915_ioctls[];
extern int i915_max_ioctl; extern int i915_max_ioctl;
extern int i915_suspend(struct drm_device *dev, pm_message_t state); extern int i915_suspend_legacy(struct drm_device *dev, pm_message_t state);
extern int i915_resume(struct drm_device *dev); extern int i915_resume_legacy(struct drm_device *dev);
extern int i915_master_create(struct drm_device *dev, struct drm_master *master); extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master); extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
...@@ -2312,6 +2317,17 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, ...@@ -2312,6 +2317,17 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv); void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv); void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
void
ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask);
void
ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask);
void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
uint32_t interrupt_mask,
uint32_t enabled_irq_mask);
#define ibx_enable_display_interrupt(dev_priv, bits) \
ibx_display_interrupt_update((dev_priv), (bits), (bits))
#define ibx_disable_display_interrupt(dev_priv, bits) \
ibx_display_interrupt_update((dev_priv), (bits), 0)
/* i915_gem.c */ /* i915_gem.c */
int i915_gem_init_ioctl(struct drm_device *dev, void *data, int i915_gem_init_ioctl(struct drm_device *dev, void *data,
......
...@@ -1466,6 +1466,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, ...@@ -1466,6 +1466,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
* *
* While the mapping holds a reference on the contents of the object, it doesn't * While the mapping holds a reference on the contents of the object, it doesn't
* imply a ref on the object itself. * imply a ref on the object itself.
*
* IMPORTANT:
*
* DRM driver writers who look a this function as an example for how to do GEM
* mmap support, please don't implement mmap support like here. The modern way
* to implement DRM mmap support is with an mmap offset ioctl (like
* i915_gem_mmap_gtt) and then using the mmap syscall on the DRM fd directly.
* That way debug tooling like valgrind will understand what's going on, hiding
* the mmap call in a driver private ioctl will break that. The i915 driver only
* does cpu mmaps this way because we didn't know better.
*/ */
int int
i915_gem_mmap_ioctl(struct drm_device *dev, void *data, i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
...@@ -2800,6 +2810,9 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) ...@@ -2800,6 +2810,9 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
u32 seqno = 0; u32 seqno = 0;
int ret = 0; int ret = 0;
if (args->flags != 0)
return -EINVAL;
ret = i915_mutex_lock_interruptible(dev); ret = i915_mutex_lock_interruptible(dev);
if (ret) if (ret)
return ret; return ret;
...@@ -5259,7 +5272,7 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) ...@@ -5259,7 +5272,7 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
unsigned long timeout = msecs_to_jiffies(5000) + 1; unsigned long timeout = msecs_to_jiffies(5000) + 1;
unsigned long pinned, bound, unbound, freed; unsigned long pinned, bound, unbound, freed_pages;
bool was_interruptible; bool was_interruptible;
bool unlock; bool unlock;
...@@ -5276,7 +5289,7 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) ...@@ -5276,7 +5289,7 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
was_interruptible = dev_priv->mm.interruptible; was_interruptible = dev_priv->mm.interruptible;
dev_priv->mm.interruptible = false; dev_priv->mm.interruptible = false;
freed = i915_gem_shrink_all(dev_priv); freed_pages = i915_gem_shrink_all(dev_priv);
dev_priv->mm.interruptible = was_interruptible; dev_priv->mm.interruptible = was_interruptible;
...@@ -5307,14 +5320,15 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) ...@@ -5307,14 +5320,15 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
if (unlock) if (unlock)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
pr_info("Purging GPU memory, %lu bytes freed, %lu bytes still pinned.\n", if (freed_pages || unbound || bound)
freed, pinned); pr_info("Purging GPU memory, %lu bytes freed, %lu bytes still pinned.\n",
freed_pages << PAGE_SHIFT, pinned);
if (unbound || bound) if (unbound || bound)
pr_err("%lu and %lu bytes still available in the " pr_err("%lu and %lu bytes still available in the "
"bound and unbound GPU page lists.\n", "bound and unbound GPU page lists.\n",
bound, unbound); bound, unbound);
*(unsigned long *)ptr += freed; *(unsigned long *)ptr += freed_pages;
return NOTIFY_DONE; return NOTIFY_DONE;
} }
......
...@@ -102,22 +102,33 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) ...@@ -102,22 +102,33 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE;
} else if (INTEL_INFO(dev)->gen >= 6) { } else if (INTEL_INFO(dev)->gen >= 6) {
uint32_t dimm_c0, dimm_c1; if (dev_priv->preserve_bios_swizzle) {
dimm_c0 = I915_READ(MAD_DIMM_C0); if (I915_READ(DISP_ARB_CTL) &
dimm_c1 = I915_READ(MAD_DIMM_C1); DISP_TILE_SURFACE_SWIZZLING) {
dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK; swizzle_x = I915_BIT_6_SWIZZLE_9_10;
dimm_c1 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK; swizzle_y = I915_BIT_6_SWIZZLE_9;
/* Enable swizzling when the channels are populated with } else {
* identically sized dimms. We don't need to check the 3rd swizzle_x = I915_BIT_6_SWIZZLE_NONE;
* channel because no cpu with gpu attached ships in that swizzle_y = I915_BIT_6_SWIZZLE_NONE;
* configuration. Also, swizzling only makes sense for 2 }
* channels anyway. */
if (dimm_c0 == dimm_c1) {
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
swizzle_y = I915_BIT_6_SWIZZLE_9;
} else { } else {
swizzle_x = I915_BIT_6_SWIZZLE_NONE; uint32_t dimm_c0, dimm_c1;
swizzle_y = I915_BIT_6_SWIZZLE_NONE; dimm_c0 = I915_READ(MAD_DIMM_C0);
dimm_c1 = I915_READ(MAD_DIMM_C1);
dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
dimm_c1 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
/* Enable swizzling when the channels are populated
* with identically sized dimms. We don't need to check
* the 3rd channel because no cpu with gpu attached
* ships in that configuration. Also, swizzling only
* makes sense for 2 channels anyway. */
if (dimm_c0 == dimm_c1) {
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
swizzle_y = I915_BIT_6_SWIZZLE_9;
} else {
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
}
} }
} else if (IS_GEN5(dev)) { } else if (IS_GEN5(dev)) {
/* On Ironlake whatever DRAM config, GPU always do /* On Ironlake whatever DRAM config, GPU always do
......
...@@ -189,7 +189,6 @@ static drm_ioctl_compat_t *i915_compat_ioctls[] = { ...@@ -189,7 +189,6 @@ static drm_ioctl_compat_t *i915_compat_ioctls[] = {
[DRM_I915_ALLOC] = compat_i915_alloc [DRM_I915_ALLOC] = compat_i915_alloc
}; };
#ifdef CONFIG_COMPAT
/** /**
* Called whenever a 32-bit process running under a 64-bit kernel * Called whenever a 32-bit process running under a 64-bit kernel
* performs an ioctl on /dev/dri/card<n>. * performs an ioctl on /dev/dri/card<n>.
...@@ -218,4 +217,3 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -218,4 +217,3 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return ret; return ret;
} }
#endif
...@@ -139,7 +139,7 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */ ...@@ -139,7 +139,7 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
} while (0) } while (0)
/* For display hotplug interrupt */ /* For display hotplug interrupt */
static void void
ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask) ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
{ {
assert_spin_locked(&dev_priv->irq_lock); assert_spin_locked(&dev_priv->irq_lock);
...@@ -154,7 +154,7 @@ ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask) ...@@ -154,7 +154,7 @@ ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
} }
} }
static void void
ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask) ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
{ {
assert_spin_locked(&dev_priv->irq_lock); assert_spin_locked(&dev_priv->irq_lock);
...@@ -238,24 +238,6 @@ void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) ...@@ -238,24 +238,6 @@ void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
snb_update_pm_irq(dev_priv, mask, 0); snb_update_pm_irq(dev_priv, mask, 0);
} }
static bool ivb_can_enable_err_int(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc;
enum pipe pipe;
assert_spin_locked(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
if (crtc->cpu_fifo_underrun_disabled)
return false;
}
return true;
}
/** /**
* bdw_update_pm_irq - update GT interrupt 2 * bdw_update_pm_irq - update GT interrupt 2
* @dev_priv: driver private * @dev_priv: driver private
...@@ -296,130 +278,15 @@ void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) ...@@ -296,130 +278,15 @@ void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
bdw_update_pm_irq(dev_priv, mask, 0); bdw_update_pm_irq(dev_priv, mask, 0);
} }
static bool cpt_can_enable_serr_int(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe;
struct intel_crtc *crtc;
assert_spin_locked(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
if (crtc->pch_fifo_underrun_disabled)
return false;
}
return true;
}
void i9xx_check_fifo_underruns(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc;
spin_lock_irq(&dev_priv->irq_lock);
for_each_intel_crtc(dev, crtc) {
u32 reg = PIPESTAT(crtc->pipe);
u32 pipestat;
if (crtc->cpu_fifo_underrun_disabled)
continue;
pipestat = I915_READ(reg) & 0xffff0000;
if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0)
continue;
I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
POSTING_READ(reg);
DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
}
spin_unlock_irq(&dev_priv->irq_lock);
}
static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe,
bool enable, bool old)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg = PIPESTAT(pipe);
u32 pipestat = I915_READ(reg) & 0xffff0000;
assert_spin_locked(&dev_priv->irq_lock);
if (enable) {
I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
POSTING_READ(reg);
} else {
if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS)
DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
}
}
static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t bit = (pipe == PIPE_A) ? DE_PIPEA_FIFO_UNDERRUN :
DE_PIPEB_FIFO_UNDERRUN;
if (enable)
ironlake_enable_display_irq(dev_priv, bit);
else
ironlake_disable_display_irq(dev_priv, bit);
}
static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe,
bool enable, bool old)
{
struct drm_i915_private *dev_priv = dev->dev_private;
if (enable) {
I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
if (!ivb_can_enable_err_int(dev))
return;
ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
} else {
ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
if (old &&
I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
DRM_ERROR("uncleared fifo underrun on pipe %c\n",
pipe_name(pipe));
}
}
}
static void broadwell_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
assert_spin_locked(&dev_priv->irq_lock);
if (enable)
dev_priv->de_irq_mask[pipe] &= ~GEN8_PIPE_FIFO_UNDERRUN;
else
dev_priv->de_irq_mask[pipe] |= GEN8_PIPE_FIFO_UNDERRUN;
I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
}
/** /**
* ibx_display_interrupt_update - update SDEIMR * ibx_display_interrupt_update - update SDEIMR
* @dev_priv: driver private * @dev_priv: driver private
* @interrupt_mask: mask of interrupt bits to update * @interrupt_mask: mask of interrupt bits to update
* @enabled_irq_mask: mask of interrupt bits to enable * @enabled_irq_mask: mask of interrupt bits to enable
*/ */
static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
uint32_t interrupt_mask, uint32_t interrupt_mask,
uint32_t enabled_irq_mask) uint32_t enabled_irq_mask)
{ {
uint32_t sdeimr = I915_READ(SDEIMR); uint32_t sdeimr = I915_READ(SDEIMR);
sdeimr &= ~interrupt_mask; sdeimr &= ~interrupt_mask;
...@@ -433,160 +300,6 @@ static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, ...@@ -433,160 +300,6 @@ static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
I915_WRITE(SDEIMR, sdeimr); I915_WRITE(SDEIMR, sdeimr);
POSTING_READ(SDEIMR); POSTING_READ(SDEIMR);
} }
#define ibx_enable_display_interrupt(dev_priv, bits) \
ibx_display_interrupt_update((dev_priv), (bits), (bits))
#define ibx_disable_display_interrupt(dev_priv, bits) \
ibx_display_interrupt_update((dev_priv), (bits), 0)
static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
enum transcoder pch_transcoder,
bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t bit = (pch_transcoder == TRANSCODER_A) ?
SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
if (enable)
ibx_enable_display_interrupt(dev_priv, bit);
else
ibx_disable_display_interrupt(dev_priv, bit);
}
static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
enum transcoder pch_transcoder,
bool enable, bool old)
{
struct drm_i915_private *dev_priv = dev->dev_private;
if (enable) {
I915_WRITE(SERR_INT,
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
if (!cpt_can_enable_serr_int(dev))
return;
ibx_enable_display_interrupt(dev_priv, SDE_ERROR_CPT);
} else {
ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
if (old && I915_READ(SERR_INT) &
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
transcoder_name(pch_transcoder));
}
}
}
/**
* intel_set_cpu_fifo_underrun_reporting - enable/disable FIFO underrun messages
* @dev: drm device
* @pipe: pipe
* @enable: true if we want to report FIFO underrun errors, false otherwise
*
* This function makes us disable or enable CPU fifo underruns for a specific
* pipe. Notice that on some Gens (e.g. IVB, HSW), disabling FIFO underrun
* reporting for one pipe may also disable all the other CPU error interruts for
* the other pipes, due to the fact that there's just one interrupt mask/enable
* bit for all the pipes.
*
* Returns the previous state of underrun reporting.
*/
static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
bool old;
assert_spin_locked(&dev_priv->irq_lock);
old = !intel_crtc->cpu_fifo_underrun_disabled;
intel_crtc->cpu_fifo_underrun_disabled = !enable;
if (HAS_GMCH_DISPLAY(dev))
i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
else if (IS_GEN5(dev) || IS_GEN6(dev))
ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
else if (IS_GEN7(dev))
ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old);
else if (IS_GEN8(dev) || IS_GEN9(dev))
broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
return old;
}
bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long flags;
bool ret;
spin_lock_irqsave(&dev_priv->irq_lock, flags);
ret = __intel_set_cpu_fifo_underrun_reporting(dev, pipe, enable);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
return ret;
}
static bool __cpu_fifo_underrun_reporting_enabled(struct drm_device *dev,
enum pipe pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
return !intel_crtc->cpu_fifo_underrun_disabled;
}
/**
* intel_set_pch_fifo_underrun_reporting - enable/disable FIFO underrun messages
* @dev: drm device
* @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
* @enable: true if we want to report FIFO underrun errors, false otherwise
*
* This function makes us disable or enable PCH fifo underruns for a specific
* PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO
* underrun reporting for one transcoder may also disable all the other PCH
* error interruts for the other transcoders, due to the fact that there's just
* one interrupt mask/enable bit for all the transcoders.
*
* Returns the previous state of underrun reporting.
*/
bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
enum transcoder pch_transcoder,
bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
unsigned long flags;
bool old;
/*
* NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
* has only one pch transcoder A that all pipes can use. To avoid racy
* pch transcoder -> pipe lookups from interrupt code simply store the
* underrun statistics in crtc A. Since we never expose this anywhere
* nor use it outside of the fifo underrun code here using the "wrong"
* crtc on LPT won't cause issues.
*/
spin_lock_irqsave(&dev_priv->irq_lock, flags);
old = !intel_crtc->pch_fifo_underrun_disabled;
intel_crtc->pch_fifo_underrun_disabled = !enable;
if (HAS_PCH_IBX(dev))
ibx_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
else
cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable, old);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
return old;
}
static void static void
__i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, __i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
...@@ -2036,9 +1749,9 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) ...@@ -2036,9 +1749,9 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
* we need to be careful that we only handle what we want to * we need to be careful that we only handle what we want to
* handle. * handle.
*/ */
mask = 0;
if (__cpu_fifo_underrun_reporting_enabled(dev, pipe)) /* fifo underruns are filterered in the underrun handler. */
mask |= PIPE_FIFO_UNDERRUN_STATUS; mask = PIPE_FIFO_UNDERRUN_STATUS;
switch (pipe) { switch (pipe) {
case PIPE_A: case PIPE_A:
...@@ -2083,9 +1796,8 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) ...@@ -2083,9 +1796,8 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe); i9xx_pipe_crc_irq_handler(dev, pipe);
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS && if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
} }
if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS)
...@@ -2252,14 +1964,10 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) ...@@ -2252,14 +1964,10 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n"); DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n");
if (pch_iir & SDE_TRANSA_FIFO_UNDER) if (pch_iir & SDE_TRANSA_FIFO_UNDER)
if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_A);
false))
DRM_ERROR("PCH transcoder A FIFO underrun\n");
if (pch_iir & SDE_TRANSB_FIFO_UNDER) if (pch_iir & SDE_TRANSB_FIFO_UNDER)
if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B, intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_B);
false))
DRM_ERROR("PCH transcoder B FIFO underrun\n");
} }
static void ivb_err_int_handler(struct drm_device *dev) static void ivb_err_int_handler(struct drm_device *dev)
...@@ -2272,12 +1980,8 @@ static void ivb_err_int_handler(struct drm_device *dev) ...@@ -2272,12 +1980,8 @@ static void ivb_err_int_handler(struct drm_device *dev)
DRM_ERROR("Poison interrupt\n"); DRM_ERROR("Poison interrupt\n");
for_each_pipe(dev_priv, pipe) { for_each_pipe(dev_priv, pipe) {
if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) { if (err_int & ERR_INT_FIFO_UNDERRUN(pipe))
if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
false))
DRM_ERROR("Pipe %c FIFO underrun\n",
pipe_name(pipe));
}
if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) {
if (IS_IVYBRIDGE(dev)) if (IS_IVYBRIDGE(dev))
...@@ -2299,19 +2003,13 @@ static void cpt_serr_int_handler(struct drm_device *dev) ...@@ -2299,19 +2003,13 @@ static void cpt_serr_int_handler(struct drm_device *dev)
DRM_ERROR("PCH poison interrupt\n"); DRM_ERROR("PCH poison interrupt\n");
if (serr_int & SERR_INT_TRANS_A_FIFO_UNDERRUN) if (serr_int & SERR_INT_TRANS_A_FIFO_UNDERRUN)
if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_A);
false))
DRM_ERROR("PCH transcoder A FIFO underrun\n");
if (serr_int & SERR_INT_TRANS_B_FIFO_UNDERRUN) if (serr_int & SERR_INT_TRANS_B_FIFO_UNDERRUN)
if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_B, intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_B);
false))
DRM_ERROR("PCH transcoder B FIFO underrun\n");
if (serr_int & SERR_INT_TRANS_C_FIFO_UNDERRUN) if (serr_int & SERR_INT_TRANS_C_FIFO_UNDERRUN)
if (intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_C, intel_pch_fifo_underrun_irq_handler(dev_priv, TRANSCODER_C);
false))
DRM_ERROR("PCH transcoder C FIFO underrun\n");
I915_WRITE(SERR_INT, serr_int); I915_WRITE(SERR_INT, serr_int);
} }
...@@ -2377,9 +2075,7 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) ...@@ -2377,9 +2075,7 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir)
intel_check_page_flip(dev, pipe); intel_check_page_flip(dev, pipe);
if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
DRM_ERROR("Pipe %c FIFO underrun\n",
pipe_name(pipe));
if (de_iir & DE_PIPE_CRC_DONE(pipe)) if (de_iir & DE_PIPE_CRC_DONE(pipe))
i9xx_pipe_crc_irq_handler(dev, pipe); i9xx_pipe_crc_irq_handler(dev, pipe);
...@@ -2598,12 +2294,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) ...@@ -2598,12 +2294,9 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE) if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE)
hsw_pipe_crc_irq_handler(dev, pipe); hsw_pipe_crc_irq_handler(dev, pipe);
if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) { if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN)
if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, intel_cpu_fifo_underrun_irq_handler(dev_priv,
false)) pipe);
DRM_ERROR("Pipe %c FIFO underrun\n",
pipe_name(pipe));
}
if (IS_GEN9(dev)) if (IS_GEN9(dev))
...@@ -4120,9 +3813,9 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) ...@@ -4120,9 +3813,9 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe); i9xx_pipe_crc_irq_handler(dev, pipe);
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS && if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) intel_cpu_fifo_underrun_irq_handler(dev_priv,
DRM_ERROR("pipe %c underrun\n", pipe_name(pipe)); pipe);
} }
iir = new_iir; iir = new_iir;
...@@ -4314,9 +4007,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) ...@@ -4314,9 +4007,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe); i9xx_pipe_crc_irq_handler(dev, pipe);
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS && if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) intel_cpu_fifo_underrun_irq_handler(dev_priv,
DRM_ERROR("pipe %c underrun\n", pipe_name(pipe)); pipe);
} }
if (blc_event || (iir & I915_ASLE_INTERRUPT)) if (blc_event || (iir & I915_ASLE_INTERRUPT))
...@@ -4542,9 +4235,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) ...@@ -4542,9 +4235,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev, pipe); i9xx_pipe_crc_irq_handler(dev, pipe);
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS && if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
} }
if (blc_event || (iir & I915_ASLE_INTERRUPT)) if (blc_event || (iir & I915_ASLE_INTERRUPT))
......
...@@ -883,8 +883,8 @@ enum punit_power_well { ...@@ -883,8 +883,8 @@ enum punit_power_well {
#define _VLV_PCS23_DW11_CH0 0x042c #define _VLV_PCS23_DW11_CH0 0x042c
#define _VLV_PCS01_DW11_CH1 0x262c #define _VLV_PCS01_DW11_CH1 0x262c
#define _VLV_PCS23_DW11_CH1 0x282c #define _VLV_PCS23_DW11_CH1 0x282c
#define VLV_PCS01_DW11(ch) _PORT(ch, _VLV_PCS01_DW0_CH0, _VLV_PCS01_DW0_CH1) #define VLV_PCS01_DW11(ch) _PORT(ch, _VLV_PCS01_DW11_CH0, _VLV_PCS01_DW11_CH1)
#define VLV_PCS23_DW11(ch) _PORT(ch, _VLV_PCS23_DW0_CH0, _VLV_PCS23_DW0_CH1) #define VLV_PCS23_DW11(ch) _PORT(ch, _VLV_PCS23_DW11_CH0, _VLV_PCS23_DW11_CH1)
#define _VLV_PCS_DW12_CH0 0x8230 #define _VLV_PCS_DW12_CH0 0x8230
#define _VLV_PCS_DW12_CH1 0x8430 #define _VLV_PCS_DW12_CH1 0x8430
...@@ -4054,17 +4054,18 @@ enum punit_power_well { ...@@ -4054,17 +4054,18 @@ enum punit_power_well {
#define DSPFW_PLANEA_WM1_HI_MASK (1<<0) #define DSPFW_PLANEA_WM1_HI_MASK (1<<0)
/* drain latency register values*/ /* drain latency register values*/
#define DRAIN_LATENCY_PRECISION_16 16
#define DRAIN_LATENCY_PRECISION_32 32 #define DRAIN_LATENCY_PRECISION_32 32
#define DRAIN_LATENCY_PRECISION_64 64 #define DRAIN_LATENCY_PRECISION_64 64
#define VLV_DDL(pipe) (VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe)) #define VLV_DDL(pipe) (VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe))
#define DDL_CURSOR_PRECISION_64 (1<<31) #define DDL_CURSOR_PRECISION_HIGH (1<<31)
#define DDL_CURSOR_PRECISION_32 (0<<31) #define DDL_CURSOR_PRECISION_LOW (0<<31)
#define DDL_CURSOR_SHIFT 24 #define DDL_CURSOR_SHIFT 24
#define DDL_SPRITE_PRECISION_64(sprite) (1<<(15+8*(sprite))) #define DDL_SPRITE_PRECISION_HIGH(sprite) (1<<(15+8*(sprite)))
#define DDL_SPRITE_PRECISION_32(sprite) (0<<(15+8*(sprite))) #define DDL_SPRITE_PRECISION_LOW(sprite) (0<<(15+8*(sprite)))
#define DDL_SPRITE_SHIFT(sprite) (8+8*(sprite)) #define DDL_SPRITE_SHIFT(sprite) (8+8*(sprite))
#define DDL_PLANE_PRECISION_64 (1<<7) #define DDL_PLANE_PRECISION_HIGH (1<<7)
#define DDL_PLANE_PRECISION_32 (0<<7) #define DDL_PLANE_PRECISION_LOW (0<<7)
#define DDL_PLANE_SHIFT 0 #define DDL_PLANE_SHIFT 0
#define DRAIN_LATENCY_MASK 0x7f #define DRAIN_LATENCY_MASK 0x7f
...@@ -4207,6 +4208,7 @@ enum punit_power_well { ...@@ -4207,6 +4208,7 @@ enum punit_power_well {
#define MCURSOR_PIPE_A 0x00 #define MCURSOR_PIPE_A 0x00
#define MCURSOR_PIPE_B (1 << 28) #define MCURSOR_PIPE_B (1 << 28)
#define MCURSOR_GAMMA_ENABLE (1 << 26) #define MCURSOR_GAMMA_ENABLE (1 << 26)
#define CURSOR_ROTATE_180 (1<<15)
#define CURSOR_TRICKLE_FEED_DISABLE (1 << 14) #define CURSOR_TRICKLE_FEED_DISABLE (1 << 14)
#define _CURABASE 0x70084 #define _CURABASE 0x70084
#define _CURAPOS 0x70088 #define _CURAPOS 0x70088
...@@ -4579,6 +4581,9 @@ enum punit_power_well { ...@@ -4579,6 +4581,9 @@ enum punit_power_well {
#define PLANE_CTL_ALPHA_DISABLE ( 0 << 4) #define PLANE_CTL_ALPHA_DISABLE ( 0 << 4)
#define PLANE_CTL_ALPHA_SW_PREMULTIPLY ( 2 << 4) #define PLANE_CTL_ALPHA_SW_PREMULTIPLY ( 2 << 4)
#define PLANE_CTL_ALPHA_HW_PREMULTIPLY ( 3 << 4) #define PLANE_CTL_ALPHA_HW_PREMULTIPLY ( 3 << 4)
#define PLANE_CTL_ROTATE_MASK 0x3
#define PLANE_CTL_ROTATE_0 0x0
#define PLANE_CTL_ROTATE_180 0x2
#define _PLANE_STRIDE_1_A 0x70188 #define _PLANE_STRIDE_1_A 0x70188
#define _PLANE_STRIDE_2_A 0x70288 #define _PLANE_STRIDE_2_A 0x70288
#define _PLANE_STRIDE_3_A 0x70388 #define _PLANE_STRIDE_3_A 0x70388
......
...@@ -139,8 +139,6 @@ static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL); ...@@ -139,8 +139,6 @@ static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL);
static struct attribute *rc6_attrs[] = { static struct attribute *rc6_attrs[] = {
&dev_attr_rc6_enable.attr, &dev_attr_rc6_enable.attr,
&dev_attr_rc6_residency_ms.attr, &dev_attr_rc6_residency_ms.attr,
&dev_attr_rc6p_residency_ms.attr,
&dev_attr_rc6pp_residency_ms.attr,
NULL NULL
}; };
...@@ -148,6 +146,17 @@ static struct attribute_group rc6_attr_group = { ...@@ -148,6 +146,17 @@ static struct attribute_group rc6_attr_group = {
.name = power_group_name, .name = power_group_name,
.attrs = rc6_attrs .attrs = rc6_attrs
}; };
static struct attribute *rc6p_attrs[] = {
&dev_attr_rc6p_residency_ms.attr,
&dev_attr_rc6pp_residency_ms.attr,
NULL
};
static struct attribute_group rc6p_attr_group = {
.name = power_group_name,
.attrs = rc6p_attrs
};
#endif #endif
static int l3_access_valid(struct drm_device *dev, loff_t offset) static int l3_access_valid(struct drm_device *dev, loff_t offset)
...@@ -595,12 +604,18 @@ void i915_setup_sysfs(struct drm_device *dev) ...@@ -595,12 +604,18 @@ void i915_setup_sysfs(struct drm_device *dev)
int ret; int ret;
#ifdef CONFIG_PM #ifdef CONFIG_PM
if (INTEL_INFO(dev)->gen >= 6) { if (HAS_RC6(dev)) {
ret = sysfs_merge_group(&dev->primary->kdev->kobj, ret = sysfs_merge_group(&dev->primary->kdev->kobj,
&rc6_attr_group); &rc6_attr_group);
if (ret) if (ret)
DRM_ERROR("RC6 residency sysfs setup failed\n"); DRM_ERROR("RC6 residency sysfs setup failed\n");
} }
if (HAS_RC6p(dev)) {
ret = sysfs_merge_group(&dev->primary->kdev->kobj,
&rc6p_attr_group);
if (ret)
DRM_ERROR("RC6p residency sysfs setup failed\n");
}
#endif #endif
if (HAS_L3_DPF(dev)) { if (HAS_L3_DPF(dev)) {
ret = device_create_bin_file(dev->primary->kdev, &dpf_attrs); ret = device_create_bin_file(dev->primary->kdev, &dpf_attrs);
...@@ -640,5 +655,6 @@ void i915_teardown_sysfs(struct drm_device *dev) ...@@ -640,5 +655,6 @@ void i915_teardown_sysfs(struct drm_device *dev)
device_remove_bin_file(dev->primary->kdev, &dpf_attrs); device_remove_bin_file(dev->primary->kdev, &dpf_attrs);
#ifdef CONFIG_PM #ifdef CONFIG_PM
sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6_attr_group); sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6_attr_group);
sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6p_attr_group);
#endif #endif
} }
...@@ -775,7 +775,7 @@ static void intel_crt_reset(struct drm_connector *connector) ...@@ -775,7 +775,7 @@ static void intel_crt_reset(struct drm_connector *connector)
I915_WRITE(crt->adpa_reg, adpa); I915_WRITE(crt->adpa_reg, adpa);
POSTING_READ(crt->adpa_reg); POSTING_READ(crt->adpa_reg);
DRM_DEBUG_KMS("pch crt adpa set to 0x%x\n", adpa); DRM_DEBUG_KMS("crt adpa set to 0x%x\n", adpa);
crt->force_hotplug_required = 1; crt->force_hotplug_required = 1;
} }
......
...@@ -1291,7 +1291,7 @@ static int hsw_get_cdclk_freq(struct drm_i915_private *dev_priv) ...@@ -1291,7 +1291,7 @@ static int hsw_get_cdclk_freq(struct drm_i915_private *dev_priv)
return 450000; return 450000;
else if (freq == LCPLL_CLK_FREQ_450) else if (freq == LCPLL_CLK_FREQ_450)
return 450000; return 450000;
else if (IS_ULT(dev)) else if (IS_HSW_ULT(dev))
return 337500; return 337500;
else else
return 540000; return 540000;
......
...@@ -406,22 +406,22 @@ static void vlv_clock(int refclk, intel_clock_t *clock) ...@@ -406,22 +406,22 @@ static void vlv_clock(int refclk, intel_clock_t *clock)
/** /**
* Returns whether any output on the specified pipe is of the specified type * Returns whether any output on the specified pipe is of the specified type
*/ */
static bool intel_pipe_has_type(struct drm_crtc *crtc, int type) static bool intel_pipe_has_type(struct intel_crtc *crtc, int type)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
struct intel_encoder *encoder; struct intel_encoder *encoder;
for_each_encoder_on_crtc(dev, crtc, encoder) for_each_encoder_on_crtc(dev, &crtc->base, encoder)
if (encoder->type == type) if (encoder->type == type)
return true; return true;
return false; return false;
} }
static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, static const intel_limit_t *intel_ironlake_limit(struct intel_crtc *crtc,
int refclk) int refclk)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
const intel_limit_t *limit; const intel_limit_t *limit;
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
...@@ -442,9 +442,9 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, ...@@ -442,9 +442,9 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
return limit; return limit;
} }
static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) static const intel_limit_t *intel_g4x_limit(struct intel_crtc *crtc)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
const intel_limit_t *limit; const intel_limit_t *limit;
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
...@@ -463,9 +463,9 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) ...@@ -463,9 +463,9 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
return limit; return limit;
} }
static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk) static const intel_limit_t *intel_limit(struct intel_crtc *crtc, int refclk)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
const intel_limit_t *limit; const intel_limit_t *limit;
if (HAS_PCH_SPLIT(dev)) if (HAS_PCH_SPLIT(dev))
...@@ -576,11 +576,11 @@ static bool intel_PLL_is_valid(struct drm_device *dev, ...@@ -576,11 +576,11 @@ static bool intel_PLL_is_valid(struct drm_device *dev,
} }
static bool static bool
i9xx_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, i9xx_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
int target, int refclk, intel_clock_t *match_clock, int target, int refclk, intel_clock_t *match_clock,
intel_clock_t *best_clock) intel_clock_t *best_clock)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
intel_clock_t clock; intel_clock_t clock;
int err = target; int err = target;
...@@ -637,11 +637,11 @@ i9xx_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, ...@@ -637,11 +637,11 @@ i9xx_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
} }
static bool static bool
pnv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, pnv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
int target, int refclk, intel_clock_t *match_clock, int target, int refclk, intel_clock_t *match_clock,
intel_clock_t *best_clock) intel_clock_t *best_clock)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
intel_clock_t clock; intel_clock_t clock;
int err = target; int err = target;
...@@ -696,11 +696,11 @@ pnv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, ...@@ -696,11 +696,11 @@ pnv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
} }
static bool static bool
g4x_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, g4x_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
int target, int refclk, intel_clock_t *match_clock, int target, int refclk, intel_clock_t *match_clock,
intel_clock_t *best_clock) intel_clock_t *best_clock)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
intel_clock_t clock; intel_clock_t clock;
int max_n; int max_n;
bool found; bool found;
...@@ -753,11 +753,11 @@ g4x_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, ...@@ -753,11 +753,11 @@ g4x_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
} }
static bool static bool
vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, vlv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
int target, int refclk, intel_clock_t *match_clock, int target, int refclk, intel_clock_t *match_clock,
intel_clock_t *best_clock) intel_clock_t *best_clock)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
intel_clock_t clock; intel_clock_t clock;
unsigned int bestppm = 1000000; unsigned int bestppm = 1000000;
/* min update 19.2 MHz */ /* min update 19.2 MHz */
...@@ -810,11 +810,11 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, ...@@ -810,11 +810,11 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
} }
static bool static bool
chv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, chv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
int target, int refclk, intel_clock_t *match_clock, int target, int refclk, intel_clock_t *match_clock,
intel_clock_t *best_clock) intel_clock_t *best_clock)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
intel_clock_t clock; intel_clock_t clock;
uint64_t m2; uint64_t m2;
int found = false; int found = false;
...@@ -1567,7 +1567,7 @@ static int intel_num_dvo_pipes(struct drm_device *dev) ...@@ -1567,7 +1567,7 @@ static int intel_num_dvo_pipes(struct drm_device *dev)
for_each_intel_crtc(dev, crtc) for_each_intel_crtc(dev, crtc)
count += crtc->active && count += crtc->active &&
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO); intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO);
return count; return count;
} }
...@@ -1646,7 +1646,7 @@ static void i9xx_disable_pll(struct intel_crtc *crtc) ...@@ -1646,7 +1646,7 @@ static void i9xx_disable_pll(struct intel_crtc *crtc)
/* Disable DVO 2x clock on both PLLs if necessary */ /* Disable DVO 2x clock on both PLLs if necessary */
if (IS_I830(dev) && if (IS_I830(dev) &&
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO) && intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO) &&
intel_num_dvo_pipes(dev) == 1) { intel_num_dvo_pipes(dev) == 1) {
I915_WRITE(DPLL(PIPE_B), I915_WRITE(DPLL(PIPE_B),
I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE); I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE);
...@@ -1884,7 +1884,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, ...@@ -1884,7 +1884,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
val &= ~TRANS_INTERLACE_MASK; val &= ~TRANS_INTERLACE_MASK;
if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK)
if (HAS_PCH_IBX(dev_priv->dev) && if (HAS_PCH_IBX(dev_priv->dev) &&
intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO))
val |= TRANS_LEGACY_INTERLACED_ILK; val |= TRANS_LEGACY_INTERLACED_ILK;
else else
val |= TRANS_INTERLACED; val |= TRANS_INTERLACED;
...@@ -2007,7 +2007,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc) ...@@ -2007,7 +2007,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
* need the check. * need the check.
*/ */
if (!HAS_PCH_SPLIT(dev_priv->dev)) if (!HAS_PCH_SPLIT(dev_priv->dev))
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DSI)) if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI))
assert_dsi_pll_enabled(dev_priv); assert_dsi_pll_enabled(dev_priv);
else else
assert_pll_enabled(dev_priv, pipe); assert_pll_enabled(dev_priv, pipe);
...@@ -2359,6 +2359,7 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc, ...@@ -2359,6 +2359,7 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
struct intel_plane_config *plane_config) struct intel_plane_config *plane_config)
{ {
struct drm_device *dev = intel_crtc->base.dev; struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *c; struct drm_crtc *c;
struct intel_crtc *i; struct intel_crtc *i;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
...@@ -2390,6 +2391,9 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc, ...@@ -2390,6 +2391,9 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
continue; continue;
if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) { if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) {
if (obj->tiling_mode != I915_TILING_NONE)
dev_priv->preserve_bios_swizzle = true;
drm_framebuffer_reference(c->primary->fb); drm_framebuffer_reference(c->primary->fb);
intel_crtc->base.primary->fb = c->primary->fb; intel_crtc->base.primary->fb = c->primary->fb;
obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
...@@ -2694,6 +2698,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, ...@@ -2694,6 +2698,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
} }
plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
if (to_intel_plane(crtc->primary)->rotation == BIT(DRM_ROTATE_180))
plane_ctl |= PLANE_CTL_ROTATE_180;
I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
...@@ -2844,8 +2850,8 @@ static void intel_update_pipe_size(struct intel_crtc *crtc) ...@@ -2844,8 +2850,8 @@ static void intel_update_pipe_size(struct intel_crtc *crtc)
((adjusted_mode->crtc_hdisplay - 1) << 16) | ((adjusted_mode->crtc_hdisplay - 1) << 16) |
(adjusted_mode->crtc_vdisplay - 1)); (adjusted_mode->crtc_vdisplay - 1));
if (!crtc->config.pch_pfit.enabled && if (!crtc->config.pch_pfit.enabled &&
(intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) || (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP))) { intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
I915_WRITE(PF_CTL(crtc->pipe), 0); I915_WRITE(PF_CTL(crtc->pipe), 0);
I915_WRITE(PF_WIN_POS(crtc->pipe), 0); I915_WRITE(PF_WIN_POS(crtc->pipe), 0);
I915_WRITE(PF_WIN_SZ(crtc->pipe), 0); I915_WRITE(PF_WIN_SZ(crtc->pipe), 0);
...@@ -3753,8 +3759,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) ...@@ -3753,8 +3759,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
/* For PCH DP, enable TRANS_DP_CTL */ /* For PCH DP, enable TRANS_DP_CTL */
if (HAS_PCH_CPT(dev) && if (HAS_PCH_CPT(dev) &&
(intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT) ||
intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_EDP))) {
u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
reg = TRANS_DP_CTL(pipe); reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg); temp = I915_READ(reg);
...@@ -4031,7 +4037,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc) ...@@ -4031,7 +4037,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
return; return;
if (!HAS_PCH_SPLIT(dev_priv->dev)) { if (!HAS_PCH_SPLIT(dev_priv->dev)) {
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI))
assert_dsi_pll_enabled(dev_priv); assert_dsi_pll_enabled(dev_priv);
else else
assert_pll_enabled(dev_priv, pipe); assert_pll_enabled(dev_priv, pipe);
...@@ -4163,8 +4169,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -4163,8 +4169,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true; intel_crtc->active = true;
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
intel_set_pch_fifo_underrun_reporting(dev, pipe, true); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
for_each_encoder_on_crtc(dev, crtc, encoder) for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable) if (encoder->pre_enable)
...@@ -4278,13 +4284,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) ...@@ -4278,13 +4284,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true; intel_crtc->active = true;
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
for_each_encoder_on_crtc(dev, crtc, encoder) for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable) if (encoder->pre_enable)
encoder->pre_enable(encoder); encoder->pre_enable(encoder);
if (intel_crtc->config.has_pch_encoder) { if (intel_crtc->config.has_pch_encoder) {
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
true);
dev_priv->display.fdi_link_train(crtc); dev_priv->display.fdi_link_train(crtc);
} }
...@@ -4360,7 +4367,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ...@@ -4360,7 +4367,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
encoder->disable(encoder); encoder->disable(encoder);
if (intel_crtc->config.has_pch_encoder) if (intel_crtc->config.has_pch_encoder)
intel_set_pch_fifo_underrun_reporting(dev, pipe, false); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
intel_disable_pipe(intel_crtc); intel_disable_pipe(intel_crtc);
...@@ -4374,7 +4381,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) ...@@ -4374,7 +4381,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
ironlake_fdi_disable(crtc); ironlake_fdi_disable(crtc);
ironlake_disable_pch_transcoder(dev_priv, pipe); ironlake_disable_pch_transcoder(dev_priv, pipe);
intel_set_pch_fifo_underrun_reporting(dev, pipe, true); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
if (HAS_PCH_CPT(dev)) { if (HAS_PCH_CPT(dev)) {
/* disable TRANS_DP_CTL */ /* disable TRANS_DP_CTL */
...@@ -4427,7 +4434,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) ...@@ -4427,7 +4434,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
} }
if (intel_crtc->config.has_pch_encoder) if (intel_crtc->config.has_pch_encoder)
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false); intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
false);
intel_disable_pipe(intel_crtc); intel_disable_pipe(intel_crtc);
if (intel_crtc->config.dp_encoder_is_mst) if (intel_crtc->config.dp_encoder_is_mst)
...@@ -4441,7 +4449,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) ...@@ -4441,7 +4449,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
if (intel_crtc->config.has_pch_encoder) { if (intel_crtc->config.has_pch_encoder) {
lpt_disable_pch_transcoder(dev_priv); lpt_disable_pch_transcoder(dev_priv);
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
true);
intel_ddi_fdi_disable(crtc); intel_ddi_fdi_disable(crtc);
} }
...@@ -4615,7 +4624,7 @@ static void vlv_update_cdclk(struct drm_device *dev) ...@@ -4615,7 +4624,7 @@ static void vlv_update_cdclk(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
dev_priv->vlv_cdclk_freq = dev_priv->display.get_display_clock_speed(dev); dev_priv->vlv_cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz", DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
dev_priv->vlv_cdclk_freq); dev_priv->vlv_cdclk_freq);
/* /*
...@@ -4818,6 +4827,7 @@ static void valleyview_modeset_global_resources(struct drm_device *dev) ...@@ -4818,6 +4827,7 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
static void valleyview_crtc_enable(struct drm_crtc *crtc) static void valleyview_crtc_enable(struct drm_crtc *crtc)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *encoder; struct intel_encoder *encoder;
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
...@@ -4828,7 +4838,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) ...@@ -4828,7 +4838,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->active) if (intel_crtc->active)
return; return;
is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI); is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
if (!is_dsi) { if (!is_dsi) {
if (IS_CHERRYVIEW(dev)) if (IS_CHERRYVIEW(dev))
...@@ -4846,7 +4856,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) ...@@ -4846,7 +4856,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true; intel_crtc->active = true;
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
for_each_encoder_on_crtc(dev, crtc, encoder) for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_pll_enable) if (encoder->pre_pll_enable)
...@@ -4879,7 +4889,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) ...@@ -4879,7 +4889,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_crtc_enable_planes(crtc); intel_crtc_enable_planes(crtc);
/* Underruns don't raise interrupts, so check manually. */ /* Underruns don't raise interrupts, so check manually. */
i9xx_check_fifo_underruns(dev); i9xx_check_fifo_underruns(dev_priv);
} }
static void i9xx_set_pll_dividers(struct intel_crtc *crtc) static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
...@@ -4894,6 +4904,7 @@ static void i9xx_set_pll_dividers(struct intel_crtc *crtc) ...@@ -4894,6 +4904,7 @@ static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
static void i9xx_crtc_enable(struct drm_crtc *crtc) static void i9xx_crtc_enable(struct drm_crtc *crtc)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *encoder; struct intel_encoder *encoder;
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
...@@ -4915,7 +4926,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) ...@@ -4915,7 +4926,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true; intel_crtc->active = true;
if (!IS_GEN2(dev)) if (!IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
for_each_encoder_on_crtc(dev, crtc, encoder) for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable) if (encoder->pre_enable)
...@@ -4946,10 +4957,10 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) ...@@ -4946,10 +4957,10 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
* but leave the pipe running. * but leave the pipe running.
*/ */
if (IS_GEN2(dev)) if (IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
/* Underruns don't raise interrupts, so check manually. */ /* Underruns don't raise interrupts, so check manually. */
i9xx_check_fifo_underruns(dev); i9xx_check_fifo_underruns(dev_priv);
} }
static void i9xx_pfit_disable(struct intel_crtc *crtc) static void i9xx_pfit_disable(struct intel_crtc *crtc)
...@@ -4985,7 +4996,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) ...@@ -4985,7 +4996,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
* but leave the pipe running. * but leave the pipe running.
*/ */
if (IS_GEN2(dev)) if (IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
/* /*
* Vblank time updates from the shadow to live plane control register * Vblank time updates from the shadow to live plane control register
...@@ -5021,7 +5032,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) ...@@ -5021,7 +5032,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
if (encoder->post_disable) if (encoder->post_disable)
encoder->post_disable(encoder); encoder->post_disable(encoder);
if (!intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI)) { if (!intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI)) {
if (IS_CHERRYVIEW(dev)) if (IS_CHERRYVIEW(dev))
chv_disable_pll(dev_priv, pipe); chv_disable_pll(dev_priv, pipe);
else if (IS_VALLEYVIEW(dev)) else if (IS_VALLEYVIEW(dev))
...@@ -5031,7 +5042,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) ...@@ -5031,7 +5042,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
} }
if (!IS_GEN2(dev)) if (!IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
intel_crtc->active = false; intel_crtc->active = false;
intel_update_watermarks(crtc); intel_update_watermarks(crtc);
...@@ -5404,7 +5415,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, ...@@ -5404,7 +5415,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
* - LVDS dual channel mode * - LVDS dual channel mode
* - Double wide pipe * - Double wide pipe
*/ */
if ((intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && if ((intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
intel_is_dual_link_lvds(dev)) || pipe_config->double_wide) intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
pipe_config->pipe_src_w &= ~1; pipe_config->pipe_src_w &= ~1;
...@@ -5592,9 +5603,9 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) ...@@ -5592,9 +5603,9 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
} }
static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) static int i9xx_get_refclk(struct intel_crtc *crtc, int num_connectors)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int refclk; int refclk;
...@@ -5642,7 +5653,7 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc, ...@@ -5642,7 +5653,7 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
crtc->config.dpll_hw_state.fp0 = fp; crtc->config.dpll_hw_state.fp0 = fp;
crtc->lowfreq_avail = false; crtc->lowfreq_avail = false;
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
reduced_clock && i915.powersave) { reduced_clock && i915.powersave) {
crtc->config.dpll_hw_state.fp1 = fp2; crtc->config.dpll_hw_state.fp1 = fp2;
crtc->lowfreq_avail = true; crtc->lowfreq_avail = true;
...@@ -5811,16 +5822,16 @@ static void vlv_prepare_pll(struct intel_crtc *crtc) ...@@ -5811,16 +5822,16 @@ static void vlv_prepare_pll(struct intel_crtc *crtc)
/* Set HBR and RBR LPF coefficients */ /* Set HBR and RBR LPF coefficients */
if (crtc->config.port_clock == 162000 || if (crtc->config.port_clock == 162000 ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) || intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG) ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
0x009f0003); 0x009f0003);
else else
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe), vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
0x00d0000f); 0x00d0000f);
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) || if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP) ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) { intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
/* Use SSC source */ /* Use SSC source */
if (pipe == PIPE_A) if (pipe == PIPE_A)
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe), vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
...@@ -5840,8 +5851,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc) ...@@ -5840,8 +5851,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc)
coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe)); coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe));
coreclk = (coreclk & 0x0000ff00) | 0x01c00000; coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) || if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP)) intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
coreclk |= 0x01000000; coreclk |= 0x01000000;
vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk); vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
...@@ -5911,7 +5922,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc) ...@@ -5911,7 +5922,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc)
(2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT)); (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT));
/* Loop filter */ /* Loop filter */
refclk = i9xx_get_refclk(&crtc->base, 0); refclk = i9xx_get_refclk(crtc, 0);
loopfilter = 5 << DPIO_CHV_PROP_COEFF_SHIFT | loopfilter = 5 << DPIO_CHV_PROP_COEFF_SHIFT |
2 << DPIO_CHV_GAIN_CTRL_SHIFT; 2 << DPIO_CHV_GAIN_CTRL_SHIFT;
if (refclk == 100000) if (refclk == 100000)
...@@ -5943,12 +5954,12 @@ static void i9xx_update_pll(struct intel_crtc *crtc, ...@@ -5943,12 +5954,12 @@ static void i9xx_update_pll(struct intel_crtc *crtc,
i9xx_update_pll_dividers(crtc, reduced_clock); i9xx_update_pll_dividers(crtc, reduced_clock);
is_sdvo = intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_SDVO) || is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI); intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
dpll = DPLL_VGA_MODE_DIS; dpll = DPLL_VGA_MODE_DIS;
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS)) if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
dpll |= DPLLB_MODE_LVDS; dpll |= DPLLB_MODE_LVDS;
else else
dpll |= DPLLB_MODE_DAC_SERIAL; dpll |= DPLLB_MODE_DAC_SERIAL;
...@@ -5961,7 +5972,7 @@ static void i9xx_update_pll(struct intel_crtc *crtc, ...@@ -5961,7 +5972,7 @@ static void i9xx_update_pll(struct intel_crtc *crtc,
if (is_sdvo) if (is_sdvo)
dpll |= DPLL_SDVO_HIGH_SPEED; dpll |= DPLL_SDVO_HIGH_SPEED;
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
dpll |= DPLL_SDVO_HIGH_SPEED; dpll |= DPLL_SDVO_HIGH_SPEED;
/* compute bitmask from p1 value */ /* compute bitmask from p1 value */
...@@ -5991,7 +6002,7 @@ static void i9xx_update_pll(struct intel_crtc *crtc, ...@@ -5991,7 +6002,7 @@ static void i9xx_update_pll(struct intel_crtc *crtc,
if (crtc->config.sdvo_tv_clock) if (crtc->config.sdvo_tv_clock)
dpll |= PLL_REF_INPUT_TVCLKINBC; dpll |= PLL_REF_INPUT_TVCLKINBC;
else if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
intel_panel_use_ssc(dev_priv) && num_connectors < 2) intel_panel_use_ssc(dev_priv) && num_connectors < 2)
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
else else
...@@ -6020,7 +6031,7 @@ static void i8xx_update_pll(struct intel_crtc *crtc, ...@@ -6020,7 +6031,7 @@ static void i8xx_update_pll(struct intel_crtc *crtc,
dpll = DPLL_VGA_MODE_DIS; dpll = DPLL_VGA_MODE_DIS;
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
} else { } else {
if (clock->p1 == 2) if (clock->p1 == 2)
...@@ -6031,10 +6042,10 @@ static void i8xx_update_pll(struct intel_crtc *crtc, ...@@ -6031,10 +6042,10 @@ static void i8xx_update_pll(struct intel_crtc *crtc,
dpll |= PLL_P2_DIVIDE_BY_4; dpll |= PLL_P2_DIVIDE_BY_4;
} }
if (!IS_I830(dev) && intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO)) if (!IS_I830(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_DVO))
dpll |= DPLL_DVO_2X_MODE; dpll |= DPLL_DVO_2X_MODE;
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) && if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
intel_panel_use_ssc(dev_priv) && num_connectors < 2) intel_panel_use_ssc(dev_priv) && num_connectors < 2)
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
else else
...@@ -6065,7 +6076,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) ...@@ -6065,7 +6076,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
crtc_vtotal -= 1; crtc_vtotal -= 1;
crtc_vblank_end -= 1; crtc_vblank_end -= 1;
if (intel_pipe_has_type(&intel_crtc->base, INTEL_OUTPUT_SDVO)) if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO))
vsyncshift = (adjusted_mode->crtc_htotal - 1) / 2; vsyncshift = (adjusted_mode->crtc_htotal - 1) / 2;
else else
vsyncshift = adjusted_mode->crtc_hsync_start - vsyncshift = adjusted_mode->crtc_hsync_start -
...@@ -6223,7 +6234,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) ...@@ -6223,7 +6234,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
if (INTEL_INFO(dev)->gen < 4 || if (INTEL_INFO(dev)->gen < 4 ||
intel_pipe_has_type(&intel_crtc->base, INTEL_OUTPUT_SDVO)) intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO))
pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
else else
pipeconf |= PIPECONF_INTERLACE_W_SYNC_SHIFT; pipeconf |= PIPECONF_INTERLACE_W_SYNC_SHIFT;
...@@ -6237,13 +6248,12 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) ...@@ -6237,13 +6248,12 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
POSTING_READ(PIPECONF(intel_crtc->pipe)); POSTING_READ(PIPECONF(intel_crtc->pipe));
} }
static int i9xx_crtc_mode_set(struct drm_crtc *crtc, static int i9xx_crtc_mode_set(struct intel_crtc *crtc,
int x, int y, int x, int y,
struct drm_framebuffer *fb) struct drm_framebuffer *fb)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int refclk, num_connectors = 0; int refclk, num_connectors = 0;
intel_clock_t clock, reduced_clock; intel_clock_t clock, reduced_clock;
bool ok, has_reduced_clock = false; bool ok, has_reduced_clock = false;
...@@ -6251,7 +6261,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, ...@@ -6251,7 +6261,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
struct intel_encoder *encoder; struct intel_encoder *encoder;
const intel_limit_t *limit; const intel_limit_t *limit;
for_each_encoder_on_crtc(dev, crtc, encoder) { for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
switch (encoder->type) { switch (encoder->type) {
case INTEL_OUTPUT_LVDS: case INTEL_OUTPUT_LVDS:
is_lvds = true; is_lvds = true;
...@@ -6267,7 +6277,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, ...@@ -6267,7 +6277,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
if (is_dsi) if (is_dsi)
return 0; return 0;
if (!intel_crtc->config.clock_set) { if (!crtc->config.clock_set) {
refclk = i9xx_get_refclk(crtc, num_connectors); refclk = i9xx_get_refclk(crtc, num_connectors);
/* /*
...@@ -6278,7 +6288,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, ...@@ -6278,7 +6288,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
*/ */
limit = intel_limit(crtc, refclk); limit = intel_limit(crtc, refclk);
ok = dev_priv->display.find_dpll(limit, crtc, ok = dev_priv->display.find_dpll(limit, crtc,
intel_crtc->config.port_clock, crtc->config.port_clock,
refclk, NULL, &clock); refclk, NULL, &clock);
if (!ok) { if (!ok) {
DRM_ERROR("Couldn't find PLL settings for mode!\n"); DRM_ERROR("Couldn't find PLL settings for mode!\n");
...@@ -6299,23 +6309,23 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, ...@@ -6299,23 +6309,23 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
&reduced_clock); &reduced_clock);
} }
/* Compat-code for transition, will disappear. */ /* Compat-code for transition, will disappear. */
intel_crtc->config.dpll.n = clock.n; crtc->config.dpll.n = clock.n;
intel_crtc->config.dpll.m1 = clock.m1; crtc->config.dpll.m1 = clock.m1;
intel_crtc->config.dpll.m2 = clock.m2; crtc->config.dpll.m2 = clock.m2;
intel_crtc->config.dpll.p1 = clock.p1; crtc->config.dpll.p1 = clock.p1;
intel_crtc->config.dpll.p2 = clock.p2; crtc->config.dpll.p2 = clock.p2;
} }
if (IS_GEN2(dev)) { if (IS_GEN2(dev)) {
i8xx_update_pll(intel_crtc, i8xx_update_pll(crtc,
has_reduced_clock ? &reduced_clock : NULL, has_reduced_clock ? &reduced_clock : NULL,
num_connectors); num_connectors);
} else if (IS_CHERRYVIEW(dev)) { } else if (IS_CHERRYVIEW(dev)) {
chv_update_pll(intel_crtc); chv_update_pll(crtc);
} else if (IS_VALLEYVIEW(dev)) { } else if (IS_VALLEYVIEW(dev)) {
vlv_update_pll(intel_crtc); vlv_update_pll(crtc);
} else { } else {
i9xx_update_pll(intel_crtc, i9xx_update_pll(crtc,
has_reduced_clock ? &reduced_clock : NULL, has_reduced_clock ? &reduced_clock : NULL,
num_connectors); num_connectors);
} }
...@@ -7103,18 +7113,12 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, ...@@ -7103,18 +7113,12 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder; struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int refclk; int refclk;
const intel_limit_t *limit; const intel_limit_t *limit;
bool ret, is_lvds = false; bool ret, is_lvds = false;
for_each_encoder_on_crtc(dev, crtc, intel_encoder) { is_lvds = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_LVDS);
switch (intel_encoder->type) {
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
}
}
refclk = ironlake_get_refclk(crtc); refclk = ironlake_get_refclk(crtc);
...@@ -7123,9 +7127,9 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, ...@@ -7123,9 +7127,9 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
* refclk, or FALSE. The returned values represent the clock equation: * refclk, or FALSE. The returned values represent the clock equation:
* reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
*/ */
limit = intel_limit(crtc, refclk); limit = intel_limit(intel_crtc, refclk);
ret = dev_priv->display.find_dpll(limit, crtc, ret = dev_priv->display.find_dpll(limit, intel_crtc,
to_intel_crtc(crtc)->config.port_clock, intel_crtc->config.port_clock,
refclk, NULL, clock); refclk, NULL, clock);
if (!ret) if (!ret)
return false; return false;
...@@ -7138,7 +7142,7 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, ...@@ -7138,7 +7142,7 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
* downclock feature. * downclock feature.
*/ */
*has_reduced_clock = *has_reduced_clock =
dev_priv->display.find_dpll(limit, crtc, dev_priv->display.find_dpll(limit, intel_crtc,
dev_priv->lvds_downclock, dev_priv->lvds_downclock,
refclk, clock, refclk, clock,
reduced_clock); reduced_clock);
...@@ -7248,78 +7252,67 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, ...@@ -7248,78 +7252,67 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
return dpll | DPLL_VCO_ENABLE; return dpll | DPLL_VCO_ENABLE;
} }
static int ironlake_crtc_mode_set(struct drm_crtc *crtc, static int ironlake_crtc_mode_set(struct intel_crtc *crtc,
int x, int y, int x, int y,
struct drm_framebuffer *fb) struct drm_framebuffer *fb)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->base.dev;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int num_connectors = 0;
intel_clock_t clock, reduced_clock; intel_clock_t clock, reduced_clock;
u32 dpll = 0, fp = 0, fp2 = 0; u32 dpll = 0, fp = 0, fp2 = 0;
bool ok, has_reduced_clock = false; bool ok, has_reduced_clock = false;
bool is_lvds = false; bool is_lvds = false;
struct intel_encoder *encoder;
struct intel_shared_dpll *pll; struct intel_shared_dpll *pll;
for_each_encoder_on_crtc(dev, crtc, encoder) { is_lvds = intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS);
switch (encoder->type) {
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
}
num_connectors++;
}
WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)), WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
"Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev)); "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
ok = ironlake_compute_clocks(crtc, &clock, ok = ironlake_compute_clocks(&crtc->base, &clock,
&has_reduced_clock, &reduced_clock); &has_reduced_clock, &reduced_clock);
if (!ok && !intel_crtc->config.clock_set) { if (!ok && !crtc->config.clock_set) {
DRM_ERROR("Couldn't find PLL settings for mode!\n"); DRM_ERROR("Couldn't find PLL settings for mode!\n");
return -EINVAL; return -EINVAL;
} }
/* Compat-code for transition, will disappear. */ /* Compat-code for transition, will disappear. */
if (!intel_crtc->config.clock_set) { if (!crtc->config.clock_set) {
intel_crtc->config.dpll.n = clock.n; crtc->config.dpll.n = clock.n;
intel_crtc->config.dpll.m1 = clock.m1; crtc->config.dpll.m1 = clock.m1;
intel_crtc->config.dpll.m2 = clock.m2; crtc->config.dpll.m2 = clock.m2;
intel_crtc->config.dpll.p1 = clock.p1; crtc->config.dpll.p1 = clock.p1;
intel_crtc->config.dpll.p2 = clock.p2; crtc->config.dpll.p2 = clock.p2;
} }
/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
if (intel_crtc->config.has_pch_encoder) { if (crtc->config.has_pch_encoder) {
fp = i9xx_dpll_compute_fp(&intel_crtc->config.dpll); fp = i9xx_dpll_compute_fp(&crtc->config.dpll);
if (has_reduced_clock) if (has_reduced_clock)
fp2 = i9xx_dpll_compute_fp(&reduced_clock); fp2 = i9xx_dpll_compute_fp(&reduced_clock);
dpll = ironlake_compute_dpll(intel_crtc, dpll = ironlake_compute_dpll(crtc,
&fp, &reduced_clock, &fp, &reduced_clock,
has_reduced_clock ? &fp2 : NULL); has_reduced_clock ? &fp2 : NULL);
intel_crtc->config.dpll_hw_state.dpll = dpll; crtc->config.dpll_hw_state.dpll = dpll;
intel_crtc->config.dpll_hw_state.fp0 = fp; crtc->config.dpll_hw_state.fp0 = fp;
if (has_reduced_clock) if (has_reduced_clock)
intel_crtc->config.dpll_hw_state.fp1 = fp2; crtc->config.dpll_hw_state.fp1 = fp2;
else else
intel_crtc->config.dpll_hw_state.fp1 = fp; crtc->config.dpll_hw_state.fp1 = fp;
pll = intel_get_shared_dpll(intel_crtc); pll = intel_get_shared_dpll(crtc);
if (pll == NULL) { if (pll == NULL) {
DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
pipe_name(intel_crtc->pipe)); pipe_name(crtc->pipe));
return -EINVAL; return -EINVAL;
} }
} else } else
intel_put_shared_dpll(intel_crtc); intel_put_shared_dpll(crtc);
if (is_lvds && has_reduced_clock && i915.powersave) if (is_lvds && has_reduced_clock && i915.powersave)
intel_crtc->lowfreq_avail = true; crtc->lowfreq_avail = true;
else else
intel_crtc->lowfreq_avail = false; crtc->lowfreq_avail = false;
return 0; return 0;
} }
...@@ -7813,16 +7806,14 @@ static void haswell_modeset_global_resources(struct drm_device *dev) ...@@ -7813,16 +7806,14 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
modeset_update_crtc_power_domains(dev); modeset_update_crtc_power_domains(dev);
} }
static int haswell_crtc_mode_set(struct drm_crtc *crtc, static int haswell_crtc_mode_set(struct intel_crtc *crtc,
int x, int y, int x, int y,
struct drm_framebuffer *fb) struct drm_framebuffer *fb)
{ {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); if (!intel_ddi_pll_select(crtc))
if (!intel_ddi_pll_select(intel_crtc))
return -EINVAL; return -EINVAL;
intel_crtc->lowfreq_avail = false; crtc->lowfreq_avail = false;
return 0; return 0;
} }
...@@ -8062,6 +8053,7 @@ static void haswell_write_eld(struct drm_connector *connector, ...@@ -8062,6 +8053,7 @@ static void haswell_write_eld(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct drm_i915_private *dev_priv = connector->dev->dev_private; struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
uint8_t *eld = connector->eld; uint8_t *eld = connector->eld;
uint32_t eldv; uint32_t eldv;
uint32_t i; uint32_t i;
...@@ -8102,7 +8094,7 @@ static void haswell_write_eld(struct drm_connector *connector, ...@@ -8102,7 +8094,7 @@ static void haswell_write_eld(struct drm_connector *connector,
eldv = AUDIO_ELD_VALID_A << (pipe * 4); eldv = AUDIO_ELD_VALID_A << (pipe * 4);
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) {
DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */
I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */
...@@ -8145,6 +8137,7 @@ static void ironlake_write_eld(struct drm_connector *connector, ...@@ -8145,6 +8137,7 @@ static void ironlake_write_eld(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct drm_i915_private *dev_priv = connector->dev->dev_private; struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
uint8_t *eld = connector->eld; uint8_t *eld = connector->eld;
uint32_t eldv; uint32_t eldv;
uint32_t i; uint32_t i;
...@@ -8198,7 +8191,7 @@ static void ironlake_write_eld(struct drm_connector *connector, ...@@ -8198,7 +8191,7 @@ static void ironlake_write_eld(struct drm_connector *connector,
eldv = IBX_ELD_VALIDB << ((i - 1) * 4); eldv = IBX_ELD_VALIDB << ((i - 1) * 4);
} }
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) {
DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */
I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */
...@@ -8350,6 +8343,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) ...@@ -8350,6 +8343,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
cntl |= CURSOR_PIPE_CSC_ENABLE; cntl |= CURSOR_PIPE_CSC_ENABLE;
} }
if (to_intel_plane(crtc->cursor)->rotation == BIT(DRM_ROTATE_180))
cntl |= CURSOR_ROTATE_180;
if (intel_crtc->cursor_cntl != cntl) { if (intel_crtc->cursor_cntl != cntl) {
I915_WRITE(CURCNTR(pipe), cntl); I915_WRITE(CURCNTR(pipe), cntl);
POSTING_READ(CURCNTR(pipe)); POSTING_READ(CURCNTR(pipe));
...@@ -8407,6 +8403,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, ...@@ -8407,6 +8403,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
I915_WRITE(CURPOS(pipe), pos); I915_WRITE(CURPOS(pipe), pos);
/* ILK+ do this automagically */
if (HAS_GMCH_DISPLAY(dev) &&
to_intel_plane(crtc->cursor)->rotation == BIT(DRM_ROTATE_180)) {
base += (intel_crtc->cursor_height *
intel_crtc->cursor_width - 1) * 4;
}
if (IS_845G(dev) || IS_I865G(dev)) if (IS_845G(dev) || IS_I865G(dev))
i845_update_cursor(crtc, base); i845_update_cursor(crtc, base);
else else
...@@ -8450,13 +8453,6 @@ static bool cursor_size_ok(struct drm_device *dev, ...@@ -8450,13 +8453,6 @@ static bool cursor_size_ok(struct drm_device *dev,
return true; return true;
} }
/*
* intel_crtc_cursor_set_obj - Set cursor to specified GEM object
*
* Note that the object's reference will be consumed if the update fails. If
* the update succeeds, the reference of the old object (if any) will be
* consumed.
*/
static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc, static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
struct drm_i915_gem_object *obj, struct drm_i915_gem_object *obj,
uint32_t width, uint32_t height) uint32_t width, uint32_t height)
...@@ -8465,7 +8461,7 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc, ...@@ -8465,7 +8461,7 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
enum pipe pipe = intel_crtc->pipe; enum pipe pipe = intel_crtc->pipe;
unsigned old_width, stride; unsigned old_width;
uint32_t addr; uint32_t addr;
int ret; int ret;
...@@ -8477,30 +8473,11 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc, ...@@ -8477,30 +8473,11 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
goto finish; goto finish;
} }
/* Check for which cursor types we support */
if (!cursor_size_ok(dev, width, height)) {
DRM_DEBUG("Cursor dimension not supported\n");
return -EINVAL;
}
stride = roundup_pow_of_two(width) * 4;
if (obj->base.size < stride * height) {
DRM_DEBUG_KMS("buffer is too small\n");
ret = -ENOMEM;
goto fail;
}
/* we only need to pin inside GTT if cursor is non-phy */ /* we only need to pin inside GTT if cursor is non-phy */
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
if (!INTEL_INFO(dev)->cursor_needs_physical) { if (!INTEL_INFO(dev)->cursor_needs_physical) {
unsigned alignment; unsigned alignment;
if (obj->tiling_mode) {
DRM_DEBUG_KMS("cursor cannot be tiled\n");
ret = -EINVAL;
goto fail_locked;
}
/* /*
* Global gtt pte registers are special registers which actually * Global gtt pte registers are special registers which actually
* forward writes to a chunk of system memory. Which means that * forward writes to a chunk of system memory. Which means that
...@@ -8576,8 +8553,6 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc, ...@@ -8576,8 +8553,6 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
i915_gem_object_unpin_from_display_plane(obj); i915_gem_object_unpin_from_display_plane(obj);
fail_locked: fail_locked:
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
fail:
drm_gem_object_unreference_unlocked(&obj->base);
return ret; return ret;
} }
...@@ -10921,7 +10896,7 @@ static void update_scanline_offset(struct intel_crtc *crtc) ...@@ -10921,7 +10896,7 @@ static void update_scanline_offset(struct intel_crtc *crtc)
crtc->scanline_offset = vtotal - 1; crtc->scanline_offset = vtotal - 1;
} else if (HAS_DDI(dev) && } else if (HAS_DDI(dev) &&
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI)) { intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
crtc->scanline_offset = 2; crtc->scanline_offset = 2;
} else } else
crtc->scanline_offset = 1; crtc->scanline_offset = 1;
...@@ -11041,8 +11016,7 @@ static int __intel_set_mode(struct drm_crtc *crtc, ...@@ -11041,8 +11016,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
crtc->x = x; crtc->x = x;
crtc->y = y; crtc->y = y;
ret = dev_priv->display.crtc_mode_set(&intel_crtc->base, ret = dev_priv->display.crtc_mode_set(intel_crtc, x, y, fb);
x, y, fb);
if (ret) if (ret)
goto done; goto done;
} }
...@@ -11666,12 +11640,23 @@ intel_check_primary_plane(struct drm_plane *plane, ...@@ -11666,12 +11640,23 @@ intel_check_primary_plane(struct drm_plane *plane,
struct drm_rect *dest = &state->dst; struct drm_rect *dest = &state->dst;
struct drm_rect *src = &state->src; struct drm_rect *src = &state->src;
const struct drm_rect *clip = &state->clip; const struct drm_rect *clip = &state->clip;
int ret;
return drm_plane_helper_check_update(plane, crtc, fb, ret = drm_plane_helper_check_update(plane, crtc, fb,
src, dest, clip, src, dest, clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
false, true, &state->visible); false, true, &state->visible);
if (ret)
return ret;
/* no fb bound */
if (state->visible && !fb) {
DRM_ERROR("No FB bound\n");
return -EINVAL;
}
return 0;
} }
static int static int
...@@ -11683,6 +11668,8 @@ intel_commit_primary_plane(struct drm_plane *plane, ...@@ -11683,6 +11668,8 @@ intel_commit_primary_plane(struct drm_plane *plane,
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
enum pipe pipe = intel_crtc->pipe;
struct drm_framebuffer *old_fb = plane->fb;
struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
struct intel_plane *intel_plane = to_intel_plane(plane); struct intel_plane *intel_plane = to_intel_plane(plane);
...@@ -11691,76 +11678,100 @@ intel_commit_primary_plane(struct drm_plane *plane, ...@@ -11691,76 +11678,100 @@ intel_commit_primary_plane(struct drm_plane *plane,
intel_crtc_wait_for_pending_flips(crtc); intel_crtc_wait_for_pending_flips(crtc);
/* if (intel_crtc_has_pending_flip(crtc)) {
* If clipping results in a non-visible primary plane, we'll disable DRM_ERROR("pipe is still busy with an old pageflip\n");
* the primary plane. Note that this is a bit different than what return -EBUSY;
* happens if userspace explicitly disables the plane by passing fb=0 }
* because plane->fb still gets set and pinned.
*/ if (plane->fb != fb) {
if (!state->visible) {
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
if (ret == 0)
i915_gem_track_fb(old_obj, obj,
INTEL_FRONTBUFFER_PRIMARY(pipe));
mutex_unlock(&dev->struct_mutex);
if (ret != 0) {
DRM_DEBUG_KMS("pin & fence failed\n");
return ret;
}
}
crtc->primary->fb = fb;
crtc->x = src->x1;
crtc->y = src->y1;
intel_plane->crtc_x = state->orig_dst.x1;
intel_plane->crtc_y = state->orig_dst.y1;
intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
intel_plane->src_x = state->orig_src.x1;
intel_plane->src_y = state->orig_src.y1;
intel_plane->src_w = drm_rect_width(&state->orig_src);
intel_plane->src_h = drm_rect_height(&state->orig_src);
intel_plane->obj = obj;
if (intel_crtc->active) {
/* /*
* Try to pin the new fb first so that we can bail out if we * FBC does not work on some platforms for rotated
* fail. * planes, so disable it when rotation is not 0 and
* update it when rotation is set back to 0.
*
* FIXME: This is redundant with the fbc update done in
* the primary plane enable function except that that
* one is done too late. We eventually need to unify
* this.
*/ */
if (plane->fb != fb) { if (intel_crtc->primary_enabled &&
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) &&
if (ret) { dev_priv->fbc.plane == intel_crtc->plane &&
mutex_unlock(&dev->struct_mutex); intel_plane->rotation != BIT(DRM_ROTATE_0)) {
return ret; intel_disable_fbc(dev);
}
} }
i915_gem_track_fb(old_obj, obj, if (state->visible) {
INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); bool was_enabled = intel_crtc->primary_enabled;
if (intel_crtc->primary_enabled)
intel_disable_primary_hw_plane(plane, crtc);
/* FIXME: kill this fastboot hack */
intel_update_pipe_size(intel_crtc);
if (plane->fb != fb) intel_crtc->primary_enabled = true;
if (plane->fb)
intel_unpin_fb_obj(old_obj);
mutex_unlock(&dev->struct_mutex); dev_priv->display.update_primary_plane(crtc, plane->fb,
crtc->x, crtc->y);
} else {
if (intel_crtc && intel_crtc->active &&
intel_crtc->primary_enabled) {
/* /*
* FBC does not work on some platforms for rotated * BDW signals flip done immediately if the plane
* planes, so disable it when rotation is not 0 and * is disabled, even if the plane enable is already
* update it when rotation is set back to 0. * armed to occur at the next vblank :(
*
* FIXME: This is redundant with the fbc update done in
* the primary plane enable function except that that
* one is done too late. We eventually need to unify
* this.
*/ */
if (INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && if (IS_BROADWELL(dev) && !was_enabled)
dev_priv->fbc.plane == intel_crtc->plane && intel_wait_for_vblank(dev, intel_crtc->pipe);
intel_plane->rotation != BIT(DRM_ROTATE_0)) { } else {
intel_disable_fbc(dev); /*
} * If clipping results in a non-visible primary plane,
* we'll disable the primary plane. Note that this is
* a bit different than what happens if userspace
* explicitly disables the plane by passing fb=0
* because plane->fb still gets set and pinned.
*/
intel_disable_primary_hw_plane(plane, crtc);
} }
ret = intel_pipe_set_base(crtc, src->x1, src->y1, fb);
if (ret)
return ret;
if (!intel_crtc->primary_enabled) intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
intel_enable_primary_hw_plane(plane, crtc);
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
mutex_unlock(&dev->struct_mutex);
} }
intel_plane->crtc_x = state->orig_dst.x1; if (old_fb && old_fb != fb) {
intel_plane->crtc_y = state->orig_dst.y1; if (intel_crtc->active)
intel_plane->crtc_w = drm_rect_width(&state->orig_dst); intel_wait_for_vblank(dev, intel_crtc->pipe);
intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
intel_plane->src_x = state->orig_src.x1; mutex_lock(&dev->struct_mutex);
intel_plane->src_y = state->orig_src.y1; intel_unpin_fb_obj(old_obj);
intel_plane->src_w = drm_rect_width(&state->orig_src); mutex_unlock(&dev->struct_mutex);
intel_plane->src_h = drm_rect_height(&state->orig_src); }
intel_plane->obj = obj;
return 0; return 0;
} }
...@@ -11886,16 +11897,55 @@ intel_check_cursor_plane(struct drm_plane *plane, ...@@ -11886,16 +11897,55 @@ intel_check_cursor_plane(struct drm_plane *plane,
struct intel_plane_state *state) struct intel_plane_state *state)
{ {
struct drm_crtc *crtc = state->crtc; struct drm_crtc *crtc = state->crtc;
struct drm_device *dev = crtc->dev;
struct drm_framebuffer *fb = state->fb; struct drm_framebuffer *fb = state->fb;
struct drm_rect *dest = &state->dst; struct drm_rect *dest = &state->dst;
struct drm_rect *src = &state->src; struct drm_rect *src = &state->src;
const struct drm_rect *clip = &state->clip; const struct drm_rect *clip = &state->clip;
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
int crtc_w, crtc_h;
unsigned stride;
int ret;
return drm_plane_helper_check_update(plane, crtc, fb, ret = drm_plane_helper_check_update(plane, crtc, fb,
src, dest, clip, src, dest, clip,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING,
true, true, &state->visible); true, true, &state->visible);
if (ret)
return ret;
/* if we want to turn off the cursor ignore width and height */
if (!obj)
return 0;
/* Check for which cursor types we support */
crtc_w = drm_rect_width(&state->orig_dst);
crtc_h = drm_rect_height(&state->orig_dst);
if (!cursor_size_ok(dev, crtc_w, crtc_h)) {
DRM_DEBUG("Cursor dimension not supported\n");
return -EINVAL;
}
stride = roundup_pow_of_two(crtc_w) * 4;
if (obj->base.size < stride * crtc_h) {
DRM_DEBUG_KMS("buffer is too small\n");
return -ENOMEM;
}
if (fb == crtc->cursor->fb)
return 0;
/* we only need to pin inside GTT if cursor is non-phy */
mutex_lock(&dev->struct_mutex);
if (!INTEL_INFO(dev)->cursor_needs_physical && obj->tiling_mode) {
DRM_DEBUG_KMS("cursor cannot be tiled\n");
ret = -EINVAL;
}
mutex_unlock(&dev->struct_mutex);
return ret;
} }
static int static int
...@@ -11970,6 +12020,7 @@ static const struct drm_plane_funcs intel_cursor_plane_funcs = { ...@@ -11970,6 +12020,7 @@ static const struct drm_plane_funcs intel_cursor_plane_funcs = {
.update_plane = intel_cursor_plane_update, .update_plane = intel_cursor_plane_update,
.disable_plane = intel_cursor_plane_disable, .disable_plane = intel_cursor_plane_disable,
.destroy = intel_plane_destroy, .destroy = intel_plane_destroy,
.set_property = intel_plane_set_property,
}; };
static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
...@@ -11985,12 +12036,26 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, ...@@ -11985,12 +12036,26 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
cursor->max_downscale = 1; cursor->max_downscale = 1;
cursor->pipe = pipe; cursor->pipe = pipe;
cursor->plane = pipe; cursor->plane = pipe;
cursor->rotation = BIT(DRM_ROTATE_0);
drm_universal_plane_init(dev, &cursor->base, 0, drm_universal_plane_init(dev, &cursor->base, 0,
&intel_cursor_plane_funcs, &intel_cursor_plane_funcs,
intel_cursor_formats, intel_cursor_formats,
ARRAY_SIZE(intel_cursor_formats), ARRAY_SIZE(intel_cursor_formats),
DRM_PLANE_TYPE_CURSOR); DRM_PLANE_TYPE_CURSOR);
if (INTEL_INFO(dev)->gen >= 4) {
if (!dev->mode_config.rotation_property)
dev->mode_config.rotation_property =
drm_mode_create_rotation_property(dev,
BIT(DRM_ROTATE_0) |
BIT(DRM_ROTATE_180));
if (dev->mode_config.rotation_property)
drm_object_attach_property(&cursor->base.base,
dev->mode_config.rotation_property,
cursor->rotation);
}
return &cursor->base; return &cursor->base;
} }
...@@ -12157,7 +12222,7 @@ static bool intel_crt_present(struct drm_device *dev) ...@@ -12157,7 +12222,7 @@ static bool intel_crt_present(struct drm_device *dev)
if (INTEL_INFO(dev)->gen >= 9) if (INTEL_INFO(dev)->gen >= 9)
return false; return false;
if (IS_ULT(dev)) if (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
return false; return false;
if (IS_CHERRYVIEW(dev)) if (IS_CHERRYVIEW(dev))
......
...@@ -278,7 +278,7 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) ...@@ -278,7 +278,7 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
} }
static enum drm_connector_status static enum drm_connector_status
intel_mst_port_dp_detect(struct drm_connector *connector) intel_dp_mst_detect(struct drm_connector *connector, bool force)
{ {
struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_dp *intel_dp = intel_connector->mst_port; struct intel_dp *intel_dp = intel_connector->mst_port;
...@@ -286,14 +286,6 @@ intel_mst_port_dp_detect(struct drm_connector *connector) ...@@ -286,14 +286,6 @@ intel_mst_port_dp_detect(struct drm_connector *connector)
return drm_dp_mst_detect_port(&intel_dp->mst_mgr, intel_connector->port); return drm_dp_mst_detect_port(&intel_dp->mst_mgr, intel_connector->port);
} }
static enum drm_connector_status
intel_dp_mst_detect(struct drm_connector *connector, bool force)
{
enum drm_connector_status status;
status = intel_mst_port_dp_detect(connector);
return status;
}
static int static int
intel_dp_mst_set_property(struct drm_connector *connector, intel_dp_mst_set_property(struct drm_connector *connector,
struct drm_property *property, struct drm_property *property,
......
...@@ -755,12 +755,19 @@ static inline unsigned int intel_num_planes(struct intel_crtc *crtc) ...@@ -755,12 +755,19 @@ static inline unsigned int intel_num_planes(struct intel_crtc *crtc)
return INTEL_INFO(crtc->base.dev)->num_sprites[crtc->pipe] + 1; return INTEL_INFO(crtc->base.dev)->num_sprites[crtc->pipe] + 1;
} }
/* i915_irq.c */ /* intel_fifo_underrun.c */
bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
enum pipe pipe, bool enable); enum pipe pipe, bool enable);
bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev, bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
enum transcoder pch_transcoder, enum transcoder pch_transcoder,
bool enable); bool enable);
void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pipe);
void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum transcoder pch_transcoder);
void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv);
/* i915_irq.c */
void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
...@@ -779,7 +786,6 @@ static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv) ...@@ -779,7 +786,6 @@ static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
} }
int intel_get_crtc_scanline(struct intel_crtc *crtc); int intel_get_crtc_scanline(struct intel_crtc *crtc);
void i9xx_check_fifo_underruns(struct drm_device *dev);
void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv); void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv);
/* intel_crt.c */ /* intel_crt.c */
......
/*
* Copyright © 2014 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Daniel Vetter <daniel.vetter@ffwll.ch>
*
*/
#include "i915_drv.h"
#include "intel_drv.h"
/**
* DOC: fifo underrun handling
*
* The i915 driver checks for display fifo underruns using the interrupt signals
* provided by the hardware. This is enabled by default and fairly useful to
* debug display issues, especially watermark settings.
*
* If an underrun is detected this is logged into dmesg. To avoid flooding logs
* and occupying the cpu underrun interrupts are disabled after the first
* occurrence until the next modeset on a given pipe.
*
* Note that underrun detection on gmch platforms is a bit more ugly since there
* is no interrupt (despite that the signalling bit is in the PIPESTAT pipe
* interrupt register). Also on some other platforms underrun interrupts are
* shared, which means that if we detect an underrun we need to disable underrun
* reporting on all pipes.
*
* The code also supports underrun detection on the PCH transcoder.
*/
static bool ivb_can_enable_err_int(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *crtc;
enum pipe pipe;
assert_spin_locked(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
if (crtc->cpu_fifo_underrun_disabled)
return false;
}
return true;
}
static bool cpt_can_enable_serr_int(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe;
struct intel_crtc *crtc;
assert_spin_locked(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
if (crtc->pch_fifo_underrun_disabled)
return false;
}
return true;
}
/**
* i9xx_check_fifo_underruns - check for fifo underruns
* @dev_priv: i915 device instance
*
* This function checks for fifo underruns on GMCH platforms. This needs to be
* done manually on modeset to make sure that we catch all underruns since they
* do not generate an interrupt by themselves on these platforms.
*/
void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv)
{
struct intel_crtc *crtc;
spin_lock_irq(&dev_priv->irq_lock);
for_each_intel_crtc(dev_priv->dev, crtc) {
u32 reg = PIPESTAT(crtc->pipe);
u32 pipestat;
if (crtc->cpu_fifo_underrun_disabled)
continue;
pipestat = I915_READ(reg) & 0xffff0000;
if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0)
continue;
I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
POSTING_READ(reg);
DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
}
spin_unlock_irq(&dev_priv->irq_lock);
}
static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe,
bool enable, bool old)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg = PIPESTAT(pipe);
u32 pipestat = I915_READ(reg) & 0xffff0000;
assert_spin_locked(&dev_priv->irq_lock);
if (enable) {
I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
POSTING_READ(reg);
} else {
if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS)
DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
}
}
static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t bit = (pipe == PIPE_A) ? DE_PIPEA_FIFO_UNDERRUN :
DE_PIPEB_FIFO_UNDERRUN;
if (enable)
ironlake_enable_display_irq(dev_priv, bit);
else
ironlake_disable_display_irq(dev_priv, bit);
}
static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe,
bool enable, bool old)
{
struct drm_i915_private *dev_priv = dev->dev_private;
if (enable) {
I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
if (!ivb_can_enable_err_int(dev))
return;
ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
} else {
ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
if (old &&
I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
DRM_ERROR("uncleared fifo underrun on pipe %c\n",
pipe_name(pipe));
}
}
}
static void broadwell_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
assert_spin_locked(&dev_priv->irq_lock);
if (enable)
dev_priv->de_irq_mask[pipe] &= ~GEN8_PIPE_FIFO_UNDERRUN;
else
dev_priv->de_irq_mask[pipe] |= GEN8_PIPE_FIFO_UNDERRUN;
I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
}
static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
enum transcoder pch_transcoder,
bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t bit = (pch_transcoder == TRANSCODER_A) ?
SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
if (enable)
ibx_enable_display_interrupt(dev_priv, bit);
else
ibx_disable_display_interrupt(dev_priv, bit);
}
static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
enum transcoder pch_transcoder,
bool enable, bool old)
{
struct drm_i915_private *dev_priv = dev->dev_private;
if (enable) {
I915_WRITE(SERR_INT,
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
if (!cpt_can_enable_serr_int(dev))
return;
ibx_enable_display_interrupt(dev_priv, SDE_ERROR_CPT);
} else {
ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
if (old && I915_READ(SERR_INT) &
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
transcoder_name(pch_transcoder));
}
}
}
static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
bool old;
assert_spin_locked(&dev_priv->irq_lock);
old = !intel_crtc->cpu_fifo_underrun_disabled;
intel_crtc->cpu_fifo_underrun_disabled = !enable;
if (HAS_GMCH_DISPLAY(dev))
i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
else if (IS_GEN5(dev) || IS_GEN6(dev))
ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
else if (IS_GEN7(dev))
ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old);
else if (IS_GEN8(dev) || IS_GEN9(dev))
broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
return old;
}
/**
* intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrrun reporting state
* @dev_priv: i915 device instance
* @pipe: (CPU) pipe to set state for
* @enable: whether underruns should be reported or not
*
* This function sets the fifo underrun state for @pipe. It is used in the
* modeset code to avoid false positives since on many platforms underruns are
* expected when disabling or enabling the pipe.
*
* Notice that on some platforms disabling underrun reports for one pipe
* disables for all due to shared interrupts. Actual reporting is still per-pipe
* though.
*
* Returns the previous state of underrun reporting.
*/
bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
enum pipe pipe, bool enable)
{
unsigned long flags;
bool ret;
spin_lock_irqsave(&dev_priv->irq_lock, flags);
ret = __intel_set_cpu_fifo_underrun_reporting(dev_priv->dev, pipe,
enable);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
return ret;
}
static bool
__cpu_fifo_underrun_reporting_enabled(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
return !intel_crtc->cpu_fifo_underrun_disabled;
}
/**
* intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state
* @dev_priv: i915 device instance
* @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
* @enable: whether underruns should be reported or not
*
* This function makes us disable or enable PCH fifo underruns for a specific
* PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO
* underrun reporting for one transcoder may also disable all the other PCH
* error interruts for the other transcoders, due to the fact that there's just
* one interrupt mask/enable bit for all the transcoders.
*
* Returns the previous state of underrun reporting.
*/
bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
enum transcoder pch_transcoder,
bool enable)
{
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
unsigned long flags;
bool old;
/*
* NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
* has only one pch transcoder A that all pipes can use. To avoid racy
* pch transcoder -> pipe lookups from interrupt code simply store the
* underrun statistics in crtc A. Since we never expose this anywhere
* nor use it outside of the fifo underrun code here using the "wrong"
* crtc on LPT won't cause issues.
*/
spin_lock_irqsave(&dev_priv->irq_lock, flags);
old = !intel_crtc->pch_fifo_underrun_disabled;
intel_crtc->pch_fifo_underrun_disabled = !enable;
if (HAS_PCH_IBX(dev_priv->dev))
ibx_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
enable);
else
cpt_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
enable, old);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
return old;
}
/**
* intel_pch_fifo_underrun_irq_handler - handle PCH fifo underrun interrupt
* @dev_priv: i915 device instance
* @pipe: (CPU) pipe to set state for
*
* This handles a CPU fifo underrun interrupt, generating an underrun warning
* into dmesg if underrun reporting is enabled and then disables the underrun
* interrupt to avoid an irq storm.
*/
void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
/* GMCH can't disable fifo underruns, filter them. */
if (HAS_GMCH_DISPLAY(dev_priv->dev) &&
!__cpu_fifo_underrun_reporting_enabled(dev_priv, pipe))
return;
if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false))
DRM_ERROR("CPU pipe %c FIFO underrun\n",
pipe_name(pipe));
}
/**
* intel_pch_fifo_underrun_irq_handler - handle PCH fifo underrun interrupt
* @dev_priv: i915 device instance
* @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
*
* This handles a PCH fifo underrun interrupt, generating an underrun warning
* into dmesg if underrun reporting is enabled and then disables the underrun
* interrupt to avoid an irq storm.
*/
void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum transcoder pch_transcoder)
{
if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
false))
DRM_ERROR("PCH transcoder %c FIFO underrun\n",
transcoder_name(pch_transcoder));
}
...@@ -775,8 +775,9 @@ static void bdw_enable_backlight(struct intel_connector *connector) ...@@ -775,8 +775,9 @@ static void bdw_enable_backlight(struct intel_connector *connector)
if (panel->backlight.active_low_pwm) if (panel->backlight.active_low_pwm)
pch_ctl1 |= BLM_PCH_POLARITY; pch_ctl1 |= BLM_PCH_POLARITY;
/* BDW always uses the pch pwm controls. */ /* After LPT, override is the default. */
pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; if (HAS_PCH_LPT(dev_priv))
pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
POSTING_READ(BLC_PWM_PCH_CTL1); POSTING_READ(BLC_PWM_PCH_CTL1);
......
...@@ -1345,6 +1345,7 @@ static bool vlv_compute_drain_latency(struct drm_crtc *crtc, ...@@ -1345,6 +1345,7 @@ static bool vlv_compute_drain_latency(struct drm_crtc *crtc,
int *prec_mult, int *prec_mult,
int *drain_latency) int *drain_latency)
{ {
struct drm_device *dev = crtc->dev;
int entries; int entries;
int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
...@@ -1355,8 +1356,12 @@ static bool vlv_compute_drain_latency(struct drm_crtc *crtc, ...@@ -1355,8 +1356,12 @@ static bool vlv_compute_drain_latency(struct drm_crtc *crtc,
return false; return false;
entries = DIV_ROUND_UP(clock, 1000) * pixel_size; entries = DIV_ROUND_UP(clock, 1000) * pixel_size;
*prec_mult = (entries > 128) ? DRAIN_LATENCY_PRECISION_64 : if (IS_CHERRYVIEW(dev))
DRAIN_LATENCY_PRECISION_32; *prec_mult = (entries > 128) ? DRAIN_LATENCY_PRECISION_32 :
DRAIN_LATENCY_PRECISION_16;
else
*prec_mult = (entries > 128) ? DRAIN_LATENCY_PRECISION_64 :
DRAIN_LATENCY_PRECISION_32;
*drain_latency = (64 * (*prec_mult) * 4) / entries; *drain_latency = (64 * (*prec_mult) * 4) / entries;
if (*drain_latency > DRAIN_LATENCY_MASK) if (*drain_latency > DRAIN_LATENCY_MASK)
...@@ -1375,15 +1380,18 @@ static bool vlv_compute_drain_latency(struct drm_crtc *crtc, ...@@ -1375,15 +1380,18 @@ static bool vlv_compute_drain_latency(struct drm_crtc *crtc,
static void vlv_update_drain_latency(struct drm_crtc *crtc) static void vlv_update_drain_latency(struct drm_crtc *crtc)
{ {
struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pixel_size; int pixel_size;
int drain_latency; int drain_latency;
enum pipe pipe = intel_crtc->pipe; enum pipe pipe = intel_crtc->pipe;
int plane_prec, prec_mult, plane_dl; int plane_prec, prec_mult, plane_dl;
const int high_precision = IS_CHERRYVIEW(dev) ?
DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_64;
plane_dl = I915_READ(VLV_DDL(pipe)) & ~(DDL_PLANE_PRECISION_64 | plane_dl = I915_READ(VLV_DDL(pipe)) & ~(DDL_PLANE_PRECISION_HIGH |
DRAIN_LATENCY_MASK | DDL_CURSOR_PRECISION_64 | DRAIN_LATENCY_MASK | DDL_CURSOR_PRECISION_HIGH |
(DRAIN_LATENCY_MASK << DDL_CURSOR_SHIFT)); (DRAIN_LATENCY_MASK << DDL_CURSOR_SHIFT));
if (!intel_crtc_active(crtc)) { if (!intel_crtc_active(crtc)) {
...@@ -1394,9 +1402,9 @@ static void vlv_update_drain_latency(struct drm_crtc *crtc) ...@@ -1394,9 +1402,9 @@ static void vlv_update_drain_latency(struct drm_crtc *crtc)
/* Primary plane Drain Latency */ /* Primary plane Drain Latency */
pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */ pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */
if (vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, &drain_latency)) { if (vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, &drain_latency)) {
plane_prec = (prec_mult == DRAIN_LATENCY_PRECISION_64) ? plane_prec = (prec_mult == high_precision) ?
DDL_PLANE_PRECISION_64 : DDL_PLANE_PRECISION_HIGH :
DDL_PLANE_PRECISION_32; DDL_PLANE_PRECISION_LOW;
plane_dl |= plane_prec | drain_latency; plane_dl |= plane_prec | drain_latency;
} }
...@@ -1408,9 +1416,9 @@ static void vlv_update_drain_latency(struct drm_crtc *crtc) ...@@ -1408,9 +1416,9 @@ static void vlv_update_drain_latency(struct drm_crtc *crtc)
/* Program cursor DL only if it is enabled */ /* Program cursor DL only if it is enabled */
if (intel_crtc->cursor_base && if (intel_crtc->cursor_base &&
vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, &drain_latency)) { vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, &drain_latency)) {
plane_prec = (prec_mult == DRAIN_LATENCY_PRECISION_64) ? plane_prec = (prec_mult == high_precision) ?
DDL_CURSOR_PRECISION_64 : DDL_CURSOR_PRECISION_HIGH :
DDL_CURSOR_PRECISION_32; DDL_CURSOR_PRECISION_LOW;
plane_dl |= plane_prec | (drain_latency << DDL_CURSOR_SHIFT); plane_dl |= plane_prec | (drain_latency << DDL_CURSOR_SHIFT);
} }
...@@ -1578,15 +1586,17 @@ static void valleyview_update_sprite_wm(struct drm_plane *plane, ...@@ -1578,15 +1586,17 @@ static void valleyview_update_sprite_wm(struct drm_plane *plane,
int plane_prec; int plane_prec;
int sprite_dl; int sprite_dl;
int prec_mult; int prec_mult;
const int high_precision = IS_CHERRYVIEW(dev) ?
DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_64;
sprite_dl = I915_READ(VLV_DDL(pipe)) & ~(DDL_SPRITE_PRECISION_64(sprite) | sprite_dl = I915_READ(VLV_DDL(pipe)) & ~(DDL_SPRITE_PRECISION_HIGH(sprite) |
(DRAIN_LATENCY_MASK << DDL_SPRITE_SHIFT(sprite))); (DRAIN_LATENCY_MASK << DDL_SPRITE_SHIFT(sprite)));
if (enabled && vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, if (enabled && vlv_compute_drain_latency(crtc, pixel_size, &prec_mult,
&drain_latency)) { &drain_latency)) {
plane_prec = (prec_mult == DRAIN_LATENCY_PRECISION_64) ? plane_prec = (prec_mult == high_precision) ?
DDL_SPRITE_PRECISION_64(sprite) : DDL_SPRITE_PRECISION_HIGH(sprite) :
DDL_SPRITE_PRECISION_32(sprite); DDL_SPRITE_PRECISION_LOW(sprite);
sprite_dl |= plane_prec | sprite_dl |= plane_prec |
(drain_latency << DDL_SPRITE_SHIFT(sprite)); (drain_latency << DDL_SPRITE_SHIFT(sprite));
} }
...@@ -3629,10 +3639,15 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode) ...@@ -3629,10 +3639,15 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
else else
mode = 0; mode = 0;
} }
DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", if (HAS_RC6p(dev))
(mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s RC6p %s RC6pp %s\n",
(mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
(mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
(mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
else
DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s\n",
(mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off");
} }
static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6) static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
...@@ -3649,7 +3664,7 @@ static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6) ...@@ -3649,7 +3664,7 @@ static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
if (enable_rc6 >= 0) { if (enable_rc6 >= 0) {
int mask; int mask;
if (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev)) if (HAS_RC6p(dev))
mask = INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE | mask = INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE |
INTEL_RC6pp_ENABLE; INTEL_RC6pp_ENABLE;
else else
...@@ -5649,16 +5664,6 @@ static void broadwell_init_clock_gating(struct drm_device *dev) ...@@ -5649,16 +5664,6 @@ static void broadwell_init_clock_gating(struct drm_device *dev)
I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM2_LP_ILK, 0);
I915_WRITE(WM1_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0);
/* FIXME(BDW): Check all the w/a, some might only apply to
* pre-production hw. */
I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE));
I915_WRITE(_3D_CHICKEN3,
_MASKED_BIT_ENABLE(_3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2)));
/* WaSwitchSolVfFArbitrationPriority:bdw */ /* WaSwitchSolVfFArbitrationPriority:bdw */
I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
......
...@@ -665,80 +665,108 @@ intel_init_pipe_control(struct intel_engine_cs *ring) ...@@ -665,80 +665,108 @@ intel_init_pipe_control(struct intel_engine_cs *ring)
return ret; return ret;
} }
static inline void intel_ring_emit_wa(struct intel_engine_cs *ring, static int intel_ring_workarounds_emit(struct intel_engine_cs *ring)
u32 addr, u32 value)
{ {
int ret, i;
struct drm_device *dev = ring->dev; struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_workarounds *w = &dev_priv->workarounds;
if (WARN_ON(dev_priv->num_wa_regs >= I915_MAX_WA_REGS)) if (WARN_ON(w->count == 0))
return; return 0;
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); ring->gpu_caches_dirty = true;
intel_ring_emit(ring, addr); ret = intel_ring_flush_all_caches(ring);
intel_ring_emit(ring, value); if (ret)
return ret;
dev_priv->intel_wa_regs[dev_priv->num_wa_regs].addr = addr; ret = intel_ring_begin(ring, (w->count * 2 + 2));
dev_priv->intel_wa_regs[dev_priv->num_wa_regs].mask = value & 0xFFFF; if (ret)
/* value is updated with the status of remaining bits of this return ret;
* register when it is read from debugfs file
*/ intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count));
dev_priv->intel_wa_regs[dev_priv->num_wa_regs].value = value; for (i = 0; i < w->count; i++) {
dev_priv->num_wa_regs++; intel_ring_emit(ring, w->reg[i].addr);
intel_ring_emit(ring, w->reg[i].value);
}
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
ring->gpu_caches_dirty = true;
ret = intel_ring_flush_all_caches(ring);
if (ret)
return ret;
return; DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count);
return 0;
} }
static int wa_add(struct drm_i915_private *dev_priv,
const u32 addr, const u32 val, const u32 mask)
{
const u32 idx = dev_priv->workarounds.count;
if (WARN_ON(idx >= I915_MAX_WA_REGS))
return -ENOSPC;
dev_priv->workarounds.reg[idx].addr = addr;
dev_priv->workarounds.reg[idx].value = val;
dev_priv->workarounds.reg[idx].mask = mask;
dev_priv->workarounds.count++;
return 0;
}
#define WA_REG(addr, val, mask) { \
const int r = wa_add(dev_priv, (addr), (val), (mask)); \
if (r) \
return r; \
}
#define WA_SET_BIT_MASKED(addr, mask) \
WA_REG(addr, _MASKED_BIT_ENABLE(mask), (mask) & 0xffff)
#define WA_CLR_BIT_MASKED(addr, mask) \
WA_REG(addr, _MASKED_BIT_DISABLE(mask), (mask) & 0xffff)
#define WA_SET_BIT(addr, mask) WA_REG(addr, I915_READ(addr) | (mask), mask)
#define WA_CLR_BIT(addr, mask) WA_REG(addr, I915_READ(addr) & ~(mask), mask)
#define WA_WRITE(addr, val) WA_REG(addr, val, 0xffffffff)
static int bdw_init_workarounds(struct intel_engine_cs *ring) static int bdw_init_workarounds(struct intel_engine_cs *ring)
{ {
int ret;
struct drm_device *dev = ring->dev; struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
/*
* workarounds applied in this fn are part of register state context,
* they need to be re-initialized followed by gpu reset, suspend/resume,
* module reload.
*/
dev_priv->num_wa_regs = 0;
memset(dev_priv->intel_wa_regs, 0, sizeof(dev_priv->intel_wa_regs));
/*
* update the number of dwords required based on the
* actual number of workarounds applied
*/
ret = intel_ring_begin(ring, 18);
if (ret)
return ret;
/* WaDisablePartialInstShootdown:bdw */ /* WaDisablePartialInstShootdown:bdw */
/* WaDisableThreadStallDopClockGating:bdw */ /* WaDisableThreadStallDopClockGating:bdw (pre-production) */
/* FIXME: Unclear whether we really need this on production bdw. */ WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN, PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE |
_MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE STALL_DOP_GATING_DISABLE);
| STALL_DOP_GATING_DISABLE));
/* WaDisableDopClockGating:bdw May not be needed for production */ /* WaDisableDopClockGating:bdw */
intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2, WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
_MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); DOP_CLOCK_GATING_DISABLE);
intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3, WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
_MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); GEN8_SAMPLER_POWER_BYPASS_DIS);
/* Use Force Non-Coherent whenever executing a 3D context. This is a /* Use Force Non-Coherent whenever executing a 3D context. This is a
* workaround for for a possible hang in the unlikely event a TLB * workaround for for a possible hang in the unlikely event a TLB
* invalidation occurs during a PSD flush. * invalidation occurs during a PSD flush.
*/ */
/* WaDisableFenceDestinationToSLM:bdw (GT3 pre-production) */ /* WaDisableFenceDestinationToSLM:bdw (GT3 pre-production) */
intel_ring_emit_wa(ring, HDC_CHICKEN0, WA_SET_BIT_MASKED(HDC_CHICKEN0,
_MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT | HDC_FORCE_NON_COHERENT |
(IS_BDW_GT3(dev) ? (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
HDC_FENCE_DEST_SLM_DISABLE : 0)
));
/* Wa4x4STCOptimizationDisable:bdw */ /* Wa4x4STCOptimizationDisable:bdw */
intel_ring_emit_wa(ring, CACHE_MODE_1, WA_SET_BIT_MASKED(CACHE_MODE_1,
_MASKED_BIT_ENABLE(GEN8_4x4_STC_OPTIMIZATION_DISABLE)); GEN8_4x4_STC_OPTIMIZATION_DISABLE);
/* /*
* BSpec recommends 8x4 when MSAA is used, * BSpec recommends 8x4 when MSAA is used,
...@@ -748,52 +776,50 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring) ...@@ -748,52 +776,50 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
* disable bit, which we don't touch here, but it's good * disable bit, which we don't touch here, but it's good
* to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
*/ */
intel_ring_emit_wa(ring, GEN7_GT_MODE, WA_SET_BIT_MASKED(GEN7_GT_MODE,
GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4); GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4);
intel_ring_advance(ring);
DRM_DEBUG_DRIVER("Number of Workarounds applied: %d\n",
dev_priv->num_wa_regs);
return 0; return 0;
} }
static int chv_init_workarounds(struct intel_engine_cs *ring) static int chv_init_workarounds(struct intel_engine_cs *ring)
{ {
int ret;
struct drm_device *dev = ring->dev; struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
/*
* workarounds applied in this fn are part of register state context,
* they need to be re-initialized followed by gpu reset, suspend/resume,
* module reload.
*/
dev_priv->num_wa_regs = 0;
memset(dev_priv->intel_wa_regs, 0, sizeof(dev_priv->intel_wa_regs));
ret = intel_ring_begin(ring, 12);
if (ret)
return ret;
/* WaDisablePartialInstShootdown:chv */ /* WaDisablePartialInstShootdown:chv */
intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN, WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
_MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE)); PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
/* WaDisableThreadStallDopClockGating:chv */ /* WaDisableThreadStallDopClockGating:chv */
intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN, WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
_MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE)); STALL_DOP_GATING_DISABLE);
/* WaDisableDopClockGating:chv (pre-production hw) */ /* WaDisableDopClockGating:chv (pre-production hw) */
intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2, WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
_MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); DOP_CLOCK_GATING_DISABLE);
/* WaDisableSamplerPowerBypass:chv (pre-production hw) */ /* WaDisableSamplerPowerBypass:chv (pre-production hw) */
intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3, WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
_MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); GEN8_SAMPLER_POWER_BYPASS_DIS);
intel_ring_advance(ring); return 0;
}
static int init_workarounds_ring(struct intel_engine_cs *ring)
{
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
WARN_ON(ring->id != RCS);
dev_priv->workarounds.count = 0;
if (IS_BROADWELL(dev))
return bdw_init_workarounds(ring);
if (IS_CHERRYVIEW(dev))
return chv_init_workarounds(ring);
return 0; return 0;
} }
...@@ -853,7 +879,7 @@ static int init_render_ring(struct intel_engine_cs *ring) ...@@ -853,7 +879,7 @@ static int init_render_ring(struct intel_engine_cs *ring)
if (HAS_L3_DPF(dev)) if (HAS_L3_DPF(dev))
I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
return ret; return init_workarounds_ring(ring);
} }
static void render_ring_cleanup(struct intel_engine_cs *ring) static void render_ring_cleanup(struct intel_engine_cs *ring)
...@@ -2299,10 +2325,8 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ...@@ -2299,10 +2325,8 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
dev_priv->semaphore_obj = obj; dev_priv->semaphore_obj = obj;
} }
} }
if (IS_CHERRYVIEW(dev))
ring->init_context = chv_init_workarounds; ring->init_context = intel_ring_workarounds_emit;
else
ring->init_context = bdw_init_workarounds;
ring->add_request = gen6_add_request; ring->add_request = gen6_add_request;
ring->flush = gen8_render_ring_flush; ring->flush = gen8_render_ring_flush;
ring->irq_get = gen8_ring_get_irq; ring->irq_get = gen8_ring_get_irq;
......
...@@ -221,9 +221,9 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, ...@@ -221,9 +221,9 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) & if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) &
HSW_PWR_WELL_STATE_ENABLED), 20)) HSW_PWR_WELL_STATE_ENABLED), 20))
DRM_ERROR("Timeout enabling power well\n"); DRM_ERROR("Timeout enabling power well\n");
hsw_power_well_post_enable(dev_priv);
} }
hsw_power_well_post_enable(dev_priv);
} else { } else {
if (enable_requested) { if (enable_requested) {
I915_WRITE(HSW_PWR_WELL_DRIVER, 0); I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
......
...@@ -162,6 +162,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, ...@@ -162,6 +162,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
plane_ctl &= ~PLANE_CTL_YUV422_ORDER_MASK; plane_ctl &= ~PLANE_CTL_YUV422_ORDER_MASK;
plane_ctl &= ~PLANE_CTL_TILED_MASK; plane_ctl &= ~PLANE_CTL_TILED_MASK;
plane_ctl &= ~PLANE_CTL_ALPHA_MASK; plane_ctl &= ~PLANE_CTL_ALPHA_MASK;
plane_ctl &= ~PLANE_CTL_ROTATE_MASK;
/* Trickle feed has to be enabled */ /* Trickle feed has to be enabled */
plane_ctl &= ~PLANE_CTL_TRICKLE_FEED_DISABLE; plane_ctl &= ~PLANE_CTL_TRICKLE_FEED_DISABLE;
...@@ -217,6 +218,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, ...@@ -217,6 +218,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
default: default:
BUG(); BUG();
} }
if (intel_plane->rotation == BIT(DRM_ROTATE_180))
plane_ctl |= PLANE_CTL_ROTATE_180;
plane_ctl |= PLANE_CTL_ENABLE; plane_ctl |= PLANE_CTL_ENABLE;
plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE; plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
......
...@@ -360,7 +360,8 @@ void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) ...@@ -360,7 +360,8 @@ void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
} }
void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake) static void __intel_uncore_early_sanitize(struct drm_device *dev,
bool restore_forcewake)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -386,6 +387,12 @@ void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake) ...@@ -386,6 +387,12 @@ void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake)
intel_uncore_forcewake_reset(dev, restore_forcewake); intel_uncore_forcewake_reset(dev, restore_forcewake);
} }
void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake)
{
__intel_uncore_early_sanitize(dev, restore_forcewake);
i915_check_and_clear_faults(dev);
}
void intel_uncore_sanitize(struct drm_device *dev) void intel_uncore_sanitize(struct drm_device *dev)
{ {
/* BIOS often leaves RC6 enabled, but disable it for hw init */ /* BIOS often leaves RC6 enabled, but disable it for hw init */
...@@ -823,6 +830,22 @@ __gen4_write(64) ...@@ -823,6 +830,22 @@ __gen4_write(64)
#undef REG_WRITE_FOOTER #undef REG_WRITE_FOOTER
#undef REG_WRITE_HEADER #undef REG_WRITE_HEADER
#define ASSIGN_WRITE_MMIO_VFUNCS(x) \
do { \
dev_priv->uncore.funcs.mmio_writeb = x##_write8; \
dev_priv->uncore.funcs.mmio_writew = x##_write16; \
dev_priv->uncore.funcs.mmio_writel = x##_write32; \
dev_priv->uncore.funcs.mmio_writeq = x##_write64; \
} while (0)
#define ASSIGN_READ_MMIO_VFUNCS(x) \
do { \
dev_priv->uncore.funcs.mmio_readb = x##_read8; \
dev_priv->uncore.funcs.mmio_readw = x##_read16; \
dev_priv->uncore.funcs.mmio_readl = x##_read32; \
dev_priv->uncore.funcs.mmio_readq = x##_read64; \
} while (0)
void intel_uncore_init(struct drm_device *dev) void intel_uncore_init(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -830,7 +853,7 @@ void intel_uncore_init(struct drm_device *dev) ...@@ -830,7 +853,7 @@ void intel_uncore_init(struct drm_device *dev)
setup_timer(&dev_priv->uncore.force_wake_timer, setup_timer(&dev_priv->uncore.force_wake_timer,
gen6_force_wake_timer, (unsigned long)dev_priv); gen6_force_wake_timer, (unsigned long)dev_priv);
intel_uncore_early_sanitize(dev, false); __intel_uncore_early_sanitize(dev, false);
if (IS_VALLEYVIEW(dev)) { if (IS_VALLEYVIEW(dev)) {
dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get; dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get;
...@@ -879,76 +902,44 @@ void intel_uncore_init(struct drm_device *dev) ...@@ -879,76 +902,44 @@ void intel_uncore_init(struct drm_device *dev)
switch (INTEL_INFO(dev)->gen) { switch (INTEL_INFO(dev)->gen) {
default: default:
if (IS_CHERRYVIEW(dev)) { if (IS_CHERRYVIEW(dev)) {
dev_priv->uncore.funcs.mmio_writeb = chv_write8; ASSIGN_WRITE_MMIO_VFUNCS(chv);
dev_priv->uncore.funcs.mmio_writew = chv_write16; ASSIGN_READ_MMIO_VFUNCS(chv);
dev_priv->uncore.funcs.mmio_writel = chv_write32;
dev_priv->uncore.funcs.mmio_writeq = chv_write64;
dev_priv->uncore.funcs.mmio_readb = chv_read8;
dev_priv->uncore.funcs.mmio_readw = chv_read16;
dev_priv->uncore.funcs.mmio_readl = chv_read32;
dev_priv->uncore.funcs.mmio_readq = chv_read64;
} else { } else {
dev_priv->uncore.funcs.mmio_writeb = gen8_write8; ASSIGN_WRITE_MMIO_VFUNCS(gen8);
dev_priv->uncore.funcs.mmio_writew = gen8_write16; ASSIGN_READ_MMIO_VFUNCS(gen6);
dev_priv->uncore.funcs.mmio_writel = gen8_write32;
dev_priv->uncore.funcs.mmio_writeq = gen8_write64;
dev_priv->uncore.funcs.mmio_readb = gen6_read8;
dev_priv->uncore.funcs.mmio_readw = gen6_read16;
dev_priv->uncore.funcs.mmio_readl = gen6_read32;
dev_priv->uncore.funcs.mmio_readq = gen6_read64;
} }
break; break;
case 7: case 7:
case 6: case 6:
if (IS_HASWELL(dev)) { if (IS_HASWELL(dev)) {
dev_priv->uncore.funcs.mmio_writeb = hsw_write8; ASSIGN_WRITE_MMIO_VFUNCS(hsw);
dev_priv->uncore.funcs.mmio_writew = hsw_write16;
dev_priv->uncore.funcs.mmio_writel = hsw_write32;
dev_priv->uncore.funcs.mmio_writeq = hsw_write64;
} else { } else {
dev_priv->uncore.funcs.mmio_writeb = gen6_write8; ASSIGN_WRITE_MMIO_VFUNCS(gen6);
dev_priv->uncore.funcs.mmio_writew = gen6_write16;
dev_priv->uncore.funcs.mmio_writel = gen6_write32;
dev_priv->uncore.funcs.mmio_writeq = gen6_write64;
} }
if (IS_VALLEYVIEW(dev)) { if (IS_VALLEYVIEW(dev)) {
dev_priv->uncore.funcs.mmio_readb = vlv_read8; ASSIGN_READ_MMIO_VFUNCS(vlv);
dev_priv->uncore.funcs.mmio_readw = vlv_read16;
dev_priv->uncore.funcs.mmio_readl = vlv_read32;
dev_priv->uncore.funcs.mmio_readq = vlv_read64;
} else { } else {
dev_priv->uncore.funcs.mmio_readb = gen6_read8; ASSIGN_READ_MMIO_VFUNCS(gen6);
dev_priv->uncore.funcs.mmio_readw = gen6_read16;
dev_priv->uncore.funcs.mmio_readl = gen6_read32;
dev_priv->uncore.funcs.mmio_readq = gen6_read64;
} }
break; break;
case 5: case 5:
dev_priv->uncore.funcs.mmio_writeb = gen5_write8; ASSIGN_WRITE_MMIO_VFUNCS(gen5);
dev_priv->uncore.funcs.mmio_writew = gen5_write16; ASSIGN_READ_MMIO_VFUNCS(gen5);
dev_priv->uncore.funcs.mmio_writel = gen5_write32;
dev_priv->uncore.funcs.mmio_writeq = gen5_write64;
dev_priv->uncore.funcs.mmio_readb = gen5_read8;
dev_priv->uncore.funcs.mmio_readw = gen5_read16;
dev_priv->uncore.funcs.mmio_readl = gen5_read32;
dev_priv->uncore.funcs.mmio_readq = gen5_read64;
break; break;
case 4: case 4:
case 3: case 3:
case 2: case 2:
dev_priv->uncore.funcs.mmio_writeb = gen4_write8; ASSIGN_WRITE_MMIO_VFUNCS(gen4);
dev_priv->uncore.funcs.mmio_writew = gen4_write16; ASSIGN_READ_MMIO_VFUNCS(gen4);
dev_priv->uncore.funcs.mmio_writel = gen4_write32;
dev_priv->uncore.funcs.mmio_writeq = gen4_write64;
dev_priv->uncore.funcs.mmio_readb = gen4_read8;
dev_priv->uncore.funcs.mmio_readw = gen4_read16;
dev_priv->uncore.funcs.mmio_readl = gen4_read32;
dev_priv->uncore.funcs.mmio_readq = gen4_read64;
break; break;
} }
i915_check_and_clear_faults(dev);
} }
#undef ASSIGN_WRITE_MMIO_VFUNCS
#undef ASSIGN_READ_MMIO_VFUNCS
void intel_uncore_fini(struct drm_device *dev) void intel_uncore_fini(struct drm_device *dev)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册