root/drivers/gpu/drm/arm/display/komeda/komeda_plane.c

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

DEFINITIONS

This source file includes following definitions.
  1. komeda_plane_init_data_flow
  2. komeda_plane_atomic_check
  3. komeda_plane_atomic_update
  4. komeda_plane_destroy
  5. komeda_plane_reset
  6. komeda_plane_atomic_duplicate_state
  7. komeda_plane_atomic_destroy_state
  8. komeda_plane_format_mod_supported
  9. get_possible_crtcs
  10. komeda_set_crtc_plane_mask
  11. get_plane_type
  12. komeda_plane_add
  13. komeda_kms_add_planes

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
   4  * Author: James.Qian.Wang <james.qian.wang@arm.com>
   5  *
   6  */
   7 #include <drm/drm_atomic.h>
   8 #include <drm/drm_atomic_helper.h>
   9 #include <drm/drm_plane_helper.h>
  10 #include <drm/drm_print.h>
  11 #include "komeda_dev.h"
  12 #include "komeda_kms.h"
  13 #include "komeda_framebuffer.h"
  14 
  15 static int
  16 komeda_plane_init_data_flow(struct drm_plane_state *st,
  17                             struct komeda_crtc_state *kcrtc_st,
  18                             struct komeda_data_flow_cfg *dflow)
  19 {
  20         struct komeda_plane *kplane = to_kplane(st->plane);
  21         struct drm_framebuffer *fb = st->fb;
  22         const struct komeda_format_caps *caps = to_kfb(fb)->format_caps;
  23         struct komeda_pipeline *pipe = kplane->layer->base.pipeline;
  24 
  25         memset(dflow, 0, sizeof(*dflow));
  26 
  27         dflow->blending_zorder = st->normalized_zpos;
  28         if (pipe == to_kcrtc(st->crtc)->master)
  29                 dflow->blending_zorder -= kcrtc_st->max_slave_zorder;
  30         if (dflow->blending_zorder < 0) {
  31                 DRM_DEBUG_ATOMIC("%s zorder:%d < max_slave_zorder: %d.\n",
  32                                  st->plane->name, st->normalized_zpos,
  33                                  kcrtc_st->max_slave_zorder);
  34                 return -EINVAL;
  35         }
  36 
  37         dflow->pixel_blend_mode = st->pixel_blend_mode;
  38         dflow->layer_alpha = st->alpha >> 8;
  39 
  40         dflow->out_x = st->crtc_x;
  41         dflow->out_y = st->crtc_y;
  42         dflow->out_w = st->crtc_w;
  43         dflow->out_h = st->crtc_h;
  44 
  45         dflow->in_x = st->src_x >> 16;
  46         dflow->in_y = st->src_y >> 16;
  47         dflow->in_w = st->src_w >> 16;
  48         dflow->in_h = st->src_h >> 16;
  49 
  50         dflow->rot = drm_rotation_simplify(st->rotation, caps->supported_rots);
  51         if (!has_bits(dflow->rot, caps->supported_rots)) {
  52                 DRM_DEBUG_ATOMIC("rotation(0x%x) isn't supported by %s.\n",
  53                                  dflow->rot,
  54                                  komeda_get_format_name(caps->fourcc,
  55                                                         fb->modifier));
  56                 return -EINVAL;
  57         }
  58 
  59         komeda_complete_data_flow_cfg(kplane->layer, dflow, fb);
  60 
  61         return 0;
  62 }
  63 
  64 /**
  65  * komeda_plane_atomic_check - build input data flow
  66  * @plane: DRM plane
  67  * @state: the plane state object
  68  *
  69  * RETURNS:
  70  * Zero for success or -errno
  71  */
  72 static int
  73 komeda_plane_atomic_check(struct drm_plane *plane,
  74                           struct drm_plane_state *state)
  75 {
  76         struct komeda_plane *kplane = to_kplane(plane);
  77         struct komeda_plane_state *kplane_st = to_kplane_st(state);
  78         struct komeda_layer *layer = kplane->layer;
  79         struct drm_crtc_state *crtc_st;
  80         struct komeda_crtc_state *kcrtc_st;
  81         struct komeda_data_flow_cfg dflow;
  82         int err;
  83 
  84         if (!state->crtc || !state->fb)
  85                 return 0;
  86 
  87         crtc_st = drm_atomic_get_crtc_state(state->state, state->crtc);
  88         if (IS_ERR(crtc_st) || !crtc_st->enable) {
  89                 DRM_DEBUG_ATOMIC("Cannot update plane on a disabled CRTC.\n");
  90                 return -EINVAL;
  91         }
  92 
  93         /* crtc is inactive, skip the resource assignment */
  94         if (!crtc_st->active)
  95                 return 0;
  96 
  97         kcrtc_st = to_kcrtc_st(crtc_st);
  98 
  99         err = komeda_plane_init_data_flow(state, kcrtc_st, &dflow);
 100         if (err)
 101                 return err;
 102 
 103         if (dflow.en_split)
 104                 err = komeda_build_layer_split_data_flow(layer,
 105                                 kplane_st, kcrtc_st, &dflow);
 106         else
 107                 err = komeda_build_layer_data_flow(layer,
 108                                 kplane_st, kcrtc_st, &dflow);
 109 
 110         return err;
 111 }
 112 
 113 /* plane doesn't represent a real HW, so there is no HW update for plane.
 114  * komeda handles all the HW update in crtc->atomic_flush
 115  */
 116 static void
 117 komeda_plane_atomic_update(struct drm_plane *plane,
 118                            struct drm_plane_state *old_state)
 119 {
 120 }
 121 
 122 static const struct drm_plane_helper_funcs komeda_plane_helper_funcs = {
 123         .atomic_check   = komeda_plane_atomic_check,
 124         .atomic_update  = komeda_plane_atomic_update,
 125 };
 126 
 127 static void komeda_plane_destroy(struct drm_plane *plane)
 128 {
 129         drm_plane_cleanup(plane);
 130 
 131         kfree(to_kplane(plane));
 132 }
 133 
 134 static void komeda_plane_reset(struct drm_plane *plane)
 135 {
 136         struct komeda_plane_state *state;
 137         struct komeda_plane *kplane = to_kplane(plane);
 138 
 139         if (plane->state)
 140                 __drm_atomic_helper_plane_destroy_state(plane->state);
 141 
 142         kfree(plane->state);
 143         plane->state = NULL;
 144 
 145         state = kzalloc(sizeof(*state), GFP_KERNEL);
 146         if (state) {
 147                 state->base.rotation = DRM_MODE_ROTATE_0;
 148                 state->base.pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
 149                 state->base.alpha = DRM_BLEND_ALPHA_OPAQUE;
 150                 state->base.zpos = kplane->layer->base.id;
 151                 state->base.color_encoding = DRM_COLOR_YCBCR_BT601;
 152                 state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
 153                 plane->state = &state->base;
 154                 plane->state->plane = plane;
 155         }
 156 }
 157 
 158 static struct drm_plane_state *
 159 komeda_plane_atomic_duplicate_state(struct drm_plane *plane)
 160 {
 161         struct komeda_plane_state *new;
 162 
 163         if (WARN_ON(!plane->state))
 164                 return NULL;
 165 
 166         new = kzalloc(sizeof(*new), GFP_KERNEL);
 167         if (!new)
 168                 return NULL;
 169 
 170         __drm_atomic_helper_plane_duplicate_state(plane, &new->base);
 171 
 172         return &new->base;
 173 }
 174 
 175 static void
 176 komeda_plane_atomic_destroy_state(struct drm_plane *plane,
 177                                   struct drm_plane_state *state)
 178 {
 179         __drm_atomic_helper_plane_destroy_state(state);
 180         kfree(to_kplane_st(state));
 181 }
 182 
 183 static bool
 184 komeda_plane_format_mod_supported(struct drm_plane *plane,
 185                                   u32 format, u64 modifier)
 186 {
 187         struct komeda_dev *mdev = plane->dev->dev_private;
 188         struct komeda_plane *kplane = to_kplane(plane);
 189         u32 layer_type = kplane->layer->layer_type;
 190 
 191         return komeda_format_mod_supported(&mdev->fmt_tbl, layer_type,
 192                                            format, modifier, 0);
 193 }
 194 
 195 static const struct drm_plane_funcs komeda_plane_funcs = {
 196         .update_plane           = drm_atomic_helper_update_plane,
 197         .disable_plane          = drm_atomic_helper_disable_plane,
 198         .destroy                = komeda_plane_destroy,
 199         .reset                  = komeda_plane_reset,
 200         .atomic_duplicate_state = komeda_plane_atomic_duplicate_state,
 201         .atomic_destroy_state   = komeda_plane_atomic_destroy_state,
 202         .format_mod_supported   = komeda_plane_format_mod_supported,
 203 };
 204 
 205 /* for komeda, which is pipeline can be share between crtcs */
 206 static u32 get_possible_crtcs(struct komeda_kms_dev *kms,
 207                               struct komeda_pipeline *pipe)
 208 {
 209         struct komeda_crtc *crtc;
 210         u32 possible_crtcs = 0;
 211         int i;
 212 
 213         for (i = 0; i < kms->n_crtcs; i++) {
 214                 crtc = &kms->crtcs[i];
 215 
 216                 if ((pipe == crtc->master) || (pipe == crtc->slave))
 217                         possible_crtcs |= BIT(i);
 218         }
 219 
 220         return possible_crtcs;
 221 }
 222 
 223 static void
 224 komeda_set_crtc_plane_mask(struct komeda_kms_dev *kms,
 225                            struct komeda_pipeline *pipe,
 226                            struct drm_plane *plane)
 227 {
 228         struct komeda_crtc *kcrtc;
 229         int i;
 230 
 231         for (i = 0; i < kms->n_crtcs; i++) {
 232                 kcrtc = &kms->crtcs[i];
 233 
 234                 if (pipe == kcrtc->slave)
 235                         kcrtc->slave_planes |= BIT(drm_plane_index(plane));
 236         }
 237 }
 238 
 239 /* use Layer0 as primary */
 240 static u32 get_plane_type(struct komeda_kms_dev *kms,
 241                           struct komeda_component *c)
 242 {
 243         bool is_primary = (c->id == KOMEDA_COMPONENT_LAYER0);
 244 
 245         return is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 246 }
 247 
 248 static int komeda_plane_add(struct komeda_kms_dev *kms,
 249                             struct komeda_layer *layer)
 250 {
 251         struct komeda_dev *mdev = kms->base.dev_private;
 252         struct komeda_component *c = &layer->base;
 253         struct komeda_plane *kplane;
 254         struct drm_plane *plane;
 255         u32 *formats, n_formats = 0;
 256         int err;
 257 
 258         kplane = kzalloc(sizeof(*kplane), GFP_KERNEL);
 259         if (!kplane)
 260                 return -ENOMEM;
 261 
 262         plane = &kplane->base;
 263         kplane->layer = layer;
 264 
 265         formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,
 266                                                layer->layer_type, &n_formats);
 267 
 268         err = drm_universal_plane_init(&kms->base, plane,
 269                         get_possible_crtcs(kms, c->pipeline),
 270                         &komeda_plane_funcs,
 271                         formats, n_formats, komeda_supported_modifiers,
 272                         get_plane_type(kms, c),
 273                         "%s", c->name);
 274 
 275         komeda_put_fourcc_list(formats);
 276 
 277         if (err)
 278                 goto cleanup;
 279 
 280         drm_plane_helper_add(plane, &komeda_plane_helper_funcs);
 281 
 282         err = drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
 283                                                  layer->supported_rots);
 284         if (err)
 285                 goto cleanup;
 286 
 287         err = drm_plane_create_alpha_property(plane);
 288         if (err)
 289                 goto cleanup;
 290 
 291         err = drm_plane_create_blend_mode_property(plane,
 292                         BIT(DRM_MODE_BLEND_PIXEL_NONE) |
 293                         BIT(DRM_MODE_BLEND_PREMULTI)   |
 294                         BIT(DRM_MODE_BLEND_COVERAGE));
 295         if (err)
 296                 goto cleanup;
 297 
 298         err = drm_plane_create_color_properties(plane,
 299                         BIT(DRM_COLOR_YCBCR_BT601) |
 300                         BIT(DRM_COLOR_YCBCR_BT709) |
 301                         BIT(DRM_COLOR_YCBCR_BT2020),
 302                         BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
 303                         BIT(DRM_COLOR_YCBCR_FULL_RANGE),
 304                         DRM_COLOR_YCBCR_BT601,
 305                         DRM_COLOR_YCBCR_LIMITED_RANGE);
 306         if (err)
 307                 goto cleanup;
 308 
 309         err = drm_plane_create_zpos_property(plane, layer->base.id, 0, 8);
 310         if (err)
 311                 goto cleanup;
 312 
 313         komeda_set_crtc_plane_mask(kms, c->pipeline, plane);
 314 
 315         return 0;
 316 cleanup:
 317         komeda_plane_destroy(plane);
 318         return err;
 319 }
 320 
 321 int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev)
 322 {
 323         struct komeda_pipeline *pipe;
 324         int i, j, err;
 325 
 326         for (i = 0; i < mdev->n_pipelines; i++) {
 327                 pipe = mdev->pipelines[i];
 328 
 329                 for (j = 0; j < pipe->n_layers; j++) {
 330                         err = komeda_plane_add(kms, pipe->layers[j]);
 331                         if (err)
 332                                 return err;
 333                 }
 334         }
 335 
 336         return 0;
 337 }

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