diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 646563e47562..b32a6fb05338 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; - return omap_plane_set_property(crtc->primary, property, val); + /* + * 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); +} + +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 580fe10184d7..f5209412fae6 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 7813e48b6896..7011cb23d3eb 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); - return omap_crtc_flush(plane->crtc); + if (property == priv->zorder_prop) + *val = omap_state->zorder; + else + return -EINVAL; + + 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: