0001
0002
0003
0004
0005
0006
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
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
0059
0060
0061
0062
0063 #define MALIDP_ALPHA_LUT 0xffaa5500
0064
0065
0066 #define MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES (SZ_4K | SZ_64K)
0067 #define MALIDP_MMU_PREFETCH_FULL_PGSIZES (SZ_1M | SZ_2M)
0068
0069
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
0082
0083
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
0162 if (modifier == DRM_FORMAT_MOD_LINEAR) {
0163
0164
0165
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
0184 if (WARN_ON_ONCE((modifier & AFBC_SPLIT) && !(modifier & AFBC_SPARSE)))
0185 return false;
0186
0187
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
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
0219
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
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
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
0326
0327
0328
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
0372
0373
0374 static bool malidp_partial_prefetch_supported(u32 format, u64 modifier,
0375 unsigned int rotation)
0376 {
0377 bool afbc, sparse;
0378
0379
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
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
0409 return (!afbc) || (afbc && sparse);
0410
0411 case DRM_FORMAT_BGR888:
0412
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
0420 return false;
0421
0422 default:
0423 return false;
0424 }
0425 }
0426
0427
0428
0429
0430
0431
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
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
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
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
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
0557
0558
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
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
0577
0578
0579 if ((fb->format->format == DRM_FORMAT_RGB888 ||
0580 fb->format->format == DRM_FORMAT_BGR888) && !(fb->modifier))
0581 return -EINVAL;
0582 }
0583
0584
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
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
0630
0631
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
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
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
0727
0728
0729
0730
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
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
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
0810
0811
0812 if (fb->modifier) {
0813 src_w = fb->width;
0814 src_h = fb->height;
0815 } else {
0816
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
0854
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
0866 val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
0867 val &= ~LAYER_ROT_MASK;
0868
0869
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
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
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
0955
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
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
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
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
1020 if (id & (DE_VIDEO1 | DE_VIDEO2)) {
1021
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
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 }