On Thu, Dec 17, 2015 at 06:57:56PM +0000, Lionel Landwerlin wrote: > From: Shashank Sharma <shashank.sharma@xxxxxxxxx> > > Implement degamma, csc and gamma steps on CHV. > > Signed-off-by: Shashank Sharma <shashank.sharma@xxxxxxxxx> > Signed-off-by: Kausal Malladi <kausalmalladi@xxxxxxxxx> > --- > 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@xxxxxxxxx> > + * Kausal Malladi <Kausal.Malladi@xxxxxxxxx> > + */ > + > +#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 -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx