@@ -717,6 +717,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
{
struct drm_device *dev = plane->dev;
struct drm_mode_config *config = &dev->mode_config;
+ bool replaced = false;
+ int ret;
if (property == config->prop_fb_id) {
struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
@@ -762,6 +764,31 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
} else if (plane->funcs->atomic_set_property) {
return plane->funcs->atomic_set_property(plane, state,
property, val);
+ }
+ if (property == config->degamma_lut_property) {
+ ret = drm_atomic_replace_property_blob_from_id(dev,
+ &state->degamma_lut,
+ val,
+ -1,
+ &replaced);
+ state->color_mgmt_changed |= replaced;
+ return ret;
+ } else if (property == config->ctm_property) {
+ ret = drm_atomic_replace_property_blob_from_id(dev,
+ &state->ctm,
+ val,
+ sizeof(struct drm_color_ctm),
+ &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,
+ val,
+ -1,
+ &replaced);
+ state->color_mgmt_changed |= replaced;
+ return ret;
} else {
return -EINVAL;
}
@@ -814,6 +841,12 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
*val = state->src_w;
} else if (property == config->prop_src_h) {
*val = state->src_h;
+ } else if (property == config->degamma_lut_property) {
+ *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->gamma_lut_property) {
+ *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
} else if (property == plane->rotation_property) {
*val = state->rotation;
} else if (property == plane->zpos_property) {
@@ -3501,6 +3501,12 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
if (state->fb)
drm_framebuffer_get(state->fb);
+ if (state->degamma_lut)
+ drm_property_reference_blob(state->degamma_lut);
+ if (state->ctm)
+ drm_property_reference_blob(state->ctm);
+ if (state->gamma_lut)
+ drm_property_reference_blob(state->gamma_lut);
state->fence = NULL;
state->commit = NULL;
@@ -3548,6 +3554,9 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
if (state->commit)
drm_crtc_commit_put(state->commit);
+ drm_property_unreference_blob(state->degamma_lut);
+ drm_property_unreference_blob(state->ctm);
+ drm_property_unreference_blob(state->gamma_lut);
}
EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
@@ -90,6 +90,61 @@
* "GAMMA_LUT" property above.
*/
+static void drm_object_enable_color_mgmt(struct drm_mode_object *drm_object,
+ struct drm_mode_config *config,
+ uint degamma_lut_size,
+ bool has_ctm,
+ uint gamma_lut_size)
+{
+ if (degamma_lut_size) {
+ drm_object_attach_property(drm_object,
+ config->degamma_lut_property, 0);
+ drm_object_attach_property(drm_object,
+ config->degamma_lut_size_property,
+ degamma_lut_size);
+ }
+
+ if (has_ctm)
+ drm_object_attach_property(drm_object,
+ config->ctm_property, 0);
+
+ if (gamma_lut_size) {
+ drm_object_attach_property(drm_object,
+ config->gamma_lut_property, 0);
+ drm_object_attach_property(drm_object,
+ config->gamma_lut_size_property,
+ gamma_lut_size);
+ }
+}
+
+/**
+ * drm_plane_enable_color_mgmt - enable color management properties for a plane
+ * @plane: DRM plane
+ * @degamma_lut_size: the size of the degamma lut (before CSC)
+ * @has_ctm: whether to attach ctm_property for CSC matrix
+ * @gamma_lut_size: the size of the gamma lut (after CSC)
+ *
+ * This function lets the driver enable the color correction
+ * properties on a plane. This includes 3 degamma, csc and gamma
+ * properties that userspace can set and 2 size properties to inform
+ * the userspace of the lut sizes. Each of the properties is
+ * optional. The gamma and degamma properties are only attached if
+ * their size is not 0 and ctm_property is only attached if has_ctm is
+ * true.
+ */
+void drm_plane_enable_color_mgmt(struct drm_plane *plane,
+ uint degamma_lut_size,
+ bool has_ctm,
+ uint gamma_lut_size)
+{
+ struct drm_device *dev = plane->dev;
+ struct drm_mode_config *config = &dev->mode_config;
+
+ drm_object_enable_color_mgmt(&plane->base, config,
+ degamma_lut_size, has_ctm, gamma_lut_size);
+}
+EXPORT_SYMBOL(drm_plane_enable_color_mgmt);
+
/**
* drm_color_lut_extract - clamp and round LUT entries
* @user_input: input value
@@ -140,25 +195,8 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct drm_mode_config *config = &dev->mode_config;
- if (degamma_lut_size) {
- drm_object_attach_property(&crtc->base,
- config->degamma_lut_property, 0);
- drm_object_attach_property(&crtc->base,
- config->degamma_lut_size_property,
- degamma_lut_size);
- }
-
- if (has_ctm)
- drm_object_attach_property(&crtc->base,
- config->ctm_property, 0);
-
- if (gamma_lut_size) {
- drm_object_attach_property(&crtc->base,
- config->gamma_lut_property, 0);
- drm_object_attach_property(&crtc->base,
- config->gamma_lut_size_property,
- gamma_lut_size);
- }
+ drm_object_enable_color_mgmt(&crtc->base, config,
+ degamma_lut_size, has_ctm, gamma_lut_size);
}
EXPORT_SYMBOL(drm_crtc_enable_color_mgmt);
@@ -29,6 +29,11 @@ struct drm_crtc;
uint32_t drm_color_lut_extract(uint32_t user_input, uint32_t bit_precision);
+void drm_plane_enable_color_mgmt(struct drm_plane *plane,
+ uint degamma_lut_size,
+ bool has_ctm,
+ uint gamma_lut_size);
+
void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
uint degamma_lut_size,
bool has_ctm,
@@ -727,30 +727,30 @@ struct drm_mode_config {
*/
struct drm_property *aspect_ratio_property;
/**
- * @degamma_lut_property: Optional CRTC property to set the LUT used to
- * convert the framebuffer's colors to linear gamma.
+ * @degamma_lut_property: Optional CRTC or plane property to set the
+ * LUT used to convert the framebuffer's colors to linear gamma.
*/
struct drm_property *degamma_lut_property;
/**
- * @degamma_lut_size_property: Optional CRTC property for the size of
- * the degamma LUT as supported by the driver (read-only).
+ * @degamma_lut_size_property: Optional CRTC or plane property for the
+ * size of the degamma LUT as supported by the driver (read-only).
*/
struct drm_property *degamma_lut_size_property;
/**
- * @ctm_property: Optional CRTC property to set the
+ * @ctm_property: Optional CRTC or plane property to set the
* matrix used to convert colors after the lookup in the
* degamma LUT.
*/
struct drm_property *ctm_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
- * connected screen.
+ * @gamma_lut_property: Optional CRTC or plane property to set the LUT
+ * used to convert the colors, after the CTM matrix, to the gamma space
+ * of the connected screen.
*/
struct drm_property *gamma_lut_property;
/**
- * @gamma_lut_size_property: Optional CRTC property for the size of the
- * gamma LUT as supported by the driver (read-only).
+ * @gamma_lut_size_property: Optional CRTC or plane property for the
+ * size of the gamma LUT as supported by the driver (read-only).
*/
struct drm_property *gamma_lut_size_property;
@@ -105,6 +105,11 @@ struct drm_plane_state {
uint32_t src_x, src_y;
uint32_t src_h, src_w;
+ /* Color transform blob properties exposed to userspace */
+ struct drm_property_blob *degamma_lut;
+ struct drm_property_blob *ctm;
+ struct drm_property_blob *gamma_lut;
+
/* Plane rotation */
unsigned int rotation;
@@ -131,6 +136,9 @@ struct drm_plane_state {
*/
struct drm_crtc_commit *commit;
+ /* computed state bits used by drivers */
+ bool color_mgmt_changed : 1;
+
struct drm_atomic_state *state;
};