clear-pkgs-linux-iot-lts2018/0686-drm-i915-Add-interface...

251 lines
9.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Fan, Yugang" <yugang.fan@intel.com>
Date: Wed, 17 Oct 2018 10:39:24 +0800
Subject: [PATCH] drm/i915: Add interface to set ctm post offset
In Android a 4x4 color transform matrix is provided to set color
correction and color inversion, a post offset vector is also in
the matrix. As drm only provide 3x3 CTM for color transform, the
interface to set post offset is needed. So exposes it as CRTC
property named as "CTM_POST_OFFSET".
Rebased for kernel v4.19.
Change-Id: I06ede732ef3f82c07fbee1b7e7e853cdfc01ad70
Signed-off-by: Gao Chun <chun.gao@intel.com>
Signed-off-by: Yugang Fan
---
drivers/gpu/drm/drm_atomic.c | 10 ++++++++++
drivers/gpu/drm/drm_atomic_helper.c | 4 ++++
drivers/gpu/drm/drm_color_mgmt.c | 15 ++++++++++++++-
drivers/gpu/drm/drm_fb_helper.c | 1 +
drivers/gpu/drm/drm_mode_config.c | 7 +++++++
drivers/gpu/drm/i915/intel_color.c | 29 +++++++++++++++++++++++++----
include/drm/drm_crtc.h | 9 +++++++++
include/drm/drm_mode_config.h | 5 +++++
include/uapi/drm/drm_mode.h | 7 +++++++
9 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 4dac6f035c61..b1fcc77e2add 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -574,6 +574,14 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
&replaced);
state->color_mgmt_changed |= replaced;
return ret;
+ } else if (property == config->ctm_post_offset_property) {
+ ret = drm_atomic_replace_property_blob_from_id(dev,
+ &state->ctm_post_offset,
+ val,
+ sizeof(struct drm_color_ctm_post_offset), -1,
+ &replaced);
+ state->color_mgmt_changed |= replaced;
+ return ret;
} else if (property == config->gamma_lut_property) {
ret = drm_atomic_replace_property_blob_from_id(dev,
&state->gamma_lut,
@@ -636,6 +644,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
*val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
else if (property == config->ctm_property)
*val = (state->ctm) ? state->ctm->base.id : 0;
+ else if (property == config->ctm_post_offset_property)
+ *val = (state->ctm_post_offset) ? state->ctm_post_offset->base.id : 0;
else if (property == config->gamma_lut_property)
*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
else if (property == config->prop_out_fence_ptr)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 44ed41c19baa..198de948bb3f 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3518,6 +3518,8 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
drm_property_blob_get(state->degamma_lut);
if (state->ctm)
drm_property_blob_get(state->ctm);
+ if (state->ctm_post_offset)
+ drm_property_blob_get(state->ctm_post_offset);
if (state->gamma_lut)
drm_property_blob_get(state->gamma_lut);
state->mode_changed = false;
@@ -3587,6 +3589,7 @@ void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
drm_property_blob_put(state->mode_blob);
drm_property_blob_put(state->degamma_lut);
drm_property_blob_put(state->ctm);
+ drm_property_blob_put(state->ctm_post_offset);
drm_property_blob_put(state->gamma_lut);
}
EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
@@ -3983,6 +3986,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
/* Reset DEGAMMA_LUT and CTM properties. */
replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
+ replaced |= drm_property_replace_blob(&crtc_state->ctm_post_offset, NULL);
replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
crtc_state->color_mgmt_changed |= replaced;
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index b97e2de2c029..8fc8197059bd 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -64,6 +64,16 @@
* boot-up state too. Drivers can access the blob for the color conversion
* matrix through &drm_crtc_state.ctm.
*
+ * “CTM_POST_OFFSET”:
+ * Blob property to set post offset vector used to convert colors after
+ * applying ctm. The data is interpreted as a struct
+ * &drm_color_ctm_post_offset.
+ *
+ * Setting this to NULL (blob property value set to 0) means a pass-thru
+ * vector should be used. This is generally the driver boot-up state too.
+ * Drivers can access the blob for post offset vector through
+ * &drm_crtc_state.ctm_post_offset.
+ *
* “GAMMA_LUT”:
* Blob property to set the gamma lookup table (LUT) mapping pixel data
* after the transformation matrix to data sent to the connector. The
@@ -162,9 +172,12 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
degamma_lut_size);
}
- if (has_ctm)
+ if (has_ctm){
drm_object_attach_property(&crtc->base,
config->ctm_property, 0);
+ drm_object_attach_property(&crtc->base,
+ config->ctm_post_offset_property, 0);
+ }
if (gamma_lut_size) {
drm_object_attach_property(&crtc->base,
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 8cf32d9e2921..a1f3e28199bd 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1464,6 +1464,7 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
replaced = drm_property_replace_blob(&crtc_state->degamma_lut,
NULL);
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
+ replaced |= drm_property_replace_blob(&crtc_state->ctm_post_offset, NULL);
replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
gamma_lut);
crtc_state->color_mgmt_changed |= replaced;
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index 21e353bd3948..1d6ea4bb4838 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -332,6 +332,13 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
return -ENOMEM;
dev->mode_config.ctm_property = prop;
+ prop = drm_property_create(dev,
+ DRM_MODE_PROP_BLOB,
+ "CTM_POST_OFFSET", 0);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.ctm_post_offset_property = prop;
+
prop = drm_property_create(dev,
DRM_MODE_PROP_BLOB,
"GAMMA_LUT", 0);
diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
index c6a7beabd58d..8d41c8f7042a 100644
--- a/drivers/gpu/drm/i915/intel_color.c
+++ b/drivers/gpu/drm/i915/intel_color.c
@@ -230,13 +230,34 @@ static void ilk_load_csc_matrix(struct drm_crtc_state *crtc_state)
if (INTEL_GEN(dev_priv) > 6) {
uint16_t postoff = 0;
+ uint16_t postoff_red = 0;
+ uint16_t postoff_green = 0;
+ uint16_t postoff_blue = 0;
- if (limited_color_range)
+ if (limited_color_range){
postoff = (16 * (1 << 12) / 255) & 0x1fff;
+ postoff_red = postoff;
+ postoff_green = postoff;
+ postoff_blue = postoff;
+ }
+
+ if (crtc_state->ctm_post_offset) {
+ struct drm_color_ctm_post_offset *ctm_post_offset =
+ (struct drm_color_ctm_post_offset *)crtc_state->ctm_post_offset->data;
+
+ /* Convert to U0.12 format. */
+ postoff_red = ctm_post_offset->red >> 4;
+ postoff_green = ctm_post_offset->green >> 4;
+ postoff_blue = ctm_post_offset->blue >> 4;
+
+ postoff_red = clamp_val(postoff_red, postoff, 0xfff);
+ postoff_green = clamp_val(postoff_green, postoff, 0xfff);
+ postoff_blue = clamp_val(postoff_blue, postoff, 0xfff);
+ }
- 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_POSTOFF_HI(pipe), postoff_red);
+ I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff_green);
+ I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff_blue);
I915_WRITE(PIPE_CSC_MODE(pipe), 0);
} else {
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 92e7fc7f05a4..5e4f8d83181d 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -265,6 +265,15 @@ struct drm_crtc_state {
*/
struct drm_property_blob *ctm;
+ /**
+ * @ctm_post_offset:
+ *
+ * Post offset used to convert colors after applying ctm. See
+ * drm_crtc_enable_color_mgmt().The blob (if not NULL) is a &struct
+ * drm_color_ctm_post_offset.
+ */
+ struct drm_property_blob *ctm_post_offset;
+
/**
* @gamma_lut:
*
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index a0b202e1d69a..f606d2d2cbe1 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -747,6 +747,11 @@ struct drm_mode_config {
* degamma LUT.
*/
struct drm_property *ctm_property;
+ /**
+ * @ctm_post_offset_property: Optional CRTC property to set the
+ * post offset used to convert colors after applying ctm.
+ */
+ struct drm_property *ctm_post_offset_property;
/**
* @gamma_lut_property: Optional CRTC property to set the LUT used to
* convert the colors, after the CTM matrix, to the gamma space of the
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 926d80323b55..6e9e2d66a83b 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -647,6 +647,13 @@ struct drm_color_ctm {
__u64 matrix[9];
};
+struct drm_color_ctm_post_offset {
+ /* Data is U0.16 fixed point format. */
+ __u16 red;
+ __u16 green;
+ __u16 blue;
+};
+
struct drm_color_lut {
/*
* Data is U0.16 fixed point format.
--
https://clearlinux.org