On Fri, 20 Sep 2019, Animesh Manna <animesh.manna@xxxxxxxxx> wrote: > DSB can program large set of data through indexed register write > (opcode 0x9) in one shot. DSB feature can be used for bulk register > programming e.g. gamma lut programming, HDR meta data programming. > > v1: initial version. > v2: simplified code by using ALIGN(). (Chris) > v3: ascii table added as code comment. (Shashank) > v4: cosmetic changes done. (Shashank) > v5: reset ins_start_offset. (Jani) > v6: update ins_start_offset in inel_dsb_reg_write. > > Cc: Shashank Sharma <shashank.sharma@xxxxxxxxx> > Cc: Imre Deak <imre.deak@xxxxxxxxx> > Cc: Jani Nikula <jani.nikula@xxxxxxxxx> > Cc: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> > Reviewed-by: Shashank Sharma <shashank.sharma@xxxxxxxxx> > Signed-off-by: Animesh Manna <animesh.manna@xxxxxxxxx> > --- > drivers/gpu/drm/i915/display/intel_dsb.c | 68 ++++++++++++++++++++++++ > drivers/gpu/drm/i915/display/intel_dsb.h | 9 ++++ > 2 files changed, 77 insertions(+) > > diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c > index f94cd6dc98b6..faa853b08458 100644 > --- a/drivers/gpu/drm/i915/display/intel_dsb.c > +++ b/drivers/gpu/drm/i915/display/intel_dsb.c > @@ -12,8 +12,10 @@ > /* 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) > @@ -83,9 +85,74 @@ void intel_dsb_put(struct intel_dsb *dsb) > 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); > @@ -102,6 +169,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) > return; > } > > + dsb->ins_start_offset = dsb->free_pos; Okay, I'm being a pedant, but that's kind of part of the job description, I'm afraid. What if: intel_dsb_get() intel_dsb_reg_write(dsb, FOO, 0); intel_dsb_indexed_reg_write(dsb, FOO, 0); intel_dsb_commit() intel_dsb_put() BR, Jani. > buf[dsb->free_pos++] = val; > buf[dsb->free_pos++] = (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | > (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | > diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h > index 0686d67b34d5..2ae22f7309a7 100644 > --- a/drivers/gpu/drm/i915/display/intel_dsb.h > +++ b/drivers/gpu/drm/i915/display/intel_dsb.h > @@ -30,11 +30,20 @@ struct intel_dsb { > * and help in calculating tail of command buffer. > */ > int free_pos; > + > + /* > + * ins_start_offset will help to store start address of the dsb > + * instuction and help in identifying the batch of auto-increment > + * register. > + */ > + u32 ins_start_offset; > }; > > struct intel_dsb * > intel_dsb_get(struct intel_crtc *crtc); > void intel_dsb_put(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); > > #endif -- Jani Nikula, Intel Open Source Graphics Center _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx