From afc34932439fdf134be391581edcee180dd0de80 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 6 Mar 2015 18:35:16 +0200 Subject: [PATCH] drm: omapdrm: Switch crtc and plane set_property to atomic helpers 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 Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 45 +++++++-- drivers/gpu/drm/omapdrm/omap_drv.h | 2 - drivers/gpu/drm/omapdrm/omap_plane.c | 180 +++++++++++++++++++++++------------ 3 files changed, 156 insertions(+), 71 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 646563e..b32a6fb 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -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 = { diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 580fe10..f520941 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -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); diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 7813e48..7011cb2 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -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, ©->base); + + return ©->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: -- 2.7.4