/* DSB opcodes. */
 #define DSB_OPCODE_SHIFT               24
 #define DSB_OPCODE_MMIO_WRITE          0x1
+#define DSB_OPCODE_INDEXED_WRITE       0x9
 #define DSB_BYTE_EN                    0xF
 #define DSB_BYTE_EN_SHIFT              20
+#define DSB_REG_VALUE_MASK             0xfffff
 
 struct intel_dsb *
 intel_dsb_get(struct intel_crtc *crtc)
                mutex_unlock(&i915->drm.struct_mutex);
                dsb->cmd_buf = NULL;
                dsb->free_pos = 0;
+               dsb->ins_start_offset = 0;
        }
 }
 
+void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg,
+                                u32 val)
+{
+       struct intel_crtc *crtc = container_of(dsb, typeof(*crtc), dsb);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       u32 *buf = dsb->cmd_buf;
+       u32 reg_val;
+
+       if (!buf) {
+               I915_WRITE(reg, val);
+               return;
+       }
+
+       if (WARN_ON(dsb->free_pos >= DSB_BUF_SIZE)) {
+               DRM_DEBUG_KMS("DSB buffer overflow\n");
+               return;
+       }
+
+       /*
+        * For example the buffer will look like below for 3 dwords for auto
+        * increment register:
+        * +--------------------------------------------------------+
+        * | size = 3 | offset &| value1 | value2 | value3 | zero   |
+        * |          | opcode  |        |        |        |        |
+        * +--------------------------------------------------------+
+        * +          +         +        +        +        +        +
+        * 0          4         8        12       16       20       24
+        * Byte
+        *
+        * As every instruction is 8 byte aligned the index of dsb instruction
+        * will start always from even number while dealing with u32 array. If
+        * we are writing odd no of dwords, Zeros will be added in the end for
+        * padding.
+        */
+       reg_val = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
+       if (reg_val != i915_mmio_reg_offset(reg)) {
+               /* Every instruction should be 8 byte aligned. */
+               dsb->free_pos = ALIGN(dsb->free_pos, 2);
+
+               dsb->ins_start_offset = dsb->free_pos;
+
+               /* Update the size. */
+               buf[dsb->free_pos++] = 1;
+
+               /* Update the opcode and reg. */
+               buf[dsb->free_pos++] = (DSB_OPCODE_INDEXED_WRITE  <<
+                                       DSB_OPCODE_SHIFT) |
+                                       i915_mmio_reg_offset(reg);
+
+               /* Update the value. */
+               buf[dsb->free_pos++] = val;
+       } else {
+               /* Update the new value. */
+               buf[dsb->free_pos++] = val;
+
+               /* Update the size. */
+               buf[dsb->ins_start_offset]++;
+       }
+
+       /* if number of data words is odd, then the last dword should be 0.*/
+       if (dsb->free_pos & 0x1)
+               buf[dsb->free_pos] = 0;
+}
+
 void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val)
 {
        struct intel_crtc *crtc = container_of(dsb, typeof(*crtc), dsb);
                return;
        }
 
+       dsb->ins_start_offset = dsb->free_pos;
        buf[dsb->free_pos++] = val;
        buf[dsb->free_pos++] = (DSB_OPCODE_MMIO_WRITE  << DSB_OPCODE_SHIFT) |
                               (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) |