drm: introduce pipe color correction properties
[deliverable/linux.git] / drivers / gpu / drm / drm_atomic_helper.c
index 7a034b2317922be50c127ef49e63703f5781a84c..3e49a099319127106427246f1d8b04bf00ff55cd 100644 (file)
@@ -2495,8 +2495,12 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
  */
 void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
 {
-       if (crtc->state)
+       if (crtc->state) {
                drm_property_unreference_blob(crtc->state->mode_blob);
+               drm_property_unreference_blob(crtc->state->degamma_lut);
+               drm_property_unreference_blob(crtc->state->ctm);
+               drm_property_unreference_blob(crtc->state->gamma_lut);
+       }
        kfree(crtc->state);
        crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
 
@@ -2520,10 +2524,17 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
 
        if (state->mode_blob)
                drm_property_reference_blob(state->mode_blob);
+       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->mode_changed = false;
        state->active_changed = false;
        state->planes_changed = false;
        state->connectors_changed = false;
+       state->color_mgmt_changed = false;
        state->event = NULL;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
@@ -2564,6 +2575,9 @@ void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
                                            struct drm_crtc_state *state)
 {
        drm_property_unreference_blob(state->mode_blob);
+       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_crtc_destroy_state);
 
@@ -2877,3 +2891,97 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
        kfree(state);
 }
 EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
+
+/**
+ * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
+ * @crtc: CRTC object
+ * @red: red correction table
+ * @green: green correction table
+ * @blue: green correction table
+ * @start:
+ * @size: size of the tables
+ *
+ * Implements support for legacy gamma correction table for drivers
+ * that support color management through the DEGAMMA_LUT/GAMMA_LUT
+ * properties.
+ */
+void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
+                                       u16 *red, u16 *green, u16 *blue,
+                                       uint32_t start, uint32_t size)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_mode_config *config = &dev->mode_config;
+       struct drm_atomic_state *state;
+       struct drm_crtc_state *crtc_state;
+       struct drm_property_blob *blob = NULL;
+       struct drm_color_lut *blob_data;
+       int i, ret = 0;
+
+       state = drm_atomic_state_alloc(crtc->dev);
+       if (!state)
+               return;
+
+       blob = drm_property_create_blob(dev,
+                                       sizeof(struct drm_color_lut) * size,
+                                       NULL);
+       if (!blob) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       /* Prepare GAMMA_LUT with the legacy values. */
+       blob_data = (struct drm_color_lut *) blob->data;
+       for (i = 0; i < size; i++) {
+               blob_data[i].red = red[i];
+               blob_data[i].green = green[i];
+               blob_data[i].blue = blue[i];
+       }
+
+       state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
+retry:
+       crtc_state = drm_atomic_get_crtc_state(state, crtc);
+       if (IS_ERR(crtc_state)) {
+               ret = PTR_ERR(crtc_state);
+               goto fail;
+       }
+
+       /* Reset DEGAMMA_LUT and CTM properties. */
+       ret = drm_atomic_crtc_set_property(crtc, crtc_state,
+                       config->degamma_lut_property, 0);
+       if (ret)
+               goto fail;
+
+       ret = drm_atomic_crtc_set_property(crtc, crtc_state,
+                       config->ctm_property, 0);
+       if (ret)
+               goto fail;
+
+       ret = drm_atomic_crtc_set_property(crtc, crtc_state,
+                       config->gamma_lut_property, blob->base.id);
+       if (ret)
+               goto fail;
+
+       ret = drm_atomic_commit(state);
+       if (ret)
+               goto fail;
+
+       /* Driver takes ownership of state on successful commit. */
+
+       drm_property_unreference_blob(blob);
+
+       return;
+fail:
+       if (ret == -EDEADLK)
+               goto backoff;
+
+       drm_atomic_state_free(state);
+       drm_property_unreference_blob(blob);
+
+       return;
+backoff:
+       drm_atomic_state_clear(state);
+       drm_atomic_legacy_backoff(state);
+
+       goto retry;
+}
+EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
This page took 0.028449 seconds and 5 git commands to generate.