summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c197
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c5
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c5
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c4
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c3
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c29
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c12
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h4
-rw-r--r--drivers/gpu/drm/i915/intel_audio.c27
-rw-r--r--drivers/gpu/drm/i915/intel_display.c121
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c8
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c20
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c6
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c12
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c8
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c14
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h5
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c2
20 files changed, 322 insertions, 166 deletions
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 9605ff8f2fcd..306d9e4e5cf3 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -123,7 +123,7 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = {
CMD( MI_SEMAPHORE_MBOX, SMI, !F, 0xFF, R ),
CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ),
CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W,
- .reg = { .offset = 1, .mask = 0x007FFFFC } ),
+ .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ),
CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF, W | B,
.reg = { .offset = 1, .mask = 0x007FFFFC },
.bits = {{
@@ -395,16 +395,38 @@ static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = {
/*
* Register whitelists, sorted by increasing register offset.
+ */
+
+/*
+ * An individual whitelist entry granting access to register addr. If
+ * mask is non-zero the argument of immediate register writes will be
+ * AND-ed with mask, and the command will be rejected if the result
+ * doesn't match value.
+ *
+ * Registers with non-zero mask are only allowed to be written using
+ * LRI.
+ */
+struct drm_i915_reg_descriptor {
+ u32 addr;
+ u32 mask;
+ u32 value;
+};
+
+/* Convenience macro for adding 32-bit registers. */
+#define REG32(address, ...) \
+ { .addr = address, __VA_ARGS__ }
+
+/*
+ * Convenience macro for adding 64-bit registers.
*
* Some registers that userspace accesses are 64 bits. The register
* access commands only allow 32-bit accesses. Hence, we have to include
* entries for both halves of the 64-bit registers.
*/
+#define REG64(addr) \
+ REG32(addr), REG32(addr + sizeof(u32))
-/* Convenience macro for adding 64-bit registers */
-#define REG64(addr) (addr), (addr + sizeof(u32))
-
-static const u32 gen7_render_regs[] = {
+static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
REG64(GPGPU_THREADS_DISPATCHED),
REG64(HS_INVOCATION_COUNT),
REG64(DS_INVOCATION_COUNT),
@@ -417,15 +439,15 @@ static const u32 gen7_render_regs[] = {
REG64(CL_PRIMITIVES_COUNT),
REG64(PS_INVOCATION_COUNT),
REG64(PS_DEPTH_COUNT),
- OACONTROL, /* Only allowed for LRI and SRM. See below. */
+ REG32(OACONTROL), /* Only allowed for LRI and SRM. See below. */
REG64(MI_PREDICATE_SRC0),
REG64(MI_PREDICATE_SRC1),
- GEN7_3DPRIM_END_OFFSET,
- GEN7_3DPRIM_START_VERTEX,
- GEN7_3DPRIM_VERTEX_COUNT,
- GEN7_3DPRIM_INSTANCE_COUNT,
- GEN7_3DPRIM_START_INSTANCE,
- GEN7_3DPRIM_BASE_VERTEX,
+ REG32(GEN7_3DPRIM_END_OFFSET),
+ REG32(GEN7_3DPRIM_START_VERTEX),
+ REG32(GEN7_3DPRIM_VERTEX_COUNT),
+ REG32(GEN7_3DPRIM_INSTANCE_COUNT),
+ REG32(GEN7_3DPRIM_START_INSTANCE),
+ REG32(GEN7_3DPRIM_BASE_VERTEX),
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(0)),
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(1)),
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(2)),
@@ -434,33 +456,41 @@ static const u32 gen7_render_regs[] = {
REG64(GEN7_SO_PRIM_STORAGE_NEEDED(1)),
REG64(GEN7_SO_PRIM_STORAGE_NEEDED(2)),
REG64(GEN7_SO_PRIM_STORAGE_NEEDED(3)),
- GEN7_SO_WRITE_OFFSET(0),
- GEN7_SO_WRITE_OFFSET(1),
- GEN7_SO_WRITE_OFFSET(2),
- GEN7_SO_WRITE_OFFSET(3),
- GEN7_L3SQCREG1,
- GEN7_L3CNTLREG2,
- GEN7_L3CNTLREG3,
+ REG32(GEN7_SO_WRITE_OFFSET(0)),
+ REG32(GEN7_SO_WRITE_OFFSET(1)),
+ REG32(GEN7_SO_WRITE_OFFSET(2)),
+ REG32(GEN7_SO_WRITE_OFFSET(3)),
+ REG32(GEN7_L3SQCREG1),
+ REG32(GEN7_L3CNTLREG2),
+ REG32(GEN7_L3CNTLREG3),
+ REG32(HSW_SCRATCH1,
+ .mask = ~HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE,
+ .value = 0),
+ REG32(HSW_ROW_CHICKEN3,
+ .mask = ~(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE << 16 |
+ HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE),
+ .value = 0),
};
-static const u32 gen7_blt_regs[] = {
- BCS_SWCTRL,
+static const struct drm_i915_reg_descriptor gen7_blt_regs[] = {
+ REG32(BCS_SWCTRL),
};
-static const u32 ivb_master_regs[] = {
- FORCEWAKE_MT,
- DERRMR,
- GEN7_PIPE_DE_LOAD_SL(PIPE_A),
- GEN7_PIPE_DE_LOAD_SL(PIPE_B),
- GEN7_PIPE_DE_LOAD_SL(PIPE_C),
+static const struct drm_i915_reg_descriptor ivb_master_regs[] = {
+ REG32(FORCEWAKE_MT),
+ REG32(DERRMR),
+ REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_A)),
+ REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_B)),
+ REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_C)),
};
-static const u32 hsw_master_regs[] = {
- FORCEWAKE_MT,
- DERRMR,
+static const struct drm_i915_reg_descriptor hsw_master_regs[] = {
+ REG32(FORCEWAKE_MT),
+ REG32(DERRMR),
};
#undef REG64
+#undef REG32
static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
{
@@ -550,14 +580,16 @@ static bool validate_cmds_sorted(struct intel_engine_cs *ring,
return ret;
}
-static bool check_sorted(int ring_id, const u32 *reg_table, int reg_count)
+static bool check_sorted(int ring_id,
+ const struct drm_i915_reg_descriptor *reg_table,
+ int reg_count)
{
int i;
u32 previous = 0;
bool ret = true;
for (i = 0; i < reg_count; i++) {
- u32 curr = reg_table[i];
+ u32 curr = reg_table[i].addr;
if (curr < previous) {
DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n",
@@ -804,18 +836,20 @@ find_cmd(struct intel_engine_cs *ring,
return default_desc;
}
-static bool valid_reg(const u32 *table, int count, u32 addr)
+static const struct drm_i915_reg_descriptor *
+find_reg(const struct drm_i915_reg_descriptor *table,
+ int count, u32 addr)
{
- if (table && count != 0) {
+ if (table) {
int i;
for (i = 0; i < count; i++) {
- if (table[i] == addr)
- return true;
+ if (table[i].addr == addr)
+ return &table[i];
}
}
- return false;
+ return NULL;
}
static u32 *vmap_batch(struct drm_i915_gem_object *obj,
@@ -934,7 +968,7 @@ bool i915_needs_cmd_parser(struct intel_engine_cs *ring)
static bool check_cmd(const struct intel_engine_cs *ring,
const struct drm_i915_cmd_descriptor *desc,
- const u32 *cmd,
+ const u32 *cmd, u32 length,
const bool is_master,
bool *oacontrol_set)
{
@@ -950,38 +984,70 @@ static bool check_cmd(const struct intel_engine_cs *ring,
}
if (desc->flags & CMD_DESC_REGISTER) {
- u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask;
-
/*
- * OACONTROL requires some special handling for writes. We
- * want to make sure that any batch which enables OA also
- * disables it before the end of the batch. The goal is to
- * prevent one process from snooping on the perf data from
- * another process. To do that, we need to check the value
- * that will be written to the register. Hence, limit
- * OACONTROL writes to only MI_LOAD_REGISTER_IMM commands.
+ * Get the distance between individual register offset
+ * fields if the command can perform more than one
+ * access at a time.
*/
- if (reg_addr == OACONTROL) {
- if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
- DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n");
+ const u32 step = desc->reg.step ? desc->reg.step : length;
+ u32 offset;
+
+ for (offset = desc->reg.offset; offset < length;
+ offset += step) {
+ const u32 reg_addr = cmd[offset] & desc->reg.mask;
+ const struct drm_i915_reg_descriptor *reg =
+ find_reg(ring->reg_table, ring->reg_count,
+ reg_addr);
+
+ if (!reg && is_master)
+ reg = find_reg(ring->master_reg_table,
+ ring->master_reg_count,
+ reg_addr);
+
+ if (!reg) {
+ DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
+ reg_addr, *cmd, ring->id);
return false;
}
- if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1))
- *oacontrol_set = (cmd[2] != 0);
- }
+ /*
+ * OACONTROL requires some special handling for
+ * writes. We want to make sure that any batch which
+ * enables OA also disables it before the end of the
+ * batch. The goal is to prevent one process from
+ * snooping on the perf data from another process. To do
+ * that, we need to check the value that will be written
+ * to the register. Hence, limit OACONTROL writes to
+ * only MI_LOAD_REGISTER_IMM commands.
+ */
+ if (reg_addr == OACONTROL) {
+ if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
+ DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n");
+ return false;
+ }
+
+ if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1))
+ *oacontrol_set = (cmd[offset + 1] != 0);
+ }
- if (!valid_reg(ring->reg_table,
- ring->reg_count, reg_addr)) {
- if (!is_master ||
- !valid_reg(ring->master_reg_table,
- ring->master_reg_count,
- reg_addr)) {
- DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
- reg_addr,
- *cmd,
- ring->id);
- return false;
+ /*
+ * Check the value written to the register against the
+ * allowed mask/value pair given in the whitelist entry.
+ */
+ if (reg->mask) {
+ if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
+ DRM_DEBUG_DRIVER("CMD: Rejected LRM to masked register 0x%08X\n",
+ reg_addr);
+ return false;
+ }
+
+ if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) &&
+ (offset + 2 > length ||
+ (cmd[offset + 1] & reg->mask) != reg->value)) {
+ DRM_DEBUG_DRIVER("CMD: Rejected LRI to masked register 0x%08X\n",
+ reg_addr);
+ return false;
+ }
}
}
}
@@ -1105,7 +1171,8 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
break;
}
- if (!check_cmd(ring, desc, cmd, is_master, &oacontrol_set)) {
+ if (!check_cmd(ring, desc, cmd, length, is_master,
+ &oacontrol_set)) {
ret = -EINVAL;
break;
}
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 88cc793c46d3..82bbe3f2a7e1 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1725,12 +1725,15 @@ static int i915_sr_status(struct seq_file *m, void *unused)
if (HAS_PCH_SPLIT(dev))
sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN;
- else if (IS_CRESTLINE(dev) || IS_I945G(dev) || IS_I945GM(dev))
+ else if (IS_CRESTLINE(dev) || IS_G4X(dev) ||
+ IS_I945G(dev) || IS_I945GM(dev))
sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
else if (IS_I915GM(dev))
sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
else if (IS_PINEVIEW(dev))
sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
+ else if (IS_VALLEYVIEW(dev))
+ sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
intel_runtime_pm_put(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 72f5a3f9dbf2..542fac628b28 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2300,10 +2300,15 @@ struct drm_i915_cmd_descriptor {
* Describes where to find a register address in the command to check
* against the ring's register whitelist. Only valid if flags has the
* CMD_DESC_REGISTER bit set.
+ *
+ * A non-zero step value implies that the command may access multiple
+ * registers in sequence (e.g. LRI), in that case step gives the
+ * distance in dwords between individual offset fields.
*/
struct {
u32 offset;
u32 mask;
+ u32 step;
} reg;
#define MAX_CMD_DESC_BITMASKS 3
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index be35f0486202..248fd1ac7b3a 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2813,9 +2813,6 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring)
{
WARN_ON(i915_verify_lists(ring->dev));
- if (list_empty(&ring->active_list))
- return;
-
/* Retire requests first as we use it above for the early return.
* If we retire requests last, we may use a later seqno and so clear
* the requests lists without clearing the active list, leading to
@@ -3241,8 +3238,8 @@ int i915_vma_unbind(struct i915_vma *vma)
} else if (vma->ggtt_view.pages) {
sg_free_table(vma->ggtt_view.pages);
kfree(vma->ggtt_view.pages);
- vma->ggtt_view.pages = NULL;
}
+ vma->ggtt_view.pages = NULL;
}
drm_mm_remove_node(&vma->node);
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 8867818b1401..d65cbe6afb92 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -157,9 +157,7 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
struct drm_i915_gem_object *obj;
int ret;
- obj = i915_gem_object_create_stolen(dev, size);
- if (obj == NULL)
- obj = i915_gem_alloc_object(dev, size);
+ obj = i915_gem_alloc_object(dev, size);
if (obj == NULL)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index bd0e4bda2c64..a7fa14516cda 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -32,6 +32,7 @@
#include "i915_trace.h"
#include "intel_drv.h"
#include <linux/dma_remapping.h>
+#include <linux/uaccess.h>
#define __EXEC_OBJECT_HAS_PIN (1<<31)
#define __EXEC_OBJECT_HAS_FENCE (1<<30)
@@ -458,7 +459,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
}
/* We can't wait for rendering with pagefaults disabled */
- if (obj->active && in_atomic())
+ if (obj->active && pagefault_disabled())
return -EFAULT;
if (use_cpu_reloc(obj))
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 619dad1b2386..dcc6a88c560e 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -516,17 +516,17 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
struct page *page_table;
if (WARN_ON(!ppgtt->pdp.page_directory[pdpe]))
- continue;
+ break;
pd = ppgtt->pdp.page_directory[pdpe];
if (WARN_ON(!pd->page_table[pde]))
- continue;
+ break;
pt = pd->page_table[pde];
if (WARN_ON(!pt->page))
- continue;
+ break;
page_table = pt->page;
@@ -2546,6 +2546,8 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj;
struct i915_address_space *vm;
+ struct i915_vma *vma;
+ bool flush;
i915_check_and_clear_faults(dev);
@@ -2555,16 +2557,23 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
dev_priv->gtt.base.total,
true);
+ /* Cache flush objects bound into GGTT and rebind them. */
+ vm = &dev_priv->gtt.base;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
- struct i915_vma *vma = i915_gem_obj_to_vma(obj,
- &dev_priv->gtt.base);
- if (!vma)
- continue;
+ flush = false;
+ list_for_each_entry(vma, &obj->vma_list, vma_link) {
+ if (vma->vm != vm)
+ continue;
- i915_gem_clflush_object(obj, obj->pin_display);
- WARN_ON(i915_vma_bind(vma, obj->cache_level, PIN_UPDATE));
- }
+ WARN_ON(i915_vma_bind(vma, obj->cache_level,
+ PIN_UPDATE));
+ flush = true;
+ }
+
+ if (flush)
+ i915_gem_clflush_object(obj, obj->pin_display);
+ }
if (INTEL_INFO(dev)->gen >= 8) {
if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 633bd1fcab69..d61e74a08f82 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -183,8 +183,18 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
if (IS_GEN4(dev)) {
uint32_t ddc2 = I915_READ(DCC2);
- if (!(ddc2 & DCC2_MODIFIED_ENHANCED_DISABLE))
+ if (!(ddc2 & DCC2_MODIFIED_ENHANCED_DISABLE)) {
+ /* Since the swizzling may vary within an
+ * object, we have no idea what the swizzling
+ * is for any page in particular. Thus we
+ * cannot migrate tiled pages using the GPU,
+ * nor can we tell userspace what the exact
+ * swizzling is for any object.
+ */
dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES;
+ swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+ swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+ }
}
if (dcc == 0xffffffff) {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 6d3fead3a358..2030f602cbf8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3491,6 +3491,7 @@ enum skl_disp_power_wells {
#define BLM_POLARITY_PNV (1 << 0) /* pnv only */
#define BLC_HIST_CTL (dev_priv->info.display_mmio_offset + 0x61260)
+#define BLM_HISTOGRAM_ENABLE (1 << 31)
/* New registers for PCH-split platforms. Safe where new bits show up, the
* register layout machtes with gen4 BLC_PWM_CTL[12]. */
@@ -6941,6 +6942,9 @@ enum skl_disp_power_wells {
#define AUDIO_CP_READY(trans) ((1 << 1) << ((trans) * 4))
#define AUDIO_ELD_VALID(trans) ((1 << 0) << ((trans) * 4))
+#define HSW_AUD_CHICKENBIT 0x65f10
+#define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15)
+
/* HSW Power Wells */
#define HSW_PWR_WELL_BIOS 0x45400 /* CTL1 */
#define HSW_PWR_WELL_DRIVER 0x45404 /* CTL2 */
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index c4312177b0ee..3da9b8409f20 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -470,6 +470,32 @@ static void i915_audio_component_put_power(struct device *dev)
intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
}
+static void i915_audio_component_codec_wake_override(struct device *dev,
+ bool enable)
+{
+ struct drm_i915_private *dev_priv = dev_to_i915(dev);
+ u32 tmp;
+
+ if (!IS_SKYLAKE(dev_priv))
+ return;
+
+ /*
+ * Enable/disable generating the codec wake signal, overriding the
+ * internal logic to generate the codec wake to controller.
+ */
+ tmp = I915_READ(HSW_AUD_CHICKENBIT);
+ tmp &= ~SKL_AUD_CODEC_WAKE_SIGNAL;
+ I915_WRITE(HSW_AUD_CHICKENBIT, tmp);
+ usleep_range(1000, 1500);
+
+ if (enable) {
+ tmp = I915_READ(HSW_AUD_CHICKENBIT);
+ tmp |= SKL_AUD_CODEC_WAKE_SIGNAL;
+ I915_WRITE(HSW_AUD_CHICKENBIT, tmp);
+ usleep_range(1000, 1500);
+ }
+}
+
/* Get CDCLK in kHz */
static int i915_audio_component_get_cdclk_freq(struct device *dev)
{
@@ -491,6 +517,7 @@ static const struct i915_audio_component_ops i915_audio_component_ops = {
.owner = THIS_MODULE,
.get_power = i915_audio_component_get_power,
.put_power = i915_audio_component_put_power,
+ .codec_wake_override = i915_audio_component_codec_wake_override,
.get_cdclk_freq = i915_audio_component_get_cdclk_freq,
};
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4e3f302d86f7..ba9321998a41 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -87,7 +87,8 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config);
static int intel_set_mode(struct drm_crtc *crtc,
- struct drm_atomic_state *state);
+ struct drm_atomic_state *state,
+ bool force_restore);
static int intel_framebuffer_init(struct drm_device *dev,
struct intel_framebuffer *ifb,
struct drm_mode_fb_cmd2 *mode_cmd,
@@ -4853,6 +4854,9 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc)
struct intel_plane *intel_plane;
int pipe = intel_crtc->pipe;
+ if (!intel_crtc->active)
+ return;
+
intel_crtc_wait_for_pending_flips(crtc);
intel_pre_disable_primary(crtc);
@@ -7886,7 +7890,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
int pipe = pipe_config->cpu_transcoder;
enum dpio_channel port = vlv_pipe_to_channel(pipe);
intel_clock_t clock;
- u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2;
+ u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2, pll_dw3;
int refclk = 100000;
mutex_lock(&dev_priv->sb_lock);
@@ -7894,10 +7898,13 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
pll_dw0 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW0(port));
pll_dw1 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW1(port));
pll_dw2 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW2(port));
+ pll_dw3 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
mutex_unlock(&dev_priv->sb_lock);
clock.m1 = (pll_dw1 & 0x7) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0;
- clock.m2 = ((pll_dw0 & 0xff) << 22) | (pll_dw2 & 0x3fffff);
+ clock.m2 = (pll_dw0 & 0xff) << 22;
+ if (pll_dw3 & DPIO_CHV_FRAC_DIV_EN)
+ clock.m2 |= pll_dw2 & 0x3fffff;
clock.n = (pll_dw1 >> DPIO_CHV_N_DIV_SHIFT) & 0xf;
clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7;
clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f;
@@ -10096,7 +10103,7 @@ retry:
drm_mode_copy(&crtc_state->base.mode, mode);
- if (intel_set_mode(crtc, state)) {
+ if (intel_set_mode(crtc, state, true)) {
DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
if (old->release_fb)
old->release_fb->funcs->destroy(old->release_fb);
@@ -10170,7 +10177,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
if (ret)
goto fail;
- ret = intel_set_mode(crtc, state);
+ ret = intel_set_mode(crtc, state, true);
if (ret)
goto fail;
@@ -11385,10 +11392,6 @@ static void intel_modeset_fixup_state(struct drm_atomic_state *state)
crtc->base.enabled = crtc->base.state->enable;
crtc->config = to_intel_crtc_state(crtc->base.state);
}
-
- /* Copy the new configuration to the staged state, to keep the few
- * pieces of code that haven't been converted yet happy */
- intel_modeset_update_staged_output_state(state->dev);
}
static void
@@ -11870,15 +11873,15 @@ intel_modeset_update_state(struct drm_atomic_state *state)
if (!intel_encoder->base.crtc)
continue;
- for_each_crtc_in_state(state, crtc, crtc_state, i)
- if (crtc == intel_encoder->base.crtc)
- break;
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ if (crtc != intel_encoder->base.crtc)
+ continue;
- if (crtc != intel_encoder->base.crtc)
- continue;
+ if (crtc_state->enable && needs_modeset(crtc_state))
+ intel_encoder->connectors_active = false;
- if (crtc_state->enable && needs_modeset(crtc_state))
- intel_encoder->connectors_active = false;
+ break;
+ }
}
drm_atomic_helper_swap_state(state->dev, state);
@@ -11893,24 +11896,24 @@ intel_modeset_update_state(struct drm_atomic_state *state)
if (!connector->encoder || !connector->encoder->crtc)
continue;
- for_each_crtc_in_state(state, crtc, crtc_state, i)
- if (crtc == connector->encoder->crtc)
- break;
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ if (crtc != connector->encoder->crtc)
+ continue;
- if (crtc != connector->encoder->crtc)
- continue;
+ if (crtc->state->enable && needs_modeset(crtc->state)) {
+ struct drm_property *dpms_property =
+ dev->mode_config.dpms_property;
- if (crtc->state->enable && needs_modeset(crtc->state)) {
- struct drm_property *dpms_property =
- dev->mode_config.dpms_property;
+ connector->dpms = DRM_MODE_DPMS_ON;
+ drm_object_property_set_value(&connector->base,
+ dpms_property,
+ DRM_MODE_DPMS_ON);
- connector->dpms = DRM_MODE_DPMS_ON;
- drm_object_property_set_value(&connector->base,
- dpms_property,
- DRM_MODE_DPMS_ON);
+ intel_encoder = to_intel_encoder(connector->encoder);
+ intel_encoder->connectors_active = true;
+ }
- intel_encoder = to_intel_encoder(connector->encoder);
- intel_encoder->connectors_active = true;
+ break;
}
}
@@ -12646,20 +12649,24 @@ static int __intel_set_mode(struct drm_crtc *modeset_crtc,
}
static int intel_set_mode_with_config(struct drm_crtc *crtc,
- struct intel_crtc_state *pipe_config)
+ struct intel_crtc_state *pipe_config,
+ bool force_restore)
{
int ret;
ret = __intel_set_mode(crtc, pipe_config);
- if (ret == 0)
+ if (ret == 0 && force_restore) {
+ intel_modeset_update_staged_output_state(crtc->dev);
intel_modeset_check_state(crtc->dev);
+ }
return ret;
}
static int intel_set_mode(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
+ struct drm_atomic_state *state,
+ bool force_restore)
{
struct intel_crtc_state *pipe_config;
int ret = 0;
@@ -12670,7 +12677,7 @@ static int intel_set_mode(struct drm_crtc *crtc,
goto out;
}
- ret = intel_set_mode_with_config(crtc, pipe_config);
+ ret = intel_set_mode_with_config(crtc, pipe_config, force_restore);
if (ret)
goto out;
@@ -12682,7 +12689,6 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_atomic_state *state;
- struct intel_crtc *intel_crtc;
struct intel_encoder *encoder;
struct intel_connector *connector;
struct drm_connector_state *connector_state;
@@ -12725,29 +12731,23 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc)
}
}
- for_each_intel_crtc(dev, intel_crtc) {
- if (intel_crtc->new_enabled == intel_crtc->base.enabled)
- continue;
-
- crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
- if (IS_ERR(crtc_state)) {
- DRM_DEBUG_KMS("Failed to add [CRTC:%d] to state: %ld\n",
- intel_crtc->base.base.id,
- PTR_ERR(crtc_state));
- continue;
- }
+ crtc_state = intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));
+ if (IS_ERR(crtc_state)) {
+ DRM_DEBUG_KMS("Failed to add [CRTC:%d] to state: %ld\n",
+ crtc->base.id, PTR_ERR(crtc_state));
+ drm_atomic_state_free(state);
+ return;
+ }
- crtc_state->base.active = crtc_state->base.enable =
- intel_crtc->new_enabled;
+ crtc_state->base.active = crtc_state->base.enable =
+ to_intel_crtc(crtc)->new_enabled;
- if (&intel_crtc->base == crtc)
- drm_mode_copy(&crtc_state->base.mode, &crtc->mode);
- }
+ drm_mode_copy(&crtc_state->base.mode, &crtc->mode);
intel_modeset_setup_plane_state(state, crtc, &crtc->mode,
crtc->primary->fb, crtc->x, crtc->y);
- ret = intel_set_mode(crtc, state);
+ ret = intel_set_mode(crtc, state, false);
if (ret)
drm_atomic_state_free(state);
}
@@ -12947,7 +12947,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
primary_plane_was_visible = primary_plane_visible(set->crtc);
- ret = intel_set_mode_with_config(set->crtc, pipe_config);
+ ret = intel_set_mode_with_config(set->crtc, pipe_config, true);
if (ret == 0 &&
pipe_config->base.enable &&
@@ -13276,7 +13276,7 @@ intel_check_primary_plane(struct drm_plane *plane,
if (ret)
return ret;
- if (intel_crtc->active) {
+ if (crtc_state->base.active) {
struct intel_plane_state *old_state =
to_intel_plane_state(plane->state);
@@ -13309,6 +13309,16 @@ intel_check_primary_plane(struct drm_plane *plane,
intel_crtc->atomic.wait_vblank = true;
}
+ /*
+ * FIXME: Actually if we will still have any other plane enabled
+ * on the pipe we could let IPS enabled still, but for
+ * now lets consider that when we make primary invisible
+ * by setting DSPCNTR to 0 on update_primary_plane function
+ * IPS needs to be disable.
+ */
+ if (!state->visible || !fb)
+ intel_crtc->atomic.disable_ips = true;
+
intel_crtc->atomic.fb_bits |=
INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
@@ -13406,6 +13416,9 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc)
if (intel_crtc->atomic.disable_fbc)
intel_fbc_disable(dev);
+ if (intel_crtc->atomic.disable_ips)
+ hsw_disable_ips(intel_crtc);
+
if (intel_crtc->atomic.pre_disable_primary)
intel_pre_disable_primary(crtc);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 280c282da9bd..6e8faa253792 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -893,10 +893,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
continue;
}
if (status & DP_AUX_CH_CTL_DONE)
- break;
+ goto done;
}
- if (status & DP_AUX_CH_CTL_DONE)
- break;
}
if ((status & DP_AUX_CH_CTL_DONE) == 0) {
@@ -905,6 +903,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
goto out;
}
+done:
/* Check for timeout or receive error.
* Timeouts occur when the sink is not connected
*/
@@ -1141,6 +1140,9 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock)
static void
hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config, int link_bw)
{
+ memset(&pipe_config->dpll_hw_state, 0,
+ sizeof(pipe_config->dpll_hw_state));
+
switch (link_bw) {
case DP_LINK_BW_1_62:
pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2afb31a46275..105928382e21 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -485,6 +485,7 @@ struct intel_crtc_atomic_commit {
/* Sleepable operations to perform before commit */
bool wait_for_flips;
bool disable_fbc;
+ bool disable_ips;
bool pre_disable_primary;
bool update_wm;
unsigned disabled_planes;
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 92072f56e418..a64f26c670af 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -486,7 +486,7 @@ gmbus_xfer(struct i2c_adapter *adapter,
struct intel_gmbus,
adapter);
struct drm_i915_private *dev_priv = bus->dev_priv;
- int i, reg_offset;
+ int i = 0, inc, try = 0, reg_offset;
int ret = 0;
intel_aux_display_runtime_get(dev_priv);
@@ -499,12 +499,14 @@ gmbus_xfer(struct i2c_adapter *adapter,
reg_offset = dev_priv->gpio_mmio_base;
+retry:
I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
- for (i = 0; i < num; i++) {
+ for (; i < num; i += inc) {
+ inc = 1;
if (gmbus_is_index_read(msgs, i, num)) {
ret = gmbus_xfer_index_read(dev_priv, &msgs[i]);
- i += 1; /* set i to the index of the read xfer */
+ inc = 2; /* an index read is two msgs */
} else if (msgs[i].flags & I2C_M_RD) {
ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
} else {
@@ -576,6 +578,18 @@ clear_err:
adapter->name, msgs[i].addr,
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
+ /*
+ * Passive adapters sometimes NAK the first probe. Retry the first
+ * message once on -ENXIO for GMBUS transfers; the bit banging algorithm
+ * has retries internally. See also the retry loop in
+ * drm_do_probe_ddc_edid, which bails out on the first -ENXIO.
+ */
+ if (ret == -ENXIO && i == 0 && try++ == 0) {
+ DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n",
+ adapter->name);
+ goto retry;
+ }
+
goto out;
timeout:
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 9f5485ddcbe6..9b74ffae5f5a 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1085,6 +1085,12 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
+ if (ring->status_page.obj) {
+ I915_WRITE(RING_HWS_PGA(ring->mmio_base),
+ (u32)ring->status_page.gfx_addr);
+ POSTING_READ(RING_HWS_PGA(ring->mmio_base));
+ }
+
I915_WRITE(RING_MODE_GEN7(ring),
_MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
_MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 71e87abdcae7..481337436f72 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -396,16 +396,6 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
return -EINVAL;
}
-/*
- * If the vendor backlight interface is not in use and ACPI backlight interface
- * is broken, do not bother processing backlight change requests from firmware.
- */
-static bool should_ignore_backlight_request(void)
-{
- return acpi_video_backlight_support() &&
- !acpi_video_verify_backlight_support();
-}
-
static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -414,7 +404,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
- if (should_ignore_backlight_request()) {
+ if (acpi_video_get_backlight_type() == acpi_backlight_native) {
DRM_DEBUG_KMS("opregion backlight request ignored\n");
return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 7d83527f95f7..55aad2322e10 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -907,6 +907,14 @@ static void i9xx_enable_backlight(struct intel_connector *connector)
/* XXX: combine this into above write? */
intel_panel_actually_set_backlight(connector, panel->backlight.level);
+
+ /*
+ * Needed to enable backlight on some 855gm models. BLC_HIST_CTL is
+ * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2
+ * that has backlight.
+ */
+ if (IS_GEN2(dev))
+ I915_WRITE(BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE);
}
static void i965_enable_backlight(struct intel_connector *connector)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index d934f857394d..3817a6f00d9e 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -901,13 +901,6 @@ static int chv_init_workarounds(struct intel_engine_cs *ring)
GEN6_WIZ_HASHING_MASK,
GEN6_WIZ_HASHING_16x4);
- if (INTEL_REVID(dev) == SKL_REVID_C0 ||
- INTEL_REVID(dev) == SKL_REVID_D0)
- /* WaBarrierPerformanceFixDisable:skl */
- WA_SET_BIT_MASKED(HDC_CHICKEN0,
- HDC_FENCE_DEST_SLM_DISABLE |
- HDC_BARRIER_PERFORMANCE_DISABLE);
-
return 0;
}
@@ -1030,6 +1023,13 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
WA_SET_BIT_MASKED(HIZ_CHICKEN,
BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
+ if (INTEL_REVID(dev) == SKL_REVID_C0 ||
+ INTEL_REVID(dev) == SKL_REVID_D0)
+ /* WaBarrierPerformanceFixDisable:skl */
+ WA_SET_BIT_MASKED(HDC_CHICKEN0,
+ HDC_FENCE_DEST_SLM_DISABLE |
+ HDC_BARRIER_PERFORMANCE_DISABLE);
+
if (INTEL_REVID(dev) <= SKL_REVID_D0) {
/*
*Use Force Non-Coherent whenever executing a 3D context. This
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 39f6dfc0ee54..e539314ae87e 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -118,6 +118,7 @@ struct intel_ringbuffer {
};
struct intel_context;
+struct drm_i915_reg_descriptor;
struct intel_engine_cs {
const char *name;
@@ -300,14 +301,14 @@ struct intel_engine_cs {
/*
* Table of registers allowed in commands that read/write registers.
*/
- const u32 *reg_table;
+ const struct drm_i915_reg_descriptor *reg_table;
int reg_count;
/*
* Table of registers allowed in commands that read/write registers, but
* only from the DRM master.
*/
- const u32 *master_reg_table;
+ const struct drm_i915_reg_descriptor *master_reg_table;
int master_reg_count;
/*
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d24ef75596a1..aa2fd751609c 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2554,7 +2554,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
DRM_DEBUG_KMS("initialising analog device %d\n", device);
- intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL);
+ intel_sdvo_connector = intel_sdvo_connector_alloc();
if (!intel_sdvo_connector)
return false;
OpenPOWER on IntegriCloud