Message ID | 1450378678-24296-5-git-send-email-lionel.g.landwerlin@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi, On 17 December 2015 at 18:57, Lionel Landwerlin <lionel.g.landwerlin@intel.com> wrote: > @@ -311,7 +312,9 @@ static const struct intel_device_info intel_cherryview_info = { > .gen = 8, .num_pipes = 3, > .need_gfx_hws = 1, .has_hotplug = 1, > .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, > - .is_cherryview = 1, > + .is_valleyview = 1, ... ?! > + .num_samples_after_ctm = CHV_10BIT_GAMMA_MAX_VALS, > + .num_samples_before_ctm = CHV_DEGAMMA_MAX_VALS, Switch the order of these please. > +static u16 chv_prepare_csc_coeff(s64 csc_coeff) > +{ > + u16 csc_s3_12_format = 0; > + u16 csc_int_value; > + u16 csc_fract_value; > + > + if (csc_coeff < 0) > + csc_s3_12_format = CSC_COEFF_SIGN; > + csc_coeff = abs(csc_coeff); > + csc_coeff += CHV_CSC_FRACT_ROUNDOFF; > + if (csc_coeff > CHV_CSC_COEFF_MAX + 1) > + csc_coeff = CHV_CSC_COEFF_MAX + 1; > + else if (csc_coeff > CHV_CSC_COEFF_MAX) > + csc_coeff = CHV_CSC_COEFF_MAX; > + > + csc_int_value = csc_coeff >> CHV_CSC_COEFF_SHIFT; > + csc_int_value <<= CHV_CSC_COEFF_INT_SHIFT; > + > + csc_fract_value = csc_coeff >> CHV_CSC_COEFF_FRACT_SHIFT; > + > + csc_s3_12_format |= csc_int_value | csc_fract_value; Um. I'm at a loss trying to disentangle these. Here, (1 << 15) / 0x8000 is used as the sign bit; fair enough. But, anything above 0x7ffffffff generates 0x8000 as a result, which s3.12 would lead me to read as -7.999...; 0x7ffffffff itself generates +7.999.... So huge positive numbers wrap around into your minimum signed value. Is this deliberate? Is it covered by IGT? > +static int chv_set_csc(struct drm_device *dev, struct drm_property_blob *blob, > + struct drm_crtc *crtc) > +{ > + u16 temp; > + u32 word = 0; > + int count = 0; > + i915_reg_t val; > + struct drm_ctm *csc_data; > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe; > + > + if (WARN_ON(!blob)) > + return -EINVAL; Why not let blob == NULL just disable CSC here? (How do you even disable it?) > + if (blob->length != sizeof(struct drm_ctm)) { > + DRM_ERROR("Invalid length of data received\n"); > + return -EINVAL; > + } This needs to be checked earlier (in the atomic_set_property hook): failing commit is not OK. > +static int chv_set_degamma(struct drm_device *dev, > + struct drm_property_blob *blob, struct drm_crtc *crtc) What I said about the documentation around post-CTM vs. degamma makes even more sense now. ;) > +{ > + u16 red_fract, green_fract, blue_fract; > + u32 red, green, blue; > + u32 num_samples; > + u32 word = 0; > + u32 count, cgm_control, cgm_degamma_reg; > + i915_reg_t val; > + enum pipe pipe; > + struct drm_palette *degamma_data; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct drm_r32g32b32 *correction_values = NULL; > + struct drm_crtc_state *state = crtc->state; > + > + if (WARN_ON(!blob)) > + return -EINVAL; Same comment as above. > + degamma_data = (struct drm_palette *)blob->data; > + pipe = to_intel_crtc(crtc)->pipe; > + num_samples = blob->length / sizeof(struct drm_r32g32b32); > + > + switch (num_samples) { > + case GAMMA_DISABLE_VALS: > + /* Disable DeGamma functionality on Pipe - CGM Block */ Just use blob == NULL for this. > + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); > + cgm_control = I915_READ(val); > + cgm_control &= ~CGM_DEGAMMA_EN; > + state->palette_before_ctm_blob = NULL; This is really broken. In order to disable, you create a blob with len == 0, which instantly drops itself without unreferencing, i.e. no leak. Also, I thought RMW of registers was frowned upon? Maybe not. > + default: > + DRM_ERROR("Invalid number of samples for DeGamma LUT\n"); > + return -EINVAL; > + } This could just become another early-exit path. But again, this needs to be checked in, well, atomic_check, not commit. > +static int chv_set_gamma(struct drm_device *dev, struct drm_property_blob *blob, > + struct drm_crtc *crtc) > +{ > + enum pipe pipe; > + u16 red_fract, green_fract, blue_fract; > + u32 red, green, blue, num_samples; > + u32 word = 0; > + u32 count, cgm_gamma_reg, cgm_control; > + i915_reg_t val; > + struct drm_r32g32b32 *correction_values; > + struct drm_palette *gamma_data; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct drm_crtc_state *state = crtc->state; > + > + if (WARN_ON(!blob)) > + return -EINVAL; As above. > + switch (num_samples) { > + case GAMMA_DISABLE_VALS: Ditto. > + /* Disable Gamma functionality on Pipe - CGM Block */ > + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); > + cgm_control = I915_READ(val); > + cgm_control &= ~CGM_GAMMA_EN; > + I915_WRITE(val, cgm_control); > + state->palette_after_ctm_blob = NULL; AOL. > + case CHV_8BIT_GAMMA_MAX_VALS: > + case CHV_10BIT_GAMMA_MAX_VALS: Hm. At no point does the following code account for the difference between these two. What happens if you set once with 10BIT_GAMMA_MAX_VALS followed by once with 8BIT_MAX_VALS? Won't that break expectation of the second user, because you never wrote to the 257th entry? Also, this just reads 10 bits out of the values regardless. Has 8-bit been tested on CHV? It seems like it'd be totally broken, as this just assumes a 10-bit range regardless. > + default: > + DRM_ERROR("Invalid number of samples (%u) for Gamma LUT\n", > + num_samples); > + return -EINVAL; > + } See previous. > +void intel_color_manager_commit(struct drm_device *dev, > + struct drm_crtc_state *crtc_state) > +{ > + struct drm_property_blob *blob; > + struct drm_crtc *crtc = crtc_state->crtc; > + int ret = -EINVAL; Why is this initialised, especially when not actually used as a return value? > + blob = crtc_state->palette_after_ctm_blob; > + if (blob) { Drop the conditional and pass it through regardless, so you can use NULL to disable. > + /* Gamma correction is platform specific */ > + if (IS_CHERRYVIEW(dev)) > + ret = chv_set_gamma(dev, blob, crtc); > + > + if (ret) > + DRM_ERROR("set Gamma correction failed\n"); > + else > + DRM_DEBUG_DRIVER("Gamma correction success\n"); > + } So we just error but carry on? Again, this (and all the following) need to be in check, not commit. And you can just drop the 'success' message. > +void intel_crtc_attach_color_properties(struct drm_crtc *crtc) > +{ > +} ... ? > +/* Color management bit utilities */ > +#define GET_BIT_MASK(n) ((1 << n) - 1) > + > +/* Read bits of a word from bit no. 'start'(lsb) till 'n' bits */ > +#define GET_BITS(x, start, nbits) ((x >> start) & GET_BIT_MASK(nbits)) > > +/* Round off by adding 1 to the immediate lower bit */ > +#define GET_BITS_ROUNDOFF(x, start, nbits) \ > + ((GET_BITS(x, start, (nbits + 1)) + 1) >> 1) > + > +/* Clear bits of a word from bit no. 'start' till nbits */ > +#define CLEAR_BITS(x, start, nbits) ( \ > + x &= ~((GET_BIT_MASK(nbits) << start))) > + > +/* Write bit_pattern of no_bits bits in a target word */ > +#define SET_BITS(target, bit_pattern, start_bit, no_bits) \ > + do { \ > + CLEAR_BITS(target, start_bit, no_bits); \ > + target |= (bit_pattern << start_bit); \ > + } while (0) Is there actually no common set of macros for these? I would also expect to see this as lowest_bit -> highest_bit, rather than start_bit -> (start_bit -> start_bit + nbits/no_bits). > +/* CHV */ > +#define CHV_10BIT_GAMMA_MAX_VALS 257 Delete this, as it's already declared in the 'Gamma on CHV' block. > +#define CHV_DEGAMMA_MAX_VALS 65 Move this to that block. > +/* No of coeff for disabling gamma is 0 */ > +#define GAMMA_DISABLE_VALS 0 ... and delete this. > +/* Gamma on CHV */ > +#define CHV_10BIT_GAMMA_MAX_VALS 257 > +#define CHV_8BIT_GAMMA_MAX_VALS 256 > +#define CHV_10BIT_GAMMA_MSB_SHIFT 6 > +#define CHV_GAMMA_SHIFT_GREEN 16 > +#define CHV_MAX_GAMMA ((1 << 24) - 1) Shouldn't drm_palette or similar declare that the range of gamma values is [0,(1 << 24) -1], or just do some normalisation, rather than relying on people to know that CHV has a different gamma range than the type would lead you to believe? > +/* > + * CSC values are 64-bit values. For CHV, the maximum CSC value that > + * user can program is 7.99999..., which can be represented in fixed point > + * S31.32 format like this, with all fractional bits as 1 > + */ As with (de)gamma, might help to note that CSC is CTM. Also, this means that the comment I noted in the drm_ctm structure is wrong: the range really is [0..8.0) rather than [0..1.0]. > +#define CSC_MAX_VALS 9 Isn't MAX_VALS fixed at 9 everywhere ... ? > +/* Degamma on CHV */ > +#define CHV_DEGAMMA_MSB_SHIFT 2 > +#define CHV_DEGAMMA_GREEN_SHIFT 16 Slightly baffling, and also unused ... but what does it mean? Cheers, Daniel
On Thu, Dec 17, 2015 at 06:57:56PM +0000, Lionel Landwerlin wrote: > From: Shashank Sharma <shashank.sharma@intel.com> > > Implement degamma, csc and gamma steps on CHV. > > Signed-off-by: Shashank Sharma <shashank.sharma@intel.com> > Signed-off-by: Kausal Malladi <kausalmalladi@gmail.com> > --- > drivers/gpu/drm/i915/Makefile | 3 +- > drivers/gpu/drm/i915/i915_drv.c | 5 +- > drivers/gpu/drm/i915/i915_drv.h | 2 + > drivers/gpu/drm/i915/i915_reg.h | 26 +++ > drivers/gpu/drm/i915/intel_color_manager.c | 353 +++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/intel_color_manager.h | 91 ++++++++ > drivers/gpu/drm/i915/intel_display.c | 2 + > drivers/gpu/drm/i915/intel_drv.h | 4 + > 8 files changed, 484 insertions(+), 2 deletions(-) > create mode 100644 drivers/gpu/drm/i915/intel_color_manager.c > create mode 100644 drivers/gpu/drm/i915/intel_color_manager.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index 0851de07..c66d56a 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -64,7 +64,8 @@ i915-y += intel_audio.o \ > intel_overlay.o \ > intel_psr.o \ > intel_sideband.o \ > - intel_sprite.o > + intel_sprite.o \ > + intel_color_manager.o > i915-$(CONFIG_ACPI) += intel_acpi.o intel_opregion.o > i915-$(CONFIG_DRM_FBDEV_EMULATION) += intel_fbdev.o > > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c > index 3ac616d..4396300 100644 > --- a/drivers/gpu/drm/i915/i915_drv.c > +++ b/drivers/gpu/drm/i915/i915_drv.c > @@ -34,6 +34,7 @@ > #include "i915_drv.h" > #include "i915_trace.h" > #include "intel_drv.h" > +#include "intel_color_manager.h" > > #include <linux/console.h> > #include <linux/module.h> > @@ -311,7 +312,9 @@ static const struct intel_device_info intel_cherryview_info = { > .gen = 8, .num_pipes = 3, > .need_gfx_hws = 1, .has_hotplug = 1, > .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, > - .is_cherryview = 1, > + .is_valleyview = 1, > + .num_samples_after_ctm = CHV_10BIT_GAMMA_MAX_VALS, > + .num_samples_before_ctm = CHV_DEGAMMA_MAX_VALS, > .display_mmio_offset = VLV_DISPLAY_BASE, > GEN_CHV_PIPEOFFSETS, > CURSOR_OFFSETS, > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 1d28d90..4eb0fab 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -793,6 +793,8 @@ struct intel_device_info { > u8 num_sprites[I915_MAX_PIPES]; > u8 gen; > u8 ring_mask; /* Rings supported by the HW */ > + u16 num_samples_after_ctm; > + u16 num_samples_before_ctm; > DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON); > /* Register offsets for the various display pipes and transcoders */ > int pipe_offsets[I915_MAX_TRANSCODERS]; > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 007ae83..36bb320 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -8154,4 +8154,30 @@ enum skl_disp_power_wells { > #define GEN9_VEBOX_MOCS(i) _MMIO(0xcb00 + (i) * 4) /* Video MOCS registers */ > #define GEN9_BLT_MOCS(i) _MMIO(0xcc00 + (i) * 4) /* Blitter MOCS registers */ > > +/* Color Management */ > +#define PIPEA_CGM_CONTROL (VLV_DISPLAY_BASE + 0x67A00) > +#define PIPEB_CGM_CONTROL (VLV_DISPLAY_BASE + 0x69A00) > +#define PIPEC_CGM_CONTROL (VLV_DISPLAY_BASE + 0x6BA00) > +#define PIPEA_CGM_GAMMA (VLV_DISPLAY_BASE + 0x67000) > +#define PIPEB_CGM_GAMMA (VLV_DISPLAY_BASE + 0x69000) > +#define PIPEC_CGM_GAMMA (VLV_DISPLAY_BASE + 0x6B000) > +#define _PIPE_CGM_CONTROL(pipe) \ > + (_PIPE3(pipe, PIPEA_CGM_CONTROL, PIPEB_CGM_CONTROL, PIPEC_CGM_CONTROL)) > +#define _PIPE_GAMMA_BASE(pipe) \ > + (_PIPE3(pipe, PIPEA_CGM_GAMMA, PIPEB_CGM_GAMMA, PIPEC_CGM_GAMMA)) > + > +#define PIPEA_CGM_DEGAMMA (VLV_DISPLAY_BASE + 0x66000) > +#define PIPEB_CGM_DEGAMMA (VLV_DISPLAY_BASE + 0x68000) > +#define PIPEC_CGM_DEGAMMA (VLV_DISPLAY_BASE + 0x6A000) > +#define _PIPE_DEGAMMA_BASE(pipe) \ > + (_PIPE3(pipe, PIPEA_CGM_DEGAMMA, PIPEB_CGM_DEGAMMA, PIPEC_CGM_DEGAMMA)) > + > +#define PIPEA_CGM_CSC (VLV_DISPLAY_BASE + 0x67900) > +#define PIPEB_CGM_CSC (VLV_DISPLAY_BASE + 0x69900) > +#define PIPEC_CGM_CSC (VLV_DISPLAY_BASE + 0x6B900) > +#define _PIPE_CSC_BASE(pipe) \ > + (_PIPE3(pipe, PIPEA_CGM_CSC, PIPEB_CGM_CSC, PIPEC_CGM_CSC)) > + > + > + > #endif /* _I915_REG_H_ */ > diff --git a/drivers/gpu/drm/i915/intel_color_manager.c b/drivers/gpu/drm/i915/intel_color_manager.c > new file mode 100644 > index 0000000..02eee98 > --- /dev/null > +++ b/drivers/gpu/drm/i915/intel_color_manager.c > @@ -0,0 +1,353 @@ > +/* > + * Copyright © 2015 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + * Authors: > + * Shashank Sharma <shashank.sharma@intel.com> > + * Kausal Malladi <Kausal.Malladi@intel.com> > + */ > + > +#include "intel_color_manager.h" > + > +static u16 chv_prepare_csc_coeff(s64 csc_coeff) > +{ > + u16 csc_s3_12_format = 0; > + u16 csc_int_value; > + u16 csc_fract_value; > + > + if (csc_coeff < 0) > + csc_s3_12_format = CSC_COEFF_SIGN; > + csc_coeff = abs(csc_coeff); > + csc_coeff += CHV_CSC_FRACT_ROUNDOFF; > + if (csc_coeff > CHV_CSC_COEFF_MAX + 1) > + csc_coeff = CHV_CSC_COEFF_MAX + 1; > + else if (csc_coeff > CHV_CSC_COEFF_MAX) > + csc_coeff = CHV_CSC_COEFF_MAX; > + > + csc_int_value = csc_coeff >> CHV_CSC_COEFF_SHIFT; > + csc_int_value <<= CHV_CSC_COEFF_INT_SHIFT; > + > + csc_fract_value = csc_coeff >> CHV_CSC_COEFF_FRACT_SHIFT; > + > + csc_s3_12_format |= csc_int_value | csc_fract_value; > + > + return csc_s3_12_format; > +} > + > +static int chv_set_csc(struct drm_device *dev, struct drm_property_blob *blob, > + struct drm_crtc *crtc) > +{ > + u16 temp; > + u32 word = 0; > + int count = 0; > + i915_reg_t val; > + struct drm_ctm *csc_data; > + struct drm_i915_private *dev_priv = dev->dev_private; > + enum pipe pipe; > + > + if (WARN_ON(!blob)) > + return -EINVAL; > + > + if (blob->length != sizeof(struct drm_ctm)) { > + DRM_ERROR("Invalid length of data received\n"); > + return -EINVAL; > + } > + > + csc_data = (struct drm_ctm *)blob->data; > + pipe = to_intel_crtc(crtc)->pipe; > + > + /* Disable CSC functionality */ > + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); > + I915_WRITE(val, I915_READ(val) & (~CGM_CSC_EN)); > + > + DRM_DEBUG_DRIVER("Disabled CSC Functionality on Pipe %c\n", > + pipe_name(pipe)); > + > + val = _MMIO(_PIPE_CSC_BASE(pipe)); > + > + /* > + * First 8 of 9 CSC correction values go in pair, to first > + * 4 CSC register (bit 0:15 and 16:31) > + */ > + while (count < CSC_MAX_VALS - 1) { > + temp = chv_prepare_csc_coeff( > + csc_data->ctm_coeff[count]); > + SET_BITS(word, temp, 0, 16); > + count++; > + > + temp = chv_prepare_csc_coeff( > + csc_data->ctm_coeff[count]); > + SET_BITS(word, temp, 16, 16); > + count++; > + > + I915_WRITE(val, word); > + val.reg += 4; > + } > + > + /* 9th coeff goes to 5th register, bit 0:16 */ > + temp = chv_prepare_csc_coeff( > + csc_data->ctm_coeff[count]); > + SET_BITS(word, temp, 0, 16); > + I915_WRITE(val, word); > + > + /* Enable CSC functionality */ > + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); > + I915_WRITE(val, I915_READ(val) | CGM_CSC_EN); > + DRM_DEBUG_DRIVER("CSC enabled on Pipe %c\n", pipe_name(pipe)); > + return 0; > +} > + > +static int chv_set_degamma(struct drm_device *dev, > + struct drm_property_blob *blob, struct drm_crtc *crtc) > +{ > + u16 red_fract, green_fract, blue_fract; > + u32 red, green, blue; > + u32 num_samples; > + u32 word = 0; > + u32 count, cgm_control, cgm_degamma_reg; > + i915_reg_t val; > + enum pipe pipe; > + struct drm_palette *degamma_data; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct drm_r32g32b32 *correction_values = NULL; > + struct drm_crtc_state *state = crtc->state; > + > + if (WARN_ON(!blob)) > + return -EINVAL; > + > + degamma_data = (struct drm_palette *)blob->data; > + pipe = to_intel_crtc(crtc)->pipe; > + num_samples = blob->length / sizeof(struct drm_r32g32b32); > + > + switch (num_samples) { > + case GAMMA_DISABLE_VALS: If we implement my suggestion for a num_samples helper, we could put the NULL->0 samples logic into that one and nicely unify things. And probably we should also reject a gamma table with size 0 as nonsens then. > + /* Disable DeGamma functionality on Pipe - CGM Block */ > + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); > + cgm_control = I915_READ(val); > + cgm_control &= ~CGM_DEGAMMA_EN; > + state->palette_before_ctm_blob = NULL; > + > + I915_WRITE(val, cgm_control); > + DRM_DEBUG_DRIVER("DeGamma disabled on Pipe %c\n", > + pipe_name(pipe)); > + break; > + > + case CHV_DEGAMMA_MAX_VALS: > + cgm_degamma_reg = _PIPE_DEGAMMA_BASE(pipe); > + count = 0; > + correction_values = degamma_data->lut; > + while (count < CHV_DEGAMMA_MAX_VALS) { > + blue = correction_values[count].b32; > + green = correction_values[count].g32; > + red = correction_values[count].r32; > + > + if (blue > CHV_MAX_GAMMA) > + blue = CHV_MAX_GAMMA; > + > + if (green > CHV_MAX_GAMMA) > + green = CHV_MAX_GAMMA; > + > + if (red > CHV_MAX_GAMMA) > + red = CHV_MAX_GAMMA; > + > + blue_fract = GET_BITS(blue, 10, 14); > + green_fract = GET_BITS(green, 10, 14); > + red_fract = GET_BITS(red, 10, 14); > + > + /* Green (29:16) and Blue (13:0) in DWORD1 */ > + SET_BITS(word, green_fract, 16, 14); > + SET_BITS(word, blue_fract, 0, 14); > + val = _MMIO(cgm_degamma_reg); > + I915_WRITE(val, word); > + cgm_degamma_reg += 4; > + > + /* Red (13:0) to be written to DWORD2 */ > + word = red_fract; > + val = _MMIO(cgm_degamma_reg); > + I915_WRITE(val, word); > + cgm_degamma_reg += 4; > + count++; > + } > + > + DRM_DEBUG_DRIVER("DeGamma LUT loaded for Pipe %c\n", > + pipe_name(pipe)); > + > + /* Enable DeGamma on Pipe */ > + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); > + I915_WRITE(val, I915_READ(val) | CGM_DEGAMMA_EN); > + DRM_DEBUG_DRIVER("DeGamma correction enabled on Pipe %c\n", > + pipe_name(pipe)); > + break; > + > + default: > + DRM_ERROR("Invalid number of samples for DeGamma LUT\n"); > + return -EINVAL; This is a relict from pre-atomic and won't work anymore: There's no way to pass error code from _commit functions up to userspace, and there's also no way to abort an atomic commit at that stage. Input validation must happen in atomic_check callbacks (or compute_config, as we tend to call them in i915 itself). -Daniel
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 0851de07..c66d56a 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -64,7 +64,8 @@ i915-y += intel_audio.o \ intel_overlay.o \ intel_psr.o \ intel_sideband.o \ - intel_sprite.o + intel_sprite.o \ + intel_color_manager.o i915-$(CONFIG_ACPI) += intel_acpi.o intel_opregion.o i915-$(CONFIG_DRM_FBDEV_EMULATION) += intel_fbdev.o diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3ac616d..4396300 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -34,6 +34,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "intel_drv.h" +#include "intel_color_manager.h" #include <linux/console.h> #include <linux/module.h> @@ -311,7 +312,9 @@ static const struct intel_device_info intel_cherryview_info = { .gen = 8, .num_pipes = 3, .need_gfx_hws = 1, .has_hotplug = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, - .is_cherryview = 1, + .is_valleyview = 1, + .num_samples_after_ctm = CHV_10BIT_GAMMA_MAX_VALS, + .num_samples_before_ctm = CHV_DEGAMMA_MAX_VALS, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1d28d90..4eb0fab 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -793,6 +793,8 @@ struct intel_device_info { u8 num_sprites[I915_MAX_PIPES]; u8 gen; u8 ring_mask; /* Rings supported by the HW */ + u16 num_samples_after_ctm; + u16 num_samples_before_ctm; DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON); /* Register offsets for the various display pipes and transcoders */ int pipe_offsets[I915_MAX_TRANSCODERS]; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 007ae83..36bb320 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8154,4 +8154,30 @@ enum skl_disp_power_wells { #define GEN9_VEBOX_MOCS(i) _MMIO(0xcb00 + (i) * 4) /* Video MOCS registers */ #define GEN9_BLT_MOCS(i) _MMIO(0xcc00 + (i) * 4) /* Blitter MOCS registers */ +/* Color Management */ +#define PIPEA_CGM_CONTROL (VLV_DISPLAY_BASE + 0x67A00) +#define PIPEB_CGM_CONTROL (VLV_DISPLAY_BASE + 0x69A00) +#define PIPEC_CGM_CONTROL (VLV_DISPLAY_BASE + 0x6BA00) +#define PIPEA_CGM_GAMMA (VLV_DISPLAY_BASE + 0x67000) +#define PIPEB_CGM_GAMMA (VLV_DISPLAY_BASE + 0x69000) +#define PIPEC_CGM_GAMMA (VLV_DISPLAY_BASE + 0x6B000) +#define _PIPE_CGM_CONTROL(pipe) \ + (_PIPE3(pipe, PIPEA_CGM_CONTROL, PIPEB_CGM_CONTROL, PIPEC_CGM_CONTROL)) +#define _PIPE_GAMMA_BASE(pipe) \ + (_PIPE3(pipe, PIPEA_CGM_GAMMA, PIPEB_CGM_GAMMA, PIPEC_CGM_GAMMA)) + +#define PIPEA_CGM_DEGAMMA (VLV_DISPLAY_BASE + 0x66000) +#define PIPEB_CGM_DEGAMMA (VLV_DISPLAY_BASE + 0x68000) +#define PIPEC_CGM_DEGAMMA (VLV_DISPLAY_BASE + 0x6A000) +#define _PIPE_DEGAMMA_BASE(pipe) \ + (_PIPE3(pipe, PIPEA_CGM_DEGAMMA, PIPEB_CGM_DEGAMMA, PIPEC_CGM_DEGAMMA)) + +#define PIPEA_CGM_CSC (VLV_DISPLAY_BASE + 0x67900) +#define PIPEB_CGM_CSC (VLV_DISPLAY_BASE + 0x69900) +#define PIPEC_CGM_CSC (VLV_DISPLAY_BASE + 0x6B900) +#define _PIPE_CSC_BASE(pipe) \ + (_PIPE3(pipe, PIPEA_CGM_CSC, PIPEB_CGM_CSC, PIPEC_CGM_CSC)) + + + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/intel_color_manager.c b/drivers/gpu/drm/i915/intel_color_manager.c new file mode 100644 index 0000000..02eee98 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_color_manager.c @@ -0,0 +1,353 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Shashank Sharma <shashank.sharma@intel.com> + * Kausal Malladi <Kausal.Malladi@intel.com> + */ + +#include "intel_color_manager.h" + +static u16 chv_prepare_csc_coeff(s64 csc_coeff) +{ + u16 csc_s3_12_format = 0; + u16 csc_int_value; + u16 csc_fract_value; + + if (csc_coeff < 0) + csc_s3_12_format = CSC_COEFF_SIGN; + csc_coeff = abs(csc_coeff); + csc_coeff += CHV_CSC_FRACT_ROUNDOFF; + if (csc_coeff > CHV_CSC_COEFF_MAX + 1) + csc_coeff = CHV_CSC_COEFF_MAX + 1; + else if (csc_coeff > CHV_CSC_COEFF_MAX) + csc_coeff = CHV_CSC_COEFF_MAX; + + csc_int_value = csc_coeff >> CHV_CSC_COEFF_SHIFT; + csc_int_value <<= CHV_CSC_COEFF_INT_SHIFT; + + csc_fract_value = csc_coeff >> CHV_CSC_COEFF_FRACT_SHIFT; + + csc_s3_12_format |= csc_int_value | csc_fract_value; + + return csc_s3_12_format; +} + +static int chv_set_csc(struct drm_device *dev, struct drm_property_blob *blob, + struct drm_crtc *crtc) +{ + u16 temp; + u32 word = 0; + int count = 0; + i915_reg_t val; + struct drm_ctm *csc_data; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe; + + if (WARN_ON(!blob)) + return -EINVAL; + + if (blob->length != sizeof(struct drm_ctm)) { + DRM_ERROR("Invalid length of data received\n"); + return -EINVAL; + } + + csc_data = (struct drm_ctm *)blob->data; + pipe = to_intel_crtc(crtc)->pipe; + + /* Disable CSC functionality */ + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); + I915_WRITE(val, I915_READ(val) & (~CGM_CSC_EN)); + + DRM_DEBUG_DRIVER("Disabled CSC Functionality on Pipe %c\n", + pipe_name(pipe)); + + val = _MMIO(_PIPE_CSC_BASE(pipe)); + + /* + * First 8 of 9 CSC correction values go in pair, to first + * 4 CSC register (bit 0:15 and 16:31) + */ + while (count < CSC_MAX_VALS - 1) { + temp = chv_prepare_csc_coeff( + csc_data->ctm_coeff[count]); + SET_BITS(word, temp, 0, 16); + count++; + + temp = chv_prepare_csc_coeff( + csc_data->ctm_coeff[count]); + SET_BITS(word, temp, 16, 16); + count++; + + I915_WRITE(val, word); + val.reg += 4; + } + + /* 9th coeff goes to 5th register, bit 0:16 */ + temp = chv_prepare_csc_coeff( + csc_data->ctm_coeff[count]); + SET_BITS(word, temp, 0, 16); + I915_WRITE(val, word); + + /* Enable CSC functionality */ + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); + I915_WRITE(val, I915_READ(val) | CGM_CSC_EN); + DRM_DEBUG_DRIVER("CSC enabled on Pipe %c\n", pipe_name(pipe)); + return 0; +} + +static int chv_set_degamma(struct drm_device *dev, + struct drm_property_blob *blob, struct drm_crtc *crtc) +{ + u16 red_fract, green_fract, blue_fract; + u32 red, green, blue; + u32 num_samples; + u32 word = 0; + u32 count, cgm_control, cgm_degamma_reg; + i915_reg_t val; + enum pipe pipe; + struct drm_palette *degamma_data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_r32g32b32 *correction_values = NULL; + struct drm_crtc_state *state = crtc->state; + + if (WARN_ON(!blob)) + return -EINVAL; + + degamma_data = (struct drm_palette *)blob->data; + pipe = to_intel_crtc(crtc)->pipe; + num_samples = blob->length / sizeof(struct drm_r32g32b32); + + switch (num_samples) { + case GAMMA_DISABLE_VALS: + /* Disable DeGamma functionality on Pipe - CGM Block */ + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); + cgm_control = I915_READ(val); + cgm_control &= ~CGM_DEGAMMA_EN; + state->palette_before_ctm_blob = NULL; + + I915_WRITE(val, cgm_control); + DRM_DEBUG_DRIVER("DeGamma disabled on Pipe %c\n", + pipe_name(pipe)); + break; + + case CHV_DEGAMMA_MAX_VALS: + cgm_degamma_reg = _PIPE_DEGAMMA_BASE(pipe); + count = 0; + correction_values = degamma_data->lut; + while (count < CHV_DEGAMMA_MAX_VALS) { + blue = correction_values[count].b32; + green = correction_values[count].g32; + red = correction_values[count].r32; + + if (blue > CHV_MAX_GAMMA) + blue = CHV_MAX_GAMMA; + + if (green > CHV_MAX_GAMMA) + green = CHV_MAX_GAMMA; + + if (red > CHV_MAX_GAMMA) + red = CHV_MAX_GAMMA; + + blue_fract = GET_BITS(blue, 10, 14); + green_fract = GET_BITS(green, 10, 14); + red_fract = GET_BITS(red, 10, 14); + + /* Green (29:16) and Blue (13:0) in DWORD1 */ + SET_BITS(word, green_fract, 16, 14); + SET_BITS(word, blue_fract, 0, 14); + val = _MMIO(cgm_degamma_reg); + I915_WRITE(val, word); + cgm_degamma_reg += 4; + + /* Red (13:0) to be written to DWORD2 */ + word = red_fract; + val = _MMIO(cgm_degamma_reg); + I915_WRITE(val, word); + cgm_degamma_reg += 4; + count++; + } + + DRM_DEBUG_DRIVER("DeGamma LUT loaded for Pipe %c\n", + pipe_name(pipe)); + + /* Enable DeGamma on Pipe */ + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); + I915_WRITE(val, I915_READ(val) | CGM_DEGAMMA_EN); + DRM_DEBUG_DRIVER("DeGamma correction enabled on Pipe %c\n", + pipe_name(pipe)); + break; + + default: + DRM_ERROR("Invalid number of samples for DeGamma LUT\n"); + return -EINVAL; + } + return 0; +} + +static int chv_set_gamma(struct drm_device *dev, struct drm_property_blob *blob, + struct drm_crtc *crtc) +{ + enum pipe pipe; + u16 red_fract, green_fract, blue_fract; + u32 red, green, blue, num_samples; + u32 word = 0; + u32 count, cgm_gamma_reg, cgm_control; + i915_reg_t val; + struct drm_r32g32b32 *correction_values; + struct drm_palette *gamma_data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc_state *state = crtc->state; + + if (WARN_ON(!blob)) + return -EINVAL; + + gamma_data = (struct drm_palette *)blob->data; + pipe = to_intel_crtc(crtc)->pipe; + num_samples = blob->length / sizeof(struct drm_r32g32b32); + + switch (num_samples) { + case GAMMA_DISABLE_VALS: + + /* Disable Gamma functionality on Pipe - CGM Block */ + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); + cgm_control = I915_READ(val); + cgm_control &= ~CGM_GAMMA_EN; + I915_WRITE(val, cgm_control); + state->palette_after_ctm_blob = NULL; + DRM_DEBUG_DRIVER("Gamma disabled on Pipe %c\n", + pipe_name(pipe)); + return 0; + + case CHV_8BIT_GAMMA_MAX_VALS: + case CHV_10BIT_GAMMA_MAX_VALS: + + count = 0; + cgm_gamma_reg = _PIPE_GAMMA_BASE(pipe); + correction_values = gamma_data->lut; + + while (count < num_samples) { + blue = correction_values[count].b32; + green = correction_values[count].g32; + red = correction_values[count].r32; + + if (blue > CHV_MAX_GAMMA) + blue = CHV_MAX_GAMMA; + + if (green > CHV_MAX_GAMMA) + green = CHV_MAX_GAMMA; + + if (red > CHV_MAX_GAMMA) + red = CHV_MAX_GAMMA; + + /* get MSB 10 bits from fraction part (14:23) */ + blue_fract = GET_BITS(blue, 14, 10); + green_fract = GET_BITS(green, 14, 10); + red_fract = GET_BITS(red, 14, 10); + + /* Green (25:16) and Blue (9:0) to be written */ + SET_BITS(word, green_fract, 16, 10); + SET_BITS(word, blue_fract, 0, 10); + val = _MMIO(cgm_gamma_reg); + I915_WRITE(val, word); + cgm_gamma_reg += 4; + + /* Red (9:0) to be written */ + word = red_fract; + val = _MMIO(cgm_gamma_reg); + I915_WRITE(val, word); + cgm_gamma_reg += 4; + count++; + } + + /* Enable (CGM) Gamma on Pipe */ + val = _MMIO(_PIPE_CGM_CONTROL(pipe)); + I915_WRITE(val, I915_READ(val) | CGM_GAMMA_EN); + DRM_DEBUG_DRIVER("CGM Gamma enabled on Pipe %c\n", + pipe_name(pipe)); + return 0; + + default: + DRM_ERROR("Invalid number of samples (%u) for Gamma LUT\n", + num_samples); + return -EINVAL; + } +} + +void intel_color_manager_commit(struct drm_device *dev, + struct drm_crtc_state *crtc_state) +{ + struct drm_property_blob *blob; + struct drm_crtc *crtc = crtc_state->crtc; + int ret = -EINVAL; + + /* + * CRTC level color correction, once applied on the + * pipe, goes on forever, until disabled, so there is no + * need to program all those correction registers on every + * commit. Do this only when a new correction applied. + */ + if (!crtc_state->color_correction_changed) + return; + + blob = crtc_state->palette_after_ctm_blob; + if (blob) { + /* Gamma correction is platform specific */ + if (IS_CHERRYVIEW(dev)) + ret = chv_set_gamma(dev, blob, crtc); + + if (ret) + DRM_ERROR("set Gamma correction failed\n"); + else + DRM_DEBUG_DRIVER("Gamma correction success\n"); + } + + blob = crtc_state->palette_before_ctm_blob; + if (blob) { + /* Degamma correction */ + if (IS_CHERRYVIEW(dev)) + ret = chv_set_degamma(dev, blob, crtc); + + if (ret) + DRM_ERROR("set degamma correction failed\n"); + else + DRM_DEBUG_DRIVER("degamma correction success\n"); + } + + blob = crtc_state->ctm_blob; + if (blob) { + /* CSC correction */ + if (IS_CHERRYVIEW(dev)) + ret = chv_set_csc(dev, blob, crtc); + + if (ret) + DRM_ERROR("set CSC correction failed\n"); + else + DRM_DEBUG_DRIVER("CSC correction success\n"); + } + + crtc_state->color_correction_changed = false; +} + +void intel_crtc_attach_color_properties(struct drm_crtc *crtc) +{ +} diff --git a/drivers/gpu/drm/i915/intel_color_manager.h b/drivers/gpu/drm/i915/intel_color_manager.h new file mode 100644 index 0000000..04185ac --- /dev/null +++ b/drivers/gpu/drm/i915/intel_color_manager.h @@ -0,0 +1,91 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Shashank Sharma <shashank.sharma@intel.com> + * Kausal Malladi <Kausal.Malladi@intel.com> + */ +#include <drm/drmP.h> +#include <drm/drm_crtc_helper.h> +#include "i915_drv.h" + +/* Color management bit utilities */ +#define GET_BIT_MASK(n) ((1 << n) - 1) + +/* Read bits of a word from bit no. 'start'(lsb) till 'n' bits */ +#define GET_BITS(x, start, nbits) ((x >> start) & GET_BIT_MASK(nbits)) + +/* Round off by adding 1 to the immediate lower bit */ +#define GET_BITS_ROUNDOFF(x, start, nbits) \ + ((GET_BITS(x, start, (nbits + 1)) + 1) >> 1) + +/* Clear bits of a word from bit no. 'start' till nbits */ +#define CLEAR_BITS(x, start, nbits) ( \ + x &= ~((GET_BIT_MASK(nbits) << start))) + +/* Write bit_pattern of no_bits bits in a target word */ +#define SET_BITS(target, bit_pattern, start_bit, no_bits) \ + do { \ + CLEAR_BITS(target, start_bit, no_bits); \ + target |= (bit_pattern << start_bit); \ + } while (0) + +/* CHV */ +#define CHV_10BIT_GAMMA_MAX_VALS 257 +#define CHV_DEGAMMA_MAX_VALS 65 + +/* No of coeff for disabling gamma is 0 */ +#define GAMMA_DISABLE_VALS 0 + +/* Gamma on CHV */ +#define CHV_10BIT_GAMMA_MAX_VALS 257 +#define CHV_8BIT_GAMMA_MAX_VALS 256 +#define CHV_10BIT_GAMMA_MSB_SHIFT 6 +#define CHV_GAMMA_SHIFT_GREEN 16 +#define CHV_MAX_GAMMA ((1 << 24) - 1) + +/* + * CSC on CHV + * Fractional part is 32 bit, and we need only 12 MSBs for programming + * into registers. ROUNDOFF is required to minimize loss of precision. + */ +#define CHV_CSC_FRACT_ROUNDOFF (1 << 19) +/* + * CSC values are 64-bit values. For CHV, the maximum CSC value that + * user can program is 7.99999..., which can be represented in fixed point + * S31.32 format like this, with all fractional bits as 1 + */ +#define CHV_CSC_COEFF_MAX 0x00000007FFFFFFFF +#define CHV_CSC_COEFF_SHIFT 32 +#define CHV_CSC_COEFF_INT_SHIFT 12 +#define CSC_COEFF_SIGN (1 << 15) +#define CHV_CSC_COEFF_FRACT_SHIFT 20 +#define CSC_MAX_VALS 9 + +/* Degamma on CHV */ +#define CHV_DEGAMMA_MSB_SHIFT 2 +#define CHV_DEGAMMA_GREEN_SHIFT 16 + +/* CHV CGM Block */ +#define CGM_GAMMA_EN (1 << 2) +#define CGM_CSC_EN (1 << 1) +#define CGM_DEGAMMA_EN (1 << 0) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a05ba28..b9eb507 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13940,6 +13940,8 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, intel_update_pipe_config(intel_crtc, old_intel_state); else if (INTEL_INFO(dev)->gen >= 9) skl_detach_scalers(intel_crtc); + + intel_color_manager_commit(dev, crtc->state); } static void intel_finish_crtc_commit(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d523ebb..2ee655a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1604,4 +1604,8 @@ void intel_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state); extern const struct drm_plane_helper_funcs intel_plane_helper_funcs; +/* intel_color_manager.c */ +void intel_crtc_attach_color_properties(struct drm_crtc *crtc); +void intel_color_manager_commit(struct drm_device *dev, + struct drm_crtc_state *crtc_state); #endif /* __INTEL_DRV_H__ */