drm/armada: move CBSH properties into overlay plane state
authorRussell King <rmk+kernel@armlinux.org.uk>
Mon, 30 Jul 2018 10:52:34 +0000 (11:52 +0100)
committerRussell King <rmk+kernel@armlinux.org.uk>
Mon, 30 Jul 2018 10:52:34 +0000 (11:52 +0100)
Move the contrast, brightness, and saturation properties to the overlay
plane state structure, and call our overlay commit function to update
the hardware via the planes atomic_update() method.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
drivers/gpu/drm/armada/armada_crtc.h
drivers/gpu/drm/armada/armada_overlay.c

index 73ddd7d61eb48b77b7abc082389a3268171b9005..c27435a8776a8556aa74c5cf6d9fba149b549f7f 100644 (file)
@@ -42,7 +42,7 @@ struct armada_plane_work {
        struct drm_plane *plane;
        struct drm_framebuffer *old_fb;
        struct drm_pending_vblank_event *event;
-       struct armada_regs regs[14];
+       struct armada_regs regs[24];
 };
 
 struct armada_plane {
index 40868e485ae81993da713d3dbe7180e6b35ad7ec..ec3ce28f162e3fc5c66ca070b4d2d80647b26b70 100644 (file)
 #include "armada_plane.h"
 #include "armada_trace.h"
 
+#define DEFAULT_BRIGHTNESS     0
+#define DEFAULT_CONTRAST       0x4000
+#define DEFAULT_SATURATION     0x4000
+
 struct armada_ovl_plane_properties {
        uint32_t colorkey_yr;
        uint32_t colorkey_ug;
@@ -27,9 +31,6 @@ struct armada_ovl_plane_properties {
 #define K2R(val) (((val) >> 0) & 0xff)
 #define K2G(val) (((val) >> 8) & 0xff)
 #define K2B(val) (((val) >> 16) & 0xff)
-       int16_t  brightness;
-       uint16_t contrast;
-       uint16_t saturation;
        uint32_t colorkey_mode;
        uint32_t colorkey_enable;
 };
@@ -44,6 +45,26 @@ struct armada_ovl_plane {
 #define drm_to_armada_ovl_plane(p) \
        container_of(p, struct armada_ovl_plane, base.base)
 
+struct armada_overlay_state {
+       struct drm_plane_state base;
+       s16 brightness;
+       u16 contrast;
+       u16 saturation;
+};
+#define drm_to_overlay_state(s) \
+       container_of(s, struct armada_overlay_state, base)
+
+static inline u32 armada_spu_contrast(struct drm_plane_state *state)
+{
+       return drm_to_overlay_state(state)->brightness << 16 |
+              drm_to_overlay_state(state)->contrast;
+}
+
+static inline u32 armada_spu_saturation(struct drm_plane_state *state)
+{
+       /* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */
+       return drm_to_overlay_state(state)->saturation << 16;
+}
 
 static void
 armada_ovl_update_attr(struct armada_ovl_plane_properties *prop,
@@ -53,13 +74,6 @@ armada_ovl_update_attr(struct armada_ovl_plane_properties *prop,
        writel_relaxed(prop->colorkey_ug, dcrtc->base + LCD_SPU_COLORKEY_U);
        writel_relaxed(prop->colorkey_vb, dcrtc->base + LCD_SPU_COLORKEY_V);
 
-       writel_relaxed(prop->brightness << 16 | prop->contrast,
-                      dcrtc->base + LCD_SPU_CONTRAST);
-       /* Docs say 15:0, but it seems to actually be 31:16 on Armada 510 */
-       writel_relaxed(prop->saturation << 16,
-                      dcrtc->base + LCD_SPU_SATURATION);
-       writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE);
-
        spin_lock_irq(&dcrtc->irq_lock);
        armada_updatel(prop->colorkey_mode,
                       CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
@@ -191,6 +205,17 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
                armada_reg_queue_mod(regs, idx, cfg, cfg_mask,
                                     LCD_SPU_DMA_CTRL0);
 
+       val = armada_spu_contrast(state);
+       if ((!old_state->visible && state->visible) ||
+           armada_spu_contrast(old_state) != val)
+               armada_reg_queue_set(regs, idx, val, LCD_SPU_CONTRAST);
+       val = armada_spu_saturation(state);
+       if ((!old_state->visible && state->visible) ||
+           armada_spu_saturation(old_state) != val)
+               armada_reg_queue_set(regs, idx, val, LCD_SPU_SATURATION);
+       if (!old_state->visible && state->visible)
+               armada_reg_queue_set(regs, idx, 0x00002000, LCD_SPU_CBSH_HUE);
+
        dcrtc->regs_idx += idx;
 }
 
@@ -264,6 +289,10 @@ static int armada_overlay_commit(struct drm_plane *plane,
        /* Point of no return */
        swap(plane->state, state);
 
+       /* No CRTC, can't update */
+       if (!plane->state->crtc)
+               goto put_state;
+
        dcrtc->regs_idx = 0;
        dcrtc->regs = work->regs;
 
@@ -300,7 +329,7 @@ static int armada_overlay_commit(struct drm_plane *plane,
        dplane->next_work = !dplane->next_work;
 
 put_state:
-       drm_atomic_helper_plane_destroy_state(plane, state);
+       plane->funcs->atomic_destroy_state(plane, state);
        return ret;
 }
 
@@ -318,7 +347,7 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
                                 src_x, src_y, src_w, src_h);
 
        /* Construct new state for the overlay plane */
-       state = drm_atomic_helper_plane_duplicate_state(plane);
+       state = plane->funcs->atomic_duplicate_state(plane);
        if (!state)
                return -ENOMEM;
 
@@ -404,15 +433,22 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane,
                        dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
                }
                update_attr = true;
-       } else if (property == priv->brightness_prop) {
-               dplane->prop.brightness = val - 256;
-               update_attr = true;
-       } else if (property == priv->contrast_prop) {
-               dplane->prop.contrast = val;
-               update_attr = true;
-       } else if (property == priv->saturation_prop) {
-               dplane->prop.saturation = val;
-               update_attr = true;
+       } else {
+               struct drm_plane_state *state;
+               int ret;
+
+               state = plane->funcs->atomic_duplicate_state(plane);
+               if (!state)
+                       return -ENOMEM;
+
+               ret = plane->funcs->atomic_set_property(plane, state, property,
+                                                       val);
+               if (ret) {
+                       plane->funcs->atomic_destroy_state(plane, state);
+                       return ret;
+               }
+
+               return armada_overlay_commit(plane, state);
        }
 
        if (update_attr && dplane->base.base.crtc)
@@ -422,12 +458,85 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane,
        return 0;
 }
 
+static void armada_overlay_reset(struct drm_plane *plane)
+{
+       struct armada_overlay_state *state;
+
+       if (plane->state)
+               __drm_atomic_helper_plane_destroy_state(plane->state);
+       kfree(plane->state);
+
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (state) {
+               state->base.plane = plane;
+               state->base.rotation = DRM_MODE_ROTATE_0;
+               state->brightness = DEFAULT_BRIGHTNESS;
+               state->contrast = DEFAULT_CONTRAST;
+               state->saturation = DEFAULT_SATURATION;
+       }
+       plane->state = &state->base;
+}
+
+struct drm_plane_state *
+armada_overlay_duplicate_state(struct drm_plane *plane)
+{
+       struct armada_overlay_state *state;
+
+       if (WARN_ON(!plane->state))
+               return NULL;
+
+       state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL);
+       if (state)
+               __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
+       return &state->base;
+}
+
+static int armada_overlay_set_property(struct drm_plane *plane,
+       struct drm_plane_state *state, struct drm_property *property,
+       uint64_t val)
+{
+       struct armada_private *priv = plane->dev->dev_private;
+
+       if (property == priv->brightness_prop) {
+               drm_to_overlay_state(state)->brightness = val - 256;
+       } else if (property == priv->contrast_prop) {
+               drm_to_overlay_state(state)->contrast = val;
+       } else if (property == priv->saturation_prop) {
+               drm_to_overlay_state(state)->saturation = val;
+       } else {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int armada_overlay_get_property(struct drm_plane *plane,
+       const struct drm_plane_state *state, struct drm_property *property,
+       uint64_t *val)
+{
+       struct armada_private *priv = plane->dev->dev_private;
+
+       if (property == priv->brightness_prop) {
+               *val = drm_to_overlay_state(state)->brightness + 256;
+       } else if (property == priv->contrast_prop) {
+               *val = drm_to_overlay_state(state)->contrast;
+       } else if (property == priv->saturation_prop) {
+               *val = drm_to_overlay_state(state)->saturation;
+       } else {
+               return -EINVAL;
+       }
+       return 0;
+}
+
 static const struct drm_plane_funcs armada_ovl_plane_funcs = {
        .update_plane   = armada_ovl_plane_update,
        .disable_plane  = drm_plane_helper_disable,
        .destroy        = armada_ovl_plane_destroy,
        .set_property   = armada_ovl_plane_set_property,
-       .reset          = drm_atomic_helper_plane_reset,
+       .reset          = armada_overlay_reset,
+       .atomic_duplicate_state = armada_overlay_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+       .atomic_set_property = armada_overlay_set_property,
+       .atomic_get_property = armada_overlay_get_property,
 };
 
 static const uint32_t armada_ovl_formats[] = {
@@ -542,9 +651,6 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
        dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB) |
                                     CFG_ALPHAM_GRA | CFG_ALPHA(0);
        dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
-       dplane->prop.brightness = 0;
-       dplane->prop.contrast = 0x4000;
-       dplane->prop.saturation = 0x4000;
 
        mobj = &dplane->base.base.base;
        drm_object_attach_property(mobj, priv->colorkey_prop,
@@ -559,11 +665,12 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
                                   0x000000);
        drm_object_attach_property(mobj, priv->colorkey_mode_prop,
                                   CKMODE_RGB);
-       drm_object_attach_property(mobj, priv->brightness_prop, 256);
+       drm_object_attach_property(mobj, priv->brightness_prop,
+                                  256 + DEFAULT_BRIGHTNESS);
        drm_object_attach_property(mobj, priv->contrast_prop,
-                                  dplane->prop.contrast);
+                                  DEFAULT_CONTRAST);
        drm_object_attach_property(mobj, priv->saturation_prop,
-                                  dplane->prop.saturation);
+                                  DEFAULT_SATURATION);
 
        return 0;
 }