* [PATCH 0/4] Pipe level color management
@ 2016-03-16 10:57 Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 1/4] drm/i915: Extract out gamma table and CSC to their own file Lionel Landwerlin
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Lionel Landwerlin @ 2016-03-16 10:57 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
This series introduces pipe level color management for Intel platforms
on CherryView and Broadwell on.
This series is based of a previous set of patches by Shashank Sharma.
Cheers,
Lionel
v9: Rebase on nightly
v10: Mask GAMMA_MODE register value (Matt Roper)
Cleanup legacy LUT helper (Emil Velikov)
v11: Rebase on drm-nightly
Lionel Landwerlin (4):
drm/i915: Extract out gamma table and CSC to their own file
drm/i915: Do not read GAMMA_MODE register
drm/i915: Implement color management on bdw/skl/bxt/kbl
drm/i915: Implement color management on chv
Documentation/DocBook/gpu.tmpl | 6 +-
drivers/gpu/drm/i915/Makefile | 1 +
drivers/gpu/drm/i915/i915_drv.c | 27 +-
drivers/gpu/drm/i915/i915_drv.h | 8 +
drivers/gpu/drm/i915/i915_reg.h | 53 ++++
drivers/gpu/drm/i915/intel_color.c | 556 +++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_display.c | 184 +++---------
drivers/gpu/drm/i915/intel_drv.h | 12 +
drivers/gpu/drm/i915/intel_fbdev.c | 8 +
9 files changed, 695 insertions(+), 160 deletions(-)
create mode 100644 drivers/gpu/drm/i915/intel_color.c
--
2.7.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] drm/i915: Extract out gamma table and CSC to their own file
2016-03-16 10:57 [PATCH 0/4] Pipe level color management Lionel Landwerlin
@ 2016-03-16 10:57 ` Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 2/4] drm/i915: Do not read GAMMA_MODE register Lionel Landwerlin
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Lionel Landwerlin @ 2016-03-16 10:57 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
The moves a couple of functions programming the gamma LUT and CSC
units into their own file.
On generations prior to Haswell there is only a gamma LUT. From
haswell on there is also a new enhanced color correction unit that
isn't used yet. This is why we need to set the GAMMA_MODE register,
either we're using the legacy 8bits LUT or enhanced LUTs (of 10 or
12bits).
The CSC unit is only available from Haswell on.
We also need to make a special case for CherryView which is recognized
as a gen 8 but doesn't have the same enhanced color correction unit
from Haswell on.
v2: Fix access to GAMMA_MODE register on older generations than
Haswell (from Matt Roper's comments)
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
---
drivers/gpu/drm/i915/Makefile | 1 +
drivers/gpu/drm/i915/i915_drv.h | 2 +
drivers/gpu/drm/i915/intel_color.c | 191 +++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_display.c | 163 +++---------------------------
drivers/gpu/drm/i915/intel_drv.h | 10 ++
5 files changed, 216 insertions(+), 151 deletions(-)
create mode 100644 drivers/gpu/drm/i915/intel_color.c
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 5558a03..7ffb51b 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -55,6 +55,7 @@ i915-y += intel_audio.o \
intel_atomic.o \
intel_atomic_plane.o \
intel_bios.o \
+ intel_color.o \
intel_display.o \
intel_dpll_mgr.o \
intel_fbc.o \
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 80b14f1..cd0c041 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -593,6 +593,8 @@ struct drm_i915_display_funcs {
/* render clock increase/decrease */
/* display clock increase/decrease */
/* pll clock increase/decrease */
+
+ void (*load_luts)(struct drm_crtc *crtc);
};
enum forcewake_domain_id {
diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
new file mode 100644
index 0000000..35b7f62
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_color.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright © 2016 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.
+ *
+ */
+
+#include "intel_drv.h"
+
+/*
+ * Set up the pipe CSC unit.
+ *
+ * Currently only full range RGB to limited range RGB conversion
+ * is supported, but eventually this should handle various
+ * RGB<->YCbCr scenarios as well.
+ */
+static void i9xx_load_csc_matrix(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int pipe = intel_crtc->pipe;
+ uint16_t coeff = 0x7800; /* 1.0 */
+
+ /*
+ * TODO: Check what kind of values actually come out of the pipe
+ * with these coeff/postoff values and adjust to get the best
+ * accuracy. Perhaps we even need to take the bpc value into
+ * consideration.
+ */
+
+ if (intel_crtc->config->limited_color_range)
+ coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
+
+ I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
+ I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
+
+ I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
+ I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
+
+ I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
+ I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
+
+ I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
+ I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
+ I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
+
+ if (INTEL_INFO(dev)->gen > 6) {
+ uint16_t postoff = 0;
+
+ if (intel_crtc->config->limited_color_range)
+ postoff = (16 * (1 << 12) / 255) & 0x1fff;
+
+ I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
+ I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
+ I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
+
+ I915_WRITE(PIPE_CSC_MODE(pipe), 0);
+ } else {
+ uint32_t mode = CSC_MODE_YUV_TO_RGB;
+
+ if (intel_crtc->config->limited_color_range)
+ mode |= CSC_BLACK_SCREEN_OFFSET;
+
+ I915_WRITE(PIPE_CSC_MODE(pipe), mode);
+ }
+}
+
+void intel_color_set_csc(struct drm_crtc *crtc)
+{
+ i9xx_load_csc_matrix(crtc);
+}
+
+/* Loads the palette/gamma unit for the CRTC with the prepared values. */
+static void i9xx_load_luts(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ int i;
+
+ if (HAS_GMCH_DISPLAY(dev)) {
+ if (intel_crtc->config->has_dsi_encoder)
+ assert_dsi_pll_enabled(dev_priv);
+ else
+ assert_pll_enabled(dev_priv, pipe);
+ }
+
+ for (i = 0; i < 256; i++) {
+ uint32_t word = (intel_crtc->lut_r[i] << 16) |
+ (intel_crtc->lut_g[i] << 8) |
+ intel_crtc->lut_b[i];
+ if (HAS_GMCH_DISPLAY(dev))
+ I915_WRITE(PALETTE(pipe, i), word);
+ else
+ I915_WRITE(LGC_PALETTE(pipe, i), word);
+ }
+}
+
+/* Loads the legacy palette/gamma unit for the CRTC on Haswell+. */
+static void haswell_load_luts(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ bool reenable_ips = false;
+
+ /*
+ * Workaround : Do not read or write the pipe palette/gamma data while
+ * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
+ */
+ if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
+ ((I915_READ(GAMMA_MODE(intel_crtc->pipe)) & GAMMA_MODE_MODE_MASK) ==
+ GAMMA_MODE_MODE_SPLIT)) {
+ hsw_disable_ips(intel_crtc);
+ reenable_ips = true;
+ }
+ I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
+
+ i9xx_load_luts(crtc);
+
+ if (reenable_ips)
+ hsw_enable_ips(intel_crtc);
+}
+
+void intel_color_load_luts(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* The clocks have to be on to load the palette. */
+ if (!crtc->state->active)
+ return;
+
+ dev_priv->display.load_luts(crtc);
+}
+
+void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
+ u16 *blue, uint32_t start, uint32_t size)
+{
+ int end = (start + size > 256) ? 256 : start + size, i;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+ for (i = start; i < end; i++) {
+ intel_crtc->lut_r[i] = red[i] >> 8;
+ intel_crtc->lut_g[i] = green[i] >> 8;
+ intel_crtc->lut_b[i] = blue[i] >> 8;
+ }
+
+ intel_color_load_luts(crtc);
+}
+
+void intel_color_init(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ int i;
+
+ drm_mode_crtc_set_gamma_size(crtc, 256);
+ for (i = 0; i < 256; i++) {
+ intel_crtc->lut_r[i] = i;
+ intel_crtc->lut_g[i] = i;
+ intel_crtc->lut_b[i] = i;
+ }
+
+ if (IS_HASWELL(dev) ||
+ (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev))) {
+ dev_priv->display.load_luts = haswell_load_luts;
+ } else {
+ dev_priv->display.load_luts = i9xx_load_luts;
+ }
+}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ce55f0b..45c1ae6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -101,7 +101,6 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
struct intel_link_m_n *m2_n2);
static void ironlake_set_pipeconf(struct drm_crtc *crtc);
static void haswell_set_pipeconf(struct drm_crtc *crtc);
-static void intel_set_pipe_csc(struct drm_crtc *crtc);
static void vlv_prepare_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *pipe_config);
static void chv_prepare_pll(struct intel_crtc *crtc,
@@ -1180,7 +1179,7 @@ void assert_pll(struct drm_i915_private *dev_priv,
}
/* XXX: the dsi pll is shared between MIPI DSI ports */
-static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
+void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
{
u32 val;
bool cur_state;
@@ -1194,8 +1193,6 @@ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
"DSI PLL state assertion failure (expected %s, current %s)\n",
onoff(state), onoff(cur_state));
}
-#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
-#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
static void assert_fdi_tx(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
@@ -3267,7 +3264,7 @@ static void intel_update_pipe_config(struct intel_crtc *crtc,
pipe_config->pipe_src_w, pipe_config->pipe_src_h);
if (HAS_DDI(dev))
- intel_set_pipe_csc(&crtc->base);
+ intel_color_set_csc(&crtc->base);
/*
* Update pipe size and adjust fitter if needed: the reason for this is
@@ -4507,55 +4504,6 @@ void hsw_disable_ips(struct intel_crtc *crtc)
intel_wait_for_vblank(dev, crtc->pipe);
}
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-static void intel_crtc_load_lut(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum pipe pipe = intel_crtc->pipe;
- int i;
- bool reenable_ips = false;
-
- /* The clocks have to be on to load the palette. */
- if (!crtc->state->active)
- return;
-
- if (HAS_GMCH_DISPLAY(dev_priv->dev)) {
- if (intel_crtc->config->has_dsi_encoder)
- assert_dsi_pll_enabled(dev_priv);
- else
- assert_pll_enabled(dev_priv, pipe);
- }
-
- /* Workaround : Do not read or write the pipe palette/gamma data while
- * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
- */
- if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
- ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
- GAMMA_MODE_MODE_SPLIT)) {
- hsw_disable_ips(intel_crtc);
- reenable_ips = true;
- }
-
- for (i = 0; i < 256; i++) {
- i915_reg_t palreg;
-
- if (HAS_GMCH_DISPLAY(dev))
- palreg = PALETTE(pipe, i);
- else
- palreg = LGC_PALETTE(pipe, i);
-
- I915_WRITE(palreg,
- (intel_crtc->lut_r[i] << 16) |
- (intel_crtc->lut_g[i] << 8) |
- intel_crtc->lut_b[i]);
- }
-
- if (reenable_ips)
- hsw_enable_ips(intel_crtc);
-}
-
static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
{
if (intel_crtc->overlay) {
@@ -4851,7 +4799,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
* On ILK+ LUT must be loaded before the pipe is running but with
* clocks enabled
*/
- intel_crtc_load_lut(crtc);
+ intel_color_load_luts(crtc);
if (dev_priv->display.initial_watermarks != NULL)
dev_priv->display.initial_watermarks(intel_crtc->config);
@@ -4918,7 +4866,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
haswell_set_pipeconf(crtc);
- intel_set_pipe_csc(crtc);
+ intel_color_set_csc(crtc);
intel_crtc->active = true;
@@ -4947,7 +4895,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
* On ILK+ LUT must be loaded before the pipe is running but with
* clocks enabled
*/
- intel_crtc_load_lut(crtc);
+ intel_color_load_luts(crtc);
intel_ddi_set_pipe_settings(crtc);
if (!intel_crtc->config->has_dsi_encoder)
@@ -6143,7 +6091,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
i9xx_pfit_enable(intel_crtc);
- intel_crtc_load_lut(crtc);
+ intel_color_load_luts(crtc);
intel_update_watermarks(crtc);
intel_enable_pipe(intel_crtc);
@@ -6197,7 +6145,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
i9xx_pfit_enable(intel_crtc);
- intel_crtc_load_lut(crtc);
+ intel_color_load_luts(crtc);
intel_update_watermarks(crtc);
intel_enable_pipe(intel_crtc);
@@ -8665,70 +8613,6 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc)
POSTING_READ(PIPECONF(pipe));
}
-/*
- * Set up the pipe CSC unit.
- *
- * Currently only full range RGB to limited range RGB conversion
- * is supported, but eventually this should handle various
- * RGB<->YCbCr scenarios as well.
- */
-static void intel_set_pipe_csc(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int pipe = intel_crtc->pipe;
- uint16_t coeff = 0x7800; /* 1.0 */
-
- /*
- * TODO: Check what kind of values actually come out of the pipe
- * with these coeff/postoff values and adjust to get the best
- * accuracy. Perhaps we even need to take the bpc value into
- * consideration.
- */
-
- if (intel_crtc->config->limited_color_range)
- coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
-
- /*
- * GY/GU and RY/RU should be the other way around according
- * to BSpec, but reality doesn't agree. Just set them up in
- * a way that results in the correct picture.
- */
- I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
- I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
-
- I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
- I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
-
- I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
- I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
-
- I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
- I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
- I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
-
- if (INTEL_INFO(dev)->gen > 6) {
- uint16_t postoff = 0;
-
- if (intel_crtc->config->limited_color_range)
- postoff = (16 * (1 << 12) / 255) & 0x1fff;
-
- I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
- I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
- I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
-
- I915_WRITE(PIPE_CSC_MODE(pipe), 0);
- } else {
- uint32_t mode = CSC_MODE_YUV_TO_RGB;
-
- if (intel_crtc->config->limited_color_range)
- mode |= CSC_BLACK_SCREEN_OFFSET;
-
- I915_WRITE(PIPE_CSC_MODE(pipe), mode);
- }
-}
-
static void haswell_set_pipeconf(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -8751,9 +8635,6 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc)
I915_WRITE(PIPECONF(cpu_transcoder), val);
POSTING_READ(PIPECONF(cpu_transcoder));
- I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
- POSTING_READ(GAMMA_MODE(intel_crtc->pipe));
-
if (IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
val = 0;
@@ -10190,21 +10071,6 @@ static bool cursor_size_ok(struct drm_device *dev,
return true;
}
-static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
- u16 *blue, uint32_t start, uint32_t size)
-{
- int end = (start + size > 256) ? 256 : start + size, i;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
- for (i = start; i < end; i++) {
- intel_crtc->lut_r[i] = red[i] >> 8;
- intel_crtc->lut_g[i] = green[i] >> 8;
- intel_crtc->lut_b[i] = blue[i] >> 8;
- }
-
- intel_crtc_load_lut(crtc);
-}
-
/* VESA 640x480x72Hz mode to set on the pipe */
static struct drm_display_mode load_detect_mode = {
DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
@@ -11979,7 +11845,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs intel_helper_funcs = {
.mode_set_base_atomic = intel_pipe_set_base_atomic,
- .load_lut = intel_crtc_load_lut,
+ .load_lut = intel_color_load_luts,
.atomic_begin = intel_begin_crtc_commit,
.atomic_flush = intel_finish_crtc_commit,
.atomic_check = intel_crtc_atomic_check,
@@ -13714,7 +13580,7 @@ out:
#undef for_each_intel_crtc_masked
static const struct drm_crtc_funcs intel_crtc_funcs = {
- .gamma_set = intel_crtc_gamma_set,
+ .gamma_set = intel_color_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config,
.destroy = intel_crtc_destroy,
.page_flip = intel_crtc_page_flip,
@@ -14218,7 +14084,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
struct intel_crtc_state *crtc_state = NULL;
struct drm_plane *primary = NULL;
struct drm_plane *cursor = NULL;
- int i, ret;
+ int ret;
intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
if (intel_crtc == NULL)
@@ -14254,13 +14120,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
if (ret)
goto fail;
- drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
- for (i = 0; i < 256; i++) {
- intel_crtc->lut_r[i] = i;
- intel_crtc->lut_g[i] = i;
- intel_crtc->lut_b[i] = i;
- }
-
/*
* On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
* is hooked to pipe B. Hence we want plane A feeding pipe B.
@@ -14285,6 +14144,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
+ intel_color_init(&intel_crtc->base);
+
WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
return;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 02b3d22..ec4677a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1215,6 +1215,9 @@ void assert_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state);
#define assert_pll_enabled(d, p) assert_pll(d, p, true)
#define assert_pll_disabled(d, p) assert_pll(d, p, false)
+void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state);
+#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
+#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state);
#define assert_fdi_rx_pll_enabled(d, p) assert_fdi_rx_pll(d, p, true)
@@ -1675,4 +1678,11 @@ 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.c */
+void intel_color_init(struct drm_crtc *crtc);
+void intel_color_set_csc(struct drm_crtc *crtc);
+void intel_color_load_luts(struct drm_crtc *crtc);
+void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
+ u16 *blue, uint32_t start, uint32_t size);
+
#endif /* __INTEL_DRV_H__ */
--
2.7.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] drm/i915: Do not read GAMMA_MODE register
2016-03-16 10:57 [PATCH 0/4] Pipe level color management Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 1/4] drm/i915: Extract out gamma table and CSC to their own file Lionel Landwerlin
@ 2016-03-16 10:57 ` Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 3/4] drm/i915: Implement color management on bdw/skl/bxt/kbl Lionel Landwerlin
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Lionel Landwerlin @ 2016-03-16 10:57 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
Implement Daniel Stone's recommendation to not read registers to infer
the hardware's state.
v2: Read GAMMA_MODE register value at init (Matt Roper's comment)
v3: Read GAMMA_MODE register in intel_modeset_readout_hw_state along
with other registers (Matt Roper's comment).
v4: Mask GAMMA_MODE register with interesting bits when reading
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
---
drivers/gpu/drm/i915/intel_color.c | 7 +++++--
drivers/gpu/drm/i915/intel_display.c | 3 +++
drivers/gpu/drm/i915/intel_drv.h | 3 +++
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
index 35b7f62..16657eb 100644
--- a/drivers/gpu/drm/i915/intel_color.c
+++ b/drivers/gpu/drm/i915/intel_color.c
@@ -121,6 +121,8 @@ static void haswell_load_luts(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc_state *intel_crtc_state =
+ to_intel_crtc_state(crtc->state);
bool reenable_ips = false;
/*
@@ -128,11 +130,12 @@ static void haswell_load_luts(struct drm_crtc *crtc)
* GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
*/
if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
- ((I915_READ(GAMMA_MODE(intel_crtc->pipe)) & GAMMA_MODE_MODE_MASK) ==
- GAMMA_MODE_MODE_SPLIT)) {
+ (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) {
hsw_disable_ips(intel_crtc);
reenable_ips = true;
}
+
+ intel_crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
i9xx_load_luts(crtc);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 45c1ae6..fcfc71e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9843,6 +9843,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
intel_get_pipe_timings(crtc, pipe_config);
+ pipe_config->gamma_mode =
+ I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
+
if (INTEL_INFO(dev)->gen >= 9) {
skl_init_scalers(dev, crtc, pipe_config);
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ec4677a..5b97d4a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -576,6 +576,9 @@ struct intel_crtc_state {
*/
bool need_postvbl_update;
} wm;
+
+ /* Gamma mode programmed on the pipe */
+ uint32_t gamma_mode;
};
struct vlv_wm_state {
--
2.7.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] drm/i915: Implement color management on bdw/skl/bxt/kbl
2016-03-16 10:57 [PATCH 0/4] Pipe level color management Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 1/4] drm/i915: Extract out gamma table and CSC to their own file Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 2/4] drm/i915: Do not read GAMMA_MODE register Lionel Landwerlin
@ 2016-03-16 10:57 ` Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 4/4] drm/i915: Implement color management on chv Lionel Landwerlin
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Lionel Landwerlin @ 2016-03-16 10:57 UTC (permalink / raw)
To: intel-gfx; +Cc: Kumar, daniel.vetter, Kausal Malladi
Patch based on a previous series by Shashank Sharma.
v2: Do not read GAMMA_MODE register to figure what mode we're in
v3: Program PREC_PAL_GC_MAX to clamp pixel values > 1.0
Add documentation on how the Broadcast RGB property is affected by CTM
v4: Update contributors
v5: Refactor degamma/gamma LUTs load into a single function
v6: Fix missing intel_crtc variable (bisect issue)
v7: Fix & simplify limited range matrix multiplication (Matt Roper's
comment)
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
Signed-off-by: Kumar, Kiran S <kiran.s.kumar@intel.com>
Signed-off-by: Kausal Malladi <kausalmalladi@gmail.com>
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Acknowledged-by: Matt Roper <matthew.d.roper@intel.com>
---
Documentation/DocBook/gpu.tmpl | 6 +-
drivers/gpu/drm/i915/i915_drv.c | 24 ++-
drivers/gpu/drm/i915/i915_drv.h | 6 +
drivers/gpu/drm/i915/i915_reg.h | 22 +++
drivers/gpu/drm/i915/intel_color.c | 345 +++++++++++++++++++++++++++++------
drivers/gpu/drm/i915/intel_display.c | 22 ++-
drivers/gpu/drm/i915/intel_drv.h | 3 +-
drivers/gpu/drm/i915/intel_fbdev.c | 8 +
8 files changed, 371 insertions(+), 65 deletions(-)
diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl
index 1692c4d..430e99b 100644
--- a/Documentation/DocBook/gpu.tmpl
+++ b/Documentation/DocBook/gpu.tmpl
@@ -2153,7 +2153,11 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >ENUM</td>
<td valign="top" >{ "Automatic", "Full", "Limited 16:235" }</td>
<td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
+ <td valign="top" >When this property is set to Limited 16:235
+ and CTM is set, the hardware will be programmed with the
+ result of the multiplication of CTM by the limited range
+ matrix to ensure the pixels normaly in the range 0..1.0 are
+ remapped to the range 16/255..235/255.</td>
</tr>
<tr>
<td valign="top" >“audio”</td>
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 20e8200..3807b73 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -66,6 +66,9 @@ static struct drm_driver driver;
#define IVB_CURSOR_OFFSETS \
.cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET }
+#define BDW_COLORS \
+ .color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
+
static const struct intel_device_info intel_i830_info = {
.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
.has_overlay = 1, .overlay_needs_physical = 1,
@@ -288,24 +291,28 @@ static const struct intel_device_info intel_haswell_m_info = {
.is_mobile = 1,
};
+#define BDW_FEATURES \
+ HSW_FEATURES, \
+ BDW_COLORS
+
static const struct intel_device_info intel_broadwell_d_info = {
- HSW_FEATURES,
+ BDW_FEATURES,
.gen = 8,
};
static const struct intel_device_info intel_broadwell_m_info = {
- HSW_FEATURES,
+ BDW_FEATURES,
.gen = 8, .is_mobile = 1,
};
static const struct intel_device_info intel_broadwell_gt3d_info = {
- HSW_FEATURES,
+ BDW_FEATURES,
.gen = 8,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
};
static const struct intel_device_info intel_broadwell_gt3m_info = {
- HSW_FEATURES,
+ BDW_FEATURES,
.gen = 8, .is_mobile = 1,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
};
@@ -321,13 +328,13 @@ static const struct intel_device_info intel_cherryview_info = {
};
static const struct intel_device_info intel_skylake_info = {
- HSW_FEATURES,
+ BDW_FEATURES,
.is_skylake = 1,
.gen = 9,
};
static const struct intel_device_info intel_skylake_gt3_info = {
- HSW_FEATURES,
+ BDW_FEATURES,
.is_skylake = 1,
.gen = 9,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
@@ -345,17 +352,18 @@ static const struct intel_device_info intel_broxton_info = {
.has_fbc = 1,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
+ BDW_COLORS,
};
static const struct intel_device_info intel_kabylake_info = {
- HSW_FEATURES,
+ BDW_FEATURES,
.is_preliminary = 1,
.is_kabylake = 1,
.gen = 9,
};
static const struct intel_device_info intel_kabylake_gt3_info = {
- HSW_FEATURES,
+ BDW_FEATURES,
.is_preliminary = 1,
.is_kabylake = 1,
.gen = 9,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index cd0c041..e4f7059 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -594,6 +594,7 @@ struct drm_i915_display_funcs {
/* display clock increase/decrease */
/* pll clock increase/decrease */
+ void (*load_csc_matrix)(struct drm_crtc *crtc);
void (*load_luts)(struct drm_crtc *crtc);
};
@@ -745,6 +746,11 @@ struct intel_device_info {
u8 has_slice_pg:1;
u8 has_subslice_pg:1;
u8 has_eu_pg:1;
+
+ struct color_luts {
+ u16 degamma_lut_size;
+ u16 gamma_lut_size;
+ } color;
};
#undef DEFINE_FLAG
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7dfc400..d9defd3 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -7656,6 +7656,28 @@ enum skl_disp_power_wells {
#define PIPE_CSC_POSTOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
#define PIPE_CSC_POSTOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
+/* pipe degamma/gamma LUTs on IVB+ */
+#define _PAL_PREC_INDEX_A 0x4A400
+#define _PAL_PREC_INDEX_B 0x4AC00
+#define _PAL_PREC_INDEX_C 0x4B400
+#define PAL_PREC_10_12_BIT (0 << 31)
+#define PAL_PREC_SPLIT_MODE (1 << 31)
+#define PAL_PREC_AUTO_INCREMENT (1 << 15)
+#define _PAL_PREC_DATA_A 0x4A404
+#define _PAL_PREC_DATA_B 0x4AC04
+#define _PAL_PREC_DATA_C 0x4B404
+#define _PAL_PREC_GC_MAX_A 0x4A410
+#define _PAL_PREC_GC_MAX_B 0x4AC10
+#define _PAL_PREC_GC_MAX_C 0x4B410
+#define _PAL_PREC_EXT_GC_MAX_A 0x4A420
+#define _PAL_PREC_EXT_GC_MAX_B 0x4AC20
+#define _PAL_PREC_EXT_GC_MAX_C 0x4B420
+
+#define PREC_PAL_INDEX(pipe) _MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B)
+#define PREC_PAL_DATA(pipe) _MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B)
+#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4)
+#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4)
+
/* MIPI DSI registers */
#define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, 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 16657eb..c6340d8 100644
--- a/drivers/gpu/drm/i915/intel_color.c
+++ b/drivers/gpu/drm/i915/intel_color.c
@@ -24,39 +24,155 @@
#include "intel_drv.h"
+#define CTM_COEFF_SIGN (1ULL << 63)
+
+#define CTM_COEFF_1_0 (1ULL << 32)
+#define CTM_COEFF_2_0 (CTM_COEFF_1_0 << 1)
+#define CTM_COEFF_4_0 (CTM_COEFF_2_0 << 1)
+#define CTM_COEFF_0_5 (CTM_COEFF_1_0 >> 1)
+#define CTM_COEFF_0_25 (CTM_COEFF_0_5 >> 1)
+#define CTM_COEFF_0_125 (CTM_COEFF_0_25 >> 1)
+
+#define CTM_COEFF_LIMITED_RANGE ((235ULL - 16ULL) * CTM_COEFF_1_0 / 255)
+
+#define CTM_COEFF_NEGATIVE(coeff) (((coeff) & CTM_COEFF_SIGN) != 0)
+#define CTM_COEFF_ABS(coeff) ((coeff) & (CTM_COEFF_SIGN - 1))
+
+#define LEGACY_LUT_LENGTH (sizeof(struct drm_color_lut) * 256)
+
/*
- * Set up the pipe CSC unit.
+ * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
+ * format). This macro takes the coefficient we want transformed and the
+ * number of fractional bits.
*
- * Currently only full range RGB to limited range RGB conversion
- * is supported, but eventually this should handle various
- * RGB<->YCbCr scenarios as well.
+ * We only have a 9 bits precision window which slides depending on the value
+ * of the CTM coefficient and we write the value from bit 3. We also round the
+ * value.
*/
+#define I9XX_CSC_COEFF_FP(coeff, fbits) \
+ (clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8)
+
+#define I9XX_CSC_COEFF_LIMITED_RANGE \
+ I9XX_CSC_COEFF_FP(CTM_COEFF_LIMITED_RANGE, 9)
+#define I9XX_CSC_COEFF_1_0 \
+ ((7 << 12) | I9XX_CSC_COEFF_FP(CTM_COEFF_1_0, 8))
+
+static bool crtc_state_is_legacy(struct drm_crtc_state *state)
+{
+ return !state->degamma_lut &&
+ !state->ctm &&
+ state->gamma_lut &&
+ state->gamma_lut->length == LEGACY_LUT_LENGTH;
+}
+
+/*
+ * When using limited range, multiply the matrix given by userspace by
+ * the matrix that we would use for the limited range. We do the
+ * multiplication in U2.30 format.
+ */
+static void ctm_mult_by_limited(uint64_t *result, int64_t *input)
+{
+ int i;
+
+ for (i = 0; i < 9; i++)
+ result[i] = 0;
+
+ for (i = 0; i < 3; i++) {
+ int64_t user_coeff = input[i * 3 + i];
+ uint64_t limited_coeff = CTM_COEFF_LIMITED_RANGE >> 2;
+ uint64_t abs_coeff = clamp_val(CTM_COEFF_ABS(user_coeff),
+ 0,
+ CTM_COEFF_4_0 - 1) >> 2;
+
+ result[i * 3 + i] = (limited_coeff * abs_coeff) >> 27;
+ if (CTM_COEFF_NEGATIVE(user_coeff))
+ result[i * 3 + i] |= CTM_COEFF_SIGN;
+ }
+}
+
+/* Set up the pipe CSC unit. */
static void i9xx_load_csc_matrix(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
+ struct drm_crtc_state *crtc_state = crtc->state;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int pipe = intel_crtc->pipe;
- uint16_t coeff = 0x7800; /* 1.0 */
-
- /*
- * TODO: Check what kind of values actually come out of the pipe
- * with these coeff/postoff values and adjust to get the best
- * accuracy. Perhaps we even need to take the bpc value into
- * consideration.
- */
-
- if (intel_crtc->config->limited_color_range)
- coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
+ int i, pipe = intel_crtc->pipe;
+ uint16_t coeffs[9] = { 0, };
+
+ if (crtc_state->ctm) {
+ struct drm_color_ctm *ctm =
+ (struct drm_color_ctm *)crtc_state->ctm->data;
+ uint64_t input[9] = { 0, };
+
+ if (intel_crtc->config->limited_color_range) {
+ ctm_mult_by_limited(input, ctm->matrix);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(input); i++)
+ input[i] = ctm->matrix[i];
+ }
+
+ /*
+ * Convert fixed point S31.32 input to format supported by the
+ * hardware.
+ */
+ for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
+ uint64_t abs_coeff = ((1ULL << 63) - 1) & input[i];
+
+ /*
+ * Clamp input value to min/max supported by
+ * hardware.
+ */
+ abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
+
+ /* sign bit */
+ if (CTM_COEFF_NEGATIVE(input[i]))
+ coeffs[i] |= 1 << 15;
+
+ if (abs_coeff < CTM_COEFF_0_125)
+ coeffs[i] |= (3 << 12) |
+ I9XX_CSC_COEFF_FP(abs_coeff, 12);
+ else if (abs_coeff < CTM_COEFF_0_25)
+ coeffs[i] |= (2 << 12) |
+ I9XX_CSC_COEFF_FP(abs_coeff, 11);
+ else if (abs_coeff < CTM_COEFF_0_5)
+ coeffs[i] |= (1 << 12) |
+ I9XX_CSC_COEFF_FP(abs_coeff, 10);
+ else if (abs_coeff < CTM_COEFF_1_0)
+ coeffs[i] |= I9XX_CSC_COEFF_FP(abs_coeff, 9);
+ else if (abs_coeff < CTM_COEFF_2_0)
+ coeffs[i] |= (7 << 12) |
+ I9XX_CSC_COEFF_FP(abs_coeff, 8);
+ else
+ coeffs[i] |= (6 << 12) |
+ I9XX_CSC_COEFF_FP(abs_coeff, 7);
+ }
+ } else {
+ /*
+ * Load an identity matrix if no coefficients are provided.
+ *
+ * TODO: Check what kind of values actually come out of the
+ * pipe with these coeff/postoff values and adjust to get the
+ * best accuracy. Perhaps we even need to take the bpc value
+ * into consideration.
+ */
+ for (i = 0; i < 3; i++) {
+ if (intel_crtc->config->limited_color_range)
+ coeffs[i * 3 + i] =
+ I9XX_CSC_COEFF_LIMITED_RANGE;
+ else
+ coeffs[i * 3 + i] = I9XX_CSC_COEFF_1_0;
+ }
+ }
- I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
- I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
+ I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeffs[0] << 16 | coeffs[1]);
+ I915_WRITE(PIPE_CSC_COEFF_BY(pipe), coeffs[2] << 16);
- I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
- I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
+ I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeffs[3] << 16 | coeffs[4]);
+ I915_WRITE(PIPE_CSC_COEFF_BU(pipe), coeffs[5] << 16);
- I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
- I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
+ I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), coeffs[6] << 16 | coeffs[7]);
+ I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeffs[8] << 16);
I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
@@ -85,13 +201,18 @@ static void i9xx_load_csc_matrix(struct drm_crtc *crtc)
void intel_color_set_csc(struct drm_crtc *crtc)
{
- i9xx_load_csc_matrix(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (dev_priv->display.load_csc_matrix)
+ dev_priv->display.load_csc_matrix(crtc);
}
-/* Loads the palette/gamma unit for the CRTC with the prepared values. */
+/* Loads the legacy palette/gamma unit for the CRTC. */
static void i9xx_load_luts(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
+ struct drm_crtc_state *state = crtc->state;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
enum pipe pipe = intel_crtc->pipe;
@@ -104,18 +225,33 @@ static void i9xx_load_luts(struct drm_crtc *crtc)
assert_pll_enabled(dev_priv, pipe);
}
- for (i = 0; i < 256; i++) {
- uint32_t word = (intel_crtc->lut_r[i] << 16) |
- (intel_crtc->lut_g[i] << 8) |
- intel_crtc->lut_b[i];
- if (HAS_GMCH_DISPLAY(dev))
- I915_WRITE(PALETTE(pipe, i), word);
- else
- I915_WRITE(LGC_PALETTE(pipe, i), word);
+ if (state->gamma_lut) {
+ struct drm_color_lut *lut =
+ (struct drm_color_lut *) state->gamma_lut->data;
+ for (i = 0; i < 256; i++) {
+ uint32_t word =
+ (drm_color_lut_extract(lut[i].red, 8) << 16) |
+ (drm_color_lut_extract(lut[i].green, 8) << 8) |
+ drm_color_lut_extract(lut[i].blue, 8);
+
+ if (HAS_GMCH_DISPLAY(dev))
+ I915_WRITE(PALETTE(pipe, i), word);
+ else
+ I915_WRITE(LGC_PALETTE(pipe, i), word);
+ }
+ } else {
+ for (i = 0; i < 256; i++) {
+ uint32_t word = (i << 16) | (i << 8) | i;
+
+ if (HAS_GMCH_DISPLAY(dev))
+ I915_WRITE(PALETTE(pipe, i), word);
+ else
+ I915_WRITE(LGC_PALETTE(pipe, i), word);
+ }
}
}
-/* Loads the legacy palette/gamma unit for the CRTC on Haswell+. */
+/* Loads the legacy palette/gamma unit for the CRTC on Haswell. */
static void haswell_load_luts(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -144,6 +280,89 @@ static void haswell_load_luts(struct drm_crtc *crtc)
hsw_enable_ips(intel_crtc);
}
+/* Loads the palette/gamma unit for the CRTC on Broadwell+. */
+static void broadwell_load_luts(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_crtc_state *state = crtc->state;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc_state *intel_state = to_intel_crtc_state(state);
+ enum pipe pipe = to_intel_crtc(crtc)->pipe;
+ uint32_t i, lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+
+ if (crtc_state_is_legacy(state)) {
+ haswell_load_luts(crtc);
+ return;
+ }
+
+ I915_WRITE(PREC_PAL_INDEX(pipe),
+ PAL_PREC_SPLIT_MODE | PAL_PREC_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++) {
+ uint32_t word =
+ drm_color_lut_extract(lut[i].red, 10) << 20 |
+ drm_color_lut_extract(lut[i].green, 10) << 10 |
+ drm_color_lut_extract(lut[i].blue, 10);
+
+ I915_WRITE(PREC_PAL_DATA(pipe), word);
+ }
+ } else {
+ for (i = 0; i < lut_size; i++) {
+ uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1);
+
+ I915_WRITE(PREC_PAL_DATA(pipe),
+ (v << 20) | (v << 10) | v);
+ }
+ }
+
+ if (state->gamma_lut) {
+ struct drm_color_lut *lut =
+ (struct drm_color_lut *) state->gamma_lut->data;
+
+ for (i = 0; i < lut_size; i++) {
+ uint32_t word =
+ (drm_color_lut_extract(lut[i].red, 10) << 20) |
+ (drm_color_lut_extract(lut[i].green, 10) << 10) |
+ drm_color_lut_extract(lut[i].blue, 10);
+
+ I915_WRITE(PREC_PAL_DATA(pipe), word);
+ }
+
+ /* Program the max register to clamp values > 1.0. */
+ I915_WRITE(PREC_PAL_GC_MAX(pipe, 0),
+ drm_color_lut_extract(lut[i].red, 16));
+ I915_WRITE(PREC_PAL_GC_MAX(pipe, 1),
+ drm_color_lut_extract(lut[i].green, 16));
+ I915_WRITE(PREC_PAL_GC_MAX(pipe, 2),
+ drm_color_lut_extract(lut[i].blue, 16));
+ } else {
+ for (i = 0; i < lut_size; i++) {
+ uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1);
+
+ I915_WRITE(PREC_PAL_DATA(pipe),
+ (v << 20) | (v << 10) | v);
+ }
+
+ I915_WRITE(PREC_PAL_GC_MAX(pipe, 0), (1 << 16) - 1);
+ I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), (1 << 16) - 1);
+ I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), (1 << 16) - 1);
+ }
+
+ intel_state->gamma_mode = GAMMA_MODE_MODE_SPLIT;
+ I915_WRITE(GAMMA_MODE(pipe), GAMMA_MODE_MODE_SPLIT);
+ POSTING_READ(GAMMA_MODE(pipe));
+
+ /*
+ * Reset the index, otherwise it prevents the legacy palette to be
+ * written properly.
+ */
+ I915_WRITE(PREC_PAL_INDEX(pipe), 0);
+}
+
void intel_color_load_luts(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -156,39 +375,61 @@ void intel_color_load_luts(struct drm_crtc *crtc)
dev_priv->display.load_luts(crtc);
}
-void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
- u16 *blue, uint32_t start, uint32_t size)
+int intel_color_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
{
- int end = (start + size > 256) ? 256 : start + size, i;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ size_t gamma_length, degamma_length;
- for (i = start; i < end; i++) {
- intel_crtc->lut_r[i] = red[i] >> 8;
- intel_crtc->lut_g[i] = green[i] >> 8;
- intel_crtc->lut_b[i] = blue[i] >> 8;
- }
+ degamma_length = INTEL_INFO(dev)->color.degamma_lut_size *
+ sizeof(struct drm_color_lut);
+ gamma_length = INTEL_INFO(dev)->color.gamma_lut_size *
+ sizeof(struct drm_color_lut);
- intel_color_load_luts(crtc);
+ /*
+ * We allow both degamma & gamma luts at the right size or
+ * NULL.
+ */
+ if ((!crtc_state->degamma_lut ||
+ crtc_state->degamma_lut->length == degamma_length) &&
+ (!crtc_state->gamma_lut ||
+ crtc_state->gamma_lut->length == gamma_length))
+ return 0;
+
+ /*
+ * We also allow no degamma lut and a gamma lut at the legacy
+ * size (256 entries).
+ */
+ if (!crtc_state->degamma_lut &&
+ crtc_state->gamma_lut &&
+ crtc_state->gamma_lut->length == LEGACY_LUT_LENGTH)
+ return 0;
+
+ return -EINVAL;
}
void intel_color_init(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int i;
drm_mode_crtc_set_gamma_size(crtc, 256);
- for (i = 0; i < 256; i++) {
- intel_crtc->lut_r[i] = i;
- intel_crtc->lut_g[i] = i;
- intel_crtc->lut_b[i] = i;
- }
- if (IS_HASWELL(dev) ||
- (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev))) {
+ if (IS_HASWELL(dev)) {
+ dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
dev_priv->display.load_luts = haswell_load_luts;
+ } else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) ||
+ IS_BROXTON(dev) || IS_KABYLAKE(dev)) {
+ dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
+ dev_priv->display.load_luts = broadwell_load_luts;
} else {
dev_priv->display.load_luts = i9xx_load_luts;
}
+
+ /* Enable color management support when we have degamma & gamma LUTs. */
+ if (INTEL_INFO(dev)->color.degamma_lut_size != 0 &&
+ INTEL_INFO(dev)->color.gamma_lut_size != 0)
+ drm_helper_crtc_enable_color_mgmt(crtc,
+ INTEL_INFO(dev)->color.degamma_lut_size,
+ INTEL_INFO(dev)->color.gamma_lut_size);
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fcfc71e..856ce06 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11806,6 +11806,12 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
return ret;
}
+ if (crtc_state->color_mgmt_changed) {
+ ret = intel_color_check(crtc, crtc_state);
+ if (ret)
+ return ret;
+ }
+
ret = 0;
if (dev_priv->display.compute_pipe_wm) {
ret = dev_priv->display.compute_pipe_wm(pipe_config);
@@ -11848,7 +11854,6 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs intel_helper_funcs = {
.mode_set_base_atomic = intel_pipe_set_base_atomic,
- .load_lut = intel_color_load_luts,
.atomic_begin = intel_begin_crtc_commit,
.atomic_flush = intel_finish_crtc_commit,
.atomic_check = intel_crtc_atomic_check,
@@ -13474,6 +13479,18 @@ static int intel_atomic_commit(struct drm_device *dev,
dev_priv->display.crtc_enable(crtc);
}
+ if (!modeset &&
+ crtc->state->active &&
+ crtc->state->color_mgmt_changed) {
+ /*
+ * Only update color management when not doing
+ * a modeset as this will be done by
+ * crtc_enable already.
+ */
+ intel_color_set_csc(crtc);
+ intel_color_load_luts(crtc);
+ }
+
if (!modeset)
intel_pre_plane_update(to_intel_crtc_state(old_crtc_state));
@@ -13583,8 +13600,9 @@ out:
#undef for_each_intel_crtc_masked
static const struct drm_crtc_funcs intel_crtc_funcs = {
- .gamma_set = intel_color_legacy_gamma_set,
+ .gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config,
+ .set_property = drm_atomic_helper_crtc_set_property,
.destroy = intel_crtc_destroy,
.page_flip = intel_crtc_page_flip,
.atomic_duplicate_state = intel_crtc_duplicate_state,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5b97d4a..cbc8c2c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1683,9 +1683,8 @@ extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
/* intel_color.c */
void intel_color_init(struct drm_crtc *crtc);
+int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
void intel_color_set_csc(struct drm_crtc *crtc);
void intel_color_load_luts(struct drm_crtc *crtc);
-void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
- u16 *blue, uint32_t start, uint32_t size);
#endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index ae9cf6f..1765d99 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -379,6 +379,7 @@ retry:
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_fb_helper_crtc *new_crtc;
+ struct intel_crtc *intel_crtc;
fb_conn = fb_helper->connector_info[i];
connector = fb_conn->connector;
@@ -420,6 +421,13 @@ retry:
num_connectors_enabled++;
+ intel_crtc = to_intel_crtc(connector->state->crtc);
+ for (j = 0; j < 256; j++) {
+ intel_crtc->lut_r[j] = j;
+ intel_crtc->lut_g[j] = j;
+ intel_crtc->lut_b[j] = j;
+ }
+
new_crtc = intel_fb_helper_crtc(fb_helper, connector->state->crtc);
/*
--
2.7.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] drm/i915: Implement color management on chv
2016-03-16 10:57 [PATCH 0/4] Pipe level color management Lionel Landwerlin
` (2 preceding siblings ...)
2016-03-16 10:57 ` [PATCH 3/4] drm/i915: Implement color management on bdw/skl/bxt/kbl Lionel Landwerlin
@ 2016-03-16 10:57 ` Lionel Landwerlin
2016-03-16 13:30 ` ✗ Fi.CI.BAT: failure for Pipe level color management (rev11) Patchwork
2016-03-21 18:55 ` [PATCH 0/4] Pipe level color management Matt Roper
5 siblings, 0 replies; 8+ messages in thread
From: Lionel Landwerlin @ 2016-03-16 10:57 UTC (permalink / raw)
To: intel-gfx; +Cc: Kumar, daniel.vetter, Kausal Malladi
Patch based on a previous series by Shashank Sharma.
v2: Update contributors
v3: Refactor degamma/gamma LUTs load into a single function
v4: Remove unused variable
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
Signed-off-by: Kumar, Kiran S <kiran.s.kumar@intel.com>
Signed-off-by: Kausal Malladi <kausalmalladi@gmail.com>
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
---
drivers/gpu/drm/i915/i915_drv.c | 3 +
drivers/gpu/drm/i915/i915_reg.h | 31 +++++++++
drivers/gpu/drm/i915/intel_color.c | 133 +++++++++++++++++++++++++++++++++++--
3 files changed, 161 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 3807b73..8a2aaa7 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -68,6 +68,8 @@ static struct drm_driver driver;
#define BDW_COLORS \
.color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
+#define CHV_COLORS \
+ .color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }
static const struct intel_device_info intel_i830_info = {
.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
@@ -325,6 +327,7 @@ static const struct intel_device_info intel_cherryview_info = {
.display_mmio_offset = VLV_DISPLAY_BASE,
GEN_CHV_PIPEOFFSETS,
CURSOR_OFFSETS,
+ CHV_COLORS,
};
static const struct intel_device_info intel_skylake_info = {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index d9defd3..95f56a0 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -7678,6 +7678,37 @@ enum skl_disp_power_wells {
#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4)
#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4)
+/* 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)
+#define _CGM_PIPE_A_CSC_COEFF45 (VLV_DISPLAY_BASE + 0x67908)
+#define _CGM_PIPE_A_CSC_COEFF67 (VLV_DISPLAY_BASE + 0x6790C)
+#define _CGM_PIPE_A_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x67910)
+#define _CGM_PIPE_A_DEGAMMA (VLV_DISPLAY_BASE + 0x66000)
+#define _CGM_PIPE_A_GAMMA (VLV_DISPLAY_BASE + 0x67000)
+#define _CGM_PIPE_A_MODE (VLV_DISPLAY_BASE + 0x67A00)
+#define CGM_PIPE_MODE_GAMMA (1 << 2)
+#define CGM_PIPE_MODE_CSC (1 << 1)
+#define CGM_PIPE_MODE_DEGAMMA (1 << 0)
+
+#define _CGM_PIPE_B_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x69900)
+#define _CGM_PIPE_B_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x69904)
+#define _CGM_PIPE_B_CSC_COEFF45 (VLV_DISPLAY_BASE + 0x69908)
+#define _CGM_PIPE_B_CSC_COEFF67 (VLV_DISPLAY_BASE + 0x6990C)
+#define _CGM_PIPE_B_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x69910)
+#define _CGM_PIPE_B_DEGAMMA (VLV_DISPLAY_BASE + 0x68000)
+#define _CGM_PIPE_B_GAMMA (VLV_DISPLAY_BASE + 0x69000)
+#define _CGM_PIPE_B_MODE (VLV_DISPLAY_BASE + 0x69A00)
+
+#define CGM_PIPE_CSC_COEFF01(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF01, _CGM_PIPE_B_CSC_COEFF01)
+#define CGM_PIPE_CSC_COEFF23(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF23, _CGM_PIPE_B_CSC_COEFF23)
+#define CGM_PIPE_CSC_COEFF45(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF45, _CGM_PIPE_B_CSC_COEFF45)
+#define CGM_PIPE_CSC_COEFF67(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF67, _CGM_PIPE_B_CSC_COEFF67)
+#define CGM_PIPE_CSC_COEFF8(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF8, _CGM_PIPE_B_CSC_COEFF8)
+#define CGM_PIPE_DEGAMMA(pipe, i, w) _MMIO(_PIPE(pipe, _CGM_PIPE_A_DEGAMMA, _CGM_PIPE_B_DEGAMMA) + (i) * 8 + (w) * 4)
+#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)
+
/* MIPI DSI registers */
#define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, 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 c6340d8..aa0b20d 100644
--- a/drivers/gpu/drm/i915/intel_color.c
+++ b/drivers/gpu/drm/i915/intel_color.c
@@ -29,6 +29,7 @@
#define CTM_COEFF_1_0 (1ULL << 32)
#define CTM_COEFF_2_0 (CTM_COEFF_1_0 << 1)
#define CTM_COEFF_4_0 (CTM_COEFF_2_0 << 1)
+#define CTM_COEFF_8_0 (CTM_COEFF_4_0 << 1)
#define CTM_COEFF_0_5 (CTM_COEFF_1_0 >> 1)
#define CTM_COEFF_0_25 (CTM_COEFF_0_5 >> 1)
#define CTM_COEFF_0_125 (CTM_COEFF_0_25 >> 1)
@@ -199,6 +200,58 @@ static void i9xx_load_csc_matrix(struct drm_crtc *crtc)
}
}
+/*
+ * Set up the pipe CSC unit on CherryView.
+ */
+static void cherryview_load_csc_matrix(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_crtc_state *state = crtc->state;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int pipe = to_intel_crtc(crtc)->pipe;
+ uint32_t mode;
+
+ if (state->ctm) {
+ struct drm_color_ctm *ctm =
+ (struct drm_color_ctm *) state->ctm->data;
+ uint16_t coeffs[9] = { 0, };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
+ uint64_t abs_coeff =
+ ((1ULL << 63) - 1) & ctm->matrix[i];
+
+ /* Round coefficient. */
+ abs_coeff += 1 << (32 - 13);
+ /* Clamp to hardware limits. */
+ abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
+
+ /* Write coefficients in S3.12 format. */
+ if (ctm->matrix[i] & (1ULL << 63))
+ coeffs[i] = 1 << 15;
+ coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
+ coeffs[i] |= (abs_coeff >> 20) & 0xfff;
+ }
+
+ I915_WRITE(CGM_PIPE_CSC_COEFF01(pipe),
+ coeffs[1] << 16 | coeffs[0]);
+ I915_WRITE(CGM_PIPE_CSC_COEFF23(pipe),
+ coeffs[3] << 16 | coeffs[2]);
+ I915_WRITE(CGM_PIPE_CSC_COEFF45(pipe),
+ coeffs[5] << 16 | coeffs[4]);
+ I915_WRITE(CGM_PIPE_CSC_COEFF67(pipe),
+ coeffs[7] << 16 | coeffs[6]);
+ I915_WRITE(CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
+ }
+
+ mode = (state->ctm ? CGM_PIPE_MODE_CSC : 0);
+ if (!crtc_state_is_legacy(state)) {
+ mode |= (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
+ (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0);
+ }
+ I915_WRITE(CGM_PIPE_MODE(pipe), mode);
+}
+
void intel_color_set_csc(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -209,10 +262,10 @@ void intel_color_set_csc(struct drm_crtc *crtc)
}
/* Loads the legacy palette/gamma unit for the CRTC. */
-static void i9xx_load_luts(struct drm_crtc *crtc)
+static void i9xx_load_luts_internal(struct drm_crtc *crtc,
+ struct drm_property_blob *blob)
{
struct drm_device *dev = crtc->dev;
- struct drm_crtc_state *state = crtc->state;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
enum pipe pipe = intel_crtc->pipe;
@@ -225,9 +278,8 @@ static void i9xx_load_luts(struct drm_crtc *crtc)
assert_pll_enabled(dev_priv, pipe);
}
- if (state->gamma_lut) {
- struct drm_color_lut *lut =
- (struct drm_color_lut *) state->gamma_lut->data;
+ if (blob) {
+ struct drm_color_lut *lut = (struct drm_color_lut *) blob->data;
for (i = 0; i < 256; i++) {
uint32_t word =
(drm_color_lut_extract(lut[i].red, 8) << 16) |
@@ -251,6 +303,11 @@ static void i9xx_load_luts(struct drm_crtc *crtc)
}
}
+static void i9xx_load_luts(struct drm_crtc *crtc)
+{
+ i9xx_load_luts_internal(crtc, crtc->state->gamma_lut);
+}
+
/* Loads the legacy palette/gamma unit for the CRTC on Haswell. */
static void haswell_load_luts(struct drm_crtc *crtc)
{
@@ -363,6 +420,67 @@ static void broadwell_load_luts(struct drm_crtc *crtc)
I915_WRITE(PREC_PAL_INDEX(pipe), 0);
}
+/* Loads the palette/gamma unit for the CRTC on CherryView. */
+static void cherryview_load_luts(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_crtc_state *state = crtc->state;
+ enum pipe pipe = to_intel_crtc(crtc)->pipe;
+ struct drm_color_lut *lut;
+ uint32_t i, lut_size;
+ uint32_t word0, word1;
+
+ if (crtc_state_is_legacy(state)) {
+ /* Turn off degamma/gamma on CGM block. */
+ I915_WRITE(CGM_PIPE_MODE(pipe),
+ (state->ctm ? CGM_PIPE_MODE_CSC : 0));
+ i9xx_load_luts_internal(crtc, state->gamma_lut);
+ return;
+ }
+
+ if (state->degamma_lut) {
+ lut = (struct drm_color_lut *) state->degamma_lut->data;
+ lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+ for (i = 0; i < lut_size; i++) {
+ /* Write LUT in U0.14 format. */
+ word0 =
+ (drm_color_lut_extract(lut[i].green, 14) << 16) |
+ drm_color_lut_extract(lut[i].blue, 14);
+ word1 = drm_color_lut_extract(lut[i].red, 14);
+
+ I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0), word0);
+ I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1), word1);
+ }
+ }
+
+ if (state->gamma_lut) {
+ lut = (struct drm_color_lut *) state->gamma_lut->data;
+ lut_size = INTEL_INFO(dev)->color.gamma_lut_size;
+ for (i = 0; i < lut_size; i++) {
+ /* Write LUT in U0.10 format. */
+ word0 =
+ (drm_color_lut_extract(lut[i].green, 10) << 16) |
+ drm_color_lut_extract(lut[i].blue, 10);
+ word1 = drm_color_lut_extract(lut[i].red, 10);
+
+ I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0), word0);
+ I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1), word1);
+ }
+ }
+
+ I915_WRITE(CGM_PIPE_MODE(pipe),
+ (state->ctm ? CGM_PIPE_MODE_CSC : 0) |
+ (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
+ (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0));
+
+ /*
+ * Also program a linear LUT in the legacy block (behind the
+ * CGM block).
+ */
+ i9xx_load_luts_internal(crtc, NULL);
+}
+
void intel_color_load_luts(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -415,7 +533,10 @@ void intel_color_init(struct drm_crtc *crtc)
drm_mode_crtc_set_gamma_size(crtc, 256);
- if (IS_HASWELL(dev)) {
+ if (IS_CHERRYVIEW(dev)) {
+ dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix;
+ dev_priv->display.load_luts = cherryview_load_luts;
+ } else if (IS_HASWELL(dev)) {
dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
dev_priv->display.load_luts = haswell_load_luts;
} else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) ||
--
2.7.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 8+ messages in thread
* ✗ Fi.CI.BAT: failure for Pipe level color management (rev11)
2016-03-16 10:57 [PATCH 0/4] Pipe level color management Lionel Landwerlin
` (3 preceding siblings ...)
2016-03-16 10:57 ` [PATCH 4/4] drm/i915: Implement color management on chv Lionel Landwerlin
@ 2016-03-16 13:30 ` Patchwork
2016-03-21 18:55 ` [PATCH 0/4] Pipe level color management Matt Roper
5 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2016-03-16 13:30 UTC (permalink / raw)
To: Lionel Landwerlin; +Cc: intel-gfx
== Series Details ==
Series: Pipe level color management (rev11)
URL : https://patchwork.freedesktop.org/series/2720/
State : failure
== Summary ==
Series 2720v11 Pipe level color management
http://patchwork.freedesktop.org/api/1.0/series/2720/revisions/11/mbox/
Test gem_mmap_gtt:
Subgroup basic-small-copy:
dmesg-warn -> PASS (bsw-nuc-2)
Test gem_ringfill:
Subgroup basic-default-s3:
dmesg-warn -> PASS (skl-i5k-2)
Test kms_flip:
Subgroup basic-flip-vs-modeset:
pass -> DMESG-WARN (bdw-ultra)
Subgroup basic-flip-vs-wf_vblank:
dmesg-warn -> PASS (hsw-brixbox)
Test kms_pipe_crc_basic:
Subgroup hang-read-crc-pipe-c:
pass -> SKIP (hsw-brixbox)
Test pm_rpm:
Subgroup basic-pci-d3-state:
dmesg-warn -> PASS (bsw-nuc-2)
Subgroup basic-rte:
pass -> DMESG-WARN (hsw-brixbox)
bdw-ultra total:194 pass:172 dwarn:1 dfail:0 fail:0 skip:21
bsw-nuc-2 total:194 pass:157 dwarn:0 dfail:0 fail:0 skip:37
byt-nuc total:194 pass:155 dwarn:4 dfail:0 fail:0 skip:35
hsw-brixbox total:194 pass:170 dwarn:1 dfail:0 fail:0 skip:23
hsw-gt2 total:194 pass:177 dwarn:0 dfail:0 fail:0 skip:17
ivb-t430s total:194 pass:169 dwarn:0 dfail:0 fail:0 skip:25
skl-i5k-2 total:194 pass:171 dwarn:0 dfail:0 fail:0 skip:23
skl-i7k-2 total:194 pass:171 dwarn:0 dfail:0 fail:0 skip:23
skl-nuci5 total:194 pass:183 dwarn:0 dfail:0 fail:0 skip:11
Results at /archive/results/CI_IGT_test/Patchwork_1615/
9f8709ffd099e85e5e116ed7d09f1b8009f40847 drm-intel-nightly: 2016y-03m-16d-10h-30m-26s UTC integration manifest
9b84bc994de6d1879289f9c471e2fb30f55250a3 drm/i915: Implement color management on chv
a51c386933a42418ee207ba970f8b7e115931134 drm/i915: Implement color management on bdw/skl/bxt/kbl
8a50bd779952ae795266ca1fc6ecfaa41cb03431 drm/i915: Do not read GAMMA_MODE register
fe9c12e6bbdf40611fc3e2e47f8b82d40145b962 drm/i915: Extract out gamma table and CSC to their own file
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4] Pipe level color management
2016-03-16 10:57 [PATCH 0/4] Pipe level color management Lionel Landwerlin
` (4 preceding siblings ...)
2016-03-16 13:30 ` ✗ Fi.CI.BAT: failure for Pipe level color management (rev11) Patchwork
@ 2016-03-21 18:55 ` Matt Roper
2016-03-22 10:57 ` Daniel Vetter
5 siblings, 1 reply; 8+ messages in thread
From: Matt Roper @ 2016-03-21 18:55 UTC (permalink / raw)
To: Lionel Landwerlin; +Cc: daniel.vetter, intel-gfx
On Wed, Mar 16, 2016 at 10:57:13AM +0000, Lionel Landwerlin wrote:
> This series introduces pipe level color management for Intel platforms
> on CherryView and Broadwell on.
>
> This series is based of a previous set of patches by Shashank Sharma.
>
> Cheers,
>
> Lionel
>
> v9: Rebase on nightly
>
> v10: Mask GAMMA_MODE register value (Matt Roper)
> Cleanup legacy LUT helper (Emil Velikov)
>
> v11: Rebase on drm-nightly
The only issues raised by CI were a sporadic error that we already have
a bug (and fix) for at
https://bugs.freedesktop.org/show_bug.cgi?id=94349
Everything looks good, so merged these to dinq and merged the
corresponding igt tests as well. Thanks for the patches.
Matt
>
> Lionel Landwerlin (4):
> drm/i915: Extract out gamma table and CSC to their own file
> drm/i915: Do not read GAMMA_MODE register
> drm/i915: Implement color management on bdw/skl/bxt/kbl
> drm/i915: Implement color management on chv
>
> Documentation/DocBook/gpu.tmpl | 6 +-
> drivers/gpu/drm/i915/Makefile | 1 +
> drivers/gpu/drm/i915/i915_drv.c | 27 +-
> drivers/gpu/drm/i915/i915_drv.h | 8 +
> drivers/gpu/drm/i915/i915_reg.h | 53 ++++
> drivers/gpu/drm/i915/intel_color.c | 556 +++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/i915/intel_display.c | 184 +++---------
> drivers/gpu/drm/i915/intel_drv.h | 12 +
> drivers/gpu/drm/i915/intel_fbdev.c | 8 +
> 9 files changed, 695 insertions(+), 160 deletions(-)
> create mode 100644 drivers/gpu/drm/i915/intel_color.c
>
> --
> 2.7.0
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4] Pipe level color management
2016-03-21 18:55 ` [PATCH 0/4] Pipe level color management Matt Roper
@ 2016-03-22 10:57 ` Daniel Vetter
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Vetter @ 2016-03-22 10:57 UTC (permalink / raw)
To: Matt Roper; +Cc: daniel.vetter, intel-gfx
On Mon, Mar 21, 2016 at 11:55:34AM -0700, Matt Roper wrote:
> On Wed, Mar 16, 2016 at 10:57:13AM +0000, Lionel Landwerlin wrote:
> > This series introduces pipe level color management for Intel platforms
> > on CherryView and Broadwell on.
> >
> > This series is based of a previous set of patches by Shashank Sharma.
> >
> > Cheers,
> >
> > Lionel
> >
> > v9: Rebase on nightly
> >
> > v10: Mask GAMMA_MODE register value (Matt Roper)
> > Cleanup legacy LUT helper (Emil Velikov)
> >
> > v11: Rebase on drm-nightly
>
> The only issues raised by CI were a sporadic error that we already have
> a bug (and fix) for at
> https://bugs.freedesktop.org/show_bug.cgi?id=94349
>
> Everything looks good, so merged these to dinq and merged the
> corresponding igt tests as well. Thanks for the patches.
Can we please, please fast-track this bugfix instead of piling ever more
features on? That ilk wm warning has been seriously annoying everyone for
a long time ...
And imo it's totally fine if the bugfix isn't perfect, as long as it's not
clearly a bad idea and a reasonable (first/minor/whatever) step towards
the real solution.
-Daniel
>
>
> Matt
>
> >
> > Lionel Landwerlin (4):
> > drm/i915: Extract out gamma table and CSC to their own file
> > drm/i915: Do not read GAMMA_MODE register
> > drm/i915: Implement color management on bdw/skl/bxt/kbl
> > drm/i915: Implement color management on chv
> >
> > Documentation/DocBook/gpu.tmpl | 6 +-
> > drivers/gpu/drm/i915/Makefile | 1 +
> > drivers/gpu/drm/i915/i915_drv.c | 27 +-
> > drivers/gpu/drm/i915/i915_drv.h | 8 +
> > drivers/gpu/drm/i915/i915_reg.h | 53 ++++
> > drivers/gpu/drm/i915/intel_color.c | 556 +++++++++++++++++++++++++++++++++++
> > drivers/gpu/drm/i915/intel_display.c | 184 +++---------
> > drivers/gpu/drm/i915/intel_drv.h | 12 +
> > drivers/gpu/drm/i915/intel_fbdev.c | 8 +
> > 9 files changed, 695 insertions(+), 160 deletions(-)
> > create mode 100644 drivers/gpu/drm/i915/intel_color.c
> >
> > --
> > 2.7.0
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@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
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2016-03-22 10:56 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-16 10:57 [PATCH 0/4] Pipe level color management Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 1/4] drm/i915: Extract out gamma table and CSC to their own file Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 2/4] drm/i915: Do not read GAMMA_MODE register Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 3/4] drm/i915: Implement color management on bdw/skl/bxt/kbl Lionel Landwerlin
2016-03-16 10:57 ` [PATCH 4/4] drm/i915: Implement color management on chv Lionel Landwerlin
2016-03-16 13:30 ` ✗ Fi.CI.BAT: failure for Pipe level color management (rev11) Patchwork
2016-03-21 18:55 ` [PATCH 0/4] Pipe level color management Matt Roper
2016-03-22 10:57 ` Daniel Vetter
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.