MDP5 SSPPs can flip the input source horizontally or vertically.
This change is to add this support to MDP5 planes.
v1: Initial change
v2: Use existing "rotation" property instead of creating msm specific
    properties. In order to be compatiable with legacy non-atomic
    set_property, switch to drm_atomic_helper_plane_set_property
    helper function.

Signed-off-by: Jilai Wang <jilaiw at codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 49 ++++++++++++++++++++++++++-----
 1 file changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 1fbb17d..ec5b24c6 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -88,6 +88,26 @@ static const struct drm_prop_enum_list 
premultiplied_prop_enum_list[] = {
        { 1, "true" },
 };

+static void mdp5_plane_install_rotation_property(struct drm_device *dev,
+               struct drm_plane *plane)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+
+       if (!(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP) &&
+               !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP))
+               return;
+
+       if (!dev->mode_config.rotation_property)
+               dev->mode_config.rotation_property =
+                       drm_mode_create_rotation_property(dev,
+                       BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y));
+
+       if (dev->mode_config.rotation_property)
+               drm_object_attach_property(&plane->base,
+                       dev->mode_config.rotation_property,
+                       0);
+}
+
 /* helper to install properties which are common to planes and crtcs */
 void mdp5_plane_install_properties(struct drm_plane *plane,
                struct drm_mode_object *obj)
@@ -125,6 +145,8 @@ void mdp5_plane_install_properties(struct drm_plane *plane,
        INSTALL_RANGE_PROPERTY(alpha, ALPHA, 0, 255, 255);
        INSTALL_ENUM_PROPERTY(premultiplied, PREMULTIPLIED, 0);

+       mdp5_plane_install_rotation_property(dev, plane);
+
 #undef INSTALL_RANGE_PROPERTY
 #undef INSTALL_ENUM_PROPERTY
 #undef INSTALL_PROPERTY
@@ -160,13 +182,6 @@ done:
 #undef SET_PROPERTY
 }

-static int mdp5_plane_set_property(struct drm_plane *plane,
-               struct drm_property *property, uint64_t val)
-{
-       return mdp5_plane_atomic_set_property(plane, plane->state, property,
-               val);
-}
-
 static int mdp5_plane_atomic_get_property(struct drm_plane *plane,
                const struct drm_plane_state *state,
                struct drm_property *property, uint64_t *val)
@@ -254,7 +269,7 @@ static const struct drm_plane_funcs mdp5_plane_funcs = {
                .update_plane = drm_atomic_helper_update_plane,
                .disable_plane = drm_atomic_helper_disable_plane,
                .destroy = mdp5_plane_destroy,
-               .set_property = mdp5_plane_set_property,
+               .set_property = drm_atomic_helper_plane_set_property,
                .atomic_set_property = mdp5_plane_atomic_set_property,
                .atomic_get_property = mdp5_plane_atomic_get_property,
                .reset = mdp5_plane_reset,
@@ -290,6 +305,7 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
        struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
        struct drm_plane_state *old_state = plane->state;
        const struct mdp_format *format;
+       bool vflip, hflip;

        DBG("%s: check (%d -> %d)", mdp5_plane->name,
                        plane_enabled(old_state), plane_enabled(state));
@@ -314,6 +330,16 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,

                        return -EINVAL;
                }
+
+               hflip = !!(state->rotation & BIT(DRM_REFLECT_X));
+               vflip = !!(state->rotation & BIT(DRM_REFLECT_Y));
+               if ((vflip && !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) ||
+                       (hflip && !(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP))) {
+                       dev_err(plane->dev->dev,
+                               "Pipe doesn't support flip\n");
+
+                       return -EINVAL;
+               }
        }

        if (plane_enabled(state) && plane_enabled(old_state)) {
@@ -565,6 +591,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
                uint32_t src_w, uint32_t src_h)
 {
        struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct drm_plane_state *pstate = plane->state;
        struct mdp5_kms *mdp5_kms = get_kms(plane);
        struct device *dev = mdp5_kms->dev->dev;
        enum mdp5_pipe pipe = mdp5_plane->pipe;
@@ -574,6 +601,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
        uint32_t phasex_step[2] = {0,}, phasey_step[2] = {0,};
        uint32_t hdecm = 0, vdecm = 0;
        uint32_t pix_format;
+       bool vflip, hflip;
        unsigned long flags;
        int ret;

@@ -634,6 +662,9 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
                config |= get_scaley_config(src_h, crtc_h);
        }

+       hflip = !!(pstate->rotation & BIT(DRM_REFLECT_X));
+       vflip = !!(pstate->rotation & BIT(DRM_REFLECT_Y));
+
        spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);

        mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_IMG_SIZE(pipe),
@@ -675,6 +706,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
                        MDP5_PIPE_SRC_UNPACK_ELEM3(format->unpack[3]));

        mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_OP_MODE(pipe),
+                       (hflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_LR : 0) |
+                       (vflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_UD : 0) |
                        MDP5_PIPE_SRC_OP_MODE_BWC(BWC_LOSSLESS));

        /* not using secure mode: */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

Reply via email to