| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * (C) COPYRIGHT 2016 ARM Limited. All rights reserved. |
|---|
| 3 | 4 | * Author: Liviu Dudau <Liviu.Dudau@arm.com> |
|---|
| 4 | 5 | * |
|---|
| 5 | | - * This program is free software and is provided to you under the terms of the |
|---|
| 6 | | - * GNU General Public License version 2 as published by the Free Software |
|---|
| 7 | | - * Foundation, and any use by you of this program is subject to the terms |
|---|
| 8 | | - * of such GNU licence. |
|---|
| 9 | | - * |
|---|
| 10 | 6 | * ARM Mali DP plane manipulation routines. |
|---|
| 11 | 7 | */ |
|---|
| 12 | 8 | |
|---|
| 13 | | -#include <drm/drmP.h> |
|---|
| 9 | +#include <linux/iommu.h> |
|---|
| 10 | +#include <linux/platform_device.h> |
|---|
| 11 | + |
|---|
| 14 | 12 | #include <drm/drm_atomic.h> |
|---|
| 15 | 13 | #include <drm/drm_atomic_helper.h> |
|---|
| 14 | +#include <drm/drm_drv.h> |
|---|
| 16 | 15 | #include <drm/drm_fb_cma_helper.h> |
|---|
| 16 | +#include <drm/drm_fourcc.h> |
|---|
| 17 | 17 | #include <drm/drm_gem_cma_helper.h> |
|---|
| 18 | +#include <drm/drm_gem_framebuffer_helper.h> |
|---|
| 18 | 19 | #include <drm/drm_plane_helper.h> |
|---|
| 19 | 20 | #include <drm/drm_print.h> |
|---|
| 20 | 21 | |
|---|
| .. | .. |
|---|
| 36 | 37 | #define LAYER_COMP_MASK (0x3 << 12) |
|---|
| 37 | 38 | #define LAYER_COMP_PIXEL (0x3 << 12) |
|---|
| 38 | 39 | #define LAYER_COMP_PLANE (0x2 << 12) |
|---|
| 40 | +#define LAYER_PMUL_ENABLE (0x1 << 14) |
|---|
| 39 | 41 | #define LAYER_ALPHA_OFFSET (16) |
|---|
| 40 | 42 | #define LAYER_ALPHA_MASK (0xff) |
|---|
| 41 | 43 | #define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) |
|---|
| .. | .. |
|---|
| 48 | 50 | #define MALIDP550_LS_ENABLE 0x01c |
|---|
| 49 | 51 | #define MALIDP550_LS_R1_IN_SIZE 0x020 |
|---|
| 50 | 52 | |
|---|
| 53 | +#define MODIFIERS_COUNT_MAX 15 |
|---|
| 54 | + |
|---|
| 51 | 55 | /* |
|---|
| 52 | 56 | * This 4-entry look-up-table is used to determine the full 8-bit alpha value |
|---|
| 53 | 57 | * for formats with 1- or 2-bit alpha channels. |
|---|
| .. | .. |
|---|
| 55 | 59 | * opacity for 2-bit formats. |
|---|
| 56 | 60 | */ |
|---|
| 57 | 61 | #define MALIDP_ALPHA_LUT 0xffaa5500 |
|---|
| 62 | + |
|---|
| 63 | +/* page sizes the MMU prefetcher can support */ |
|---|
| 64 | +#define MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES (SZ_4K | SZ_64K) |
|---|
| 65 | +#define MALIDP_MMU_PREFETCH_FULL_PGSIZES (SZ_1M | SZ_2M) |
|---|
| 66 | + |
|---|
| 67 | +/* readahead for partial-frame prefetch */ |
|---|
| 68 | +#define MALIDP_MMU_PREFETCH_READAHEAD 8 |
|---|
| 58 | 69 | |
|---|
| 59 | 70 | static void malidp_de_plane_destroy(struct drm_plane *plane) |
|---|
| 60 | 71 | { |
|---|
| .. | .. |
|---|
| 78 | 89 | kfree(state); |
|---|
| 79 | 90 | plane->state = NULL; |
|---|
| 80 | 91 | state = kzalloc(sizeof(*state), GFP_KERNEL); |
|---|
| 81 | | - if (state) { |
|---|
| 82 | | - state->base.plane = plane; |
|---|
| 83 | | - state->base.rotation = DRM_MODE_ROTATE_0; |
|---|
| 84 | | - plane->state = &state->base; |
|---|
| 85 | | - } |
|---|
| 92 | + if (state) |
|---|
| 93 | + __drm_atomic_helper_plane_reset(plane, &state->base); |
|---|
| 86 | 94 | } |
|---|
| 87 | 95 | |
|---|
| 88 | 96 | static struct |
|---|
| .. | .. |
|---|
| 103 | 111 | state->format = m_state->format; |
|---|
| 104 | 112 | state->n_planes = m_state->n_planes; |
|---|
| 105 | 113 | |
|---|
| 114 | + state->mmu_prefetch_mode = m_state->mmu_prefetch_mode; |
|---|
| 115 | + state->mmu_prefetch_pgsize = m_state->mmu_prefetch_pgsize; |
|---|
| 116 | + |
|---|
| 106 | 117 | return &state->base; |
|---|
| 107 | 118 | } |
|---|
| 108 | 119 | |
|---|
| .. | .. |
|---|
| 115 | 126 | kfree(m_state); |
|---|
| 116 | 127 | } |
|---|
| 117 | 128 | |
|---|
| 129 | +static const char * const prefetch_mode_names[] = { |
|---|
| 130 | + [MALIDP_PREFETCH_MODE_NONE] = "MMU_PREFETCH_NONE", |
|---|
| 131 | + [MALIDP_PREFETCH_MODE_PARTIAL] = "MMU_PREFETCH_PARTIAL", |
|---|
| 132 | + [MALIDP_PREFETCH_MODE_FULL] = "MMU_PREFETCH_FULL", |
|---|
| 133 | +}; |
|---|
| 134 | + |
|---|
| 118 | 135 | static void malidp_plane_atomic_print_state(struct drm_printer *p, |
|---|
| 119 | 136 | const struct drm_plane_state *state) |
|---|
| 120 | 137 | { |
|---|
| .. | .. |
|---|
| 123 | 140 | drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size); |
|---|
| 124 | 141 | drm_printf(p, "\tformat_id=%u\n", ms->format); |
|---|
| 125 | 142 | drm_printf(p, "\tn_planes=%u\n", ms->n_planes); |
|---|
| 143 | + drm_printf(p, "\tmmu_prefetch_mode=%s\n", |
|---|
| 144 | + prefetch_mode_names[ms->mmu_prefetch_mode]); |
|---|
| 145 | + drm_printf(p, "\tmmu_prefetch_pgsize=%d\n", ms->mmu_prefetch_pgsize); |
|---|
| 146 | +} |
|---|
| 147 | + |
|---|
| 148 | +bool malidp_format_mod_supported(struct drm_device *drm, |
|---|
| 149 | + u32 format, u64 modifier) |
|---|
| 150 | +{ |
|---|
| 151 | + const struct drm_format_info *info; |
|---|
| 152 | + const u64 *modifiers; |
|---|
| 153 | + struct malidp_drm *malidp = drm->dev_private; |
|---|
| 154 | + const struct malidp_hw_regmap *map = &malidp->dev->hw->map; |
|---|
| 155 | + |
|---|
| 156 | + if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID)) |
|---|
| 157 | + return false; |
|---|
| 158 | + |
|---|
| 159 | + /* Some pixel formats are supported without any modifier */ |
|---|
| 160 | + if (modifier == DRM_FORMAT_MOD_LINEAR) { |
|---|
| 161 | + /* |
|---|
| 162 | + * However these pixel formats need to be supported with |
|---|
| 163 | + * modifiers only |
|---|
| 164 | + */ |
|---|
| 165 | + return !malidp_hw_format_is_afbc_only(format); |
|---|
| 166 | + } |
|---|
| 167 | + |
|---|
| 168 | + if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) { |
|---|
| 169 | + DRM_ERROR("Unknown modifier (not Arm)\n"); |
|---|
| 170 | + return false; |
|---|
| 171 | + } |
|---|
| 172 | + |
|---|
| 173 | + if (modifier & |
|---|
| 174 | + ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) { |
|---|
| 175 | + DRM_DEBUG_KMS("Unsupported modifiers\n"); |
|---|
| 176 | + return false; |
|---|
| 177 | + } |
|---|
| 178 | + |
|---|
| 179 | + modifiers = malidp_format_modifiers; |
|---|
| 180 | + |
|---|
| 181 | + /* SPLIT buffers must use SPARSE layout */ |
|---|
| 182 | + if (WARN_ON_ONCE((modifier & AFBC_SPLIT) && !(modifier & AFBC_SPARSE))) |
|---|
| 183 | + return false; |
|---|
| 184 | + |
|---|
| 185 | + /* CBR only applies to YUV formats, where YTR should be always 0 */ |
|---|
| 186 | + if (WARN_ON_ONCE((modifier & AFBC_CBR) && (modifier & AFBC_YTR))) |
|---|
| 187 | + return false; |
|---|
| 188 | + |
|---|
| 189 | + while (*modifiers != DRM_FORMAT_MOD_INVALID) { |
|---|
| 190 | + if (*modifiers == modifier) |
|---|
| 191 | + break; |
|---|
| 192 | + |
|---|
| 193 | + modifiers++; |
|---|
| 194 | + } |
|---|
| 195 | + |
|---|
| 196 | + /* return false, if the modifier was not found */ |
|---|
| 197 | + if (*modifiers == DRM_FORMAT_MOD_INVALID) { |
|---|
| 198 | + DRM_DEBUG_KMS("Unsupported modifier\n"); |
|---|
| 199 | + return false; |
|---|
| 200 | + } |
|---|
| 201 | + |
|---|
| 202 | + info = drm_format_info(format); |
|---|
| 203 | + |
|---|
| 204 | + if (info->num_planes != 1) { |
|---|
| 205 | + DRM_DEBUG_KMS("AFBC buffers expect one plane\n"); |
|---|
| 206 | + return false; |
|---|
| 207 | + } |
|---|
| 208 | + |
|---|
| 209 | + if (malidp_hw_format_is_linear_only(format) == true) { |
|---|
| 210 | + DRM_DEBUG_KMS("Given format (0x%x) is supported is linear mode only\n", |
|---|
| 211 | + format); |
|---|
| 212 | + return false; |
|---|
| 213 | + } |
|---|
| 214 | + |
|---|
| 215 | + /* |
|---|
| 216 | + * RGB formats need to provide YTR modifier and YUV formats should not |
|---|
| 217 | + * provide YTR modifier. |
|---|
| 218 | + */ |
|---|
| 219 | + if (!(info->is_yuv) != !!(modifier & AFBC_FORMAT_MOD_YTR)) { |
|---|
| 220 | + DRM_DEBUG_KMS("AFBC_FORMAT_MOD_YTR is %s for %s formats\n", |
|---|
| 221 | + info->is_yuv ? "disallowed" : "mandatory", |
|---|
| 222 | + info->is_yuv ? "YUV" : "RGB"); |
|---|
| 223 | + return false; |
|---|
| 224 | + } |
|---|
| 225 | + |
|---|
| 226 | + if (modifier & AFBC_SPLIT) { |
|---|
| 227 | + if (!info->is_yuv) { |
|---|
| 228 | + if (info->cpp[0] <= 2) { |
|---|
| 229 | + DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n"); |
|---|
| 230 | + return false; |
|---|
| 231 | + } |
|---|
| 232 | + } |
|---|
| 233 | + |
|---|
| 234 | + if ((info->hsub != 1) || (info->vsub != 1)) { |
|---|
| 235 | + if (!(format == DRM_FORMAT_YUV420_10BIT && |
|---|
| 236 | + (map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) { |
|---|
| 237 | + DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n"); |
|---|
| 238 | + return false; |
|---|
| 239 | + } |
|---|
| 240 | + } |
|---|
| 241 | + } |
|---|
| 242 | + |
|---|
| 243 | + if (modifier & AFBC_CBR) { |
|---|
| 244 | + if ((info->hsub == 1) || (info->vsub == 1)) { |
|---|
| 245 | + DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n"); |
|---|
| 246 | + return false; |
|---|
| 247 | + } |
|---|
| 248 | + } |
|---|
| 249 | + |
|---|
| 250 | + return true; |
|---|
| 251 | +} |
|---|
| 252 | + |
|---|
| 253 | +static bool malidp_format_mod_supported_per_plane(struct drm_plane *plane, |
|---|
| 254 | + u32 format, u64 modifier) |
|---|
| 255 | +{ |
|---|
| 256 | + return malidp_format_mod_supported(plane->dev, format, modifier); |
|---|
| 126 | 257 | } |
|---|
| 127 | 258 | |
|---|
| 128 | 259 | static const struct drm_plane_funcs malidp_de_plane_funcs = { |
|---|
| .. | .. |
|---|
| 133 | 264 | .atomic_duplicate_state = malidp_duplicate_plane_state, |
|---|
| 134 | 265 | .atomic_destroy_state = malidp_destroy_plane_state, |
|---|
| 135 | 266 | .atomic_print_state = malidp_plane_atomic_print_state, |
|---|
| 267 | + .format_mod_supported = malidp_format_mod_supported_per_plane, |
|---|
| 136 | 268 | }; |
|---|
| 137 | 269 | |
|---|
| 138 | 270 | static int malidp_se_check_scaling(struct malidp_plane *mp, |
|---|
| .. | .. |
|---|
| 176 | 308 | return 0; |
|---|
| 177 | 309 | } |
|---|
| 178 | 310 | |
|---|
| 311 | +static u32 malidp_get_pgsize_bitmap(struct malidp_plane *mp) |
|---|
| 312 | +{ |
|---|
| 313 | + u32 pgsize_bitmap = 0; |
|---|
| 314 | + |
|---|
| 315 | + if (iommu_present(&platform_bus_type)) { |
|---|
| 316 | + struct iommu_domain *mmu_dom = |
|---|
| 317 | + iommu_get_domain_for_dev(mp->base.dev->dev); |
|---|
| 318 | + |
|---|
| 319 | + if (mmu_dom) |
|---|
| 320 | + pgsize_bitmap = mmu_dom->pgsize_bitmap; |
|---|
| 321 | + } |
|---|
| 322 | + |
|---|
| 323 | + return pgsize_bitmap; |
|---|
| 324 | +} |
|---|
| 325 | + |
|---|
| 326 | +/* |
|---|
| 327 | + * Check if the framebuffer is entirely made up of pages at least pgsize in |
|---|
| 328 | + * size. Only a heuristic: assumes that each scatterlist entry has been aligned |
|---|
| 329 | + * to the largest page size smaller than its length and that the MMU maps to |
|---|
| 330 | + * the largest page size possible. |
|---|
| 331 | + */ |
|---|
| 332 | +static bool malidp_check_pages_threshold(struct malidp_plane_state *ms, |
|---|
| 333 | + u32 pgsize) |
|---|
| 334 | +{ |
|---|
| 335 | + int i; |
|---|
| 336 | + |
|---|
| 337 | + for (i = 0; i < ms->n_planes; i++) { |
|---|
| 338 | + struct drm_gem_object *obj; |
|---|
| 339 | + struct drm_gem_cma_object *cma_obj; |
|---|
| 340 | + struct sg_table *sgt; |
|---|
| 341 | + struct scatterlist *sgl; |
|---|
| 342 | + |
|---|
| 343 | + obj = drm_gem_fb_get_obj(ms->base.fb, i); |
|---|
| 344 | + cma_obj = to_drm_gem_cma_obj(obj); |
|---|
| 345 | + |
|---|
| 346 | + if (cma_obj->sgt) |
|---|
| 347 | + sgt = cma_obj->sgt; |
|---|
| 348 | + else |
|---|
| 349 | + sgt = obj->funcs->get_sg_table(obj); |
|---|
| 350 | + |
|---|
| 351 | + if (IS_ERR(sgt)) |
|---|
| 352 | + return false; |
|---|
| 353 | + |
|---|
| 354 | + sgl = sgt->sgl; |
|---|
| 355 | + |
|---|
| 356 | + while (sgl) { |
|---|
| 357 | + if (sgl->length < pgsize) { |
|---|
| 358 | + if (!cma_obj->sgt) |
|---|
| 359 | + kfree(sgt); |
|---|
| 360 | + return false; |
|---|
| 361 | + } |
|---|
| 362 | + |
|---|
| 363 | + sgl = sg_next(sgl); |
|---|
| 364 | + } |
|---|
| 365 | + if (!cma_obj->sgt) |
|---|
| 366 | + kfree(sgt); |
|---|
| 367 | + } |
|---|
| 368 | + |
|---|
| 369 | + return true; |
|---|
| 370 | +} |
|---|
| 371 | + |
|---|
| 372 | +/* |
|---|
| 373 | + * Check if it is possible to enable partial-frame MMU prefetch given the |
|---|
| 374 | + * current format, AFBC state and rotation. |
|---|
| 375 | + */ |
|---|
| 376 | +static bool malidp_partial_prefetch_supported(u32 format, u64 modifier, |
|---|
| 377 | + unsigned int rotation) |
|---|
| 378 | +{ |
|---|
| 379 | + bool afbc, sparse; |
|---|
| 380 | + |
|---|
| 381 | + /* rotation and horizontal flip not supported for partial prefetch */ |
|---|
| 382 | + if (rotation & (DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | |
|---|
| 383 | + DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X)) |
|---|
| 384 | + return false; |
|---|
| 385 | + |
|---|
| 386 | + afbc = modifier & DRM_FORMAT_MOD_ARM_AFBC(0); |
|---|
| 387 | + sparse = modifier & AFBC_FORMAT_MOD_SPARSE; |
|---|
| 388 | + |
|---|
| 389 | + switch (format) { |
|---|
| 390 | + case DRM_FORMAT_ARGB2101010: |
|---|
| 391 | + case DRM_FORMAT_RGBA1010102: |
|---|
| 392 | + case DRM_FORMAT_BGRA1010102: |
|---|
| 393 | + case DRM_FORMAT_ARGB8888: |
|---|
| 394 | + case DRM_FORMAT_RGBA8888: |
|---|
| 395 | + case DRM_FORMAT_BGRA8888: |
|---|
| 396 | + case DRM_FORMAT_XRGB8888: |
|---|
| 397 | + case DRM_FORMAT_XBGR8888: |
|---|
| 398 | + case DRM_FORMAT_RGBX8888: |
|---|
| 399 | + case DRM_FORMAT_BGRX8888: |
|---|
| 400 | + case DRM_FORMAT_RGB888: |
|---|
| 401 | + case DRM_FORMAT_RGBA5551: |
|---|
| 402 | + case DRM_FORMAT_RGB565: |
|---|
| 403 | + /* always supported */ |
|---|
| 404 | + return true; |
|---|
| 405 | + |
|---|
| 406 | + case DRM_FORMAT_ABGR2101010: |
|---|
| 407 | + case DRM_FORMAT_ABGR8888: |
|---|
| 408 | + case DRM_FORMAT_ABGR1555: |
|---|
| 409 | + case DRM_FORMAT_BGR565: |
|---|
| 410 | + /* supported, but if AFBC then must be sparse mode */ |
|---|
| 411 | + return (!afbc) || (afbc && sparse); |
|---|
| 412 | + |
|---|
| 413 | + case DRM_FORMAT_BGR888: |
|---|
| 414 | + /* supported, but not for AFBC */ |
|---|
| 415 | + return !afbc; |
|---|
| 416 | + |
|---|
| 417 | + case DRM_FORMAT_YUYV: |
|---|
| 418 | + case DRM_FORMAT_UYVY: |
|---|
| 419 | + case DRM_FORMAT_NV12: |
|---|
| 420 | + case DRM_FORMAT_YUV420: |
|---|
| 421 | + /* not supported */ |
|---|
| 422 | + return false; |
|---|
| 423 | + |
|---|
| 424 | + default: |
|---|
| 425 | + return false; |
|---|
| 426 | + } |
|---|
| 427 | +} |
|---|
| 428 | + |
|---|
| 429 | +/* |
|---|
| 430 | + * Select the preferred MMU prefetch mode. Full-frame prefetch is preferred as |
|---|
| 431 | + * long as the framebuffer is all large pages. Otherwise partial-frame prefetch |
|---|
| 432 | + * is selected as long as it is supported for the current format. The selected |
|---|
| 433 | + * page size for prefetch is returned in pgsize_bitmap. |
|---|
| 434 | + */ |
|---|
| 435 | +static enum mmu_prefetch_mode malidp_mmu_prefetch_select_mode |
|---|
| 436 | + (struct malidp_plane_state *ms, u32 *pgsize_bitmap) |
|---|
| 437 | +{ |
|---|
| 438 | + u32 pgsizes; |
|---|
| 439 | + |
|---|
| 440 | + /* get the full-frame prefetch page size(s) supported by the MMU */ |
|---|
| 441 | + pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_FULL_PGSIZES; |
|---|
| 442 | + |
|---|
| 443 | + while (pgsizes) { |
|---|
| 444 | + u32 largest_pgsize = 1 << __fls(pgsizes); |
|---|
| 445 | + |
|---|
| 446 | + if (malidp_check_pages_threshold(ms, largest_pgsize)) { |
|---|
| 447 | + *pgsize_bitmap = largest_pgsize; |
|---|
| 448 | + return MALIDP_PREFETCH_MODE_FULL; |
|---|
| 449 | + } |
|---|
| 450 | + |
|---|
| 451 | + pgsizes -= largest_pgsize; |
|---|
| 452 | + } |
|---|
| 453 | + |
|---|
| 454 | + /* get the partial-frame prefetch page size(s) supported by the MMU */ |
|---|
| 455 | + pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES; |
|---|
| 456 | + |
|---|
| 457 | + if (malidp_partial_prefetch_supported(ms->base.fb->format->format, |
|---|
| 458 | + ms->base.fb->modifier, |
|---|
| 459 | + ms->base.rotation)) { |
|---|
| 460 | + /* partial prefetch using the smallest page size */ |
|---|
| 461 | + *pgsize_bitmap = 1 << __ffs(pgsizes); |
|---|
| 462 | + return MALIDP_PREFETCH_MODE_PARTIAL; |
|---|
| 463 | + } |
|---|
| 464 | + *pgsize_bitmap = 0; |
|---|
| 465 | + return MALIDP_PREFETCH_MODE_NONE; |
|---|
| 466 | +} |
|---|
| 467 | + |
|---|
| 468 | +static u32 malidp_calc_mmu_control_value(enum mmu_prefetch_mode mode, |
|---|
| 469 | + u8 readahead, u8 n_planes, u32 pgsize) |
|---|
| 470 | +{ |
|---|
| 471 | + u32 mmu_ctrl = 0; |
|---|
| 472 | + |
|---|
| 473 | + if (mode != MALIDP_PREFETCH_MODE_NONE) { |
|---|
| 474 | + mmu_ctrl |= MALIDP_MMU_CTRL_EN; |
|---|
| 475 | + |
|---|
| 476 | + if (mode == MALIDP_PREFETCH_MODE_PARTIAL) { |
|---|
| 477 | + mmu_ctrl |= MALIDP_MMU_CTRL_MODE; |
|---|
| 478 | + mmu_ctrl |= MALIDP_MMU_CTRL_PP_NUM_REQ(readahead); |
|---|
| 479 | + } |
|---|
| 480 | + |
|---|
| 481 | + if (pgsize == SZ_64K || pgsize == SZ_2M) { |
|---|
| 482 | + int i; |
|---|
| 483 | + |
|---|
| 484 | + for (i = 0; i < n_planes; i++) |
|---|
| 485 | + mmu_ctrl |= MALIDP_MMU_CTRL_PX_PS(i); |
|---|
| 486 | + } |
|---|
| 487 | + } |
|---|
| 488 | + |
|---|
| 489 | + return mmu_ctrl; |
|---|
| 490 | +} |
|---|
| 491 | + |
|---|
| 492 | +static void malidp_de_prefetch_settings(struct malidp_plane *mp, |
|---|
| 493 | + struct malidp_plane_state *ms) |
|---|
| 494 | +{ |
|---|
| 495 | + if (!mp->layer->mmu_ctrl_offset) |
|---|
| 496 | + return; |
|---|
| 497 | + |
|---|
| 498 | + /* get the page sizes supported by the MMU */ |
|---|
| 499 | + ms->mmu_prefetch_pgsize = malidp_get_pgsize_bitmap(mp); |
|---|
| 500 | + ms->mmu_prefetch_mode = |
|---|
| 501 | + malidp_mmu_prefetch_select_mode(ms, &ms->mmu_prefetch_pgsize); |
|---|
| 502 | +} |
|---|
| 503 | + |
|---|
| 179 | 504 | static int malidp_de_plane_check(struct drm_plane *plane, |
|---|
| 180 | 505 | struct drm_plane_state *state) |
|---|
| 181 | 506 | { |
|---|
| .. | .. |
|---|
| 183 | 508 | struct malidp_plane_state *ms = to_malidp_plane_state(state); |
|---|
| 184 | 509 | bool rotated = state->rotation & MALIDP_ROTATED_MASK; |
|---|
| 185 | 510 | struct drm_framebuffer *fb; |
|---|
| 511 | + u16 pixel_alpha = state->pixel_blend_mode; |
|---|
| 186 | 512 | int i, ret; |
|---|
| 513 | + unsigned int block_w, block_h; |
|---|
| 187 | 514 | |
|---|
| 188 | | - if (!state->crtc || !state->fb) |
|---|
| 515 | + if (!state->crtc || WARN_ON(!state->fb)) |
|---|
| 189 | 516 | return 0; |
|---|
| 190 | 517 | |
|---|
| 191 | 518 | fb = state->fb; |
|---|
| 192 | 519 | |
|---|
| 193 | 520 | ms->format = malidp_hw_get_format_id(&mp->hwdev->hw->map, |
|---|
| 194 | | - mp->layer->id, |
|---|
| 195 | | - fb->format->format); |
|---|
| 521 | + mp->layer->id, fb->format->format, |
|---|
| 522 | + !!fb->modifier); |
|---|
| 196 | 523 | if (ms->format == MALIDP_INVALID_FORMAT_ID) |
|---|
| 197 | 524 | return -EINVAL; |
|---|
| 198 | 525 | |
|---|
| 199 | 526 | ms->n_planes = fb->format->num_planes; |
|---|
| 200 | 527 | for (i = 0; i < ms->n_planes; i++) { |
|---|
| 201 | 528 | u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated); |
|---|
| 202 | | - if (fb->pitches[i] & (alignment - 1)) { |
|---|
| 529 | + |
|---|
| 530 | + if (((fb->pitches[i] * drm_format_info_block_height(fb->format, i)) |
|---|
| 531 | + & (alignment - 1)) && !(fb->modifier)) { |
|---|
| 203 | 532 | DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n", |
|---|
| 204 | 533 | fb->pitches[i], i); |
|---|
| 205 | 534 | return -EINVAL; |
|---|
| 206 | 535 | } |
|---|
| 536 | + } |
|---|
| 537 | + |
|---|
| 538 | + block_w = drm_format_info_block_width(fb->format, 0); |
|---|
| 539 | + block_h = drm_format_info_block_height(fb->format, 0); |
|---|
| 540 | + if (fb->width % block_w || fb->height % block_h) { |
|---|
| 541 | + DRM_DEBUG_KMS("Buffer width/height needs to be a multiple of tile sizes"); |
|---|
| 542 | + return -EINVAL; |
|---|
| 543 | + } |
|---|
| 544 | + if ((state->src_x >> 16) % block_w || (state->src_y >> 16) % block_h) { |
|---|
| 545 | + DRM_DEBUG_KMS("Plane src_x/src_y needs to be a multiple of tile sizes"); |
|---|
| 546 | + return -EINVAL; |
|---|
| 207 | 547 | } |
|---|
| 208 | 548 | |
|---|
| 209 | 549 | if ((state->crtc_w > mp->hwdev->max_line_size) || |
|---|
| .. | .. |
|---|
| 226 | 566 | if (ret) |
|---|
| 227 | 567 | return ret; |
|---|
| 228 | 568 | |
|---|
| 229 | | - /* packed RGB888 / BGR888 can't be rotated or flipped */ |
|---|
| 230 | | - if (state->rotation != DRM_MODE_ROTATE_0 && |
|---|
| 231 | | - (fb->format->format == DRM_FORMAT_RGB888 || |
|---|
| 232 | | - fb->format->format == DRM_FORMAT_BGR888)) |
|---|
| 569 | + /* validate the rotation constraints for each layer */ |
|---|
| 570 | + if (state->rotation != DRM_MODE_ROTATE_0) { |
|---|
| 571 | + if (mp->layer->rot == ROTATE_NONE) |
|---|
| 572 | + return -EINVAL; |
|---|
| 573 | + if ((mp->layer->rot == ROTATE_COMPRESSED) && !(fb->modifier)) |
|---|
| 574 | + return -EINVAL; |
|---|
| 575 | + /* |
|---|
| 576 | + * packed RGB888 / BGR888 can't be rotated or flipped |
|---|
| 577 | + * unless they are stored in a compressed way |
|---|
| 578 | + */ |
|---|
| 579 | + if ((fb->format->format == DRM_FORMAT_RGB888 || |
|---|
| 580 | + fb->format->format == DRM_FORMAT_BGR888) && !(fb->modifier)) |
|---|
| 581 | + return -EINVAL; |
|---|
| 582 | + } |
|---|
| 583 | + |
|---|
| 584 | + /* SMART layer does not support AFBC */ |
|---|
| 585 | + if (mp->layer->id == DE_SMART && fb->modifier) { |
|---|
| 586 | + DRM_ERROR("AFBC framebuffer not supported in SMART layer"); |
|---|
| 233 | 587 | return -EINVAL; |
|---|
| 588 | + } |
|---|
| 234 | 589 | |
|---|
| 235 | 590 | ms->rotmem_size = 0; |
|---|
| 236 | 591 | if (state->rotation & MALIDP_ROTATED_MASK) { |
|---|
| .. | .. |
|---|
| 238 | 593 | |
|---|
| 239 | 594 | val = mp->hwdev->hw->rotmem_required(mp->hwdev, state->crtc_w, |
|---|
| 240 | 595 | state->crtc_h, |
|---|
| 241 | | - fb->format->format); |
|---|
| 596 | + fb->format->format, |
|---|
| 597 | + !!(fb->modifier)); |
|---|
| 242 | 598 | if (val < 0) |
|---|
| 243 | 599 | return val; |
|---|
| 244 | 600 | |
|---|
| 245 | 601 | ms->rotmem_size = val; |
|---|
| 246 | 602 | } |
|---|
| 603 | + |
|---|
| 604 | + /* HW can't support plane + pixel blending */ |
|---|
| 605 | + if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) && |
|---|
| 606 | + (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE) && |
|---|
| 607 | + fb->format->has_alpha) |
|---|
| 608 | + return -EINVAL; |
|---|
| 609 | + |
|---|
| 610 | + malidp_de_prefetch_settings(mp, ms); |
|---|
| 247 | 611 | |
|---|
| 248 | 612 | return 0; |
|---|
| 249 | 613 | } |
|---|
| .. | .. |
|---|
| 261 | 625 | num_strides = (mp->hwdev->hw->features & |
|---|
| 262 | 626 | MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2; |
|---|
| 263 | 627 | |
|---|
| 264 | | - for (i = 0; i < num_strides; ++i) |
|---|
| 265 | | - malidp_hw_write(mp->hwdev, pitches[i], |
|---|
| 628 | + /* |
|---|
| 629 | + * The drm convention for pitch is that it needs to cover width * cpp, |
|---|
| 630 | + * but our hardware wants the pitch/stride to cover all rows included |
|---|
| 631 | + * in a tile. |
|---|
| 632 | + */ |
|---|
| 633 | + for (i = 0; i < num_strides; ++i) { |
|---|
| 634 | + unsigned int block_h = drm_format_info_block_height(mp->base.state->fb->format, i); |
|---|
| 635 | + |
|---|
| 636 | + malidp_hw_write(mp->hwdev, pitches[i] * block_h, |
|---|
| 266 | 637 | mp->layer->base + |
|---|
| 267 | 638 | mp->layer->stride_offset + i * 4); |
|---|
| 639 | + } |
|---|
| 268 | 640 | } |
|---|
| 269 | 641 | |
|---|
| 270 | 642 | static const s16 |
|---|
| .. | .. |
|---|
| 321 | 693 | } |
|---|
| 322 | 694 | } |
|---|
| 323 | 695 | |
|---|
| 696 | +static void malidp_de_set_mmu_control(struct malidp_plane *mp, |
|---|
| 697 | + struct malidp_plane_state *ms) |
|---|
| 698 | +{ |
|---|
| 699 | + u32 mmu_ctrl; |
|---|
| 700 | + |
|---|
| 701 | + /* check hardware supports MMU prefetch */ |
|---|
| 702 | + if (!mp->layer->mmu_ctrl_offset) |
|---|
| 703 | + return; |
|---|
| 704 | + |
|---|
| 705 | + mmu_ctrl = malidp_calc_mmu_control_value(ms->mmu_prefetch_mode, |
|---|
| 706 | + MALIDP_MMU_PREFETCH_READAHEAD, |
|---|
| 707 | + ms->n_planes, |
|---|
| 708 | + ms->mmu_prefetch_pgsize); |
|---|
| 709 | + |
|---|
| 710 | + malidp_hw_write(mp->hwdev, mmu_ctrl, |
|---|
| 711 | + mp->layer->base + mp->layer->mmu_ctrl_offset); |
|---|
| 712 | +} |
|---|
| 713 | + |
|---|
| 714 | +static void malidp_set_plane_base_addr(struct drm_framebuffer *fb, |
|---|
| 715 | + struct malidp_plane *mp, |
|---|
| 716 | + int plane_index) |
|---|
| 717 | +{ |
|---|
| 718 | + dma_addr_t paddr; |
|---|
| 719 | + u16 ptr; |
|---|
| 720 | + struct drm_plane *plane = &mp->base; |
|---|
| 721 | + bool afbc = fb->modifier ? true : false; |
|---|
| 722 | + |
|---|
| 723 | + ptr = mp->layer->ptr + (plane_index << 4); |
|---|
| 724 | + |
|---|
| 725 | + /* |
|---|
| 726 | + * drm_fb_cma_get_gem_addr() alters the physical base address of the |
|---|
| 727 | + * framebuffer as per the plane's src_x, src_y co-ordinates (ie to |
|---|
| 728 | + * take care of source cropping). |
|---|
| 729 | + * For AFBC, this is not needed as the cropping is handled by _AD_CROP_H |
|---|
| 730 | + * and _AD_CROP_V registers. |
|---|
| 731 | + */ |
|---|
| 732 | + if (!afbc) { |
|---|
| 733 | + paddr = drm_fb_cma_get_gem_addr(fb, plane->state, |
|---|
| 734 | + plane_index); |
|---|
| 735 | + } else { |
|---|
| 736 | + struct drm_gem_cma_object *obj; |
|---|
| 737 | + |
|---|
| 738 | + obj = drm_fb_cma_get_gem_obj(fb, plane_index); |
|---|
| 739 | + |
|---|
| 740 | + if (WARN_ON(!obj)) |
|---|
| 741 | + return; |
|---|
| 742 | + paddr = obj->paddr; |
|---|
| 743 | + } |
|---|
| 744 | + |
|---|
| 745 | + malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr); |
|---|
| 746 | + malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4); |
|---|
| 747 | +} |
|---|
| 748 | + |
|---|
| 749 | +static void malidp_de_set_plane_afbc(struct drm_plane *plane) |
|---|
| 750 | +{ |
|---|
| 751 | + struct malidp_plane *mp; |
|---|
| 752 | + u32 src_w, src_h, val = 0, src_x, src_y; |
|---|
| 753 | + struct drm_framebuffer *fb = plane->state->fb; |
|---|
| 754 | + |
|---|
| 755 | + mp = to_malidp_plane(plane); |
|---|
| 756 | + |
|---|
| 757 | + /* no afbc_decoder_offset means AFBC is not supported on this plane */ |
|---|
| 758 | + if (!mp->layer->afbc_decoder_offset) |
|---|
| 759 | + return; |
|---|
| 760 | + |
|---|
| 761 | + if (!fb->modifier) { |
|---|
| 762 | + malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset); |
|---|
| 763 | + return; |
|---|
| 764 | + } |
|---|
| 765 | + |
|---|
| 766 | + /* convert src values from Q16 fixed point to integer */ |
|---|
| 767 | + src_w = plane->state->src_w >> 16; |
|---|
| 768 | + src_h = plane->state->src_h >> 16; |
|---|
| 769 | + src_x = plane->state->src_x >> 16; |
|---|
| 770 | + src_y = plane->state->src_y >> 16; |
|---|
| 771 | + |
|---|
| 772 | + val = ((fb->width - (src_x + src_w)) << MALIDP_AD_CROP_RIGHT_OFFSET) | |
|---|
| 773 | + src_x; |
|---|
| 774 | + malidp_hw_write(mp->hwdev, val, |
|---|
| 775 | + mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_H); |
|---|
| 776 | + |
|---|
| 777 | + val = ((fb->height - (src_y + src_h)) << MALIDP_AD_CROP_BOTTOM_OFFSET) | |
|---|
| 778 | + src_y; |
|---|
| 779 | + malidp_hw_write(mp->hwdev, val, |
|---|
| 780 | + mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_V); |
|---|
| 781 | + |
|---|
| 782 | + val = MALIDP_AD_EN; |
|---|
| 783 | + if (fb->modifier & AFBC_FORMAT_MOD_SPLIT) |
|---|
| 784 | + val |= MALIDP_AD_BS; |
|---|
| 785 | + if (fb->modifier & AFBC_FORMAT_MOD_YTR) |
|---|
| 786 | + val |= MALIDP_AD_YTR; |
|---|
| 787 | + |
|---|
| 788 | + malidp_hw_write(mp->hwdev, val, mp->layer->afbc_decoder_offset); |
|---|
| 789 | +} |
|---|
| 790 | + |
|---|
| 324 | 791 | static void malidp_de_plane_update(struct drm_plane *plane, |
|---|
| 325 | 792 | struct drm_plane_state *old_state) |
|---|
| 326 | 793 | { |
|---|
| 327 | 794 | struct malidp_plane *mp; |
|---|
| 328 | 795 | struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); |
|---|
| 796 | + struct drm_plane_state *state = plane->state; |
|---|
| 797 | + u16 pixel_alpha = state->pixel_blend_mode; |
|---|
| 798 | + u8 plane_alpha = state->alpha >> 8; |
|---|
| 329 | 799 | u32 src_w, src_h, dest_w, dest_h, val; |
|---|
| 330 | 800 | int i; |
|---|
| 331 | | - bool format_has_alpha = plane->state->fb->format->has_alpha; |
|---|
| 801 | + struct drm_framebuffer *fb = plane->state->fb; |
|---|
| 332 | 802 | |
|---|
| 333 | 803 | mp = to_malidp_plane(plane); |
|---|
| 334 | 804 | |
|---|
| 335 | | - /* convert src values from Q16 fixed point to integer */ |
|---|
| 336 | | - src_w = plane->state->src_w >> 16; |
|---|
| 337 | | - src_h = plane->state->src_h >> 16; |
|---|
| 338 | | - dest_w = plane->state->crtc_w; |
|---|
| 339 | | - dest_h = plane->state->crtc_h; |
|---|
| 805 | + /* |
|---|
| 806 | + * For AFBC framebuffer, use the framebuffer width and height for |
|---|
| 807 | + * configuring layer input size register. |
|---|
| 808 | + */ |
|---|
| 809 | + if (fb->modifier) { |
|---|
| 810 | + src_w = fb->width; |
|---|
| 811 | + src_h = fb->height; |
|---|
| 812 | + } else { |
|---|
| 813 | + /* convert src values from Q16 fixed point to integer */ |
|---|
| 814 | + src_w = state->src_w >> 16; |
|---|
| 815 | + src_h = state->src_h >> 16; |
|---|
| 816 | + } |
|---|
| 817 | + |
|---|
| 818 | + dest_w = state->crtc_w; |
|---|
| 819 | + dest_h = state->crtc_h; |
|---|
| 340 | 820 | |
|---|
| 341 | 821 | val = malidp_hw_read(mp->hwdev, mp->layer->base); |
|---|
| 342 | 822 | val = (val & ~LAYER_FORMAT_MASK) | ms->format; |
|---|
| 343 | 823 | malidp_hw_write(mp->hwdev, val, mp->layer->base); |
|---|
| 344 | 824 | |
|---|
| 345 | | - for (i = 0; i < ms->n_planes; i++) { |
|---|
| 346 | | - /* calculate the offset for the layer's plane registers */ |
|---|
| 347 | | - u16 ptr = mp->layer->ptr + (i << 4); |
|---|
| 348 | | - dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb, |
|---|
| 349 | | - plane->state, i); |
|---|
| 825 | + for (i = 0; i < ms->n_planes; i++) |
|---|
| 826 | + malidp_set_plane_base_addr(fb, mp, i); |
|---|
| 350 | 827 | |
|---|
| 351 | | - malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); |
|---|
| 352 | | - malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); |
|---|
| 353 | | - } |
|---|
| 828 | + malidp_de_set_mmu_control(mp, ms); |
|---|
| 829 | + |
|---|
| 354 | 830 | malidp_de_set_plane_pitches(mp, ms->n_planes, |
|---|
| 355 | | - plane->state->fb->pitches); |
|---|
| 831 | + state->fb->pitches); |
|---|
| 356 | 832 | |
|---|
| 357 | 833 | if ((plane->state->color_encoding != old_state->color_encoding) || |
|---|
| 358 | 834 | (plane->state->color_range != old_state->color_range)) |
|---|
| .. | .. |
|---|
| 365 | 841 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), |
|---|
| 366 | 842 | mp->layer->base + MALIDP_LAYER_COMP_SIZE); |
|---|
| 367 | 843 | |
|---|
| 368 | | - malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) | |
|---|
| 369 | | - LAYER_V_VAL(plane->state->crtc_y), |
|---|
| 844 | + malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) | |
|---|
| 845 | + LAYER_V_VAL(state->crtc_y), |
|---|
| 370 | 846 | mp->layer->base + MALIDP_LAYER_OFFSET); |
|---|
| 371 | 847 | |
|---|
| 372 | | - if (mp->layer->id == DE_SMART) |
|---|
| 848 | + if (mp->layer->id == DE_SMART) { |
|---|
| 849 | + /* |
|---|
| 850 | + * Enable the first rectangle in the SMART layer to be |
|---|
| 851 | + * able to use it as a drm plane. |
|---|
| 852 | + */ |
|---|
| 853 | + malidp_hw_write(mp->hwdev, 1, |
|---|
| 854 | + mp->layer->base + MALIDP550_LS_ENABLE); |
|---|
| 373 | 855 | malidp_hw_write(mp->hwdev, |
|---|
| 374 | 856 | LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), |
|---|
| 375 | 857 | mp->layer->base + MALIDP550_LS_R1_IN_SIZE); |
|---|
| 858 | + } |
|---|
| 859 | + |
|---|
| 860 | + malidp_de_set_plane_afbc(plane); |
|---|
| 376 | 861 | |
|---|
| 377 | 862 | /* first clear the rotation bits */ |
|---|
| 378 | 863 | val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL); |
|---|
| 379 | 864 | val &= ~LAYER_ROT_MASK; |
|---|
| 380 | 865 | |
|---|
| 381 | 866 | /* setup the rotation and axis flip bits */ |
|---|
| 382 | | - if (plane->state->rotation & DRM_MODE_ROTATE_MASK) |
|---|
| 867 | + if (state->rotation & DRM_MODE_ROTATE_MASK) |
|---|
| 383 | 868 | val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << |
|---|
| 384 | 869 | LAYER_ROT_OFFSET; |
|---|
| 385 | | - if (plane->state->rotation & DRM_MODE_REFLECT_X) |
|---|
| 870 | + if (state->rotation & DRM_MODE_REFLECT_X) |
|---|
| 386 | 871 | val |= LAYER_H_FLIP; |
|---|
| 387 | | - if (plane->state->rotation & DRM_MODE_REFLECT_Y) |
|---|
| 872 | + if (state->rotation & DRM_MODE_REFLECT_Y) |
|---|
| 388 | 873 | val |= LAYER_V_FLIP; |
|---|
| 389 | 874 | |
|---|
| 390 | | - val &= ~LAYER_COMP_MASK; |
|---|
| 391 | | - if (format_has_alpha) { |
|---|
| 875 | + val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE | LAYER_ALPHA(0xff)); |
|---|
| 392 | 876 | |
|---|
| 393 | | - /* |
|---|
| 394 | | - * always enable pixel alpha blending until we have a way |
|---|
| 395 | | - * to change blend modes |
|---|
| 396 | | - */ |
|---|
| 397 | | - val |= LAYER_COMP_PIXEL; |
|---|
| 398 | | - } else { |
|---|
| 399 | | - |
|---|
| 400 | | - /* |
|---|
| 401 | | - * do not enable pixel alpha blending as the color channel |
|---|
| 402 | | - * does not have any alpha information |
|---|
| 403 | | - */ |
|---|
| 877 | + if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) { |
|---|
| 404 | 878 | val |= LAYER_COMP_PLANE; |
|---|
| 405 | | - |
|---|
| 406 | | - /* Set layer alpha coefficient to 0xff ie fully opaque */ |
|---|
| 407 | | - val |= LAYER_ALPHA(0xff); |
|---|
| 879 | + } else if (state->fb->format->has_alpha) { |
|---|
| 880 | + /* We only care about blend mode if the format has alpha */ |
|---|
| 881 | + switch (pixel_alpha) { |
|---|
| 882 | + case DRM_MODE_BLEND_PREMULTI: |
|---|
| 883 | + val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE; |
|---|
| 884 | + break; |
|---|
| 885 | + case DRM_MODE_BLEND_COVERAGE: |
|---|
| 886 | + val |= LAYER_COMP_PIXEL; |
|---|
| 887 | + break; |
|---|
| 888 | + } |
|---|
| 408 | 889 | } |
|---|
| 890 | + val |= LAYER_ALPHA(plane_alpha); |
|---|
| 409 | 891 | |
|---|
| 410 | 892 | val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); |
|---|
| 411 | | - if (plane->state->crtc) { |
|---|
| 893 | + if (state->crtc) { |
|---|
| 412 | 894 | struct malidp_crtc_state *m = |
|---|
| 413 | | - to_malidp_crtc_state(plane->state->crtc->state); |
|---|
| 895 | + to_malidp_crtc_state(state->crtc->state); |
|---|
| 414 | 896 | |
|---|
| 415 | 897 | if (m->scaler_config.scale_enable && |
|---|
| 416 | 898 | m->scaler_config.plane_src_id == mp->layer->id) |
|---|
| .. | .. |
|---|
| 440 | 922 | .atomic_disable = malidp_de_plane_disable, |
|---|
| 441 | 923 | }; |
|---|
| 442 | 924 | |
|---|
| 925 | +static const uint64_t linear_only_modifiers[] = { |
|---|
| 926 | + DRM_FORMAT_MOD_LINEAR, |
|---|
| 927 | + DRM_FORMAT_MOD_INVALID |
|---|
| 928 | +}; |
|---|
| 929 | + |
|---|
| 443 | 930 | int malidp_de_planes_init(struct drm_device *drm) |
|---|
| 444 | 931 | { |
|---|
| 445 | 932 | struct malidp_drm *malidp = drm->dev_private; |
|---|
| .. | .. |
|---|
| 449 | 936 | unsigned long crtcs = BIT(drm->mode_config.num_crtc); |
|---|
| 450 | 937 | unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | |
|---|
| 451 | 938 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; |
|---|
| 939 | + unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | |
|---|
| 940 | + BIT(DRM_MODE_BLEND_PREMULTI) | |
|---|
| 941 | + BIT(DRM_MODE_BLEND_COVERAGE); |
|---|
| 452 | 942 | u32 *formats; |
|---|
| 453 | | - int ret, i, j, n; |
|---|
| 943 | + int ret, i = 0, j = 0, n; |
|---|
| 944 | + u64 supported_modifiers[MODIFIERS_COUNT_MAX]; |
|---|
| 945 | + const u64 *modifiers; |
|---|
| 946 | + |
|---|
| 947 | + modifiers = malidp_format_modifiers; |
|---|
| 948 | + |
|---|
| 949 | + if (!(map->features & MALIDP_DEVICE_AFBC_SUPPORT_SPLIT)) { |
|---|
| 950 | + /* |
|---|
| 951 | + * Since our hardware does not support SPLIT, so build the list |
|---|
| 952 | + * of supported modifiers excluding SPLIT ones. |
|---|
| 953 | + */ |
|---|
| 954 | + while (*modifiers != DRM_FORMAT_MOD_INVALID) { |
|---|
| 955 | + if (!(*modifiers & AFBC_SPLIT)) |
|---|
| 956 | + supported_modifiers[j++] = *modifiers; |
|---|
| 957 | + |
|---|
| 958 | + modifiers++; |
|---|
| 959 | + } |
|---|
| 960 | + supported_modifiers[j++] = DRM_FORMAT_MOD_INVALID; |
|---|
| 961 | + modifiers = supported_modifiers; |
|---|
| 962 | + } |
|---|
| 454 | 963 | |
|---|
| 455 | 964 | formats = kcalloc(map->n_pixel_formats, sizeof(*formats), GFP_KERNEL); |
|---|
| 456 | 965 | if (!formats) { |
|---|
| .. | .. |
|---|
| 475 | 984 | |
|---|
| 476 | 985 | plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY : |
|---|
| 477 | 986 | DRM_PLANE_TYPE_OVERLAY; |
|---|
| 987 | + |
|---|
| 988 | + /* |
|---|
| 989 | + * All the layers except smart layer supports AFBC modifiers. |
|---|
| 990 | + */ |
|---|
| 478 | 991 | ret = drm_universal_plane_init(drm, &plane->base, crtcs, |
|---|
| 479 | | - &malidp_de_plane_funcs, formats, |
|---|
| 480 | | - n, NULL, plane_type, NULL); |
|---|
| 992 | + &malidp_de_plane_funcs, formats, n, |
|---|
| 993 | + (id == DE_SMART) ? linear_only_modifiers : modifiers, |
|---|
| 994 | + plane_type, NULL); |
|---|
| 995 | + |
|---|
| 481 | 996 | if (ret < 0) |
|---|
| 482 | 997 | goto cleanup; |
|---|
| 483 | 998 | |
|---|
| .. | .. |
|---|
| 486 | 1001 | plane->hwdev = malidp->dev; |
|---|
| 487 | 1002 | plane->layer = &map->layers[i]; |
|---|
| 488 | 1003 | |
|---|
| 1004 | + drm_plane_create_alpha_property(&plane->base); |
|---|
| 1005 | + drm_plane_create_blend_mode_property(&plane->base, blend_caps); |
|---|
| 1006 | + |
|---|
| 489 | 1007 | if (id == DE_SMART) { |
|---|
| 490 | | - /* |
|---|
| 491 | | - * Enable the first rectangle in the SMART layer to be |
|---|
| 492 | | - * able to use it as a drm plane. |
|---|
| 493 | | - */ |
|---|
| 494 | | - malidp_hw_write(malidp->dev, 1, |
|---|
| 495 | | - plane->layer->base + MALIDP550_LS_ENABLE); |
|---|
| 496 | 1008 | /* Skip the features which the SMART layer doesn't have. */ |
|---|
| 497 | 1009 | continue; |
|---|
| 498 | 1010 | } |
|---|