root/drivers/gpu/drm/omapdrm/omap_plane.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. omap_plane_prepare_fb
  2. omap_plane_cleanup_fb
  3. omap_plane_atomic_update
  4. omap_plane_atomic_disable
  5. omap_plane_atomic_check
  6. omap_plane_destroy
  7. omap_plane_install_properties
  8. omap_plane_reset
  9. omap_plane_atomic_set_property
  10. omap_plane_atomic_get_property
  11. omap_plane_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
   4  * Author: Rob Clark <rob.clark@linaro.org>
   5  */
   6 
   7 #include <drm/drm_atomic.h>
   8 #include <drm/drm_atomic_helper.h>
   9 #include <drm/drm_plane_helper.h>
  10 
  11 #include "omap_dmm_tiler.h"
  12 #include "omap_drv.h"
  13 
  14 /*
  15  * plane funcs
  16  */
  17 
  18 #define to_omap_plane(x) container_of(x, struct omap_plane, base)
  19 
  20 struct omap_plane {
  21         struct drm_plane base;
  22         enum omap_plane_id id;
  23         const char *name;
  24 };
  25 
  26 static int omap_plane_prepare_fb(struct drm_plane *plane,
  27                                  struct drm_plane_state *new_state)
  28 {
  29         if (!new_state->fb)
  30                 return 0;
  31 
  32         return omap_framebuffer_pin(new_state->fb);
  33 }
  34 
  35 static void omap_plane_cleanup_fb(struct drm_plane *plane,
  36                                   struct drm_plane_state *old_state)
  37 {
  38         if (old_state->fb)
  39                 omap_framebuffer_unpin(old_state->fb);
  40 }
  41 
  42 static void omap_plane_atomic_update(struct drm_plane *plane,
  43                                      struct drm_plane_state *old_state)
  44 {
  45         struct omap_drm_private *priv = plane->dev->dev_private;
  46         struct omap_plane *omap_plane = to_omap_plane(plane);
  47         struct drm_plane_state *state = plane->state;
  48         struct omap_overlay_info info;
  49         int ret;
  50 
  51         DBG("%s, crtc=%p fb=%p", omap_plane->name, state->crtc, state->fb);
  52 
  53         memset(&info, 0, sizeof(info));
  54         info.rotation_type = OMAP_DSS_ROT_NONE;
  55         info.rotation = DRM_MODE_ROTATE_0;
  56         info.global_alpha = state->alpha >> 8;
  57         info.zorder = state->normalized_zpos;
  58         if (state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
  59                 info.pre_mult_alpha = 1;
  60         else
  61                 info.pre_mult_alpha = 0;
  62 
  63         /* update scanout: */
  64         omap_framebuffer_update_scanout(state->fb, state, &info);
  65 
  66         DBG("%dx%d -> %dx%d (%d)", info.width, info.height,
  67                         info.out_width, info.out_height,
  68                         info.screen_width);
  69         DBG("%d,%d %pad %pad", info.pos_x, info.pos_y,
  70                         &info.paddr, &info.p_uv_addr);
  71 
  72         /* and finally, update omapdss: */
  73         ret = priv->dispc_ops->ovl_setup(priv->dispc, omap_plane->id, &info,
  74                               omap_crtc_timings(state->crtc), false,
  75                               omap_crtc_channel(state->crtc));
  76         if (ret) {
  77                 dev_err(plane->dev->dev, "Failed to setup plane %s\n",
  78                         omap_plane->name);
  79                 priv->dispc_ops->ovl_enable(priv->dispc, omap_plane->id, false);
  80                 return;
  81         }
  82 
  83         priv->dispc_ops->ovl_enable(priv->dispc, omap_plane->id, true);
  84 }
  85 
  86 static void omap_plane_atomic_disable(struct drm_plane *plane,
  87                                       struct drm_plane_state *old_state)
  88 {
  89         struct omap_drm_private *priv = plane->dev->dev_private;
  90         struct omap_plane *omap_plane = to_omap_plane(plane);
  91 
  92         plane->state->rotation = DRM_MODE_ROTATE_0;
  93         plane->state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY
  94                            ? 0 : omap_plane->id;
  95 
  96         priv->dispc_ops->ovl_enable(priv->dispc, omap_plane->id, false);
  97 }
  98 
  99 static int omap_plane_atomic_check(struct drm_plane *plane,
 100                                    struct drm_plane_state *state)
 101 {
 102         struct drm_crtc_state *crtc_state;
 103 
 104         if (!state->fb)
 105                 return 0;
 106 
 107         /* crtc should only be NULL when disabling (i.e., !state->fb) */
 108         if (WARN_ON(!state->crtc))
 109                 return 0;
 110 
 111         crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc);
 112         /* we should have a crtc state if the plane is attached to a crtc */
 113         if (WARN_ON(!crtc_state))
 114                 return 0;
 115 
 116         if (!crtc_state->enable)
 117                 return 0;
 118 
 119         if (state->crtc_x < 0 || state->crtc_y < 0)
 120                 return -EINVAL;
 121 
 122         if (state->crtc_x + state->crtc_w > crtc_state->adjusted_mode.hdisplay)
 123                 return -EINVAL;
 124 
 125         if (state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay)
 126                 return -EINVAL;
 127 
 128         if (state->rotation != DRM_MODE_ROTATE_0 &&
 129             !omap_framebuffer_supports_rotation(state->fb))
 130                 return -EINVAL;
 131 
 132         return 0;
 133 }
 134 
 135 static const struct drm_plane_helper_funcs omap_plane_helper_funcs = {
 136         .prepare_fb = omap_plane_prepare_fb,
 137         .cleanup_fb = omap_plane_cleanup_fb,
 138         .atomic_check = omap_plane_atomic_check,
 139         .atomic_update = omap_plane_atomic_update,
 140         .atomic_disable = omap_plane_atomic_disable,
 141 };
 142 
 143 static void omap_plane_destroy(struct drm_plane *plane)
 144 {
 145         struct omap_plane *omap_plane = to_omap_plane(plane);
 146 
 147         DBG("%s", omap_plane->name);
 148 
 149         drm_plane_cleanup(plane);
 150 
 151         kfree(omap_plane);
 152 }
 153 
 154 /* helper to install properties which are common to planes and crtcs */
 155 void omap_plane_install_properties(struct drm_plane *plane,
 156                 struct drm_mode_object *obj)
 157 {
 158         struct drm_device *dev = plane->dev;
 159         struct omap_drm_private *priv = dev->dev_private;
 160 
 161         if (priv->has_dmm) {
 162                 if (!plane->rotation_property)
 163                         drm_plane_create_rotation_property(plane,
 164                                                            DRM_MODE_ROTATE_0,
 165                                                            DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
 166                                                            DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270 |
 167                                                            DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y);
 168 
 169                 /* Attach the rotation property also to the crtc object */
 170                 if (plane->rotation_property && obj != &plane->base)
 171                         drm_object_attach_property(obj, plane->rotation_property,
 172                                                    DRM_MODE_ROTATE_0);
 173         }
 174 
 175         drm_object_attach_property(obj, priv->zorder_prop, 0);
 176 }
 177 
 178 static void omap_plane_reset(struct drm_plane *plane)
 179 {
 180         struct omap_plane *omap_plane = to_omap_plane(plane);
 181 
 182         drm_atomic_helper_plane_reset(plane);
 183         if (!plane->state)
 184                 return;
 185 
 186         /*
 187          * Set the zpos default depending on whether we are a primary or overlay
 188          * plane.
 189          */
 190         plane->state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY
 191                            ? 0 : omap_plane->id;
 192 }
 193 
 194 static int omap_plane_atomic_set_property(struct drm_plane *plane,
 195                                           struct drm_plane_state *state,
 196                                           struct drm_property *property,
 197                                           u64 val)
 198 {
 199         struct omap_drm_private *priv = plane->dev->dev_private;
 200 
 201         if (property == priv->zorder_prop)
 202                 state->zpos = val;
 203         else
 204                 return -EINVAL;
 205 
 206         return 0;
 207 }
 208 
 209 static int omap_plane_atomic_get_property(struct drm_plane *plane,
 210                                           const struct drm_plane_state *state,
 211                                           struct drm_property *property,
 212                                           u64 *val)
 213 {
 214         struct omap_drm_private *priv = plane->dev->dev_private;
 215 
 216         if (property == priv->zorder_prop)
 217                 *val = state->zpos;
 218         else
 219                 return -EINVAL;
 220 
 221         return 0;
 222 }
 223 
 224 static const struct drm_plane_funcs omap_plane_funcs = {
 225         .update_plane = drm_atomic_helper_update_plane,
 226         .disable_plane = drm_atomic_helper_disable_plane,
 227         .reset = omap_plane_reset,
 228         .destroy = omap_plane_destroy,
 229         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
 230         .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 231         .atomic_set_property = omap_plane_atomic_set_property,
 232         .atomic_get_property = omap_plane_atomic_get_property,
 233 };
 234 
 235 static const char *plane_id_to_name[] = {
 236         [OMAP_DSS_GFX] = "gfx",
 237         [OMAP_DSS_VIDEO1] = "vid1",
 238         [OMAP_DSS_VIDEO2] = "vid2",
 239         [OMAP_DSS_VIDEO3] = "vid3",
 240 };
 241 
 242 static const enum omap_plane_id plane_idx_to_id[] = {
 243         OMAP_DSS_GFX,
 244         OMAP_DSS_VIDEO1,
 245         OMAP_DSS_VIDEO2,
 246         OMAP_DSS_VIDEO3,
 247 };
 248 
 249 /* initialize plane */
 250 struct drm_plane *omap_plane_init(struct drm_device *dev,
 251                 int idx, enum drm_plane_type type,
 252                 u32 possible_crtcs)
 253 {
 254         struct omap_drm_private *priv = dev->dev_private;
 255         unsigned int num_planes = priv->dispc_ops->get_num_ovls(priv->dispc);
 256         struct drm_plane *plane;
 257         struct omap_plane *omap_plane;
 258         enum omap_plane_id id;
 259         int ret;
 260         u32 nformats;
 261         const u32 *formats;
 262 
 263         if (WARN_ON(idx >= ARRAY_SIZE(plane_idx_to_id)))
 264                 return ERR_PTR(-EINVAL);
 265 
 266         id = plane_idx_to_id[idx];
 267 
 268         DBG("%s: type=%d", plane_id_to_name[id], type);
 269 
 270         omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
 271         if (!omap_plane)
 272                 return ERR_PTR(-ENOMEM);
 273 
 274         formats = priv->dispc_ops->ovl_get_color_modes(priv->dispc, id);
 275         for (nformats = 0; formats[nformats]; ++nformats)
 276                 ;
 277         omap_plane->id = id;
 278         omap_plane->name = plane_id_to_name[id];
 279 
 280         plane = &omap_plane->base;
 281 
 282         ret = drm_universal_plane_init(dev, plane, possible_crtcs,
 283                                        &omap_plane_funcs, formats,
 284                                        nformats, NULL, type, NULL);
 285         if (ret < 0)
 286                 goto error;
 287 
 288         drm_plane_helper_add(plane, &omap_plane_helper_funcs);
 289 
 290         omap_plane_install_properties(plane, &plane->base);
 291         drm_plane_create_zpos_property(plane, 0, 0, num_planes - 1);
 292         drm_plane_create_alpha_property(plane);
 293         drm_plane_create_blend_mode_property(plane, BIT(DRM_MODE_BLEND_PREMULTI) |
 294                                              BIT(DRM_MODE_BLEND_COVERAGE));
 295 
 296         return plane;
 297 
 298 error:
 299         dev_err(dev->dev, "%s(): could not create plane: %s\n",
 300                 __func__, plane_id_to_name[id]);
 301 
 302         kfree(omap_plane);
 303         return NULL;
 304 }

/* [<][>][^][v][top][bottom][index][help] */