v1:
1. Fix typos
2. Remove the LUT size check from intel driver
3. Rename old LUT check to indicate it's a channel change
Signed-off-by: Mark Yacoub <markyacoub@xxxxxxxxxxxx>
---
drivers/gpu/drm/drm_atomic_helper.c | 60 ++++++++++++++++++++++
drivers/gpu/drm/drm_color_mgmt.c | 14 ++---
drivers/gpu/drm/i915/display/intel_color.c | 14 ++---
include/drm/drm_atomic_helper.h | 1 +
include/drm/drm_color_mgmt.h | 7 +--
include/drm/drm_crtc.h | 11 ++++
6 files changed, 89 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index bc3487964fb5e..5feb2ad0209c3 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -929,6 +929,62 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
}
EXPORT_SYMBOL(drm_atomic_helper_check_planes);
+/**
+ * drm_atomic_helper_check_crtcs - validate state object for CRTC changes
+ * @state: the driver state object
+ *
+ * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the new
+ * state holds them.
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state)
+{
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *new_crtc_state;
+ int i;
+
+ for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) {
+ if (new_crtc_state->color_mgmt_changed &&
+ new_crtc_state->gamma_lut) {
+ uint64_t supported_lut_size = crtc->gamma_lut_size;
+ uint32_t supported_legacy_lut_size = crtc->gamma_size;
+ uint32_t new_state_lut_size =
+ drm_color_lut_size(new_crtc_state->gamma_lut);
+
+ if (new_state_lut_size != supported_lut_size &&
+ new_state_lut_size != supported_legacy_lut_size) {
+ drm_dbg_state(
+ state->dev,
+ "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n",
+ supported_lut_size,
+ supported_legacy_lut_size,
+ new_state_lut_size);
+ return -EINVAL;
+ }
+ }
+
+ if (new_crtc_state->color_mgmt_changed &&
+ new_crtc_state->degamma_lut) {
+ uint32_t new_state_lut_size =
+ drm_color_lut_size(new_crtc_state->degamma_lut);
+ uint64_t supported_lut_size = crtc->degamma_lut_size;
+
+ if (new_state_lut_size != supported_lut_size) {
+ drm_dbg_state(
+ state->dev,
+ "Invalid Degamma LUT size. Should be %u but got %u.\n",
+ supported_lut_size, new_state_lut_size);
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_atomic_helper_check_crtcs);
+
/**
* drm_atomic_helper_check - validate state object
* @dev: DRM device
@@ -974,6 +1030,10 @@ int drm_atomic_helper_check(struct drm_device *dev,
if (ret)
return ret;
+ ret = drm_atomic_helper_check_crtcs(state);
+ if (ret)
+ return ret;
+
if (state->legacy_cursor_update)
state->async_update = !drm_atomic_helper_async_check(dev, state);
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index bb14f488c8f6c..e5b820ce823bf 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -166,6 +166,7 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
struct drm_mode_config *config = &dev->mode_config;
if (degamma_lut_size) {
+ crtc->degamma_lut_size = degamma_lut_size;
drm_object_attach_property(&crtc->base,
config->degamma_lut_property, 0);
drm_object_attach_property(&crtc->base,
@@ -178,6 +179,7 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
config->ctm_property, 0);
if (gamma_lut_size) {
+ crtc->gamma_lut_size = gamma_lut_size;
drm_object_attach_property(&crtc->base,
config->gamma_lut_property, 0);
drm_object_attach_property(&crtc->base,
@@ -585,17 +587,17 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
EXPORT_SYMBOL(drm_plane_create_color_properties);
/**
- * drm_color_lut_check - check validity of lookup table
+ * drm_color_lut_channels_check - check validity of the channels in the lookup table
* @lut: property blob containing LUT to check
* @tests: bitmask of tests to run
*
- * Helper to check whether a userspace-provided lookup table is valid and
- * satisfies hardware requirements. Drivers pass a bitmask indicating which of
- * the tests in &drm_color_lut_tests should be performed.
+ * Helper to check whether each color channel of userspace-provided lookup table is valid and
+ * satisfies hardware requirements. Drivers pass a bitmask indicating which of in
+ * &drm_color_lut_channels_tests should be performed.
*
* Returns 0 on success, -EINVAL on failure.
*/
-int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests)
+int drm_color_lut_channels_check(const struct drm_property_blob *lut, u32 tests)
{
const struct drm_color_lut *entry;
int i;
@@ -625,4 +627,4 @@ int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests)
return 0;
}
-EXPORT_SYMBOL(drm_color_lut_check);
+EXPORT_SYMBOL(drm_color_lut_channels_check);
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index dab892d2251ba..a308fe52746ac 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -1285,7 +1285,7 @@ static int check_luts(const struct intel_crtc_state *crtc_state)
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
int gamma_length, degamma_length;
- u32 gamma_tests, degamma_tests;
+ u32 gamma_channels_tests, degamma_channels_tests;
/* Always allow legacy gamma LUT with no further checking. */
if (crtc_state_is_legacy_gamma(crtc_state))
@@ -1300,15 +1300,11 @@ static int check_luts(const struct intel_crtc_state *crtc_state)
degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size;
gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size;
- degamma_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests;
- gamma_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests;
+ degamma_channels_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests;
+ gamma_channels_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests;
- if (check_lut_size(degamma_lut, degamma_length) ||
- check_lut_size(gamma_lut, gamma_length))
- return -EINVAL;
-
- if (drm_color_lut_check(degamma_lut, degamma_tests) ||
- drm_color_lut_check(gamma_lut, gamma_tests))
+ if (drm_color_lut_channels_check(degamma_lut, degamma_channels_tests) ||
+ drm_color_lut_channels_check(gamma_lut, gamma_channels_tests))
return -EINVAL;
return 0;
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 4045e2507e11c..a22d32a7a8719 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -38,6 +38,7 @@ struct drm_atomic_state;
struct drm_private_obj;
struct drm_private_state;
+int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state);
int drm_atomic_helper_check_modeset(struct drm_device *dev,
struct drm_atomic_state *state);
int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 81c298488b0c8..cb1bf361ad3e3 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -94,12 +94,12 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
enum drm_color_range default_range);
/**
- * enum drm_color_lut_tests - hw-specific LUT tests to perform
+ * enum drm_color_lut_channels_tests - hw-specific LUT tests to perform
*
* The drm_color_lut_check() function takes a bitmask of the values here to
* determine which tests to apply to a userspace-provided LUT.
*/
-enum drm_color_lut_tests {
+enum drm_color_lut_channels_tests {
/**
* @DRM_COLOR_LUT_EQUAL_CHANNELS:
*
@@ -119,5 +119,6 @@ enum drm_color_lut_tests {
DRM_COLOR_LUT_NON_DECREASING = BIT(1),
};
-int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests);
+int drm_color_lut_channels_check(const struct drm_property_blob *lut,
+ u32 tests);
#endif
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 2deb15d7e1610..cabd3ef1a6e32 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1072,6 +1072,17 @@ struct drm_crtc {
/** @funcs: CRTC control functions */
const struct drm_crtc_funcs *funcs;
+ /**
+ * @degamma_lut_size: Size of degamma LUT.
+ */
+ uint32_t degamma_lut_size;
+
+ /**
+ * @gamma_lut_size: Size of Gamma LUT. Not used by legacy userspace such as
+ * X, which doesn't support large lut sizes.
+ */
+ uint32_t gamma_lut_size;
+
/**
* @gamma_size: Size of legacy gamma ramp reported to userspace. Set up
* by calling drm_mode_crtc_set_gamma_size().