drm/exynos: make zpos property configurable
authorMarek Szyprowski <m.szyprowski@samsung.com>
Wed, 16 Dec 2015 12:21:43 +0000 (13:21 +0100)
committerInki Dae <daeinki@gmail.com>
Tue, 12 Jan 2016 15:16:34 +0000 (00:16 +0900)
This patch adds all infrastructure to make zpos plane property
configurable from userspace.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_plane.c

index 588b6763f9c7a89b01d2c167e648aea7058b6ae5..f0827dbebb7ddb6d1a20f8d91fdc58f65cf4f9c1 100644 (file)
@@ -64,6 +64,7 @@ struct exynos_drm_plane_state {
        struct exynos_drm_rect src;
        unsigned int h_ratio;
        unsigned int v_ratio;
+       unsigned int zpos;
 };
 
 static inline struct exynos_drm_plane_state *
@@ -91,11 +92,12 @@ struct exynos_drm_plane {
 
 #define EXYNOS_DRM_PLANE_CAP_DOUBLE    (1 << 0)
 #define EXYNOS_DRM_PLANE_CAP_SCALE     (1 << 1)
+#define EXYNOS_DRM_PLANE_CAP_ZPOS      (1 << 2)
 
 /*
  * Exynos DRM plane configuration structure.
  *
- * @zpos: z-position of the plane.
+ * @zpos: initial z-position of the plane.
  * @type: type of the plane (primary, cursor or overlay).
  * @pixel_formats: supported pixel formats.
  * @num_pixel_formats: number of elements in 'pixel_formats'.
index e45730ad67f2b2c03bb4b03c18cbe7c84f2adf64..d86227236f5519f93099565622956f00530b7e24 100644 (file)
@@ -124,6 +124,7 @@ static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
 
 static void exynos_drm_plane_reset(struct drm_plane *plane)
 {
+       struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
        struct exynos_drm_plane_state *exynos_state;
 
        if (plane->state) {
@@ -136,6 +137,7 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
 
        exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
        if (exynos_state) {
+               exynos_state->zpos = exynos_plane->config->zpos;
                plane->state = &exynos_state->base;
                plane->state->plane = plane;
        }
@@ -153,6 +155,7 @@ exynos_drm_plane_duplicate_state(struct drm_plane *plane)
                return NULL;
 
        __drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
+       copy->zpos = exynos_state->zpos;
        return &copy->base;
 }
 
@@ -165,13 +168,53 @@ static void exynos_drm_plane_destroy_state(struct drm_plane *plane,
        kfree(old_exynos_state);
 }
 
+static int exynos_drm_plane_atomic_set_property(struct drm_plane *plane,
+                                               struct drm_plane_state *state,
+                                               struct drm_property *property,
+                                               uint64_t val)
+{
+       struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
+       struct exynos_drm_plane_state *exynos_state =
+                                       to_exynos_plane_state(state);
+       struct exynos_drm_private *dev_priv = plane->dev->dev_private;
+       const struct exynos_drm_plane_config *config = exynos_plane->config;
+
+       if (property == dev_priv->plane_zpos_property &&
+           (config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS))
+               exynos_state->zpos = val;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int exynos_drm_plane_atomic_get_property(struct drm_plane *plane,
+                                         const struct drm_plane_state *state,
+                                         struct drm_property *property,
+                                         uint64_t *val)
+{
+       const struct exynos_drm_plane_state *exynos_state =
+               container_of(state, const struct exynos_drm_plane_state, base);
+       struct exynos_drm_private *dev_priv = plane->dev->dev_private;
+
+       if (property == dev_priv->plane_zpos_property)
+               *val = exynos_state->zpos;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
 static struct drm_plane_funcs exynos_plane_funcs = {
        .update_plane   = drm_atomic_helper_update_plane,
        .disable_plane  = drm_atomic_helper_disable_plane,
        .destroy        = drm_plane_cleanup,
+       .set_property   = drm_atomic_helper_plane_set_property,
        .reset          = exynos_drm_plane_reset,
        .atomic_duplicate_state = exynos_drm_plane_duplicate_state,
        .atomic_destroy_state = exynos_drm_plane_destroy_state,
+       .atomic_set_property = exynos_drm_plane_atomic_set_property,
+       .atomic_get_property = exynos_drm_plane_atomic_get_property,
 };
 
 static int
@@ -267,8 +310,8 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
 
        prop = dev_priv->plane_zpos_property;
        if (!prop) {
-               prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE,
-                                                "zpos", 0, MAX_PLANE - 1);
+               prop = drm_property_create_range(dev, 0, "zpos",
+                                                0, MAX_PLANE - 1);
                if (!prop)
                        return;
 
@@ -301,9 +344,7 @@ int exynos_plane_init(struct drm_device *dev,
        exynos_plane->index = index;
        exynos_plane->config = config;
 
-       if (config->type == DRM_PLANE_TYPE_OVERLAY)
-               exynos_plane_attach_zpos_property(&exynos_plane->base,
-                                                 config->zpos);
+       exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos);
 
        return 0;
 }