Hi, On 17 December 2015 at 18:57, Lionel Landwerlin <lionel.g.landwerlin@xxxxxxxxx> wrote: > @@ -289,22 +289,30 @@ static const struct intel_device_info intel_haswell_m_info = { > static const struct intel_device_info intel_broadwell_d_info = { > HSW_FEATURES, > .gen = 8, > + .num_samples_after_ctm = BDW_SPLITGAMMA_MAX_VALS, > + .num_samples_before_ctm = BDW_DEGAMMA_MAX_VALS, > }; Nitpick I know, but please invert before and after for the sake of my sanity. > +static void bdw_write_8bit_gamma_legacy(struct drm_device *dev, > + struct drm_r32g32b32 *correction_values, i915_reg_t palette) > +{ > + u16 blue_fract, green_fract, red_fract; > + u32 blue, green, red; > + u32 count = 0; > + u32 word = 0; > + struct drm_i915_private *dev_priv = dev->dev_private; > + > + while (count < BDW_8BIT_GAMMA_MAX_VALS) { > + blue = correction_values[count].b32; > + green = correction_values[count].g32; > + red = correction_values[count].r32; > + > + /* > + * Maximum possible gamma correction value supported > + * for BDW is 0xFFFFFFFF, so clamp the values accordingly > + */ Eh? 0xFFFFFFFF != (1 << 24) - 1. > + if (blue >= BDW_MAX_GAMMA) > + blue = BDW_MAX_GAMMA; > + if (green >= BDW_MAX_GAMMA) > + green = BDW_MAX_GAMMA; > + if (red >= BDW_MAX_GAMMA) > + red = BDW_MAX_GAMMA; > rather than >=. > + /* > + * Gamma correction values are sent in 8.24 format > + * with 8 int and 24 fraction bits. BDW 10 bit gamma > + * unit expects correction registers to be programmed in > + * 0.10 format, with 0 int and 16 fraction bits. So take '0.10 format, with 0 int and 16 fraction bits' ... > + * MSB 10 bit values(bits 23-14) from the fraction part and > + * prepare the correction registers. > + */ The comment here is helpful, but colour me confused: we just discard the 8 integer bits anyway? Why do they exist? Every time I think I've worked out which of [0,1.0] and [0,8.0) is the correct range, I realise I'm wrong. > +static void bdw_write_12bit_gamma_precision(struct drm_device *dev, > + struct drm_r32g32b32 *correction_values, i915_reg_t pal_prec_data, > + enum pipe pipe) Why does this take a pipe where all the others don't, and also not take a num_coeff, also unlike the others? > + /* Program first 512 values in precision palette */ > + while (count < BDW_12BIT_GAMMA_MAX_VALS - 1) { Um, this is a for loop. > + /* > + * Maximum possible gamma correction value supported > + * for BDW is 0xFFFFFFFF, so clamp the values accordingly > + */ Again, not 0xffffffff. > + /* > + * Framework's general gamma format is 8.24 (8 int 16 fraction) 8 int 16?! > + * BDW Platform's supported gamma format is 16 bit correction > + * values in 0.16 format. So extract higher 16 fraction bits > + * from 8.24 gamma correction values. Isn't this the 12-bit mode? Colour me stupid, but what makes this 12-bit rather than 16-bit? Anyway. > + */ > + red_fract = GET_BITS(red, 8, 16); > + green_fract = GET_BITS(green, 8, 16); > + blue_fract = GET_BITS(blue, 8, 16); Okay, at least the range is consistent here - still [0,1.0], with the integer component totally ignored. > + gamma_data = (struct drm_palette *)blob->data; > + pipe = to_intel_crtc(crtc)->pipe; > + num_samples = blob->length / sizeof(struct drm_r32g32b32); > + > + pal_prec_index = _MMIO(_PREC_PAL_INDEX(pipe)); > + pal_prec_data = _MMIO(_PREC_PAL_DATA(pipe)); > + correction_values = (struct drm_r32g32b32 *)&gamma_data->lut; > + > + switch (num_samples) { > + case GAMMA_DISABLE_VALS: > + /* Disable Gamma functionality on Pipe */ > + DRM_DEBUG_DRIVER("Disabling gamma on Pipe %c\n", > + pipe_name(pipe)); > + if ((mode & GAMMA_MODE_MODE_MASK) == GAMMA_MODE_MODE_12BIT) > + bdw_reset_gamma(dev_priv, pipe); > + state->palette_after_ctm_blob = NULL; > + word = GAMMA_MODE_MODE_8BIT; > + break; Right, so we program the gamma unit to 8-bit mode (sensible!), and write a linear palette (sensible!) ... but only if we were previously in 12-bit gamma mode. What? So, if I start with 10-bit gamma and then disable the gamma unit, my gamma won't be disabled, but will be an 8-bit interpretation of the previous 10-bit gamma ramp? Ouch. Also broken when going from 8-bit -> disabled. Surely just make that check unconditional. (Again, this should also be blob == NULL, not a blob with length 0 which is subsequently leaked. Wait, how do you even create a length-0 blob ... ?!) > + case BDW_8BIT_GAMMA_MAX_VALS: > + /* Legacy palette */ > + bdw_write_8bit_gamma_legacy(dev, correction_values, > + LGC_PALETTE(pipe, 0)); > + word = GAMMA_MODE_MODE_8BIT; > + break; > + > + case BDW_SPLITGAMMA_MAX_VALS: > + index = num_samples; > + index |= BDW_INDEX_AUTO_INCREMENT | BDW_INDEX_SPLIT_MODE; > + I915_WRITE(pal_prec_index, index); > + bdw_write_10bit_gamma_precision(dev, correction_values, > + pal_prec_data, BDW_SPLITGAMMA_MAX_VALS); > + word = GAMMA_MODE_MODE_SPLIT; > + break; > + > + case BDW_12BIT_GAMMA_MAX_VALS: > + index = BDW_INDEX_AUTO_INCREMENT; > + I915_WRITE(pal_prec_index, index); > + bdw_write_12bit_gamma_precision(dev, correction_values, > + pal_prec_data, pipe); > + word = GAMMA_MODE_MODE_12BIT; > + break; > + > + case BDW_10BIT_GAMMA_MAX_VALS: > + index = BDW_INDEX_AUTO_INCREMENT; > + I915_WRITE(pal_prec_index, index); > + bdw_write_10bit_gamma_precision(dev, correction_values, > + pal_prec_data, BDW_10BIT_GAMMA_MAX_VALS); > + word = GAMMA_MODE_MODE_10BIT; > + break; This is pretty upsetting; we appear to have: - 8-bit gamma: length 256 on BDW and CHV (consistency! but CHV seems to just use 10-bit anyway) - 10-bit gamma: length 257 on CHV, 1024 on BDW (or 512 for split) - 12-bit gamma: length 513 on BDW How is generic userspace supposed to determine this? We will never have these kinds of per-device lookup tables. Using semi-arbitrary length values to determine this is absolutely the wrong approach. How about exposing it through properties? Maybe declare PALETTE_AFTER_CTM_8BIT (hardcoded to 256), PALETTE_AFTER_CTM_10BIT, etc, with the lengths required? Or maybe an array of values, sorted in ascending order of entry depth (i.e. [ 8BIT_LENGTH, 10BIT_LENGTH, 12BIT_LENGTH ]). Is split-gamma mode actually bound to 10-bit (and that table length) only, or is it independent of mode? I don't really know what to suggest about that one. > + switch (num_samples) { > + case GAMMA_DISABLE_VALS: > + /* Disable degamma on Pipe */ > + mode = I915_READ(GAMMA_MODE(pipe)) & ~GAMMA_MODE_MODE_MASK; > + I915_WRITE(GAMMA_MODE(pipe), mode | GAMMA_MODE_MODE_8BIT); Why aren't these writes coalesced as they are in bdw_set_gamma? > + state->palette_before_ctm_blob = NULL; > + DRM_DEBUG_DRIVER("Disabling degamma on Pipe %c\n", > + pipe_name(pipe)); > + break; blob == NULL. > + case BDW_SPLITGAMMA_MAX_VALS: > + pal_prec_index = _MMIO(_PREC_PAL_INDEX(pipe)); > + pal_prec_data = _MMIO(_PREC_PAL_DATA(pipe)); > + correction_values = degamma_data->lut; > + > + index = BDW_INDEX_AUTO_INCREMENT | BDW_INDEX_SPLIT_MODE; > + I915_WRITE(pal_prec_index, index); > + > + bdw_write_10bit_gamma_precision(dev, > + correction_values, > + pal_prec_data, > + BDW_SPLITGAMMA_MAX_VALS); > + > + /* Enable degamma on Pipe */ > + mode = I915_READ(GAMMA_MODE(pipe)); > + mode &= ~GAMMA_MODE_MODE_MASK; > + I915_WRITE(GAMMA_MODE(pipe), mode | GAMMA_MODE_MODE_SPLIT); > + DRM_DEBUG_DRIVER("degamma correction enabled on Pipe %c\n", > + pipe_name(pipe)); > + break; Ouch, so it's 8-bit or split, nothing else. Again, that's going to be pretty hard for generic userspace to figure out. > +static uint32_t bdw_prepare_csc_coeff(int64_t coeff) CHV is using s64 rather than int64_t here. > +#define BDW_MAX_GAMMA ((1 << 24) - 1) Well, at least this is consistent with CHV. Cheers, Daniel _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx