Merge tag 'drm-intel-next-2016-03-30' of git://anongit.freedesktop.org/drm-intel...
authorDave Airlie <airlied@redhat.com>
Tue, 5 Apr 2016 23:40:07 +0000 (09:40 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 5 Apr 2016 23:40:07 +0000 (09:40 +1000)
- VBT code refactor for a clean split between parsing&using of firmware
  information (Jani)
- untangle the pll computation code, and splitting up the monster
  i9xx_crtc_compute_clocks (Ander)
- dsi support for bxt (Jani, Shashank Sharma and others)
- color manager (i.e. de-gamma, color conversion matrix & gamma support) from
  Lionel Landwerlin
- Vulkan hsw support in the command parser (Jordan Justen)
- large-scale renaming of intel_engine_cs variables/parameters to avoid the epic
  ring vs. engine confusion introduced in gen8 (Tvrtko Ursulin)
- few atomic patches from Maarten&Matt, big one is two-stage wm programming on ilk-bdw
- refactor driver load and add infrastructure to inject load failures for
  testing, from Imre
- various small things all over

* tag 'drm-intel-next-2016-03-30' of git://anongit.freedesktop.org/drm-intel: (179 commits)
  drm/i915: Update DRIVER_DATE to 20160330
  drm/i915: Call intel_dp_mst_resume() before resuming displays
  drm/i915: Fix races on fbdev
  drm/i915: remove unused dev_priv->render_reclock_avail
  drm/i915: move sdvo mappings to vbt data
  drm/i915: move edp low vswing config to vbt data
  drm/i915: use a substruct in vbt data for edp
  drm/i915: replace for_each_engine()
  drm/i915: introduce for_each_engine_id()
  drm/i915/bxt: Fix DSI HW state readout
  drm/i915: Remove vblank wait from hsw_enable_ips, v2.
  drm/i915: Tidy aliasing_gtt_bind_vma()
  drm/i915: Split PNV version of crtc_compute_clock()
  drm/i915: Split g4x_crtc_compute_clock()
  drm/i915: Split i8xx_crtc_compute_clock()
  drm/i915: Split CHV and VLV specific crtc_compute_clock() hooks
  drm/i915: Merge ironlake_compute_clocks() and ironlake_crtc_compute_clock()
  drm/i915: Move fp divisor calculation into ironlake_compute_dpll()
  drm/i915: Pass crtc_state->dpll directly to ->find_dpll()
  drm/i915: Simplify ironlake_crtc_compute_clock() CPU eDP case
  ...

68 files changed:
Documentation/DocBook/gpu.tmpl
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/Kconfig.debug [new file with mode: 0644]
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/i915_cmd_parser.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_debug.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_gtt.h
drivers/gpu/drm/i915/i915_gem_render_state.c
drivers/gpu/drm/i915/i915_gem_render_state.h
drivers/gpu/drm/i915/i915_gem_stolen.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_guc_submission.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/i915_params.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/i915_vgpu.c
drivers/gpu/drm/i915/intel_atomic.c
drivers/gpu/drm/i915/intel_atomic_plane.c
drivers/gpu/drm/i915/intel_audio.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_color.c [new file with mode: 0644]
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_csr.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_dpll_mgr.c [new file with mode: 0644]
drivers/gpu/drm/i915/intel_dpll_mgr.h [new file with mode: 0644]
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
drivers/gpu/drm/i915/intel_dsi_pll.c
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_fifo_underrun.c
drivers/gpu/drm/i915/intel_guc_loader.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_lrc.h
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_mocs.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_psr.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/i915/intel_vbt_defs.h [new file with mode: 0644]

index 1692c4d..1464fb2 100644 (file)
@@ -2153,7 +2153,11 @@ void intel_crt_init(struct drm_device *dev)
        <td valign="top" >ENUM</td>
        <td valign="top" >{ "Automatic", "Full", "Limited 16:235" }</td>
        <td valign="top" >Connector</td>
-       <td valign="top" >TBD</td>
+       <td valign="top" >When this property is set to Limited 16:235
+               and CTM is set, the hardware will be programmed with the
+               result of the multiplication of CTM by the limited range
+               matrix to ensure the pixels normaly in the range 0..1.0 are
+               remapped to the range 16/255..235/255.</td>
        </tr>
        <tr>
        <td valign="top" >“audio”</td>
@@ -3334,7 +3338,7 @@ int num_ioctls;</synopsis>
        <title>Video BIOS Table (VBT)</title>
 !Pdrivers/gpu/drm/i915/intel_bios.c Video BIOS Table (VBT)
 !Idrivers/gpu/drm/i915/intel_bios.c
-!Idrivers/gpu/drm/i915/intel_bios.h
+!Idrivers/gpu/drm/i915/intel_vbt_defs.h
       </sect2>
     </sect1>
 
index 20a5d04..29a32b1 100644 (file)
@@ -56,3 +56,9 @@ config DRM_I915_USERPTR
          selected to enabled full userptr support.
 
          If in doubt, say "Y".
+
+menu "drm/i915 Debugging"
+depends on DRM_I915
+depends on EXPERT
+source drivers/gpu/drm/i915/Kconfig.debug
+endmenu
diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
new file mode 100644 (file)
index 0000000..649a562
--- /dev/null
@@ -0,0 +1,12 @@
+config DRM_I915_DEBUG
+        bool "Enable additional driver debugging"
+        depends on DRM_I915
+        default n
+        help
+          Choose this option to turn on extra driver debugging that may affect
+          performance but will catch some internal issues.
+
+          Recommended for driver developers only.
+
+          If in doubt, say "N".
+
index 0851de0..7ffb51b 100644 (file)
@@ -55,7 +55,9 @@ i915-y += intel_audio.o \
          intel_atomic.o \
          intel_atomic_plane.o \
          intel_bios.o \
+         intel_color.o \
          intel_display.o \
+         intel_dpll_mgr.o \
          intel_fbc.o \
          intel_fifo_underrun.o \
          intel_frontbuffer.o \
index 814d894..a337f33 100644 (file)
@@ -444,6 +444,7 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
        REG64(CL_PRIMITIVES_COUNT),
        REG64(PS_INVOCATION_COUNT),
        REG64(PS_DEPTH_COUNT),
+       REG64_IDX(RING_TIMESTAMP, RENDER_RING_BASE),
        REG32(OACONTROL), /* Only allowed for LRI and SRM. See below. */
        REG64(MI_PREDICATE_SRC0),
        REG64(MI_PREDICATE_SRC1),
@@ -471,6 +472,25 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
        REG32(GEN7_L3SQCREG1),
        REG32(GEN7_L3CNTLREG2),
        REG32(GEN7_L3CNTLREG3),
+};
+
+static const struct drm_i915_reg_descriptor hsw_render_regs[] = {
+       REG64_IDX(HSW_CS_GPR, 0),
+       REG64_IDX(HSW_CS_GPR, 1),
+       REG64_IDX(HSW_CS_GPR, 2),
+       REG64_IDX(HSW_CS_GPR, 3),
+       REG64_IDX(HSW_CS_GPR, 4),
+       REG64_IDX(HSW_CS_GPR, 5),
+       REG64_IDX(HSW_CS_GPR, 6),
+       REG64_IDX(HSW_CS_GPR, 7),
+       REG64_IDX(HSW_CS_GPR, 8),
+       REG64_IDX(HSW_CS_GPR, 9),
+       REG64_IDX(HSW_CS_GPR, 10),
+       REG64_IDX(HSW_CS_GPR, 11),
+       REG64_IDX(HSW_CS_GPR, 12),
+       REG64_IDX(HSW_CS_GPR, 13),
+       REG64_IDX(HSW_CS_GPR, 14),
+       REG64_IDX(HSW_CS_GPR, 15),
        REG32(HSW_SCRATCH1,
              .mask = ~HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE,
              .value = 0),
@@ -500,6 +520,33 @@ static const struct drm_i915_reg_descriptor hsw_master_regs[] = {
 #undef REG64
 #undef REG32
 
+struct drm_i915_reg_table {
+       const struct drm_i915_reg_descriptor *regs;
+       int num_regs;
+       bool master;
+};
+
+static const struct drm_i915_reg_table ivb_render_reg_tables[] = {
+       { gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false },
+       { ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true },
+};
+
+static const struct drm_i915_reg_table ivb_blt_reg_tables[] = {
+       { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false },
+       { ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true },
+};
+
+static const struct drm_i915_reg_table hsw_render_reg_tables[] = {
+       { gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false },
+       { hsw_render_regs, ARRAY_SIZE(hsw_render_regs), false },
+       { hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true },
+};
+
+static const struct drm_i915_reg_table hsw_blt_reg_tables[] = {
+       { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false },
+       { hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true },
+};
+
 static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
 {
        u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
@@ -555,7 +602,7 @@ static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header)
        return 0;
 }
 
-static bool validate_cmds_sorted(struct intel_engine_cs *ring,
+static bool validate_cmds_sorted(struct intel_engine_cs *engine,
                                 const struct drm_i915_cmd_table *cmd_tables,
                                 int cmd_table_count)
 {
@@ -577,7 +624,7 @@ static bool validate_cmds_sorted(struct intel_engine_cs *ring,
 
                        if (curr < previous) {
                                DRM_ERROR("CMD: table not sorted ring=%d table=%d entry=%d cmd=0x%08X prev=0x%08X\n",
-                                         ring->id, i, j, curr, previous);
+                                         engine->id, i, j, curr, previous);
                                ret = false;
                        }
 
@@ -611,11 +658,18 @@ static bool check_sorted(int ring_id,
        return ret;
 }
 
-static bool validate_regs_sorted(struct intel_engine_cs *ring)
+static bool validate_regs_sorted(struct intel_engine_cs *engine)
 {
-       return check_sorted(ring->id, ring->reg_table, ring->reg_count) &&
-               check_sorted(ring->id, ring->master_reg_table,
-                            ring->master_reg_count);
+       int i;
+       const struct drm_i915_reg_table *table;
+
+       for (i = 0; i < engine->reg_table_count; i++) {
+               table = &engine->reg_tables[i];
+               if (!check_sorted(engine->id, table->regs, table->num_regs))
+                       return false;
+       }
+
+       return true;
 }
 
 struct cmd_node {
@@ -639,13 +693,13 @@ struct cmd_node {
  */
 #define CMD_HASH_MASK STD_MI_OPCODE_MASK
 
-static int init_hash_table(struct intel_engine_cs *ring,
+static int init_hash_table(struct intel_engine_cs *engine,
                           const struct drm_i915_cmd_table *cmd_tables,
                           int cmd_table_count)
 {
        int i, j;
 
-       hash_init(ring->cmd_hash);
+       hash_init(engine->cmd_hash);
 
        for (i = 0; i < cmd_table_count; i++) {
                const struct drm_i915_cmd_table *table = &cmd_tables[i];
@@ -660,7 +714,7 @@ static int init_hash_table(struct intel_engine_cs *ring,
                                return -ENOMEM;
 
                        desc_node->desc = desc;
-                       hash_add(ring->cmd_hash, &desc_node->node,
+                       hash_add(engine->cmd_hash, &desc_node->node,
                                 desc->cmd.value & CMD_HASH_MASK);
                }
        }
@@ -668,13 +722,13 @@ static int init_hash_table(struct intel_engine_cs *ring,
        return 0;
 }
 
-static void fini_hash_table(struct intel_engine_cs *ring)
+static void fini_hash_table(struct intel_engine_cs *engine)
 {
        struct hlist_node *tmp;
        struct cmd_node *desc_node;
        int i;
 
-       hash_for_each_safe(ring->cmd_hash, i, tmp, desc_node, node) {
+       hash_for_each_safe(engine->cmd_hash, i, tmp, desc_node, node) {
                hash_del(&desc_node->node);
                kfree(desc_node);
        }
@@ -690,18 +744,18 @@ static void fini_hash_table(struct intel_engine_cs *ring)
  *
  * Return: non-zero if initialization fails
  */
-int i915_cmd_parser_init_ring(struct intel_engine_cs *ring)
+int i915_cmd_parser_init_ring(struct intel_engine_cs *engine)
 {
        const struct drm_i915_cmd_table *cmd_tables;
        int cmd_table_count;
        int ret;
 
-       if (!IS_GEN7(ring->dev))
+       if (!IS_GEN7(engine->dev))
                return 0;
 
-       switch (ring->id) {
+       switch (engine->id) {
        case RCS:
-               if (IS_HASWELL(ring->dev)) {
+               if (IS_HASWELL(engine->dev)) {
                        cmd_tables = hsw_render_ring_cmds;
                        cmd_table_count =
                                ARRAY_SIZE(hsw_render_ring_cmds);
@@ -710,26 +764,23 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *ring)
                        cmd_table_count = ARRAY_SIZE(gen7_render_cmds);
                }
 
-               ring->reg_table = gen7_render_regs;
-               ring->reg_count = ARRAY_SIZE(gen7_render_regs);
-
-               if (IS_HASWELL(ring->dev)) {
-                       ring->master_reg_table = hsw_master_regs;
-                       ring->master_reg_count = ARRAY_SIZE(hsw_master_regs);
+               if (IS_HASWELL(engine->dev)) {
+                       engine->reg_tables = hsw_render_reg_tables;
+                       engine->reg_table_count = ARRAY_SIZE(hsw_render_reg_tables);
                } else {
-                       ring->master_reg_table = ivb_master_regs;
-                       ring->master_reg_count = ARRAY_SIZE(ivb_master_regs);
+                       engine->reg_tables = ivb_render_reg_tables;
+                       engine->reg_table_count = ARRAY_SIZE(ivb_render_reg_tables);
                }
 
-               ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
+               engine->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
                break;
        case VCS:
                cmd_tables = gen7_video_cmds;
                cmd_table_count = ARRAY_SIZE(gen7_video_cmds);
-               ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
+               engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
                break;
        case BCS:
-               if (IS_HASWELL(ring->dev)) {
+               if (IS_HASWELL(engine->dev)) {
                        cmd_tables = hsw_blt_ring_cmds;
                        cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmds);
                } else {
@@ -737,44 +788,41 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *ring)
                        cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
                }
 
-               ring->reg_table = gen7_blt_regs;
-               ring->reg_count = ARRAY_SIZE(gen7_blt_regs);
-
-               if (IS_HASWELL(ring->dev)) {
-                       ring->master_reg_table = hsw_master_regs;
-                       ring->master_reg_count = ARRAY_SIZE(hsw_master_regs);
+               if (IS_HASWELL(engine->dev)) {
+                       engine->reg_tables = hsw_blt_reg_tables;
+                       engine->reg_table_count = ARRAY_SIZE(hsw_blt_reg_tables);
                } else {
-                       ring->master_reg_table = ivb_master_regs;
-                       ring->master_reg_count = ARRAY_SIZE(ivb_master_regs);
+                       engine->reg_tables = ivb_blt_reg_tables;
+                       engine->reg_table_count = ARRAY_SIZE(ivb_blt_reg_tables);
                }
 
-               ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
+               engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
                break;
        case VECS:
                cmd_tables = hsw_vebox_cmds;
                cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds);
                /* VECS can use the same length_mask function as VCS */
-               ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
+               engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
                break;
        default:
                DRM_ERROR("CMD: cmd_parser_init with unknown ring: %d\n",
-                         ring->id);
+                         engine->id);
                BUG();
        }
 
-       BUG_ON(!validate_cmds_sorted(ring, cmd_tables, cmd_table_count));
-       BUG_ON(!validate_regs_sorted(ring));
+       BUG_ON(!validate_cmds_sorted(engine, cmd_tables, cmd_table_count));
+       BUG_ON(!validate_regs_sorted(engine));
 
-       WARN_ON(!hash_empty(ring->cmd_hash));
+       WARN_ON(!hash_empty(engine->cmd_hash));
 
-       ret = init_hash_table(ring, cmd_tables, cmd_table_count);
+       ret = init_hash_table(engine, cmd_tables, cmd_table_count);
        if (ret) {
                DRM_ERROR("CMD: cmd_parser_init failed!\n");
-               fini_hash_table(ring);
+               fini_hash_table(engine);
                return ret;
        }
 
-       ring->needs_cmd_parser = true;
+       engine->needs_cmd_parser = true;
 
        return 0;
 }
@@ -786,21 +834,21 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *ring)
  * Releases any resources related to command parsing that may have been
  * initialized for the specified ring.
  */
-void i915_cmd_parser_fini_ring(struct intel_engine_cs *ring)
+void i915_cmd_parser_fini_ring(struct intel_engine_cs *engine)
 {
-       if (!ring->needs_cmd_parser)
+       if (!engine->needs_cmd_parser)
                return;
 
-       fini_hash_table(ring);
+       fini_hash_table(engine);
 }
 
 static const struct drm_i915_cmd_descriptor*
-find_cmd_in_table(struct intel_engine_cs *ring,
+find_cmd_in_table(struct intel_engine_cs *engine,
                  u32 cmd_header)
 {
        struct cmd_node *desc_node;
 
-       hash_for_each_possible(ring->cmd_hash, desc_node, node,
+       hash_for_each_possible(engine->cmd_hash, desc_node, node,
                               cmd_header & CMD_HASH_MASK) {
                const struct drm_i915_cmd_descriptor *desc = desc_node->desc;
                u32 masked_cmd = desc->cmd.mask & cmd_header;
@@ -822,18 +870,18 @@ find_cmd_in_table(struct intel_engine_cs *ring,
  * ring's default length encoding and returns default_desc.
  */
 static const struct drm_i915_cmd_descriptor*
-find_cmd(struct intel_engine_cs *ring,
+find_cmd(struct intel_engine_cs *engine,
         u32 cmd_header,
         struct drm_i915_cmd_descriptor *default_desc)
 {
        const struct drm_i915_cmd_descriptor *desc;
        u32 mask;
 
-       desc = find_cmd_in_table(ring, cmd_header);
+       desc = find_cmd_in_table(engine, cmd_header);
        if (desc)
                return desc;
 
-       mask = ring->get_cmd_length_mask(cmd_header);
+       mask = engine->get_cmd_length_mask(cmd_header);
        if (!mask)
                return NULL;
 
@@ -848,12 +896,31 @@ static const struct drm_i915_reg_descriptor *
 find_reg(const struct drm_i915_reg_descriptor *table,
         int count, u32 addr)
 {
-       if (table) {
-               int i;
+       int i;
+
+       for (i = 0; i < count; i++) {
+               if (i915_mmio_reg_offset(table[i].addr) == addr)
+                       return &table[i];
+       }
 
-               for (i = 0; i < count; i++) {
-                       if (i915_mmio_reg_offset(table[i].addr) == addr)
-                               return &table[i];
+       return NULL;
+}
+
+static const struct drm_i915_reg_descriptor *
+find_reg_in_tables(const struct drm_i915_reg_table *tables,
+                  int count, bool is_master, u32 addr)
+{
+       int i;
+       const struct drm_i915_reg_table *table;
+       const struct drm_i915_reg_descriptor *reg;
+
+       for (i = 0; i < count; i++) {
+               table = &tables[i];
+               if (!table->master || is_master) {
+                       reg = find_reg(table->regs, table->num_regs,
+                                      addr);
+                       if (reg != NULL)
+                               return reg;
                }
        }
 
@@ -963,18 +1030,18 @@ unpin_src:
  *
  * Return: true if the ring requires software command parsing
  */
-bool i915_needs_cmd_parser(struct intel_engine_cs *ring)
+bool i915_needs_cmd_parser(struct intel_engine_cs *engine)
 {
-       if (!ring->needs_cmd_parser)
+       if (!engine->needs_cmd_parser)
                return false;
 
-       if (!USES_PPGTT(ring->dev))
+       if (!USES_PPGTT(engine->dev))
                return false;
 
        return (i915.enable_cmd_parser == 1);
 }
 
-static bool check_cmd(const struct intel_engine_cs *ring,
+static bool check_cmd(const struct intel_engine_cs *engine,
                      const struct drm_i915_cmd_descriptor *desc,
                      const u32 *cmd, u32 length,
                      const bool is_master,
@@ -1004,17 +1071,14 @@ static bool check_cmd(const struct intel_engine_cs *ring,
                     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);
+                               find_reg_in_tables(engine->reg_tables,
+                                                  engine->reg_table_count,
+                                                  is_master,
+                                                  reg_addr);
 
                        if (!reg) {
                                DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
-                                                reg_addr, *cmd, ring->id);
+                                                reg_addr, *cmd, engine->id);
                                return false;
                        }
 
@@ -1087,7 +1151,7 @@ static bool check_cmd(const struct intel_engine_cs *ring,
                                                 *cmd,
                                                 desc->bits[i].mask,
                                                 desc->bits[i].expected,
-                                                dword, ring->id);
+                                                dword, engine->id);
                                return false;
                        }
                }
@@ -1113,7 +1177,7 @@ static bool check_cmd(const struct intel_engine_cs *ring,
  * Return: non-zero if the parser finds violations or otherwise fails; -EACCES
  * if the batch appears legal but should use hardware parsing
  */
-int i915_parse_cmds(struct intel_engine_cs *ring,
+int i915_parse_cmds(struct intel_engine_cs *engine,
                    struct drm_i915_gem_object *batch_obj,
                    struct drm_i915_gem_object *shadow_batch_obj,
                    u32 batch_start_offset,
@@ -1147,7 +1211,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
                if (*cmd == MI_BATCH_BUFFER_END)
                        break;
 
-               desc = find_cmd(ring, *cmd, &default_desc);
+               desc = find_cmd(engine, *cmd, &default_desc);
                if (!desc) {
                        DRM_DEBUG_DRIVER("CMD: Unrecognized command: 0x%08X\n",
                                         *cmd);
@@ -1179,7 +1243,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
                        break;
                }
 
-               if (!check_cmd(ring, desc, cmd, length, is_master,
+               if (!check_cmd(engine, desc, cmd, length, is_master,
                               &oacontrol_set)) {
                        ret = -EINVAL;
                        break;
@@ -1223,6 +1287,7 @@ int i915_cmd_parser_get_version(void)
         * 3. Allow access to the GPGPU_THREADS_DISPATCHED register.
         * 4. L3 atomic chicken bits of HSW_SCRATCH1 and HSW_ROW_CHICKEN3.
         * 5. GPGPU dispatch compute indirect registers.
+        * 6. TIMESTAMP register and Haswell CS GPR registers
         */
-       return 5;
+       return 6;
 }
index a0f1bd7..d02f8ce 100644 (file)
@@ -129,10 +129,10 @@ static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
        struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct i915_vma *vma;
        int pin_count = 0;
-       int i;
+       enum intel_engine_id id;
 
        seq_printf(m, "%pK: %s%s%s%s %8zdKiB %02x %02x [ ",
                   &obj->base,
@@ -143,9 +143,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
                   obj->base.size / 1024,
                   obj->base.read_domains,
                   obj->base.write_domain);
-       for_each_ring(ring, dev_priv, i)
+       for_each_engine_id(engine, dev_priv, id)
                seq_printf(m, "%x ",
-                               i915_gem_request_get_seqno(obj->last_read_req[i]));
+                               i915_gem_request_get_seqno(obj->last_read_req[id]));
        seq_printf(m, "] %x %x%s%s%s",
                   i915_gem_request_get_seqno(obj->last_write_req),
                   i915_gem_request_get_seqno(obj->last_fenced_req),
@@ -184,7 +184,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
        }
        if (obj->last_write_req != NULL)
                seq_printf(m, " (%s)",
-                          i915_gem_request_get_ring(obj->last_write_req)->name);
+                          i915_gem_request_get_engine(obj->last_write_req)->name);
        if (obj->frontbuffer_bits)
                seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits);
 }
@@ -203,7 +203,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
        struct list_head *head;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct i915_address_space *vm = &dev_priv->gtt.base;
+       struct i915_address_space *vm = &dev_priv->ggtt.base;
        struct i915_vma *vma;
        u64 total_obj_size, total_gtt_size;
        int count, ret;
@@ -397,15 +397,15 @@ static void print_batch_pool_stats(struct seq_file *m,
 {
        struct drm_i915_gem_object *obj;
        struct file_stats stats;
-       struct intel_engine_cs *ring;
-       int i, j;
+       struct intel_engine_cs *engine;
+       int j;
 
        memset(&stats, 0, sizeof(stats));
 
-       for_each_ring(ring, dev_priv, i) {
-               for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) {
+       for_each_engine(engine, dev_priv) {
+               for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
                        list_for_each_entry(obj,
-                                           &ring->batch_pool.cache_list[j],
+                                           &engine->batch_pool.cache_list[j],
                                            batch_pool_link)
                                per_file_stats(0, obj, &stats);
                }
@@ -433,7 +433,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
        u32 count, mappable_count, purgeable_count;
        u64 size, mappable_size, purgeable_size;
        struct drm_i915_gem_object *obj;
-       struct i915_address_space *vm = &dev_priv->gtt.base;
+       struct i915_address_space *vm = &dev_priv->ggtt.base;
        struct drm_file *file;
        struct i915_vma *vma;
        int ret;
@@ -492,8 +492,8 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
                   count, size);
 
        seq_printf(m, "%llu [%llu] gtt total\n",
-                  dev_priv->gtt.base.total,
-                  (u64)dev_priv->gtt.mappable_end - dev_priv->gtt.base.start);
+                  dev_priv->ggtt.base.total,
+                  (u64)dev_priv->ggtt.mappable_end - dev_priv->ggtt.base.start);
 
        seq_putc(m, '\n');
        print_batch_pool_stats(m, dev_priv);
@@ -591,14 +591,13 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
                                           pipe, plane);
                        }
                        if (work->flip_queued_req) {
-                               struct intel_engine_cs *ring =
-                                       i915_gem_request_get_ring(work->flip_queued_req);
+                               struct intel_engine_cs *engine = i915_gem_request_get_engine(work->flip_queued_req);
 
                                seq_printf(m, "Flip queued on %s at seqno %x, next seqno %x [current breadcrumb %x], completed? %d\n",
-                                          ring->name,
+                                          engine->name,
                                           i915_gem_request_get_seqno(work->flip_queued_req),
                                           dev_priv->next_seqno,
-                                          ring->get_seqno(ring, true),
+                                          engine->get_seqno(engine, true),
                                           i915_gem_request_completed(work->flip_queued_req, true));
                        } else
                                seq_printf(m, "Flip not associated with any ring\n");
@@ -637,28 +636,28 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        int total = 0;
-       int ret, i, j;
+       int ret, j;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
 
-       for_each_ring(ring, dev_priv, i) {
-               for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) {
+       for_each_engine(engine, dev_priv) {
+               for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
                        int count;
 
                        count = 0;
                        list_for_each_entry(obj,
-                                           &ring->batch_pool.cache_list[j],
+                                           &engine->batch_pool.cache_list[j],
                                            batch_pool_link)
                                count++;
                        seq_printf(m, "%s cache[%d]: %d objects\n",
-                                  ring->name, j, count);
+                                  engine->name, j, count);
 
                        list_for_each_entry(obj,
-                                           &ring->batch_pool.cache_list[j],
+                                           &engine->batch_pool.cache_list[j],
                                            batch_pool_link) {
                                seq_puts(m, "   ");
                                describe_obj(m, obj);
@@ -681,26 +680,26 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
        struct drm_info_node *node = m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct drm_i915_gem_request *req;
-       int ret, any, i;
+       int ret, any;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
 
        any = 0;
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine(engine, dev_priv) {
                int count;
 
                count = 0;
-               list_for_each_entry(req, &ring->request_list, list)
+               list_for_each_entry(req, &engine->request_list, list)
                        count++;
                if (count == 0)
                        continue;
 
-               seq_printf(m, "%s requests: %d\n", ring->name, count);
-               list_for_each_entry(req, &ring->request_list, list) {
+               seq_printf(m, "%s requests: %d\n", engine->name, count);
+               list_for_each_entry(req, &engine->request_list, list) {
                        struct task_struct *task;
 
                        rcu_read_lock();
@@ -726,11 +725,11 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
 }
 
 static void i915_ring_seqno_info(struct seq_file *m,
-                                struct intel_engine_cs *ring)
+                                struct intel_engine_cs *engine)
 {
-       if (ring->get_seqno) {
+       if (engine->get_seqno) {
                seq_printf(m, "Current sequence (%s): %x\n",
-                          ring->name, ring->get_seqno(ring, false));
+                          engine->name, engine->get_seqno(engine, false));
        }
 }
 
@@ -739,16 +738,16 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
        struct drm_info_node *node = m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int ret, i;
+       struct intel_engine_cs *engine;
+       int ret;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
        intel_runtime_pm_get(dev_priv);
 
-       for_each_ring(ring, dev_priv, i)
-               i915_ring_seqno_info(m, ring);
+       for_each_engine(engine, dev_priv)
+               i915_ring_seqno_info(m, engine);
 
        intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
@@ -762,7 +761,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
        struct drm_info_node *node = m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        int ret, i, pipe;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -934,13 +933,13 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                seq_printf(m, "Graphics Interrupt mask:         %08x\n",
                           I915_READ(GTIMR));
        }
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine(engine, dev_priv) {
                if (INTEL_INFO(dev)->gen >= 6) {
                        seq_printf(m,
                                   "Graphics Interrupt mask (%s):       %08x\n",
-                                  ring->name, I915_READ_IMR(ring));
+                                  engine->name, I915_READ_IMR(engine));
                }
-               i915_ring_seqno_info(m, ring);
+               i915_ring_seqno_info(m, engine);
        }
        intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
@@ -981,12 +980,12 @@ static int i915_hws_info(struct seq_file *m, void *data)
        struct drm_info_node *node = m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        const u32 *hws;
        int i;
 
-       ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
-       hws = ring->status_page.page_addr;
+       engine = &dev_priv->engine[(uintptr_t)node->info_ent->data];
+       hws = engine->status_page.page_addr;
        if (hws == NULL)
                return 0;
 
@@ -1331,11 +1330,12 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
        struct drm_info_node *node = m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       u64 acthd[I915_NUM_RINGS];
-       u32 seqno[I915_NUM_RINGS];
+       struct intel_engine_cs *engine;
+       u64 acthd[I915_NUM_ENGINES];
+       u32 seqno[I915_NUM_ENGINES];
        u32 instdone[I915_NUM_INSTDONE_REG];
-       int i, j;
+       enum intel_engine_id id;
+       int j;
 
        if (!i915.enable_hangcheck) {
                seq_printf(m, "Hangcheck disabled\n");
@@ -1344,9 +1344,9 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
 
        intel_runtime_pm_get(dev_priv);
 
-       for_each_ring(ring, dev_priv, i) {
-               seqno[i] = ring->get_seqno(ring, false);
-               acthd[i] = intel_ring_get_active_head(ring);
+       for_each_engine_id(engine, dev_priv, id) {
+               seqno[id] = engine->get_seqno(engine, false);
+               acthd[id] = intel_ring_get_active_head(engine);
        }
 
        i915_get_extra_instdone(dev, instdone);
@@ -1360,19 +1360,17 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
        } else
                seq_printf(m, "Hangcheck inactive\n");
 
-       for_each_ring(ring, dev_priv, i) {
-               seq_printf(m, "%s:\n", ring->name);
+       for_each_engine_id(engine, dev_priv, id) {
+               seq_printf(m, "%s:\n", engine->name);
                seq_printf(m, "\tseqno = %x [current %x]\n",
-                          ring->hangcheck.seqno, seqno[i]);
+                          engine->hangcheck.seqno, seqno[id]);
                seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n",
-                          (long long)ring->hangcheck.acthd,
-                          (long long)acthd[i]);
-               seq_printf(m, "\tmax ACTHD = 0x%08llx\n",
-                          (long long)ring->hangcheck.max_acthd);
-               seq_printf(m, "\tscore = %d\n", ring->hangcheck.score);
-               seq_printf(m, "\taction = %d\n", ring->hangcheck.action);
-
-               if (ring->id == RCS) {
+                          (long long)engine->hangcheck.acthd,
+                          (long long)acthd[id]);
+               seq_printf(m, "\tscore = %d\n", engine->hangcheck.score);
+               seq_printf(m, "\taction = %d\n", engine->hangcheck.action);
+
+               if (engine->id == RCS) {
                        seq_puts(m, "\tinstdone read =");
 
                        for (j = 0; j < I915_NUM_INSTDONE_REG; j++)
@@ -1382,7 +1380,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
 
                        for (j = 0; j < I915_NUM_INSTDONE_REG; j++)
                                seq_printf(m, " 0x%08x",
-                                          ring->hangcheck.instdone[j]);
+                                          engine->hangcheck.instdone[j]);
 
                        seq_puts(m, "\n");
                }
@@ -1948,9 +1946,10 @@ static int i915_context_status(struct seq_file *m, void *unused)
        struct drm_info_node *node = m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct intel_context *ctx;
-       int ret, i;
+       enum intel_engine_id id;
+       int ret;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
@@ -1968,13 +1967,13 @@ static int i915_context_status(struct seq_file *m, void *unused)
 
                if (i915.enable_execlists) {
                        seq_putc(m, '\n');
-                       for_each_ring(ring, dev_priv, i) {
+                       for_each_engine_id(engine, dev_priv, id) {
                                struct drm_i915_gem_object *ctx_obj =
-                                       ctx->engine[i].state;
+                                       ctx->engine[id].state;
                                struct intel_ringbuffer *ringbuf =
-                                       ctx->engine[i].ringbuf;
+                                       ctx->engine[id].ringbuf;
 
-                               seq_printf(m, "%s: ", ring->name);
+                               seq_printf(m, "%s: ", engine->name);
                                if (ctx_obj)
                                        describe_obj(m, ctx_obj);
                                if (ringbuf)
@@ -1995,22 +1994,22 @@ static int i915_context_status(struct seq_file *m, void *unused)
 
 static void i915_dump_lrc_obj(struct seq_file *m,
                              struct intel_context *ctx,
-                             struct intel_engine_cs *ring)
+                             struct intel_engine_cs *engine)
 {
        struct page *page;
        uint32_t *reg_state;
        int j;
-       struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state;
+       struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
        unsigned long ggtt_offset = 0;
 
        if (ctx_obj == NULL) {
                seq_printf(m, "Context on %s with no gem object\n",
-                          ring->name);
+                          engine->name);
                return;
        }
 
-       seq_printf(m, "CONTEXT: %s %u\n", ring->name,
-                  intel_execlists_ctx_id(ctx, ring));
+       seq_printf(m, "CONTEXT: %s %u\n", engine->name,
+                  intel_execlists_ctx_id(ctx, engine));
 
        if (!i915_gem_obj_ggtt_bound(ctx_obj))
                seq_puts(m, "\tNot bound in GGTT\n");
@@ -2043,9 +2042,9 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct intel_context *ctx;
-       int ret, i;
+       int ret;
 
        if (!i915.enable_execlists) {
                seq_printf(m, "Logical Ring Contexts are disabled\n");
@@ -2058,8 +2057,8 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
 
        list_for_each_entry(ctx, &dev_priv->context_list, link)
                if (ctx != dev_priv->kernel_context)
-                       for_each_ring(ring, dev_priv, i)
-                               i915_dump_lrc_obj(m, ctx, ring);
+                       for_each_engine(engine, dev_priv)
+                               i915_dump_lrc_obj(m, ctx, engine);
 
        mutex_unlock(&dev->struct_mutex);
 
@@ -2071,15 +2070,14 @@ static int i915_execlists(struct seq_file *m, void *data)
        struct drm_info_node *node = (struct drm_info_node *)m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        u32 status_pointer;
        u8 read_pointer;
        u8 write_pointer;
        u32 status;
        u32 ctx_id;
        struct list_head *cursor;
-       int ring_id, i;
-       int ret;
+       int i, ret;
 
        if (!i915.enable_execlists) {
                seq_puts(m, "Logical Ring Contexts are disabled\n");
@@ -2092,22 +2090,22 @@ static int i915_execlists(struct seq_file *m, void *data)
 
        intel_runtime_pm_get(dev_priv);
 
-       for_each_ring(ring, dev_priv, ring_id) {
+       for_each_engine(engine, dev_priv) {
                struct drm_i915_gem_request *head_req = NULL;
                int count = 0;
                unsigned long flags;
 
-               seq_printf(m, "%s\n", ring->name);
+               seq_printf(m, "%s\n", engine->name);
 
-               status = I915_READ(RING_EXECLIST_STATUS_LO(ring));
-               ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(ring));
+               status = I915_READ(RING_EXECLIST_STATUS_LO(engine));
+               ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(engine));
                seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n",
                           status, ctx_id);
 
-               status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
+               status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
                seq_printf(m, "\tStatus pointer: 0x%08X\n", status_pointer);
 
-               read_pointer = ring->next_context_status_buffer;
+               read_pointer = engine->next_context_status_buffer;
                write_pointer = GEN8_CSB_WRITE_PTR(status_pointer);
                if (read_pointer > write_pointer)
                        write_pointer += GEN8_CSB_ENTRIES;
@@ -2115,24 +2113,25 @@ static int i915_execlists(struct seq_file *m, void *data)
                           read_pointer, write_pointer);
 
                for (i = 0; i < GEN8_CSB_ENTRIES; i++) {
-                       status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i));
-                       ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i));
+                       status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, i));
+                       ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, i));
 
                        seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n",
                                   i, status, ctx_id);
                }
 
-               spin_lock_irqsave(&ring->execlist_lock, flags);
-               list_for_each(cursor, &ring->execlist_queue)
+               spin_lock_irqsave(&engine->execlist_lock, flags);
+               list_for_each(cursor, &engine->execlist_queue)
                        count++;
-               head_req = list_first_entry_or_null(&ring->execlist_queue,
-                               struct drm_i915_gem_request, execlist_link);
-               spin_unlock_irqrestore(&ring->execlist_lock, flags);
+               head_req = list_first_entry_or_null(&engine->execlist_queue,
+                                                   struct drm_i915_gem_request,
+                                                   execlist_link);
+               spin_unlock_irqrestore(&engine->execlist_lock, flags);
 
                seq_printf(m, "\t%d requests in queue\n", count);
                if (head_req) {
                        seq_printf(m, "\tHead request id: %u\n",
-                                  intel_execlists_ctx_id(head_req->ctx, ring));
+                                  intel_execlists_ctx_id(head_req->ctx, engine));
                        seq_printf(m, "\tHead request tail: %u\n",
                                   head_req->tail);
                }
@@ -2248,19 +2247,19 @@ static int per_file_ctx(int id, void *ptr, void *data)
 static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
-       int unused, i;
+       int i;
 
        if (!ppgtt)
                return;
 
-       for_each_ring(ring, dev_priv, unused) {
-               seq_printf(m, "%s\n", ring->name);
+       for_each_engine(engine, dev_priv) {
+               seq_printf(m, "%s\n", engine->name);
                for (i = 0; i < 4; i++) {
-                       u64 pdp = I915_READ(GEN8_RING_PDP_UDW(ring, i));
+                       u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i));
                        pdp <<= 32;
-                       pdp |= I915_READ(GEN8_RING_PDP_LDW(ring, i));
+                       pdp |= I915_READ(GEN8_RING_PDP_LDW(engine, i));
                        seq_printf(m, "\tPDP%d 0x%016llx\n", i, pdp);
                }
        }
@@ -2269,19 +2268,22 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
        if (INTEL_INFO(dev)->gen == 6)
                seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE));
 
-       for_each_ring(ring, dev_priv, i) {
-               seq_printf(m, "%s\n", ring->name);
+       for_each_engine(engine, dev_priv) {
+               seq_printf(m, "%s\n", engine->name);
                if (INTEL_INFO(dev)->gen == 7)
-                       seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(RING_MODE_GEN7(ring)));
-               seq_printf(m, "PP_DIR_BASE: 0x%08x\n", I915_READ(RING_PP_DIR_BASE(ring)));
-               seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n", I915_READ(RING_PP_DIR_BASE_READ(ring)));
-               seq_printf(m, "PP_DIR_DCLV: 0x%08x\n", I915_READ(RING_PP_DIR_DCLV(ring)));
+                       seq_printf(m, "GFX_MODE: 0x%08x\n",
+                                  I915_READ(RING_MODE_GEN7(engine)));
+               seq_printf(m, "PP_DIR_BASE: 0x%08x\n",
+                          I915_READ(RING_PP_DIR_BASE(engine)));
+               seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n",
+                          I915_READ(RING_PP_DIR_BASE_READ(engine)));
+               seq_printf(m, "PP_DIR_DCLV: 0x%08x\n",
+                          I915_READ(RING_PP_DIR_DCLV(engine)));
        }
        if (dev_priv->mm.aliasing_ppgtt) {
                struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
@@ -2336,12 +2338,11 @@ out_put:
 
 static int count_irq_waiters(struct drm_i915_private *i915)
 {
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        int count = 0;
-       int i;
 
-       for_each_ring(ring, i915, i)
-               count += ring->irq_refcount;
+       for_each_engine(engine, i915)
+               count += engine->irq_refcount;
 
        return count;
 }
@@ -2449,9 +2450,8 @@ static void i915_guc_client_info(struct seq_file *m,
                                 struct drm_i915_private *dev_priv,
                                 struct i915_guc_client *client)
 {
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        uint64_t tot = 0;
-       uint32_t i;
 
        seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n",
                client->priority, client->ctx_index, client->proc_desc_offset);
@@ -2464,11 +2464,11 @@ static void i915_guc_client_info(struct seq_file *m,
        seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
        seq_printf(m, "\tLast submission result: %d\n", client->retcode);
 
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine(engine, dev_priv) {
                seq_printf(m, "\tSubmissions: %llu %s\n",
-                               client->submissions[ring->guc_id],
-                               ring->name);
-               tot += client->submissions[ring->guc_id];
+                               client->submissions[engine->guc_id],
+                               engine->name);
+               tot += client->submissions[engine->guc_id];
        }
        seq_printf(m, "\tTotal: %llu\n", tot);
 }
@@ -2480,8 +2480,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_guc guc;
        struct i915_guc_client client = {};
-       struct intel_engine_cs *ring;
-       enum intel_ring_id i;
+       struct intel_engine_cs *engine;
        u64 total = 0;
 
        if (!HAS_GUC_SCHED(dev_priv->dev))
@@ -2504,11 +2503,11 @@ static int i915_guc_info(struct seq_file *m, void *data)
        seq_printf(m, "GuC last action error code: %d\n", guc.action_err);
 
        seq_printf(m, "\nGuC submissions:\n");
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine(engine, dev_priv) {
                seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n",
-                       ring->name, guc.submissions[ring->guc_id],
-                       guc.last_seqno[ring->guc_id]);
-               total += guc.submissions[ring->guc_id];
+                       engine->name, guc.submissions[engine->guc_id],
+                       guc.last_seqno[engine->guc_id]);
+               total += guc.submissions[engine->guc_id];
        }
        seq_printf(m, "\t%s: %llu\n", "Total", total);
 
@@ -3130,9 +3129,10 @@ static int i915_semaphore_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;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        int num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
-       int i, j, ret;
+       enum intel_engine_id id;
+       int j, ret;
 
        if (!i915_semaphore_is_enabled(dev)) {
                seq_puts(m, "Semaphores are disabled\n");
@@ -3151,14 +3151,14 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
                page = i915_gem_object_get_page(dev_priv->semaphore_obj, 0);
 
                seqno = (uint64_t *)kmap_atomic(page);
-               for_each_ring(ring, dev_priv, i) {
+               for_each_engine_id(engine, dev_priv, id) {
                        uint64_t offset;
 
-                       seq_printf(m, "%s\n", ring->name);
+                       seq_printf(m, "%s\n", engine->name);
 
                        seq_puts(m, "  Last signal:");
                        for (j = 0; j < num_rings; j++) {
-                               offset = i * I915_NUM_RINGS + j;
+                               offset = id * I915_NUM_ENGINES + j;
                                seq_printf(m, "0x%08llx (0x%02llx) ",
                                           seqno[offset], offset * 8);
                        }
@@ -3166,7 +3166,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
 
                        seq_puts(m, "  Last wait:  ");
                        for (j = 0; j < num_rings; j++) {
-                               offset = i + (j * I915_NUM_RINGS);
+                               offset = id + (j * I915_NUM_ENGINES);
                                seq_printf(m, "0x%08llx (0x%02llx) ",
                                           seqno[offset], offset * 8);
                        }
@@ -3176,18 +3176,18 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
                kunmap_atomic(seqno);
        } else {
                seq_puts(m, "  Last signal:");
-               for_each_ring(ring, dev_priv, i)
+               for_each_engine(engine, dev_priv)
                        for (j = 0; j < num_rings; j++)
                                seq_printf(m, "0x%08x\n",
-                                          I915_READ(ring->semaphore.mbox.signal[j]));
+                                          I915_READ(engine->semaphore.mbox.signal[j]));
                seq_putc(m, '\n');
        }
 
        seq_puts(m, "\nSync seqno:\n");
-       for_each_ring(ring, dev_priv, i) {
-               for (j = 0; j < num_rings; j++) {
-                       seq_printf(m, "  0x%08x ", ring->semaphore.sync_seqno[j]);
-               }
+       for_each_engine(engine, dev_priv) {
+               for (j = 0; j < num_rings; j++)
+                       seq_printf(m, "  0x%08x ",
+                                  engine->semaphore.sync_seqno[j]);
                seq_putc(m, '\n');
        }
        seq_putc(m, '\n');
@@ -3209,8 +3209,8 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
                struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
 
                seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->name, pll->id);
-               seq_printf(m, " crtc_mask: 0x%08x, active: %d, on: %s\n",
-                          pll->config.crtc_mask, pll->active, yesno(pll->on));
+               seq_printf(m, " crtc_mask: 0x%08x, active: 0x%x, on: %s\n",
+                          pll->config.crtc_mask, pll->active_mask, yesno(pll->on));
                seq_printf(m, " tracked hardware state:\n");
                seq_printf(m, " dpll:    0x%08x\n", pll->config.hw_state.dpll);
                seq_printf(m, " dpll_md: 0x%08x\n",
@@ -3228,11 +3228,12 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
 {
        int i;
        int ret;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_workarounds *workarounds = &dev_priv->workarounds;
+       enum intel_engine_id id;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
@@ -3241,9 +3242,9 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
        intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "Workarounds applied: %d\n", workarounds->count);
-       for_each_ring(ring, dev_priv, i)
+       for_each_engine_id(engine, dev_priv, id)
                seq_printf(m, "HW whitelist count for %s: %d\n",
-                          ring->name, workarounds->hw_whitelist_count[i]);
+                          engine->name, workarounds->hw_whitelist_count[id]);
        for (i = 0; i < workarounds->count; ++i) {
                i915_reg_t addr;
                u32 mask, value, read;
index 1c6d227..1ac1ea9 100644 (file)
 #include <linux/pm_runtime.h>
 #include <linux/oom.h>
 
+static unsigned int i915_load_fail_count;
+
+bool __i915_inject_load_failure(const char *func, int line)
+{
+       if (i915_load_fail_count >= i915.inject_load_failure)
+               return false;
+
+       if (++i915_load_fail_count == i915.inject_load_failure) {
+               DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n",
+                        i915.inject_load_failure, func, line);
+               return true;
+       }
+
+       return false;
+}
+
+#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI"
+#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \
+                   "providing the dmesg log by booting with drm.debug=0xf"
+
+void
+__i915_printk(struct drm_i915_private *dev_priv, const char *level,
+             const char *fmt, ...)
+{
+       static bool shown_bug_once;
+       struct device *dev = dev_priv->dev->dev;
+       bool is_error = level[1] <= KERN_ERR[1];
+       bool is_debug = level[1] == KERN_DEBUG[1];
+       struct va_format vaf;
+       va_list args;
+
+       if (is_debug && !(drm_debug & DRM_UT_DRIVER))
+               return;
+
+       va_start(args, fmt);
+
+       vaf.fmt = fmt;
+       vaf.va = &args;
+
+       dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
+                  __builtin_return_address(0), &vaf);
+
+       if (is_error && !shown_bug_once) {
+               dev_notice(dev, "%s", FDO_BUG_MSG);
+               shown_bug_once = true;
+       }
+
+       va_end(args);
+}
+
+static bool i915_error_injected(struct drm_i915_private *dev_priv)
+{
+       return i915.inject_load_failure &&
+              i915_load_fail_count == i915.inject_load_failure;
+}
+
+#define i915_load_error(dev_priv, fmt, ...)                                 \
+       __i915_printk(dev_priv,                                              \
+                     i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \
+                     fmt, ##__VA_ARGS__)
 
 static int i915_getparam(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
@@ -87,16 +147,16 @@ static int i915_getparam(struct drm_device *dev, void *data,
                value = 1;
                break;
        case I915_PARAM_HAS_BSD:
-               value = intel_ring_initialized(&dev_priv->ring[VCS]);
+               value = intel_engine_initialized(&dev_priv->engine[VCS]);
                break;
        case I915_PARAM_HAS_BLT:
-               value = intel_ring_initialized(&dev_priv->ring[BCS]);
+               value = intel_engine_initialized(&dev_priv->engine[BCS]);
                break;
        case I915_PARAM_HAS_VEBOX:
-               value = intel_ring_initialized(&dev_priv->ring[VECS]);
+               value = intel_engine_initialized(&dev_priv->engine[VECS]);
                break;
        case I915_PARAM_HAS_BSD2:
-               value = intel_ring_initialized(&dev_priv->ring[VCS2]);
+               value = intel_engine_initialized(&dev_priv->engine[VCS2]);
                break;
        case I915_PARAM_HAS_RELAXED_FENCING:
                value = 1;
@@ -370,6 +430,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
+       if (i915_inject_load_failure())
+               return -ENODEV;
+
        ret = intel_bios_init(dev_priv);
        if (ret)
                DRM_INFO("failed to find VBIOS tables\n");
@@ -430,11 +493,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
         * Some ports require correctly set-up hpd registers for detection to
         * work properly (leading to ghost connected connector status), e.g. VGA
         * on gm45.  Hence we can only set up the initial fbdev config after hpd
-        * irqs are fully enabled. Now we should scan for the initial config
-        * only once hotplug handling is enabled, but due to screwed-up locking
-        * around kms/fbdev init we can't protect the fdbev initial config
-        * scanning against hotplug events. Hence do this first and ignore the
-        * tiny window where we will loose hotplug notifactions.
+        * irqs are fully enabled. We protect the fbdev initial config scanning
+        * against hotplug events by waiting in intel_fbdev_output_poll_changed
+        * until the asynchronous thread has finished.
         */
        intel_fbdev_initial_config_async(dev);
 
@@ -444,7 +505,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
 
 cleanup_gem:
        mutex_lock(&dev->struct_mutex);
-       i915_gem_cleanup_ringbuffer(dev);
+       i915_gem_cleanup_engines(dev);
        i915_gem_context_fini(dev);
        mutex_unlock(&dev->struct_mutex);
 cleanup_irq:
@@ -453,6 +514,7 @@ cleanup_irq:
        intel_teardown_gmbus(dev);
 cleanup_csr:
        intel_csr_ucode_fini(dev_priv);
+       intel_power_domains_fini(dev_priv);
        vga_switcheroo_unregister_client(dev->pdev);
 cleanup_vga_client:
        vga_client_register(dev->pdev, NULL, NULL, NULL);
@@ -472,8 +534,8 @@ static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
        if (!ap)
                return -ENOMEM;
 
-       ap->ranges[0].base = dev_priv->gtt.mappable_base;
-       ap->ranges[0].size = dev_priv->gtt.mappable_end;
+       ap->ranges[0].base = dev_priv->ggtt.mappable_base;
+       ap->ranges[0].size = dev_priv->ggtt.mappable_end;
 
        primary =
                pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
@@ -853,6 +915,10 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
        else if (INTEL_INFO(dev)->gen >= 9)
                gen9_sseu_info_init(dev);
 
+       /* Snooping is broken on BXT A stepping. */
+       info->has_snoop = !info->has_llc;
+       info->has_snoop &= !IS_BXT_REVID(dev, 0, BXT_REVID_A1);
+
        DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total);
        DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total);
        DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice);
@@ -929,6 +995,84 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
        destroy_workqueue(dev_priv->wq);
 }
 
+/**
+ * i915_driver_init_early - setup state not requiring device access
+ * @dev_priv: device private
+ *
+ * Initialize everything that is a "SW-only" state, that is state not
+ * requiring accessing the device or exposing the driver via kernel internal
+ * or userspace interfaces. Example steps belonging here: lock initialization,
+ * system memory allocation, setting up device specific attributes and
+ * function hooks not requiring accessing the device.
+ */
+static int i915_driver_init_early(struct drm_i915_private *dev_priv,
+                                 struct drm_device *dev,
+                                 struct intel_device_info *info)
+{
+       struct intel_device_info *device_info;
+       int ret = 0;
+
+       if (i915_inject_load_failure())
+               return -ENODEV;
+
+       /* Setup the write-once "constant" device info */
+       device_info = (struct intel_device_info *)&dev_priv->info;
+       memcpy(device_info, info, sizeof(dev_priv->info));
+       device_info->device_id = dev->pdev->device;
+
+       spin_lock_init(&dev_priv->irq_lock);
+       spin_lock_init(&dev_priv->gpu_error.lock);
+       mutex_init(&dev_priv->backlight_lock);
+       spin_lock_init(&dev_priv->uncore.lock);
+       spin_lock_init(&dev_priv->mm.object_stat_lock);
+       spin_lock_init(&dev_priv->mmio_flip_lock);
+       mutex_init(&dev_priv->sb_lock);
+       mutex_init(&dev_priv->modeset_restore_lock);
+       mutex_init(&dev_priv->av_mutex);
+       mutex_init(&dev_priv->wm.wm_mutex);
+       mutex_init(&dev_priv->pps_mutex);
+
+       ret = i915_workqueues_init(dev_priv);
+       if (ret < 0)
+               return ret;
+
+       /* This must be called before any calls to HAS_PCH_* */
+       intel_detect_pch(dev);
+
+       intel_pm_setup(dev);
+       intel_init_dpio(dev_priv);
+       intel_power_domains_init(dev_priv);
+       intel_irq_init(dev_priv);
+       intel_init_display_hooks(dev_priv);
+       intel_init_clock_gating_hooks(dev_priv);
+       intel_init_audio_hooks(dev_priv);
+       i915_gem_load_init(dev);
+
+       intel_display_crc_init(dev);
+
+       i915_dump_device_info(dev_priv);
+
+       /* Not all pre-production machines fall into this category, only the
+        * very first ones. Almost everything should work, except for maybe
+        * suspend/resume. And we don't implement workarounds that affect only
+        * pre-production machines. */
+       if (IS_HSW_EARLY_SDV(dev))
+               DRM_INFO("This is an early pre-production Haswell machine. "
+                        "It may not be fully functional.\n");
+
+       return 0;
+}
+
+/**
+ * i915_driver_cleanup_early - cleanup the setup done in i915_driver_init_early()
+ * @dev_priv: device private
+ */
+static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
+{
+       i915_gem_load_cleanup(dev_priv->dev);
+       i915_workqueues_cleanup(dev_priv);
+}
+
 static int i915_mmio_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -970,84 +1114,73 @@ static void i915_mmio_cleanup(struct drm_device *dev)
 }
 
 /**
- * i915_driver_load - setup chip and create an initial config
- * @dev: DRM device
- * @flags: startup flags
+ * i915_driver_init_mmio - setup device MMIO
+ * @dev_priv: device private
  *
- * The driver load routine has to do several things:
- *   - drive output discovery via intel_modeset_init()
- *   - initialize the memory manager
- *   - allocate initial config memory
- *   - setup the DRM framebuffer with the allocated memory
+ * Setup minimal device state necessary for MMIO accesses later in the
+ * initialization sequence. The setup here should avoid any other device-wide
+ * side effects or exposing the driver via kernel internal or user space
+ * interfaces.
  */
-int i915_driver_load(struct drm_device *dev, unsigned long flags)
+static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv;
-       struct intel_device_info *info, *device_info;
-       int ret = 0;
-       uint32_t aperture_size;
-
-       info = (struct intel_device_info *) flags;
-
-       dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       dev->dev_private = dev_priv;
-       dev_priv->dev = dev;
+       struct drm_device *dev = dev_priv->dev;
+       int ret;
 
-       /* Setup the write-once "constant" device info */
-       device_info = (struct intel_device_info *)&dev_priv->info;
-       memcpy(device_info, info, sizeof(dev_priv->info));
-       device_info->device_id = dev->pdev->device;
+       if (i915_inject_load_failure())
+               return -ENODEV;
 
-       spin_lock_init(&dev_priv->irq_lock);
-       spin_lock_init(&dev_priv->gpu_error.lock);
-       mutex_init(&dev_priv->backlight_lock);
-       spin_lock_init(&dev_priv->uncore.lock);
-       spin_lock_init(&dev_priv->mm.object_stat_lock);
-       spin_lock_init(&dev_priv->mmio_flip_lock);
-       mutex_init(&dev_priv->sb_lock);
-       mutex_init(&dev_priv->modeset_restore_lock);
-       mutex_init(&dev_priv->av_mutex);
+       if (i915_get_bridge_dev(dev))
+               return -EIO;
 
-       ret = i915_workqueues_init(dev_priv);
+       ret = i915_mmio_setup(dev);
        if (ret < 0)
-               goto out_free_priv;
+               goto put_bridge;
 
-       intel_pm_setup(dev);
+       intel_uncore_init(dev);
 
-       intel_runtime_pm_get(dev_priv);
+       return 0;
 
-       intel_display_crc_init(dev);
+put_bridge:
+       pci_dev_put(dev_priv->bridge_dev);
 
-       i915_dump_device_info(dev_priv);
+       return ret;
+}
 
-       /* Not all pre-production machines fall into this category, only the
-        * very first ones. Almost everything should work, except for maybe
-        * suspend/resume. And we don't implement workarounds that affect only
       * pre-production machines. */
-       if (IS_HSW_EARLY_SDV(dev))
-               DRM_INFO("This is an early pre-production Haswell machine. "
-                        "It may not be fully functional.\n");
+/**
+ * i915_driver_cleanup_mmio - cleanup the setup done in i915_driver_init_mmio()
+ * @dev_priv: device private
+ */
+static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
 
-       if (i915_get_bridge_dev(dev)) {
-               ret = -EIO;
-               goto out_runtime_pm_put;
-       }
+       intel_uncore_fini(dev);
+       i915_mmio_cleanup(dev);
+       pci_dev_put(dev_priv->bridge_dev);
+}
 
-       ret = i915_mmio_setup(dev);
-       if (ret < 0)
-               goto put_bridge;
+/**
+ * i915_driver_init_hw - setup state requiring device access
+ * @dev_priv: device private
+ *
+ * Setup state that requires accessing the device, but doesn't require
+ * exposing the driver via kernel internal or userspace interfaces.
+ */
+static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       uint32_t aperture_size;
+       int ret;
 
-       /* This must be called before any calls to HAS_PCH_* */
-       intel_detect_pch(dev);
+       if (i915_inject_load_failure())
+               return -ENODEV;
 
-       intel_uncore_init(dev);
+       intel_device_info_runtime_init(dev);
 
        ret = i915_gem_gtt_init(dev);
        if (ret)
-               goto out_uncore_fini;
+               return ret;
 
        /* WARNING: Apparently we must kick fbdev drivers before vgacon,
         * otherwise the vga fbdev driver falls over. */
@@ -1080,26 +1213,27 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
                dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
 
-       aperture_size = dev_priv->gtt.mappable_end;
+       aperture_size = dev_priv->ggtt.mappable_end;
 
-       dev_priv->gtt.mappable =
-               io_mapping_create_wc(dev_priv->gtt.mappable_base,
+       dev_priv->ggtt.mappable =
+               io_mapping_create_wc(dev_priv->ggtt.mappable_base,
                                     aperture_size);
-       if (dev_priv->gtt.mappable == NULL) {
+       if (dev_priv->ggtt.mappable == NULL) {
                ret = -EIO;
                goto out_gtt;
        }
 
-       dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
+       dev_priv->ggtt.mtrr = arch_phys_wc_add(dev_priv->ggtt.mappable_base,
                                              aperture_size);
 
-       intel_irq_init(dev_priv);
+       pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY,
+                          PM_QOS_DEFAULT_VALUE);
+
        intel_uncore_sanitize(dev);
 
        intel_opregion_setup(dev);
 
-       i915_gem_load_init(dev);
-       i915_gem_shrinker_init(dev_priv);
+       i915_gem_load_init_fences(dev_priv);
 
        /* On the 945G/GM, the chipset reports the MSI capability on the
         * integrated graphics even though the support isn't actually there
@@ -1117,24 +1251,43 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                        DRM_DEBUG_DRIVER("can't enable MSI");
        }
 
-       intel_device_info_runtime_init(dev);
+       return 0;
 
-       intel_init_dpio(dev_priv);
+out_gtt:
+       i915_global_gtt_cleanup(dev);
 
-       if (INTEL_INFO(dev)->num_pipes) {
-               ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
-               if (ret)
-                       goto out_gem_unload;
-       }
+       return ret;
+}
 
-       intel_power_domains_init(dev_priv);
+/**
+ * i915_driver_cleanup_hw - cleanup the setup done in i915_driver_init_hw()
+ * @dev_priv: device private
+ */
+static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
 
-       ret = i915_load_modeset_init(dev);
-       if (ret < 0) {
-               DRM_ERROR("failed to init modeset\n");
-               goto out_power_well;
-       }
+       if (dev->pdev->msi_enabled)
+               pci_disable_msi(dev->pdev);
+
+       pm_qos_remove_request(&dev_priv->pm_qos);
+       arch_phys_wc_del(dev_priv->ggtt.mtrr);
+       io_mapping_free(dev_priv->ggtt.mappable);
+       i915_global_gtt_cleanup(dev);
+}
 
+/**
+ * i915_driver_register - register the driver with the rest of the system
+ * @dev_priv: device private
+ *
+ * Perform any steps necessary to make the driver available via kernel
+ * internal or userspace interfaces.
+ */
+static void i915_driver_register(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+
+       i915_gem_shrinker_init(dev_priv);
        /*
         * Notify a valid surface after modesetting,
         * when running inside a VM.
@@ -1144,48 +1297,107 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        i915_setup_sysfs(dev);
 
-       if (INTEL_INFO(dev)->num_pipes) {
+       if (INTEL_INFO(dev_priv)->num_pipes) {
                /* Must be done after probing outputs */
                intel_opregion_init(dev);
                acpi_video_register();
        }
 
-       if (IS_GEN5(dev))
+       if (IS_GEN5(dev_priv))
                intel_gpu_ips_init(dev_priv);
 
-       intel_runtime_pm_enable(dev_priv);
-
        i915_audio_component_init(dev_priv);
+}
+
+/**
+ * i915_driver_unregister - cleanup the registration done in i915_driver_regiser()
+ * @dev_priv: device private
+ */
+static void i915_driver_unregister(struct drm_i915_private *dev_priv)
+{
+       i915_audio_component_cleanup(dev_priv);
+       intel_gpu_ips_teardown();
+       acpi_video_unregister();
+       intel_opregion_fini(dev_priv->dev);
+       i915_teardown_sysfs(dev_priv->dev);
+       i915_gem_shrinker_cleanup(dev_priv);
+}
+
+/**
+ * i915_driver_load - setup chip and create an initial config
+ * @dev: DRM device
+ * @flags: startup flags
+ *
+ * The driver load routine has to do several things:
+ *   - drive output discovery via intel_modeset_init()
+ *   - initialize the memory manager
+ *   - allocate initial config memory
+ *   - setup the DRM framebuffer with the allocated memory
+ */
+int i915_driver_load(struct drm_device *dev, unsigned long flags)
+{
+       struct drm_i915_private *dev_priv;
+       int ret = 0;
+
+       dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       dev->dev_private = dev_priv;
+       /* Must be set before calling __i915_printk */
+       dev_priv->dev = dev;
+
+       ret = i915_driver_init_early(dev_priv, dev,
+                                    (struct intel_device_info *)flags);
+
+       if (ret < 0)
+               goto out_free_priv;
+
+       intel_runtime_pm_get(dev_priv);
+
+       ret = i915_driver_init_mmio(dev_priv);
+       if (ret < 0)
+               goto out_runtime_pm_put;
+
+       ret = i915_driver_init_hw(dev_priv);
+       if (ret < 0)
+               goto out_cleanup_mmio;
+
+       /*
+        * TODO: move the vblank init and parts of modeset init steps into one
+        * of the i915_driver_init_/i915_driver_register functions according
+        * to the role/effect of the given init step.
+        */
+       if (INTEL_INFO(dev)->num_pipes) {
+               ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
+               if (ret)
+                       goto out_cleanup_hw;
+       }
+
+       ret = i915_load_modeset_init(dev);
+       if (ret < 0)
+               goto out_cleanup_vblank;
+
+       i915_driver_register(dev_priv);
+
+       intel_runtime_pm_enable(dev_priv);
 
        intel_runtime_pm_put(dev_priv);
 
        return 0;
 
-out_power_well:
-       intel_power_domains_fini(dev_priv);
+out_cleanup_vblank:
        drm_vblank_cleanup(dev);
-out_gem_unload:
-       i915_gem_shrinker_cleanup(dev_priv);
-
-       if (dev->pdev->msi_enabled)
-               pci_disable_msi(dev->pdev);
-
-       intel_teardown_mchbar(dev);
-       pm_qos_remove_request(&dev_priv->pm_qos);
-       arch_phys_wc_del(dev_priv->gtt.mtrr);
-       io_mapping_free(dev_priv->gtt.mappable);
-out_gtt:
-       i915_global_gtt_cleanup(dev);
-out_uncore_fini:
-       intel_uncore_fini(dev);
-       i915_mmio_cleanup(dev);
-put_bridge:
-       pci_dev_put(dev_priv->bridge_dev);
-       i915_gem_load_cleanup(dev);
+out_cleanup_hw:
+       i915_driver_cleanup_hw(dev_priv);
+out_cleanup_mmio:
+       i915_driver_cleanup_mmio(dev_priv);
 out_runtime_pm_put:
        intel_runtime_pm_put(dev_priv);
-       i915_workqueues_cleanup(dev_priv);
+       i915_driver_cleanup_early(dev_priv);
 out_free_priv:
+       i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
+
        kfree(dev_priv);
 
        return ret;
@@ -1198,26 +1410,15 @@ int i915_driver_unload(struct drm_device *dev)
 
        intel_fbdev_fini(dev);
 
-       i915_audio_component_cleanup(dev_priv);
-
        ret = i915_gem_suspend(dev);
        if (ret) {
                DRM_ERROR("failed to idle hardware: %d\n", ret);
                return ret;
        }
 
-       intel_power_domains_fini(dev_priv);
-
-       intel_gpu_ips_teardown();
-
-       i915_teardown_sysfs(dev);
-
-       i915_gem_shrinker_cleanup(dev_priv);
+       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
-       io_mapping_free(dev_priv->gtt.mappable);
-       arch_phys_wc_del(dev_priv->gtt.mtrr);
-
-       acpi_video_unregister();
+       i915_driver_unregister(dev_priv);
 
        drm_vblank_cleanup(dev);
 
@@ -1246,31 +1447,24 @@ int i915_driver_unload(struct drm_device *dev)
        cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
        i915_destroy_error_state(dev);
 
-       if (dev->pdev->msi_enabled)
-               pci_disable_msi(dev->pdev);
-
-       intel_opregion_fini(dev);
-
        /* Flush any outstanding unpin_work. */
        flush_workqueue(dev_priv->wq);
 
        intel_guc_ucode_fini(dev);
        mutex_lock(&dev->struct_mutex);
-       i915_gem_cleanup_ringbuffer(dev);
+       i915_gem_cleanup_engines(dev);
        i915_gem_context_fini(dev);
        mutex_unlock(&dev->struct_mutex);
        intel_fbc_cleanup_cfb(dev_priv);
 
-       pm_qos_remove_request(&dev_priv->pm_qos);
+       intel_power_domains_fini(dev_priv);
 
-       i915_global_gtt_cleanup(dev);
+       i915_driver_cleanup_hw(dev_priv);
+       i915_driver_cleanup_mmio(dev_priv);
 
-       intel_uncore_fini(dev);
-       i915_mmio_cleanup(dev);
+       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
-       i915_gem_load_cleanup(dev);
-       pci_dev_put(dev_priv->bridge_dev);
-       i915_workqueues_cleanup(dev_priv);
+       i915_driver_cleanup_early(dev_priv);
        kfree(dev_priv);
 
        return 0;
index 4c0dd35..349e17c 100644 (file)
@@ -66,6 +66,11 @@ static struct drm_driver driver;
 #define IVB_CURSOR_OFFSETS \
        .cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET }
 
+#define BDW_COLORS \
+       .color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
+#define CHV_COLORS \
+       .color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }
+
 static const struct intel_device_info intel_i830_info = {
        .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
        .has_overlay = 1, .overlay_needs_physical = 1,
@@ -288,24 +293,28 @@ static const struct intel_device_info intel_haswell_m_info = {
        .is_mobile = 1,
 };
 
+#define BDW_FEATURES \
+       HSW_FEATURES, \
+       BDW_COLORS
+
 static const struct intel_device_info intel_broadwell_d_info = {
-       HSW_FEATURES,
+       BDW_FEATURES,
        .gen = 8,
 };
 
 static const struct intel_device_info intel_broadwell_m_info = {
-       HSW_FEATURES,
+       BDW_FEATURES,
        .gen = 8, .is_mobile = 1,
 };
 
 static const struct intel_device_info intel_broadwell_gt3d_info = {
-       HSW_FEATURES,
+       BDW_FEATURES,
        .gen = 8,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
 };
 
 static const struct intel_device_info intel_broadwell_gt3m_info = {
-       HSW_FEATURES,
+       BDW_FEATURES,
        .gen = 8, .is_mobile = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
 };
@@ -318,16 +327,17 @@ static const struct intel_device_info intel_cherryview_info = {
        .display_mmio_offset = VLV_DISPLAY_BASE,
        GEN_CHV_PIPEOFFSETS,
        CURSOR_OFFSETS,
+       CHV_COLORS,
 };
 
 static const struct intel_device_info intel_skylake_info = {
-       HSW_FEATURES,
+       BDW_FEATURES,
        .is_skylake = 1,
        .gen = 9,
 };
 
 static const struct intel_device_info intel_skylake_gt3_info = {
-       HSW_FEATURES,
+       BDW_FEATURES,
        .is_skylake = 1,
        .gen = 9,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
@@ -345,17 +355,18 @@ static const struct intel_device_info intel_broxton_info = {
        .has_fbc = 1,
        GEN_DEFAULT_PIPEOFFSETS,
        IVB_CURSOR_OFFSETS,
+       BDW_COLORS,
 };
 
 static const struct intel_device_info intel_kabylake_info = {
-       HSW_FEATURES,
+       BDW_FEATURES,
        .is_preliminary = 1,
        .is_kabylake = 1,
        .gen = 9,
 };
 
 static const struct intel_device_info intel_kabylake_gt3_info = {
-       HSW_FEATURES,
+       BDW_FEATURES,
        .is_preliminary = 1,
        .is_kabylake = 1,
        .gen = 9,
@@ -504,6 +515,7 @@ void intel_detect_pch(struct drm_device *dev)
                                WARN_ON(!IS_SKYLAKE(dev) &&
                                        !IS_KABYLAKE(dev));
                        } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
+                                  (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) ||
                                   ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
                                    pch->subsystem_vendor == 0x1af4 &&
                                    pch->subsystem_device == 0x1100)) {
@@ -758,10 +770,10 @@ static int i915_drm_resume(struct drm_device *dev)
                dev_priv->display.hpd_irq_setup(dev);
        spin_unlock_irq(&dev_priv->irq_lock);
 
-       intel_display_resume(dev);
-
        intel_dp_mst_resume(dev);
 
+       intel_display_resume(dev);
+
        /*
         * ... but also need to make sure that hotplug processing
         * doesn't cause havoc. Like in the driver load code we don't
@@ -881,7 +893,7 @@ int i915_reset(struct drm_device *dev)
 
        simulated = dev_priv->gpu_error.stop_rings != 0;
 
-       ret = intel_gpu_reset(dev);
+       ret = intel_gpu_reset(dev, ALL_ENGINES);
 
        /* Also reset the gpu hangman. */
        if (simulated) {
index 1048093..f6d7159 100644 (file)
 #include <linux/kref.h>
 #include <linux/pm_qos.h>
 #include "intel_guc.h"
+#include "intel_dpll_mgr.h"
 
 /* General customization:
  */
 
 #define DRIVER_NAME            "i915"
 #define DRIVER_DESC            "Intel Graphics"
-#define DRIVER_DATE            "20160229"
+#define DRIVER_DATE            "20160330"
 
 #undef WARN_ON
 /* Many gcc seem to no see through this and fall over :( */
 #define I915_STATE_WARN_ON(x)                                          \
        I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")")
 
+bool __i915_inject_load_failure(const char *func, int line);
+#define i915_inject_load_failure() \
+       __i915_inject_load_failure(__func__, __LINE__)
+
 static inline const char *yesno(bool v)
 {
        return v ? "yes" : "no";
@@ -122,9 +127,35 @@ enum transcoder {
        TRANSCODER_B,
        TRANSCODER_C,
        TRANSCODER_EDP,
+       TRANSCODER_DSI_A,
+       TRANSCODER_DSI_C,
        I915_MAX_TRANSCODERS
 };
-#define transcoder_name(t) ((t) + 'A')
+
+static inline const char *transcoder_name(enum transcoder transcoder)
+{
+       switch (transcoder) {
+       case TRANSCODER_A:
+               return "A";
+       case TRANSCODER_B:
+               return "B";
+       case TRANSCODER_C:
+               return "C";
+       case TRANSCODER_EDP:
+               return "EDP";
+       case TRANSCODER_DSI_A:
+               return "DSI A";
+       case TRANSCODER_DSI_C:
+               return "DSI C";
+       default:
+               return "<invalid>";
+       }
+}
+
+static inline bool transcoder_is_dsi(enum transcoder transcoder)
+{
+       return transcoder == TRANSCODER_DSI_A || transcoder == TRANSCODER_DSI_C;
+}
 
 /*
  * I915_MAX_PLANES in the enum below is the maximum (across all platforms)
@@ -176,6 +207,8 @@ enum intel_display_power_domain {
        POWER_DOMAIN_TRANSCODER_B,
        POWER_DOMAIN_TRANSCODER_C,
        POWER_DOMAIN_TRANSCODER_EDP,
+       POWER_DOMAIN_TRANSCODER_DSI_A,
+       POWER_DOMAIN_TRANSCODER_DSI_C,
        POWER_DOMAIN_PORT_DDI_A_LANES,
        POWER_DOMAIN_PORT_DDI_B_LANES,
        POWER_DOMAIN_PORT_DDI_C_LANES,
@@ -273,6 +306,10 @@ struct i915_hotplug {
             (__s) < INTEL_INFO(__dev_priv)->num_sprites[(__p)];        \
             (__s)++)
 
+#define for_each_port_masked(__port, __ports_mask) \
+       for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++)  \
+               for_each_if ((__ports_mask) & (1 << (__port)))
+
 #define for_each_crtc(dev, crtc) \
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 
@@ -340,81 +377,6 @@ struct drm_i915_file_private {
        unsigned int bsd_ring;
 };
 
-enum intel_dpll_id {
-       DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
-       /* real shared dpll ids must be >= 0 */
-       DPLL_ID_PCH_PLL_A = 0,
-       DPLL_ID_PCH_PLL_B = 1,
-       /* hsw/bdw */
-       DPLL_ID_WRPLL1 = 0,
-       DPLL_ID_WRPLL2 = 1,
-       DPLL_ID_SPLL = 2,
-
-       /* skl */
-       DPLL_ID_SKL_DPLL1 = 0,
-       DPLL_ID_SKL_DPLL2 = 1,
-       DPLL_ID_SKL_DPLL3 = 2,
-};
-#define I915_NUM_PLLS 3
-
-struct intel_dpll_hw_state {
-       /* i9xx, pch plls */
-       uint32_t dpll;
-       uint32_t dpll_md;
-       uint32_t fp0;
-       uint32_t fp1;
-
-       /* hsw, bdw */
-       uint32_t wrpll;
-       uint32_t spll;
-
-       /* skl */
-       /*
-        * DPLL_CTRL1 has 6 bits for each each this DPLL. We store those in
-        * lower part of ctrl1 and they get shifted into position when writing
-        * the register.  This allows us to easily compare the state to share
-        * the DPLL.
-        */
-       uint32_t ctrl1;
-       /* HDMI only, 0 when used for DP */
-       uint32_t cfgcr1, cfgcr2;
-
-       /* bxt */
-       uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
-                pcsdw12;
-};
-
-struct intel_shared_dpll_config {
-       unsigned crtc_mask; /* mask of CRTCs sharing this PLL */
-       struct intel_dpll_hw_state hw_state;
-};
-
-struct intel_shared_dpll {
-       struct intel_shared_dpll_config config;
-
-       int active; /* count of number of active CRTCs (i.e. DPMS on) */
-       bool on; /* is the PLL actually active? Disabled during modeset */
-       const char *name;
-       /* should match the index in the dev_priv->shared_dplls array */
-       enum intel_dpll_id id;
-       /* The mode_set hook is optional and should be used together with the
-        * intel_prepare_shared_dpll function. */
-       void (*mode_set)(struct drm_i915_private *dev_priv,
-                        struct intel_shared_dpll *pll);
-       void (*enable)(struct drm_i915_private *dev_priv,
-                      struct intel_shared_dpll *pll);
-       void (*disable)(struct drm_i915_private *dev_priv,
-                       struct intel_shared_dpll *pll);
-       bool (*get_hw_state)(struct drm_i915_private *dev_priv,
-                            struct intel_shared_dpll *pll,
-                            struct intel_dpll_hw_state *hw_state);
-};
-
-#define SKL_DPLL0 0
-#define SKL_DPLL1 1
-#define SKL_DPLL2 2
-#define SKL_DPLL3 3
-
 /* Used by dp and fdi links */
 struct intel_link_m_n {
        uint32_t        tu;
@@ -533,7 +495,7 @@ struct drm_i915_error_state {
                u32 cpu_ring_head;
                u32 cpu_ring_tail;
 
-               u32 semaphore_seqno[I915_NUM_RINGS - 1];
+               u32 semaphore_seqno[I915_NUM_ENGINES - 1];
 
                /* Register state */
                u32 start;
@@ -553,7 +515,7 @@ struct drm_i915_error_state {
                u32 fault_reg;
                u64 faddr;
                u32 rc_psmi; /* sleep state */
-               u32 semaphore_mboxes[I915_NUM_RINGS - 1];
+               u32 semaphore_mboxes[I915_NUM_ENGINES - 1];
 
                struct drm_i915_error_object {
                        int page_count;
@@ -561,6 +523,8 @@ struct drm_i915_error_state {
                        u32 *pages[0];
                } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
 
+               struct drm_i915_error_object *wa_ctx;
+
                struct drm_i915_error_request {
                        long jiffies;
                        u32 seqno;
@@ -577,12 +541,12 @@ struct drm_i915_error_state {
 
                pid_t pid;
                char comm[TASK_COMM_LEN];
-       } ring[I915_NUM_RINGS];
+       } ring[I915_NUM_ENGINES];
 
        struct drm_i915_error_buffer {
                u32 size;
                u32 name;
-               u32 rseqno[I915_NUM_RINGS], wseqno;
+               u32 rseqno[I915_NUM_ENGINES], wseqno;
                u64 gtt_offset;
                u32 read_domains;
                u32 write_domain;
@@ -611,27 +575,12 @@ struct dpll;
 struct drm_i915_display_funcs {
        int (*get_display_clock_speed)(struct drm_device *dev);
        int (*get_fifo_size)(struct drm_device *dev, int plane);
-       /**
-        * find_dpll() - Find the best values for the PLL
-        * @limit: limits for the PLL
-        * @crtc: current CRTC
-        * @target: target frequency in kHz
-        * @refclk: reference clock frequency in kHz
-        * @match_clock: if provided, @best_clock P divider must
-        *               match the P divider from @match_clock
-        *               used for LVDS downclocking
-        * @best_clock: best PLL values found
-        *
-        * Returns true on success, false on failure.
-        */
-       bool (*find_dpll)(const struct intel_limit *limit,
-                         struct intel_crtc_state *crtc_state,
-                         int target, int refclk,
-                         struct dpll *match_clock,
-                         struct dpll *best_clock);
-       int (*compute_pipe_wm)(struct intel_crtc *crtc,
-                              struct drm_atomic_state *state);
-       void (*program_watermarks)(struct intel_crtc_state *cstate);
+       int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
+       int (*compute_intermediate_wm)(struct drm_device *dev,
+                                      struct intel_crtc *intel_crtc,
+                                      struct intel_crtc_state *newstate);
+       void (*initial_watermarks)(struct intel_crtc_state *cstate);
+       void (*optimize_watermarks)(struct intel_crtc_state *cstate);
        void (*update_wm)(struct drm_crtc *crtc);
        int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
        void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
@@ -662,6 +611,9 @@ struct drm_i915_display_funcs {
        /* render clock increase/decrease */
        /* display clock increase/decrease */
        /* pll clock increase/decrease */
+
+       void (*load_csc_matrix)(struct drm_crtc *crtc);
+       void (*load_luts)(struct drm_crtc *crtc);
 };
 
 enum forcewake_domain_id {
@@ -750,6 +702,7 @@ struct intel_csr {
        i915_reg_t mmioaddr[8];
        uint32_t mmiodata[8];
        uint32_t dc_state;
+       uint32_t allowed_dc_mask;
 };
 
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
@@ -779,6 +732,7 @@ struct intel_csr {
        func(overlay_needs_physical) sep \
        func(supports_tv) sep \
        func(has_llc) sep \
+       func(has_snoop) sep \
        func(has_ddi) sep \
        func(has_fpga_dbg)
 
@@ -810,6 +764,11 @@ struct intel_device_info {
        u8 has_slice_pg:1;
        u8 has_subslice_pg:1;
        u8 has_eu_pg:1;
+
+       struct color_luts {
+               u16 degamma_lut_size;
+               u16 gamma_lut_size;
+       } color;
 };
 
 #undef DEFINE_FLAG
@@ -891,7 +850,7 @@ struct intel_context {
                struct i915_vma *lrc_vma;
                u64 lrc_desc;
                uint32_t *lrc_reg_state;
-       } engine[I915_NUM_RINGS];
+       } engine[I915_NUM_ENGINES];
 
        struct list_head link;
 };
@@ -1482,21 +1441,22 @@ struct intel_vbt_data {
        unsigned int lvds_use_ssc:1;
        unsigned int display_clock_mode:1;
        unsigned int fdi_rx_polarity_inverted:1;
-       unsigned int has_mipi:1;
        int lvds_ssc_freq;
        unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
 
        enum drrs_support_type drrs_type;
 
-       /* eDP */
-       int edp_rate;
-       int edp_lanes;
-       int edp_preemphasis;
-       int edp_vswing;
-       bool edp_initialized;
-       bool edp_support;
-       int edp_bpp;
-       struct edp_power_seq edp_pps;
+       struct {
+               int rate;
+               int lanes;
+               int preemphasis;
+               int vswing;
+               bool low_vswing;
+               bool initialized;
+               bool support;
+               int bpp;
+               struct edp_power_seq pps;
+       } edp;
 
        struct {
                bool full_link;
@@ -1516,7 +1476,6 @@ struct intel_vbt_data {
 
        /* MIPI DSI */
        struct {
-               u16 port;
                u16 panel_id;
                struct mipi_config *config;
                struct mipi_pps_data *pps;
@@ -1532,6 +1491,7 @@ struct intel_vbt_data {
        union child_device_config *child_dev;
 
        struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS];
+       struct sdvo_device_mapping sdvo_mappings[2];
 };
 
 enum intel_ddb_partitioning {
@@ -1706,7 +1666,7 @@ struct i915_wa_reg {
 struct i915_workarounds {
        struct i915_wa_reg reg[I915_MAX_WA_REGS];
        u32 count;
-       u32 hw_whitelist_count[I915_NUM_RINGS];
+       u32 hw_whitelist_count[I915_NUM_ENGINES];
 };
 
 struct i915_virtual_gpu {
@@ -1719,7 +1679,7 @@ struct i915_execbuffer_params {
        uint32_t                        dispatch_flags;
        uint32_t                        args_batch_start_offset;
        uint64_t                        batch_obj_vm_offset;
-       struct intel_engine_cs          *ring;
+       struct intel_engine_cs *engine;
        struct drm_i915_gem_object      *batch_obj;
        struct intel_context            *ctx;
        struct drm_i915_gem_request     *request;
@@ -1771,7 +1731,7 @@ struct drm_i915_private {
        wait_queue_head_t gmbus_wait_queue;
 
        struct pci_dev *bridge_dev;
-       struct intel_engine_cs ring[I915_NUM_RINGS];
+       struct intel_engine_cs engine[I915_NUM_ENGINES];
        struct drm_i915_gem_object *semaphore_obj;
        uint32_t last_seqno, next_seqno;
 
@@ -1829,6 +1789,7 @@ struct drm_i915_private {
        unsigned int skl_boot_cdclk;
        unsigned int cdclk_freq, max_cdclk_freq, atomic_cdclk_freq;
        unsigned int max_dotclk_freq;
+       unsigned int rawclk_freq;
        unsigned int hpll_freq;
        unsigned int czclk_freq;
 
@@ -1855,7 +1816,7 @@ struct drm_i915_private {
        struct drm_atomic_state *modeset_restore_state;
 
        struct list_head vm_list; /* Global list of all address spaces */
-       struct i915_gtt gtt; /* VM representing the global address space */
+       struct i915_ggtt ggtt; /* VM representing the global address space */
 
        struct i915_gem_mm mm;
        DECLARE_HASHTABLE(mm_structs, 7);
@@ -1863,8 +1824,6 @@ struct drm_i915_private {
 
        /* Kernel Modesetting */
 
-       struct sdvo_device_mapping sdvo_mappings[2];
-
        struct drm_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
        struct drm_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
        wait_queue_head_t pending_flip_queue;
@@ -1876,6 +1835,7 @@ struct drm_i915_private {
        /* dpll and cdclk state is protected by connection_mutex */
        int num_shared_dpll;
        struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
+       const struct intel_dpll_mgr *dpll_mgr;
 
        unsigned int active_crtcs;
        unsigned int min_pixclk[I915_MAX_PIPES];
@@ -1884,9 +1844,6 @@ struct drm_i915_private {
 
        struct i915_workarounds workarounds;
 
-       /* Reclocking support */
-       bool render_reclock_avail;
-
        struct i915_frontbuffer_tracking fb_tracking;
 
        u16 orig_clock;
@@ -1980,6 +1937,13 @@ struct drm_i915_private {
                };
 
                uint8_t max_level;
+
+               /*
+                * Should be held around atomic WM register writing; also
+                * protects * intel_crtc->wm.active and
+                * cstate->wm.need_postvbl_update.
+                */
+               struct mutex wm_mutex;
        } wm;
 
        struct i915_runtime_pm pm;
@@ -1989,15 +1953,13 @@ struct drm_i915_private {
                int (*execbuf_submit)(struct i915_execbuffer_params *params,
                                      struct drm_i915_gem_execbuffer2 *args,
                                      struct list_head *vmas);
-               int (*init_rings)(struct drm_device *dev);
-               void (*cleanup_ring)(struct intel_engine_cs *ring);
-               void (*stop_ring)(struct intel_engine_cs *ring);
+               int (*init_engines)(struct drm_device *dev);
+               void (*cleanup_engine)(struct intel_engine_cs *engine);
+               void (*stop_engine)(struct intel_engine_cs *engine);
        } gt;
 
        struct intel_context *kernel_context;
 
-       bool edp_low_vswing;
-
        /* perform PHY state sanity checks? */
        bool chv_phy_assert[2];
 
@@ -2024,10 +1986,28 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
        return container_of(guc, struct drm_i915_private, guc);
 }
 
-/* Iterate over initialised rings */
-#define for_each_ring(ring__, dev_priv__, i__) \
-       for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
-               for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
+/* Simple iterator over all initialised engines */
+#define for_each_engine(engine__, dev_priv__) \
+       for ((engine__) = &(dev_priv__)->engine[0]; \
+            (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
+            (engine__)++) \
+               for_each_if (intel_engine_initialized(engine__))
+
+/* Iterator with engine_id */
+#define for_each_engine_id(engine__, dev_priv__, id__) \
+       for ((engine__) = &(dev_priv__)->engine[0], (id__) = 0; \
+            (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
+            (engine__)++) \
+               for_each_if (((id__) = (engine__)->id, \
+                             intel_engine_initialized(engine__)))
+
+/* Iterator over subset of engines selected by mask */
+#define for_each_engine_masked(engine__, dev_priv__, mask__) \
+       for ((engine__) = &(dev_priv__)->engine[0]; \
+            (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
+            (engine__)++) \
+               for_each_if (((mask__) & intel_engine_flag(engine__)) && \
+                            intel_engine_initialized(engine__))
 
 enum hdmi_force_audio {
        HDMI_AUDIO_OFF_DVI = -2,        /* no aux data for HDMI-DVI converter */
@@ -2097,7 +2077,7 @@ struct drm_i915_gem_object {
        struct drm_mm_node *stolen;
        struct list_head global_list;
 
-       struct list_head ring_list[I915_NUM_RINGS];
+       struct list_head engine_list[I915_NUM_ENGINES];
        /** Used in execbuf to temporarily hold a ref */
        struct list_head obj_exec_link;
 
@@ -2108,7 +2088,7 @@ struct drm_i915_gem_object {
         * rendering and so a non-zero seqno), and is not set if it i s on
         * inactive (ready to be unbound) list.
         */
-       unsigned int active:I915_NUM_RINGS;
+       unsigned int active:I915_NUM_ENGINES;
 
        /**
         * This is set if the object has been written to since last bound
@@ -2187,7 +2167,7 @@ struct drm_i915_gem_object {
         * read request. This allows for the CPU to read from an active
         * buffer by only waiting for the write to complete.
         * */
-       struct drm_i915_gem_request *last_read_req[I915_NUM_RINGS];
+       struct drm_i915_gem_request *last_read_req[I915_NUM_ENGINES];
        struct drm_i915_gem_request *last_write_req;
        /** Breadcrumb of last fenced GPU access to the buffer. */
        struct drm_i915_gem_request *last_fenced_req;
@@ -2242,7 +2222,7 @@ struct drm_i915_gem_request {
 
        /** On Which ring this request was generated */
        struct drm_i915_private *i915;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
 
         /** GEM sequence number associated with the previous request,
          * when the HWS breadcrumb is equal to this the GPU is processing
@@ -2335,9 +2315,9 @@ i915_gem_request_get_seqno(struct drm_i915_gem_request *req)
 }
 
 static inline struct intel_engine_cs *
-i915_gem_request_get_ring(struct drm_i915_gem_request *req)
+i915_gem_request_get_engine(struct drm_i915_gem_request *req)
 {
-       return req ? req->ring : NULL;
+       return req ? req->engine : NULL;
 }
 
 static inline struct drm_i915_gem_request *
@@ -2351,7 +2331,7 @@ i915_gem_request_reference(struct drm_i915_gem_request *req)
 static inline void
 i915_gem_request_unreference(struct drm_i915_gem_request *req)
 {
-       WARN_ON(!mutex_is_locked(&req->ring->dev->struct_mutex));
+       WARN_ON(!mutex_is_locked(&req->engine->dev->struct_mutex));
        kref_put(&req->ref, i915_gem_request_free);
 }
 
@@ -2363,7 +2343,7 @@ i915_gem_request_unreference__unlocked(struct drm_i915_gem_request *req)
        if (!req)
                return;
 
-       dev = req->ring->dev;
+       dev = req->engine->dev;
        if (kref_put_mutex(&req->ref, i915_gem_request_free, &dev->struct_mutex))
                mutex_unlock(&dev->struct_mutex);
 }
@@ -2611,11 +2591,14 @@ struct drm_i915_cmd_table {
 #define BLT_RING               (1<<BCS)
 #define VEBOX_RING             (1<<VECS)
 #define BSD2_RING              (1<<VCS2)
+#define ALL_ENGINES            (~0)
+
 #define HAS_BSD(dev)           (INTEL_INFO(dev)->ring_mask & BSD_RING)
 #define HAS_BSD2(dev)          (INTEL_INFO(dev)->ring_mask & BSD2_RING)
 #define HAS_BLT(dev)           (INTEL_INFO(dev)->ring_mask & BLT_RING)
 #define HAS_VEBOX(dev)         (INTEL_INFO(dev)->ring_mask & VEBOX_RING)
 #define HAS_LLC(dev)           (INTEL_INFO(dev)->has_llc)
+#define HAS_SNOOP(dev)         (INTEL_INFO(dev)->has_snoop)
 #define HAS_WT(dev)            ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \
                                 __I915__(dev)->ellc_size)
 #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
@@ -2695,6 +2678,7 @@ struct drm_i915_cmd_table {
 #define INTEL_PCH_SPT_DEVICE_ID_TYPE           0xA100
 #define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE                0x9D00
 #define INTEL_PCH_P2X_DEVICE_ID_TYPE           0x7100
+#define INTEL_PCH_P3X_DEVICE_ID_TYPE           0x7000
 #define INTEL_PCH_QEMU_DEVICE_ID_TYPE          0x2900 /* qemu q35 has 2918 */
 
 #define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type)
@@ -2726,6 +2710,13 @@ extern int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state);
 extern int i915_resume_switcheroo(struct drm_device *dev);
 
 /* i915_dma.c */
+void __printf(3, 4)
+__i915_printk(struct drm_i915_private *dev_priv, const char *level,
+             const char *fmt, ...);
+
+#define i915_report_error(dev_priv, fmt, ...)                             \
+       __i915_printk(dev_priv, KERN_ERR, fmt, ##__VA_ARGS__)
+
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
 extern int i915_driver_unload(struct drm_device *);
 extern int i915_driver_open(struct drm_device *dev, struct drm_file *file);
@@ -2738,9 +2729,10 @@ extern void i915_driver_postclose(struct drm_device *dev,
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
 #endif
-extern int intel_gpu_reset(struct drm_device *dev);
+extern int intel_gpu_reset(struct drm_device *dev, u32 engine_mask);
 extern bool intel_has_gpu_reset(struct drm_device *dev);
 extern int i915_reset(struct drm_device *dev);
+extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
 extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
@@ -2757,7 +2749,7 @@ bool intel_hpd_pin_to_port(enum hpd_pin pin, enum port *port);
 /* i915_irq.c */
 void i915_queue_hangcheck(struct drm_device *dev);
 __printf(3, 4)
-void i915_handle_error(struct drm_device *dev, bool wedged,
+void i915_handle_error(struct drm_device *dev, u32 engine_mask,
                       const char *fmt, ...);
 
 extern void intel_irq_init(struct drm_i915_private *dev_priv);
@@ -2893,6 +2885,7 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
 void i915_gem_load_init(struct drm_device *dev);
 void i915_gem_load_cleanup(struct drm_device *dev);
+void i915_gem_load_init_fences(struct drm_i915_private *dev_priv);
 void *i915_gem_object_alloc(struct drm_device *dev);
 void i915_gem_object_free(struct drm_i915_gem_object *obj);
 void i915_gem_object_init(struct drm_i915_gem_object *obj,
@@ -3006,14 +2999,14 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
 static inline bool i915_gem_request_started(struct drm_i915_gem_request *req,
                                           bool lazy_coherency)
 {
-       u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
+       u32 seqno = req->engine->get_seqno(req->engine, lazy_coherency);
        return i915_seqno_passed(seqno, req->previous_seqno);
 }
 
 static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
                                              bool lazy_coherency)
 {
-       u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
+       u32 seqno = req->engine->get_seqno(req->engine, lazy_coherency);
        return i915_seqno_passed(seqno, req->seqno);
 }
 
@@ -3021,10 +3014,10 @@ int __must_check i915_gem_get_seqno(struct drm_device *dev, u32 *seqno);
 int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno);
 
 struct drm_i915_gem_request *
-i915_gem_find_active_request(struct intel_engine_cs *ring);
+i915_gem_find_active_request(struct intel_engine_cs *engine);
 
 bool i915_gem_retire_requests(struct drm_device *dev);
-void i915_gem_retire_requests_ring(struct intel_engine_cs *ring);
+void i915_gem_retire_requests_ring(struct intel_engine_cs *engine);
 int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
                                      bool interruptible);
 
@@ -3059,11 +3052,11 @@ static inline bool i915_stop_ring_allow_warn(struct drm_i915_private *dev_priv)
 void i915_gem_reset(struct drm_device *dev);
 bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
 int __must_check i915_gem_init(struct drm_device *dev);
-int i915_gem_init_rings(struct drm_device *dev);
+int i915_gem_init_engines(struct drm_device *dev);
 int __must_check i915_gem_init_hw(struct drm_device *dev);
 int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice);
 void i915_gem_init_swizzling(struct drm_device *dev);
-void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
+void i915_gem_cleanup_engines(struct drm_device *dev);
 int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_suspend(struct drm_device *dev);
 void __i915_add_request(struct drm_i915_gem_request *req,
@@ -3155,7 +3148,7 @@ bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj);
 
 /* Some GGTT VM helpers */
 #define i915_obj_to_ggtt(obj) \
-       (&((struct drm_i915_private *)(obj)->base.dev->dev_private)->gtt.base)
+       (&((struct drm_i915_private *)(obj)->base.dev->dev_private)->ggtt.base)
 
 static inline struct i915_hw_ppgtt *
 i915_vm_to_ppgtt(struct i915_address_space *vm)
@@ -3342,7 +3335,7 @@ static inline void i915_error_state_buf_release(
 {
        kfree(eb->buf);
 }
-void i915_capture_error_state(struct drm_device *dev, bool wedge,
+void i915_capture_error_state(struct drm_device *dev, u32 engine_mask,
                              const char *error_msg);
 void i915_error_state_get(struct drm_device *dev,
                          struct i915_error_state_file_priv *error_priv);
@@ -3354,10 +3347,10 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type);
 
 /* i915_cmd_parser.c */
 int i915_cmd_parser_get_version(void);
-int i915_cmd_parser_init_ring(struct intel_engine_cs *ring);
-void i915_cmd_parser_fini_ring(struct intel_engine_cs *ring);
-bool i915_needs_cmd_parser(struct intel_engine_cs *ring);
-int i915_parse_cmds(struct intel_engine_cs *ring,
+int i915_cmd_parser_init_ring(struct intel_engine_cs *engine);
+void i915_cmd_parser_fini_ring(struct intel_engine_cs *engine);
+bool i915_needs_cmd_parser(struct intel_engine_cs *engine);
+int i915_parse_cmds(struct intel_engine_cs *engine,
                    struct drm_i915_gem_object *batch_obj,
                    struct drm_i915_gem_object *shadow_batch_obj,
                    u32 batch_start_offset,
@@ -3391,6 +3384,10 @@ extern void intel_i2c_reset(struct drm_device *dev);
 /* intel_bios.c */
 int intel_bios_init(struct drm_i915_private *dev_priv);
 bool intel_bios_is_valid_vbt(const void *buf, size_t size);
+bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
+bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
+bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
+bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
 
 /* intel_opregion.c */
 #ifdef CONFIG_ACPI
@@ -3628,11 +3625,11 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms)
        }
 }
 
-static inline void i915_trace_irq_get(struct intel_engine_cs *ring,
+static inline void i915_trace_irq_get(struct intel_engine_cs *engine,
                                      struct drm_i915_gem_request *req)
 {
-       if (ring->trace_irq_req == NULL && ring->irq_get(ring))
-               i915_gem_request_assign(&ring->trace_irq_req, req);
+       if (engine->trace_irq_req == NULL && engine->irq_get(engine))
+               i915_gem_request_assign(&engine->trace_irq_req, req);
 }
 
 #endif
index 3d31d3a..c7a997a 100644 (file)
@@ -132,7 +132,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_get_aperture *args = data;
-       struct i915_gtt *ggtt = &dev_priv->gtt;
+       struct i915_ggtt *ggtt = &dev_priv->ggtt;
        struct i915_vma *vma;
        size_t pinned;
 
@@ -146,7 +146,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
                        pinned += vma->node.size;
        mutex_unlock(&dev->struct_mutex);
 
-       args->aper_size = dev_priv->gtt.base.total;
+       args->aper_size = dev_priv->ggtt.base.total;
        args->aper_available_size = args->aper_size - pinned;
 
        return 0;
@@ -807,7 +807,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
                 * source page isn't available.  Return the error and we'll
                 * retry in the slow path.
                 */
-               if (fast_user_write(dev_priv->gtt.mappable, page_base,
+               if (fast_user_write(dev_priv->ggtt.mappable, page_base,
                                    page_offset, user_data, page_length)) {
                        ret = -EFAULT;
                        goto out_flush;
@@ -1141,9 +1141,9 @@ static void fake_irq(unsigned long data)
 }
 
 static bool missed_irq(struct drm_i915_private *dev_priv,
-                      struct intel_engine_cs *ring)
+                      struct intel_engine_cs *engine)
 {
-       return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
+       return test_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings);
 }
 
 static unsigned long local_clock_us(unsigned *cpu)
@@ -1193,7 +1193,7 @@ static int __i915_spin_request(struct drm_i915_gem_request *req, int state)
         * takes to sleep on a request, on the order of a microsecond.
         */
 
-       if (req->ring->irq_refcount)
+       if (req->engine->irq_refcount)
                return -EBUSY;
 
        /* Only spin if we know the GPU is processing this request */
@@ -1243,11 +1243,11 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
                        s64 *timeout,
                        struct intel_rps_client *rps)
 {
-       struct intel_engine_cs *ring = i915_gem_request_get_ring(req);
-       struct drm_device *dev = ring->dev;
+       struct intel_engine_cs *engine = i915_gem_request_get_engine(req);
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        const bool irq_test_in_progress =
-               ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
+               ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_engine_flag(engine);
        int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
        DEFINE_WAIT(wait);
        unsigned long timeout_expire;
@@ -1288,7 +1288,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
        if (ret == 0)
                goto out;
 
-       if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) {
+       if (!irq_test_in_progress && WARN_ON(!engine->irq_get(engine))) {
                ret = -ENODEV;
                goto out;
        }
@@ -1296,7 +1296,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
        for (;;) {
                struct timer_list timer;
 
-               prepare_to_wait(&ring->irq_queue, &wait, state);
+               prepare_to_wait(&engine->irq_queue, &wait, state);
 
                /* We need to check whether any gpu reset happened in between
                 * the caller grabbing the seqno and now ... */
@@ -1325,11 +1325,11 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
                }
 
                timer.function = NULL;
-               if (timeout || missed_irq(dev_priv, ring)) {
+               if (timeout || missed_irq(dev_priv, engine)) {
                        unsigned long expire;
 
                        setup_timer_on_stack(&timer, fake_irq, (unsigned long)current);
-                       expire = missed_irq(dev_priv, ring) ? jiffies + 1 : timeout_expire;
+                       expire = missed_irq(dev_priv, engine) ? jiffies + 1 : timeout_expire;
                        mod_timer(&timer, expire);
                }
 
@@ -1341,9 +1341,9 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
                }
        }
        if (!irq_test_in_progress)
-               ring->irq_put(ring);
+               engine->irq_put(engine);
 
-       finish_wait(&ring->irq_queue, &wait);
+       finish_wait(&engine->irq_queue, &wait);
 
 out:
        trace_i915_gem_request_wait_end(req);
@@ -1370,7 +1370,6 @@ out:
 int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
                                   struct drm_file *file)
 {
-       struct drm_i915_private *dev_private;
        struct drm_i915_file_private *file_priv;
 
        WARN_ON(!req || !file || req->file_priv);
@@ -1381,7 +1380,6 @@ int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
        if (req->file_priv)
                return -EINVAL;
 
-       dev_private = req->ring->dev->dev_private;
        file_priv = file->driver_priv;
 
        spin_lock(&file_priv->mm.lock);
@@ -1434,7 +1432,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
 static void
 __i915_gem_request_retire__upto(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *engine = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct drm_i915_gem_request *tmp;
 
        lockdep_assert_held(&engine->dev->struct_mutex);
@@ -1466,7 +1464,7 @@ i915_wait_request(struct drm_i915_gem_request *req)
 
        BUG_ON(req == NULL);
 
-       dev = req->ring->dev;
+       dev = req->engine->dev;
        dev_priv = dev->dev_private;
        interruptible = dev_priv->mm.interruptible;
 
@@ -1505,14 +1503,14 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
                        if (ret)
                                return ret;
 
-                       i = obj->last_write_req->ring->id;
+                       i = obj->last_write_req->engine->id;
                        if (obj->last_read_req[i] == obj->last_write_req)
                                i915_gem_object_retire__read(obj, i);
                        else
                                i915_gem_object_retire__write(obj);
                }
        } else {
-               for (i = 0; i < I915_NUM_RINGS; i++) {
+               for (i = 0; i < I915_NUM_ENGINES; i++) {
                        if (obj->last_read_req[i] == NULL)
                                continue;
 
@@ -1532,7 +1530,7 @@ static void
 i915_gem_object_retire_request(struct drm_i915_gem_object *obj,
                               struct drm_i915_gem_request *req)
 {
-       int ring = req->ring->id;
+       int ring = req->engine->id;
 
        if (obj->last_read_req[ring] == req)
                i915_gem_object_retire__read(obj, ring);
@@ -1552,7 +1550,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
 {
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_i915_gem_request *requests[I915_NUM_RINGS];
+       struct drm_i915_gem_request *requests[I915_NUM_ENGINES];
        unsigned reset_counter;
        int ret, i, n = 0;
 
@@ -1577,7 +1575,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
 
                requests[n++] = i915_gem_request_reference(req);
        } else {
-               for (i = 0; i < I915_NUM_RINGS; i++) {
+               for (i = 0; i < I915_NUM_ENGINES; i++) {
                        struct drm_i915_gem_request *req;
 
                        req = obj->last_read_req[i];
@@ -1827,7 +1825,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        }
 
        /* Use a partial view if the object is bigger than the aperture. */
-       if (obj->base.size >= dev_priv->gtt.mappable_end &&
+       if (obj->base.size >= dev_priv->ggtt.mappable_end &&
            obj->tiling_mode == I915_TILING_NONE) {
                static const unsigned int chunk_size = 256; // 1 MiB
 
@@ -1855,7 +1853,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                goto unpin;
 
        /* Finally, remap it using the new GTT offset */
-       pfn = dev_priv->gtt.mappable_base +
+       pfn = dev_priv->ggtt.mappable_base +
                i915_gem_obj_ggtt_offset_view(obj, &view);
        pfn >>= PAGE_SHIFT;
 
@@ -2404,17 +2402,17 @@ void i915_vma_move_to_active(struct i915_vma *vma,
                             struct drm_i915_gem_request *req)
 {
        struct drm_i915_gem_object *obj = vma->obj;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
 
-       ring = i915_gem_request_get_ring(req);
+       engine = i915_gem_request_get_engine(req);
 
        /* Add a reference if we're newly entering the active list. */
        if (obj->active == 0)
                drm_gem_object_reference(&obj->base);
-       obj->active |= intel_ring_flag(ring);
+       obj->active |= intel_engine_flag(engine);
 
-       list_move_tail(&obj->ring_list[ring->id], &ring->active_list);
-       i915_gem_request_assign(&obj->last_read_req[ring->id], req);
+       list_move_tail(&obj->engine_list[engine->id], &engine->active_list);
+       i915_gem_request_assign(&obj->last_read_req[engine->id], req);
 
        list_move_tail(&vma->vm_link, &vma->vm->active_list);
 }
@@ -2423,7 +2421,7 @@ static void
 i915_gem_object_retire__write(struct drm_i915_gem_object *obj)
 {
        RQ_BUG_ON(obj->last_write_req == NULL);
-       RQ_BUG_ON(!(obj->active & intel_ring_flag(obj->last_write_req->ring)));
+       RQ_BUG_ON(!(obj->active & intel_engine_flag(obj->last_write_req->engine)));
 
        i915_gem_request_assign(&obj->last_write_req, NULL);
        intel_fb_obj_flush(obj, true, ORIGIN_CS);
@@ -2437,10 +2435,10 @@ i915_gem_object_retire__read(struct drm_i915_gem_object *obj, int ring)
        RQ_BUG_ON(obj->last_read_req[ring] == NULL);
        RQ_BUG_ON(!(obj->active & (1 << ring)));
 
-       list_del_init(&obj->ring_list[ring]);
+       list_del_init(&obj->engine_list[ring]);
        i915_gem_request_assign(&obj->last_read_req[ring], NULL);
 
-       if (obj->last_write_req && obj->last_write_req->ring->id == ring)
+       if (obj->last_write_req && obj->last_write_req->engine->id == ring)
                i915_gem_object_retire__write(obj);
 
        obj->active &= ~(1 << ring);
@@ -2467,23 +2465,23 @@ static int
 i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int ret, i, j;
+       struct intel_engine_cs *engine;
+       int ret, j;
 
        /* Carefully retire all requests without writing to the rings */
-       for_each_ring(ring, dev_priv, i) {
-               ret = intel_ring_idle(ring);
+       for_each_engine(engine, dev_priv) {
+               ret = intel_engine_idle(engine);
                if (ret)
                        return ret;
        }
        i915_gem_retire_requests(dev);
 
        /* Finally reset hw state */
-       for_each_ring(ring, dev_priv, i) {
-               intel_ring_init_seqno(ring, seqno);
+       for_each_engine(engine, dev_priv) {
+               intel_ring_init_seqno(engine, seqno);
 
-               for (j = 0; j < ARRAY_SIZE(ring->semaphore.sync_seqno); j++)
-                       ring->semaphore.sync_seqno[j] = 0;
+               for (j = 0; j < ARRAY_SIZE(engine->semaphore.sync_seqno); j++)
+                       engine->semaphore.sync_seqno[j] = 0;
        }
 
        return 0;
@@ -2542,7 +2540,7 @@ void __i915_add_request(struct drm_i915_gem_request *request,
                        struct drm_i915_gem_object *obj,
                        bool flush_caches)
 {
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct drm_i915_private *dev_priv;
        struct intel_ringbuffer *ringbuf;
        u32 request_start;
@@ -2551,8 +2549,8 @@ void __i915_add_request(struct drm_i915_gem_request *request,
        if (WARN_ON(request == NULL))
                return;
 
-       ring = request->ring;
-       dev_priv = ring->dev->dev_private;
+       engine = request->engine;
+       dev_priv = request->i915;
        ringbuf = request->ringbuf;
 
        /*
@@ -2587,9 +2585,9 @@ void __i915_add_request(struct drm_i915_gem_request *request,
        request->postfix = intel_ring_get_tail(ringbuf);
 
        if (i915.enable_execlists)
-               ret = ring->emit_request(request);
+               ret = engine->emit_request(request);
        else {
-               ret = ring->add_request(request);
+               ret = engine->add_request(request);
 
                request->tail = intel_ring_get_tail(ringbuf);
        }
@@ -2607,13 +2605,13 @@ void __i915_add_request(struct drm_i915_gem_request *request,
        request->batch_obj = obj;
 
        request->emitted_jiffies = jiffies;
-       request->previous_seqno = ring->last_submitted_seqno;
-       ring->last_submitted_seqno = request->seqno;
-       list_add_tail(&request->list, &ring->request_list);
+       request->previous_seqno = engine->last_submitted_seqno;
+       engine->last_submitted_seqno = request->seqno;
+       list_add_tail(&request->list, &engine->request_list);
 
        trace_i915_gem_request_add(request);
 
-       i915_queue_hangcheck(ring->dev);
+       i915_queue_hangcheck(engine->dev);
 
        queue_delayed_work(dev_priv->wq,
                           &dev_priv->mm.retire_work,
@@ -2680,7 +2678,7 @@ void i915_gem_request_free(struct kref *req_ref)
 
        if (ctx) {
                if (i915.enable_execlists && ctx != req->i915->kernel_context)
-                       intel_lr_context_unpin(ctx, req->ring);
+                       intel_lr_context_unpin(ctx, req->engine);
 
                i915_gem_context_unreference(ctx);
        }
@@ -2689,11 +2687,11 @@ void i915_gem_request_free(struct kref *req_ref)
 }
 
 static inline int
-__i915_gem_request_alloc(struct intel_engine_cs *ring,
+__i915_gem_request_alloc(struct intel_engine_cs *engine,
                         struct intel_context *ctx,
                         struct drm_i915_gem_request **req_out)
 {
-       struct drm_i915_private *dev_priv = to_i915(ring->dev);
+       struct drm_i915_private *dev_priv = to_i915(engine->dev);
        struct drm_i915_gem_request *req;
        int ret;
 
@@ -2706,13 +2704,13 @@ __i915_gem_request_alloc(struct intel_engine_cs *ring,
        if (req == NULL)
                return -ENOMEM;
 
-       ret = i915_gem_get_seqno(ring->dev, &req->seqno);
+       ret = i915_gem_get_seqno(engine->dev, &req->seqno);
        if (ret)
                goto err;
 
        kref_init(&req->ref);
        req->i915 = dev_priv;
-       req->ring = ring;
+       req->engine = engine;
        req->ctx  = ctx;
        i915_gem_context_reference(req->ctx);
 
@@ -2787,11 +2785,11 @@ void i915_gem_request_cancel(struct drm_i915_gem_request *req)
 }
 
 struct drm_i915_gem_request *
-i915_gem_find_active_request(struct intel_engine_cs *ring)
+i915_gem_find_active_request(struct intel_engine_cs *engine)
 {
        struct drm_i915_gem_request *request;
 
-       list_for_each_entry(request, &ring->request_list, list) {
+       list_for_each_entry(request, &engine->request_list, list) {
                if (i915_gem_request_completed(request, false))
                        continue;
 
@@ -2801,38 +2799,38 @@ i915_gem_find_active_request(struct intel_engine_cs *ring)
        return NULL;
 }
 
-static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
-                                      struct intel_engine_cs *ring)
+static void i915_gem_reset_engine_status(struct drm_i915_private *dev_priv,
+                                      struct intel_engine_cs *engine)
 {
        struct drm_i915_gem_request *request;
        bool ring_hung;
 
-       request = i915_gem_find_active_request(ring);
+       request = i915_gem_find_active_request(engine);
 
        if (request == NULL)
                return;
 
-       ring_hung = ring->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG;
+       ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG;
 
        i915_set_reset_status(dev_priv, request->ctx, ring_hung);
 
-       list_for_each_entry_continue(request, &ring->request_list, list)
+       list_for_each_entry_continue(request, &engine->request_list, list)
                i915_set_reset_status(dev_priv, request->ctx, false);
 }
 
-static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
-                                       struct intel_engine_cs *ring)
+static void i915_gem_reset_engine_cleanup(struct drm_i915_private *dev_priv,
+                                       struct intel_engine_cs *engine)
 {
        struct intel_ringbuffer *buffer;
 
-       while (!list_empty(&ring->active_list)) {
+       while (!list_empty(&engine->active_list)) {
                struct drm_i915_gem_object *obj;
 
-               obj = list_first_entry(&ring->active_list,
+               obj = list_first_entry(&engine->active_list,
                                       struct drm_i915_gem_object,
-                                      ring_list[ring->id]);
+                                      engine_list[engine->id]);
 
-               i915_gem_object_retire__read(obj, ring->id);
+               i915_gem_object_retire__read(obj, engine->id);
        }
 
        /*
@@ -2842,14 +2840,14 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
         */
 
        if (i915.enable_execlists) {
-               spin_lock_irq(&ring->execlist_lock);
+               spin_lock_irq(&engine->execlist_lock);
 
                /* list_splice_tail_init checks for empty lists */
-               list_splice_tail_init(&ring->execlist_queue,
-                                     &ring->execlist_retired_req_list);
+               list_splice_tail_init(&engine->execlist_queue,
+                                     &engine->execlist_retired_req_list);
 
-               spin_unlock_irq(&ring->execlist_lock);
-               intel_execlists_retire_requests(ring);
+               spin_unlock_irq(&engine->execlist_lock);
+               intel_execlists_retire_requests(engine);
        }
 
        /*
@@ -2859,10 +2857,10 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
         * implicit references on things like e.g. ppgtt address spaces through
         * the request.
         */
-       while (!list_empty(&ring->request_list)) {
+       while (!list_empty(&engine->request_list)) {
                struct drm_i915_gem_request *request;
 
-               request = list_first_entry(&ring->request_list,
+               request = list_first_entry(&engine->request_list,
                                           struct drm_i915_gem_request,
                                           list);
 
@@ -2876,7 +2874,7 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
         * upon reset is less than when we start. Do one more pass over
         * all the ringbuffers to reset last_retired_head.
         */
-       list_for_each_entry(buffer, &ring->buffers, link) {
+       list_for_each_entry(buffer, &engine->buffers, link) {
                buffer->last_retired_head = buffer->tail;
                intel_ring_update_space(buffer);
        }
@@ -2885,19 +2883,18 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
 void i915_gem_reset(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
        /*
         * Before we free the objects from the requests, we need to inspect
         * them for finding the guilty party. As the requests only borrow
         * their reference to the objects, the inspection must be done first.
         */
-       for_each_ring(ring, dev_priv, i)
-               i915_gem_reset_ring_status(dev_priv, ring);
+       for_each_engine(engine, dev_priv)
+               i915_gem_reset_engine_status(dev_priv, engine);
 
-       for_each_ring(ring, dev_priv, i)
-               i915_gem_reset_ring_cleanup(dev_priv, ring);
+       for_each_engine(engine, dev_priv)
+               i915_gem_reset_engine_cleanup(dev_priv, engine);
 
        i915_gem_context_reset(dev);
 
@@ -2910,19 +2907,19 @@ void i915_gem_reset(struct drm_device *dev)
  * This function clears the request list as sequence numbers are passed.
  */
 void
-i915_gem_retire_requests_ring(struct intel_engine_cs *ring)
+i915_gem_retire_requests_ring(struct intel_engine_cs *engine)
 {
-       WARN_ON(i915_verify_lists(ring->dev));
+       WARN_ON(i915_verify_lists(engine->dev));
 
        /* 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
         * confusion.
         */
-       while (!list_empty(&ring->request_list)) {
+       while (!list_empty(&engine->request_list)) {
                struct drm_i915_gem_request *request;
 
-               request = list_first_entry(&ring->request_list,
+               request = list_first_entry(&engine->request_list,
                                           struct drm_i915_gem_request,
                                           list);
 
@@ -2936,45 +2933,44 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring)
         * by the ringbuffer to the flushing/inactive lists as appropriate,
         * before we free the context associated with the requests.
         */
-       while (!list_empty(&ring->active_list)) {
+       while (!list_empty(&engine->active_list)) {
                struct drm_i915_gem_object *obj;
 
-               obj = list_first_entry(&ring->active_list,
-                                     struct drm_i915_gem_object,
-                                     ring_list[ring->id]);
+               obj = list_first_entry(&engine->active_list,
+                                      struct drm_i915_gem_object,
+                                      engine_list[engine->id]);
 
-               if (!list_empty(&obj->last_read_req[ring->id]->list))
+               if (!list_empty(&obj->last_read_req[engine->id]->list))
                        break;
 
-               i915_gem_object_retire__read(obj, ring->id);
+               i915_gem_object_retire__read(obj, engine->id);
        }
 
-       if (unlikely(ring->trace_irq_req &&
-                    i915_gem_request_completed(ring->trace_irq_req, true))) {
-               ring->irq_put(ring);
-               i915_gem_request_assign(&ring->trace_irq_req, NULL);
+       if (unlikely(engine->trace_irq_req &&
+                    i915_gem_request_completed(engine->trace_irq_req, true))) {
+               engine->irq_put(engine);
+               i915_gem_request_assign(&engine->trace_irq_req, NULL);
        }
 
-       WARN_ON(i915_verify_lists(ring->dev));
+       WARN_ON(i915_verify_lists(engine->dev));
 }
 
 bool
 i915_gem_retire_requests(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        bool idle = true;
-       int i;
 
-       for_each_ring(ring, dev_priv, i) {
-               i915_gem_retire_requests_ring(ring);
-               idle &= list_empty(&ring->request_list);
+       for_each_engine(engine, dev_priv) {
+               i915_gem_retire_requests_ring(engine);
+               idle &= list_empty(&engine->request_list);
                if (i915.enable_execlists) {
-                       spin_lock_irq(&ring->execlist_lock);
-                       idle &= list_empty(&ring->execlist_queue);
-                       spin_unlock_irq(&ring->execlist_lock);
+                       spin_lock_irq(&engine->execlist_lock);
+                       idle &= list_empty(&engine->execlist_queue);
+                       spin_unlock_irq(&engine->execlist_lock);
 
-                       intel_execlists_retire_requests(ring);
+                       intel_execlists_retire_requests(engine);
                }
        }
 
@@ -3011,25 +3007,21 @@ i915_gem_idle_work_handler(struct work_struct *work)
        struct drm_i915_private *dev_priv =
                container_of(work, typeof(*dev_priv), mm.idle_work.work);
        struct drm_device *dev = dev_priv->dev;
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
-       for_each_ring(ring, dev_priv, i)
-               if (!list_empty(&ring->request_list))
+       for_each_engine(engine, dev_priv)
+               if (!list_empty(&engine->request_list))
                        return;
 
        /* we probably should sync with hangcheck here, using cancel_work_sync.
-        * Also locking seems to be fubar here, ring->request_list is protected
+        * Also locking seems to be fubar here, engine->request_list is protected
         * by dev->struct_mutex. */
 
        intel_mark_idle(dev);
 
        if (mutex_trylock(&dev->struct_mutex)) {
-               struct intel_engine_cs *ring;
-               int i;
-
-               for_each_ring(ring, dev_priv, i)
-                       i915_gem_batch_pool_fini(&ring->batch_pool);
+               for_each_engine(engine, dev_priv)
+                       i915_gem_batch_pool_fini(&engine->batch_pool);
 
                mutex_unlock(&dev->struct_mutex);
        }
@@ -3048,7 +3040,7 @@ i915_gem_object_flush_active(struct drm_i915_gem_object *obj)
        if (!obj->active)
                return 0;
 
-       for (i = 0; i < I915_NUM_RINGS; i++) {
+       for (i = 0; i < I915_NUM_ENGINES; i++) {
                struct drm_i915_gem_request *req;
 
                req = obj->last_read_req[i];
@@ -3096,7 +3088,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_wait *args = data;
        struct drm_i915_gem_object *obj;
-       struct drm_i915_gem_request *req[I915_NUM_RINGS];
+       struct drm_i915_gem_request *req[I915_NUM_ENGINES];
        unsigned reset_counter;
        int i, n = 0;
        int ret;
@@ -3133,7 +3125,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
        drm_gem_object_unreference(&obj->base);
        reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 
-       for (i = 0; i < I915_NUM_RINGS; i++) {
+       for (i = 0; i < I915_NUM_ENGINES; i++) {
                if (obj->last_read_req[i] == NULL)
                        continue;
 
@@ -3166,7 +3158,7 @@ __i915_gem_object_sync(struct drm_i915_gem_object *obj,
        struct intel_engine_cs *from;
        int ret;
 
-       from = i915_gem_request_get_ring(from_req);
+       from = i915_gem_request_get_engine(from_req);
        if (to == from)
                return 0;
 
@@ -3260,7 +3252,7 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,
                     struct drm_i915_gem_request **to_req)
 {
        const bool readonly = obj->base.pending_write_domain == 0;
-       struct drm_i915_gem_request *req[I915_NUM_RINGS];
+       struct drm_i915_gem_request *req[I915_NUM_ENGINES];
        int ret, i, n;
 
        if (!obj->active)
@@ -3274,7 +3266,7 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,
                if (obj->last_write_req)
                        req[n++] = obj->last_write_req;
        } else {
-               for (i = 0; i < I915_NUM_RINGS; i++)
+               for (i = 0; i < I915_NUM_ENGINES; i++)
                        if (obj->last_read_req[i])
                                req[n++] = obj->last_read_req[i];
        }
@@ -3391,15 +3383,15 @@ int __i915_vma_unbind_no_wait(struct i915_vma *vma)
 int i915_gpu_idle(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int ret, i;
+       struct intel_engine_cs *engine;
+       int ret;
 
        /* Flush everything onto the inactive list. */
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine(engine, dev_priv) {
                if (!i915.enable_execlists) {
                        struct drm_i915_gem_request *req;
 
-                       req = i915_gem_request_alloc(ring, NULL);
+                       req = i915_gem_request_alloc(engine, NULL);
                        if (IS_ERR(req))
                                return PTR_ERR(req);
 
@@ -3412,7 +3404,7 @@ int i915_gpu_idle(struct drm_device *dev)
                        i915_add_request_no_flush(req);
                }
 
-               ret = intel_ring_idle(ring);
+               ret = intel_engine_idle(engine);
                if (ret)
                        return ret;
        }
@@ -3513,7 +3505,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
        start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
        end = vm->total;
        if (flags & PIN_MAPPABLE)
-               end = min_t(u64, end, dev_priv->gtt.mappable_end);
+               end = min_t(u64, end, dev_priv->ggtt.mappable_end);
        if (flags & PIN_ZONE_4G)
                end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE);
 
@@ -3774,7 +3766,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
        vma = i915_gem_obj_to_ggtt(obj);
        if (vma && drm_mm_node_allocated(&vma->node) && !obj->active)
                list_move_tail(&vma->vm_link,
-                              &to_i915(obj->base.dev)->gtt.base.inactive_list);
+                              &to_i915(obj->base.dev)->ggtt.base.inactive_list);
 
        return 0;
 }
@@ -3949,7 +3941,7 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
                 * cacheline, whereas normally such cachelines would get
                 * invalidated.
                 */
-               if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
+               if (!HAS_LLC(dev) && !HAS_SNOOP(dev))
                        return -ENODEV;
 
                level = I915_CACHE_LLC;
@@ -4211,7 +4203,7 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
                     (vma->node.start & (fence_alignment - 1)) == 0);
 
        mappable = (vma->node.start + fence_size <=
-                   to_i915(obj->base.dev)->gtt.mappable_end);
+                   to_i915(obj->base.dev)->ggtt.mappable_end);
 
        obj->map_and_fenceable = mappable && fenceable;
 }
@@ -4359,15 +4351,15 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
        if (obj->active) {
                int i;
 
-               for (i = 0; i < I915_NUM_RINGS; i++) {
+               for (i = 0; i < I915_NUM_ENGINES; i++) {
                        struct drm_i915_gem_request *req;
 
                        req = obj->last_read_req[i];
                        if (req)
-                               args->busy |= 1 << (16 + req->ring->exec_id);
+                               args->busy |= 1 << (16 + req->engine->exec_id);
                }
                if (obj->last_write_req)
-                       args->busy |= obj->last_write_req->ring->exec_id;
+                       args->busy |= obj->last_write_req->engine->exec_id;
        }
 
 unref:
@@ -4447,8 +4439,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
        int i;
 
        INIT_LIST_HEAD(&obj->global_list);
-       for (i = 0; i < I915_NUM_RINGS; i++)
-               INIT_LIST_HEAD(&obj->ring_list[i]);
+       for (i = 0; i < I915_NUM_ENGINES; i++)
+               INIT_LIST_HEAD(&obj->engine_list[i]);
        INIT_LIST_HEAD(&obj->obj_exec_link);
        INIT_LIST_HEAD(&obj->vma_list);
        INIT_LIST_HEAD(&obj->batch_pool_link);
@@ -4653,14 +4645,13 @@ void i915_gem_vma_destroy(struct i915_vma *vma)
 }
 
 static void
-i915_gem_stop_ringbuffers(struct drm_device *dev)
+i915_gem_stop_engines(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
-       for_each_ring(ring, dev_priv, i)
-               dev_priv->gt.stop_ring(ring);
+       for_each_engine(engine, dev_priv)
+               dev_priv->gt.stop_engine(engine);
 }
 
 int
@@ -4676,7 +4667,7 @@ i915_gem_suspend(struct drm_device *dev)
 
        i915_gem_retire_requests(dev);
 
-       i915_gem_stop_ringbuffers(dev);
+       i915_gem_stop_engines(dev);
        mutex_unlock(&dev->struct_mutex);
 
        cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
@@ -4697,8 +4688,8 @@ err:
 
 int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice)
 {
-       struct intel_engine_cs *ring = req->ring;
-       struct drm_device *dev = ring->dev;
+       struct intel_engine_cs *engine = req->engine;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 *remap_info = dev_priv->l3_parity.remap_info[slice];
        int i, ret;
@@ -4716,12 +4707,12 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice)
         * at initialization time.
         */
        for (i = 0; i < GEN7_L3LOG_SIZE / 4; i++) {
-               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit_reg(ring, GEN7_L3LOG(slice, i));
-               intel_ring_emit(ring, remap_info[i]);
+               intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+               intel_ring_emit_reg(engine, GEN7_L3LOG(slice, i));
+               intel_ring_emit(engine, remap_info[i]);
        }
 
-       intel_ring_advance(ring);
+       intel_ring_advance(engine);
 
        return ret;
 }
@@ -4778,7 +4769,7 @@ static void init_unused_rings(struct drm_device *dev)
        }
 }
 
-int i915_gem_init_rings(struct drm_device *dev)
+int i915_gem_init_engines(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
@@ -4814,13 +4805,13 @@ int i915_gem_init_rings(struct drm_device *dev)
        return 0;
 
 cleanup_vebox_ring:
-       intel_cleanup_ring_buffer(&dev_priv->ring[VECS]);
+       intel_cleanup_engine(&dev_priv->engine[VECS]);
 cleanup_blt_ring:
-       intel_cleanup_ring_buffer(&dev_priv->ring[BCS]);
+       intel_cleanup_engine(&dev_priv->engine[BCS]);
 cleanup_bsd_ring:
-       intel_cleanup_ring_buffer(&dev_priv->ring[VCS]);
+       intel_cleanup_engine(&dev_priv->engine[VCS]);
 cleanup_render_ring:
-       intel_cleanup_ring_buffer(&dev_priv->ring[RCS]);
+       intel_cleanup_engine(&dev_priv->engine[RCS]);
 
        return ret;
 }
@@ -4829,8 +4820,8 @@ int
 i915_gem_init_hw(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int ret, i, j;
+       struct intel_engine_cs *engine;
+       int ret, j;
 
        if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
                return -EIO;
@@ -4876,8 +4867,8 @@ i915_gem_init_hw(struct drm_device *dev)
        }
 
        /* Need to do basic initialisation of all rings first: */
-       for_each_ring(ring, dev_priv, i) {
-               ret = ring->init_hw(ring);
+       for_each_engine(engine, dev_priv) {
+               ret = engine->init_hw(engine);
                if (ret)
                        goto out;
        }
@@ -4901,34 +4892,36 @@ i915_gem_init_hw(struct drm_device *dev)
                goto out;
 
        /* Now it is safe to go back round and do everything else: */
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine(engine, dev_priv) {
                struct drm_i915_gem_request *req;
 
-               req = i915_gem_request_alloc(ring, NULL);
+               req = i915_gem_request_alloc(engine, NULL);
                if (IS_ERR(req)) {
                        ret = PTR_ERR(req);
-                       i915_gem_cleanup_ringbuffer(dev);
+                       i915_gem_cleanup_engines(dev);
                        goto out;
                }
 
-               if (ring->id == RCS) {
+               if (engine->id == RCS) {
                        for (j = 0; j < NUM_L3_SLICES(dev); j++)
                                i915_gem_l3_remap(req, j);
                }
 
                ret = i915_ppgtt_init_ring(req);
                if (ret && ret != -EIO) {
-                       DRM_ERROR("PPGTT enable ring #%d failed %d\n", i, ret);
+                       DRM_ERROR("PPGTT enable %s failed %d\n",
+                                 engine->name, ret);
                        i915_gem_request_cancel(req);
-                       i915_gem_cleanup_ringbuffer(dev);
+                       i915_gem_cleanup_engines(dev);
                        goto out;
                }
 
                ret = i915_gem_context_enable(req);
                if (ret && ret != -EIO) {
-                       DRM_ERROR("Context enable ring #%d failed %d\n", i, ret);
+                       DRM_ERROR("Context enable %s failed %d\n",
+                                 engine->name, ret);
                        i915_gem_request_cancel(req);
-                       i915_gem_cleanup_ringbuffer(dev);
+                       i915_gem_cleanup_engines(dev);
                        goto out;
                }
 
@@ -4952,14 +4945,14 @@ int i915_gem_init(struct drm_device *dev)
 
        if (!i915.enable_execlists) {
                dev_priv->gt.execbuf_submit = i915_gem_ringbuffer_submission;
-               dev_priv->gt.init_rings = i915_gem_init_rings;
-               dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer;
-               dev_priv->gt.stop_ring = intel_stop_ring_buffer;
+               dev_priv->gt.init_engines = i915_gem_init_engines;
+               dev_priv->gt.cleanup_engine = intel_cleanup_engine;
+               dev_priv->gt.stop_engine = intel_stop_engine;
        } else {
                dev_priv->gt.execbuf_submit = intel_execlists_submission;
-               dev_priv->gt.init_rings = intel_logical_rings_init;
-               dev_priv->gt.cleanup_ring = intel_logical_ring_cleanup;
-               dev_priv->gt.stop_ring = intel_logical_ring_stop;
+               dev_priv->gt.init_engines = intel_logical_rings_init;
+               dev_priv->gt.cleanup_engine = intel_logical_ring_cleanup;
+               dev_priv->gt.stop_engine = intel_logical_ring_stop;
        }
 
        /* This is just a security blanket to placate dragons.
@@ -4980,7 +4973,7 @@ int i915_gem_init(struct drm_device *dev)
        if (ret)
                goto out_unlock;
 
-       ret = dev_priv->gt.init_rings(dev);
+       ret = dev_priv->gt.init_engines(dev);
        if (ret)
                goto out_unlock;
 
@@ -5003,29 +4996,52 @@ out_unlock:
 }
 
 void
-i915_gem_cleanup_ringbuffer(struct drm_device *dev)
+i915_gem_cleanup_engines(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
-       for_each_ring(ring, dev_priv, i)
-               dev_priv->gt.cleanup_ring(ring);
+       for_each_engine(engine, dev_priv)
+               dev_priv->gt.cleanup_engine(engine);
 
-    if (i915.enable_execlists)
-            /*
-             * Neither the BIOS, ourselves or any other kernel
-             * expects the system to be in execlists mode on startup,
-             * so we need to reset the GPU back to legacy mode.
-             */
-            intel_gpu_reset(dev);
+       if (i915.enable_execlists)
+               /*
+                * Neither the BIOS, ourselves or any other kernel
+                * expects the system to be in execlists mode on startup,
+                * so we need to reset the GPU back to legacy mode.
+                */
+               intel_gpu_reset(dev, ALL_ENGINES);
 }
 
 static void
-init_ring_lists(struct intel_engine_cs *ring)
+init_engine_lists(struct intel_engine_cs *engine)
 {
-       INIT_LIST_HEAD(&ring->active_list);
-       INIT_LIST_HEAD(&ring->request_list);
+       INIT_LIST_HEAD(&engine->active_list);
+       INIT_LIST_HEAD(&engine->request_list);
+}
+
+void
+i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+
+       if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) &&
+           !IS_CHERRYVIEW(dev_priv))
+               dev_priv->num_fence_regs = 32;
+       else if (INTEL_INFO(dev_priv)->gen >= 4 || IS_I945G(dev_priv) ||
+                IS_I945GM(dev_priv) || IS_G33(dev_priv))
+               dev_priv->num_fence_regs = 16;
+       else
+               dev_priv->num_fence_regs = 8;
+
+       if (intel_vgpu_active(dev))
+               dev_priv->num_fence_regs =
+                               I915_READ(vgtif_reg(avail_rs.fence_num));
+
+       /* Initialize fence registers to zero */
+       i915_gem_restore_fences(dev);
+
+       i915_gem_detect_bit_6_swizzle(dev);
 }
 
 void
@@ -5055,8 +5071,8 @@ i915_gem_load_init(struct drm_device *dev)
        INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
        INIT_LIST_HEAD(&dev_priv->mm.bound_list);
        INIT_LIST_HEAD(&dev_priv->mm.fence_list);
-       for (i = 0; i < I915_NUM_RINGS; i++)
-               init_ring_lists(&dev_priv->ring[i]);
+       for (i = 0; i < I915_NUM_ENGINES; i++)
+               init_engine_lists(&dev_priv->engine[i]);
        for (i = 0; i < I915_MAX_NUM_FENCES; i++)
                INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
        INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
@@ -5067,17 +5083,6 @@ i915_gem_load_init(struct drm_device *dev)
 
        dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
 
-       if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))
-               dev_priv->num_fence_regs = 32;
-       else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
-               dev_priv->num_fence_regs = 16;
-       else
-               dev_priv->num_fence_regs = 8;
-
-       if (intel_vgpu_active(dev))
-               dev_priv->num_fence_regs =
-                               I915_READ(vgtif_reg(avail_rs.fence_num));
-
        /*
         * Set initial sequence number for requests.
         * Using this number allows the wraparound to happen early,
@@ -5086,11 +5091,8 @@ i915_gem_load_init(struct drm_device *dev)
        dev_priv->next_seqno = ((u32)~0 - 0x1100);
        dev_priv->last_seqno = ((u32)~0 - 0x1101);
 
-       /* Initialize fence registers to zero */
        INIT_LIST_HEAD(&dev_priv->mm.fence_list);
-       i915_gem_restore_fences(dev);
 
-       i915_gem_detect_bit_6_swizzle(dev);
        init_waitqueue_head(&dev_priv->pending_flip_queue);
 
        dev_priv->mm.interruptible = true;
index 5dd84e1..fe580cb 100644 (file)
@@ -345,12 +345,12 @@ void i915_gem_context_reset(struct drm_device *dev)
                        intel_lr_context_reset(dev, ctx);
        }
 
-       for (i = 0; i < I915_NUM_RINGS; i++) {
-               struct intel_engine_cs *ring = &dev_priv->ring[i];
+       for (i = 0; i < I915_NUM_ENGINES; i++) {
+               struct intel_engine_cs *engine = &dev_priv->engine[i];
 
-               if (ring->last_context) {
-                       i915_gem_context_unpin(ring->last_context, ring);
-                       ring->last_context = NULL;
+               if (engine->last_context) {
+                       i915_gem_context_unpin(engine->last_context, engine);
+                       engine->last_context = NULL;
                }
        }
 
@@ -413,7 +413,7 @@ void i915_gem_context_fini(struct drm_device *dev)
                /* The only known way to stop the gpu from accessing the hw context is
                 * to reset it. Do this as the very last operation to avoid confusing
                 * other code, leading to spurious errors. */
-               intel_gpu_reset(dev);
+               intel_gpu_reset(dev, ALL_ENGINES);
 
                /* When default context is created and switched to, base object refcount
                 * will be 2 (+1 from object creation and +1 from do_switch()).
@@ -421,17 +421,17 @@ void i915_gem_context_fini(struct drm_device *dev)
                 * to default context. So we need to unreference the base object once
                 * to offset the do_switch part, so that i915_gem_context_unreference()
                 * can then free the base object correctly. */
-               WARN_ON(!dev_priv->ring[RCS].last_context);
+               WARN_ON(!dev_priv->engine[RCS].last_context);
 
                i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state);
        }
 
-       for (i = I915_NUM_RINGS; --i >= 0;) {
-               struct intel_engine_cs *ring = &dev_priv->ring[i];
+       for (i = I915_NUM_ENGINES; --i >= 0;) {
+               struct intel_engine_cs *engine = &dev_priv->engine[i];
 
-               if (ring->last_context) {
-                       i915_gem_context_unpin(ring->last_context, ring);
-                       ring->last_context = NULL;
+               if (engine->last_context) {
+                       i915_gem_context_unpin(engine->last_context, engine);
+                       engine->last_context = NULL;
                }
        }
 
@@ -441,14 +441,14 @@ void i915_gem_context_fini(struct drm_device *dev)
 
 int i915_gem_context_enable(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        if (i915.enable_execlists) {
-               if (ring->init_context == NULL)
+               if (engine->init_context == NULL)
                        return 0;
 
-               ret = ring->init_context(req);
+               ret = engine->init_context(req);
        } else
                ret = i915_switch_context(req);
 
@@ -510,35 +510,35 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
 static inline int
 mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        u32 flags = hw_flags | MI_MM_SPACE_GTT;
        const int num_rings =
                /* Use an extended w/a on ivb+ if signalling from other rings */
-               i915_semaphore_is_enabled(ring->dev) ?
-               hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 :
+               i915_semaphore_is_enabled(engine->dev) ?
+               hweight32(INTEL_INFO(engine->dev)->ring_mask) - 1 :
                0;
-       int len, i, ret;
+       int len, ret;
 
        /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB
         * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value
         * explicitly, so we rely on the value at ring init, stored in
         * itlb_before_ctx_switch.
         */
-       if (IS_GEN6(ring->dev)) {
-               ret = ring->flush(req, I915_GEM_GPU_DOMAINS, 0);
+       if (IS_GEN6(engine->dev)) {
+               ret = engine->flush(req, I915_GEM_GPU_DOMAINS, 0);
                if (ret)
                        return ret;
        }
 
        /* These flags are for resource streamer on HSW+ */
-       if (IS_HASWELL(ring->dev) || INTEL_INFO(ring->dev)->gen >= 8)
+       if (IS_HASWELL(engine->dev) || INTEL_INFO(engine->dev)->gen >= 8)
                flags |= (HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN);
-       else if (INTEL_INFO(ring->dev)->gen < 8)
+       else if (INTEL_INFO(engine->dev)->gen < 8)
                flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN);
 
 
        len = 4;
-       if (INTEL_INFO(ring->dev)->gen >= 7)
+       if (INTEL_INFO(engine->dev)->gen >= 7)
                len += 2 + (num_rings ? 4*num_rings + 2 : 0);
 
        ret = intel_ring_begin(req, len);
@@ -546,54 +546,61 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
                return ret;
 
        /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */
-       if (INTEL_INFO(ring->dev)->gen >= 7) {
-               intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
+       if (INTEL_INFO(engine->dev)->gen >= 7) {
+               intel_ring_emit(engine, MI_ARB_ON_OFF | MI_ARB_DISABLE);
                if (num_rings) {
                        struct intel_engine_cs *signaller;
 
-                       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings));
-                       for_each_ring(signaller, to_i915(ring->dev), i) {
-                               if (signaller == ring)
+                       intel_ring_emit(engine,
+                                       MI_LOAD_REGISTER_IMM(num_rings));
+                       for_each_engine(signaller, to_i915(engine->dev)) {
+                               if (signaller == engine)
                                        continue;
 
-                               intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base));
-                               intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
+                               intel_ring_emit_reg(engine,
+                                                   RING_PSMI_CTL(signaller->mmio_base));
+                               intel_ring_emit(engine,
+                                               _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
                        }
                }
        }
 
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_emit(ring, MI_SET_CONTEXT);
-       intel_ring_emit(ring, i915_gem_obj_ggtt_offset(req->ctx->legacy_hw_ctx.rcs_state) |
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_emit(engine, MI_SET_CONTEXT);
+       intel_ring_emit(engine,
+                       i915_gem_obj_ggtt_offset(req->ctx->legacy_hw_ctx.rcs_state) |
                        flags);
        /*
         * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
         * WaMiSetContext_Hang:snb,ivb,vlv
         */
-       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_emit(engine, MI_NOOP);
 
-       if (INTEL_INFO(ring->dev)->gen >= 7) {
+       if (INTEL_INFO(engine->dev)->gen >= 7) {
                if (num_rings) {
                        struct intel_engine_cs *signaller;
 
-                       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings));
-                       for_each_ring(signaller, to_i915(ring->dev), i) {
-                               if (signaller == ring)
+                       intel_ring_emit(engine,
+                                       MI_LOAD_REGISTER_IMM(num_rings));
+                       for_each_engine(signaller, to_i915(engine->dev)) {
+                               if (signaller == engine)
                                        continue;
 
-                               intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base));
-                               intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
+                               intel_ring_emit_reg(engine,
+                                                   RING_PSMI_CTL(signaller->mmio_base));
+                               intel_ring_emit(engine,
+                                               _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
                        }
                }
-               intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE);
+               intel_ring_emit(engine, MI_ARB_ON_OFF | MI_ARB_ENABLE);
        }
 
-       intel_ring_advance(ring);
+       intel_ring_advance(engine);
 
        return ret;
 }
 
-static inline bool should_skip_switch(struct intel_engine_cs *ring,
+static inline bool should_skip_switch(struct intel_engine_cs *engine,
                                      struct intel_context *from,
                                      struct intel_context *to)
 {
@@ -601,42 +608,42 @@ static inline bool should_skip_switch(struct intel_engine_cs *ring,
                return false;
 
        if (to->ppgtt && from == to &&
-           !(intel_ring_flag(ring) & to->ppgtt->pd_dirty_rings))
+           !(intel_engine_flag(engine) & to->ppgtt->pd_dirty_rings))
                return true;
 
        return false;
 }
 
 static bool
-needs_pd_load_pre(struct intel_engine_cs *ring, struct intel_context *to)
+needs_pd_load_pre(struct intel_engine_cs *engine, struct intel_context *to)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
 
        if (!to->ppgtt)
                return false;
 
-       if (INTEL_INFO(ring->dev)->gen < 8)
+       if (INTEL_INFO(engine->dev)->gen < 8)
                return true;
 
-       if (ring != &dev_priv->ring[RCS])
+       if (engine != &dev_priv->engine[RCS])
                return true;
 
        return false;
 }
 
 static bool
-needs_pd_load_post(struct intel_engine_cs *ring, struct intel_context *to,
-               u32 hw_flags)
+needs_pd_load_post(struct intel_engine_cs *engine, struct intel_context *to,
+                  u32 hw_flags)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
 
        if (!to->ppgtt)
                return false;
 
-       if (!IS_GEN8(ring->dev))
+       if (!IS_GEN8(engine->dev))
                return false;
 
-       if (ring != &dev_priv->ring[RCS])
+       if (engine != &dev_priv->engine[RCS])
                return false;
 
        if (hw_flags & MI_RESTORE_INHIBIT)
@@ -648,25 +655,26 @@ needs_pd_load_post(struct intel_engine_cs *ring, struct intel_context *to,
 static int do_switch(struct drm_i915_gem_request *req)
 {
        struct intel_context *to = req->ctx;
-       struct intel_engine_cs *ring = req->ring;
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
-       struct intel_context *from = ring->last_context;
+       struct intel_engine_cs *engine = req->engine;
+       struct drm_i915_private *dev_priv = req->i915;
+       struct intel_context *from = engine->last_context;
        u32 hw_flags = 0;
        bool uninitialized = false;
        int ret, i;
 
-       if (from != NULL && ring == &dev_priv->ring[RCS]) {
+       if (from != NULL && engine == &dev_priv->engine[RCS]) {
                BUG_ON(from->legacy_hw_ctx.rcs_state == NULL);
                BUG_ON(!i915_gem_obj_is_pinned(from->legacy_hw_ctx.rcs_state));
        }
 
-       if (should_skip_switch(ring, from, to))
+       if (should_skip_switch(engine, from, to))
                return 0;
 
        /* Trying to pin first makes error handling easier. */
-       if (ring == &dev_priv->ring[RCS]) {
+       if (engine == &dev_priv->engine[RCS]) {
                ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
-                                           get_context_alignment(ring->dev), 0);
+                                           get_context_alignment(engine->dev),
+                                           0);
                if (ret)
                        return ret;
        }
@@ -676,23 +684,23 @@ static int do_switch(struct drm_i915_gem_request *req)
         * evict_everything - as a last ditch gtt defrag effort that also
         * switches to the default context. Hence we need to reload from here.
         */
-       from = ring->last_context;
+       from = engine->last_context;
 
-       if (needs_pd_load_pre(ring, to)) {
+       if (needs_pd_load_pre(engine, to)) {
                /* Older GENs and non render rings still want the load first,
                 * "PP_DCLV followed by PP_DIR_BASE register through Load
                 * Register Immediate commands in Ring Buffer before submitting
                 * a context."*/
-               trace_switch_mm(ring, to);
+               trace_switch_mm(engine, to);
                ret = to->ppgtt->switch_mm(to->ppgtt, req);
                if (ret)
                        goto unpin_out;
 
                /* Doing a PD load always reloads the page dirs */
-               to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(ring);
+               to->ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine);
        }
 
-       if (ring != &dev_priv->ring[RCS]) {
+       if (engine != &dev_priv->engine[RCS]) {
                if (from)
                        i915_gem_context_unreference(from);
                goto done;
@@ -717,14 +725,14 @@ static int do_switch(struct drm_i915_gem_request *req)
                 * space. This means we must enforce that a page table load
                 * occur when this occurs. */
        } else if (to->ppgtt &&
-                  (intel_ring_flag(ring) & to->ppgtt->pd_dirty_rings)) {
+                  (intel_engine_flag(engine) & to->ppgtt->pd_dirty_rings)) {
                hw_flags |= MI_FORCE_RESTORE;
-               to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(ring);
+               to->ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine);
        }
 
        /* We should never emit switch_mm more than once */
-       WARN_ON(needs_pd_load_pre(ring, to) &&
-               needs_pd_load_post(ring, to, hw_flags));
+       WARN_ON(needs_pd_load_pre(engine, to) &&
+               needs_pd_load_post(engine, to, hw_flags));
 
        ret = mi_set_context(req, hw_flags);
        if (ret)
@@ -733,8 +741,8 @@ static int do_switch(struct drm_i915_gem_request *req)
        /* GEN8 does *not* require an explicit reload if the PDPs have been
         * setup, and we do not wish to move them.
         */
-       if (needs_pd_load_post(ring, to, hw_flags)) {
-               trace_switch_mm(ring, to);
+       if (needs_pd_load_post(engine, to, hw_flags)) {
+               trace_switch_mm(engine, to);
                ret = to->ppgtt->switch_mm(to->ppgtt, req);
                /* The hardware context switch is emitted, but we haven't
                 * actually changed the state - so it's probably safe to bail
@@ -787,11 +795,11 @@ static int do_switch(struct drm_i915_gem_request *req)
 
 done:
        i915_gem_context_reference(to);
-       ring->last_context = to;
+       engine->last_context = to;
 
        if (uninitialized) {
-               if (ring->init_context) {
-                       ret = ring->init_context(req);
+               if (engine->init_context) {
+                       ret = engine->init_context(req);
                        if (ret)
                                DRM_ERROR("ring init context: %d\n", ret);
                }
@@ -800,7 +808,7 @@ done:
        return 0;
 
 unpin_out:
-       if (ring->id == RCS)
+       if (engine->id == RCS)
                i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state);
        return ret;
 }
@@ -820,18 +828,18 @@ unpin_out:
  */
 int i915_switch_context(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct intel_engine_cs *engine = req->engine;
+       struct drm_i915_private *dev_priv = req->i915;
 
        WARN_ON(i915.enable_execlists);
        WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
        if (req->ctx->legacy_hw_ctx.rcs_state == NULL) { /* We have the fake context */
-               if (req->ctx != ring->last_context) {
+               if (req->ctx != engine->last_context) {
                        i915_gem_context_reference(req->ctx);
-                       if (ring->last_context)
-                               i915_gem_context_unreference(ring->last_context);
-                       ring->last_context = req->ctx;
+                       if (engine->last_context)
+                               i915_gem_context_unreference(engine->last_context);
+                       engine->last_context = req->ctx;
                }
                return 0;
        }
@@ -937,7 +945,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
                else if (to_i915(dev)->mm.aliasing_ppgtt)
                        args->value = to_i915(dev)->mm.aliasing_ppgtt->base.total;
                else
-                       args->value = to_i915(dev)->gtt.base.total;
+                       args->value = to_i915(dev)->ggtt.base.total;
                break;
        default:
                ret = -EINVAL;
index 17299d0..a565164 100644 (file)
@@ -36,29 +36,29 @@ i915_verify_lists(struct drm_device *dev)
        static int warned;
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct drm_i915_gem_object *obj;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        int err = 0;
-       int i;
 
        if (warned)
                return 0;
 
-       for_each_ring(ring, dev_priv, i) {
-               list_for_each_entry(obj, &ring->active_list, ring_list[ring->id]) {
+       for_each_engine(engine, dev_priv) {
+               list_for_each_entry(obj, &engine->active_list,
+                                   engine_list[engine->id]) {
                        if (obj->base.dev != dev ||
                            !atomic_read(&obj->base.refcount.refcount)) {
                                DRM_ERROR("%s: freed active obj %p\n",
-                                         ring->name, obj);
+                                         engine->name, obj);
                                err++;
                                break;
                        } else if (!obj->active ||
-                                  obj->last_read_req[ring->id] == NULL) {
+                                  obj->last_read_req[engine->id] == NULL) {
                                DRM_ERROR("%s: invalid active obj %p\n",
-                                         ring->name, obj);
+                                         engine->name, obj);
                                err++;
                        } else if (obj->base.write_domain) {
                                DRM_ERROR("%s: invalid write obj %p (w %x)\n",
-                                         ring->name,
+                                         engine->name,
                                          obj, obj->base.write_domain);
                                err++;
                        }
index 1328bc5..374a0cb 100644 (file)
@@ -330,7 +330,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
        /* Map the page containing the relocation we're going to perform.  */
        offset = i915_gem_obj_ggtt_offset(obj);
        offset += reloc->offset;
-       reloc_page = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
+       reloc_page = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable,
                                              offset & PAGE_MASK);
        iowrite32(lower_32_bits(delta), reloc_page + offset_in_page(offset));
 
@@ -340,7 +340,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
                if (offset_in_page(offset) == 0) {
                        io_mapping_unmap_atomic(reloc_page);
                        reloc_page =
-                               io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
+                               io_mapping_map_atomic_wc(dev_priv->ggtt.mappable,
                                                         offset);
                }
 
@@ -599,7 +599,7 @@ static bool only_mappable_for_reloc(unsigned int flags)
 
 static int
 i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
-                               struct intel_engine_cs *ring,
+                               struct intel_engine_cs *engine,
                                bool *need_reloc)
 {
        struct drm_i915_gem_object *obj = vma->obj;
@@ -713,7 +713,7 @@ eb_vma_misplaced(struct i915_vma *vma)
 }
 
 static int
-i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
+i915_gem_execbuffer_reserve(struct intel_engine_cs *engine,
                            struct list_head *vmas,
                            struct intel_context *ctx,
                            bool *need_relocs)
@@ -723,10 +723,10 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
        struct i915_address_space *vm;
        struct list_head ordered_vmas;
        struct list_head pinned_vmas;
-       bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
+       bool has_fenced_gpu_access = INTEL_INFO(engine->dev)->gen < 4;
        int retry;
 
-       i915_gem_retire_requests_ring(ring);
+       i915_gem_retire_requests_ring(engine);
 
        vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm;
 
@@ -788,7 +788,9 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
                        if (eb_vma_misplaced(vma))
                                ret = i915_vma_unbind(vma);
                        else
-                               ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs);
+                               ret = i915_gem_execbuffer_reserve_vma(vma,
+                                                                     engine,
+                                                                     need_relocs);
                        if (ret)
                                goto err;
                }
@@ -798,7 +800,8 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
                        if (drm_mm_node_allocated(&vma->node))
                                continue;
 
-                       ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs);
+                       ret = i915_gem_execbuffer_reserve_vma(vma, engine,
+                                                             need_relocs);
                        if (ret)
                                goto err;
                }
@@ -821,7 +824,7 @@ static int
 i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
                                  struct drm_i915_gem_execbuffer2 *args,
                                  struct drm_file *file,
-                                 struct intel_engine_cs *ring,
+                                 struct intel_engine_cs *engine,
                                  struct eb_vmas *eb,
                                  struct drm_i915_gem_exec_object2 *exec,
                                  struct intel_context *ctx)
@@ -910,7 +913,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
                goto err;
 
        need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-       ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, ctx, &need_relocs);
+       ret = i915_gem_execbuffer_reserve(engine, &eb->vmas, ctx,
+                                         &need_relocs);
        if (ret)
                goto err;
 
@@ -938,7 +942,7 @@ static int
 i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req,
                                struct list_head *vmas)
 {
-       const unsigned other_rings = ~intel_ring_flag(req->ring);
+       const unsigned other_rings = ~intel_engine_flag(req->engine);
        struct i915_vma *vma;
        uint32_t flush_domains = 0;
        bool flush_chipset = false;
@@ -948,7 +952,7 @@ i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req,
                struct drm_i915_gem_object *obj = vma->obj;
 
                if (obj->active & other_rings) {
-                       ret = i915_gem_object_sync(obj, req->ring, &req);
+                       ret = i915_gem_object_sync(obj, req->engine, &req);
                        if (ret)
                                return ret;
                }
@@ -960,7 +964,7 @@ i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req,
        }
 
        if (flush_chipset)
-               i915_gem_chipset_flush(req->ring->dev);
+               i915_gem_chipset_flush(req->engine->dev);
 
        if (flush_domains & I915_GEM_DOMAIN_GTT)
                wmb();
@@ -1062,12 +1066,12 @@ validate_exec_list(struct drm_device *dev,
 
 static struct intel_context *
 i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
-                         struct intel_engine_cs *ring, const u32 ctx_id)
+                         struct intel_engine_cs *engine, const u32 ctx_id)
 {
        struct intel_context *ctx = NULL;
        struct i915_ctx_hang_stats *hs;
 
-       if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE)
+       if (engine->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE)
                return ERR_PTR(-EINVAL);
 
        ctx = i915_gem_context_get(file->driver_priv, ctx_id);
@@ -1080,8 +1084,8 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
                return ERR_PTR(-EIO);
        }
 
-       if (i915.enable_execlists && !ctx->engine[ring->id].state) {
-               int ret = intel_lr_context_deferred_alloc(ctx, ring);
+       if (i915.enable_execlists && !ctx->engine[engine->id].state) {
+               int ret = intel_lr_context_deferred_alloc(ctx, engine);
                if (ret) {
                        DRM_DEBUG("Could not create LRC %u: %d\n", ctx_id, ret);
                        return ERR_PTR(ret);
@@ -1095,7 +1099,7 @@ void
 i915_gem_execbuffer_move_to_active(struct list_head *vmas,
                                   struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = i915_gem_request_get_ring(req);
+       struct intel_engine_cs *engine = i915_gem_request_get_engine(req);
        struct i915_vma *vma;
 
        list_for_each_entry(vma, vmas, exec_list) {
@@ -1122,7 +1126,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
                if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) {
                        i915_gem_request_assign(&obj->last_fenced_req, req);
                        if (entry->flags & __EXEC_OBJECT_HAS_FENCE) {
-                               struct drm_i915_private *dev_priv = to_i915(ring->dev);
+                               struct drm_i915_private *dev_priv = to_i915(engine->dev);
                                list_move_tail(&dev_priv->fence_regs[obj->fence_reg].lru_list,
                                               &dev_priv->mm.fence_list);
                        }
@@ -1136,7 +1140,7 @@ void
 i915_gem_execbuffer_retire_commands(struct i915_execbuffer_params *params)
 {
        /* Unconditionally force add_request to emit a full flush. */
-       params->ring->gpu_caches_dirty = true;
+       params->engine->gpu_caches_dirty = true;
 
        /* Add a breadcrumb for the completion of the batch buffer */
        __i915_add_request(params->request, params->batch_obj, true);
@@ -1146,11 +1150,11 @@ static int
 i915_reset_gen7_sol_offsets(struct drm_device *dev,
                            struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret, i;
 
-       if (!IS_GEN7(dev) || ring != &dev_priv->ring[RCS]) {
+       if (!IS_GEN7(dev) || engine != &dev_priv->engine[RCS]) {
                DRM_DEBUG("sol reset is gen7/rcs only\n");
                return -EINVAL;
        }
@@ -1160,18 +1164,18 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,
                return ret;
 
        for (i = 0; i < 4; i++) {
-               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit_reg(ring, GEN7_SO_WRITE_OFFSET(i));
-               intel_ring_emit(ring, 0);
+               intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+               intel_ring_emit_reg(engine, GEN7_SO_WRITE_OFFSET(i));
+               intel_ring_emit(engine, 0);
        }
 
-       intel_ring_advance(ring);
+       intel_ring_advance(engine);
 
        return 0;
 }
 
 static struct drm_i915_gem_object*
-i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
+i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
                          struct drm_i915_gem_exec_object2 *shadow_exec_entry,
                          struct eb_vmas *eb,
                          struct drm_i915_gem_object *batch_obj,
@@ -1183,12 +1187,12 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
        struct i915_vma *vma;
        int ret;
 
-       shadow_batch_obj = i915_gem_batch_pool_get(&ring->batch_pool,
+       shadow_batch_obj = i915_gem_batch_pool_get(&engine->batch_pool,
                                                   PAGE_ALIGN(batch_len));
        if (IS_ERR(shadow_batch_obj))
                return shadow_batch_obj;
 
-       ret = i915_parse_cmds(ring,
+       ret = i915_parse_cmds(engine,
                              batch_obj,
                              shadow_batch_obj,
                              batch_start_offset,
@@ -1229,7 +1233,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
                               struct list_head *vmas)
 {
        struct drm_device *dev = params->dev;
-       struct intel_engine_cs *ring = params->ring;
+       struct intel_engine_cs *engine = params->engine;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u64 exec_start, exec_len;
        int instp_mode;
@@ -1244,8 +1248,8 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
        if (ret)
                return ret;
 
-       WARN(params->ctx->ppgtt && params->ctx->ppgtt->pd_dirty_rings & (1<<ring->id),
-            "%s didn't clear reload\n", ring->name);
+       WARN(params->ctx->ppgtt && params->ctx->ppgtt->pd_dirty_rings & (1<<engine->id),
+            "%s didn't clear reload\n", engine->name);
 
        instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK;
        instp_mask = I915_EXEC_CONSTANTS_MASK;
@@ -1253,7 +1257,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
        case I915_EXEC_CONSTANTS_REL_GENERAL:
        case I915_EXEC_CONSTANTS_ABSOLUTE:
        case I915_EXEC_CONSTANTS_REL_SURFACE:
-               if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) {
+               if (instp_mode != 0 && engine != &dev_priv->engine[RCS]) {
                        DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
                        return -EINVAL;
                }
@@ -1280,17 +1284,17 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
                return -EINVAL;
        }
 
-       if (ring == &dev_priv->ring[RCS] &&
+       if (engine == &dev_priv->engine[RCS] &&
            instp_mode != dev_priv->relative_constants_mode) {
                ret = intel_ring_begin(params->request, 4);
                if (ret)
                        return ret;
 
-               intel_ring_emit(ring, MI_NOOP);
-               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit_reg(ring, INSTPM);
-               intel_ring_emit(ring, instp_mask << 16 | instp_mode);
-               intel_ring_advance(ring);
+               intel_ring_emit(engine, MI_NOOP);
+               intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+               intel_ring_emit_reg(engine, INSTPM);
+               intel_ring_emit(engine, instp_mask << 16 | instp_mode);
+               intel_ring_advance(engine);
 
                dev_priv->relative_constants_mode = instp_mode;
        }
@@ -1308,7 +1312,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
        if (exec_len == 0)
                exec_len = params->batch_obj->base.size;
 
-       ret = ring->dispatch_execbuffer(params->request,
+       ret = engine->dispatch_execbuffer(params->request,
                                        exec_start, exec_len,
                                        params->dispatch_flags);
        if (ret)
@@ -1365,7 +1369,7 @@ eb_get_batch(struct eb_vmas *eb)
 
 #define I915_USER_RINGS (4)
 
-static const enum intel_ring_id user_ring_map[I915_USER_RINGS + 1] = {
+static const enum intel_engine_id user_ring_map[I915_USER_RINGS + 1] = {
        [I915_EXEC_DEFAULT]     = RCS,
        [I915_EXEC_RENDER]      = RCS,
        [I915_EXEC_BLT]         = BCS,
@@ -1408,12 +1412,12 @@ eb_select_ring(struct drm_i915_private *dev_priv,
                        return -EINVAL;
                }
 
-               *ring = &dev_priv->ring[_VCS(bsd_idx)];
+               *ring = &dev_priv->engine[_VCS(bsd_idx)];
        } else {
-               *ring = &dev_priv->ring[user_ring_map[user_ring_id]];
+               *ring = &dev_priv->engine[user_ring_map[user_ring_id]];
        }
 
-       if (!intel_ring_initialized(*ring)) {
+       if (!intel_engine_initialized(*ring)) {
                DRM_DEBUG("execbuf with invalid ring: %u\n", user_ring_id);
                return -EINVAL;
        }
@@ -1432,7 +1436,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        struct eb_vmas *eb;
        struct drm_i915_gem_object *batch_obj;
        struct drm_i915_gem_exec_object2 shadow_exec_entry;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct intel_context *ctx;
        struct i915_address_space *vm;
        struct i915_execbuffer_params params_master; /* XXX: will be removed later */
@@ -1459,7 +1463,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        if (args->flags & I915_EXEC_IS_PINNED)
                dispatch_flags |= I915_DISPATCH_PINNED;
 
-       ret = eb_select_ring(dev_priv, file, args, &ring);
+       ret = eb_select_ring(dev_priv, file, args, &engine);
        if (ret)
                return ret;
 
@@ -1473,9 +1477,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                        DRM_DEBUG("RS is only allowed for Haswell, Gen8 and above\n");
                        return -EINVAL;
                }
-               if (ring->id != RCS) {
+               if (engine->id != RCS) {
                        DRM_DEBUG("RS is not available on %s\n",
-                                ring->name);
+                                engine->name);
                        return -EINVAL;
                }
 
@@ -1488,7 +1492,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        if (ret)
                goto pre_mutex_err;
 
-       ctx = i915_gem_validate_context(dev, file, ring, ctx_id);
+       ctx = i915_gem_validate_context(dev, file, engine, ctx_id);
        if (IS_ERR(ctx)) {
                mutex_unlock(&dev->struct_mutex);
                ret = PTR_ERR(ctx);
@@ -1500,7 +1504,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        if (ctx->ppgtt)
                vm = &ctx->ppgtt->base;
        else
-               vm = &dev_priv->gtt.base;
+               vm = &dev_priv->ggtt.base;
 
        memset(&params_master, 0x00, sizeof(params_master));
 
@@ -1522,7 +1526,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
        /* Move the objects en-masse into the GTT, evicting if necessary. */
        need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-       ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, ctx, &need_relocs);
+       ret = i915_gem_execbuffer_reserve(engine, &eb->vmas, ctx,
+                                         &need_relocs);
        if (ret)
                goto err;
 
@@ -1531,7 +1536,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                ret = i915_gem_execbuffer_relocate(eb);
        if (ret) {
                if (ret == -EFAULT) {
-                       ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring,
+                       ret = i915_gem_execbuffer_relocate_slow(dev, args, file,
+                                                               engine,
                                                                eb, exec, ctx);
                        BUG_ON(!mutex_is_locked(&dev->struct_mutex));
                }
@@ -1547,16 +1553,16 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        }
 
        params->args_batch_start_offset = args->batch_start_offset;
-       if (i915_needs_cmd_parser(ring) && args->batch_len) {
+       if (i915_needs_cmd_parser(engine) && args->batch_len) {
                struct drm_i915_gem_object *parsed_batch_obj;
 
-               parsed_batch_obj = i915_gem_execbuffer_parse(ring,
-                                                     &shadow_exec_entry,
-                                                     eb,
-                                                     batch_obj,
-                                                     args->batch_start_offset,
-                                                     args->batch_len,
-                                                     file->is_master);
+               parsed_batch_obj = i915_gem_execbuffer_parse(engine,
+                                                            &shadow_exec_entry,
+                                                            eb,
+                                                            batch_obj,
+                                                            args->batch_start_offset,
+                                                            args->batch_len,
+                                                            file->is_master);
                if (IS_ERR(parsed_batch_obj)) {
                        ret = PTR_ERR(parsed_batch_obj);
                        goto err;
@@ -1608,7 +1614,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                params->batch_obj_vm_offset = i915_gem_obj_offset(batch_obj, vm);
 
        /* Allocate a request for this batch buffer nice and early. */
-       req = i915_gem_request_alloc(ring, ctx);
+       req = i915_gem_request_alloc(engine, ctx);
        if (IS_ERR(req)) {
                ret = PTR_ERR(req);
                goto err_batch_unpin;
@@ -1626,7 +1632,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
         */
        params->dev                     = dev;
        params->file                    = file;
-       params->ring                    = ring;
+       params->engine                    = engine;
        params->dispatch_flags          = dispatch_flags;
        params->batch_obj               = batch_obj;
        params->ctx                     = ctx;
index 49e4f26..7cfafdc 100644 (file)
@@ -658,7 +658,7 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req,
                          unsigned entry,
                          dma_addr_t addr)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        BUG_ON(entry >= 4);
@@ -667,13 +667,13 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req,
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-       intel_ring_emit_reg(ring, GEN8_RING_PDP_UDW(ring, entry));
-       intel_ring_emit(ring, upper_32_bits(addr));
-       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-       intel_ring_emit_reg(ring, GEN8_RING_PDP_LDW(ring, entry));
-       intel_ring_emit(ring, lower_32_bits(addr));
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+       intel_ring_emit_reg(engine, GEN8_RING_PDP_UDW(engine, entry));
+       intel_ring_emit(engine, upper_32_bits(addr));
+       intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+       intel_ring_emit_reg(engine, GEN8_RING_PDP_LDW(engine, entry));
+       intel_ring_emit(engine, lower_32_bits(addr));
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -1637,7 +1637,7 @@ static void gen6_write_page_range(struct drm_i915_private *dev_priv,
 
        /* Make sure write is complete before other code can use this page
         * table. Also require for WC mapped PTEs */
-       readl(dev_priv->gtt.gsm);
+       readl(dev_priv->ggtt.gsm);
 }
 
 static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt)
@@ -1650,11 +1650,11 @@ static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt)
 static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
                         struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        /* NB: TLBs must be flushed and invalidated before a switch */
-       ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+       ret = engine->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
        if (ret)
                return ret;
 
@@ -1662,13 +1662,13 @@ static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
-       intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring));
-       intel_ring_emit(ring, PP_DIR_DCLV_2G);
-       intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring));
-       intel_ring_emit(ring, get_pd_offset(ppgtt));
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(2));
+       intel_ring_emit_reg(engine, RING_PP_DIR_DCLV(engine));
+       intel_ring_emit(engine, PP_DIR_DCLV_2G);
+       intel_ring_emit_reg(engine, RING_PP_DIR_BASE(engine));
+       intel_ring_emit(engine, get_pd_offset(ppgtt));
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -1676,22 +1676,22 @@ static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
 static int vgpu_mm_switch(struct i915_hw_ppgtt *ppgtt,
                          struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
 
-       I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
-       I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt));
+       I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G);
+       I915_WRITE(RING_PP_DIR_BASE(engine), get_pd_offset(ppgtt));
        return 0;
 }
 
 static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
                          struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        /* NB: TLBs must be flushed and invalidated before a switch */
-       ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+       ret = engine->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
        if (ret)
                return ret;
 
@@ -1699,17 +1699,17 @@ static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
-       intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring));
-       intel_ring_emit(ring, PP_DIR_DCLV_2G);
-       intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring));
-       intel_ring_emit(ring, get_pd_offset(ppgtt));
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(2));
+       intel_ring_emit_reg(engine, RING_PP_DIR_DCLV(engine));
+       intel_ring_emit(engine, PP_DIR_DCLV_2G);
+       intel_ring_emit_reg(engine, RING_PP_DIR_BASE(engine));
+       intel_ring_emit(engine, get_pd_offset(ppgtt));
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
 
        /* XXX: RCS is the only one to auto invalidate the TLBs? */
-       if (ring->id != RCS) {
-               ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+       if (engine->id != RCS) {
+               ret = engine->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
                if (ret)
                        return ret;
        }
@@ -1720,15 +1720,15 @@ static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
 static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
                          struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct drm_device *dev = ppgtt->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
 
-       I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
-       I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt));
+       I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G);
+       I915_WRITE(RING_PP_DIR_BASE(engine), get_pd_offset(ppgtt));
 
-       POSTING_READ(RING_PP_DIR_DCLV(ring));
+       POSTING_READ(RING_PP_DIR_DCLV(engine));
 
        return 0;
 }
@@ -1736,12 +1736,11 @@ static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
 static void gen8_ppgtt_enable(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int j;
+       struct intel_engine_cs *engine;
 
-       for_each_ring(ring, dev_priv, j) {
+       for_each_engine(engine, dev_priv) {
                u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0;
-               I915_WRITE(RING_MODE_GEN7(ring),
+               I915_WRITE(RING_MODE_GEN7(engine),
                           _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level));
        }
 }
@@ -1749,9 +1748,8 @@ static void gen8_ppgtt_enable(struct drm_device *dev)
 static void gen7_ppgtt_enable(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        uint32_t ecochk, ecobits;
-       int i;
 
        ecobits = I915_READ(GAC_ECO_BITS);
        I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
@@ -1765,9 +1763,9 @@ static void gen7_ppgtt_enable(struct drm_device *dev)
        }
        I915_WRITE(GAM_ECOCHK, ecochk);
 
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine(engine, dev_priv) {
                /* GFX_MODE is per-ring on gen7+ */
-               I915_WRITE(RING_MODE_GEN7(ring),
+               I915_WRITE(RING_MODE_GEN7(engine),
                           _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
        }
 }
@@ -1932,7 +1930,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm,
 
        /* Make sure write is complete before other code can use this page
         * table. Also require for WC mapped PTEs */
-       readl(dev_priv->gtt.gsm);
+       readl(dev_priv->ggtt.gsm);
 
        mark_tlbs_dirty(ppgtt);
        return 0;
@@ -2005,23 +2003,23 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
         * allocator works in address space sizes, so it's multiplied by page
         * size. We allocate at the top of the GTT to avoid fragmentation.
         */
-       BUG_ON(!drm_mm_initialized(&dev_priv->gtt.base.mm));
+       BUG_ON(!drm_mm_initialized(&dev_priv->ggtt.base.mm));
 
        ret = gen6_init_scratch(vm);
        if (ret)
                return ret;
 
 alloc:
-       ret = drm_mm_insert_node_in_range_generic(&dev_priv->gtt.base.mm,
+       ret = drm_mm_insert_node_in_range_generic(&dev_priv->ggtt.base.mm,
                                                  &ppgtt->node, GEN6_PD_SIZE,
                                                  GEN6_PD_ALIGN, 0,
-                                                 0, dev_priv->gtt.base.total,
+                                                 0, dev_priv->ggtt.base.total,
                                                  DRM_MM_TOPDOWN);
        if (ret == -ENOSPC && !retried) {
-               ret = i915_gem_evict_something(dev, &dev_priv->gtt.base,
+               ret = i915_gem_evict_something(dev, &dev_priv->ggtt.base,
                                               GEN6_PD_SIZE, GEN6_PD_ALIGN,
                                               I915_CACHE_NONE,
-                                              0, dev_priv->gtt.base.total,
+                                              0, dev_priv->ggtt.base.total,
                                               0);
                if (ret)
                        goto err_out;
@@ -2034,7 +2032,7 @@ alloc:
                goto err_out;
 
 
-       if (ppgtt->node.start < dev_priv->gtt.mappable_end)
+       if (ppgtt->node.start < dev_priv->ggtt.mappable_end)
                DRM_DEBUG("Forced to use aperture for PDEs\n");
 
        return 0;
@@ -2065,7 +2063,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
-       ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode;
+       ppgtt->base.pte_encode = dev_priv->ggtt.base.pte_encode;
        if (IS_GEN6(dev)) {
                ppgtt->switch_mm = gen6_mm_switch;
        } else if (IS_HASWELL(dev)) {
@@ -2095,7 +2093,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
        ppgtt->pd.base.ggtt_offset =
                ppgtt->node.start / PAGE_SIZE * sizeof(gen6_pte_t);
 
-       ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm +
+       ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->ggtt.gsm +
                ppgtt->pd.base.ggtt_offset / sizeof(gen6_pte_t);
 
        gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total);
@@ -2192,7 +2190,7 @@ int i915_ppgtt_init_hw(struct drm_device *dev)
 
 int i915_ppgtt_init_ring(struct drm_i915_gem_request *req)
 {
-       struct drm_i915_private *dev_priv = req->ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = req->i915;
        struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
 
        if (i915.enable_execlists)
@@ -2265,7 +2263,7 @@ static bool do_idling(struct drm_i915_private *dev_priv)
 {
        bool ret = dev_priv->mm.interruptible;
 
-       if (unlikely(dev_priv->gtt.do_idle_maps)) {
+       if (unlikely(dev_priv->ggtt.do_idle_maps)) {
                dev_priv->mm.interruptible = false;
                if (i915_gpu_idle(dev_priv->dev)) {
                        DRM_ERROR("Couldn't idle GPU\n");
@@ -2279,22 +2277,21 @@ static bool do_idling(struct drm_i915_private *dev_priv)
 
 static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
 {
-       if (unlikely(dev_priv->gtt.do_idle_maps))
+       if (unlikely(dev_priv->ggtt.do_idle_maps))
                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_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
        if (INTEL_INFO(dev)->gen < 6)
                return;
 
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine(engine, dev_priv) {
                u32 fault_reg;
-               fault_reg = I915_READ(RING_FAULT_REG(ring));
+               fault_reg = I915_READ(RING_FAULT_REG(engine));
                if (fault_reg & RING_FAULT_VALID) {
                        DRM_DEBUG_DRIVER("Unexpected fault\n"
                                         "\tAddr: 0x%08lx\n"
@@ -2305,11 +2302,11 @@ void i915_check_and_clear_faults(struct drm_device *dev)
                                         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),
+                       I915_WRITE(RING_FAULT_REG(engine),
                                   fault_reg & ~RING_FAULT_VALID);
                }
        }
-       POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS]));
+       POSTING_READ(RING_FAULT_REG(&dev_priv->engine[RCS]));
 }
 
 static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
@@ -2334,9 +2331,9 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
 
        i915_check_and_clear_faults(dev);
 
-       dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
-                                      dev_priv->gtt.base.start,
-                                      dev_priv->gtt.base.total,
+       dev_priv->ggtt.base.clear_range(&dev_priv->ggtt.base,
+                                      dev_priv->ggtt.base.start,
+                                      dev_priv->ggtt.base.total,
                                       true);
 
        i915_ggtt_flush(dev_priv);
@@ -2370,7 +2367,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
        struct drm_i915_private *dev_priv = vm->dev->dev_private;
        unsigned first_entry = start >> PAGE_SHIFT;
        gen8_pte_t __iomem *gtt_entries =
-               (gen8_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
+               (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + first_entry;
        int i = 0;
        struct sg_page_iter sg_iter;
        dma_addr_t addr = 0; /* shut up gcc */
@@ -2447,7 +2444,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
        struct drm_i915_private *dev_priv = vm->dev->dev_private;
        unsigned first_entry = start >> PAGE_SHIFT;
        gen6_pte_t __iomem *gtt_entries =
-               (gen6_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
+               (gen6_pte_t __iomem *)dev_priv->ggtt.gsm + first_entry;
        int i = 0;
        struct sg_page_iter sg_iter;
        dma_addr_t addr = 0;
@@ -2491,8 +2488,8 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
        unsigned first_entry = start >> PAGE_SHIFT;
        unsigned num_entries = length >> PAGE_SHIFT;
        gen8_pte_t scratch_pte, __iomem *gtt_base =
-               (gen8_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
-       const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
+               (gen8_pte_t __iomem *) dev_priv->ggtt.gsm + first_entry;
+       const int max_entries = gtt_total_entries(dev_priv->ggtt) - first_entry;
        int i;
        int rpm_atomic_seq;
 
@@ -2522,8 +2519,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
        unsigned first_entry = start >> PAGE_SHIFT;
        unsigned num_entries = length >> PAGE_SHIFT;
        gen6_pte_t scratch_pte, __iomem *gtt_base =
-               (gen6_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
-       const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
+               (gen6_pte_t __iomem *) dev_priv->ggtt.gsm + first_entry;
+       const int max_entries = gtt_total_entries(dev_priv->ggtt) - first_entry;
        int i;
        int rpm_atomic_seq;
 
@@ -2613,32 +2610,31 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
                                 enum i915_cache_level cache_level,
                                 u32 flags)
 {
-       struct drm_device *dev = vma->vm->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_i915_gem_object *obj = vma->obj;
-       struct sg_table *pages = obj->pages;
-       u32 pte_flags = 0;
+       u32 pte_flags;
        int ret;
 
        ret = i915_get_ggtt_vma_pages(vma);
        if (ret)
                return ret;
-       pages = vma->ggtt_view.pages;
 
        /* Currently applicable only to VLV */
-       if (obj->gt_ro)
+       pte_flags = 0;
+       if (vma->obj->gt_ro)
                pte_flags |= PTE_READ_ONLY;
 
 
        if (flags & GLOBAL_BIND) {
-               vma->vm->insert_entries(vma->vm, pages,
+               vma->vm->insert_entries(vma->vm,
+                                       vma->ggtt_view.pages,
                                        vma->node.start,
                                        cache_level, pte_flags);
        }
 
        if (flags & LOCAL_BIND) {
-               struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
-               appgtt->base.insert_entries(&appgtt->base, pages,
+               struct i915_hw_ppgtt *appgtt =
+                       to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
+               appgtt->base.insert_entries(&appgtt->base,
+                                           vma->ggtt_view.pages,
                                            vma->node.start,
                                            cache_level, pte_flags);
        }
@@ -2718,7 +2714,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
         * of the aperture.
         */
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
+       struct i915_address_space *ggtt_vm = &dev_priv->ggtt.base;
        struct drm_mm_node *entry;
        struct drm_i915_gem_object *obj;
        unsigned long hole_start, hole_end;
@@ -2801,8 +2797,8 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
                                        true);
 
                dev_priv->mm.aliasing_ppgtt = ppgtt;
-               WARN_ON(dev_priv->gtt.base.bind_vma != ggtt_bind_vma);
-               dev_priv->gtt.base.bind_vma = aliasing_gtt_bind_vma;
+               WARN_ON(dev_priv->ggtt.base.bind_vma != ggtt_bind_vma);
+               dev_priv->ggtt.base.bind_vma = aliasing_gtt_bind_vma;
        }
 
        return 0;
@@ -2813,8 +2809,8 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        u64 gtt_size, mappable_size;
 
-       gtt_size = dev_priv->gtt.base.total;
-       mappable_size = dev_priv->gtt.mappable_end;
+       gtt_size = dev_priv->ggtt.base.total;
+       mappable_size = dev_priv->ggtt.mappable_end;
 
        i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
 }
@@ -2822,7 +2818,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
 void i915_global_gtt_cleanup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct i915_address_space *vm = &dev_priv->gtt.base;
+       struct i915_address_space *vm = &dev_priv->ggtt.base;
 
        if (dev_priv->mm.aliasing_ppgtt) {
                struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
@@ -2940,10 +2936,10 @@ static int ggtt_probe_common(struct drm_device *dev,
         * readback check when writing GTT PTE entries.
         */
        if (IS_BROXTON(dev))
-               dev_priv->gtt.gsm = ioremap_nocache(gtt_phys_addr, gtt_size);
+               dev_priv->ggtt.gsm = ioremap_nocache(gtt_phys_addr, gtt_size);
        else
-               dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size);
-       if (!dev_priv->gtt.gsm) {
+               dev_priv->ggtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size);
+       if (!dev_priv->ggtt.gsm) {
                DRM_ERROR("Failed to map the gtt page table\n");
                return -ENOMEM;
        }
@@ -2952,11 +2948,11 @@ static int ggtt_probe_common(struct drm_device *dev,
        if (IS_ERR(scratch_page)) {
                DRM_ERROR("Scratch setup failed\n");
                /* iounmap will also get called at remove, but meh */
-               iounmap(dev_priv->gtt.gsm);
+               iounmap(dev_priv->ggtt.gsm);
                return PTR_ERR(scratch_page);
        }
 
-       dev_priv->gtt.base.scratch_page = scratch_page;
+       dev_priv->ggtt.base.scratch_page = scratch_page;
 
        return 0;
 }
@@ -3034,20 +3030,16 @@ static void chv_setup_private_ppat(struct drm_i915_private *dev_priv)
        I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32);
 }
 
-static int gen8_gmch_probe(struct drm_device *dev,
-                          u64 *gtt_total,
-                          size_t *stolen,
-                          phys_addr_t *mappable_base,
-                          u64 *mappable_end)
+static int gen8_gmch_probe(struct i915_ggtt *ggtt)
 {
+       struct drm_device *dev = ggtt->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u64 gtt_size;
        u16 snb_gmch_ctl;
        int ret;
 
        /* TODO: We're not aware of mappable constraints on gen8 yet */
-       *mappable_base = pci_resource_start(dev->pdev, 2);
-       *mappable_end = pci_resource_len(dev->pdev, 2);
+       ggtt->mappable_base = pci_resource_start(dev->pdev, 2);
+       ggtt->mappable_end = pci_resource_len(dev->pdev, 2);
 
        if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(39)))
                pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(39));
@@ -3055,56 +3047,51 @@ static int gen8_gmch_probe(struct drm_device *dev,
        pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
 
        if (INTEL_INFO(dev)->gen >= 9) {
-               *stolen = gen9_get_stolen_size(snb_gmch_ctl);
-               gtt_size = gen8_get_total_gtt_size(snb_gmch_ctl);
+               ggtt->stolen_size = gen9_get_stolen_size(snb_gmch_ctl);
+               ggtt->size = gen8_get_total_gtt_size(snb_gmch_ctl);
        } else if (IS_CHERRYVIEW(dev)) {
-               *stolen = chv_get_stolen_size(snb_gmch_ctl);
-               gtt_size = chv_get_total_gtt_size(snb_gmch_ctl);
+               ggtt->stolen_size = chv_get_stolen_size(snb_gmch_ctl);
+               ggtt->size = chv_get_total_gtt_size(snb_gmch_ctl);
        } else {
-               *stolen = gen8_get_stolen_size(snb_gmch_ctl);
-               gtt_size = gen8_get_total_gtt_size(snb_gmch_ctl);
+               ggtt->stolen_size = gen8_get_stolen_size(snb_gmch_ctl);
+               ggtt->size = gen8_get_total_gtt_size(snb_gmch_ctl);
        }
 
-       *gtt_total = (gtt_size / sizeof(gen8_pte_t)) << PAGE_SHIFT;
+       ggtt->base.total = (ggtt->size / sizeof(gen8_pte_t)) << PAGE_SHIFT;
 
        if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
                chv_setup_private_ppat(dev_priv);
        else
                bdw_setup_private_ppat(dev_priv);
 
-       ret = ggtt_probe_common(dev, gtt_size);
-
-       dev_priv->gtt.base.clear_range = gen8_ggtt_clear_range;
-       dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries;
-       dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
-       dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
+       ret = ggtt_probe_common(dev, ggtt->size);
 
+       ggtt->base.clear_range = gen8_ggtt_clear_range;
        if (IS_CHERRYVIEW(dev_priv))
-               dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries__BKL;
+               ggtt->base.insert_entries = gen8_ggtt_insert_entries__BKL;
+       else
+               ggtt->base.insert_entries = gen8_ggtt_insert_entries;
+       ggtt->base.bind_vma = ggtt_bind_vma;
+       ggtt->base.unbind_vma = ggtt_unbind_vma;
+
 
        return ret;
 }
 
-static int gen6_gmch_probe(struct drm_device *dev,
-                          u64 *gtt_total,
-                          size_t *stolen,
-                          phys_addr_t *mappable_base,
-                          u64 *mappable_end)
+static int gen6_gmch_probe(struct i915_ggtt *ggtt)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned int gtt_size;
+       struct drm_device *dev = ggtt->base.dev;
        u16 snb_gmch_ctl;
        int ret;
 
-       *mappable_base = pci_resource_start(dev->pdev, 2);
-       *mappable_end = pci_resource_len(dev->pdev, 2);
+       ggtt->mappable_base = pci_resource_start(dev->pdev, 2);
+       ggtt->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 ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) {
-               DRM_ERROR("Unknown GMADR size (%llx)\n",
-                         dev_priv->gtt.mappable_end);
+       if ((ggtt->mappable_end < (64<<20) || (ggtt->mappable_end > (512<<20)))) {
+               DRM_ERROR("Unknown GMADR size (%llx)\n", ggtt->mappable_end);
                return -ENXIO;
        }
 
@@ -3112,36 +3099,31 @@ static int gen6_gmch_probe(struct drm_device *dev,
                pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40));
        pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
 
-       *stolen = gen6_get_stolen_size(snb_gmch_ctl);
-
-       gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl);
-       *gtt_total = (gtt_size / sizeof(gen6_pte_t)) << PAGE_SHIFT;
+       ggtt->stolen_size = gen6_get_stolen_size(snb_gmch_ctl);
+       ggtt->size = gen6_get_total_gtt_size(snb_gmch_ctl);
+       ggtt->base.total = (ggtt->size / sizeof(gen6_pte_t)) << PAGE_SHIFT;
 
-       ret = ggtt_probe_common(dev, gtt_size);
+       ret = ggtt_probe_common(dev, ggtt->size);
 
-       dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range;
-       dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries;
-       dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
-       dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
+       ggtt->base.clear_range = gen6_ggtt_clear_range;
+       ggtt->base.insert_entries = gen6_ggtt_insert_entries;
+       ggtt->base.bind_vma = ggtt_bind_vma;
+       ggtt->base.unbind_vma = ggtt_unbind_vma;
 
        return ret;
 }
 
 static void gen6_gmch_remove(struct i915_address_space *vm)
 {
+       struct i915_ggtt *ggtt = container_of(vm, struct i915_ggtt, base);
 
-       struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
-
-       iounmap(gtt->gsm);
+       iounmap(ggtt->gsm);
        free_scratch_page(vm->dev, vm->scratch_page);
 }
 
-static int i915_gmch_probe(struct drm_device *dev,
-                          u64 *gtt_total,
-                          size_t *stolen,
-                          phys_addr_t *mappable_base,
-                          u64 *mappable_end)
+static int i915_gmch_probe(struct i915_ggtt *ggtt)
 {
+       struct drm_device *dev = ggtt->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
@@ -3151,15 +3133,16 @@ static int i915_gmch_probe(struct drm_device *dev,
                return -EIO;
        }
 
-       intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end);
+       intel_gtt_get(&ggtt->base.total, &ggtt->stolen_size,
+                     &ggtt->mappable_base, &ggtt->mappable_end);
 
-       dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev);
-       dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries;
-       dev_priv->gtt.base.clear_range = i915_ggtt_clear_range;
-       dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
-       dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
+       ggtt->do_idle_maps = needs_idle_maps(dev_priv->dev);
+       ggtt->base.insert_entries = i915_ggtt_insert_entries;
+       ggtt->base.clear_range = i915_ggtt_clear_range;
+       ggtt->base.bind_vma = ggtt_bind_vma;
+       ggtt->base.unbind_vma = ggtt_unbind_vma;
 
-       if (unlikely(dev_priv->gtt.do_idle_maps))
+       if (unlikely(ggtt->do_idle_maps))
                DRM_INFO("applying Ironlake quirks for intel_iommu\n");
 
        return 0;
@@ -3173,38 +3156,45 @@ static void i915_gmch_remove(struct i915_address_space *vm)
 int i915_gem_gtt_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct i915_gtt *gtt = &dev_priv->gtt;
+       struct i915_ggtt *ggtt = &dev_priv->ggtt;
        int ret;
 
        if (INTEL_INFO(dev)->gen <= 5) {
-               gtt->gtt_probe = i915_gmch_probe;
-               gtt->base.cleanup = i915_gmch_remove;
+               ggtt->probe = i915_gmch_probe;
+               ggtt->base.cleanup = i915_gmch_remove;
        } else if (INTEL_INFO(dev)->gen < 8) {
-               gtt->gtt_probe = gen6_gmch_probe;
-               gtt->base.cleanup = gen6_gmch_remove;
+               ggtt->probe = gen6_gmch_probe;
+               ggtt->base.cleanup = gen6_gmch_remove;
                if (IS_HASWELL(dev) && dev_priv->ellc_size)
-                       gtt->base.pte_encode = iris_pte_encode;
+                       ggtt->base.pte_encode = iris_pte_encode;
                else if (IS_HASWELL(dev))
-                       gtt->base.pte_encode = hsw_pte_encode;
+                       ggtt->base.pte_encode = hsw_pte_encode;
                else if (IS_VALLEYVIEW(dev))
-                       gtt->base.pte_encode = byt_pte_encode;
+                       ggtt->base.pte_encode = byt_pte_encode;
                else if (INTEL_INFO(dev)->gen >= 7)
-                       gtt->base.pte_encode = ivb_pte_encode;
+                       ggtt->base.pte_encode = ivb_pte_encode;
                else
-                       gtt->base.pte_encode = snb_pte_encode;
+                       ggtt->base.pte_encode = snb_pte_encode;
        } else {
-               dev_priv->gtt.gtt_probe = gen8_gmch_probe;
-               dev_priv->gtt.base.cleanup = gen6_gmch_remove;
+               ggtt->probe = gen8_gmch_probe;
+               ggtt->base.cleanup = gen6_gmch_remove;
        }
 
-       gtt->base.dev = dev;
-       gtt->base.is_ggtt = true;
+       ggtt->base.dev = dev;
+       ggtt->base.is_ggtt = true;
 
-       ret = gtt->gtt_probe(dev, &gtt->base.total, &gtt->stolen_size,
-                            &gtt->mappable_base, &gtt->mappable_end);
+       ret = ggtt->probe(ggtt);
        if (ret)
                return ret;
 
+       if ((ggtt->base.total - 1) >> 32) {
+               DRM_ERROR("We never expected a Global GTT with more than 32bits"
+                         "of address space! Found %lldM!\n",
+                         ggtt->base.total >> 20);
+               ggtt->base.total = 1ULL << 32;
+               ggtt->mappable_end = min(ggtt->mappable_end, ggtt->base.total);
+       }
+
        /*
         * Initialise stolen early so that we may reserve preallocated
         * objects for the BIOS to KMS transition.
@@ -3215,9 +3205,9 @@ int i915_gem_gtt_init(struct drm_device *dev)
 
        /* GMADR is the PCI mmio aperture into the global GTT. */
        DRM_INFO("Memory usable by graphics device = %lluM\n",
-                gtt->base.total >> 20);
-       DRM_DEBUG_DRIVER("GMADR size = %lldM\n", gtt->mappable_end >> 20);
-       DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20);
+                ggtt->base.total >> 20);
+       DRM_DEBUG_DRIVER("GMADR size = %lldM\n", ggtt->mappable_end >> 20);
+       DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", ggtt->stolen_size >> 20);
 #ifdef CONFIG_INTEL_IOMMU
        if (intel_iommu_gfx_mapped)
                DRM_INFO("VT-d active for gfx access\n");
@@ -3234,7 +3224,7 @@ int i915_gem_gtt_init(struct drm_device *dev)
        return 0;
 
 out_gtt_cleanup:
-       gtt->base.cleanup(&dev_priv->gtt.base);
+       ggtt->base.cleanup(&dev_priv->ggtt.base);
 
        return ret;
 }
@@ -3250,13 +3240,13 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
        i915_check_and_clear_faults(dev);
 
        /* First fill our portion of the GTT with scratch pages */
-       dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
-                                      dev_priv->gtt.base.start,
-                                      dev_priv->gtt.base.total,
+       dev_priv->ggtt.base.clear_range(&dev_priv->ggtt.base,
+                                      dev_priv->ggtt.base.start,
+                                      dev_priv->ggtt.base.total,
                                       true);
 
        /* Cache flush objects bound into GGTT and rebind them. */
-       vm = &dev_priv->gtt.base;
+       vm = &dev_priv->ggtt.base;
        list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
                flush = false;
                list_for_each_entry(vma, &obj->vma_list, obj_link) {
@@ -3377,11 +3367,6 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
        unsigned int column, row;
        unsigned int src_idx;
 
-       if (!sg) {
-               st->nents = 0;
-               sg = st->sgl;
-       }
-
        for (column = 0; column < width; column++) {
                src_idx = stride * (height - 1) + column;
                for (row = 0; row < height; row++) {
@@ -3405,7 +3390,7 @@ static struct sg_table *
 intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
                          struct drm_i915_gem_object *obj)
 {
-       unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
+       unsigned int size_pages = rot_info->plane[0].width * rot_info->plane[0].height;
        unsigned int size_pages_uv;
        struct sg_page_iter sg_iter;
        unsigned long i;
@@ -3423,7 +3408,7 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
 
        /* Account for UV plane with NV12. */
        if (rot_info->pixel_format == DRM_FORMAT_NV12)
-               size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
+               size_pages_uv = rot_info->plane[1].width * rot_info->plane[1].height;
        else
                size_pages_uv = 0;
 
@@ -3443,11 +3428,14 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
                i++;
        }
 
+       st->nents = 0;
+       sg = st->sgl;
+
        /* Rotate the pages. */
        sg = rotate_pages(page_addr_list, 0,
-                    rot_info->width_pages, rot_info->height_pages,
-                    rot_info->width_pages,
-                    st, NULL);
+                         rot_info->plane[0].width, rot_info->plane[0].height,
+                         rot_info->plane[0].width,
+                         st, sg);
 
        /* Append the UV plane if NV12. */
        if (rot_info->pixel_format == DRM_FORMAT_NV12) {
@@ -3459,18 +3447,15 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
 
                rot_info->uv_start_page = uv_start_page;
 
-               rotate_pages(page_addr_list, uv_start_page,
-                            rot_info->width_pages_uv,
-                            rot_info->height_pages_uv,
-                            rot_info->width_pages_uv,
-                            st, sg);
+               sg = rotate_pages(page_addr_list, rot_info->uv_start_page,
+                                 rot_info->plane[1].width, rot_info->plane[1].height,
+                                 rot_info->plane[1].width,
+                                 st, sg);
        }
 
-       DRM_DEBUG_KMS(
-                     "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n",
-                     obj->base.size, rot_info->pitch, rot_info->height,
-                     rot_info->pixel_format, rot_info->width_pages,
-                     rot_info->height_pages, size_pages + size_pages_uv,
+       DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n",
+                     obj->base.size, rot_info->plane[0].width,
+                     rot_info->plane[0].height, size_pages + size_pages_uv,
                      size_pages);
 
        drm_free_large(page_addr_list);
@@ -3482,11 +3467,9 @@ err_sg_alloc:
 err_st_alloc:
        drm_free_large(page_addr_list);
 
-       DRM_DEBUG_KMS(
-                     "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n",
-                     obj->base.size, ret, rot_info->pitch, rot_info->height,
-                     rot_info->pixel_format, rot_info->width_pages,
-                     rot_info->height_pages, size_pages + size_pages_uv,
+       DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%d) (%ux%u tiles, %u pages (%u plane 0))\n",
+                     obj->base.size, ret, rot_info->plane[0].width,
+                     rot_info->plane[0].height, size_pages + size_pages_uv,
                      size_pages);
        return ERR_PTR(ret);
 }
@@ -3634,7 +3617,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
        if (view->type == I915_GGTT_VIEW_NORMAL) {
                return obj->base.size;
        } else if (view->type == I915_GGTT_VIEW_ROTATED) {
-               return view->params.rotated.size;
+               return intel_rotation_info_size(&view->params.rotated) << PAGE_SHIFT;
        } else if (view->type == I915_GGTT_VIEW_PARTIAL) {
                return view->params.partial.size << PAGE_SHIFT;
        } else {
index 8774f1b..d804be0 100644 (file)
@@ -135,16 +135,13 @@ enum i915_ggtt_view_type {
 };
 
 struct intel_rotation_info {
-       unsigned int height;
-       unsigned int pitch;
        unsigned int uv_offset;
        uint32_t pixel_format;
-       uint64_t fb_modifier;
-       unsigned int width_pages, height_pages;
-       uint64_t size;
-       unsigned int width_pages_uv, height_pages_uv;
-       uint64_t size_uv;
        unsigned int uv_start_page;
+       struct {
+               /* tiles */
+               unsigned int width, height;
+       } plane[2];
 };
 
 struct i915_ggtt_view {
@@ -342,13 +339,14 @@ struct i915_address_space {
  * and correct (in cases like swizzling). That region is referred to as GMADR in
  * the spec.
  */
-struct i915_gtt {
+struct i915_ggtt {
        struct i915_address_space base;
 
        size_t stolen_size;             /* Total size of stolen memory */
        size_t stolen_usable_size;      /* Total size minus BIOS reserved */
        size_t stolen_reserved_base;
        size_t stolen_reserved_size;
+       size_t size;                    /* Total size of Global GTT */
        u64 mappable_end;               /* End offset that we can CPU map */
        struct io_mapping *mappable;    /* Mapping to our CPU mappable region */
        phys_addr_t mappable_base;      /* PA of our GMADR */
@@ -360,10 +358,7 @@ struct i915_gtt {
 
        int mtrr;
 
-       /* global gtt ops */
-       int (*gtt_probe)(struct drm_device *dev, u64 *gtt_total,
-                         size_t *stolen, phys_addr_t *mappable_base,
-                         u64 *mappable_end);
+       int (*probe)(struct i915_ggtt *ggtt);
 };
 
 struct i915_hw_ppgtt {
index fc7e6d5..71611bf 100644 (file)
@@ -169,15 +169,15 @@ void i915_gem_render_state_fini(struct render_state *so)
        drm_gem_object_unreference(&so->obj->base);
 }
 
-int i915_gem_render_state_prepare(struct intel_engine_cs *ring,
+int i915_gem_render_state_prepare(struct intel_engine_cs *engine,
                                  struct render_state *so)
 {
        int ret;
 
-       if (WARN_ON(ring->id != RCS))
+       if (WARN_ON(engine->id != RCS))
                return -ENOENT;
 
-       ret = render_state_init(so, ring->dev);
+       ret = render_state_init(so, engine->dev);
        if (ret)
                return ret;
 
@@ -198,21 +198,21 @@ int i915_gem_render_state_init(struct drm_i915_gem_request *req)
        struct render_state so;
        int ret;
 
-       ret = i915_gem_render_state_prepare(req->ring, &so);
+       ret = i915_gem_render_state_prepare(req->engine, &so);
        if (ret)
                return ret;
 
        if (so.rodata == NULL)
                return 0;
 
-       ret = req->ring->dispatch_execbuffer(req, so.ggtt_offset,
+       ret = req->engine->dispatch_execbuffer(req, so.ggtt_offset,
                                             so.rodata->batch_items * 4,
                                             I915_DISPATCH_SECURE);
        if (ret)
                goto out;
 
        if (so.aux_batch_size > 8) {
-               ret = req->ring->dispatch_execbuffer(req,
+               ret = req->engine->dispatch_execbuffer(req,
                                                     (so.ggtt_offset +
                                                      so.aux_batch_offset),
                                                     so.aux_batch_size,
index e641bb0..6aaa3a1 100644 (file)
@@ -43,7 +43,7 @@ struct render_state {
 
 int i915_gem_render_state_init(struct drm_i915_gem_request *req);
 void i915_gem_render_state_fini(struct render_state *so);
-int i915_gem_render_state_prepare(struct intel_engine_cs *ring,
+int i915_gem_render_state_prepare(struct intel_engine_cs *engine,
                                  struct render_state *so);
 
 #endif /* _I915_GEM_RENDER_STATE_H_ */
index 2e6e9fb..de891c9 100644 (file)
@@ -74,7 +74,7 @@ int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
 {
        return i915_gem_stolen_insert_node_in_range(dev_priv, node, size,
                                        alignment, 0,
-                                       dev_priv->gtt.stolen_usable_size);
+                                       dev_priv->ggtt.stolen_usable_size);
 }
 
 void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
@@ -134,7 +134,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
                                         I85X_DRB3, &tmp);
                tom = tmp * MB(32);
 
-               base = tom - tseg_size - dev_priv->gtt.stolen_size;
+               base = tom - tseg_size - dev_priv->ggtt.stolen_size;
        } else if (IS_845G(dev)) {
                u32 tseg_size = 0;
                u32 tom;
@@ -158,7 +158,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
                                         I830_DRB3, &tmp);
                tom = tmp * MB(32);
 
-               base = tom - tseg_size - dev_priv->gtt.stolen_size;
+               base = tom - tseg_size - dev_priv->ggtt.stolen_size;
        } else if (IS_I830(dev)) {
                u32 tseg_size = 0;
                u32 tom;
@@ -178,7 +178,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
                                         I830_DRB3, &tmp);
                tom = tmp * MB(32);
 
-               base = tom - tseg_size - dev_priv->gtt.stolen_size;
+               base = tom - tseg_size - dev_priv->ggtt.stolen_size;
        }
 
        if (base == 0)
@@ -189,8 +189,8 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
                struct {
                        u32 start, end;
                } stolen[2] = {
-                       { .start = base, .end = base + dev_priv->gtt.stolen_size, },
-                       { .start = base, .end = base + dev_priv->gtt.stolen_size, },
+                       { .start = base, .end = base + dev_priv->ggtt.stolen_size, },
+                       { .start = base, .end = base + dev_priv->ggtt.stolen_size, },
                };
                u64 gtt_start, gtt_end;
 
@@ -200,7 +200,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
                                (gtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
                else
                        gtt_start &= PGTBL_ADDRESS_LO_MASK;
-               gtt_end = gtt_start + gtt_total_entries(dev_priv->gtt) * 4;
+               gtt_end = gtt_start + gtt_total_entries(dev_priv->ggtt) * 4;
 
                if (gtt_start >= stolen[0].start && gtt_start < stolen[0].end)
                        stolen[0].end = gtt_start;
@@ -211,10 +211,10 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
                if (stolen[0].end - stolen[0].start >
                    stolen[1].end - stolen[1].start) {
                        base = stolen[0].start;
-                       dev_priv->gtt.stolen_size = stolen[0].end - stolen[0].start;
+                       dev_priv->ggtt.stolen_size = stolen[0].end - stolen[0].start;
                } else {
                        base = stolen[1].start;
-                       dev_priv->gtt.stolen_size = stolen[1].end - stolen[1].start;
+                       dev_priv->ggtt.stolen_size = stolen[1].end - stolen[1].start;
                }
 
                if (stolen[0].start != stolen[1].start ||
@@ -223,7 +223,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
                                      (unsigned long long) gtt_start,
                                      (unsigned long long) gtt_end - 1);
                        DRM_DEBUG_KMS("Stolen memory adjusted to 0x%x-0x%x\n",
-                                     base, base + (u32) dev_priv->gtt.stolen_size - 1);
+                                     base, base + (u32) dev_priv->ggtt.stolen_size - 1);
                }
        }
 
@@ -233,7 +233,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
         * kernel. So if the region is already marked as busy, something
         * is seriously wrong.
         */
-       r = devm_request_mem_region(dev->dev, base, dev_priv->gtt.stolen_size,
+       r = devm_request_mem_region(dev->dev, base, dev_priv->ggtt.stolen_size,
                                    "Graphics Stolen Memory");
        if (r == NULL) {
                /*
@@ -245,7 +245,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
                 * reservation starting from 1 instead of 0.
                 */
                r = devm_request_mem_region(dev->dev, base + 1,
-                                           dev_priv->gtt.stolen_size - 1,
+                                           dev_priv->ggtt.stolen_size - 1,
                                            "Graphics Stolen Memory");
                /*
                 * GEN3 firmware likes to smash pci bridges into the stolen
@@ -253,7 +253,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
                 */
                if (r == NULL && !IS_GEN3(dev)) {
                        DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
-                                 base, base + (uint32_t)dev_priv->gtt.stolen_size);
+                                 base, base + (uint32_t)dev_priv->ggtt.stolen_size);
                        base = 0;
                }
        }
@@ -278,7 +278,7 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv,
                                     CTG_STOLEN_RESERVED :
                                     ELK_STOLEN_RESERVED);
        unsigned long stolen_top = dev_priv->mm.stolen_base +
-               dev_priv->gtt.stolen_size;
+               dev_priv->ggtt.stolen_size;
 
        *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16;
 
@@ -372,7 +372,7 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv,
        uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED);
        unsigned long stolen_top;
 
-       stolen_top = dev_priv->mm.stolen_base + dev_priv->gtt.stolen_size;
+       stolen_top = dev_priv->mm.stolen_base + dev_priv->ggtt.stolen_size;
 
        *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
 
@@ -401,14 +401,14 @@ int i915_gem_init_stolen(struct drm_device *dev)
        }
 #endif
 
-       if (dev_priv->gtt.stolen_size == 0)
+       if (dev_priv->ggtt.stolen_size == 0)
                return 0;
 
        dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
        if (dev_priv->mm.stolen_base == 0)
                return 0;
 
-       stolen_top = dev_priv->mm.stolen_base + dev_priv->gtt.stolen_size;
+       stolen_top = dev_priv->mm.stolen_base + dev_priv->ggtt.stolen_size;
 
        switch (INTEL_INFO(dev_priv)->gen) {
        case 2:
@@ -458,18 +458,18 @@ int i915_gem_init_stolen(struct drm_device *dev)
                return 0;
        }
 
-       dev_priv->gtt.stolen_reserved_base = reserved_base;
-       dev_priv->gtt.stolen_reserved_size = reserved_size;
+       dev_priv->ggtt.stolen_reserved_base = reserved_base;
+       dev_priv->ggtt.stolen_reserved_size = reserved_size;
 
        /* It is possible for the reserved area to end before the end of stolen
         * memory, so just consider the start. */
        reserved_total = stolen_top - reserved_base;
 
        DRM_DEBUG_KMS("Memory reserved for graphics device: %zuK, usable: %luK\n",
-                     dev_priv->gtt.stolen_size >> 10,
-                     (dev_priv->gtt.stolen_size - reserved_total) >> 10);
+                     dev_priv->ggtt.stolen_size >> 10,
+                     (dev_priv->ggtt.stolen_size - reserved_total) >> 10);
 
-       dev_priv->gtt.stolen_usable_size = dev_priv->gtt.stolen_size -
+       dev_priv->ggtt.stolen_usable_size = dev_priv->ggtt.stolen_size -
                                           reserved_total;
 
        /*
@@ -483,7 +483,7 @@ int i915_gem_init_stolen(struct drm_device *dev)
         * i915_gem_stolen_insert_node_in_range(). We may want to fix the fbcon
         * problem later.
         */
-       drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size);
+       drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->ggtt.stolen_usable_size);
 
        return 0;
 }
@@ -497,7 +497,7 @@ i915_pages_create_for_stolen(struct drm_device *dev,
        struct scatterlist *sg;
 
        DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size);
-       BUG_ON(offset > dev_priv->gtt.stolen_size - size);
+       BUG_ON(offset > dev_priv->ggtt.stolen_size - size);
 
        /* We hide that we have no struct page backing our stolen object
         * by wrapping the contiguous physical allocation with a fake
@@ -629,7 +629,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
                                               u32 size)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct i915_address_space *ggtt = &dev_priv->gtt.base;
+       struct i915_address_space *ggtt = &dev_priv->ggtt.base;
        struct drm_i915_gem_object *obj;
        struct drm_mm_node *stolen;
        struct i915_vma *vma;
index 6be40f3..291a939 100644 (file)
@@ -758,6 +758,13 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file
        int ret;
        u32 handle;
 
+       if (!HAS_LLC(dev) && !HAS_SNOOP(dev)) {
+               /* We cannot support coherent userptr objects on hw without
+                * LLC and broken snooping.
+                */
+               return -ENODEV;
+       }
+
        if (args->flags & ~(I915_USERPTR_READ_ONLY |
                            I915_USERPTR_UNSYNCHRONIZED))
                return -EINVAL;
index 831895b..54c2086 100644 (file)
@@ -198,7 +198,7 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m,
                           err->size,
                           err->read_domains,
                           err->write_domain);
-               for (i = 0; i < I915_NUM_RINGS; i++)
+               for (i = 0; i < I915_NUM_ENGINES; i++)
                        err_printf(m, "%02x ", err->rseqno[i]);
 
                err_printf(m, "] %02x", err->wseqno);
@@ -230,8 +230,6 @@ static const char *hangcheck_action_to_str(enum intel_ring_hangcheck_action a)
                return "wait";
        case HANGCHECK_ACTIVE:
                return "active";
-       case HANGCHECK_ACTIVE_LOOP:
-               return "active (loop)";
        case HANGCHECK_KICK:
                return "kick";
        case HANGCHECK_HUNG:
@@ -433,7 +431,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
        for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
                obj = error->ring[i].batchbuffer;
                if (obj) {
-                       err_puts(m, dev_priv->ring[i].name);
+                       err_puts(m, dev_priv->engine[i].name);
                        if (error->ring[i].pid != -1)
                                err_printf(m, " (submitted by %s [%d])",
                                           error->ring[i].comm,
@@ -447,14 +445,14 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
                obj = error->ring[i].wa_batchbuffer;
                if (obj) {
                        err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n",
-                                  dev_priv->ring[i].name,
+                                  dev_priv->engine[i].name,
                                   lower_32_bits(obj->gtt_offset));
                        print_error_obj(m, obj);
                }
 
                if (error->ring[i].num_requests) {
                        err_printf(m, "%s --- %d requests\n",
-                                  dev_priv->ring[i].name,
+                                  dev_priv->engine[i].name,
                                   error->ring[i].num_requests);
                        for (j = 0; j < error->ring[i].num_requests; j++) {
                                err_printf(m, "  seqno 0x%08x, emitted %ld, tail 0x%08x\n",
@@ -466,7 +464,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
 
                if ((obj = error->ring[i].ringbuffer)) {
                        err_printf(m, "%s --- ringbuffer = 0x%08x\n",
-                                  dev_priv->ring[i].name,
+                                  dev_priv->engine[i].name,
                                   lower_32_bits(obj->gtt_offset));
                        print_error_obj(m, obj);
                }
@@ -480,7 +478,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
                                hws_page = &obj->pages[LRC_PPHWSP_PN][0];
                        }
                        err_printf(m, "%s --- HW Status = 0x%08llx\n",
-                                  dev_priv->ring[i].name, hws_offset);
+                                  dev_priv->engine[i].name, hws_offset);
                        offset = 0;
                        for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
                                err_printf(m, "[%04x] %08x %08x %08x %08x\n",
@@ -493,9 +491,31 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
                        }
                }
 
+               obj = error->ring[i].wa_ctx;
+               if (obj) {
+                       u64 wa_ctx_offset = obj->gtt_offset;
+                       u32 *wa_ctx_page = &obj->pages[0][0];
+                       struct intel_engine_cs *engine = &dev_priv->engine[RCS];
+                       u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size +
+                                          engine->wa_ctx.per_ctx.size);
+
+                       err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n",
+                                  dev_priv->engine[i].name, wa_ctx_offset);
+                       offset = 0;
+                       for (elt = 0; elt < wa_ctx_size; elt += 4) {
+                               err_printf(m, "[%04x] %08x %08x %08x %08x\n",
+                                          offset,
+                                          wa_ctx_page[elt + 0],
+                                          wa_ctx_page[elt + 1],
+                                          wa_ctx_page[elt + 2],
+                                          wa_ctx_page[elt + 3]);
+                               offset += 16;
+                       }
+               }
+
                if ((obj = error->ring[i].ctx)) {
                        err_printf(m, "%s --- HW Context = 0x%08x\n",
-                                  dev_priv->ring[i].name,
+                                  dev_priv->engine[i].name,
                                   lower_32_bits(obj->gtt_offset));
                        print_error_obj(m, obj);
                }
@@ -585,6 +605,7 @@ static void i915_error_state_free(struct kref *error_ref)
                i915_error_object_free(error->ring[i].hws_page);
                i915_error_object_free(error->ring[i].ctx);
                kfree(error->ring[i].requests);
+               i915_error_object_free(error->ring[i].wa_ctx);
        }
 
        i915_error_object_free(error->semaphore_obj);
@@ -632,7 +653,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
                vma = i915_gem_obj_to_ggtt(src);
        use_ggtt = (src->cache_level == I915_CACHE_NONE &&
                   vma && (vma->bound & GLOBAL_BIND) &&
-                  reloc_offset + num_pages * PAGE_SIZE <= dev_priv->gtt.mappable_end);
+                  reloc_offset + num_pages * PAGE_SIZE <= dev_priv->ggtt.mappable_end);
 
        /* Cannot access stolen address directly, try to use the aperture */
        if (src->stolen) {
@@ -642,7 +663,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
                        goto unwind;
 
                reloc_offset = i915_gem_obj_ggtt_offset(src);
-               if (reloc_offset + num_pages * PAGE_SIZE > dev_priv->gtt.mappable_end)
+               if (reloc_offset + num_pages * PAGE_SIZE > dev_priv->ggtt.mappable_end)
                        goto unwind;
        }
 
@@ -668,7 +689,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
                         * captures what the GPU read.
                         */
 
-                       s = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
+                       s = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable,
                                                     reloc_offset);
                        memcpy_fromio(d, s, PAGE_SIZE);
                        io_mapping_unmap_atomic(s);
@@ -701,7 +722,7 @@ unwind:
        return NULL;
 }
 #define i915_error_ggtt_object_create(dev_priv, src) \
-       i915_error_object_create((dev_priv), (src), &(dev_priv)->gtt.base)
+       i915_error_object_create((dev_priv), (src), &(dev_priv)->ggtt.base)
 
 static void capture_bo(struct drm_i915_error_buffer *err,
                       struct i915_vma *vma)
@@ -711,7 +732,7 @@ static void capture_bo(struct drm_i915_error_buffer *err,
 
        err->size = obj->base.size;
        err->name = obj->base.name;
-       for (i = 0; i < I915_NUM_RINGS; i++)
+       for (i = 0; i < I915_NUM_ENGINES; i++)
                err->rseqno[i] = i915_gem_request_get_seqno(obj->last_read_req[i]);
        err->wseqno = i915_gem_request_get_seqno(obj->last_write_req);
        err->gtt_offset = vma->node.start;
@@ -726,7 +747,7 @@ static void capture_bo(struct drm_i915_error_buffer *err,
        err->purgeable = obj->madv != I915_MADV_WILLNEED;
        err->userptr = obj->userptr.mm != NULL;
        err->ring = obj->last_write_req ?
-                       i915_gem_request_get_ring(obj->last_write_req)->id : -1;
+                       i915_gem_request_get_engine(obj->last_write_req)->id : -1;
        err->cache_level = obj->cache_level;
 }
 
@@ -788,7 +809,7 @@ static uint32_t i915_error_generate_code(struct drm_i915_private *dev_priv,
         * synchronization commands which almost always appear in the case
         * strictly a client bug. Use instdone to differentiate those some.
         */
-       for (i = 0; i < I915_NUM_RINGS; i++) {
+       for (i = 0; i < I915_NUM_ENGINES; i++) {
                if (error->ring[i].hangcheck_action == HANGCHECK_HUNG) {
                        if (ring_id)
                                *ring_id = i;
@@ -821,11 +842,11 @@ static void i915_gem_record_fences(struct drm_device *dev,
 
 static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv,
                                        struct drm_i915_error_state *error,
-                                       struct intel_engine_cs *ring,
+                                       struct intel_engine_cs *engine,
                                        struct drm_i915_error_ring *ering)
 {
        struct intel_engine_cs *to;
-       int i;
+       enum intel_engine_id id;
 
        if (!i915_semaphore_is_enabled(dev_priv->dev))
                return;
@@ -835,68 +856,69 @@ static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv,
                        i915_error_ggtt_object_create(dev_priv,
                                                      dev_priv->semaphore_obj);
 
-       for_each_ring(to, dev_priv, i) {
+       for_each_engine_id(to, dev_priv, id) {
                int idx;
                u16 signal_offset;
                u32 *tmp;
 
-               if (ring == to)
+               if (engine == to)
                        continue;
 
-               signal_offset = (GEN8_SIGNAL_OFFSET(ring, i) & (PAGE_SIZE - 1))
+               signal_offset = (GEN8_SIGNAL_OFFSET(engine, id) & (PAGE_SIZE - 1))
                                / 4;
                tmp = error->semaphore_obj->pages[0];
-               idx = intel_ring_sync_index(ring, to);
+               idx = intel_ring_sync_index(engine, to);
 
                ering->semaphore_mboxes[idx] = tmp[signal_offset];
-               ering->semaphore_seqno[idx] = ring->semaphore.sync_seqno[idx];
+               ering->semaphore_seqno[idx] = engine->semaphore.sync_seqno[idx];
        }
 }
 
 static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv,
-                                       struct intel_engine_cs *ring,
+                                       struct intel_engine_cs *engine,
                                        struct drm_i915_error_ring *ering)
 {
-       ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(ring->mmio_base));
-       ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(ring->mmio_base));
-       ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
-       ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
+       ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(engine->mmio_base));
+       ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(engine->mmio_base));
+       ering->semaphore_seqno[0] = engine->semaphore.sync_seqno[0];
+       ering->semaphore_seqno[1] = engine->semaphore.sync_seqno[1];
 
        if (HAS_VEBOX(dev_priv->dev)) {
                ering->semaphore_mboxes[2] =
-                       I915_READ(RING_SYNC_2(ring->mmio_base));
-               ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
+                       I915_READ(RING_SYNC_2(engine->mmio_base));
+               ering->semaphore_seqno[2] = engine->semaphore.sync_seqno[2];
        }
 }
 
 static void i915_record_ring_state(struct drm_device *dev,
                                   struct drm_i915_error_state *error,
-                                  struct intel_engine_cs *ring,
+                                  struct intel_engine_cs *engine,
                                   struct drm_i915_error_ring *ering)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (INTEL_INFO(dev)->gen >= 6) {
-               ering->rc_psmi = I915_READ(RING_PSMI_CTL(ring->mmio_base));
-               ering->fault_reg = I915_READ(RING_FAULT_REG(ring));
+               ering->rc_psmi = I915_READ(RING_PSMI_CTL(engine->mmio_base));
+               ering->fault_reg = I915_READ(RING_FAULT_REG(engine));
                if (INTEL_INFO(dev)->gen >= 8)
-                       gen8_record_semaphore_state(dev_priv, error, ring, ering);
+                       gen8_record_semaphore_state(dev_priv, error, engine,
+                                                   ering);
                else
-                       gen6_record_semaphore_state(dev_priv, ring, ering);
+                       gen6_record_semaphore_state(dev_priv, engine, ering);
        }
 
        if (INTEL_INFO(dev)->gen >= 4) {
-               ering->faddr = I915_READ(RING_DMA_FADD(ring->mmio_base));
-               ering->ipeir = I915_READ(RING_IPEIR(ring->mmio_base));
-               ering->ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
-               ering->instdone = I915_READ(RING_INSTDONE(ring->mmio_base));
-               ering->instps = I915_READ(RING_INSTPS(ring->mmio_base));
-               ering->bbaddr = I915_READ(RING_BBADDR(ring->mmio_base));
+               ering->faddr = I915_READ(RING_DMA_FADD(engine->mmio_base));
+               ering->ipeir = I915_READ(RING_IPEIR(engine->mmio_base));
+               ering->ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
+               ering->instdone = I915_READ(RING_INSTDONE(engine->mmio_base));
+               ering->instps = I915_READ(RING_INSTPS(engine->mmio_base));
+               ering->bbaddr = I915_READ(RING_BBADDR(engine->mmio_base));
                if (INTEL_INFO(dev)->gen >= 8) {
-                       ering->faddr |= (u64) I915_READ(RING_DMA_FADD_UDW(ring->mmio_base)) << 32;
-                       ering->bbaddr |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32;
+                       ering->faddr |= (u64) I915_READ(RING_DMA_FADD_UDW(engine->mmio_base)) << 32;
+                       ering->bbaddr |= (u64) I915_READ(RING_BBADDR_UDW(engine->mmio_base)) << 32;
                }
-               ering->bbstate = I915_READ(RING_BBSTATE(ring->mmio_base));
+               ering->bbstate = I915_READ(RING_BBSTATE(engine->mmio_base));
        } else {
                ering->faddr = I915_READ(DMA_FADD_I8XX);
                ering->ipeir = I915_READ(IPEIR);
@@ -904,20 +926,20 @@ static void i915_record_ring_state(struct drm_device *dev,
                ering->instdone = I915_READ(GEN2_INSTDONE);
        }
 
-       ering->waiting = waitqueue_active(&ring->irq_queue);
-       ering->instpm = I915_READ(RING_INSTPM(ring->mmio_base));
-       ering->seqno = ring->get_seqno(ring, false);
-       ering->acthd = intel_ring_get_active_head(ring);
-       ering->start = I915_READ_START(ring);
-       ering->head = I915_READ_HEAD(ring);
-       ering->tail = I915_READ_TAIL(ring);
-       ering->ctl = I915_READ_CTL(ring);
+       ering->waiting = waitqueue_active(&engine->irq_queue);
+       ering->instpm = I915_READ(RING_INSTPM(engine->mmio_base));
+       ering->seqno = engine->get_seqno(engine, false);
+       ering->acthd = intel_ring_get_active_head(engine);
+       ering->start = I915_READ_START(engine);
+       ering->head = I915_READ_HEAD(engine);
+       ering->tail = I915_READ_TAIL(engine);
+       ering->ctl = I915_READ_CTL(engine);
 
        if (I915_NEED_GFX_HWS(dev)) {
                i915_reg_t mmio;
 
                if (IS_GEN7(dev)) {
-                       switch (ring->id) {
+                       switch (engine->id) {
                        default:
                        case RCS:
                                mmio = RENDER_HWS_PGA_GEN7;
@@ -932,51 +954,51 @@ static void i915_record_ring_state(struct drm_device *dev,
                                mmio = VEBOX_HWS_PGA_GEN7;
                                break;
                        }
-               } else if (IS_GEN6(ring->dev)) {
-                       mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
+               } else if (IS_GEN6(engine->dev)) {
+                       mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
                } else {
                        /* XXX: gen8 returns to sanity */
-                       mmio = RING_HWS_PGA(ring->mmio_base);
+                       mmio = RING_HWS_PGA(engine->mmio_base);
                }
 
                ering->hws = I915_READ(mmio);
        }
 
-       ering->hangcheck_score = ring->hangcheck.score;
-       ering->hangcheck_action = ring->hangcheck.action;
+       ering->hangcheck_score = engine->hangcheck.score;
+       ering->hangcheck_action = engine->hangcheck.action;
 
        if (USES_PPGTT(dev)) {
                int i;
 
-               ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(ring));
+               ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(engine));
 
                if (IS_GEN6(dev))
                        ering->vm_info.pp_dir_base =
-                               I915_READ(RING_PP_DIR_BASE_READ(ring));
+                               I915_READ(RING_PP_DIR_BASE_READ(engine));
                else if (IS_GEN7(dev))
                        ering->vm_info.pp_dir_base =
-                               I915_READ(RING_PP_DIR_BASE(ring));
+                               I915_READ(RING_PP_DIR_BASE(engine));
                else if (INTEL_INFO(dev)->gen >= 8)
                        for (i = 0; i < 4; i++) {
                                ering->vm_info.pdp[i] =
-                                       I915_READ(GEN8_RING_PDP_UDW(ring, i));
+                                       I915_READ(GEN8_RING_PDP_UDW(engine, i));
                                ering->vm_info.pdp[i] <<= 32;
                                ering->vm_info.pdp[i] |=
-                                       I915_READ(GEN8_RING_PDP_LDW(ring, i));
+                                       I915_READ(GEN8_RING_PDP_LDW(engine, i));
                        }
        }
 }
 
 
-static void i915_gem_record_active_context(struct intel_engine_cs *ring,
+static void i915_gem_record_active_context(struct intel_engine_cs *engine,
                                           struct drm_i915_error_state *error,
                                           struct drm_i915_error_ring *ering)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        struct drm_i915_gem_object *obj;
 
        /* Currently render ring is the only HW context user */
-       if (ring->id != RCS || !error->ccid)
+       if (engine->id != RCS || !error->ccid)
                return;
 
        list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
@@ -997,26 +1019,26 @@ static void i915_gem_record_rings(struct drm_device *dev,
        struct drm_i915_gem_request *request;
        int i, count;
 
-       for (i = 0; i < I915_NUM_RINGS; i++) {
-               struct intel_engine_cs *ring = &dev_priv->ring[i];
+       for (i = 0; i < I915_NUM_ENGINES; i++) {
+               struct intel_engine_cs *engine = &dev_priv->engine[i];
                struct intel_ringbuffer *rbuf;
 
                error->ring[i].pid = -1;
 
-               if (ring->dev == NULL)
+               if (engine->dev == NULL)
                        continue;
 
                error->ring[i].valid = true;
 
-               i915_record_ring_state(dev, error, ring, &error->ring[i]);
+               i915_record_ring_state(dev, error, engine, &error->ring[i]);
 
-               request = i915_gem_find_active_request(ring);
+               request = i915_gem_find_active_request(engine);
                if (request) {
                        struct i915_address_space *vm;
 
                        vm = request->ctx && request->ctx->ppgtt ?
                                &request->ctx->ppgtt->base :
-                               &dev_priv->gtt.base;
+                               &dev_priv->ggtt.base;
 
                        /* We need to copy these to an anonymous buffer
                         * as the simplest method to avoid being overwritten
@@ -1030,7 +1052,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
                        if (HAS_BROKEN_CS_TLB(dev_priv->dev))
                                error->ring[i].wa_batchbuffer =
                                        i915_error_ggtt_object_create(dev_priv,
-                                                            ring->scratch.obj);
+                                                            engine->scratch.obj);
 
                        if (request->pid) {
                                struct task_struct *task;
@@ -1052,11 +1074,11 @@ static void i915_gem_record_rings(struct drm_device *dev,
                         * executed).
                         */
                        if (request)
-                               rbuf = request->ctx->engine[ring->id].ringbuf;
+                               rbuf = request->ctx->engine[engine->id].ringbuf;
                        else
-                               rbuf = dev_priv->kernel_context->engine[ring->id].ringbuf;
+                               rbuf = dev_priv->kernel_context->engine[engine->id].ringbuf;
                } else
-                       rbuf = ring->buffer;
+                       rbuf = engine->buffer;
 
                error->ring[i].cpu_ring_head = rbuf->head;
                error->ring[i].cpu_ring_tail = rbuf->tail;
@@ -1065,12 +1087,19 @@ static void i915_gem_record_rings(struct drm_device *dev,
                        i915_error_ggtt_object_create(dev_priv, rbuf->obj);
 
                error->ring[i].hws_page =
-                       i915_error_ggtt_object_create(dev_priv, ring->status_page.obj);
+                       i915_error_ggtt_object_create(dev_priv,
+                                                     engine->status_page.obj);
+
+               if (engine->wa_ctx.obj) {
+                       error->ring[i].wa_ctx =
+                               i915_error_ggtt_object_create(dev_priv,
+                                                             engine->wa_ctx.obj);
+               }
 
-               i915_gem_record_active_context(ring, error, &error->ring[i]);
+               i915_gem_record_active_context(engine, error, &error->ring[i]);
 
                count = 0;
-               list_for_each_entry(request, &ring->request_list, list)
+               list_for_each_entry(request, &engine->request_list, list)
                        count++;
 
                error->ring[i].num_requests = count;
@@ -1083,7 +1112,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
                }
 
                count = 0;
-               list_for_each_entry(request, &ring->request_list, list) {
+               list_for_each_entry(request, &engine->request_list, list) {
                        struct drm_i915_error_request *erq;
 
                        if (count >= error->ring[i].num_requests) {
@@ -1272,7 +1301,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
 
 static void i915_error_capture_msg(struct drm_device *dev,
                                   struct drm_i915_error_state *error,
-                                  bool wedged,
+                                  u32 engine_mask,
                                   const char *error_msg)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1295,7 +1324,7 @@ static void i915_error_capture_msg(struct drm_device *dev,
        scnprintf(error->error_msg + len, sizeof(error->error_msg) - len,
                  ", reason: %s, action: %s",
                  error_msg,
-                 wedged ? "reset" : "continue");
+                 engine_mask ? "reset" : "continue");
 }
 
 static void i915_capture_gen_state(struct drm_i915_private *dev_priv,
@@ -1318,7 +1347,7 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv,
  * out a structure which becomes available in debugfs for user level tools
  * to pick up.
  */
-void i915_capture_error_state(struct drm_device *dev, bool wedged,
+void i915_capture_error_state(struct drm_device *dev, u32 engine_mask,
                              const char *error_msg)
 {
        static bool warned;
@@ -1346,7 +1375,7 @@ void i915_capture_error_state(struct drm_device *dev, bool wedged,
        error->overlay = intel_overlay_capture_error_state(dev);
        error->display = intel_display_capture_error_state(dev);
 
-       i915_error_capture_msg(dev, error, wedged, error_msg);
+       i915_error_capture_msg(dev, error, engine_mask, error_msg);
        DRM_INFO("%s\n", error->error_msg);
 
        spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
index d7543ef..da86bdb 100644 (file)
@@ -377,11 +377,11 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
                              struct i915_guc_client *client)
 {
        struct drm_i915_private *dev_priv = guc_to_i915(guc);
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct intel_context *ctx = client->owner;
        struct guc_context_desc desc;
        struct sg_table *sg;
-       int i;
+       enum intel_engine_id id;
 
        memset(&desc, 0, sizeof(desc));
 
@@ -390,8 +390,8 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
        desc.priority = client->priority;
        desc.db_id = client->doorbell_id;
 
-       for_each_ring(ring, dev_priv, i) {
-               struct guc_execlist_context *lrc = &desc.lrc[ring->guc_id];
+       for_each_engine_id(engine, dev_priv, id) {
+               struct guc_execlist_context *lrc = &desc.lrc[engine->guc_id];
                struct drm_i915_gem_object *obj;
                uint64_t ctx_desc;
 
@@ -402,27 +402,27 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
                 * for now who owns a GuC client. But for future owner of GuC
                 * client, need to make sure lrc is pinned prior to enter here.
                 */
-               obj = ctx->engine[i].state;
+               obj = ctx->engine[id].state;
                if (!obj)
                        break;  /* XXX: continue? */
 
-               ctx_desc = intel_lr_context_descriptor(ctx, ring);
+               ctx_desc = intel_lr_context_descriptor(ctx, engine);
                lrc->context_desc = (u32)ctx_desc;
 
                /* The state page is after PPHWSP */
                lrc->ring_lcra = i915_gem_obj_ggtt_offset(obj) +
                                LRC_STATE_PN * PAGE_SIZE;
                lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) |
-                               (ring->guc_id << GUC_ELC_ENGINE_OFFSET);
+                               (engine->guc_id << GUC_ELC_ENGINE_OFFSET);
 
-               obj = ctx->engine[i].ringbuf->obj;
+               obj = ctx->engine[id].ringbuf->obj;
 
                lrc->ring_begin = i915_gem_obj_ggtt_offset(obj);
                lrc->ring_end = lrc->ring_begin + obj->base.size - 1;
                lrc->ring_next_free_location = lrc->ring_begin;
                lrc->ring_current_tail_pointer_value = 0;
 
-               desc.engines_used |= (1 << ring->guc_id);
+               desc.engines_used |= (1 << engine->guc_id);
        }
 
        WARN_ON(desc.engines_used == 0);
@@ -542,11 +542,12 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc,
        wq_len = sizeof(struct guc_wq_item) / sizeof(u32) - 1;
        wqi->header = WQ_TYPE_INORDER |
                        (wq_len << WQ_LEN_SHIFT) |
-                       (rq->ring->guc_id << WQ_TARGET_SHIFT) |
+                       (rq->engine->guc_id << WQ_TARGET_SHIFT) |
                        WQ_NO_WCFLUSH_WAIT;
 
        /* The GuC wants only the low-order word of the context descriptor */
-       wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, rq->ring);
+       wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx,
+                                                            rq->engine);
 
        /* The GuC firmware wants the tail index in QWords, not bytes */
        tail = rq->ringbuf->tail >> 3;
@@ -569,7 +570,7 @@ int i915_guc_submit(struct i915_guc_client *client,
                    struct drm_i915_gem_request *rq)
 {
        struct intel_guc *guc = client->guc;
-       unsigned int engine_id = rq->ring->guc_id;
+       unsigned int engine_id = rq->engine->guc_id;
        int q_ret, b_ret;
 
        q_ret = guc_add_workqueue_item(client, rq);
@@ -839,9 +840,9 @@ static void guc_create_ads(struct intel_guc *guc)
        struct guc_ads *ads;
        struct guc_policies *policies;
        struct guc_mmio_reg_state *reg_state;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct page *page;
-       u32 size, i;
+       u32 size;
 
        /* The ads obj includes the struct itself and buffers passed to GuC */
        size = sizeof(struct guc_ads) + sizeof(struct guc_policies) +
@@ -867,11 +868,11 @@ static void guc_create_ads(struct intel_guc *guc)
         * so its address won't change after we've told the GuC where
         * to find it.
         */
-       ring = &dev_priv->ring[RCS];
-       ads->golden_context_lrca = ring->status_page.gfx_addr;
+       engine = &dev_priv->engine[RCS];
+       ads->golden_context_lrca = engine->status_page.gfx_addr;
 
-       for_each_ring(ring, dev_priv, i)
-               ads->eng_state_size[ring->guc_id] = intel_lr_context_size(ring);
+       for_each_engine(engine, dev_priv)
+               ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine);
 
        /* GuC scheduling policies */
        policies = (void *)ads + sizeof(struct guc_ads);
@@ -883,12 +884,12 @@ static void guc_create_ads(struct intel_guc *guc)
        /* MMIO reg state */
        reg_state = (void *)policies + sizeof(struct guc_policies);
 
-       for_each_ring(ring, dev_priv, i) {
-               reg_state->mmio_white_list[ring->guc_id].mmio_start =
-                       ring->mmio_base + GUC_MMIO_WHITE_LIST_START;
+       for_each_engine(engine, dev_priv) {
+               reg_state->mmio_white_list[engine->guc_id].mmio_start =
+                       engine->mmio_base + GUC_MMIO_WHITE_LIST_START;
 
                /* Nothing to be saved or restored for now. */
-               reg_state->mmio_white_list[ring->guc_id].count = 0;
+               reg_state->mmio_white_list[engine->guc_id].count = 0;
        }
 
        ads->reg_state_addr = ads->scheduler_policies +
index d1a46ef..5aa4239 100644 (file)
@@ -994,14 +994,14 @@ static void ironlake_rps_change_irq_handler(struct drm_device *dev)
        return;
 }
 
-static void notify_ring(struct intel_engine_cs *ring)
+static void notify_ring(struct intel_engine_cs *engine)
 {
-       if (!intel_ring_initialized(ring))
+       if (!intel_engine_initialized(engine))
                return;
 
-       trace_i915_gem_request_notify(ring);
+       trace_i915_gem_request_notify(engine);
 
-       wake_up_all(&ring->irq_queue);
+       wake_up_all(&engine->irq_queue);
 }
 
 static void vlv_c0_read(struct drm_i915_private *dev_priv,
@@ -1079,11 +1079,10 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
 
 static bool any_waiters(struct drm_i915_private *dev_priv)
 {
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
-       for_each_ring(ring, dev_priv, i)
-               if (ring->irq_refcount)
+       for_each_engine(engine, dev_priv)
+               if (engine->irq_refcount)
                        return true;
 
        return false;
@@ -1291,9 +1290,9 @@ static void ilk_gt_irq_handler(struct drm_device *dev,
 {
        if (gt_iir &
            (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
-               notify_ring(&dev_priv->ring[RCS]);
+               notify_ring(&dev_priv->engine[RCS]);
        if (gt_iir & ILK_BSD_USER_INTERRUPT)
-               notify_ring(&dev_priv->ring[VCS]);
+               notify_ring(&dev_priv->engine[VCS]);
 }
 
 static void snb_gt_irq_handler(struct drm_device *dev,
@@ -1303,11 +1302,11 @@ static void snb_gt_irq_handler(struct drm_device *dev,
 
        if (gt_iir &
            (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
-               notify_ring(&dev_priv->ring[RCS]);
+               notify_ring(&dev_priv->engine[RCS]);
        if (gt_iir & GT_BSD_USER_INTERRUPT)
-               notify_ring(&dev_priv->ring[VCS]);
+               notify_ring(&dev_priv->engine[VCS]);
        if (gt_iir & GT_BLT_USER_INTERRUPT)
-               notify_ring(&dev_priv->ring[BCS]);
+               notify_ring(&dev_priv->engine[BCS]);
 
        if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
                      GT_BSD_CS_ERROR_INTERRUPT |
@@ -1319,12 +1318,12 @@ static void snb_gt_irq_handler(struct drm_device *dev,
 }
 
 static __always_inline void
-gen8_cs_irq_handler(struct intel_engine_cs *ring, u32 iir, int test_shift)
+gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
 {
        if (iir & (GT_RENDER_USER_INTERRUPT << test_shift))
-               notify_ring(ring);
+               notify_ring(engine);
        if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift))
-               intel_lrc_irq_handler(ring);
+               intel_lrc_irq_handler(engine);
 }
 
 static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
@@ -1338,11 +1337,11 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
                        I915_WRITE_FW(GEN8_GT_IIR(0), iir);
                        ret = IRQ_HANDLED;
 
-                       gen8_cs_irq_handler(&dev_priv->ring[RCS],
-                                       iir, GEN8_RCS_IRQ_SHIFT);
+                       gen8_cs_irq_handler(&dev_priv->engine[RCS],
+                                           iir, GEN8_RCS_IRQ_SHIFT);
 
-                       gen8_cs_irq_handler(&dev_priv->ring[BCS],
-                                       iir, GEN8_BCS_IRQ_SHIFT);
+                       gen8_cs_irq_handler(&dev_priv->engine[BCS],
+                                           iir, GEN8_BCS_IRQ_SHIFT);
                } else
                        DRM_ERROR("The master control interrupt lied (GT0)!\n");
        }
@@ -1353,11 +1352,11 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
                        I915_WRITE_FW(GEN8_GT_IIR(1), iir);
                        ret = IRQ_HANDLED;
 
-                       gen8_cs_irq_handler(&dev_priv->ring[VCS],
-                                       iir, GEN8_VCS1_IRQ_SHIFT);
+                       gen8_cs_irq_handler(&dev_priv->engine[VCS],
+                                           iir, GEN8_VCS1_IRQ_SHIFT);
 
-                       gen8_cs_irq_handler(&dev_priv->ring[VCS2],
-                                       iir, GEN8_VCS2_IRQ_SHIFT);
+                       gen8_cs_irq_handler(&dev_priv->engine[VCS2],
+                                           iir, GEN8_VCS2_IRQ_SHIFT);
                } else
                        DRM_ERROR("The master control interrupt lied (GT1)!\n");
        }
@@ -1368,8 +1367,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
                        I915_WRITE_FW(GEN8_GT_IIR(3), iir);
                        ret = IRQ_HANDLED;
 
-                       gen8_cs_irq_handler(&dev_priv->ring[VECS],
-                                       iir, GEN8_VECS_IRQ_SHIFT);
+                       gen8_cs_irq_handler(&dev_priv->engine[VECS],
+                                           iir, GEN8_VECS_IRQ_SHIFT);
                } else
                        DRM_ERROR("The master control interrupt lied (GT3)!\n");
        }
@@ -1629,7 +1628,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
 
        if (HAS_VEBOX(dev_priv->dev)) {
                if (pm_iir & PM_VEBOX_USER_INTERRUPT)
-                       notify_ring(&dev_priv->ring[VECS]);
+                       notify_ring(&dev_priv->engine[VECS]);
 
                if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT)
                        DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir);
@@ -2449,8 +2448,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
 static void i915_error_wake_up(struct drm_i915_private *dev_priv,
                               bool reset_completed)
 {
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
        /*
         * Notify all waiters for GPU completion events that reset state has
@@ -2460,8 +2458,8 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv,
         */
 
        /* Wake up __wait_seqno, potentially holding dev->struct_mutex. */
-       for_each_ring(ring, dev_priv, i)
-               wake_up_all(&ring->irq_queue);
+       for_each_engine(engine, dev_priv)
+               wake_up_all(&engine->irq_queue);
 
        /* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */
        wake_up_all(&dev_priv->pending_flip_queue);
@@ -2653,14 +2651,14 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
 /**
  * i915_handle_error - handle a gpu error
  * @dev: drm device
- *
+ * @engine_mask: mask representing engines that are hung
  * Do some basic checking of register state at error time and
  * dump it to the syslog.  Also call i915_capture_error_state() to make
  * sure we get a record and make it available in debugfs.  Fire a uevent
  * so userspace knows something bad happened (should trigger collection
  * of a ring dump etc.).
  */
-void i915_handle_error(struct drm_device *dev, bool wedged,
+void i915_handle_error(struct drm_device *dev, u32 engine_mask,
                       const char *fmt, ...)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2671,10 +2669,10 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
        vscnprintf(error_msg, sizeof(error_msg), fmt, args);
        va_end(args);
 
-       i915_capture_error_state(dev, wedged, error_msg);
+       i915_capture_error_state(dev, engine_mask, error_msg);
        i915_report_and_clear_eir(dev);
 
-       if (wedged) {
+       if (engine_mask) {
                atomic_or(I915_RESET_IN_PROGRESS_FLAG,
                                &dev_priv->gpu_error.reset_counter);
 
@@ -2805,10 +2803,10 @@ static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe)
 }
 
 static bool
-ring_idle(struct intel_engine_cs *ring, u32 seqno)
+ring_idle(struct intel_engine_cs *engine, u32 seqno)
 {
-       return (list_empty(&ring->request_list) ||
-               i915_seqno_passed(seqno, ring->last_submitted_seqno));
+       return (list_empty(&engine->request_list) ||
+               i915_seqno_passed(seqno, engine->last_submitted_seqno));
 }
 
 static bool
@@ -2824,42 +2822,42 @@ ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
 }
 
 static struct intel_engine_cs *
-semaphore_wait_to_signaller_ring(struct intel_engine_cs *ring, u32 ipehr, u64 offset)
+semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr,
+                                u64 offset)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        struct intel_engine_cs *signaller;
-       int i;
 
        if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
-               for_each_ring(signaller, dev_priv, i) {
-                       if (ring == signaller)
+               for_each_engine(signaller, dev_priv) {
+                       if (engine == signaller)
                                continue;
 
-                       if (offset == signaller->semaphore.signal_ggtt[ring->id])
+                       if (offset == signaller->semaphore.signal_ggtt[engine->id])
                                return signaller;
                }
        } else {
                u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
 
-               for_each_ring(signaller, dev_priv, i) {
-                       if(ring == signaller)
+               for_each_engine(signaller, dev_priv) {
+                       if(engine == signaller)
                                continue;
 
-                       if (sync_bits == signaller->semaphore.mbox.wait[ring->id])
+                       if (sync_bits == signaller->semaphore.mbox.wait[engine->id])
                                return signaller;
                }
        }
 
        DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x, offset 0x%016llx\n",
-                 ring->id, ipehr, offset);
+                 engine->id, ipehr, offset);
 
        return NULL;
 }
 
 static struct intel_engine_cs *
-semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
+semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        u32 cmd, ipehr, head;
        u64 offset = 0;
        int i, backwards;
@@ -2881,11 +2879,11 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
         * Therefore, this function does not support execlist mode in its
         * current form. Just return NULL and move on.
         */
-       if (ring->buffer == NULL)
+       if (engine->buffer == NULL)
                return NULL;
 
-       ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
-       if (!ipehr_is_semaphore_wait(ring->dev, ipehr))
+       ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
+       if (!ipehr_is_semaphore_wait(engine->dev, ipehr))
                return NULL;
 
        /*
@@ -2896,8 +2894,8 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
         * point at at batch, and semaphores are always emitted into the
         * ringbuffer itself.
         */
-       head = I915_READ_HEAD(ring) & HEAD_ADDR;
-       backwards = (INTEL_INFO(ring->dev)->gen >= 8) ? 5 : 4;
+       head = I915_READ_HEAD(engine) & HEAD_ADDR;
+       backwards = (INTEL_INFO(engine->dev)->gen >= 8) ? 5 : 4;
 
        for (i = backwards; i; --i) {
                /*
@@ -2905,10 +2903,10 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
                 * our ring is smaller than what the hardware (and hence
                 * HEAD_ADDR) allows. Also handles wrap-around.
                 */
-               head &= ring->buffer->size - 1;
+               head &= engine->buffer->size - 1;
 
                /* This here seems to blow up */
-               cmd = ioread32(ring->buffer->virtual_start + head);
+               cmd = ioread32(engine->buffer->virtual_start + head);
                if (cmd == ipehr)
                        break;
 
@@ -2918,29 +2916,29 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
        if (!i)
                return NULL;
 
-       *seqno = ioread32(ring->buffer->virtual_start + head + 4) + 1;
-       if (INTEL_INFO(ring->dev)->gen >= 8) {
-               offset = ioread32(ring->buffer->virtual_start + head + 12);
+       *seqno = ioread32(engine->buffer->virtual_start + head + 4) + 1;
+       if (INTEL_INFO(engine->dev)->gen >= 8) {
+               offset = ioread32(engine->buffer->virtual_start + head + 12);
                offset <<= 32;
-               offset = ioread32(ring->buffer->virtual_start + head + 8);
+               offset = ioread32(engine->buffer->virtual_start + head + 8);
        }
-       return semaphore_wait_to_signaller_ring(ring, ipehr, offset);
+       return semaphore_wait_to_signaller_ring(engine, ipehr, offset);
 }
 
-static int semaphore_passed(struct intel_engine_cs *ring)
+static int semaphore_passed(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        struct intel_engine_cs *signaller;
        u32 seqno;
 
-       ring->hangcheck.deadlock++;
+       engine->hangcheck.deadlock++;
 
-       signaller = semaphore_waits_for(ring, &seqno);
+       signaller = semaphore_waits_for(engine, &seqno);
        if (signaller == NULL)
                return -1;
 
        /* Prevent pathological recursion due to driver bugs */
-       if (signaller->hangcheck.deadlock >= I915_NUM_RINGS)
+       if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES)
                return -1;
 
        if (i915_seqno_passed(signaller->get_seqno(signaller, false), seqno))
@@ -2956,23 +2954,22 @@ static int semaphore_passed(struct intel_engine_cs *ring)
 
 static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
 {
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
-       for_each_ring(ring, dev_priv, i)
-               ring->hangcheck.deadlock = 0;
+       for_each_engine(engine, dev_priv)
+               engine->hangcheck.deadlock = 0;
 }
 
-static bool subunits_stuck(struct intel_engine_cs *ring)
+static bool subunits_stuck(struct intel_engine_cs *engine)
 {
        u32 instdone[I915_NUM_INSTDONE_REG];
        bool stuck;
        int i;
 
-       if (ring->id != RCS)
+       if (engine->id != RCS)
                return true;
 
-       i915_get_extra_instdone(ring->dev, instdone);
+       i915_get_extra_instdone(engine->dev, instdone);
 
        /* There might be unstable subunit states even when
         * actual head is not moving. Filter out the unstable ones by
@@ -2981,49 +2978,44 @@ static bool subunits_stuck(struct intel_engine_cs *ring)
         */
        stuck = true;
        for (i = 0; i < I915_NUM_INSTDONE_REG; i++) {
-               const u32 tmp = instdone[i] | ring->hangcheck.instdone[i];
+               const u32 tmp = instdone[i] | engine->hangcheck.instdone[i];
 
-               if (tmp != ring->hangcheck.instdone[i])
+               if (tmp != engine->hangcheck.instdone[i])
                        stuck = false;
 
-               ring->hangcheck.instdone[i] |= tmp;
+               engine->hangcheck.instdone[i] |= tmp;
        }
 
        return stuck;
 }
 
 static enum intel_ring_hangcheck_action
-head_stuck(struct intel_engine_cs *ring, u64 acthd)
+head_stuck(struct intel_engine_cs *engine, u64 acthd)
 {
-       if (acthd != ring->hangcheck.acthd) {
+       if (acthd != engine->hangcheck.acthd) {
 
                /* Clear subunit states on head movement */
-               memset(ring->hangcheck.instdone, 0,
-                      sizeof(ring->hangcheck.instdone));
-
-               if (acthd > ring->hangcheck.max_acthd) {
-                       ring->hangcheck.max_acthd = acthd;
-                       return HANGCHECK_ACTIVE;
-               }
+               memset(engine->hangcheck.instdone, 0,
+                      sizeof(engine->hangcheck.instdone));
 
-               return HANGCHECK_ACTIVE_LOOP;
+               return HANGCHECK_ACTIVE;
        }
 
-       if (!subunits_stuck(ring))
+       if (!subunits_stuck(engine))
                return HANGCHECK_ACTIVE;
 
        return HANGCHECK_HUNG;
 }
 
 static enum intel_ring_hangcheck_action
-ring_stuck(struct intel_engine_cs *ring, u64 acthd)
+ring_stuck(struct intel_engine_cs *engine, u64 acthd)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum intel_ring_hangcheck_action ha;
        u32 tmp;
 
-       ha = head_stuck(ring, acthd);
+       ha = head_stuck(engine, acthd);
        if (ha != HANGCHECK_HUNG)
                return ha;
 
@@ -3035,24 +3027,24 @@ ring_stuck(struct intel_engine_cs *ring, u64 acthd)
         * and break the hang. This should work on
         * all but the second generation chipsets.
         */
-       tmp = I915_READ_CTL(ring);
+       tmp = I915_READ_CTL(engine);
        if (tmp & RING_WAIT) {
-               i915_handle_error(dev, false,
+               i915_handle_error(dev, 0,
                                  "Kicking stuck wait on %s",
-                                 ring->name);
-               I915_WRITE_CTL(ring, tmp);
+                                 engine->name);
+               I915_WRITE_CTL(engine, tmp);
                return HANGCHECK_KICK;
        }
 
        if (INTEL_INFO(dev)->gen >= 6 && tmp & RING_WAIT_SEMAPHORE) {
-               switch (semaphore_passed(ring)) {
+               switch (semaphore_passed(engine)) {
                default:
                        return HANGCHECK_HUNG;
                case 1:
-                       i915_handle_error(dev, false,
+                       i915_handle_error(dev, 0,
                                          "Kicking stuck semaphore on %s",
-                                         ring->name);
-                       I915_WRITE_CTL(ring, tmp);
+                                         engine->name);
+                       I915_WRITE_CTL(engine, tmp);
                        return HANGCHECK_KICK;
                case 0:
                        return HANGCHECK_WAIT;
@@ -3076,13 +3068,14 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
                container_of(work, typeof(*dev_priv),
                             gpu_error.hangcheck_work.work);
        struct drm_device *dev = dev_priv->dev;
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
        int busy_count = 0, rings_hung = 0;
-       bool stuck[I915_NUM_RINGS] = { 0 };
+       bool stuck[I915_NUM_ENGINES] = { 0 };
 #define BUSY 1
 #define KICK 5
 #define HUNG 20
+#define ACTIVE_DECAY 15
 
        if (!i915.enable_hangcheck)
                return;
@@ -3100,33 +3093,33 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
         */
        intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
 
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine_id(engine, dev_priv, id) {
                u64 acthd;
                u32 seqno;
                bool busy = true;
 
                semaphore_clear_deadlocks(dev_priv);
 
-               seqno = ring->get_seqno(ring, false);
-               acthd = intel_ring_get_active_head(ring);
+               seqno = engine->get_seqno(engine, false);
+               acthd = intel_ring_get_active_head(engine);
 
-               if (ring->hangcheck.seqno == seqno) {
-                       if (ring_idle(ring, seqno)) {
-                               ring->hangcheck.action = HANGCHECK_IDLE;
+               if (engine->hangcheck.seqno == seqno) {
+                       if (ring_idle(engine, seqno)) {
+                               engine->hangcheck.action = HANGCHECK_IDLE;
 
-                               if (waitqueue_active(&ring->irq_queue)) {
+                               if (waitqueue_active(&engine->irq_queue)) {
                                        /* Issue a wake-up to catch stuck h/w. */
-                                       if (!test_and_set_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings)) {
-                                               if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)))
+                                       if (!test_and_set_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings)) {
+                                               if (!(dev_priv->gpu_error.test_irq_rings & intel_engine_flag(engine)))
                                                        DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
-                                                                 ring->name);
+                                                                 engine->name);
                                                else
                                                        DRM_INFO("Fake missed irq on %s\n",
-                                                                ring->name);
-                                               wake_up_all(&ring->irq_queue);
+                                                                engine->name);
+                                               wake_up_all(&engine->irq_queue);
                                        }
                                        /* Safeguard against driver failure */
-                                       ring->hangcheck.score += BUSY;
+                                       engine->hangcheck.score += BUSY;
                                } else
                                        busy = false;
                        } else {
@@ -3145,58 +3138,59 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
                                 * being repeatedly kicked and so responsible
                                 * for stalling the machine.
                                 */
-                               ring->hangcheck.action = ring_stuck(ring,
-                                                                   acthd);
+                               engine->hangcheck.action = ring_stuck(engine,
+                                                                     acthd);
 
-                               switch (ring->hangcheck.action) {
+                               switch (engine->hangcheck.action) {
                                case HANGCHECK_IDLE:
                                case HANGCHECK_WAIT:
-                               case HANGCHECK_ACTIVE:
                                        break;
-                               case HANGCHECK_ACTIVE_LOOP:
-                                       ring->hangcheck.score += BUSY;
+                               case HANGCHECK_ACTIVE:
+                                       engine->hangcheck.score += BUSY;
                                        break;
                                case HANGCHECK_KICK:
-                                       ring->hangcheck.score += KICK;
+                                       engine->hangcheck.score += KICK;
                                        break;
                                case HANGCHECK_HUNG:
-                                       ring->hangcheck.score += HUNG;
-                                       stuck[i] = true;
+                                       engine->hangcheck.score += HUNG;
+                                       stuck[id] = true;
                                        break;
                                }
                        }
                } else {
-                       ring->hangcheck.action = HANGCHECK_ACTIVE;
+                       engine->hangcheck.action = HANGCHECK_ACTIVE;
 
                        /* Gradually reduce the count so that we catch DoS
                         * attempts across multiple batches.
                         */
-                       if (ring->hangcheck.score > 0)
-                               ring->hangcheck.score--;
+                       if (engine->hangcheck.score > 0)
+                               engine->hangcheck.score -= ACTIVE_DECAY;
+                       if (engine->hangcheck.score < 0)
+                               engine->hangcheck.score = 0;
 
                        /* Clear head and subunit states on seqno movement */
-                       ring->hangcheck.acthd = ring->hangcheck.max_acthd = 0;
+                       engine->hangcheck.acthd = 0;
 
-                       memset(ring->hangcheck.instdone, 0,
-                              sizeof(ring->hangcheck.instdone));
+                       memset(engine->hangcheck.instdone, 0,
+                              sizeof(engine->hangcheck.instdone));
                }
 
-               ring->hangcheck.seqno = seqno;
-               ring->hangcheck.acthd = acthd;
+               engine->hangcheck.seqno = seqno;
+               engine->hangcheck.acthd = acthd;
                busy_count += busy;
        }
 
-       for_each_ring(ring, dev_priv, i) {
-               if (ring->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) {
+       for_each_engine_id(engine, dev_priv, id) {
+               if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) {
                        DRM_INFO("%s on %s\n",
-                                stuck[i] ? "stuck" : "no progress",
-                                ring->name);
-                       rings_hung++;
+                                stuck[id] ? "stuck" : "no progress",
+                                engine->name);
+                       rings_hung |= intel_engine_flag(engine);
                }
        }
 
        if (rings_hung) {
-               i915_handle_error(dev, true, "Ring hung");
+               i915_handle_error(dev, rings_hung, "Engine(s) hung");
                goto out;
        }
 
@@ -4044,7 +4038,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
                new_iir = I915_READ16(IIR); /* Flush posted writes */
 
                if (iir & I915_USER_INTERRUPT)
-                       notify_ring(&dev_priv->ring[RCS]);
+                       notify_ring(&dev_priv->engine[RCS]);
 
                for_each_pipe(dev_priv, pipe) {
                        int plane = pipe;
@@ -4240,7 +4234,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
                new_iir = I915_READ(IIR); /* Flush posted writes */
 
                if (iir & I915_USER_INTERRUPT)
-                       notify_ring(&dev_priv->ring[RCS]);
+                       notify_ring(&dev_priv->engine[RCS]);
 
                for_each_pipe(dev_priv, pipe) {
                        int plane = pipe;
@@ -4470,9 +4464,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
                new_iir = I915_READ(IIR); /* Flush posted writes */
 
                if (iir & I915_USER_INTERRUPT)
-                       notify_ring(&dev_priv->ring[RCS]);
+                       notify_ring(&dev_priv->engine[RCS]);
                if (iir & I915_BSD_USER_INTERRUPT)
-                       notify_ring(&dev_priv->ring[VCS]);
+                       notify_ring(&dev_priv->engine[VCS]);
 
                for_each_pipe(dev_priv, pipe) {
                        if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
@@ -4567,8 +4561,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work,
                          i915_hangcheck_elapsed);
 
-       pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
-
        if (IS_GEN2(dev_priv)) {
                dev->max_vblank_count = 0;
                dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
index 278c9c4..1779f02 100644 (file)
@@ -56,6 +56,8 @@ struct i915_params i915 __read_mostly = {
        .edp_vswing = 0,
        .enable_guc_submission = false,
        .guc_log_level = -1,
+       .enable_dp_mst = true,
+       .inject_load_failure = 0,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -201,3 +203,10 @@ MODULE_PARM_DESC(enable_guc_submission, "Enable GuC submission (default:false)")
 module_param_named(guc_log_level, i915.guc_log_level, int, 0400);
 MODULE_PARM_DESC(guc_log_level,
        "GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
+
+module_param_named_unsafe(enable_dp_mst, i915.enable_dp_mst, bool, 0600);
+MODULE_PARM_DESC(enable_dp_mst,
+       "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)");
+module_param_named_unsafe(inject_load_failure, i915.inject_load_failure, uint, 0400);
+MODULE_PARM_DESC(inject_load_failure,
+       "Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)");
index bd5026b..02bc278 100644 (file)
@@ -49,6 +49,7 @@ struct i915_params {
        int use_mmio_flip;
        int mmio_debug;
        int edp_vswing;
+       unsigned int inject_load_failure;
        /* leave bools at the end to not create holes */
        bool enable_hangcheck;
        bool fastboot;
@@ -59,6 +60,7 @@ struct i915_params {
        bool enable_guc_submission;
        bool verbose_state_checks;
        bool nuclear_pageflip;
+       bool enable_dp_mst;
 };
 
 extern struct i915_params i915 __read_mostly;
index f76cbf3..c839ce9 100644 (file)
@@ -164,6 +164,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define  GEN6_GRDOM_RENDER             (1 << 1)
 #define  GEN6_GRDOM_MEDIA              (1 << 2)
 #define  GEN6_GRDOM_BLT                        (1 << 3)
+#define  GEN6_GRDOM_VECS               (1 << 4)
+#define  GEN8_GRDOM_MEDIA2             (1 << 7)
 
 #define RING_PP_DIR_BASE(ring)         _MMIO((ring)->mmio_base+0x228)
 #define RING_PP_DIR_BASE_READ(ring)    _MMIO((ring)->mmio_base+0x518)
@@ -586,6 +588,10 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define GEN7_GPGPU_DISPATCHDIMY         _MMIO(0x2504)
 #define GEN7_GPGPU_DISPATCHDIMZ         _MMIO(0x2508)
 
+/* There are the 16 64-bit CS General Purpose Registers */
+#define HSW_CS_GPR(n)                   _MMIO(0x2600 + (n) * 8)
+#define HSW_CS_GPR_UDW(n)               _MMIO(0x2600 + (n) * 8 + 4)
+
 #define OACONTROL _MMIO(0x2360)
 
 #define _GEN7_PIPEA_DE_LOAD_SL 0x70068
@@ -786,6 +792,7 @@ enum skl_disp_power_wells {
 #define  DSI_PLL_M1_DIV_MASK                   (0x1ff << 0)
 #define CCK_CZ_CLOCK_CONTROL                   0x62
 #define CCK_DISPLAY_CLOCK_CONTROL              0x6b
+#define CCK_DISPLAY_REF_CLOCK_CONTROL          0x6c
 #define  CCK_TRUNK_FORCE_ON                    (1 << 17)
 #define  CCK_TRUNK_FORCE_OFF                   (1 << 16)
 #define  CCK_FREQUENCY_STATUS                  (0x1f << 8)
@@ -1795,6 +1802,7 @@ enum skl_disp_power_wells {
 
 #define VLV_DISPLAY_BASE 0x180000
 #define VLV_MIPI_BASE VLV_DISPLAY_BASE
+#define BXT_MIPI_BASE 0x60000
 
 #define VLV_GU_CTL0    _MMIO(VLV_DISPLAY_BASE + 0x2030)
 #define VLV_GU_CTL1    _MMIO(VLV_DISPLAY_BASE + 0x2034)
@@ -7102,6 +7110,7 @@ enum skl_disp_power_wells {
 #define   GEN9_CCS_TLB_PREFETCH_ENABLE (1<<3)
 
 #define GEN8_ROW_CHICKEN               _MMIO(0xe4f0)
+#define   FLOW_CONTROL_ENABLE          (1<<15)
 #define   PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE        (1<<8)
 #define   STALL_DOP_GATING_DISABLE             (1<<5)
 
@@ -7362,9 +7371,11 @@ enum skl_disp_power_wells {
 /* SBI offsets */
 #define  SBI_SSCDIVINTPHASE                    0x0200
 #define  SBI_SSCDIVINTPHASE6                   0x0600
-#define   SBI_SSCDIVINTPHASE_DIVSEL_MASK       ((0x7f)<<1)
+#define   SBI_SSCDIVINTPHASE_DIVSEL_SHIFT      1
+#define   SBI_SSCDIVINTPHASE_DIVSEL_MASK       (0x7f<<1)
 #define   SBI_SSCDIVINTPHASE_DIVSEL(x)         ((x)<<1)
-#define   SBI_SSCDIVINTPHASE_INCVAL_MASK       ((0x7f)<<8)
+#define   SBI_SSCDIVINTPHASE_INCVAL_SHIFT      8
+#define   SBI_SSCDIVINTPHASE_INCVAL_MASK       (0x7f<<8)
 #define   SBI_SSCDIVINTPHASE_INCVAL(x)         ((x)<<8)
 #define   SBI_SSCDIVINTPHASE_DIR(x)            ((x)<<15)
 #define   SBI_SSCDIVINTPHASE_PROPAGATE         (1<<0)
@@ -7374,6 +7385,8 @@ enum skl_disp_power_wells {
 #define   SBI_SSCCTL_PATHALT                   (1<<3)
 #define   SBI_SSCCTL_DISABLE                   (1<<0)
 #define  SBI_SSCAUXDIV6                                0x0610
+#define   SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT     4
+#define   SBI_SSCAUXDIV_FINALDIV2SEL_MASK      (1<<4)
 #define   SBI_SSCAUXDIV_FINALDIV2SEL(x)                ((x)<<4)
 #define  SBI_DBUFF0                            0x2a00
 #define  SBI_GEN0                              0x1f00
@@ -7651,6 +7664,59 @@ enum skl_disp_power_wells {
 #define PIPE_CSC_POSTOFF_ME(pipe)      _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
 #define PIPE_CSC_POSTOFF_LO(pipe)      _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
 
+/* pipe degamma/gamma LUTs on IVB+ */
+#define _PAL_PREC_INDEX_A      0x4A400
+#define _PAL_PREC_INDEX_B      0x4AC00
+#define _PAL_PREC_INDEX_C      0x4B400
+#define   PAL_PREC_10_12_BIT           (0 << 31)
+#define   PAL_PREC_SPLIT_MODE          (1 << 31)
+#define   PAL_PREC_AUTO_INCREMENT      (1 << 15)
+#define _PAL_PREC_DATA_A       0x4A404
+#define _PAL_PREC_DATA_B       0x4AC04
+#define _PAL_PREC_DATA_C       0x4B404
+#define _PAL_PREC_GC_MAX_A     0x4A410
+#define _PAL_PREC_GC_MAX_B     0x4AC10
+#define _PAL_PREC_GC_MAX_C     0x4B410
+#define _PAL_PREC_EXT_GC_MAX_A 0x4A420
+#define _PAL_PREC_EXT_GC_MAX_B 0x4AC20
+#define _PAL_PREC_EXT_GC_MAX_C 0x4B420
+
+#define PREC_PAL_INDEX(pipe)           _MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B)
+#define PREC_PAL_DATA(pipe)            _MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B)
+#define PREC_PAL_GC_MAX(pipe, i)       _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4)
+#define PREC_PAL_EXT_GC_MAX(pipe, i)   _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4)
+
+/* pipe CSC & degamma/gamma LUTs on CHV */
+#define _CGM_PIPE_A_CSC_COEFF01        (VLV_DISPLAY_BASE + 0x67900)
+#define _CGM_PIPE_A_CSC_COEFF23        (VLV_DISPLAY_BASE + 0x67904)
+#define _CGM_PIPE_A_CSC_COEFF45        (VLV_DISPLAY_BASE + 0x67908)
+#define _CGM_PIPE_A_CSC_COEFF67        (VLV_DISPLAY_BASE + 0x6790C)
+#define _CGM_PIPE_A_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x67910)
+#define _CGM_PIPE_A_DEGAMMA    (VLV_DISPLAY_BASE + 0x66000)
+#define _CGM_PIPE_A_GAMMA      (VLV_DISPLAY_BASE + 0x67000)
+#define _CGM_PIPE_A_MODE       (VLV_DISPLAY_BASE + 0x67A00)
+#define   CGM_PIPE_MODE_GAMMA  (1 << 2)
+#define   CGM_PIPE_MODE_CSC    (1 << 1)
+#define   CGM_PIPE_MODE_DEGAMMA        (1 << 0)
+
+#define _CGM_PIPE_B_CSC_COEFF01        (VLV_DISPLAY_BASE + 0x69900)
+#define _CGM_PIPE_B_CSC_COEFF23        (VLV_DISPLAY_BASE + 0x69904)
+#define _CGM_PIPE_B_CSC_COEFF45        (VLV_DISPLAY_BASE + 0x69908)
+#define _CGM_PIPE_B_CSC_COEFF67        (VLV_DISPLAY_BASE + 0x6990C)
+#define _CGM_PIPE_B_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x69910)
+#define _CGM_PIPE_B_DEGAMMA    (VLV_DISPLAY_BASE + 0x68000)
+#define _CGM_PIPE_B_GAMMA      (VLV_DISPLAY_BASE + 0x69000)
+#define _CGM_PIPE_B_MODE       (VLV_DISPLAY_BASE + 0x69A00)
+
+#define CGM_PIPE_CSC_COEFF01(pipe)     _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF01, _CGM_PIPE_B_CSC_COEFF01)
+#define CGM_PIPE_CSC_COEFF23(pipe)     _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF23, _CGM_PIPE_B_CSC_COEFF23)
+#define CGM_PIPE_CSC_COEFF45(pipe)     _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF45, _CGM_PIPE_B_CSC_COEFF45)
+#define CGM_PIPE_CSC_COEFF67(pipe)     _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF67, _CGM_PIPE_B_CSC_COEFF67)
+#define CGM_PIPE_CSC_COEFF8(pipe)      _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF8, _CGM_PIPE_B_CSC_COEFF8)
+#define CGM_PIPE_DEGAMMA(pipe, i, w)   _MMIO(_PIPE(pipe, _CGM_PIPE_A_DEGAMMA, _CGM_PIPE_B_DEGAMMA) + (i) * 8 + (w) * 4)
+#define CGM_PIPE_GAMMA(pipe, i, w)     _MMIO(_PIPE(pipe, _CGM_PIPE_A_GAMMA, _CGM_PIPE_B_GAMMA) + (i) * 8 + (w) * 4)
+#define CGM_PIPE_MODE(pipe)            _MMIO_PIPE(pipe, _CGM_PIPE_A_MODE, _CGM_PIPE_B_MODE)
+
 /* MIPI DSI registers */
 
 #define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c)   /* ports A and C only */
@@ -7665,58 +7731,62 @@ enum skl_disp_power_wells {
 #define  BXT_MIPI_DIV_SHIFT(port)              \
                        _MIPI_PORT(port, BXT_MIPI1_DIV_SHIFT, \
                                        BXT_MIPI2_DIV_SHIFT)
-/* Var clock divider to generate TX source. Result must be < 39.5 M */
-#define  BXT_MIPI1_ESCLK_VAR_DIV_MASK          (0x3F << 26)
-#define  BXT_MIPI2_ESCLK_VAR_DIV_MASK          (0x3F << 10)
-#define  BXT_MIPI_ESCLK_VAR_DIV_MASK(port)     \
-                       _MIPI_PORT(port, BXT_MIPI1_ESCLK_VAR_DIV_MASK, \
-                                               BXT_MIPI2_ESCLK_VAR_DIV_MASK)
-
-#define  BXT_MIPI_ESCLK_VAR_DIV(port, val)     \
-                       (val << BXT_MIPI_DIV_SHIFT(port))
+
 /* TX control divider to select actual TX clock output from (8x/var) */
-#define  BXT_MIPI1_TX_ESCLK_SHIFT              21
-#define  BXT_MIPI2_TX_ESCLK_SHIFT              5
+#define  BXT_MIPI1_TX_ESCLK_SHIFT              26
+#define  BXT_MIPI2_TX_ESCLK_SHIFT              10
 #define  BXT_MIPI_TX_ESCLK_SHIFT(port)         \
                        _MIPI_PORT(port, BXT_MIPI1_TX_ESCLK_SHIFT, \
                                        BXT_MIPI2_TX_ESCLK_SHIFT)
-#define  BXT_MIPI1_TX_ESCLK_FIXDIV_MASK                (3 << 21)
-#define  BXT_MIPI2_TX_ESCLK_FIXDIV_MASK                (3 << 5)
+#define  BXT_MIPI1_TX_ESCLK_FIXDIV_MASK                (0x3F << 26)
+#define  BXT_MIPI2_TX_ESCLK_FIXDIV_MASK                (0x3F << 10)
 #define  BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port)   \
                        _MIPI_PORT(port, BXT_MIPI1_TX_ESCLK_FIXDIV_MASK, \
-                                               BXT_MIPI2_TX_ESCLK_FIXDIV_MASK)
-#define  BXT_MIPI_TX_ESCLK_8XDIV_BY2(port)     \
-               (0x0 << BXT_MIPI_TX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_TX_ESCLK_8XDIV_BY4(port)     \
-               (0x1 << BXT_MIPI_TX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_TX_ESCLK_8XDIV_BY8(port)     \
-               (0x2 << BXT_MIPI_TX_ESCLK_SHIFT(port))
-/* RX control divider to select actual RX clock output from 8x*/
-#define  BXT_MIPI1_RX_ESCLK_SHIFT              19
-#define  BXT_MIPI2_RX_ESCLK_SHIFT              3
-#define  BXT_MIPI_RX_ESCLK_SHIFT(port)         \
-                       _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_SHIFT, \
-                                       BXT_MIPI2_RX_ESCLK_SHIFT)
-#define  BXT_MIPI1_RX_ESCLK_FIXDIV_MASK                (3 << 19)
-#define  BXT_MIPI2_RX_ESCLK_FIXDIV_MASK                (3 << 3)
-#define  BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port)   \
-               (3 << BXT_MIPI_RX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_RX_ESCLK_8X_BY2(port)        \
-               (1 << BXT_MIPI_RX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_RX_ESCLK_8X_BY3(port)        \
-               (2 << BXT_MIPI_RX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_RX_ESCLK_8X_BY4(port)        \
-               (3 << BXT_MIPI_RX_ESCLK_SHIFT(port))
-/* BXT-A WA: Always prog DPHY dividers to 00 */
-#define  BXT_MIPI1_DPHY_DIV_SHIFT              16
-#define  BXT_MIPI2_DPHY_DIV_SHIFT              0
-#define  BXT_MIPI_DPHY_DIV_SHIFT(port)         \
-                       _MIPI_PORT(port, BXT_MIPI1_DPHY_DIV_SHIFT, \
-                                       BXT_MIPI2_DPHY_DIV_SHIFT)
-#define  BXT_MIPI_1_DPHY_DIVIDER_MASK          (3 << 16)
-#define  BXT_MIPI_2_DPHY_DIVIDER_MASK          (3 << 0)
-#define  BXT_MIPI_DPHY_DIVIDER_MASK(port)      \
-               (3 << BXT_MIPI_DPHY_DIV_SHIFT(port))
+                                       BXT_MIPI2_TX_ESCLK_FIXDIV_MASK)
+#define  BXT_MIPI_TX_ESCLK_DIVIDER(port, val)  \
+               ((val & 0x3F) << BXT_MIPI_TX_ESCLK_SHIFT(port))
+/* RX upper control divider to select actual RX clock output from 8x */
+#define  BXT_MIPI1_RX_ESCLK_UPPER_SHIFT                21
+#define  BXT_MIPI2_RX_ESCLK_UPPER_SHIFT                5
+#define  BXT_MIPI_RX_ESCLK_UPPER_SHIFT(port)           \
+                       _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_UPPER_SHIFT, \
+                                       BXT_MIPI2_RX_ESCLK_UPPER_SHIFT)
+#define  BXT_MIPI1_RX_ESCLK_UPPER_FIXDIV_MASK          (3 << 21)
+#define  BXT_MIPI2_RX_ESCLK_UPPER_FIXDIV_MASK          (3 << 5)
+#define  BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port)     \
+                       _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_UPPER_FIXDIV_MASK, \
+                                       BXT_MIPI2_RX_ESCLK_UPPER_FIXDIV_MASK)
+#define  BXT_MIPI_RX_ESCLK_UPPER_DIVIDER(port, val)    \
+               ((val & 3) << BXT_MIPI_RX_ESCLK_UPPER_SHIFT(port))
+/* 8/3X divider to select the actual 8/3X clock output from 8x */
+#define  BXT_MIPI1_8X_BY3_SHIFT                19
+#define  BXT_MIPI2_8X_BY3_SHIFT                3
+#define  BXT_MIPI_8X_BY3_SHIFT(port)          \
+                       _MIPI_PORT(port, BXT_MIPI1_8X_BY3_SHIFT, \
+                                       BXT_MIPI2_8X_BY3_SHIFT)
+#define  BXT_MIPI1_8X_BY3_DIVIDER_MASK         (3 << 19)
+#define  BXT_MIPI2_8X_BY3_DIVIDER_MASK         (3 << 3)
+#define  BXT_MIPI_8X_BY3_DIVIDER_MASK(port)    \
+                       _MIPI_PORT(port, BXT_MIPI1_8X_BY3_DIVIDER_MASK, \
+                                               BXT_MIPI2_8X_BY3_DIVIDER_MASK)
+#define  BXT_MIPI_8X_BY3_DIVIDER(port, val)    \
+                       ((val & 3) << BXT_MIPI_8X_BY3_SHIFT(port))
+/* RX lower control divider to select actual RX clock output from 8x */
+#define  BXT_MIPI1_RX_ESCLK_LOWER_SHIFT                16
+#define  BXT_MIPI2_RX_ESCLK_LOWER_SHIFT                0
+#define  BXT_MIPI_RX_ESCLK_LOWER_SHIFT(port)           \
+                       _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_LOWER_SHIFT, \
+                                       BXT_MIPI2_RX_ESCLK_LOWER_SHIFT)
+#define  BXT_MIPI1_RX_ESCLK_LOWER_FIXDIV_MASK          (3 << 16)
+#define  BXT_MIPI2_RX_ESCLK_LOWER_FIXDIV_MASK          (3 << 0)
+#define  BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port)     \
+                       _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_LOWER_FIXDIV_MASK, \
+                                       BXT_MIPI2_RX_ESCLK_LOWER_FIXDIV_MASK)
+#define  BXT_MIPI_RX_ESCLK_LOWER_DIVIDER(port, val)    \
+               ((val & 3) << BXT_MIPI_RX_ESCLK_LOWER_SHIFT(port))
+
+#define RX_DIVIDER_BIT_1_2                     0x3
+#define RX_DIVIDER_BIT_3_4                     0xC
 
 /* BXT MIPI mode configure */
 #define  _BXT_MIPIA_TRANS_HACTIVE                      0x6B0F8
@@ -7741,9 +7811,11 @@ enum skl_disp_power_wells {
 #define  BXT_DSIC_16X_BY2              (1 << 10)
 #define  BXT_DSIC_16X_BY3              (2 << 10)
 #define  BXT_DSIC_16X_BY4              (3 << 10)
+#define  BXT_DSIC_16X_MASK             (3 << 10)
 #define  BXT_DSIA_16X_BY2              (1 << 8)
 #define  BXT_DSIA_16X_BY3              (2 << 8)
 #define  BXT_DSIA_16X_BY4              (3 << 8)
+#define  BXT_DSIA_16X_MASK             (3 << 8)
 #define  BXT_DSI_FREQ_SEL_SHIFT                8
 #define  BXT_DSI_FREQ_SEL_MASK         (0xF << BXT_DSI_FREQ_SEL_SHIFT)
 
@@ -7878,8 +7950,8 @@ enum skl_disp_power_wells {
 #define  VID_MODE_FORMAT_MASK                          (0xf << 7)
 #define  VID_MODE_NOT_SUPPORTED                                (0 << 7)
 #define  VID_MODE_FORMAT_RGB565                                (1 << 7)
-#define  VID_MODE_FORMAT_RGB666                                (2 << 7)
-#define  VID_MODE_FORMAT_RGB666_LOOSE                  (3 << 7)
+#define  VID_MODE_FORMAT_RGB666_PACKED                 (2 << 7)
+#define  VID_MODE_FORMAT_RGB666                                (3 << 7)
 #define  VID_MODE_FORMAT_RGB888                                (4 << 7)
 #define  CMD_MODE_CHANNEL_NUMBER_SHIFT                 5
 #define  CMD_MODE_CHANNEL_NUMBER_MASK                  (3 << 5)
@@ -8135,6 +8207,7 @@ enum skl_disp_power_wells {
 #define  READ_REQUEST_PRIORITY_HIGH                    (3 << 3)
 #define  RGB_FLIP_TO_BGR                               (1 << 2)
 
+#define  BXT_PIPE_SELECT_SHIFT                         7
 #define  BXT_PIPE_SELECT_MASK                          (7 << 7)
 #define  BXT_PIPE_SELECT(pipe)                         ((pipe) << 7)
 
index c6188dd..2d576b7 100644 (file)
@@ -370,6 +370,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
        flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
+       intel_runtime_pm_get(dev_priv);
+
        mutex_lock(&dev_priv->rps.hw_lock);
 
        val = intel_freq_opcode(dev_priv, val);
@@ -378,6 +380,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
            val > dev_priv->rps.max_freq ||
            val < dev_priv->rps.min_freq_softlimit) {
                mutex_unlock(&dev_priv->rps.hw_lock);
+               intel_runtime_pm_put(dev_priv);
                return -EINVAL;
        }
 
@@ -398,6 +401,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
        mutex_unlock(&dev_priv->rps.hw_lock);
 
+       intel_runtime_pm_put(dev_priv);
+
        return count;
 }
 
@@ -433,6 +438,8 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
        flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
+       intel_runtime_pm_get(dev_priv);
+
        mutex_lock(&dev_priv->rps.hw_lock);
 
        val = intel_freq_opcode(dev_priv, val);
@@ -441,6 +448,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
            val > dev_priv->rps.max_freq ||
            val > dev_priv->rps.max_freq_softlimit) {
                mutex_unlock(&dev_priv->rps.hw_lock);
+               intel_runtime_pm_put(dev_priv);
                return -EINVAL;
        }
 
@@ -457,6 +465,8 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
        mutex_unlock(&dev_priv->rps.hw_lock);
 
+       intel_runtime_pm_put(dev_priv);
+
        return count;
 
 }
index fa09e55..afdd8ae 100644 (file)
@@ -464,7 +464,7 @@ TRACE_EVENT(i915_gem_ring_sync_to,
            TP_fast_assign(
                           __entry->dev = from->dev->primary->index;
                           __entry->sync_from = from->id;
-                          __entry->sync_to = to_req->ring->id;
+                          __entry->sync_to = to_req->engine->id;
                           __entry->seqno = i915_gem_request_get_seqno(req);
                           ),
 
@@ -486,13 +486,13 @@ TRACE_EVENT(i915_gem_ring_dispatch,
                             ),
 
            TP_fast_assign(
-                          struct intel_engine_cs *ring =
-                                               i915_gem_request_get_ring(req);
-                          __entry->dev = ring->dev->primary->index;
-                          __entry->ring = ring->id;
+                          struct intel_engine_cs *engine =
+                                               i915_gem_request_get_engine(req);
+                          __entry->dev = engine->dev->primary->index;
+                          __entry->ring = engine->id;
                           __entry->seqno = i915_gem_request_get_seqno(req);
                           __entry->flags = flags;
-                          i915_trace_irq_get(ring, req);
+                          i915_trace_irq_get(engine, req);
                           ),
 
            TP_printk("dev=%u, ring=%u, seqno=%u, flags=%x",
@@ -511,8 +511,8 @@ TRACE_EVENT(i915_gem_ring_flush,
                             ),
 
            TP_fast_assign(
-                          __entry->dev = req->ring->dev->primary->index;
-                          __entry->ring = req->ring->id;
+                          __entry->dev = req->engine->dev->primary->index;
+                          __entry->ring = req->engine->id;
                           __entry->invalidate = invalidate;
                           __entry->flush = flush;
                           ),
@@ -533,10 +533,10 @@ DECLARE_EVENT_CLASS(i915_gem_request,
                             ),
 
            TP_fast_assign(
-                          struct intel_engine_cs *ring =
-                                               i915_gem_request_get_ring(req);
-                          __entry->dev = ring->dev->primary->index;
-                          __entry->ring = ring->id;
+                          struct intel_engine_cs *engine =
+                                               i915_gem_request_get_engine(req);
+                          __entry->dev = engine->dev->primary->index;
+                          __entry->ring = engine->id;
                           __entry->seqno = i915_gem_request_get_seqno(req);
                           ),
 
@@ -550,8 +550,8 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add,
 );
 
 TRACE_EVENT(i915_gem_request_notify,
-           TP_PROTO(struct intel_engine_cs *ring),
-           TP_ARGS(ring),
+           TP_PROTO(struct intel_engine_cs *engine),
+           TP_ARGS(engine),
 
            TP_STRUCT__entry(
                             __field(u32, dev)
@@ -560,9 +560,9 @@ TRACE_EVENT(i915_gem_request_notify,
                             ),
 
            TP_fast_assign(
-                          __entry->dev = ring->dev->primary->index;
-                          __entry->ring = ring->id;
-                          __entry->seqno = ring->get_seqno(ring, false);
+                          __entry->dev = engine->dev->primary->index;
+                          __entry->ring = engine->id;
+                          __entry->seqno = engine->get_seqno(engine, false);
                           ),
 
            TP_printk("dev=%u, ring=%u, seqno=%u",
@@ -597,13 +597,13 @@ TRACE_EVENT(i915_gem_request_wait_begin,
             * less desirable.
             */
            TP_fast_assign(
-                          struct intel_engine_cs *ring =
-                                               i915_gem_request_get_ring(req);
-                          __entry->dev = ring->dev->primary->index;
-                          __entry->ring = ring->id;
+                          struct intel_engine_cs *engine =
+                                               i915_gem_request_get_engine(req);
+                          __entry->dev = engine->dev->primary->index;
+                          __entry->ring = engine->id;
                           __entry->seqno = i915_gem_request_get_seqno(req);
                           __entry->blocking =
-                                    mutex_is_locked(&ring->dev->struct_mutex);
+                                    mutex_is_locked(&engine->dev->struct_mutex);
                           ),
 
            TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s",
@@ -777,9 +777,9 @@ DEFINE_EVENT(i915_context, i915_context_free,
  * called only if full ppgtt is enabled.
  */
 TRACE_EVENT(switch_mm,
-       TP_PROTO(struct intel_engine_cs *ring, struct intel_context *to),
+       TP_PROTO(struct intel_engine_cs *engine, struct intel_context *to),
 
-       TP_ARGS(ring, to),
+       TP_ARGS(engine, to),
 
        TP_STRUCT__entry(
                        __field(u32, ring)
@@ -789,10 +789,10 @@ TRACE_EVENT(switch_mm,
        ),
 
        TP_fast_assign(
-                       __entry->ring = ring->id;
+                       __entry->ring = engine->id;
                        __entry->to = to;
                        __entry->vm = to->ppgtt? &to->ppgtt->base : NULL;
-                       __entry->dev = ring->dev->primary->index;
+                       __entry->dev = engine->dev->primary->index;
        ),
 
        TP_printk("dev=%u, ring=%u, ctx=%p, ctx_vm=%p",
index dea7429..2891bcf 100644 (file)
@@ -181,7 +181,7 @@ static int vgt_balloon_space(struct drm_mm *mm,
 int intel_vgt_balloon(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
+       struct i915_address_space *ggtt_vm = &dev_priv->ggtt.base;
        unsigned long ggtt_vm_end = ggtt_vm->start + ggtt_vm->total;
 
        unsigned long mappable_base, mappable_size, mappable_end;
@@ -203,18 +203,18 @@ int intel_vgt_balloon(struct drm_device *dev)
                 unmappable_base, unmappable_size / 1024);
 
        if (mappable_base < ggtt_vm->start ||
-           mappable_end > dev_priv->gtt.mappable_end ||
-           unmappable_base < dev_priv->gtt.mappable_end ||
+           mappable_end > dev_priv->ggtt.mappable_end ||
+           unmappable_base < dev_priv->ggtt.mappable_end ||
            unmappable_end > ggtt_vm_end) {
                DRM_ERROR("Invalid ballooning configuration!\n");
                return -EINVAL;
        }
 
        /* Unmappable graphic memory ballooning */
-       if (unmappable_base > dev_priv->gtt.mappable_end) {
+       if (unmappable_base > dev_priv->ggtt.mappable_end) {
                ret = vgt_balloon_space(&ggtt_vm->mm,
                                        &bl_info.space[2],
-                                       dev_priv->gtt.mappable_end,
+                                       dev_priv->ggtt.mappable_end,
                                        unmappable_base);
 
                if (ret)
@@ -244,11 +244,11 @@ int intel_vgt_balloon(struct drm_device *dev)
                        goto err;
        }
 
-       if (mappable_end < dev_priv->gtt.mappable_end) {
+       if (mappable_end < dev_priv->ggtt.mappable_end) {
                ret = vgt_balloon_space(&ggtt_vm->mm,
                                        &bl_info.space[1],
                                        mappable_end,
-                                       dev_priv->gtt.mappable_end);
+                                       dev_priv->ggtt.mappable_end);
 
                if (ret)
                        goto err;
index 8e579a8..50ff90a 100644 (file)
@@ -96,8 +96,11 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
        crtc_state->update_pipe = false;
        crtc_state->disable_lp_wm = false;
        crtc_state->disable_cxsr = false;
-       crtc_state->wm_changed = false;
+       crtc_state->update_wm_pre = false;
+       crtc_state->update_wm_post = false;
        crtc_state->fb_changed = false;
+       crtc_state->wm.need_postvbl_update = false;
+       crtc_state->fb_bits = 0;
 
        return &crtc_state->base;
 }
index e0b851a..7de7721 100644 (file)
@@ -195,12 +195,10 @@ static void intel_plane_atomic_update(struct drm_plane *plane,
        struct intel_plane_state *intel_state =
                to_intel_plane_state(plane->state);
        struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
-       struct drm_crtc_state *crtc_state =
-               drm_atomic_get_existing_crtc_state(old_state->state, crtc);
 
        if (intel_state->visible)
                intel_plane->update_plane(plane,
-                                         to_intel_crtc_state(crtc_state),
+                                         to_intel_crtc_state(crtc->state),
                                          intel_state);
        else
                intel_plane->disable_plane(plane, crtc);
index 30f9214..fdc8b2a 100644 (file)
@@ -564,23 +564,21 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
 }
 
 /**
- * intel_init_audio - Set up chip specific audio functions
- * @dev: drm device
+ * intel_init_audio_hooks - Set up chip specific audio hooks
+ * @dev_priv: device private
  */
-void intel_init_audio(struct drm_device *dev)
+void intel_init_audio_hooks(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (IS_G4X(dev)) {
+       if (IS_G4X(dev_priv)) {
                dev_priv->display.audio_codec_enable = g4x_audio_codec_enable;
                dev_priv->display.audio_codec_disable = g4x_audio_codec_disable;
-       } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+       } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                dev_priv->display.audio_codec_enable = ilk_audio_codec_enable;
                dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
-       } else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) {
+       } else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) {
                dev_priv->display.audio_codec_enable = hsw_audio_codec_enable;
                dev_priv->display.audio_codec_disable = hsw_audio_codec_disable;
-       } else if (HAS_PCH_SPLIT(dev)) {
+       } else if (HAS_PCH_SPLIT(dev_priv)) {
                dev_priv->display.audio_codec_enable = ilk_audio_codec_enable;
                dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
        }
index bf62a19..9c406b0 100644 (file)
@@ -29,7 +29,9 @@
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
-#include "intel_bios.h"
+
+#define _INTEL_BIOS_PRIVATE
+#include "intel_vbt_defs.h"
 
 /**
  * DOC: Video BIOS Table (VBT)
@@ -480,7 +482,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
                              child->slave_addr,
                              (child->dvo_port == DEVICE_PORT_DVOB) ?
                              "SDVOB" : "SDVOC");
-               p_mapping = &(dev_priv->sdvo_mappings[child->dvo_port - 1]);
+               p_mapping = &dev_priv->vbt.sdvo_mappings[child->dvo_port - 1];
                if (!p_mapping->initialized) {
                        p_mapping->dvo_port = child->dvo_port;
                        p_mapping->slave_addr = child->slave_addr;
@@ -525,10 +527,7 @@ parse_driver_features(struct drm_i915_private *dev_priv,
                return;
 
        if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
-               dev_priv->vbt.edp_support = 1;
-
-       if (driver->dual_frequency)
-               dev_priv->render_reclock_avail = true;
+               dev_priv->vbt.edp.support = 1;
 
        DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled);
        /*
@@ -550,20 +549,20 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 
        edp = find_section(bdb, BDB_EDP);
        if (!edp) {
-               if (dev_priv->vbt.edp_support)
+               if (dev_priv->vbt.edp.support)
                        DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
                return;
        }
 
        switch ((edp->color_depth >> (panel_type * 2)) & 3) {
        case EDP_18BPP:
-               dev_priv->vbt.edp_bpp = 18;
+               dev_priv->vbt.edp.bpp = 18;
                break;
        case EDP_24BPP:
-               dev_priv->vbt.edp_bpp = 24;
+               dev_priv->vbt.edp.bpp = 24;
                break;
        case EDP_30BPP:
-               dev_priv->vbt.edp_bpp = 30;
+               dev_priv->vbt.edp.bpp = 30;
                break;
        }
 
@@ -571,14 +570,14 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
        edp_pps = &edp->power_seqs[panel_type];
        edp_link_params = &edp->link_params[panel_type];
 
-       dev_priv->vbt.edp_pps = *edp_pps;
+       dev_priv->vbt.edp.pps = *edp_pps;
 
        switch (edp_link_params->rate) {
        case EDP_RATE_1_62:
-               dev_priv->vbt.edp_rate = DP_LINK_BW_1_62;
+               dev_priv->vbt.edp.rate = DP_LINK_BW_1_62;
                break;
        case EDP_RATE_2_7:
-               dev_priv->vbt.edp_rate = DP_LINK_BW_2_7;
+               dev_priv->vbt.edp.rate = DP_LINK_BW_2_7;
                break;
        default:
                DRM_DEBUG_KMS("VBT has unknown eDP link rate value %u\n",
@@ -588,13 +587,13 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 
        switch (edp_link_params->lanes) {
        case EDP_LANE_1:
-               dev_priv->vbt.edp_lanes = 1;
+               dev_priv->vbt.edp.lanes = 1;
                break;
        case EDP_LANE_2:
-               dev_priv->vbt.edp_lanes = 2;
+               dev_priv->vbt.edp.lanes = 2;
                break;
        case EDP_LANE_4:
-               dev_priv->vbt.edp_lanes = 4;
+               dev_priv->vbt.edp.lanes = 4;
                break;
        default:
                DRM_DEBUG_KMS("VBT has unknown eDP lane count value %u\n",
@@ -604,16 +603,16 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 
        switch (edp_link_params->preemphasis) {
        case EDP_PREEMPHASIS_NONE:
-               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
+               dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
                break;
        case EDP_PREEMPHASIS_3_5dB:
-               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
+               dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
                break;
        case EDP_PREEMPHASIS_6dB:
-               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
+               dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
                break;
        case EDP_PREEMPHASIS_9_5dB:
-               dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
+               dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
                break;
        default:
                DRM_DEBUG_KMS("VBT has unknown eDP pre-emphasis value %u\n",
@@ -623,16 +622,16 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 
        switch (edp_link_params->vswing) {
        case EDP_VSWING_0_4V:
-               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
+               dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
                break;
        case EDP_VSWING_0_6V:
-               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
+               dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
                break;
        case EDP_VSWING_0_8V:
-               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
+               dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
                break;
        case EDP_VSWING_1_2V:
-               dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
+               dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
                break;
        default:
                DRM_DEBUG_KMS("VBT has unknown eDP voltage swing value %u\n",
@@ -645,10 +644,10 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 
                /* Don't read from VBT if module parameter has valid value*/
                if (i915.edp_vswing) {
-                       dev_priv->edp_low_vswing = i915.edp_vswing == 1;
+                       dev_priv->vbt.edp.low_vswing = i915.edp_vswing == 1;
                } else {
                        vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF;
-                       dev_priv->edp_low_vswing = vswing == 0;
+                       dev_priv->vbt.edp.low_vswing = vswing == 0;
                }
        }
 }
@@ -706,7 +705,7 @@ parse_mipi_config(struct drm_i915_private *dev_priv,
        const struct mipi_pps_data *pps;
 
        /* parse MIPI blocks only if LFP type is MIPI */
-       if (!dev_priv->vbt.has_mipi)
+       if (!intel_bios_is_dsi_present(dev_priv, NULL))
                return;
 
        /* Initialize this to undefined indicating no generic MIPI support */
@@ -1232,14 +1231,6 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
                        continue;
                }
 
-               if (p_child->common.dvo_port >= DVO_PORT_MIPIA
-                   && p_child->common.dvo_port <= DVO_PORT_MIPID
-                   &&p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT) {
-                       DRM_DEBUG_KMS("Found MIPI as LFP\n");
-                       dev_priv->vbt.has_mipi = 1;
-                       dev_priv->vbt.dsi.port = p_child->common.dvo_port;
-               }
-
                child_dev_ptr = dev_priv->vbt.child_dev + count;
                count++;
 
@@ -1431,3 +1422,166 @@ intel_bios_init(struct drm_i915_private *dev_priv)
 
        return 0;
 }
+
+/**
+ * intel_bios_is_tv_present - is integrated TV present in VBT
+ * @dev_priv:  i915 device instance
+ *
+ * Return true if TV is present. If no child devices were parsed from VBT,
+ * assume TV is present.
+ */
+bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv)
+{
+       union child_device_config *p_child;
+       int i;
+
+       if (!dev_priv->vbt.int_tv_support)
+               return false;
+
+       if (!dev_priv->vbt.child_dev_num)
+               return true;
+
+       for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+               p_child = dev_priv->vbt.child_dev + i;
+               /*
+                * If the device type is not TV, continue.
+                */
+               switch (p_child->old.device_type) {
+               case DEVICE_TYPE_INT_TV:
+               case DEVICE_TYPE_TV:
+               case DEVICE_TYPE_TV_SVIDEO_COMPOSITE:
+                       break;
+               default:
+                       continue;
+               }
+               /* Only when the addin_offset is non-zero, it is regarded
+                * as present.
+                */
+               if (p_child->old.addin_offset)
+                       return true;
+       }
+
+       return false;
+}
+
+/**
+ * intel_bios_is_lvds_present - is LVDS present in VBT
+ * @dev_priv:  i915 device instance
+ * @i2c_pin:   i2c pin for LVDS if present
+ *
+ * Return true if LVDS is present. If no child devices were parsed from VBT,
+ * assume LVDS is present.
+ */
+bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin)
+{
+       int i;
+
+       if (!dev_priv->vbt.child_dev_num)
+               return true;
+
+       for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+               union child_device_config *uchild = dev_priv->vbt.child_dev + i;
+               struct old_child_dev_config *child = &uchild->old;
+
+               /* If the device type is not LFP, continue.
+                * We have to check both the new identifiers as well as the
+                * old for compatibility with some BIOSes.
+                */
+               if (child->device_type != DEVICE_TYPE_INT_LFP &&
+                   child->device_type != DEVICE_TYPE_LFP)
+                       continue;
+
+               if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin))
+                       *i2c_pin = child->i2c_pin;
+
+               /* However, we cannot trust the BIOS writers to populate
+                * the VBT correctly.  Since LVDS requires additional
+                * information from AIM blocks, a non-zero addin offset is
+                * a good indicator that the LVDS is actually present.
+                */
+               if (child->addin_offset)
+                       return true;
+
+               /* But even then some BIOS writers perform some black magic
+                * and instantiate the device without reference to any
+                * additional data.  Trust that if the VBT was written into
+                * the OpRegion then they have validated the LVDS's existence.
+                */
+               if (dev_priv->opregion.vbt)
+                       return true;
+       }
+
+       return false;
+}
+
+/**
+ * intel_bios_is_port_edp - is the device in given port eDP
+ * @dev_priv:  i915 device instance
+ * @port:      port to check
+ *
+ * Return true if the device in %port is eDP.
+ */
+bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port)
+{
+       union child_device_config *p_child;
+       static const short port_mapping[] = {
+               [PORT_B] = DVO_PORT_DPB,
+               [PORT_C] = DVO_PORT_DPC,
+               [PORT_D] = DVO_PORT_DPD,
+               [PORT_E] = DVO_PORT_DPE,
+       };
+       int i;
+
+       if (!dev_priv->vbt.child_dev_num)
+               return false;
+
+       for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+               p_child = dev_priv->vbt.child_dev + i;
+
+               if (p_child->common.dvo_port == port_mapping[port] &&
+                   (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) ==
+                   (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS))
+                       return true;
+       }
+
+       return false;
+}
+
+/**
+ * intel_bios_is_dsi_present - is DSI present in VBT
+ * @dev_priv:  i915 device instance
+ * @port:      port for DSI if present
+ *
+ * Return true if DSI is present, and return the port in %port.
+ */
+bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv,
+                              enum port *port)
+{
+       union child_device_config *p_child;
+       u8 dvo_port;
+       int i;
+
+       for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+               p_child = dev_priv->vbt.child_dev + i;
+
+               if (!(p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT))
+                       continue;
+
+               dvo_port = p_child->common.dvo_port;
+
+               switch (dvo_port) {
+               case DVO_PORT_MIPIA:
+               case DVO_PORT_MIPIC:
+                       if (port)
+                               *port = dvo_port - DVO_PORT_MIPIA;
+                       return true;
+               case DVO_PORT_MIPIB:
+               case DVO_PORT_MIPID:
+                       DRM_DEBUG_KMS("VBT has unsupported DSI port %c\n",
+                                     port_name(dvo_port - DVO_PORT_MIPIA));
+                       break;
+               }
+       }
+
+       return false;
+}
index 350d4e0..ab0ea31 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2006 Intel Corporation
+ * Copyright © 2016 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
- *
- * Authors:
- *    Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _INTEL_BIOS_H_
-#define _INTEL_BIOS_H_
-
-/**
- * struct vbt_header - VBT Header structure
- * @signature:         VBT signature, always starts with "$VBT"
- * @version:           Version of this structure
- * @header_size:       Size of this structure
- * @vbt_size:          Size of VBT (VBT Header, BDB Header and data blocks)
- * @vbt_checksum:      Checksum
- * @reserved0:         Reserved
- * @bdb_offset:                Offset of &struct bdb_header from beginning of VBT
- * @aim_offset:                Offsets of add-in data blocks from beginning of VBT
- */
-struct vbt_header {
-       u8 signature[20];
-       u16 version;
-       u16 header_size;
-       u16 vbt_size;
-       u8 vbt_checksum;
-       u8 reserved0;
-       u32 bdb_offset;
-       u32 aim_offset[4];
-} __packed;
-
-/**
- * struct bdb_header - BDB Header structure
- * @signature:         BDB signature "BIOS_DATA_BLOCK"
- * @version:           Version of the data block definitions
- * @header_size:       Size of this structure
- * @bdb_size:          Size of BDB (BDB Header and data blocks)
- */
-struct bdb_header {
-       u8 signature[16];
-       u16 version;
-       u16 header_size;
-       u16 bdb_size;
-} __packed;
-
-/* strictly speaking, this is a "skip" block, but it has interesting info */
-struct vbios_data {
-       u8 type; /* 0 == desktop, 1 == mobile */
-       u8 relstage;
-       u8 chipset;
-       u8 lvds_present:1;
-       u8 tv_present:1;
-       u8 rsvd2:6; /* finish byte */
-       u8 rsvd3[4];
-       u8 signon[155];
-       u8 copyright[61];
-       u16 code_segment;
-       u8 dos_boot_mode;
-       u8 bandwidth_percent;
-       u8 rsvd4; /* popup memory size */
-       u8 resize_pci_bios;
-       u8 rsvd5; /* is crt already on ddc2 */
-} __packed;
-
-/*
- * There are several types of BIOS data blocks (BDBs), each block has
- * an ID and size in the first 3 bytes (ID in first, size in next 2).
- * Known types are listed below.
  */
-#define BDB_GENERAL_FEATURES     1
-#define BDB_GENERAL_DEFINITIONS          2
-#define BDB_OLD_TOGGLE_LIST      3
-#define BDB_MODE_SUPPORT_LIST    4
-#define BDB_GENERIC_MODE_TABLE   5
-#define BDB_EXT_MMIO_REGS        6
-#define BDB_SWF_IO               7
-#define BDB_SWF_MMIO             8
-#define BDB_PSR                          9
-#define BDB_MODE_REMOVAL_TABLE  10
-#define BDB_CHILD_DEVICE_TABLE  11
-#define BDB_DRIVER_FEATURES     12
-#define BDB_DRIVER_PERSISTENCE  13
-#define BDB_EXT_TABLE_PTRS      14
-#define BDB_DOT_CLOCK_OVERRIDE  15
-#define BDB_DISPLAY_SELECT      16
-/* 17 rsvd */
-#define BDB_DRIVER_ROTATION     18
-#define BDB_DISPLAY_REMOVE      19
-#define BDB_OEM_CUSTOM          20
-#define BDB_EFP_LIST            21 /* workarounds for VGA hsync/vsync */
-#define BDB_SDVO_LVDS_OPTIONS   22
-#define BDB_SDVO_PANEL_DTDS     23
-#define BDB_SDVO_LVDS_PNP_IDS   24
-#define BDB_SDVO_LVDS_POWER_SEQ         25
-#define BDB_TV_OPTIONS          26
-#define BDB_EDP                         27
-#define BDB_LVDS_OPTIONS        40
-#define BDB_LVDS_LFP_DATA_PTRS  41
-#define BDB_LVDS_LFP_DATA       42
-#define BDB_LVDS_BACKLIGHT      43
-#define BDB_LVDS_POWER          44
-#define BDB_MIPI_CONFIG                 52
-#define BDB_MIPI_SEQUENCE       53
-#define BDB_SKIP               254 /* VBIOS private block, ignore */
-
-struct bdb_general_features {
-        /* bits 1 */
-       u8 panel_fitting:2;
-       u8 flexaim:1;
-       u8 msg_enable:1;
-       u8 clear_screen:3;
-       u8 color_flip:1;
-
-        /* bits 2 */
-       u8 download_ext_vbt:1;
-       u8 enable_ssc:1;
-       u8 ssc_freq:1;
-       u8 enable_lfp_on_override:1;
-       u8 disable_ssc_ddt:1;
-       u8 rsvd7:1;
-       u8 display_clock_mode:1;
-       u8 rsvd8:1; /* finish byte */
-
-        /* bits 3 */
-       u8 disable_smooth_vision:1;
-       u8 single_dvi:1;
-       u8 rsvd9:1;
-       u8 fdi_rx_polarity_inverted:1;
-       u8 rsvd10:4; /* finish byte */
-
-        /* bits 4 */
-       u8 legacy_monitor_detect;
-
-        /* bits 5 */
-       u8 int_crt_support:1;
-       u8 int_tv_support:1;
-       u8 int_efp_support:1;
-       u8 dp_ssc_enb:1;        /* PCH attached eDP supports SSC */
-       u8 dp_ssc_freq:1;       /* SSC freq for PCH attached eDP */
-       u8 rsvd11:3; /* finish byte */
-} __packed;
-
-/* pre-915 */
-#define GPIO_PIN_DVI_LVDS      0x03 /* "DVI/LVDS DDC GPIO pins" */
-#define GPIO_PIN_ADD_I2C       0x05 /* "ADDCARD I2C GPIO pins" */
-#define GPIO_PIN_ADD_DDC       0x04 /* "ADDCARD DDC GPIO pins" */
-#define GPIO_PIN_ADD_DDC_I2C   0x06 /* "ADDCARD DDC/I2C GPIO pins" */
-
-/* Pre 915 */
-#define DEVICE_TYPE_NONE       0x00
-#define DEVICE_TYPE_CRT                0x01
-#define DEVICE_TYPE_TV         0x09
-#define DEVICE_TYPE_EFP                0x12
-#define DEVICE_TYPE_LFP                0x22
-/* On 915+ */
-#define DEVICE_TYPE_CRT_DPMS           0x6001
-#define DEVICE_TYPE_CRT_DPMS_HOTPLUG   0x4001
-#define DEVICE_TYPE_TV_COMPOSITE       0x0209
-#define DEVICE_TYPE_TV_MACROVISION     0x0289
-#define DEVICE_TYPE_TV_RF_COMPOSITE    0x020c
-#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE        0x0609
-#define DEVICE_TYPE_TV_SCART           0x0209
-#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
-#define DEVICE_TYPE_EFP_HOTPLUG_PWR    0x6012
-#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR        0x6052
-#define DEVICE_TYPE_EFP_DVI_I          0x6053
-#define DEVICE_TYPE_EFP_DVI_D_DUAL     0x6152
-#define DEVICE_TYPE_EFP_DVI_D_HDCP     0x60d2
-#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR        0x6062
-#define DEVICE_TYPE_OPENLDI_DUALPIX    0x6162
-#define DEVICE_TYPE_LFP_PANELLINK      0x5012
-#define DEVICE_TYPE_LFP_CMOS_PWR       0x5042
-#define DEVICE_TYPE_LFP_LVDS_PWR       0x5062
-#define DEVICE_TYPE_LFP_LVDS_DUAL      0x5162
-#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2
-
-#define DEVICE_CFG_NONE                0x00
-#define DEVICE_CFG_12BIT_DVOB  0x01
-#define DEVICE_CFG_12BIT_DVOC  0x02
-#define DEVICE_CFG_24BIT_DVOBC 0x09
-#define DEVICE_CFG_24BIT_DVOCB 0x0a
-#define DEVICE_CFG_DUAL_DVOB   0x11
-#define DEVICE_CFG_DUAL_DVOC   0x12
-#define DEVICE_CFG_DUAL_DVOBC  0x13
-#define DEVICE_CFG_DUAL_LINK_DVOBC     0x19
-#define DEVICE_CFG_DUAL_LINK_DVOCB     0x1a
-
-#define DEVICE_WIRE_NONE       0x00
-#define DEVICE_WIRE_DVOB       0x01
-#define DEVICE_WIRE_DVOC       0x02
-#define DEVICE_WIRE_DVOBC      0x03
-#define DEVICE_WIRE_DVOBB      0x05
-#define DEVICE_WIRE_DVOCC      0x06
-#define DEVICE_WIRE_DVOB_MASTER 0x0d
-#define DEVICE_WIRE_DVOC_MASTER 0x0e
-
-#define DEVICE_PORT_DVOA       0x00 /* none on 845+ */
-#define DEVICE_PORT_DVOB       0x01
-#define DEVICE_PORT_DVOC       0x02
 
 /*
- * We used to keep this struct but without any version control. We should avoid
- * using it in the future, but it should be safe to keep using it in the old
- * code. Do not change; we rely on its size.
+ * Please use intel_vbt_defs.h for VBT private data, to hide and abstract away
+ * the VBT from the rest of the driver. Add the parsed, clean data to struct
+ * intel_vbt_data within struct drm_i915_private.
  */
-struct old_child_dev_config {
-       u16 handle;
-       u16 device_type;
-       u8  device_id[10]; /* ascii string */
-       u16 addin_offset;
-       u8  dvo_port; /* See Device_PORT_* above */
-       u8  i2c_pin;
-       u8  slave_addr;
-       u8  ddc_pin;
-       u16 edid_ptr;
-       u8  dvo_cfg; /* See DEVICE_CFG_* above */
-       u8  dvo2_port;
-       u8  i2c2_pin;
-       u8  slave2_addr;
-       u8  ddc2_pin;
-       u8  capabilities;
-       u8  dvo_wiring;/* See DEVICE_WIRE_* above */
-       u8  dvo2_wiring;
-       u16 extended_type;
-       u8  dvo_function;
-} __packed;
-
-/* This one contains field offsets that are known to be common for all BDB
- * versions. Notice that the meaning of the contents contents may still change,
- * but at least the offsets are consistent. */
-
-/* Definitions for flags_1 */
-#define IBOOST_ENABLE (1<<3)
-
-struct common_child_dev_config {
-       u16 handle;
-       u16 device_type;
-       u8 not_common1[12];
-       u8 dvo_port;
-       u8 not_common2[2];
-       u8 ddc_pin;
-       u16 edid_ptr;
-       u8 obsolete;
-       u8 flags_1;
-       u8 not_common3[13];
-       u8 iboost_level;
-} __packed;
-
-
-/* This field changes depending on the BDB version, so the most reliable way to
- * read it is by checking the BDB version and reading the raw pointer. */
-union child_device_config {
-       /* This one is safe to be used anywhere, but the code should still check
-        * the BDB version. */
-       u8 raw[33];
-       /* This one should only be kept for legacy code. */
-       struct old_child_dev_config old;
-       /* This one should also be safe to use anywhere, even without version
-        * checks. */
-       struct common_child_dev_config common;
-} __packed;
-
-struct bdb_general_definitions {
-       /* DDC GPIO */
-       u8 crt_ddc_gmbus_pin;
-
-       /* DPMS bits */
-       u8 dpms_acpi:1;
-       u8 skip_boot_crt_detect:1;
-       u8 dpms_aim:1;
-       u8 rsvd1:5; /* finish byte */
-
-       /* boot device bits */
-       u8 boot_display[2];
-       u8 child_dev_size;
-
-       /*
-        * Device info:
-        * If TV is present, it'll be at devices[0].
-        * LVDS will be next, either devices[0] or [1], if present.
-        * On some platforms the number of device is 6. But could be as few as
-        * 4 if both TV and LVDS are missing.
-        * And the device num is related with the size of general definition
-        * block. It is obtained by using the following formula:
-        * number = (block_size - sizeof(bdb_general_definitions))/
-        *           defs->child_dev_size;
-        */
-       uint8_t devices[0];
-} __packed;
-
-/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */
-#define MODE_MASK              0x3
-
-struct bdb_lvds_options {
-       u8 panel_type;
-       u8 rsvd1;
-       /* LVDS capabilities, stored in a dword */
-       u8 pfit_mode:2;
-       u8 pfit_text_mode_enhanced:1;
-       u8 pfit_gfx_mode_enhanced:1;
-       u8 pfit_ratio_auto:1;
-       u8 pixel_dither:1;
-       u8 lvds_edid:1;
-       u8 rsvd2:1;
-       u8 rsvd4;
-       /* LVDS Panel channel bits stored here */
-       u32 lvds_panel_channel_bits;
-       /* LVDS SSC (Spread Spectrum Clock) bits stored here. */
-       u16 ssc_bits;
-       u16 ssc_freq;
-       u16 ssc_ddt;
-       /* Panel color depth defined here */
-       u16 panel_color_depth;
-       /* LVDS panel type bits stored here */
-       u32 dps_panel_type_bits;
-       /* LVDS backlight control type bits stored here */
-       u32 blt_control_type_bits;
-} __packed;
-
-/* LFP pointer table contains entries to the struct below */
-struct bdb_lvds_lfp_data_ptr {
-       u16 fp_timing_offset; /* offsets are from start of bdb */
-       u8 fp_table_size;
-       u16 dvo_timing_offset;
-       u8 dvo_table_size;
-       u16 panel_pnp_id_offset;
-       u8 pnp_table_size;
-} __packed;
-
-struct bdb_lvds_lfp_data_ptrs {
-       u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
-       struct bdb_lvds_lfp_data_ptr ptr[16];
-} __packed;
-
-/* LFP data has 3 blocks per entry */
-struct lvds_fp_timing {
-       u16 x_res;
-       u16 y_res;
-       u32 lvds_reg;
-       u32 lvds_reg_val;
-       u32 pp_on_reg;
-       u32 pp_on_reg_val;
-       u32 pp_off_reg;
-       u32 pp_off_reg_val;
-       u32 pp_cycle_reg;
-       u32 pp_cycle_reg_val;
-       u32 pfit_reg;
-       u32 pfit_reg_val;
-       u16 terminator;
-} __packed;
-
-struct lvds_dvo_timing {
-       u16 clock;              /**< In 10khz */
-       u8 hactive_lo;
-       u8 hblank_lo;
-       u8 hblank_hi:4;
-       u8 hactive_hi:4;
-       u8 vactive_lo;
-       u8 vblank_lo;
-       u8 vblank_hi:4;
-       u8 vactive_hi:4;
-       u8 hsync_off_lo;
-       u8 hsync_pulse_width;
-       u8 vsync_pulse_width:4;
-       u8 vsync_off:4;
-       u8 rsvd0:6;
-       u8 hsync_off_hi:2;
-       u8 h_image;
-       u8 v_image;
-       u8 max_hv;
-       u8 h_border;
-       u8 v_border;
-       u8 rsvd1:3;
-       u8 digital:2;
-       u8 vsync_positive:1;
-       u8 hsync_positive:1;
-       u8 rsvd2:1;
-} __packed;
-
-struct lvds_pnp_id {
-       u16 mfg_name;
-       u16 product_code;
-       u32 serial;
-       u8 mfg_week;
-       u8 mfg_year;
-} __packed;
-
-struct bdb_lvds_lfp_data_entry {
-       struct lvds_fp_timing fp_timing;
-       struct lvds_dvo_timing dvo_timing;
-       struct lvds_pnp_id pnp_id;
-} __packed;
-
-struct bdb_lvds_lfp_data {
-       struct bdb_lvds_lfp_data_entry data[16];
-} __packed;
-
-#define BDB_BACKLIGHT_TYPE_NONE        0
-#define BDB_BACKLIGHT_TYPE_PWM 2
-
-struct bdb_lfp_backlight_data_entry {
-       u8 type:2;
-       u8 active_low_pwm:1;
-       u8 obsolete1:5;
-       u16 pwm_freq_hz;
-       u8 min_brightness;
-       u8 obsolete2;
-       u8 obsolete3;
-} __packed;
-
-struct bdb_lfp_backlight_data {
-       u8 entry_size;
-       struct bdb_lfp_backlight_data_entry data[16];
-       u8 level[16];
-} __packed;
-
-struct aimdb_header {
-       char signature[16];
-       char oem_device[20];
-       u16 aimdb_version;
-       u16 aimdb_header_size;
-       u16 aimdb_size;
-} __packed;
-
-struct aimdb_block {
-       u8 aimdb_id;
-       u16 aimdb_size;
-} __packed;
 
-struct vch_panel_data {
-       u16 fp_timing_offset;
-       u8 fp_timing_size;
-       u16 dvo_timing_offset;
-       u8 dvo_timing_size;
-       u16 text_fitting_offset;
-       u8 text_fitting_size;
-       u16 graphics_fitting_offset;
-       u8 graphics_fitting_size;
-} __packed;
-
-struct vch_bdb_22 {
-       struct aimdb_block aimdb_block;
-       struct vch_panel_data panels[16];
-} __packed;
-
-struct bdb_sdvo_lvds_options {
-       u8 panel_backlight;
-       u8 h40_set_panel_type;
-       u8 panel_type;
-       u8 ssc_clk_freq;
-       u16 als_low_trip;
-       u16 als_high_trip;
-       u8 sclalarcoeff_tab_row_num;
-       u8 sclalarcoeff_tab_row_size;
-       u8 coefficient[8];
-       u8 panel_misc_bits_1;
-       u8 panel_misc_bits_2;
-       u8 panel_misc_bits_3;
-       u8 panel_misc_bits_4;
-} __packed;
-
-
-#define BDB_DRIVER_FEATURE_NO_LVDS             0
-#define BDB_DRIVER_FEATURE_INT_LVDS            1
-#define BDB_DRIVER_FEATURE_SDVO_LVDS           2
-#define BDB_DRIVER_FEATURE_EDP                 3
-
-struct bdb_driver_features {
-       u8 boot_dev_algorithm:1;
-       u8 block_display_switch:1;
-       u8 allow_display_switch:1;
-       u8 hotplug_dvo:1;
-       u8 dual_view_zoom:1;
-       u8 int15h_hook:1;
-       u8 sprite_in_clone:1;
-       u8 primary_lfp_id:1;
-
-       u16 boot_mode_x;
-       u16 boot_mode_y;
-       u8 boot_mode_bpp;
-       u8 boot_mode_refresh;
-
-       u16 enable_lfp_primary:1;
-       u16 selective_mode_pruning:1;
-       u16 dual_frequency:1;
-       u16 render_clock_freq:1; /* 0: high freq; 1: low freq */
-       u16 nt_clone_support:1;
-       u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
-       u16 sprite_display_assign:1; /* 0: secondary; 1: primary */
-       u16 cui_aspect_scaling:1;
-       u16 preserve_aspect_ratio:1;
-       u16 sdvo_device_power_down:1;
-       u16 crt_hotplug:1;
-       u16 lvds_config:2;
-       u16 tv_hotplug:1;
-       u16 hdmi_config:2;
-
-       u8 static_display:1;
-       u8 reserved2:7;
-       u16 legacy_crt_max_x;
-       u16 legacy_crt_max_y;
-       u8 legacy_crt_max_refresh;
-
-       u8 hdmi_termination;
-       u8 custom_vbt_version;
-       /* Driver features data block */
-       u16 rmpm_enabled:1;
-       u16 s2ddt_enabled:1;
-       u16 dpst_enabled:1;
-       u16 bltclt_enabled:1;
-       u16 adb_enabled:1;
-       u16 drrs_enabled:1;
-       u16 grs_enabled:1;
-       u16 gpmt_enabled:1;
-       u16 tbt_enabled:1;
-       u16 psr_enabled:1;
-       u16 ips_enabled:1;
-       u16 reserved3:4;
-       u16 pc_feature_valid:1;
-} __packed;
-
-#define EDP_18BPP      0
-#define EDP_24BPP      1
-#define EDP_30BPP      2
-#define EDP_RATE_1_62  0
-#define EDP_RATE_2_7   1
-#define EDP_LANE_1     0
-#define EDP_LANE_2     1
-#define EDP_LANE_4     3
-#define EDP_PREEMPHASIS_NONE   0
-#define EDP_PREEMPHASIS_3_5dB  1
-#define EDP_PREEMPHASIS_6dB    2
-#define EDP_PREEMPHASIS_9_5dB  3
-#define EDP_VSWING_0_4V                0
-#define EDP_VSWING_0_6V                1
-#define EDP_VSWING_0_8V                2
-#define EDP_VSWING_1_2V                3
+#ifndef _INTEL_BIOS_H_
+#define _INTEL_BIOS_H_
 
 struct edp_power_seq {
        u16 t1_t3;
@@ -565,245 +38,37 @@ struct edp_power_seq {
        u16 t11_t12;
 } __packed;
 
-struct edp_link_params {
-       u8 rate:4;
-       u8 lanes:4;
-       u8 preemphasis:4;
-       u8 vswing:4;
-} __packed;
-
-struct bdb_edp {
-       struct edp_power_seq power_seqs[16];
-       u32 color_depth;
-       struct edp_link_params link_params[16];
-       u32 sdrrs_msa_timing_delay;
-
-       /* ith bit indicates enabled/disabled for (i+1)th panel */
-       u16 edp_s3d_feature;
-       u16 edp_t3_optimization;
-       u64 edp_vswing_preemph;         /* v173 */
-} __packed;
-
-struct psr_table {
-       /* Feature bits */
-       u8 full_link:1;
-       u8 require_aux_to_wakeup:1;
-       u8 feature_bits_rsvd:6;
-
-       /* Wait times */
-       u8 idle_frames:4;
-       u8 lines_to_wait:3;
-       u8 wait_times_rsvd:1;
-
-       /* TP wake up time in multiple of 100 */
-       u16 tp1_wakeup_time;
-       u16 tp2_tp3_wakeup_time;
-} __packed;
-
-struct bdb_psr {
-       struct psr_table psr_table[16];
-} __packed;
-
-/*
- * Driver<->VBIOS interaction occurs through scratch bits in
- * GR18 & SWF*.
- */
-
-/* GR18 bits are set on display switch and hotkey events */
-#define GR18_DRIVER_SWITCH_EN  (1<<7) /* 0: VBIOS control, 1: driver control */
-#define GR18_HOTKEY_MASK       0x78 /* See also SWF4 15:0 */
-#define   GR18_HK_NONE         (0x0<<3)
-#define   GR18_HK_LFP_STRETCH  (0x1<<3)
-#define   GR18_HK_TOGGLE_DISP  (0x2<<3)
-#define   GR18_HK_DISP_SWITCH  (0x4<<3) /* see SWF14 15:0 for what to enable */
-#define   GR18_HK_POPUP_DISABLED (0x6<<3)
-#define   GR18_HK_POPUP_ENABLED        (0x7<<3)
-#define   GR18_HK_PFIT         (0x8<<3)
-#define   GR18_HK_APM_CHANGE   (0xa<<3)
-#define   GR18_HK_MULTIPLE     (0xc<<3)
-#define GR18_USER_INT_EN       (1<<2)
-#define GR18_A0000_FLUSH_EN    (1<<1)
-#define GR18_SMM_EN            (1<<0)
-
-/* Set by driver, cleared by VBIOS */
-#define SWF00_YRES_SHIFT       16
-#define SWF00_XRES_SHIFT       0
-#define SWF00_RES_MASK         0xffff
-
-/* Set by VBIOS at boot time and driver at runtime */
-#define SWF01_TV2_FORMAT_SHIFT 8
-#define SWF01_TV1_FORMAT_SHIFT 0
-#define SWF01_TV_FORMAT_MASK   0xffff
-
-#define SWF10_VBIOS_BLC_I2C_EN (1<<29)
-#define SWF10_GTT_OVERRIDE_EN  (1<<28)
-#define SWF10_LFP_DPMS_OVR     (1<<27) /* override DPMS on display switch */
-#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
-#define   SWF10_OLD_TOGGLE     0x0
-#define   SWF10_TOGGLE_LIST_1  0x1
-#define   SWF10_TOGGLE_LIST_2  0x2
-#define   SWF10_TOGGLE_LIST_3  0x3
-#define   SWF10_TOGGLE_LIST_4  0x4
-#define SWF10_PANNING_EN       (1<<23)
-#define SWF10_DRIVER_LOADED    (1<<22)
-#define SWF10_EXTENDED_DESKTOP (1<<21)
-#define SWF10_EXCLUSIVE_MODE   (1<<20)
-#define SWF10_OVERLAY_EN       (1<<19)
-#define SWF10_PLANEB_HOLDOFF   (1<<18)
-#define SWF10_PLANEA_HOLDOFF   (1<<17)
-#define SWF10_VGA_HOLDOFF      (1<<16)
-#define SWF10_ACTIVE_DISP_MASK 0xffff
-#define   SWF10_PIPEB_LFP2     (1<<15)
-#define   SWF10_PIPEB_EFP2     (1<<14)
-#define   SWF10_PIPEB_TV2      (1<<13)
-#define   SWF10_PIPEB_CRT2     (1<<12)
-#define   SWF10_PIPEB_LFP      (1<<11)
-#define   SWF10_PIPEB_EFP      (1<<10)
-#define   SWF10_PIPEB_TV       (1<<9)
-#define   SWF10_PIPEB_CRT      (1<<8)
-#define   SWF10_PIPEA_LFP2     (1<<7)
-#define   SWF10_PIPEA_EFP2     (1<<6)
-#define   SWF10_PIPEA_TV2      (1<<5)
-#define   SWF10_PIPEA_CRT2     (1<<4)
-#define   SWF10_PIPEA_LFP      (1<<3)
-#define   SWF10_PIPEA_EFP      (1<<2)
-#define   SWF10_PIPEA_TV       (1<<1)
-#define   SWF10_PIPEA_CRT      (1<<0)
-
-#define SWF11_MEMORY_SIZE_SHIFT        16
-#define SWF11_SV_TEST_EN       (1<<15)
-#define SWF11_IS_AGP           (1<<14)
-#define SWF11_DISPLAY_HOLDOFF  (1<<13)
-#define SWF11_DPMS_REDUCED     (1<<12)
-#define SWF11_IS_VBE_MODE      (1<<11)
-#define SWF11_PIPEB_ACCESS     (1<<10) /* 0 here means pipe a */
-#define SWF11_DPMS_MASK                0x07
-#define   SWF11_DPMS_OFF       (1<<2)
-#define   SWF11_DPMS_SUSPEND   (1<<1)
-#define   SWF11_DPMS_STANDBY   (1<<0)
-#define   SWF11_DPMS_ON                0
-
-#define SWF14_GFX_PFIT_EN      (1<<31)
-#define SWF14_TEXT_PFIT_EN     (1<<30)
-#define SWF14_LID_STATUS_CLOSED        (1<<29) /* 0 here means open */
-#define SWF14_POPUP_EN         (1<<28)
-#define SWF14_DISPLAY_HOLDOFF  (1<<27)
-#define SWF14_DISP_DETECT_EN   (1<<26)
-#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
-#define SWF14_DRIVER_STATUS    (1<<24)
-#define SWF14_OS_TYPE_WIN9X    (1<<23)
-#define SWF14_OS_TYPE_WINNT    (1<<22)
-/* 21:19 rsvd */
-#define SWF14_PM_TYPE_MASK     0x00070000
-#define   SWF14_PM_ACPI_VIDEO  (0x4 << 16)
-#define   SWF14_PM_ACPI                (0x3 << 16)
-#define   SWF14_PM_APM_12      (0x2 << 16)
-#define   SWF14_PM_APM_11      (0x1 << 16)
-#define SWF14_HK_REQUEST_MASK  0x0000ffff /* see GR18 6:3 for event type */
-          /* if GR18 indicates a display switch */
-#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
-#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
-#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
-#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
-#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
-#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
-#define   SWF14_DS_PIPEB_TV_EN   (1<<9)
-#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
-#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
-#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
-#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
-#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
-#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
-#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
-#define   SWF14_DS_PIPEA_TV_EN   (1<<1)
-#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
-          /* if GR18 indicates a panel fitting request */
-#define   SWF14_PFIT_EN                (1<<0) /* 0 means disable */
-          /* if GR18 indicates an APM change request */
-#define   SWF14_APM_HIBERNATE  0x4
-#define   SWF14_APM_SUSPEND    0x3
-#define   SWF14_APM_STANDBY    0x1
-#define   SWF14_APM_RESTORE    0x0
-
-/* Add the device class for LFP, TV, HDMI */
-#define         DEVICE_TYPE_INT_LFP    0x1022
-#define         DEVICE_TYPE_INT_TV     0x1009
-#define         DEVICE_TYPE_HDMI       0x60D2
-#define         DEVICE_TYPE_DP         0x68C6
-#define         DEVICE_TYPE_eDP        0x78C6
-
-#define  DEVICE_TYPE_CLASS_EXTENSION   (1 << 15)
-#define  DEVICE_TYPE_POWER_MANAGEMENT  (1 << 14)
-#define  DEVICE_TYPE_HOTPLUG_SIGNALING (1 << 13)
-#define  DEVICE_TYPE_INTERNAL_CONNECTOR        (1 << 12)
-#define  DEVICE_TYPE_NOT_HDMI_OUTPUT   (1 << 11)
-#define  DEVICE_TYPE_MIPI_OUTPUT       (1 << 10)
-#define  DEVICE_TYPE_COMPOSITE_OUTPUT  (1 << 9)
-#define  DEVICE_TYPE_DUAL_CHANNEL      (1 << 8)
-#define  DEVICE_TYPE_HIGH_SPEED_LINK   (1 << 6)
-#define  DEVICE_TYPE_LVDS_SINGALING    (1 << 5)
-#define  DEVICE_TYPE_TMDS_DVI_SIGNALING        (1 << 4)
-#define  DEVICE_TYPE_VIDEO_SIGNALING   (1 << 3)
-#define  DEVICE_TYPE_DISPLAYPORT_OUTPUT        (1 << 2)
-#define  DEVICE_TYPE_DIGITAL_OUTPUT    (1 << 1)
-#define  DEVICE_TYPE_ANALOG_OUTPUT     (1 << 0)
-
-/*
- * Bits we care about when checking for DEVICE_TYPE_eDP
- * Depending on the system, the other bits may or may not
- * be set for eDP outputs.
- */
-#define DEVICE_TYPE_eDP_BITS \
-       (DEVICE_TYPE_INTERNAL_CONNECTOR | \
-        DEVICE_TYPE_MIPI_OUTPUT | \
-        DEVICE_TYPE_COMPOSITE_OUTPUT | \
-        DEVICE_TYPE_DUAL_CHANNEL | \
-        DEVICE_TYPE_LVDS_SINGALING | \
-        DEVICE_TYPE_TMDS_DVI_SIGNALING | \
-        DEVICE_TYPE_VIDEO_SIGNALING | \
-        DEVICE_TYPE_DISPLAYPORT_OUTPUT | \
-        DEVICE_TYPE_ANALOG_OUTPUT)
-
-/* define the DVO port for HDMI output type */
-#define                DVO_B           1
-#define                DVO_C           2
-#define                DVO_D           3
-
-/* Possible values for the "DVO Port" field for versions >= 155: */
-#define DVO_PORT_HDMIA 0
-#define DVO_PORT_HDMIB 1
-#define DVO_PORT_HDMIC 2
-#define DVO_PORT_HDMID 3
-#define DVO_PORT_LVDS  4
-#define DVO_PORT_TV    5
-#define DVO_PORT_CRT   6
-#define DVO_PORT_DPB   7
-#define DVO_PORT_DPC   8
-#define DVO_PORT_DPD   9
-#define DVO_PORT_DPA   10
-#define DVO_PORT_DPE   11
-#define DVO_PORT_HDMIE 12
-#define DVO_PORT_MIPIA 21
-#define DVO_PORT_MIPIB 22
-#define DVO_PORT_MIPIC 23
-#define DVO_PORT_MIPID 24
+/* MIPI Sequence Block definitions */
+enum mipi_seq {
+       MIPI_SEQ_END = 0,
+       MIPI_SEQ_ASSERT_RESET,
+       MIPI_SEQ_INIT_OTP,
+       MIPI_SEQ_DISPLAY_ON,
+       MIPI_SEQ_DISPLAY_OFF,
+       MIPI_SEQ_DEASSERT_RESET,
+       MIPI_SEQ_BACKLIGHT_ON,          /* sequence block v2+ */
+       MIPI_SEQ_BACKLIGHT_OFF,         /* sequence block v2+ */
+       MIPI_SEQ_TEAR_ON,               /* sequence block v2+ */
+       MIPI_SEQ_TEAR_OFF,              /* sequence block v3+ */
+       MIPI_SEQ_POWER_ON,              /* sequence block v3+ */
+       MIPI_SEQ_POWER_OFF,             /* sequence block v3+ */
+       MIPI_SEQ_MAX
+};
 
-/* Block 52 contains MIPI Panel info
- * 6 such enteries will there. Index into correct
- * entery is based on the panel_index in #40 LFP
- */
-#define MAX_MIPI_CONFIGURATIONS        6
+enum mipi_seq_element {
+       MIPI_SEQ_ELEM_END = 0,
+       MIPI_SEQ_ELEM_SEND_PKT,
+       MIPI_SEQ_ELEM_DELAY,
+       MIPI_SEQ_ELEM_GPIO,
+       MIPI_SEQ_ELEM_I2C,              /* sequence block v2+ */
+       MIPI_SEQ_ELEM_SPI,              /* sequence block v3+ */
+       MIPI_SEQ_ELEM_PMIC,             /* sequence block v3+ */
+       MIPI_SEQ_ELEM_MAX
+};
 
 #define MIPI_DSI_UNDEFINED_PANEL_ID    0
 #define MIPI_DSI_GENERIC_PANEL_ID      1
 
-/*
- * PMIC vs SoC Backlight support specified in pwm_blc
- * field in mipi_config block below.
-*/
-#define PPS_BLC_PMIC   0
-#define PPS_BLC_SOC    1
-
 struct mipi_config {
        u16 panel_id;
 
@@ -821,6 +86,8 @@ struct mipi_config {
        u32 video_transfer_mode:2;
 
        u32 cabc_supported:1;
+#define PPS_BLC_PMIC   0
+#define PPS_BLC_SOC    1
        u32 pwm_blc:1;
 
        /* Bit 13:10 */
@@ -924,12 +191,7 @@ struct mipi_config {
 
 } __packed;
 
-/* Block 52 contains MIPI configuration block
- * 6 * bdb_mipi_config, followed by 6 pps data
- * block below
- *
- * all delays has a unit of 100us
- */
+/* all delays have a unit of 100us */
 struct mipi_pps_data {
        u16 panel_on_delay;
        u16 bl_enable_delay;
@@ -938,57 +200,4 @@ struct mipi_pps_data {
        u16 panel_power_cycle_delay;
 } __packed;
 
-struct bdb_mipi_config {
-       struct mipi_config config[MAX_MIPI_CONFIGURATIONS];
-       struct mipi_pps_data pps[MAX_MIPI_CONFIGURATIONS];
-} __packed;
-
-/* Block 53 contains MIPI sequences as needed by the panel
- * for enabling it. This block can be variable in size and
- * can be maximum of 6 blocks
- */
-struct bdb_mipi_sequence {
-       u8 version;
-       u8 data[0];
-} __packed;
-
-/* MIPI Sequnece Block definitions */
-enum mipi_seq {
-       MIPI_SEQ_END = 0,
-       MIPI_SEQ_ASSERT_RESET,
-       MIPI_SEQ_INIT_OTP,
-       MIPI_SEQ_DISPLAY_ON,
-       MIPI_SEQ_DISPLAY_OFF,
-       MIPI_SEQ_DEASSERT_RESET,
-       MIPI_SEQ_BACKLIGHT_ON,          /* sequence block v2+ */
-       MIPI_SEQ_BACKLIGHT_OFF,         /* sequence block v2+ */
-       MIPI_SEQ_TEAR_ON,               /* sequence block v2+ */
-       MIPI_SEQ_TEAR_OFF,              /* sequence block v3+ */
-       MIPI_SEQ_POWER_ON,              /* sequence block v3+ */
-       MIPI_SEQ_POWER_OFF,             /* sequence block v3+ */
-       MIPI_SEQ_MAX
-};
-
-enum mipi_seq_element {
-       MIPI_SEQ_ELEM_END = 0,
-       MIPI_SEQ_ELEM_SEND_PKT,
-       MIPI_SEQ_ELEM_DELAY,
-       MIPI_SEQ_ELEM_GPIO,
-       MIPI_SEQ_ELEM_I2C,              /* sequence block v2+ */
-       MIPI_SEQ_ELEM_SPI,              /* sequence block v3+ */
-       MIPI_SEQ_ELEM_PMIC,             /* sequence block v3+ */
-       MIPI_SEQ_ELEM_MAX
-};
-
-enum mipi_gpio_pin_index {
-       MIPI_GPIO_UNDEFINED = 0,
-       MIPI_GPIO_PANEL_ENABLE,
-       MIPI_GPIO_BL_ENABLE,
-       MIPI_GPIO_PWM_ENABLE,
-       MIPI_GPIO_RESET_N,
-       MIPI_GPIO_PWR_DOWN_R,
-       MIPI_GPIO_STDBY_RST_N,
-       MIPI_GPIO_MAX
-};
-
 #endif /* _INTEL_BIOS_H_ */
diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
new file mode 100644 (file)
index 0000000..aa0b20d
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "intel_drv.h"
+
+#define CTM_COEFF_SIGN (1ULL << 63)
+
+#define CTM_COEFF_1_0  (1ULL << 32)
+#define CTM_COEFF_2_0  (CTM_COEFF_1_0 << 1)
+#define CTM_COEFF_4_0  (CTM_COEFF_2_0 << 1)
+#define CTM_COEFF_8_0  (CTM_COEFF_4_0 << 1)
+#define CTM_COEFF_0_5  (CTM_COEFF_1_0 >> 1)
+#define CTM_COEFF_0_25 (CTM_COEFF_0_5 >> 1)
+#define CTM_COEFF_0_125        (CTM_COEFF_0_25 >> 1)
+
+#define CTM_COEFF_LIMITED_RANGE ((235ULL - 16ULL) * CTM_COEFF_1_0 / 255)
+
+#define CTM_COEFF_NEGATIVE(coeff)      (((coeff) & CTM_COEFF_SIGN) != 0)
+#define CTM_COEFF_ABS(coeff)           ((coeff) & (CTM_COEFF_SIGN - 1))
+
+#define LEGACY_LUT_LENGTH              (sizeof(struct drm_color_lut) * 256)
+
+/*
+ * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
+ * format). This macro takes the coefficient we want transformed and the
+ * number of fractional bits.
+ *
+ * We only have a 9 bits precision window which slides depending on the value
+ * of the CTM coefficient and we write the value from bit 3. We also round the
+ * value.
+ */
+#define I9XX_CSC_COEFF_FP(coeff, fbits)        \
+       (clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8)
+
+#define I9XX_CSC_COEFF_LIMITED_RANGE   \
+       I9XX_CSC_COEFF_FP(CTM_COEFF_LIMITED_RANGE, 9)
+#define I9XX_CSC_COEFF_1_0             \
+       ((7 << 12) | I9XX_CSC_COEFF_FP(CTM_COEFF_1_0, 8))
+
+static bool crtc_state_is_legacy(struct drm_crtc_state *state)
+{
+       return !state->degamma_lut &&
+               !state->ctm &&
+               state->gamma_lut &&
+               state->gamma_lut->length == LEGACY_LUT_LENGTH;
+}
+
+/*
+ * When using limited range, multiply the matrix given by userspace by
+ * the matrix that we would use for the limited range. We do the
+ * multiplication in U2.30 format.
+ */
+static void ctm_mult_by_limited(uint64_t *result, int64_t *input)
+{
+       int i;
+
+       for (i = 0; i < 9; i++)
+               result[i] = 0;
+
+       for (i = 0; i < 3; i++) {
+               int64_t user_coeff = input[i * 3 + i];
+               uint64_t limited_coeff = CTM_COEFF_LIMITED_RANGE >> 2;
+               uint64_t abs_coeff = clamp_val(CTM_COEFF_ABS(user_coeff),
+                                              0,
+                                              CTM_COEFF_4_0 - 1) >> 2;
+
+               result[i * 3 + i] = (limited_coeff * abs_coeff) >> 27;
+               if (CTM_COEFF_NEGATIVE(user_coeff))
+                       result[i * 3 + i] |= CTM_COEFF_SIGN;
+       }
+}
+
+/* Set up the pipe CSC unit. */
+static void i9xx_load_csc_matrix(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int i, pipe = intel_crtc->pipe;
+       uint16_t coeffs[9] = { 0, };
+
+       if (crtc_state->ctm) {
+               struct drm_color_ctm *ctm =
+                       (struct drm_color_ctm *)crtc_state->ctm->data;
+               uint64_t input[9] = { 0, };
+
+               if (intel_crtc->config->limited_color_range) {
+                       ctm_mult_by_limited(input, ctm->matrix);
+               } else {
+                       for (i = 0; i < ARRAY_SIZE(input); i++)
+                               input[i] = ctm->matrix[i];
+               }
+
+               /*
+                * Convert fixed point S31.32 input to format supported by the
+                * hardware.
+                */
+               for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
+                       uint64_t abs_coeff = ((1ULL << 63) - 1) & input[i];
+
+                       /*
+                        * Clamp input value to min/max supported by
+                        * hardware.
+                        */
+                       abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
+
+                       /* sign bit */
+                       if (CTM_COEFF_NEGATIVE(input[i]))
+                               coeffs[i] |= 1 << 15;
+
+                       if (abs_coeff < CTM_COEFF_0_125)
+                               coeffs[i] |= (3 << 12) |
+                                       I9XX_CSC_COEFF_FP(abs_coeff, 12);
+                       else if (abs_coeff < CTM_COEFF_0_25)
+                               coeffs[i] |= (2 << 12) |
+                                       I9XX_CSC_COEFF_FP(abs_coeff, 11);
+                       else if (abs_coeff < CTM_COEFF_0_5)
+                               coeffs[i] |= (1 << 12) |
+                                       I9XX_CSC_COEFF_FP(abs_coeff, 10);
+                       else if (abs_coeff < CTM_COEFF_1_0)
+                               coeffs[i] |= I9XX_CSC_COEFF_FP(abs_coeff, 9);
+                       else if (abs_coeff < CTM_COEFF_2_0)
+                               coeffs[i] |= (7 << 12) |
+                                       I9XX_CSC_COEFF_FP(abs_coeff, 8);
+                       else
+                               coeffs[i] |= (6 << 12) |
+                                       I9XX_CSC_COEFF_FP(abs_coeff, 7);
+               }
+       } else {
+               /*
+                * Load an identity matrix if no coefficients are provided.
+                *
+                * 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.
+                */
+               for (i = 0; i < 3; i++) {
+                       if (intel_crtc->config->limited_color_range)
+                               coeffs[i * 3 + i] =
+                                       I9XX_CSC_COEFF_LIMITED_RANGE;
+                       else
+                               coeffs[i * 3 + i] = I9XX_CSC_COEFF_1_0;
+               }
+       }
+
+       I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeffs[0] << 16 | coeffs[1]);
+       I915_WRITE(PIPE_CSC_COEFF_BY(pipe), coeffs[2] << 16);
+
+       I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeffs[3] << 16 | coeffs[4]);
+       I915_WRITE(PIPE_CSC_COEFF_BU(pipe), coeffs[5] << 16);
+
+       I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), coeffs[6] << 16 | coeffs[7]);
+       I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeffs[8] << 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 (intel_crtc->config->limited_color_range)
+                       postoff = (16 * (1 << 12) / 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 (intel_crtc->config->limited_color_range)
+                       mode |= CSC_BLACK_SCREEN_OFFSET;
+
+               I915_WRITE(PIPE_CSC_MODE(pipe), mode);
+       }
+}
+
+/*
+ * Set up the pipe CSC unit on CherryView.
+ */
+static void cherryview_load_csc_matrix(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_crtc_state *state = crtc->state;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipe = to_intel_crtc(crtc)->pipe;
+       uint32_t mode;
+
+       if (state->ctm) {
+               struct drm_color_ctm *ctm =
+                       (struct drm_color_ctm *) state->ctm->data;
+               uint16_t coeffs[9] = { 0, };
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
+                       uint64_t abs_coeff =
+                               ((1ULL << 63) - 1) & ctm->matrix[i];
+
+                       /* Round coefficient. */
+                       abs_coeff += 1 << (32 - 13);
+                       /* Clamp to hardware limits. */
+                       abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
+
+                       /* Write coefficients in S3.12 format. */
+                       if (ctm->matrix[i] & (1ULL << 63))
+                               coeffs[i] = 1 << 15;
+                       coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
+                       coeffs[i] |= (abs_coeff >> 20) & 0xfff;
+               }
+
+               I915_WRITE(CGM_PIPE_CSC_COEFF01(pipe),
+                          coeffs[1] << 16 | coeffs[0]);
+               I915_WRITE(CGM_PIPE_CSC_COEFF23(pipe),
+                          coeffs[3] << 16 | coeffs[2]);
+               I915_WRITE(CGM_PIPE_CSC_COEFF45(pipe),
+                          coeffs[5] << 16 | coeffs[4]);
+               I915_WRITE(CGM_PIPE_CSC_COEFF67(pipe),
+                          coeffs[7] << 16 | coeffs[6]);
+               I915_WRITE(CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
+       }
+
+       mode = (state->ctm ? CGM_PIPE_MODE_CSC : 0);
+       if (!crtc_state_is_legacy(state)) {
+               mode |= (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
+                       (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0);
+       }
+       I915_WRITE(CGM_PIPE_MODE(pipe), mode);
+}
+
+void intel_color_set_csc(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->display.load_csc_matrix)
+               dev_priv->display.load_csc_matrix(crtc);
+}
+
+/* Loads the legacy palette/gamma unit for the CRTC. */
+static void i9xx_load_luts_internal(struct drm_crtc *crtc,
+                                   struct drm_property_blob *blob)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       enum pipe pipe = intel_crtc->pipe;
+       int i;
+
+       if (HAS_GMCH_DISPLAY(dev)) {
+               if (intel_crtc->config->has_dsi_encoder)
+                       assert_dsi_pll_enabled(dev_priv);
+               else
+                       assert_pll_enabled(dev_priv, pipe);
+       }
+
+       if (blob) {
+               struct drm_color_lut *lut = (struct drm_color_lut *) blob->data;
+               for (i = 0; i < 256; i++) {
+                       uint32_t word =
+                               (drm_color_lut_extract(lut[i].red, 8) << 16) |
+                               (drm_color_lut_extract(lut[i].green, 8) << 8) |
+                               drm_color_lut_extract(lut[i].blue, 8);
+
+                       if (HAS_GMCH_DISPLAY(dev))
+                               I915_WRITE(PALETTE(pipe, i), word);
+                       else
+                               I915_WRITE(LGC_PALETTE(pipe, i), word);
+               }
+       } else {
+               for (i = 0; i < 256; i++) {
+                       uint32_t word = (i << 16) | (i << 8) | i;
+
+                       if (HAS_GMCH_DISPLAY(dev))
+                               I915_WRITE(PALETTE(pipe, i), word);
+                       else
+                               I915_WRITE(LGC_PALETTE(pipe, i), word);
+               }
+       }
+}
+
+static void i9xx_load_luts(struct drm_crtc *crtc)
+{
+       i9xx_load_luts_internal(crtc, crtc->state->gamma_lut);
+}
+
+/* Loads the legacy palette/gamma unit for the CRTC on Haswell. */
+static void haswell_load_luts(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);
+       struct intel_crtc_state *intel_crtc_state =
+               to_intel_crtc_state(crtc->state);
+       bool reenable_ips = false;
+
+       /*
+        * Workaround : Do not read or write the pipe palette/gamma data while
+        * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
+        */
+       if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
+           (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) {
+               hsw_disable_ips(intel_crtc);
+               reenable_ips = true;
+       }
+
+       intel_crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
+       I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
+
+       i9xx_load_luts(crtc);
+
+       if (reenable_ips)
+               hsw_enable_ips(intel_crtc);
+}
+
+/* Loads the palette/gamma unit for the CRTC on Broadwell+. */
+static void broadwell_load_luts(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_crtc_state *state = crtc->state;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc_state *intel_state = to_intel_crtc_state(state);
+       enum pipe pipe = to_intel_crtc(crtc)->pipe;
+       uint32_t i, lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+
+       if (crtc_state_is_legacy(state)) {
+               haswell_load_luts(crtc);
+               return;
+       }
+
+       I915_WRITE(PREC_PAL_INDEX(pipe),
+                  PAL_PREC_SPLIT_MODE | PAL_PREC_AUTO_INCREMENT);
+
+       if (state->degamma_lut) {
+               struct drm_color_lut *lut =
+                       (struct drm_color_lut *) state->degamma_lut->data;
+
+               for (i = 0; i < lut_size; i++) {
+                       uint32_t word =
+                       drm_color_lut_extract(lut[i].red, 10) << 20 |
+                       drm_color_lut_extract(lut[i].green, 10) << 10 |
+                       drm_color_lut_extract(lut[i].blue, 10);
+
+                       I915_WRITE(PREC_PAL_DATA(pipe), word);
+               }
+       } else {
+               for (i = 0; i < lut_size; i++) {
+                       uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1);
+
+                       I915_WRITE(PREC_PAL_DATA(pipe),
+                                  (v << 20) | (v << 10) | v);
+               }
+       }
+
+       if (state->gamma_lut) {
+               struct drm_color_lut *lut =
+                       (struct drm_color_lut *) state->gamma_lut->data;
+
+               for (i = 0; i < lut_size; i++) {
+                       uint32_t word =
+                       (drm_color_lut_extract(lut[i].red, 10) << 20) |
+                       (drm_color_lut_extract(lut[i].green, 10) << 10) |
+                       drm_color_lut_extract(lut[i].blue, 10);
+
+                       I915_WRITE(PREC_PAL_DATA(pipe), word);
+               }
+
+               /* Program the max register to clamp values > 1.0. */
+               I915_WRITE(PREC_PAL_GC_MAX(pipe, 0),
+                          drm_color_lut_extract(lut[i].red, 16));
+               I915_WRITE(PREC_PAL_GC_MAX(pipe, 1),
+                          drm_color_lut_extract(lut[i].green, 16));
+               I915_WRITE(PREC_PAL_GC_MAX(pipe, 2),
+                          drm_color_lut_extract(lut[i].blue, 16));
+       } else {
+               for (i = 0; i < lut_size; i++) {
+                       uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1);
+
+                       I915_WRITE(PREC_PAL_DATA(pipe),
+                                  (v << 20) | (v << 10) | v);
+               }
+
+               I915_WRITE(PREC_PAL_GC_MAX(pipe, 0), (1 << 16) - 1);
+               I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), (1 << 16) - 1);
+               I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), (1 << 16) - 1);
+       }
+
+       intel_state->gamma_mode = GAMMA_MODE_MODE_SPLIT;
+       I915_WRITE(GAMMA_MODE(pipe), GAMMA_MODE_MODE_SPLIT);
+       POSTING_READ(GAMMA_MODE(pipe));
+
+       /*
+        * Reset the index, otherwise it prevents the legacy palette to be
+        * written properly.
+        */
+       I915_WRITE(PREC_PAL_INDEX(pipe), 0);
+}
+
+/* Loads the palette/gamma unit for the CRTC on CherryView. */
+static void cherryview_load_luts(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc_state *state = crtc->state;
+       enum pipe pipe = to_intel_crtc(crtc)->pipe;
+       struct drm_color_lut *lut;
+       uint32_t i, lut_size;
+       uint32_t word0, word1;
+
+       if (crtc_state_is_legacy(state)) {
+               /* Turn off degamma/gamma on CGM block. */
+               I915_WRITE(CGM_PIPE_MODE(pipe),
+                          (state->ctm ? CGM_PIPE_MODE_CSC : 0));
+               i9xx_load_luts_internal(crtc, state->gamma_lut);
+               return;
+       }
+
+       if (state->degamma_lut) {
+               lut = (struct drm_color_lut *) state->degamma_lut->data;
+               lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+               for (i = 0; i < lut_size; i++) {
+                       /* Write LUT in U0.14 format. */
+                       word0 =
+                       (drm_color_lut_extract(lut[i].green, 14) << 16) |
+                       drm_color_lut_extract(lut[i].blue, 14);
+                       word1 = drm_color_lut_extract(lut[i].red, 14);
+
+                       I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0), word0);
+                       I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1), word1);
+               }
+       }
+
+       if (state->gamma_lut) {
+               lut = (struct drm_color_lut *) state->gamma_lut->data;
+               lut_size = INTEL_INFO(dev)->color.gamma_lut_size;
+               for (i = 0; i < lut_size; i++) {
+                       /* Write LUT in U0.10 format. */
+                       word0 =
+                       (drm_color_lut_extract(lut[i].green, 10) << 16) |
+                       drm_color_lut_extract(lut[i].blue, 10);
+                       word1 = drm_color_lut_extract(lut[i].red, 10);
+
+                       I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0), word0);
+                       I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1), word1);
+               }
+       }
+
+       I915_WRITE(CGM_PIPE_MODE(pipe),
+                  (state->ctm ? CGM_PIPE_MODE_CSC : 0) |
+                  (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
+                  (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0));
+
+       /*
+        * Also program a linear LUT in the legacy block (behind the
+        * CGM block).
+        */
+       i9xx_load_luts_internal(crtc, NULL);
+}
+
+void intel_color_load_luts(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       /* The clocks have to be on to load the palette. */
+       if (!crtc->state->active)
+               return;
+
+       dev_priv->display.load_luts(crtc);
+}
+
+int intel_color_check(struct drm_crtc *crtc,
+                     struct drm_crtc_state *crtc_state)
+{
+       struct drm_device *dev = crtc->dev;
+       size_t gamma_length, degamma_length;
+
+       degamma_length = INTEL_INFO(dev)->color.degamma_lut_size *
+               sizeof(struct drm_color_lut);
+       gamma_length = INTEL_INFO(dev)->color.gamma_lut_size *
+               sizeof(struct drm_color_lut);
+
+       /*
+        * We allow both degamma & gamma luts at the right size or
+        * NULL.
+        */
+       if ((!crtc_state->degamma_lut ||
+            crtc_state->degamma_lut->length == degamma_length) &&
+           (!crtc_state->gamma_lut ||
+            crtc_state->gamma_lut->length == gamma_length))
+               return 0;
+
+       /*
+        * We also allow no degamma lut and a gamma lut at the legacy
+        * size (256 entries).
+        */
+       if (!crtc_state->degamma_lut &&
+           crtc_state->gamma_lut &&
+           crtc_state->gamma_lut->length == LEGACY_LUT_LENGTH)
+               return 0;
+
+       return -EINVAL;
+}
+
+void intel_color_init(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       drm_mode_crtc_set_gamma_size(crtc, 256);
+
+       if (IS_CHERRYVIEW(dev)) {
+               dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix;
+               dev_priv->display.load_luts = cherryview_load_luts;
+       } else if (IS_HASWELL(dev)) {
+               dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
+               dev_priv->display.load_luts = haswell_load_luts;
+       } else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) ||
+                  IS_BROXTON(dev) || IS_KABYLAKE(dev)) {
+               dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
+               dev_priv->display.load_luts = broadwell_load_luts;
+       } else {
+               dev_priv->display.load_luts = i9xx_load_luts;
+       }
+
+       /* Enable color management support when we have degamma & gamma LUTs. */
+       if (INTEL_INFO(dev)->color.degamma_lut_size != 0 &&
+           INTEL_INFO(dev)->color.gamma_lut_size != 0)
+               drm_helper_crtc_enable_color_mgmt(crtc,
+                                       INTEL_INFO(dev)->color.degamma_lut_size,
+                                       INTEL_INFO(dev)->color.gamma_lut_size);
+}
index 505fc5c..a2a31fd 100644 (file)
@@ -120,22 +120,16 @@ static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
 static void intel_crt_get_config(struct intel_encoder *encoder,
                                 struct intel_crtc_state *pipe_config)
 {
-       struct drm_device *dev = encoder->base.dev;
-       int dotclock;
-
        pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
 
-       dotclock = pipe_config->port_clock;
-
-       if (HAS_PCH_SPLIT(dev))
-               ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
-       pipe_config->base.adjusted_mode.crtc_clock = dotclock;
+       pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
 }
 
 static void hsw_crt_get_config(struct intel_encoder *encoder,
                               struct intel_crtc_state *pipe_config)
 {
+       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+
        intel_ddi_get_config(encoder, pipe_config);
 
        pipe_config->base.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
@@ -143,6 +137,8 @@ static void hsw_crt_get_config(struct intel_encoder *encoder,
                                              DRM_MODE_FLAG_PVSYNC |
                                              DRM_MODE_FLAG_NVSYNC);
        pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
+
+       pipe_config->base.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv);
 }
 
 /* Note: The caller is required to filter out dpms modes not supported by the
@@ -222,18 +218,26 @@ intel_crt_mode_valid(struct drm_connector *connector,
 {
        struct drm_device *dev = connector->dev;
        int max_dotclk = to_i915(dev)->max_dotclk_freq;
+       int max_clock;
 
-       int max_clock = 0;
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
 
        if (mode->clock < 25000)
                return MODE_CLOCK_LOW;
 
-       if (IS_GEN2(dev))
-               max_clock = 350000;
-       else
+       if (HAS_PCH_LPT(dev))
+               max_clock = 180000;
+       else if (IS_VALLEYVIEW(dev))
+               /*
+                * 270 MHz due to current DPLL limits,
+                * DAC limit supposedly 355 MHz.
+                */
+               max_clock = 270000;
+       else if (IS_GEN3(dev) || IS_GEN4(dev))
                max_clock = 400000;
+       else
+               max_clock = 350000;
        if (mode->clock > max_clock)
                return MODE_CLOCK_HIGH;
 
@@ -261,15 +265,9 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
                pipe_config->pipe_bpp = 24;
 
        /* FDI must always be 2.7 GHz */
-       if (HAS_DDI(dev)) {
-               pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL;
+       if (HAS_DDI(dev))
                pipe_config->port_clock = 135000 * 2;
 
-               pipe_config->dpll_hw_state.wrpll = 0;
-               pipe_config->dpll_hw_state.spll =
-                       SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
-       }
-
        return true;
 }
 
@@ -652,6 +650,8 @@ intel_crt_detect(struct drm_connector *connector, bool force)
                else if (INTEL_INFO(dev)->gen < 4)
                        status = intel_crt_load_detect(crt,
                                to_intel_crtc(connector->state->crtc)->pipe);
+               else if (i915.load_detect_test)
+                       status = connector_status_disconnected;
                else
                        status = connector_status_unknown;
                intel_release_load_detect_pipe(connector, &tmp, &ctx);
index 902054e..3f57cb9 100644 (file)
@@ -188,28 +188,49 @@ static const struct stepping_info bxt_stepping_info[] = {
        {'B', '0'}, {'B', '1'}, {'B', '2'}
 };
 
-static const struct stepping_info *intel_get_stepping_info(struct drm_device *dev)
+static const struct stepping_info no_stepping_info = { '*', '*' };
+
+static const struct stepping_info *
+intel_get_stepping_info(struct drm_i915_private *dev_priv)
 {
        const struct stepping_info *si;
        unsigned int size;
 
-       if (IS_KABYLAKE(dev)) {
+       if (IS_KABYLAKE(dev_priv)) {
                size = ARRAY_SIZE(kbl_stepping_info);
                si = kbl_stepping_info;
-       } else if (IS_SKYLAKE(dev)) {
+       } else if (IS_SKYLAKE(dev_priv)) {
                size = ARRAY_SIZE(skl_stepping_info);
                si = skl_stepping_info;
-       } else if (IS_BROXTON(dev)) {
+       } else if (IS_BROXTON(dev_priv)) {
                size = ARRAY_SIZE(bxt_stepping_info);
                si = bxt_stepping_info;
        } else {
-               return NULL;
+               size = 0;
        }
 
-       if (INTEL_REVID(dev) < size)
-               return si + INTEL_REVID(dev);
+       if (INTEL_REVID(dev_priv) < size)
+               return si + INTEL_REVID(dev_priv);
+
+       return &no_stepping_info;
+}
+
+static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
+{
+       uint32_t val, mask;
+
+       mask = DC_STATE_DEBUG_MASK_MEMORY_UP;
+
+       if (IS_BROXTON(dev_priv))
+               mask |= DC_STATE_DEBUG_MASK_CORES;
 
-       return NULL;
+       /* The below bit doesn't need to be cleared ever afterwards */
+       val = I915_READ(DC_STATE_DEBUG);
+       if ((val & mask) != mask) {
+               val |= mask;
+               I915_WRITE(DC_STATE_DEBUG, val);
+               POSTING_READ(DC_STATE_DEBUG);
+       }
 }
 
 /**
@@ -220,19 +241,19 @@ static const struct stepping_info *intel_get_stepping_info(struct drm_device *de
  * Everytime display comes back from low power state this function is called to
  * copy the firmware from internal memory to registers.
  */
-bool intel_csr_load_program(struct drm_i915_private *dev_priv)
+void intel_csr_load_program(struct drm_i915_private *dev_priv)
 {
        u32 *payload = dev_priv->csr.dmc_payload;
        uint32_t i, fw_size;
 
        if (!IS_GEN9(dev_priv)) {
                DRM_ERROR("No CSR support available for this platform\n");
-               return false;
+               return;
        }
 
        if (!dev_priv->csr.dmc_payload) {
                DRM_ERROR("Tried to program CSR with empty payload\n");
-               return false;
+               return;
        }
 
        fw_size = dev_priv->csr.dmc_fw_size;
@@ -246,19 +267,17 @@ bool intel_csr_load_program(struct drm_i915_private *dev_priv)
 
        dev_priv->csr.dc_state = 0;
 
-       return true;
+       gen9_set_dc_state_debugmask(dev_priv);
 }
 
 static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
                              const struct firmware *fw)
 {
-       struct drm_device *dev = dev_priv->dev;
        struct intel_css_header *css_header;
        struct intel_package_header *package_header;
        struct intel_dmc_header *dmc_header;
        struct intel_csr *csr = &dev_priv->csr;
-       const struct stepping_info *stepping_info = intel_get_stepping_info(dev);
-       char stepping, substepping;
+       const struct stepping_info *si = intel_get_stepping_info(dev_priv);
        uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
        uint32_t i;
        uint32_t *dmc_payload;
@@ -266,14 +285,6 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
        if (!fw)
                return NULL;
 
-       if (!stepping_info) {
-               DRM_ERROR("Unknown stepping info, firmware loading failed\n");
-               return NULL;
-       }
-
-       stepping = stepping_info->stepping;
-       substepping = stepping_info->substepping;
-
        /* Extract CSS Header information*/
        css_header = (struct intel_css_header *)fw->data;
        if (sizeof(struct intel_css_header) !=
@@ -285,7 +296,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
 
        csr->version = css_header->version;
 
-       if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
+       if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
            csr->version < SKL_CSR_VERSION_REQUIRED) {
                DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u,"
                         " please upgrade to v%u.%u or later"
@@ -313,11 +324,11 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
        /* Search for dmc_offset to find firware binary. */
        for (i = 0; i < package_header->num_entries; i++) {
                if (package_header->fw_info[i].substepping == '*' &&
-                   stepping == package_header->fw_info[i].stepping) {
+                   si->stepping == package_header->fw_info[i].stepping) {
                        dmc_offset = package_header->fw_info[i].offset;
                        break;
-               } else if (stepping == package_header->fw_info[i].stepping &&
-                       substepping == package_header->fw_info[i].substepping) {
+               } else if (si->stepping == package_header->fw_info[i].stepping &&
+                          si->substepping == package_header->fw_info[i].substepping) {
                        dmc_offset = package_header->fw_info[i].offset;
                        break;
                } else if (package_header->fw_info[i].stepping == '*' &&
@@ -325,7 +336,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
                        dmc_offset = package_header->fw_info[i].offset;
        }
        if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
-               DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
+               DRM_ERROR("Firmware not supported for %c stepping\n",
+                         si->stepping);
                return NULL;
        }
        readcount += dmc_offset;
@@ -371,9 +383,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
                return NULL;
        }
 
-       memcpy(dmc_payload, &fw->data[readcount], nbytes);
-
-       return dmc_payload;
+       return memcpy(dmc_payload, &fw->data[readcount], nbytes);
 }
 
 static void csr_load_work_fn(struct work_struct *work)
@@ -388,18 +398,12 @@ static void csr_load_work_fn(struct work_struct *work)
 
        ret = request_firmware(&fw, dev_priv->csr.fw_path,
                               &dev_priv->dev->pdev->dev);
-       if (!fw)
-               goto out;
-
-       dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw);
-       if (!dev_priv->csr.dmc_payload)
-               goto out;
+       if (fw)
+               dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw);
 
-       /* load csr program during system boot, as needed for DC states */
-       intel_csr_load_program(dev_priv);
-
-out:
        if (dev_priv->csr.dmc_payload) {
+               intel_csr_load_program(dev_priv);
+
                intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
                DRM_INFO("Finished loading %s (v%u.%u)\n",
index 62de9f4..1e08385 100644 (file)
@@ -360,7 +360,7 @@ skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries)
 static const struct ddi_buf_trans *
 skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
 {
-       if (dev_priv->edp_low_vswing) {
+       if (dev_priv->vbt.edp.low_vswing) {
                if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) {
                        *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp);
                        return skl_y_ddi_translations_edp;
@@ -724,160 +724,6 @@ intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state)
 }
 
 #define LC_FREQ 2700
-#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
-
-#define P_MIN 2
-#define P_MAX 64
-#define P_INC 2
-
-/* Constraints for PLL good behavior */
-#define REF_MIN 48
-#define REF_MAX 400
-#define VCO_MIN 2400
-#define VCO_MAX 4800
-
-#define abs_diff(a, b) ({                      \
-       typeof(a) __a = (a);                    \
-       typeof(b) __b = (b);                    \
-       (void) (&__a == &__b);                  \
-       __a > __b ? (__a - __b) : (__b - __a); })
-
-struct hsw_wrpll_rnp {
-       unsigned p, n2, r2;
-};
-
-static unsigned hsw_wrpll_get_budget_for_freq(int clock)
-{
-       unsigned budget;
-
-       switch (clock) {
-       case 25175000:
-       case 25200000:
-       case 27000000:
-       case 27027000:
-       case 37762500:
-       case 37800000:
-       case 40500000:
-       case 40541000:
-       case 54000000:
-       case 54054000:
-       case 59341000:
-       case 59400000:
-       case 72000000:
-       case 74176000:
-       case 74250000:
-       case 81000000:
-       case 81081000:
-       case 89012000:
-       case 89100000:
-       case 108000000:
-       case 108108000:
-       case 111264000:
-       case 111375000:
-       case 148352000:
-       case 148500000:
-       case 162000000:
-       case 162162000:
-       case 222525000:
-       case 222750000:
-       case 296703000:
-       case 297000000:
-               budget = 0;
-               break;
-       case 233500000:
-       case 245250000:
-       case 247750000:
-       case 253250000:
-       case 298000000:
-               budget = 1500;
-               break;
-       case 169128000:
-       case 169500000:
-       case 179500000:
-       case 202000000:
-               budget = 2000;
-               break;
-       case 256250000:
-       case 262500000:
-       case 270000000:
-       case 272500000:
-       case 273750000:
-       case 280750000:
-       case 281250000:
-       case 286000000:
-       case 291750000:
-               budget = 4000;
-               break;
-       case 267250000:
-       case 268500000:
-               budget = 5000;
-               break;
-       default:
-               budget = 1000;
-               break;
-       }
-
-       return budget;
-}
-
-static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
-                                unsigned r2, unsigned n2, unsigned p,
-                                struct hsw_wrpll_rnp *best)
-{
-       uint64_t a, b, c, d, diff, diff_best;
-
-       /* No best (r,n,p) yet */
-       if (best->p == 0) {
-               best->p = p;
-               best->n2 = n2;
-               best->r2 = r2;
-               return;
-       }
-
-       /*
-        * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
-        * freq2k.
-        *
-        * delta = 1e6 *
-        *         abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
-        *         freq2k;
-        *
-        * and we would like delta <= budget.
-        *
-        * If the discrepancy is above the PPM-based budget, always prefer to
-        * improve upon the previous solution.  However, if you're within the
-        * budget, try to maximize Ref * VCO, that is N / (P * R^2).
-        */
-       a = freq2k * budget * p * r2;
-       b = freq2k * budget * best->p * best->r2;
-       diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
-       diff_best = abs_diff(freq2k * best->p * best->r2,
-                            LC_FREQ_2K * best->n2);
-       c = 1000000 * diff;
-       d = 1000000 * diff_best;
-
-       if (a < c && b < d) {
-               /* If both are above the budget, pick the closer */
-               if (best->p * best->r2 * diff < p * r2 * diff_best) {
-                       best->p = p;
-                       best->n2 = n2;
-                       best->r2 = r2;
-               }
-       } else if (a >= c && b < d) {
-               /* If A is below the threshold but B is above it?  Update. */
-               best->p = p;
-               best->n2 = n2;
-               best->r2 = r2;
-       } else if (a >= c && b >= d) {
-               /* Both are below the limit, so pick the higher n2/(r2*r2) */
-               if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
-                       best->p = p;
-                       best->n2 = n2;
-                       best->r2 = r2;
-               }
-       }
-       /* Otherwise a < c && b >= d, do nothing */
-}
 
 static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
                                   i915_reg_t reg)
@@ -1139,363 +985,20 @@ void intel_ddi_clock_get(struct intel_encoder *encoder,
                bxt_ddi_clock_get(encoder, pipe_config);
 }
 
-static void
-hsw_ddi_calculate_wrpll(int clock /* in Hz */,
-                       unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
-{
-       uint64_t freq2k;
-       unsigned p, n2, r2;
-       struct hsw_wrpll_rnp best = { 0, 0, 0 };
-       unsigned budget;
-
-       freq2k = clock / 100;
-
-       budget = hsw_wrpll_get_budget_for_freq(clock);
-
-       /* Special case handling for 540 pixel clock: bypass WR PLL entirely
-        * and directly pass the LC PLL to it. */
-       if (freq2k == 5400000) {
-               *n2_out = 2;
-               *p_out = 1;
-               *r2_out = 2;
-               return;
-       }
-
-       /*
-        * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
-        * the WR PLL.
-        *
-        * We want R so that REF_MIN <= Ref <= REF_MAX.
-        * Injecting R2 = 2 * R gives:
-        *   REF_MAX * r2 > LC_FREQ * 2 and
-        *   REF_MIN * r2 < LC_FREQ * 2
-        *
-        * Which means the desired boundaries for r2 are:
-        *  LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
-        *
-        */
-       for (r2 = LC_FREQ * 2 / REF_MAX + 1;
-            r2 <= LC_FREQ * 2 / REF_MIN;
-            r2++) {
-
-               /*
-                * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
-                *
-                * Once again we want VCO_MIN <= VCO <= VCO_MAX.
-                * Injecting R2 = 2 * R and N2 = 2 * N, we get:
-                *   VCO_MAX * r2 > n2 * LC_FREQ and
-                *   VCO_MIN * r2 < n2 * LC_FREQ)
-                *
-                * Which means the desired boundaries for n2 are:
-                * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
-                */
-               for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
-                    n2 <= VCO_MAX * r2 / LC_FREQ;
-                    n2++) {
-
-                       for (p = P_MIN; p <= P_MAX; p += P_INC)
-                               hsw_wrpll_update_rnp(freq2k, budget,
-                                                    r2, n2, p, &best);
-               }
-       }
-
-       *n2_out = best.n2;
-       *p_out = best.p;
-       *r2_out = best.r2;
-}
-
 static bool
 hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
                   struct intel_crtc_state *crtc_state,
                   struct intel_encoder *intel_encoder)
 {
-       int clock = crtc_state->port_clock;
-
-       if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-               struct intel_shared_dpll *pll;
-               uint32_t val;
-               unsigned p, n2, r2;
-
-               hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
-
-               val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
-                     WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
-                     WRPLL_DIVIDER_POST(p);
-
-               memset(&crtc_state->dpll_hw_state, 0,
-                      sizeof(crtc_state->dpll_hw_state));
-
-               crtc_state->dpll_hw_state.wrpll = val;
-
-               pll = intel_get_shared_dpll(intel_crtc, crtc_state);
-               if (pll == NULL) {
-                       DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
-                                        pipe_name(intel_crtc->pipe));
-                       return false;
-               }
-
-               crtc_state->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
-       } else if (crtc_state->ddi_pll_sel == PORT_CLK_SEL_SPLL) {
-               struct drm_atomic_state *state = crtc_state->base.state;
-               struct intel_shared_dpll_config *spll =
-                       &intel_atomic_get_shared_dpll_state(state)[DPLL_ID_SPLL];
-
-               if (spll->crtc_mask &&
-                   WARN_ON(spll->hw_state.spll != crtc_state->dpll_hw_state.spll))
-                       return false;
-
-               crtc_state->shared_dpll = DPLL_ID_SPLL;
-               spll->hw_state.spll = crtc_state->dpll_hw_state.spll;
-               spll->crtc_mask |= 1 << intel_crtc->pipe;
-       }
-
-       return true;
-}
-
-struct skl_wrpll_context {
-       uint64_t min_deviation;         /* current minimal deviation */
-       uint64_t central_freq;          /* chosen central freq */
-       uint64_t dco_freq;              /* chosen dco freq */
-       unsigned int p;                 /* chosen divider */
-};
-
-static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
-{
-       memset(ctx, 0, sizeof(*ctx));
-
-       ctx->min_deviation = U64_MAX;
-}
-
-/* DCO freq must be within +1%/-6%  of the DCO central freq */
-#define SKL_DCO_MAX_PDEVIATION 100
-#define SKL_DCO_MAX_NDEVIATION 600
-
-static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
-                                 uint64_t central_freq,
-                                 uint64_t dco_freq,
-                                 unsigned int divider)
-{
-       uint64_t deviation;
-
-       deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
-                             central_freq);
-
-       /* positive deviation */
-       if (dco_freq >= central_freq) {
-               if (deviation < SKL_DCO_MAX_PDEVIATION &&
-                   deviation < ctx->min_deviation) {
-                       ctx->min_deviation = deviation;
-                       ctx->central_freq = central_freq;
-                       ctx->dco_freq = dco_freq;
-                       ctx->p = divider;
-               }
-       /* negative deviation */
-       } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
-                  deviation < ctx->min_deviation) {
-               ctx->min_deviation = deviation;
-               ctx->central_freq = central_freq;
-               ctx->dco_freq = dco_freq;
-               ctx->p = divider;
-       }
-}
-
-static void skl_wrpll_get_multipliers(unsigned int p,
-                                     unsigned int *p0 /* out */,
-                                     unsigned int *p1 /* out */,
-                                     unsigned int *p2 /* out */)
-{
-       /* even dividers */
-       if (p % 2 == 0) {
-               unsigned int half = p / 2;
-
-               if (half == 1 || half == 2 || half == 3 || half == 5) {
-                       *p0 = 2;
-                       *p1 = 1;
-                       *p2 = half;
-               } else if (half % 2 == 0) {
-                       *p0 = 2;
-                       *p1 = half / 2;
-                       *p2 = 2;
-               } else if (half % 3 == 0) {
-                       *p0 = 3;
-                       *p1 = half / 3;
-                       *p2 = 2;
-               } else if (half % 7 == 0) {
-                       *p0 = 7;
-                       *p1 = half / 7;
-                       *p2 = 2;
-               }
-       } else if (p == 3 || p == 9) {  /* 3, 5, 7, 9, 15, 21, 35 */
-               *p0 = 3;
-               *p1 = 1;
-               *p2 = p / 3;
-       } else if (p == 5 || p == 7) {
-               *p0 = p;
-               *p1 = 1;
-               *p2 = 1;
-       } else if (p == 15) {
-               *p0 = 3;
-               *p1 = 1;
-               *p2 = 5;
-       } else if (p == 21) {
-               *p0 = 7;
-               *p1 = 1;
-               *p2 = 3;
-       } else if (p == 35) {
-               *p0 = 7;
-               *p1 = 1;
-               *p2 = 5;
-       }
-}
-
-struct skl_wrpll_params {
-       uint32_t        dco_fraction;
-       uint32_t        dco_integer;
-       uint32_t        qdiv_ratio;
-       uint32_t        qdiv_mode;
-       uint32_t        kdiv;
-       uint32_t        pdiv;
-       uint32_t        central_freq;
-};
-
-static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
-                                     uint64_t afe_clock,
-                                     uint64_t central_freq,
-                                     uint32_t p0, uint32_t p1, uint32_t p2)
-{
-       uint64_t dco_freq;
-
-       switch (central_freq) {
-       case 9600000000ULL:
-               params->central_freq = 0;
-               break;
-       case 9000000000ULL:
-               params->central_freq = 1;
-               break;
-       case 8400000000ULL:
-               params->central_freq = 3;
-       }
-
-       switch (p0) {
-       case 1:
-               params->pdiv = 0;
-               break;
-       case 2:
-               params->pdiv = 1;
-               break;
-       case 3:
-               params->pdiv = 2;
-               break;
-       case 7:
-               params->pdiv = 4;
-               break;
-       default:
-               WARN(1, "Incorrect PDiv\n");
-       }
-
-       switch (p2) {
-       case 5:
-               params->kdiv = 0;
-               break;
-       case 2:
-               params->kdiv = 1;
-               break;
-       case 3:
-               params->kdiv = 2;
-               break;
-       case 1:
-               params->kdiv = 3;
-               break;
-       default:
-               WARN(1, "Incorrect KDiv\n");
-       }
-
-       params->qdiv_ratio = p1;
-       params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
-
-       dco_freq = p0 * p1 * p2 * afe_clock;
-
-       /*
-        * Intermediate values are in Hz.
-        * Divide by MHz to match bsepc
-        */
-       params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
-       params->dco_fraction =
-               div_u64((div_u64(dco_freq, 24) -
-                        params->dco_integer * MHz(1)) * 0x8000, MHz(1));
-}
-
-static bool
-skl_ddi_calculate_wrpll(int clock /* in Hz */,
-                       struct skl_wrpll_params *wrpll_params)
-{
-       uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
-       uint64_t dco_central_freq[3] = {8400000000ULL,
-                                       9000000000ULL,
-                                       9600000000ULL};
-       static const int even_dividers[] = {  4,  6,  8, 10, 12, 14, 16, 18, 20,
-                                            24, 28, 30, 32, 36, 40, 42, 44,
-                                            48, 52, 54, 56, 60, 64, 66, 68,
-                                            70, 72, 76, 78, 80, 84, 88, 90,
-                                            92, 96, 98 };
-       static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
-       static const struct {
-               const int *list;
-               int n_dividers;
-       } dividers[] = {
-               { even_dividers, ARRAY_SIZE(even_dividers) },
-               { odd_dividers, ARRAY_SIZE(odd_dividers) },
-       };
-       struct skl_wrpll_context ctx;
-       unsigned int dco, d, i;
-       unsigned int p0, p1, p2;
-
-       skl_wrpll_context_init(&ctx);
-
-       for (d = 0; d < ARRAY_SIZE(dividers); d++) {
-               for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
-                       for (i = 0; i < dividers[d].n_dividers; i++) {
-                               unsigned int p = dividers[d].list[i];
-                               uint64_t dco_freq = p * afe_clock;
-
-                               skl_wrpll_try_divider(&ctx,
-                                                     dco_central_freq[dco],
-                                                     dco_freq,
-                                                     p);
-                               /*
-                                * Skip the remaining dividers if we're sure to
-                                * have found the definitive divider, we can't
-                                * improve a 0 deviation.
-                                */
-                               if (ctx.min_deviation == 0)
-                                       goto skip_remaining_dividers;
-                       }
-               }
-
-skip_remaining_dividers:
-               /*
-                * If a solution is found with an even divider, prefer
-                * this one.
-                */
-               if (d == 0 && ctx.p)
-                       break;
-       }
-
-       if (!ctx.p) {
-               DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
-               return false;
-       }
+       struct intel_shared_dpll *pll;
 
-       /*
-        * gcc incorrectly analyses that these can be used without being
-        * initialized. To be fair, it's hard to guess.
-        */
-       p0 = p1 = p2 = 0;
-       skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
-       skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
-                                 p0, p1, p2);
+       pll = intel_get_shared_dpll(intel_crtc, crtc_state,
+                                   intel_encoder);
+       if (!pll)
+               DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
+                                pipe_name(intel_crtc->pipe));
 
-       return true;
+       return pll;
 }
 
 static bool
@@ -1504,218 +1007,23 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc,
                   struct intel_encoder *intel_encoder)
 {
        struct intel_shared_dpll *pll;
-       uint32_t ctrl1, cfgcr1, cfgcr2;
-       int clock = crtc_state->port_clock;
-
-       /*
-        * See comment in intel_dpll_hw_state to understand why we always use 0
-        * as the DPLL id in this function.
-        */
 
-       ctrl1 = DPLL_CTRL1_OVERRIDE(0);
-
-       if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-               struct skl_wrpll_params wrpll_params = { 0, };
-
-               ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
-
-               if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
-                       return false;
-
-               cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
-                        DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
-                        wrpll_params.dco_integer;
-
-               cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
-                        DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
-                        DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
-                        DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
-                        wrpll_params.central_freq;
-       } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
-                  intel_encoder->type == INTEL_OUTPUT_DP_MST) {
-               switch (crtc_state->port_clock / 2) {
-               case 81000:
-                       ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
-                       break;
-               case 135000:
-                       ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
-                       break;
-               case 270000:
-                       ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
-                       break;
-               }
-
-               cfgcr1 = cfgcr2 = 0;
-       } else if (intel_encoder->type == INTEL_OUTPUT_EDP) {
-               return true;
-       } else
-               return false;
-
-       memset(&crtc_state->dpll_hw_state, 0,
-              sizeof(crtc_state->dpll_hw_state));
-
-       crtc_state->dpll_hw_state.ctrl1 = ctrl1;
-       crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
-       crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
-
-       pll = intel_get_shared_dpll(intel_crtc, crtc_state);
+       pll = intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder);
        if (pll == NULL) {
                DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
                                 pipe_name(intel_crtc->pipe));
                return false;
        }
 
-       /* shared DPLL id 0 is DPLL 1 */
-       crtc_state->ddi_pll_sel = pll->id + 1;
-
        return true;
 }
 
-/* bxt clock parameters */
-struct bxt_clk_div {
-       int clock;
-       uint32_t p1;
-       uint32_t p2;
-       uint32_t m2_int;
-       uint32_t m2_frac;
-       bool m2_frac_en;
-       uint32_t n;
-};
-
-/* pre-calculated values for DP linkrates */
-static const struct bxt_clk_div bxt_dp_clk_val[] = {
-       {162000, 4, 2, 32, 1677722, 1, 1},
-       {270000, 4, 1, 27,       0, 0, 1},
-       {540000, 2, 1, 27,       0, 0, 1},
-       {216000, 3, 2, 32, 1677722, 1, 1},
-       {243000, 4, 1, 24, 1258291, 1, 1},
-       {324000, 4, 1, 32, 1677722, 1, 1},
-       {432000, 3, 1, 32, 1677722, 1, 1}
-};
-
 static bool
 bxt_ddi_pll_select(struct intel_crtc *intel_crtc,
                   struct intel_crtc_state *crtc_state,
                   struct intel_encoder *intel_encoder)
 {
-       struct intel_shared_dpll *pll;
-       struct bxt_clk_div clk_div = {0};
-       int vco = 0;
-       uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
-       uint32_t lanestagger;
-       int clock = crtc_state->port_clock;
-
-       if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-               intel_clock_t best_clock;
-
-               /* Calculate HDMI div */
-               /*
-                * FIXME: tie the following calculation into
-                * i9xx_crtc_compute_clock
-                */
-               if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
-                       DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
-                                        clock, pipe_name(intel_crtc->pipe));
-                       return false;
-               }
-
-               clk_div.p1 = best_clock.p1;
-               clk_div.p2 = best_clock.p2;
-               WARN_ON(best_clock.m1 != 2);
-               clk_div.n = best_clock.n;
-               clk_div.m2_int = best_clock.m2 >> 22;
-               clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1);
-               clk_div.m2_frac_en = clk_div.m2_frac != 0;
-
-               vco = best_clock.vco;
-       } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
-                       intel_encoder->type == INTEL_OUTPUT_EDP) {
-               int i;
-
-               clk_div = bxt_dp_clk_val[0];
-               for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
-                       if (bxt_dp_clk_val[i].clock == clock) {
-                               clk_div = bxt_dp_clk_val[i];
-                               break;
-                       }
-               }
-               vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2;
-       }
-
-       if (vco >= 6200000 && vco <= 6700000) {
-               prop_coef = 4;
-               int_coef = 9;
-               gain_ctl = 3;
-               targ_cnt = 8;
-       } else if ((vco > 5400000 && vco < 6200000) ||
-                       (vco >= 4800000 && vco < 5400000)) {
-               prop_coef = 5;
-               int_coef = 11;
-               gain_ctl = 3;
-               targ_cnt = 9;
-       } else if (vco == 5400000) {
-               prop_coef = 3;
-               int_coef = 8;
-               gain_ctl = 1;
-               targ_cnt = 9;
-       } else {
-               DRM_ERROR("Invalid VCO\n");
-               return false;
-       }
-
-       memset(&crtc_state->dpll_hw_state, 0,
-              sizeof(crtc_state->dpll_hw_state));
-
-       if (clock > 270000)
-               lanestagger = 0x18;
-       else if (clock > 135000)
-               lanestagger = 0x0d;
-       else if (clock > 67000)
-               lanestagger = 0x07;
-       else if (clock > 33000)
-               lanestagger = 0x04;
-       else
-               lanestagger = 0x02;
-
-       crtc_state->dpll_hw_state.ebb0 =
-               PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2);
-       crtc_state->dpll_hw_state.pll0 = clk_div.m2_int;
-       crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n);
-       crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac;
-
-       if (clk_div.m2_frac_en)
-               crtc_state->dpll_hw_state.pll3 =
-                       PORT_PLL_M2_FRAC_ENABLE;
-
-       crtc_state->dpll_hw_state.pll6 =
-               prop_coef | PORT_PLL_INT_COEFF(int_coef);
-       crtc_state->dpll_hw_state.pll6 |=
-               PORT_PLL_GAIN_CTL(gain_ctl);
-
-       crtc_state->dpll_hw_state.pll8 = targ_cnt;
-
-       crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
-
-       crtc_state->dpll_hw_state.pll10 =
-               PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
-               | PORT_PLL_DCO_AMP_OVR_EN_H;
-
-       crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
-
-       crtc_state->dpll_hw_state.pcsdw12 =
-               LANESTAGGER_STRAP_OVRD | lanestagger;
-
-       pll = intel_get_shared_dpll(intel_crtc, crtc_state);
-       if (pll == NULL) {
-               DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
-                       pipe_name(intel_crtc->pipe));
-               return false;
-       }
-
-       /* shared DPLL id 0 is DPLL A */
-       crtc_state->ddi_pll_sel = pll->id;
-
-       return true;
+       return !!intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder);
 }
 
 /*
@@ -1753,6 +1061,8 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
        uint32_t temp;
 
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP_MST) {
+               WARN_ON(transcoder_is_dsi(cpu_transcoder));
+
                temp = TRANS_MSA_SYNC_CLK;
                switch (intel_crtc->config->pipe_bpp) {
                case 18:
@@ -2121,7 +1431,7 @@ static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv,
        u32 n_entries, i;
        uint32_t val;
 
-       if (type == INTEL_OUTPUT_EDP && dev_priv->edp_low_vswing) {
+       if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
                n_entries = ARRAY_SIZE(bxt_ddi_translations_edp);
                ddi_translations = bxt_ddi_translations_edp;
        } else if (type == INTEL_OUTPUT_DISPLAYPORT
@@ -2259,24 +1569,6 @@ void intel_ddi_clk_select(struct intel_encoder *encoder,
                uint32_t dpll = pipe_config->ddi_pll_sel;
                uint32_t val;
 
-               /*
-                * DPLL0 is used for eDP and is the only "private" DPLL (as
-                * opposed to shared) on SKL
-                */
-               if (encoder->type == INTEL_OUTPUT_EDP) {
-                       WARN_ON(dpll != SKL_DPLL0);
-
-                       val = I915_READ(DPLL_CTRL1);
-
-                       val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) |
-                                DPLL_CTRL1_SSC(dpll) |
-                                DPLL_CTRL1_LINK_RATE_MASK(dpll));
-                       val |= pipe_config->dpll_hw_state.ctrl1 << (dpll * 6);
-
-                       I915_WRITE(DPLL_CTRL1, val);
-                       POSTING_READ(DPLL_CTRL1);
-               }
-
                /* DDI -> PLL mapping  */
                val = I915_READ(DPLL_CTRL2);
 
@@ -2430,235 +1722,6 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
        }
 }
 
-static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
-                              struct intel_shared_dpll *pll)
-{
-       I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
-       POSTING_READ(WRPLL_CTL(pll->id));
-       udelay(20);
-}
-
-static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
-                               struct intel_shared_dpll *pll)
-{
-       I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
-       POSTING_READ(SPLL_CTL);
-       udelay(20);
-}
-
-static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
-                                 struct intel_shared_dpll *pll)
-{
-       uint32_t val;
-
-       val = I915_READ(WRPLL_CTL(pll->id));
-       I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
-       POSTING_READ(WRPLL_CTL(pll->id));
-}
-
-static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
-                                struct intel_shared_dpll *pll)
-{
-       uint32_t val;
-
-       val = I915_READ(SPLL_CTL);
-       I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
-       POSTING_READ(SPLL_CTL);
-}
-
-static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
-                                      struct intel_shared_dpll *pll,
-                                      struct intel_dpll_hw_state *hw_state)
-{
-       uint32_t val;
-
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
-               return false;
-
-       val = I915_READ(WRPLL_CTL(pll->id));
-       hw_state->wrpll = val;
-
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-
-       return val & WRPLL_PLL_ENABLE;
-}
-
-static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
-                                     struct intel_shared_dpll *pll,
-                                     struct intel_dpll_hw_state *hw_state)
-{
-       uint32_t val;
-
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
-               return false;
-
-       val = I915_READ(SPLL_CTL);
-       hw_state->spll = val;
-
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-
-       return val & SPLL_PLL_ENABLE;
-}
-
-
-static const char * const hsw_ddi_pll_names[] = {
-       "WRPLL 1",
-       "WRPLL 2",
-       "SPLL"
-};
-
-static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv)
-{
-       int i;
-
-       dev_priv->num_shared_dpll = 3;
-
-       for (i = 0; i < 2; i++) {
-               dev_priv->shared_dplls[i].id = i;
-               dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
-               dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable;
-               dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable;
-               dev_priv->shared_dplls[i].get_hw_state =
-                       hsw_ddi_wrpll_get_hw_state;
-       }
-
-       /* SPLL is special, but needs to be initialized anyway.. */
-       dev_priv->shared_dplls[i].id = i;
-       dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
-       dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable;
-       dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable;
-       dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state;
-
-}
-
-static const char * const skl_ddi_pll_names[] = {
-       "DPLL 1",
-       "DPLL 2",
-       "DPLL 3",
-};
-
-struct skl_dpll_regs {
-       i915_reg_t ctl, cfgcr1, cfgcr2;
-};
-
-/* this array is indexed by the *shared* pll id */
-static const struct skl_dpll_regs skl_dpll_regs[3] = {
-       {
-               /* DPLL 1 */
-               .ctl = LCPLL2_CTL,
-               .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
-               .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
-       },
-       {
-               /* DPLL 2 */
-               .ctl = WRPLL_CTL(0),
-               .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
-               .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
-       },
-       {
-               /* DPLL 3 */
-               .ctl = WRPLL_CTL(1),
-               .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
-               .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
-       },
-};
-
-static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
-                              struct intel_shared_dpll *pll)
-{
-       uint32_t val;
-       unsigned int dpll;
-       const struct skl_dpll_regs *regs = skl_dpll_regs;
-
-       /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
-       dpll = pll->id + 1;
-
-       val = I915_READ(DPLL_CTRL1);
-
-       val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) |
-                DPLL_CTRL1_LINK_RATE_MASK(dpll));
-       val |= pll->config.hw_state.ctrl1 << (dpll * 6);
-
-       I915_WRITE(DPLL_CTRL1, val);
-       POSTING_READ(DPLL_CTRL1);
-
-       I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
-       I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
-       POSTING_READ(regs[pll->id].cfgcr1);
-       POSTING_READ(regs[pll->id].cfgcr2);
-
-       /* the enable bit is always bit 31 */
-       I915_WRITE(regs[pll->id].ctl,
-                  I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
-
-       if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5))
-               DRM_ERROR("DPLL %d not locked\n", dpll);
-}
-
-static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
-                               struct intel_shared_dpll *pll)
-{
-       const struct skl_dpll_regs *regs = skl_dpll_regs;
-
-       /* the enable bit is always bit 31 */
-       I915_WRITE(regs[pll->id].ctl,
-                  I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
-       POSTING_READ(regs[pll->id].ctl);
-}
-
-static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
-                                    struct intel_shared_dpll *pll,
-                                    struct intel_dpll_hw_state *hw_state)
-{
-       uint32_t val;
-       unsigned int dpll;
-       const struct skl_dpll_regs *regs = skl_dpll_regs;
-       bool ret;
-
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
-               return false;
-
-       ret = false;
-
-       /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
-       dpll = pll->id + 1;
-
-       val = I915_READ(regs[pll->id].ctl);
-       if (!(val & LCPLL_PLL_ENABLE))
-               goto out;
-
-       val = I915_READ(DPLL_CTRL1);
-       hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f;
-
-       /* avoid reading back stale values if HDMI mode is not enabled */
-       if (val & DPLL_CTRL1_HDMI_MODE(dpll)) {
-               hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
-               hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
-       }
-       ret = true;
-
-out:
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-
-       return ret;
-}
-
-static void skl_shared_dplls_init(struct drm_i915_private *dev_priv)
-{
-       int i;
-
-       dev_priv->num_shared_dpll = 3;
-
-       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-               dev_priv->shared_dplls[i].id = i;
-               dev_priv->shared_dplls[i].name = skl_ddi_pll_names[i];
-               dev_priv->shared_dplls[i].disable = skl_ddi_pll_disable;
-               dev_priv->shared_dplls[i].enable = skl_ddi_pll_enable;
-               dev_priv->shared_dplls[i].get_hw_state =
-                       skl_ddi_pll_get_hw_state;
-       }
-}
-
 static void broxton_phy_init(struct drm_i915_private *dev_priv,
                             enum dpio_phy phy)
 {
@@ -2783,249 +1846,6 @@ void broxton_ddi_phy_uninit(struct drm_device *dev)
        I915_WRITE(BXT_P_CR_GT_DISP_PWRON, 0);
 }
 
-static const char * const bxt_ddi_pll_names[] = {
-       "PORT PLL A",
-       "PORT PLL B",
-       "PORT PLL C",
-};
-
-static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
-                               struct intel_shared_dpll *pll)
-{
-       uint32_t temp;
-       enum port port = (enum port)pll->id;    /* 1:1 port->PLL mapping */
-
-       temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
-       temp &= ~PORT_PLL_REF_SEL;
-       /* Non-SSC reference */
-       I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
-
-       /* Disable 10 bit clock */
-       temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
-       temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
-       I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
-
-       /* Write P1 & P2 */
-       temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
-       temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
-       temp |= pll->config.hw_state.ebb0;
-       I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
-
-       /* Write M2 integer */
-       temp = I915_READ(BXT_PORT_PLL(port, 0));
-       temp &= ~PORT_PLL_M2_MASK;
-       temp |= pll->config.hw_state.pll0;
-       I915_WRITE(BXT_PORT_PLL(port, 0), temp);
-
-       /* Write N */
-       temp = I915_READ(BXT_PORT_PLL(port, 1));
-       temp &= ~PORT_PLL_N_MASK;
-       temp |= pll->config.hw_state.pll1;
-       I915_WRITE(BXT_PORT_PLL(port, 1), temp);
-
-       /* Write M2 fraction */
-       temp = I915_READ(BXT_PORT_PLL(port, 2));
-       temp &= ~PORT_PLL_M2_FRAC_MASK;
-       temp |= pll->config.hw_state.pll2;
-       I915_WRITE(BXT_PORT_PLL(port, 2), temp);
-
-       /* Write M2 fraction enable */
-       temp = I915_READ(BXT_PORT_PLL(port, 3));
-       temp &= ~PORT_PLL_M2_FRAC_ENABLE;
-       temp |= pll->config.hw_state.pll3;
-       I915_WRITE(BXT_PORT_PLL(port, 3), temp);
-
-       /* Write coeff */
-       temp = I915_READ(BXT_PORT_PLL(port, 6));
-       temp &= ~PORT_PLL_PROP_COEFF_MASK;
-       temp &= ~PORT_PLL_INT_COEFF_MASK;
-       temp &= ~PORT_PLL_GAIN_CTL_MASK;
-       temp |= pll->config.hw_state.pll6;
-       I915_WRITE(BXT_PORT_PLL(port, 6), temp);
-
-       /* Write calibration val */
-       temp = I915_READ(BXT_PORT_PLL(port, 8));
-       temp &= ~PORT_PLL_TARGET_CNT_MASK;
-       temp |= pll->config.hw_state.pll8;
-       I915_WRITE(BXT_PORT_PLL(port, 8), temp);
-
-       temp = I915_READ(BXT_PORT_PLL(port, 9));
-       temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
-       temp |= pll->config.hw_state.pll9;
-       I915_WRITE(BXT_PORT_PLL(port, 9), temp);
-
-       temp = I915_READ(BXT_PORT_PLL(port, 10));
-       temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
-       temp &= ~PORT_PLL_DCO_AMP_MASK;
-       temp |= pll->config.hw_state.pll10;
-       I915_WRITE(BXT_PORT_PLL(port, 10), temp);
-
-       /* Recalibrate with new settings */
-       temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
-       temp |= PORT_PLL_RECALIBRATE;
-       I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
-       temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
-       temp |= pll->config.hw_state.ebb4;
-       I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
-
-       /* Enable PLL */
-       temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
-       temp |= PORT_PLL_ENABLE;
-       I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
-       POSTING_READ(BXT_PORT_PLL_ENABLE(port));
-
-       if (wait_for_atomic_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
-                       PORT_PLL_LOCK), 200))
-               DRM_ERROR("PLL %d not locked\n", port);
-
-       /*
-        * While we write to the group register to program all lanes at once we
-        * can read only lane registers and we pick lanes 0/1 for that.
-        */
-       temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
-       temp &= ~LANE_STAGGER_MASK;
-       temp &= ~LANESTAGGER_STRAP_OVRD;
-       temp |= pll->config.hw_state.pcsdw12;
-       I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
-}
-
-static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
-                                       struct intel_shared_dpll *pll)
-{
-       enum port port = (enum port)pll->id;    /* 1:1 port->PLL mapping */
-       uint32_t temp;
-
-       temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
-       temp &= ~PORT_PLL_ENABLE;
-       I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
-       POSTING_READ(BXT_PORT_PLL_ENABLE(port));
-}
-
-static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
-                                       struct intel_shared_dpll *pll,
-                                       struct intel_dpll_hw_state *hw_state)
-{
-       enum port port = (enum port)pll->id;    /* 1:1 port->PLL mapping */
-       uint32_t val;
-       bool ret;
-
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
-               return false;
-
-       ret = false;
-
-       val = I915_READ(BXT_PORT_PLL_ENABLE(port));
-       if (!(val & PORT_PLL_ENABLE))
-               goto out;
-
-       hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
-       hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
-
-       hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
-       hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
-
-       hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
-       hw_state->pll0 &= PORT_PLL_M2_MASK;
-
-       hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
-       hw_state->pll1 &= PORT_PLL_N_MASK;
-
-       hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
-       hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
-
-       hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
-       hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
-
-       hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
-       hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
-                         PORT_PLL_INT_COEFF_MASK |
-                         PORT_PLL_GAIN_CTL_MASK;
-
-       hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
-       hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
-
-       hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
-       hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
-
-       hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
-       hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
-                          PORT_PLL_DCO_AMP_MASK;
-
-       /*
-        * While we write to the group register to program all lanes at once we
-        * can read only lane registers. We configure all lanes the same way, so
-        * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
-        */
-       hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
-       if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
-               DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
-                                hw_state->pcsdw12,
-                                I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
-       hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
-
-       ret = true;
-
-out:
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-
-       return ret;
-}
-
-static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv)
-{
-       int i;
-
-       dev_priv->num_shared_dpll = 3;
-
-       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-               dev_priv->shared_dplls[i].id = i;
-               dev_priv->shared_dplls[i].name = bxt_ddi_pll_names[i];
-               dev_priv->shared_dplls[i].disable = bxt_ddi_pll_disable;
-               dev_priv->shared_dplls[i].enable = bxt_ddi_pll_enable;
-               dev_priv->shared_dplls[i].get_hw_state =
-                       bxt_ddi_pll_get_hw_state;
-       }
-}
-
-void intel_ddi_pll_init(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t val = I915_READ(LCPLL_CTL);
-
-       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
-               skl_shared_dplls_init(dev_priv);
-       else if (IS_BROXTON(dev))
-               bxt_shared_dplls_init(dev_priv);
-       else
-               hsw_shared_dplls_init(dev_priv);
-
-       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
-               int cdclk_freq;
-
-               cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
-               dev_priv->skl_boot_cdclk = cdclk_freq;
-               if (skl_sanitize_cdclk(dev_priv))
-                       DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
-               if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
-                       DRM_ERROR("LCPLL1 is disabled\n");
-       } else if (IS_BROXTON(dev)) {
-               broxton_init_cdclk(dev);
-               broxton_ddi_phy_init(dev);
-       } else {
-               /*
-                * The LCPLL register should be turned on by the BIOS. For now
-                * let's just check its state and print errors in case
-                * something is wrong.  Don't even try to turn it on.
-                */
-
-               if (val & LCPLL_CD_SOURCE_FCLK)
-                       DRM_ERROR("CDCLK source is not LCPLL\n");
-
-               if (val & LCPLL_PLL_DISABLE)
-                       DRM_ERROR("LCPLL is disabled\n");
-       }
-}
-
 void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -3124,6 +1944,10 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
        struct intel_hdmi *intel_hdmi;
        u32 temp, flags = 0;
 
+       /* XXX: DSI transcoder paranoia */
+       if (WARN_ON(transcoder_is_dsi(cpu_transcoder)))
+               return;
+
        temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
        if (temp & TRANS_DDI_PHSYNC)
                flags |= DRM_MODE_FLAG_PHSYNC;
@@ -3178,8 +2002,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
        pipe_config->has_audio =
                intel_ddi_is_audio_enabled(dev_priv, intel_crtc);
 
-       if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp &&
-           pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
+       if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.bpp &&
+           pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) {
                /*
                 * This is a big fat ugly hack.
                 *
@@ -3194,8 +2018,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
                 * load.
                 */
                DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n",
-                             pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp);
-               dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
+                             pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp);
+               dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp;
        }
 
        intel_ddi_clock_get(encoder, pipe_config);
index 6e0d828..29aa64b 100644 (file)
@@ -36,6 +36,7 @@
 #include "intel_drv.h"
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
+#include "intel_dsi.h"
 #include "i915_trace.h"
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -96,12 +97,13 @@ static int intel_framebuffer_init(struct drm_device *dev,
                                  struct drm_i915_gem_object *obj);
 static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc);
 static void intel_set_pipe_timings(struct intel_crtc *intel_crtc);
+static void intel_set_pipe_src_size(struct intel_crtc *intel_crtc);
 static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
                                         struct intel_link_m_n *m_n,
                                         struct intel_link_m_n *m2_n2);
 static void ironlake_set_pipeconf(struct drm_crtc *crtc);
 static void haswell_set_pipeconf(struct drm_crtc *crtc);
-static void intel_set_pipe_csc(struct drm_crtc *crtc);
+static void haswell_set_pipemisc(struct drm_crtc *crtc);
 static void vlv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_state *pipe_config);
 static void chv_prepare_pll(struct intel_crtc *crtc,
@@ -110,13 +112,11 @@ static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
 static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
 static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
        struct intel_crtc_state *crtc_state);
-static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
-                          int num_connectors);
 static void skylake_pfit_enable(struct intel_crtc *crtc);
 static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
-static void intel_pre_disable_primary(struct drm_crtc *crtc);
+static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
 
 typedef struct {
        int     min, max;
@@ -169,49 +169,62 @@ static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
        return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, divider + 1);
 }
 
-int
-intel_pch_rawclk(struct drm_device *dev)
+static int
+intel_pch_rawclk(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       WARN_ON(!HAS_PCH_SPLIT(dev));
+       return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
+}
 
-       return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK;
+static int
+intel_vlv_hrawclk(struct drm_i915_private *dev_priv)
+{
+       return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
+                                     CCK_DISPLAY_REF_CLOCK_CONTROL);
 }
 
-/* hrawclock is 1/4 the FSB frequency */
-int intel_hrawclk(struct drm_device *dev)
+static int
+intel_g4x_hrawclk(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t clkcfg;
 
-       /* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
-       if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
-               return 200;
-
+       /* hrawclock is 1/4 the FSB frequency */
        clkcfg = I915_READ(CLKCFG);
        switch (clkcfg & CLKCFG_FSB_MASK) {
        case CLKCFG_FSB_400:
-               return 100;
+               return 100000;
        case CLKCFG_FSB_533:
-               return 133;
+               return 133333;
        case CLKCFG_FSB_667:
-               return 166;
+               return 166667;
        case CLKCFG_FSB_800:
-               return 200;
+               return 200000;
        case CLKCFG_FSB_1067:
-               return 266;
+               return 266667;
        case CLKCFG_FSB_1333:
-               return 333;
+               return 333333;
        /* these two are just a guess; one of them might be right */
        case CLKCFG_FSB_1600:
        case CLKCFG_FSB_1600_ALT:
-               return 400;
+               return 400000;
        default:
-               return 133;
+               return 133333;
        }
 }
 
+static void intel_update_rawclk(struct drm_i915_private *dev_priv)
+{
+       if (HAS_PCH_SPLIT(dev_priv))
+               dev_priv->rawclk_freq = intel_pch_rawclk(dev_priv);
+       else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+               dev_priv->rawclk_freq = intel_vlv_hrawclk(dev_priv);
+       else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
+               dev_priv->rawclk_freq = intel_g4x_hrawclk(dev_priv);
+       else
+               return; /* no rawclk on other platforms, or no need to know it */
+
+       DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
+}
+
 static void intel_update_czclk(struct drm_i915_private *dev_priv)
 {
        if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
@@ -224,13 +237,15 @@ static void intel_update_czclk(struct drm_i915_private *dev_priv)
 }
 
 static inline u32 /* units of 100MHz */
-intel_fdi_link_freq(struct drm_device *dev)
+intel_fdi_link_freq(struct drm_i915_private *dev_priv,
+                   const struct intel_crtc_state *pipe_config)
 {
-       if (IS_GEN5(dev)) {
-               struct drm_i915_private *dev_priv = dev->dev_private;
-               return (I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2;
-       } else
-               return 27;
+       if (HAS_DDI(dev_priv))
+               return pipe_config->port_clock; /* SPLL */
+       else if (IS_GEN5(dev_priv))
+               return ((I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2) * 10000;
+       else
+               return 270000;
 }
 
 static const intel_limit_t intel_limits_i8xx_dac = {
@@ -550,89 +565,6 @@ static bool intel_pipe_will_have_type(const struct intel_crtc_state *crtc_state,
        return false;
 }
 
-static const intel_limit_t *
-intel_ironlake_limit(struct intel_crtc_state *crtc_state, int refclk)
-{
-       struct drm_device *dev = crtc_state->base.crtc->dev;
-       const intel_limit_t *limit;
-
-       if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-               if (intel_is_dual_link_lvds(dev)) {
-                       if (refclk == 100000)
-                               limit = &intel_limits_ironlake_dual_lvds_100m;
-                       else
-                               limit = &intel_limits_ironlake_dual_lvds;
-               } else {
-                       if (refclk == 100000)
-                               limit = &intel_limits_ironlake_single_lvds_100m;
-                       else
-                               limit = &intel_limits_ironlake_single_lvds;
-               }
-       } else
-               limit = &intel_limits_ironlake_dac;
-
-       return limit;
-}
-
-static const intel_limit_t *
-intel_g4x_limit(struct intel_crtc_state *crtc_state)
-{
-       struct drm_device *dev = crtc_state->base.crtc->dev;
-       const intel_limit_t *limit;
-
-       if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-               if (intel_is_dual_link_lvds(dev))
-                       limit = &intel_limits_g4x_dual_channel_lvds;
-               else
-                       limit = &intel_limits_g4x_single_channel_lvds;
-       } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_HDMI) ||
-                  intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
-               limit = &intel_limits_g4x_hdmi;
-       } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_SDVO)) {
-               limit = &intel_limits_g4x_sdvo;
-       } else /* The option is for other outputs */
-               limit = &intel_limits_i9xx_sdvo;
-
-       return limit;
-}
-
-static const intel_limit_t *
-intel_limit(struct intel_crtc_state *crtc_state, int refclk)
-{
-       struct drm_device *dev = crtc_state->base.crtc->dev;
-       const intel_limit_t *limit;
-
-       if (IS_BROXTON(dev))
-               limit = &intel_limits_bxt;
-       else if (HAS_PCH_SPLIT(dev))
-               limit = intel_ironlake_limit(crtc_state, refclk);
-       else if (IS_G4X(dev)) {
-               limit = intel_g4x_limit(crtc_state);
-       } else if (IS_PINEVIEW(dev)) {
-               if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
-                       limit = &intel_limits_pineview_lvds;
-               else
-                       limit = &intel_limits_pineview_sdvo;
-       } else if (IS_CHERRYVIEW(dev)) {
-               limit = &intel_limits_chv;
-       } else if (IS_VALLEYVIEW(dev)) {
-               limit = &intel_limits_vlv;
-       } else if (!IS_GEN2(dev)) {
-               if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
-                       limit = &intel_limits_i9xx_lvds;
-               else
-                       limit = &intel_limits_i9xx_sdvo;
-       } else {
-               if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
-                       limit = &intel_limits_i8xx_lvds;
-               else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_DVO))
-                       limit = &intel_limits_i8xx_dvo;
-               else
-                       limit = &intel_limits_i8xx_dac;
-       }
-       return limit;
-}
-
 /*
  * Platform specific helpers to calculate the port PLL loopback- (clock.m),
  * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
@@ -763,6 +695,16 @@ i9xx_select_p2_div(const intel_limit_t *limit,
        }
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ *
+ * Target and reference clocks are specified in kHz.
+ *
+ * If match_clock is provided, then best_clock P divider must match the P
+ * divider from @match_clock used for LVDS downclocking.
+ */
 static bool
 i9xx_find_best_dpll(const intel_limit_t *limit,
                    struct intel_crtc_state *crtc_state,
@@ -810,6 +752,16 @@ i9xx_find_best_dpll(const intel_limit_t *limit,
        return (err != target);
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ *
+ * Target and reference clocks are specified in kHz.
+ *
+ * If match_clock is provided, then best_clock P divider must match the P
+ * divider from @match_clock used for LVDS downclocking.
+ */
 static bool
 pnv_find_best_dpll(const intel_limit_t *limit,
                   struct intel_crtc_state *crtc_state,
@@ -855,6 +807,16 @@ pnv_find_best_dpll(const intel_limit_t *limit,
        return (err != target);
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ *
+ * Target and reference clocks are specified in kHz.
+ *
+ * If match_clock is provided, then best_clock P divider must match the P
+ * divider from @match_clock used for LVDS downclocking.
+ */
 static bool
 g4x_find_best_dpll(const intel_limit_t *limit,
                   struct intel_crtc_state *crtc_state,
@@ -943,6 +905,11 @@ static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq,
        return *error_ppm + 10 < best_error_ppm;
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ */
 static bool
 vlv_find_best_dpll(const intel_limit_t *limit,
                   struct intel_crtc_state *crtc_state,
@@ -997,6 +964,11 @@ vlv_find_best_dpll(const intel_limit_t *limit,
        return found;
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ */
 static bool
 chv_find_best_dpll(const intel_limit_t *limit,
                   struct intel_crtc_state *crtc_state,
@@ -1058,9 +1030,10 @@ chv_find_best_dpll(const intel_limit_t *limit,
 bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
                        intel_clock_t *best_clock)
 {
-       int refclk = i9xx_get_refclk(crtc_state, 0);
+       int refclk = 100000;
+       const intel_limit_t *limit = &intel_limits_bxt;
 
-       return chv_find_best_dpll(intel_limit(crtc_state, refclk), crtc_state,
+       return chv_find_best_dpll(limit, crtc_state,
                                  target_clock, refclk, NULL, best_clock);
 }
 
@@ -1165,7 +1138,7 @@ void assert_pll(struct drm_i915_private *dev_priv,
 }
 
 /* XXX: the dsi pll is shared between MIPI DSI ports */
-static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
+void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
 {
        u32 val;
        bool cur_state;
@@ -1179,36 +1152,6 @@ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
             "DSI PLL state assertion failure (expected %s, current %s)\n",
                        onoff(state), onoff(cur_state));
 }
-#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
-#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
-
-struct intel_shared_dpll *
-intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
-{
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
-
-       if (crtc->config->shared_dpll < 0)
-               return NULL;
-
-       return &dev_priv->shared_dplls[crtc->config->shared_dpll];
-}
-
-/* For ILK+ */
-void assert_shared_dpll(struct drm_i915_private *dev_priv,
-                       struct intel_shared_dpll *pll,
-                       bool state)
-{
-       bool cur_state;
-       struct intel_dpll_hw_state hw_state;
-
-       if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
-               return;
-
-       cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
-       I915_STATE_WARN(cur_state != state,
-            "%s assertion failure (expected %s, current %s)\n",
-                       pll->name, onoff(state), onoff(cur_state));
-}
 
 static void assert_fdi_tx(struct drm_i915_private *dev_priv,
                          enum pipe pipe, bool state)
@@ -1446,21 +1389,8 @@ static void assert_vblank_disabled(struct drm_crtc *crtc)
                drm_crtc_vblank_put(crtc);
 }
 
-static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
-{
-       u32 val;
-       bool enabled;
-
-       I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev)));
-
-       val = I915_READ(PCH_DREF_CONTROL);
-       enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
-                           DREF_SUPERSPREAD_SOURCE_MASK));
-       I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
-}
-
-static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
-                                          enum pipe pipe)
+void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
+                                   enum pipe pipe)
 {
        u32 val;
        bool enabled;
@@ -1856,100 +1786,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
                     port_name(dport->port), I915_READ(dpll_reg) & port_mask, expected_mask);
 }
 
-static void intel_prepare_shared_dpll(struct intel_crtc *crtc)
-{
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
-
-       if (WARN_ON(pll == NULL))
-               return;
-
-       WARN_ON(!pll->config.crtc_mask);
-       if (pll->active == 0) {
-               DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
-               WARN_ON(pll->on);
-               assert_shared_dpll_disabled(dev_priv, pll);
-
-               pll->mode_set(dev_priv, pll);
-       }
-}
-
-/**
- * intel_enable_shared_dpll - enable PCH PLL
- * @dev_priv: i915 private structure
- * @pipe: pipe PLL to enable
- *
- * The PCH PLL needs to be enabled before the PCH transcoder, since it
- * drives the transcoder clock.
- */
-static void intel_enable_shared_dpll(struct intel_crtc *crtc)
-{
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
-
-       if (WARN_ON(pll == NULL))
-               return;
-
-       if (WARN_ON(pll->config.crtc_mask == 0))
-               return;
-
-       DRM_DEBUG_KMS("enable %s (active %d, on? %d) for crtc %d\n",
-                     pll->name, pll->active, pll->on,
-                     crtc->base.base.id);
-
-       if (pll->active++) {
-               WARN_ON(!pll->on);
-               assert_shared_dpll_enabled(dev_priv, pll);
-               return;
-       }
-       WARN_ON(pll->on);
-
-       intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
-
-       DRM_DEBUG_KMS("enabling %s\n", pll->name);
-       pll->enable(dev_priv, pll);
-       pll->on = true;
-}
-
-static void intel_disable_shared_dpll(struct intel_crtc *crtc)
-{
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
-
-       /* PCH only available on ILK+ */
-       if (INTEL_INFO(dev)->gen < 5)
-               return;
-
-       if (pll == NULL)
-               return;
-
-       if (WARN_ON(!(pll->config.crtc_mask & (1 << drm_crtc_index(&crtc->base)))))
-               return;
-
-       DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n",
-                     pll->name, pll->active, pll->on,
-                     crtc->base.base.id);
-
-       if (WARN_ON(pll->active == 0)) {
-               assert_shared_dpll_disabled(dev_priv, pll);
-               return;
-       }
-
-       assert_shared_dpll_enabled(dev_priv, pll);
-       WARN_ON(!pll->on);
-       if (--pll->active)
-               return;
-
-       DRM_DEBUG_KMS("disabling %s\n", pll->name);
-       pll->disable(dev_priv, pll);
-       pll->on = false;
-
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-}
-
 static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
                                           enum pipe pipe)
 {
@@ -1963,8 +1799,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        BUG_ON(!HAS_PCH_SPLIT(dev));
 
        /* Make sure PCH DPLL is enabled */
-       assert_shared_dpll_enabled(dev_priv,
-                                  intel_crtc_to_shared_dpll(intel_crtc));
+       assert_shared_dpll_enabled(dev_priv, intel_crtc->config->shared_dpll);
 
        /* FDI must be feeding us bits for PCH ports */
        assert_fdi_tx_enabled(dev_priv, pipe);
@@ -2225,8 +2060,8 @@ static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
        return IS_GEN2(dev_priv) ? 2048 : 4096;
 }
 
-static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
-                                    uint64_t fb_modifier, unsigned int cpp)
+static unsigned int intel_tile_width_bytes(const struct drm_i915_private *dev_priv,
+                                          uint64_t fb_modifier, unsigned int cpp)
 {
        switch (fb_modifier) {
        case DRM_FORMAT_MOD_NONE:
@@ -2269,7 +2104,21 @@ unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
                return 1;
        else
                return intel_tile_size(dev_priv) /
-                       intel_tile_width(dev_priv, fb_modifier, cpp);
+                       intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
+}
+
+/* Return the tile dimensions in pixel units */
+static void intel_tile_dims(const struct drm_i915_private *dev_priv,
+                           unsigned int *tile_width,
+                           unsigned int *tile_height,
+                           uint64_t fb_modifier,
+                           unsigned int cpp)
+{
+       unsigned int tile_width_bytes =
+               intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
+
+       *tile_width = tile_width_bytes / cpp;
+       *tile_height = intel_tile_size(dev_priv) / tile_width_bytes;
 }
 
 unsigned int
@@ -2282,48 +2131,54 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
        return ALIGN(height, tile_height);
 }
 
-static void
-intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
-                       const struct drm_plane_state *plane_state)
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info)
 {
-       struct drm_i915_private *dev_priv = to_i915(fb->dev);
-       struct intel_rotation_info *info = &view->params.rotated;
-       unsigned int tile_size, tile_width, tile_height, cpp;
-
-       *view = i915_ggtt_view_normal;
+       unsigned int size = 0;
+       int i;
 
-       if (!plane_state)
-               return;
+       for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++)
+               size += rot_info->plane[i].width * rot_info->plane[i].height;
 
-       if (!intel_rotation_90_or_270(plane_state->rotation))
-               return;
+       return size;
+}
 
-       *view = i915_ggtt_view_rotated;
+static void
+intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
+                       const struct drm_framebuffer *fb,
+                       unsigned int rotation)
+{
+       if (intel_rotation_90_or_270(rotation)) {
+               *view = i915_ggtt_view_rotated;
+               view->params.rotated = to_intel_framebuffer(fb)->rot_info;
+       } else {
+               *view = i915_ggtt_view_normal;
+       }
+}
 
-       info->height = fb->height;
-       info->pixel_format = fb->pixel_format;
-       info->pitch = fb->pitches[0];
-       info->uv_offset = fb->offsets[1];
-       info->fb_modifier = fb->modifier[0];
+static void
+intel_fill_fb_info(struct drm_i915_private *dev_priv,
+                  struct drm_framebuffer *fb)
+{
+       struct intel_rotation_info *info = &to_intel_framebuffer(fb)->rot_info;
+       unsigned int tile_size, tile_width, tile_height, cpp;
 
        tile_size = intel_tile_size(dev_priv);
 
        cpp = drm_format_plane_cpp(fb->pixel_format, 0);
-       tile_width = intel_tile_width(dev_priv, fb->modifier[0], cpp);
-       tile_height = tile_size / tile_width;
+       intel_tile_dims(dev_priv, &tile_width, &tile_height,
+                       fb->modifier[0], cpp);
 
-       info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
-       info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
-       info->size = info->width_pages * info->height_pages * tile_size;
+       info->plane[0].width = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp);
+       info->plane[0].height = DIV_ROUND_UP(fb->height, tile_height);
 
        if (info->pixel_format == DRM_FORMAT_NV12) {
                cpp = drm_format_plane_cpp(fb->pixel_format, 1);
-               tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
-               tile_height = tile_size / tile_width;
+               intel_tile_dims(dev_priv, &tile_width, &tile_height,
+                               fb->modifier[1], cpp);
 
-               info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
-               info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
-               info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
+               info->uv_offset = fb->offsets[1];
+               info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
+               info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height);
        }
 }
 
@@ -2360,9 +2215,8 @@ static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv
 }
 
 int
-intel_pin_and_fence_fb_obj(struct drm_plane *plane,
-                          struct drm_framebuffer *fb,
-                          const struct drm_plane_state *plane_state)
+intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
+                          unsigned int rotation)
 {
        struct drm_device *dev = fb->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2375,7 +2229,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
 
        alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
 
-       intel_fill_fb_ggtt_view(&view, fb, plane_state);
+       intel_fill_fb_ggtt_view(&view, fb, rotation);
 
        /* Note that the w/a also requires 64 PTE of padding following the
         * bo. We currently fill all unused PTE with the shadow page and so
@@ -2433,15 +2287,14 @@ err_pm:
        return ret;
 }
 
-static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
-                              const struct drm_plane_state *plane_state)
+static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
 {
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct i915_ggtt_view view;
 
        WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
 
-       intel_fill_fb_ggtt_view(&view, fb, plane_state);
+       intel_fill_fb_ggtt_view(&view, fb, rotation);
 
        if (view.type == I915_GGTT_VIEW_NORMAL)
                i915_gem_object_unpin_fence(obj);
@@ -2449,38 +2302,93 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
        i915_gem_object_unpin_from_display_plane(obj, &view);
 }
 
-/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
- * is assumed to be a power-of-two. */
-u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
-                             int *x, int *y,
-                             uint64_t fb_modifier,
-                             unsigned int cpp,
-                             unsigned int pitch)
+/*
+ * Adjust the tile offset by moving the difference into
+ * the x/y offsets.
+ *
+ * Input tile dimensions and pitch must already be
+ * rotated to match x and y, and in pixel units.
+ */
+static u32 intel_adjust_tile_offset(int *x, int *y,
+                                   unsigned int tile_width,
+                                   unsigned int tile_height,
+                                   unsigned int tile_size,
+                                   unsigned int pitch_tiles,
+                                   u32 old_offset,
+                                   u32 new_offset)
+{
+       unsigned int tiles;
+
+       WARN_ON(old_offset & (tile_size - 1));
+       WARN_ON(new_offset & (tile_size - 1));
+       WARN_ON(new_offset > old_offset);
+
+       tiles = (old_offset - new_offset) / tile_size;
+
+       *y += tiles / pitch_tiles * tile_height;
+       *x += tiles % pitch_tiles * tile_width;
+
+       return new_offset;
+}
+
+/*
+ * Computes the linear offset to the base tile and adjusts
+ * x, y. bytes per pixel is assumed to be a power-of-two.
+ *
+ * In the 90/270 rotated case, x and y are assumed
+ * to be already rotated to match the rotated GTT view, and
+ * pitch is the tile_height aligned framebuffer height.
+ */
+u32 intel_compute_tile_offset(int *x, int *y,
+                             const struct drm_framebuffer *fb, int plane,
+                             unsigned int pitch,
+                             unsigned int rotation)
 {
+       const struct drm_i915_private *dev_priv = to_i915(fb->dev);
+       uint64_t fb_modifier = fb->modifier[plane];
+       unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+       u32 offset, offset_aligned, alignment;
+
+       alignment = intel_surf_alignment(dev_priv, fb_modifier);
+       if (alignment)
+               alignment--;
+
        if (fb_modifier != DRM_FORMAT_MOD_NONE) {
                unsigned int tile_size, tile_width, tile_height;
-               unsigned int tile_rows, tiles;
+               unsigned int tile_rows, tiles, pitch_tiles;
 
                tile_size = intel_tile_size(dev_priv);
-               tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
-               tile_height = tile_size / tile_width;
+               intel_tile_dims(dev_priv, &tile_width, &tile_height,
+                               fb_modifier, cpp);
+
+               if (intel_rotation_90_or_270(rotation)) {
+                       pitch_tiles = pitch / tile_height;
+                       swap(tile_width, tile_height);
+               } else {
+                       pitch_tiles = pitch / (tile_width * cpp);
+               }
 
                tile_rows = *y / tile_height;
                *y %= tile_height;
 
-               tiles = *x / (tile_width/cpp);
-               *x %= tile_width/cpp;
+               tiles = *x / tile_width;
+               *x %= tile_width;
 
-               return tile_rows * pitch * tile_height + tiles * tile_size;
-       } else {
-               unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
-               unsigned int offset;
+               offset = (tile_rows * pitch_tiles + tiles) * tile_size;
+               offset_aligned = offset & ~alignment;
 
+               intel_adjust_tile_offset(x, y, tile_width, tile_height,
+                                        tile_size, pitch_tiles,
+                                        offset, offset_aligned);
+       } else {
                offset = *y * pitch + *x * cpp;
+               offset_aligned = offset & ~alignment;
+
                *y = (offset & alignment) / pitch;
                *x = ((offset & alignment) - *y * pitch) / cpp;
-               return offset & ~alignment;
        }
+
+       return offset_aligned;
 }
 
 static int i9xx_format_to_fourcc(int format)
@@ -2551,7 +2459,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
        /* If the FB is too big, just don't use it since fbdev is not very
         * important and we should probably use that space with FBC or other
         * features. */
-       if (size_aligned * 2 > dev_priv->gtt.stolen_usable_size)
+       if (size_aligned * 2 > dev_priv->ggtt.stolen_usable_size)
                return false;
 
        mutex_lock(&dev->struct_mutex);
@@ -2667,7 +2575,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
         */
        to_intel_plane_state(plane_state)->visible = false;
        crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
-       intel_pre_disable_primary(&intel_crtc->base);
+       intel_pre_disable_primary_noatomic(&intel_crtc->base);
        intel_plane->disable_plane(primary, &intel_crtc->base);
 
        return;
@@ -2716,6 +2624,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
        u32 linear_offset;
        u32 dspcntr;
        i915_reg_t reg = DSPCNTR(plane);
+       unsigned int rotation = plane_state->base.rotation;
        int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
        int x = plane_state->src.x1 >> 16;
        int y = plane_state->src.y1 >> 16;
@@ -2780,15 +2689,14 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
 
        if (INTEL_INFO(dev)->gen >= 4) {
                intel_crtc->dspaddr_offset =
-                       intel_compute_tile_offset(dev_priv, &x, &y,
-                                                 fb->modifier[0], cpp,
-                                                 fb->pitches[0]);
+                       intel_compute_tile_offset(&x, &y, fb, 0,
+                                                 fb->pitches[0], rotation);
                linear_offset -= intel_crtc->dspaddr_offset;
        } else {
                intel_crtc->dspaddr_offset = linear_offset;
        }
 
-       if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+       if (rotation == BIT(DRM_ROTATE_180)) {
                dspcntr |= DISPPLANE_ROTATE_180;
 
                x += (crtc_state->pipe_src_w - 1);
@@ -2846,6 +2754,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
        u32 linear_offset;
        u32 dspcntr;
        i915_reg_t reg = DSPCNTR(plane);
+       unsigned int rotation = plane_state->base.rotation;
        int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
        int x = plane_state->src.x1 >> 16;
        int y = plane_state->src.y1 >> 16;
@@ -2887,11 +2796,10 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
 
        linear_offset = y * fb->pitches[0] + x * cpp;
        intel_crtc->dspaddr_offset =
-               intel_compute_tile_offset(dev_priv, &x, &y,
-                                         fb->modifier[0], cpp,
-                                         fb->pitches[0]);
+               intel_compute_tile_offset(&x, &y, fb, 0,
+                                         fb->pitches[0], rotation);
        linear_offset -= intel_crtc->dspaddr_offset;
-       if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+       if (rotation == BIT(DRM_ROTATE_180)) {
                dspcntr |= DISPPLANE_ROTATE_180;
 
                if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
@@ -2931,7 +2839,7 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
        } else {
                int cpp = drm_format_plane_cpp(pixel_format, 0);
 
-               return intel_tile_width(dev_priv, fb_modifier, cpp);
+               return intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
        }
 }
 
@@ -2944,7 +2852,7 @@ u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
        u64 offset;
 
        intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb,
-                               intel_plane->base.state);
+                               intel_plane->base.state->rotation);
 
        vma = i915_gem_obj_to_ggtt_view(obj, &view);
        if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
@@ -3315,7 +3223,7 @@ static void intel_update_pipe_config(struct intel_crtc *crtc,
                      pipe_config->pipe_src_w, pipe_config->pipe_src_h);
 
        if (HAS_DDI(dev))
-               intel_set_pipe_csc(&crtc->base);
+               intel_color_set_csc(&crtc->base);
 
        /*
         * Update pipe size and adjust fitter if needed: the reason for this is
@@ -3955,37 +3863,35 @@ static void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
 /* Program iCLKIP clock to the desired frequency */
 static void lpt_program_iclkip(struct drm_crtc *crtc)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        int clock = to_intel_crtc(crtc)->config->base.adjusted_mode.crtc_clock;
        u32 divsel, phaseinc, auxdiv, phasedir = 0;
        u32 temp;
 
        lpt_disable_iclkip(dev_priv);
 
-       /* 20MHz is a corner case which is out of range for the 7-bit divisor */
-       if (clock == 20000) {
-               auxdiv = 1;
-               divsel = 0x41;
-               phaseinc = 0x20;
-       } else {
-               /* The iCLK virtual clock root frequency is in MHz,
-                * but the adjusted_mode->crtc_clock in in KHz. To get the
-                * divisors, it is necessary to divide one by another, so we
-                * convert the virtual clock precision to KHz here for higher
-                * precision.
-                */
+       /* The iCLK virtual clock root frequency is in MHz,
+        * but the adjusted_mode->crtc_clock in in KHz. To get the
+        * divisors, it is necessary to divide one by another, so we
+        * convert the virtual clock precision to KHz here for higher
+        * precision.
+        */
+       for (auxdiv = 0; auxdiv < 2; auxdiv++) {
                u32 iclk_virtual_root_freq = 172800 * 1000;
                u32 iclk_pi_range = 64;
-               u32 desired_divisor, msb_divisor_value, pi_value;
+               u32 desired_divisor;
 
-               desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock);
-               msb_divisor_value = desired_divisor / iclk_pi_range;
-               pi_value = desired_divisor % iclk_pi_range;
+               desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq,
+                                                   clock << auxdiv);
+               divsel = (desired_divisor / iclk_pi_range) - 2;
+               phaseinc = desired_divisor % iclk_pi_range;
 
-               auxdiv = 0;
-               divsel = msb_divisor_value - 2;
-               phaseinc = pi_value;
+               /*
+                * Near 20MHz is a corner case which is
+                * out of range for the 7-bit divisor
+                */
+               if (divsel <= 0x7f)
+                       break;
        }
 
        /* This should not happen with any sane values */
@@ -4032,6 +3938,43 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
        I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
 }
 
+int lpt_get_iclkip(struct drm_i915_private *dev_priv)
+{
+       u32 divsel, phaseinc, auxdiv;
+       u32 iclk_virtual_root_freq = 172800 * 1000;
+       u32 iclk_pi_range = 64;
+       u32 desired_divisor;
+       u32 temp;
+
+       if ((I915_READ(PIXCLK_GATE) & PIXCLK_GATE_UNGATE) == 0)
+               return 0;
+
+       mutex_lock(&dev_priv->sb_lock);
+
+       temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
+       if (temp & SBI_SSCCTL_DISABLE) {
+               mutex_unlock(&dev_priv->sb_lock);
+               return 0;
+       }
+
+       temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
+       divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >>
+               SBI_SSCDIVINTPHASE_DIVSEL_SHIFT;
+       phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >>
+               SBI_SSCDIVINTPHASE_INCVAL_SHIFT;
+
+       temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
+       auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >>
+               SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT;
+
+       mutex_unlock(&dev_priv->sb_lock);
+
+       desired_divisor = (divsel + 2) * iclk_pi_range + phaseinc;
+
+       return DIV_ROUND_CLOSEST(iclk_virtual_root_freq,
+                                desired_divisor << auxdiv);
+}
+
 static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
                                                enum pipe pch_transcoder)
 {
@@ -4159,7 +4102,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
                temp = I915_READ(PCH_DPLL_SEL);
                temp |= TRANS_DPLL_ENABLE(pipe);
                sel = TRANS_DPLLB_SEL(pipe);
-               if (intel_crtc->config->shared_dpll == DPLL_ID_PCH_PLL_B)
+               if (intel_crtc->config->shared_dpll ==
+                   intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B))
                        temp |= sel;
                else
                        temp &= ~sel;
@@ -4238,118 +4182,11 @@ static void lpt_pch_enable(struct drm_crtc *crtc)
        lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
 }
 
-struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
-                                               struct intel_crtc_state *crtc_state)
+static void cpt_verify_modeset(struct drm_device *dev, int pipe)
 {
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
-       struct intel_shared_dpll *pll;
-       struct intel_shared_dpll_config *shared_dpll;
-       enum intel_dpll_id i;
-       int max = dev_priv->num_shared_dpll;
-
-       shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
-
-       if (HAS_PCH_IBX(dev_priv->dev)) {
-               /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
-               i = (enum intel_dpll_id) crtc->pipe;
-               pll = &dev_priv->shared_dplls[i];
-
-               DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
-                             crtc->base.base.id, pll->name);
-
-               WARN_ON(shared_dpll[i].crtc_mask);
-
-               goto found;
-       }
-
-       if (IS_BROXTON(dev_priv->dev)) {
-               /* PLL is attached to port in bxt */
-               struct intel_encoder *encoder;
-               struct intel_digital_port *intel_dig_port;
-
-               encoder = intel_ddi_get_crtc_new_encoder(crtc_state);
-               if (WARN_ON(!encoder))
-                       return NULL;
-
-               intel_dig_port = enc_to_dig_port(&encoder->base);
-               /* 1:1 mapping between ports and PLLs */
-               i = (enum intel_dpll_id)intel_dig_port->port;
-               pll = &dev_priv->shared_dplls[i];
-               DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
-                       crtc->base.base.id, pll->name);
-               WARN_ON(shared_dpll[i].crtc_mask);
-
-               goto found;
-       } else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv))
-               /* Do not consider SPLL */
-               max = 2;
-
-       for (i = 0; i < max; i++) {
-               pll = &dev_priv->shared_dplls[i];
-
-               /* Only want to check enabled timings first */
-               if (shared_dpll[i].crtc_mask == 0)
-                       continue;
-
-               if (memcmp(&crtc_state->dpll_hw_state,
-                          &shared_dpll[i].hw_state,
-                          sizeof(crtc_state->dpll_hw_state)) == 0) {
-                       DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n",
-                                     crtc->base.base.id, pll->name,
-                                     shared_dpll[i].crtc_mask,
-                                     pll->active);
-                       goto found;
-               }
-       }
-
-       /* Ok no matching timings, maybe there's a free one? */
-       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-               pll = &dev_priv->shared_dplls[i];
-               if (shared_dpll[i].crtc_mask == 0) {
-                       DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
-                                     crtc->base.base.id, pll->name);
-                       goto found;
-               }
-       }
-
-       return NULL;
-
-found:
-       if (shared_dpll[i].crtc_mask == 0)
-               shared_dpll[i].hw_state =
-                       crtc_state->dpll_hw_state;
-
-       crtc_state->shared_dpll = i;
-       DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
-                        pipe_name(crtc->pipe));
-
-       shared_dpll[i].crtc_mask |= 1 << crtc->pipe;
-
-       return pll;
-}
-
-static void intel_shared_dpll_commit(struct drm_atomic_state *state)
-{
-       struct drm_i915_private *dev_priv = to_i915(state->dev);
-       struct intel_shared_dpll_config *shared_dpll;
-       struct intel_shared_dpll *pll;
-       enum intel_dpll_id i;
-
-       if (!to_intel_atomic_state(state)->dpll_set)
-               return;
-
-       shared_dpll = to_intel_atomic_state(state)->shared_dpll;
-       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-               pll = &dev_priv->shared_dplls[i];
-               pll->config = shared_dpll[i];
-       }
-}
-
-static void cpt_verify_modeset(struct drm_device *dev, int pipe)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       i915_reg_t dslreg = PIPEDSL(pipe);
-       u32 temp;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       i915_reg_t dslreg = PIPEDSL(pipe);
+       u32 temp;
 
        temp = I915_READ(dslreg);
        udelay(500);
@@ -4576,8 +4413,11 @@ void hsw_enable_ips(struct intel_crtc *crtc)
        if (!crtc->config->ips_enabled)
                return;
 
-       /* We can only enable IPS after we enable a plane and wait for a vblank */
-       intel_wait_for_vblank(dev, crtc->pipe);
+       /*
+        * We can only enable IPS after we enable a plane and wait for a vblank
+        * This function is called from post_plane_update, which is run after
+        * a vblank wait.
+        */
 
        assert_plane_enabled(dev_priv, crtc->plane);
        if (IS_BROADWELL(dev)) {
@@ -4626,55 +4466,6 @@ void hsw_disable_ips(struct intel_crtc *crtc)
        intel_wait_for_vblank(dev, crtc->pipe);
 }
 
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-static void intel_crtc_load_lut(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);
-       enum pipe pipe = intel_crtc->pipe;
-       int i;
-       bool reenable_ips = false;
-
-       /* The clocks have to be on to load the palette. */
-       if (!crtc->state->active)
-               return;
-
-       if (HAS_GMCH_DISPLAY(dev_priv->dev)) {
-               if (intel_crtc->config->has_dsi_encoder)
-                       assert_dsi_pll_enabled(dev_priv);
-               else
-                       assert_pll_enabled(dev_priv, pipe);
-       }
-
-       /* Workaround : Do not read or write the pipe palette/gamma data while
-        * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
-        */
-       if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
-           ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
-            GAMMA_MODE_MODE_SPLIT)) {
-               hsw_disable_ips(intel_crtc);
-               reenable_ips = true;
-       }
-
-       for (i = 0; i < 256; i++) {
-               i915_reg_t palreg;
-
-               if (HAS_GMCH_DISPLAY(dev))
-                       palreg = PALETTE(pipe, i);
-               else
-                       palreg = LGC_PALETTE(pipe, i);
-
-               I915_WRITE(palreg,
-                          (intel_crtc->lut_r[i] << 16) |
-                          (intel_crtc->lut_g[i] << 8) |
-                          intel_crtc->lut_b[i]);
-       }
-
-       if (reenable_ips)
-               hsw_enable_ips(intel_crtc);
-}
-
 static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
 {
        if (intel_crtc->overlay) {
@@ -4734,16 +4525,7 @@ intel_post_enable_primary(struct drm_crtc *crtc)
        intel_check_pch_fifo_underruns(dev_priv);
 }
 
-/**
- * intel_pre_disable_primary - Perform operations before disabling primary plane
- * @crtc: the CRTC whose primary plane is to be disabled
- *
- * Performs potentially sleeping operations that must be done before the
- * primary plane is disabled, such as updating FBC and IPS.  Note that this may
- * be called due to an explicit primary plane update, or due to an implicit
- * disable that is caused when a sprite plane completely hides the primary
- * plane.
- */
+/* FIXME move all this to pre_plane_update() with proper state tracking */
 static void
 intel_pre_disable_primary(struct drm_crtc *crtc)
 {
@@ -4761,6 +4543,26 @@ intel_pre_disable_primary(struct drm_crtc *crtc)
        if (IS_GEN2(dev))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 
+       /*
+        * FIXME IPS should be fine as long as one plane is
+        * enabled, but in practice it seems to have problems
+        * when going from primary only to sprite only and vice
+        * versa.
+        */
+       hsw_disable_ips(intel_crtc);
+}
+
+/* FIXME get rid of this and use pre_plane_update */
+static void
+intel_pre_disable_primary_noatomic(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);
+       int pipe = intel_crtc->pipe;
+
+       intel_pre_disable_primary(crtc);
+
        /*
         * Vblank time updates from the shadow to live plane control register
         * are blocked if the memory self-refresh mode is active at that
@@ -4775,37 +4577,39 @@ intel_pre_disable_primary(struct drm_crtc *crtc)
                dev_priv->wm.vlv.cxsr = false;
                intel_wait_for_vblank(dev, pipe);
        }
-
-       /*
-        * FIXME IPS should be fine as long as one plane is
-        * enabled, but in practice it seems to have problems
-        * when going from primary only to sprite only and vice
-        * versa.
-        */
-       hsw_disable_ips(intel_crtc);
 }
 
-static void intel_post_plane_update(struct intel_crtc *crtc)
+static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
 {
-       struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
+       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
+       struct drm_atomic_state *old_state = old_crtc_state->base.state;
        struct intel_crtc_state *pipe_config =
                to_intel_crtc_state(crtc->base.state);
        struct drm_device *dev = crtc->base.dev;
+       struct drm_plane *primary = crtc->base.primary;
+       struct drm_plane_state *old_pri_state =
+               drm_atomic_get_existing_plane_state(old_state, primary);
 
-       intel_frontbuffer_flip(dev, atomic->fb_bits);
+       intel_frontbuffer_flip(dev, pipe_config->fb_bits);
 
        crtc->wm.cxsr_allowed = true;
 
-       if (pipe_config->wm_changed && pipe_config->base.active)
+       if (pipe_config->update_wm_post && pipe_config->base.active)
                intel_update_watermarks(&crtc->base);
 
-       if (atomic->update_fbc)
-               intel_fbc_post_update(crtc);
+       if (old_pri_state) {
+               struct intel_plane_state *primary_state =
+                       to_intel_plane_state(primary->state);
+               struct intel_plane_state *old_primary_state =
+                       to_intel_plane_state(old_pri_state);
 
-       if (atomic->post_enable_primary)
-               intel_post_enable_primary(&crtc->base);
+               intel_fbc_post_update(crtc);
 
-       memset(atomic, 0, sizeof(*atomic));
+               if (primary_state->visible &&
+                   (needs_modeset(&pipe_config->base) ||
+                    !old_primary_state->visible))
+                       intel_post_enable_primary(&crtc->base);
+       }
 }
 
 static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
@@ -4813,7 +4617,6 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
        struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
        struct intel_crtc_state *pipe_config =
                to_intel_crtc_state(crtc->base.state);
        struct drm_atomic_state *old_state = old_crtc_state->base.state;
@@ -4822,15 +4625,14 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
                drm_atomic_get_existing_plane_state(old_state, primary);
        bool modeset = needs_modeset(&pipe_config->base);
 
-       if (atomic->update_fbc)
-               intel_fbc_pre_update(crtc);
-
        if (old_pri_state) {
                struct intel_plane_state *primary_state =
                        to_intel_plane_state(primary->state);
                struct intel_plane_state *old_primary_state =
                        to_intel_plane_state(old_pri_state);
 
+               intel_fbc_pre_update(crtc);
+
                if (old_primary_state->visible &&
                    (modeset || !primary_state->visible))
                        intel_pre_disable_primary(&crtc->base);
@@ -4839,11 +4641,58 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
        if (pipe_config->disable_cxsr) {
                crtc->wm.cxsr_allowed = false;
 
-               if (old_crtc_state->base.active)
+               /*
+                * Vblank time updates from the shadow to live plane control register
+                * are blocked if the memory self-refresh mode is active at that
+                * moment. So to make sure the plane gets truly disabled, disable
+                * first the self-refresh mode. The self-refresh enable bit in turn
+                * will be checked/applied by the HW only at the next frame start
+                * event which is after the vblank start event, so we need to have a
+                * wait-for-vblank between disabling the plane and the pipe.
+                */
+               if (old_crtc_state->base.active) {
                        intel_set_memory_cxsr(dev_priv, false);
+                       dev_priv->wm.vlv.cxsr = false;
+                       intel_wait_for_vblank(dev, crtc->pipe);
+               }
+       }
+
+       /*
+        * IVB workaround: must disable low power watermarks for at least
+        * one frame before enabling scaling.  LP watermarks can be re-enabled
+        * when scaling is disabled.
+        *
+        * WaCxSRDisabledForSpriteScaling:ivb
+        */
+       if (pipe_config->disable_lp_wm) {
+               ilk_disable_lp_wm(dev);
+               intel_wait_for_vblank(dev, crtc->pipe);
        }
 
-       if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed)
+       /*
+        * If we're doing a modeset, we're done.  No need to do any pre-vblank
+        * watermark programming here.
+        */
+       if (needs_modeset(&pipe_config->base))
+               return;
+
+       /*
+        * For platforms that support atomic watermarks, program the
+        * 'intermediate' watermarks immediately.  On pre-gen9 platforms, these
+        * will be the intermediate values that are safe for both pre- and
+        * post- vblank; when vblank happens, the 'active' values will be set
+        * to the final 'target' values and we'll do this again to get the
+        * optimal watermarks.  For gen9+ platforms, the values we program here
+        * will be the final target values which will get automatically latched
+        * at vblank time; no further programming will be necessary.
+        *
+        * If a platform hasn't been transitioned to atomic watermarks yet,
+        * we'll continue to update watermarks the old way, if flags tell
+        * us to.
+        */
+       if (dev_priv->display.initial_watermarks != NULL)
+               dev_priv->display.initial_watermarks(pipe_config);
+       else if (pipe_config->update_wm_pre)
                intel_update_watermarks(&crtc->base);
 }
 
@@ -4888,6 +4737,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
                intel_dp_set_m_n(intel_crtc, M1_N1);
 
        intel_set_pipe_timings(intel_crtc);
+       intel_set_pipe_src_size(intel_crtc);
 
        if (intel_crtc->config->has_pch_encoder) {
                intel_cpu_transcoder_set_m_n(intel_crtc,
@@ -4920,9 +4770,10 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
         * On ILK+ LUT must be loaded before the pipe is running but with
         * clocks enabled
         */
-       intel_crtc_load_lut(crtc);
+       intel_color_load_luts(crtc);
 
-       intel_update_watermarks(crtc);
+       if (dev_priv->display.initial_watermarks != NULL)
+               dev_priv->display.initial_watermarks(intel_crtc->config);
        intel_enable_pipe(intel_crtc);
 
        if (intel_crtc->config->has_pch_encoder)
@@ -4956,6 +4807,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe, hsw_workaround_pipe;
+       enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
        struct intel_crtc_state *pipe_config =
                to_intel_crtc_state(crtc->state);
 
@@ -4966,16 +4818,20 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
                intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
                                                      false);
 
-       if (intel_crtc_to_shared_dpll(intel_crtc))
+       if (intel_crtc->config->shared_dpll)
                intel_enable_shared_dpll(intel_crtc);
 
        if (intel_crtc->config->has_dp_encoder)
                intel_dp_set_m_n(intel_crtc, M1_N1);
 
-       intel_set_pipe_timings(intel_crtc);
+       if (!intel_crtc->config->has_dsi_encoder)
+               intel_set_pipe_timings(intel_crtc);
 
-       if (intel_crtc->config->cpu_transcoder != TRANSCODER_EDP) {
-               I915_WRITE(PIPE_MULT(intel_crtc->config->cpu_transcoder),
+       intel_set_pipe_src_size(intel_crtc);
+
+       if (cpu_transcoder != TRANSCODER_EDP &&
+           !transcoder_is_dsi(cpu_transcoder)) {
+               I915_WRITE(PIPE_MULT(cpu_transcoder),
                           intel_crtc->config->pixel_multiplier - 1);
        }
 
@@ -4984,9 +4840,12 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
                                     &intel_crtc->config->fdi_m_n, NULL);
        }
 
-       haswell_set_pipeconf(crtc);
+       if (!intel_crtc->config->has_dsi_encoder)
+               haswell_set_pipeconf(crtc);
+
+       haswell_set_pipemisc(crtc);
 
-       intel_set_pipe_csc(crtc);
+       intel_color_set_csc(crtc);
 
        intel_crtc->active = true;
 
@@ -5015,14 +4874,20 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
         * On ILK+ LUT must be loaded before the pipe is running but with
         * clocks enabled
         */
-       intel_crtc_load_lut(crtc);
+       intel_color_load_luts(crtc);
 
        intel_ddi_set_pipe_settings(crtc);
        if (!intel_crtc->config->has_dsi_encoder)
                intel_ddi_enable_transcoder_func(crtc);
 
-       intel_update_watermarks(crtc);
-       intel_enable_pipe(intel_crtc);
+       if (dev_priv->display.initial_watermarks != NULL)
+               dev_priv->display.initial_watermarks(pipe_config);
+       else
+               intel_update_watermarks(crtc);
+
+       /* XXX: Do the pipe assertions at the right place for BXT DSI. */
+       if (!intel_crtc->config->has_dsi_encoder)
+               intel_enable_pipe(intel_crtc);
 
        if (intel_crtc->config->has_pch_encoder)
                lpt_pch_enable(crtc);
@@ -5155,7 +5020,9 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
        drm_crtc_vblank_off(crtc);
        assert_vblank_disabled(crtc);
 
-       intel_disable_pipe(intel_crtc);
+       /* XXX: Do the pipe assertions at the right place for BXT DSI. */
+       if (!intel_crtc->config->has_dsi_encoder)
+               intel_disable_pipe(intel_crtc);
 
        if (intel_crtc->config->dp_encoder_is_mst)
                intel_ddi_set_vc_payload_alloc(crtc, false);
@@ -5330,6 +5197,9 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc,
                mask |= BIT(intel_display_port_power_domain(intel_encoder));
        }
 
+       if (crtc_state->shared_dpll)
+               mask |= BIT(POWER_DOMAIN_PLLS);
+
        return mask;
 }
 
@@ -6174,6 +6044,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
                intel_dp_set_m_n(intel_crtc, M1_N1);
 
        intel_set_pipe_timings(intel_crtc);
+       intel_set_pipe_src_size(intel_crtc);
 
        if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) {
                struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6208,8 +6079,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 
        i9xx_pfit_enable(intel_crtc);
 
-       intel_crtc_load_lut(crtc);
+       intel_color_load_luts(crtc);
 
+       intel_update_watermarks(crtc);
        intel_enable_pipe(intel_crtc);
 
        assert_vblank_disabled(crtc);
@@ -6245,6 +6117,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
                intel_dp_set_m_n(intel_crtc, M1_N1);
 
        intel_set_pipe_timings(intel_crtc);
+       intel_set_pipe_src_size(intel_crtc);
 
        i9xx_set_pipeconf(intel_crtc);
 
@@ -6261,7 +6134,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
        i9xx_pfit_enable(intel_crtc);
 
-       intel_crtc_load_lut(crtc);
+       intel_color_load_luts(crtc);
 
        intel_update_watermarks(crtc);
        intel_enable_pipe(intel_crtc);
@@ -6299,10 +6172,9 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
        /*
         * On gen2 planes are double buffered but the pipe isn't, so we must
         * wait for planes to fully turn off before disabling the pipe.
-        * We also need to wait on all gmch platforms because of the
-        * self-refresh mode constraint explained above.
         */
-       intel_wait_for_vblank(dev, pipe);
+       if (IS_GEN2(dev))
+               intel_wait_for_vblank(dev, pipe);
 
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->disable(encoder);
@@ -6337,6 +6209,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 
 static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
 {
+       struct intel_encoder *encoder;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        enum intel_display_power_domain domain;
@@ -6348,14 +6221,27 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
        if (to_intel_plane_state(crtc->primary->state)->visible) {
                WARN_ON(intel_crtc->unpin_work);
 
-               intel_pre_disable_primary(crtc);
+               intel_pre_disable_primary_noatomic(crtc);
 
                intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
                to_intel_plane_state(crtc->primary->state)->visible = false;
        }
 
        dev_priv->display.crtc_disable(crtc);
+
+       DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was enabled, now disabled\n",
+                     crtc->base.id);
+
+       WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0);
+       crtc->state->active = false;
        intel_crtc->active = false;
+       crtc->enabled = false;
+       crtc->state->connector_mask = 0;
+       crtc->state->encoder_mask = 0;
+
+       for_each_encoder_on_crtc(crtc->dev, crtc, encoder)
+               encoder->base.crtc = NULL;
+
        intel_fbc_disable(intel_crtc);
        intel_update_watermarks(crtc);
        intel_disable_shared_dpll(intel_crtc);
@@ -6568,7 +6454,7 @@ retry:
         * Hence the bw of each lane in terms of the mode signal
         * is:
         */
-       link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
+       link_bw = intel_fdi_link_freq(to_i915(dev), pipe_config);
 
        fdi_dotclock = adjusted_mode->crtc_clock;
 
@@ -6580,8 +6466,7 @@ retry:
        intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
                               link_bw, &pipe_config->fdi_m_n);
 
-       ret = ironlake_check_fdi_lanes(intel_crtc->base.dev,
-                                      intel_crtc->pipe, pipe_config);
+       ret = ironlake_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config);
        if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
                pipe_config->pipe_bpp -= 2*3;
                DRM_DEBUG_KMS("fdi link bw constraint, reducing pipe bpp to %i\n",
@@ -7133,30 +7018,6 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
                && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
-static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
-                          int num_connectors)
-{
-       struct drm_device *dev = crtc_state->base.crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int refclk;
-
-       WARN_ON(!crtc_state->base.state);
-
-       if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) {
-               refclk = 100000;
-       } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-           intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-               refclk = dev_priv->vbt.lvds_ssc_freq;
-               DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
-       } else if (!IS_GEN2(dev)) {
-               refclk = 96000;
-       } else {
-               refclk = 48000;
-       }
-
-       return refclk;
-}
-
 static uint32_t pnv_dpll_compute_fp(struct dpll *dpll)
 {
        return (1 << dpll->n) << 16 | dpll->m2;
@@ -7586,8 +7447,7 @@ void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe)
 
 static void i9xx_compute_dpll(struct intel_crtc *crtc,
                              struct intel_crtc_state *crtc_state,
-                             intel_clock_t *reduced_clock,
-                             int num_connectors)
+                             intel_clock_t *reduced_clock)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7646,7 +7506,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc,
        if (crtc_state->sdvo_tv_clock)
                dpll |= PLL_REF_INPUT_TVCLKINBC;
        else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-                intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+                intel_panel_use_ssc(dev_priv))
                dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
        else
                dpll |= PLL_REF_INPUT_DREFCLK;
@@ -7663,8 +7523,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc,
 
 static void i8xx_compute_dpll(struct intel_crtc *crtc,
                              struct intel_crtc_state *crtc_state,
-                             intel_clock_t *reduced_clock,
-                             int num_connectors)
+                             intel_clock_t *reduced_clock)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7690,7 +7549,7 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc,
                dpll |= DPLL_DVO_2X_MODE;
 
        if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-                intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+           intel_panel_use_ssc(dev_priv))
                dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
        else
                dpll |= PLL_REF_INPUT_DREFCLK;
@@ -7759,6 +7618,14 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
            (pipe == PIPE_B || pipe == PIPE_C))
                I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder)));
 
+}
+
+static void intel_set_pipe_src_size(struct intel_crtc *intel_crtc)
+{
+       struct drm_device *dev = intel_crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = intel_crtc->pipe;
+
        /* pipesrc controls the size that is scaled from, which should
         * always be the user's requested size.
         */
@@ -7800,6 +7667,14 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
                pipe_config->base.adjusted_mode.crtc_vtotal += 1;
                pipe_config->base.adjusted_mode.crtc_vblank_end += 1;
        }
+}
+
+static void intel_get_pipe_src_size(struct intel_crtc *crtc,
+                                   struct intel_crtc_state *pipe_config)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp;
 
        tmp = I915_READ(PIPESRC(crtc->pipe));
        pipe_config->pipe_src_h = (tmp & 0xffff) + 1;
@@ -7897,114 +7772,243 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
        POSTING_READ(PIPECONF(intel_crtc->pipe));
 }
 
-static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
+static int i8xx_crtc_compute_clock(struct intel_crtc *crtc,
                                   struct intel_crtc_state *crtc_state)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int refclk, num_connectors = 0;
-       intel_clock_t clock;
-       bool ok;
        const intel_limit_t *limit;
-       struct drm_atomic_state *state = crtc_state->base.state;
-       struct drm_connector *connector;
-       struct drm_connector_state *connector_state;
-       int i;
+       int refclk = 48000;
 
        memset(&crtc_state->dpll_hw_state, 0,
               sizeof(crtc_state->dpll_hw_state));
 
-       if (crtc_state->has_dsi_encoder)
-               return 0;
-
-       for_each_connector_in_state(state, connector, connector_state, i) {
-               if (connector_state->crtc == &crtc->base)
-                       num_connectors++;
-       }
-
-       if (!crtc_state->clock_set) {
-               refclk = i9xx_get_refclk(crtc_state, num_connectors);
-
-               /*
-                * Returns a set of divisors for the desired target clock with
-                * the given refclk, or FALSE.  The returned values represent
-                * the clock equation: reflck * (5 * (m1 + 2) + (m2 + 2)) / (n +
-                * 2) / p1 / p2.
-                */
-               limit = intel_limit(crtc_state, refclk);
-               ok = dev_priv->display.find_dpll(limit, crtc_state,
-                                                crtc_state->port_clock,
-                                                refclk, NULL, &clock);
-               if (!ok) {
-                       DRM_ERROR("Couldn't find PLL settings for mode!\n");
-                       return -EINVAL;
+       if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+               if (intel_panel_use_ssc(dev_priv)) {
+                       refclk = dev_priv->vbt.lvds_ssc_freq;
+                       DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
                }
 
-               /* Compat-code for transition, will disappear. */
-               crtc_state->dpll.n = clock.n;
-               crtc_state->dpll.m1 = clock.m1;
-               crtc_state->dpll.m2 = clock.m2;
-               crtc_state->dpll.p1 = clock.p1;
-               crtc_state->dpll.p2 = clock.p2;
+               limit = &intel_limits_i8xx_lvds;
+       } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_DVO)) {
+               limit = &intel_limits_i8xx_dvo;
+       } else {
+               limit = &intel_limits_i8xx_dac;
        }
 
-       if (IS_GEN2(dev)) {
-               i8xx_compute_dpll(crtc, crtc_state, NULL,
-                                 num_connectors);
-       } else if (IS_CHERRYVIEW(dev)) {
-               chv_compute_dpll(crtc, crtc_state);
-       } else if (IS_VALLEYVIEW(dev)) {
-               vlv_compute_dpll(crtc, crtc_state);
-       } else {
-               i9xx_compute_dpll(crtc, crtc_state, NULL,
-                                 num_connectors);
+       if (!crtc_state->clock_set &&
+           !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+                                refclk, NULL, &crtc_state->dpll)) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return -EINVAL;
        }
 
+       i8xx_compute_dpll(crtc, crtc_state, NULL);
+
        return 0;
 }
 
-static void i9xx_get_pfit_config(struct intel_crtc *crtc,
-                                struct intel_crtc_state *pipe_config)
+static int g4x_crtc_compute_clock(struct intel_crtc *crtc,
+                                 struct intel_crtc_state *crtc_state)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t tmp;
+       const intel_limit_t *limit;
+       int refclk = 96000;
 
-       if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
-               return;
+       memset(&crtc_state->dpll_hw_state, 0,
+              sizeof(crtc_state->dpll_hw_state));
 
-       tmp = I915_READ(PFIT_CONTROL);
-       if (!(tmp & PFIT_ENABLE))
-               return;
+       if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+               if (intel_panel_use_ssc(dev_priv)) {
+                       refclk = dev_priv->vbt.lvds_ssc_freq;
+                       DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
+               }
 
-       /* Check whether the pfit is attached to our pipe. */
-       if (INTEL_INFO(dev)->gen < 4) {
-               if (crtc->pipe != PIPE_B)
-                       return;
+               if (intel_is_dual_link_lvds(dev))
+                       limit = &intel_limits_g4x_dual_channel_lvds;
+               else
+                       limit = &intel_limits_g4x_single_channel_lvds;
+       } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_HDMI) ||
+                  intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
+               limit = &intel_limits_g4x_hdmi;
+       } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_SDVO)) {
+               limit = &intel_limits_g4x_sdvo;
        } else {
-               if ((tmp & PFIT_PIPE_MASK) != (crtc->pipe << PFIT_PIPE_SHIFT))
-                       return;
+               /* The option is for other outputs */
+               limit = &intel_limits_i9xx_sdvo;
        }
 
-       pipe_config->gmch_pfit.control = tmp;
-       pipe_config->gmch_pfit.pgm_ratios = I915_READ(PFIT_PGM_RATIOS);
-       if (INTEL_INFO(dev)->gen < 5)
-               pipe_config->gmch_pfit.lvds_border_bits =
-                       I915_READ(LVDS) & LVDS_BORDER_ENABLE;
+       if (!crtc_state->clock_set &&
+           !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+                               refclk, NULL, &crtc_state->dpll)) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return -EINVAL;
+       }
+
+       i9xx_compute_dpll(crtc, crtc_state, NULL);
+
+       return 0;
 }
 
-static void vlv_crtc_clock_get(struct intel_crtc *crtc,
-                              struct intel_crtc_state *pipe_config)
+static int pnv_crtc_compute_clock(struct intel_crtc *crtc,
+                                 struct intel_crtc_state *crtc_state)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe = pipe_config->cpu_transcoder;
-       intel_clock_t clock;
-       u32 mdiv;
-       int refclk = 100000;
+       const intel_limit_t *limit;
+       int refclk = 96000;
 
-       /* In case of MIPI DPLL will not even be used */
-       if (!(pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE))
+       memset(&crtc_state->dpll_hw_state, 0,
+              sizeof(crtc_state->dpll_hw_state));
+
+       if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+               if (intel_panel_use_ssc(dev_priv)) {
+                       refclk = dev_priv->vbt.lvds_ssc_freq;
+                       DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
+               }
+
+               limit = &intel_limits_pineview_lvds;
+       } else {
+               limit = &intel_limits_pineview_sdvo;
+       }
+
+       if (!crtc_state->clock_set &&
+           !pnv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+                               refclk, NULL, &crtc_state->dpll)) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return -EINVAL;
+       }
+
+       i9xx_compute_dpll(crtc, crtc_state, NULL);
+
+       return 0;
+}
+
+static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
+                                  struct intel_crtc_state *crtc_state)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       const intel_limit_t *limit;
+       int refclk = 96000;
+
+       memset(&crtc_state->dpll_hw_state, 0,
+              sizeof(crtc_state->dpll_hw_state));
+
+       if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+               if (intel_panel_use_ssc(dev_priv)) {
+                       refclk = dev_priv->vbt.lvds_ssc_freq;
+                       DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
+               }
+
+               limit = &intel_limits_i9xx_lvds;
+       } else {
+               limit = &intel_limits_i9xx_sdvo;
+       }
+
+       if (!crtc_state->clock_set &&
+           !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+                                refclk, NULL, &crtc_state->dpll)) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return -EINVAL;
+       }
+
+       i9xx_compute_dpll(crtc, crtc_state, NULL);
+
+       return 0;
+}
+
+static int chv_crtc_compute_clock(struct intel_crtc *crtc,
+                                 struct intel_crtc_state *crtc_state)
+{
+       int refclk = 100000;
+       const intel_limit_t *limit = &intel_limits_chv;
+
+       memset(&crtc_state->dpll_hw_state, 0,
+              sizeof(crtc_state->dpll_hw_state));
+
+       if (crtc_state->has_dsi_encoder)
+               return 0;
+
+       if (!crtc_state->clock_set &&
+           !chv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+                               refclk, NULL, &crtc_state->dpll)) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return -EINVAL;
+       }
+
+       chv_compute_dpll(crtc, crtc_state);
+
+       return 0;
+}
+
+static int vlv_crtc_compute_clock(struct intel_crtc *crtc,
+                                 struct intel_crtc_state *crtc_state)
+{
+       int refclk = 100000;
+       const intel_limit_t *limit = &intel_limits_vlv;
+
+       memset(&crtc_state->dpll_hw_state, 0,
+              sizeof(crtc_state->dpll_hw_state));
+
+       if (crtc_state->has_dsi_encoder)
+               return 0;
+
+       if (!crtc_state->clock_set &&
+           !vlv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+                               refclk, NULL, &crtc_state->dpll)) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return -EINVAL;
+       }
+
+       vlv_compute_dpll(crtc, crtc_state);
+
+       return 0;
+}
+
+static void i9xx_get_pfit_config(struct intel_crtc *crtc,
+                                struct intel_crtc_state *pipe_config)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
+               return;
+
+       tmp = I915_READ(PFIT_CONTROL);
+       if (!(tmp & PFIT_ENABLE))
+               return;
+
+       /* Check whether the pfit is attached to our pipe. */
+       if (INTEL_INFO(dev)->gen < 4) {
+               if (crtc->pipe != PIPE_B)
+                       return;
+       } else {
+               if ((tmp & PFIT_PIPE_MASK) != (crtc->pipe << PFIT_PIPE_SHIFT))
+                       return;
+       }
+
+       pipe_config->gmch_pfit.control = tmp;
+       pipe_config->gmch_pfit.pgm_ratios = I915_READ(PFIT_PGM_RATIOS);
+       if (INTEL_INFO(dev)->gen < 5)
+               pipe_config->gmch_pfit.lvds_border_bits =
+                       I915_READ(LVDS) & LVDS_BORDER_ENABLE;
+}
+
+static void vlv_crtc_clock_get(struct intel_crtc *crtc,
+                              struct intel_crtc_state *pipe_config)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipe = pipe_config->cpu_transcoder;
+       intel_clock_t clock;
+       u32 mdiv;
+       int refclk = 100000;
+
+       /* In case of MIPI DPLL will not even be used */
+       if (!(pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE))
                return;
 
        mutex_lock(&dev_priv->sb_lock);
@@ -8133,7 +8137,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                return false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
-       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
+       pipe_config->shared_dpll = NULL;
 
        ret = false;
 
@@ -8165,6 +8169,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
 
        intel_get_pipe_timings(crtc, pipe_config);
+       intel_get_pipe_src_size(crtc, pipe_config);
 
        i9xx_get_pfit_config(crtc, pipe_config);
 
@@ -8638,42 +8643,6 @@ void intel_init_pch_refclk(struct drm_device *dev)
                lpt_init_pch_refclk(dev);
 }
 
-static int ironlake_get_refclk(struct intel_crtc_state *crtc_state)
-{
-       struct drm_device *dev = crtc_state->base.crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_atomic_state *state = crtc_state->base.state;
-       struct drm_connector *connector;
-       struct drm_connector_state *connector_state;
-       struct intel_encoder *encoder;
-       int num_connectors = 0, i;
-       bool is_lvds = false;
-
-       for_each_connector_in_state(state, connector, connector_state, i) {
-               if (connector_state->crtc != crtc_state->base.crtc)
-                       continue;
-
-               encoder = to_intel_encoder(connector_state->best_encoder);
-
-               switch (encoder->type) {
-               case INTEL_OUTPUT_LVDS:
-                       is_lvds = true;
-                       break;
-               default:
-                       break;
-               }
-               num_connectors++;
-       }
-
-       if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-               DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n",
-                             dev_priv->vbt.lvds_ssc_freq);
-               return dev_priv->vbt.lvds_ssc_freq;
-       }
-
-       return 120000;
-}
-
 static void ironlake_set_pipeconf(struct drm_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
@@ -8716,82 +8685,14 @@ 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)
-{
-       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 (intel_crtc->config->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 (intel_crtc->config->limited_color_range)
-                       postoff = (16 * (1 << 12) / 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 (intel_crtc->config->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_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = crtc->dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       enum pipe pipe = intel_crtc->pipe;
        enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
-       uint32_t val;
+       u32 val = 0;
 
-       val = 0;
-
-       if (IS_HASWELL(dev) && intel_crtc->config->dither)
+       if (IS_HASWELL(dev_priv) && intel_crtc->config->dither)
                val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
 
        if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
@@ -8801,12 +8702,15 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc)
 
        I915_WRITE(PIPECONF(cpu_transcoder), val);
        POSTING_READ(PIPECONF(cpu_transcoder));
+}
 
-       I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
-       POSTING_READ(GAMMA_MODE(intel_crtc->pipe));
+static void haswell_set_pipemisc(struct drm_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       if (IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
-               val = 0;
+       if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
+               u32 val = 0;
 
                switch (intel_crtc->config->pipe_bpp) {
                case 18:
@@ -8829,39 +8733,10 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc)
                if (intel_crtc->config->dither)
                        val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
 
-               I915_WRITE(PIPEMISC(pipe), val);
+               I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
        }
 }
 
-static bool ironlake_compute_clocks(struct drm_crtc *crtc,
-                                   struct intel_crtc_state *crtc_state,
-                                   intel_clock_t *clock,
-                                   bool *has_reduced_clock,
-                                   intel_clock_t *reduced_clock)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int refclk;
-       const intel_limit_t *limit;
-       bool ret;
-
-       refclk = ironlake_get_refclk(crtc_state);
-
-       /*
-        * Returns a set of divisors for the desired target clock with the given
-        * refclk, or FALSE.  The returned values represent the clock equation:
-        * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
-        */
-       limit = intel_limit(crtc_state, refclk);
-       ret = dev_priv->display.find_dpll(limit, crtc_state,
-                                         crtc_state->port_clock,
-                                         refclk, NULL, clock);
-       if (!ret)
-               return false;
-
-       return true;
-}
-
 int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp)
 {
        /*
@@ -8878,10 +8753,9 @@ static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor)
        return i9xx_dpll_compute_m(dpll) < factor * dpll->n;
 }
 
-static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
-                                     struct intel_crtc_state *crtc_state,
-                                     u32 *fp,
-                                     intel_clock_t *reduced_clock, u32 *fp2)
+static void ironlake_compute_dpll(struct intel_crtc *intel_crtc,
+                                 struct intel_crtc_state *crtc_state,
+                                 intel_clock_t *reduced_clock)
 {
        struct drm_crtc *crtc = &intel_crtc->base;
        struct drm_device *dev = crtc->dev;
@@ -8890,8 +8764,8 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
        struct drm_connector *connector;
        struct drm_connector_state *connector_state;
        struct intel_encoder *encoder;
-       uint32_t dpll;
-       int factor, num_connectors = 0, i;
+       u32 dpll, fp, fp2;
+       int factor, i;
        bool is_lvds = false, is_sdvo = false;
 
        for_each_connector_in_state(state, connector, connector_state, i) {
@@ -8911,8 +8785,6 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
                default:
                        break;
                }
-
-               num_connectors++;
        }
 
        /* Enable autotuning of the PLL clock (if permissible) */
@@ -8925,11 +8797,19 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
        } else if (crtc_state->sdvo_tv_clock)
                factor = 20;
 
+       fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
+
        if (ironlake_needs_fb_cb_tune(&crtc_state->dpll, factor))
-               *fp |= FP_CB_TUNE;
+               fp |= FP_CB_TUNE;
 
-       if (fp2 && (reduced_clock->m < factor * reduced_clock->n))
-               *fp2 |= FP_CB_TUNE;
+       if (reduced_clock) {
+               fp2 = i9xx_dpll_compute_fp(reduced_clock);
+
+               if (reduced_clock->m < factor * reduced_clock->n)
+                       fp2 |= FP_CB_TUNE;
+       } else {
+               fp2 = fp;
+       }
 
        dpll = 0;
 
@@ -8966,76 +8846,80 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
                break;
        }
 
-       if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+       if (is_lvds && intel_panel_use_ssc(dev_priv))
                dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
        else
                dpll |= PLL_REF_INPUT_DREFCLK;
 
-       return dpll | DPLL_VCO_ENABLE;
+       dpll |= DPLL_VCO_ENABLE;
+
+       crtc_state->dpll_hw_state.dpll = dpll;
+       crtc_state->dpll_hw_state.fp0 = fp;
+       crtc_state->dpll_hw_state.fp1 = fp2;
 }
 
 static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
                                       struct intel_crtc_state *crtc_state)
 {
        struct drm_device *dev = crtc->base.dev;
-       intel_clock_t clock, reduced_clock;
-       u32 dpll = 0, fp = 0, fp2 = 0;
-       bool ok, has_reduced_clock = false;
-       bool is_lvds = false;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       intel_clock_t reduced_clock;
+       bool has_reduced_clock = false;
        struct intel_shared_dpll *pll;
+       const intel_limit_t *limit;
+       int refclk = 120000;
 
        memset(&crtc_state->dpll_hw_state, 0,
               sizeof(crtc_state->dpll_hw_state));
 
-       is_lvds = intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS);
+       crtc->lowfreq_avail = false;
+
+       /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
+       if (!crtc_state->has_pch_encoder)
+               return 0;
+
+       if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+               if (intel_panel_use_ssc(dev_priv)) {
+                       DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n",
+                                     dev_priv->vbt.lvds_ssc_freq);
+                       refclk = dev_priv->vbt.lvds_ssc_freq;
+               }
 
-       WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
-            "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
+               if (intel_is_dual_link_lvds(dev)) {
+                       if (refclk == 100000)
+                               limit = &intel_limits_ironlake_dual_lvds_100m;
+                       else
+                               limit = &intel_limits_ironlake_dual_lvds;
+               } else {
+                       if (refclk == 100000)
+                               limit = &intel_limits_ironlake_single_lvds_100m;
+                       else
+                               limit = &intel_limits_ironlake_single_lvds;
+               }
+       } else {
+               limit = &intel_limits_ironlake_dac;
+       }
 
-       ok = ironlake_compute_clocks(&crtc->base, crtc_state, &clock,
-                                    &has_reduced_clock, &reduced_clock);
-       if (!ok && !crtc_state->clock_set) {
+       if (!crtc_state->clock_set &&
+           !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+                               refclk, NULL, &crtc_state->dpll)) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
                return -EINVAL;
        }
-       /* Compat-code for transition, will disappear. */
-       if (!crtc_state->clock_set) {
-               crtc_state->dpll.n = clock.n;
-               crtc_state->dpll.m1 = clock.m1;
-               crtc_state->dpll.m2 = clock.m2;
-               crtc_state->dpll.p1 = clock.p1;
-               crtc_state->dpll.p2 = clock.p2;
-       }
 
-       /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
-       if (crtc_state->has_pch_encoder) {
-               fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
-               if (has_reduced_clock)
-                       fp2 = i9xx_dpll_compute_fp(&reduced_clock);
-
-               dpll = ironlake_compute_dpll(crtc, crtc_state,
-                                            &fp, &reduced_clock,
-                                            has_reduced_clock ? &fp2 : NULL);
+       ironlake_compute_dpll(crtc, crtc_state,
+                             has_reduced_clock ? &reduced_clock : NULL);
 
-               crtc_state->dpll_hw_state.dpll = dpll;
-               crtc_state->dpll_hw_state.fp0 = fp;
-               if (has_reduced_clock)
-                       crtc_state->dpll_hw_state.fp1 = fp2;
-               else
-                       crtc_state->dpll_hw_state.fp1 = fp;
-
-               pll = intel_get_shared_dpll(crtc, crtc_state);
-               if (pll == NULL) {
-                       DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
-                                        pipe_name(crtc->pipe));
-                       return -EINVAL;
-               }
+       pll = intel_get_shared_dpll(crtc, crtc_state, NULL);
+       if (pll == NULL) {
+               DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
+                                pipe_name(crtc->pipe));
+               return -EINVAL;
        }
 
-       if (is_lvds && has_reduced_clock)
+       if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
+           has_reduced_clock)
                crtc->lowfreq_avail = true;
-       else
-               crtc->lowfreq_avail = false;
 
        return 0;
 }
@@ -9337,7 +9221,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
                return false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
-       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
+       pipe_config->shared_dpll = NULL;
 
        ret = false;
        tmp = I915_READ(PIPECONF(crtc->pipe));
@@ -9366,6 +9250,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 
        if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
                struct intel_shared_dpll *pll;
+               enum intel_dpll_id pll_id;
 
                pipe_config->has_pch_encoder = true;
 
@@ -9376,20 +9261,21 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
                ironlake_get_fdi_m_n_config(crtc, pipe_config);
 
                if (HAS_PCH_IBX(dev_priv->dev)) {
-                       pipe_config->shared_dpll =
-                               (enum intel_dpll_id) crtc->pipe;
+                       pll_id = (enum intel_dpll_id) crtc->pipe;
                } else {
                        tmp = I915_READ(PCH_DPLL_SEL);
                        if (tmp & TRANS_DPLLB_SEL(crtc->pipe))
-                               pipe_config->shared_dpll = DPLL_ID_PCH_PLL_B;
+                               pll_id = DPLL_ID_PCH_PLL_B;
                        else
-                               pipe_config->shared_dpll = DPLL_ID_PCH_PLL_A;
+                               pll_id= DPLL_ID_PCH_PLL_A;
                }
 
-               pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
+               pipe_config->shared_dpll =
+                       intel_get_shared_dpll_by_id(dev_priv, pll_id);
+               pll = pipe_config->shared_dpll;
 
-               WARN_ON(!pll->get_hw_state(dev_priv, pll,
-                                          &pipe_config->dpll_hw_state));
+               WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll,
+                                                &pipe_config->dpll_hw_state));
 
                tmp = pipe_config->dpll_hw_state.dpll;
                pipe_config->pixel_multiplier =
@@ -9402,6 +9288,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        }
 
        intel_get_pipe_timings(crtc, pipe_config);
+       intel_get_pipe_src_size(crtc, pipe_config);
 
        ironlake_get_pfit_config(crtc, pipe_config);
 
@@ -9709,8 +9596,8 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
        val |= LCPLL_CD_SOURCE_FCLK;
        I915_WRITE(LCPLL_CTL, val);
 
-       if (wait_for_atomic_us(I915_READ(LCPLL_CTL) &
-                              LCPLL_CD_SOURCE_FCLK_DONE, 1))
+       if (wait_for_us(I915_READ(LCPLL_CTL) &
+                       LCPLL_CD_SOURCE_FCLK_DONE, 1))
                DRM_ERROR("Switching to FCLK failed\n");
 
        val = I915_READ(LCPLL_CTL);
@@ -9744,8 +9631,8 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
        val &= ~LCPLL_CD_SOURCE_FCLK;
        I915_WRITE(LCPLL_CTL, val);
 
-       if (wait_for_atomic_us((I915_READ(LCPLL_CTL) &
-                               LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
+       if (wait_for_us((I915_READ(LCPLL_CTL) &
+                       LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
                DRM_ERROR("Switching back to LCPLL failed\n");
 
        mutex_lock(&dev_priv->rps.hw_lock);
@@ -9822,72 +9709,193 @@ static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv,
                                enum port port,
                                struct intel_crtc_state *pipe_config)
 {
+       enum intel_dpll_id id;
+
        switch (port) {
        case PORT_A:
                pipe_config->ddi_pll_sel = SKL_DPLL0;
-               pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1;
+               id = DPLL_ID_SKL_DPLL0;
                break;
        case PORT_B:
                pipe_config->ddi_pll_sel = SKL_DPLL1;
-               pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2;
+               id = DPLL_ID_SKL_DPLL1;
                break;
        case PORT_C:
                pipe_config->ddi_pll_sel = SKL_DPLL2;
-               pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3;
+               id = DPLL_ID_SKL_DPLL2;
                break;
        default:
                DRM_ERROR("Incorrect port type\n");
+               return;
        }
+
+       pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);
 }
 
 static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv,
                                enum port port,
                                struct intel_crtc_state *pipe_config)
 {
-       u32 temp, dpll_ctl1;
+       enum intel_dpll_id id;
+       u32 temp;
 
        temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port);
        pipe_config->ddi_pll_sel = temp >> (port * 3 + 1);
 
        switch (pipe_config->ddi_pll_sel) {
        case SKL_DPLL0:
-               /*
-                * On SKL the eDP DPLL (DPLL0 as we don't use SSC) is not part
-                * of the shared DPLL framework and thus needs to be read out
-                * separately
-                */
-               dpll_ctl1 = I915_READ(DPLL_CTRL1);
-               pipe_config->dpll_hw_state.ctrl1 = dpll_ctl1 & 0x3f;
+               id = DPLL_ID_SKL_DPLL0;
                break;
        case SKL_DPLL1:
-               pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1;
+               id = DPLL_ID_SKL_DPLL1;
                break;
        case SKL_DPLL2:
-               pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2;
+               id = DPLL_ID_SKL_DPLL2;
                break;
        case SKL_DPLL3:
-               pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3;
+               id = DPLL_ID_SKL_DPLL3;
                break;
+       default:
+               MISSING_CASE(pipe_config->ddi_pll_sel);
+               return;
+       }
+
+       pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);
+}
+
+static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
+                               enum port port,
+                               struct intel_crtc_state *pipe_config)
+{
+       enum intel_dpll_id id;
+
+       pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
+
+       switch (pipe_config->ddi_pll_sel) {
+       case PORT_CLK_SEL_WRPLL1:
+               id = DPLL_ID_WRPLL1;
+               break;
+       case PORT_CLK_SEL_WRPLL2:
+               id = DPLL_ID_WRPLL2;
+               break;
+       case PORT_CLK_SEL_SPLL:
+               id = DPLL_ID_SPLL;
+               break;
+       case PORT_CLK_SEL_LCPLL_810:
+               id = DPLL_ID_LCPLL_810;
+               break;
+       case PORT_CLK_SEL_LCPLL_1350:
+               id = DPLL_ID_LCPLL_1350;
+               break;
+       case PORT_CLK_SEL_LCPLL_2700:
+               id = DPLL_ID_LCPLL_2700;
+               break;
+       default:
+               MISSING_CASE(pipe_config->ddi_pll_sel);
+               /* fall through */
+       case PORT_CLK_SEL_NONE:
+               return;
+       }
+
+       pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);
+}
+
+static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
+                                    struct intel_crtc_state *pipe_config,
+                                    unsigned long *power_domain_mask)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum intel_display_power_domain power_domain;
+       u32 tmp;
+
+       pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
+
+       /*
+        * XXX: Do intel_display_power_get_if_enabled before reading this (for
+        * consistency and less surprising code; it's in always on power).
+        */
+       tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
+       if (tmp & TRANS_DDI_FUNC_ENABLE) {
+               enum pipe trans_edp_pipe;
+               switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
+               default:
+                       WARN(1, "unknown pipe linked to edp transcoder\n");
+               case TRANS_DDI_EDP_INPUT_A_ONOFF:
+               case TRANS_DDI_EDP_INPUT_A_ON:
+                       trans_edp_pipe = PIPE_A;
+                       break;
+               case TRANS_DDI_EDP_INPUT_B_ONOFF:
+                       trans_edp_pipe = PIPE_B;
+                       break;
+               case TRANS_DDI_EDP_INPUT_C_ONOFF:
+                       trans_edp_pipe = PIPE_C;
+                       break;
+               }
+
+               if (trans_edp_pipe == crtc->pipe)
+                       pipe_config->cpu_transcoder = TRANSCODER_EDP;
        }
+
+       power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+       *power_domain_mask |= BIT(power_domain);
+
+       tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
+
+       return tmp & PIPECONF_ENABLE;
 }
 
-static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
-                               enum port port,
-                               struct intel_crtc_state *pipe_config)
-{
-       pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
+static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
+                                        struct intel_crtc_state *pipe_config,
+                                        unsigned long *power_domain_mask)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum intel_display_power_domain power_domain;
+       enum port port;
+       enum transcoder cpu_transcoder;
+       u32 tmp;
+
+       pipe_config->has_dsi_encoder = false;
+
+       for_each_port_masked(port, BIT(PORT_A) | BIT(PORT_C)) {
+               if (port == PORT_A)
+                       cpu_transcoder = TRANSCODER_DSI_A;
+               else
+                       cpu_transcoder = TRANSCODER_DSI_C;
+
+               power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
+               if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+                       continue;
+               *power_domain_mask |= BIT(power_domain);
+
+               /*
+                * The PLL needs to be enabled with a valid divider
+                * configuration, otherwise accessing DSI registers will hang
+                * the machine. See BSpec North Display Engine
+                * registers/MIPI[BXT]. We can break out here early, since we
+                * need the same DSI PLL to be enabled for both DSI ports.
+                */
+               if (!intel_dsi_pll_is_enabled(dev_priv))
+                       break;
+
+               /* XXX: this works for video mode only */
+               tmp = I915_READ(BXT_MIPI_PORT_CTRL(port));
+               if (!(tmp & DPI_ENABLE))
+                       continue;
+
+               tmp = I915_READ(MIPI_CTRL(port));
+               if ((tmp & BXT_PIPE_SELECT_MASK) != BXT_PIPE_SELECT(crtc->pipe))
+                       continue;
 
-       switch (pipe_config->ddi_pll_sel) {
-       case PORT_CLK_SEL_WRPLL1:
-               pipe_config->shared_dpll = DPLL_ID_WRPLL1;
-               break;
-       case PORT_CLK_SEL_WRPLL2:
-               pipe_config->shared_dpll = DPLL_ID_WRPLL2;
-               break;
-       case PORT_CLK_SEL_SPLL:
-               pipe_config->shared_dpll = DPLL_ID_SPLL;
+               pipe_config->cpu_transcoder = cpu_transcoder;
+               pipe_config->has_dsi_encoder = true;
                break;
        }
+
+       return pipe_config->has_dsi_encoder;
 }
 
 static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
@@ -9910,11 +9918,10 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
        else
                haswell_get_ddi_pll(dev_priv, port, pipe_config);
 
-       if (pipe_config->shared_dpll >= 0) {
-               pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
-
-               WARN_ON(!pll->get_hw_state(dev_priv, pll,
-                                          &pipe_config->dpll_hw_state));
+       pll = pipe_config->shared_dpll;
+       if (pll) {
+               WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll,
+                                                &pipe_config->dpll_hw_state));
        }
 
        /*
@@ -9941,53 +9948,37 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum intel_display_power_domain power_domain;
        unsigned long power_domain_mask;
-       uint32_t tmp;
-       bool ret;
+       bool active;
 
        power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
        if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
        power_domain_mask = BIT(power_domain);
 
-       ret = false;
-
-       pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
-       pipe_config->shared_dpll = DPLL_ID_PRIVATE;
+       pipe_config->shared_dpll = NULL;
 
-       tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
-       if (tmp & TRANS_DDI_FUNC_ENABLE) {
-               enum pipe trans_edp_pipe;
-               switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
-               default:
-                       WARN(1, "unknown pipe linked to edp transcoder\n");
-               case TRANS_DDI_EDP_INPUT_A_ONOFF:
-               case TRANS_DDI_EDP_INPUT_A_ON:
-                       trans_edp_pipe = PIPE_A;
-                       break;
-               case TRANS_DDI_EDP_INPUT_B_ONOFF:
-                       trans_edp_pipe = PIPE_B;
-                       break;
-               case TRANS_DDI_EDP_INPUT_C_ONOFF:
-                       trans_edp_pipe = PIPE_C;
-                       break;
-               }
+       active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_mask);
 
-               if (trans_edp_pipe == crtc->pipe)
-                       pipe_config->cpu_transcoder = TRANSCODER_EDP;
+       if (IS_BROXTON(dev_priv)) {
+               bxt_get_dsi_transcoder_state(crtc, pipe_config,
+                                            &power_domain_mask);
+               WARN_ON(active && pipe_config->has_dsi_encoder);
+               if (pipe_config->has_dsi_encoder)
+                       active = true;
        }
 
-       power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       if (!active)
                goto out;
-       power_domain_mask |= BIT(power_domain);
 
-       tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
-       if (!(tmp & PIPECONF_ENABLE))
-               goto out;
+       if (!pipe_config->has_dsi_encoder) {
+               haswell_get_ddi_port_state(crtc, pipe_config);
+               intel_get_pipe_timings(crtc, pipe_config);
+       }
 
-       haswell_get_ddi_port_state(crtc, pipe_config);
+       intel_get_pipe_src_size(crtc, pipe_config);
 
-       intel_get_pipe_timings(crtc, pipe_config);
+       pipe_config->gamma_mode =
+               I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
 
        if (INTEL_INFO(dev)->gen >= 9) {
                skl_init_scalers(dev, crtc, pipe_config);
@@ -10011,20 +10002,19 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
                        (I915_READ(IPS_CTL) & IPS_ENABLE);
 
-       if (pipe_config->cpu_transcoder != TRANSCODER_EDP) {
+       if (pipe_config->cpu_transcoder != TRANSCODER_EDP &&
+           !transcoder_is_dsi(pipe_config->cpu_transcoder)) {
                pipe_config->pixel_multiplier =
                        I915_READ(PIPE_MULT(pipe_config->cpu_transcoder)) + 1;
        } else {
                pipe_config->pixel_multiplier = 1;
        }
 
-       ret = true;
-
 out:
        for_each_power_domain(power_domain, power_domain_mask)
                intel_display_power_put(dev_priv, power_domain);
 
-       return ret;
+       return active;
 }
 
 static void i845_update_cursor(struct drm_crtc *crtc, u32 base,
@@ -10217,21 +10207,6 @@ static bool cursor_size_ok(struct drm_device *dev,
        return true;
 }
 
-static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-                                u16 *blue, uint32_t start, uint32_t size)
-{
-       int end = (start + size > 256) ? 256 : start + size, i;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       for (i = start; i < end; i++) {
-               intel_crtc->lut_r[i] = red[i] >> 8;
-               intel_crtc->lut_g[i] = green[i] >> 8;
-               intel_crtc->lut_b[i] = blue[i] >> 8;
-       }
-
-       intel_crtc_load_lut(crtc);
-}
-
 /* VESA 640x480x72Hz mode to set on the pipe */
 static struct drm_display_mode load_detect_mode = {
        DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
@@ -10719,19 +10694,18 @@ int intel_dotclock_calculate(int link_freq,
 static void ironlake_pch_clock_get(struct intel_crtc *crtc,
                                   struct intel_crtc_state *pipe_config)
 {
-       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        /* read out port_clock from the DPLL */
        i9xx_crtc_clock_get(crtc, pipe_config);
 
        /*
-        * This value does not include pixel_multiplier.
-        * We will check that port_clock and adjusted_mode.crtc_clock
-        * agree once we know their relationship in the encoder's
-        * get_config() function.
+        * In case there is an active pipe without active ports,
+        * we may need some idea for the dotclock anyway.
+        * Calculate one based on the FDI configuration.
         */
        pipe_config->base.adjusted_mode.crtc_clock =
-               intel_dotclock_calculate(intel_fdi_link_freq(dev) * 10000,
+               intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config),
                                         &pipe_config->fdi_m_n);
 }
 
@@ -10850,7 +10824,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
        struct drm_plane *primary = crtc->base.primary;
 
        mutex_lock(&dev->struct_mutex);
-       intel_unpin_fb_obj(work->old_fb, primary->state);
+       intel_unpin_fb_obj(work->old_fb, primary->state->rotation);
        drm_gem_object_unreference(&work->pending_flip_obj->base);
 
        if (work->flip_queued_req)
@@ -11004,7 +10978,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
                                 struct drm_i915_gem_request *req,
                                 uint32_t flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        u32 flip_mask;
        int ret;
@@ -11020,13 +10994,13 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
                flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
        else
                flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_emit(ring, MI_DISPLAY_FLIP |
+       intel_ring_emit(engine, MI_WAIT_FOR_EVENT | flip_mask);
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_emit(engine, MI_DISPLAY_FLIP |
                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       intel_ring_emit(ring, fb->pitches[0]);
-       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
-       intel_ring_emit(ring, 0); /* aux display base address, unused */
+       intel_ring_emit(engine, fb->pitches[0]);
+       intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset);
+       intel_ring_emit(engine, 0); /* aux display base address, unused */
 
        intel_mark_page_flip_active(intel_crtc->unpin_work);
        return 0;
@@ -11039,7 +11013,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
                                 struct drm_i915_gem_request *req,
                                 uint32_t flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        u32 flip_mask;
        int ret;
@@ -11052,13 +11026,13 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
                flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
        else
                flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 |
+       intel_ring_emit(engine, MI_WAIT_FOR_EVENT | flip_mask);
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_emit(engine, MI_DISPLAY_FLIP_I915 |
                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       intel_ring_emit(ring, fb->pitches[0]);
-       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
-       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_emit(engine, fb->pitches[0]);
+       intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset);
+       intel_ring_emit(engine, MI_NOOP);
 
        intel_mark_page_flip_active(intel_crtc->unpin_work);
        return 0;
@@ -11071,7 +11045,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
                                 struct drm_i915_gem_request *req,
                                 uint32_t flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t pf, pipesrc;
@@ -11085,10 +11059,10 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
         * Display Registers (which do not change across a page-flip)
         * so we need only reprogram the base address.
         */
-       intel_ring_emit(ring, MI_DISPLAY_FLIP |
+       intel_ring_emit(engine, MI_DISPLAY_FLIP |
                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       intel_ring_emit(ring, fb->pitches[0]);
-       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset |
+       intel_ring_emit(engine, fb->pitches[0]);
+       intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset |
                        obj->tiling_mode);
 
        /* XXX Enabling the panel-fitter across page-flip is so far
@@ -11097,7 +11071,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
         */
        pf = 0;
        pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
-       intel_ring_emit(ring, pf | pipesrc);
+       intel_ring_emit(engine, pf | pipesrc);
 
        intel_mark_page_flip_active(intel_crtc->unpin_work);
        return 0;
@@ -11110,7 +11084,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
                                 struct drm_i915_gem_request *req,
                                 uint32_t flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t pf, pipesrc;
@@ -11120,10 +11094,10 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_DISPLAY_FLIP |
+       intel_ring_emit(engine, MI_DISPLAY_FLIP |
                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode);
-       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
+       intel_ring_emit(engine, fb->pitches[0] | obj->tiling_mode);
+       intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset);
 
        /* Contrary to the suggestions in the documentation,
         * "Enable Panel Fitter" does not seem to be required when page
@@ -11133,7 +11107,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
         */
        pf = 0;
        pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
-       intel_ring_emit(ring, pf | pipesrc);
+       intel_ring_emit(engine, pf | pipesrc);
 
        intel_mark_page_flip_active(intel_crtc->unpin_work);
        return 0;
@@ -11146,7 +11120,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
                                 struct drm_i915_gem_request *req,
                                 uint32_t flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t plane_bit = 0;
        int len, ret;
@@ -11167,7 +11141,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
        }
 
        len = 4;
-       if (ring->id == RCS) {
+       if (engine->id == RCS) {
                len += 6;
                /*
                 * On Gen 8, SRM is now taking an extra dword to accommodate
@@ -11205,36 +11179,36 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
         * for the RCS also doesn't appear to drop events. Setting the DERRMR
         * to zero does lead to lockups within MI_DISPLAY_FLIP.
         */
-       if (ring->id == RCS) {
-               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit_reg(ring, DERRMR);
-               intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
-                                       DERRMR_PIPEB_PRI_FLIP_DONE |
-                                       DERRMR_PIPEC_PRI_FLIP_DONE));
+       if (engine->id == RCS) {
+               intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+               intel_ring_emit_reg(engine, DERRMR);
+               intel_ring_emit(engine, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
+                                         DERRMR_PIPEB_PRI_FLIP_DONE |
+                                         DERRMR_PIPEC_PRI_FLIP_DONE));
                if (IS_GEN8(dev))
-                       intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 |
+                       intel_ring_emit(engine, MI_STORE_REGISTER_MEM_GEN8 |
                                              MI_SRM_LRM_GLOBAL_GTT);
                else
-                       intel_ring_emit(ring, MI_STORE_REGISTER_MEM |
+                       intel_ring_emit(engine, MI_STORE_REGISTER_MEM |
                                              MI_SRM_LRM_GLOBAL_GTT);
-               intel_ring_emit_reg(ring, DERRMR);
-               intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
+               intel_ring_emit_reg(engine, DERRMR);
+               intel_ring_emit(engine, engine->scratch.gtt_offset + 256);
                if (IS_GEN8(dev)) {
-                       intel_ring_emit(ring, 0);
-                       intel_ring_emit(ring, MI_NOOP);
+                       intel_ring_emit(engine, 0);
+                       intel_ring_emit(engine, MI_NOOP);
                }
        }
 
-       intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
-       intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
-       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
-       intel_ring_emit(ring, (MI_NOOP));
+       intel_ring_emit(engine, MI_DISPLAY_FLIP_I915 | plane_bit);
+       intel_ring_emit(engine, (fb->pitches[0] | obj->tiling_mode));
+       intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset);
+       intel_ring_emit(engine, (MI_NOOP));
 
        intel_mark_page_flip_active(intel_crtc->unpin_work);
        return 0;
 }
 
-static bool use_mmio_flip(struct intel_engine_cs *ring,
+static bool use_mmio_flip(struct intel_engine_cs *engine,
                          struct drm_i915_gem_object *obj)
 {
        /*
@@ -11245,10 +11219,10 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,
         * So using MMIO flips there would disrupt this mechanism.
         */
 
-       if (ring == NULL)
+       if (engine == NULL)
                return true;
 
-       if (INTEL_INFO(ring->dev)->gen < 5)
+       if (INTEL_INFO(engine->dev)->gen < 5)
                return false;
 
        if (i915.use_mmio_flip < 0)
@@ -11262,7 +11236,7 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,
                                                       false))
                return true;
        else
-               return ring != i915_gem_request_get_ring(obj->last_write_req);
+               return engine != i915_gem_request_get_engine(obj->last_write_req);
 }
 
 static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
@@ -11508,7 +11482,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        struct drm_plane *primary = crtc->primary;
        enum pipe pipe = intel_crtc->pipe;
        struct intel_unpin_work *work;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        bool mmio_flip;
        struct drm_i915_gem_request *request = NULL;
        int ret;
@@ -11595,21 +11569,21 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
                work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
 
        if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
-               ring = &dev_priv->ring[BCS];
+               engine = &dev_priv->engine[BCS];
                if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode)
                        /* vlv: DISPLAY_FLIP fails to change tiling */
-                       ring = NULL;
+                       engine = NULL;
        } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
-               ring = &dev_priv->ring[BCS];
+               engine = &dev_priv->engine[BCS];
        } else if (INTEL_INFO(dev)->gen >= 7) {
-               ring = i915_gem_request_get_ring(obj->last_write_req);
-               if (ring == NULL || ring->id != RCS)
-                       ring = &dev_priv->ring[BCS];
+               engine = i915_gem_request_get_engine(obj->last_write_req);
+               if (engine == NULL || engine->id != RCS)
+                       engine = &dev_priv->engine[BCS];
        } else {
-               ring = &dev_priv->ring[RCS];
+               engine = &dev_priv->engine[RCS];
        }
 
-       mmio_flip = use_mmio_flip(ring, obj);
+       mmio_flip = use_mmio_flip(engine, obj);
 
        /* When using CS flips, we want to emit semaphores between rings.
         * However, when using mmio flips we will create a task to do the
@@ -11617,13 +11591,12 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
         * into the display plane and skip any waits.
         */
        if (!mmio_flip) {
-               ret = i915_gem_object_sync(obj, ring, &request);
+               ret = i915_gem_object_sync(obj, engine, &request);
                if (ret)
                        goto cleanup_pending;
        }
 
-       ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
-                                        crtc->primary->state);
+       ret = intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
        if (ret)
                goto cleanup_pending;
 
@@ -11640,7 +11613,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
                                        obj->last_write_req);
        } else {
                if (!request) {
-                       request = i915_gem_request_alloc(ring, NULL);
+                       request = i915_gem_request_alloc(engine, NULL);
                        if (IS_ERR(request)) {
                                ret = PTR_ERR(request);
                                goto cleanup_unpin;
@@ -11673,7 +11646,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        return 0;
 
 cleanup_unpin:
-       intel_unpin_fb_obj(fb, crtc->primary->state);
+       intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
 cleanup_pending:
        if (!IS_ERR_OR_NULL(request))
                i915_gem_request_cancel(request);
@@ -11786,6 +11759,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_plane *plane = plane_state->plane;
        struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_plane_state *old_plane_state =
                to_intel_plane_state(plane->state);
        int idx = intel_crtc->base.base.id, ret;
@@ -11834,42 +11808,43 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
                         plane->base.id, was_visible, visible,
                         turn_off, turn_on, mode_changed);
 
-       if (turn_on || turn_off) {
-               pipe_config->wm_changed = true;
+       if (turn_on) {
+               pipe_config->update_wm_pre = true;
+
+               /* must disable cxsr around plane enable/disable */
+               if (plane->type != DRM_PLANE_TYPE_CURSOR)
+                       pipe_config->disable_cxsr = true;
+       } else if (turn_off) {
+               pipe_config->update_wm_post = true;
 
                /* must disable cxsr around plane enable/disable */
                if (plane->type != DRM_PLANE_TYPE_CURSOR)
                        pipe_config->disable_cxsr = true;
        } else if (intel_wm_need_update(plane, plane_state)) {
-               pipe_config->wm_changed = true;
+               /* FIXME bollocks */
+               pipe_config->update_wm_pre = true;
+               pipe_config->update_wm_post = true;
        }
 
-       if (visible || was_visible)
-               intel_crtc->atomic.fb_bits |=
-                       to_intel_plane(plane)->frontbuffer_bit;
+       /* Pre-gen9 platforms need two-step watermark updates */
+       if ((pipe_config->update_wm_pre || pipe_config->update_wm_post) &&
+           INTEL_INFO(dev)->gen < 9 && dev_priv->display.optimize_watermarks)
+               to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
 
-       switch (plane->type) {
-       case DRM_PLANE_TYPE_PRIMARY:
-               intel_crtc->atomic.post_enable_primary = turn_on;
-               intel_crtc->atomic.update_fbc = true;
+       if (visible || was_visible)
+               pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit;
 
-               break;
-       case DRM_PLANE_TYPE_CURSOR:
-               break;
-       case DRM_PLANE_TYPE_OVERLAY:
-               /*
-                * WaCxSRDisabledForSpriteScaling:ivb
-                *
-                * cstate->update_wm was already set above, so this flag will
-                * take effect when we commit and program watermarks.
-                */
-               if (IS_IVYBRIDGE(dev) &&
-                   needs_scaling(to_intel_plane_state(plane_state)) &&
-                   !needs_scaling(old_plane_state))
-                       pipe_config->disable_lp_wm = true;
+       /*
+        * WaCxSRDisabledForSpriteScaling:ivb
+        *
+        * cstate->update_wm was already set above, so this flag will
+        * take effect when we commit and program watermarks.
+        */
+       if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev) &&
+           needs_scaling(to_intel_plane_state(plane_state)) &&
+           !needs_scaling(old_plane_state))
+               pipe_config->disable_lp_wm = true;
 
-               break;
-       }
        return 0;
 }
 
@@ -11941,22 +11916,49 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
        }
 
        if (mode_changed && !crtc_state->active)
-               pipe_config->wm_changed = true;
+               pipe_config->update_wm_post = true;
 
        if (mode_changed && crtc_state->enable &&
            dev_priv->display.crtc_compute_clock &&
-           !WARN_ON(pipe_config->shared_dpll != DPLL_ID_PRIVATE)) {
+           !WARN_ON(pipe_config->shared_dpll)) {
                ret = dev_priv->display.crtc_compute_clock(intel_crtc,
                                                           pipe_config);
                if (ret)
                        return ret;
        }
 
+       if (crtc_state->color_mgmt_changed) {
+               ret = intel_color_check(crtc, crtc_state);
+               if (ret)
+                       return ret;
+       }
+
        ret = 0;
        if (dev_priv->display.compute_pipe_wm) {
-               ret = dev_priv->display.compute_pipe_wm(intel_crtc, state);
-               if (ret)
+               ret = dev_priv->display.compute_pipe_wm(pipe_config);
+               if (ret) {
+                       DRM_DEBUG_KMS("Target pipe watermarks are invalid\n");
+                       return ret;
+               }
+       }
+
+       if (dev_priv->display.compute_intermediate_wm &&
+           !to_intel_atomic_state(state)->skip_intermediate_wm) {
+               if (WARN_ON(!dev_priv->display.compute_pipe_wm))
+                       return 0;
+
+               /*
+                * Calculate 'intermediate' watermarks that satisfy both the
+                * old state and the new state.  We can program these
+                * immediately.
+                */
+               ret = dev_priv->display.compute_intermediate_wm(crtc->dev,
+                                                               intel_crtc,
+                                                               pipe_config);
+               if (ret) {
+                       DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n");
                        return ret;
+               }
        }
 
        if (INTEL_INFO(dev)->gen >= 9) {
@@ -11973,7 +11975,6 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
 
 static const struct drm_crtc_helper_funcs intel_helper_funcs = {
        .mode_set_base_atomic = intel_pipe_set_base_atomic,
-       .load_lut = intel_crtc_load_lut,
        .atomic_begin = intel_begin_crtc_commit,
        .atomic_flush = intel_finish_crtc_commit,
        .atomic_check = intel_crtc_atomic_check,
@@ -12090,7 +12091,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
        DRM_DEBUG_KMS("[CRTC:%d]%s config %p for pipe %c\n", crtc->base.base.id,
                      context, pipe_config, pipe_name(crtc->pipe));
 
-       DRM_DEBUG_KMS("cpu_transcoder: %c\n", transcoder_name(pipe_config->cpu_transcoder));
+       DRM_DEBUG_KMS("cpu_transcoder: %s\n", transcoder_name(pipe_config->cpu_transcoder));
        DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n",
                      pipe_config->pipe_bpp, pipe_config->dither);
        DRM_DEBUG_KMS("fdi/pch: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
@@ -12166,7 +12167,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
                              pipe_config->dpll_hw_state.cfgcr1,
                              pipe_config->dpll_hw_state.cfgcr2);
        } else if (HAS_DDI(dev)) {
-               DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
+               DRM_DEBUG_KMS("ddi_pll_sel: 0x%x; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
                              pipe_config->ddi_pll_sel,
                              pipe_config->dpll_hw_state.wrpll,
                              pipe_config->dpll_hw_state.spll);
@@ -12269,7 +12270,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
        struct drm_crtc_state tmp_state;
        struct intel_crtc_scaler_state scaler_state;
        struct intel_dpll_hw_state dpll_hw_state;
-       enum intel_dpll_id shared_dpll;
+       struct intel_shared_dpll *shared_dpll;
        uint32_t ddi_pll_sel;
        bool force_thru;
 
@@ -12539,6 +12540,15 @@ intel_pipe_config_compare(struct drm_device *dev,
                ret = false; \
        }
 
+#define PIPE_CONF_CHECK_P(name)        \
+       if (current_config->name != pipe_config->name) { \
+               INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
+                         "(expected %p, found %p)\n", \
+                         current_config->name, \
+                         pipe_config->name); \
+               ret = false; \
+       }
+
 #define PIPE_CONF_CHECK_M_N(name) \
        if (!intel_compare_link_m_n(&current_config->name, \
                                    &pipe_config->name,\
@@ -12706,7 +12716,7 @@ intel_pipe_config_compare(struct drm_device *dev,
 
        PIPE_CONF_CHECK_X(ddi_pll_sel);
 
-       PIPE_CONF_CHECK_I(shared_dpll);
+       PIPE_CONF_CHECK_P(shared_dpll);
        PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
        PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
        PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
@@ -12725,6 +12735,7 @@ intel_pipe_config_compare(struct drm_device *dev,
 
 #undef PIPE_CONF_CHECK_X
 #undef PIPE_CONF_CHECK_I
+#undef PIPE_CONF_CHECK_P
 #undef PIPE_CONF_CHECK_I_ALT
 #undef PIPE_CONF_CHECK_FLAGS
 #undef PIPE_CONF_CHECK_CLOCK_FUZZY
@@ -12734,6 +12745,24 @@ intel_pipe_config_compare(struct drm_device *dev,
        return ret;
 }
 
+static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv,
+                                          const struct intel_crtc_state *pipe_config)
+{
+       if (pipe_config->has_pch_encoder) {
+               int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config),
+                                                           &pipe_config->fdi_m_n);
+               int dotclock = pipe_config->base.adjusted_mode.crtc_clock;
+
+               /*
+                * FDI already provided one idea for the dotclock.
+                * Yell if the encoder disagrees.
+                */
+               WARN(!intel_fuzzy_clock_check(fdi_dotclock, dotclock),
+                    "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n",
+                    fdi_dotclock, dotclock);
+       }
+}
+
 static void check_wm_state(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -12907,6 +12936,8 @@ check_crtc_state(struct drm_device *dev, struct drm_atomic_state *old_state)
                if (!crtc->state->active)
                        continue;
 
+               intel_pipe_config_sanity_check(dev_priv, pipe_config);
+
                sw_config = to_intel_crtc_state(crtc->state);
                if (!intel_pipe_config_compare(dev, sw_config,
                                               pipe_config, false)) {
@@ -12928,39 +12959,44 @@ check_shared_dpll_state(struct drm_device *dev)
        int i;
 
        for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-               struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
-               int enabled_crtcs = 0, active_crtcs = 0;
+               struct intel_shared_dpll *pll =
+                       intel_get_shared_dpll_by_id(dev_priv, i);
+               unsigned enabled_crtcs = 0, active_crtcs = 0;
                bool active;
 
                memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
 
                DRM_DEBUG_KMS("%s\n", pll->name);
 
-               active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state);
+               active = pll->funcs.get_hw_state(dev_priv, pll, &dpll_hw_state);
+
+               I915_STATE_WARN(pll->active_mask & ~pll->config.crtc_mask,
+                    "more active pll users than references: %x vs %x\n",
+                    pll->active_mask, pll->config.crtc_mask);
 
-               I915_STATE_WARN(pll->active > hweight32(pll->config.crtc_mask),
-                    "more active pll users than references: %i vs %i\n",
-                    pll->active, hweight32(pll->config.crtc_mask));
-               I915_STATE_WARN(pll->active && !pll->on,
-                    "pll in active use but not on in sw tracking\n");
-               I915_STATE_WARN(pll->on && !pll->active,
-                    "pll in on but not on in use in sw tracking\n");
-               I915_STATE_WARN(pll->on != active,
-                    "pll on state mismatch (expected %i, found %i)\n",
-                    pll->on, active);
+               if (!(pll->flags & INTEL_DPLL_ALWAYS_ON)) {
+                       I915_STATE_WARN(!pll->on && pll->active_mask,
+                            "pll in active use but not on in sw tracking\n");
+                       I915_STATE_WARN(pll->on && !pll->active_mask,
+                            "pll is on but not used by any active crtc\n");
+                       I915_STATE_WARN(pll->on != active,
+                            "pll on state mismatch (expected %i, found %i)\n",
+                            pll->on, active);
+               }
 
                for_each_intel_crtc(dev, crtc) {
-                       if (crtc->base.state->enable && intel_crtc_to_shared_dpll(crtc) == pll)
-                               enabled_crtcs++;
-                       if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
-                               active_crtcs++;
-               }
-               I915_STATE_WARN(pll->active != active_crtcs,
-                    "pll active crtcs mismatch (expected %i, found %i)\n",
-                    pll->active, active_crtcs);
-               I915_STATE_WARN(hweight32(pll->config.crtc_mask) != enabled_crtcs,
-                    "pll enabled crtcs mismatch (expected %i, found %i)\n",
-                    hweight32(pll->config.crtc_mask), enabled_crtcs);
+                       if (crtc->base.state->enable && crtc->config->shared_dpll == pll)
+                               enabled_crtcs |= 1 << drm_crtc_index(&crtc->base);
+                       if (crtc->base.state->active && crtc->config->shared_dpll == pll)
+                               active_crtcs |= 1 << drm_crtc_index(&crtc->base);
+               }
+
+               I915_STATE_WARN(pll->active_mask != active_crtcs,
+                    "pll active crtcs mismatch (expected %x, found %x)\n",
+                    pll->active_mask, active_crtcs);
+               I915_STATE_WARN(pll->config.crtc_mask != enabled_crtcs,
+                    "pll enabled crtcs mismatch (expected %x, found %x)\n",
+                    pll->config.crtc_mask, enabled_crtcs);
 
                I915_STATE_WARN(pll->on && memcmp(&pll->config.hw_state, &dpll_hw_state,
                                       sizeof(dpll_hw_state)),
@@ -12979,18 +13015,6 @@ intel_modeset_check_state(struct drm_device *dev,
        check_shared_dpll_state(dev);
 }
 
-void ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,
-                                    int dotclock)
-{
-       /*
-        * FDI already provided one idea for the dotclock.
-        * Yell if the encoder disagrees.
-        */
-       WARN(!intel_fuzzy_clock_check(pipe_config->base.adjusted_mode.crtc_clock, dotclock),
-            "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n",
-            pipe_config->base.adjusted_mode.crtc_clock, dotclock);
-}
-
 static void update_scanline_offset(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
@@ -13043,20 +13067,21 @@ static void intel_modeset_clear_plls(struct drm_atomic_state *state)
 
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-               int old_dpll = to_intel_crtc_state(crtc->state)->shared_dpll;
+               struct intel_shared_dpll *old_dpll =
+                       to_intel_crtc_state(crtc->state)->shared_dpll;
 
                if (!needs_modeset(crtc_state))
                        continue;
 
-               to_intel_crtc_state(crtc_state)->shared_dpll = DPLL_ID_PRIVATE;
+               to_intel_crtc_state(crtc_state)->shared_dpll = NULL;
 
-               if (old_dpll == DPLL_ID_PRIVATE)
+               if (!old_dpll)
                        continue;
 
                if (!shared_dpll)
                        shared_dpll = intel_atomic_get_shared_dpll_state(state);
 
-               shared_dpll[old_dpll].crtc_mask &= ~(1 << intel_crtc->pipe);
+               intel_shared_dpll_config_put(shared_dpll, old_dpll, intel_crtc);
        }
 }
 
@@ -13268,9 +13293,6 @@ static int intel_atomic_check(struct drm_device *dev,
                struct intel_crtc_state *pipe_config =
                        to_intel_crtc_state(crtc_state);
 
-               memset(&to_intel_crtc(crtc)->atomic, 0,
-                      sizeof(struct intel_crtc_atomic_commit));
-
                /* Catch I915_MODE_FLAG_INHERITED */
                if (crtc_state->mode.private_flags != crtc->state->mode.private_flags)
                        crtc_state->mode_changed = true;
@@ -13451,12 +13473,12 @@ static bool needs_vblank_wait(struct intel_crtc_state *crtc_state)
                return true;
 
        /* wm changes, need vblank before final wm's */
-       if (crtc_state->wm_changed)
+       if (crtc_state->update_wm_post)
                return true;
 
        /*
         * cxsr is re-enabled after vblank.
-        * This is already handled by crtc_state->wm_changed,
+        * This is already handled by crtc_state->update_wm_post,
         * but added for clarity.
         */
        if (crtc_state->disable_cxsr)
@@ -13487,8 +13509,9 @@ static int intel_atomic_commit(struct drm_device *dev,
 {
        struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *old_crtc_state;
        struct drm_crtc *crtc;
+       struct intel_crtc_state *intel_cstate;
        int ret = 0, i;
        bool hw_check = intel_state->modeset;
        unsigned long put_domains[I915_MAX_PIPES] = {};
@@ -13501,7 +13524,8 @@ static int intel_atomic_commit(struct drm_device *dev,
        }
 
        drm_atomic_helper_swap_state(dev, state);
-       dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
+       dev_priv->wm.config = intel_state->wm_config;
+       intel_shared_dpll_commit(state);
 
        if (intel_state->modeset) {
                memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
@@ -13512,7 +13536,7 @@ static int intel_atomic_commit(struct drm_device *dev,
                intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
        }
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
                if (needs_modeset(crtc->state) ||
@@ -13527,10 +13551,10 @@ static int intel_atomic_commit(struct drm_device *dev,
                if (!needs_modeset(crtc->state))
                        continue;
 
-               intel_pre_plane_update(to_intel_crtc_state(crtc_state));
+               intel_pre_plane_update(to_intel_crtc_state(old_crtc_state));
 
-               if (crtc_state->active) {
-                       intel_crtc_disable_planes(crtc, crtc_state->plane_mask);
+               if (old_crtc_state->active) {
+                       intel_crtc_disable_planes(crtc, old_crtc_state->plane_mask);
                        dev_priv->display.crtc_disable(crtc);
                        intel_crtc->active = false;
                        intel_fbc_disable(intel_crtc);
@@ -13553,8 +13577,6 @@ static int intel_atomic_commit(struct drm_device *dev,
        intel_modeset_update_crtc_state(state);
 
        if (intel_state->modeset) {
-               intel_shared_dpll_commit(state);
-
                drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
 
                if (dev_priv->display.modeset_commit_cdclk &&
@@ -13563,7 +13585,7 @@ static int intel_atomic_commit(struct drm_device *dev,
        }
 
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+       for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
                bool modeset = needs_modeset(crtc->state);
                struct intel_crtc_state *pipe_config =
@@ -13575,15 +13597,28 @@ static int intel_atomic_commit(struct drm_device *dev,
                        dev_priv->display.crtc_enable(crtc);
                }
 
+               if (!modeset &&
+                   crtc->state->active &&
+                   crtc->state->color_mgmt_changed) {
+                       /*
+                        * Only update color management when not doing
+                        * a modeset as this will be done by
+                        * crtc_enable already.
+                        */
+                       intel_color_set_csc(crtc);
+                       intel_color_load_luts(crtc);
+               }
+
                if (!modeset)
-                       intel_pre_plane_update(to_intel_crtc_state(crtc_state));
+                       intel_pre_plane_update(to_intel_crtc_state(old_crtc_state));
 
-               if (crtc->state->active && intel_crtc->atomic.update_fbc)
+               if (crtc->state->active &&
+                   drm_atomic_get_existing_plane_state(state, crtc->primary))
                        intel_fbc_enable(intel_crtc);
 
                if (crtc->state->active &&
                    (crtc->state->planes_changed || update_pipe))
-                       drm_atomic_helper_commit_planes_on_crtc(crtc_state);
+                       drm_atomic_helper_commit_planes_on_crtc(old_crtc_state);
 
                if (pipe_config->base.active && needs_vblank_wait(pipe_config))
                        crtc_vblank_mask |= 1 << i;
@@ -13594,8 +13629,22 @@ static int intel_atomic_commit(struct drm_device *dev,
        if (!state->legacy_cursor_update)
                intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask);
 
-       for_each_crtc_in_state(state, crtc, crtc_state, i) {
-               intel_post_plane_update(to_intel_crtc(crtc));
+       /*
+        * Now that the vblank has passed, we can go ahead and program the
+        * optimal watermarks on platforms that need two-step watermark
+        * programming.
+        *
+        * TODO: Move this (and other cleanup) to an async worker eventually.
+        */
+       for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+               intel_cstate = to_intel_crtc_state(crtc->state);
+
+               if (dev_priv->display.optimize_watermarks)
+                       dev_priv->display.optimize_watermarks(intel_cstate);
+       }
+
+       for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+               intel_post_plane_update(to_intel_crtc_state(old_crtc_state));
 
                if (put_domains[i])
                        modeset_put_power_domains(dev_priv, put_domains[i]);
@@ -13670,116 +13719,15 @@ out:
 #undef for_each_intel_crtc_masked
 
 static const struct drm_crtc_funcs intel_crtc_funcs = {
-       .gamma_set = intel_crtc_gamma_set,
+       .gamma_set = drm_atomic_helper_legacy_gamma_set,
        .set_config = drm_atomic_helper_set_config,
+       .set_property = drm_atomic_helper_crtc_set_property,
        .destroy = intel_crtc_destroy,
        .page_flip = intel_crtc_page_flip,
        .atomic_duplicate_state = intel_crtc_duplicate_state,
        .atomic_destroy_state = intel_crtc_destroy_state,
 };
 
-static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
-                                     struct intel_shared_dpll *pll,
-                                     struct intel_dpll_hw_state *hw_state)
-{
-       uint32_t val;
-
-       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
-               return false;
-
-       val = I915_READ(PCH_DPLL(pll->id));
-       hw_state->dpll = val;
-       hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
-       hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
-
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-
-       return val & DPLL_VCO_ENABLE;
-}
-
-static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
-                                 struct intel_shared_dpll *pll)
-{
-       I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
-       I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
-}
-
-static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
-                               struct intel_shared_dpll *pll)
-{
-       /* PCH refclock must be enabled first */
-       ibx_assert_pch_refclk_enabled(dev_priv);
-
-       I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
-
-       /* Wait for the clocks to stabilize. */
-       POSTING_READ(PCH_DPLL(pll->id));
-       udelay(150);
-
-       /* The pixel multiplier can only be updated once the
-        * DPLL is enabled and the clocks are stable.
-        *
-        * So write it again.
-        */
-       I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
-       POSTING_READ(PCH_DPLL(pll->id));
-       udelay(200);
-}
-
-static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
-                                struct intel_shared_dpll *pll)
-{
-       struct drm_device *dev = dev_priv->dev;
-       struct intel_crtc *crtc;
-
-       /* Make sure no transcoder isn't still depending on us. */
-       for_each_intel_crtc(dev, crtc) {
-               if (intel_crtc_to_shared_dpll(crtc) == pll)
-                       assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
-       }
-
-       I915_WRITE(PCH_DPLL(pll->id), 0);
-       POSTING_READ(PCH_DPLL(pll->id));
-       udelay(200);
-}
-
-static char *ibx_pch_dpll_names[] = {
-       "PCH DPLL A",
-       "PCH DPLL B",
-};
-
-static void ibx_pch_dpll_init(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
-
-       dev_priv->num_shared_dpll = 2;
-
-       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-               dev_priv->shared_dplls[i].id = i;
-               dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i];
-               dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set;
-               dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable;
-               dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable;
-               dev_priv->shared_dplls[i].get_hw_state =
-                       ibx_pch_dpll_get_hw_state;
-       }
-}
-
-static void intel_shared_dpll_init(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (HAS_DDI(dev))
-               intel_ddi_pll_init(dev);
-       else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
-               ibx_pch_dpll_init(dev);
-       else
-               dev_priv->num_shared_dpll = 0;
-
-       BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
-}
-
 /**
  * intel_prepare_plane_fb - Prepare fb for usage on plane
  * @plane: drm plane to prepare for
@@ -13853,7 +13801,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                if (ret)
                        DRM_DEBUG_KMS("failed to attach phys object\n");
        } else {
-               ret = intel_pin_and_fence_fb_obj(plane, fb, new_state);
+               ret = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
        }
 
        if (ret == 0) {
@@ -13897,7 +13845,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
 
        if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
            !INTEL_INFO(dev)->cursor_needs_physical))
-               intel_unpin_fb_obj(old_state->fb, old_state);
+               intel_unpin_fb_obj(old_state->fb, old_state->rotation);
 
        /* prepare_fb aborted? */
        if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) ||
@@ -13905,7 +13853,6 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
                i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
 
        i915_gem_request_assign(&old_intel_state->wait_req, NULL);
-
 }
 
 int
@@ -14277,7 +14224,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
        struct intel_crtc_state *crtc_state = NULL;
        struct drm_plane *primary = NULL;
        struct drm_plane *cursor = NULL;
-       int i, ret;
+       int ret;
 
        intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
        if (intel_crtc == NULL)
@@ -14313,13 +14260,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
        if (ret)
                goto fail;
 
-       drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
-       for (i = 0; i < 256; i++) {
-               intel_crtc->lut_r[i] = i;
-               intel_crtc->lut_g[i] = i;
-               intel_crtc->lut_b[i] = i;
-       }
-
        /*
         * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
         * is hooked to pipe B. Hence we want plane A feeding pipe B.
@@ -14344,6 +14284,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
        drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
+       intel_color_init(&intel_crtc->base);
+
        WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
        return;
 
@@ -14468,6 +14410,8 @@ static void intel_setup_outputs(struct drm_device *dev)
                intel_ddi_init(dev, PORT_A);
                intel_ddi_init(dev, PORT_B);
                intel_ddi_init(dev, PORT_C);
+
+               intel_dsi_init(dev);
        } else if (HAS_DDI(dev)) {
                int found;
 
@@ -14837,6 +14781,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
        drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
        intel_fb->obj = obj;
 
+       intel_fill_fb_info(dev_priv, &intel_fb->base);
+
        ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
        if (ret) {
                DRM_ERROR("framebuffer init failed %d\n", ret);
@@ -14884,23 +14830,13 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {
        .atomic_state_clear = intel_atomic_state_clear,
 };
 
-/* Set up chip specific display functions */
-static void intel_init_display(struct drm_device *dev)
+/**
+ * intel_init_display_hooks - initialize the display modesetting hooks
+ * @dev_priv: device private
+ */
+void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (HAS_PCH_SPLIT(dev) || IS_G4X(dev))
-               dev_priv->display.find_dpll = g4x_find_best_dpll;
-       else if (IS_CHERRYVIEW(dev))
-               dev_priv->display.find_dpll = chv_find_best_dpll;
-       else if (IS_VALLEYVIEW(dev))
-               dev_priv->display.find_dpll = vlv_find_best_dpll;
-       else if (IS_PINEVIEW(dev))
-               dev_priv->display.find_dpll = pnv_find_best_dpll;
-       else
-               dev_priv->display.find_dpll = i9xx_find_best_dpll;
-
-       if (INTEL_INFO(dev)->gen >= 9) {
+       if (INTEL_INFO(dev_priv)->gen >= 9) {
                dev_priv->display.get_pipe_config = haswell_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        skylake_get_initial_plane_config;
@@ -14908,7 +14844,7 @@ static void intel_init_display(struct drm_device *dev)
                        haswell_crtc_compute_clock;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
-       } else if (HAS_DDI(dev)) {
+       } else if (HAS_DDI(dev_priv)) {
                dev_priv->display.get_pipe_config = haswell_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        ironlake_get_initial_plane_config;
@@ -14916,7 +14852,7 @@ static void intel_init_display(struct drm_device *dev)
                        haswell_crtc_compute_clock;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
-       } else if (HAS_PCH_SPLIT(dev)) {
+       } else if (HAS_PCH_SPLIT(dev_priv)) {
                dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        ironlake_get_initial_plane_config;
@@ -14924,106 +14860,134 @@ static void intel_init_display(struct drm_device *dev)
                        ironlake_crtc_compute_clock;
                dev_priv->display.crtc_enable = ironlake_crtc_enable;
                dev_priv->display.crtc_disable = ironlake_crtc_disable;
-       } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+       } else if (IS_CHERRYVIEW(dev_priv)) {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        i9xx_get_initial_plane_config;
-               dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
+               dev_priv->display.crtc_compute_clock = chv_crtc_compute_clock;
                dev_priv->display.crtc_enable = valleyview_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
-       } else {
+       } else if (IS_VALLEYVIEW(dev_priv)) {
+               dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+               dev_priv->display.get_initial_plane_config =
+                       i9xx_get_initial_plane_config;
+               dev_priv->display.crtc_compute_clock = vlv_crtc_compute_clock;
+               dev_priv->display.crtc_enable = valleyview_crtc_enable;
+               dev_priv->display.crtc_disable = i9xx_crtc_disable;
+       } else if (IS_G4X(dev_priv)) {
+               dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+               dev_priv->display.get_initial_plane_config =
+                       i9xx_get_initial_plane_config;
+               dev_priv->display.crtc_compute_clock = g4x_crtc_compute_clock;
+               dev_priv->display.crtc_enable = i9xx_crtc_enable;
+               dev_priv->display.crtc_disable = i9xx_crtc_disable;
+       } else if (IS_PINEVIEW(dev_priv)) {
+               dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+               dev_priv->display.get_initial_plane_config =
+                       i9xx_get_initial_plane_config;
+               dev_priv->display.crtc_compute_clock = pnv_crtc_compute_clock;
+               dev_priv->display.crtc_enable = i9xx_crtc_enable;
+               dev_priv->display.crtc_disable = i9xx_crtc_disable;
+       } else if (!IS_GEN2(dev_priv)) {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        i9xx_get_initial_plane_config;
                dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
                dev_priv->display.crtc_enable = i9xx_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
+       } else {
+               dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+               dev_priv->display.get_initial_plane_config =
+                       i9xx_get_initial_plane_config;
+               dev_priv->display.crtc_compute_clock = i8xx_crtc_compute_clock;
+               dev_priv->display.crtc_enable = i9xx_crtc_enable;
+               dev_priv->display.crtc_disable = i9xx_crtc_disable;
        }
 
        /* Returns the core display clock speed */
-       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        skylake_get_display_clock_speed;
-       else if (IS_BROXTON(dev))
+       else if (IS_BROXTON(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        broxton_get_display_clock_speed;
-       else if (IS_BROADWELL(dev))
+       else if (IS_BROADWELL(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        broadwell_get_display_clock_speed;
-       else if (IS_HASWELL(dev))
+       else if (IS_HASWELL(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        haswell_get_display_clock_speed;
-       else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+       else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        valleyview_get_display_clock_speed;
-       else if (IS_GEN5(dev))
+       else if (IS_GEN5(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        ilk_get_display_clock_speed;
-       else if (IS_I945G(dev) || IS_BROADWATER(dev) ||
-                IS_GEN6(dev) || IS_IVYBRIDGE(dev))
+       else if (IS_I945G(dev_priv) || IS_BROADWATER(dev_priv) ||
+                IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        i945_get_display_clock_speed;
-       else if (IS_GM45(dev))
+       else if (IS_GM45(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        gm45_get_display_clock_speed;
-       else if (IS_CRESTLINE(dev))
+       else if (IS_CRESTLINE(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        i965gm_get_display_clock_speed;
-       else if (IS_PINEVIEW(dev))
+       else if (IS_PINEVIEW(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        pnv_get_display_clock_speed;
-       else if (IS_G33(dev) || IS_G4X(dev))
+       else if (IS_G33(dev_priv) || IS_G4X(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        g33_get_display_clock_speed;
-       else if (IS_I915G(dev))
+       else if (IS_I915G(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        i915_get_display_clock_speed;
-       else if (IS_I945GM(dev) || IS_845G(dev))
+       else if (IS_I945GM(dev_priv) || IS_845G(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        i9xx_misc_get_display_clock_speed;
-       else if (IS_I915GM(dev))
+       else if (IS_I915GM(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        i915gm_get_display_clock_speed;
-       else if (IS_I865G(dev))
+       else if (IS_I865G(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        i865_get_display_clock_speed;
-       else if (IS_I85X(dev))
+       else if (IS_I85X(dev_priv))
                dev_priv->display.get_display_clock_speed =
                        i85x_get_display_clock_speed;
        else { /* 830 */
-               WARN(!IS_I830(dev), "Unknown platform. Assuming 133 MHz CDCLK\n");
+               WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz CDCLK\n");
                dev_priv->display.get_display_clock_speed =
                        i830_get_display_clock_speed;
        }
 
-       if (IS_GEN5(dev)) {
+       if (IS_GEN5(dev_priv)) {
                dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
-       } else if (IS_GEN6(dev)) {
+       } else if (IS_GEN6(dev_priv)) {
                dev_priv->display.fdi_link_train = gen6_fdi_link_train;
-       } else if (IS_IVYBRIDGE(dev)) {
+       } else if (IS_IVYBRIDGE(dev_priv)) {
                /* FIXME: detect B0+ stepping and use auto training */
                dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
-       } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+       } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
                dev_priv->display.fdi_link_train = hsw_fdi_link_train;
-               if (IS_BROADWELL(dev)) {
+               if (IS_BROADWELL(dev_priv)) {
                        dev_priv->display.modeset_commit_cdclk =
                                broadwell_modeset_commit_cdclk;
                        dev_priv->display.modeset_calc_cdclk =
                                broadwell_modeset_calc_cdclk;
                }
-       } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+       } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                dev_priv->display.modeset_commit_cdclk =
                        valleyview_modeset_commit_cdclk;
                dev_priv->display.modeset_calc_cdclk =
                        valleyview_modeset_calc_cdclk;
-       } else if (IS_BROXTON(dev)) {
+       } else if (IS_BROXTON(dev_priv)) {
                dev_priv->display.modeset_commit_cdclk =
                        broxton_modeset_commit_cdclk;
                dev_priv->display.modeset_calc_cdclk =
                        broxton_modeset_calc_cdclk;
        }
 
-       switch (INTEL_INFO(dev)->gen) {
+       switch (INTEL_INFO(dev_priv)->gen) {
        case 2:
                dev_priv->display.queue_flip = intel_gen2_queue_flip;
                break;
@@ -15050,8 +15014,6 @@ static void intel_init_display(struct drm_device *dev)
                /* Default just returns -ENODEV to indicate unsupported */
                dev_priv->display.queue_flip = intel_default_queue_flip;
        }
-
-       mutex_init(&dev_priv->pps_mutex);
 }
 
 /*
@@ -15274,7 +15236,7 @@ static void sanitize_watermarks(struct drm_device *dev)
        int i;
 
        /* Only supported on platforms that use atomic watermark design */
-       if (!dev_priv->display.program_watermarks)
+       if (!dev_priv->display.optimize_watermarks)
                return;
 
        /*
@@ -15295,6 +15257,13 @@ retry:
        if (WARN_ON(IS_ERR(state)))
                goto fail;
 
+       /*
+        * Hardware readout is the only time we don't want to calculate
+        * intermediate watermarks (since we don't trust the current
+        * watermarks).
+        */
+       to_intel_atomic_state(state)->skip_intermediate_wm = true;
+
        ret = intel_atomic_check(dev, state);
        if (ret) {
                /*
@@ -15317,7 +15286,8 @@ retry:
        for_each_crtc_in_state(state, crtc, cstate, i) {
                struct intel_crtc_state *cs = to_intel_crtc_state(cstate);
 
-               dev_priv->display.program_watermarks(cs);
+               cs->wm.need_postvbl_update = true;
+               dev_priv->display.optimize_watermarks(cs);
        }
 
        drm_atomic_state_free(state);
@@ -15370,9 +15340,6 @@ void intel_modeset_init(struct drm_device *dev)
                }
        }
 
-       intel_init_display(dev);
-       intel_init_audio(dev);
-
        if (IS_GEN2(dev)) {
                dev->mode_config.max_width = 2048;
                dev->mode_config.max_height = 2048;
@@ -15395,7 +15362,7 @@ void intel_modeset_init(struct drm_device *dev)
                dev->mode_config.cursor_height = MAX_CURSOR_HEIGHT;
        }
 
-       dev->mode_config.fb_base = dev_priv->gtt.mappable_base;
+       dev->mode_config.fb_base = dev_priv->ggtt.mappable_base;
 
        DRM_DEBUG_KMS("%d display pipe%s available.\n",
                      INTEL_INFO(dev)->num_pipes,
@@ -15412,6 +15379,7 @@ void intel_modeset_init(struct drm_device *dev)
        }
 
        intel_update_czclk(dev_priv);
+       intel_update_rawclk(dev_priv);
        intel_update_cdclk(dev);
 
        intel_shared_dpll_init(dev);
@@ -15524,10 +15492,15 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       i915_reg_t reg = PIPECONF(crtc->config->cpu_transcoder);
+       enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
 
        /* Clear any frame start delays used for debugging left by the BIOS */
-       I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+       if (!transcoder_is_dsi(cpu_transcoder)) {
+               i915_reg_t reg = PIPECONF(cpu_transcoder);
+
+               I915_WRITE(reg,
+                          I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+       }
 
        /* restore vblank interrupts to correct state */
        drm_crtc_vblank_reset(&crtc->base);
@@ -15575,38 +15548,9 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 
        /* Adjust the state of the output pipe according to whether we
         * have active connectors/encoders. */
-       if (!intel_crtc_has_encoders(crtc))
+       if (crtc->active && !intel_crtc_has_encoders(crtc))
                intel_crtc_disable_noatomic(&crtc->base);
 
-       if (crtc->active != crtc->base.state->active) {
-               struct intel_encoder *encoder;
-
-               /* This can happen either due to bugs in the get_hw_state
-                * functions or because of calls to intel_crtc_disable_noatomic,
-                * or because the pipe is force-enabled due to the
-                * pipe A quirk. */
-               DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
-                             crtc->base.base.id,
-                             crtc->base.state->enable ? "enabled" : "disabled",
-                             crtc->active ? "enabled" : "disabled");
-
-               WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, NULL) < 0);
-               crtc->base.state->active = crtc->active;
-               crtc->base.enabled = crtc->active;
-               crtc->base.state->connector_mask = 0;
-               crtc->base.state->encoder_mask = 0;
-
-               /* Because we only establish the connector -> encoder ->
-                * crtc links if something is active, this means the
-                * crtc is now deactivated. Break the links. connector
-                * -> encoder links are only establish when things are
-                *  actually up, hence no need to break them. */
-               WARN_ON(crtc->active);
-
-               for_each_encoder_on_crtc(dev, &crtc->base, encoder)
-                       encoder->base.crtc = NULL;
-       }
-
        if (crtc->active || HAS_GMCH_DISPLAY(dev)) {
                /*
                 * We start out with underrun reporting disabled to avoid races.
@@ -15775,22 +15719,17 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
        for (i = 0; i < dev_priv->num_shared_dpll; i++) {
                struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
 
-               pll->on = pll->get_hw_state(dev_priv, pll,
-                                           &pll->config.hw_state);
-               pll->active = 0;
+               pll->on = pll->funcs.get_hw_state(dev_priv, pll,
+                                                 &pll->config.hw_state);
                pll->config.crtc_mask = 0;
                for_each_intel_crtc(dev, crtc) {
-                       if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) {
-                               pll->active++;
+                       if (crtc->active && crtc->config->shared_dpll == pll)
                                pll->config.crtc_mask |= 1 << crtc->pipe;
-                       }
                }
+               pll->active_mask = pll->config.crtc_mask;
 
                DRM_DEBUG_KMS("%s hw state readout: crtc_mask 0x%08x, on %i\n",
                              pll->name, pll->config.crtc_mask, pll->on);
-
-               if (pll->config.crtc_mask)
-                       intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
        }
 
        for_each_intel_encoder(dev, encoder) {
@@ -15872,6 +15811,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                        drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
                        update_scanline_offset(crtc);
                }
+
+               intel_pipe_config_sanity_check(dev_priv, crtc->config);
        }
 }
 
@@ -15906,12 +15847,12 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
        for (i = 0; i < dev_priv->num_shared_dpll; i++) {
                struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
 
-               if (!pll->on || pll->active)
+               if (!pll->on || pll->active_mask)
                        continue;
 
                DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name);
 
-               pll->disable(dev_priv, pll);
+               pll->funcs.disable(dev_priv, pll);
                pll->on = false;
        }
 
@@ -16020,9 +15961,8 @@ void intel_modeset_gem_init(struct drm_device *dev)
                        continue;
 
                mutex_lock(&dev->struct_mutex);
-               ret = intel_pin_and_fence_fb_obj(c->primary,
-                                                c->primary->fb,
-                                                c->primary->state);
+               ret = intel_pin_and_fence_fb_obj(c->primary->fb,
+                                                c->primary->state->rotation);
                mutex_unlock(&dev->struct_mutex);
                if (ret) {
                        DRM_ERROR("failed to pin boot fb on pipe %d\n",
@@ -16231,6 +16171,7 @@ intel_display_capture_error_state(struct drm_device *dev)
                        error->pipe[i].stat = I915_READ(PIPESTAT(i));
        }
 
+       /* Note: this does not include DSI transcoders. */
        error->num_transcoders = INTEL_INFO(dev)->num_pipes;
        if (HAS_DDI(dev_priv->dev))
                error->num_transcoders++; /* Account for eDP. */
@@ -16303,7 +16244,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
        }
 
        for (i = 0; i < error->num_transcoders; i++) {
-               err_printf(m, "CPU transcoder: %c\n",
+               err_printf(m, "CPU transcoder: %s\n",
                           transcoder_name(error->transcoder[i].cpu_transcoder));
                err_printf(m, "  Power: %s\n",
                           onoff(error->transcoder[i].power_domain_on));
index f069a82..3bdd8ba 100644 (file)
@@ -671,60 +671,55 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
        return status;
 }
 
-static uint32_t i9xx_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       struct drm_device *dev = intel_dig_port->base.base.dev;
+       struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
+
+       if (index)
+               return 0;
 
        /*
         * The clock divider is based off the hrawclk, and would like to run at
-        * 2MHz.  So, take the hrawclk value and divide by 2 and use that
+        * 2MHz.  So, take the hrawclk value and divide by 2000 and use that
         */
-       return index ? 0 : DIV_ROUND_CLOSEST(intel_hrawclk(dev), 2);
+       return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
 }
 
 static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       struct drm_device *dev = intel_dig_port->base.base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 
        if (index)
                return 0;
 
-       if (intel_dig_port->port == PORT_A) {
+       /*
+        * The clock divider is based off the cdclk or PCH rawclk, and would
+        * like to run at 2MHz.  So, take the cdclk or PCH rawclk value and
+        * divide by 2000 and use that
+        */
+       if (intel_dig_port->port == PORT_A)
                return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
-
-       } else {
-               return DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2);
-       }
+       else
+               return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
 }
 
 static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       struct drm_device *dev = intel_dig_port->base.base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 
-       if (intel_dig_port->port == PORT_A) {
-               if (index)
-                       return 0;
-               return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
-       } else if (HAS_PCH_LPT_H(dev_priv)) {
+       if (intel_dig_port->port != PORT_A && HAS_PCH_LPT_H(dev_priv)) {
                /* Workaround for non-ULT HSW */
                switch (index) {
                case 0: return 63;
                case 1: return 72;
                default: return 0;
                }
-       } else  {
-               return index ? 0 : DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2);
        }
-}
 
-static uint32_t vlv_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
-{
-       return index ? 0 : 100;
+       return ilk_get_aux_clock_divider(intel_dp, index);
 }
 
 static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
@@ -737,10 +732,10 @@ static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
        return index ? 0 : 1;
 }
 
-static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp,
-                                     bool has_aux_irq,
-                                     int send_bytes,
-                                     uint32_t aux_clock_divider)
+static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
+                                    bool has_aux_irq,
+                                    int send_bytes,
+                                    uint32_t aux_clock_divider)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_device *dev = intel_dig_port->base.base.dev;
@@ -1229,71 +1224,6 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector)
        intel_connector_unregister(intel_connector);
 }
 
-static void
-skl_edp_set_pll_config(struct intel_crtc_state *pipe_config)
-{
-       u32 ctrl1;
-
-       memset(&pipe_config->dpll_hw_state, 0,
-              sizeof(pipe_config->dpll_hw_state));
-
-       pipe_config->ddi_pll_sel = SKL_DPLL0;
-       pipe_config->dpll_hw_state.cfgcr1 = 0;
-       pipe_config->dpll_hw_state.cfgcr2 = 0;
-
-       ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
-       switch (pipe_config->port_clock / 2) {
-       case 81000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
-                                             SKL_DPLL0);
-               break;
-       case 135000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350,
-                                             SKL_DPLL0);
-               break;
-       case 270000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700,
-                                             SKL_DPLL0);
-               break;
-       case 162000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620,
-                                             SKL_DPLL0);
-               break;
-       /* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which
-       results in CDCLK change. Need to handle the change of CDCLK by
-       disabling pipes and re-enabling them */
-       case 108000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
-                                             SKL_DPLL0);
-               break;
-       case 216000:
-               ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160,
-                                             SKL_DPLL0);
-               break;
-
-       }
-       pipe_config->dpll_hw_state.ctrl1 = ctrl1;
-}
-
-void
-hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config)
-{
-       memset(&pipe_config->dpll_hw_state, 0,
-              sizeof(pipe_config->dpll_hw_state));
-
-       switch (pipe_config->port_clock / 2) {
-       case 81000:
-               pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
-               break;
-       case 135000:
-               pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
-               break;
-       case 270000:
-               pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
-               break;
-       }
-}
-
 static int
 intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
 {
@@ -1570,10 +1500,10 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
                /* Get bpp from vbt only for panels that dont have bpp in edid */
                if (intel_connector->base.display_info.bpc == 0 &&
-                       (dev_priv->vbt.edp_bpp && dev_priv->vbt.edp_bpp < bpp)) {
+                       (dev_priv->vbt.edp.bpp && dev_priv->vbt.edp.bpp < bpp)) {
                        DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n",
-                                     dev_priv->vbt.edp_bpp);
-                       bpp = dev_priv->vbt.edp_bpp;
+                                     dev_priv->vbt.edp.bpp);
+                       bpp = dev_priv->vbt.edp.bpp;
                }
 
                /*
@@ -1651,13 +1581,7 @@ found:
                                &pipe_config->dp_m2_n2);
        }
 
-       if ((IS_SKYLAKE(dev)  || IS_KABYLAKE(dev)) && is_edp(intel_dp))
-               skl_edp_set_pll_config(pipe_config);
-       else if (IS_BROXTON(dev))
-               /* handled in ddi */;
-       else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               hsw_dp_set_ddi_pll_sel(pipe_config);
-       else
+       if (!HAS_DDI(dev))
                intel_dp_set_clock(encoder, pipe_config);
 
        return true;
@@ -1779,11 +1703,11 @@ static void wait_panel_status(struct intel_dp *intel_dp,
                        I915_READ(pp_stat_reg),
                        I915_READ(pp_ctrl_reg));
 
-       if (_wait_for((I915_READ(pp_stat_reg) & mask) == value, 5000, 10)) {
+       if (_wait_for((I915_READ(pp_stat_reg) & mask) == value,
+                     5 * USEC_PER_SEC, 10 * USEC_PER_MSEC))
                DRM_ERROR("Panel status timeout: status %08x control %08x\n",
                                I915_READ(pp_stat_reg),
                                I915_READ(pp_ctrl_reg));
-       }
 
        DRM_DEBUG_KMS("Wait complete\n");
 }
@@ -2409,7 +2333,6 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum port port = dp_to_dig_port(intel_dp)->port;
        struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
-       int dotclock;
 
        tmp = I915_READ(intel_dp->output_reg);
 
@@ -2459,16 +2382,12 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
                        pipe_config->port_clock = 270000;
        }
 
-       dotclock = intel_dotclock_calculate(pipe_config->port_clock,
-                                           &pipe_config->dp_m_n);
+       pipe_config->base.adjusted_mode.crtc_clock =
+               intel_dotclock_calculate(pipe_config->port_clock,
+                                        &pipe_config->dp_m_n);
 
-       if (HAS_PCH_SPLIT(dev_priv->dev) && port != PORT_A)
-               ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
-       pipe_config->base.adjusted_mode.crtc_clock = dotclock;
-
-       if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp &&
-           pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
+       if (is_edp(intel_dp) && dev_priv->vbt.edp.bpp &&
+           pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) {
                /*
                 * This is a big fat ugly hack.
                 *
@@ -2483,8 +2402,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
                 * load.
                 */
                DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n",
-                             pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp);
-               dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
+                             pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp);
+               dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp;
        }
 }
 
@@ -3238,7 +3157,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
        if (IS_BROXTON(dev))
                return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
        else if (INTEL_INFO(dev)->gen >= 9) {
-               if (dev_priv->edp_low_vswing && port == PORT_A)
+               if (dev_priv->vbt.edp.low_vswing && port == PORT_A)
                        return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
                return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
        } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
@@ -3963,6 +3882,9 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
 {
        u8 buf[1];
 
+       if (!i915.enable_dp_mst)
+               return false;
+
        if (!intel_dp->can_mst)
                return false;
 
@@ -5071,14 +4993,6 @@ put_power:
 bool intel_dp_is_edp(struct drm_device *dev, enum port port)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       union child_device_config *p_child;
-       int i;
-       static const short port_mapping[] = {
-               [PORT_B] = DVO_PORT_DPB,
-               [PORT_C] = DVO_PORT_DPC,
-               [PORT_D] = DVO_PORT_DPD,
-               [PORT_E] = DVO_PORT_DPE,
-       };
 
        /*
         * eDP not supported on g4x. so bail out early just
@@ -5090,18 +5004,7 @@ bool intel_dp_is_edp(struct drm_device *dev, enum port port)
        if (port == PORT_A)
                return true;
 
-       if (!dev_priv->vbt.child_dev_num)
-               return false;
-
-       for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
-               p_child = dev_priv->vbt.child_dev + i;
-
-               if (p_child->common.dvo_port == port_mapping[port] &&
-                   (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) ==
-                   (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS))
-                       return true;
-       }
-       return false;
+       return intel_bios_is_port_edp(dev_priv, port);
 }
 
 void
@@ -5208,7 +5111,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
        DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
                      cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
 
-       vbt = dev_priv->vbt.edp_pps;
+       vbt = dev_priv->vbt.edp.pps;
 
        /* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
         * our hw here, which are all in 100usec. */
@@ -5259,7 +5162,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 pp_on, pp_off, pp_div, port_sel = 0;
-       int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
+       int div = dev_priv->rawclk_freq / 1000;
        i915_reg_t pp_on_reg, pp_off_reg, pp_div_reg, pp_ctrl_reg;
        enum port port = dp_to_dig_port(intel_dp)->port;
        const struct edp_power_seq *seq = &intel_dp->pps_delays;
@@ -5852,19 +5755,17 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        /* intel_dp vfuncs */
        if (INTEL_INFO(dev)->gen >= 9)
                intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
-       else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
-               intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
        else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
        else if (HAS_PCH_SPLIT(dev))
                intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
        else
-               intel_dp->get_aux_clock_divider = i9xx_get_aux_clock_divider;
+               intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
 
        if (INTEL_INFO(dev)->gen >= 9)
                intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
        else
-               intel_dp->get_aux_send_ctl = i9xx_get_aux_send_ctl;
+               intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
 
        if (HAS_DDI(dev))
                intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain;
index a2bd698..94b4e83 100644 (file)
@@ -33,7 +33,6 @@
 static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
                                        struct intel_crtc_state *pipe_config)
 {
-       struct drm_device *dev = encoder->base.dev;
        struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
        struct intel_digital_port *intel_dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &intel_dig_port->dp;
@@ -92,9 +91,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
 
        pipe_config->dp_m_n.tu = slots;
 
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               hsw_dp_set_ddi_pll_sel(pipe_config);
-
        return true;
 
 }
@@ -506,6 +502,8 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct drm_device *dev = connector->dev;
 
+       intel_connector->unregister(intel_connector);
+
        /* need to nuke the connector */
        drm_modeset_lock_all(dev);
        if (connector->state->crtc) {
@@ -519,11 +517,7 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
 
                WARN(ret, "Disabling mst crtc failed with %i\n", ret);
        }
-       drm_modeset_unlock_all(dev);
-
-       intel_connector->unregister(intel_connector);
 
-       drm_modeset_lock_all(dev);
        intel_connector_remove_from_fbdev(intel_connector);
        drm_connector_cleanup(connector);
        drm_modeset_unlock_all(dev);
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
new file mode 100644 (file)
index 0000000..19bfe67
--- /dev/null
@@ -0,0 +1,1773 @@
+/*
+ * Copyright © 2006-2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "intel_drv.h"
+
+struct intel_shared_dpll *
+intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
+                           enum intel_dpll_id id)
+{
+       return &dev_priv->shared_dplls[id];
+}
+
+enum intel_dpll_id
+intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
+                        struct intel_shared_dpll *pll)
+{
+       if (WARN_ON(pll < dev_priv->shared_dplls||
+                   pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll]))
+               return -1;
+
+       return (enum intel_dpll_id) (pll - dev_priv->shared_dplls);
+}
+
+void
+intel_shared_dpll_config_get(struct intel_shared_dpll_config *config,
+                            struct intel_shared_dpll *pll,
+                            struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
+
+       config[id].crtc_mask |= 1 << crtc->pipe;
+}
+
+void
+intel_shared_dpll_config_put(struct intel_shared_dpll_config *config,
+                            struct intel_shared_dpll *pll,
+                            struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
+
+       config[id].crtc_mask &= ~(1 << crtc->pipe);
+}
+
+/* For ILK+ */
+void assert_shared_dpll(struct drm_i915_private *dev_priv,
+                       struct intel_shared_dpll *pll,
+                       bool state)
+{
+       bool cur_state;
+       struct intel_dpll_hw_state hw_state;
+
+       if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
+               return;
+
+       cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
+       I915_STATE_WARN(cur_state != state,
+            "%s assertion failure (expected %s, current %s)\n",
+                       pll->name, onoff(state), onoff(cur_state));
+}
+
+void intel_prepare_shared_dpll(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_shared_dpll *pll = crtc->config->shared_dpll;
+
+       if (WARN_ON(pll == NULL))
+               return;
+
+       WARN_ON(!pll->config.crtc_mask);
+       if (pll->active_mask == 0) {
+               DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
+               WARN_ON(pll->on);
+               assert_shared_dpll_disabled(dev_priv, pll);
+
+               pll->funcs.mode_set(dev_priv, pll);
+       }
+}
+
+/**
+ * intel_enable_shared_dpll - enable PCH PLL
+ * @dev_priv: i915 private structure
+ * @pipe: pipe PLL to enable
+ *
+ * The PCH PLL needs to be enabled before the PCH transcoder, since it
+ * drives the transcoder clock.
+ */
+void intel_enable_shared_dpll(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_shared_dpll *pll = crtc->config->shared_dpll;
+       unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
+       unsigned old_mask = pll->active_mask;
+
+       if (WARN_ON(pll == NULL))
+               return;
+
+       if (WARN_ON(!(pll->config.crtc_mask & crtc_mask)) ||
+           WARN_ON(pll->active_mask & crtc_mask))
+               return;
+
+       pll->active_mask |= crtc_mask;
+
+       DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n",
+                     pll->name, pll->active_mask, pll->on,
+                     crtc->base.base.id);
+
+       if (old_mask) {
+               WARN_ON(!pll->on);
+               assert_shared_dpll_enabled(dev_priv, pll);
+               return;
+       }
+       WARN_ON(pll->on);
+
+       DRM_DEBUG_KMS("enabling %s\n", pll->name);
+       pll->funcs.enable(dev_priv, pll);
+       pll->on = true;
+}
+
+void intel_disable_shared_dpll(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_shared_dpll *pll = crtc->config->shared_dpll;
+       unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
+
+       /* PCH only available on ILK+ */
+       if (INTEL_INFO(dev)->gen < 5)
+               return;
+
+       if (pll == NULL)
+               return;
+
+       if (WARN_ON(!(pll->active_mask & crtc_mask)))
+               return;
+
+       DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
+                     pll->name, pll->active_mask, pll->on,
+                     crtc->base.base.id);
+
+       assert_shared_dpll_enabled(dev_priv, pll);
+       WARN_ON(!pll->on);
+
+       pll->active_mask &= ~crtc_mask;
+       if (pll->active_mask)
+               return;
+
+       DRM_DEBUG_KMS("disabling %s\n", pll->name);
+       pll->funcs.disable(dev_priv, pll);
+       pll->on = false;
+}
+
+static struct intel_shared_dpll *
+intel_find_shared_dpll(struct intel_crtc *crtc,
+                      struct intel_crtc_state *crtc_state,
+                      enum intel_dpll_id range_min,
+                      enum intel_dpll_id range_max)
+{
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct intel_shared_dpll *pll;
+       struct intel_shared_dpll_config *shared_dpll;
+       enum intel_dpll_id i;
+
+       shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
+
+       for (i = range_min; i <= range_max; i++) {
+               pll = &dev_priv->shared_dplls[i];
+
+               /* Only want to check enabled timings first */
+               if (shared_dpll[i].crtc_mask == 0)
+                       continue;
+
+               if (memcmp(&crtc_state->dpll_hw_state,
+                          &shared_dpll[i].hw_state,
+                          sizeof(crtc_state->dpll_hw_state)) == 0) {
+                       DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, active %x)\n",
+                                     crtc->base.base.id, pll->name,
+                                     shared_dpll[i].crtc_mask,
+                                     pll->active_mask);
+                       return pll;
+               }
+       }
+
+       /* Ok no matching timings, maybe there's a free one? */
+       for (i = range_min; i <= range_max; i++) {
+               pll = &dev_priv->shared_dplls[i];
+               if (shared_dpll[i].crtc_mask == 0) {
+                       DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
+                                     crtc->base.base.id, pll->name);
+                       return pll;
+               }
+       }
+
+       return NULL;
+}
+
+static void
+intel_reference_shared_dpll(struct intel_shared_dpll *pll,
+                           struct intel_crtc_state *crtc_state)
+{
+       struct intel_shared_dpll_config *shared_dpll;
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       enum intel_dpll_id i = pll->id;
+
+       shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
+
+       if (shared_dpll[i].crtc_mask == 0)
+               shared_dpll[i].hw_state =
+                       crtc_state->dpll_hw_state;
+
+       crtc_state->shared_dpll = pll;
+       DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
+                        pipe_name(crtc->pipe));
+
+       intel_shared_dpll_config_get(shared_dpll, pll, crtc);
+}
+
+void intel_shared_dpll_commit(struct drm_atomic_state *state)
+{
+       struct drm_i915_private *dev_priv = to_i915(state->dev);
+       struct intel_shared_dpll_config *shared_dpll;
+       struct intel_shared_dpll *pll;
+       enum intel_dpll_id i;
+
+       if (!to_intel_atomic_state(state)->dpll_set)
+               return;
+
+       shared_dpll = to_intel_atomic_state(state)->shared_dpll;
+       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+               pll = &dev_priv->shared_dplls[i];
+               pll->config = shared_dpll[i];
+       }
+}
+
+static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
+                                     struct intel_shared_dpll *pll,
+                                     struct intel_dpll_hw_state *hw_state)
+{
+       uint32_t val;
+
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+               return false;
+
+       val = I915_READ(PCH_DPLL(pll->id));
+       hw_state->dpll = val;
+       hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
+       hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
+
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return val & DPLL_VCO_ENABLE;
+}
+
+static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
+                                 struct intel_shared_dpll *pll)
+{
+       I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
+       I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
+}
+
+static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
+{
+       u32 val;
+       bool enabled;
+
+       I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev)));
+
+       val = I915_READ(PCH_DREF_CONTROL);
+       enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
+                           DREF_SUPERSPREAD_SOURCE_MASK));
+       I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
+}
+
+static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
+                               struct intel_shared_dpll *pll)
+{
+       /* PCH refclock must be enabled first */
+       ibx_assert_pch_refclk_enabled(dev_priv);
+
+       I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
+
+       /* Wait for the clocks to stabilize. */
+       POSTING_READ(PCH_DPLL(pll->id));
+       udelay(150);
+
+       /* The pixel multiplier can only be updated once the
+        * DPLL is enabled and the clocks are stable.
+        *
+        * So write it again.
+        */
+       I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
+       POSTING_READ(PCH_DPLL(pll->id));
+       udelay(200);
+}
+
+static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
+                                struct intel_shared_dpll *pll)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct intel_crtc *crtc;
+
+       /* Make sure no transcoder isn't still depending on us. */
+       for_each_intel_crtc(dev, crtc) {
+               if (crtc->config->shared_dpll == pll)
+                       assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
+       }
+
+       I915_WRITE(PCH_DPLL(pll->id), 0);
+       POSTING_READ(PCH_DPLL(pll->id));
+       udelay(200);
+}
+
+static struct intel_shared_dpll *
+ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+            struct intel_encoder *encoder)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       struct intel_shared_dpll *pll;
+       enum intel_dpll_id i;
+
+       if (HAS_PCH_IBX(dev_priv)) {
+               /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
+               i = (enum intel_dpll_id) crtc->pipe;
+               pll = &dev_priv->shared_dplls[i];
+
+               DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
+                             crtc->base.base.id, pll->name);
+       } else {
+               pll = intel_find_shared_dpll(crtc, crtc_state,
+                                            DPLL_ID_PCH_PLL_A,
+                                            DPLL_ID_PCH_PLL_B);
+       }
+
+       /* reference the pll */
+       intel_reference_shared_dpll(pll, crtc_state);
+
+       return pll;
+}
+
+static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
+       .mode_set = ibx_pch_dpll_mode_set,
+       .enable = ibx_pch_dpll_enable,
+       .disable = ibx_pch_dpll_disable,
+       .get_hw_state = ibx_pch_dpll_get_hw_state,
+};
+
+static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
+                              struct intel_shared_dpll *pll)
+{
+       I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
+       POSTING_READ(WRPLL_CTL(pll->id));
+       udelay(20);
+}
+
+static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
+                               struct intel_shared_dpll *pll)
+{
+       I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
+       POSTING_READ(SPLL_CTL);
+       udelay(20);
+}
+
+static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
+                                 struct intel_shared_dpll *pll)
+{
+       uint32_t val;
+
+       val = I915_READ(WRPLL_CTL(pll->id));
+       I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
+       POSTING_READ(WRPLL_CTL(pll->id));
+}
+
+static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
+                                struct intel_shared_dpll *pll)
+{
+       uint32_t val;
+
+       val = I915_READ(SPLL_CTL);
+       I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
+       POSTING_READ(SPLL_CTL);
+}
+
+static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
+                                      struct intel_shared_dpll *pll,
+                                      struct intel_dpll_hw_state *hw_state)
+{
+       uint32_t val;
+
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+               return false;
+
+       val = I915_READ(WRPLL_CTL(pll->id));
+       hw_state->wrpll = val;
+
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return val & WRPLL_PLL_ENABLE;
+}
+
+static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
+                                     struct intel_shared_dpll *pll,
+                                     struct intel_dpll_hw_state *hw_state)
+{
+       uint32_t val;
+
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+               return false;
+
+       val = I915_READ(SPLL_CTL);
+       hw_state->spll = val;
+
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return val & SPLL_PLL_ENABLE;
+}
+
+static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll)
+{
+       switch (pll->id) {
+       case DPLL_ID_WRPLL1:
+               return PORT_CLK_SEL_WRPLL1;
+       case DPLL_ID_WRPLL2:
+               return PORT_CLK_SEL_WRPLL2;
+       case DPLL_ID_SPLL:
+               return PORT_CLK_SEL_SPLL;
+       case DPLL_ID_LCPLL_810:
+               return PORT_CLK_SEL_LCPLL_810;
+       case DPLL_ID_LCPLL_1350:
+               return PORT_CLK_SEL_LCPLL_1350;
+       case DPLL_ID_LCPLL_2700:
+               return PORT_CLK_SEL_LCPLL_2700;
+       default:
+               return PORT_CLK_SEL_NONE;
+       }
+}
+
+#define LC_FREQ 2700
+#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
+
+#define P_MIN 2
+#define P_MAX 64
+#define P_INC 2
+
+/* Constraints for PLL good behavior */
+#define REF_MIN 48
+#define REF_MAX 400
+#define VCO_MIN 2400
+#define VCO_MAX 4800
+
+struct hsw_wrpll_rnp {
+       unsigned p, n2, r2;
+};
+
+static unsigned hsw_wrpll_get_budget_for_freq(int clock)
+{
+       unsigned budget;
+
+       switch (clock) {
+       case 25175000:
+       case 25200000:
+       case 27000000:
+       case 27027000:
+       case 37762500:
+       case 37800000:
+       case 40500000:
+       case 40541000:
+       case 54000000:
+       case 54054000:
+       case 59341000:
+       case 59400000:
+       case 72000000:
+       case 74176000:
+       case 74250000:
+       case 81000000:
+       case 81081000:
+       case 89012000:
+       case 89100000:
+       case 108000000:
+       case 108108000:
+       case 111264000:
+       case 111375000:
+       case 148352000:
+       case 148500000:
+       case 162000000:
+       case 162162000:
+       case 222525000:
+       case 222750000:
+       case 296703000:
+       case 297000000:
+               budget = 0;
+               break;
+       case 233500000:
+       case 245250000:
+       case 247750000:
+       case 253250000:
+       case 298000000:
+               budget = 1500;
+               break;
+       case 169128000:
+       case 169500000:
+       case 179500000:
+       case 202000000:
+               budget = 2000;
+               break;
+       case 256250000:
+       case 262500000:
+       case 270000000:
+       case 272500000:
+       case 273750000:
+       case 280750000:
+       case 281250000:
+       case 286000000:
+       case 291750000:
+               budget = 4000;
+               break;
+       case 267250000:
+       case 268500000:
+               budget = 5000;
+               break;
+       default:
+               budget = 1000;
+               break;
+       }
+
+       return budget;
+}
+
+static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
+                                unsigned r2, unsigned n2, unsigned p,
+                                struct hsw_wrpll_rnp *best)
+{
+       uint64_t a, b, c, d, diff, diff_best;
+
+       /* No best (r,n,p) yet */
+       if (best->p == 0) {
+               best->p = p;
+               best->n2 = n2;
+               best->r2 = r2;
+               return;
+       }
+
+       /*
+        * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
+        * freq2k.
+        *
+        * delta = 1e6 *
+        *         abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
+        *         freq2k;
+        *
+        * and we would like delta <= budget.
+        *
+        * If the discrepancy is above the PPM-based budget, always prefer to
+        * improve upon the previous solution.  However, if you're within the
+        * budget, try to maximize Ref * VCO, that is N / (P * R^2).
+        */
+       a = freq2k * budget * p * r2;
+       b = freq2k * budget * best->p * best->r2;
+       diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
+       diff_best = abs_diff(freq2k * best->p * best->r2,
+                            LC_FREQ_2K * best->n2);
+       c = 1000000 * diff;
+       d = 1000000 * diff_best;
+
+       if (a < c && b < d) {
+               /* If both are above the budget, pick the closer */
+               if (best->p * best->r2 * diff < p * r2 * diff_best) {
+                       best->p = p;
+                       best->n2 = n2;
+                       best->r2 = r2;
+               }
+       } else if (a >= c && b < d) {
+               /* If A is below the threshold but B is above it?  Update. */
+               best->p = p;
+               best->n2 = n2;
+               best->r2 = r2;
+       } else if (a >= c && b >= d) {
+               /* Both are below the limit, so pick the higher n2/(r2*r2) */
+               if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
+                       best->p = p;
+                       best->n2 = n2;
+                       best->r2 = r2;
+               }
+       }
+       /* Otherwise a < c && b >= d, do nothing */
+}
+
+static void
+hsw_ddi_calculate_wrpll(int clock /* in Hz */,
+                       unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
+{
+       uint64_t freq2k;
+       unsigned p, n2, r2;
+       struct hsw_wrpll_rnp best = { 0, 0, 0 };
+       unsigned budget;
+
+       freq2k = clock / 100;
+
+       budget = hsw_wrpll_get_budget_for_freq(clock);
+
+       /* Special case handling for 540 pixel clock: bypass WR PLL entirely
+        * and directly pass the LC PLL to it. */
+       if (freq2k == 5400000) {
+               *n2_out = 2;
+               *p_out = 1;
+               *r2_out = 2;
+               return;
+       }
+
+       /*
+        * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
+        * the WR PLL.
+        *
+        * We want R so that REF_MIN <= Ref <= REF_MAX.
+        * Injecting R2 = 2 * R gives:
+        *   REF_MAX * r2 > LC_FREQ * 2 and
+        *   REF_MIN * r2 < LC_FREQ * 2
+        *
+        * Which means the desired boundaries for r2 are:
+        *  LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
+        *
+        */
+       for (r2 = LC_FREQ * 2 / REF_MAX + 1;
+            r2 <= LC_FREQ * 2 / REF_MIN;
+            r2++) {
+
+               /*
+                * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
+                *
+                * Once again we want VCO_MIN <= VCO <= VCO_MAX.
+                * Injecting R2 = 2 * R and N2 = 2 * N, we get:
+                *   VCO_MAX * r2 > n2 * LC_FREQ and
+                *   VCO_MIN * r2 < n2 * LC_FREQ)
+                *
+                * Which means the desired boundaries for n2 are:
+                * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
+                */
+               for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
+                    n2 <= VCO_MAX * r2 / LC_FREQ;
+                    n2++) {
+
+                       for (p = P_MIN; p <= P_MAX; p += P_INC)
+                               hsw_wrpll_update_rnp(freq2k, budget,
+                                                    r2, n2, p, &best);
+               }
+       }
+
+       *n2_out = best.n2;
+       *p_out = best.p;
+       *r2_out = best.r2;
+}
+
+static struct intel_shared_dpll *
+hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+            struct intel_encoder *encoder)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       struct intel_shared_dpll *pll;
+       int clock = crtc_state->port_clock;
+
+       memset(&crtc_state->dpll_hw_state, 0,
+              sizeof(crtc_state->dpll_hw_state));
+
+       if (encoder->type == INTEL_OUTPUT_HDMI) {
+               uint32_t val;
+               unsigned p, n2, r2;
+
+               hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
+
+               val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
+                     WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
+                     WRPLL_DIVIDER_POST(p);
+
+               crtc_state->dpll_hw_state.wrpll = val;
+
+               pll = intel_find_shared_dpll(crtc, crtc_state,
+                                            DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
+
+       } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+                  encoder->type == INTEL_OUTPUT_DP_MST ||
+                  encoder->type == INTEL_OUTPUT_EDP) {
+               enum intel_dpll_id pll_id;
+
+               switch (clock / 2) {
+               case 81000:
+                       pll_id = DPLL_ID_LCPLL_810;
+                       break;
+               case 135000:
+                       pll_id = DPLL_ID_LCPLL_1350;
+                       break;
+               case 270000:
+                       pll_id = DPLL_ID_LCPLL_2700;
+                       break;
+               default:
+                       DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
+                       return NULL;
+               }
+
+               pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
+
+       } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
+               if (WARN_ON(crtc_state->port_clock / 2 != 135000))
+                       return NULL;
+
+               crtc_state->dpll_hw_state.spll =
+                       SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
+
+               pll = intel_find_shared_dpll(crtc, crtc_state,
+                                            DPLL_ID_SPLL, DPLL_ID_SPLL);
+       } else {
+               return NULL;
+       }
+
+       if (!pll)
+               return NULL;
+
+       crtc_state->ddi_pll_sel = hsw_pll_to_ddi_pll_sel(pll);
+
+       intel_reference_shared_dpll(pll, crtc_state);
+
+       return pll;
+}
+
+
+static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
+       .enable = hsw_ddi_wrpll_enable,
+       .disable = hsw_ddi_wrpll_disable,
+       .get_hw_state = hsw_ddi_wrpll_get_hw_state,
+};
+
+static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
+       .enable = hsw_ddi_spll_enable,
+       .disable = hsw_ddi_spll_disable,
+       .get_hw_state = hsw_ddi_spll_get_hw_state,
+};
+
+static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
+                                struct intel_shared_dpll *pll)
+{
+}
+
+static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
+                                 struct intel_shared_dpll *pll)
+{
+}
+
+static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
+                                      struct intel_shared_dpll *pll,
+                                      struct intel_dpll_hw_state *hw_state)
+{
+       return true;
+}
+
+static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
+       .enable = hsw_ddi_lcpll_enable,
+       .disable = hsw_ddi_lcpll_disable,
+       .get_hw_state = hsw_ddi_lcpll_get_hw_state,
+};
+
+struct skl_dpll_regs {
+       i915_reg_t ctl, cfgcr1, cfgcr2;
+};
+
+/* this array is indexed by the *shared* pll id */
+static const struct skl_dpll_regs skl_dpll_regs[4] = {
+       {
+               /* DPLL 0 */
+               .ctl = LCPLL1_CTL,
+               /* DPLL 0 doesn't support HDMI mode */
+       },
+       {
+               /* DPLL 1 */
+               .ctl = LCPLL2_CTL,
+               .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
+               .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
+       },
+       {
+               /* DPLL 2 */
+               .ctl = WRPLL_CTL(0),
+               .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
+               .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
+       },
+       {
+               /* DPLL 3 */
+               .ctl = WRPLL_CTL(1),
+               .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
+               .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
+       },
+};
+
+static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
+                                   struct intel_shared_dpll *pll)
+{
+       uint32_t val;
+
+       val = I915_READ(DPLL_CTRL1);
+
+       val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
+                DPLL_CTRL1_LINK_RATE_MASK(pll->id));
+       val |= pll->config.hw_state.ctrl1 << (pll->id * 6);
+
+       I915_WRITE(DPLL_CTRL1, val);
+       POSTING_READ(DPLL_CTRL1);
+}
+
+static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
+                              struct intel_shared_dpll *pll)
+{
+       const struct skl_dpll_regs *regs = skl_dpll_regs;
+
+       skl_ddi_pll_write_ctrl1(dev_priv, pll);
+
+       I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
+       I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
+       POSTING_READ(regs[pll->id].cfgcr1);
+       POSTING_READ(regs[pll->id].cfgcr2);
+
+       /* the enable bit is always bit 31 */
+       I915_WRITE(regs[pll->id].ctl,
+                  I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
+
+       if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(pll->id), 5))
+               DRM_ERROR("DPLL %d not locked\n", pll->id);
+}
+
+static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
+                                struct intel_shared_dpll *pll)
+{
+       skl_ddi_pll_write_ctrl1(dev_priv, pll);
+}
+
+static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
+                               struct intel_shared_dpll *pll)
+{
+       const struct skl_dpll_regs *regs = skl_dpll_regs;
+
+       /* the enable bit is always bit 31 */
+       I915_WRITE(regs[pll->id].ctl,
+                  I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
+       POSTING_READ(regs[pll->id].ctl);
+}
+
+static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
+                                 struct intel_shared_dpll *pll)
+{
+}
+
+static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
+                                    struct intel_shared_dpll *pll,
+                                    struct intel_dpll_hw_state *hw_state)
+{
+       uint32_t val;
+       const struct skl_dpll_regs *regs = skl_dpll_regs;
+       bool ret;
+
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+               return false;
+
+       ret = false;
+
+       val = I915_READ(regs[pll->id].ctl);
+       if (!(val & LCPLL_PLL_ENABLE))
+               goto out;
+
+       val = I915_READ(DPLL_CTRL1);
+       hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
+
+       /* avoid reading back stale values if HDMI mode is not enabled */
+       if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
+               hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
+               hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
+       }
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return ret;
+}
+
+static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
+                                      struct intel_shared_dpll *pll,
+                                      struct intel_dpll_hw_state *hw_state)
+{
+       uint32_t val;
+       const struct skl_dpll_regs *regs = skl_dpll_regs;
+       bool ret;
+
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+               return false;
+
+       ret = false;
+
+       /* DPLL0 is always enabled since it drives CDCLK */
+       val = I915_READ(regs[pll->id].ctl);
+       if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
+               goto out;
+
+       val = I915_READ(DPLL_CTRL1);
+       hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
+
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return ret;
+}
+
+struct skl_wrpll_context {
+       uint64_t min_deviation;         /* current minimal deviation */
+       uint64_t central_freq;          /* chosen central freq */
+       uint64_t dco_freq;              /* chosen dco freq */
+       unsigned int p;                 /* chosen divider */
+};
+
+static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
+{
+       memset(ctx, 0, sizeof(*ctx));
+
+       ctx->min_deviation = U64_MAX;
+}
+
+/* DCO freq must be within +1%/-6%  of the DCO central freq */
+#define SKL_DCO_MAX_PDEVIATION 100
+#define SKL_DCO_MAX_NDEVIATION 600
+
+static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
+                                 uint64_t central_freq,
+                                 uint64_t dco_freq,
+                                 unsigned int divider)
+{
+       uint64_t deviation;
+
+       deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
+                             central_freq);
+
+       /* positive deviation */
+       if (dco_freq >= central_freq) {
+               if (deviation < SKL_DCO_MAX_PDEVIATION &&
+                   deviation < ctx->min_deviation) {
+                       ctx->min_deviation = deviation;
+                       ctx->central_freq = central_freq;
+                       ctx->dco_freq = dco_freq;
+                       ctx->p = divider;
+               }
+       /* negative deviation */
+       } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
+                  deviation < ctx->min_deviation) {
+               ctx->min_deviation = deviation;
+               ctx->central_freq = central_freq;
+               ctx->dco_freq = dco_freq;
+               ctx->p = divider;
+       }
+}
+
+static void skl_wrpll_get_multipliers(unsigned int p,
+                                     unsigned int *p0 /* out */,
+                                     unsigned int *p1 /* out */,
+                                     unsigned int *p2 /* out */)
+{
+       /* even dividers */
+       if (p % 2 == 0) {
+               unsigned int half = p / 2;
+
+               if (half == 1 || half == 2 || half == 3 || half == 5) {
+                       *p0 = 2;
+                       *p1 = 1;
+                       *p2 = half;
+               } else if (half % 2 == 0) {
+                       *p0 = 2;
+                       *p1 = half / 2;
+                       *p2 = 2;
+               } else if (half % 3 == 0) {
+                       *p0 = 3;
+                       *p1 = half / 3;
+                       *p2 = 2;
+               } else if (half % 7 == 0) {
+                       *p0 = 7;
+                       *p1 = half / 7;
+                       *p2 = 2;
+               }
+       } else if (p == 3 || p == 9) {  /* 3, 5, 7, 9, 15, 21, 35 */
+               *p0 = 3;
+               *p1 = 1;
+               *p2 = p / 3;
+       } else if (p == 5 || p == 7) {
+               *p0 = p;
+               *p1 = 1;
+               *p2 = 1;
+       } else if (p == 15) {
+               *p0 = 3;
+               *p1 = 1;
+               *p2 = 5;
+       } else if (p == 21) {
+               *p0 = 7;
+               *p1 = 1;
+               *p2 = 3;
+       } else if (p == 35) {
+               *p0 = 7;
+               *p1 = 1;
+               *p2 = 5;
+       }
+}
+
+struct skl_wrpll_params {
+       uint32_t        dco_fraction;
+       uint32_t        dco_integer;
+       uint32_t        qdiv_ratio;
+       uint32_t        qdiv_mode;
+       uint32_t        kdiv;
+       uint32_t        pdiv;
+       uint32_t        central_freq;
+};
+
+static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
+                                     uint64_t afe_clock,
+                                     uint64_t central_freq,
+                                     uint32_t p0, uint32_t p1, uint32_t p2)
+{
+       uint64_t dco_freq;
+
+       switch (central_freq) {
+       case 9600000000ULL:
+               params->central_freq = 0;
+               break;
+       case 9000000000ULL:
+               params->central_freq = 1;
+               break;
+       case 8400000000ULL:
+               params->central_freq = 3;
+       }
+
+       switch (p0) {
+       case 1:
+               params->pdiv = 0;
+               break;
+       case 2:
+               params->pdiv = 1;
+               break;
+       case 3:
+               params->pdiv = 2;
+               break;
+       case 7:
+               params->pdiv = 4;
+               break;
+       default:
+               WARN(1, "Incorrect PDiv\n");
+       }
+
+       switch (p2) {
+       case 5:
+               params->kdiv = 0;
+               break;
+       case 2:
+               params->kdiv = 1;
+               break;
+       case 3:
+               params->kdiv = 2;
+               break;
+       case 1:
+               params->kdiv = 3;
+               break;
+       default:
+               WARN(1, "Incorrect KDiv\n");
+       }
+
+       params->qdiv_ratio = p1;
+       params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
+
+       dco_freq = p0 * p1 * p2 * afe_clock;
+
+       /*
+        * Intermediate values are in Hz.
+        * Divide by MHz to match bsepc
+        */
+       params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
+       params->dco_fraction =
+               div_u64((div_u64(dco_freq, 24) -
+                        params->dco_integer * MHz(1)) * 0x8000, MHz(1));
+}
+
+static bool
+skl_ddi_calculate_wrpll(int clock /* in Hz */,
+                       struct skl_wrpll_params *wrpll_params)
+{
+       uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
+       uint64_t dco_central_freq[3] = {8400000000ULL,
+                                       9000000000ULL,
+                                       9600000000ULL};
+       static const int even_dividers[] = {  4,  6,  8, 10, 12, 14, 16, 18, 20,
+                                            24, 28, 30, 32, 36, 40, 42, 44,
+                                            48, 52, 54, 56, 60, 64, 66, 68,
+                                            70, 72, 76, 78, 80, 84, 88, 90,
+                                            92, 96, 98 };
+       static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
+       static const struct {
+               const int *list;
+               int n_dividers;
+       } dividers[] = {
+               { even_dividers, ARRAY_SIZE(even_dividers) },
+               { odd_dividers, ARRAY_SIZE(odd_dividers) },
+       };
+       struct skl_wrpll_context ctx;
+       unsigned int dco, d, i;
+       unsigned int p0, p1, p2;
+
+       skl_wrpll_context_init(&ctx);
+
+       for (d = 0; d < ARRAY_SIZE(dividers); d++) {
+               for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
+                       for (i = 0; i < dividers[d].n_dividers; i++) {
+                               unsigned int p = dividers[d].list[i];
+                               uint64_t dco_freq = p * afe_clock;
+
+                               skl_wrpll_try_divider(&ctx,
+                                                     dco_central_freq[dco],
+                                                     dco_freq,
+                                                     p);
+                               /*
+                                * Skip the remaining dividers if we're sure to
+                                * have found the definitive divider, we can't
+                                * improve a 0 deviation.
+                                */
+                               if (ctx.min_deviation == 0)
+                                       goto skip_remaining_dividers;
+                       }
+               }
+
+skip_remaining_dividers:
+               /*
+                * If a solution is found with an even divider, prefer
+                * this one.
+                */
+               if (d == 0 && ctx.p)
+                       break;
+       }
+
+       if (!ctx.p) {
+               DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
+               return false;
+       }
+
+       /*
+        * gcc incorrectly analyses that these can be used without being
+        * initialized. To be fair, it's hard to guess.
+        */
+       p0 = p1 = p2 = 0;
+       skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
+       skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
+                                 p0, p1, p2);
+
+       return true;
+}
+
+static struct intel_shared_dpll *
+skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+            struct intel_encoder *encoder)
+{
+       struct intel_shared_dpll *pll;
+       uint32_t ctrl1, cfgcr1, cfgcr2;
+       int clock = crtc_state->port_clock;
+
+       /*
+        * See comment in intel_dpll_hw_state to understand why we always use 0
+        * as the DPLL id in this function.
+        */
+
+       ctrl1 = DPLL_CTRL1_OVERRIDE(0);
+
+       if (encoder->type == INTEL_OUTPUT_HDMI) {
+               struct skl_wrpll_params wrpll_params = { 0, };
+
+               ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
+
+               if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
+                       return NULL;
+
+               cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
+                        DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
+                        wrpll_params.dco_integer;
+
+               cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
+                        DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
+                        DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
+                        DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
+                        wrpll_params.central_freq;
+       } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+                  encoder->type == INTEL_OUTPUT_DP_MST ||
+                  encoder->type == INTEL_OUTPUT_EDP) {
+               switch (crtc_state->port_clock / 2) {
+               case 81000:
+                       ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
+                       break;
+               case 135000:
+                       ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
+                       break;
+               case 270000:
+                       ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
+                       break;
+               /* eDP 1.4 rates */
+               case 162000:
+                       ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
+                       break;
+               /* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which
+               results in CDCLK change. Need to handle the change of CDCLK by
+               disabling pipes and re-enabling them */
+               case 108000:
+                       ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
+                       break;
+               case 216000:
+                       ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
+                       break;
+               }
+
+               cfgcr1 = cfgcr2 = 0;
+       } else {
+               return NULL;
+       }
+
+       memset(&crtc_state->dpll_hw_state, 0,
+              sizeof(crtc_state->dpll_hw_state));
+
+       crtc_state->dpll_hw_state.ctrl1 = ctrl1;
+       crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
+       crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
+
+       if (encoder->type == INTEL_OUTPUT_EDP)
+               pll = intel_find_shared_dpll(crtc, crtc_state,
+                                            DPLL_ID_SKL_DPLL0,
+                                            DPLL_ID_SKL_DPLL0);
+       else
+               pll = intel_find_shared_dpll(crtc, crtc_state,
+                                            DPLL_ID_SKL_DPLL1,
+                                            DPLL_ID_SKL_DPLL3);
+       if (!pll)
+               return NULL;
+
+       crtc_state->ddi_pll_sel = pll->id;
+
+       intel_reference_shared_dpll(pll, crtc_state);
+
+       return pll;
+}
+
+static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
+       .enable = skl_ddi_pll_enable,
+       .disable = skl_ddi_pll_disable,
+       .get_hw_state = skl_ddi_pll_get_hw_state,
+};
+
+static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
+       .enable = skl_ddi_dpll0_enable,
+       .disable = skl_ddi_dpll0_disable,
+       .get_hw_state = skl_ddi_dpll0_get_hw_state,
+};
+
+static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
+                               struct intel_shared_dpll *pll)
+{
+       uint32_t temp;
+       enum port port = (enum port)pll->id;    /* 1:1 port->PLL mapping */
+
+       temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
+       temp &= ~PORT_PLL_REF_SEL;
+       /* Non-SSC reference */
+       I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
+
+       /* Disable 10 bit clock */
+       temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
+       temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
+       I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+
+       /* Write P1 & P2 */
+       temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
+       temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
+       temp |= pll->config.hw_state.ebb0;
+       I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
+
+       /* Write M2 integer */
+       temp = I915_READ(BXT_PORT_PLL(port, 0));
+       temp &= ~PORT_PLL_M2_MASK;
+       temp |= pll->config.hw_state.pll0;
+       I915_WRITE(BXT_PORT_PLL(port, 0), temp);
+
+       /* Write N */
+       temp = I915_READ(BXT_PORT_PLL(port, 1));
+       temp &= ~PORT_PLL_N_MASK;
+       temp |= pll->config.hw_state.pll1;
+       I915_WRITE(BXT_PORT_PLL(port, 1), temp);
+
+       /* Write M2 fraction */
+       temp = I915_READ(BXT_PORT_PLL(port, 2));
+       temp &= ~PORT_PLL_M2_FRAC_MASK;
+       temp |= pll->config.hw_state.pll2;
+       I915_WRITE(BXT_PORT_PLL(port, 2), temp);
+
+       /* Write M2 fraction enable */
+       temp = I915_READ(BXT_PORT_PLL(port, 3));
+       temp &= ~PORT_PLL_M2_FRAC_ENABLE;
+       temp |= pll->config.hw_state.pll3;
+       I915_WRITE(BXT_PORT_PLL(port, 3), temp);
+
+       /* Write coeff */
+       temp = I915_READ(BXT_PORT_PLL(port, 6));
+       temp &= ~PORT_PLL_PROP_COEFF_MASK;
+       temp &= ~PORT_PLL_INT_COEFF_MASK;
+       temp &= ~PORT_PLL_GAIN_CTL_MASK;
+       temp |= pll->config.hw_state.pll6;
+       I915_WRITE(BXT_PORT_PLL(port, 6), temp);
+
+       /* Write calibration val */
+       temp = I915_READ(BXT_PORT_PLL(port, 8));
+       temp &= ~PORT_PLL_TARGET_CNT_MASK;
+       temp |= pll->config.hw_state.pll8;
+       I915_WRITE(BXT_PORT_PLL(port, 8), temp);
+
+       temp = I915_READ(BXT_PORT_PLL(port, 9));
+       temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
+       temp |= pll->config.hw_state.pll9;
+       I915_WRITE(BXT_PORT_PLL(port, 9), temp);
+
+       temp = I915_READ(BXT_PORT_PLL(port, 10));
+       temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
+       temp &= ~PORT_PLL_DCO_AMP_MASK;
+       temp |= pll->config.hw_state.pll10;
+       I915_WRITE(BXT_PORT_PLL(port, 10), temp);
+
+       /* Recalibrate with new settings */
+       temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
+       temp |= PORT_PLL_RECALIBRATE;
+       I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+       temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
+       temp |= pll->config.hw_state.ebb4;
+       I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+
+       /* Enable PLL */
+       temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
+       temp |= PORT_PLL_ENABLE;
+       I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
+       POSTING_READ(BXT_PORT_PLL_ENABLE(port));
+
+       if (wait_for_atomic_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
+                       PORT_PLL_LOCK), 200))
+               DRM_ERROR("PLL %d not locked\n", port);
+
+       /*
+        * While we write to the group register to program all lanes at once we
+        * can read only lane registers and we pick lanes 0/1 for that.
+        */
+       temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
+       temp &= ~LANE_STAGGER_MASK;
+       temp &= ~LANESTAGGER_STRAP_OVRD;
+       temp |= pll->config.hw_state.pcsdw12;
+       I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
+}
+
+static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
+                                       struct intel_shared_dpll *pll)
+{
+       enum port port = (enum port)pll->id;    /* 1:1 port->PLL mapping */
+       uint32_t temp;
+
+       temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
+       temp &= ~PORT_PLL_ENABLE;
+       I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
+       POSTING_READ(BXT_PORT_PLL_ENABLE(port));
+}
+
+static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
+                                       struct intel_shared_dpll *pll,
+                                       struct intel_dpll_hw_state *hw_state)
+{
+       enum port port = (enum port)pll->id;    /* 1:1 port->PLL mapping */
+       uint32_t val;
+       bool ret;
+
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+               return false;
+
+       ret = false;
+
+       val = I915_READ(BXT_PORT_PLL_ENABLE(port));
+       if (!(val & PORT_PLL_ENABLE))
+               goto out;
+
+       hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
+       hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
+
+       hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
+       hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
+
+       hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
+       hw_state->pll0 &= PORT_PLL_M2_MASK;
+
+       hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
+       hw_state->pll1 &= PORT_PLL_N_MASK;
+
+       hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
+       hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
+
+       hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
+       hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
+
+       hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
+       hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
+                         PORT_PLL_INT_COEFF_MASK |
+                         PORT_PLL_GAIN_CTL_MASK;
+
+       hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
+       hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
+
+       hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
+       hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
+
+       hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
+       hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
+                          PORT_PLL_DCO_AMP_MASK;
+
+       /*
+        * While we write to the group register to program all lanes at once we
+        * can read only lane registers. We configure all lanes the same way, so
+        * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
+        */
+       hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
+       if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
+               DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
+                                hw_state->pcsdw12,
+                                I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
+       hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
+
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return ret;
+}
+
+/* bxt clock parameters */
+struct bxt_clk_div {
+       int clock;
+       uint32_t p1;
+       uint32_t p2;
+       uint32_t m2_int;
+       uint32_t m2_frac;
+       bool m2_frac_en;
+       uint32_t n;
+};
+
+/* pre-calculated values for DP linkrates */
+static const struct bxt_clk_div bxt_dp_clk_val[] = {
+       {162000, 4, 2, 32, 1677722, 1, 1},
+       {270000, 4, 1, 27,       0, 0, 1},
+       {540000, 2, 1, 27,       0, 0, 1},
+       {216000, 3, 2, 32, 1677722, 1, 1},
+       {243000, 4, 1, 24, 1258291, 1, 1},
+       {324000, 4, 1, 32, 1677722, 1, 1},
+       {432000, 3, 1, 32, 1677722, 1, 1}
+};
+
+static struct intel_shared_dpll *
+bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+            struct intel_encoder *encoder)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       struct intel_shared_dpll *pll;
+       enum intel_dpll_id i;
+       struct intel_digital_port *intel_dig_port;
+       struct bxt_clk_div clk_div = {0};
+       int vco = 0;
+       uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
+       uint32_t lanestagger;
+       int clock = crtc_state->port_clock;
+
+       if (encoder->type == INTEL_OUTPUT_HDMI) {
+               intel_clock_t best_clock;
+
+               /* Calculate HDMI div */
+               /*
+                * FIXME: tie the following calculation into
+                * i9xx_crtc_compute_clock
+                */
+               if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
+                       DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
+                                        clock, pipe_name(crtc->pipe));
+                       return NULL;
+               }
+
+               clk_div.p1 = best_clock.p1;
+               clk_div.p2 = best_clock.p2;
+               WARN_ON(best_clock.m1 != 2);
+               clk_div.n = best_clock.n;
+               clk_div.m2_int = best_clock.m2 >> 22;
+               clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1);
+               clk_div.m2_frac_en = clk_div.m2_frac != 0;
+
+               vco = best_clock.vco;
+       } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+                  encoder->type == INTEL_OUTPUT_EDP) {
+               int i;
+
+               clk_div = bxt_dp_clk_val[0];
+               for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
+                       if (bxt_dp_clk_val[i].clock == clock) {
+                               clk_div = bxt_dp_clk_val[i];
+                               break;
+                       }
+               }
+               vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2;
+       }
+
+       if (vco >= 6200000 && vco <= 6700000) {
+               prop_coef = 4;
+               int_coef = 9;
+               gain_ctl = 3;
+               targ_cnt = 8;
+       } else if ((vco > 5400000 && vco < 6200000) ||
+                       (vco >= 4800000 && vco < 5400000)) {
+               prop_coef = 5;
+               int_coef = 11;
+               gain_ctl = 3;
+               targ_cnt = 9;
+       } else if (vco == 5400000) {
+               prop_coef = 3;
+               int_coef = 8;
+               gain_ctl = 1;
+               targ_cnt = 9;
+       } else {
+               DRM_ERROR("Invalid VCO\n");
+               return NULL;
+       }
+
+       memset(&crtc_state->dpll_hw_state, 0,
+              sizeof(crtc_state->dpll_hw_state));
+
+       if (clock > 270000)
+               lanestagger = 0x18;
+       else if (clock > 135000)
+               lanestagger = 0x0d;
+       else if (clock > 67000)
+               lanestagger = 0x07;
+       else if (clock > 33000)
+               lanestagger = 0x04;
+       else
+               lanestagger = 0x02;
+
+       crtc_state->dpll_hw_state.ebb0 =
+               PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2);
+       crtc_state->dpll_hw_state.pll0 = clk_div.m2_int;
+       crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n);
+       crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac;
+
+       if (clk_div.m2_frac_en)
+               crtc_state->dpll_hw_state.pll3 =
+                       PORT_PLL_M2_FRAC_ENABLE;
+
+       crtc_state->dpll_hw_state.pll6 =
+               prop_coef | PORT_PLL_INT_COEFF(int_coef);
+       crtc_state->dpll_hw_state.pll6 |=
+               PORT_PLL_GAIN_CTL(gain_ctl);
+
+       crtc_state->dpll_hw_state.pll8 = targ_cnt;
+
+       crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
+
+       crtc_state->dpll_hw_state.pll10 =
+               PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
+               | PORT_PLL_DCO_AMP_OVR_EN_H;
+
+       crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
+
+       crtc_state->dpll_hw_state.pcsdw12 =
+               LANESTAGGER_STRAP_OVRD | lanestagger;
+
+       intel_dig_port = enc_to_dig_port(&encoder->base);
+
+       /* 1:1 mapping between ports and PLLs */
+       i = (enum intel_dpll_id) intel_dig_port->port;
+       pll = intel_get_shared_dpll_by_id(dev_priv, i);
+
+       DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
+               crtc->base.base.id, pll->name);
+
+       intel_reference_shared_dpll(pll, crtc_state);
+
+       /* shared DPLL id 0 is DPLL A */
+       crtc_state->ddi_pll_sel = pll->id;
+
+       return pll;
+}
+
+static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
+       .enable = bxt_ddi_pll_enable,
+       .disable = bxt_ddi_pll_disable,
+       .get_hw_state = bxt_ddi_pll_get_hw_state,
+};
+
+static void intel_ddi_pll_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t val = I915_READ(LCPLL_CTL);
+
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+               int cdclk_freq;
+
+               cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
+               dev_priv->skl_boot_cdclk = cdclk_freq;
+               if (skl_sanitize_cdclk(dev_priv))
+                       DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
+               if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
+                       DRM_ERROR("LCPLL1 is disabled\n");
+       } else if (IS_BROXTON(dev)) {
+               broxton_init_cdclk(dev);
+               broxton_ddi_phy_init(dev);
+       } else {
+               /*
+                * The LCPLL register should be turned on by the BIOS. For now
+                * let's just check its state and print errors in case
+                * something is wrong.  Don't even try to turn it on.
+                */
+
+               if (val & LCPLL_CD_SOURCE_FCLK)
+                       DRM_ERROR("CDCLK source is not LCPLL\n");
+
+               if (val & LCPLL_PLL_DISABLE)
+                       DRM_ERROR("LCPLL is disabled\n");
+       }
+}
+
+struct dpll_info {
+       const char *name;
+       const int id;
+       const struct intel_shared_dpll_funcs *funcs;
+       uint32_t flags;
+};
+
+struct intel_dpll_mgr {
+       const struct dpll_info *dpll_info;
+
+       struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
+                                             struct intel_crtc_state *crtc_state,
+                                             struct intel_encoder *encoder);
+};
+
+static const struct dpll_info pch_plls[] = {
+       { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
+       { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
+       { NULL, -1, NULL, 0 },
+};
+
+static const struct intel_dpll_mgr pch_pll_mgr = {
+       .dpll_info = pch_plls,
+       .get_dpll = ibx_get_dpll,
+};
+
+static const struct dpll_info hsw_plls[] = {
+       { "WRPLL 1",    DPLL_ID_WRPLL1,     &hsw_ddi_wrpll_funcs, 0 },
+       { "WRPLL 2",    DPLL_ID_WRPLL2,     &hsw_ddi_wrpll_funcs, 0 },
+       { "SPLL",       DPLL_ID_SPLL,       &hsw_ddi_spll_funcs,  0 },
+       { "LCPLL 810",  DPLL_ID_LCPLL_810,  &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
+       { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
+       { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
+       { NULL, -1, NULL, },
+};
+
+static const struct intel_dpll_mgr hsw_pll_mgr = {
+       .dpll_info = hsw_plls,
+       .get_dpll = hsw_get_dpll,
+};
+
+static const struct dpll_info skl_plls[] = {
+       { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
+       { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs,   0 },
+       { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs,   0 },
+       { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs,   0 },
+       { NULL, -1, NULL, },
+};
+
+static const struct intel_dpll_mgr skl_pll_mgr = {
+       .dpll_info = skl_plls,
+       .get_dpll = skl_get_dpll,
+};
+
+static const struct dpll_info bxt_plls[] = {
+       { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
+       { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
+       { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
+       { NULL, -1, NULL, },
+};
+
+static const struct intel_dpll_mgr bxt_pll_mgr = {
+       .dpll_info = bxt_plls,
+       .get_dpll = bxt_get_dpll,
+};
+
+void intel_shared_dpll_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       const struct intel_dpll_mgr *dpll_mgr = NULL;
+       const struct dpll_info *dpll_info;
+       int i;
+
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+               dpll_mgr = &skl_pll_mgr;
+       else if (IS_BROXTON(dev))
+               dpll_mgr = &bxt_pll_mgr;
+       else if (HAS_DDI(dev))
+               dpll_mgr = &hsw_pll_mgr;
+       else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+               dpll_mgr = &pch_pll_mgr;
+
+       if (!dpll_mgr) {
+               dev_priv->num_shared_dpll = 0;
+               return;
+       }
+
+       dpll_info = dpll_mgr->dpll_info;
+
+       for (i = 0; dpll_info[i].id >= 0; i++) {
+               WARN_ON(i != dpll_info[i].id);
+
+               dev_priv->shared_dplls[i].id = dpll_info[i].id;
+               dev_priv->shared_dplls[i].name = dpll_info[i].name;
+               dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
+               dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
+       }
+
+       dev_priv->dpll_mgr = dpll_mgr;
+       dev_priv->num_shared_dpll = i;
+
+       BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
+
+       /* FIXME: Move this to a more suitable place */
+       if (HAS_DDI(dev))
+               intel_ddi_pll_init(dev);
+}
+
+struct intel_shared_dpll *
+intel_get_shared_dpll(struct intel_crtc *crtc,
+                     struct intel_crtc_state *crtc_state,
+                     struct intel_encoder *encoder)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
+
+       if (WARN_ON(!dpll_mgr))
+               return NULL;
+
+       return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
+}
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
new file mode 100644 (file)
index 0000000..89c5ada
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2012-2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _INTEL_DPLL_MGR_H_
+#define _INTEL_DPLL_MGR_H_
+
+/*FIXME: Move this to a more appropriate place. */
+#define abs_diff(a, b) ({                      \
+       typeof(a) __a = (a);                    \
+       typeof(b) __b = (b);                    \
+       (void) (&__a == &__b);                  \
+       __a > __b ? (__a - __b) : (__b - __a); })
+
+struct drm_i915_private;
+struct intel_crtc;
+struct intel_crtc_state;
+struct intel_encoder;
+
+struct intel_shared_dpll;
+struct intel_dpll_mgr;
+
+enum intel_dpll_id {
+       DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
+       /* real shared dpll ids must be >= 0 */
+       DPLL_ID_PCH_PLL_A = 0,
+       DPLL_ID_PCH_PLL_B = 1,
+       /* hsw/bdw */
+       DPLL_ID_WRPLL1 = 0,
+       DPLL_ID_WRPLL2 = 1,
+       DPLL_ID_SPLL = 2,
+       DPLL_ID_LCPLL_810 = 3,
+       DPLL_ID_LCPLL_1350 = 4,
+       DPLL_ID_LCPLL_2700 = 5,
+
+       /* skl */
+       DPLL_ID_SKL_DPLL0 = 0,
+       DPLL_ID_SKL_DPLL1 = 1,
+       DPLL_ID_SKL_DPLL2 = 2,
+       DPLL_ID_SKL_DPLL3 = 3,
+};
+#define I915_NUM_PLLS 6
+
+/** Inform the state checker that the DPLL is kept enabled even if not
+ * in use by any crtc.
+ */
+#define INTEL_DPLL_ALWAYS_ON   (1 << 0)
+
+struct intel_dpll_hw_state {
+       /* i9xx, pch plls */
+       uint32_t dpll;
+       uint32_t dpll_md;
+       uint32_t fp0;
+       uint32_t fp1;
+
+       /* hsw, bdw */
+       uint32_t wrpll;
+       uint32_t spll;
+
+       /* skl */
+       /*
+        * DPLL_CTRL1 has 6 bits for each each this DPLL. We store those in
+        * lower part of ctrl1 and they get shifted into position when writing
+        * the register.  This allows us to easily compare the state to share
+        * the DPLL.
+        */
+       uint32_t ctrl1;
+       /* HDMI only, 0 when used for DP */
+       uint32_t cfgcr1, cfgcr2;
+
+       /* bxt */
+       uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
+                pcsdw12;
+};
+
+struct intel_shared_dpll_config {
+       unsigned crtc_mask; /* mask of CRTCs sharing this PLL */
+       struct intel_dpll_hw_state hw_state;
+};
+
+struct intel_shared_dpll_funcs {
+       /* The mode_set hook is optional and should be used together with the
+        * intel_prepare_shared_dpll function. */
+       void (*mode_set)(struct drm_i915_private *dev_priv,
+                        struct intel_shared_dpll *pll);
+       void (*enable)(struct drm_i915_private *dev_priv,
+                      struct intel_shared_dpll *pll);
+       void (*disable)(struct drm_i915_private *dev_priv,
+                       struct intel_shared_dpll *pll);
+       bool (*get_hw_state)(struct drm_i915_private *dev_priv,
+                            struct intel_shared_dpll *pll,
+                            struct intel_dpll_hw_state *hw_state);
+};
+
+struct intel_shared_dpll {
+       struct intel_shared_dpll_config config;
+
+       unsigned active_mask; /* mask of active CRTCs (i.e. DPMS on) */
+       bool on; /* is the PLL actually active? Disabled during modeset */
+       const char *name;
+       /* should match the index in the dev_priv->shared_dplls array */
+       enum intel_dpll_id id;
+
+       struct intel_shared_dpll_funcs funcs;
+
+       uint32_t flags;
+};
+
+#define SKL_DPLL0 0
+#define SKL_DPLL1 1
+#define SKL_DPLL2 2
+#define SKL_DPLL3 3
+
+/* shared dpll functions */
+struct intel_shared_dpll *
+intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
+                           enum intel_dpll_id id);
+enum intel_dpll_id
+intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
+                        struct intel_shared_dpll *pll);
+void
+intel_shared_dpll_config_get(struct intel_shared_dpll_config *config,
+                            struct intel_shared_dpll *pll,
+                            struct intel_crtc *crtc);
+void
+intel_shared_dpll_config_put(struct intel_shared_dpll_config *config,
+                            struct intel_shared_dpll *pll,
+                            struct intel_crtc *crtc);
+void assert_shared_dpll(struct drm_i915_private *dev_priv,
+                       struct intel_shared_dpll *pll,
+                       bool state);
+#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
+#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
+struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
+                                               struct intel_crtc_state *state,
+                                               struct intel_encoder *encoder);
+void intel_prepare_shared_dpll(struct intel_crtc *crtc);
+void intel_enable_shared_dpll(struct intel_crtc *crtc);
+void intel_disable_shared_dpll(struct intel_crtc *crtc);
+void intel_shared_dpll_commit(struct drm_atomic_state *state);
+void intel_shared_dpll_init(struct drm_device *dev);
+
+
+#endif /* _INTEL_DPLL_MGR_H_ */
index 4c027d6..c87b450 100644 (file)
  * contexts. Note that it's important that we check the condition again after
  * having timed out, since the timeout could be due to preemption or similar and
  * we've never had a chance to check the condition before the timeout.
+ *
+ * TODO: When modesetting has fully transitioned to atomic, the below
+ * drm_can_sleep() can be removed and in_atomic()/!in_atomic() asserts
+ * added.
  */
-#define _wait_for(COND, MS, W) ({ \
-       unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1;   \
+#define _wait_for(COND, US, W) ({ \
+       unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1;   \
        int ret__ = 0;                                                  \
        while (!(COND)) {                                               \
                if (time_after(jiffies, timeout__)) {                   \
@@ -55,7 +59,7 @@
                        break;                                          \
                }                                                       \
                if ((W) && drm_can_sleep()) {                           \
-                       usleep_range((W)*1000, (W)*2000);               \
+                       usleep_range((W), (W)*2);                       \
                } else {                                                \
                        cpu_relax();                                    \
                }                                                       \
        ret__;                                                          \
 })
 
-#define wait_for(COND, MS) _wait_for(COND, MS, 1)
-#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0)
-#define wait_for_atomic_us(COND, US) _wait_for((COND), \
-                                              DIV_ROUND_UP((US), 1000), 0)
+#define wait_for(COND, MS)             _wait_for((COND), (MS) * 1000, 1000)
+#define wait_for_us(COND, US)          _wait_for((COND), (US), 1)
+
+/* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */
+#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT)
+# define _WAIT_FOR_ATOMIC_CHECK WARN_ON_ONCE(!in_atomic())
+#else
+# define _WAIT_FOR_ATOMIC_CHECK do { } while (0)
+#endif
+
+#define _wait_for_atomic(COND, US) ({ \
+       unsigned long end__; \
+       int ret__ = 0; \
+       _WAIT_FOR_ATOMIC_CHECK; \
+       BUILD_BUG_ON((US) > 50000); \
+       end__ = (local_clock() >> 10) + (US) + 1; \
+       while (!(COND)) { \
+               if (time_after((unsigned long)(local_clock() >> 10), end__)) { \
+                       /* Unlike the regular wait_for(), this atomic variant \
+                        * cannot be preempted (and we'll just ignore the issue\
+                        * of irq interruptions) and so we know that no time \
+                        * has passed since the last check of COND and can \
+                        * immediately report the timeout. \
+                        */ \
+                       ret__ = -ETIMEDOUT; \
+                       break; \
+               } \
+               cpu_relax(); \
+       } \
+       ret__; \
+})
+
+#define wait_for_atomic(COND, MS)      _wait_for_atomic((COND), (MS) * 1000)
+#define wait_for_atomic_us(COND, US)   _wait_for_atomic((COND), (US))
 
 #define KHz(x) (1000 * (x))
 #define MHz(x) KHz(1000 * (x))
@@ -118,6 +152,7 @@ enum intel_output_type {
 struct intel_framebuffer {
        struct drm_framebuffer base;
        struct drm_i915_gem_object *obj;
+       struct intel_rotation_info rot_info;
 };
 
 struct intel_fbdev {
@@ -260,6 +295,12 @@ struct intel_atomic_state {
 
        struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
        struct intel_wm_config wm_config;
+
+       /*
+        * Current watermarks can't be trusted during hardware readout, so
+        * don't bother calculating intermediate watermarks.
+        */
+       bool skip_intermediate_wm;
 };
 
 struct intel_plane_state {
@@ -349,6 +390,7 @@ struct intel_crtc_scaler_state {
 
 struct intel_pipe_wm {
        struct intel_wm_level wm[5];
+       struct intel_wm_level raw_wm[5];
        uint32_t linetime;
        bool fbc_wm_enabled;
        bool pipe_enabled;
@@ -376,9 +418,10 @@ struct intel_crtc_state {
 #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS      (1<<0) /* unreliable sync mode.flags */
        unsigned long quirks;
 
+       unsigned fb_bits; /* framebuffers to flip */
        bool update_pipe; /* can a fast modeset be performed? */
        bool disable_cxsr;
-       bool wm_changed; /* watermarks are updated */
+       bool update_wm_pre, update_wm_post; /* watermarks are updated */
        bool fb_changed; /* fb on any of the planes is changed */
 
        /* Pipe source size (ie. panel fitter input size)
@@ -394,7 +437,8 @@ struct intel_crtc_state {
        bool has_infoframe;
 
        /* CPU Transcoder for the pipe. Currently this can only differ from the
-        * pipe on Haswell (where we have a special eDP transcoder). */
+        * pipe on Haswell and later (where we have a special eDP transcoder)
+        * and Broxton (where we have special DSI transcoders). */
        enum transcoder cpu_transcoder;
 
        /*
@@ -441,8 +485,8 @@ struct intel_crtc_state {
         * haswell. */
        struct dpll dpll;
 
-       /* Selected dpll when shared or DPLL_ID_PRIVATE. */
-       enum intel_dpll_id shared_dpll;
+       /* Selected dpll when shared or NULL. */
+       struct intel_shared_dpll *shared_dpll;
 
        /*
         * - PORT_CLK_SEL for DDI ports on HSW/BDW.
@@ -510,14 +554,33 @@ struct intel_crtc_state {
 
        struct {
                /*
-                * optimal watermarks, programmed post-vblank when this state
-                * is committed
+                * Optimal watermarks, programmed post-vblank when this state
+                * is committed.
                 */
                union {
                        struct intel_pipe_wm ilk;
                        struct skl_pipe_wm skl;
                } optimal;
+
+               /*
+                * Intermediate watermarks; these can be programmed immediately
+                * since they satisfy both the current configuration we're
+                * switching away from and the new configuration we're switching
+                * to.
+                */
+               struct intel_pipe_wm intermediate;
+
+               /*
+                * Platforms with two-step watermark programming will need to
+                * update watermark programming post-vblank to switch from the
+                * safe intermediate watermarks to the optimal final
+                * watermarks.
+                */
+               bool need_postvbl_update;
        } wm;
+
+       /* Gamma mode programmed on the pipe */
+       uint32_t gamma_mode;
 };
 
 struct vlv_wm_state {
@@ -537,23 +600,6 @@ struct intel_mmio_flip {
        unsigned int rotation;
 };
 
-/*
- * Tracking of operations that need to be performed at the beginning/end of an
- * atomic commit, outside the atomic section where interrupts are disabled.
- * These are generally operations that grab mutexes or might otherwise sleep
- * and thus can't be run with interrupts disabled.
- */
-struct intel_crtc_atomic_commit {
-       /* Sleepable operations to perform before commit */
-
-       /* Sleepable operations to perform after commit */
-       unsigned fb_bits;
-       bool post_enable_primary;
-
-       /* Sleepable operations to perform before and after commit */
-       bool update_fbc;
-};
-
 struct intel_crtc {
        struct drm_crtc base;
        enum pipe pipe;
@@ -600,6 +646,7 @@ struct intel_crtc {
                        struct intel_pipe_wm ilk;
                        struct skl_pipe_wm skl;
                } active;
+
                /* allow CxSR on this pipe */
                bool cxsr_allowed;
        } wm;
@@ -613,8 +660,6 @@ struct intel_crtc {
                int scanline_start;
        } debug;
 
-       struct intel_crtc_atomic_commit atomic;
-
        /* scalers available on this crtc */
        int num_scalers;
 
@@ -1007,7 +1052,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc);
 void intel_ddi_init(struct drm_device *dev, enum port port);
 enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder);
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
-void intel_ddi_pll_init(struct drm_device *dev);
 void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc);
 void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
                                       enum transcoder cpu_transcoder);
@@ -1051,7 +1095,7 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
                              uint64_t fb_modifier, uint32_t pixel_format);
 
 /* intel_audio.c */
-void intel_init_audio(struct drm_device *dev);
+void intel_init_audio_hooks(struct drm_i915_private *dev_priv);
 void intel_audio_codec_enable(struct intel_encoder *encoder);
 void intel_audio_codec_disable(struct intel_encoder *encoder);
 void i915_audio_component_init(struct drm_i915_private *dev_priv);
@@ -1059,9 +1103,9 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
 /* intel_display.c */
 extern const struct drm_plane_funcs intel_plane_funcs;
+void intel_init_display_hooks(struct drm_i915_private *dev_priv);
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
 bool intel_has_pending_fb_unpin(struct drm_device *dev);
-int intel_pch_rawclk(struct drm_device *dev);
-int intel_hrawclk(struct drm_device *dev);
 void intel_mark_busy(struct drm_device *dev);
 void intel_mark_idle(struct drm_device *dev);
 void intel_crtc_restore_mode(struct drm_crtc *crtc);
@@ -1106,9 +1150,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 void intel_release_load_detect_pipe(struct drm_connector *connector,
                                    struct intel_load_detect_pipe *old,
                                    struct drm_modeset_acquire_ctx *ctx);
-int intel_pin_and_fence_fb_obj(struct drm_plane *plane,
-                              struct drm_framebuffer *fb,
-                              const struct drm_plane_state *plane_state);
+int intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
+                              unsigned int rotation);
 struct drm_framebuffer *
 __intel_framebuffer_create(struct drm_device *dev,
                           struct drm_mode_fb_cmd2 *mode_cmd,
@@ -1144,19 +1187,13 @@ intel_rotation_90_or_270(unsigned int rotation)
 void intel_create_rotation_property(struct drm_device *dev,
                                        struct intel_plane *plane);
 
-/* shared dpll functions */
-struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
-void assert_shared_dpll(struct drm_i915_private *dev_priv,
-                       struct intel_shared_dpll *pll,
-                       bool state);
-#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
-#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
-struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
-                                               struct intel_crtc_state *state);
+void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
+                                   enum pipe pipe);
 
 int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
                     const struct dpll *dpll);
 void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe);
+int lpt_get_iclkip(struct drm_i915_private *dev_priv);
 
 /* modesetting asserts */
 void assert_panel_unlocked(struct drm_i915_private *dev_priv,
@@ -1165,6 +1202,9 @@ void assert_pll(struct drm_i915_private *dev_priv,
                enum pipe pipe, bool state);
 #define assert_pll_enabled(d, p) assert_pll(d, p, true)
 #define assert_pll_disabled(d, p) assert_pll(d, p, false)
+void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state);
+#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
+#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
 void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
                       enum pipe pipe, bool state);
 #define assert_fdi_rx_pll_enabled(d, p) assert_fdi_rx_pll(d, p, true)
@@ -1172,11 +1212,10 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
 void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
 #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
 #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
-u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
-                             int *x, int *y,
-                             uint64_t fb_modifier,
-                             unsigned int cpp,
-                             unsigned int pitch);
+u32 intel_compute_tile_offset(int *x, int *y,
+                             const struct drm_framebuffer *fb, int plane,
+                             unsigned int pitch,
+                             unsigned int rotation);
 void intel_prepare_reset(struct drm_device *dev);
 void intel_finish_reset(struct drm_device *dev);
 void hsw_enable_pc8(struct drm_i915_private *dev_priv);
@@ -1196,9 +1235,6 @@ void intel_dp_get_m_n(struct intel_crtc *crtc,
                      struct intel_crtc_state *pipe_config);
 void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
 int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
-void
-ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,
-                               int dotclock);
 bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
                        intel_clock_t *best_clock);
 int chv_calc_dpll_params(int refclk, intel_clock_t *pll_clock);
@@ -1226,7 +1262,7 @@ u32 skl_plane_ctl_rotation(unsigned int rotation);
 
 /* intel_csr.c */
 void intel_csr_ucode_init(struct drm_i915_private *);
-bool intel_csr_load_program(struct drm_i915_private *);
+void intel_csr_load_program(struct drm_i915_private *);
 void intel_csr_ucode_fini(struct drm_i915_private *);
 
 /* intel_dp.c */
@@ -1266,7 +1302,6 @@ void intel_edp_drrs_invalidate(struct drm_device *dev,
 void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
 bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
                                         struct intel_digital_port *port);
-void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config);
 
 void
 intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
@@ -1541,6 +1576,7 @@ void intel_suspend_hw(struct drm_device *dev);
 int ilk_wm_max_level(const struct drm_device *dev);
 void intel_update_watermarks(struct drm_crtc *crtc);
 void intel_init_pm(struct drm_device *dev);
+void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv);
 void intel_pm_setup(struct drm_device *dev);
 void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
 void intel_gpu_ips_teardown(void);
@@ -1565,6 +1601,7 @@ void skl_wm_get_hw_state(struct drm_device *dev);
 void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
                          struct skl_ddb_allocation *ddb /* out */);
 uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config);
+bool ilk_disable_lp_wm(struct drm_device *dev);
 int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6);
 
 /* intel_sdvo.c */
@@ -1606,6 +1643,18 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
 
        return to_intel_crtc_state(crtc_state);
 }
+
+static inline struct intel_plane_state *
+intel_atomic_get_existing_plane_state(struct drm_atomic_state *state,
+                                     struct intel_plane *plane)
+{
+       struct drm_plane_state *plane_state;
+
+       plane_state = drm_atomic_get_existing_plane_state(state, &plane->base);
+
+       return to_intel_plane_state(plane_state);
+}
+
 int intel_atomic_setup_scalers(struct drm_device *dev,
        struct intel_crtc *intel_crtc,
        struct intel_crtc_state *crtc_state);
@@ -1617,4 +1666,10 @@ void intel_plane_destroy_state(struct drm_plane *plane,
                               struct drm_plane_state *state);
 extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
 
+/* intel_color.c */
+void intel_color_init(struct drm_crtc *crtc);
+int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
+void intel_color_set_csc(struct drm_crtc *crtc);
+void intel_color_load_luts(struct drm_crtc *crtc);
+
 #endif /* __INTEL_DRV_H__ */
index 01b8e9f..0de74e1 100644 (file)
@@ -268,6 +268,7 @@ static inline bool is_cmd_mode(struct intel_dsi *intel_dsi)
 static bool intel_dsi_compute_config(struct intel_encoder *encoder,
                                     struct intel_crtc_state *pipe_config)
 {
+       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
        struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi,
                                                   base);
        struct intel_connector *intel_connector = intel_dsi->attached_connector;
@@ -284,6 +285,14 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder,
        /* DSI uses short packets for sync events, so clear mode flags for DSI */
        adjusted_mode->flags = 0;
 
+       if (IS_BROXTON(dev_priv)) {
+               /* Dual link goes to DSI transcoder A. */
+               if (intel_dsi->ports == BIT(PORT_C))
+                       pipe_config->cpu_transcoder = TRANSCODER_DSI_C;
+               else
+                       pipe_config->cpu_transcoder = TRANSCODER_DSI_A;
+       }
+
        return true;
 }
 
@@ -403,7 +412,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder)
                temp &= ~LANE_CONFIGURATION_MASK;
                temp &= ~DUAL_LINK_MODE_MASK;
 
-               if (intel_dsi->ports == ((1 << PORT_A) | (1 << PORT_C))) {
+               if (intel_dsi->ports == (BIT(PORT_A) | BIT(PORT_C))) {
                        temp |= (intel_dsi->dual_link - 1)
                                                << DUAL_LINK_MODE_SHIFT;
                        temp |= intel_crtc->pipe ?
@@ -667,7 +676,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
        struct drm_device *dev = encoder->base.dev;
        enum intel_display_power_domain power_domain;
        enum port port;
-       bool ret;
+       bool active = false;
 
        DRM_DEBUG_KMS("\n");
 
@@ -675,38 +684,60 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
        if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
-       ret = false;
+       /*
+        * On Broxton the PLL needs to be enabled with a valid divider
+        * configuration, otherwise accessing DSI registers will hang the
+        * machine. See BSpec North Display Engine registers/MIPI[BXT].
+        */
+       if (IS_BROXTON(dev_priv) && !intel_dsi_pll_is_enabled(dev_priv))
+               goto out_put_power;
 
        /* XXX: this only works for one DSI output */
        for_each_dsi_port(port, intel_dsi->ports) {
                i915_reg_t ctrl_reg = IS_BROXTON(dev) ?
                        BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
-               u32 dpi_enabled, func;
-
-               func = I915_READ(MIPI_DSI_FUNC_PRG(port));
-               dpi_enabled = I915_READ(ctrl_reg) & DPI_ENABLE;
+               bool enabled = I915_READ(ctrl_reg) & DPI_ENABLE;
 
                /* Due to some hardware limitations on BYT, MIPI Port C DPI
                 * Enable bit does not get set. To check whether DSI Port C
                 * was enabled in BIOS, check the Pipe B enable bit
                 */
                if (IS_VALLEYVIEW(dev) && port == PORT_C)
-                       dpi_enabled = I915_READ(PIPECONF(PIPE_B)) &
-                                                       PIPECONF_ENABLE;
+                       enabled = I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE;
 
-               if (dpi_enabled || (func & CMD_MODE_DATA_WIDTH_MASK)) {
-                       if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) {
-                               *pipe = port == PORT_A ? PIPE_A : PIPE_B;
-                               ret = true;
+               /* Try command mode if video mode not enabled */
+               if (!enabled) {
+                       u32 tmp = I915_READ(MIPI_DSI_FUNC_PRG(port));
+                       enabled = tmp & CMD_MODE_DATA_WIDTH_MASK;
+               }
 
-                               goto out;
-                       }
+               if (!enabled)
+                       continue;
+
+               if (!(I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY))
+                       continue;
+
+               if (IS_BROXTON(dev_priv)) {
+                       u32 tmp = I915_READ(MIPI_CTRL(port));
+                       tmp &= BXT_PIPE_SELECT_MASK;
+                       tmp >>= BXT_PIPE_SELECT_SHIFT;
+
+                       if (WARN_ON(tmp > PIPE_C))
+                               continue;
+
+                       *pipe = tmp;
+               } else {
+                       *pipe = port == PORT_A ? PIPE_A : PIPE_B;
                }
+
+               active = true;
+               break;
        }
-out:
+
+out_put_power:
        intel_display_power_put(dev_priv, power_domain);
 
-       return ret;
+       return active;
 }
 
 static void intel_dsi_get_config(struct intel_encoder *encoder,
@@ -787,7 +818,7 @@ static void set_dsi_timings(struct drm_encoder *encoder,
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
        enum port port;
-       unsigned int bpp = dsi_pixel_format_bpp(intel_dsi->pixel_format);
+       unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
        unsigned int lane_count = intel_dsi->lane_count;
 
        u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp;
@@ -849,6 +880,23 @@ static void set_dsi_timings(struct drm_encoder *encoder,
        }
 }
 
+static u32 pixel_format_to_reg(enum mipi_dsi_pixel_format fmt)
+{
+       switch (fmt) {
+       case MIPI_DSI_FMT_RGB888:
+               return VID_MODE_FORMAT_RGB888;
+       case MIPI_DSI_FMT_RGB666:
+               return VID_MODE_FORMAT_RGB666;
+       case MIPI_DSI_FMT_RGB666_PACKED:
+               return VID_MODE_FORMAT_RGB666_PACKED;
+       case MIPI_DSI_FMT_RGB565:
+               return VID_MODE_FORMAT_RGB565;
+       default:
+               MISSING_CASE(fmt);
+               return VID_MODE_FORMAT_RGB666;
+       }
+}
+
 static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
 {
        struct drm_encoder *encoder = &intel_encoder->base;
@@ -858,7 +906,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
        const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
        enum port port;
-       unsigned int bpp = dsi_pixel_format_bpp(intel_dsi->pixel_format);
+       unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
        u32 val, tmp;
        u16 mode_hdisplay;
 
@@ -917,9 +965,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
                val |= CMD_MODE_DATA_WIDTH_8_BIT; /* XXX */
        } else {
                val |= intel_dsi->channel << VID_MODE_CHANNEL_NUMBER_SHIFT;
-
-               /* XXX: cross-check bpp vs. pixel format? */
-               val |= intel_dsi->pixel_format;
+               val |= pixel_format_to_reg(intel_dsi->pixel_format);
        }
 
        tmp = 0;
@@ -1121,11 +1167,13 @@ void intel_dsi_init(struct drm_device *dev)
        DRM_DEBUG_KMS("\n");
 
        /* There is no detection method for MIPI so rely on VBT */
-       if (!dev_priv->vbt.has_mipi)
+       if (!intel_bios_is_dsi_present(dev_priv, &port))
                return;
 
        if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
+       } else if (IS_BROXTON(dev)) {
+               dev_priv->mipi_mmio_base = BXT_MIPI_BASE;
        } else {
                DRM_ERROR("Unsupported Mipi device to reg base");
                return;
@@ -1161,17 +1209,21 @@ void intel_dsi_init(struct drm_device *dev)
        intel_connector->get_hw_state = intel_connector_get_hw_state;
        intel_connector->unregister = intel_connector_unregister;
 
-       /* Pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI port C */
-       if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIA) {
-               intel_encoder->crtc_mask = (1 << PIPE_A);
-               intel_dsi->ports = (1 << PORT_A);
-       } else if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIC) {
-               intel_encoder->crtc_mask = (1 << PIPE_B);
-               intel_dsi->ports = (1 << PORT_C);
-       }
+       /*
+        * On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI
+        * port C. BXT isn't limited like this.
+        */
+       if (IS_BROXTON(dev_priv))
+               intel_encoder->crtc_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C);
+       else if (port == PORT_A)
+               intel_encoder->crtc_mask = BIT(PIPE_A);
+       else
+               intel_encoder->crtc_mask = BIT(PIPE_B);
 
        if (dev_priv->vbt.dsi.config->dual_link)
-               intel_dsi->ports = ((1 << PORT_A) | (1 << PORT_C));
+               intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C);
+       else
+               intel_dsi->ports = BIT(port);
 
        /* Create a DSI host (and a device) for each port. */
        for_each_dsi_port(port, intel_dsi->ports) {
index 92f3922..ec58ead 100644 (file)
@@ -34,8 +34,6 @@
 #define DSI_DUAL_LINK_FRONT_BACK       1
 #define DSI_DUAL_LINK_PIXEL_ALT                2
 
-int dsi_pixel_format_bpp(int pixel_format);
-
 struct intel_dsi_host;
 
 struct intel_dsi {
@@ -64,8 +62,12 @@ struct intel_dsi {
        /* number of DSI lanes */
        unsigned int lane_count;
 
-       /* video mode pixel format for MIPI_DSI_FUNC_PRG register */
-       u32 pixel_format;
+       /*
+        * video mode pixel format
+        *
+        * XXX: consolidate on .format in struct mipi_dsi_device.
+        */
+       enum mipi_dsi_pixel_format pixel_format;
 
        /* video mode format for MIPI_VIDEO_MODE_FORMAT register */
        u32 video_mode_format;
@@ -117,15 +119,14 @@ static inline struct intel_dsi_host *to_intel_dsi_host(struct mipi_dsi_host *h)
        return container_of(h, struct intel_dsi_host, base);
 }
 
-#define for_each_dsi_port(__port, __ports_mask) \
-       for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++)  \
-               for_each_if ((__ports_mask) & (1 << (__port)))
+#define for_each_dsi_port(__port, __ports_mask) for_each_port_masked(__port, __ports_mask)
 
 static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
 {
        return container_of(encoder, struct intel_dsi, base.base);
 }
 
+bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv);
 extern void intel_enable_dsi_pll(struct intel_encoder *encoder);
 extern void intel_disable_dsi_pll(struct intel_encoder *encoder);
 extern u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp);
index 7f145b4..8302a97 100644 (file)
@@ -412,6 +412,25 @@ static const struct drm_panel_funcs vbt_panel_funcs = {
        .get_modes = vbt_panel_get_modes,
 };
 
+/* XXX: This should be done when parsing the VBT in intel_bios.c */
+static enum mipi_dsi_pixel_format pixel_format_from_vbt(u32 fmt)
+{
+       /* It just so happens the VBT matches register contents. */
+       switch (fmt) {
+       case VID_MODE_FORMAT_RGB888:
+               return MIPI_DSI_FMT_RGB888;
+       case VID_MODE_FORMAT_RGB666:
+               return MIPI_DSI_FMT_RGB666;
+       case VID_MODE_FORMAT_RGB666_PACKED:
+               return MIPI_DSI_FMT_RGB666_PACKED;
+       case VID_MODE_FORMAT_RGB565:
+               return MIPI_DSI_FMT_RGB565;
+       default:
+               MISSING_CASE(fmt);
+               return MIPI_DSI_FMT_RGB666;
+       }
+}
+
 struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
 {
        struct drm_device *dev = intel_dsi->base.base.dev;
@@ -420,7 +439,7 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
        struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps;
        struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode;
        struct vbt_panel *vbt_panel;
-       u32 bits_per_pixel = 24;
+       u32 bpp;
        u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui;
        u32 ui_num, ui_den;
        u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
@@ -436,12 +455,11 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
        intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
        intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
        intel_dsi->lane_count = mipi_config->lane_cnt + 1;
-       intel_dsi->pixel_format = mipi_config->videomode_color_format << 7;
+       intel_dsi->pixel_format = pixel_format_from_vbt(mipi_config->videomode_color_format << 7);
+       bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
+
        intel_dsi->dual_link = mipi_config->dual_link;
        intel_dsi->pixel_overlap = mipi_config->pixel_overlap;
-
-       bits_per_pixel = dsi_pixel_format_bpp(intel_dsi->pixel_format);
-
        intel_dsi->operation_mode = mipi_config->is_cmd_mode;
        intel_dsi->video_mode_format = mipi_config->video_transfer_mode;
        intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
@@ -475,8 +493,7 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
         */
        if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
                if (mipi_config->target_burst_mode_freq) {
-                       computed_ddr =
-                               (pclk * bits_per_pixel) / intel_dsi->lane_count;
+                       computed_ddr = (pclk * bpp) / intel_dsi->lane_count;
 
                        if (mipi_config->target_burst_mode_freq <
                                                                computed_ddr) {
@@ -499,7 +516,7 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
        intel_dsi->burst_mode_ratio = burst_mode_ratio;
        intel_dsi->pclk = pclk;
 
-       bitrate = (pclk * bits_per_pixel) / intel_dsi->lane_count;
+       bitrate = (pclk * bpp) / intel_dsi->lane_count;
 
        switch (intel_dsi->escape_clk_div) {
        case 0:
index 70883c5..4e53fcf 100644 (file)
 #include "i915_drv.h"
 #include "intel_dsi.h"
 
-int dsi_pixel_format_bpp(int pixel_format)
-{
-       int bpp;
-
-       switch (pixel_format) {
-       default:
-       case VID_MODE_FORMAT_RGB888:
-       case VID_MODE_FORMAT_RGB666_LOOSE:
-               bpp = 24;
-               break;
-       case VID_MODE_FORMAT_RGB666:
-               bpp = 18;
-               break;
-       case VID_MODE_FORMAT_RGB565:
-               bpp = 16;
-               break;
-       }
-
-       return bpp;
-}
-
 struct dsi_mnp {
        u32 dsi_pll_ctrl;
        u32 dsi_pll_div;
@@ -64,10 +43,11 @@ static const u32 lfsr_converts[] = {
 };
 
 /* Get DSI clock from pixel clock */
-static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count)
+static u32 dsi_clk_from_pclk(u32 pclk, enum mipi_dsi_pixel_format fmt,
+                            int lane_count)
 {
        u32 dsi_clk_khz;
-       u32 bpp = dsi_pixel_format_bpp(pixel_format);
+       u32 bpp = mipi_dsi_pixel_format_to_bpp(fmt);
 
        /* DSI data rate = pixel clock * bits per pixel / lane count
           pixel clock is converted from KHz to Hz */
@@ -212,6 +192,36 @@ static void vlv_disable_dsi_pll(struct intel_encoder *encoder)
        mutex_unlock(&dev_priv->sb_lock);
 }
 
+static bool bxt_dsi_pll_is_enabled(struct drm_i915_private *dev_priv)
+{
+       bool enabled;
+       u32 val;
+       u32 mask;
+
+       mask = BXT_DSI_PLL_DO_ENABLE | BXT_DSI_PLL_LOCKED;
+       val = I915_READ(BXT_DSI_PLL_ENABLE);
+       enabled = (val & mask) == mask;
+
+       if (!enabled)
+               return false;
+
+       /*
+        * Both dividers must be programmed with valid values even if only one
+        * of the PLL is used, see BSpec/Broxton Clocks. Check this here for
+        * paranoia, since BIOS is known to misconfigure PLLs in this way at
+        * times, and since accessing DSI registers with invalid dividers
+        * causes a system hang.
+        */
+       val = I915_READ(BXT_DSI_PLL_CTL);
+       if (!(val & BXT_DSIA_16X_MASK) || !(val & BXT_DSIC_16X_MASK)) {
+               DRM_DEBUG_DRIVER("PLL is enabled with invalid divider settings (%08x)\n",
+                                val);
+               enabled = false;
+       }
+
+       return enabled;
+}
+
 static void bxt_disable_dsi_pll(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@@ -232,9 +242,9 @@ static void bxt_disable_dsi_pll(struct intel_encoder *encoder)
                DRM_ERROR("Timeout waiting for PLL lock deassertion\n");
 }
 
-static void assert_bpp_mismatch(int pixel_format, int pipe_bpp)
+static void assert_bpp_mismatch(enum mipi_dsi_pixel_format fmt, int pipe_bpp)
 {
-       int bpp = dsi_pixel_format_bpp(pixel_format);
+       int bpp = mipi_dsi_pixel_format_to_bpp(fmt);
 
        WARN(bpp != pipe_bpp,
             "bpp match assertion failure (expected %d, current %d)\n",
@@ -362,35 +372,57 @@ static void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
 /* Program BXT Mipi clocks and dividers */
 static void bxt_dsi_program_clocks(struct drm_device *dev, enum port port)
 {
-       u32 tmp;
-       u32 divider;
-       u32 dsi_rate;
-       u32 pll_ratio;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp;
+       u32 dsi_rate = 0;
+       u32 pll_ratio = 0;
+       u32 rx_div;
+       u32 tx_div;
+       u32 rx_div_upper;
+       u32 rx_div_lower;
+       u32 mipi_8by3_divider;
 
        /* Clear old configurations */
        tmp = I915_READ(BXT_MIPI_CLOCK_CTL);
        tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port));
-       tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port));
-       tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port));
-       tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port));
+       tmp &= ~(BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port));
+       tmp &= ~(BXT_MIPI_8X_BY3_DIVIDER_MASK(port));
+       tmp &= ~(BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port));
 
        /* Get the current DSI rate(actual) */
        pll_ratio = I915_READ(BXT_DSI_PLL_CTL) &
                                BXT_DSI_PLL_RATIO_MASK;
        dsi_rate = (BXT_REF_CLOCK_KHZ * pll_ratio) / 2;
 
-       /* Max possible output of clock is 39.5 MHz, program value -1 */
-       divider = (dsi_rate / BXT_MAX_VAR_OUTPUT_KHZ) - 1;
-       tmp |= BXT_MIPI_ESCLK_VAR_DIV(port, divider);
+       /*
+        * tx clock should be <= 20MHz and the div value must be
+        * subtracted by 1 as per bspec
+        */
+       tx_div = DIV_ROUND_UP(dsi_rate, 20000) - 1;
+       /*
+        * rx clock should be <= 150MHz and the div value must be
+        * subtracted by 1 as per bspec
+        */
+       rx_div = DIV_ROUND_UP(dsi_rate, 150000) - 1;
 
        /*
-        * Tx escape clock must be as close to 20MHz possible, but should
-        * not exceed it. Hence select divide by 2
+        * rx divider value needs to be updated in the
+        * two differnt bit fields in the register hence splitting the
+        * rx divider value accordingly
         */
-       tmp |= BXT_MIPI_TX_ESCLK_8XDIV_BY2(port);
+       rx_div_lower = rx_div & RX_DIVIDER_BIT_1_2;
+       rx_div_upper = (rx_div & RX_DIVIDER_BIT_3_4) >> 2;
+
+       /* As per bpsec program the 8/3X clock divider to the below value */
+       if (dev_priv->vbt.dsi.config->is_cmd_mode)
+               mipi_8by3_divider = 0x2;
+       else
+               mipi_8by3_divider = 0x3;
 
-       tmp |= BXT_MIPI_RX_ESCLK_8X_BY3(port);
+       tmp |= BXT_MIPI_8X_BY3_DIVIDER(port, mipi_8by3_divider);
+       tmp |= BXT_MIPI_TX_ESCLK_DIVIDER(port, tx_div);
+       tmp |= BXT_MIPI_RX_ESCLK_LOWER_DIVIDER(port, rx_div_lower);
+       tmp |= BXT_MIPI_RX_ESCLK_UPPER_DIVIDER(port, rx_div_upper);
 
        I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp);
 }
@@ -484,6 +516,16 @@ static void bxt_enable_dsi_pll(struct intel_encoder *encoder)
        DRM_DEBUG_KMS("DSI PLL locked\n");
 }
 
+bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv)
+{
+       if (IS_BROXTON(dev_priv))
+               return bxt_dsi_pll_is_enabled(dev_priv);
+
+       MISSING_CASE(INTEL_DEVID(dev_priv));
+
+       return false;
+}
+
 void intel_enable_dsi_pll(struct intel_encoder *encoder)
 {
        struct drm_device *dev = encoder->base.dev;
@@ -513,9 +555,9 @@ static void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
        /* Clear old configurations */
        tmp = I915_READ(BXT_MIPI_CLOCK_CTL);
        tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port));
-       tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port));
-       tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port));
-       tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port));
+       tmp &= ~(BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port));
+       tmp &= ~(BXT_MIPI_8X_BY3_DIVIDER_MASK(port));
+       tmp &= ~(BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port));
        I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp);
        I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP);
 }
index 0f0492f..2e571f5 100644 (file)
@@ -516,9 +516,9 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
         * underruns, even if that range is not reserved by the BIOS. */
        if (IS_BROADWELL(dev_priv) ||
            IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
-               end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024;
+               end = dev_priv->ggtt.stolen_size - 8 * 1024 * 1024;
        else
-               end = dev_priv->gtt.stolen_usable_size;
+               end = dev_priv->ggtt.stolen_usable_size;
 
        /* HACK: This code depends on what we will do in *_enable_fbc. If that
         * code changes, this code needs to change as well.
index 97a91e6..153ea7a 100644 (file)
@@ -146,7 +146,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
        /* If the FB is too big, just don't use it since fbdev is not very
         * important and we should probably use that space with FBC or other
         * features. */
-       if (size * 2 < dev_priv->gtt.stolen_usable_size)
+       if (size * 2 < dev_priv->ggtt.stolen_usable_size)
                obj = i915_gem_object_create_stolen(dev, size);
        if (obj == NULL)
                obj = i915_gem_alloc_object(dev, size);
@@ -220,7 +220,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
         * This also validates that any existing fb inherited from the
         * BIOS is suitable for own access.
         */
-       ret = intel_pin_and_fence_fb_obj(NULL, &ifbdev->fb->base, NULL);
+       ret = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0));
        if (ret)
                goto out_unlock;
 
@@ -244,13 +244,13 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
        /* setup aperture base/size for vesafb takeover */
        info->apertures->ranges[0].base = dev->mode_config.fb_base;
-       info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
+       info->apertures->ranges[0].size = dev_priv->ggtt.mappable_end;
 
        info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj);
        info->fix.smem_len = size;
 
        info->screen_base =
-               ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
+               ioremap_wc(dev_priv->ggtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
                           size);
        if (!info->screen_base) {
                DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
@@ -379,6 +379,7 @@ retry:
                struct drm_connector *connector;
                struct drm_encoder *encoder;
                struct drm_fb_helper_crtc *new_crtc;
+               struct intel_crtc *intel_crtc;
 
                fb_conn = fb_helper->connector_info[i];
                connector = fb_conn->connector;
@@ -420,6 +421,13 @@ retry:
 
                num_connectors_enabled++;
 
+               intel_crtc = to_intel_crtc(connector->state->crtc);
+               for (j = 0; j < 256; j++) {
+                       intel_crtc->lut_r[j] = j;
+                       intel_crtc->lut_g[j] = j;
+                       intel_crtc->lut_b[j] = j;
+               }
+
                new_crtc = intel_fb_helper_crtc(fb_helper, connector->state->crtc);
 
                /*
@@ -800,6 +808,8 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
 void intel_fbdev_output_poll_changed(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+
+       async_synchronize_full();
        if (dev_priv->fbdev)
                drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
 }
@@ -811,6 +821,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)
        struct intel_fbdev *ifbdev = dev_priv->fbdev;
        struct drm_fb_helper *fb_helper;
 
+       async_synchronize_full();
        if (!ifbdev)
                return;
 
index bda5266..19e50fd 100644 (file)
@@ -212,7 +212,7 @@ static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
        I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
        POSTING_READ(SERR_INT);
 
-       DRM_ERROR("pch fifo underrun on pch transcoder %c\n",
+       DRM_ERROR("pch fifo underrun on pch transcoder %s\n",
                  transcoder_name(pch_transcoder));
 }
 
@@ -235,7 +235,7 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
 
                if (old && I915_READ(SERR_INT) &
                    SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
-                       DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
+                       DRM_ERROR("uncleared pch fifo underrun on pch transcoder %s\n",
                                  transcoder_name(pch_transcoder));
                }
        }
@@ -386,7 +386,7 @@ void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
 {
        if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
                                                  false))
-               DRM_ERROR("PCH transcoder %c FIFO underrun\n",
+               DRM_ERROR("PCH transcoder %s FIFO underrun\n",
                          transcoder_name(pch_transcoder));
 }
 
index 82a3c03..b4976f9 100644 (file)
@@ -59,7 +59,7 @@
  *
  */
 
-#define I915_SKL_GUC_UCODE "i915/skl_guc_ver4.bin"
+#define I915_SKL_GUC_UCODE "i915/skl_guc_ver6.bin"
 MODULE_FIRMWARE(I915_SKL_GUC_UCODE);
 
 /* User-friendly representation of an enum */
@@ -81,14 +81,14 @@ const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status)
 
 static void direct_interrupts_to_host(struct drm_i915_private *dev_priv)
 {
-       struct intel_engine_cs *ring;
-       int i, irqs;
+       struct intel_engine_cs *engine;
+       int irqs;
 
        /* tell all command streamers NOT to forward interrupts and vblank to GuC */
        irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER);
        irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING);
-       for_each_ring(ring, dev_priv, i)
-               I915_WRITE(RING_MODE_GEN7(ring), irqs);
+       for_each_engine(engine, dev_priv)
+               I915_WRITE(RING_MODE_GEN7(engine), irqs);
 
        /* route all GT interrupts to the host */
        I915_WRITE(GUC_BCS_RCS_IER, 0);
@@ -98,14 +98,14 @@ static void direct_interrupts_to_host(struct drm_i915_private *dev_priv)
 
 static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv)
 {
-       struct intel_engine_cs *ring;
-       int i, irqs;
+       struct intel_engine_cs *engine;
+       int irqs;
 
        /* tell all command streamers to forward interrupts and vblank to GuC */
        irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_ALWAYS);
        irqs |= _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING);
-       for_each_ring(ring, dev_priv, i)
-               I915_WRITE(RING_MODE_GEN7(ring), irqs);
+       for_each_engine(engine, dev_priv)
+               I915_WRITE(RING_MODE_GEN7(engine), irqs);
 
        /* route USER_INTERRUPT to Host, all others are sent to GuC. */
        irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
@@ -595,8 +595,8 @@ void intel_guc_ucode_init(struct drm_device *dev)
                fw_path = NULL;
        } else if (IS_SKYLAKE(dev)) {
                fw_path = I915_SKL_GUC_UCODE;
-               guc_fw->guc_fw_major_wanted = 4;
-               guc_fw->guc_fw_minor_wanted = 3;
+               guc_fw->guc_fw_major_wanted = 6;
+               guc_fw->guc_fw_minor_wanted = 1;
        } else {
                i915.enable_guc_submission = false;
                fw_path = "";   /* unknown device */
index a0d8dae..e2dab48 100644 (file)
@@ -952,9 +952,6 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
        if (pipe_config->pixel_multiplier)
                dotclock /= pipe_config->pixel_multiplier;
 
-       if (HAS_PCH_SPLIT(dev_priv->dev))
-               ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
        pipe_config->base.adjusted_mode.crtc_clock = dotclock;
 }
 
index 6a978ce..5d4ca3b 100644 (file)
@@ -228,8 +228,8 @@ enum {
 
 static int intel_lr_context_pin(struct intel_context *ctx,
                                struct intel_engine_cs *engine);
-static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
-               struct drm_i915_gem_object *default_ctx_obj);
+static void lrc_setup_hardware_status_page(struct intel_engine_cs *engine,
+                                          struct drm_i915_gem_object *default_ctx_obj);
 
 
 /**
@@ -266,20 +266,23 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists
 }
 
 static void
-logical_ring_init_platform_invariants(struct intel_engine_cs *ring)
+logical_ring_init_platform_invariants(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
 
-       ring->disable_lite_restore_wa = (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
+       if (IS_GEN8(dev) || IS_GEN9(dev))
+               engine->idle_lite_restore_wa = ~0;
+
+       engine->disable_lite_restore_wa = (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
                                        IS_BXT_REVID(dev, 0, BXT_REVID_A1)) &&
-                                       (ring->id == VCS || ring->id == VCS2);
+                                       (engine->id == VCS || engine->id == VCS2);
 
-       ring->ctx_desc_template = GEN8_CTX_VALID;
-       ring->ctx_desc_template |= GEN8_CTX_ADDRESSING_MODE(dev) <<
+       engine->ctx_desc_template = GEN8_CTX_VALID;
+       engine->ctx_desc_template |= GEN8_CTX_ADDRESSING_MODE(dev) <<
                                   GEN8_CTX_ADDRESSING_MODE_SHIFT;
        if (IS_GEN8(dev))
-               ring->ctx_desc_template |= GEN8_CTX_L3LLC_COHERENT;
-       ring->ctx_desc_template |= GEN8_CTX_PRIVILEGE;
+               engine->ctx_desc_template |= GEN8_CTX_L3LLC_COHERENT;
+       engine->ctx_desc_template |= GEN8_CTX_PRIVILEGE;
 
        /* TODO: WaDisableLiteRestore when we start using semaphore
         * signalling between Command Streamers */
@@ -287,8 +290,8 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *ring)
 
        /* WaEnableForceRestoreInCtxtDescForVCS:skl */
        /* WaEnableForceRestoreInCtxtDescForVCS:bxt */
-       if (ring->disable_lite_restore_wa)
-               ring->ctx_desc_template |= GEN8_CTX_FORCE_RESTORE;
+       if (engine->disable_lite_restore_wa)
+               engine->ctx_desc_template |= GEN8_CTX_FORCE_RESTORE;
 }
 
 /**
@@ -311,24 +314,24 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *ring)
  */
 static void
 intel_lr_context_descriptor_update(struct intel_context *ctx,
-                                  struct intel_engine_cs *ring)
+                                  struct intel_engine_cs *engine)
 {
        uint64_t lrca, desc;
 
-       lrca = ctx->engine[ring->id].lrc_vma->node.start +
+       lrca = ctx->engine[engine->id].lrc_vma->node.start +
               LRC_PPHWSP_PN * PAGE_SIZE;
 
-       desc = ring->ctx_desc_template;                    /* bits  0-11 */
+       desc = engine->ctx_desc_template;                          /* bits  0-11 */
        desc |= lrca;                                      /* bits 12-31 */
        desc |= (lrca >> PAGE_SHIFT) << GEN8_CTX_ID_SHIFT; /* bits 32-51 */
 
-       ctx->engine[ring->id].lrc_desc = desc;
+       ctx->engine[engine->id].lrc_desc = desc;
 }
 
 uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
-                                    struct intel_engine_cs *ring)
+                                    struct intel_engine_cs *engine)
 {
-       return ctx->engine[ring->id].lrc_desc;
+       return ctx->engine[engine->id].lrc_desc;
 }
 
 /**
@@ -348,98 +351,104 @@ uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
  * Return: 20-bits globally unique context ID.
  */
 u32 intel_execlists_ctx_id(struct intel_context *ctx,
-                          struct intel_engine_cs *ring)
+                          struct intel_engine_cs *engine)
 {
-       return intel_lr_context_descriptor(ctx, ring) >> GEN8_CTX_ID_SHIFT;
+       return intel_lr_context_descriptor(ctx, engine) >> GEN8_CTX_ID_SHIFT;
 }
 
 static void execlists_elsp_write(struct drm_i915_gem_request *rq0,
                                 struct drm_i915_gem_request *rq1)
 {
 
-       struct intel_engine_cs *ring = rq0->ring;
-       struct drm_device *dev = ring->dev;
+       struct intel_engine_cs *engine = rq0->engine;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint64_t desc[2];
 
        if (rq1) {
-               desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->ring);
+               desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->engine);
                rq1->elsp_submitted++;
        } else {
                desc[1] = 0;
        }
 
-       desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->ring);
+       desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->engine);
        rq0->elsp_submitted++;
 
        /* You must always write both descriptors in the order below. */
-       spin_lock(&dev_priv->uncore.lock);
-       intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL);
-       I915_WRITE_FW(RING_ELSP(ring), upper_32_bits(desc[1]));
-       I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[1]));
+       I915_WRITE_FW(RING_ELSP(engine), upper_32_bits(desc[1]));
+       I915_WRITE_FW(RING_ELSP(engine), lower_32_bits(desc[1]));
 
-       I915_WRITE_FW(RING_ELSP(ring), upper_32_bits(desc[0]));
+       I915_WRITE_FW(RING_ELSP(engine), upper_32_bits(desc[0]));
        /* The context is automatically loaded after the following */
-       I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[0]));
+       I915_WRITE_FW(RING_ELSP(engine), lower_32_bits(desc[0]));
 
        /* ELSP is a wo register, use another nearby reg for posting */
-       POSTING_READ_FW(RING_EXECLIST_STATUS_LO(ring));
-       intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL);
-       spin_unlock(&dev_priv->uncore.lock);
+       POSTING_READ_FW(RING_EXECLIST_STATUS_LO(engine));
+}
+
+static void
+execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state)
+{
+       ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
+       ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
+       ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
+       ASSIGN_CTX_PDP(ppgtt, reg_state, 0);
 }
 
-static int execlists_update_context(struct drm_i915_gem_request *rq)
+static void execlists_update_context(struct drm_i915_gem_request *rq)
 {
-       struct intel_engine_cs *ring = rq->ring;
+       struct intel_engine_cs *engine = rq->engine;
        struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt;
-       uint32_t *reg_state = rq->ctx->engine[ring->id].lrc_reg_state;
+       uint32_t *reg_state = rq->ctx->engine[engine->id].lrc_reg_state;
 
        reg_state[CTX_RING_TAIL+1] = rq->tail;
 
-       if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
-               /* True 32b PPGTT with dynamic page allocation: update PDP
-                * registers and point the unallocated PDPs to scratch page.
-                * PML4 is allocated during ppgtt init, so this is not needed
-                * in 48-bit mode.
-                */
-               ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
-               ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
-               ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
-               ASSIGN_CTX_PDP(ppgtt, reg_state, 0);
-       }
-
-       return 0;
+       /* True 32b PPGTT with dynamic page allocation: update PDP
+        * registers and point the unallocated PDPs to scratch page.
+        * PML4 is allocated during ppgtt init, so this is not needed
+        * in 48-bit mode.
+        */
+       if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
+               execlists_update_context_pdps(ppgtt, reg_state);
 }
 
 static void execlists_submit_requests(struct drm_i915_gem_request *rq0,
                                      struct drm_i915_gem_request *rq1)
 {
+       struct drm_i915_private *dev_priv = rq0->i915;
+
+       /* BUG_ON(!irqs_disabled());  */
+
        execlists_update_context(rq0);
 
        if (rq1)
                execlists_update_context(rq1);
 
+       spin_lock(&dev_priv->uncore.lock);
+       intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL);
+
        execlists_elsp_write(rq0, rq1);
+
+       intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL);
+       spin_unlock(&dev_priv->uncore.lock);
 }
 
-static void execlists_context_unqueue(struct intel_engine_cs *ring)
+static void execlists_context_unqueue(struct intel_engine_cs *engine)
 {
        struct drm_i915_gem_request *req0 = NULL, *req1 = NULL;
-       struct drm_i915_gem_request *cursor = NULL, *tmp = NULL;
+       struct drm_i915_gem_request *cursor, *tmp;
 
-       assert_spin_locked(&ring->execlist_lock);
+       assert_spin_locked(&engine->execlist_lock);
 
        /*
         * If irqs are not active generate a warning as batches that finish
         * without the irqs may get lost and a GPU Hang may occur.
         */
-       WARN_ON(!intel_irqs_enabled(ring->dev->dev_private));
-
-       if (list_empty(&ring->execlist_queue))
-               return;
+       WARN_ON(!intel_irqs_enabled(engine->dev->dev_private));
 
        /* Try to read in pairs */
-       list_for_each_entry_safe(cursor, tmp, &ring->execlist_queue,
+       list_for_each_entry_safe(cursor, tmp, &engine->execlist_queue,
                                 execlist_link) {
                if (!req0) {
                        req0 = cursor;
@@ -448,77 +457,83 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)
                         * will update tail past first request's workload */
                        cursor->elsp_submitted = req0->elsp_submitted;
                        list_move_tail(&req0->execlist_link,
-                                      &ring->execlist_retired_req_list);
+                                      &engine->execlist_retired_req_list);
                        req0 = cursor;
                } else {
                        req1 = cursor;
+                       WARN_ON(req1->elsp_submitted);
                        break;
                }
        }
 
-       if (IS_GEN8(ring->dev) || IS_GEN9(ring->dev)) {
+       if (unlikely(!req0))
+               return;
+
+       if (req0->elsp_submitted & engine->idle_lite_restore_wa) {
                /*
-                * WaIdleLiteRestore: make sure we never cause a lite
-                * restore with HEAD==TAIL
+                * WaIdleLiteRestore: make sure we never cause a lite restore
+                * with HEAD==TAIL.
+                *
+                * Apply the wa NOOPS to prevent ring:HEAD == req:TAIL as we
+                * resubmit the request. See gen8_emit_request() for where we
+                * prepare the padding after the end of the request.
                 */
-               if (req0->elsp_submitted) {
-                       /*
-                        * Apply the wa NOOPS to prevent ring:HEAD == req:TAIL
-                        * as we resubmit the request. See gen8_emit_request()
-                        * for where we prepare the padding after the end of the
-                        * request.
-                        */
-                       struct intel_ringbuffer *ringbuf;
+               struct intel_ringbuffer *ringbuf;
 
-                       ringbuf = req0->ctx->engine[ring->id].ringbuf;
-                       req0->tail += 8;
-                       req0->tail &= ringbuf->size - 1;
-               }
+               ringbuf = req0->ctx->engine[engine->id].ringbuf;
+               req0->tail += 8;
+               req0->tail &= ringbuf->size - 1;
        }
 
-       WARN_ON(req1 && req1->elsp_submitted);
-
        execlists_submit_requests(req0, req1);
 }
 
-static bool execlists_check_remove_request(struct intel_engine_cs *ring,
-                                          u32 request_id)
+static unsigned int
+execlists_check_remove_request(struct intel_engine_cs *engine, u32 request_id)
 {
        struct drm_i915_gem_request *head_req;
 
-       assert_spin_locked(&ring->execlist_lock);
+       assert_spin_locked(&engine->execlist_lock);
 
-       head_req = list_first_entry_or_null(&ring->execlist_queue,
+       head_req = list_first_entry_or_null(&engine->execlist_queue,
                                            struct drm_i915_gem_request,
                                            execlist_link);
 
-       if (head_req != NULL) {
-               if (intel_execlists_ctx_id(head_req->ctx, ring) == request_id) {
-                       WARN(head_req->elsp_submitted == 0,
-                            "Never submitted head request\n");
+       if (!head_req)
+               return 0;
 
-                       if (--head_req->elsp_submitted <= 0) {
-                               list_move_tail(&head_req->execlist_link,
-                                              &ring->execlist_retired_req_list);
-                               return true;
-                       }
-               }
-       }
+       if (unlikely(intel_execlists_ctx_id(head_req->ctx, engine) != request_id))
+               return 0;
+
+       WARN(head_req->elsp_submitted == 0, "Never submitted head request\n");
+
+       if (--head_req->elsp_submitted > 0)
+               return 0;
+
+       list_move_tail(&head_req->execlist_link,
+                      &engine->execlist_retired_req_list);
 
-       return false;
+       return 1;
 }
 
-static void get_context_status(struct intel_engine_cs *ring,
-                              u8 read_pointer,
-                              u32 *status, u32 *context_id)
+static u32
+get_context_status(struct intel_engine_cs *engine, unsigned int read_pointer,
+                  u32 *context_id)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
+       u32 status;
 
-       if (WARN_ON(read_pointer >= GEN8_CSB_ENTRIES))
-               return;
+       read_pointer %= GEN8_CSB_ENTRIES;
 
-       *status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer));
-       *context_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer));
+       status = I915_READ_FW(RING_CONTEXT_STATUS_BUF_LO(engine, read_pointer));
+
+       if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
+               return 0;
+
+       *context_id = I915_READ_FW(RING_CONTEXT_STATUS_BUF_HI(engine,
+                                                             read_pointer));
+
+       return status;
 }
 
 /**
@@ -528,92 +543,94 @@ static void get_context_status(struct intel_engine_cs *ring,
  * Check the unread Context Status Buffers and manage the submission of new
  * contexts to the ELSP accordingly.
  */
-void intel_lrc_irq_handler(struct intel_engine_cs *ring)
+void intel_lrc_irq_handler(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        u32 status_pointer;
-       u8 read_pointer;
-       u8 write_pointer;
-       u32 status = 0;
-       u32 status_id;
-       u32 submit_contexts = 0;
+       unsigned int read_pointer, write_pointer;
+       u32 csb[GEN8_CSB_ENTRIES][2];
+       unsigned int csb_read = 0, i;
+       unsigned int submit_contexts = 0;
+
+       spin_lock(&dev_priv->uncore.lock);
+       intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL);
 
-       status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
+       status_pointer = I915_READ_FW(RING_CONTEXT_STATUS_PTR(engine));
 
-       read_pointer = ring->next_context_status_buffer;
+       read_pointer = engine->next_context_status_buffer;
        write_pointer = GEN8_CSB_WRITE_PTR(status_pointer);
        if (read_pointer > write_pointer)
                write_pointer += GEN8_CSB_ENTRIES;
 
-       spin_lock(&ring->execlist_lock);
-
        while (read_pointer < write_pointer) {
+               if (WARN_ON_ONCE(csb_read == GEN8_CSB_ENTRIES))
+                       break;
+               csb[csb_read][0] = get_context_status(engine, ++read_pointer,
+                                                     &csb[csb_read][1]);
+               csb_read++;
+       }
 
-               get_context_status(ring, ++read_pointer % GEN8_CSB_ENTRIES,
-                                  &status, &status_id);
+       engine->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES;
 
-               if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
-                       continue;
+       /* Update the read pointer to the old write pointer. Manual ringbuffer
+        * management ftw </sarcasm> */
+       I915_WRITE_FW(RING_CONTEXT_STATUS_PTR(engine),
+                     _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK,
+                                   engine->next_context_status_buffer << 8));
 
-               if (status & GEN8_CTX_STATUS_PREEMPTED) {
-                       if (status & GEN8_CTX_STATUS_LITE_RESTORE) {
-                               if (execlists_check_remove_request(ring, status_id))
+       intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL);
+       spin_unlock(&dev_priv->uncore.lock);
+
+       spin_lock(&engine->execlist_lock);
+
+       for (i = 0; i < csb_read; i++) {
+               if (unlikely(csb[i][0] & GEN8_CTX_STATUS_PREEMPTED)) {
+                       if (csb[i][0] & GEN8_CTX_STATUS_LITE_RESTORE) {
+                               if (execlists_check_remove_request(engine, csb[i][1]))
                                        WARN(1, "Lite Restored request removed from queue\n");
                        } else
                                WARN(1, "Preemption without Lite Restore\n");
                }
 
-               if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) ||
-                   (status & GEN8_CTX_STATUS_ELEMENT_SWITCH)) {
-                       if (execlists_check_remove_request(ring, status_id))
-                               submit_contexts++;
-               }
+               if (csb[i][0] & (GEN8_CTX_STATUS_ACTIVE_IDLE |
+                   GEN8_CTX_STATUS_ELEMENT_SWITCH))
+                       submit_contexts +=
+                               execlists_check_remove_request(engine, csb[i][1]);
        }
 
-       if (ring->disable_lite_restore_wa) {
-               /* Prevent a ctx to preempt itself */
-               if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) &&
-                   (submit_contexts != 0))
-                       execlists_context_unqueue(ring);
-       } else if (submit_contexts != 0) {
-               execlists_context_unqueue(ring);
+       if (submit_contexts) {
+               if (!engine->disable_lite_restore_wa ||
+                   (csb[i][0] & GEN8_CTX_STATUS_ACTIVE_IDLE))
+                       execlists_context_unqueue(engine);
        }
 
-       spin_unlock(&ring->execlist_lock);
+       spin_unlock(&engine->execlist_lock);
 
        if (unlikely(submit_contexts > 2))
                DRM_ERROR("More than two context complete events?\n");
-
-       ring->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES;
-
-       /* Update the read pointer to the old write pointer. Manual ringbuffer
-        * management ftw </sarcasm> */
-       I915_WRITE(RING_CONTEXT_STATUS_PTR(ring),
-                  _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK,
-                                ring->next_context_status_buffer << 8));
 }
 
-static int execlists_context_queue(struct drm_i915_gem_request *request)
+static void execlists_context_queue(struct drm_i915_gem_request *request)
 {
-       struct intel_engine_cs *ring = request->ring;
+       struct intel_engine_cs *engine = request->engine;
        struct drm_i915_gem_request *cursor;
        int num_elements = 0;
 
        if (request->ctx != request->i915->kernel_context)
-               intel_lr_context_pin(request->ctx, ring);
+               intel_lr_context_pin(request->ctx, engine);
 
        i915_gem_request_reference(request);
 
-       spin_lock_irq(&ring->execlist_lock);
+       spin_lock_irq(&engine->execlist_lock);
 
-       list_for_each_entry(cursor, &ring->execlist_queue, execlist_link)
+       list_for_each_entry(cursor, &engine->execlist_queue, execlist_link)
                if (++num_elements > 2)
                        break;
 
        if (num_elements > 2) {
                struct drm_i915_gem_request *tail_req;
 
-               tail_req = list_last_entry(&ring->execlist_queue,
+               tail_req = list_last_entry(&engine->execlist_queue,
                                           struct drm_i915_gem_request,
                                           execlist_link);
 
@@ -621,41 +638,39 @@ static int execlists_context_queue(struct drm_i915_gem_request *request)
                        WARN(tail_req->elsp_submitted != 0,
                                "More than 2 already-submitted reqs queued\n");
                        list_move_tail(&tail_req->execlist_link,
-                                      &ring->execlist_retired_req_list);
+                                      &engine->execlist_retired_req_list);
                }
        }
 
-       list_add_tail(&request->execlist_link, &ring->execlist_queue);
+       list_add_tail(&request->execlist_link, &engine->execlist_queue);
        if (num_elements == 0)
-               execlists_context_unqueue(ring);
-
-       spin_unlock_irq(&ring->execlist_lock);
+               execlists_context_unqueue(engine);
 
-       return 0;
+       spin_unlock_irq(&engine->execlist_lock);
 }
 
 static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        uint32_t flush_domains;
        int ret;
 
        flush_domains = 0;
-       if (ring->gpu_caches_dirty)
+       if (engine->gpu_caches_dirty)
                flush_domains = I915_GEM_GPU_DOMAINS;
 
-       ret = ring->emit_flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
+       ret = engine->emit_flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
        if (ret)
                return ret;
 
-       ring->gpu_caches_dirty = false;
+       engine->gpu_caches_dirty = false;
        return 0;
 }
 
 static int execlists_move_to_gpu(struct drm_i915_gem_request *req,
                                 struct list_head *vmas)
 {
-       const unsigned other_rings = ~intel_ring_flag(req->ring);
+       const unsigned other_rings = ~intel_engine_flag(req->engine);
        struct i915_vma *vma;
        uint32_t flush_domains = 0;
        bool flush_chipset = false;
@@ -665,7 +680,7 @@ static int execlists_move_to_gpu(struct drm_i915_gem_request *req,
                struct drm_i915_gem_object *obj = vma->obj;
 
                if (obj->active & other_rings) {
-                       ret = i915_gem_object_sync(obj, req->ring, &req);
+                       ret = i915_gem_object_sync(obj, req->engine, &req);
                        if (ret)
                                return ret;
                }
@@ -689,7 +704,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
 {
        int ret = 0;
 
-       request->ringbuf = request->ctx->engine[request->ring->id].ringbuf;
+       request->ringbuf = request->ctx->engine[request->engine->id].ringbuf;
 
        if (i915.enable_guc_submission) {
                /*
@@ -705,7 +720,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
        }
 
        if (request->ctx != request->i915->kernel_context)
-               ret = intel_lr_context_pin(request->ctx, request->ring);
+               ret = intel_lr_context_pin(request->ctx, request->engine);
 
        return ret;
 }
@@ -714,7 +729,7 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req,
                                       int bytes)
 {
        struct intel_ringbuffer *ringbuf = req->ringbuf;
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct drm_i915_gem_request *target;
        unsigned space;
        int ret;
@@ -725,7 +740,7 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req,
        /* The whole point of reserving space is to not wait! */
        WARN_ON(ringbuf->reserved_in_use);
 
-       list_for_each_entry(target, &ring->request_list, list) {
+       list_for_each_entry(target, &engine->request_list, list) {
                /*
                 * The request queue is per-engine, so can contain requests
                 * from multiple ringbuffers. Here, we must ignore any that
@@ -741,7 +756,7 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req,
                        break;
        }
 
-       if (WARN_ON(&target->list == &ring->request_list))
+       if (WARN_ON(&target->list == &engine->request_list))
                return -ENOSPC;
 
        ret = i915_wait_request(target);
@@ -766,7 +781,7 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
 {
        struct intel_ringbuffer *ringbuf = request->ringbuf;
        struct drm_i915_private *dev_priv = request->i915;
-       struct intel_engine_cs *engine = request->ring;
+       struct intel_engine_cs *engine = request->engine;
 
        intel_logical_ring_advance(ringbuf);
        request->tail = ringbuf->tail;
@@ -781,7 +796,7 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
        intel_logical_ring_emit(ringbuf, MI_NOOP);
        intel_logical_ring_advance(ringbuf);
 
-       if (intel_ring_stopped(engine))
+       if (intel_engine_stopped(engine))
                return 0;
 
        if (engine->last_context != request->ctx) {
@@ -883,7 +898,7 @@ int intel_logical_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
        int ret;
 
        WARN_ON(req == NULL);
-       dev_priv = req->ring->dev->dev_private;
+       dev_priv = req->i915;
 
        ret = i915_gem_check_wedge(&dev_priv->gpu_error,
                                   dev_priv->mm.interruptible);
@@ -935,9 +950,9 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
                               struct list_head *vmas)
 {
        struct drm_device       *dev = params->dev;
-       struct intel_engine_cs  *ring = params->ring;
+       struct intel_engine_cs *engine = params->engine;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_ringbuffer *ringbuf = params->ctx->engine[ring->id].ringbuf;
+       struct intel_ringbuffer *ringbuf = params->ctx->engine[engine->id].ringbuf;
        u64 exec_start;
        int instp_mode;
        u32 instp_mask;
@@ -949,7 +964,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
        case I915_EXEC_CONSTANTS_REL_GENERAL:
        case I915_EXEC_CONSTANTS_ABSOLUTE:
        case I915_EXEC_CONSTANTS_REL_SURFACE:
-               if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) {
+               if (instp_mode != 0 && engine != &dev_priv->engine[RCS]) {
                        DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
                        return -EINVAL;
                }
@@ -978,7 +993,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
        if (ret)
                return ret;
 
-       if (ring == &dev_priv->ring[RCS] &&
+       if (engine == &dev_priv->engine[RCS] &&
            instp_mode != dev_priv->relative_constants_mode) {
                ret = intel_logical_ring_begin(params->request, 4);
                if (ret)
@@ -996,7 +1011,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
        exec_start = params->batch_obj_vm_offset +
                     args->batch_start_offset;
 
-       ret = ring->emit_bb_start(params->request, exec_start, params->dispatch_flags);
+       ret = engine->emit_bb_start(params->request, exec_start, params->dispatch_flags);
        if (ret)
                return ret;
 
@@ -1008,83 +1023,83 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
        return 0;
 }
 
-void intel_execlists_retire_requests(struct intel_engine_cs *ring)
+void intel_execlists_retire_requests(struct intel_engine_cs *engine)
 {
        struct drm_i915_gem_request *req, *tmp;
        struct list_head retired_list;
 
-       WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex));
-       if (list_empty(&ring->execlist_retired_req_list))
+       WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex));
+       if (list_empty(&engine->execlist_retired_req_list))
                return;
 
        INIT_LIST_HEAD(&retired_list);
-       spin_lock_irq(&ring->execlist_lock);
-       list_replace_init(&ring->execlist_retired_req_list, &retired_list);
-       spin_unlock_irq(&ring->execlist_lock);
+       spin_lock_irq(&engine->execlist_lock);
+       list_replace_init(&engine->execlist_retired_req_list, &retired_list);
+       spin_unlock_irq(&engine->execlist_lock);
 
        list_for_each_entry_safe(req, tmp, &retired_list, execlist_link) {
                struct intel_context *ctx = req->ctx;
                struct drm_i915_gem_object *ctx_obj =
-                               ctx->engine[ring->id].state;
+                               ctx->engine[engine->id].state;
 
                if (ctx_obj && (ctx != req->i915->kernel_context))
-                       intel_lr_context_unpin(ctx, ring);
+                       intel_lr_context_unpin(ctx, engine);
 
                list_del(&req->execlist_link);
                i915_gem_request_unreference(req);
        }
 }
 
-void intel_logical_ring_stop(struct intel_engine_cs *ring)
+void intel_logical_ring_stop(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        int ret;
 
-       if (!intel_ring_initialized(ring))
+       if (!intel_engine_initialized(engine))
                return;
 
-       ret = intel_ring_idle(ring);
-       if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error))
+       ret = intel_engine_idle(engine);
+       if (ret && !i915_reset_in_progress(&to_i915(engine->dev)->gpu_error))
                DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
-                         ring->name, ret);
+                         engine->name, ret);
 
        /* TODO: Is this correct with Execlists enabled? */
-       I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
-       if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
-               DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
+       I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING));
+       if (wait_for((I915_READ_MODE(engine) & MODE_IDLE) != 0, 1000)) {
+               DRM_ERROR("%s :timed out trying to stop ring\n", engine->name);
                return;
        }
-       I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING));
+       I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
 }
 
 int logical_ring_flush_all_caches(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
-       if (!ring->gpu_caches_dirty)
+       if (!engine->gpu_caches_dirty)
                return 0;
 
-       ret = ring->emit_flush(req, 0, I915_GEM_GPU_DOMAINS);
+       ret = engine->emit_flush(req, 0, I915_GEM_GPU_DOMAINS);
        if (ret)
                return ret;
 
-       ring->gpu_caches_dirty = false;
+       engine->gpu_caches_dirty = false;
        return 0;
 }
 
 static int intel_lr_context_do_pin(struct intel_context *ctx,
-                                  struct intel_engine_cs *ring)
+                                  struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state;
-       struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf;
+       struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
+       struct intel_ringbuffer *ringbuf = ctx->engine[engine->id].ringbuf;
        struct page *lrc_state_page;
        uint32_t *lrc_reg_state;
        int ret;
 
-       WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex));
+       WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex));
 
        ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN,
                        PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
@@ -1097,15 +1112,15 @@ static int intel_lr_context_do_pin(struct intel_context *ctx,
                goto unpin_ctx_obj;
        }
 
-       ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf);
+       ret = intel_pin_and_map_ringbuffer_obj(engine->dev, ringbuf);
        if (ret)
                goto unpin_ctx_obj;
 
-       ctx->engine[ring->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj);
-       intel_lr_context_descriptor_update(ctx, ring);
+       ctx->engine[engine->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj);
+       intel_lr_context_descriptor_update(ctx, engine);
        lrc_reg_state = kmap(lrc_state_page);
        lrc_reg_state[CTX_RING_BUFFER_START+1] = ringbuf->vma->node.start;
-       ctx->engine[ring->id].lrc_reg_state = lrc_reg_state;
+       ctx->engine[engine->id].lrc_reg_state = lrc_reg_state;
        ctx_obj->dirty = true;
 
        /* Invalidate GuC TLB. */
@@ -1160,16 +1175,16 @@ void intel_lr_context_unpin(struct intel_context *ctx,
 static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
 {
        int ret, i;
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct intel_ringbuffer *ringbuf = req->ringbuf;
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_workarounds *w = &dev_priv->workarounds;
 
        if (w->count == 0)
                return 0;
 
-       ring->gpu_caches_dirty = true;
+       engine->gpu_caches_dirty = true;
        ret = logical_ring_flush_all_caches(req);
        if (ret)
                return ret;
@@ -1187,7 +1202,7 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
 
        intel_logical_ring_advance(ringbuf);
 
-       ring->gpu_caches_dirty = true;
+       engine->gpu_caches_dirty = true;
        ret = logical_ring_flush_all_caches(req);
        if (ret)
                return ret;
@@ -1223,7 +1238,7 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
  * This WA is also required for Gen9 so extracting as a function avoids
  * code duplication.
  */
-static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring,
+static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine,
                                                uint32_t *const batch,
                                                uint32_t index)
 {
@@ -1235,13 +1250,13 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring,
         * this batch updates GEN8_L3SQCREG4 with default value we need to
         * set this bit here to retain the WA during flush.
         */
-       if (IS_SKL_REVID(ring->dev, 0, SKL_REVID_E0))
+       if (IS_SKL_REVID(engine->dev, 0, SKL_REVID_E0))
                l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS;
 
        wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
                                   MI_SRM_LRM_GLOBAL_GTT));
        wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
-       wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256);
+       wa_ctx_emit(batch, index, engine->scratch.gtt_offset + 256);
        wa_ctx_emit(batch, index, 0);
 
        wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1));
@@ -1259,7 +1274,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring,
        wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8 |
                                   MI_SRM_LRM_GLOBAL_GTT));
        wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
-       wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256);
+       wa_ctx_emit(batch, index, engine->scratch.gtt_offset + 256);
        wa_ctx_emit(batch, index, 0);
 
        return index;
@@ -1312,7 +1327,7 @@ static inline int wa_ctx_end(struct i915_wa_ctx_bb *wa_ctx,
  * Return: non-zero if we exceed the PAGE_SIZE limit.
  */
 
-static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring,
+static int gen8_init_indirectctx_bb(struct intel_engine_cs *engine,
                                    struct i915_wa_ctx_bb *wa_ctx,
                                    uint32_t *const batch,
                                    uint32_t *offset)
@@ -1324,8 +1339,8 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring,
        wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE);
 
        /* WaFlushCoherentL3CacheLinesAtContextSwitch:bdw */
-       if (IS_BROADWELL(ring->dev)) {
-               int rc = gen8_emit_flush_coherentl3_wa(ring, batch, index);
+       if (IS_BROADWELL(engine->dev)) {
+               int rc = gen8_emit_flush_coherentl3_wa(engine, batch, index);
                if (rc < 0)
                        return rc;
                index = rc;
@@ -1333,7 +1348,7 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring,
 
        /* WaClearSlmSpaceAtContextSwitch:bdw,chv */
        /* Actual scratch location is at 128 bytes offset */
-       scratch_addr = ring->scratch.gtt_offset + 2*CACHELINE_BYTES;
+       scratch_addr = engine->scratch.gtt_offset + 2*CACHELINE_BYTES;
 
        wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6));
        wa_ctx_emit(batch, index, (PIPE_CONTROL_FLUSH_L3 |
@@ -1375,7 +1390,7 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring,
  *  This batch is terminated with MI_BATCH_BUFFER_END and so we need not add padding
  *  to align it with cacheline as padding after MI_BATCH_BUFFER_END is redundant.
  */
-static int gen8_init_perctx_bb(struct intel_engine_cs *ring,
+static int gen8_init_perctx_bb(struct intel_engine_cs *engine,
                               struct i915_wa_ctx_bb *wa_ctx,
                               uint32_t *const batch,
                               uint32_t *offset)
@@ -1390,13 +1405,13 @@ static int gen8_init_perctx_bb(struct intel_engine_cs *ring,
        return wa_ctx_end(wa_ctx, *offset = index, 1);
 }
 
-static int gen9_init_indirectctx_bb(struct intel_engine_cs *ring,
+static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine,
                                    struct i915_wa_ctx_bb *wa_ctx,
                                    uint32_t *const batch,
                                    uint32_t *offset)
 {
        int ret;
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
 
        /* WaDisableCtxRestoreArbitration:skl,bxt */
@@ -1405,7 +1420,7 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *ring,
                wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE);
 
        /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */
-       ret = gen8_emit_flush_coherentl3_wa(ring, batch, index);
+       ret = gen8_emit_flush_coherentl3_wa(engine, batch, index);
        if (ret < 0)
                return ret;
        index = ret;
@@ -1417,12 +1432,12 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *ring,
        return wa_ctx_end(wa_ctx, *offset = index, CACHELINE_DWORDS);
 }
 
-static int gen9_init_perctx_bb(struct intel_engine_cs *ring,
+static int gen9_init_perctx_bb(struct intel_engine_cs *engine,
                               struct i915_wa_ctx_bb *wa_ctx,
                               uint32_t *const batch,
                               uint32_t *offset)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
 
        /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
@@ -1445,60 +1460,61 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *ring,
        return wa_ctx_end(wa_ctx, *offset = index, 1);
 }
 
-static int lrc_setup_wa_ctx_obj(struct intel_engine_cs *ring, u32 size)
+static int lrc_setup_wa_ctx_obj(struct intel_engine_cs *engine, u32 size)
 {
        int ret;
 
-       ring->wa_ctx.obj = i915_gem_alloc_object(ring->dev, PAGE_ALIGN(size));
-       if (!ring->wa_ctx.obj) {
+       engine->wa_ctx.obj = i915_gem_alloc_object(engine->dev,
+                                                  PAGE_ALIGN(size));
+       if (!engine->wa_ctx.obj) {
                DRM_DEBUG_DRIVER("alloc LRC WA ctx backing obj failed.\n");
                return -ENOMEM;
        }
 
-       ret = i915_gem_obj_ggtt_pin(ring->wa_ctx.obj, PAGE_SIZE, 0);
+       ret = i915_gem_obj_ggtt_pin(engine->wa_ctx.obj, PAGE_SIZE, 0);
        if (ret) {
                DRM_DEBUG_DRIVER("pin LRC WA ctx backing obj failed: %d\n",
                                 ret);
-               drm_gem_object_unreference(&ring->wa_ctx.obj->base);
+               drm_gem_object_unreference(&engine->wa_ctx.obj->base);
                return ret;
        }
 
        return 0;
 }
 
-static void lrc_destroy_wa_ctx_obj(struct intel_engine_cs *ring)
+static void lrc_destroy_wa_ctx_obj(struct intel_engine_cs *engine)
 {
-       if (ring->wa_ctx.obj) {
-               i915_gem_object_ggtt_unpin(ring->wa_ctx.obj);
-               drm_gem_object_unreference(&ring->wa_ctx.obj->base);
-               ring->wa_ctx.obj = NULL;
+       if (engine->wa_ctx.obj) {
+               i915_gem_object_ggtt_unpin(engine->wa_ctx.obj);
+               drm_gem_object_unreference(&engine->wa_ctx.obj->base);
+               engine->wa_ctx.obj = NULL;
        }
 }
 
-static int intel_init_workaround_bb(struct intel_engine_cs *ring)
+static int intel_init_workaround_bb(struct intel_engine_cs *engine)
 {
        int ret;
        uint32_t *batch;
        uint32_t offset;
        struct page *page;
-       struct i915_ctx_workarounds *wa_ctx = &ring->wa_ctx;
+       struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx;
 
-       WARN_ON(ring->id != RCS);
+       WARN_ON(engine->id != RCS);
 
        /* update this when WA for higher Gen are added */
-       if (INTEL_INFO(ring->dev)->gen > 9) {
+       if (INTEL_INFO(engine->dev)->gen > 9) {
                DRM_ERROR("WA batch buffer is not initialized for Gen%d\n",
-                         INTEL_INFO(ring->dev)->gen);
+                         INTEL_INFO(engine->dev)->gen);
                return 0;
        }
 
        /* some WA perform writes to scratch page, ensure it is valid */
-       if (ring->scratch.obj == NULL) {
-               DRM_ERROR("scratch page not allocated for %s\n", ring->name);
+       if (engine->scratch.obj == NULL) {
+               DRM_ERROR("scratch page not allocated for %s\n", engine->name);
                return -EINVAL;
        }
 
-       ret = lrc_setup_wa_ctx_obj(ring, PAGE_SIZE);
+       ret = lrc_setup_wa_ctx_obj(engine, PAGE_SIZE);
        if (ret) {
                DRM_DEBUG_DRIVER("Failed to setup context WA page: %d\n", ret);
                return ret;
@@ -1508,29 +1524,29 @@ static int intel_init_workaround_bb(struct intel_engine_cs *ring)
        batch = kmap_atomic(page);
        offset = 0;
 
-       if (INTEL_INFO(ring->dev)->gen == 8) {
-               ret = gen8_init_indirectctx_bb(ring,
+       if (INTEL_INFO(engine->dev)->gen == 8) {
+               ret = gen8_init_indirectctx_bb(engine,
                                               &wa_ctx->indirect_ctx,
                                               batch,
                                               &offset);
                if (ret)
                        goto out;
 
-               ret = gen8_init_perctx_bb(ring,
+               ret = gen8_init_perctx_bb(engine,
                                          &wa_ctx->per_ctx,
                                          batch,
                                          &offset);
                if (ret)
                        goto out;
-       } else if (INTEL_INFO(ring->dev)->gen == 9) {
-               ret = gen9_init_indirectctx_bb(ring,
+       } else if (INTEL_INFO(engine->dev)->gen == 9) {
+               ret = gen9_init_indirectctx_bb(engine,
                                               &wa_ctx->indirect_ctx,
                                               batch,
                                               &offset);
                if (ret)
                        goto out;
 
-               ret = gen9_init_perctx_bb(ring,
+               ret = gen9_init_perctx_bb(engine,
                                          &wa_ctx->per_ctx,
                                          batch,
                                          &offset);
@@ -1541,27 +1557,28 @@ static int intel_init_workaround_bb(struct intel_engine_cs *ring)
 out:
        kunmap_atomic(batch);
        if (ret)
-               lrc_destroy_wa_ctx_obj(ring);
+               lrc_destroy_wa_ctx_obj(engine);
 
        return ret;
 }
 
-static int gen8_init_common_ring(struct intel_engine_cs *ring)
+static int gen8_init_common_ring(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u8 next_context_status_buffer_hw;
+       unsigned int next_context_status_buffer_hw;
 
-       lrc_setup_hardware_status_page(ring,
-                               dev_priv->kernel_context->engine[ring->id].state);
+       lrc_setup_hardware_status_page(engine,
+                                      dev_priv->kernel_context->engine[engine->id].state);
 
-       I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
-       I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
+       I915_WRITE_IMR(engine,
+                      ~(engine->irq_enable_mask | engine->irq_keep_mask));
+       I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff);
 
-       I915_WRITE(RING_MODE_GEN7(ring),
+       I915_WRITE(RING_MODE_GEN7(engine),
                   _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
                   _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
-       POSTING_READ(RING_MODE_GEN7(ring));
+       POSTING_READ(RING_MODE_GEN7(engine));
 
        /*
         * Instead of resetting the Context Status Buffer (CSB) read pointer to
@@ -1576,7 +1593,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
         * BXT  |         ?                |         ?            |
         */
        next_context_status_buffer_hw =
-               GEN8_CSB_WRITE_PTR(I915_READ(RING_CONTEXT_STATUS_PTR(ring)));
+               GEN8_CSB_WRITE_PTR(I915_READ(RING_CONTEXT_STATUS_PTR(engine)));
 
        /*
         * When the CSB registers are reset (also after power-up / gpu reset),
@@ -1586,21 +1603,21 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
        if (next_context_status_buffer_hw == GEN8_CSB_PTR_MASK)
                next_context_status_buffer_hw = (GEN8_CSB_ENTRIES - 1);
 
-       ring->next_context_status_buffer = next_context_status_buffer_hw;
-       DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name);
+       engine->next_context_status_buffer = next_context_status_buffer_hw;
+       DRM_DEBUG_DRIVER("Execlists enabled for %s\n", engine->name);
 
-       memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
+       intel_engine_init_hangcheck(engine);
 
        return 0;
 }
 
-static int gen8_init_render_ring(struct intel_engine_cs *ring)
+static int gen8_init_render_ring(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
-       ret = gen8_init_common_ring(ring);
+       ret = gen8_init_common_ring(engine);
        if (ret)
                return ret;
 
@@ -1614,24 +1631,24 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring)
 
        I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
 
-       return init_workarounds_ring(ring);
+       return init_workarounds_ring(engine);
 }
 
-static int gen9_init_render_ring(struct intel_engine_cs *ring)
+static int gen9_init_render_ring(struct intel_engine_cs *engine)
 {
        int ret;
 
-       ret = gen8_init_common_ring(ring);
+       ret = gen8_init_common_ring(engine);
        if (ret)
                return ret;
 
-       return init_workarounds_ring(ring);
+       return init_workarounds_ring(engine);
 }
 
 static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req)
 {
        struct i915_hw_ppgtt *ppgtt = req->ctx->ppgtt;
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        struct intel_ringbuffer *ringbuf = req->ringbuf;
        const int num_lri_cmds = GEN8_LEGACY_PDPES * 2;
        int i, ret;
@@ -1644,9 +1661,11 @@ static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req)
        for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) {
                const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
 
-               intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_UDW(ring, i));
+               intel_logical_ring_emit_reg(ringbuf,
+                                           GEN8_RING_PDP_UDW(engine, i));
                intel_logical_ring_emit(ringbuf, upper_32_bits(pd_daddr));
-               intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_LDW(ring, i));
+               intel_logical_ring_emit_reg(ringbuf,
+                                           GEN8_RING_PDP_LDW(engine, i));
                intel_logical_ring_emit(ringbuf, lower_32_bits(pd_daddr));
        }
 
@@ -1670,7 +1689,7 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req,
         * not idle). PML4 is allocated during ppgtt init so this is
         * not needed in 48-bit.*/
        if (req->ctx->ppgtt &&
-           (intel_ring_flag(req->ring) & req->ctx->ppgtt->pd_dirty_rings)) {
+           (intel_engine_flag(req->engine) & req->ctx->ppgtt->pd_dirty_rings)) {
                if (!USES_FULL_48BIT_PPGTT(req->i915) &&
                    !intel_vgpu_active(req->i915->dev)) {
                        ret = intel_logical_ring_emit_pdps(req);
@@ -1678,7 +1697,7 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req,
                                return ret;
                }
 
-               req->ctx->ppgtt->pd_dirty_rings &= ~intel_ring_flag(req->ring);
+               req->ctx->ppgtt->pd_dirty_rings &= ~intel_engine_flag(req->engine);
        }
 
        ret = intel_logical_ring_begin(req, 4);
@@ -1698,9 +1717,9 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req,
        return 0;
 }
 
-static bool gen8_logical_ring_get_irq(struct intel_engine_cs *ring)
+static bool gen8_logical_ring_get_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
@@ -1708,25 +1727,26 @@ static bool gen8_logical_ring_get_irq(struct intel_engine_cs *ring)
                return false;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (ring->irq_refcount++ == 0) {
-               I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
-               POSTING_READ(RING_IMR(ring->mmio_base));
+       if (engine->irq_refcount++ == 0) {
+               I915_WRITE_IMR(engine,
+                              ~(engine->irq_enable_mask | engine->irq_keep_mask));
+               POSTING_READ(RING_IMR(engine->mmio_base));
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
        return true;
 }
 
-static void gen8_logical_ring_put_irq(struct intel_engine_cs *ring)
+static void gen8_logical_ring_put_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (--ring->irq_refcount == 0) {
-               I915_WRITE_IMR(ring, ~ring->irq_keep_mask);
-               POSTING_READ(RING_IMR(ring->mmio_base));
+       if (--engine->irq_refcount == 0) {
+               I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
+               POSTING_READ(RING_IMR(engine->mmio_base));
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
@@ -1736,8 +1756,8 @@ static int gen8_emit_flush(struct drm_i915_gem_request *request,
                           u32 unused)
 {
        struct intel_ringbuffer *ringbuf = request->ringbuf;
-       struct intel_engine_cs *ring = ringbuf->ring;
-       struct drm_device *dev = ring->dev;
+       struct intel_engine_cs *engine = ringbuf->engine;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t cmd;
        int ret;
@@ -1757,7 +1777,7 @@ static int gen8_emit_flush(struct drm_i915_gem_request *request,
 
        if (invalidate_domains & I915_GEM_GPU_DOMAINS) {
                cmd |= MI_INVALIDATE_TLB;
-               if (ring == &dev_priv->ring[VCS])
+               if (engine == &dev_priv->engine[VCS])
                        cmd |= MI_INVALIDATE_BSD;
        }
 
@@ -1777,8 +1797,8 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
                                  u32 flush_domains)
 {
        struct intel_ringbuffer *ringbuf = request->ringbuf;
-       struct intel_engine_cs *ring = ringbuf->ring;
-       u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+       struct intel_engine_cs *engine = ringbuf->engine;
+       u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
        bool vf_flush_wa = false;
        u32 flags = 0;
        int ret;
@@ -1806,7 +1826,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
                 * On GEN9: before VF_CACHE_INVALIDATE we need to emit a NULL
                 * pipe control.
                 */
-               if (IS_GEN9(ring->dev))
+               if (IS_GEN9(engine->dev))
                        vf_flush_wa = true;
        }
 
@@ -1834,17 +1854,18 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
        return 0;
 }
 
-static u32 gen8_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+static u32 gen8_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency)
 {
-       return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+       return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
-static void gen8_set_seqno(struct intel_engine_cs *ring, u32 seqno)
+static void gen8_set_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-       intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
+       intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
 }
 
-static u32 bxt_a_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+static u32 bxt_a_get_seqno(struct intel_engine_cs *engine,
+                          bool lazy_coherency)
 {
 
        /*
@@ -1859,17 +1880,17 @@ static u32 bxt_a_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
         */
 
        if (!lazy_coherency)
-               intel_flush_status_page(ring, I915_GEM_HWS_INDEX);
+               intel_flush_status_page(engine, I915_GEM_HWS_INDEX);
 
-       return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+       return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
-static void bxt_a_set_seqno(struct intel_engine_cs *ring, u32 seqno)
+static void bxt_a_set_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-       intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
+       intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
 
        /* See bxt_a_get_seqno() explaining the reason for the clflush. */
-       intel_flush_status_page(ring, I915_GEM_HWS_INDEX);
+       intel_flush_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
 /*
@@ -1899,7 +1920,7 @@ static int gen8_emit_request(struct drm_i915_gem_request *request)
        intel_logical_ring_emit(ringbuf,
                                (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW);
        intel_logical_ring_emit(ringbuf,
-                               hws_seqno_address(request->ring) |
+                               hws_seqno_address(request->engine) |
                                MI_FLUSH_DW_USE_GTT);
        intel_logical_ring_emit(ringbuf, 0);
        intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
@@ -1926,7 +1947,7 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request)
                                (PIPE_CONTROL_GLOBAL_GTT_IVB |
                                 PIPE_CONTROL_CS_STALL |
                                 PIPE_CONTROL_QW_WRITE));
-       intel_logical_ring_emit(ringbuf, hws_seqno_address(request->ring));
+       intel_logical_ring_emit(ringbuf, hws_seqno_address(request->engine));
        intel_logical_ring_emit(ringbuf, 0);
        intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
        intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT);
@@ -1938,19 +1959,19 @@ static int intel_lr_context_render_state_init(struct drm_i915_gem_request *req)
        struct render_state so;
        int ret;
 
-       ret = i915_gem_render_state_prepare(req->ring, &so);
+       ret = i915_gem_render_state_prepare(req->engine, &so);
        if (ret)
                return ret;
 
        if (so.rodata == NULL)
                return 0;
 
-       ret = req->ring->emit_bb_start(req, so.ggtt_offset,
+       ret = req->engine->emit_bb_start(req, so.ggtt_offset,
                                       I915_DISPATCH_SECURE);
        if (ret)
                goto out;
 
-       ret = req->ring->emit_bb_start(req,
+       ret = req->engine->emit_bb_start(req,
                                       (so.ggtt_offset + so.aux_batch_offset),
                                       I915_DISPATCH_SECURE);
        if (ret)
@@ -1988,146 +2009,147 @@ static int gen8_init_rcs_context(struct drm_i915_gem_request *req)
  * @ring: Engine Command Streamer.
  *
  */
-void intel_logical_ring_cleanup(struct intel_engine_cs *ring)
+void intel_logical_ring_cleanup(struct intel_engine_cs *engine)
 {
        struct drm_i915_private *dev_priv;
 
-       if (!intel_ring_initialized(ring))
+       if (!intel_engine_initialized(engine))
                return;
 
-       dev_priv = ring->dev->dev_private;
+       dev_priv = engine->dev->dev_private;
 
-       if (ring->buffer) {
-               intel_logical_ring_stop(ring);
-               WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
+       if (engine->buffer) {
+               intel_logical_ring_stop(engine);
+               WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
        }
 
-       if (ring->cleanup)
-               ring->cleanup(ring);
+       if (engine->cleanup)
+               engine->cleanup(engine);
 
-       i915_cmd_parser_fini_ring(ring);
-       i915_gem_batch_pool_fini(&ring->batch_pool);
+       i915_cmd_parser_fini_ring(engine);
+       i915_gem_batch_pool_fini(&engine->batch_pool);
 
-       if (ring->status_page.obj) {
-               kunmap(sg_page(ring->status_page.obj->pages->sgl));
-               ring->status_page.obj = NULL;
+       if (engine->status_page.obj) {
+               kunmap(sg_page(engine->status_page.obj->pages->sgl));
+               engine->status_page.obj = NULL;
        }
 
-       ring->disable_lite_restore_wa = false;
-       ring->ctx_desc_template = 0;
+       engine->idle_lite_restore_wa = 0;
+       engine->disable_lite_restore_wa = false;
+       engine->ctx_desc_template = 0;
 
-       lrc_destroy_wa_ctx_obj(ring);
-       ring->dev = NULL;
+       lrc_destroy_wa_ctx_obj(engine);
+       engine->dev = NULL;
 }
 
 static void
 logical_ring_default_vfuncs(struct drm_device *dev,
-                           struct intel_engine_cs *ring)
+                           struct intel_engine_cs *engine)
 {
        /* Default vfuncs which can be overriden by each engine. */
-       ring->init_hw = gen8_init_common_ring;
-       ring->emit_request = gen8_emit_request;
-       ring->emit_flush = gen8_emit_flush;
-       ring->irq_get = gen8_logical_ring_get_irq;
-       ring->irq_put = gen8_logical_ring_put_irq;
-       ring->emit_bb_start = gen8_emit_bb_start;
+       engine->init_hw = gen8_init_common_ring;
+       engine->emit_request = gen8_emit_request;
+       engine->emit_flush = gen8_emit_flush;
+       engine->irq_get = gen8_logical_ring_get_irq;
+       engine->irq_put = gen8_logical_ring_put_irq;
+       engine->emit_bb_start = gen8_emit_bb_start;
        if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
-               ring->get_seqno = bxt_a_get_seqno;
-               ring->set_seqno = bxt_a_set_seqno;
+               engine->get_seqno = bxt_a_get_seqno;
+               engine->set_seqno = bxt_a_set_seqno;
        } else {
-               ring->get_seqno = gen8_get_seqno;
-               ring->set_seqno = gen8_set_seqno;
+               engine->get_seqno = gen8_get_seqno;
+               engine->set_seqno = gen8_set_seqno;
        }
 }
 
 static inline void
-logical_ring_default_irqs(struct intel_engine_cs *ring, unsigned shift)
+logical_ring_default_irqs(struct intel_engine_cs *engine, unsigned shift)
 {
-       ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift;
-       ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift;
+       engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift;
+       engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift;
 }
 
 static int
-logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring)
+logical_ring_init(struct drm_device *dev, struct intel_engine_cs *engine)
 {
        struct intel_context *dctx = to_i915(dev)->kernel_context;
        int ret;
 
        /* Intentionally left blank. */
-       ring->buffer = NULL;
+       engine->buffer = NULL;
 
-       ring->dev = dev;
-       INIT_LIST_HEAD(&ring->active_list);
-       INIT_LIST_HEAD(&ring->request_list);
-       i915_gem_batch_pool_init(dev, &ring->batch_pool);
-       init_waitqueue_head(&ring->irq_queue);
+       engine->dev = dev;
+       INIT_LIST_HEAD(&engine->active_list);
+       INIT_LIST_HEAD(&engine->request_list);
+       i915_gem_batch_pool_init(dev, &engine->batch_pool);
+       init_waitqueue_head(&engine->irq_queue);
 
-       INIT_LIST_HEAD(&ring->buffers);
-       INIT_LIST_HEAD(&ring->execlist_queue);
-       INIT_LIST_HEAD(&ring->execlist_retired_req_list);
-       spin_lock_init(&ring->execlist_lock);
+       INIT_LIST_HEAD(&engine->buffers);
+       INIT_LIST_HEAD(&engine->execlist_queue);
+       INIT_LIST_HEAD(&engine->execlist_retired_req_list);
+       spin_lock_init(&engine->execlist_lock);
 
-       logical_ring_init_platform_invariants(ring);
+       logical_ring_init_platform_invariants(engine);
 
-       ret = i915_cmd_parser_init_ring(ring);
+       ret = i915_cmd_parser_init_ring(engine);
        if (ret)
                goto error;
 
-       ret = intel_lr_context_deferred_alloc(dctx, ring);
+       ret = intel_lr_context_deferred_alloc(dctx, engine);
        if (ret)
                goto error;
 
        /* As this is the default context, always pin it */
-       ret = intel_lr_context_do_pin(dctx, ring);
+       ret = intel_lr_context_do_pin(dctx, engine);
        if (ret) {
                DRM_ERROR(
                        "Failed to pin and map ringbuffer %s: %d\n",
-                       ring->name, ret);
+                       engine->name, ret);
                goto error;
        }
 
        return 0;
 
 error:
-       intel_logical_ring_cleanup(ring);
+       intel_logical_ring_cleanup(engine);
        return ret;
 }
 
 static int logical_render_ring_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+       struct intel_engine_cs *engine = &dev_priv->engine[RCS];
        int ret;
 
-       ring->name = "render ring";
-       ring->id = RCS;
-       ring->exec_id = I915_EXEC_RENDER;
-       ring->guc_id = GUC_RENDER_ENGINE;
-       ring->mmio_base = RENDER_RING_BASE;
+       engine->name = "render ring";
+       engine->id = RCS;
+       engine->exec_id = I915_EXEC_RENDER;
+       engine->guc_id = GUC_RENDER_ENGINE;
+       engine->mmio_base = RENDER_RING_BASE;
 
-       logical_ring_default_irqs(ring, GEN8_RCS_IRQ_SHIFT);
+       logical_ring_default_irqs(engine, GEN8_RCS_IRQ_SHIFT);
        if (HAS_L3_DPF(dev))
-               ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
+               engine->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
 
-       logical_ring_default_vfuncs(dev, ring);
+       logical_ring_default_vfuncs(dev, engine);
 
        /* Override some for render ring. */
        if (INTEL_INFO(dev)->gen >= 9)
-               ring->init_hw = gen9_init_render_ring;
+               engine->init_hw = gen9_init_render_ring;
        else
-               ring->init_hw = gen8_init_render_ring;
-       ring->init_context = gen8_init_rcs_context;
-       ring->cleanup = intel_fini_pipe_control;
-       ring->emit_flush = gen8_emit_flush_render;
-       ring->emit_request = gen8_emit_request_render;
+               engine->init_hw = gen8_init_render_ring;
+       engine->init_context = gen8_init_rcs_context;
+       engine->cleanup = intel_fini_pipe_control;
+       engine->emit_flush = gen8_emit_flush_render;
+       engine->emit_request = gen8_emit_request_render;
 
-       ring->dev = dev;
+       engine->dev = dev;
 
-       ret = intel_init_pipe_control(ring);
+       ret = intel_init_pipe_control(engine);
        if (ret)
                return ret;
 
-       ret = intel_init_workaround_bb(ring);
+       ret = intel_init_workaround_bb(engine);
        if (ret) {
                /*
                 * We continue even if we fail to initialize WA batch
@@ -2138,9 +2160,9 @@ static int logical_render_ring_init(struct drm_device *dev)
                          ret);
        }
 
-       ret = logical_ring_init(dev, ring);
+       ret = logical_ring_init(dev, engine);
        if (ret) {
-               lrc_destroy_wa_ctx_obj(ring);
+               lrc_destroy_wa_ctx_obj(engine);
        }
 
        return ret;
@@ -2149,69 +2171,69 @@ static int logical_render_ring_init(struct drm_device *dev)
 static int logical_bsd_ring_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[VCS];
+       struct intel_engine_cs *engine = &dev_priv->engine[VCS];
 
-       ring->name = "bsd ring";
-       ring->id = VCS;
-       ring->exec_id = I915_EXEC_BSD;
-       ring->guc_id = GUC_VIDEO_ENGINE;
-       ring->mmio_base = GEN6_BSD_RING_BASE;
+       engine->name = "bsd ring";
+       engine->id = VCS;
+       engine->exec_id = I915_EXEC_BSD;
+       engine->guc_id = GUC_VIDEO_ENGINE;
+       engine->mmio_base = GEN6_BSD_RING_BASE;
 
-       logical_ring_default_irqs(ring, GEN8_VCS1_IRQ_SHIFT);
-       logical_ring_default_vfuncs(dev, ring);
+       logical_ring_default_irqs(engine, GEN8_VCS1_IRQ_SHIFT);
+       logical_ring_default_vfuncs(dev, engine);
 
-       return logical_ring_init(dev, ring);
+       return logical_ring_init(dev, engine);
 }
 
 static int logical_bsd2_ring_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[VCS2];
+       struct intel_engine_cs *engine = &dev_priv->engine[VCS2];
 
-       ring->name = "bsd2 ring";
-       ring->id = VCS2;
-       ring->exec_id = I915_EXEC_BSD;
-       ring->guc_id = GUC_VIDEO_ENGINE2;
-       ring->mmio_base = GEN8_BSD2_RING_BASE;
+       engine->name = "bsd2 ring";
+       engine->id = VCS2;
+       engine->exec_id = I915_EXEC_BSD;
+       engine->guc_id = GUC_VIDEO_ENGINE2;
+       engine->mmio_base = GEN8_BSD2_RING_BASE;
 
-       logical_ring_default_irqs(ring, GEN8_VCS2_IRQ_SHIFT);
-       logical_ring_default_vfuncs(dev, ring);
+       logical_ring_default_irqs(engine, GEN8_VCS2_IRQ_SHIFT);
+       logical_ring_default_vfuncs(dev, engine);
 
-       return logical_ring_init(dev, ring);
+       return logical_ring_init(dev, engine);
 }
 
 static int logical_blt_ring_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[BCS];
+       struct intel_engine_cs *engine = &dev_priv->engine[BCS];
 
-       ring->name = "blitter ring";
-       ring->id = BCS;
-       ring->exec_id = I915_EXEC_BLT;
-       ring->guc_id = GUC_BLITTER_ENGINE;
-       ring->mmio_base = BLT_RING_BASE;
+       engine->name = "blitter ring";
+       engine->id = BCS;
+       engine->exec_id = I915_EXEC_BLT;
+       engine->guc_id = GUC_BLITTER_ENGINE;
+       engine->mmio_base = BLT_RING_BASE;
 
-       logical_ring_default_irqs(ring, GEN8_BCS_IRQ_SHIFT);
-       logical_ring_default_vfuncs(dev, ring);
+       logical_ring_default_irqs(engine, GEN8_BCS_IRQ_SHIFT);
+       logical_ring_default_vfuncs(dev, engine);
 
-       return logical_ring_init(dev, ring);
+       return logical_ring_init(dev, engine);
 }
 
 static int logical_vebox_ring_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[VECS];
+       struct intel_engine_cs *engine = &dev_priv->engine[VECS];
 
-       ring->name = "video enhancement ring";
-       ring->id = VECS;
-       ring->exec_id = I915_EXEC_VEBOX;
-       ring->guc_id = GUC_VIDEOENHANCE_ENGINE;
-       ring->mmio_base = VEBOX_RING_BASE;
+       engine->name = "video enhancement ring";
+       engine->id = VECS;
+       engine->exec_id = I915_EXEC_VEBOX;
+       engine->guc_id = GUC_VIDEOENHANCE_ENGINE;
+       engine->mmio_base = VEBOX_RING_BASE;
 
-       logical_ring_default_irqs(ring, GEN8_VECS_IRQ_SHIFT);
-       logical_ring_default_vfuncs(dev, ring);
+       logical_ring_default_irqs(engine, GEN8_VECS_IRQ_SHIFT);
+       logical_ring_default_vfuncs(dev, engine);
 
-       return logical_ring_init(dev, ring);
+       return logical_ring_init(dev, engine);
 }
 
 /**
@@ -2219,7 +2241,7 @@ static int logical_vebox_ring_init(struct drm_device *dev)
  * @dev: DRM device.
  *
  * This function inits the engines for an Execlists submission style (the equivalent in the
- * legacy ringbuffer submission world would be i915_gem_init_rings). It does it only for
+ * legacy ringbuffer submission world would be i915_gem_init_engines). It does it only for
  * those engines that are present in the hardware.
  *
  * Return: non-zero if the initialization failed.
@@ -2260,13 +2282,13 @@ int intel_logical_rings_init(struct drm_device *dev)
        return 0;
 
 cleanup_vebox_ring:
-       intel_logical_ring_cleanup(&dev_priv->ring[VECS]);
+       intel_logical_ring_cleanup(&dev_priv->engine[VECS]);
 cleanup_blt_ring:
-       intel_logical_ring_cleanup(&dev_priv->ring[BCS]);
+       intel_logical_ring_cleanup(&dev_priv->engine[BCS]);
 cleanup_bsd_ring:
-       intel_logical_ring_cleanup(&dev_priv->ring[VCS]);
+       intel_logical_ring_cleanup(&dev_priv->engine[VCS]);
 cleanup_render_ring:
-       intel_logical_ring_cleanup(&dev_priv->ring[RCS]);
+       intel_logical_ring_cleanup(&dev_priv->engine[RCS]);
 
        return ret;
 }
@@ -2314,13 +2336,13 @@ make_rpcs(struct drm_device *dev)
        return rpcs;
 }
 
-static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *ring)
+static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *engine)
 {
        u32 indirect_ctx_offset;
 
-       switch (INTEL_INFO(ring->dev)->gen) {
+       switch (INTEL_INFO(engine->dev)->gen) {
        default:
-               MISSING_CASE(INTEL_INFO(ring->dev)->gen);
+               MISSING_CASE(INTEL_INFO(engine->dev)->gen);
                /* fall through */
        case 9:
                indirect_ctx_offset =
@@ -2337,9 +2359,10 @@ static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *ring)
 
 static int
 populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_obj,
-                   struct intel_engine_cs *ring, struct intel_ringbuffer *ringbuf)
+                   struct intel_engine_cs *engine,
+                   struct intel_ringbuffer *ringbuf)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
        struct page *page;
@@ -2374,33 +2397,47 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
         * recreate this batchbuffer with new values (including all the missing
         * MI_LOAD_REGISTER_IMM commands that we are not initializing here). */
        reg_state[CTX_LRI_HEADER_0] =
-               MI_LOAD_REGISTER_IMM(ring->id == RCS ? 14 : 11) | MI_LRI_FORCE_POSTED;
-       ASSIGN_CTX_REG(reg_state, CTX_CONTEXT_CONTROL, RING_CONTEXT_CONTROL(ring),
+               MI_LOAD_REGISTER_IMM(engine->id == RCS ? 14 : 11) | MI_LRI_FORCE_POSTED;
+       ASSIGN_CTX_REG(reg_state, CTX_CONTEXT_CONTROL,
+                      RING_CONTEXT_CONTROL(engine),
                       _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH |
                                          CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT |
                                          (HAS_RESOURCE_STREAMER(dev) ?
                                            CTX_CTRL_RS_CTX_ENABLE : 0)));
-       ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(ring->mmio_base), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(ring->mmio_base), 0);
+       ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(engine->mmio_base),
+                      0);
+       ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(engine->mmio_base),
+                      0);
        /* Ring buffer start address is not known until the buffer is pinned.
         * It is written to the context image in execlists_update_context()
         */
-       ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START, RING_START(ring->mmio_base), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, RING_CTL(ring->mmio_base),
+       ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START,
+                      RING_START(engine->mmio_base), 0);
+       ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL,
+                      RING_CTL(engine->mmio_base),
                       ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID);
-       ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U, RING_BBADDR_UDW(ring->mmio_base), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L, RING_BBADDR(ring->mmio_base), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_BB_STATE, RING_BBSTATE(ring->mmio_base),
+       ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U,
+                      RING_BBADDR_UDW(engine->mmio_base), 0);
+       ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L,
+                      RING_BBADDR(engine->mmio_base), 0);
+       ASSIGN_CTX_REG(reg_state, CTX_BB_STATE,
+                      RING_BBSTATE(engine->mmio_base),
                       RING_BB_PPGTT);
-       ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_U, RING_SBBADDR_UDW(ring->mmio_base), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_L, RING_SBBADDR(ring->mmio_base), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_STATE, RING_SBBSTATE(ring->mmio_base), 0);
-       if (ring->id == RCS) {
-               ASSIGN_CTX_REG(reg_state, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(ring->mmio_base), 0);
-               ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX, RING_INDIRECT_CTX(ring->mmio_base), 0);
-               ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX_OFFSET, RING_INDIRECT_CTX_OFFSET(ring->mmio_base), 0);
-               if (ring->wa_ctx.obj) {
-                       struct i915_ctx_workarounds *wa_ctx = &ring->wa_ctx;
+       ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_U,
+                      RING_SBBADDR_UDW(engine->mmio_base), 0);
+       ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_L,
+                      RING_SBBADDR(engine->mmio_base), 0);
+       ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_STATE,
+                      RING_SBBSTATE(engine->mmio_base), 0);
+       if (engine->id == RCS) {
+               ASSIGN_CTX_REG(reg_state, CTX_BB_PER_CTX_PTR,
+                              RING_BB_PER_CTX_PTR(engine->mmio_base), 0);
+               ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX,
+                              RING_INDIRECT_CTX(engine->mmio_base), 0);
+               ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX_OFFSET,
+                              RING_INDIRECT_CTX_OFFSET(engine->mmio_base), 0);
+               if (engine->wa_ctx.obj) {
+                       struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx;
                        uint32_t ggtt_offset = i915_gem_obj_ggtt_offset(wa_ctx->obj);
 
                        reg_state[CTX_RCS_INDIRECT_CTX+1] =
@@ -2408,7 +2445,7 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
                                (wa_ctx->indirect_ctx.size / CACHELINE_DWORDS);
 
                        reg_state[CTX_RCS_INDIRECT_CTX_OFFSET+1] =
-                               intel_lr_indirect_ctx_offset(ring) << 6;
+                               intel_lr_indirect_ctx_offset(engine) << 6;
 
                        reg_state[CTX_BB_PER_CTX_PTR+1] =
                                (ggtt_offset + wa_ctx->per_ctx.offset * sizeof(uint32_t)) |
@@ -2416,16 +2453,25 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
                }
        }
        reg_state[CTX_LRI_HEADER_1] = MI_LOAD_REGISTER_IMM(9) | MI_LRI_FORCE_POSTED;
-       ASSIGN_CTX_REG(reg_state, CTX_CTX_TIMESTAMP, RING_CTX_TIMESTAMP(ring->mmio_base), 0);
+       ASSIGN_CTX_REG(reg_state, CTX_CTX_TIMESTAMP,
+                      RING_CTX_TIMESTAMP(engine->mmio_base), 0);
        /* PDP values well be assigned later if needed */
-       ASSIGN_CTX_REG(reg_state, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(ring, 3), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(ring, 3), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(ring, 2), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(ring, 2), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(ring, 1), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(ring, 1), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(ring, 0), 0);
-       ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(ring, 0), 0);
+       ASSIGN_CTX_REG(reg_state, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(engine, 3),
+                      0);
+       ASSIGN_CTX_REG(reg_state, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(engine, 3),
+                      0);
+       ASSIGN_CTX_REG(reg_state, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(engine, 2),
+                      0);
+       ASSIGN_CTX_REG(reg_state, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(engine, 2),
+                      0);
+       ASSIGN_CTX_REG(reg_state, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(engine, 1),
+                      0);
+       ASSIGN_CTX_REG(reg_state, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(engine, 1),
+                      0);
+       ASSIGN_CTX_REG(reg_state, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(engine, 0),
+                      0);
+       ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(engine, 0),
+                      0);
 
        if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
                /* 64b PPGTT (48bit canonical)
@@ -2439,13 +2485,10 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o
                 * With dynamic page allocation, PDPs may not be allocated at
                 * this point. Point the unallocated PDPs to the scratch page
                 */
-               ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
-               ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
-               ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
-               ASSIGN_CTX_PDP(ppgtt, reg_state, 0);
+               execlists_update_context_pdps(ppgtt, reg_state);
        }
 
-       if (ring->id == RCS) {
+       if (engine->id == RCS) {
                reg_state[CTX_LRI_HEADER_2] = MI_LOAD_REGISTER_IMM(1);
                ASSIGN_CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE,
                               make_rpcs(dev));
@@ -2469,7 +2512,7 @@ void intel_lr_context_free(struct intel_context *ctx)
 {
        int i;
 
-       for (i = I915_NUM_RINGS; --i >= 0; ) {
+       for (i = I915_NUM_ENGINES; --i >= 0; ) {
                struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf;
                struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state;
 
@@ -2501,15 +2544,15 @@ void intel_lr_context_free(struct intel_context *ctx)
  * in LRC mode, but does not include the "shared data page" used with
  * GuC submission. The caller should account for this if using the GuC.
  */
-uint32_t intel_lr_context_size(struct intel_engine_cs *ring)
+uint32_t intel_lr_context_size(struct intel_engine_cs *engine)
 {
        int ret = 0;
 
-       WARN_ON(INTEL_INFO(ring->dev)->gen < 8);
+       WARN_ON(INTEL_INFO(engine->dev)->gen < 8);
 
-       switch (ring->id) {
+       switch (engine->id) {
        case RCS:
-               if (INTEL_INFO(ring->dev)->gen >= 9)
+               if (INTEL_INFO(engine->dev)->gen >= 9)
                        ret = GEN9_LR_CONTEXT_RENDER_SIZE;
                else
                        ret = GEN8_LR_CONTEXT_RENDER_SIZE;
@@ -2525,22 +2568,22 @@ uint32_t intel_lr_context_size(struct intel_engine_cs *ring)
        return ret;
 }
 
-static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
-               struct drm_i915_gem_object *default_ctx_obj)
+static void lrc_setup_hardware_status_page(struct intel_engine_cs *engine,
+                                          struct drm_i915_gem_object *default_ctx_obj)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        struct page *page;
 
        /* The HWSP is part of the default context object in LRC mode. */
-       ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj)
+       engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj)
                        + LRC_PPHWSP_PN * PAGE_SIZE;
        page = i915_gem_object_get_page(default_ctx_obj, LRC_PPHWSP_PN);
-       ring->status_page.page_addr = kmap(page);
-       ring->status_page.obj = default_ctx_obj;
+       engine->status_page.page_addr = kmap(page);
+       engine->status_page.obj = default_ctx_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_HWS_PGA(engine->mmio_base),
+                       (u32)engine->status_page.gfx_addr);
+       POSTING_READ(RING_HWS_PGA(engine->mmio_base));
 }
 
 /**
@@ -2558,18 +2601,18 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
  */
 
 int intel_lr_context_deferred_alloc(struct intel_context *ctx,
-                                   struct intel_engine_cs *ring)
+                                   struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_gem_object *ctx_obj;
        uint32_t context_size;
        struct intel_ringbuffer *ringbuf;
        int ret;
 
        WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL);
-       WARN_ON(ctx->engine[ring->id].state);
+       WARN_ON(ctx->engine[engine->id].state);
 
-       context_size = round_up(intel_lr_context_size(ring), 4096);
+       context_size = round_up(intel_lr_context_size(engine), 4096);
 
        /* One extra page as the sharing data between driver and GuC */
        context_size += PAGE_SIZE * LRC_PPHWSP_PN;
@@ -2580,32 +2623,32 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx,
                return -ENOMEM;
        }
 
-       ringbuf = intel_engine_create_ringbuffer(ring, 4 * PAGE_SIZE);
+       ringbuf = intel_engine_create_ringbuffer(engine, 4 * PAGE_SIZE);
        if (IS_ERR(ringbuf)) {
                ret = PTR_ERR(ringbuf);
                goto error_deref_obj;
        }
 
-       ret = populate_lr_context(ctx, ctx_obj, ring, ringbuf);
+       ret = populate_lr_context(ctx, ctx_obj, engine, ringbuf);
        if (ret) {
                DRM_DEBUG_DRIVER("Failed to populate LRC: %d\n", ret);
                goto error_ringbuf;
        }
 
-       ctx->engine[ring->id].ringbuf = ringbuf;
-       ctx->engine[ring->id].state = ctx_obj;
+       ctx->engine[engine->id].ringbuf = ringbuf;
+       ctx->engine[engine->id].state = ctx_obj;
 
-       if (ctx != ctx->i915->kernel_context && ring->init_context) {
+       if (ctx != ctx->i915->kernel_context && engine->init_context) {
                struct drm_i915_gem_request *req;
 
-               req = i915_gem_request_alloc(ring, ctx);
+               req = i915_gem_request_alloc(engine, ctx);
                if (IS_ERR(req)) {
                        ret = PTR_ERR(req);
                        DRM_ERROR("ring create req: %d\n", ret);
                        goto error_ringbuf;
                }
 
-               ret = ring->init_context(req);
+               ret = engine->init_context(req);
                if (ret) {
                        DRM_ERROR("ring init context: %d\n",
                                ret);
@@ -2620,8 +2663,8 @@ error_ringbuf:
        intel_ringbuffer_free(ringbuf);
 error_deref_obj:
        drm_gem_object_unreference(&ctx_obj->base);
-       ctx->engine[ring->id].ringbuf = NULL;
-       ctx->engine[ring->id].state = NULL;
+       ctx->engine[engine->id].ringbuf = NULL;
+       ctx->engine[engine->id].state = NULL;
        return ret;
 }
 
@@ -2629,14 +2672,13 @@ void intel_lr_context_reset(struct drm_device *dev,
                        struct intel_context *ctx)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       int i;
+       struct intel_engine_cs *engine;
 
-       for_each_ring(ring, dev_priv, i) {
+       for_each_engine(engine, dev_priv) {
                struct drm_i915_gem_object *ctx_obj =
-                               ctx->engine[ring->id].state;
+                               ctx->engine[engine->id].state;
                struct intel_ringbuffer *ringbuf =
-                               ctx->engine[ring->id].ringbuf;
+                               ctx->engine[engine->id].ringbuf;
                uint32_t *reg_state;
                struct page *page;
 
index e6cda3e..a17cb12 100644 (file)
@@ -57,8 +57,8 @@
 /* Logical Rings */
 int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request);
 int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request);
-void intel_logical_ring_stop(struct intel_engine_cs *ring);
-void intel_logical_ring_cleanup(struct intel_engine_cs *ring);
+void intel_logical_ring_stop(struct intel_engine_cs *engine);
+void intel_logical_ring_cleanup(struct intel_engine_cs *engine);
 int intel_logical_rings_init(struct drm_device *dev);
 int intel_logical_ring_begin(struct drm_i915_gem_request *req, int num_dwords);
 
@@ -98,18 +98,18 @@ static inline void intel_logical_ring_emit_reg(struct intel_ringbuffer *ringbuf,
 #define LRC_STATE_PN   (LRC_PPHWSP_PN + 1)
 
 void intel_lr_context_free(struct intel_context *ctx);
-uint32_t intel_lr_context_size(struct intel_engine_cs *ring);
+uint32_t intel_lr_context_size(struct intel_engine_cs *engine);
 int intel_lr_context_deferred_alloc(struct intel_context *ctx,
-                                   struct intel_engine_cs *ring);
+                                   struct intel_engine_cs *engine);
 void intel_lr_context_unpin(struct intel_context *ctx,
                            struct intel_engine_cs *engine);
 void intel_lr_context_reset(struct drm_device *dev,
                        struct intel_context *ctx);
 uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
-                                    struct intel_engine_cs *ring);
+                                    struct intel_engine_cs *engine);
 
 u32 intel_execlists_ctx_id(struct intel_context *ctx,
-                          struct intel_engine_cs *ring);
+                          struct intel_engine_cs *engine);
 
 /* Execlists */
 int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists);
@@ -118,7 +118,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
                               struct drm_i915_gem_execbuffer2 *args,
                               struct list_head *vmas);
 
-void intel_lrc_irq_handler(struct intel_engine_cs *ring);
-void intel_execlists_retire_requests(struct intel_engine_cs *ring);
+void intel_lrc_irq_handler(struct intel_engine_cs *engine);
+void intel_execlists_retire_requests(struct intel_engine_cs *engine);
 
 #endif /* _INTEL_LRC_H_ */
index 30a8403..5d2b257 100644 (file)
@@ -109,7 +109,6 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
        u32 tmp, flags = 0;
-       int dotclock;
 
        tmp = I915_READ(lvds_encoder->reg);
        if (tmp & LVDS_HSYNC_POLARITY)
@@ -130,12 +129,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
                pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
        }
 
-       dotclock = pipe_config->port_clock;
-
-       if (HAS_PCH_SPLIT(dev_priv->dev))
-               ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
-       pipe_config->base.adjusted_mode.crtc_clock = dotclock;
+       pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
 }
 
 static void intel_pre_enable_lvds(struct intel_encoder *encoder)
@@ -151,7 +145,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
        if (HAS_PCH_SPLIT(dev)) {
                assert_fdi_rx_pll_disabled(dev_priv, pipe);
                assert_shared_dpll_disabled(dev_priv,
-                                           intel_crtc_to_shared_dpll(crtc));
+                                           crtc->config->shared_dpll);
        } else {
                assert_pll_disabled(dev_priv, pipe);
        }
@@ -781,57 +775,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
        { }     /* terminating entry */
 };
 
-/*
- * Enumerate the child dev array parsed from VBT to check whether
- * the LVDS is present.
- * If it is present, return 1.
- * If it is not present, return false.
- * If no child dev is parsed from VBT, it assumes that the LVDS is present.
- */
-static bool lvds_is_present_in_vbt(struct drm_device *dev,
-                                  u8 *i2c_pin)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
-
-       if (!dev_priv->vbt.child_dev_num)
-               return true;
-
-       for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
-               union child_device_config *uchild = dev_priv->vbt.child_dev + i;
-               struct old_child_dev_config *child = &uchild->old;
-
-               /* If the device type is not LFP, continue.
-                * We have to check both the new identifiers as well as the
-                * old for compatibility with some BIOSes.
-                */
-               if (child->device_type != DEVICE_TYPE_INT_LFP &&
-                   child->device_type != DEVICE_TYPE_LFP)
-                       continue;
-
-               if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin))
-                       *i2c_pin = child->i2c_pin;
-
-               /* However, we cannot trust the BIOS writers to populate
-                * the VBT correctly.  Since LVDS requires additional
-                * information from AIM blocks, a non-zero addin offset is
-                * a good indicator that the LVDS is actually present.
-                */
-               if (child->addin_offset)
-                       return true;
-
-               /* But even then some BIOS writers perform some black magic
-                * and instantiate the device without reference to any
-                * additional data.  Trust that if the VBT was written into
-                * the OpRegion then they have validated the LVDS's existence.
-                */
-               if (dev_priv->opregion.vbt)
-                       return true;
-       }
-
-       return false;
-}
-
 static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
 {
        DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
@@ -981,14 +924,14 @@ void intel_lvds_init(struct drm_device *dev)
        if (HAS_PCH_SPLIT(dev)) {
                if ((lvds & LVDS_DETECTED) == 0)
                        return;
-               if (dev_priv->vbt.edp_support) {
+               if (dev_priv->vbt.edp.support) {
                        DRM_DEBUG_KMS("disable LVDS for eDP support\n");
                        return;
                }
        }
 
        pin = GMBUS_PIN_PANEL;
-       if (!lvds_is_present_in_vbt(dev, &pin)) {
+       if (!intel_bios_is_lvds_present(dev_priv, &pin)) {
                if ((lvds & LVDS_PORT_EN) == 0) {
                        DRM_DEBUG_KMS("LVDS is not present in VBT\n");
                        return;
index fed7bea..7c7ac0a 100644 (file)
@@ -159,7 +159,7 @@ static bool get_mocs_settings(struct drm_device *dev,
        return result;
 }
 
-static i915_reg_t mocs_register(enum intel_ring_id ring, int index)
+static i915_reg_t mocs_register(enum intel_engine_id ring, int index)
 {
        switch (ring) {
        case RCS:
@@ -191,7 +191,7 @@ static i915_reg_t mocs_register(enum intel_ring_id ring, int index)
  */
 static int emit_mocs_control_table(struct drm_i915_gem_request *req,
                                   const struct drm_i915_mocs_table *table,
-                                  enum intel_ring_id ring)
+                                  enum intel_engine_id ring)
 {
        struct intel_ringbuffer *ringbuf = req->ringbuf;
        unsigned int index;
@@ -322,14 +322,14 @@ int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req)
        struct drm_i915_mocs_table t;
        int ret;
 
-       if (get_mocs_settings(req->ring->dev, &t)) {
+       if (get_mocs_settings(req->engine->dev, &t)) {
                struct drm_i915_private *dev_priv = req->i915;
-               struct intel_engine_cs *ring;
-               enum intel_ring_id ring_id;
+               struct intel_engine_cs *engine;
+               enum intel_engine_id id;
 
                /* Program the control registers */
-               for_each_ring(ring, dev_priv, ring_id) {
-                       ret = emit_mocs_control_table(req, &t, ring_id);
+               for_each_engine_id(engine, dev_priv, id) {
+                       ret = emit_mocs_control_table(req, &t, id);
                        if (ret)
                                return ret;
                }
index 9168413..e1acb41 100644 (file)
@@ -196,7 +196,7 @@ intel_overlay_map_regs(struct intel_overlay *overlay)
        if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
                regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr;
        else
-               regs = io_mapping_map_wc(dev_priv->gtt.mappable,
+               regs = io_mapping_map_wc(dev_priv->ggtt.mappable,
                                         i915_gem_obj_ggtt_offset(overlay->reg_bo));
 
        return regs;
@@ -233,14 +233,14 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 {
        struct drm_device *dev = overlay->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+       struct intel_engine_cs *engine = &dev_priv->engine[RCS];
        struct drm_i915_gem_request *req;
        int ret;
 
        WARN_ON(overlay->active);
        WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
 
-       req = i915_gem_request_alloc(ring, NULL);
+       req = i915_gem_request_alloc(engine, NULL);
        if (IS_ERR(req))
                return PTR_ERR(req);
 
@@ -252,11 +252,11 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 
        overlay->active = true;
 
-       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
-       intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
-       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
+       intel_ring_emit(engine, overlay->flip_addr | OFC_UPDATE);
+       intel_ring_emit(engine, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
 
        return intel_overlay_do_wait_request(overlay, req, NULL);
 }
@@ -267,7 +267,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
 {
        struct drm_device *dev = overlay->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+       struct intel_engine_cs *engine = &dev_priv->engine[RCS];
        struct drm_i915_gem_request *req;
        u32 flip_addr = overlay->flip_addr;
        u32 tmp;
@@ -283,7 +283,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
        if (tmp & (1 << 17))
                DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
 
-       req = i915_gem_request_alloc(ring, NULL);
+       req = i915_gem_request_alloc(engine, NULL);
        if (IS_ERR(req))
                return PTR_ERR(req);
 
@@ -293,9 +293,9 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
                return ret;
        }
 
-       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
-       intel_ring_emit(ring, flip_addr);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
+       intel_ring_emit(engine, flip_addr);
+       intel_ring_advance(engine);
 
        WARN_ON(overlay->last_flip_req);
        i915_gem_request_assign(&overlay->last_flip_req, req);
@@ -336,7 +336,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
 {
        struct drm_device *dev = overlay->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+       struct intel_engine_cs *engine = &dev_priv->engine[RCS];
        struct drm_i915_gem_request *req;
        u32 flip_addr = overlay->flip_addr;
        int ret;
@@ -349,7 +349,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
         * of the hw. Do it in both cases */
        flip_addr |= OFC_UPDATE;
 
-       req = i915_gem_request_alloc(ring, NULL);
+       req = i915_gem_request_alloc(engine, NULL);
        if (IS_ERR(req))
                return PTR_ERR(req);
 
@@ -360,22 +360,23 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        }
 
        /* wait for overlay to go idle */
-       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
-       intel_ring_emit(ring, flip_addr);
-       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
+       intel_ring_emit(engine, flip_addr);
+       intel_ring_emit(engine, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
        /* turn overlay off */
        if (IS_I830(dev)) {
                /* Workaround: Don't disable the overlay fully, since otherwise
                 * it dies on the next OVERLAY_ON cmd. */
-               intel_ring_emit(ring, MI_NOOP);
-               intel_ring_emit(ring, MI_NOOP);
-               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(engine, MI_NOOP);
+               intel_ring_emit(engine, MI_NOOP);
+               intel_ring_emit(engine, MI_NOOP);
        } else {
-               intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
-               intel_ring_emit(ring, flip_addr);
-               intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+               intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+               intel_ring_emit(engine, flip_addr);
+               intel_ring_emit(engine,
+                               MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
        }
-       intel_ring_advance(ring);
+       intel_ring_advance(engine);
 
        return intel_overlay_do_wait_request(overlay, req, intel_overlay_off_tail);
 }
@@ -408,7 +409,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
 {
        struct drm_device *dev = overlay->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+       struct intel_engine_cs *engine = &dev_priv->engine[RCS];
        int ret;
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -423,7 +424,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
                /* synchronous slowpath */
                struct drm_i915_gem_request *req;
 
-               req = i915_gem_request_alloc(ring, NULL);
+               req = i915_gem_request_alloc(engine, NULL);
                if (IS_ERR(req))
                        return PTR_ERR(req);
 
@@ -433,9 +434,10 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
                        return ret;
                }
 
-               intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
-               intel_ring_emit(ring, MI_NOOP);
-               intel_ring_advance(ring);
+               intel_ring_emit(engine,
+                               MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+               intel_ring_emit(engine, MI_NOOP);
+               intel_ring_advance(engine);
 
                ret = intel_overlay_do_wait_request(overlay, req,
                                                    intel_overlay_release_old_vid_tail);
@@ -1488,7 +1490,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
                regs = (struct overlay_registers __iomem *)
                        overlay->reg_bo->phys_handle->vaddr;
        else
-               regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
+               regs = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable,
                                                i915_gem_obj_ggtt_offset(overlay->reg_bo));
 
        return regs;
index 21ee647..8c8996f 100644 (file)
@@ -1240,7 +1240,7 @@ static void intel_backlight_device_unregister(struct intel_connector *connector)
  */
 static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-       return KHz(19200) / pwm_freq_hz;
+       return DIV_ROUND_CLOSEST(KHz(19200), pwm_freq_hz);
 }
 
 /*
@@ -1251,16 +1251,14 @@ static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-       u32 mul, clock;
+       u32 mul;
 
        if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY)
                mul = 128;
        else
                mul = 16;
 
-       clock = MHz(24);
-
-       return clock / (pwm_freq_hz * mul);
+       return DIV_ROUND_CLOSEST(MHz(24), pwm_freq_hz * mul);
 }
 
 /*
@@ -1283,7 +1281,7 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
        else
                clock = MHz(24); /* LPT:LP */
 
-       return clock / (pwm_freq_hz * mul);
+       return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul);
 }
 
 /*
@@ -1292,10 +1290,9 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
  */
 static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-       struct drm_device *dev = connector->base.dev;
-       int clock = MHz(intel_pch_rawclk(dev));
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 
-       return clock / (pwm_freq_hz * 128);
+       return DIV_ROUND_CLOSEST(KHz(dev_priv->rawclk_freq), pwm_freq_hz * 128);
 }
 
 /*
@@ -1308,16 +1305,15 @@ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
  */
 static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-       struct drm_device *dev = connector->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        int clock;
 
-       if (IS_PINEVIEW(dev))
-               clock = MHz(intel_hrawclk(dev));
+       if (IS_PINEVIEW(dev_priv))
+               clock = KHz(dev_priv->rawclk_freq);
        else
-               clock = 1000 * dev_priv->cdclk_freq;
+               clock = KHz(dev_priv->cdclk_freq);
 
-       return clock / (pwm_freq_hz * 32);
+       return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32);
 }
 
 /*
@@ -1332,11 +1328,11 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
        int clock;
 
        if (IS_G4X(dev_priv))
-               clock = MHz(intel_hrawclk(dev));
+               clock = KHz(dev_priv->rawclk_freq);
        else
-               clock = 1000 * dev_priv->cdclk_freq;
+               clock = KHz(dev_priv->cdclk_freq);
 
-       return clock / (pwm_freq_hz * 128);
+       return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
 }
 
 /*
@@ -1346,19 +1342,21 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
  */
 static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-       struct drm_device *dev = connector->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int clock;
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+       int mul, clock;
 
        if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) {
-               if (IS_CHERRYVIEW(dev))
-                       return KHz(19200) / (pwm_freq_hz * 16);
+               if (IS_CHERRYVIEW(dev_priv))
+                       clock = KHz(19200);
                else
-                       return MHz(25) / (pwm_freq_hz * 16);
+                       clock = MHz(25);
+               mul = 16;
        } else {
-               clock = intel_hrawclk(dev);
-               return MHz(clock) / (pwm_freq_hz * 128);
+               clock = KHz(dev_priv->rawclk_freq);
+               mul = 128;
        }
+
+       return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul);
 }
 
 static u32 get_backlight_max_vbt(struct intel_connector *connector)
@@ -1745,7 +1743,7 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
                panel->backlight.get = pch_get_backlight;
                panel->backlight.hz_to_pwm = pch_hz_to_pwm;
        } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-               if (dev_priv->vbt.has_mipi) {
+               if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) {
                        panel->backlight.setup = pwm_setup_backlight;
                        panel->backlight.enable = pwm_enable_backlight;
                        panel->backlight.disable = pwm_disable_backlight;
index 347d4df..6a04761 100644 (file)
@@ -487,20 +487,6 @@ static const struct intel_watermark_params g4x_cursor_wm_info = {
        .guard_size = 2,
        .cacheline_size = G4X_FIFO_LINE_SIZE,
 };
-static const struct intel_watermark_params valleyview_wm_info = {
-       .fifo_size = VALLEYVIEW_FIFO_SIZE,
-       .max_wm = VALLEYVIEW_MAX_WM,
-       .default_wm = VALLEYVIEW_MAX_WM,
-       .guard_size = 2,
-       .cacheline_size = G4X_FIFO_LINE_SIZE,
-};
-static const struct intel_watermark_params valleyview_cursor_wm_info = {
-       .fifo_size = I965_CURSOR_FIFO,
-       .max_wm = VALLEYVIEW_CURSOR_MAX_WM,
-       .default_wm = I965_CURSOR_DFT_WM,
-       .guard_size = 2,
-       .cacheline_size = G4X_FIFO_LINE_SIZE,
-};
 static const struct intel_watermark_params i965_cursor_wm_info = {
        .fifo_size = I965_CURSOR_FIFO,
        .max_wm = I965_CURSOR_MAX_WM,
@@ -2010,11 +1996,18 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
                cur_latency *= 5;
        }
 
-       result->pri_val = ilk_compute_pri_wm(cstate, pristate,
-                                            pri_latency, level);
-       result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
-       result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
-       result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
+       if (pristate) {
+               result->pri_val = ilk_compute_pri_wm(cstate, pristate,
+                                                    pri_latency, level);
+               result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
+       }
+
+       if (sprstate)
+               result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
+
+       if (curstate)
+               result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
+
        result->enable = true;
 }
 
@@ -2278,99 +2271,170 @@ static void skl_setup_wm_latency(struct drm_device *dev)
        intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
 }
 
+static bool ilk_validate_pipe_wm(struct drm_device *dev,
+                                struct intel_pipe_wm *pipe_wm)
+{
+       /* LP0 watermark maximums depend on this pipe alone */
+       const struct intel_wm_config config = {
+               .num_pipes_active = 1,
+               .sprites_enabled = pipe_wm->sprites_enabled,
+               .sprites_scaled = pipe_wm->sprites_scaled,
+       };
+       struct ilk_wm_maximums max;
+
+       /* LP0 watermarks always use 1/2 DDB partitioning */
+       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+
+       /* At least LP0 must be valid */
+       if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) {
+               DRM_DEBUG_KMS("LP0 watermark invalid\n");
+               return false;
+       }
+
+       return true;
+}
+
 /* Compute new watermarks for the pipe */
-static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc,
-                              struct drm_atomic_state *state)
+static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate)
 {
+       struct drm_atomic_state *state = cstate->base.state;
+       struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
        struct intel_pipe_wm *pipe_wm;
-       struct drm_device *dev = intel_crtc->base.dev;
+       struct drm_device *dev = state->dev;
        const struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc_state *cstate = NULL;
        struct intel_plane *intel_plane;
-       struct drm_plane_state *ps;
        struct intel_plane_state *pristate = NULL;
        struct intel_plane_state *sprstate = NULL;
        struct intel_plane_state *curstate = NULL;
-       int level, max_level = ilk_wm_max_level(dev);
-       /* LP0 watermark maximums depend on this pipe alone */
-       struct intel_wm_config config = {
-               .num_pipes_active = 1,
-       };
+       int level, max_level = ilk_wm_max_level(dev), usable_level;
        struct ilk_wm_maximums max;
 
-       cstate = intel_atomic_get_crtc_state(state, intel_crtc);
-       if (IS_ERR(cstate))
-               return PTR_ERR(cstate);
-
        pipe_wm = &cstate->wm.optimal.ilk;
-       memset(pipe_wm, 0, sizeof(*pipe_wm));
 
        for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
-               ps = drm_atomic_get_plane_state(state,
-                                               &intel_plane->base);
-               if (IS_ERR(ps))
-                       return PTR_ERR(ps);
+               struct intel_plane_state *ps;
+
+               ps = intel_atomic_get_existing_plane_state(state,
+                                                          intel_plane);
+               if (!ps)
+                       continue;
 
                if (intel_plane->base.type == DRM_PLANE_TYPE_PRIMARY)
-                       pristate = to_intel_plane_state(ps);
+                       pristate = ps;
                else if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY)
-                       sprstate = to_intel_plane_state(ps);
+                       sprstate = ps;
                else if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
-                       curstate = to_intel_plane_state(ps);
+                       curstate = ps;
        }
 
-       config.sprites_enabled = sprstate->visible;
-       config.sprites_scaled = sprstate->visible &&
-               (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 ||
-               drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16);
-
        pipe_wm->pipe_enabled = cstate->base.active;
-       pipe_wm->sprites_enabled = config.sprites_enabled;
-       pipe_wm->sprites_scaled = config.sprites_scaled;
+       if (sprstate) {
+               pipe_wm->sprites_enabled = sprstate->visible;
+               pipe_wm->sprites_scaled = sprstate->visible &&
+                       (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 ||
+                        drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16);
+       }
+
+       usable_level = max_level;
 
        /* ILK/SNB: LP2+ watermarks only w/o sprites */
-       if (INTEL_INFO(dev)->gen <= 6 && sprstate->visible)
-               max_level = 1;
+       if (INTEL_INFO(dev)->gen <= 6 && pipe_wm->sprites_enabled)
+               usable_level = 1;
 
        /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
-       if (config.sprites_scaled)
-               max_level = 0;
+       if (pipe_wm->sprites_scaled)
+               usable_level = 0;
 
        ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate,
-                            pristate, sprstate, curstate, &pipe_wm->wm[0]);
+                            pristate, sprstate, curstate, &pipe_wm->raw_wm[0]);
+
+       memset(&pipe_wm->wm, 0, sizeof(pipe_wm->wm));
+       pipe_wm->wm[0] = pipe_wm->raw_wm[0];
 
        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate);
 
-       /* LP0 watermarks always use 1/2 DDB partitioning */
-       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
-
-       /* At least LP0 must be valid */
-       if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
+       if (!ilk_validate_pipe_wm(dev, pipe_wm))
                return -EINVAL;
 
        ilk_compute_wm_reg_maximums(dev, 1, &max);
 
        for (level = 1; level <= max_level; level++) {
-               struct intel_wm_level wm = {};
+               struct intel_wm_level *wm = &pipe_wm->raw_wm[level];
 
                ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate,
-                                    pristate, sprstate, curstate, &wm);
+                                    pristate, sprstate, curstate, wm);
 
                /*
                 * Disable any watermark level that exceeds the
                 * register maximums since such watermarks are
                 * always invalid.
                 */
-               if (!ilk_validate_wm_level(level, &max, &wm))
-                       break;
+               if (level > usable_level)
+                       continue;
 
-               pipe_wm->wm[level] = wm;
+               if (ilk_validate_wm_level(level, &max, wm))
+                       pipe_wm->wm[level] = *wm;
+               else
+                       usable_level = level;
        }
 
        return 0;
 }
 
+/*
+ * Build a set of 'intermediate' watermark values that satisfy both the old
+ * state and the new state.  These can be programmed to the hardware
+ * immediately.
+ */
+static int ilk_compute_intermediate_wm(struct drm_device *dev,
+                                      struct intel_crtc *intel_crtc,
+                                      struct intel_crtc_state *newstate)
+{
+       struct intel_pipe_wm *a = &newstate->wm.intermediate;
+       struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk;
+       int level, max_level = ilk_wm_max_level(dev);
+
+       /*
+        * Start with the final, target watermarks, then combine with the
+        * currently active watermarks to get values that are safe both before
+        * and after the vblank.
+        */
+       *a = newstate->wm.optimal.ilk;
+       a->pipe_enabled |= b->pipe_enabled;
+       a->sprites_enabled |= b->sprites_enabled;
+       a->sprites_scaled |= b->sprites_scaled;
+
+       for (level = 0; level <= max_level; level++) {
+               struct intel_wm_level *a_wm = &a->wm[level];
+               const struct intel_wm_level *b_wm = &b->wm[level];
+
+               a_wm->enable &= b_wm->enable;
+               a_wm->pri_val = max(a_wm->pri_val, b_wm->pri_val);
+               a_wm->spr_val = max(a_wm->spr_val, b_wm->spr_val);
+               a_wm->cur_val = max(a_wm->cur_val, b_wm->cur_val);
+               a_wm->fbc_val = max(a_wm->fbc_val, b_wm->fbc_val);
+       }
+
+       /*
+        * We need to make sure that these merged watermark values are
+        * actually a valid configuration themselves.  If they're not,
+        * there's no safe way to transition from the old state to
+        * the new state, so we need to fail the atomic transaction.
+        */
+       if (!ilk_validate_pipe_wm(dev, a))
+               return -EINVAL;
+
+       /*
+        * If our intermediate WM are identical to the final WM, then we can
+        * omit the post-vblank programming; only update if it's different.
+        */
+       if (memcmp(a, &newstate->wm.optimal.ilk, sizeof(*a)) == 0)
+               newstate->wm.need_postvbl_update = false;
+
+       return 0;
+}
+
 /*
  * Merge the watermarks from all active pipes for a specific level.
  */
@@ -2383,9 +2447,7 @@ static void ilk_merge_wm_level(struct drm_device *dev,
        ret_wm->enable = true;
 
        for_each_intel_crtc(dev, intel_crtc) {
-               const struct intel_crtc_state *cstate =
-                       to_intel_crtc_state(intel_crtc->base.state);
-               const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
+               const struct intel_pipe_wm *active = &intel_crtc->wm.active.ilk;
                const struct intel_wm_level *wm = &active->wm[level];
 
                if (!active->pipe_enabled)
@@ -2533,15 +2595,14 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 
        /* LP0 register values */
        for_each_intel_crtc(dev, intel_crtc) {
-               const struct intel_crtc_state *cstate =
-                       to_intel_crtc_state(intel_crtc->base.state);
                enum pipe pipe = intel_crtc->pipe;
-               const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0];
+               const struct intel_wm_level *r =
+                       &intel_crtc->wm.active.ilk.wm[0];
 
                if (WARN_ON(!r->enable))
                        continue;
 
-               results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime;
+               results->wm_linetime[pipe] = intel_crtc->wm.active.ilk.linetime;
 
                results->wm_pipe[pipe] =
                        (r->pri_val << WM0_PIPE_PLANE_SHIFT) |
@@ -2748,7 +2809,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
        dev_priv->wm.hw = *results;
 }
 
-static bool ilk_disable_lp_wm(struct drm_device *dev)
+bool ilk_disable_lp_wm(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -3643,11 +3704,9 @@ static void ilk_compute_wm_config(struct drm_device *dev,
        }
 }
 
-static void ilk_program_watermarks(struct intel_crtc_state *cstate)
+static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
 {
-       struct drm_crtc *crtc = cstate->base.crtc;
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_device *dev = dev_priv->dev;
        struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
        struct ilk_wm_maximums max;
        struct intel_wm_config config = {};
@@ -3678,28 +3737,28 @@ static void ilk_program_watermarks(struct intel_crtc_state *cstate)
        ilk_write_wm_values(dev_priv, &results);
 }
 
-static void ilk_update_wm(struct drm_crtc *crtc)
+static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
-
-       WARN_ON(cstate->base.active != intel_crtc->active);
+       struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+       struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
 
-       /*
-        * IVB workaround: must disable low power watermarks for at least
-        * one frame before enabling scaling.  LP watermarks can be re-enabled
-        * when scaling is disabled.
-        *
-        * WaCxSRDisabledForSpriteScaling:ivb
-        */
-       if (cstate->disable_lp_wm) {
-               ilk_disable_lp_wm(crtc->dev);
-               intel_wait_for_vblank(crtc->dev, intel_crtc->pipe);
-       }
+       mutex_lock(&dev_priv->wm.wm_mutex);
+       intel_crtc->wm.active.ilk = cstate->wm.intermediate;
+       ilk_program_watermarks(dev_priv);
+       mutex_unlock(&dev_priv->wm.wm_mutex);
+}
 
-       intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
+static void ilk_optimize_watermarks(struct intel_crtc_state *cstate)
+{
+       struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+       struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
 
-       ilk_program_watermarks(cstate);
+       mutex_lock(&dev_priv->wm.wm_mutex);
+       if (cstate->wm.need_postvbl_update) {
+               intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
+               ilk_program_watermarks(dev_priv);
+       }
+       mutex_unlock(&dev_priv->wm.wm_mutex);
 }
 
 static void skl_pipe_wm_active_state(uint32_t val,
@@ -4585,9 +4644,9 @@ static bool bxt_check_bios_rc6_setup(const struct drm_device *dev)
         * for this check.
         */
        rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK;
-       if (!((rc6_ctx_base >= dev_priv->gtt.stolen_reserved_base) &&
-             (rc6_ctx_base + PAGE_SIZE <= dev_priv->gtt.stolen_reserved_base +
-                                       dev_priv->gtt.stolen_reserved_size))) {
+       if (!((rc6_ctx_base >= dev_priv->ggtt.stolen_reserved_base) &&
+             (rc6_ctx_base + PAGE_SIZE <= dev_priv->ggtt.stolen_reserved_base +
+                                       dev_priv->ggtt.stolen_reserved_size))) {
                DRM_DEBUG_KMS("RC6 Base address not as expected.\n");
                enable_rc6 = false;
        }
@@ -4756,9 +4815,8 @@ static void gen9_enable_rps(struct drm_device *dev)
 static void gen9_enable_rc6(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        uint32_t rc6_mask = 0;
-       int unused;
 
        /* 1a: Software RC state - RC0 */
        I915_WRITE(GEN6_RC_STATE, 0);
@@ -4779,8 +4837,8 @@ static void gen9_enable_rc6(struct drm_device *dev)
                I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
-       for_each_ring(ring, dev_priv, unused)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
        if (HAS_GUC_UCODE(dev))
                I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA);
@@ -4826,9 +4884,8 @@ static void gen9_enable_rc6(struct drm_device *dev)
 static void gen8_enable_rps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        uint32_t rc6_mask = 0;
-       int unused;
 
        /* 1a: Software RC state - RC0 */
        I915_WRITE(GEN6_RC_STATE, 0);
@@ -4847,8 +4904,8 @@ static void gen8_enable_rps(struct drm_device *dev)
        I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
-       for_each_ring(ring, dev_priv, unused)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
        I915_WRITE(GEN6_RC_SLEEP, 0);
        if (IS_BROADWELL(dev))
                I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */
@@ -4908,11 +4965,11 @@ static void gen8_enable_rps(struct drm_device *dev)
 static void gen6_enable_rps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        u32 rc6vids, pcu_mbox = 0, rc6_mask = 0;
        u32 gtfifodbg;
        int rc6_mode;
-       int i, ret;
+       int ret;
 
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
@@ -4944,8 +5001,8 @@ static void gen6_enable_rps(struct drm_device *dev)
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 
-       for_each_ring(ring, dev_priv, i)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
        I915_WRITE(GEN6_RC_SLEEP, 0);
        I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
@@ -5232,7 +5289,7 @@ static void cherryview_setup_pctx(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long pctx_paddr, paddr;
-       struct i915_gtt *gtt = &dev_priv->gtt;
+       struct i915_ggtt *ggtt = &dev_priv->ggtt;
        u32 pcbr;
        int pctx_size = 32*1024;
 
@@ -5240,7 +5297,7 @@ static void cherryview_setup_pctx(struct drm_device *dev)
        if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
                DRM_DEBUG_DRIVER("BIOS didn't set up PCBR, fixing up\n");
                paddr = (dev_priv->mm.stolen_base +
-                        (gtt->stolen_size - pctx_size));
+                        (ggtt->stolen_size - pctx_size));
 
                pctx_paddr = (paddr & (~4095));
                I915_WRITE(VLV_PCBR, pctx_paddr);
@@ -5436,9 +5493,8 @@ static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
 static void cherryview_enable_rps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        u32 gtfifodbg, val, rc6_mode = 0, pcbr;
-       int i;
 
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
@@ -5463,8 +5519,8 @@ static void cherryview_enable_rps(struct drm_device *dev)
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
 
-       for_each_ring(ring, dev_priv, i)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
        I915_WRITE(GEN6_RC_SLEEP, 0);
 
        /* TO threshold set to 500 us ( 0x186 * 1.28 us) */
@@ -5534,9 +5590,8 @@ static void cherryview_enable_rps(struct drm_device *dev)
 static void valleyview_enable_rps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        u32 gtfifodbg, val, rc6_mode = 0;
-       int i;
 
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
@@ -5574,8 +5629,8 @@ static void valleyview_enable_rps(struct drm_device *dev)
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 
-       for_each_ring(ring, dev_priv, i)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
        I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
 
@@ -5951,17 +6006,16 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
 bool i915_gpu_busy(void)
 {
        struct drm_i915_private *dev_priv;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        bool ret = false;
-       int i;
 
        spin_lock_irq(&mchdev_lock);
        if (!i915_mch_dev)
                goto out_unlock;
        dev_priv = i915_mch_dev;
 
-       for_each_ring(ring, dev_priv, i)
-               ret |= !list_empty(&ring->request_list);
+       for_each_engine(engine, dev_priv)
+               ret |= !list_empty(&engine->request_list);
 
 out_unlock:
        spin_unlock_irq(&mchdev_lock);
@@ -7038,8 +7092,7 @@ void intel_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (dev_priv->display.init_clock_gating)
-               dev_priv->display.init_clock_gating(dev);
+       dev_priv->display.init_clock_gating(dev);
 }
 
 void intel_suspend_hw(struct drm_device *dev)
@@ -7048,6 +7101,60 @@ void intel_suspend_hw(struct drm_device *dev)
                lpt_suspend_hw(dev);
 }
 
+static void nop_init_clock_gating(struct drm_device *dev)
+{
+       DRM_DEBUG_KMS("No clock gating settings or workarounds applied.\n");
+}
+
+/**
+ * intel_init_clock_gating_hooks - setup the clock gating hooks
+ * @dev_priv: device private
+ *
+ * Setup the hooks that configure which clocks of a given platform can be
+ * gated and also apply various GT and display specific workarounds for these
+ * platforms. Note that some GT specific workarounds are applied separately
+ * when GPU contexts or batchbuffers start their execution.
+ */
+void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv)
+{
+       if (IS_SKYLAKE(dev_priv))
+               dev_priv->display.init_clock_gating = nop_init_clock_gating;
+       else if (IS_KABYLAKE(dev_priv))
+               dev_priv->display.init_clock_gating = nop_init_clock_gating;
+       else if (IS_BROXTON(dev_priv))
+               dev_priv->display.init_clock_gating = bxt_init_clock_gating;
+       else if (IS_BROADWELL(dev_priv))
+               dev_priv->display.init_clock_gating = broadwell_init_clock_gating;
+       else if (IS_CHERRYVIEW(dev_priv))
+               dev_priv->display.init_clock_gating = cherryview_init_clock_gating;
+       else if (IS_HASWELL(dev_priv))
+               dev_priv->display.init_clock_gating = haswell_init_clock_gating;
+       else if (IS_IVYBRIDGE(dev_priv))
+               dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
+       else if (IS_VALLEYVIEW(dev_priv))
+               dev_priv->display.init_clock_gating = valleyview_init_clock_gating;
+       else if (IS_GEN6(dev_priv))
+               dev_priv->display.init_clock_gating = gen6_init_clock_gating;
+       else if (IS_GEN5(dev_priv))
+               dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
+       else if (IS_G4X(dev_priv))
+               dev_priv->display.init_clock_gating = g4x_init_clock_gating;
+       else if (IS_CRESTLINE(dev_priv))
+               dev_priv->display.init_clock_gating = crestline_init_clock_gating;
+       else if (IS_BROADWATER(dev_priv))
+               dev_priv->display.init_clock_gating = broadwater_init_clock_gating;
+       else if (IS_GEN3(dev_priv))
+               dev_priv->display.init_clock_gating = gen3_init_clock_gating;
+       else if (IS_I85X(dev_priv) || IS_I865G(dev_priv))
+               dev_priv->display.init_clock_gating = i85x_init_clock_gating;
+       else if (IS_GEN2(dev_priv))
+               dev_priv->display.init_clock_gating = i830_init_clock_gating;
+       else {
+               MISSING_CASE(INTEL_DEVID(dev_priv));
+               dev_priv->display.init_clock_gating = nop_init_clock_gating;
+       }
+}
+
 /* Set up chip specific power management-related functions */
 void intel_init_pm(struct drm_device *dev)
 {
@@ -7064,10 +7171,6 @@ void intel_init_pm(struct drm_device *dev)
        /* For FIFO watermark updates */
        if (INTEL_INFO(dev)->gen >= 9) {
                skl_setup_wm_latency(dev);
-
-               if (IS_BROXTON(dev))
-                       dev_priv->display.init_clock_gating =
-                               bxt_init_clock_gating;
                dev_priv->display.update_wm = skl_update_wm;
        } else if (HAS_PCH_SPLIT(dev)) {
                ilk_setup_wm_latency(dev);
@@ -7076,36 +7179,23 @@ void intel_init_pm(struct drm_device *dev)
                     dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
                    (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
                     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
-                       dev_priv->display.update_wm = ilk_update_wm;
                        dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
-                       dev_priv->display.program_watermarks = ilk_program_watermarks;
+                       dev_priv->display.compute_intermediate_wm =
+                               ilk_compute_intermediate_wm;
+                       dev_priv->display.initial_watermarks =
+                               ilk_initial_watermarks;
+                       dev_priv->display.optimize_watermarks =
+                               ilk_optimize_watermarks;
                } else {
                        DRM_DEBUG_KMS("Failed to read display plane latency. "
                                      "Disable CxSR\n");
                }
-
-               if (IS_GEN5(dev))
-                       dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
-               else if (IS_GEN6(dev))
-                       dev_priv->display.init_clock_gating = gen6_init_clock_gating;
-               else if (IS_IVYBRIDGE(dev))
-                       dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
-               else if (IS_HASWELL(dev))
-                       dev_priv->display.init_clock_gating = haswell_init_clock_gating;
-               else if (INTEL_INFO(dev)->gen == 8)
-                       dev_priv->display.init_clock_gating = broadwell_init_clock_gating;
        } else if (IS_CHERRYVIEW(dev)) {
                vlv_setup_wm_latency(dev);
-
                dev_priv->display.update_wm = vlv_update_wm;
-               dev_priv->display.init_clock_gating =
-                       cherryview_init_clock_gating;
        } else if (IS_VALLEYVIEW(dev)) {
                vlv_setup_wm_latency(dev);
-
                dev_priv->display.update_wm = vlv_update_wm;
-               dev_priv->display.init_clock_gating =
-                       valleyview_init_clock_gating;
        } else if (IS_PINEVIEW(dev)) {
                if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
                                            dev_priv->is_ddr3,
@@ -7121,20 +7211,13 @@ void intel_init_pm(struct drm_device *dev)
                        dev_priv->display.update_wm = NULL;
                } else
                        dev_priv->display.update_wm = pineview_update_wm;
-               dev_priv->display.init_clock_gating = gen3_init_clock_gating;
        } else if (IS_G4X(dev)) {
                dev_priv->display.update_wm = g4x_update_wm;
-               dev_priv->display.init_clock_gating = g4x_init_clock_gating;
        } else if (IS_GEN4(dev)) {
                dev_priv->display.update_wm = i965_update_wm;
-               if (IS_CRESTLINE(dev))
-                       dev_priv->display.init_clock_gating = crestline_init_clock_gating;
-               else if (IS_BROADWATER(dev))
-                       dev_priv->display.init_clock_gating = broadwater_init_clock_gating;
        } else if (IS_GEN3(dev)) {
                dev_priv->display.update_wm = i9xx_update_wm;
                dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
-               dev_priv->display.init_clock_gating = gen3_init_clock_gating;
        } else if (IS_GEN2(dev)) {
                if (INTEL_INFO(dev)->num_pipes == 1) {
                        dev_priv->display.update_wm = i845_update_wm;
@@ -7143,11 +7226,6 @@ void intel_init_pm(struct drm_device *dev)
                        dev_priv->display.update_wm = i9xx_update_wm;
                        dev_priv->display.get_fifo_size = i830_get_fifo_size;
                }
-
-               if (IS_I85X(dev) || IS_I865G(dev))
-                       dev_priv->display.init_clock_gating = i85x_init_clock_gating;
-               else
-                       dev_priv->display.init_clock_gating = i830_init_clock_gating;
        } else {
                DRM_ERROR("unexpected fall-through in intel_init_pm\n");
        }
@@ -7302,7 +7380,7 @@ static void __intel_rps_boost_work(struct work_struct *work)
        struct drm_i915_gem_request *req = boost->req;
 
        if (!i915_gem_request_completed(req, true))
-               gen6_rps_boost(to_i915(req->ring->dev), NULL,
+               gen6_rps_boost(to_i915(req->engine->dev), NULL,
                               req->emitted_jiffies);
 
        i915_gem_request_unreference__unlocked(req);
index 0b42ada..38e9518 100644 (file)
@@ -507,7 +507,8 @@ static void hsw_psr_disable(struct intel_dp *intel_dp)
 
                /* Wait till PSR is idle */
                if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL) &
-                              EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
+                              EDP_PSR_STATUS_STATE_MASK) == 0,
+                              2 * USEC_PER_SEC, 10 * USEC_PER_MSEC))
                        DRM_ERROR("Timed out waiting for PSR Idle State\n");
 
                dev_priv->psr.active = false;
@@ -780,8 +781,7 @@ void intel_psr_init(struct drm_device *dev)
 
        /* Per platform default */
        if (i915.enable_psr == -1) {
-               if (IS_HASWELL(dev) || IS_BROADWELL(dev) ||
-                   IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+               if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                        i915.enable_psr = 1;
                else
                        i915.enable_psr = 0;
index 45ce45a..a492bca 100644 (file)
@@ -59,19 +59,19 @@ int intel_ring_space(struct intel_ringbuffer *ringbuf)
        return ringbuf->space;
 }
 
-bool intel_ring_stopped(struct intel_engine_cs *ring)
+bool intel_engine_stopped(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
-       return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring);
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
+       return dev_priv->gpu_error.stop_rings & intel_engine_flag(engine);
 }
 
-static void __intel_ring_advance(struct intel_engine_cs *ring)
+static void __intel_ring_advance(struct intel_engine_cs *engine)
 {
-       struct intel_ringbuffer *ringbuf = ring->buffer;
+       struct intel_ringbuffer *ringbuf = engine->buffer;
        ringbuf->tail &= ringbuf->size - 1;
-       if (intel_ring_stopped(ring))
+       if (intel_engine_stopped(engine))
                return;
-       ring->write_tail(ring, ringbuf->tail);
+       engine->write_tail(engine, ringbuf->tail);
 }
 
 static int
@@ -79,7 +79,7 @@ gen2_render_ring_flush(struct drm_i915_gem_request *req,
                       u32      invalidate_domains,
                       u32      flush_domains)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        u32 cmd;
        int ret;
 
@@ -94,9 +94,9 @@ gen2_render_ring_flush(struct drm_i915_gem_request *req,
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, cmd);
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, cmd);
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -106,8 +106,8 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req,
                       u32      invalidate_domains,
                       u32      flush_domains)
 {
-       struct intel_engine_cs *ring = req->ring;
-       struct drm_device *dev = ring->dev;
+       struct intel_engine_cs *engine = req->engine;
+       struct drm_device *dev = engine->dev;
        u32 cmd;
        int ret;
 
@@ -153,9 +153,9 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req,
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, cmd);
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, cmd);
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -200,34 +200,34 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req,
 static int
 intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
-       u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+       struct intel_engine_cs *engine = req->engine;
+       u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
        int ret;
 
        ret = intel_ring_begin(req, 6);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
-       intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
+       intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5));
+       intel_ring_emit(engine, PIPE_CONTROL_CS_STALL |
                        PIPE_CONTROL_STALL_AT_SCOREBOARD);
-       intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
-       intel_ring_emit(ring, 0); /* low dword */
-       intel_ring_emit(ring, 0); /* high dword */
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+       intel_ring_emit(engine, 0); /* low dword */
+       intel_ring_emit(engine, 0); /* high dword */
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
 
        ret = intel_ring_begin(req, 6);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
-       intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
-       intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
-       intel_ring_emit(ring, 0);
-       intel_ring_emit(ring, 0);
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5));
+       intel_ring_emit(engine, PIPE_CONTROL_QW_WRITE);
+       intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+       intel_ring_emit(engine, 0);
+       intel_ring_emit(engine, 0);
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -236,9 +236,9 @@ static int
 gen6_render_ring_flush(struct drm_i915_gem_request *req,
                       u32 invalidate_domains, u32 flush_domains)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        u32 flags = 0;
-       u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+       u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
        int ret;
 
        /* Force SNB workarounds for PIPE_CONTROL flushes */
@@ -276,11 +276,11 @@ gen6_render_ring_flush(struct drm_i915_gem_request *req,
        if (ret)
                return ret;
 
-       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, 0);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4));
+       intel_ring_emit(engine, flags);
+       intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
+       intel_ring_emit(engine, 0);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -288,19 +288,19 @@ gen6_render_ring_flush(struct drm_i915_gem_request *req,
 static int
 gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        ret = intel_ring_begin(req, 4);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
-       intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
+       intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4));
+       intel_ring_emit(engine, PIPE_CONTROL_CS_STALL |
                              PIPE_CONTROL_STALL_AT_SCOREBOARD);
-       intel_ring_emit(ring, 0);
-       intel_ring_emit(ring, 0);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, 0);
+       intel_ring_emit(engine, 0);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -309,9 +309,9 @@ static int
 gen7_render_ring_flush(struct drm_i915_gem_request *req,
                       u32 invalidate_domains, u32 flush_domains)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        u32 flags = 0;
-       u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+       u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
        int ret;
 
        /*
@@ -360,11 +360,11 @@ gen7_render_ring_flush(struct drm_i915_gem_request *req,
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
-       intel_ring_emit(ring, flags);
-       intel_ring_emit(ring, scratch_addr);
-       intel_ring_emit(ring, 0);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4));
+       intel_ring_emit(engine, flags);
+       intel_ring_emit(engine, scratch_addr);
+       intel_ring_emit(engine, 0);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -373,20 +373,20 @@ static int
 gen8_emit_pipe_control(struct drm_i915_gem_request *req,
                       u32 flags, u32 scratch_addr)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        ret = intel_ring_begin(req, 6);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
-       intel_ring_emit(ring, flags);
-       intel_ring_emit(ring, scratch_addr);
-       intel_ring_emit(ring, 0);
-       intel_ring_emit(ring, 0);
-       intel_ring_emit(ring, 0);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6));
+       intel_ring_emit(engine, flags);
+       intel_ring_emit(engine, scratch_addr);
+       intel_ring_emit(engine, 0);
+       intel_ring_emit(engine, 0);
+       intel_ring_emit(engine, 0);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -396,7 +396,7 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req,
                       u32 invalidate_domains, u32 flush_domains)
 {
        u32 flags = 0;
-       u32 scratch_addr = req->ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+       u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
        int ret;
 
        flags |= PIPE_CONTROL_CS_STALL;
@@ -429,51 +429,51 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req,
        return gen8_emit_pipe_control(req, flags, scratch_addr);
 }
 
-static void ring_write_tail(struct intel_engine_cs *ring,
+static void ring_write_tail(struct intel_engine_cs *engine,
                            u32 value)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
-       I915_WRITE_TAIL(ring, value);
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
+       I915_WRITE_TAIL(engine, value);
 }
 
-u64 intel_ring_get_active_head(struct intel_engine_cs *ring)
+u64 intel_ring_get_active_head(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        u64 acthd;
 
-       if (INTEL_INFO(ring->dev)->gen >= 8)
-               acthd = I915_READ64_2x32(RING_ACTHD(ring->mmio_base),
-                                        RING_ACTHD_UDW(ring->mmio_base));
-       else if (INTEL_INFO(ring->dev)->gen >= 4)
-               acthd = I915_READ(RING_ACTHD(ring->mmio_base));
+       if (INTEL_INFO(engine->dev)->gen >= 8)
+               acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
+                                        RING_ACTHD_UDW(engine->mmio_base));
+       else if (INTEL_INFO(engine->dev)->gen >= 4)
+               acthd = I915_READ(RING_ACTHD(engine->mmio_base));
        else
                acthd = I915_READ(ACTHD);
 
        return acthd;
 }
 
-static void ring_setup_phys_status_page(struct intel_engine_cs *ring)
+static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        u32 addr;
 
        addr = dev_priv->status_page_dmah->busaddr;
-       if (INTEL_INFO(ring->dev)->gen >= 4)
+       if (INTEL_INFO(engine->dev)->gen >= 4)
                addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
        I915_WRITE(HWS_PGA, addr);
 }
 
-static void intel_ring_setup_status_page(struct intel_engine_cs *ring)
+static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_device *dev = engine->dev;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        i915_reg_t mmio;
 
        /* The ring status page addresses are no longer next to the rest of
         * the ring registers as of gen7.
         */
        if (IS_GEN7(dev)) {
-               switch (ring->id) {
+               switch (engine->id) {
                case RCS:
                        mmio = RENDER_HWS_PGA_GEN7;
                        break;
@@ -492,14 +492,14 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring)
                        mmio = VEBOX_HWS_PGA_GEN7;
                        break;
                }
-       } else if (IS_GEN6(ring->dev)) {
-               mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
+       } else if (IS_GEN6(engine->dev)) {
+               mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
        } else {
                /* XXX: gen8 returns to sanity */
-               mmio = RING_HWS_PGA(ring->mmio_base);
+               mmio = RING_HWS_PGA(engine->mmio_base);
        }
 
-       I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
+       I915_WRITE(mmio, (u32)engine->status_page.gfx_addr);
        POSTING_READ(mmio);
 
        /*
@@ -510,10 +510,10 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring)
         * invalidating the TLB?
         */
        if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) {
-               i915_reg_t reg = RING_INSTPM(ring->mmio_base);
+               i915_reg_t reg = RING_INSTPM(engine->mmio_base);
 
                /* ring should be idle before issuing a sync flush*/
-               WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
+               WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
 
                I915_WRITE(reg,
                           _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
@@ -521,117 +521,125 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring)
                if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0,
                             1000))
                        DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
-                                 ring->name);
+                                 engine->name);
        }
 }
 
-static bool stop_ring(struct intel_engine_cs *ring)
+static bool stop_ring(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = to_i915(ring->dev);
+       struct drm_i915_private *dev_priv = to_i915(engine->dev);
 
-       if (!IS_GEN2(ring->dev)) {
-               I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
-               if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
-                       DRM_ERROR("%s : timed out trying to stop ring\n", ring->name);
+       if (!IS_GEN2(engine->dev)) {
+               I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING));
+               if (wait_for((I915_READ_MODE(engine) & MODE_IDLE) != 0, 1000)) {
+                       DRM_ERROR("%s : timed out trying to stop ring\n",
+                                 engine->name);
                        /* Sometimes we observe that the idle flag is not
                         * set even though the ring is empty. So double
                         * check before giving up.
                         */
-                       if (I915_READ_HEAD(ring) != I915_READ_TAIL(ring))
+                       if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine))
                                return false;
                }
        }
 
-       I915_WRITE_CTL(ring, 0);
-       I915_WRITE_HEAD(ring, 0);
-       ring->write_tail(ring, 0);
+       I915_WRITE_CTL(engine, 0);
+       I915_WRITE_HEAD(engine, 0);
+       engine->write_tail(engine, 0);
 
-       if (!IS_GEN2(ring->dev)) {
-               (void)I915_READ_CTL(ring);
-               I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING));
+       if (!IS_GEN2(engine->dev)) {
+               (void)I915_READ_CTL(engine);
+               I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
        }
 
-       return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0;
+       return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0;
 }
 
-static int init_ring_common(struct intel_engine_cs *ring)
+void intel_engine_init_hangcheck(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       memset(&engine->hangcheck, 0, sizeof(engine->hangcheck));
+}
+
+static int init_ring_common(struct intel_engine_cs *engine)
+{
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_ringbuffer *ringbuf = ring->buffer;
+       struct intel_ringbuffer *ringbuf = engine->buffer;
        struct drm_i915_gem_object *obj = ringbuf->obj;
        int ret = 0;
 
        intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
-       if (!stop_ring(ring)) {
+       if (!stop_ring(engine)) {
                /* G45 ring initialization often fails to reset head to zero */
                DRM_DEBUG_KMS("%s head not reset to zero "
                              "ctl %08x head %08x tail %08x start %08x\n",
-                             ring->name,
-                             I915_READ_CTL(ring),
-                             I915_READ_HEAD(ring),
-                             I915_READ_TAIL(ring),
-                             I915_READ_START(ring));
+                             engine->name,
+                             I915_READ_CTL(engine),
+                             I915_READ_HEAD(engine),
+                             I915_READ_TAIL(engine),
+                             I915_READ_START(engine));
 
-               if (!stop_ring(ring)) {
+               if (!stop_ring(engine)) {
                        DRM_ERROR("failed to set %s head to zero "
                                  "ctl %08x head %08x tail %08x start %08x\n",
-                                 ring->name,
-                                 I915_READ_CTL(ring),
-                                 I915_READ_HEAD(ring),
-                                 I915_READ_TAIL(ring),
-                                 I915_READ_START(ring));
+                                 engine->name,
+                                 I915_READ_CTL(engine),
+                                 I915_READ_HEAD(engine),
+                                 I915_READ_TAIL(engine),
+                                 I915_READ_START(engine));
                        ret = -EIO;
                        goto out;
                }
        }
 
        if (I915_NEED_GFX_HWS(dev))
-               intel_ring_setup_status_page(ring);
+               intel_ring_setup_status_page(engine);
        else
-               ring_setup_phys_status_page(ring);
+               ring_setup_phys_status_page(engine);
 
        /* Enforce ordering by reading HEAD register back */
-       I915_READ_HEAD(ring);
+       I915_READ_HEAD(engine);
 
        /* Initialize the ring. This must happen _after_ we've cleared the ring
         * registers with the above sequence (the readback of the HEAD registers
         * also enforces ordering), otherwise the hw might lose the new ring
         * register values. */
-       I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj));
+       I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj));
 
        /* WaClearRingBufHeadRegAtInit:ctg,elk */
-       if (I915_READ_HEAD(ring))
+       if (I915_READ_HEAD(engine))
                DRM_DEBUG("%s initialization failed [head=%08x], fudging\n",
-                         ring->name, I915_READ_HEAD(ring));
-       I915_WRITE_HEAD(ring, 0);
-       (void)I915_READ_HEAD(ring);
+                         engine->name, I915_READ_HEAD(engine));
+       I915_WRITE_HEAD(engine, 0);
+       (void)I915_READ_HEAD(engine);
 
-       I915_WRITE_CTL(ring,
+       I915_WRITE_CTL(engine,
                        ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES)
                        | RING_VALID);
 
        /* If the head is still not zero, the ring is dead */
-       if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 &&
-                    I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) &&
-                    (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) {
+       if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 &&
+                    I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) &&
+                    (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) {
                DRM_ERROR("%s initialization failed "
                          "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n",
-                         ring->name,
-                         I915_READ_CTL(ring), I915_READ_CTL(ring) & RING_VALID,
-                         I915_READ_HEAD(ring), I915_READ_TAIL(ring),
-                         I915_READ_START(ring), (unsigned long)i915_gem_obj_ggtt_offset(obj));
+                         engine->name,
+                         I915_READ_CTL(engine),
+                         I915_READ_CTL(engine) & RING_VALID,
+                         I915_READ_HEAD(engine), I915_READ_TAIL(engine),
+                         I915_READ_START(engine),
+                         (unsigned long)i915_gem_obj_ggtt_offset(obj));
                ret = -EIO;
                goto out;
        }
 
        ringbuf->last_retired_head = -1;
-       ringbuf->head = I915_READ_HEAD(ring);
-       ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
+       ringbuf->head = I915_READ_HEAD(engine);
+       ringbuf->tail = I915_READ_TAIL(engine) & TAIL_ADDR;
        intel_ring_update_space(ringbuf);
 
-       memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
+       intel_engine_init_hangcheck(engine);
 
 out:
        intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
@@ -640,59 +648,60 @@ out:
 }
 
 void
-intel_fini_pipe_control(struct intel_engine_cs *ring)
+intel_fini_pipe_control(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
 
-       if (ring->scratch.obj == NULL)
+       if (engine->scratch.obj == NULL)
                return;
 
        if (INTEL_INFO(dev)->gen >= 5) {
-               kunmap(sg_page(ring->scratch.obj->pages->sgl));
-               i915_gem_object_ggtt_unpin(ring->scratch.obj);
+               kunmap(sg_page(engine->scratch.obj->pages->sgl));
+               i915_gem_object_ggtt_unpin(engine->scratch.obj);
        }
 
-       drm_gem_object_unreference(&ring->scratch.obj->base);
-       ring->scratch.obj = NULL;
+       drm_gem_object_unreference(&engine->scratch.obj->base);
+       engine->scratch.obj = NULL;
 }
 
 int
-intel_init_pipe_control(struct intel_engine_cs *ring)
+intel_init_pipe_control(struct intel_engine_cs *engine)
 {
        int ret;
 
-       WARN_ON(ring->scratch.obj);
+       WARN_ON(engine->scratch.obj);
 
-       ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096);
-       if (ring->scratch.obj == NULL) {
+       engine->scratch.obj = i915_gem_alloc_object(engine->dev, 4096);
+       if (engine->scratch.obj == NULL) {
                DRM_ERROR("Failed to allocate seqno page\n");
                ret = -ENOMEM;
                goto err;
        }
 
-       ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC);
+       ret = i915_gem_object_set_cache_level(engine->scratch.obj,
+                                             I915_CACHE_LLC);
        if (ret)
                goto err_unref;
 
-       ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0);
+       ret = i915_gem_obj_ggtt_pin(engine->scratch.obj, 4096, 0);
        if (ret)
                goto err_unref;
 
-       ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj);
-       ring->scratch.cpu_page = kmap(sg_page(ring->scratch.obj->pages->sgl));
-       if (ring->scratch.cpu_page == NULL) {
+       engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(engine->scratch.obj);
+       engine->scratch.cpu_page = kmap(sg_page(engine->scratch.obj->pages->sgl));
+       if (engine->scratch.cpu_page == NULL) {
                ret = -ENOMEM;
                goto err_unpin;
        }
 
        DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
-                        ring->name, ring->scratch.gtt_offset);
+                        engine->name, engine->scratch.gtt_offset);
        return 0;
 
 err_unpin:
-       i915_gem_object_ggtt_unpin(ring->scratch.obj);
+       i915_gem_object_ggtt_unpin(engine->scratch.obj);
 err_unref:
-       drm_gem_object_unreference(&ring->scratch.obj->base);
+       drm_gem_object_unreference(&engine->scratch.obj->base);
 err:
        return ret;
 }
@@ -700,15 +709,15 @@ err:
 static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
 {
        int ret, i;
-       struct intel_engine_cs *ring = req->ring;
-       struct drm_device *dev = ring->dev;
+       struct intel_engine_cs *engine = req->engine;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_workarounds *w = &dev_priv->workarounds;
 
        if (w->count == 0)
                return 0;
 
-       ring->gpu_caches_dirty = true;
+       engine->gpu_caches_dirty = true;
        ret = intel_ring_flush_all_caches(req);
        if (ret)
                return ret;
@@ -717,16 +726,16 @@ static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count));
+       intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(w->count));
        for (i = 0; i < w->count; i++) {
-               intel_ring_emit_reg(ring, w->reg[i].addr);
-               intel_ring_emit(ring, w->reg[i].value);
+               intel_ring_emit_reg(engine, w->reg[i].addr);
+               intel_ring_emit(engine, w->reg[i].value);
        }
-       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_emit(engine, MI_NOOP);
 
-       intel_ring_advance(ring);
+       intel_ring_advance(engine);
 
-       ring->gpu_caches_dirty = true;
+       engine->gpu_caches_dirty = true;
        ret = intel_ring_flush_all_caches(req);
        if (ret)
                return ret;
@@ -789,25 +798,26 @@ static int wa_add(struct drm_i915_private *dev_priv,
 
 #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
 
-static int wa_ring_whitelist_reg(struct intel_engine_cs *ring, i915_reg_t reg)
+static int wa_ring_whitelist_reg(struct intel_engine_cs *engine,
+                                i915_reg_t reg)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
        struct i915_workarounds *wa = &dev_priv->workarounds;
-       const uint32_t index = wa->hw_whitelist_count[ring->id];
+       const uint32_t index = wa->hw_whitelist_count[engine->id];
 
        if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS))
                return -EINVAL;
 
-       WA_WRITE(RING_FORCE_TO_NONPRIV(ring->mmio_base, index),
+       WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index),
                 i915_mmio_reg_offset(reg));
-       wa->hw_whitelist_count[ring->id]++;
+       wa->hw_whitelist_count[engine->id]++;
 
        return 0;
 }
 
-static int gen8_init_workarounds(struct intel_engine_cs *ring)
+static int gen8_init_workarounds(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
@@ -857,13 +867,13 @@ static int gen8_init_workarounds(struct intel_engine_cs *ring)
        return 0;
 }
 
-static int bdw_init_workarounds(struct intel_engine_cs *ring)
+static int bdw_init_workarounds(struct intel_engine_cs *engine)
 {
        int ret;
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       ret = gen8_init_workarounds(ring);
+       ret = gen8_init_workarounds(engine);
        if (ret)
                return ret;
 
@@ -886,13 +896,13 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
        return 0;
 }
 
-static int chv_init_workarounds(struct intel_engine_cs *ring)
+static int chv_init_workarounds(struct intel_engine_cs *engine)
 {
        int ret;
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       ret = gen8_init_workarounds(ring);
+       ret = gen8_init_workarounds(engine);
        if (ret)
                return ret;
 
@@ -905,9 +915,9 @@ static int chv_init_workarounds(struct intel_engine_cs *ring)
        return 0;
 }
 
-static int gen9_init_workarounds(struct intel_engine_cs *ring)
+static int gen9_init_workarounds(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
        int ret;
@@ -920,8 +930,10 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
        I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
                   ECOCHK_DIS_TLB);
 
+       /* WaClearFlowControlGpgpuContextSave:skl,bxt */
        /* WaDisablePartialInstShootdown:skl,bxt */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
+                         FLOW_CONTROL_ENABLE |
                          PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
 
        /* Syncing dependencies between camera and graphics:skl,bxt */
@@ -986,21 +998,21 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
                                    GEN8_LQSC_FLUSH_COHERENT_LINES));
 
        /* WaEnablePreemptionGranularityControlByUMD:skl,bxt */
-       ret= wa_ring_whitelist_reg(ring, GEN8_CS_CHICKEN1);
+       ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
        if (ret)
                return ret;
 
        /* WaAllowUMDToModifyHDCChicken1:skl,bxt */
-       ret = wa_ring_whitelist_reg(ring, GEN8_HDC_CHICKEN1);
+       ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1);
        if (ret)
                return ret;
 
        return 0;
 }
 
-static int skl_tune_iz_hashing(struct intel_engine_cs *ring)
+static int skl_tune_iz_hashing(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u8 vals[3] = { 0, 0, 0 };
        unsigned int i;
@@ -1040,13 +1052,13 @@ static int skl_tune_iz_hashing(struct intel_engine_cs *ring)
        return 0;
 }
 
-static int skl_init_workarounds(struct intel_engine_cs *ring)
+static int skl_init_workarounds(struct intel_engine_cs *engine)
 {
        int ret;
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       ret = gen9_init_workarounds(ring);
+       ret = gen9_init_workarounds(engine);
        if (ret)
                return ret;
 
@@ -1113,20 +1125,20 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
                        GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
 
        /* WaDisableLSQCROPERFforOCL:skl */
-       ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4);
+       ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
        if (ret)
                return ret;
 
-       return skl_tune_iz_hashing(ring);
+       return skl_tune_iz_hashing(engine);
 }
 
-static int bxt_init_workarounds(struct intel_engine_cs *ring)
+static int bxt_init_workarounds(struct intel_engine_cs *engine)
 {
        int ret;
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       ret = gen9_init_workarounds(ring);
+       ret = gen9_init_workarounds(engine);
        if (ret)
                return ret;
 
@@ -1157,11 +1169,11 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring)
        /* WaDisableObjectLevelPreemtionForInstanceId:bxt */
        /* WaDisableLSQCROPERFforOCL:bxt */
        if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
-               ret = wa_ring_whitelist_reg(ring, GEN9_CS_DEBUG_MODE1);
+               ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1);
                if (ret)
                        return ret;
 
-               ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4);
+               ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
                if (ret)
                        return ret;
        }
@@ -1169,36 +1181,36 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring)
        return 0;
 }
 
-int init_workarounds_ring(struct intel_engine_cs *ring)
+int init_workarounds_ring(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       WARN_ON(ring->id != RCS);
+       WARN_ON(engine->id != RCS);
 
        dev_priv->workarounds.count = 0;
        dev_priv->workarounds.hw_whitelist_count[RCS] = 0;
 
        if (IS_BROADWELL(dev))
-               return bdw_init_workarounds(ring);
+               return bdw_init_workarounds(engine);
 
        if (IS_CHERRYVIEW(dev))
-               return chv_init_workarounds(ring);
+               return chv_init_workarounds(engine);
 
        if (IS_SKYLAKE(dev))
-               return skl_init_workarounds(ring);
+               return skl_init_workarounds(engine);
 
        if (IS_BROXTON(dev))
-               return bxt_init_workarounds(ring);
+               return bxt_init_workarounds(engine);
 
        return 0;
 }
 
-static int init_render_ring(struct intel_engine_cs *ring)
+static int init_render_ring(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int ret = init_ring_common(ring);
+       int ret = init_ring_common(engine);
        if (ret)
                return ret;
 
@@ -1241,14 +1253,14 @@ static int init_render_ring(struct intel_engine_cs *ring)
                I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
 
        if (HAS_L3_DPF(dev))
-               I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
+               I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev));
 
-       return init_workarounds_ring(ring);
+       return init_workarounds_ring(engine);
 }
 
-static void render_ring_cleanup(struct intel_engine_cs *ring)
+static void render_ring_cleanup(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (dev_priv->semaphore_obj) {
@@ -1257,18 +1269,19 @@ static void render_ring_cleanup(struct intel_engine_cs *ring)
                dev_priv->semaphore_obj = NULL;
        }
 
-       intel_fini_pipe_control(ring);
+       intel_fini_pipe_control(engine);
 }
 
 static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req,
                           unsigned int num_dwords)
 {
 #define MBOX_UPDATE_DWORDS 8
-       struct intel_engine_cs *signaller = signaller_req->ring;
+       struct intel_engine_cs *signaller = signaller_req->engine;
        struct drm_device *dev = signaller->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *waiter;
-       int i, ret, num_rings;
+       enum intel_engine_id id;
+       int ret, num_rings;
 
        num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
        num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
@@ -1278,9 +1291,9 @@ static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req,
        if (ret)
                return ret;
 
-       for_each_ring(waiter, dev_priv, i) {
+       for_each_engine_id(waiter, dev_priv, id) {
                u32 seqno;
-               u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
+               u64 gtt_offset = signaller->semaphore.signal_ggtt[id];
                if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
                        continue;
 
@@ -1305,11 +1318,12 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req,
                           unsigned int num_dwords)
 {
 #define MBOX_UPDATE_DWORDS 6
-       struct intel_engine_cs *signaller = signaller_req->ring;
+       struct intel_engine_cs *signaller = signaller_req->engine;
        struct drm_device *dev = signaller->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *waiter;
-       int i, ret, num_rings;
+       enum intel_engine_id id;
+       int ret, num_rings;
 
        num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
        num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
@@ -1319,9 +1333,9 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req,
        if (ret)
                return ret;
 
-       for_each_ring(waiter, dev_priv, i) {
+       for_each_engine_id(waiter, dev_priv, id) {
                u32 seqno;
-               u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
+               u64 gtt_offset = signaller->semaphore.signal_ggtt[id];
                if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
                        continue;
 
@@ -1343,11 +1357,12 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req,
 static int gen6_signal(struct drm_i915_gem_request *signaller_req,
                       unsigned int num_dwords)
 {
-       struct intel_engine_cs *signaller = signaller_req->ring;
+       struct intel_engine_cs *signaller = signaller_req->engine;
        struct drm_device *dev = signaller->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *useless;
-       int i, ret, num_rings;
+       enum intel_engine_id id;
+       int ret, num_rings;
 
 #define MBOX_UPDATE_DWORDS 3
        num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
@@ -1358,8 +1373,8 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req,
        if (ret)
                return ret;
 
-       for_each_ring(useless, dev_priv, i) {
-               i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[i];
+       for_each_engine_id(useless, dev_priv, id) {
+               i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[id];
 
                if (i915_mmio_reg_valid(mbox_reg)) {
                        u32 seqno = i915_gem_request_get_seqno(signaller_req);
@@ -1388,22 +1403,23 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req,
 static int
 gen6_add_request(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
-       if (ring->semaphore.signal)
-               ret = ring->semaphore.signal(req, 4);
+       if (engine->semaphore.signal)
+               ret = engine->semaphore.signal(req, 4);
        else
                ret = intel_ring_begin(req, 4);
 
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
-       intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-       intel_ring_emit(ring, i915_gem_request_get_seqno(req));
-       intel_ring_emit(ring, MI_USER_INTERRUPT);
-       __intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_STORE_DWORD_INDEX);
+       intel_ring_emit(engine,
+                       I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+       intel_ring_emit(engine, i915_gem_request_get_seqno(req));
+       intel_ring_emit(engine, MI_USER_INTERRUPT);
+       __intel_ring_advance(engine);
 
        return 0;
 }
@@ -1428,7 +1444,7 @@ gen8_ring_sync(struct drm_i915_gem_request *waiter_req,
               struct intel_engine_cs *signaller,
               u32 seqno)
 {
-       struct intel_engine_cs *waiter = waiter_req->ring;
+       struct intel_engine_cs *waiter = waiter_req->engine;
        struct drm_i915_private *dev_priv = waiter->dev->dev_private;
        int ret;
 
@@ -1454,7 +1470,7 @@ gen6_ring_sync(struct drm_i915_gem_request *waiter_req,
               struct intel_engine_cs *signaller,
               u32 seqno)
 {
-       struct intel_engine_cs *waiter = waiter_req->ring;
+       struct intel_engine_cs *waiter = waiter_req->engine;
        u32 dw1 = MI_SEMAPHORE_MBOX |
                  MI_SEMAPHORE_COMPARE |
                  MI_SEMAPHORE_REGISTER;
@@ -1502,8 +1518,8 @@ do {                                                                      \
 static int
 pc_render_add_request(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
-       u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+       struct intel_engine_cs *engine = req->engine;
+       u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
        int ret;
 
        /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently
@@ -1518,78 +1534,82 @@ pc_render_add_request(struct drm_i915_gem_request *req)
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+       intel_ring_emit(engine,
+                       GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
                        PIPE_CONTROL_WRITE_FLUSH |
                        PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
-       intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
-       intel_ring_emit(ring, i915_gem_request_get_seqno(req));
-       intel_ring_emit(ring, 0);
-       PIPE_CONTROL_FLUSH(ring, scratch_addr);
+       intel_ring_emit(engine,
+                       engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
+       intel_ring_emit(engine, i915_gem_request_get_seqno(req));
+       intel_ring_emit(engine, 0);
+       PIPE_CONTROL_FLUSH(engine, scratch_addr);
        scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */
-       PIPE_CONTROL_FLUSH(ring, scratch_addr);
+       PIPE_CONTROL_FLUSH(engine, scratch_addr);
        scratch_addr += 2 * CACHELINE_BYTES;
-       PIPE_CONTROL_FLUSH(ring, scratch_addr);
+       PIPE_CONTROL_FLUSH(engine, scratch_addr);
        scratch_addr += 2 * CACHELINE_BYTES;
-       PIPE_CONTROL_FLUSH(ring, scratch_addr);
+       PIPE_CONTROL_FLUSH(engine, scratch_addr);
        scratch_addr += 2 * CACHELINE_BYTES;
-       PIPE_CONTROL_FLUSH(ring, scratch_addr);
+       PIPE_CONTROL_FLUSH(engine, scratch_addr);
        scratch_addr += 2 * CACHELINE_BYTES;
-       PIPE_CONTROL_FLUSH(ring, scratch_addr);
+       PIPE_CONTROL_FLUSH(engine, scratch_addr);
 
-       intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+       intel_ring_emit(engine,
+                       GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
                        PIPE_CONTROL_WRITE_FLUSH |
                        PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
                        PIPE_CONTROL_NOTIFY);
-       intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
-       intel_ring_emit(ring, i915_gem_request_get_seqno(req));
-       intel_ring_emit(ring, 0);
-       __intel_ring_advance(ring);
+       intel_ring_emit(engine,
+                       engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
+       intel_ring_emit(engine, i915_gem_request_get_seqno(req));
+       intel_ring_emit(engine, 0);
+       __intel_ring_advance(engine);
 
        return 0;
 }
 
 static u32
-gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+gen6_ring_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency)
 {
        /* Workaround to force correct ordering between irq and seqno writes on
         * ivb (and maybe also on snb) by reading from a CS register (like
         * ACTHD) before reading the status page. */
        if (!lazy_coherency) {
-               struct drm_i915_private *dev_priv = ring->dev->dev_private;
-               POSTING_READ(RING_ACTHD(ring->mmio_base));
+               struct drm_i915_private *dev_priv = engine->dev->dev_private;
+               POSTING_READ(RING_ACTHD(engine->mmio_base));
        }
 
-       return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+       return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
 static u32
-ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+ring_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency)
 {
-       return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+       return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
 static void
-ring_set_seqno(struct intel_engine_cs *ring, u32 seqno)
+ring_set_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-       intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
+       intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
 }
 
 static u32
-pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+pc_render_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency)
 {
-       return ring->scratch.cpu_page[0];
+       return engine->scratch.cpu_page[0];
 }
 
 static void
-pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno)
+pc_render_set_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-       ring->scratch.cpu_page[0] = seqno;
+       engine->scratch.cpu_page[0] = seqno;
 }
 
 static bool
-gen5_ring_get_irq(struct intel_engine_cs *ring)
+gen5_ring_get_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
@@ -1597,30 +1617,30 @@ gen5_ring_get_irq(struct intel_engine_cs *ring)
                return false;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (ring->irq_refcount++ == 0)
-               gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
+       if (engine->irq_refcount++ == 0)
+               gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask);
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
        return true;
 }
 
 static void
-gen5_ring_put_irq(struct intel_engine_cs *ring)
+gen5_ring_put_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (--ring->irq_refcount == 0)
-               gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
+       if (--engine->irq_refcount == 0)
+               gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask);
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
 static bool
-i9xx_ring_get_irq(struct intel_engine_cs *ring)
+i9xx_ring_get_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
@@ -1628,8 +1648,8 @@ i9xx_ring_get_irq(struct intel_engine_cs *ring)
                return false;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (ring->irq_refcount++ == 0) {
-               dev_priv->irq_mask &= ~ring->irq_enable_mask;
+       if (engine->irq_refcount++ == 0) {
+               dev_priv->irq_mask &= ~engine->irq_enable_mask;
                I915_WRITE(IMR, dev_priv->irq_mask);
                POSTING_READ(IMR);
        }
@@ -1639,15 +1659,15 @@ i9xx_ring_get_irq(struct intel_engine_cs *ring)
 }
 
 static void
-i9xx_ring_put_irq(struct intel_engine_cs *ring)
+i9xx_ring_put_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (--ring->irq_refcount == 0) {
-               dev_priv->irq_mask |= ring->irq_enable_mask;
+       if (--engine->irq_refcount == 0) {
+               dev_priv->irq_mask |= engine->irq_enable_mask;
                I915_WRITE(IMR, dev_priv->irq_mask);
                POSTING_READ(IMR);
        }
@@ -1655,9 +1675,9 @@ i9xx_ring_put_irq(struct intel_engine_cs *ring)
 }
 
 static bool
-i8xx_ring_get_irq(struct intel_engine_cs *ring)
+i8xx_ring_get_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
@@ -1665,8 +1685,8 @@ i8xx_ring_get_irq(struct intel_engine_cs *ring)
                return false;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (ring->irq_refcount++ == 0) {
-               dev_priv->irq_mask &= ~ring->irq_enable_mask;
+       if (engine->irq_refcount++ == 0) {
+               dev_priv->irq_mask &= ~engine->irq_enable_mask;
                I915_WRITE16(IMR, dev_priv->irq_mask);
                POSTING_READ16(IMR);
        }
@@ -1676,15 +1696,15 @@ i8xx_ring_get_irq(struct intel_engine_cs *ring)
 }
 
 static void
-i8xx_ring_put_irq(struct intel_engine_cs *ring)
+i8xx_ring_put_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (--ring->irq_refcount == 0) {
-               dev_priv->irq_mask |= ring->irq_enable_mask;
+       if (--engine->irq_refcount == 0) {
+               dev_priv->irq_mask |= engine->irq_enable_mask;
                I915_WRITE16(IMR, dev_priv->irq_mask);
                POSTING_READ16(IMR);
        }
@@ -1696,42 +1716,43 @@ bsd_ring_flush(struct drm_i915_gem_request *req,
               u32     invalidate_domains,
               u32     flush_domains)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        ret = intel_ring_begin(req, 2);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_FLUSH);
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_FLUSH);
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
        return 0;
 }
 
 static int
 i9xx_add_request(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        ret = intel_ring_begin(req, 4);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
-       intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-       intel_ring_emit(ring, i915_gem_request_get_seqno(req));
-       intel_ring_emit(ring, MI_USER_INTERRUPT);
-       __intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_STORE_DWORD_INDEX);
+       intel_ring_emit(engine,
+                       I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+       intel_ring_emit(engine, i915_gem_request_get_seqno(req));
+       intel_ring_emit(engine, MI_USER_INTERRUPT);
+       __intel_ring_advance(engine);
 
        return 0;
 }
 
 static bool
-gen6_ring_get_irq(struct intel_engine_cs *ring)
+gen6_ring_get_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
@@ -1739,14 +1760,14 @@ gen6_ring_get_irq(struct intel_engine_cs *ring)
                return false;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (ring->irq_refcount++ == 0) {
-               if (HAS_L3_DPF(dev) && ring->id == RCS)
-                       I915_WRITE_IMR(ring,
-                                      ~(ring->irq_enable_mask |
+       if (engine->irq_refcount++ == 0) {
+               if (HAS_L3_DPF(dev) && engine->id == RCS)
+                       I915_WRITE_IMR(engine,
+                                      ~(engine->irq_enable_mask |
                                         GT_PARITY_ERROR(dev)));
                else
-                       I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
-               gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
+                       I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
+               gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask);
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
@@ -1754,27 +1775,27 @@ gen6_ring_get_irq(struct intel_engine_cs *ring)
 }
 
 static void
-gen6_ring_put_irq(struct intel_engine_cs *ring)
+gen6_ring_put_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (--ring->irq_refcount == 0) {
-               if (HAS_L3_DPF(dev) && ring->id == RCS)
-                       I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
+       if (--engine->irq_refcount == 0) {
+               if (HAS_L3_DPF(dev) && engine->id == RCS)
+                       I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev));
                else
-                       I915_WRITE_IMR(ring, ~0);
-               gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
+                       I915_WRITE_IMR(engine, ~0);
+               gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask);
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
 static bool
-hsw_vebox_get_irq(struct intel_engine_cs *ring)
+hsw_vebox_get_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
@@ -1782,9 +1803,9 @@ hsw_vebox_get_irq(struct intel_engine_cs *ring)
                return false;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (ring->irq_refcount++ == 0) {
-               I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
-               gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask);
+       if (engine->irq_refcount++ == 0) {
+               I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
+               gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask);
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
@@ -1792,24 +1813,24 @@ hsw_vebox_get_irq(struct intel_engine_cs *ring)
 }
 
 static void
-hsw_vebox_put_irq(struct intel_engine_cs *ring)
+hsw_vebox_put_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (--ring->irq_refcount == 0) {
-               I915_WRITE_IMR(ring, ~0);
-               gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask);
+       if (--engine->irq_refcount == 0) {
+               I915_WRITE_IMR(engine, ~0);
+               gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask);
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
 static bool
-gen8_ring_get_irq(struct intel_engine_cs *ring)
+gen8_ring_get_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
@@ -1817,15 +1838,15 @@ gen8_ring_get_irq(struct intel_engine_cs *ring)
                return false;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (ring->irq_refcount++ == 0) {
-               if (HAS_L3_DPF(dev) && ring->id == RCS) {
-                       I915_WRITE_IMR(ring,
-                                      ~(ring->irq_enable_mask |
+       if (engine->irq_refcount++ == 0) {
+               if (HAS_L3_DPF(dev) && engine->id == RCS) {
+                       I915_WRITE_IMR(engine,
+                                      ~(engine->irq_enable_mask |
                                         GT_RENDER_L3_PARITY_ERROR_INTERRUPT));
                } else {
-                       I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
+                       I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
                }
-               POSTING_READ(RING_IMR(ring->mmio_base));
+               POSTING_READ(RING_IMR(engine->mmio_base));
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
@@ -1833,21 +1854,21 @@ gen8_ring_get_irq(struct intel_engine_cs *ring)
 }
 
 static void
-gen8_ring_put_irq(struct intel_engine_cs *ring)
+gen8_ring_put_irq(struct intel_engine_cs *engine)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long flags;
 
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
-       if (--ring->irq_refcount == 0) {
-               if (HAS_L3_DPF(dev) && ring->id == RCS) {
-                       I915_WRITE_IMR(ring,
+       if (--engine->irq_refcount == 0) {
+               if (HAS_L3_DPF(dev) && engine->id == RCS) {
+                       I915_WRITE_IMR(engine,
                                       ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
                } else {
-                       I915_WRITE_IMR(ring, ~0);
+                       I915_WRITE_IMR(engine, ~0);
                }
-               POSTING_READ(RING_IMR(ring->mmio_base));
+               POSTING_READ(RING_IMR(engine->mmio_base));
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
@@ -1857,20 +1878,20 @@ i965_dispatch_execbuffer(struct drm_i915_gem_request *req,
                         u64 offset, u32 length,
                         unsigned dispatch_flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        ret = intel_ring_begin(req, 2);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring,
+       intel_ring_emit(engine,
                        MI_BATCH_BUFFER_START |
                        MI_BATCH_GTT |
                        (dispatch_flags & I915_DISPATCH_SECURE ?
                         0 : MI_BATCH_NON_SECURE_I965));
-       intel_ring_emit(ring, offset);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, offset);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -1884,8 +1905,8 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req,
                         u64 offset, u32 len,
                         unsigned dispatch_flags)
 {
-       struct intel_engine_cs *ring = req->ring;
-       u32 cs_offset = ring->scratch.gtt_offset;
+       struct intel_engine_cs *engine = req->engine;
+       u32 cs_offset = engine->scratch.gtt_offset;
        int ret;
 
        ret = intel_ring_begin(req, 6);
@@ -1893,13 +1914,13 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req,
                return ret;
 
        /* Evict the invalid PTE TLBs */
-       intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA);
-       intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
-       intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */
-       intel_ring_emit(ring, cs_offset);
-       intel_ring_emit(ring, 0xdeadbeef);
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, COLOR_BLT_CMD | BLT_WRITE_RGBA);
+       intel_ring_emit(engine, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
+       intel_ring_emit(engine, I830_TLB_ENTRIES << 16 | 4); /* load each page */
+       intel_ring_emit(engine, cs_offset);
+       intel_ring_emit(engine, 0xdeadbeef);
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
 
        if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) {
                if (len > I830_BATCH_LIMIT)
@@ -1913,16 +1934,17 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req,
                 * stable batch scratch bo area (so that the CS never
                 * stumbles over its tlb invalidation bug) ...
                 */
-               intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
-               intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
-               intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096);
-               intel_ring_emit(ring, cs_offset);
-               intel_ring_emit(ring, 4096);
-               intel_ring_emit(ring, offset);
-
-               intel_ring_emit(ring, MI_FLUSH);
-               intel_ring_emit(ring, MI_NOOP);
-               intel_ring_advance(ring);
+               intel_ring_emit(engine, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
+               intel_ring_emit(engine,
+                               BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
+               intel_ring_emit(engine, DIV_ROUND_UP(len, 4096) << 16 | 4096);
+               intel_ring_emit(engine, cs_offset);
+               intel_ring_emit(engine, 4096);
+               intel_ring_emit(engine, offset);
+
+               intel_ring_emit(engine, MI_FLUSH);
+               intel_ring_emit(engine, MI_NOOP);
+               intel_ring_advance(engine);
 
                /* ... and execute it. */
                offset = cs_offset;
@@ -1932,10 +1954,10 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req,
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
-       intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
-                                       0 : MI_BATCH_NON_SECURE));
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
+       intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
+                                         0 : MI_BATCH_NON_SECURE));
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -1945,55 +1967,55 @@ i915_dispatch_execbuffer(struct drm_i915_gem_request *req,
                         u64 offset, u32 len,
                         unsigned dispatch_flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        ret = intel_ring_begin(req, 2);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
-       intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
-                                       0 : MI_BATCH_NON_SECURE));
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
+       intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
+                                         0 : MI_BATCH_NON_SECURE));
+       intel_ring_advance(engine);
 
        return 0;
 }
 
-static void cleanup_phys_status_page(struct intel_engine_cs *ring)
+static void cleanup_phys_status_page(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = to_i915(ring->dev);
+       struct drm_i915_private *dev_priv = to_i915(engine->dev);
 
        if (!dev_priv->status_page_dmah)
                return;
 
-       drm_pci_free(ring->dev, dev_priv->status_page_dmah);
-       ring->status_page.page_addr = NULL;
+       drm_pci_free(engine->dev, dev_priv->status_page_dmah);
+       engine->status_page.page_addr = NULL;
 }
 
-static void cleanup_status_page(struct intel_engine_cs *ring)
+static void cleanup_status_page(struct intel_engine_cs *engine)
 {
        struct drm_i915_gem_object *obj;
 
-       obj = ring->status_page.obj;
+       obj = engine->status_page.obj;
        if (obj == NULL)
                return;
 
        kunmap(sg_page(obj->pages->sgl));
        i915_gem_object_ggtt_unpin(obj);
        drm_gem_object_unreference(&obj->base);
-       ring->status_page.obj = NULL;
+       engine->status_page.obj = NULL;
 }
 
-static int init_status_page(struct intel_engine_cs *ring)
+static int init_status_page(struct intel_engine_cs *engine)
 {
-       struct drm_i915_gem_object *obj = ring->status_page.obj;
+       struct drm_i915_gem_object *obj = engine->status_page.obj;
 
        if (obj == NULL) {
                unsigned flags;
                int ret;
 
-               obj = i915_gem_alloc_object(ring->dev, 4096);
+               obj = i915_gem_alloc_object(engine->dev, 4096);
                if (obj == NULL) {
                        DRM_ERROR("Failed to allocate status page\n");
                        return -ENOMEM;
@@ -2004,7 +2026,7 @@ static int init_status_page(struct intel_engine_cs *ring)
                        goto err_unref;
 
                flags = 0;
-               if (!HAS_LLC(ring->dev))
+               if (!HAS_LLC(engine->dev))
                        /* On g33, we cannot place HWS above 256MiB, so
                         * restrict its pinning to the low mappable arena.
                         * Though this restriction is not documented for
@@ -2023,32 +2045,32 @@ err_unref:
                        return ret;
                }
 
-               ring->status_page.obj = obj;
+               engine->status_page.obj = obj;
        }
 
-       ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
-       ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
-       memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+       engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
+       engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
+       memset(engine->status_page.page_addr, 0, PAGE_SIZE);
 
        DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
-                       ring->name, ring->status_page.gfx_addr);
+                       engine->name, engine->status_page.gfx_addr);
 
        return 0;
 }
 
-static int init_phys_status_page(struct intel_engine_cs *ring)
+static int init_phys_status_page(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
 
        if (!dev_priv->status_page_dmah) {
                dev_priv->status_page_dmah =
-                       drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE);
+                       drm_pci_alloc(engine->dev, PAGE_SIZE, PAGE_SIZE);
                if (!dev_priv->status_page_dmah)
                        return -ENOMEM;
        }
 
-       ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
-       memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+       engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
+       memset(engine->status_page.page_addr, 0, PAGE_SIZE);
 
        return 0;
 }
@@ -2122,7 +2144,7 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
                /* Access through the GTT requires the device to be awake. */
                assert_rpm_wakelock_held(dev_priv);
 
-               ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base +
+               ringbuf->virtual_start = ioremap_wc(dev_priv->ggtt.mappable_base +
                                                    i915_gem_obj_ggtt_offset(obj), ringbuf->size);
                if (ringbuf->virtual_start == NULL) {
                        i915_gem_object_ggtt_unpin(obj);
@@ -2175,7 +2197,7 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)
                return ERR_PTR(-ENOMEM);
        }
 
-       ring->ring = engine;
+       ring->engine = engine;
        list_add(&ring->link, &engine->buffers);
 
        ring->size = size;
@@ -2211,37 +2233,38 @@ intel_ringbuffer_free(struct intel_ringbuffer *ring)
 }
 
 static int intel_init_ring_buffer(struct drm_device *dev,
-                                 struct intel_engine_cs *ring)
+                                 struct intel_engine_cs *engine)
 {
        struct intel_ringbuffer *ringbuf;
        int ret;
 
-       WARN_ON(ring->buffer);
+       WARN_ON(engine->buffer);
 
-       ring->dev = dev;
-       INIT_LIST_HEAD(&ring->active_list);
-       INIT_LIST_HEAD(&ring->request_list);
-       INIT_LIST_HEAD(&ring->execlist_queue);
-       INIT_LIST_HEAD(&ring->buffers);
-       i915_gem_batch_pool_init(dev, &ring->batch_pool);
-       memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno));
+       engine->dev = dev;
+       INIT_LIST_HEAD(&engine->active_list);
+       INIT_LIST_HEAD(&engine->request_list);
+       INIT_LIST_HEAD(&engine->execlist_queue);
+       INIT_LIST_HEAD(&engine->buffers);
+       i915_gem_batch_pool_init(dev, &engine->batch_pool);
+       memset(engine->semaphore.sync_seqno, 0,
+              sizeof(engine->semaphore.sync_seqno));
 
-       init_waitqueue_head(&ring->irq_queue);
+       init_waitqueue_head(&engine->irq_queue);
 
-       ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE);
+       ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE);
        if (IS_ERR(ringbuf)) {
                ret = PTR_ERR(ringbuf);
                goto error;
        }
-       ring->buffer = ringbuf;
+       engine->buffer = ringbuf;
 
        if (I915_NEED_GFX_HWS(dev)) {
-               ret = init_status_page(ring);
+               ret = init_status_page(engine);
                if (ret)
                        goto error;
        } else {
-               WARN_ON(ring->id != RCS);
-               ret = init_phys_status_page(ring);
+               WARN_ON(engine->id != RCS);
+               ret = init_phys_status_page(engine);
                if (ret)
                        goto error;
        }
@@ -2249,58 +2272,58 @@ static int intel_init_ring_buffer(struct drm_device *dev,
        ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf);
        if (ret) {
                DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n",
-                               ring->name, ret);
+                               engine->name, ret);
                intel_destroy_ringbuffer_obj(ringbuf);
                goto error;
        }
 
-       ret = i915_cmd_parser_init_ring(ring);
+       ret = i915_cmd_parser_init_ring(engine);
        if (ret)
                goto error;
 
        return 0;
 
 error:
-       intel_cleanup_ring_buffer(ring);
+       intel_cleanup_engine(engine);
        return ret;
 }
 
-void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
+void intel_cleanup_engine(struct intel_engine_cs *engine)
 {
        struct drm_i915_private *dev_priv;
 
-       if (!intel_ring_initialized(ring))
+       if (!intel_engine_initialized(engine))
                return;
 
-       dev_priv = to_i915(ring->dev);
+       dev_priv = to_i915(engine->dev);
 
-       if (ring->buffer) {
-               intel_stop_ring_buffer(ring);
-               WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
+       if (engine->buffer) {
+               intel_stop_engine(engine);
+               WARN_ON(!IS_GEN2(engine->dev) && (I915_READ_MODE(engine) & MODE_IDLE) == 0);
 
-               intel_unpin_ringbuffer_obj(ring->buffer);
-               intel_ringbuffer_free(ring->buffer);
-               ring->buffer = NULL;
+               intel_unpin_ringbuffer_obj(engine->buffer);
+               intel_ringbuffer_free(engine->buffer);
+               engine->buffer = NULL;
        }
 
-       if (ring->cleanup)
-               ring->cleanup(ring);
+       if (engine->cleanup)
+               engine->cleanup(engine);
 
-       if (I915_NEED_GFX_HWS(ring->dev)) {
-               cleanup_status_page(ring);
+       if (I915_NEED_GFX_HWS(engine->dev)) {
+               cleanup_status_page(engine);
        } else {
-               WARN_ON(ring->id != RCS);
-               cleanup_phys_status_page(ring);
+               WARN_ON(engine->id != RCS);
+               cleanup_phys_status_page(engine);
        }
 
-       i915_cmd_parser_fini_ring(ring);
-       i915_gem_batch_pool_fini(&ring->batch_pool);
-       ring->dev = NULL;
+       i915_cmd_parser_fini_ring(engine);
+       i915_gem_batch_pool_fini(&engine->batch_pool);
+       engine->dev = NULL;
 }
 
-static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
+static int ring_wait_for_space(struct intel_engine_cs *engine, int n)
 {
-       struct intel_ringbuffer *ringbuf = ring->buffer;
+       struct intel_ringbuffer *ringbuf = engine->buffer;
        struct drm_i915_gem_request *request;
        unsigned space;
        int ret;
@@ -2311,14 +2334,14 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
        /* The whole point of reserving space is to not wait! */
        WARN_ON(ringbuf->reserved_in_use);
 
-       list_for_each_entry(request, &ring->request_list, list) {
+       list_for_each_entry(request, &engine->request_list, list) {
                space = __intel_ring_space(request->postfix, ringbuf->tail,
                                           ringbuf->size);
                if (space >= n)
                        break;
        }
 
-       if (WARN_ON(&request->list == &ring->request_list))
+       if (WARN_ON(&request->list == &engine->request_list))
                return -ENOSPC;
 
        ret = i915_wait_request(request);
@@ -2343,28 +2366,28 @@ static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf)
        intel_ring_update_space(ringbuf);
 }
 
-int intel_ring_idle(struct intel_engine_cs *ring)
+int intel_engine_idle(struct intel_engine_cs *engine)
 {
        struct drm_i915_gem_request *req;
 
        /* Wait upon the last request to be completed */
-       if (list_empty(&ring->request_list))
+       if (list_empty(&engine->request_list))
                return 0;
 
-       req = list_entry(ring->request_list.prev,
-                       struct drm_i915_gem_request,
-                       list);
+       req = list_entry(engine->request_list.prev,
+                        struct drm_i915_gem_request,
+                        list);
 
        /* Make sure we do not trigger any retires */
        return __i915_wait_request(req,
-                                  atomic_read(&to_i915(ring->dev)->gpu_error.reset_counter),
-                                  to_i915(ring->dev)->mm.interruptible,
+                                  atomic_read(&to_i915(engine->dev)->gpu_error.reset_counter),
+                                  to_i915(engine->dev)->mm.interruptible,
                                   NULL, NULL);
 }
 
 int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request)
 {
-       request->ringbuf = request->ring->buffer;
+       request->ringbuf = request->engine->buffer;
        return 0;
 }
 
@@ -2430,9 +2453,9 @@ void intel_ring_reserved_space_end(struct intel_ringbuffer *ringbuf)
        ringbuf->reserved_in_use = false;
 }
 
-static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes)
+static int __intel_ring_prepare(struct intel_engine_cs *engine, int bytes)
 {
-       struct intel_ringbuffer *ringbuf = ring->buffer;
+       struct intel_ringbuffer *ringbuf = engine->buffer;
        int remain_usable = ringbuf->effective_size - ringbuf->tail;
        int remain_actual = ringbuf->size - ringbuf->tail;
        int ret, total_bytes, wait_bytes = 0;
@@ -2466,7 +2489,7 @@ static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes)
        }
 
        if (wait_bytes) {
-               ret = ring_wait_for_space(ring, wait_bytes);
+               ret = ring_wait_for_space(engine, wait_bytes);
                if (unlikely(ret))
                        return ret;
 
@@ -2480,32 +2503,32 @@ static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes)
 int intel_ring_begin(struct drm_i915_gem_request *req,
                     int num_dwords)
 {
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct drm_i915_private *dev_priv;
        int ret;
 
        WARN_ON(req == NULL);
-       ring = req->ring;
-       dev_priv = ring->dev->dev_private;
+       engine = req->engine;
+       dev_priv = req->i915;
 
        ret = i915_gem_check_wedge(&dev_priv->gpu_error,
                                   dev_priv->mm.interruptible);
        if (ret)
                return ret;
 
-       ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t));
+       ret = __intel_ring_prepare(engine, num_dwords * sizeof(uint32_t));
        if (ret)
                return ret;
 
-       ring->buffer->space -= num_dwords * sizeof(uint32_t);
+       engine->buffer->space -= num_dwords * sizeof(uint32_t);
        return 0;
 }
 
 /* Align the ring tail to a cacheline boundary */
 int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
-       int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
+       struct intel_engine_cs *engine = req->engine;
+       int num_dwords = (engine->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
        int ret;
 
        if (num_dwords == 0)
@@ -2517,33 +2540,33 @@ int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
                return ret;
 
        while (num_dwords--)
-               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(engine, MI_NOOP);
 
-       intel_ring_advance(ring);
+       intel_ring_advance(engine);
 
        return 0;
 }
 
-void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno)
+void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-       struct drm_device *dev = ring->dev;
+       struct drm_device *dev = engine->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) {
-               I915_WRITE(RING_SYNC_0(ring->mmio_base), 0);
-               I915_WRITE(RING_SYNC_1(ring->mmio_base), 0);
+               I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
+               I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
                if (HAS_VEBOX(dev))
-                       I915_WRITE(RING_SYNC_2(ring->mmio_base), 0);
+                       I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
        }
 
-       ring->set_seqno(ring, seqno);
-       ring->hangcheck.seqno = seqno;
+       engine->set_seqno(engine, seqno);
+       engine->hangcheck.seqno = seqno;
 }
 
-static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring,
+static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine,
                                     u32 value)
 {
-       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
 
        /* Every tail move must follow the sequence below */
 
@@ -2563,8 +2586,8 @@ static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring,
                DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
 
        /* Now that the ring is fully powered up, update the tail */
-       I915_WRITE_TAIL(ring, value);
-       POSTING_READ(RING_TAIL(ring->mmio_base));
+       I915_WRITE_TAIL(engine, value);
+       POSTING_READ(RING_TAIL(engine->mmio_base));
 
        /* Let the ring send IDLE messages to the GT again,
         * and so let it sleep to conserve power when idle.
@@ -2576,7 +2599,7 @@ static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring,
 static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req,
                               u32 invalidate, u32 flush)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        uint32_t cmd;
        int ret;
 
@@ -2585,7 +2608,7 @@ static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req,
                return ret;
 
        cmd = MI_FLUSH_DW;
-       if (INTEL_INFO(ring->dev)->gen >= 8)
+       if (INTEL_INFO(engine->dev)->gen >= 8)
                cmd += 1;
 
        /* We always require a command barrier so that subsequent
@@ -2604,16 +2627,17 @@ static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req,
        if (invalidate & I915_GEM_GPU_DOMAINS)
                cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
 
-       intel_ring_emit(ring, cmd);
-       intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
-       if (INTEL_INFO(ring->dev)->gen >= 8) {
-               intel_ring_emit(ring, 0); /* upper addr */
-               intel_ring_emit(ring, 0); /* value */
+       intel_ring_emit(engine, cmd);
+       intel_ring_emit(engine,
+                       I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
+       if (INTEL_INFO(engine->dev)->gen >= 8) {
+               intel_ring_emit(engine, 0); /* upper addr */
+               intel_ring_emit(engine, 0); /* value */
        } else  {
-               intel_ring_emit(ring, 0);
-               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(engine, 0);
+               intel_ring_emit(engine, MI_NOOP);
        }
-       intel_ring_advance(ring);
+       intel_ring_advance(engine);
        return 0;
 }
 
@@ -2622,8 +2646,8 @@ gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req,
                              u64 offset, u32 len,
                              unsigned dispatch_flags)
 {
-       struct intel_engine_cs *ring = req->ring;
-       bool ppgtt = USES_PPGTT(ring->dev) &&
+       struct intel_engine_cs *engine = req->engine;
+       bool ppgtt = USES_PPGTT(engine->dev) &&
                        !(dispatch_flags & I915_DISPATCH_SECURE);
        int ret;
 
@@ -2632,13 +2656,13 @@ gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req,
                return ret;
 
        /* FIXME(BDW): Address space and security selectors. */
-       intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) |
+       intel_ring_emit(engine, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) |
                        (dispatch_flags & I915_DISPATCH_RS ?
                         MI_BATCH_RESOURCE_STREAMER : 0));
-       intel_ring_emit(ring, lower_32_bits(offset));
-       intel_ring_emit(ring, upper_32_bits(offset));
-       intel_ring_emit(ring, MI_NOOP);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, lower_32_bits(offset));
+       intel_ring_emit(engine, upper_32_bits(offset));
+       intel_ring_emit(engine, MI_NOOP);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -2648,22 +2672,22 @@ hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req,
                             u64 offset, u32 len,
                             unsigned dispatch_flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        ret = intel_ring_begin(req, 2);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring,
+       intel_ring_emit(engine,
                        MI_BATCH_BUFFER_START |
                        (dispatch_flags & I915_DISPATCH_SECURE ?
                         0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) |
                        (dispatch_flags & I915_DISPATCH_RS ?
                         MI_BATCH_RESOURCE_STREAMER : 0));
        /* bit0-7 is the length on GEN6+ */
-       intel_ring_emit(ring, offset);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, offset);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -2673,20 +2697,20 @@ gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req,
                              u64 offset, u32 len,
                              unsigned dispatch_flags)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
        ret = intel_ring_begin(req, 2);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring,
+       intel_ring_emit(engine,
                        MI_BATCH_BUFFER_START |
                        (dispatch_flags & I915_DISPATCH_SECURE ?
                         0 : MI_BATCH_NON_SECURE_I965));
        /* bit0-7 is the length on GEN6+ */
-       intel_ring_emit(ring, offset);
-       intel_ring_advance(ring);
+       intel_ring_emit(engine, offset);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -2696,8 +2720,8 @@ gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req,
 static int gen6_ring_flush(struct drm_i915_gem_request *req,
                           u32 invalidate, u32 flush)
 {
-       struct intel_engine_cs *ring = req->ring;
-       struct drm_device *dev = ring->dev;
+       struct intel_engine_cs *engine = req->engine;
+       struct drm_device *dev = engine->dev;
        uint32_t cmd;
        int ret;
 
@@ -2724,16 +2748,17 @@ static int gen6_ring_flush(struct drm_i915_gem_request *req,
         */
        if (invalidate & I915_GEM_DOMAIN_RENDER)
                cmd |= MI_INVALIDATE_TLB;
-       intel_ring_emit(ring, cmd);
-       intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
+       intel_ring_emit(engine, cmd);
+       intel_ring_emit(engine,
+                       I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
        if (INTEL_INFO(dev)->gen >= 8) {
-               intel_ring_emit(ring, 0); /* upper addr */
-               intel_ring_emit(ring, 0); /* value */
+               intel_ring_emit(engine, 0); /* upper addr */
+               intel_ring_emit(engine, 0); /* value */
        } else  {
-               intel_ring_emit(ring, 0);
-               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(engine, 0);
+               intel_ring_emit(engine, MI_NOOP);
        }
-       intel_ring_advance(ring);
+       intel_ring_advance(engine);
 
        return 0;
 }
@@ -2741,14 +2766,14 @@ static int gen6_ring_flush(struct drm_i915_gem_request *req,
 int intel_init_render_ring_buffer(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+       struct intel_engine_cs *engine = &dev_priv->engine[RCS];
        struct drm_i915_gem_object *obj;
        int ret;
 
-       ring->name = "render ring";
-       ring->id = RCS;
-       ring->exec_id = I915_EXEC_RENDER;
-       ring->mmio_base = RENDER_RING_BASE;
+       engine->name = "render ring";
+       engine->id = RCS;
+       engine->exec_id = I915_EXEC_RENDER;
+       engine->mmio_base = RENDER_RING_BASE;
 
        if (INTEL_INFO(dev)->gen >= 8) {
                if (i915_semaphore_is_enabled(dev)) {
@@ -2768,34 +2793,34 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
                        }
                }
 
-               ring->init_context = intel_rcs_ctx_init;
-               ring->add_request = gen6_add_request;
-               ring->flush = gen8_render_ring_flush;
-               ring->irq_get = gen8_ring_get_irq;
-               ring->irq_put = gen8_ring_put_irq;
-               ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
-               ring->get_seqno = gen6_ring_get_seqno;
-               ring->set_seqno = ring_set_seqno;
+               engine->init_context = intel_rcs_ctx_init;
+               engine->add_request = gen6_add_request;
+               engine->flush = gen8_render_ring_flush;
+               engine->irq_get = gen8_ring_get_irq;
+               engine->irq_put = gen8_ring_put_irq;
+               engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
+               engine->get_seqno = gen6_ring_get_seqno;
+               engine->set_seqno = ring_set_seqno;
                if (i915_semaphore_is_enabled(dev)) {
                        WARN_ON(!dev_priv->semaphore_obj);
-                       ring->semaphore.sync_to = gen8_ring_sync;
-                       ring->semaphore.signal = gen8_rcs_signal;
-                       GEN8_RING_SEMAPHORE_INIT;
+                       engine->semaphore.sync_to = gen8_ring_sync;
+                       engine->semaphore.signal = gen8_rcs_signal;
+                       GEN8_RING_SEMAPHORE_INIT(engine);
                }
        } else if (INTEL_INFO(dev)->gen >= 6) {
-               ring->init_context = intel_rcs_ctx_init;
-               ring->add_request = gen6_add_request;
-               ring->flush = gen7_render_ring_flush;
+               engine->init_context = intel_rcs_ctx_init;
+               engine->add_request = gen6_add_request;
+               engine->flush = gen7_render_ring_flush;
                if (INTEL_INFO(dev)->gen == 6)
-                       ring->flush = gen6_render_ring_flush;
-               ring->irq_get = gen6_ring_get_irq;
-               ring->irq_put = gen6_ring_put_irq;
-               ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
-               ring->get_seqno = gen6_ring_get_seqno;
-               ring->set_seqno = ring_set_seqno;
+                       engine->flush = gen6_render_ring_flush;
+               engine->irq_get = gen6_ring_get_irq;
+               engine->irq_put = gen6_ring_put_irq;
+               engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
+               engine->get_seqno = gen6_ring_get_seqno;
+               engine->set_seqno = ring_set_seqno;
                if (i915_semaphore_is_enabled(dev)) {
-                       ring->semaphore.sync_to = gen6_ring_sync;
-                       ring->semaphore.signal = gen6_signal;
+                       engine->semaphore.sync_to = gen6_ring_sync;
+                       engine->semaphore.signal = gen6_signal;
                        /*
                         * The current semaphore is only applied on pre-gen8
                         * platform.  And there is no VCS2 ring on the pre-gen8
@@ -2803,59 +2828,59 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
                         * initialized as INVALID.  Gen8 will initialize the
                         * sema between VCS2 and RCS later.
                         */
-                       ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
-                       ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
-                       ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
-                       ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
-                       ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-                       ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
-                       ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
-                       ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
-                       ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
-                       ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+                       engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+                       engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
+                       engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
+                       engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
+                       engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+                       engine->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+                       engine->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
+                       engine->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
+                       engine->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
+                       engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
                }
        } else if (IS_GEN5(dev)) {
-               ring->add_request = pc_render_add_request;
-               ring->flush = gen4_render_ring_flush;
-               ring->get_seqno = pc_render_get_seqno;
-               ring->set_seqno = pc_render_set_seqno;
-               ring->irq_get = gen5_ring_get_irq;
-               ring->irq_put = gen5_ring_put_irq;
-               ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT |
+               engine->add_request = pc_render_add_request;
+               engine->flush = gen4_render_ring_flush;
+               engine->get_seqno = pc_render_get_seqno;
+               engine->set_seqno = pc_render_set_seqno;
+               engine->irq_get = gen5_ring_get_irq;
+               engine->irq_put = gen5_ring_put_irq;
+               engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT |
                                        GT_RENDER_PIPECTL_NOTIFY_INTERRUPT;
        } else {
-               ring->add_request = i9xx_add_request;
+               engine->add_request = i9xx_add_request;
                if (INTEL_INFO(dev)->gen < 4)
-                       ring->flush = gen2_render_ring_flush;
+                       engine->flush = gen2_render_ring_flush;
                else
-                       ring->flush = gen4_render_ring_flush;
-               ring->get_seqno = ring_get_seqno;
-               ring->set_seqno = ring_set_seqno;
+                       engine->flush = gen4_render_ring_flush;
+               engine->get_seqno = ring_get_seqno;
+               engine->set_seqno = ring_set_seqno;
                if (IS_GEN2(dev)) {
-                       ring->irq_get = i8xx_ring_get_irq;
-                       ring->irq_put = i8xx_ring_put_irq;
+                       engine->irq_get = i8xx_ring_get_irq;
+                       engine->irq_put = i8xx_ring_put_irq;
                } else {
-                       ring->irq_get = i9xx_ring_get_irq;
-                       ring->irq_put = i9xx_ring_put_irq;
+                       engine->irq_get = i9xx_ring_get_irq;
+                       engine->irq_put = i9xx_ring_put_irq;
                }
-               ring->irq_enable_mask = I915_USER_INTERRUPT;
+               engine->irq_enable_mask = I915_USER_INTERRUPT;
        }
-       ring->write_tail = ring_write_tail;
+       engine->write_tail = ring_write_tail;
 
        if (IS_HASWELL(dev))
-               ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
+               engine->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
        else if (IS_GEN8(dev))
-               ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+               engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
        else if (INTEL_INFO(dev)->gen >= 6)
-               ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+               engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
        else if (INTEL_INFO(dev)->gen >= 4)
-               ring->dispatch_execbuffer = i965_dispatch_execbuffer;
+               engine->dispatch_execbuffer = i965_dispatch_execbuffer;
        else if (IS_I830(dev) || IS_845G(dev))
-               ring->dispatch_execbuffer = i830_dispatch_execbuffer;
+               engine->dispatch_execbuffer = i830_dispatch_execbuffer;
        else
-               ring->dispatch_execbuffer = i915_dispatch_execbuffer;
-       ring->init_hw = init_render_ring;
-       ring->cleanup = render_ring_cleanup;
+               engine->dispatch_execbuffer = i915_dispatch_execbuffer;
+       engine->init_hw = init_render_ring;
+       engine->cleanup = render_ring_cleanup;
 
        /* Workaround batchbuffer to combat CS tlb bug. */
        if (HAS_BROKEN_CS_TLB(dev)) {
@@ -2872,16 +2897,16 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
                        return ret;
                }
 
-               ring->scratch.obj = obj;
-               ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj);
+               engine->scratch.obj = obj;
+               engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj);
        }
 
-       ret = intel_init_ring_buffer(dev, ring);
+       ret = intel_init_ring_buffer(dev, engine);
        if (ret)
                return ret;
 
        if (INTEL_INFO(dev)->gen >= 5) {
-               ret = intel_init_pipe_control(ring);
+               ret = intel_init_pipe_control(engine);
                if (ret)
                        return ret;
        }
@@ -2892,75 +2917,75 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 int intel_init_bsd_ring_buffer(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[VCS];
+       struct intel_engine_cs *engine = &dev_priv->engine[VCS];
 
-       ring->name = "bsd ring";
-       ring->id = VCS;
-       ring->exec_id = I915_EXEC_BSD;
+       engine->name = "bsd ring";
+       engine->id = VCS;
+       engine->exec_id = I915_EXEC_BSD;
 
-       ring->write_tail = ring_write_tail;
+       engine->write_tail = ring_write_tail;
        if (INTEL_INFO(dev)->gen >= 6) {
-               ring->mmio_base = GEN6_BSD_RING_BASE;
+               engine->mmio_base = GEN6_BSD_RING_BASE;
                /* gen6 bsd needs a special wa for tail updates */
                if (IS_GEN6(dev))
-                       ring->write_tail = gen6_bsd_ring_write_tail;
-               ring->flush = gen6_bsd_ring_flush;
-               ring->add_request = gen6_add_request;
-               ring->get_seqno = gen6_ring_get_seqno;
-               ring->set_seqno = ring_set_seqno;
+                       engine->write_tail = gen6_bsd_ring_write_tail;
+               engine->flush = gen6_bsd_ring_flush;
+               engine->add_request = gen6_add_request;
+               engine->get_seqno = gen6_ring_get_seqno;
+               engine->set_seqno = ring_set_seqno;
                if (INTEL_INFO(dev)->gen >= 8) {
-                       ring->irq_enable_mask =
+                       engine->irq_enable_mask =
                                GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT;
-                       ring->irq_get = gen8_ring_get_irq;
-                       ring->irq_put = gen8_ring_put_irq;
-                       ring->dispatch_execbuffer =
+                       engine->irq_get = gen8_ring_get_irq;
+                       engine->irq_put = gen8_ring_put_irq;
+                       engine->dispatch_execbuffer =
                                gen8_ring_dispatch_execbuffer;
                        if (i915_semaphore_is_enabled(dev)) {
-                               ring->semaphore.sync_to = gen8_ring_sync;
-                               ring->semaphore.signal = gen8_xcs_signal;
-                               GEN8_RING_SEMAPHORE_INIT;
+                               engine->semaphore.sync_to = gen8_ring_sync;
+                               engine->semaphore.signal = gen8_xcs_signal;
+                               GEN8_RING_SEMAPHORE_INIT(engine);
                        }
                } else {
-                       ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
-                       ring->irq_get = gen6_ring_get_irq;
-                       ring->irq_put = gen6_ring_put_irq;
-                       ring->dispatch_execbuffer =
+                       engine->irq_enable_mask = GT_BSD_USER_INTERRUPT;
+                       engine->irq_get = gen6_ring_get_irq;
+                       engine->irq_put = gen6_ring_put_irq;
+                       engine->dispatch_execbuffer =
                                gen6_ring_dispatch_execbuffer;
                        if (i915_semaphore_is_enabled(dev)) {
-                               ring->semaphore.sync_to = gen6_ring_sync;
-                               ring->semaphore.signal = gen6_signal;
-                               ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
-                               ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
-                               ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
-                               ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
-                               ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-                               ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
-                               ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
-                               ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
-                               ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
-                               ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+                               engine->semaphore.sync_to = gen6_ring_sync;
+                               engine->semaphore.signal = gen6_signal;
+                               engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
+                               engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+                               engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
+                               engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
+                               engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+                               engine->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
+                               engine->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+                               engine->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
+                               engine->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
+                               engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
                        }
                }
        } else {
-               ring->mmio_base = BSD_RING_BASE;
-               ring->flush = bsd_ring_flush;
-               ring->add_request = i9xx_add_request;
-               ring->get_seqno = ring_get_seqno;
-               ring->set_seqno = ring_set_seqno;
+               engine->mmio_base = BSD_RING_BASE;
+               engine->flush = bsd_ring_flush;
+               engine->add_request = i9xx_add_request;
+               engine->get_seqno = ring_get_seqno;
+               engine->set_seqno = ring_set_seqno;
                if (IS_GEN5(dev)) {
-                       ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
-                       ring->irq_get = gen5_ring_get_irq;
-                       ring->irq_put = gen5_ring_put_irq;
+                       engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
+                       engine->irq_get = gen5_ring_get_irq;
+                       engine->irq_put = gen5_ring_put_irq;
                } else {
-                       ring->irq_enable_mask = I915_BSD_USER_INTERRUPT;
-                       ring->irq_get = i9xx_ring_get_irq;
-                       ring->irq_put = i9xx_ring_put_irq;
+                       engine->irq_enable_mask = I915_BSD_USER_INTERRUPT;
+                       engine->irq_get = i9xx_ring_get_irq;
+                       engine->irq_put = i9xx_ring_put_irq;
                }
-               ring->dispatch_execbuffer = i965_dispatch_execbuffer;
+               engine->dispatch_execbuffer = i965_dispatch_execbuffer;
        }
-       ring->init_hw = init_ring_common;
+       engine->init_hw = init_ring_common;
 
-       return intel_init_ring_buffer(dev, ring);
+       return intel_init_ring_buffer(dev, engine);
 }
 
 /**
@@ -2969,68 +2994,68 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
 int intel_init_bsd2_ring_buffer(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[VCS2];
-
-       ring->name = "bsd2 ring";
-       ring->id = VCS2;
-       ring->exec_id = I915_EXEC_BSD;
-
-       ring->write_tail = ring_write_tail;
-       ring->mmio_base = GEN8_BSD2_RING_BASE;
-       ring->flush = gen6_bsd_ring_flush;
-       ring->add_request = gen6_add_request;
-       ring->get_seqno = gen6_ring_get_seqno;
-       ring->set_seqno = ring_set_seqno;
-       ring->irq_enable_mask =
+       struct intel_engine_cs *engine = &dev_priv->engine[VCS2];
+
+       engine->name = "bsd2 ring";
+       engine->id = VCS2;
+       engine->exec_id = I915_EXEC_BSD;
+
+       engine->write_tail = ring_write_tail;
+       engine->mmio_base = GEN8_BSD2_RING_BASE;
+       engine->flush = gen6_bsd_ring_flush;
+       engine->add_request = gen6_add_request;
+       engine->get_seqno = gen6_ring_get_seqno;
+       engine->set_seqno = ring_set_seqno;
+       engine->irq_enable_mask =
                        GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT;
-       ring->irq_get = gen8_ring_get_irq;
-       ring->irq_put = gen8_ring_put_irq;
-       ring->dispatch_execbuffer =
+       engine->irq_get = gen8_ring_get_irq;
+       engine->irq_put = gen8_ring_put_irq;
+       engine->dispatch_execbuffer =
                        gen8_ring_dispatch_execbuffer;
        if (i915_semaphore_is_enabled(dev)) {
-               ring->semaphore.sync_to = gen8_ring_sync;
-               ring->semaphore.signal = gen8_xcs_signal;
-               GEN8_RING_SEMAPHORE_INIT;
+               engine->semaphore.sync_to = gen8_ring_sync;
+               engine->semaphore.signal = gen8_xcs_signal;
+               GEN8_RING_SEMAPHORE_INIT(engine);
        }
-       ring->init_hw = init_ring_common;
+       engine->init_hw = init_ring_common;
 
-       return intel_init_ring_buffer(dev, ring);
+       return intel_init_ring_buffer(dev, engine);
 }
 
 int intel_init_blt_ring_buffer(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[BCS];
-
-       ring->name = "blitter ring";
-       ring->id = BCS;
-       ring->exec_id = I915_EXEC_BLT;
-
-       ring->mmio_base = BLT_RING_BASE;
-       ring->write_tail = ring_write_tail;
-       ring->flush = gen6_ring_flush;
-       ring->add_request = gen6_add_request;
-       ring->get_seqno = gen6_ring_get_seqno;
-       ring->set_seqno = ring_set_seqno;
+       struct intel_engine_cs *engine = &dev_priv->engine[BCS];
+
+       engine->name = "blitter ring";
+       engine->id = BCS;
+       engine->exec_id = I915_EXEC_BLT;
+
+       engine->mmio_base = BLT_RING_BASE;
+       engine->write_tail = ring_write_tail;
+       engine->flush = gen6_ring_flush;
+       engine->add_request = gen6_add_request;
+       engine->get_seqno = gen6_ring_get_seqno;
+       engine->set_seqno = ring_set_seqno;
        if (INTEL_INFO(dev)->gen >= 8) {
-               ring->irq_enable_mask =
+               engine->irq_enable_mask =
                        GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
-               ring->irq_get = gen8_ring_get_irq;
-               ring->irq_put = gen8_ring_put_irq;
-               ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+               engine->irq_get = gen8_ring_get_irq;
+               engine->irq_put = gen8_ring_put_irq;
+               engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
                if (i915_semaphore_is_enabled(dev)) {
-                       ring->semaphore.sync_to = gen8_ring_sync;
-                       ring->semaphore.signal = gen8_xcs_signal;
-                       GEN8_RING_SEMAPHORE_INIT;
+                       engine->semaphore.sync_to = gen8_ring_sync;
+                       engine->semaphore.signal = gen8_xcs_signal;
+                       GEN8_RING_SEMAPHORE_INIT(engine);
                }
        } else {
-               ring->irq_enable_mask = GT_BLT_USER_INTERRUPT;
-               ring->irq_get = gen6_ring_get_irq;
-               ring->irq_put = gen6_ring_put_irq;
-               ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+               engine->irq_enable_mask = GT_BLT_USER_INTERRUPT;
+               engine->irq_get = gen6_ring_get_irq;
+               engine->irq_put = gen6_ring_put_irq;
+               engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
                if (i915_semaphore_is_enabled(dev)) {
-                       ring->semaphore.signal = gen6_signal;
-                       ring->semaphore.sync_to = gen6_ring_sync;
+                       engine->semaphore.signal = gen6_signal;
+                       engine->semaphore.sync_to = gen6_ring_sync;
                        /*
                         * The current semaphore is only applied on pre-gen8
                         * platform.  And there is no VCS2 ring on the pre-gen8
@@ -3038,127 +3063,127 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
                         * initialized as INVALID.  Gen8 will initialize the
                         * sema between BCS and VCS2 later.
                         */
-                       ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
-                       ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
-                       ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
-                       ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
-                       ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-                       ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
-                       ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
-                       ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
-                       ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
-                       ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+                       engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
+                       engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
+                       engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+                       engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
+                       engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+                       engine->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
+                       engine->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
+                       engine->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+                       engine->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
+                       engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
                }
        }
-       ring->init_hw = init_ring_common;
+       engine->init_hw = init_ring_common;
 
-       return intel_init_ring_buffer(dev, ring);
+       return intel_init_ring_buffer(dev, engine);
 }
 
 int intel_init_vebox_ring_buffer(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring = &dev_priv->ring[VECS];
+       struct intel_engine_cs *engine = &dev_priv->engine[VECS];
 
-       ring->name = "video enhancement ring";
-       ring->id = VECS;
-       ring->exec_id = I915_EXEC_VEBOX;
+       engine->name = "video enhancement ring";
+       engine->id = VECS;
+       engine->exec_id = I915_EXEC_VEBOX;
 
-       ring->mmio_base = VEBOX_RING_BASE;
-       ring->write_tail = ring_write_tail;
-       ring->flush = gen6_ring_flush;
-       ring->add_request = gen6_add_request;
-       ring->get_seqno = gen6_ring_get_seqno;
-       ring->set_seqno = ring_set_seqno;
+       engine->mmio_base = VEBOX_RING_BASE;
+       engine->write_tail = ring_write_tail;
+       engine->flush = gen6_ring_flush;
+       engine->add_request = gen6_add_request;
+       engine->get_seqno = gen6_ring_get_seqno;
+       engine->set_seqno = ring_set_seqno;
 
        if (INTEL_INFO(dev)->gen >= 8) {
-               ring->irq_enable_mask =
+               engine->irq_enable_mask =
                        GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT;
-               ring->irq_get = gen8_ring_get_irq;
-               ring->irq_put = gen8_ring_put_irq;
-               ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+               engine->irq_get = gen8_ring_get_irq;
+               engine->irq_put = gen8_ring_put_irq;
+               engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
                if (i915_semaphore_is_enabled(dev)) {
-                       ring->semaphore.sync_to = gen8_ring_sync;
-                       ring->semaphore.signal = gen8_xcs_signal;
-                       GEN8_RING_SEMAPHORE_INIT;
+                       engine->semaphore.sync_to = gen8_ring_sync;
+                       engine->semaphore.signal = gen8_xcs_signal;
+                       GEN8_RING_SEMAPHORE_INIT(engine);
                }
        } else {
-               ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
-               ring->irq_get = hsw_vebox_get_irq;
-               ring->irq_put = hsw_vebox_put_irq;
-               ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+               engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
+               engine->irq_get = hsw_vebox_get_irq;
+               engine->irq_put = hsw_vebox_put_irq;
+               engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
                if (i915_semaphore_is_enabled(dev)) {
-                       ring->semaphore.sync_to = gen6_ring_sync;
-                       ring->semaphore.signal = gen6_signal;
-                       ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
-                       ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
-                       ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
-                       ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
-                       ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-                       ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
-                       ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
-                       ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
-                       ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
-                       ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+                       engine->semaphore.sync_to = gen6_ring_sync;
+                       engine->semaphore.signal = gen6_signal;
+                       engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
+                       engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
+                       engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
+                       engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+                       engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+                       engine->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
+                       engine->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
+                       engine->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
+                       engine->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+                       engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
                }
        }
-       ring->init_hw = init_ring_common;
+       engine->init_hw = init_ring_common;
 
-       return intel_init_ring_buffer(dev, ring);
+       return intel_init_ring_buffer(dev, engine);
 }
 
 int
 intel_ring_flush_all_caches(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        int ret;
 
-       if (!ring->gpu_caches_dirty)
+       if (!engine->gpu_caches_dirty)
                return 0;
 
-       ret = ring->flush(req, 0, I915_GEM_GPU_DOMAINS);
+       ret = engine->flush(req, 0, I915_GEM_GPU_DOMAINS);
        if (ret)
                return ret;
 
        trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS);
 
-       ring->gpu_caches_dirty = false;
+       engine->gpu_caches_dirty = false;
        return 0;
 }
 
 int
 intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = req->ring;
+       struct intel_engine_cs *engine = req->engine;
        uint32_t flush_domains;
        int ret;
 
        flush_domains = 0;
-       if (ring->gpu_caches_dirty)
+       if (engine->gpu_caches_dirty)
                flush_domains = I915_GEM_GPU_DOMAINS;
 
-       ret = ring->flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
+       ret = engine->flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
        if (ret)
                return ret;
 
        trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
 
-       ring->gpu_caches_dirty = false;
+       engine->gpu_caches_dirty = false;
        return 0;
 }
 
 void
-intel_stop_ring_buffer(struct intel_engine_cs *ring)
+intel_stop_engine(struct intel_engine_cs *engine)
 {
        int ret;
 
-       if (!intel_ring_initialized(ring))
+       if (!intel_engine_initialized(engine))
                return;
 
-       ret = intel_ring_idle(ring);
-       if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error))
+       ret = intel_engine_idle(engine);
+       if (ret && !i915_reset_in_progress(&to_i915(engine->dev)->gpu_error))
                DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
-                         ring->name, ret);
+                         engine->name, ret);
 
-       stop_ring(ring);
+       stop_ring(engine);
 }
index 566b0ae..221a946 100644 (file)
@@ -55,31 +55,30 @@ struct  intel_hw_status_page {
 #define i915_semaphore_seqno_size sizeof(uint64_t)
 #define GEN8_SIGNAL_OFFSET(__ring, to)                      \
        (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
-       ((__ring)->id * I915_NUM_RINGS * i915_semaphore_seqno_size) +   \
+       ((__ring)->id * I915_NUM_ENGINES * i915_semaphore_seqno_size) + \
        (i915_semaphore_seqno_size * (to)))
 
 #define GEN8_WAIT_OFFSET(__ring, from)                      \
        (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
-       ((from) * I915_NUM_RINGS * i915_semaphore_seqno_size) + \
+       ((from) * I915_NUM_ENGINES * i915_semaphore_seqno_size) + \
        (i915_semaphore_seqno_size * (__ring)->id))
 
-#define GEN8_RING_SEMAPHORE_INIT do { \
+#define GEN8_RING_SEMAPHORE_INIT(e) do { \
        if (!dev_priv->semaphore_obj) { \
                break; \
        } \
-       ring->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET(ring, RCS); \
-       ring->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET(ring, VCS); \
-       ring->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET(ring, BCS); \
-       ring->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET(ring, VECS); \
-       ring->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET(ring, VCS2); \
-       ring->semaphore.signal_ggtt[ring->id] = MI_SEMAPHORE_SYNC_INVALID; \
+       (e)->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET((e), RCS); \
+       (e)->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET((e), VCS); \
+       (e)->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET((e), BCS); \
+       (e)->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET((e), VECS); \
+       (e)->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET((e), VCS2); \
+       (e)->semaphore.signal_ggtt[(e)->id] = MI_SEMAPHORE_SYNC_INVALID; \
        } while(0)
 
 enum intel_ring_hangcheck_action {
        HANGCHECK_IDLE = 0,
        HANGCHECK_WAIT,
        HANGCHECK_ACTIVE,
-       HANGCHECK_ACTIVE_LOOP,
        HANGCHECK_KICK,
        HANGCHECK_HUNG,
 };
@@ -88,7 +87,6 @@ enum intel_ring_hangcheck_action {
 
 struct intel_ring_hangcheck {
        u64 acthd;
-       u64 max_acthd;
        u32 seqno;
        int score;
        enum intel_ring_hangcheck_action action;
@@ -101,7 +99,7 @@ struct intel_ringbuffer {
        void __iomem *virtual_start;
        struct i915_vma *vma;
 
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        struct list_head link;
 
        u32 head;
@@ -125,7 +123,7 @@ struct intel_ringbuffer {
 };
 
 struct intel_context;
-struct drm_i915_reg_descriptor;
+struct drm_i915_reg_table;
 
 /*
  * we use a single page to load ctx workarounds so all of these
@@ -148,14 +146,14 @@ struct  i915_ctx_workarounds {
 
 struct  intel_engine_cs {
        const char      *name;
-       enum intel_ring_id {
+       enum intel_engine_id {
                RCS = 0,
                BCS,
                VCS,
                VCS2,   /* Keep instances of the same type engine together. */
                VECS
        } id;
-#define I915_NUM_RINGS 5
+#define I915_NUM_ENGINES 5
 #define _VCS(n) (VCS + (n))
        unsigned int exec_id;
        unsigned int guc_id;
@@ -246,16 +244,16 @@ struct  intel_engine_cs {
         *  ie. transpose of f(x, y)
         */
        struct {
-               u32     sync_seqno[I915_NUM_RINGS-1];
+               u32     sync_seqno[I915_NUM_ENGINES-1];
 
                union {
                        struct {
                                /* our mbox written by others */
-                               u32             wait[I915_NUM_RINGS];
+                               u32             wait[I915_NUM_ENGINES];
                                /* mboxes this ring signals to */
-                               i915_reg_t      signal[I915_NUM_RINGS];
+                               i915_reg_t      signal[I915_NUM_ENGINES];
                        } mbox;
-                       u64             signal_ggtt[I915_NUM_RINGS];
+                       u64             signal_ggtt[I915_NUM_ENGINES];
                };
 
                /* AKA wait() */
@@ -271,7 +269,8 @@ struct  intel_engine_cs {
        spinlock_t execlist_lock;
        struct list_head execlist_queue;
        struct list_head execlist_retired_req_list;
-       u8 next_context_status_buffer;
+       unsigned int next_context_status_buffer;
+       unsigned int idle_lite_restore_wa;
        bool disable_lite_restore_wa;
        u32 ctx_desc_template;
        u32             irq_keep_mask; /* bitmask for interrupts that should not be masked */
@@ -332,15 +331,8 @@ struct  intel_engine_cs {
        /*
         * Table of registers allowed in commands that read/write registers.
         */
-       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 struct drm_i915_reg_descriptor *master_reg_table;
-       int master_reg_count;
+       const struct drm_i915_reg_table *reg_tables;
+       int reg_table_count;
 
        /*
         * Returns the bitmask for the length field of the specified command.
@@ -356,19 +348,19 @@ struct  intel_engine_cs {
 };
 
 static inline bool
-intel_ring_initialized(struct intel_engine_cs *ring)
+intel_engine_initialized(struct intel_engine_cs *engine)
 {
-       return ring->dev != NULL;
+       return engine->dev != NULL;
 }
 
 static inline unsigned
-intel_ring_flag(struct intel_engine_cs *ring)
+intel_engine_flag(struct intel_engine_cs *engine)
 {
-       return 1 << ring->id;
+       return 1 << engine->id;
 }
 
 static inline u32
-intel_ring_sync_index(struct intel_engine_cs *ring,
+intel_ring_sync_index(struct intel_engine_cs *engine,
                      struct intel_engine_cs *other)
 {
        int idx;
@@ -381,34 +373,34 @@ intel_ring_sync_index(struct intel_engine_cs *ring,
         * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs;
         */
 
-       idx = (other - ring) - 1;
+       idx = (other - engine) - 1;
        if (idx < 0)
-               idx += I915_NUM_RINGS;
+               idx += I915_NUM_ENGINES;
 
        return idx;
 }
 
 static inline void
-intel_flush_status_page(struct intel_engine_cs *ring, int reg)
+intel_flush_status_page(struct intel_engine_cs *engine, int reg)
 {
-       drm_clflush_virt_range(&ring->status_page.page_addr[reg],
+       drm_clflush_virt_range(&engine->status_page.page_addr[reg],
                               sizeof(uint32_t));
 }
 
 static inline u32
-intel_read_status_page(struct intel_engine_cs *ring,
+intel_read_status_page(struct intel_engine_cs *engine,
                       int reg)
 {
        /* Ensure that the compiler doesn't optimize away the load. */
        barrier();
-       return ring->status_page.page_addr[reg];
+       return engine->status_page.page_addr[reg];
 }
 
 static inline void
-intel_write_status_page(struct intel_engine_cs *ring,
+intel_write_status_page(struct intel_engine_cs *engine,
                        int reg, u32 value)
 {
-       ring->status_page.page_addr[reg] = value;
+       engine->status_page.page_addr[reg] = value;
 }
 
 /*
@@ -439,42 +431,42 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
 void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf);
 void intel_ringbuffer_free(struct intel_ringbuffer *ring);
 
-void intel_stop_ring_buffer(struct intel_engine_cs *ring);
-void intel_cleanup_ring_buffer(struct intel_engine_cs *ring);
+void intel_stop_engine(struct intel_engine_cs *engine);
+void intel_cleanup_engine(struct intel_engine_cs *engine);
 
 int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request);
 
 int __must_check intel_ring_begin(struct drm_i915_gem_request *req, int n);
 int __must_check intel_ring_cacheline_align(struct drm_i915_gem_request *req);
-static inline void intel_ring_emit(struct intel_engine_cs *ring,
+static inline void intel_ring_emit(struct intel_engine_cs *engine,
                                   u32 data)
 {
-       struct intel_ringbuffer *ringbuf = ring->buffer;
+       struct intel_ringbuffer *ringbuf = engine->buffer;
        iowrite32(data, ringbuf->virtual_start + ringbuf->tail);
        ringbuf->tail += 4;
 }
-static inline void intel_ring_emit_reg(struct intel_engine_cs *ring,
+static inline void intel_ring_emit_reg(struct intel_engine_cs *engine,
                                       i915_reg_t reg)
 {
-       intel_ring_emit(ring, i915_mmio_reg_offset(reg));
+       intel_ring_emit(engine, i915_mmio_reg_offset(reg));
 }
-static inline void intel_ring_advance(struct intel_engine_cs *ring)
+static inline void intel_ring_advance(struct intel_engine_cs *engine)
 {
-       struct intel_ringbuffer *ringbuf = ring->buffer;
+       struct intel_ringbuffer *ringbuf = engine->buffer;
        ringbuf->tail &= ringbuf->size - 1;
 }
 int __intel_ring_space(int head, int tail, int size);
 void intel_ring_update_space(struct intel_ringbuffer *ringbuf);
 int intel_ring_space(struct intel_ringbuffer *ringbuf);
-bool intel_ring_stopped(struct intel_engine_cs *ring);
+bool intel_engine_stopped(struct intel_engine_cs *engine);
 
-int __must_check intel_ring_idle(struct intel_engine_cs *ring);
-void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno);
+int __must_check intel_engine_idle(struct intel_engine_cs *engine);
+void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno);
 int intel_ring_flush_all_caches(struct drm_i915_gem_request *req);
 int intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req);
 
-void intel_fini_pipe_control(struct intel_engine_cs *ring);
-int intel_init_pipe_control(struct intel_engine_cs *ring);
+void intel_fini_pipe_control(struct intel_engine_cs *engine);
+int intel_init_pipe_control(struct intel_engine_cs *engine);
 
 int intel_init_render_ring_buffer(struct drm_device *dev);
 int intel_init_bsd_ring_buffer(struct drm_device *dev);
@@ -482,9 +474,9 @@ int intel_init_bsd2_ring_buffer(struct drm_device *dev);
 int intel_init_blt_ring_buffer(struct drm_device *dev);
 int intel_init_vebox_ring_buffer(struct drm_device *dev);
 
-u64 intel_ring_get_active_head(struct intel_engine_cs *ring);
+u64 intel_ring_get_active_head(struct intel_engine_cs *engine);
 
-int init_workarounds_ring(struct intel_engine_cs *ring);
+int init_workarounds_ring(struct intel_engine_cs *engine);
 
 static inline u32 intel_ring_get_tail(struct intel_ringbuffer *ringbuf)
 {
index 6e54d97..d189a00 100644 (file)
@@ -89,6 +89,10 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
                return "TRANSCODER_C";
        case POWER_DOMAIN_TRANSCODER_EDP:
                return "TRANSCODER_EDP";
+       case POWER_DOMAIN_TRANSCODER_DSI_A:
+               return "TRANSCODER_DSI_A";
+       case POWER_DOMAIN_TRANSCODER_DSI_C:
+               return "TRANSCODER_DSI_C";
        case POWER_DOMAIN_PORT_DDI_A_LANES:
                return "PORT_DDI_A_LANES";
        case POWER_DOMAIN_PORT_DDI_B_LANES:
@@ -419,8 +423,11 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
        BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS |         \
        BIT(POWER_DOMAIN_PIPE_A) |                      \
        BIT(POWER_DOMAIN_TRANSCODER_EDP) |              \
+       BIT(POWER_DOMAIN_TRANSCODER_DSI_A) |            \
+       BIT(POWER_DOMAIN_TRANSCODER_DSI_C) |            \
        BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |         \
        BIT(POWER_DOMAIN_PORT_DDI_A_LANES) |            \
+       BIT(POWER_DOMAIN_PORT_DSI) |                    \
        BIT(POWER_DOMAIN_AUX_A) |                       \
        BIT(POWER_DOMAIN_PLLS) |                        \
        BIT(POWER_DOMAIN_INIT))
@@ -458,8 +465,6 @@ static void assert_can_enable_dc9(struct drm_i915_private *dev_priv)
 static void assert_can_disable_dc9(struct drm_i915_private *dev_priv)
 {
        WARN(intel_irqs_enabled(dev_priv), "Interrupts not disabled yet.\n");
-       WARN(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9),
-               "DC9 already programmed to be disabled.\n");
        WARN(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5,
                "DC5 still not disabled.\n");
 
@@ -472,24 +477,6 @@ static void assert_can_disable_dc9(struct drm_i915_private *dev_priv)
          */
 }
 
-static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
-{
-       uint32_t val, mask;
-
-       mask = DC_STATE_DEBUG_MASK_MEMORY_UP;
-
-       if (IS_BROXTON(dev_priv))
-               mask |= DC_STATE_DEBUG_MASK_CORES;
-
-       /* The below bit doesn't need to be cleared ever afterwards */
-       val = I915_READ(DC_STATE_DEBUG);
-       if ((val & mask) != mask) {
-               val |= mask;
-               I915_WRITE(DC_STATE_DEBUG, val);
-               POSTING_READ(DC_STATE_DEBUG);
-       }
-}
-
 static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
                                u32 state)
 {
@@ -538,12 +525,8 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
        else
                mask |= DC_STATE_EN_UPTO_DC6;
 
-       WARN_ON_ONCE(state & ~mask);
-
-       if (i915.enable_dc == 0)
-               state = DC_STATE_DISABLE;
-       else if (i915.enable_dc == 1 && state > DC_STATE_EN_UPTO_DC5)
-               state = DC_STATE_EN_UPTO_DC5;
+       if (WARN_ON_ONCE(state & ~dev_priv->csr.allowed_dc_mask))
+               state &= dev_priv->csr.allowed_dc_mask;
 
        val = I915_READ(DC_STATE_EN);
        DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n",
@@ -606,18 +589,6 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
        assert_csr_loaded(dev_priv);
 }
 
-static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
-{
-       /*
-        * During initialization, the firmware may not be loaded yet.
-        * We still want to make sure that the DC enabling flag is cleared.
-        */
-       if (dev_priv->power_domains.initializing)
-               return;
-
-       assert_rpm_wakelock_held(dev_priv);
-}
-
 static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
 {
        assert_can_enable_dc5(dev_priv);
@@ -642,30 +613,6 @@ static void assert_can_enable_dc6(struct drm_i915_private *dev_priv)
        assert_csr_loaded(dev_priv);
 }
 
-static void assert_can_disable_dc6(struct drm_i915_private *dev_priv)
-{
-       /*
-        * During initialization, the firmware may not be loaded yet.
-        * We still want to make sure that the DC enabling flag is cleared.
-        */
-       if (dev_priv->power_domains.initializing)
-               return;
-
-       WARN_ONCE(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
-                 "DC6 already programmed to be disabled.\n");
-}
-
-static void gen9_disable_dc5_dc6(struct drm_i915_private *dev_priv)
-{
-       assert_can_disable_dc5(dev_priv);
-
-       if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
-           i915.enable_dc != 0 && i915.enable_dc != 1)
-               assert_can_disable_dc6(dev_priv);
-
-       gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
-}
-
 void skl_enable_dc6(struct drm_i915_private *dev_priv)
 {
        assert_can_enable_dc6(dev_priv);
@@ -678,8 +625,6 @@ void skl_enable_dc6(struct drm_i915_private *dev_priv)
 
 void skl_disable_dc6(struct drm_i915_private *dev_priv)
 {
-       assert_can_disable_dc6(dev_priv);
-
        DRM_DEBUG_KMS("Disabling DC6\n");
 
        gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
@@ -833,32 +778,25 @@ static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
 static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
                                          struct i915_power_well *power_well)
 {
-       gen9_disable_dc5_dc6(dev_priv);
+       gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 }
 
 static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv,
                                           struct i915_power_well *power_well)
 {
-       if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
-           i915.enable_dc != 0 && i915.enable_dc != 1)
+       if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6)
                skl_enable_dc6(dev_priv);
-       else
+       else if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5)
                gen9_enable_dc5(dev_priv);
 }
 
 static void gen9_dc_off_power_well_sync_hw(struct drm_i915_private *dev_priv,
                                           struct i915_power_well *power_well)
 {
-       if (power_well->count > 0) {
-               gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
-       } else {
-               if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
-                   i915.enable_dc != 0 &&
-                   i915.enable_dc != 1)
-                       gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
-               else
-                       gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5);
-       }
+       if (power_well->count > 0)
+               gen9_dc_off_power_well_enable(dev_priv, power_well);
+       else
+               gen9_dc_off_power_well_disable(dev_priv, power_well);
 }
 
 static void i9xx_always_on_power_well_noop(struct drm_i915_private *dev_priv,
@@ -2023,6 +1961,55 @@ sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv,
        return 1;
 }
 
+static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
+                                   int enable_dc)
+{
+       uint32_t mask;
+       int requested_dc;
+       int max_dc;
+
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+               max_dc = 2;
+               mask = 0;
+       } else if (IS_BROXTON(dev_priv)) {
+               max_dc = 1;
+               /*
+                * DC9 has a separate HW flow from the rest of the DC states,
+                * not depending on the DMC firmware. It's needed by system
+                * suspend/resume, so allow it unconditionally.
+                */
+               mask = DC_STATE_EN_DC9;
+       } else {
+               max_dc = 0;
+               mask = 0;
+       }
+
+       if (!i915.disable_power_well)
+               max_dc = 0;
+
+       if (enable_dc >= 0 && enable_dc <= max_dc) {
+               requested_dc = enable_dc;
+       } else if (enable_dc == -1) {
+               requested_dc = max_dc;
+       } else if (enable_dc > max_dc && enable_dc <= 2) {
+               DRM_DEBUG_KMS("Adjusting requested max DC state (%d->%d)\n",
+                             enable_dc, max_dc);
+               requested_dc = max_dc;
+       } else {
+               DRM_ERROR("Unexpected value for enable_dc (%d)\n", enable_dc);
+               requested_dc = max_dc;
+       }
+
+       if (requested_dc > 1)
+               mask |= DC_STATE_EN_UPTO_DC6;
+       if (requested_dc > 0)
+               mask |= DC_STATE_EN_UPTO_DC5;
+
+       DRM_DEBUG_KMS("Allowed DC state mask %02x\n", mask);
+
+       return mask;
+}
+
 #define set_power_wells(power_domains, __power_wells) ({               \
        (power_domains)->power_wells = (__power_wells);                 \
        (power_domains)->power_well_count = ARRAY_SIZE(__power_wells);  \
@@ -2041,6 +2028,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
 
        i915.disable_power_well = sanitize_disable_power_well_option(dev_priv,
                                                     i915.disable_power_well);
+       dev_priv->csr.allowed_dc_mask = get_allowed_dc_mask(dev_priv,
+                                                           i915.enable_dc);
 
        BUILD_BUG_ON(POWER_DOMAIN_NUM > 31);
 
@@ -2141,8 +2130,8 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv,
 
        skl_init_cdclk(dev_priv);
 
-       if (dev_priv->csr.dmc_payload && intel_csr_load_program(dev_priv))
-               gen9_set_dc_state_debugmask(dev_priv);
+       if (dev_priv->csr.dmc_payload)
+               intel_csr_load_program(dev_priv);
 }
 
 static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
index 4ecc076..2128fae 100644 (file)
@@ -1398,12 +1398,10 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
        }
 
        dotclock = pipe_config->port_clock;
+
        if (pipe_config->pixel_multiplier)
                dotclock /= pipe_config->pixel_multiplier;
 
-       if (HAS_PCH_SPLIT(dev))
-               ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
        pipe_config->base.adjusted_mode.crtc_clock = dotclock;
 
        /* Cross check the port pixel multiplier with the sdvo encoder state. */
@@ -2262,9 +2260,9 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
        struct sdvo_device_mapping *mapping;
 
        if (sdvo->port == PORT_B)
-               mapping = &(dev_priv->sdvo_mappings[0]);
+               mapping = &dev_priv->vbt.sdvo_mappings[0];
        else
-               mapping = &(dev_priv->sdvo_mappings[1]);
+               mapping = &dev_priv->vbt.sdvo_mappings[1];
 
        if (mapping->initialized)
                sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4);
@@ -2280,9 +2278,9 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
        u8 pin;
 
        if (sdvo->port == PORT_B)
-               mapping = &dev_priv->sdvo_mappings[0];
+               mapping = &dev_priv->vbt.sdvo_mappings[0];
        else
-               mapping = &dev_priv->sdvo_mappings[1];
+               mapping = &dev_priv->vbt.sdvo_mappings[1];
 
        if (mapping->initialized &&
            intel_gmbus_is_valid_pin(dev_priv, mapping->i2c_pin))
@@ -2318,11 +2316,11 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo)
        struct sdvo_device_mapping *my_mapping, *other_mapping;
 
        if (sdvo->port == PORT_B) {
-               my_mapping = &dev_priv->sdvo_mappings[0];
-               other_mapping = &dev_priv->sdvo_mappings[1];
+               my_mapping = &dev_priv->vbt.sdvo_mappings[0];
+               other_mapping = &dev_priv->vbt.sdvo_mappings[1];
        } else {
-               my_mapping = &dev_priv->sdvo_mappings[1];
-               other_mapping = &dev_priv->sdvo_mappings[0];
+               my_mapping = &dev_priv->vbt.sdvo_mappings[1];
+               other_mapping = &dev_priv->vbt.sdvo_mappings[0];
        }
 
        /* If the BIOS described our SDVO device, take advantage of it. */
index a2582c4..8821533 100644 (file)
@@ -193,7 +193,7 @@ skl_update_plane(struct drm_plane *drm_plane,
        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
        u32 surf_addr;
        u32 tile_height, plane_offset, plane_size;
-       unsigned int rotation;
+       unsigned int rotation = plane_state->base.rotation;
        int x_offset, y_offset;
        int crtc_x = plane_state->dst.x1;
        int crtc_y = plane_state->dst.y1;
@@ -213,7 +213,6 @@ skl_update_plane(struct drm_plane *drm_plane,
        plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
        plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
 
-       rotation = plane_state->base.rotation;
        plane_ctl |= skl_plane_ctl_rotation(rotation);
 
        stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
@@ -351,6 +350,7 @@ vlv_update_plane(struct drm_plane *dplane,
        int plane = intel_plane->plane;
        u32 sprctl;
        u32 sprsurf_offset, linear_offset;
+       unsigned int rotation = dplane->state->rotation;
        int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
        int crtc_x = plane_state->dst.x1;
@@ -423,12 +423,11 @@ vlv_update_plane(struct drm_plane *dplane,
        crtc_h--;
 
        linear_offset = y * fb->pitches[0] + x * cpp;
-       sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
-                                                  fb->modifier[0], cpp,
-                                                  fb->pitches[0]);
+       sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
+                                                  fb->pitches[0], rotation);
        linear_offset -= sprsurf_offset;
 
-       if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+       if (rotation == BIT(DRM_ROTATE_180)) {
                sprctl |= SP_ROTATE_180;
 
                x += src_w;
@@ -493,6 +492,7 @@ ivb_update_plane(struct drm_plane *plane,
        enum pipe pipe = intel_plane->pipe;
        u32 sprctl, sprscale = 0;
        u32 sprsurf_offset, linear_offset;
+       unsigned int rotation = plane_state->base.rotation;
        int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
        int crtc_x = plane_state->dst.x1;
@@ -556,12 +556,11 @@ ivb_update_plane(struct drm_plane *plane,
                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 
        linear_offset = y * fb->pitches[0] + x * cpp;
-       sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
-                                                  fb->modifier[0], cpp,
-                                                  fb->pitches[0]);
+       sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
+                                                  fb->pitches[0], rotation);
        linear_offset -= sprsurf_offset;
 
-       if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+       if (rotation == BIT(DRM_ROTATE_180)) {
                sprctl |= SPRITE_ROTATE_180;
 
                /* HSW and BDW does this automagically in hardware */
@@ -634,6 +633,7 @@ ilk_update_plane(struct drm_plane *plane,
        int pipe = intel_plane->pipe;
        u32 dvscntr, dvsscale;
        u32 dvssurf_offset, linear_offset;
+       unsigned int rotation = plane_state->base.rotation;
        int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
        int crtc_x = plane_state->dst.x1;
@@ -693,12 +693,11 @@ ilk_update_plane(struct drm_plane *plane,
                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
        linear_offset = y * fb->pitches[0] + x * cpp;
-       dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
-                                                  fb->modifier[0], cpp,
-                                                  fb->pitches[0]);
+       dvssurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
+                                                  fb->pitches[0], rotation);
        linear_offset -= dvssurf_offset;
 
-       if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+       if (rotation == BIT(DRM_ROTATE_180)) {
                dvscntr |= DVS_ROTATE_180;
 
                x += src_w;
index 6745bad..223129d 100644 (file)
@@ -326,24 +326,12 @@ static const struct color_conversion sdtv_csc_yprpb = {
        .rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200,
 };
 
-static const struct color_conversion sdtv_csc_rgb = {
-       .ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166,
-       .ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166,
-       .rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166,
-};
-
 static const struct color_conversion hdtv_csc_yprpb = {
        .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145,
        .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200,
        .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200,
 };
 
-static const struct color_conversion hdtv_csc_rgb = {
-       .ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166,
-       .ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166,
-       .rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166,
-};
-
 static const struct video_levels component_levels = {
        .blank = 279, .black = 279, .burst = 0,
 };
@@ -1531,47 +1519,6 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = {
        .destroy = intel_encoder_destroy,
 };
 
-/*
- * Enumerate the child dev array parsed from VBT to check whether
- * the integrated TV is present.
- * If it is present, return 1.
- * If it is not present, return false.
- * If no child dev is parsed from VBT, it assumes that the TV is present.
- */
-static int tv_is_present_in_vbt(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       union child_device_config *p_child;
-       int i, ret;
-
-       if (!dev_priv->vbt.child_dev_num)
-               return 1;
-
-       ret = 0;
-       for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
-               p_child = dev_priv->vbt.child_dev + i;
-               /*
-                * If the device type is not TV, continue.
-                */
-               switch (p_child->old.device_type) {
-               case DEVICE_TYPE_INT_TV:
-               case DEVICE_TYPE_TV:
-               case DEVICE_TYPE_TV_SVIDEO_COMPOSITE:
-                       break;
-               default:
-                       continue;
-               }
-               /* Only when the addin_offset is non-zero, it is regarded
-                * as present.
-                */
-               if (p_child->old.addin_offset) {
-                       ret = 1;
-                       break;
-               }
-       }
-       return ret;
-}
-
 void
 intel_tv_init(struct drm_device *dev)
 {
@@ -1587,13 +1534,10 @@ intel_tv_init(struct drm_device *dev)
        if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
                return;
 
-       if (!tv_is_present_in_vbt(dev)) {
+       if (!intel_bios_is_tv_present(dev_priv)) {
                DRM_DEBUG_KMS("Integrated TV is not present.\n");
                return;
        }
-       /* Even if we have an encoder we may not have a connector */
-       if (!dev_priv->vbt.int_tv_support)
-               return;
 
        /*
         * Sanity check the TV output by checking to see if the
index 436d8f2..512b7fa 100644 (file)
@@ -1433,7 +1433,7 @@ static int i915_reset_complete(struct drm_device *dev)
        return (gdrst & GRDOM_RESET_STATUS) == 0;
 }
 
-static int i915_do_reset(struct drm_device *dev)
+static int i915_do_reset(struct drm_device *dev, unsigned engine_mask)
 {
        /* assert reset for at least 20 usec */
        pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_RESET_ENABLE);
@@ -1450,13 +1450,13 @@ static int g4x_reset_complete(struct drm_device *dev)
        return (gdrst & GRDOM_RESET_ENABLE) == 0;
 }
 
-static int g33_do_reset(struct drm_device *dev)
+static int g33_do_reset(struct drm_device *dev, unsigned engine_mask)
 {
        pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_RESET_ENABLE);
        return wait_for(g4x_reset_complete(dev), 500);
 }
 
-static int g4x_do_reset(struct drm_device *dev)
+static int g4x_do_reset(struct drm_device *dev, unsigned engine_mask)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
@@ -1486,7 +1486,7 @@ static int g4x_do_reset(struct drm_device *dev)
        return 0;
 }
 
-static int ironlake_do_reset(struct drm_device *dev)
+static int ironlake_do_reset(struct drm_device *dev, unsigned engine_mask)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
@@ -1510,75 +1510,132 @@ static int ironlake_do_reset(struct drm_device *dev)
        return 0;
 }
 
-static int gen6_do_reset(struct drm_device *dev)
+/* Reset the hardware domains (GENX_GRDOM_*) specified by mask */
+static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv,
+                               u32 hw_domain_mask)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int     ret;
-
-       /* Reset the chip */
+       int ret;
 
        /* GEN6_GDRST is not in the gt power well, no need to check
         * for fifo space for the write or forcewake the chip for
         * the read
         */
-       __raw_i915_write32(dev_priv, GEN6_GDRST, GEN6_GRDOM_FULL);
+       __raw_i915_write32(dev_priv, GEN6_GDRST, hw_domain_mask);
+
+#define ACKED ((__raw_i915_read32(dev_priv, GEN6_GDRST) & hw_domain_mask) == 0)
+       /* Spin waiting for the device to ack the reset requests */
+       ret = wait_for(ACKED, 500);
+#undef ACKED
+
+       return ret;
+}
 
-       /* Spin waiting for the device to ack the reset request */
-       ret = wait_for((__raw_i915_read32(dev_priv, GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+/**
+ * gen6_reset_engines - reset individual engines
+ * @dev: DRM device
+ * @engine_mask: mask of intel_ring_flag() engines or ALL_ENGINES for full reset
+ *
+ * This function will reset the individual engines that are set in engine_mask.
+ * If you provide ALL_ENGINES as mask, full global domain reset will be issued.
+ *
+ * Note: It is responsibility of the caller to handle the difference between
+ * asking full domain reset versus reset for all available individual engines.
+ *
+ * Returns 0 on success, nonzero on error.
+ */
+static int gen6_reset_engines(struct drm_device *dev, unsigned engine_mask)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_engine_cs *engine;
+       const u32 hw_engine_mask[I915_NUM_ENGINES] = {
+               [RCS] = GEN6_GRDOM_RENDER,
+               [BCS] = GEN6_GRDOM_BLT,
+               [VCS] = GEN6_GRDOM_MEDIA,
+               [VCS2] = GEN8_GRDOM_MEDIA2,
+               [VECS] = GEN6_GRDOM_VECS,
+       };
+       u32 hw_mask;
+       int ret;
+
+       if (engine_mask == ALL_ENGINES) {
+               hw_mask = GEN6_GRDOM_FULL;
+       } else {
+               hw_mask = 0;
+               for_each_engine_masked(engine, dev_priv, engine_mask)
+                       hw_mask |= hw_engine_mask[engine->id];
+       }
+
+       ret = gen6_hw_domain_reset(dev_priv, hw_mask);
 
        intel_uncore_forcewake_reset(dev, true);
 
        return ret;
 }
 
-static int wait_for_register(struct drm_i915_private *dev_priv,
-                            i915_reg_t reg,
-                            const u32 mask,
-                            const u32 value,
-                            const unsigned long timeout_ms)
+static int wait_for_register_fw(struct drm_i915_private *dev_priv,
+                               i915_reg_t reg,
+                               const u32 mask,
+                               const u32 value,
+                               const unsigned long timeout_ms)
+{
+       return wait_for((I915_READ_FW(reg) & mask) == value, timeout_ms);
+}
+
+static int gen8_request_engine_reset(struct intel_engine_cs *engine)
+{
+       int ret;
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
+
+       I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
+                     _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
+
+       ret = wait_for_register_fw(dev_priv,
+                                  RING_RESET_CTL(engine->mmio_base),
+                                  RESET_CTL_READY_TO_RESET,
+                                  RESET_CTL_READY_TO_RESET,
+                                  700);
+       if (ret)
+               DRM_ERROR("%s: reset request timeout\n", engine->name);
+
+       return ret;
+}
+
+static void gen8_unrequest_engine_reset(struct intel_engine_cs *engine)
 {
-       return wait_for((I915_READ(reg) & mask) == value, timeout_ms);
+       struct drm_i915_private *dev_priv = engine->dev->dev_private;
+
+       I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
+                     _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET));
 }
 
-static int gen8_do_reset(struct drm_device *dev)
+static int gen8_reset_engines(struct drm_device *dev, unsigned engine_mask)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *engine;
-       int i;
-
-       for_each_ring(engine, dev_priv, i) {
-               I915_WRITE(RING_RESET_CTL(engine->mmio_base),
-                          _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
 
-               if (wait_for_register(dev_priv,
-                                     RING_RESET_CTL(engine->mmio_base),
-                                     RESET_CTL_READY_TO_RESET,
-                                     RESET_CTL_READY_TO_RESET,
-                                     700)) {
-                       DRM_ERROR("%s: reset request timeout\n", engine->name);
+       for_each_engine_masked(engine, dev_priv, engine_mask)
+               if (gen8_request_engine_reset(engine))
                        goto not_ready;
-               }
-       }
 
-       return gen6_do_reset(dev);
+       return gen6_reset_engines(dev, engine_mask);
 
 not_ready:
-       for_each_ring(engine, dev_priv, i)
-               I915_WRITE(RING_RESET_CTL(engine->mmio_base),
-                          _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET));
+       for_each_engine_masked(engine, dev_priv, engine_mask)
+               gen8_unrequest_engine_reset(engine);
 
        return -EIO;
 }
 
-static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *)
+static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *,
+                                                         unsigned engine_mask)
 {
        if (!i915.reset)
                return NULL;
 
        if (INTEL_INFO(dev)->gen >= 8)
-               return gen8_do_reset;
+               return gen8_reset_engines;
        else if (INTEL_INFO(dev)->gen >= 6)
-               return gen6_do_reset;
+               return gen6_reset_engines;
        else if (IS_GEN5(dev))
                return ironlake_do_reset;
        else if (IS_G4X(dev))
@@ -1591,10 +1648,10 @@ static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *)
                return NULL;
 }
 
-int intel_gpu_reset(struct drm_device *dev)
+int intel_gpu_reset(struct drm_device *dev, unsigned engine_mask)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int (*reset)(struct drm_device *);
+       int (*reset)(struct drm_device *, unsigned);
        int ret;
 
        reset = intel_get_gpu_reset(dev);
@@ -1605,7 +1662,7 @@ int intel_gpu_reset(struct drm_device *dev)
         * request may be dropped and never completes (causing -EIO).
         */
        intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
-       ret = reset(dev);
+       ret = reset(dev, engine_mask);
        intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 
        return ret;
diff --git a/drivers/gpu/drm/i915/intel_vbt_defs.h b/drivers/gpu/drm/i915/intel_vbt_defs.h
new file mode 100644 (file)
index 0000000..749dcea
--- /dev/null
@@ -0,0 +1,826 @@
+/*
+ * Copyright © 2006-2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/*
+ * This information is private to VBT parsing in intel_bios.c.
+ *
+ * Please do NOT include anywhere else.
+ */
+#ifndef _INTEL_BIOS_PRIVATE
+#error "intel_vbt_defs.h is private to intel_bios.c"
+#endif
+
+#ifndef _INTEL_VBT_DEFS_H_
+#define _INTEL_VBT_DEFS_H_
+
+#include "intel_bios.h"
+
+/**
+ * struct vbt_header - VBT Header structure
+ * @signature:         VBT signature, always starts with "$VBT"
+ * @version:           Version of this structure
+ * @header_size:       Size of this structure
+ * @vbt_size:          Size of VBT (VBT Header, BDB Header and data blocks)
+ * @vbt_checksum:      Checksum
+ * @reserved0:         Reserved
+ * @bdb_offset:                Offset of &struct bdb_header from beginning of VBT
+ * @aim_offset:                Offsets of add-in data blocks from beginning of VBT
+ */
+struct vbt_header {
+       u8 signature[20];
+       u16 version;
+       u16 header_size;
+       u16 vbt_size;
+       u8 vbt_checksum;
+       u8 reserved0;
+       u32 bdb_offset;
+       u32 aim_offset[4];
+} __packed;
+
+/**
+ * struct bdb_header - BDB Header structure
+ * @signature:         BDB signature "BIOS_DATA_BLOCK"
+ * @version:           Version of the data block definitions
+ * @header_size:       Size of this structure
+ * @bdb_size:          Size of BDB (BDB Header and data blocks)
+ */
+struct bdb_header {
+       u8 signature[16];
+       u16 version;
+       u16 header_size;
+       u16 bdb_size;
+} __packed;
+
+/* strictly speaking, this is a "skip" block, but it has interesting info */
+struct vbios_data {
+       u8 type; /* 0 == desktop, 1 == mobile */
+       u8 relstage;
+       u8 chipset;
+       u8 lvds_present:1;
+       u8 tv_present:1;
+       u8 rsvd2:6; /* finish byte */
+       u8 rsvd3[4];
+       u8 signon[155];
+       u8 copyright[61];
+       u16 code_segment;
+       u8 dos_boot_mode;
+       u8 bandwidth_percent;
+       u8 rsvd4; /* popup memory size */
+       u8 resize_pci_bios;
+       u8 rsvd5; /* is crt already on ddc2 */
+} __packed;
+
+/*
+ * There are several types of BIOS data blocks (BDBs), each block has
+ * an ID and size in the first 3 bytes (ID in first, size in next 2).
+ * Known types are listed below.
+ */
+#define BDB_GENERAL_FEATURES     1
+#define BDB_GENERAL_DEFINITIONS          2
+#define BDB_OLD_TOGGLE_LIST      3
+#define BDB_MODE_SUPPORT_LIST    4
+#define BDB_GENERIC_MODE_TABLE   5
+#define BDB_EXT_MMIO_REGS        6
+#define BDB_SWF_IO               7
+#define BDB_SWF_MMIO             8
+#define BDB_PSR                          9
+#define BDB_MODE_REMOVAL_TABLE  10
+#define BDB_CHILD_DEVICE_TABLE  11
+#define BDB_DRIVER_FEATURES     12
+#define BDB_DRIVER_PERSISTENCE  13
+#define BDB_EXT_TABLE_PTRS      14
+#define BDB_DOT_CLOCK_OVERRIDE  15
+#define BDB_DISPLAY_SELECT      16
+/* 17 rsvd */
+#define BDB_DRIVER_ROTATION     18
+#define BDB_DISPLAY_REMOVE      19
+#define BDB_OEM_CUSTOM          20
+#define BDB_EFP_LIST            21 /* workarounds for VGA hsync/vsync */
+#define BDB_SDVO_LVDS_OPTIONS   22
+#define BDB_SDVO_PANEL_DTDS     23
+#define BDB_SDVO_LVDS_PNP_IDS   24
+#define BDB_SDVO_LVDS_POWER_SEQ         25
+#define BDB_TV_OPTIONS          26
+#define BDB_EDP                         27
+#define BDB_LVDS_OPTIONS        40
+#define BDB_LVDS_LFP_DATA_PTRS  41
+#define BDB_LVDS_LFP_DATA       42
+#define BDB_LVDS_BACKLIGHT      43
+#define BDB_LVDS_POWER          44
+#define BDB_MIPI_CONFIG                 52
+#define BDB_MIPI_SEQUENCE       53
+#define BDB_SKIP               254 /* VBIOS private block, ignore */
+
+struct bdb_general_features {
+        /* bits 1 */
+       u8 panel_fitting:2;
+       u8 flexaim:1;
+       u8 msg_enable:1;
+       u8 clear_screen:3;
+       u8 color_flip:1;
+
+        /* bits 2 */
+       u8 download_ext_vbt:1;
+       u8 enable_ssc:1;
+       u8 ssc_freq:1;
+       u8 enable_lfp_on_override:1;
+       u8 disable_ssc_ddt:1;
+       u8 rsvd7:1;
+       u8 display_clock_mode:1;
+       u8 rsvd8:1; /* finish byte */
+
+        /* bits 3 */
+       u8 disable_smooth_vision:1;
+       u8 single_dvi:1;
+       u8 rsvd9:1;
+       u8 fdi_rx_polarity_inverted:1;
+       u8 rsvd10:4; /* finish byte */
+
+        /* bits 4 */
+       u8 legacy_monitor_detect;
+
+        /* bits 5 */
+       u8 int_crt_support:1;
+       u8 int_tv_support:1;
+       u8 int_efp_support:1;
+       u8 dp_ssc_enb:1;        /* PCH attached eDP supports SSC */
+       u8 dp_ssc_freq:1;       /* SSC freq for PCH attached eDP */
+       u8 rsvd11:3; /* finish byte */
+} __packed;
+
+/* pre-915 */
+#define GPIO_PIN_DVI_LVDS      0x03 /* "DVI/LVDS DDC GPIO pins" */
+#define GPIO_PIN_ADD_I2C       0x05 /* "ADDCARD I2C GPIO pins" */
+#define GPIO_PIN_ADD_DDC       0x04 /* "ADDCARD DDC GPIO pins" */
+#define GPIO_PIN_ADD_DDC_I2C   0x06 /* "ADDCARD DDC/I2C GPIO pins" */
+
+/* Pre 915 */
+#define DEVICE_TYPE_NONE       0x00
+#define DEVICE_TYPE_CRT                0x01
+#define DEVICE_TYPE_TV         0x09
+#define DEVICE_TYPE_EFP                0x12
+#define DEVICE_TYPE_LFP                0x22
+/* On 915+ */
+#define DEVICE_TYPE_CRT_DPMS           0x6001
+#define DEVICE_TYPE_CRT_DPMS_HOTPLUG   0x4001
+#define DEVICE_TYPE_TV_COMPOSITE       0x0209
+#define DEVICE_TYPE_TV_MACROVISION     0x0289
+#define DEVICE_TYPE_TV_RF_COMPOSITE    0x020c
+#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE        0x0609
+#define DEVICE_TYPE_TV_SCART           0x0209
+#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
+#define DEVICE_TYPE_EFP_HOTPLUG_PWR    0x6012
+#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR        0x6052
+#define DEVICE_TYPE_EFP_DVI_I          0x6053
+#define DEVICE_TYPE_EFP_DVI_D_DUAL     0x6152
+#define DEVICE_TYPE_EFP_DVI_D_HDCP     0x60d2
+#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR        0x6062
+#define DEVICE_TYPE_OPENLDI_DUALPIX    0x6162
+#define DEVICE_TYPE_LFP_PANELLINK      0x5012
+#define DEVICE_TYPE_LFP_CMOS_PWR       0x5042
+#define DEVICE_TYPE_LFP_LVDS_PWR       0x5062
+#define DEVICE_TYPE_LFP_LVDS_DUAL      0x5162
+#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2
+
+#define DEVICE_CFG_NONE                0x00
+#define DEVICE_CFG_12BIT_DVOB  0x01
+#define DEVICE_CFG_12BIT_DVOC  0x02
+#define DEVICE_CFG_24BIT_DVOBC 0x09
+#define DEVICE_CFG_24BIT_DVOCB 0x0a
+#define DEVICE_CFG_DUAL_DVOB   0x11
+#define DEVICE_CFG_DUAL_DVOC   0x12
+#define DEVICE_CFG_DUAL_DVOBC  0x13
+#define DEVICE_CFG_DUAL_LINK_DVOBC     0x19
+#define DEVICE_CFG_DUAL_LINK_DVOCB     0x1a
+
+#define DEVICE_WIRE_NONE       0x00
+#define DEVICE_WIRE_DVOB       0x01
+#define DEVICE_WIRE_DVOC       0x02
+#define DEVICE_WIRE_DVOBC      0x03
+#define DEVICE_WIRE_DVOBB      0x05
+#define DEVICE_WIRE_DVOCC      0x06
+#define DEVICE_WIRE_DVOB_MASTER 0x0d
+#define DEVICE_WIRE_DVOC_MASTER 0x0e
+
+#define DEVICE_PORT_DVOA       0x00 /* none on 845+ */
+#define DEVICE_PORT_DVOB       0x01
+#define DEVICE_PORT_DVOC       0x02
+
+/*
+ * We used to keep this struct but without any version control. We should avoid
+ * using it in the future, but it should be safe to keep using it in the old
+ * code. Do not change; we rely on its size.
+ */
+struct old_child_dev_config {
+       u16 handle;
+       u16 device_type;
+       u8  device_id[10]; /* ascii string */
+       u16 addin_offset;
+       u8  dvo_port; /* See Device_PORT_* above */
+       u8  i2c_pin;
+       u8  slave_addr;
+       u8  ddc_pin;
+       u16 edid_ptr;
+       u8  dvo_cfg; /* See DEVICE_CFG_* above */
+       u8  dvo2_port;
+       u8  i2c2_pin;
+       u8  slave2_addr;
+       u8  ddc2_pin;
+       u8  capabilities;
+       u8  dvo_wiring;/* See DEVICE_WIRE_* above */
+       u8  dvo2_wiring;
+       u16 extended_type;
+       u8  dvo_function;
+} __packed;
+
+/* This one contains field offsets that are known to be common for all BDB
+ * versions. Notice that the meaning of the contents contents may still change,
+ * but at least the offsets are consistent. */
+
+/* Definitions for flags_1 */
+#define IBOOST_ENABLE (1<<3)
+
+struct common_child_dev_config {
+       u16 handle;
+       u16 device_type;
+       u8 not_common1[12];
+       u8 dvo_port;
+       u8 not_common2[2];
+       u8 ddc_pin;
+       u16 edid_ptr;
+       u8 obsolete;
+       u8 flags_1;
+       u8 not_common3[13];
+       u8 iboost_level;
+} __packed;
+
+
+/* This field changes depending on the BDB version, so the most reliable way to
+ * read it is by checking the BDB version and reading the raw pointer. */
+union child_device_config {
+       /* This one is safe to be used anywhere, but the code should still check
+        * the BDB version. */
+       u8 raw[33];
+       /* This one should only be kept for legacy code. */
+       struct old_child_dev_config old;
+       /* This one should also be safe to use anywhere, even without version
+        * checks. */
+       struct common_child_dev_config common;
+} __packed;
+
+struct bdb_general_definitions {
+       /* DDC GPIO */
+       u8 crt_ddc_gmbus_pin;
+
+       /* DPMS bits */
+       u8 dpms_acpi:1;
+       u8 skip_boot_crt_detect:1;
+       u8 dpms_aim:1;
+       u8 rsvd1:5; /* finish byte */
+
+       /* boot device bits */
+       u8 boot_display[2];
+       u8 child_dev_size;
+
+       /*
+        * Device info:
+        * If TV is present, it'll be at devices[0].
+        * LVDS will be next, either devices[0] or [1], if present.
+        * On some platforms the number of device is 6. But could be as few as
+        * 4 if both TV and LVDS are missing.
+        * And the device num is related with the size of general definition
+        * block. It is obtained by using the following formula:
+        * number = (block_size - sizeof(bdb_general_definitions))/
+        *           defs->child_dev_size;
+        */
+       uint8_t devices[0];
+} __packed;
+
+/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */
+#define MODE_MASK              0x3
+
+struct bdb_lvds_options {
+       u8 panel_type;
+       u8 rsvd1;
+       /* LVDS capabilities, stored in a dword */
+       u8 pfit_mode:2;
+       u8 pfit_text_mode_enhanced:1;
+       u8 pfit_gfx_mode_enhanced:1;
+       u8 pfit_ratio_auto:1;
+       u8 pixel_dither:1;
+       u8 lvds_edid:1;
+       u8 rsvd2:1;
+       u8 rsvd4;
+       /* LVDS Panel channel bits stored here */
+       u32 lvds_panel_channel_bits;
+       /* LVDS SSC (Spread Spectrum Clock) bits stored here. */
+       u16 ssc_bits;
+       u16 ssc_freq;
+       u16 ssc_ddt;
+       /* Panel color depth defined here */
+       u16 panel_color_depth;
+       /* LVDS panel type bits stored here */
+       u32 dps_panel_type_bits;
+       /* LVDS backlight control type bits stored here */
+       u32 blt_control_type_bits;
+} __packed;
+
+/* LFP pointer table contains entries to the struct below */
+struct bdb_lvds_lfp_data_ptr {
+       u16 fp_timing_offset; /* offsets are from start of bdb */
+       u8 fp_table_size;
+       u16 dvo_timing_offset;
+       u8 dvo_table_size;
+       u16 panel_pnp_id_offset;
+       u8 pnp_table_size;
+} __packed;
+
+struct bdb_lvds_lfp_data_ptrs {
+       u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
+       struct bdb_lvds_lfp_data_ptr ptr[16];
+} __packed;
+
+/* LFP data has 3 blocks per entry */
+struct lvds_fp_timing {
+       u16 x_res;
+       u16 y_res;
+       u32 lvds_reg;
+       u32 lvds_reg_val;
+       u32 pp_on_reg;
+       u32 pp_on_reg_val;
+       u32 pp_off_reg;
+       u32 pp_off_reg_val;
+       u32 pp_cycle_reg;
+       u32 pp_cycle_reg_val;
+       u32 pfit_reg;
+       u32 pfit_reg_val;
+       u16 terminator;
+} __packed;
+
+struct lvds_dvo_timing {
+       u16 clock;              /**< In 10khz */
+       u8 hactive_lo;
+       u8 hblank_lo;
+       u8 hblank_hi:4;
+       u8 hactive_hi:4;
+       u8 vactive_lo;
+       u8 vblank_lo;
+       u8 vblank_hi:4;
+       u8 vactive_hi:4;
+       u8 hsync_off_lo;
+       u8 hsync_pulse_width;
+       u8 vsync_pulse_width:4;
+       u8 vsync_off:4;
+       u8 rsvd0:6;
+       u8 hsync_off_hi:2;
+       u8 h_image;
+       u8 v_image;
+       u8 max_hv;
+       u8 h_border;
+       u8 v_border;
+       u8 rsvd1:3;
+       u8 digital:2;
+       u8 vsync_positive:1;
+       u8 hsync_positive:1;
+       u8 rsvd2:1;
+} __packed;
+
+struct lvds_pnp_id {
+       u16 mfg_name;
+       u16 product_code;
+       u32 serial;
+       u8 mfg_week;
+       u8 mfg_year;
+} __packed;
+
+struct bdb_lvds_lfp_data_entry {
+       struct lvds_fp_timing fp_timing;
+       struct lvds_dvo_timing dvo_timing;
+       struct lvds_pnp_id pnp_id;
+} __packed;
+
+struct bdb_lvds_lfp_data {
+       struct bdb_lvds_lfp_data_entry data[16];
+} __packed;
+
+#define BDB_BACKLIGHT_TYPE_NONE        0
+#define BDB_BACKLIGHT_TYPE_PWM 2
+
+struct bdb_lfp_backlight_data_entry {
+       u8 type:2;
+       u8 active_low_pwm:1;
+       u8 obsolete1:5;
+       u16 pwm_freq_hz;
+       u8 min_brightness;
+       u8 obsolete2;
+       u8 obsolete3;
+} __packed;
+
+struct bdb_lfp_backlight_data {
+       u8 entry_size;
+       struct bdb_lfp_backlight_data_entry data[16];
+       u8 level[16];
+} __packed;
+
+struct aimdb_header {
+       char signature[16];
+       char oem_device[20];
+       u16 aimdb_version;
+       u16 aimdb_header_size;
+       u16 aimdb_size;
+} __packed;
+
+struct aimdb_block {
+       u8 aimdb_id;
+       u16 aimdb_size;
+} __packed;
+
+struct vch_panel_data {
+       u16 fp_timing_offset;
+       u8 fp_timing_size;
+       u16 dvo_timing_offset;
+       u8 dvo_timing_size;
+       u16 text_fitting_offset;
+       u8 text_fitting_size;
+       u16 graphics_fitting_offset;
+       u8 graphics_fitting_size;
+} __packed;
+
+struct vch_bdb_22 {
+       struct aimdb_block aimdb_block;
+       struct vch_panel_data panels[16];
+} __packed;
+
+struct bdb_sdvo_lvds_options {
+       u8 panel_backlight;
+       u8 h40_set_panel_type;
+       u8 panel_type;
+       u8 ssc_clk_freq;
+       u16 als_low_trip;
+       u16 als_high_trip;
+       u8 sclalarcoeff_tab_row_num;
+       u8 sclalarcoeff_tab_row_size;
+       u8 coefficient[8];
+       u8 panel_misc_bits_1;
+       u8 panel_misc_bits_2;
+       u8 panel_misc_bits_3;
+       u8 panel_misc_bits_4;
+} __packed;
+
+
+#define BDB_DRIVER_FEATURE_NO_LVDS             0
+#define BDB_DRIVER_FEATURE_INT_LVDS            1
+#define BDB_DRIVER_FEATURE_SDVO_LVDS           2
+#define BDB_DRIVER_FEATURE_EDP                 3
+
+struct bdb_driver_features {
+       u8 boot_dev_algorithm:1;
+       u8 block_display_switch:1;
+       u8 allow_display_switch:1;
+       u8 hotplug_dvo:1;
+       u8 dual_view_zoom:1;
+       u8 int15h_hook:1;
+       u8 sprite_in_clone:1;
+       u8 primary_lfp_id:1;
+
+       u16 boot_mode_x;
+       u16 boot_mode_y;
+       u8 boot_mode_bpp;
+       u8 boot_mode_refresh;
+
+       u16 enable_lfp_primary:1;
+       u16 selective_mode_pruning:1;
+       u16 dual_frequency:1;
+       u16 render_clock_freq:1; /* 0: high freq; 1: low freq */
+       u16 nt_clone_support:1;
+       u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
+       u16 sprite_display_assign:1; /* 0: secondary; 1: primary */
+       u16 cui_aspect_scaling:1;
+       u16 preserve_aspect_ratio:1;
+       u16 sdvo_device_power_down:1;
+       u16 crt_hotplug:1;
+       u16 lvds_config:2;
+       u16 tv_hotplug:1;
+       u16 hdmi_config:2;
+
+       u8 static_display:1;
+       u8 reserved2:7;
+       u16 legacy_crt_max_x;
+       u16 legacy_crt_max_y;
+       u8 legacy_crt_max_refresh;
+
+       u8 hdmi_termination;
+       u8 custom_vbt_version;
+       /* Driver features data block */
+       u16 rmpm_enabled:1;
+       u16 s2ddt_enabled:1;
+       u16 dpst_enabled:1;
+       u16 bltclt_enabled:1;
+       u16 adb_enabled:1;
+       u16 drrs_enabled:1;
+       u16 grs_enabled:1;
+       u16 gpmt_enabled:1;
+       u16 tbt_enabled:1;
+       u16 psr_enabled:1;
+       u16 ips_enabled:1;
+       u16 reserved3:4;
+       u16 pc_feature_valid:1;
+} __packed;
+
+#define EDP_18BPP      0
+#define EDP_24BPP      1
+#define EDP_30BPP      2
+#define EDP_RATE_1_62  0
+#define EDP_RATE_2_7   1
+#define EDP_LANE_1     0
+#define EDP_LANE_2     1
+#define EDP_LANE_4     3
+#define EDP_PREEMPHASIS_NONE   0
+#define EDP_PREEMPHASIS_3_5dB  1
+#define EDP_PREEMPHASIS_6dB    2
+#define EDP_PREEMPHASIS_9_5dB  3
+#define EDP_VSWING_0_4V                0
+#define EDP_VSWING_0_6V                1
+#define EDP_VSWING_0_8V                2
+#define EDP_VSWING_1_2V                3
+
+
+struct edp_link_params {
+       u8 rate:4;
+       u8 lanes:4;
+       u8 preemphasis:4;
+       u8 vswing:4;
+} __packed;
+
+struct bdb_edp {
+       struct edp_power_seq power_seqs[16];
+       u32 color_depth;
+       struct edp_link_params link_params[16];
+       u32 sdrrs_msa_timing_delay;
+
+       /* ith bit indicates enabled/disabled for (i+1)th panel */
+       u16 edp_s3d_feature;
+       u16 edp_t3_optimization;
+       u64 edp_vswing_preemph;         /* v173 */
+} __packed;
+
+struct psr_table {
+       /* Feature bits */
+       u8 full_link:1;
+       u8 require_aux_to_wakeup:1;
+       u8 feature_bits_rsvd:6;
+
+       /* Wait times */
+       u8 idle_frames:4;
+       u8 lines_to_wait:3;
+       u8 wait_times_rsvd:1;
+
+       /* TP wake up time in multiple of 100 */
+       u16 tp1_wakeup_time;
+       u16 tp2_tp3_wakeup_time;
+} __packed;
+
+struct bdb_psr {
+       struct psr_table psr_table[16];
+} __packed;
+
+/*
+ * Driver<->VBIOS interaction occurs through scratch bits in
+ * GR18 & SWF*.
+ */
+
+/* GR18 bits are set on display switch and hotkey events */
+#define GR18_DRIVER_SWITCH_EN  (1<<7) /* 0: VBIOS control, 1: driver control */
+#define GR18_HOTKEY_MASK       0x78 /* See also SWF4 15:0 */
+#define   GR18_HK_NONE         (0x0<<3)
+#define   GR18_HK_LFP_STRETCH  (0x1<<3)
+#define   GR18_HK_TOGGLE_DISP  (0x2<<3)
+#define   GR18_HK_DISP_SWITCH  (0x4<<3) /* see SWF14 15:0 for what to enable */
+#define   GR18_HK_POPUP_DISABLED (0x6<<3)
+#define   GR18_HK_POPUP_ENABLED        (0x7<<3)
+#define   GR18_HK_PFIT         (0x8<<3)
+#define   GR18_HK_APM_CHANGE   (0xa<<3)
+#define   GR18_HK_MULTIPLE     (0xc<<3)
+#define GR18_USER_INT_EN       (1<<2)
+#define GR18_A0000_FLUSH_EN    (1<<1)
+#define GR18_SMM_EN            (1<<0)
+
+/* Set by driver, cleared by VBIOS */
+#define SWF00_YRES_SHIFT       16
+#define SWF00_XRES_SHIFT       0
+#define SWF00_RES_MASK         0xffff
+
+/* Set by VBIOS at boot time and driver at runtime */
+#define SWF01_TV2_FORMAT_SHIFT 8
+#define SWF01_TV1_FORMAT_SHIFT 0
+#define SWF01_TV_FORMAT_MASK   0xffff
+
+#define SWF10_VBIOS_BLC_I2C_EN (1<<29)
+#define SWF10_GTT_OVERRIDE_EN  (1<<28)
+#define SWF10_LFP_DPMS_OVR     (1<<27) /* override DPMS on display switch */
+#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
+#define   SWF10_OLD_TOGGLE     0x0
+#define   SWF10_TOGGLE_LIST_1  0x1
+#define   SWF10_TOGGLE_LIST_2  0x2
+#define   SWF10_TOGGLE_LIST_3  0x3
+#define   SWF10_TOGGLE_LIST_4  0x4
+#define SWF10_PANNING_EN       (1<<23)
+#define SWF10_DRIVER_LOADED    (1<<22)
+#define SWF10_EXTENDED_DESKTOP (1<<21)
+#define SWF10_EXCLUSIVE_MODE   (1<<20)
+#define SWF10_OVERLAY_EN       (1<<19)
+#define SWF10_PLANEB_HOLDOFF   (1<<18)
+#define SWF10_PLANEA_HOLDOFF   (1<<17)
+#define SWF10_VGA_HOLDOFF      (1<<16)
+#define SWF10_ACTIVE_DISP_MASK 0xffff
+#define   SWF10_PIPEB_LFP2     (1<<15)
+#define   SWF10_PIPEB_EFP2     (1<<14)
+#define   SWF10_PIPEB_TV2      (1<<13)
+#define   SWF10_PIPEB_CRT2     (1<<12)
+#define   SWF10_PIPEB_LFP      (1<<11)
+#define   SWF10_PIPEB_EFP      (1<<10)
+#define   SWF10_PIPEB_TV       (1<<9)
+#define   SWF10_PIPEB_CRT      (1<<8)
+#define   SWF10_PIPEA_LFP2     (1<<7)
+#define   SWF10_PIPEA_EFP2     (1<<6)
+#define   SWF10_PIPEA_TV2      (1<<5)
+#define   SWF10_PIPEA_CRT2     (1<<4)
+#define   SWF10_PIPEA_LFP      (1<<3)
+#define   SWF10_PIPEA_EFP      (1<<2)
+#define   SWF10_PIPEA_TV       (1<<1)
+#define   SWF10_PIPEA_CRT      (1<<0)
+
+#define SWF11_MEMORY_SIZE_SHIFT        16
+#define SWF11_SV_TEST_EN       (1<<15)
+#define SWF11_IS_AGP           (1<<14)
+#define SWF11_DISPLAY_HOLDOFF  (1<<13)
+#define SWF11_DPMS_REDUCED     (1<<12)
+#define SWF11_IS_VBE_MODE      (1<<11)
+#define SWF11_PIPEB_ACCESS     (1<<10) /* 0 here means pipe a */
+#define SWF11_DPMS_MASK                0x07
+#define   SWF11_DPMS_OFF       (1<<2)
+#define   SWF11_DPMS_SUSPEND   (1<<1)
+#define   SWF11_DPMS_STANDBY   (1<<0)
+#define   SWF11_DPMS_ON                0
+
+#define SWF14_GFX_PFIT_EN      (1<<31)
+#define SWF14_TEXT_PFIT_EN     (1<<30)
+#define SWF14_LID_STATUS_CLOSED        (1<<29) /* 0 here means open */
+#define SWF14_POPUP_EN         (1<<28)
+#define SWF14_DISPLAY_HOLDOFF  (1<<27)
+#define SWF14_DISP_DETECT_EN   (1<<26)
+#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
+#define SWF14_DRIVER_STATUS    (1<<24)
+#define SWF14_OS_TYPE_WIN9X    (1<<23)
+#define SWF14_OS_TYPE_WINNT    (1<<22)
+/* 21:19 rsvd */
+#define SWF14_PM_TYPE_MASK     0x00070000
+#define   SWF14_PM_ACPI_VIDEO  (0x4 << 16)
+#define   SWF14_PM_ACPI                (0x3 << 16)
+#define   SWF14_PM_APM_12      (0x2 << 16)
+#define   SWF14_PM_APM_11      (0x1 << 16)
+#define SWF14_HK_REQUEST_MASK  0x0000ffff /* see GR18 6:3 for event type */
+          /* if GR18 indicates a display switch */
+#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
+#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
+#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
+#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
+#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
+#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
+#define   SWF14_DS_PIPEB_TV_EN   (1<<9)
+#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
+#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
+#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
+#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
+#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
+#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
+#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
+#define   SWF14_DS_PIPEA_TV_EN   (1<<1)
+#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
+          /* if GR18 indicates a panel fitting request */
+#define   SWF14_PFIT_EN                (1<<0) /* 0 means disable */
+          /* if GR18 indicates an APM change request */
+#define   SWF14_APM_HIBERNATE  0x4
+#define   SWF14_APM_SUSPEND    0x3
+#define   SWF14_APM_STANDBY    0x1
+#define   SWF14_APM_RESTORE    0x0
+
+/* Add the device class for LFP, TV, HDMI */
+#define         DEVICE_TYPE_INT_LFP    0x1022
+#define         DEVICE_TYPE_INT_TV     0x1009
+#define         DEVICE_TYPE_HDMI       0x60D2
+#define         DEVICE_TYPE_DP         0x68C6
+#define         DEVICE_TYPE_eDP        0x78C6
+
+#define  DEVICE_TYPE_CLASS_EXTENSION   (1 << 15)
+#define  DEVICE_TYPE_POWER_MANAGEMENT  (1 << 14)
+#define  DEVICE_TYPE_HOTPLUG_SIGNALING (1 << 13)
+#define  DEVICE_TYPE_INTERNAL_CONNECTOR        (1 << 12)
+#define  DEVICE_TYPE_NOT_HDMI_OUTPUT   (1 << 11)
+#define  DEVICE_TYPE_MIPI_OUTPUT       (1 << 10)
+#define  DEVICE_TYPE_COMPOSITE_OUTPUT  (1 << 9)
+#define  DEVICE_TYPE_DUAL_CHANNEL      (1 << 8)
+#define  DEVICE_TYPE_HIGH_SPEED_LINK   (1 << 6)
+#define  DEVICE_TYPE_LVDS_SINGALING    (1 << 5)
+#define  DEVICE_TYPE_TMDS_DVI_SIGNALING        (1 << 4)
+#define  DEVICE_TYPE_VIDEO_SIGNALING   (1 << 3)
+#define  DEVICE_TYPE_DISPLAYPORT_OUTPUT        (1 << 2)
+#define  DEVICE_TYPE_DIGITAL_OUTPUT    (1 << 1)
+#define  DEVICE_TYPE_ANALOG_OUTPUT     (1 << 0)
+
+/*
+ * Bits we care about when checking for DEVICE_TYPE_eDP
+ * Depending on the system, the other bits may or may not
+ * be set for eDP outputs.
+ */
+#define DEVICE_TYPE_eDP_BITS \
+       (DEVICE_TYPE_INTERNAL_CONNECTOR | \
+        DEVICE_TYPE_MIPI_OUTPUT | \
+        DEVICE_TYPE_COMPOSITE_OUTPUT | \
+        DEVICE_TYPE_DUAL_CHANNEL | \
+        DEVICE_TYPE_LVDS_SINGALING | \
+        DEVICE_TYPE_TMDS_DVI_SIGNALING | \
+        DEVICE_TYPE_VIDEO_SIGNALING | \
+        DEVICE_TYPE_DISPLAYPORT_OUTPUT | \
+        DEVICE_TYPE_ANALOG_OUTPUT)
+
+/* define the DVO port for HDMI output type */
+#define                DVO_B           1
+#define                DVO_C           2
+#define                DVO_D           3
+
+/* Possible values for the "DVO Port" field for versions >= 155: */
+#define DVO_PORT_HDMIA 0
+#define DVO_PORT_HDMIB 1
+#define DVO_PORT_HDMIC 2
+#define DVO_PORT_HDMID 3
+#define DVO_PORT_LVDS  4
+#define DVO_PORT_TV    5
+#define DVO_PORT_CRT   6
+#define DVO_PORT_DPB   7
+#define DVO_PORT_DPC   8
+#define DVO_PORT_DPD   9
+#define DVO_PORT_DPA   10
+#define DVO_PORT_DPE   11
+#define DVO_PORT_HDMIE 12
+#define DVO_PORT_MIPIA 21
+#define DVO_PORT_MIPIB 22
+#define DVO_PORT_MIPIC 23
+#define DVO_PORT_MIPID 24
+
+/* Block 52 contains MIPI configuration block
+ * 6 * bdb_mipi_config, followed by 6 pps data block
+ * block below
+ */
+#define MAX_MIPI_CONFIGURATIONS        6
+
+struct bdb_mipi_config {
+       struct mipi_config config[MAX_MIPI_CONFIGURATIONS];
+       struct mipi_pps_data pps[MAX_MIPI_CONFIGURATIONS];
+} __packed;
+
+/* Block 53 contains MIPI sequences as needed by the panel
+ * for enabling it. This block can be variable in size and
+ * can be maximum of 6 blocks
+ */
+struct bdb_mipi_sequence {
+       u8 version;
+       u8 data[0];
+} __packed;
+
+enum mipi_gpio_pin_index {
+       MIPI_GPIO_UNDEFINED = 0,
+       MIPI_GPIO_PANEL_ENABLE,
+       MIPI_GPIO_BL_ENABLE,
+       MIPI_GPIO_PWM_ENABLE,
+       MIPI_GPIO_RESET_N,
+       MIPI_GPIO_PWR_DOWN_R,
+       MIPI_GPIO_STDBY_RST_N,
+       MIPI_GPIO_MAX
+};
+
+#endif /* _INTEL_VBT_DEFS_H_ */