Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel into drm-next

So here's my promised pile of fixes for 3.9. I've dropped the core prep
patches for vt-switchless suspend/resume as discussed on irc. Highlights:
- Fix dmar on g4x. Not really gfx related, but I'm fed up with getting
  blamed for dmar crapouts.
- Disable wc ptes updates on ilk when dmar is enabled (Chris). So again,
  dmar, but this time gfx related :(
- Reduced range support for hsw, using the pipe CSC (Ville).
- Fixup pll limits for gen3/4 (Patrick Jakobsson). The sdvo patch is
  already confirmed to fix 2 bug reports, so added cc: stable on that one.
- Regression fix for 8bit fb console (Ville).
- Preserve lane reversal bits on DDI/FDI ports (Damien).
- Page flip vs. gpu hang fixes (Ville). Unfortuntely not quite all of
  them, need to decide what to do with the currently still in-flight ones.
- Panel fitter regression fix from Mika Kuoppala (was accidentally left on
  on some pipes with the new modset code since 3.7). This also improves
  the modeset sequence and might help a few other unrelated issues with
  lvds.
- Write backlight regs even harder ... another installement in our eternal
  fight against the BIOS and backlights.
- Fixup lid notifier vs. suspend/resume races (Zhang Rui). Prep work for
  new ACPI stuff, but closing the race itself seems worthwile on its own.
- A few other small fixes and tiny cleanups all over.

Lots of the patches are cc: stable since I've stalled on a few
not-so-important fixes for 3.8 due to the grumpy noise Linus made.

* 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel: (33 commits)
  intel/iommu: force writebuffer-flush quirk on Gen 4 Chipsets
  drm/i915: Disable WC PTE updates to w/a buggy IOMMU on ILK
  drm/i915: Implement pipe CSC based limited range RGB output
  drm/i915: inverted brightness quirk for Acer Aspire 4736Z
  drm/i915: Print the hw context status is debugfs
  drm/i915: Use HAS_L3_GPU_CACHE in i915_gem_l3_remap
  drm/i915: Fix PIPE_CONTROL DW/QW write through global GTT on IVB+
  drm/i915: Set i9xx sdvo clock limits according to specifications
  drm/i915: Set i9xx lvds clock limits according to specifications
  drm/i915: Preserve the DDI link reversal configuration
  drm/i915: Preserve the FDI line reversal override bit on CPT
  drm/i915: add missing \n to UTS_RELEASE in the error_state
  drm: Use C8 instead of RGB332 when determining the format from depth/bpp
  drm: Fill depth/bits_per_pixel for C8 format
  drm/i915: don't clflush gem objects in stolen memory
  drm/i915: Don't wait for page flips if there was GPU reset
  drm/i915: Kill obj->pending_flip
  drm/i915: Fix a typo in a intel_modeset_stage_output_state() comment
  drm/i915: remove bogus mutex_unlock from error-path
  drm/i915: Print the pipe control page GTT address
  ...
This commit is contained in:
Dave Airlie 2013-02-20 11:40:49 +10:00
commit b81e059ec5
24 changed files with 482 additions and 238 deletions

View File

@ -572,6 +572,40 @@ static void intel_gtt_cleanup(void)
intel_gtt_teardown_scratch_page();
}
/* Certain Gen5 chipsets require require idling the GPU before
* unmapping anything from the GTT when VT-d is enabled.
*/
static inline int needs_ilk_vtd_wa(void)
{
#ifdef CONFIG_INTEL_IOMMU
const unsigned short gpu_devid = intel_private.pcidev->device;
/* Query intel_iommu to see if we need the workaround. Presumably that
* was loaded first.
*/
if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
intel_iommu_gfx_mapped)
return 1;
#endif
return 0;
}
static bool intel_gtt_can_wc(void)
{
if (INTEL_GTT_GEN <= 2)
return false;
if (INTEL_GTT_GEN >= 6)
return false;
/* Reports of major corruption with ILK vt'd enabled */
if (needs_ilk_vtd_wa())
return false;
return true;
}
static int intel_gtt_init(void)
{
u32 gma_addr;
@ -601,7 +635,7 @@ static int intel_gtt_init(void)
gtt_map_size = intel_private.gtt_total_entries * 4;
intel_private.gtt = NULL;
if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2)
if (intel_gtt_can_wc())
intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr,
gtt_map_size);
if (intel_private.gtt == NULL)
@ -1072,7 +1106,6 @@ static void i965_write_entry(dma_addr_t addr,
writel(addr | pte_flags, intel_private.gtt + entry);
}
static int i9xx_setup(void)
{
u32 reg_addr, gtt_addr;
@ -1371,10 +1404,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
}
EXPORT_SYMBOL(intel_gmch_probe);
void intel_gtt_get(size_t *gtt_total, size_t *stolen_size)
void intel_gtt_get(size_t *gtt_total, size_t *stolen_size,
phys_addr_t *mappable_base, unsigned long *mappable_end)
{
*gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT;
*stolen_size = intel_private.stolen_size;
*mappable_base = intel_private.gma_bus_addr;
*mappable_end = intel_private.gtt_mappable_entries << PAGE_SHIFT;
}
EXPORT_SYMBOL(intel_gtt_get);

View File

@ -2267,7 +2267,7 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
switch (bpp) {
case 8:
fmt = DRM_FORMAT_RGB332;
fmt = DRM_FORMAT_C8;
break;
case 16:
if (depth == 15)
@ -3870,6 +3870,7 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
int *bpp)
{
switch (format) {
case DRM_FORMAT_C8:
case DRM_FORMAT_RGB332:
case DRM_FORMAT_BGR233:
*depth = 8;

View File

@ -694,7 +694,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
error->time.tv_usec);
seq_printf(m, "Kernel: " UTS_RELEASE);
seq_printf(m, "Kernel: " UTS_RELEASE "\n");
seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
seq_printf(m, "EIR: 0x%08x\n", error->eir);
seq_printf(m, "IER: 0x%08x\n", error->ier);
@ -1484,7 +1484,8 @@ static int i915_context_status(struct seq_file *m, void *unused)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
int ret;
struct intel_ring_buffer *ring;
int ret, i;
ret = mutex_lock_interruptible(&dev->mode_config.mutex);
if (ret)
@ -1502,6 +1503,14 @@ static int i915_context_status(struct seq_file *m, void *unused)
seq_printf(m, "\n");
}
for_each_ring(ring, dev_priv, i) {
if (ring->default_context) {
seq_printf(m, "HW default context %s ring ", ring->name);
describe_obj(m, ring->default_context->obj);
seq_printf(m, "\n");
}
}
mutex_unlock(&dev->mode_config.mutex);
return 0;

View File

@ -1610,6 +1610,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
mutex_init(&dev_priv->dpio_lock);
mutex_init(&dev_priv->rps.hw_lock);
mutex_init(&dev_priv->modeset_restore_lock);
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
dev_priv->num_pipe = 3;

View File

@ -470,6 +470,11 @@ static int i915_drm_freeze(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
/* ignore lid events during suspend */
mutex_lock(&dev_priv->modeset_restore_lock);
dev_priv->modeset_restore = MODESET_SUSPENDED;
mutex_unlock(&dev_priv->modeset_restore_lock);
intel_set_power_well(dev, true);
drm_kms_helper_poll_disable(dev);
@ -496,9 +501,6 @@ static int i915_drm_freeze(struct drm_device *dev)
intel_opregion_fini(dev);
/* Modeset on resume, not lid events */
dev_priv->modeset_on_lid = 0;
console_lock();
intel_fbdev_set_suspend(dev, 1);
console_unlock();
@ -574,8 +576,6 @@ static int __i915_drm_thaw(struct drm_device *dev)
intel_opregion_init(dev);
dev_priv->modeset_on_lid = 0;
/*
* The console lock can be pretty contented on resume due
* to all the printk activity. Try to keep it out of the hot
@ -588,6 +588,9 @@ static int __i915_drm_thaw(struct drm_device *dev)
schedule_work(&dev_priv->console_resume_work);
}
mutex_lock(&dev_priv->modeset_restore_lock);
dev_priv->modeset_restore = MODESET_DONE;
mutex_unlock(&dev_priv->modeset_restore_lock);
return error;
}

View File

@ -399,7 +399,8 @@ struct i915_gtt {
/* global gtt ops */
int (*gtt_probe)(struct drm_device *dev, size_t *gtt_total,
size_t *stolen);
size_t *stolen, phys_addr_t *mappable_base,
unsigned long *mappable_end);
void (*gtt_remove)(struct drm_device *dev);
void (*gtt_clear_range)(struct drm_device *dev,
unsigned int first_entry,
@ -846,6 +847,12 @@ struct i915_gpu_error {
unsigned int stop_rings;
};
enum modeset_restore {
MODESET_ON_LID_OPEN,
MODESET_DONE,
MODESET_SUSPENDED,
};
typedef struct drm_i915_private {
struct drm_device *dev;
struct kmem_cache *slab;
@ -919,7 +926,7 @@ typedef struct drm_i915_private {
/* overlay */
struct intel_overlay *overlay;
bool sprite_scaling_enabled;
unsigned int sprite_scaling_enabled;
/* LVDS info */
int backlight_level; /* restore backlight to this value */
@ -967,8 +974,8 @@ typedef struct drm_i915_private {
unsigned long quirks;
/* Register state */
bool modeset_on_lid;
enum modeset_restore modeset_restore;
struct mutex modeset_restore_lock;
struct i915_gtt gtt;
@ -1033,7 +1040,7 @@ typedef struct drm_i915_private {
bool hw_contexts_disabled;
uint32_t hw_context_size;
bool fdi_rx_polarity_reversed;
u32 fdi_rx_config;
struct i915_suspend_saved_registers regfile;
@ -1208,13 +1215,6 @@ struct drm_i915_gem_object {
/** for phy allocated objects */
struct drm_i915_gem_phys_object *phys_obj;
/**
* Number of crtcs where this object is currently the fb, but
* will be page flipped away on the next vblank. When it
* reaches 0, dev_priv->pending_flip_queue will be woken up.
*/
atomic_t pending_flip;
};
#define to_gem_object(obj) (&((struct drm_i915_gem_object *)(obj))->base)

View File

@ -3021,6 +3021,13 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj)
if (obj->pages == NULL)
return;
/*
* Stolen memory is always coherent with the GPU as it is explicitly
* marked as wc by the system, or the system is cache-coherent.
*/
if (obj->stolen)
return;
/* If the GPU is snooping the contents of the CPU cache,
* we do not need to manually clear the CPU cache lines. However,
* the caches are only snooped when the render cache is
@ -3865,7 +3872,7 @@ void i915_gem_l3_remap(struct drm_device *dev)
u32 misccpctl;
int i;
if (!IS_IVYBRIDGE(dev))
if (!HAS_L3_GPU_CACHE(dev))
return;
if (!dev_priv->l3_parity.remap_info)
@ -3930,22 +3937,11 @@ intel_enable_blt(struct drm_device *dev)
return true;
}
int
i915_gem_init_hw(struct drm_device *dev)
static int i915_gem_init_rings(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
return -EIO;
if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1))
I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000);
i915_gem_l3_remap(dev);
i915_gem_init_swizzling(dev);
ret = intel_init_render_ring_buffer(dev);
if (ret)
return ret;
@ -3963,6 +3959,38 @@ i915_gem_init_hw(struct drm_device *dev)
}
ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000));
if (ret)
goto cleanup_blt_ring;
return 0;
cleanup_blt_ring:
intel_cleanup_ring_buffer(&dev_priv->ring[BCS]);
cleanup_bsd_ring:
intel_cleanup_ring_buffer(&dev_priv->ring[VCS]);
cleanup_render_ring:
intel_cleanup_ring_buffer(&dev_priv->ring[RCS]);
return ret;
}
int
i915_gem_init_hw(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int ret;
if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
return -EIO;
if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1))
I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000);
i915_gem_l3_remap(dev);
i915_gem_init_swizzling(dev);
ret = i915_gem_init_rings(dev);
if (ret)
return ret;
@ -3974,12 +4002,6 @@ i915_gem_init_hw(struct drm_device *dev)
i915_gem_init_ppgtt(dev);
return 0;
cleanup_bsd_ring:
intel_cleanup_ring_buffer(&dev_priv->ring[VCS]);
cleanup_render_ring:
intel_cleanup_ring_buffer(&dev_priv->ring[RCS]);
return ret;
}
int i915_gem_init(struct drm_device *dev)

View File

@ -126,13 +126,8 @@ static int get_context_size(struct drm_device *dev)
static void do_destroy(struct i915_hw_context *ctx)
{
struct drm_device *dev = ctx->obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
if (ctx->file_priv)
idr_remove(&ctx->file_priv->context_idr, ctx->id);
else
BUG_ON(ctx != dev_priv->ring[RCS].default_context);
drm_gem_object_unreference(&ctx->obj->base);
kfree(ctx);
@ -242,7 +237,6 @@ err_destroy:
void i915_gem_context_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t ctx_size;
if (!HAS_HW_CONTEXTS(dev)) {
dev_priv->hw_contexts_disabled = true;
@ -254,11 +248,9 @@ void i915_gem_context_init(struct drm_device *dev)
dev_priv->ring[RCS].default_context)
return;
ctx_size = get_context_size(dev);
dev_priv->hw_context_size = get_context_size(dev);
dev_priv->hw_context_size = round_up(dev_priv->hw_context_size, 4096);
dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
if (ctx_size <= 0 || ctx_size > (1<<20)) {
if (dev_priv->hw_context_size > (1<<20)) {
dev_priv->hw_contexts_disabled = true;
return;
}

View File

@ -725,7 +725,9 @@ static inline size_t gen7_get_stolen_size(u16 snb_gmch_ctl)
static int gen6_gmch_probe(struct drm_device *dev,
size_t *gtt_total,
size_t *stolen)
size_t *stolen,
phys_addr_t *mappable_base,
unsigned long *mappable_end)
{
struct drm_i915_private *dev_priv = dev->dev_private;
phys_addr_t gtt_bus_addr;
@ -733,11 +735,13 @@ static int gen6_gmch_probe(struct drm_device *dev,
u16 snb_gmch_ctl;
int ret;
*mappable_base = pci_resource_start(dev->pdev, 2);
*mappable_end = pci_resource_len(dev->pdev, 2);
/* 64/512MB is the current min/max we actually know of, but this is just
* a coarse sanity check.
*/
if ((dev_priv->gtt.mappable_end < (64<<20) ||
(dev_priv->gtt.mappable_end > (512<<20)))) {
if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) {
DRM_ERROR("Unknown GMADR size (%lx)\n",
dev_priv->gtt.mappable_end);
return -ENXIO;
@ -782,7 +786,9 @@ static void gen6_gmch_remove(struct drm_device *dev)
static int i915_gmch_probe(struct drm_device *dev,
size_t *gtt_total,
size_t *stolen)
size_t *stolen,
phys_addr_t *mappable_base,
unsigned long *mappable_end)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
@ -793,7 +799,7 @@ static int i915_gmch_probe(struct drm_device *dev,
return -EIO;
}
intel_gtt_get(gtt_total, stolen);
intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end);
dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev);
dev_priv->gtt.gtt_clear_range = i915_ggtt_clear_range;
@ -814,9 +820,6 @@ int i915_gem_gtt_init(struct drm_device *dev)
unsigned long gtt_size;
int ret;
gtt->mappable_base = pci_resource_start(dev->pdev, 2);
gtt->mappable_end = pci_resource_len(dev->pdev, 2);
if (INTEL_INFO(dev)->gen <= 5) {
dev_priv->gtt.gtt_probe = i915_gmch_probe;
dev_priv->gtt.gtt_remove = i915_gmch_remove;
@ -826,7 +829,9 @@ int i915_gem_gtt_init(struct drm_device *dev)
}
ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total,
&dev_priv->gtt.stolen_size);
&dev_priv->gtt.stolen_size,
&gtt->mappable_base,
&gtt->mappable_end);
if (ret)
return ret;

View File

@ -1924,7 +1924,7 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
* This register is the same on all known PCH chips.
*/
static void ironlake_enable_pch_hotplug(struct drm_device *dev)
static void ibx_enable_hotplug(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 hotplug;
@ -1937,6 +1937,28 @@ static void ironlake_enable_pch_hotplug(struct drm_device *dev)
I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
}
static void ibx_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 mask;
if (HAS_PCH_IBX(dev))
mask = SDE_HOTPLUG_MASK |
SDE_GMBUS |
SDE_AUX_MASK;
else
mask = SDE_HOTPLUG_MASK_CPT |
SDE_GMBUS_CPT |
SDE_AUX_MASK_CPT;
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
I915_WRITE(SDEIMR, ~mask);
I915_WRITE(SDEIER, mask);
POSTING_READ(SDEIER);
ibx_enable_hotplug(dev);
}
static int ironlake_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@ -1945,8 +1967,6 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
DE_AUX_CHANNEL_A;
u32 render_irqs;
u32 hotplug_mask;
u32 pch_irq_mask;
dev_priv->irq_mask = ~display_mask;
@ -1974,30 +1994,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
I915_WRITE(GTIER, render_irqs);
POSTING_READ(GTIER);
if (HAS_PCH_CPT(dev)) {
hotplug_mask = (SDE_CRT_HOTPLUG_CPT |
SDE_PORTB_HOTPLUG_CPT |
SDE_PORTC_HOTPLUG_CPT |
SDE_PORTD_HOTPLUG_CPT |
SDE_GMBUS_CPT |
SDE_AUX_MASK_CPT);
} else {
hotplug_mask = (SDE_CRT_HOTPLUG |
SDE_PORTB_HOTPLUG |
SDE_PORTC_HOTPLUG |
SDE_PORTD_HOTPLUG |
SDE_GMBUS |
SDE_AUX_MASK);
}
pch_irq_mask = ~hotplug_mask;
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
I915_WRITE(SDEIMR, pch_irq_mask);
I915_WRITE(SDEIER, hotplug_mask);
POSTING_READ(SDEIER);
ironlake_enable_pch_hotplug(dev);
ibx_irq_postinstall(dev);
if (IS_IRONLAKE_M(dev)) {
/* Clear & enable PCU event interrupts */
@ -2020,8 +2017,6 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
DE_PLANEA_FLIP_DONE_IVB |
DE_AUX_CHANNEL_A_IVB;
u32 render_irqs;
u32 hotplug_mask;
u32 pch_irq_mask;
dev_priv->irq_mask = ~display_mask;
@ -2045,20 +2040,7 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
I915_WRITE(GTIER, render_irqs);
POSTING_READ(GTIER);
hotplug_mask = (SDE_CRT_HOTPLUG_CPT |
SDE_PORTB_HOTPLUG_CPT |
SDE_PORTC_HOTPLUG_CPT |
SDE_PORTD_HOTPLUG_CPT |
SDE_GMBUS_CPT |
SDE_AUX_MASK_CPT);
pch_irq_mask = ~hotplug_mask;
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
I915_WRITE(SDEIMR, pch_irq_mask);
I915_WRITE(SDEIER, hotplug_mask);
POSTING_READ(SDEIER);
ironlake_enable_pch_hotplug(dev);
ibx_irq_postinstall(dev);
return 0;
}
@ -2137,12 +2119,12 @@ static void valleyview_hpd_irq_setup(struct drm_device *dev)
u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
/* Note HDMI and DP share bits */
if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
hotplug_en |= HDMIB_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
hotplug_en |= HDMIC_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
hotplug_en |= HDMID_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & PORTB_HOTPLUG_INT_STATUS)
hotplug_en |= PORTB_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & PORTC_HOTPLUG_INT_STATUS)
hotplug_en |= PORTC_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & PORTD_HOTPLUG_INT_STATUS)
hotplug_en |= PORTD_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915)
hotplug_en |= SDVOC_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915)
@ -2408,12 +2390,12 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
if (I915_HAS_HOTPLUG(dev)) {
hotplug_en = I915_READ(PORT_HOTPLUG_EN);
if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
hotplug_en |= HDMIB_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
hotplug_en |= HDMIC_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
hotplug_en |= HDMID_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & PORTB_HOTPLUG_INT_STATUS)
hotplug_en |= PORTB_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & PORTC_HOTPLUG_INT_STATUS)
hotplug_en |= PORTC_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & PORTD_HOTPLUG_INT_STATUS)
hotplug_en |= PORTD_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915)
hotplug_en |= SDVOC_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915)
@ -2642,12 +2624,12 @@ static void i965_hpd_irq_setup(struct drm_device *dev)
/* Note HDMI and DP share hotplug bits */
hotplug_en = 0;
if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
hotplug_en |= HDMIB_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
hotplug_en |= HDMIC_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
hotplug_en |= HDMID_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & PORTB_HOTPLUG_INT_STATUS)
hotplug_en |= PORTB_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & PORTC_HOTPLUG_INT_STATUS)
hotplug_en |= PORTC_HOTPLUG_INT_EN;
if (dev_priv->hotplug_supported_mask & PORTD_HOTPLUG_INT_STATUS)
hotplug_en |= PORTD_HOTPLUG_INT_EN;
if (IS_G4X(dev)) {
if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X)
hotplug_en |= SDVOC_HOTPLUG_INT_EN;

View File

@ -308,6 +308,7 @@
#define DISPLAY_PLANE_A (0<<20)
#define DISPLAY_PLANE_B (1<<20)
#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
#define PIPE_CONTROL_GLOBAL_GTT_IVB (1<<24) /* gen7+ */
#define PIPE_CONTROL_CS_STALL (1<<20)
#define PIPE_CONTROL_TLB_INVALIDATE (1<<18)
#define PIPE_CONTROL_QW_WRITE (1<<14)
@ -1235,6 +1236,10 @@
#define MAD_DIMM_A_SIZE_SHIFT 0
#define MAD_DIMM_A_SIZE_MASK (0xff << MAD_DIMM_A_SIZE_SHIFT)
/** snb MCH registers for priority tuning */
#define MCH_SSKPD (MCHBAR_MIRROR_BASE_SNB + 0x5d10)
#define MCH_SSKPD_WM0_MASK 0x3f
#define MCH_SSKPD_WM0_VAL 0xc
/* Clocking configuration register */
#define CLKCFG 0x10c00
@ -1625,12 +1630,9 @@
/* Hotplug control (945+ only) */
#define PORT_HOTPLUG_EN (dev_priv->info->display_mmio_offset + 0x61110)
#define HDMIB_HOTPLUG_INT_EN (1 << 29)
#define DPB_HOTPLUG_INT_EN (1 << 29)
#define HDMIC_HOTPLUG_INT_EN (1 << 28)
#define DPC_HOTPLUG_INT_EN (1 << 28)
#define HDMID_HOTPLUG_INT_EN (1 << 27)
#define DPD_HOTPLUG_INT_EN (1 << 27)
#define PORTB_HOTPLUG_INT_EN (1 << 29)
#define PORTC_HOTPLUG_INT_EN (1 << 28)
#define PORTD_HOTPLUG_INT_EN (1 << 27)
#define SDVOB_HOTPLUG_INT_EN (1 << 26)
#define SDVOC_HOTPLUG_INT_EN (1 << 25)
#define TV_HOTPLUG_INT_EN (1 << 18)
@ -1653,19 +1655,12 @@
#define PORT_HOTPLUG_STAT (dev_priv->info->display_mmio_offset + 0x61114)
/* HDMI/DP bits are gen4+ */
#define DPB_HOTPLUG_LIVE_STATUS (1 << 29)
#define DPC_HOTPLUG_LIVE_STATUS (1 << 28)
#define DPD_HOTPLUG_LIVE_STATUS (1 << 27)
#define DPD_HOTPLUG_INT_STATUS (3 << 21)
#define DPC_HOTPLUG_INT_STATUS (3 << 19)
#define DPB_HOTPLUG_INT_STATUS (3 << 17)
/* HDMI bits are shared with the DP bits */
#define HDMIB_HOTPLUG_LIVE_STATUS (1 << 29)
#define HDMIC_HOTPLUG_LIVE_STATUS (1 << 28)
#define HDMID_HOTPLUG_LIVE_STATUS (1 << 27)
#define HDMID_HOTPLUG_INT_STATUS (3 << 21)
#define HDMIC_HOTPLUG_INT_STATUS (3 << 19)
#define HDMIB_HOTPLUG_INT_STATUS (3 << 17)
#define PORTB_HOTPLUG_LIVE_STATUS (1 << 29)
#define PORTC_HOTPLUG_LIVE_STATUS (1 << 28)
#define PORTD_HOTPLUG_LIVE_STATUS (1 << 27)
#define PORTD_HOTPLUG_INT_STATUS (3 << 21)
#define PORTC_HOTPLUG_INT_STATUS (3 << 19)
#define PORTB_HOTPLUG_INT_STATUS (3 << 17)
/* CRT/TV common between gen3+ */
#define CRT_HOTPLUG_INT_STATUS (1 << 11)
#define TV_HOTPLUG_INT_STATUS (1 << 10)
@ -2954,6 +2949,7 @@
#define CURSOR_ENABLE 0x80000000
#define CURSOR_GAMMA_ENABLE 0x40000000
#define CURSOR_STRIDE_MASK 0x30000000
#define CURSOR_PIPE_CSC_ENABLE (1<<24)
#define CURSOR_FORMAT_SHIFT 24
#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT)
#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT)
@ -3015,6 +3011,7 @@
#define DISPPLANE_RGBA888 (0xf<<26)
#define DISPPLANE_STEREO_ENABLE (1<<25)
#define DISPPLANE_STEREO_DISABLE 0
#define DISPPLANE_PIPE_CSC_ENABLE (1<<24)
#define DISPPLANE_SEL_PIPE_SHIFT 24
#define DISPPLANE_SEL_PIPE_MASK (3<<DISPPLANE_SEL_PIPE_SHIFT)
#define DISPPLANE_SEL_PIPE_A 0
@ -3103,6 +3100,7 @@
#define DVS_FORMAT_RGBX101010 (1<<25)
#define DVS_FORMAT_RGBX888 (2<<25)
#define DVS_FORMAT_RGBX161616 (3<<25)
#define DVS_PIPE_CSC_ENABLE (1<<24)
#define DVS_SOURCE_KEY (1<<22)
#define DVS_RGB_ORDER_XBGR (1<<20)
#define DVS_YUV_BYTE_ORDER_MASK (3<<16)
@ -3170,7 +3168,7 @@
#define SPRITE_FORMAT_RGBX161616 (3<<25)
#define SPRITE_FORMAT_YUV444 (4<<25)
#define SPRITE_FORMAT_XR_BGR101010 (5<<25) /* Extended range */
#define SPRITE_CSC_ENABLE (1<<24)
#define SPRITE_PIPE_CSC_ENABLE (1<<24)
#define SPRITE_SOURCE_KEY (1<<22)
#define SPRITE_RGB_ORDER_RGBX (1<<20) /* only for 888 and 161616 */
#define SPRITE_YUV_TO_RGB_CSC_DISABLE (1<<19)
@ -3917,7 +3915,7 @@
#define FDI_10BPC (1<<16)
#define FDI_6BPC (2<<16)
#define FDI_12BPC (3<<16)
#define FDI_LINK_REVERSE_OVERWRITE (1<<15)
#define FDI_RX_LINK_REVERSAL_OVERRIDE (1<<15)
#define FDI_DMI_LINK_REVERSE_MASK (1<<14)
#define FDI_RX_PLL_ENABLE (1<<13)
#define FDI_FS_ERR_CORRECT_ENABLE (1<<11)
@ -4272,8 +4270,8 @@
#define GEN6_PCODE_READ_MIN_FREQ_TABLE 0x9
#define GEN6_PCODE_WRITE_RC6VIDS 0x4
#define GEN6_PCODE_READ_RC6VIDS 0x5
#define GEN6_ENCODE_RC6_VID(mv) (((mv) / 5) - 245) < 0 ?: 0
#define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) > 0 ? ((vids) * 5) + 245 : 0)
#define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5)
#define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245)
#define GEN6_PCODE_DATA 0x138128
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
@ -4516,6 +4514,7 @@
#define DDI_BUF_EMP_800MV_0DB_HSW (7<<24) /* Sel7 */
#define DDI_BUF_EMP_800MV_3_5DB_HSW (8<<24) /* Sel8 */
#define DDI_BUF_EMP_MASK (0xf<<24)
#define DDI_BUF_PORT_REVERSAL (1<<16)
#define DDI_BUF_IS_IDLE (1<<7)
#define DDI_A_4_LANES (1<<4)
#define DDI_PORT_WIDTH_X1 (0<<1)
@ -4649,4 +4648,51 @@
#define WM_DBG_DISALLOW_MAXFIFO (1<<1)
#define WM_DBG_DISALLOW_SPRITE (1<<2)
/* pipe CSC */
#define _PIPE_A_CSC_COEFF_RY_GY 0x49010
#define _PIPE_A_CSC_COEFF_BY 0x49014
#define _PIPE_A_CSC_COEFF_RU_GU 0x49018
#define _PIPE_A_CSC_COEFF_BU 0x4901c
#define _PIPE_A_CSC_COEFF_RV_GV 0x49020
#define _PIPE_A_CSC_COEFF_BV 0x49024
#define _PIPE_A_CSC_MODE 0x49028
#define _PIPE_A_CSC_PREOFF_HI 0x49030
#define _PIPE_A_CSC_PREOFF_ME 0x49034
#define _PIPE_A_CSC_PREOFF_LO 0x49038
#define _PIPE_A_CSC_POSTOFF_HI 0x49040
#define _PIPE_A_CSC_POSTOFF_ME 0x49044
#define _PIPE_A_CSC_POSTOFF_LO 0x49048
#define _PIPE_B_CSC_COEFF_RY_GY 0x49110
#define _PIPE_B_CSC_COEFF_BY 0x49114
#define _PIPE_B_CSC_COEFF_RU_GU 0x49118
#define _PIPE_B_CSC_COEFF_BU 0x4911c
#define _PIPE_B_CSC_COEFF_RV_GV 0x49120
#define _PIPE_B_CSC_COEFF_BV 0x49124
#define _PIPE_B_CSC_MODE 0x49128
#define _PIPE_B_CSC_PREOFF_HI 0x49130
#define _PIPE_B_CSC_PREOFF_ME 0x49134
#define _PIPE_B_CSC_PREOFF_LO 0x49138
#define _PIPE_B_CSC_POSTOFF_HI 0x49140
#define _PIPE_B_CSC_POSTOFF_ME 0x49144
#define _PIPE_B_CSC_POSTOFF_LO 0x49148
#define CSC_BLACK_SCREEN_OFFSET (1 << 2)
#define CSC_POSITION_BEFORE_GAMMA (1 << 1)
#define CSC_MODE_YUV_TO_RGB (1 << 0)
#define PIPE_CSC_COEFF_RY_GY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY)
#define PIPE_CSC_COEFF_BY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY)
#define PIPE_CSC_COEFF_RU_GU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU)
#define PIPE_CSC_COEFF_BU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BU, _PIPE_B_CSC_COEFF_BU)
#define PIPE_CSC_COEFF_RV_GV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, _PIPE_B_CSC_COEFF_RV_GV)
#define PIPE_CSC_COEFF_BV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BV, _PIPE_B_CSC_COEFF_BV)
#define PIPE_CSC_MODE(pipe) _PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE)
#define PIPE_CSC_PREOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, _PIPE_B_CSC_PREOFF_HI)
#define PIPE_CSC_PREOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, _PIPE_B_CSC_PREOFF_ME)
#define PIPE_CSC_PREOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, _PIPE_B_CSC_PREOFF_LO)
#define PIPE_CSC_POSTOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, _PIPE_B_CSC_POSTOFF_HI)
#define PIPE_CSC_POSTOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
#define PIPE_CSC_POSTOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
#endif /* _I915_REG_H_ */

View File

@ -800,10 +800,14 @@ void intel_crt_init(struct drm_device *dev)
dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
/*
* TODO: find a proper way to discover whether we need to set the
* polarity reversal bit or not, instead of relying on the BIOS.
* TODO: find a proper way to discover whether we need to set the the
* polarity and link reversal bits or not, instead of relying on the
* BIOS.
*/
if (HAS_PCH_LPT(dev))
dev_priv->fdi_rx_polarity_reversed =
!!(I915_READ(_FDI_RXA_CTL) & FDI_RX_POLARITY_REVERSED_LPT);
if (HAS_PCH_LPT(dev)) {
u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT |
FDI_RX_LINK_REVERSAL_OVERRIDE;
dev_priv->fdi_rx_config = I915_READ(_FDI_RXA_CTL) & fdi_config;
}
}

View File

@ -180,10 +180,8 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
/* Enable the PCH Receiver FDI PLL */
rx_ctl_val = FDI_RX_PLL_ENABLE | FDI_RX_ENHANCE_FRAME_ENABLE |
((intel_crtc->fdi_lanes - 1) << 19);
if (dev_priv->fdi_rx_polarity_reversed)
rx_ctl_val |= FDI_RX_POLARITY_REVERSED_LPT;
rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
FDI_RX_PLL_ENABLE | ((intel_crtc->fdi_lanes - 1) << 19);
I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
POSTING_READ(_FDI_RXA_CTL);
udelay(220);
@ -205,7 +203,10 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
DP_TP_CTL_LINK_TRAIN_PAT1 |
DP_TP_CTL_ENABLE);
/* Configure and enable DDI_BUF_CTL for DDI E with next voltage */
/* Configure and enable DDI_BUF_CTL for DDI E with next voltage.
* DDI E does not support port reversal, the functionality is
* achieved on the PCH side in FDI_RX_CTL, so no need to set the
* port reversal bit */
I915_WRITE(DDI_BUF_CTL(PORT_E),
DDI_BUF_CTL_ENABLE |
((intel_crtc->fdi_lanes - 1) << 1) |
@ -680,8 +681,11 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
intel_crtc->eld_vld = false;
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_digital_port *intel_dig_port =
enc_to_dig_port(encoder);
intel_dp->DP = DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
intel_dp->DP = intel_dig_port->port_reversal |
DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
switch (intel_dp->lane_count) {
case 1:
intel_dp->DP |= DDI_PORT_WIDTH_X1;
@ -1304,11 +1308,15 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
uint32_t tmp;
if (type == INTEL_OUTPUT_HDMI) {
struct intel_digital_port *intel_dig_port =
enc_to_dig_port(encoder);
/* In HDMI/DVI mode, the port width, and swing/emphasis values
* are ignored so nothing special needs to be done besides
* enabling the port.
*/
I915_WRITE(DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE);
I915_WRITE(DDI_BUF_CTL(port),
intel_dig_port->port_reversal | DDI_BUF_CTL_ENABLE);
} else if (type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@ -1485,6 +1493,7 @@ static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = {
void intel_ddi_init(struct drm_device *dev, enum port port)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_digital_port *intel_dig_port;
struct intel_encoder *intel_encoder;
struct drm_encoder *encoder;
@ -1525,6 +1534,8 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
intel_encoder->get_hw_state = intel_ddi_get_hw_state;
intel_dig_port->port = port;
intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
DDI_BUF_PORT_REVERSAL;
if (hdmi_connector)
intel_dig_port->hdmi.sdvox_reg = DDI_BUF_CTL(port);
else

View File

@ -154,8 +154,8 @@ static const intel_limit_t intel_limits_i9xx_sdvo = {
.vco = { .min = 1400000, .max = 2800000 },
.n = { .min = 1, .max = 6 },
.m = { .min = 70, .max = 120 },
.m1 = { .min = 10, .max = 22 },
.m2 = { .min = 5, .max = 9 },
.m1 = { .min = 8, .max = 18 },
.m2 = { .min = 3, .max = 7 },
.p = { .min = 5, .max = 80 },
.p1 = { .min = 1, .max = 8 },
.p2 = { .dot_limit = 200000,
@ -168,8 +168,8 @@ static const intel_limit_t intel_limits_i9xx_lvds = {
.vco = { .min = 1400000, .max = 2800000 },
.n = { .min = 1, .max = 6 },
.m = { .min = 70, .max = 120 },
.m1 = { .min = 10, .max = 22 },
.m2 = { .min = 5, .max = 9 },
.m1 = { .min = 8, .max = 18 },
.m2 = { .min = 3, .max = 7 },
.p = { .min = 7, .max = 98 },
.p1 = { .min = 1, .max = 8 },
.p2 = { .dot_limit = 112000,
@ -2226,12 +2226,6 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
bool was_interruptible = dev_priv->mm.interruptible;
int ret;
WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
wait_event(dev_priv->pending_flip_queue,
i915_reset_in_progress(&dev_priv->gpu_error) ||
atomic_read(&obj->pending_flip) == 0);
/* Big Hammer, we also need to ensure that any pending
* MI_WAIT_FOR_EVENT inside a user batch buffer on the
* current scanout is retired before unpinning the old
@ -2874,10 +2868,12 @@ static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
unsigned long flags;
bool pending;
if (i915_reset_in_progress(&dev_priv->gpu_error))
if (i915_reset_in_progress(&dev_priv->gpu_error) ||
intel_crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
return false;
spin_lock_irqsave(&dev->event_lock, flags);
@ -3615,6 +3611,11 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_update_watermarks(dev);
intel_enable_pll(dev_priv, pipe);
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable)
encoder->pre_enable(encoder);
intel_enable_pipe(dev_priv, pipe, false);
intel_enable_plane(dev_priv, plane, pipe);
@ -3637,6 +3638,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
struct intel_encoder *encoder;
int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane;
u32 pctl;
if (!intel_crtc->active)
@ -3656,6 +3658,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_disable_plane(dev_priv, plane, pipe);
intel_disable_pipe(dev_priv, pipe);
/* Disable pannel fitter if it is on this pipe. */
pctl = I915_READ(PFIT_CONTROL);
if ((pctl & PFIT_ENABLE) &&
((pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT) == pipe)
I915_WRITE(PFIT_CONTROL, 0);
intel_disable_pll(dev_priv, pipe);
intel_crtc->active = false;
@ -5109,6 +5118,71 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
POSTING_READ(PIPECONF(pipe));
}
/*
* Set up the pipe CSC unit.
*
* Currently only full range RGB to limited range RGB conversion
* is supported, but eventually this should handle various
* RGB<->YCbCr scenarios as well.
*/
static void intel_set_pipe_csc(struct drm_crtc *crtc,
const struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
uint16_t coeff = 0x7800; /* 1.0 */
/*
* TODO: Check what kind of values actually come out of the pipe
* with these coeff/postoff values and adjust to get the best
* accuracy. Perhaps we even need to take the bpc value into
* consideration.
*/
if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
/*
* GY/GU and RY/RU should be the other way around according
* to BSpec, but reality doesn't agree. Just set them up in
* a way that results in the correct picture.
*/
I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
if (INTEL_INFO(dev)->gen > 6) {
uint16_t postoff = 0;
if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
postoff = (16 * (1 << 13) / 255) & 0x1fff;
I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
I915_WRITE(PIPE_CSC_MODE(pipe), 0);
} else {
uint32_t mode = CSC_MODE_YUV_TO_RGB;
if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
mode |= CSC_BLACK_SCREEN_OFFSET;
I915_WRITE(PIPE_CSC_MODE(pipe), mode);
}
}
static void haswell_set_pipeconf(struct drm_crtc *crtc,
struct drm_display_mode *adjusted_mode,
bool dither)
@ -5697,8 +5771,10 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
haswell_set_pipeconf(crtc, adjusted_mode, dither);
intel_set_pipe_csc(crtc, adjusted_mode);
/* Set up the display plane register */
I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE);
POSTING_READ(DSPCNTR(plane));
ret = intel_pipe_set_base(crtc, x, y, fb);
@ -6103,6 +6179,8 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
cntl |= CURSOR_MODE_DISABLE;
}
if (IS_HASWELL(dev))
cntl |= CURSOR_PIPE_CSC_ENABLE;
I915_WRITE(CURCNTR_IVB(pipe), cntl);
intel_crtc->cursor_visible = visible;
@ -7235,6 +7313,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
work->enable_stall_check = true;
atomic_inc(&intel_crtc->unpin_work_count);
intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
ret = dev_priv->display.queue_flip(dev, crtc, fb, obj);
if (ret)
@ -7876,7 +7955,7 @@ intel_modeset_stage_output_state(struct drm_device *dev,
struct intel_encoder *encoder;
int count, ro;
/* The upper layers ensure that we either disabl a crtc or have a list
/* The upper layers ensure that we either disable a crtc or have a list
* of connectors. For paranoia, double-check this. */
WARN_ON(!set->fb && (set->num_connectors != 0));
WARN_ON(set->fb && (set->num_connectors == 0));
@ -8655,6 +8734,9 @@ static struct intel_quirk intel_quirks[] = {
/* Acer/Packard Bell NCL20 */
{ 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
/* Acer Aspire 4736Z */
{ 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
};
static void intel_init_quirks(struct drm_device *dev)

View File

@ -2302,13 +2302,13 @@ g4x_dp_detect(struct intel_dp *intel_dp)
switch (intel_dig_port->port) {
case PORT_B:
bit = DPB_HOTPLUG_LIVE_STATUS;
bit = PORTB_HOTPLUG_LIVE_STATUS;
break;
case PORT_C:
bit = DPC_HOTPLUG_LIVE_STATUS;
bit = PORTC_HOTPLUG_LIVE_STATUS;
break;
case PORT_D:
bit = DPD_HOTPLUG_LIVE_STATUS;
bit = PORTD_HOTPLUG_LIVE_STATUS;
break;
default:
return connector_status_unknown;
@ -2837,15 +2837,15 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
name = "DPDDC-A";
break;
case PORT_B:
dev_priv->hotplug_supported_mask |= DPB_HOTPLUG_INT_STATUS;
dev_priv->hotplug_supported_mask |= PORTB_HOTPLUG_INT_STATUS;
name = "DPDDC-B";
break;
case PORT_C:
dev_priv->hotplug_supported_mask |= DPC_HOTPLUG_INT_STATUS;
dev_priv->hotplug_supported_mask |= PORTC_HOTPLUG_INT_STATUS;
name = "DPDDC-C";
break;
case PORT_D:
dev_priv->hotplug_supported_mask |= DPD_HOTPLUG_INT_STATUS;
dev_priv->hotplug_supported_mask |= PORTD_HOTPLUG_INT_STATUS;
name = "DPDDC-D";
break;
default:

View File

@ -235,6 +235,9 @@ struct intel_crtc {
/* We can share PLLs across outputs if the timings match */
struct intel_pch_pll *pch_pll;
uint32_t ddi_pll_sel;
/* reset counter value when the last flip was submitted */
unsigned int reset_counter;
};
struct intel_plane {
@ -390,6 +393,7 @@ struct intel_dp {
struct intel_digital_port {
struct intel_encoder base;
enum port port;
u32 port_reversal;
struct intel_dp dp;
struct intel_hdmi hdmi;
};

View File

@ -802,10 +802,10 @@ static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi)
switch (intel_dig_port->port) {
case PORT_B:
bit = HDMIB_HOTPLUG_LIVE_STATUS;
bit = PORTB_HOTPLUG_LIVE_STATUS;
break;
case PORT_C:
bit = HDMIC_HOTPLUG_LIVE_STATUS;
bit = PORTC_HOTPLUG_LIVE_STATUS;
break;
default:
bit = 0;
@ -1021,15 +1021,15 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
switch (port) {
case PORT_B:
intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
dev_priv->hotplug_supported_mask |= PORTB_HOTPLUG_INT_STATUS;
break;
case PORT_C:
intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
dev_priv->hotplug_supported_mask |= PORTC_HOTPLUG_INT_STATUS;
break;
case PORT_D:
intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
dev_priv->hotplug_supported_mask |= PORTD_HOTPLUG_INT_STATUS;
break;
case PORT_A:
/* Internal port only for eDP. */

View File

@ -51,7 +51,6 @@ struct intel_lvds_encoder {
u32 pfit_control;
u32 pfit_pgm_ratios;
bool pfit_dirty;
bool is_dual_link;
u32 reg;
@ -151,6 +150,29 @@ static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder)
I915_WRITE(lvds_encoder->reg, temp);
}
static void intel_pre_enable_lvds(struct intel_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct intel_lvds_encoder *enc = to_lvds_encoder(&encoder->base);
struct drm_i915_private *dev_priv = dev->dev_private;
if (HAS_PCH_SPLIT(dev) || !enc->pfit_control)
return;
/*
* Enable automatic panel scaling so that non-native modes
* fill the screen. The panel fitter should only be
* adjusted whilst the pipe is disabled, according to
* register description and PRM.
*/
DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
enc->pfit_control,
enc->pfit_pgm_ratios);
I915_WRITE(PFIT_PGM_RATIOS, enc->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, enc->pfit_control);
}
/**
* Sets the power state for the panel.
*/
@ -172,22 +194,6 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
if (lvds_encoder->pfit_dirty) {
/*
* Enable automatic panel scaling so that non-native modes
* fill the screen. The panel fitter should only be
* adjusted whilst the pipe is disabled, according to
* register description and PRM.
*/
DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
lvds_encoder->pfit_control,
lvds_encoder->pfit_pgm_ratios);
I915_WRITE(PFIT_PGM_RATIOS, lvds_encoder->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, lvds_encoder->pfit_control);
lvds_encoder->pfit_dirty = false;
}
I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
POSTING_READ(lvds_encoder->reg);
if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000))
@ -217,11 +223,6 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000))
DRM_ERROR("timed out waiting for panel to power off\n");
if (lvds_encoder->pfit_control) {
I915_WRITE(PFIT_CONTROL, 0);
lvds_encoder->pfit_dirty = true;
}
I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
POSTING_READ(lvds_encoder->reg);
}
@ -461,7 +462,6 @@ out:
pfit_pgm_ratios != lvds_encoder->pfit_pgm_ratios) {
lvds_encoder->pfit_control = pfit_control;
lvds_encoder->pfit_pgm_ratios = pfit_pgm_ratios;
lvds_encoder->pfit_dirty = true;
}
dev_priv->lvds_border_bits = border;
@ -547,13 +547,14 @@ static const struct dmi_system_id intel_no_modeset_on_lid[] = {
};
/*
* Lid events. Note the use of 'modeset_on_lid':
* - we set it on lid close, and reset it on open
* Lid events. Note the use of 'modeset':
* - we set it to MODESET_ON_LID_OPEN on lid close,
* and set it to MODESET_DONE on open
* - we use it as a "only once" bit (ie we ignore
* duplicate events where it was already properly
* set/reset)
* - the suspend/resume paths will also set it to
* zero, since they restore the mode ("lid open").
* duplicate events where it was already properly set)
* - the suspend/resume paths will set it to
* MODESET_SUSPENDED and ignore the lid open event,
* because they restore the mode ("lid open").
*/
static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
void *unused)
@ -567,6 +568,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
return NOTIFY_OK;
mutex_lock(&dev_priv->modeset_restore_lock);
if (dev_priv->modeset_restore == MODESET_SUSPENDED)
goto exit;
/*
* check and update the status of LVDS connector after receiving
* the LID nofication event.
@ -575,21 +579,24 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
/* Don't force modeset on machines where it causes a GPU lockup */
if (dmi_check_system(intel_no_modeset_on_lid))
return NOTIFY_OK;
goto exit;
if (!acpi_lid_open()) {
dev_priv->modeset_on_lid = 1;
return NOTIFY_OK;
/* do modeset on next lid open event */
dev_priv->modeset_restore = MODESET_ON_LID_OPEN;
goto exit;
}
if (!dev_priv->modeset_on_lid)
return NOTIFY_OK;
dev_priv->modeset_on_lid = 0;
if (dev_priv->modeset_restore == MODESET_DONE)
goto exit;
drm_modeset_lock_all(dev);
intel_modeset_setup_hw_state(dev, true);
drm_modeset_unlock_all(dev);
dev_priv->modeset_restore = MODESET_DONE;
exit:
mutex_unlock(&dev_priv->modeset_restore_lock);
return NOTIFY_OK;
}
@ -1093,6 +1100,7 @@ bool intel_lvds_init(struct drm_device *dev)
DRM_MODE_ENCODER_LVDS);
intel_encoder->enable = intel_enable_lvds;
intel_encoder->pre_enable = intel_pre_enable_lvds;
intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds;
intel_encoder->disable = intel_disable_lvds;
intel_encoder->get_hw_state = intel_lvds_get_hw_state;

View File

@ -321,6 +321,9 @@ void intel_panel_enable_backlight(struct drm_device *dev,
if (dev_priv->backlight_level == 0)
dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
dev_priv->backlight_enabled = true;
intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
if (INTEL_INFO(dev)->gen >= 4) {
uint32_t reg, tmp;
@ -356,12 +359,12 @@ void intel_panel_enable_backlight(struct drm_device *dev,
}
set_level:
/* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1.
* BLC_PWM_CPU_CTL may be cleared to zero automatically when these
* registers are set.
/* Check the current backlight level and try to set again if it's zero.
* On some machines, BLC_PWM_CPU_CTL is cleared to zero automatically
* when BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1 are written.
*/
dev_priv->backlight_enabled = true;
intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
if (!intel_panel_get_backlight(dev))
intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
}
static void intel_panel_init_backlight(struct drm_device *dev)

View File

@ -2289,7 +2289,6 @@ err_unpin:
i915_gem_object_unpin(ctx);
err_unref:
drm_gem_object_unreference(&ctx->base);
mutex_unlock(&dev->struct_mutex);
return NULL;
}
@ -3584,6 +3583,19 @@ static void cpt_init_clock_gating(struct drm_device *dev)
}
}
static void gen6_check_mch_setup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t tmp;
tmp = I915_READ(MCH_SSKPD);
if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL) {
DRM_INFO("Wrong MCH_SSKPD value: 0x%08x\n", tmp);
DRM_INFO("This can cause pipe underruns and display issues.\n");
DRM_INFO("Please upgrade your BIOS to fix this.\n");
}
}
static void gen6_init_clock_gating(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@ -3676,6 +3688,8 @@ static void gen6_init_clock_gating(struct drm_device *dev)
I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_GT_MODE_HI));
cpt_init_clock_gating(dev);
gen6_check_mch_setup(dev);
}
static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
@ -3861,6 +3875,8 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
cpt_init_clock_gating(dev);
gen6_check_mch_setup(dev);
}
static void valleyview_init_clock_gating(struct drm_device *dev)

View File

@ -318,6 +318,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring,
* TLB invalidate requires a post-sync write.
*/
flags |= PIPE_CONTROL_QW_WRITE;
flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
/* Workaround: we must issue a pipe_control with CS-stall bit
* set before a pipe_control command that has the state cache
@ -331,7 +332,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring,
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
intel_ring_emit(ring, flags);
intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, scratch_addr);
intel_ring_emit(ring, 0);
intel_ring_advance(ring);
@ -467,6 +468,9 @@ init_pipe_control(struct intel_ring_buffer *ring)
if (pc->cpu_page == NULL)
goto err_unpin;
DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
ring->name, pc->gtt_offset);
pc->obj = obj;
ring->private = pc;
return 0;

View File

@ -50,6 +50,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
u32 sprctl, sprscale = 0;
unsigned long sprsurf_offset, linear_offset;
int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
sprctl = I915_READ(SPRCTL(pipe));
@ -89,6 +90,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
sprctl |= SPRITE_ENABLE;
if (IS_HASWELL(dev))
sprctl |= SPRITE_PIPE_CSC_ENABLE;
/* Sizes are 0 based */
src_w--;
src_h--;
@ -103,19 +107,15 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
* when scaling is disabled.
*/
if (crtc_w != src_w || crtc_h != src_h) {
if (!dev_priv->sprite_scaling_enabled) {
dev_priv->sprite_scaling_enabled = true;
dev_priv->sprite_scaling_enabled |= 1 << pipe;
if (!scaling_was_enabled) {
intel_update_watermarks(dev);
intel_wait_for_vblank(dev, pipe);
}
sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
} else {
if (dev_priv->sprite_scaling_enabled) {
dev_priv->sprite_scaling_enabled = false;
/* potentially re-enable LP watermarks */
intel_update_watermarks(dev);
}
}
} else
dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
@ -141,6 +141,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
I915_WRITE(SPRCTL(pipe), sprctl);
I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
POSTING_READ(SPRSURF(pipe));
/* potentially re-enable LP watermarks */
if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
intel_update_watermarks(dev);
}
static void
@ -150,6 +154,7 @@ ivb_disable_plane(struct drm_plane *plane)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
int pipe = intel_plane->pipe;
bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
/* Can't leave the scaler enabled... */
@ -159,8 +164,11 @@ ivb_disable_plane(struct drm_plane *plane)
I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
POSTING_READ(SPRSURF(pipe));
dev_priv->sprite_scaling_enabled = false;
intel_update_watermarks(dev);
dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
/* potentially re-enable LP watermarks */
if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
intel_update_watermarks(dev);
}
static int

View File

@ -4253,13 +4253,19 @@ static void quirk_iommu_rwbf(struct pci_dev *dev)
{
/*
* Mobile 4 Series Chipset neglects to set RWBF capability,
* but needs it:
* but needs it. Same seems to hold for the desktop versions.
*/
printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
rwbf_quirk = 1;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
#define GGC 0x52
#define GGC_MEMORY_SIZE_MASK (0xf << 8)

View File

@ -3,7 +3,8 @@
#ifndef _DRM_INTEL_GTT_H
#define _DRM_INTEL_GTT_H
void intel_gtt_get(size_t *gtt_total, size_t *stolen_size);
void intel_gtt_get(size_t *gtt_total, size_t *stolen_size,
phys_addr_t *mappable_base, unsigned long *mappable_end);
int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
struct agp_bridge_data *bridge);