drm/i915/dsb: Handle the indexed vs. not inside the DSB code
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Fri, 16 Dec 2022 00:38:05 +0000 (02:38 +0200)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Fri, 13 Jan 2023 14:54:03 +0000 (16:54 +0200)
The DSB indexed register write insturction is purely an internal
DSB implementation detail, no reason why the caller should have to
know about it. So let's just have the caller emit blind register
writes let the DSB code convert things to an indexed write if/when
multiple writes occur to the same register offset in a row.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-9-ville.syrjala@linux.intel.com
Reviewed-by: Animesh Manna <animesh.manna@intel.com>
drivers/gpu/drm/i915/display/intel_color.c
drivers/gpu/drm/i915/display/intel_dsb.c
drivers/gpu/drm/i915/display/intel_dsb.h

index d57631b..7660335 100644 (file)
@@ -847,17 +847,6 @@ static void ilk_lut_write(const struct intel_crtc_state *crtc_state,
                intel_de_write_fw(i915, reg, val);
 }
 
-static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state,
-                                 i915_reg_t reg, u32 val)
-{
-       struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
-
-       if (crtc_state->dsb)
-               intel_dsb_indexed_reg_write(crtc_state->dsb, reg, val);
-       else
-               intel_de_write_fw(i915, reg, val);
-}
-
 static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
                           const struct drm_property_blob *blob)
 {
@@ -962,8 +951,8 @@ static void bdw_load_lut_10(const struct intel_crtc_state *crtc_state,
                      prec_index);
 
        for (i = 0; i < lut_size; i++)
-               ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
-                                     ilk_lut_10(&lut[i]));
+               ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
+                             ilk_lut_10(&lut[i]));
 
        /*
         * Reset the index, otherwise it prevents the legacy palette to be
@@ -1093,13 +1082,13 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state,
                 * ToDo: Extend to max 7.0. Enable 32 bit input value
                 * as compared to just 16 to achieve this.
                 */
-               ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe),
-                                     lut[i].green);
+               ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
+                             lut[i].green);
        }
 
        /* Clamp values > 1.0. */
        while (i++ < glk_degamma_lut_size(i915))
-               ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
+               ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
 
        ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0);
 }
@@ -1165,10 +1154,10 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state)
        for (i = 0; i < 9; i++) {
                const struct drm_color_lut *entry = &lut[i];
 
-               ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
-                                     ilk_lut_12p4_ldw(entry));
-               ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
-                                     ilk_lut_12p4_udw(entry));
+               ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
+                             ilk_lut_12p4_ldw(entry));
+               ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
+                             ilk_lut_12p4_udw(entry));
        }
 
        ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe),
@@ -1204,10 +1193,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
        for (i = 1; i < 257; i++) {
                entry = &lut[i * 8];
 
-               ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
-                                     ilk_lut_12p4_ldw(entry));
-               ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
-                                     ilk_lut_12p4_udw(entry));
+               ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
+                             ilk_lut_12p4_ldw(entry));
+               ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
+                             ilk_lut_12p4_udw(entry));
        }
 
        /*
@@ -1225,10 +1214,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
        for (i = 0; i < 256; i++) {
                entry = &lut[i * 8 * 128];
 
-               ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
-                                     ilk_lut_12p4_ldw(entry));
-               ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
-                                     ilk_lut_12p4_udw(entry));
+               ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
+                             ilk_lut_12p4_ldw(entry));
+               ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
+                             ilk_lut_12p4_udw(entry));
        }
 
        ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
index fcc3f49..fa4b808 100644 (file)
@@ -114,32 +114,28 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
        return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
 }
 
+static bool intel_dsb_prev_ins_is_mmio_write(struct intel_dsb *dsb, i915_reg_t reg)
+{
+       return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_MMIO_WRITE, reg);
+}
+
 static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg)
 {
        return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_INDEXED_WRITE, reg);
 }
 
 /**
- * intel_dsb_indexed_reg_write() -Write to the DSB context for auto
- * increment register.
+ * intel_dsb_reg_write() - Emit register wriite to the DSB context
  * @dsb: DSB context
  * @reg: register address.
  * @val: value.
  *
  * This function is used for writing register-value pair in command
- * buffer of DSB for auto-increment register. During command buffer overflow,
- * a warning is thrown and rest all erroneous condition register programming
- * is done through mmio write.
+ * buffer of DSB.
  */
-
-void intel_dsb_indexed_reg_write(struct intel_dsb *dsb,
-                                i915_reg_t reg, u32 val)
+void intel_dsb_reg_write(struct intel_dsb *dsb,
+                        i915_reg_t reg, u32 val)
 {
-       u32 *buf = dsb->cmd_buf;
-
-       if (!assert_dsb_has_room(dsb))
-               return;
-
        /*
         * For example the buffer will look like below for 3 dwords for auto
         * increment register:
@@ -156,57 +152,39 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb,
         * we are writing odd no of dwords, Zeros will be added in the end for
         * padding.
         */
-       if (!intel_dsb_prev_ins_is_indexed_write(dsb, reg)) {
-               /* Every instruction should be 8 byte aligned. */
-               dsb->free_pos = ALIGN(dsb->free_pos, 2);
+       if (!intel_dsb_prev_ins_is_mmio_write(dsb, reg) &&
+           !intel_dsb_prev_ins_is_indexed_write(dsb, reg)) {
+               intel_dsb_emit(dsb, val,
+                              (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) |
+                              (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) |
+                              i915_mmio_reg_offset(reg));
+       } else {
+               u32 *buf = dsb->cmd_buf;
 
-               dsb->ins_start_offset = dsb->free_pos;
+               if (!assert_dsb_has_room(dsb))
+                       return;
 
-               /* Update the size. */
-               buf[dsb->free_pos++] = 1;
+               /* convert to indexed write? */
+               if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) {
+                       u32 prev_val = buf[dsb->ins_start_offset + 0];
 
-               /* Update the opcode and reg. */
-               buf[dsb->free_pos++] = (DSB_OPCODE_INDEXED_WRITE  <<
-                                       DSB_OPCODE_SHIFT) |
-                                       i915_mmio_reg_offset(reg);
+                       buf[dsb->ins_start_offset + 0] = 1; /* size */
+                       buf[dsb->ins_start_offset + 1] =
+                               (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) |
+                               i915_mmio_reg_offset(reg);
+                       buf[dsb->ins_start_offset + 2] = prev_val;
 
-               /* Update the value. */
-               buf[dsb->free_pos++] = val;
-       } else {
-               /* Update the new value. */
-               buf[dsb->free_pos++] = val;
+                       dsb->free_pos++;
+               }
 
+               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;
-}
-
-/**
- * intel_dsb_reg_write() -Write to the DSB context for normal
- * register.
- * @crtc_state: intel_crtc_state structure
- * @reg: register address.
- * @val: value.
- *
- * This function is used for writing register-value pair in command
- * buffer of DSB. During command buffer overflow, a warning  is thrown
- * and rest all erroneous condition register programming is done
- * through mmio write.
- */
-void intel_dsb_reg_write(struct intel_dsb *dsb,
-                        i915_reg_t reg, u32 val)
-{
-       if (!assert_dsb_has_room(dsb))
-               return;
 
-       intel_dsb_emit(dsb, val,
-                      (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) |
-                      (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) |
-                      i915_mmio_reg_offset(reg));
+               /* if number of data words is odd, then the last dword should be 0.*/
+               if (dsb->free_pos & 0x1)
+                       buf[dsb->free_pos] = 0;
+       }
 }
 
 /**
index 25f13c4..25d7740 100644 (file)
@@ -17,8 +17,6 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc);
 void intel_dsb_cleanup(struct intel_dsb *dsb);
 void intel_dsb_reg_write(struct intel_dsb *dsb,
                         i915_reg_t reg, u32 val);
-void intel_dsb_indexed_reg_write(struct intel_dsb *dsb,
-                                i915_reg_t reg, u32 val);
 void intel_dsb_commit(struct intel_dsb *dsb);
 
 #endif