On Thu, 28 Mar 2019, Swati Sharma <swati2.sharma@xxxxxxxxx> wrote: > Added state checker to validate gamma_lut values. This > reads hardware state, and compares the originally requested > state to the state read from hardware. > > v1: -Implementation done for legacy platforms (removed all the placeholders) (Jani) > -Added inverse function of drm_color_lut_extract to convert hardware > read values back to user values (code written by Jani) > -Renamed get_config() to color_config() (Jani) > -Placed all platform specific shifts and masks in i915_reg.h (Jani) > -Renamed i9xx_get_config to i9xx_color_config and all related > functions (Jani) > -Removed debug logs from compare function (Jani) > -Renamed intel_compare_blob to intel_compare_lut and added platform specific > bit precision of the readout into the function (Jani) > -Renamed macro PIPE_CONF_CHECK_BLOB to PIPE_CONF_CHECK_COLOR_LUT (Jani) > -Added check if blobs can be NULL (Jani) > -Added function in intel_color.c that returns the bit precision (Jani), > didn't add in device info since its gonna die soon (Ville) > > TODO: > -Add a separate function to log errors at the higher level Should be a separate follow-up patch. > -Haven't moved intel_compare_lut() from intel_display.c to intel_color.c > Since all the comparison functions are placed in intel_display, isn't > it the right place (or) we want to move to consolidate color related functions > together? Opinion? Please correct me if I am wrong. Consolidate color to intel_color.c, as all the info about the blob and its use is there. > -Optimizations and refractoring > > Signed-off-by: Swati Sharma <swati2.sharma@xxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_drv.h | 1 + > drivers/gpu/drm/i915/i915_reg.h | 12 +++ > drivers/gpu/drm/i915/intel_color.c | 186 +++++++++++++++++++++++++++++++++-- > drivers/gpu/drm/i915/intel_display.c | 48 +++++++++ > drivers/gpu/drm/i915/intel_drv.h | 2 + > 5 files changed, 243 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index c4ffe19..b422ea6 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -334,6 +334,7 @@ struct drm_i915_display_funcs { > * involved with the same commit. > */ > void (*load_luts)(const struct intel_crtc_state *crtc_state); > + void (*color_config)(struct intel_crtc_state *crtc_state); Please call this *get* config. Same for the platform specific functions. It doesn't configure, it reads the configuration. > }; > > #define CSR_VERSION(major, minor) ((major) << 16 | (minor)) > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index c0cd7a8..2813033 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -7156,6 +7156,10 @@ enum { > #define _LGC_PALETTE_B 0x4a800 > #define LGC_PALETTE(pipe, i) _MMIO(_PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) + (i) * 4) > No blank line here. Ditto for the other groups. > +#define LGC_PALETTE_RED_MASK (0xFF << 16) > +#define LGC_PALETTE_GREEN_MASK (0xFF << 8) > +#define LGC_PALETTE_BLUE_MASK (0xFF << 0) Please indent according to the comment at the top of the file. Please define these using the new REG_GENMASK() and use the REG_FIELD_PREP() and REG_FIELD_GET() macros in code. Ditto for the other groups. > + > #define _GAMMA_MODE_A 0x4a480 > #define _GAMMA_MODE_B 0x4ac80 > #define GAMMA_MODE(pipe) _MMIO_PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B) > @@ -10102,6 +10106,10 @@ enum skl_power_gate { > #define PRE_CSC_GAMC_INDEX(pipe) _MMIO_PIPE(pipe, _PRE_CSC_GAMC_INDEX_A, _PRE_CSC_GAMC_INDEX_B) > #define PRE_CSC_GAMC_DATA(pipe) _MMIO_PIPE(pipe, _PRE_CSC_GAMC_DATA_A, _PRE_CSC_GAMC_DATA_B) > > +#define PREC_PAL_DATA_RED_MASK (0x3FF << 20) > +#define PREC_PAL_DATA_GREEN_MASK (0x3FF << 10) > +#define PREC_PAL_DATA_BLUE_MASK (0x3FF << 0) > + > /* pipe CSC & degamma/gamma LUTs on CHV */ > #define _CGM_PIPE_A_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x67900) > #define _CGM_PIPE_A_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x67904) > @@ -10133,6 +10141,10 @@ enum skl_power_gate { > #define CGM_PIPE_GAMMA(pipe, i, w) _MMIO(_PIPE(pipe, _CGM_PIPE_A_GAMMA, _CGM_PIPE_B_GAMMA) + (i) * 8 + (w) * 4) > #define CGM_PIPE_MODE(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_MODE, _CGM_PIPE_B_MODE) > > +#define CGM_PIPE_GAMMA_RED_MASK (0x3FF << 0) > +#define CGM_PIPE_GAMMA_GREEN_MASK (0x3FF << 16) > +#define CGM_PIPE_GAMMA_BLUE_MASK (0x3FF << 0) > + > /* MIPI DSI registers */ > > #define _MIPI_PORT(port, a, c) (((port) == PORT_A) ? a : c) /* ports A and C only */ > diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c > index da7a07d..bd4f1b1 100644 > --- a/drivers/gpu/drm/i915/intel_color.c > +++ b/drivers/gpu/drm/i915/intel_color.c > @@ -679,6 +679,172 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state) > dev_priv->display.load_luts(crtc_state); > } > > +u32 intel_color_bit_precision(struct drm_i915_private *dev_priv) > +{ > + if (INTEL_GEN(dev_priv) >= 9) > + return 10; > + else > + return 8; > +} Can be made static if the comparison function is moved here. > + > +/* convert hw value with given bit_precision to lut property val */ > +static u32 intel_color_lut_pack(u32 val, u32 bit_precision) > +{ > + u32 max = 0xFFFF >> (16 - bit_precision); > + > + val = clamp_val(val, 0, max); > + > + if (bit_precision < 16) > + val <<= 16 - bit_precision; > + > + return val; > +} > + > +static void i9xx_internal_gamma_config(struct intel_crtc_state *crtc_state) "get" missing in name, same throughout. > +{ > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); > + struct drm_device *dev = crtc->base.dev; > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + u32 i, tmp; > + enum pipe pipe = crtc->pipe; > + struct drm_property_blob *blob = NULL; > + struct drm_color_lut *blob_data; > + > + blob = drm_property_create_blob(dev, > + sizeof(struct drm_color_lut) * 256, > + NULL); > + if (IS_ERR(blob)) > + return; > + > + blob_data = blob->data; > + > + for (i = 0; i < 256; i++) { > + if (HAS_GMCH(dev_priv)) > + tmp = I915_READ(PALETTE(pipe, i)); > + else > + tmp = I915_READ(LGC_PALETTE(pipe, i)); > + blob_data[i].red = intel_color_lut_pack((tmp & LGC_PALETTE_RED_MASK) >> 16, 8); > + blob_data[i].green = intel_color_lut_pack((tmp & LGC_PALETTE_GREEN_MASK) >> 8, 8); > + blob_data[i].blue = intel_color_lut_pack((tmp & LGC_PALETTE_BLUE_MASK), 8); Please use REG_FIELD_GET(). Same throughout. > + } > + > + crtc_state->base.gamma_lut = blob; > +} > + > +static void i9xx_color_config(struct intel_crtc_state *crtc_state) > +{ > + i9xx_internal_gamma_config(crtc_state); > +} > + > +static void cherryview_gamma_config(struct intel_crtc_state *crtc_state) > +{ > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); > + struct drm_device *dev = crtc->base.dev; > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + u32 i, tmp, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; > + enum pipe pipe = crtc->pipe; > + struct drm_property_blob *blob = NULL; > + struct drm_color_lut *blob_data; > + > + blob = drm_property_create_blob(dev, > + sizeof(struct drm_color_lut) * 256, > + NULL); > + if (IS_ERR(blob)) > + return; > + > + blob_data = blob->data; > + > + for (i = 0; i < lut_size; i++) { > + tmp = I915_READ(CGM_PIPE_GAMMA(pipe, i, 0)); > + blob_data[i].green = intel_color_lut_pack((tmp & CGM_PIPE_GAMMA_GREEN_MASK) >> 16, 10); > + blob_data[i].blue = intel_color_lut_pack((tmp & CGM_PIPE_GAMMA_BLUE_MASK), 10); > + tmp = I915_READ(CGM_PIPE_GAMMA(pipe, i, 1)); > + blob_data[i].red = intel_color_lut_pack((tmp & CGM_PIPE_GAMMA_RED_MASK), 10); > + } > + > + crtc_state->base.gamma_lut = blob; > +} > + > +static void bdw_gamma_config(struct intel_crtc_state *crtc_state, u32 offset) > +{ > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); > + struct drm_device *dev = crtc->base.dev; > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + u32 i, tmp, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; > + enum pipe pipe = crtc->pipe; > + struct drm_property_blob *blob = NULL; > + struct drm_color_lut *blob_data; > + > + WARN_ON(offset & ~PAL_PREC_INDEX_VALUE_MASK); > + > + I915_WRITE(PREC_PAL_INDEX(pipe), > + (offset ? PAL_PREC_SPLIT_MODE : 0) | > + PAL_PREC_AUTO_INCREMENT | > + offset); > + > + blob = drm_property_create_blob(dev, > + sizeof(struct drm_color_lut) * lut_size, > + NULL); > + if (IS_ERR(blob)) > + return; > + > + blob_data = blob->data; > + > + for (i = 0; i < lut_size; i++) { > + tmp = I915_READ(PREC_PAL_DATA(pipe)); > + blob_data[i].red = intel_color_lut_pack((tmp & PREC_PAL_DATA_RED_MASK) >> 20, 10); > + blob_data[i].green = intel_color_lut_pack((tmp & PREC_PAL_DATA_GREEN_MASK) >> 10, 10); > + blob_data[i].blue = intel_color_lut_pack((tmp & PREC_PAL_DATA_BLUE_MASK), 10); > + } > + > + I915_WRITE(PREC_PAL_INDEX(pipe), 0); > + > + crtc_state->base.gamma_lut = blob; > +} > + > +static void cherryview_color_config(struct intel_crtc_state *crtc_state) > +{ > + if (crtc_state_is_legacy_gamma(crtc_state)) > + i9xx_color_config(crtc_state); > + else > + cherryview_gamma_config(crtc_state); > +} > + > +static void broadwell_color_config(struct intel_crtc_state *crtc_state) > +{ > + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); > + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); > + > + if (crtc_state_is_legacy_gamma(crtc_state)) > + i9xx_color_config(crtc_state); > + else > + bdw_gamma_config(crtc_state, > + INTEL_INFO(dev_priv)->color.degamma_lut_size); > +} > + > +static void glk_color_config(struct intel_crtc_state *crtc_state) > +{ > + if (crtc_state_is_legacy_gamma(crtc_state)) > + i9xx_color_config(crtc_state); > + else > + bdw_gamma_config(crtc_state, 0); > +} > + > +static void icl_color_config(struct intel_crtc_state *crtc_state) > +{ > + if (crtc_state_is_legacy_gamma(crtc_state)) > + i9xx_color_config(crtc_state); > + else > + bdw_gamma_config(crtc_state, 0); > +} > + > +void intel_color_config(struct intel_crtc_state *crtc_state) > +{ > + struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); > + > + dev_priv->display.color_config(crtc_state); > +} > + > void intel_color_commit(const struct intel_crtc_state *crtc_state) > { > struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); > @@ -834,21 +1000,29 @@ void intel_color_init(struct intel_crtc *crtc) > drm_mode_crtc_set_gamma_size(&crtc->base, 256); > > if (HAS_GMCH(dev_priv)) { > - if (IS_CHERRYVIEW(dev_priv)) > + if (IS_CHERRYVIEW(dev_priv)) { > dev_priv->display.load_luts = cherryview_load_luts; > - else > + dev_priv->display.color_config = cherryview_color_config; > + } else { > dev_priv->display.load_luts = i9xx_load_luts; > + dev_priv->display.color_config = i9xx_color_config; > + } > > dev_priv->display.color_commit = i9xx_color_commit; > } else { > - if (IS_ICELAKE(dev_priv)) > + if (IS_ICELAKE(dev_priv)) { > dev_priv->display.load_luts = icl_load_luts; > - else if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) > + dev_priv->display.color_config = icl_color_config; > + } else if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) { > dev_priv->display.load_luts = glk_load_luts; > - else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) > + dev_priv->display.color_config = glk_color_config; > + } else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) { > dev_priv->display.load_luts = broadwell_load_luts; > - else > + dev_priv->display.color_config = broadwell_color_config; > + } else { > dev_priv->display.load_luts = i9xx_load_luts; > + dev_priv->display.color_config = i9xx_color_config; > + } > > if (INTEL_GEN(dev_priv) >= 9) > dev_priv->display.color_commit = skl_color_commit; > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 963b4bd..31bb652 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -8212,6 +8212,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, > > i9xx_get_pipe_color_config(pipe_config); > > + intel_color_config(pipe_config); > + > if (INTEL_GEN(dev_priv) < 4) > pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE; > > @@ -9284,6 +9286,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, > > i9xx_get_pipe_color_config(pipe_config); > > + intel_color_config(pipe_config); > + > if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { > struct intel_shared_dpll *pll; > enum intel_dpll_id pll_id; > @@ -9932,6 +9936,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, > i9xx_get_pipe_color_config(pipe_config); > } > > + intel_color_config(pipe_config); > + > power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe); > if (intel_display_power_get_if_enabled(dev_priv, power_domain)) { > WARN_ON(power_domain_mask & BIT_ULL(power_domain)); > @@ -11990,6 +11996,36 @@ static bool fastboot_enabled(struct drm_i915_private *dev_priv) > return false; > } > > +static bool intel_compare_color_lut(struct drm_property_blob *blob1, > + struct drm_property_blob *blob2, > + u32 bit_precision) > +{ > + struct drm_color_lut *sw_lut = blob1->data; > + struct drm_color_lut *hw_lut = blob2->data; > + u32 err = 0xFFFF >> bit_precision; > + int sw_lut_size, hw_lut_size; > + int i; > + > + sw_lut_size = drm_color_lut_size(blob1); > + hw_lut_size = drm_color_lut_size(blob2); > + > + if (IS_ERR(blob1) || IS_ERR(blob2)) > + return false; Mmmh, if this condition is true, we've oopsed on drm_color_lut_size() already. > + > + if (sw_lut_size != hw_lut_size) > + return false; > + > + for (i = 0; i < sw_lut_size; i++) { > + if (((abs((long)hw_lut[i].red - sw_lut[i].red)) >= err) || > + ((abs((long)hw_lut[i].blue - sw_lut[i].blue)) >= err) || > + ((abs((long)hw_lut[i].green - sw_lut[i].green)) >= err)) { I think using an inline function for the comparison with err slack would be nice. > + return false; > + } > + } > + > + return true; > +} I think separate the get config part from the state checker part to another patch. I think move this function to intel_color.c, as intel_display.c is already overcrowded. Pass dev_priv to it so it can handle bit precision internally instead, and you can make intel_color_bit_precision() static. (Or just inline that in the function.) > + > static bool > intel_pipe_config_compare(struct drm_i915_private *dev_priv, > struct intel_crtc_state *current_config, > @@ -11997,6 +12033,7 @@ static bool fastboot_enabled(struct drm_i915_private *dev_priv) > bool adjust) > { > bool ret = true; > + u32 bit_precision; > bool fixup_inherited = adjust && > (current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) && > !(pipe_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED); > @@ -12148,6 +12185,14 @@ static bool fastboot_enabled(struct drm_i915_private *dev_priv) > } \ > } while (0) > > +#define PIPE_CONF_CHECK_COLOR_LUT(name, bit_precision) do { \ > + if (!intel_compare_color_lut(current_config->name, pipe_config->name, bit_precision)) { \ > + pipe_config_err(adjust, __stringify(name), \ > + "hw_state doesn't match sw_state\n"); \ > + ret = false; \ > + } \ > +} while (0) > + > #define PIPE_CONF_QUIRK(quirk) \ > ((current_config->quirks | pipe_config->quirks) & (quirk)) > > @@ -12287,6 +12332,9 @@ static bool fastboot_enabled(struct drm_i915_private *dev_priv) > PIPE_CONF_CHECK_INFOFRAME(spd); > PIPE_CONF_CHECK_INFOFRAME(hdmi); > > + bit_precision = intel_color_bit_precision(dev_priv); > + PIPE_CONF_CHECK_COLOR_LUT(base.gamma_lut, bit_precision); > + > #undef PIPE_CONF_CHECK_X > #undef PIPE_CONF_CHECK_I > #undef PIPE_CONF_CHECK_BOOL > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index 40ebc94..6a89d2d 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -2512,6 +2512,8 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ > int intel_color_check(struct intel_crtc_state *crtc_state); > void intel_color_commit(const struct intel_crtc_state *crtc_state); > void intel_color_load_luts(const struct intel_crtc_state *crtc_state); > +void intel_color_config(struct intel_crtc_state *crtc_state); > +u32 intel_color_bit_precision(struct drm_i915_private *dev_priv); > > /* intel_lspcon.c */ > bool lspcon_init(struct intel_digital_port *intel_dig_port); -- Jani Nikula, Intel Open Source Graphics Center _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx