[Intel-gfx] [PATCH 1/3] drm/i915/icl: Add icl pipe degamma and gamma support
Matt Roper
matthew.d.roper at intel.com
Wed Oct 31 23:40:23 UTC 2018
On Tue, Oct 30, 2018 at 05:03:57PM -0700, Matt Roper wrote:
> On Wed, Oct 24, 2018 at 08:30:11PM +0530, Uma Shankar wrote:
> > Add support for icl pipe degamma and gamma.
> >
> > v2: Removed a POSTING_READ and corrected the Bit
> > Definition as per Maarten's comments.
> >
> > Signed-off-by: Uma Shankar <uma.shankar at intel.com>
> > ---
> > drivers/gpu/drm/i915/i915_reg.h | 3 ++
> > drivers/gpu/drm/i915/intel_color.c | 74 ++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 77 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 8bd61f9..3adf689 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -6965,6 +6965,9 @@ enum {
> > #define GAMMA_MODE_MODE_12BIT (2 << 0)
> > #define GAMMA_MODE_MODE_SPLIT (3 << 0)
> >
> > +#define PRE_CSC_GAMMA_ENABLE (1 << 31)
> > +#define POST_CSC_GAMMA_ENABLE (1 << 30)
> > +
> > /* DMC/CSR */
> > #define CSR_PROGRAM(i) _MMIO(0x80000 + (i) * 4)
> > #define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0
> > diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
> > index 5127da2..12c659f 100644
> > --- a/drivers/gpu/drm/i915/intel_color.c
> > +++ b/drivers/gpu/drm/i915/intel_color.c
> > @@ -424,6 +424,7 @@ static void bdw_load_gamma_lut(struct drm_crtc_state *state, u32 offset)
> > struct drm_i915_private *dev_priv = to_i915(state->crtc->dev);
> > enum pipe pipe = to_intel_crtc(state->crtc)->pipe;
> > uint32_t i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
> > + uint32_t tmp;
> >
> > WARN_ON(offset & ~PAL_PREC_INDEX_VALUE_MASK);
> >
> > @@ -464,6 +465,11 @@ static void bdw_load_gamma_lut(struct drm_crtc_state *state, u32 offset)
> > I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), (1 << 16) - 1);
> > I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), (1 << 16) - 1);
> > }
> > +
> > + if (IS_ICELAKE(dev_priv)) {
>
> We probably want to do "INTEL_GEN(dev_priv) >= 11" here to future-proof
> this against future gen's (or other platforms that might match gen11
> design without being classified as icelake).
>
> > + tmp = I915_READ(GAMMA_MODE(pipe));
> > + I915_WRITE(GAMMA_MODE(pipe), tmp | POST_CSC_GAMMA_ENABLE);
> > + }
>
> We generally try to avoid read-modify-write approaches to updating
> registers; it's better to build the full register value from scratch to
> make sure we know exactly what's in it.
>
> There are a few places in this patch you do a r-m-w cycle. I'd suggest
> we add an intel_crtc_state->gamma_mode field and calculate all the
> appropriate bits during the atomic check phase. Then we can just do a
>
> if (INTEL_GEN(dev_priv) >= 11)
> I915_WRITE(GAMMA_MODE(pipe), intel_crtc_state->gamma_mode);
>
> once somewhere more central any time crtc_state->color_mgmt_changed is
> true.
>
> > }
> >
> > /* Loads the palette/gamma unit for the CRTC on Broadwell+. */
> > @@ -523,6 +529,50 @@ static void glk_load_degamma_lut(struct drm_crtc_state *state)
> > I915_WRITE(PRE_CSC_GAMC_DATA(pipe), (1 << 16));
> > }
> >
> > +static void icl_load_degamma_lut(struct drm_crtc_state *state)
> > +{
> > + struct drm_i915_private *dev_priv = to_i915(state->crtc->dev);
> > + enum pipe pipe = to_intel_crtc(state->crtc)->pipe;
> > + const uint32_t lut_size = 33;
>
> Isn't this the value from INTEL_INFO(dev)->color.degamma_lut_size?
> Actually, upon closer inspection it looks like LUT size, ranges, etc. is
> sort of complicated; more comments farther down.
>
> > + uint32_t tmp, i;
> > +
> > + /*
> > + * When setting the auto-increment bit, the hardware seems to
> > + * ignore the index bits, so we need to reset it to index 0
> > + * separately.
> > + */
>
> The final sentence of the bspec description says (emphasis mine):
>
> "While in auto increment mode, after performing reads or writes
> to only part of the range, the auto increment bit must be
> cleared *before* resetting the index value."
>
> so I suspect it's technically the first write (which disables the
> auto-increment) that ignores the index bits. Then your second write
> both sets the index bits (to 0) and turns auto-increment back on.
>
> > + I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), 0);
> > + I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), PRE_CSC_GAMC_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++) {
> > + /*
> > + * Currently Clamp input to 1.0.
> > + * ToDo: Extend to max 7.0.
> > + */
>
> This comment is a little confusing. I think what you mean is that this
> for() loop covers the first 33 entries, which represent the range of
> inputs from 0 to 1.0. The remaining two entries are for extended range
> of inputs (representing gamma values at 3.0 and 7.0) and are not evenly
> spaced.
>
> > + uint32_t word =
> > + drm_color_lut_extract(lut[i].red, 16);
> > + I915_WRITE(PRE_CSC_GAMC_DATA(pipe), word);
> > + }
>
> Following the loop is where we'd need to deal with the two extended
> range entries, right? So if we leave dealing with extended range
> properly as a TODO for now, then I think we want to fill them in with
> linear values. E.g.,
>
> I915_WRITE(PRE_CSC_GAMC_DATA(pipe), 0x30000);
> I915_WRITE(PRE_CSC_GAMC_DATA(pipe), 0x70000);
Actually, it looks like you actually do set these at the bottom of the
function (and clamp to 1.0), so that's fine and you can disregard this
comment.
Matt
>
> Also, I believe the 1.0 input can have a value >= 1.0, so we need to
> extract more bits of precision for that.
>
> I'm not really an expert on how this color management stuff gets used by
> userspace in practice, but I suspect our current ABI probably needs to
> be augmented to deal more complicated gamma LUT's than we support today.
> E.g., different ranges with different input values, precision, etc. Do
> we have a clear understanding of if/how userspace wants to deal with
> extended range?
>
> > + } else {
> > + /* load a linear table. */
> > + for (i = 0; i < lut_size; i++) {
> > + uint32_t v = (i * (1 << 16)) / (lut_size - 1);
> > +
> > + I915_WRITE(PRE_CSC_GAMC_DATA(pipe), v);
> > + }
>
> As above, I think we should still fill in the last two entries with
> linear values for now.
>
> > + }
> > +
> > + tmp = I915_READ(GAMMA_MODE(pipe));
> > + I915_WRITE(GAMMA_MODE(pipe), tmp | PRE_CSC_GAMMA_ENABLE);
> > +
> > + /* Clamp values > 1.0. */
> > + while (i++ < 35)
> > + I915_WRITE(PRE_CSC_GAMC_DATA(pipe), (1 << 16));
> > +}
> > +
> > static void glk_load_luts(struct drm_crtc_state *state)
> > {
> > struct drm_crtc *crtc = state->crtc;
> > @@ -606,6 +656,28 @@ static void cherryview_load_luts(struct drm_crtc_state *state)
> > i9xx_load_luts_internal(crtc, NULL, to_intel_crtc_state(state));
> > }
> >
> > +static void icl_load_luts(struct drm_crtc_state *state)
> > +{
> > + struct drm_crtc *crtc = state->crtc;
> > + struct drm_device *dev = crtc->dev;
> > + struct drm_i915_private *dev_priv = to_i915(dev);
> > + struct intel_crtc_state *intel_state = to_intel_crtc_state(state);
> > + enum pipe pipe = to_intel_crtc(crtc)->pipe;
> > +
> > + icl_load_degamma_lut(state);
> > +
> > + if (crtc_state_is_legacy_gamma(state)) {
> > + haswell_load_luts(state);
> > + return;
> > + }
>
> This block will only run if there's no degamma LUT, so it might be
> slightly easier to read the code if we move this above the
> icl_load_degamma_lut() call above?
>
> > +
> > + bdw_load_gamma_lut(state, 0);
> > + intel_state->gamma_mode = GAMMA_MODE_MODE_10BIT;
>
> I think we also need to update PAL_EXT_GC_MAX with a FP3.16 for the 3.0
> input value and the PAL_EXT2_GC_MAX for the 7.0 input. Assuming we want
> to leave the ABI details of this until later, I assume we'd handle this
> with linear values like I suggested for the degamma extended range
> entries?
>
>
> Matt
>
> > +
> > + I915_WRITE(GAMMA_MODE(pipe), I915_READ(GAMMA_MODE(pipe)) |
> > + intel_state->gamma_mode);
> > +}
> > +
> > void intel_color_load_luts(struct drm_crtc_state *crtc_state)
> > {
> > struct drm_device *dev = crtc_state->crtc->dev;
> > @@ -662,6 +734,8 @@ void intel_color_init(struct drm_crtc *crtc)
> > } else if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) {
> > dev_priv->display.load_csc_matrix = ilk_load_csc_matrix;
> > dev_priv->display.load_luts = glk_load_luts;
> > + } else if (IS_ICELAKE(dev_priv)) {
> > + dev_priv->display.load_luts = icl_load_luts;
> > } else {
> > dev_priv->display.load_luts = i9xx_load_luts;
> > }
> > --
> > 1.9.1
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
More information about the Intel-gfx
mailing list