drm: omapdrm: Switch crtc and plane set_property to atomic helpers
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 6 Mar 2015 16:35:16 +0000 (18:35 +0200)
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 12 Jun 2015 19:52:48 +0000 (22:52 +0300)
Allow setting up plane properties atomically using the plane
set_property atomic helper. The properties are now stored in the plane
state (requiring subclassing it) and applied when updating the planes.

The CRTC exposes the properties of its primary plane for legacy reason.
We can't get rid of that API, so simply delegate it to the primary
plane.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_drv.h
drivers/gpu/drm/omapdrm/omap_plane.c

index 646563e4756212d832bb2b10e5988362da9a4ea2..b32a6fb053389d38f4c88d12a2947fe0ed25cb16 100644 (file)
@@ -540,17 +540,44 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc)
        omap_crtc_flush(crtc);
 
        dispc_runtime_put();
+
+       crtc->invert_dimensions = !!(crtc->primary->state->rotation &
+                                   (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270)));
 }
 
-static int omap_crtc_set_property(struct drm_crtc *crtc,
-               struct drm_property *property, uint64_t val)
+static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
+                                        struct drm_crtc_state *state,
+                                        struct drm_property *property,
+                                        uint64_t val)
 {
-       if (property == crtc->dev->mode_config.rotation_property) {
-               crtc->invert_dimensions =
-                               !!(val & ((1LL << DRM_ROTATE_90) | (1LL << DRM_ROTATE_270)));
-       }
+       struct drm_plane_state *plane_state;
+       struct drm_plane *plane = crtc->primary;
+
+       /*
+        * Delegate property set to the primary plane. Get the plane state and
+        * set the property directly.
+        */
+
+       plane_state = drm_atomic_get_plane_state(state->state, plane);
+       if (!plane_state)
+               return -EINVAL;
+
+       return drm_atomic_plane_set_property(plane, plane_state, property, val);
+}
 
-       return omap_plane_set_property(crtc->primary, property, val);
+static int omap_crtc_atomic_get_property(struct drm_crtc *crtc,
+                                        const struct drm_crtc_state *state,
+                                        struct drm_property *property,
+                                        uint64_t *val)
+{
+       /*
+        * Delegate property get to the primary plane. The
+        * drm_atomic_plane_get_property() function isn't exported, but can be
+        * called through drm_object_property_get_value() as that will call
+        * drm_atomic_get_property() for atomic drivers.
+        */
+       return drm_object_property_get_value(&crtc->primary->base, property,
+                                            val);
 }
 
 static const struct drm_crtc_funcs omap_crtc_funcs = {
@@ -558,9 +585,11 @@ static const struct drm_crtc_funcs omap_crtc_funcs = {
        .set_config = drm_atomic_helper_set_config,
        .destroy = omap_crtc_destroy,
        .page_flip = drm_atomic_helper_page_flip,
-       .set_property = omap_crtc_set_property,
+       .set_property = drm_atomic_helper_crtc_set_property,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .atomic_set_property = omap_crtc_atomic_set_property,
+       .atomic_get_property = omap_crtc_atomic_get_property,
 };
 
 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
index 580fe10184d72becea35f13dc92c91d837e37060..f5209412fae64e94223514b075347155aac58d6e 100644 (file)
@@ -154,8 +154,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 int omap_plane_set_enable(struct drm_plane *plane, bool enable);
 void omap_plane_install_properties(struct drm_plane *plane,
                struct drm_mode_object *obj);
-int omap_plane_set_property(struct drm_plane *plane,
-               struct drm_property *property, uint64_t val);
 
 struct drm_encoder *omap_encoder_init(struct drm_device *dev,
                struct omap_dss_device *dssdev);
index 7813e48b6896d0863e9b436dce1fd7f907f57140..7011cb23d3ebb7f890d8d38af1145e74c6d2c10b 100644 (file)
@@ -51,10 +51,22 @@ struct omap_plane {
        struct omap_drm_irq error_irq;
 };
 
-static int __omap_plane_setup(struct omap_plane *omap_plane,
-                             struct drm_crtc *crtc,
-                             struct drm_framebuffer *fb)
+struct omap_plane_state {
+       struct drm_plane_state base;
+
+       unsigned int zorder;
+};
+
+static inline struct omap_plane_state *
+to_omap_plane_state(struct drm_plane_state *state)
 {
+       return container_of(state, struct omap_plane_state, base);
+}
+
+static int omap_plane_setup(struct omap_plane *omap_plane)
+{
+       struct drm_plane_state *state = omap_plane->base.state;
+       struct omap_plane_state *omap_state = to_omap_plane_state(state);
        struct omap_overlay_info *info = &omap_plane->info;
        struct drm_device *dev = omap_plane->base.dev;
        int ret;
@@ -66,8 +78,10 @@ static int __omap_plane_setup(struct omap_plane *omap_plane,
                return 0;
        }
 
+       info->zorder = omap_state->zorder;
+
        /* update scanout: */
-       omap_framebuffer_update_scanout(fb, &omap_plane->win, info);
+       omap_framebuffer_update_scanout(state->fb, &omap_plane->win, info);
 
        DBG("%dx%d -> %dx%d (%d)", info->width, info->height,
                        info->out_width, info->out_height,
@@ -76,11 +90,11 @@ static int __omap_plane_setup(struct omap_plane *omap_plane,
                        &info->paddr, &info->p_uv_addr);
 
        dispc_ovl_set_channel_out(omap_plane->id,
-                                 omap_crtc_channel(crtc));
+                                 omap_crtc_channel(state->crtc));
 
        /* and finally, update omapdss: */
        ret = dispc_ovl_setup(omap_plane->id, info, false,
-                             omap_crtc_timings(crtc), false);
+                             omap_crtc_timings(state->crtc), false);
        if (ret) {
                dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret);
                return ret;
@@ -91,27 +105,21 @@ static int __omap_plane_setup(struct omap_plane *omap_plane,
        return 0;
 }
 
-static int omap_plane_setup(struct omap_plane *omap_plane)
-{
-       struct drm_plane *plane = &omap_plane->base;
-       int ret;
-
-       dispc_runtime_get();
-       ret = __omap_plane_setup(omap_plane, plane->crtc, plane->fb);
-       dispc_runtime_put();
-
-       return ret;
-}
-
 int omap_plane_set_enable(struct drm_plane *plane, bool enable)
 {
        struct omap_plane *omap_plane = to_omap_plane(plane);
+       int ret;
 
        if (enable == omap_plane->enabled)
                return 0;
 
        omap_plane->enabled = enable;
-       return omap_plane_setup(omap_plane);
+
+       dispc_runtime_get();
+       ret = omap_plane_setup(omap_plane);
+       dispc_runtime_put();
+
+       return ret;
 }
 
 static int omap_plane_prepare_fb(struct drm_plane *plane,
@@ -140,8 +148,10 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
        if (!state->fb || !state->crtc)
                return;
 
+       win->rotation = state->rotation;
+
        /* omap_framebuffer_update_scanout() takes adjusted src */
-       switch (omap_plane->win.rotation & 0xf) {
+       switch (state->rotation & 0xf) {
        case BIT(DRM_ROTATE_90):
        case BIT(DRM_ROTATE_270):
                src_w = state->src_h;
@@ -165,23 +175,24 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
        win->src_h = src_h >> 16;
 
        omap_plane->enabled = true;
-       __omap_plane_setup(omap_plane, state->crtc, state->fb);
+       omap_plane_setup(omap_plane);
 }
 
 static void omap_plane_atomic_disable(struct drm_plane *plane,
                                      struct drm_plane_state *old_state)
 {
+       struct omap_plane_state *omap_state = to_omap_plane_state(plane->state);
        struct omap_plane *omap_plane = to_omap_plane(plane);
 
-       omap_plane->win.rotation = BIT(DRM_ROTATE_0);
-       omap_plane->info.zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
-                               ? 0 : omap_plane->id;
+       plane->state->rotation = BIT(DRM_ROTATE_0);
+       omap_state->zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
+                          ? 0 : omap_plane->id;
 
        if (!omap_plane->enabled)
                return;
 
        omap_plane->enabled = false;
-       __omap_plane_setup(omap_plane, NULL, NULL);
+       omap_plane_setup(omap_plane);
 }
 
 static const struct drm_plane_helper_funcs omap_plane_helper_funcs = {
@@ -191,6 +202,33 @@ static const struct drm_plane_helper_funcs omap_plane_helper_funcs = {
        .atomic_disable = omap_plane_atomic_disable,
 };
 
+static void omap_plane_reset(struct drm_plane *plane)
+{
+       struct omap_plane *omap_plane = to_omap_plane(plane);
+       struct omap_plane_state *omap_state;
+
+       if (plane->state && plane->state->fb)
+               drm_framebuffer_unreference(plane->state->fb);
+
+       kfree(plane->state);
+       plane->state = NULL;
+
+       omap_state = kzalloc(sizeof(*omap_state), GFP_KERNEL);
+       if (omap_state == NULL)
+               return;
+
+       /*
+        * Set defaults depending on whether we are a primary or overlay
+        * plane.
+        */
+       omap_state->zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
+                          ? 0 : omap_plane->id;
+       omap_state->base.rotation = BIT(DRM_ROTATE_0);
+
+       plane->state = &omap_state->base;
+       plane->state->plane = plane;
+}
+
 static void omap_plane_destroy(struct drm_plane *plane)
 {
        struct omap_plane *omap_plane = to_omap_plane(plane);
@@ -220,45 +258,75 @@ void omap_plane_install_properties(struct drm_plane *plane,
        drm_object_attach_property(obj, priv->zorder_prop, 0);
 }
 
-int omap_plane_set_property(struct drm_plane *plane,
-               struct drm_property *property, uint64_t val)
+static struct drm_plane_state *
+omap_plane_atomic_duplicate_state(struct drm_plane *plane)
+{
+       struct omap_plane_state *state;
+       struct omap_plane_state *copy;
+
+       if (WARN_ON(!plane->state))
+               return NULL;
+
+       state = to_omap_plane_state(plane->state);
+       copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
+       if (copy == NULL)
+               return NULL;
+
+       __drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
+
+       return &copy->base;
+}
+
+static void omap_plane_atomic_destroy_state(struct drm_plane *plane,
+                                           struct drm_plane_state *state)
+{
+       __drm_atomic_helper_plane_destroy_state(plane, state);
+       kfree(to_omap_plane_state(state));
+}
+
+static int omap_plane_atomic_set_property(struct drm_plane *plane,
+                                         struct drm_plane_state *state,
+                                         struct drm_property *property,
+                                         uint64_t val)
 {
-       struct omap_plane *omap_plane = to_omap_plane(plane);
        struct omap_drm_private *priv = plane->dev->dev_private;
-       int ret;
+       struct omap_plane_state *omap_state = to_omap_plane_state(state);
 
-       if (property == plane->dev->mode_config.rotation_property) {
-               DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val);
-               omap_plane->win.rotation = val;
-       } else if (property == priv->zorder_prop) {
-               DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val);
-               omap_plane->info.zorder = val;
-       } else {
+       if (property == priv->zorder_prop)
+               omap_state->zorder = val;
+       else
                return -EINVAL;
-       }
 
-       /*
-        * We're done if the plane is disabled, properties will be applied the
-        * next time it becomes enabled.
-        */
-       if (!omap_plane->enabled)
-               return 0;
+       return 0;
+}
 
-       ret = omap_plane_setup(omap_plane);
-       if (ret < 0)
-               return ret;
+static int omap_plane_atomic_get_property(struct drm_plane *plane,
+                                         const struct drm_plane_state *state,
+                                         struct drm_property *property,
+                                         uint64_t *val)
+{
+       struct omap_drm_private *priv = plane->dev->dev_private;
+       const struct omap_plane_state *omap_state =
+               container_of(state, const struct omap_plane_state, base);
+
+       if (property == priv->zorder_prop)
+               *val = omap_state->zorder;
+       else
+               return -EINVAL;
 
-       return omap_crtc_flush(plane->crtc);
+       return 0;
 }
 
 static const struct drm_plane_funcs omap_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
-       .reset = drm_atomic_helper_plane_reset,
+       .reset = omap_plane_reset,
        .destroy = omap_plane_destroy,
-       .set_property = omap_plane_set_property,
-       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+       .set_property = drm_atomic_helper_plane_set_property,
+       .atomic_duplicate_state = omap_plane_atomic_duplicate_state,
+       .atomic_destroy_state = omap_plane_atomic_destroy_state,
+       .atomic_set_property = omap_plane_atomic_set_property,
+       .atomic_get_property = omap_plane_atomic_get_property,
 };
 
 static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
@@ -330,16 +398,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
        info->global_alpha = 0xff;
        info->mirror = 0;
 
-       /* Set defaults depending on whether we are a CRTC or overlay
-        * layer.
-        * TODO add ioctl to give userspace an API to change this.. this
-        * will come in a subsequent patch.
-        */
-       if (type == DRM_PLANE_TYPE_PRIMARY)
-               omap_plane->info.zorder = 0;
-       else
-               omap_plane->info.zorder = id;
-
        return plane;
 
 error: