提交 b403b73c 编写于 作者: L Linus Torvalds

Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "Travelling slowed down getting these out.

  Two vmwgfx fixes, a radeon revert to avoid a regression, i915 fixes,
  and some ioctl sizing issues fixed with 32 on 64"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/radeon/audio: don't set speaker allocation on DCE4+
  drm/radeon: rework audio option
  drm/radeon/audio: don't set speaker allocation on DCE3.2
  drm/radeon: make missing smc ucode non-fatal (CI)
  drm/radeon: make missing smc ucode non-fatal (r7xx-SI)
  drm/radeon/uvd: revert lower msg&fb buffer requirements on UVD3
  drm/radeon: stop the leaks in cik_ib_test
  drm/radeon/atom: workaround vbios bug in transmitter table on rs780
  drm/i915: Disable GGTT PTEs on GEN6+ suspend
  drm/i915: Make PTE valid encoding optional
  drm: Pad drm_mode_get_connector to 64-bit boundary
  drm: Prevent overwriting from userspace underallocating core ioctl structs
  drm/vmwgfx: Don't kill clients on VT switch
  drm/vmwgfx: Don't put resources with invalid id's on lru list
  drm/i915: disable LVDS clock gating on CPT v2
...@@ -402,9 +402,16 @@ long drm_ioctl(struct file *filp, ...@@ -402,9 +402,16 @@ long drm_ioctl(struct file *filp,
cmd = ioctl->cmd_drv; cmd = ioctl->cmd_drv;
} }
else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) { else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
u32 drv_size;
ioctl = &drm_ioctls[nr]; ioctl = &drm_ioctls[nr];
cmd = ioctl->cmd;
drv_size = _IOC_SIZE(ioctl->cmd);
usize = asize = _IOC_SIZE(cmd); usize = asize = _IOC_SIZE(cmd);
if (drv_size > asize)
asize = drv_size;
cmd = ioctl->cmd;
} else } else
goto err_i1; goto err_i1;
......
...@@ -505,6 +505,8 @@ static int i915_drm_freeze(struct drm_device *dev) ...@@ -505,6 +505,8 @@ static int i915_drm_freeze(struct drm_device *dev)
intel_modeset_suspend_hw(dev); intel_modeset_suspend_hw(dev);
} }
i915_gem_suspend_gtt_mappings(dev);
i915_save_state(dev); i915_save_state(dev);
intel_opregion_fini(dev); intel_opregion_fini(dev);
...@@ -648,7 +650,8 @@ static int i915_drm_thaw(struct drm_device *dev) ...@@ -648,7 +650,8 @@ static int i915_drm_thaw(struct drm_device *dev)
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);
} } else if (drm_core_check_feature(dev, DRIVER_MODESET))
i915_check_and_clear_faults(dev);
__i915_drm_thaw(dev); __i915_drm_thaw(dev);
......
...@@ -497,10 +497,12 @@ struct i915_address_space { ...@@ -497,10 +497,12 @@ struct i915_address_space {
/* FIXME: Need a more generic return type */ /* FIXME: Need a more generic return type */
gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr, gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
enum i915_cache_level level); enum i915_cache_level level,
bool valid); /* Create a valid PTE */
void (*clear_range)(struct i915_address_space *vm, void (*clear_range)(struct i915_address_space *vm,
unsigned int first_entry, unsigned int first_entry,
unsigned int num_entries); unsigned int num_entries,
bool use_scratch);
void (*insert_entries)(struct i915_address_space *vm, void (*insert_entries)(struct i915_address_space *vm,
struct sg_table *st, struct sg_table *st,
unsigned int first_entry, unsigned int first_entry,
...@@ -2065,6 +2067,8 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, ...@@ -2065,6 +2067,8 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
struct drm_i915_gem_object *obj); struct drm_i915_gem_object *obj);
void i915_check_and_clear_faults(struct drm_device *dev);
void i915_gem_suspend_gtt_mappings(struct drm_device *dev);
void i915_gem_restore_gtt_mappings(struct drm_device *dev); void i915_gem_restore_gtt_mappings(struct drm_device *dev);
int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj); int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
......
...@@ -58,9 +58,10 @@ ...@@ -58,9 +58,10 @@
#define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) #define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6)
static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
enum i915_cache_level level) enum i915_cache_level level,
bool valid)
{ {
gen6_gtt_pte_t pte = GEN6_PTE_VALID; gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= GEN6_PTE_ADDR_ENCODE(addr); pte |= GEN6_PTE_ADDR_ENCODE(addr);
switch (level) { switch (level) {
...@@ -79,9 +80,10 @@ static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, ...@@ -79,9 +80,10 @@ static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
} }
static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
enum i915_cache_level level) enum i915_cache_level level,
bool valid)
{ {
gen6_gtt_pte_t pte = GEN6_PTE_VALID; gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= GEN6_PTE_ADDR_ENCODE(addr); pte |= GEN6_PTE_ADDR_ENCODE(addr);
switch (level) { switch (level) {
...@@ -105,9 +107,10 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, ...@@ -105,9 +107,10 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
#define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2) #define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2)
static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
enum i915_cache_level level) enum i915_cache_level level,
bool valid)
{ {
gen6_gtt_pte_t pte = GEN6_PTE_VALID; gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= GEN6_PTE_ADDR_ENCODE(addr); pte |= GEN6_PTE_ADDR_ENCODE(addr);
/* Mark the page as writeable. Other platforms don't have a /* Mark the page as writeable. Other platforms don't have a
...@@ -122,9 +125,10 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, ...@@ -122,9 +125,10 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
} }
static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
enum i915_cache_level level) enum i915_cache_level level,
bool valid)
{ {
gen6_gtt_pte_t pte = GEN6_PTE_VALID; gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= HSW_PTE_ADDR_ENCODE(addr); pte |= HSW_PTE_ADDR_ENCODE(addr);
if (level != I915_CACHE_NONE) if (level != I915_CACHE_NONE)
...@@ -134,9 +138,10 @@ static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, ...@@ -134,9 +138,10 @@ static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
} }
static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
enum i915_cache_level level) enum i915_cache_level level,
bool valid)
{ {
gen6_gtt_pte_t pte = GEN6_PTE_VALID; gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= HSW_PTE_ADDR_ENCODE(addr); pte |= HSW_PTE_ADDR_ENCODE(addr);
switch (level) { switch (level) {
...@@ -236,7 +241,8 @@ static int gen6_ppgtt_enable(struct drm_device *dev) ...@@ -236,7 +241,8 @@ static int gen6_ppgtt_enable(struct drm_device *dev)
/* PPGTT support for Sandybdrige/Gen6 and later */ /* PPGTT support for Sandybdrige/Gen6 and later */
static void gen6_ppgtt_clear_range(struct i915_address_space *vm, static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
unsigned first_entry, unsigned first_entry,
unsigned num_entries) unsigned num_entries,
bool use_scratch)
{ {
struct i915_hw_ppgtt *ppgtt = struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base); container_of(vm, struct i915_hw_ppgtt, base);
...@@ -245,7 +251,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, ...@@ -245,7 +251,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
unsigned last_pte, i; unsigned last_pte, i;
scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
while (num_entries) { while (num_entries) {
last_pte = first_pte + num_entries; last_pte = first_pte + num_entries;
...@@ -282,7 +288,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, ...@@ -282,7 +288,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
dma_addr_t page_addr; dma_addr_t page_addr;
page_addr = sg_page_iter_dma_address(&sg_iter); page_addr = sg_page_iter_dma_address(&sg_iter);
pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level); pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level, true);
if (++act_pte == I915_PPGTT_PT_ENTRIES) { if (++act_pte == I915_PPGTT_PT_ENTRIES) {
kunmap_atomic(pt_vaddr); kunmap_atomic(pt_vaddr);
act_pt++; act_pt++;
...@@ -367,7 +373,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ...@@ -367,7 +373,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
} }
ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.clear_range(&ppgtt->base, 0,
ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES); ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true);
ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t); ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t);
...@@ -444,7 +450,8 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, ...@@ -444,7 +450,8 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
{ {
ppgtt->base.clear_range(&ppgtt->base, ppgtt->base.clear_range(&ppgtt->base,
i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT, i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
obj->base.size >> PAGE_SHIFT); obj->base.size >> PAGE_SHIFT,
true);
} }
extern int intel_iommu_gfx_mapped; extern int intel_iommu_gfx_mapped;
...@@ -485,15 +492,65 @@ static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) ...@@ -485,15 +492,65 @@ static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
dev_priv->mm.interruptible = interruptible; dev_priv->mm.interruptible = interruptible;
} }
void i915_check_and_clear_faults(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring;
int i;
if (INTEL_INFO(dev)->gen < 6)
return;
for_each_ring(ring, dev_priv, i) {
u32 fault_reg;
fault_reg = I915_READ(RING_FAULT_REG(ring));
if (fault_reg & RING_FAULT_VALID) {
DRM_DEBUG_DRIVER("Unexpected fault\n"
"\tAddr: 0x%08lx\\n"
"\tAddress space: %s\n"
"\tSource ID: %d\n"
"\tType: %d\n",
fault_reg & PAGE_MASK,
fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT",
RING_FAULT_SRCID(fault_reg),
RING_FAULT_FAULT_TYPE(fault_reg));
I915_WRITE(RING_FAULT_REG(ring),
fault_reg & ~RING_FAULT_VALID);
}
}
POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS]));
}
void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
/* Don't bother messing with faults pre GEN6 as we have little
* documentation supporting that it's a good idea.
*/
if (INTEL_INFO(dev)->gen < 6)
return;
i915_check_and_clear_faults(dev);
dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
dev_priv->gtt.base.start / PAGE_SIZE,
dev_priv->gtt.base.total / PAGE_SIZE,
false);
}
void i915_gem_restore_gtt_mappings(struct drm_device *dev) void i915_gem_restore_gtt_mappings(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
i915_check_and_clear_faults(dev);
/* First fill our portion of the GTT with scratch pages */ /* First fill our portion of the GTT with scratch pages */
dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
dev_priv->gtt.base.start / PAGE_SIZE, dev_priv->gtt.base.start / PAGE_SIZE,
dev_priv->gtt.base.total / PAGE_SIZE); dev_priv->gtt.base.total / PAGE_SIZE,
true);
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
i915_gem_clflush_object(obj, obj->pin_display); i915_gem_clflush_object(obj, obj->pin_display);
...@@ -536,7 +593,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, ...@@ -536,7 +593,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
addr = sg_page_iter_dma_address(&sg_iter); addr = sg_page_iter_dma_address(&sg_iter);
iowrite32(vm->pte_encode(addr, level), &gtt_entries[i]); iowrite32(vm->pte_encode(addr, level, true), &gtt_entries[i]);
i++; i++;
} }
...@@ -548,7 +605,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, ...@@ -548,7 +605,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
*/ */
if (i != 0) if (i != 0)
WARN_ON(readl(&gtt_entries[i-1]) != WARN_ON(readl(&gtt_entries[i-1]) !=
vm->pte_encode(addr, level)); vm->pte_encode(addr, level, true));
/* This next bit makes the above posting read even more important. We /* This next bit makes the above posting read even more important. We
* want to flush the TLBs only after we're certain all the PTE updates * want to flush the TLBs only after we're certain all the PTE updates
...@@ -560,7 +617,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, ...@@ -560,7 +617,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
static void gen6_ggtt_clear_range(struct i915_address_space *vm, static void gen6_ggtt_clear_range(struct i915_address_space *vm,
unsigned int first_entry, unsigned int first_entry,
unsigned int num_entries) unsigned int num_entries,
bool use_scratch)
{ {
struct drm_i915_private *dev_priv = vm->dev->dev_private; struct drm_i915_private *dev_priv = vm->dev->dev_private;
gen6_gtt_pte_t scratch_pte, __iomem *gtt_base = gen6_gtt_pte_t scratch_pte, __iomem *gtt_base =
...@@ -573,7 +631,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, ...@@ -573,7 +631,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
first_entry, num_entries, max_entries)) first_entry, num_entries, max_entries))
num_entries = max_entries; num_entries = max_entries;
scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch);
for (i = 0; i < num_entries; i++) for (i = 0; i < num_entries; i++)
iowrite32(scratch_pte, &gtt_base[i]); iowrite32(scratch_pte, &gtt_base[i]);
readl(gtt_base); readl(gtt_base);
...@@ -594,7 +653,8 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm, ...@@ -594,7 +653,8 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm,
static void i915_ggtt_clear_range(struct i915_address_space *vm, static void i915_ggtt_clear_range(struct i915_address_space *vm,
unsigned int first_entry, unsigned int first_entry,
unsigned int num_entries) unsigned int num_entries,
bool unused)
{ {
intel_gtt_clear_range(first_entry, num_entries); intel_gtt_clear_range(first_entry, num_entries);
} }
...@@ -622,7 +682,8 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) ...@@ -622,7 +682,8 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
entry, entry,
obj->base.size >> PAGE_SHIFT); obj->base.size >> PAGE_SHIFT,
true);
obj->has_global_gtt_mapping = 0; obj->has_global_gtt_mapping = 0;
} }
...@@ -709,11 +770,11 @@ void i915_gem_setup_global_gtt(struct drm_device *dev, ...@@ -709,11 +770,11 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
const unsigned long count = (hole_end - hole_start) / PAGE_SIZE; const unsigned long count = (hole_end - hole_start) / PAGE_SIZE;
DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
hole_start, hole_end); hole_start, hole_end);
ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count); ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count, true);
} }
/* And finally clear the reserved guard page */ /* And finally clear the reserved guard page */
ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1); ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1, true);
} }
static bool static bool
......
...@@ -604,6 +604,10 @@ ...@@ -604,6 +604,10 @@
#define ARB_MODE_SWIZZLE_IVB (1<<5) #define ARB_MODE_SWIZZLE_IVB (1<<5)
#define RENDER_HWS_PGA_GEN7 (0x04080) #define RENDER_HWS_PGA_GEN7 (0x04080)
#define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) #define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id)
#define RING_FAULT_GTTSEL_MASK (1<<11)
#define RING_FAULT_SRCID(x) ((x >> 3) & 0xff)
#define RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3)
#define RING_FAULT_VALID (1<<0)
#define DONE_REG 0x40b0 #define DONE_REG 0x40b0
#define BSD_HWS_PGA_GEN7 (0x04180) #define BSD_HWS_PGA_GEN7 (0x04180)
#define BLT_HWS_PGA_GEN7 (0x04280) #define BLT_HWS_PGA_GEN7 (0x04280)
...@@ -4279,7 +4283,9 @@ ...@@ -4279,7 +4283,9 @@
#define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN) #define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN)
#define SOUTH_DSPCLK_GATE_D 0xc2020 #define SOUTH_DSPCLK_GATE_D 0xc2020
#define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1<<30)
#define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29) #define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29)
#define PCH_CPUNIT_CLOCK_GATE_DISABLE (1<<14)
#define PCH_LP_PARTITION_LEVEL_DISABLE (1<<12) #define PCH_LP_PARTITION_LEVEL_DISABLE (1<<12)
/* CPU: FDI_TX */ /* CPU: FDI_TX */
......
...@@ -4759,7 +4759,9 @@ static void cpt_init_clock_gating(struct drm_device *dev) ...@@ -4759,7 +4759,9 @@ static void cpt_init_clock_gating(struct drm_device *dev)
* gating for the panel power sequencer or it will fail to * gating for the panel power sequencer or it will fail to
* start up when no ports are active. * start up when no ports are active.
*/ */
I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE |
PCH_DPLUNIT_CLOCK_GATE_DISABLE |
PCH_CPUNIT_CLOCK_GATE_DISABLE);
I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) | I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
DPLS_EDP_PPS_FIX_DIS); DPLS_EDP_PPS_FIX_DIS);
/* The below fixes the weird display corruption, a few pixels shifted /* The below fixes the weird display corruption, a few pixels shifted
......
...@@ -707,24 +707,37 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) ...@@ -707,24 +707,37 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
switch (connector->connector_type) { switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) || if (radeon_audio != 0) {
(drm_detect_hdmi_monitor(radeon_connector->edid) && if (radeon_connector->use_digital &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))) (radeon_connector->audio == RADEON_AUDIO_ENABLE))
return ATOM_ENCODER_MODE_HDMI; return ATOM_ENCODER_MODE_HDMI;
else if (radeon_connector->use_digital) else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else if (radeon_connector->use_digital)
return ATOM_ENCODER_MODE_DVI;
else
return ATOM_ENCODER_MODE_CRT;
} else if (radeon_connector->use_digital) {
return ATOM_ENCODER_MODE_DVI; return ATOM_ENCODER_MODE_DVI;
else } else {
return ATOM_ENCODER_MODE_CRT; return ATOM_ENCODER_MODE_CRT;
}
break; break;
case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA: case DRM_MODE_CONNECTOR_HDMIA:
default: default:
if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) || if (radeon_audio != 0) {
(drm_detect_hdmi_monitor(radeon_connector->edid) && if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
(radeon_connector->audio == RADEON_AUDIO_AUTO))) return ATOM_ENCODER_MODE_HDMI;
return ATOM_ENCODER_MODE_HDMI; else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
else (radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else
return ATOM_ENCODER_MODE_DVI;
} else {
return ATOM_ENCODER_MODE_DVI; return ATOM_ENCODER_MODE_DVI;
}
break; break;
case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_LVDS:
return ATOM_ENCODER_MODE_LVDS; return ATOM_ENCODER_MODE_LVDS;
...@@ -732,14 +745,19 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) ...@@ -732,14 +745,19 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
case DRM_MODE_CONNECTOR_DisplayPort: case DRM_MODE_CONNECTOR_DisplayPort:
dig_connector = radeon_connector->con_priv; dig_connector = radeon_connector->con_priv;
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
return ATOM_ENCODER_MODE_DP; return ATOM_ENCODER_MODE_DP;
else if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) || } else if (radeon_audio != 0) {
(drm_detect_hdmi_monitor(radeon_connector->edid) && if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
(radeon_connector->audio == RADEON_AUDIO_AUTO))) return ATOM_ENCODER_MODE_HDMI;
return ATOM_ENCODER_MODE_HDMI; else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
else (radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else
return ATOM_ENCODER_MODE_DVI;
} else {
return ATOM_ENCODER_MODE_DVI; return ATOM_ENCODER_MODE_DVI;
}
break; break;
case DRM_MODE_CONNECTOR_eDP: case DRM_MODE_CONNECTOR_eDP:
return ATOM_ENCODER_MODE_DP; return ATOM_ENCODER_MODE_DP;
...@@ -1655,7 +1673,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) ...@@ -1655,7 +1673,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
* does the same thing and more. * does the same thing and more.
*/ */
if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) && if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) &&
(rdev->family != CHIP_RS880)) (rdev->family != CHIP_RS780) && (rdev->family != CHIP_RS880))
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
} }
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
......
...@@ -1694,6 +1694,7 @@ static int cik_init_microcode(struct radeon_device *rdev) ...@@ -1694,6 +1694,7 @@ static int cik_init_microcode(struct radeon_device *rdev)
fw_name); fw_name);
release_firmware(rdev->smc_fw); release_firmware(rdev->smc_fw);
rdev->smc_fw = NULL; rdev->smc_fw = NULL;
err = 0;
} else if (rdev->smc_fw->size != smc_req_size) { } else if (rdev->smc_fw->size != smc_req_size) {
printk(KERN_ERR printk(KERN_ERR
"cik_smc: Bogus length %zu in firmware \"%s\"\n", "cik_smc: Bogus length %zu in firmware \"%s\"\n",
...@@ -3182,6 +3183,7 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -3182,6 +3183,7 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256); r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256);
if (r) { if (r) {
DRM_ERROR("radeon: failed to get ib (%d).\n", r); DRM_ERROR("radeon: failed to get ib (%d).\n", r);
radeon_scratch_free(rdev, scratch);
return r; return r;
} }
ib.ptr[0] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); ib.ptr[0] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
...@@ -3198,6 +3200,8 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -3198,6 +3200,8 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
r = radeon_fence_wait(ib.fence, false); r = radeon_fence_wait(ib.fence, false);
if (r) { if (r) {
DRM_ERROR("radeon: fence wait failed (%d).\n", r); DRM_ERROR("radeon: fence wait failed (%d).\n", r);
radeon_scratch_free(rdev, scratch);
radeon_ib_free(rdev, &ib);
return r; return r;
} }
for (i = 0; i < rdev->usec_timeout; i++) { for (i = 0; i < rdev->usec_timeout; i++) {
......
...@@ -113,6 +113,9 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) ...@@ -113,6 +113,9 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
u8 *sadb; u8 *sadb;
int sad_count; int sad_count;
/* XXX: setting this register causes hangs on some asics */
return;
if (!dig->afmt->pin) if (!dig->afmt->pin)
return; return;
......
...@@ -67,6 +67,9 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder) ...@@ -67,6 +67,9 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
u8 *sadb; u8 *sadb;
int sad_count; int sad_count;
/* XXX: setting this register causes hangs on some asics */
return;
list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
if (connector->encoder == encoder) if (connector->encoder == encoder)
radeon_connector = to_radeon_connector(connector); radeon_connector = to_radeon_connector(connector);
......
...@@ -804,6 +804,7 @@ int ni_init_microcode(struct radeon_device *rdev) ...@@ -804,6 +804,7 @@ int ni_init_microcode(struct radeon_device *rdev)
fw_name); fw_name);
release_firmware(rdev->smc_fw); release_firmware(rdev->smc_fw);
rdev->smc_fw = NULL; rdev->smc_fw = NULL;
err = 0;
} else if (rdev->smc_fw->size != smc_req_size) { } else if (rdev->smc_fw->size != smc_req_size) {
printk(KERN_ERR printk(KERN_ERR
"ni_mc: Bogus length %zu in firmware \"%s\"\n", "ni_mc: Bogus length %zu in firmware \"%s\"\n",
......
...@@ -2302,6 +2302,7 @@ int r600_init_microcode(struct radeon_device *rdev) ...@@ -2302,6 +2302,7 @@ int r600_init_microcode(struct radeon_device *rdev)
fw_name); fw_name);
release_firmware(rdev->smc_fw); release_firmware(rdev->smc_fw);
rdev->smc_fw = NULL; rdev->smc_fw = NULL;
err = 0;
} else if (rdev->smc_fw->size != smc_req_size) { } else if (rdev->smc_fw->size != smc_req_size) {
printk(KERN_ERR printk(KERN_ERR
"smc: Bogus length %zu in firmware \"%s\"\n", "smc: Bogus length %zu in firmware \"%s\"\n",
......
...@@ -309,6 +309,9 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder) ...@@ -309,6 +309,9 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
u8 *sadb; u8 *sadb;
int sad_count; int sad_count;
/* XXX: setting this register causes hangs on some asics */
return;
list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
if (connector->encoder == encoder) if (connector->encoder == encoder)
radeon_connector = to_radeon_connector(connector); radeon_connector = to_radeon_connector(connector);
......
...@@ -1658,9 +1658,12 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1658,9 +1658,12 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property, rdev->mode_info.underscan_vborder_property,
0); 0);
drm_object_attach_property(&radeon_connector->base.base, if (radeon_audio != 0)
rdev->mode_info.audio_property, drm_object_attach_property(&radeon_connector->base.base,
RADEON_AUDIO_DISABLE); rdev->mode_info.audio_property,
(radeon_audio == 1) ?
RADEON_AUDIO_AUTO :
RADEON_AUDIO_DISABLE);
subpixel_order = SubPixelHorizontalRGB; subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true; connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_HDMIB) if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
...@@ -1754,10 +1757,12 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1754,10 +1757,12 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.underscan_vborder_property, rdev->mode_info.underscan_vborder_property,
0); 0);
} }
if (ASIC_IS_DCE2(rdev)) { if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE); (radeon_audio == 1) ?
RADEON_AUDIO_AUTO :
RADEON_AUDIO_DISABLE);
} }
if (connector_type == DRM_MODE_CONNECTOR_DVII) { if (connector_type == DRM_MODE_CONNECTOR_DVII) {
radeon_connector->dac_load_detect = true; radeon_connector->dac_load_detect = true;
...@@ -1799,10 +1804,12 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1799,10 +1804,12 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.underscan_vborder_property, rdev->mode_info.underscan_vborder_property,
0); 0);
} }
if (ASIC_IS_DCE2(rdev)) { if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE); (radeon_audio == 1) ?
RADEON_AUDIO_AUTO :
RADEON_AUDIO_DISABLE);
} }
subpixel_order = SubPixelHorizontalRGB; subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true; connector->interlace_allowed = true;
...@@ -1843,10 +1850,12 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1843,10 +1850,12 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.underscan_vborder_property, rdev->mode_info.underscan_vborder_property,
0); 0);
} }
if (ASIC_IS_DCE2(rdev)) { if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_DISABLE); (radeon_audio == 1) ?
RADEON_AUDIO_AUTO :
RADEON_AUDIO_DISABLE);
} }
connector->interlace_allowed = true; connector->interlace_allowed = true;
/* in theory with a DP to VGA converter... */ /* in theory with a DP to VGA converter... */
......
...@@ -85,9 +85,8 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) ...@@ -85,9 +85,8 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
VRAM, also but everything into VRAM on AGP cards to avoid VRAM, also but everything into VRAM on AGP cards to avoid
image corruptions */ image corruptions */
if (p->ring == R600_RING_TYPE_UVD_INDEX && if (p->ring == R600_RING_TYPE_UVD_INDEX &&
p->rdev->family < CHIP_PALM &&
(i == 0 || drm_pci_device_is_agp(p->rdev->ddev))) { (i == 0 || drm_pci_device_is_agp(p->rdev->ddev))) {
/* TODO: is this still needed for NI+ ? */
p->relocs[i].lobj.domain = p->relocs[i].lobj.domain =
RADEON_GEM_DOMAIN_VRAM; RADEON_GEM_DOMAIN_VRAM;
......
...@@ -153,7 +153,7 @@ int radeon_benchmarking = 0; ...@@ -153,7 +153,7 @@ int radeon_benchmarking = 0;
int radeon_testing = 0; int radeon_testing = 0;
int radeon_connector_table = 0; int radeon_connector_table = 0;
int radeon_tv = 1; int radeon_tv = 1;
int radeon_audio = 1; int radeon_audio = -1;
int radeon_disp_priority = 0; int radeon_disp_priority = 0;
int radeon_hw_i2c = 0; int radeon_hw_i2c = 0;
int radeon_pcie_gen2 = -1; int radeon_pcie_gen2 = -1;
...@@ -196,7 +196,7 @@ module_param_named(connector_table, radeon_connector_table, int, 0444); ...@@ -196,7 +196,7 @@ module_param_named(connector_table, radeon_connector_table, int, 0444);
MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
module_param_named(tv, radeon_tv, int, 0444); module_param_named(tv, radeon_tv, int, 0444);
MODULE_PARM_DESC(audio, "Audio enable (1 = enable)"); MODULE_PARM_DESC(audio, "Audio enable (-1 = auto, 0 = disable, 1 = enable)");
module_param_named(audio, radeon_audio, int, 0444); module_param_named(audio, radeon_audio, int, 0444);
MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)"); MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)");
......
...@@ -476,7 +476,8 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, ...@@ -476,7 +476,8 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
if (p->rdev->family < CHIP_PALM && (cmd == 0 || cmd == 0x3) && /* TODO: is this still necessary on NI+ ? */
if ((cmd == 0 || cmd == 0x3) &&
(start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) { (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) {
DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n", DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",
start, end); start, end);
......
...@@ -1681,6 +1681,7 @@ static int si_init_microcode(struct radeon_device *rdev) ...@@ -1681,6 +1681,7 @@ static int si_init_microcode(struct radeon_device *rdev)
fw_name); fw_name);
release_firmware(rdev->smc_fw); release_firmware(rdev->smc_fw);
rdev->smc_fw = NULL; rdev->smc_fw = NULL;
err = 0;
} else if (rdev->smc_fw->size != smc_req_size) { } else if (rdev->smc_fw->size != smc_req_size) {
printk(KERN_ERR printk(KERN_ERR
"si_smc: Bogus length %zu in firmware \"%s\"\n", "si_smc: Bogus length %zu in firmware \"%s\"\n",
......
...@@ -212,8 +212,8 @@ int uvd_v1_0_start(struct radeon_device *rdev) ...@@ -212,8 +212,8 @@ int uvd_v1_0_start(struct radeon_device *rdev)
/* enable VCPU clock */ /* enable VCPU clock */
WREG32(UVD_VCPU_CNTL, 1 << 9); WREG32(UVD_VCPU_CNTL, 1 << 9);
/* enable UMC and NC0 */ /* enable UMC */
WREG32_P(UVD_LMI_CTRL2, 1 << 13, ~((1 << 8) | (1 << 13))); WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
/* boot up the VCPU */ /* boot up the VCPU */
WREG32(UVD_SOFT_RESET, 0); WREG32(UVD_SOFT_RESET, 0);
......
...@@ -740,9 +740,17 @@ static void vmw_postclose(struct drm_device *dev, ...@@ -740,9 +740,17 @@ static void vmw_postclose(struct drm_device *dev,
struct vmw_fpriv *vmw_fp; struct vmw_fpriv *vmw_fp;
vmw_fp = vmw_fpriv(file_priv); vmw_fp = vmw_fpriv(file_priv);
ttm_object_file_release(&vmw_fp->tfile);
if (vmw_fp->locked_master) if (vmw_fp->locked_master) {
struct vmw_master *vmaster =
vmw_master(vmw_fp->locked_master);
ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
ttm_vt_unlock(&vmaster->lock);
drm_master_put(&vmw_fp->locked_master); drm_master_put(&vmw_fp->locked_master);
}
ttm_object_file_release(&vmw_fp->tfile);
kfree(vmw_fp); kfree(vmw_fp);
} }
...@@ -925,14 +933,13 @@ static void vmw_master_drop(struct drm_device *dev, ...@@ -925,14 +933,13 @@ static void vmw_master_drop(struct drm_device *dev,
vmw_fp->locked_master = drm_master_get(file_priv->master); vmw_fp->locked_master = drm_master_get(file_priv->master);
ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile); ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
vmw_execbuf_release_pinned_bo(dev_priv);
if (unlikely((ret != 0))) { if (unlikely((ret != 0))) {
DRM_ERROR("Unable to lock TTM at VT switch.\n"); DRM_ERROR("Unable to lock TTM at VT switch.\n");
drm_master_put(&vmw_fp->locked_master); drm_master_put(&vmw_fp->locked_master);
} }
ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); ttm_lock_set_kill(&vmaster->lock, false, SIGTERM);
vmw_execbuf_release_pinned_bo(dev_priv);
if (!dev_priv->enable_fb) { if (!dev_priv->enable_fb) {
ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM); ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
......
...@@ -970,7 +970,7 @@ void vmw_resource_unreserve(struct vmw_resource *res, ...@@ -970,7 +970,7 @@ void vmw_resource_unreserve(struct vmw_resource *res,
if (new_backup) if (new_backup)
res->backup_offset = new_backup_offset; res->backup_offset = new_backup_offset;
if (!res->func->may_evict) if (!res->func->may_evict || res->id == -1)
return; return;
write_lock(&dev_priv->resource_lock); write_lock(&dev_priv->resource_lock);
......
...@@ -223,6 +223,8 @@ struct drm_mode_get_connector { ...@@ -223,6 +223,8 @@ struct drm_mode_get_connector {
__u32 connection; __u32 connection;
__u32 mm_width, mm_height; /**< HxW in millimeters */ __u32 mm_width, mm_height; /**< HxW in millimeters */
__u32 subpixel; __u32 subpixel;
__u32 pad;
}; };
#define DRM_MODE_PROP_PENDING (1<<0) #define DRM_MODE_PROP_PENDING (1<<0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册