Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
0004  * Author: Liviu Dudau <Liviu.Dudau@arm.com>
0005  *
0006  * ARM Mali DP plane manipulation routines.
0007  */
0008 
0009 #include <linux/iommu.h>
0010 #include <linux/platform_device.h>
0011 
0012 #include <drm/drm_atomic.h>
0013 #include <drm/drm_atomic_helper.h>
0014 #include <drm/drm_blend.h>
0015 #include <drm/drm_drv.h>
0016 #include <drm/drm_fb_cma_helper.h>
0017 #include <drm/drm_fourcc.h>
0018 #include <drm/drm_framebuffer.h>
0019 #include <drm/drm_gem_cma_helper.h>
0020 #include <drm/drm_gem_framebuffer_helper.h>
0021 #include <drm/drm_plane_helper.h>
0022 #include <drm/drm_print.h>
0023 
0024 #include "malidp_hw.h"
0025 #include "malidp_drv.h"
0026 
0027 /* Layer specific register offsets */
0028 #define MALIDP_LAYER_FORMAT     0x000
0029 #define   LAYER_FORMAT_MASK     0x3f
0030 #define MALIDP_LAYER_CONTROL        0x004
0031 #define   LAYER_ENABLE          (1 << 0)
0032 #define   LAYER_FLOWCFG_MASK        7
0033 #define   LAYER_FLOWCFG(x)      (((x) & LAYER_FLOWCFG_MASK) << 1)
0034 #define     LAYER_FLOWCFG_SCALE_SE  3
0035 #define   LAYER_ROT_OFFSET      8
0036 #define   LAYER_H_FLIP          (1 << 10)
0037 #define   LAYER_V_FLIP          (1 << 11)
0038 #define   LAYER_ROT_MASK        (0xf << 8)
0039 #define   LAYER_COMP_MASK       (0x3 << 12)
0040 #define   LAYER_COMP_PIXEL      (0x3 << 12)
0041 #define   LAYER_COMP_PLANE      (0x2 << 12)
0042 #define   LAYER_PMUL_ENABLE     (0x1 << 14)
0043 #define   LAYER_ALPHA_OFFSET        (16)
0044 #define   LAYER_ALPHA_MASK      (0xff)
0045 #define   LAYER_ALPHA(x)        (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET)
0046 #define MALIDP_LAYER_COMPOSE        0x008
0047 #define MALIDP_LAYER_SIZE       0x00c
0048 #define   LAYER_H_VAL(x)        (((x) & 0x1fff) << 0)
0049 #define   LAYER_V_VAL(x)        (((x) & 0x1fff) << 16)
0050 #define MALIDP_LAYER_COMP_SIZE      0x010
0051 #define MALIDP_LAYER_OFFSET     0x014
0052 #define MALIDP550_LS_ENABLE     0x01c
0053 #define MALIDP550_LS_R1_IN_SIZE     0x020
0054 
0055 #define MODIFIERS_COUNT_MAX     15
0056 
0057 /*
0058  * This 4-entry look-up-table is used to determine the full 8-bit alpha value
0059  * for formats with 1- or 2-bit alpha channels.
0060  * We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0%
0061  * opacity for 2-bit formats.
0062  */
0063 #define MALIDP_ALPHA_LUT 0xffaa5500
0064 
0065 /* page sizes the MMU prefetcher can support */
0066 #define MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES (SZ_4K | SZ_64K)
0067 #define MALIDP_MMU_PREFETCH_FULL_PGSIZES    (SZ_1M | SZ_2M)
0068 
0069 /* readahead for partial-frame prefetch */
0070 #define MALIDP_MMU_PREFETCH_READAHEAD       8
0071 
0072 static void malidp_de_plane_destroy(struct drm_plane *plane)
0073 {
0074     struct malidp_plane *mp = to_malidp_plane(plane);
0075 
0076     drm_plane_cleanup(plane);
0077     kfree(mp);
0078 }
0079 
0080 /*
0081  * Replicate what the default ->reset hook does: free the state pointer and
0082  * allocate a new empty object. We just need enough space to store
0083  * a malidp_plane_state instead of a drm_plane_state.
0084  */
0085 static void malidp_plane_reset(struct drm_plane *plane)
0086 {
0087     struct malidp_plane_state *state = to_malidp_plane_state(plane->state);
0088 
0089     if (state)
0090         __drm_atomic_helper_plane_destroy_state(&state->base);
0091     kfree(state);
0092     plane->state = NULL;
0093     state = kzalloc(sizeof(*state), GFP_KERNEL);
0094     if (state)
0095         __drm_atomic_helper_plane_reset(plane, &state->base);
0096 }
0097 
0098 static struct
0099 drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
0100 {
0101     struct malidp_plane_state *state, *m_state;
0102 
0103     if (!plane->state)
0104         return NULL;
0105 
0106     state = kmalloc(sizeof(*state), GFP_KERNEL);
0107     if (!state)
0108         return NULL;
0109 
0110     m_state = to_malidp_plane_state(plane->state);
0111     __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
0112     state->rotmem_size = m_state->rotmem_size;
0113     state->format = m_state->format;
0114     state->n_planes = m_state->n_planes;
0115 
0116     state->mmu_prefetch_mode = m_state->mmu_prefetch_mode;
0117     state->mmu_prefetch_pgsize = m_state->mmu_prefetch_pgsize;
0118 
0119     return &state->base;
0120 }
0121 
0122 static void malidp_destroy_plane_state(struct drm_plane *plane,
0123                        struct drm_plane_state *state)
0124 {
0125     struct malidp_plane_state *m_state = to_malidp_plane_state(state);
0126 
0127     __drm_atomic_helper_plane_destroy_state(state);
0128     kfree(m_state);
0129 }
0130 
0131 static const char * const prefetch_mode_names[] = {
0132     [MALIDP_PREFETCH_MODE_NONE] = "MMU_PREFETCH_NONE",
0133     [MALIDP_PREFETCH_MODE_PARTIAL] = "MMU_PREFETCH_PARTIAL",
0134     [MALIDP_PREFETCH_MODE_FULL] = "MMU_PREFETCH_FULL",
0135 };
0136 
0137 static void malidp_plane_atomic_print_state(struct drm_printer *p,
0138                         const struct drm_plane_state *state)
0139 {
0140     struct malidp_plane_state *ms = to_malidp_plane_state(state);
0141 
0142     drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size);
0143     drm_printf(p, "\tformat_id=%u\n", ms->format);
0144     drm_printf(p, "\tn_planes=%u\n", ms->n_planes);
0145     drm_printf(p, "\tmmu_prefetch_mode=%s\n",
0146            prefetch_mode_names[ms->mmu_prefetch_mode]);
0147     drm_printf(p, "\tmmu_prefetch_pgsize=%d\n", ms->mmu_prefetch_pgsize);
0148 }
0149 
0150 bool malidp_format_mod_supported(struct drm_device *drm,
0151                  u32 format, u64 modifier)
0152 {
0153     const struct drm_format_info *info;
0154     const u64 *modifiers;
0155     struct malidp_drm *malidp = drm->dev_private;
0156     const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
0157 
0158     if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
0159         return false;
0160 
0161     /* Some pixel formats are supported without any modifier */
0162     if (modifier == DRM_FORMAT_MOD_LINEAR) {
0163         /*
0164          * However these pixel formats need to be supported with
0165          * modifiers only
0166          */
0167         return !malidp_hw_format_is_afbc_only(format);
0168     }
0169 
0170     if (!fourcc_mod_is_vendor(modifier, ARM)) {
0171         DRM_ERROR("Unknown modifier (not Arm)\n");
0172         return false;
0173     }
0174 
0175     if (modifier &
0176         ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
0177         DRM_DEBUG_KMS("Unsupported modifiers\n");
0178         return false;
0179     }
0180 
0181     modifiers = malidp_format_modifiers;
0182 
0183     /* SPLIT buffers must use SPARSE layout */
0184     if (WARN_ON_ONCE((modifier & AFBC_SPLIT) && !(modifier & AFBC_SPARSE)))
0185         return false;
0186 
0187     /* CBR only applies to YUV formats, where YTR should be always 0 */
0188     if (WARN_ON_ONCE((modifier & AFBC_CBR) && (modifier & AFBC_YTR)))
0189         return false;
0190 
0191     while (*modifiers != DRM_FORMAT_MOD_INVALID) {
0192         if (*modifiers == modifier)
0193             break;
0194 
0195         modifiers++;
0196     }
0197 
0198     /* return false, if the modifier was not found */
0199     if (*modifiers == DRM_FORMAT_MOD_INVALID) {
0200         DRM_DEBUG_KMS("Unsupported modifier\n");
0201         return false;
0202     }
0203 
0204     info = drm_format_info(format);
0205 
0206     if (info->num_planes != 1) {
0207         DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
0208         return false;
0209     }
0210 
0211     if (malidp_hw_format_is_linear_only(format) == true) {
0212         DRM_DEBUG_KMS("Given format (0x%x) is supported is linear mode only\n",
0213                   format);
0214         return false;
0215     }
0216 
0217     /*
0218      * RGB formats need to provide YTR modifier and YUV formats should not
0219      * provide YTR modifier.
0220      */
0221     if (!(info->is_yuv) != !!(modifier & AFBC_FORMAT_MOD_YTR)) {
0222         DRM_DEBUG_KMS("AFBC_FORMAT_MOD_YTR is %s for %s formats\n",
0223                   info->is_yuv ? "disallowed" : "mandatory",
0224                   info->is_yuv ? "YUV" : "RGB");
0225         return false;
0226     }
0227 
0228     if (modifier & AFBC_SPLIT) {
0229         if (!info->is_yuv) {
0230             if (info->cpp[0] <= 2) {
0231                 DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");
0232                 return false;
0233             }
0234         }
0235 
0236         if ((info->hsub != 1) || (info->vsub != 1)) {
0237             if (!(format == DRM_FORMAT_YUV420_10BIT &&
0238                   (map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) {
0239                 DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n");
0240                 return false;
0241             }
0242         }
0243     }
0244 
0245     if (modifier & AFBC_CBR) {
0246         if ((info->hsub == 1) || (info->vsub == 1)) {
0247             DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n");
0248             return false;
0249         }
0250     }
0251 
0252     return true;
0253 }
0254 
0255 static bool malidp_format_mod_supported_per_plane(struct drm_plane *plane,
0256                           u32 format, u64 modifier)
0257 {
0258     return malidp_format_mod_supported(plane->dev, format, modifier);
0259 }
0260 
0261 static const struct drm_plane_funcs malidp_de_plane_funcs = {
0262     .update_plane = drm_atomic_helper_update_plane,
0263     .disable_plane = drm_atomic_helper_disable_plane,
0264     .destroy = malidp_de_plane_destroy,
0265     .reset = malidp_plane_reset,
0266     .atomic_duplicate_state = malidp_duplicate_plane_state,
0267     .atomic_destroy_state = malidp_destroy_plane_state,
0268     .atomic_print_state = malidp_plane_atomic_print_state,
0269     .format_mod_supported = malidp_format_mod_supported_per_plane,
0270 };
0271 
0272 static int malidp_se_check_scaling(struct malidp_plane *mp,
0273                    struct drm_plane_state *state)
0274 {
0275     struct drm_crtc_state *crtc_state =
0276         drm_atomic_get_existing_crtc_state(state->state, state->crtc);
0277     struct malidp_crtc_state *mc;
0278     u32 src_w, src_h;
0279     int ret;
0280 
0281     if (!crtc_state)
0282         return -EINVAL;
0283 
0284     mc = to_malidp_crtc_state(crtc_state);
0285 
0286     ret = drm_atomic_helper_check_plane_state(state, crtc_state,
0287                           0, INT_MAX, true, true);
0288     if (ret)
0289         return ret;
0290 
0291     if (state->rotation & MALIDP_ROTATED_MASK) {
0292         src_w = state->src_h >> 16;
0293         src_h = state->src_w >> 16;
0294     } else {
0295         src_w = state->src_w >> 16;
0296         src_h = state->src_h >> 16;
0297     }
0298 
0299     if ((state->crtc_w == src_w) && (state->crtc_h == src_h)) {
0300         /* Scaling not necessary for this plane. */
0301         mc->scaled_planes_mask &= ~(mp->layer->id);
0302         return 0;
0303     }
0304 
0305     if (mp->layer->id & (DE_SMART | DE_GRAPHICS2))
0306         return -EINVAL;
0307 
0308     mc->scaled_planes_mask |= mp->layer->id;
0309     /* Defer scaling requirements calculation to the crtc check. */
0310     return 0;
0311 }
0312 
0313 static u32 malidp_get_pgsize_bitmap(struct malidp_plane *mp)
0314 {
0315     struct iommu_domain *mmu_dom;
0316 
0317     mmu_dom = iommu_get_domain_for_dev(mp->base.dev->dev);
0318     if (mmu_dom)
0319         return mmu_dom->pgsize_bitmap;
0320 
0321     return 0;
0322 }
0323 
0324 /*
0325  * Check if the framebuffer is entirely made up of pages at least pgsize in
0326  * size. Only a heuristic: assumes that each scatterlist entry has been aligned
0327  * to the largest page size smaller than its length and that the MMU maps to
0328  * the largest page size possible.
0329  */
0330 static bool malidp_check_pages_threshold(struct malidp_plane_state *ms,
0331                      u32 pgsize)
0332 {
0333     int i;
0334 
0335     for (i = 0; i < ms->n_planes; i++) {
0336         struct drm_gem_object *obj;
0337         struct drm_gem_cma_object *cma_obj;
0338         struct sg_table *sgt;
0339         struct scatterlist *sgl;
0340 
0341         obj = drm_gem_fb_get_obj(ms->base.fb, i);
0342         cma_obj = to_drm_gem_cma_obj(obj);
0343 
0344         if (cma_obj->sgt)
0345             sgt = cma_obj->sgt;
0346         else
0347             sgt = obj->funcs->get_sg_table(obj);
0348 
0349         if (IS_ERR(sgt))
0350             return false;
0351 
0352         sgl = sgt->sgl;
0353 
0354         while (sgl) {
0355             if (sgl->length < pgsize) {
0356                 if (!cma_obj->sgt)
0357                     kfree(sgt);
0358                 return false;
0359             }
0360 
0361             sgl = sg_next(sgl);
0362         }
0363         if (!cma_obj->sgt)
0364             kfree(sgt);
0365     }
0366 
0367     return true;
0368 }
0369 
0370 /*
0371  * Check if it is possible to enable partial-frame MMU prefetch given the
0372  * current format, AFBC state and rotation.
0373  */
0374 static bool malidp_partial_prefetch_supported(u32 format, u64 modifier,
0375                           unsigned int rotation)
0376 {
0377     bool afbc, sparse;
0378 
0379     /* rotation and horizontal flip not supported for partial prefetch */
0380     if (rotation & (DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
0381             DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X))
0382         return false;
0383 
0384     afbc = modifier & DRM_FORMAT_MOD_ARM_AFBC(0);
0385     sparse = modifier & AFBC_FORMAT_MOD_SPARSE;
0386 
0387     switch (format) {
0388     case DRM_FORMAT_ARGB2101010:
0389     case DRM_FORMAT_RGBA1010102:
0390     case DRM_FORMAT_BGRA1010102:
0391     case DRM_FORMAT_ARGB8888:
0392     case DRM_FORMAT_RGBA8888:
0393     case DRM_FORMAT_BGRA8888:
0394     case DRM_FORMAT_XRGB8888:
0395     case DRM_FORMAT_XBGR8888:
0396     case DRM_FORMAT_RGBX8888:
0397     case DRM_FORMAT_BGRX8888:
0398     case DRM_FORMAT_RGB888:
0399     case DRM_FORMAT_RGBA5551:
0400     case DRM_FORMAT_RGB565:
0401         /* always supported */
0402         return true;
0403 
0404     case DRM_FORMAT_ABGR2101010:
0405     case DRM_FORMAT_ABGR8888:
0406     case DRM_FORMAT_ABGR1555:
0407     case DRM_FORMAT_BGR565:
0408         /* supported, but if AFBC then must be sparse mode */
0409         return (!afbc) || (afbc && sparse);
0410 
0411     case DRM_FORMAT_BGR888:
0412         /* supported, but not for AFBC */
0413         return !afbc;
0414 
0415     case DRM_FORMAT_YUYV:
0416     case DRM_FORMAT_UYVY:
0417     case DRM_FORMAT_NV12:
0418     case DRM_FORMAT_YUV420:
0419         /* not supported */
0420         return false;
0421 
0422     default:
0423         return false;
0424     }
0425 }
0426 
0427 /*
0428  * Select the preferred MMU prefetch mode. Full-frame prefetch is preferred as
0429  * long as the framebuffer is all large pages. Otherwise partial-frame prefetch
0430  * is selected as long as it is supported for the current format. The selected
0431  * page size for prefetch is returned in pgsize_bitmap.
0432  */
0433 static enum mmu_prefetch_mode malidp_mmu_prefetch_select_mode
0434         (struct malidp_plane_state *ms, u32 *pgsize_bitmap)
0435 {
0436     u32 pgsizes;
0437 
0438     /* get the full-frame prefetch page size(s) supported by the MMU */
0439     pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_FULL_PGSIZES;
0440 
0441     while (pgsizes) {
0442         u32 largest_pgsize = 1 << __fls(pgsizes);
0443 
0444         if (malidp_check_pages_threshold(ms, largest_pgsize)) {
0445             *pgsize_bitmap = largest_pgsize;
0446             return MALIDP_PREFETCH_MODE_FULL;
0447         }
0448 
0449         pgsizes -= largest_pgsize;
0450     }
0451 
0452     /* get the partial-frame prefetch page size(s) supported by the MMU */
0453     pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES;
0454 
0455     if (malidp_partial_prefetch_supported(ms->base.fb->format->format,
0456                           ms->base.fb->modifier,
0457                           ms->base.rotation)) {
0458         /* partial prefetch using the smallest page size */
0459         *pgsize_bitmap = 1 << __ffs(pgsizes);
0460         return MALIDP_PREFETCH_MODE_PARTIAL;
0461     }
0462     *pgsize_bitmap = 0;
0463     return MALIDP_PREFETCH_MODE_NONE;
0464 }
0465 
0466 static u32 malidp_calc_mmu_control_value(enum mmu_prefetch_mode mode,
0467                      u8 readahead, u8 n_planes, u32 pgsize)
0468 {
0469     u32 mmu_ctrl = 0;
0470 
0471     if (mode != MALIDP_PREFETCH_MODE_NONE) {
0472         mmu_ctrl |= MALIDP_MMU_CTRL_EN;
0473 
0474         if (mode == MALIDP_PREFETCH_MODE_PARTIAL) {
0475             mmu_ctrl |= MALIDP_MMU_CTRL_MODE;
0476             mmu_ctrl |= MALIDP_MMU_CTRL_PP_NUM_REQ(readahead);
0477         }
0478 
0479         if (pgsize == SZ_64K || pgsize == SZ_2M) {
0480             int i;
0481 
0482             for (i = 0; i < n_planes; i++)
0483                 mmu_ctrl |= MALIDP_MMU_CTRL_PX_PS(i);
0484         }
0485     }
0486 
0487     return mmu_ctrl;
0488 }
0489 
0490 static void malidp_de_prefetch_settings(struct malidp_plane *mp,
0491                     struct malidp_plane_state *ms)
0492 {
0493     if (!mp->layer->mmu_ctrl_offset)
0494         return;
0495 
0496     /* get the page sizes supported by the MMU */
0497     ms->mmu_prefetch_pgsize = malidp_get_pgsize_bitmap(mp);
0498     ms->mmu_prefetch_mode  =
0499         malidp_mmu_prefetch_select_mode(ms, &ms->mmu_prefetch_pgsize);
0500 }
0501 
0502 static int malidp_de_plane_check(struct drm_plane *plane,
0503                  struct drm_atomic_state *state)
0504 {
0505     struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
0506                                          plane);
0507     struct malidp_plane *mp = to_malidp_plane(plane);
0508     struct malidp_plane_state *ms = to_malidp_plane_state(new_plane_state);
0509     bool rotated = new_plane_state->rotation & MALIDP_ROTATED_MASK;
0510     struct drm_framebuffer *fb;
0511     u16 pixel_alpha = new_plane_state->pixel_blend_mode;
0512     int i, ret;
0513     unsigned int block_w, block_h;
0514 
0515     if (!new_plane_state->crtc || WARN_ON(!new_plane_state->fb))
0516         return 0;
0517 
0518     fb = new_plane_state->fb;
0519 
0520     ms->format = malidp_hw_get_format_id(&mp->hwdev->hw->map,
0521                          mp->layer->id, fb->format->format,
0522                          !!fb->modifier);
0523     if (ms->format == MALIDP_INVALID_FORMAT_ID)
0524         return -EINVAL;
0525 
0526     ms->n_planes = fb->format->num_planes;
0527     for (i = 0; i < ms->n_planes; i++) {
0528         u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated);
0529 
0530         if (((fb->pitches[i] * drm_format_info_block_height(fb->format, i))
0531                 & (alignment - 1)) && !(fb->modifier)) {
0532             DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
0533                       fb->pitches[i], i);
0534             return -EINVAL;
0535         }
0536     }
0537 
0538     block_w = drm_format_info_block_width(fb->format, 0);
0539     block_h = drm_format_info_block_height(fb->format, 0);
0540     if (fb->width % block_w || fb->height % block_h) {
0541         DRM_DEBUG_KMS("Buffer width/height needs to be a multiple of tile sizes");
0542         return -EINVAL;
0543     }
0544     if ((new_plane_state->src_x >> 16) % block_w || (new_plane_state->src_y >> 16) % block_h) {
0545         DRM_DEBUG_KMS("Plane src_x/src_y needs to be a multiple of tile sizes");
0546         return -EINVAL;
0547     }
0548 
0549     if ((new_plane_state->crtc_w > mp->hwdev->max_line_size) ||
0550         (new_plane_state->crtc_h > mp->hwdev->max_line_size) ||
0551         (new_plane_state->crtc_w < mp->hwdev->min_line_size) ||
0552         (new_plane_state->crtc_h < mp->hwdev->min_line_size))
0553         return -EINVAL;
0554 
0555     /*
0556      * DP550/650 video layers can accept 3 plane formats only if
0557      * fb->pitches[1] == fb->pitches[2] since they don't have a
0558      * third plane stride register.
0559      */
0560     if (ms->n_planes == 3 &&
0561         !(mp->hwdev->hw->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) &&
0562         (new_plane_state->fb->pitches[1] != new_plane_state->fb->pitches[2]))
0563         return -EINVAL;
0564 
0565     ret = malidp_se_check_scaling(mp, new_plane_state);
0566     if (ret)
0567         return ret;
0568 
0569     /* validate the rotation constraints for each layer */
0570     if (new_plane_state->rotation != DRM_MODE_ROTATE_0) {
0571         if (mp->layer->rot == ROTATE_NONE)
0572             return -EINVAL;
0573         if ((mp->layer->rot == ROTATE_COMPRESSED) && !(fb->modifier))
0574             return -EINVAL;
0575         /*
0576          * packed RGB888 / BGR888 can't be rotated or flipped
0577          * unless they are stored in a compressed way
0578          */
0579         if ((fb->format->format == DRM_FORMAT_RGB888 ||
0580              fb->format->format == DRM_FORMAT_BGR888) && !(fb->modifier))
0581             return -EINVAL;
0582     }
0583 
0584     /* SMART layer does not support AFBC */
0585     if (mp->layer->id == DE_SMART && fb->modifier) {
0586         DRM_ERROR("AFBC framebuffer not supported in SMART layer");
0587         return -EINVAL;
0588     }
0589 
0590     ms->rotmem_size = 0;
0591     if (new_plane_state->rotation & MALIDP_ROTATED_MASK) {
0592         int val;
0593 
0594         val = mp->hwdev->hw->rotmem_required(mp->hwdev, new_plane_state->crtc_w,
0595                              new_plane_state->crtc_h,
0596                              fb->format->format,
0597                              !!(fb->modifier));
0598         if (val < 0)
0599             return val;
0600 
0601         ms->rotmem_size = val;
0602     }
0603 
0604     /* HW can't support plane + pixel blending */
0605     if ((new_plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
0606         (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE) &&
0607         fb->format->has_alpha)
0608         return -EINVAL;
0609 
0610     malidp_de_prefetch_settings(mp, ms);
0611 
0612     return 0;
0613 }
0614 
0615 static void malidp_de_set_plane_pitches(struct malidp_plane *mp,
0616                     int num_planes, unsigned int pitches[3])
0617 {
0618     int i;
0619     int num_strides = num_planes;
0620 
0621     if (!mp->layer->stride_offset)
0622         return;
0623 
0624     if (num_planes == 3)
0625         num_strides = (mp->hwdev->hw->features &
0626                    MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2;
0627 
0628     /*
0629      * The drm convention for pitch is that it needs to cover width * cpp,
0630      * but our hardware wants the pitch/stride to cover all rows included
0631      * in a tile.
0632      */
0633     for (i = 0; i < num_strides; ++i) {
0634         unsigned int block_h = drm_format_info_block_height(mp->base.state->fb->format, i);
0635 
0636         malidp_hw_write(mp->hwdev, pitches[i] * block_h,
0637                 mp->layer->base +
0638                 mp->layer->stride_offset + i * 4);
0639     }
0640 }
0641 
0642 static const s16
0643 malidp_yuv2rgb_coeffs[][DRM_COLOR_RANGE_MAX][MALIDP_COLORADJ_NUM_COEFFS] = {
0644     [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
0645         1192,    0, 1634,
0646         1192, -401, -832,
0647         1192, 2066,    0,
0648           64,  512,  512
0649     },
0650     [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_FULL_RANGE] = {
0651         1024,    0, 1436,
0652         1024, -352, -731,
0653         1024, 1815,    0,
0654            0,  512,  512
0655     },
0656     [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
0657         1192,    0, 1836,
0658         1192, -218, -546,
0659         1192, 2163,    0,
0660           64,  512,  512
0661     },
0662     [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_FULL_RANGE] = {
0663         1024,    0, 1613,
0664         1024, -192, -479,
0665         1024, 1900,    0,
0666            0,  512,  512
0667     },
0668     [DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
0669         1024,    0, 1476,
0670         1024, -165, -572,
0671         1024, 1884,    0,
0672            0,  512,  512
0673     },
0674     [DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_FULL_RANGE] = {
0675         1024,    0, 1510,
0676         1024, -168, -585,
0677         1024, 1927,    0,
0678            0,  512,  512
0679     }
0680 };
0681 
0682 static void malidp_de_set_color_encoding(struct malidp_plane *plane,
0683                      enum drm_color_encoding enc,
0684                      enum drm_color_range range)
0685 {
0686     unsigned int i;
0687 
0688     for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
0689         /* coefficients are signed, two's complement values */
0690         malidp_hw_write(plane->hwdev, malidp_yuv2rgb_coeffs[enc][range][i],
0691                 plane->layer->base + plane->layer->yuv2rgb_offset +
0692                 i * 4);
0693     }
0694 }
0695 
0696 static void malidp_de_set_mmu_control(struct malidp_plane *mp,
0697                       struct malidp_plane_state *ms)
0698 {
0699     u32 mmu_ctrl;
0700 
0701     /* check hardware supports MMU prefetch */
0702     if (!mp->layer->mmu_ctrl_offset)
0703         return;
0704 
0705     mmu_ctrl = malidp_calc_mmu_control_value(ms->mmu_prefetch_mode,
0706                          MALIDP_MMU_PREFETCH_READAHEAD,
0707                          ms->n_planes,
0708                          ms->mmu_prefetch_pgsize);
0709 
0710     malidp_hw_write(mp->hwdev, mmu_ctrl,
0711             mp->layer->base + mp->layer->mmu_ctrl_offset);
0712 }
0713 
0714 static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
0715                        struct malidp_plane *mp,
0716                        int plane_index)
0717 {
0718     dma_addr_t paddr;
0719     u16 ptr;
0720     struct drm_plane *plane = &mp->base;
0721     bool afbc = fb->modifier ? true : false;
0722 
0723     ptr = mp->layer->ptr + (plane_index << 4);
0724 
0725     /*
0726      * drm_fb_cma_get_gem_addr() alters the physical base address of the
0727      * framebuffer as per the plane's src_x, src_y co-ordinates (ie to
0728      * take care of source cropping).
0729      * For AFBC, this is not needed as the cropping is handled by _AD_CROP_H
0730      * and _AD_CROP_V registers.
0731      */
0732     if (!afbc) {
0733         paddr = drm_fb_cma_get_gem_addr(fb, plane->state,
0734                         plane_index);
0735     } else {
0736         struct drm_gem_cma_object *obj;
0737 
0738         obj = drm_fb_cma_get_gem_obj(fb, plane_index);
0739 
0740         if (WARN_ON(!obj))
0741             return;
0742         paddr = obj->paddr;
0743     }
0744 
0745     malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr);
0746     malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4);
0747 }
0748 
0749 static void malidp_de_set_plane_afbc(struct drm_plane *plane)
0750 {
0751     struct malidp_plane *mp;
0752     u32 src_w, src_h, val = 0, src_x, src_y;
0753     struct drm_framebuffer *fb = plane->state->fb;
0754 
0755     mp = to_malidp_plane(plane);
0756 
0757     /* no afbc_decoder_offset means AFBC is not supported on this plane */
0758     if (!mp->layer->afbc_decoder_offset)
0759         return;
0760 
0761     if (!fb->modifier) {
0762         malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
0763         return;
0764     }
0765 
0766     /* convert src values from Q16 fixed point to integer */
0767     src_w = plane->state->src_w >> 16;
0768     src_h = plane->state->src_h >> 16;
0769     src_x = plane->state->src_x >> 16;
0770     src_y = plane->state->src_y >> 16;
0771 
0772     val = ((fb->width - (src_x + src_w)) << MALIDP_AD_CROP_RIGHT_OFFSET) |
0773            src_x;
0774     malidp_hw_write(mp->hwdev, val,
0775             mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_H);
0776 
0777     val = ((fb->height - (src_y + src_h)) << MALIDP_AD_CROP_BOTTOM_OFFSET) |
0778            src_y;
0779     malidp_hw_write(mp->hwdev, val,
0780             mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_V);
0781 
0782     val = MALIDP_AD_EN;
0783     if (fb->modifier & AFBC_FORMAT_MOD_SPLIT)
0784         val |= MALIDP_AD_BS;
0785     if (fb->modifier & AFBC_FORMAT_MOD_YTR)
0786         val |= MALIDP_AD_YTR;
0787 
0788     malidp_hw_write(mp->hwdev, val, mp->layer->afbc_decoder_offset);
0789 }
0790 
0791 static void malidp_de_plane_update(struct drm_plane *plane,
0792                    struct drm_atomic_state *state)
0793 {
0794     struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
0795                                        plane);
0796     struct malidp_plane *mp;
0797     struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
0798     struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
0799                                        plane);
0800     u16 pixel_alpha = new_state->pixel_blend_mode;
0801     u8 plane_alpha = new_state->alpha >> 8;
0802     u32 src_w, src_h, dest_w, dest_h, val;
0803     int i;
0804     struct drm_framebuffer *fb = plane->state->fb;
0805 
0806     mp = to_malidp_plane(plane);
0807 
0808     /*
0809      * For AFBC framebuffer, use the framebuffer width and height for
0810      * configuring layer input size register.
0811      */
0812     if (fb->modifier) {
0813         src_w = fb->width;
0814         src_h = fb->height;
0815     } else {
0816         /* convert src values from Q16 fixed point to integer */
0817         src_w = new_state->src_w >> 16;
0818         src_h = new_state->src_h >> 16;
0819     }
0820 
0821     dest_w = new_state->crtc_w;
0822     dest_h = new_state->crtc_h;
0823 
0824     val = malidp_hw_read(mp->hwdev, mp->layer->base);
0825     val = (val & ~LAYER_FORMAT_MASK) | ms->format;
0826     malidp_hw_write(mp->hwdev, val, mp->layer->base);
0827 
0828     for (i = 0; i < ms->n_planes; i++)
0829         malidp_set_plane_base_addr(fb, mp, i);
0830 
0831     malidp_de_set_mmu_control(mp, ms);
0832 
0833     malidp_de_set_plane_pitches(mp, ms->n_planes,
0834                     new_state->fb->pitches);
0835 
0836     if ((plane->state->color_encoding != old_state->color_encoding) ||
0837         (plane->state->color_range != old_state->color_range))
0838         malidp_de_set_color_encoding(mp, plane->state->color_encoding,
0839                          plane->state->color_range);
0840 
0841     malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
0842             mp->layer->base + MALIDP_LAYER_SIZE);
0843 
0844     malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
0845             mp->layer->base + MALIDP_LAYER_COMP_SIZE);
0846 
0847     malidp_hw_write(mp->hwdev, LAYER_H_VAL(new_state->crtc_x) |
0848             LAYER_V_VAL(new_state->crtc_y),
0849             mp->layer->base + MALIDP_LAYER_OFFSET);
0850 
0851     if (mp->layer->id == DE_SMART) {
0852         /*
0853          * Enable the first rectangle in the SMART layer to be
0854          * able to use it as a drm plane.
0855          */
0856         malidp_hw_write(mp->hwdev, 1,
0857                 mp->layer->base + MALIDP550_LS_ENABLE);
0858         malidp_hw_write(mp->hwdev,
0859                 LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
0860                 mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
0861     }
0862 
0863     malidp_de_set_plane_afbc(plane);
0864 
0865     /* first clear the rotation bits */
0866     val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
0867     val &= ~LAYER_ROT_MASK;
0868 
0869     /* setup the rotation and axis flip bits */
0870     if (new_state->rotation & DRM_MODE_ROTATE_MASK)
0871         val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) <<
0872                LAYER_ROT_OFFSET;
0873     if (new_state->rotation & DRM_MODE_REFLECT_X)
0874         val |= LAYER_H_FLIP;
0875     if (new_state->rotation & DRM_MODE_REFLECT_Y)
0876         val |= LAYER_V_FLIP;
0877 
0878     val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE | LAYER_ALPHA(0xff));
0879 
0880     if (new_state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
0881         val |= LAYER_COMP_PLANE;
0882     } else if (new_state->fb->format->has_alpha) {
0883         /* We only care about blend mode if the format has alpha */
0884         switch (pixel_alpha) {
0885         case DRM_MODE_BLEND_PREMULTI:
0886             val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE;
0887             break;
0888         case DRM_MODE_BLEND_COVERAGE:
0889             val |= LAYER_COMP_PIXEL;
0890             break;
0891         }
0892     }
0893     val |= LAYER_ALPHA(plane_alpha);
0894 
0895     val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
0896     if (new_state->crtc) {
0897         struct malidp_crtc_state *m =
0898             to_malidp_crtc_state(new_state->crtc->state);
0899 
0900         if (m->scaler_config.scale_enable &&
0901             m->scaler_config.plane_src_id == mp->layer->id)
0902             val |= LAYER_FLOWCFG(LAYER_FLOWCFG_SCALE_SE);
0903     }
0904 
0905     /* set the 'enable layer' bit */
0906     val |= LAYER_ENABLE;
0907 
0908     malidp_hw_write(mp->hwdev, val,
0909             mp->layer->base + MALIDP_LAYER_CONTROL);
0910 }
0911 
0912 static void malidp_de_plane_disable(struct drm_plane *plane,
0913                     struct drm_atomic_state *state)
0914 {
0915     struct malidp_plane *mp = to_malidp_plane(plane);
0916 
0917     malidp_hw_clearbits(mp->hwdev,
0918                 LAYER_ENABLE | LAYER_FLOWCFG(LAYER_FLOWCFG_MASK),
0919                 mp->layer->base + MALIDP_LAYER_CONTROL);
0920 }
0921 
0922 static const struct drm_plane_helper_funcs malidp_de_plane_helper_funcs = {
0923     .atomic_check = malidp_de_plane_check,
0924     .atomic_update = malidp_de_plane_update,
0925     .atomic_disable = malidp_de_plane_disable,
0926 };
0927 
0928 static const uint64_t linear_only_modifiers[] = {
0929     DRM_FORMAT_MOD_LINEAR,
0930     DRM_FORMAT_MOD_INVALID
0931 };
0932 
0933 int malidp_de_planes_init(struct drm_device *drm)
0934 {
0935     struct malidp_drm *malidp = drm->dev_private;
0936     const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
0937     struct malidp_plane *plane = NULL;
0938     enum drm_plane_type plane_type;
0939     unsigned long crtcs = BIT(drm->mode_config.num_crtc);
0940     unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
0941                   DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
0942     unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
0943                   BIT(DRM_MODE_BLEND_PREMULTI)   |
0944                   BIT(DRM_MODE_BLEND_COVERAGE);
0945     u32 *formats;
0946     int ret, i = 0, j = 0, n;
0947     u64 supported_modifiers[MODIFIERS_COUNT_MAX];
0948     const u64 *modifiers;
0949 
0950     modifiers = malidp_format_modifiers;
0951 
0952     if (!(map->features & MALIDP_DEVICE_AFBC_SUPPORT_SPLIT)) {
0953         /*
0954          * Since our hardware does not support SPLIT, so build the list
0955          * of supported modifiers excluding SPLIT ones.
0956          */
0957         while (*modifiers != DRM_FORMAT_MOD_INVALID) {
0958             if (!(*modifiers & AFBC_SPLIT))
0959                 supported_modifiers[j++] = *modifiers;
0960 
0961             modifiers++;
0962         }
0963         supported_modifiers[j++] = DRM_FORMAT_MOD_INVALID;
0964         modifiers = supported_modifiers;
0965     }
0966 
0967     formats = kcalloc(map->n_pixel_formats, sizeof(*formats), GFP_KERNEL);
0968     if (!formats) {
0969         ret = -ENOMEM;
0970         goto cleanup;
0971     }
0972 
0973     for (i = 0; i < map->n_layers; i++) {
0974         u8 id = map->layers[i].id;
0975 
0976         plane = kzalloc(sizeof(*plane), GFP_KERNEL);
0977         if (!plane) {
0978             ret = -ENOMEM;
0979             goto cleanup;
0980         }
0981 
0982         /* build the list of DRM supported formats based on the map */
0983         for (n = 0, j = 0;  j < map->n_pixel_formats; j++) {
0984             if ((map->pixel_formats[j].layer & id) == id)
0985                 formats[n++] = map->pixel_formats[j].format;
0986         }
0987 
0988         plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
0989                     DRM_PLANE_TYPE_OVERLAY;
0990 
0991         /*
0992          * All the layers except smart layer supports AFBC modifiers.
0993          */
0994         ret = drm_universal_plane_init(drm, &plane->base, crtcs,
0995                 &malidp_de_plane_funcs, formats, n,
0996                 (id == DE_SMART) ? linear_only_modifiers : modifiers,
0997                 plane_type, NULL);
0998 
0999         if (ret < 0)
1000             goto cleanup;
1001 
1002         drm_plane_helper_add(&plane->base,
1003                      &malidp_de_plane_helper_funcs);
1004         plane->hwdev = malidp->dev;
1005         plane->layer = &map->layers[i];
1006 
1007         drm_plane_create_alpha_property(&plane->base);
1008         drm_plane_create_blend_mode_property(&plane->base, blend_caps);
1009 
1010         if (id == DE_SMART) {
1011             /* Skip the features which the SMART layer doesn't have. */
1012             continue;
1013         }
1014 
1015         drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, flags);
1016         malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
1017                 plane->layer->base + MALIDP_LAYER_COMPOSE);
1018 
1019         /* Attach the YUV->RGB property only to video layers */
1020         if (id & (DE_VIDEO1 | DE_VIDEO2)) {
1021             /* default encoding for YUV->RGB is BT601 NARROW */
1022             enum drm_color_encoding enc = DRM_COLOR_YCBCR_BT601;
1023             enum drm_color_range range = DRM_COLOR_YCBCR_LIMITED_RANGE;
1024 
1025             ret = drm_plane_create_color_properties(&plane->base,
1026                     BIT(DRM_COLOR_YCBCR_BT601) | \
1027                     BIT(DRM_COLOR_YCBCR_BT709) | \
1028                     BIT(DRM_COLOR_YCBCR_BT2020),
1029                     BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \
1030                     BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1031                     enc, range);
1032             if (!ret)
1033                 /* program the HW registers */
1034                 malidp_de_set_color_encoding(plane, enc, range);
1035             else
1036                 DRM_WARN("Failed to create video layer %d color properties\n", id);
1037         }
1038     }
1039 
1040     kfree(formats);
1041 
1042     return 0;
1043 
1044 cleanup:
1045     kfree(formats);
1046 
1047     return ret;
1048 }