[Intel-gfx] [PATCH 1/3] drm/i915/icl: Add icl pipe degamma and gamma support
Shankar, Uma
uma.shankar at intel.com
Thu Nov 1 19:07:30 UTC 2018
>-----Original Message-----
>From: Roper, Matthew D
>Sent: Thursday, November 1, 2018 5:10 AM
>To: Shankar, Uma <uma.shankar at intel.com>
>Cc: intel-gfx at lists.freedesktop.org; Syrjala, Ville <ville.syrjala at intel.com>;
>Lankhorst, Maarten <maarten.lankhorst at intel.com>
>Subject: Re: [Intel-gfx] [PATCH 1/3] drm/i915/icl: Add icl pipe degamma and
>gamma support
>
>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).
Ok, will modify this.
>> > + 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.
Sure, will do it in similar way.
>> > }
>> >
>> > /* 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?
Yes, this hardcoding can be dropped from here.
>> Actually, upon closer inspection it looks like LUT size, ranges, etc.
>> is sort of complicated; more comments farther down.
Yeah, with the introduction of multi segmented gamma this is really
not straight forward. Current implementation just handle things without
multi segmented gamma. I will add support of multi segmented gamma
and introduce some kind of tuples (set of 3 or 4 struct elements to define
a segment). Ville has given some ideas on the same.
>>
>> > + 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.
Yes, this is my understanding as well. So, when we need to reprogram the
LUT, take index to 0 and set auto increment. This is working and all the
LUT values get programmed correctly.
>> > + 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.
Yes, you are right. I will add bit more explanation here though, to avoid
ambiguity and give more clarity.
>> > + 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.
Yes, the 34th and 35the entry is programmed to clamp at 1.0.
>
>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?
I believe current userspace just goes for 1.0. Yes, we can extend and add and
extended mode as well to deal with these 7.0 ranges. I will try to create some
kind of design and send a RFC for input to handle multi segment as well as such
extended range inputs. Will try to catch Ville as well for his inputs :)
>> > + } 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.
This is ok and taken care as mentioned above.
>> > + }
>> > +
>> > + 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?
Sure, I will do that.
>> > +
>> > + 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?
As mentioned above, will try to create some RFC for review to handle extended ranges.
Thanks Matt for your review and valuable comments.
Regards,
Uma Shankar
>>
>> 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