diff options
author | Dave Airlie <airlied@redhat.com> | 2018-10-03 21:30:58 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-10-03 21:31:05 -0400 |
commit | c530174b90fa3bcaa83d168b001b574bcb2da021 (patch) | |
tree | cea54e53f6652f365ffa993d80afbcd8516b01c9 | |
parent | 41050757fd5bb063d45e3cc2cda4bca10d9b82b5 (diff) | |
parent | 3dae1c0919d8c46710187df4fa1a43622289a1f5 (diff) |
Merge branch 'for-upstream/mali-dp' of git://linux-arm.org/linux-ld into drm-next
misc mali-dp updates.
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Liviu Dudau <Liviu.Dudau@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181003105009.GD1156@e110455-lin.cambridge.arm.com
-rw-r--r-- | drivers/gpu/drm/arm/malidp_crtc.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.c | 128 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.c | 58 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_planes.c | 347 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_regs.h | 11 |
7 files changed, 520 insertions, 73 deletions
diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index ef44202fb43f..e1b72782848c 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c | |||
@@ -348,19 +348,20 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, | |||
348 | 348 | ||
349 | /* | 349 | /* |
350 | * check if there is enough rotation memory available for planes | 350 | * check if there is enough rotation memory available for planes |
351 | * that need 90° and 270° rotation. Each plane has set its required | 351 | * that need 90° and 270° rotion or planes that are compressed. |
352 | * memory size in the ->plane_check() callback, here we only make | 352 | * Each plane has set its required memory size in the ->plane_check() |
353 | * sure that the sums are less that the total usable memory. | 353 | * callback, here we only make sure that the sums are less that the |
354 | * total usable memory. | ||
354 | * | 355 | * |
355 | * The rotation memory allocation algorithm (for each plane): | 356 | * The rotation memory allocation algorithm (for each plane): |
356 | * a. If no more rotated planes exist, all remaining rotate | 357 | * a. If no more rotated or compressed planes exist, all remaining |
357 | * memory in the bank is available for use by the plane. | 358 | * rotate memory in the bank is available for use by the plane. |
358 | * b. If other rotated planes exist, and plane's layer ID is | 359 | * b. If other rotated or compressed planes exist, and plane's |
359 | * DE_VIDEO1, it can use all the memory from first bank if | 360 | * layer ID is DE_VIDEO1, it can use all the memory from first bank |
360 | * secondary rotation memory bank is available, otherwise it can | 361 | * if secondary rotation memory bank is available, otherwise it can |
361 | * use up to half the bank's memory. | 362 | * use up to half the bank's memory. |
362 | * c. If other rotated planes exist, and plane's layer ID is not | 363 | * c. If other rotated or compressed planes exist, and plane's layer ID |
363 | * DE_VIDEO1, it can use half of the available memory | 364 | * is not DE_VIDEO1, it can use half of the available memory. |
364 | * | 365 | * |
365 | * Note: this algorithm assumes that the order in which the planes are | 366 | * Note: this algorithm assumes that the order in which the planes are |
366 | * checked always has DE_VIDEO1 plane first in the list if it is | 367 | * checked always has DE_VIDEO1 plane first in the list if it is |
@@ -372,7 +373,9 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, | |||
372 | 373 | ||
373 | /* first count the number of rotated planes */ | 374 | /* first count the number of rotated planes */ |
374 | drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { | 375 | drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { |
375 | if (pstate->rotation & MALIDP_ROTATED_MASK) | 376 | struct drm_framebuffer *fb = pstate->fb; |
377 | |||
378 | if ((pstate->rotation & MALIDP_ROTATED_MASK) || fb->modifier) | ||
376 | rotated_planes++; | 379 | rotated_planes++; |
377 | } | 380 | } |
378 | 381 | ||
@@ -388,8 +391,9 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc, | |||
388 | drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { | 391 | drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { |
389 | struct malidp_plane *mp = to_malidp_plane(plane); | 392 | struct malidp_plane *mp = to_malidp_plane(plane); |
390 | struct malidp_plane_state *ms = to_malidp_plane_state(pstate); | 393 | struct malidp_plane_state *ms = to_malidp_plane_state(pstate); |
394 | struct drm_framebuffer *fb = pstate->fb; | ||
391 | 395 | ||
392 | if (pstate->rotation & MALIDP_ROTATED_MASK) { | 396 | if ((pstate->rotation & MALIDP_ROTATED_MASK) || fb->modifier) { |
393 | /* process current plane */ | 397 | /* process current plane */ |
394 | rotated_planes--; | 398 | rotated_planes--; |
395 | 399 | ||
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 34eec1a22428..90214851637f 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "malidp_hw.h" | 37 | #include "malidp_hw.h" |
38 | 38 | ||
39 | #define MALIDP_CONF_VALID_TIMEOUT 250 | 39 | #define MALIDP_CONF_VALID_TIMEOUT 250 |
40 | #define AFBC_HEADER_SIZE 16 | ||
40 | 41 | ||
41 | static void malidp_write_gamma_table(struct malidp_hw_device *hwdev, | 42 | static void malidp_write_gamma_table(struct malidp_hw_device *hwdev, |
42 | u32 data[MALIDP_COEFFTAB_NUM_COEFFS]) | 43 | u32 data[MALIDP_COEFFTAB_NUM_COEFFS]) |
@@ -258,8 +259,133 @@ static const struct drm_mode_config_helper_funcs malidp_mode_config_helpers = { | |||
258 | .atomic_commit_tail = malidp_atomic_commit_tail, | 259 | .atomic_commit_tail = malidp_atomic_commit_tail, |
259 | }; | 260 | }; |
260 | 261 | ||
262 | static bool | ||
263 | malidp_verify_afbc_framebuffer_caps(struct drm_device *dev, | ||
264 | const struct drm_mode_fb_cmd2 *mode_cmd) | ||
265 | { | ||
266 | const struct drm_format_info *info; | ||
267 | |||
268 | if ((mode_cmd->modifier[0] >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) { | ||
269 | DRM_DEBUG_KMS("Unknown modifier (not Arm)\n"); | ||
270 | return false; | ||
271 | } | ||
272 | |||
273 | if (mode_cmd->modifier[0] & | ||
274 | ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) { | ||
275 | DRM_DEBUG_KMS("Unsupported modifiers\n"); | ||
276 | return false; | ||
277 | } | ||
278 | |||
279 | info = drm_get_format_info(dev, mode_cmd); | ||
280 | if (!info) { | ||
281 | DRM_DEBUG_KMS("Unable to get the format information\n"); | ||
282 | return false; | ||
283 | } | ||
284 | |||
285 | if (info->num_planes != 1) { | ||
286 | DRM_DEBUG_KMS("AFBC buffers expect one plane\n"); | ||
287 | return false; | ||
288 | } | ||
289 | |||
290 | if (mode_cmd->offsets[0] != 0) { | ||
291 | DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n"); | ||
292 | return false; | ||
293 | } | ||
294 | |||
295 | switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) { | ||
296 | case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: | ||
297 | if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) { | ||
298 | DRM_DEBUG_KMS("AFBC buffers must be aligned to 16 pixels\n"); | ||
299 | return false; | ||
300 | } | ||
301 | break; | ||
302 | default: | ||
303 | DRM_DEBUG_KMS("Unsupported AFBC block size\n"); | ||
304 | return false; | ||
305 | } | ||
306 | |||
307 | return true; | ||
308 | } | ||
309 | |||
310 | static bool | ||
311 | malidp_verify_afbc_framebuffer_size(struct drm_device *dev, | ||
312 | struct drm_file *file, | ||
313 | const struct drm_mode_fb_cmd2 *mode_cmd) | ||
314 | { | ||
315 | int n_superblocks = 0; | ||
316 | const struct drm_format_info *info; | ||
317 | struct drm_gem_object *objs = NULL; | ||
318 | u32 afbc_superblock_size = 0, afbc_superblock_height = 0; | ||
319 | u32 afbc_superblock_width = 0, afbc_size = 0; | ||
320 | |||
321 | switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) { | ||
322 | case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: | ||
323 | afbc_superblock_height = 16; | ||
324 | afbc_superblock_width = 16; | ||
325 | break; | ||
326 | default: | ||
327 | DRM_DEBUG_KMS("AFBC superblock size is not supported\n"); | ||
328 | return false; | ||
329 | } | ||
330 | |||
331 | info = drm_get_format_info(dev, mode_cmd); | ||
332 | |||
333 | n_superblocks = (mode_cmd->width / afbc_superblock_width) * | ||
334 | (mode_cmd->height / afbc_superblock_height); | ||
335 | |||
336 | afbc_superblock_size = info->cpp[0] * afbc_superblock_width * | ||
337 | afbc_superblock_height; | ||
338 | |||
339 | afbc_size = ALIGN(n_superblocks * AFBC_HEADER_SIZE, 128); | ||
340 | |||
341 | if (mode_cmd->width * info->cpp[0] != mode_cmd->pitches[0]) { | ||
342 | DRM_DEBUG_KMS("Invalid value of pitch (=%u) should be same as width (=%u) * cpp (=%u)\n", | ||
343 | mode_cmd->pitches[0], mode_cmd->width, info->cpp[0]); | ||
344 | return false; | ||
345 | } | ||
346 | |||
347 | objs = drm_gem_object_lookup(file, mode_cmd->handles[0]); | ||
348 | if (!objs) { | ||
349 | DRM_DEBUG_KMS("Failed to lookup GEM object\n"); | ||
350 | return false; | ||
351 | } | ||
352 | |||
353 | if (objs->size < afbc_size) { | ||
354 | DRM_DEBUG_KMS("buffer size (%zu) too small for AFBC buffer size = %u\n", | ||
355 | objs->size, afbc_size); | ||
356 | drm_gem_object_put_unlocked(objs); | ||
357 | return false; | ||
358 | } | ||
359 | |||
360 | drm_gem_object_put_unlocked(objs); | ||
361 | |||
362 | return true; | ||
363 | } | ||
364 | |||
365 | static bool | ||
366 | malidp_verify_afbc_framebuffer(struct drm_device *dev, struct drm_file *file, | ||
367 | const struct drm_mode_fb_cmd2 *mode_cmd) | ||
368 | { | ||
369 | if (malidp_verify_afbc_framebuffer_caps(dev, mode_cmd)) | ||
370 | return malidp_verify_afbc_framebuffer_size(dev, file, mode_cmd); | ||
371 | |||
372 | return false; | ||
373 | } | ||
374 | |||
375 | struct drm_framebuffer * | ||
376 | malidp_fb_create(struct drm_device *dev, struct drm_file *file, | ||
377 | const struct drm_mode_fb_cmd2 *mode_cmd) | ||
378 | { | ||
379 | if (mode_cmd->modifier[0]) { | ||
380 | if (!malidp_verify_afbc_framebuffer(dev, file, mode_cmd)) | ||
381 | return ERR_PTR(-EINVAL); | ||
382 | } | ||
383 | |||
384 | return drm_gem_fb_create(dev, file, mode_cmd); | ||
385 | } | ||
386 | |||
261 | static const struct drm_mode_config_funcs malidp_mode_config_funcs = { | 387 | static const struct drm_mode_config_funcs malidp_mode_config_funcs = { |
262 | .fb_create = drm_gem_fb_create, | 388 | .fb_create = malidp_fb_create, |
263 | .atomic_check = drm_atomic_helper_check, | 389 | .atomic_check = drm_atomic_helper_check, |
264 | .atomic_commit = drm_atomic_helper_commit, | 390 | .atomic_commit = drm_atomic_helper_commit, |
265 | }; | 391 | }; |
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index e3eb0cb1f385..b76c86f18a56 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h | |||
@@ -55,6 +55,12 @@ struct malidp_plane { | |||
55 | const struct malidp_layer *layer; | 55 | const struct malidp_layer *layer; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | enum mmu_prefetch_mode { | ||
59 | MALIDP_PREFETCH_MODE_NONE, | ||
60 | MALIDP_PREFETCH_MODE_PARTIAL, | ||
61 | MALIDP_PREFETCH_MODE_FULL, | ||
62 | }; | ||
63 | |||
58 | struct malidp_plane_state { | 64 | struct malidp_plane_state { |
59 | struct drm_plane_state base; | 65 | struct drm_plane_state base; |
60 | 66 | ||
@@ -63,6 +69,8 @@ struct malidp_plane_state { | |||
63 | /* internal format ID */ | 69 | /* internal format ID */ |
64 | u8 format; | 70 | u8 format; |
65 | u8 n_planes; | 71 | u8 n_planes; |
72 | enum mmu_prefetch_mode mmu_prefetch_mode; | ||
73 | u32 mmu_prefetch_pgsize; | ||
66 | }; | 74 | }; |
67 | 75 | ||
68 | #define to_malidp_plane(x) container_of(x, struct malidp_plane, base) | 76 | #define to_malidp_plane(x) container_of(x, struct malidp_plane, base) |
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 2781e462c1ed..7aad7dd80d8c 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c | |||
@@ -84,16 +84,48 @@ static const struct malidp_format_id malidp550_de_formats[] = { | |||
84 | }; | 84 | }; |
85 | 85 | ||
86 | static const struct malidp_layer malidp500_layers[] = { | 86 | static const struct malidp_layer malidp500_layers[] = { |
87 | { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB }, | 87 | /* id, base address, fb pointer address base, stride offset, |
88 | { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 }, | 88 | * yuv2rgb matrix offset, mmu control register offset, rotation_features |
89 | { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 }, | 89 | */ |
90 | { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, | ||
91 | MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY }, | ||
92 | { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, | ||
93 | MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY }, | ||
94 | { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, | ||
95 | MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY }, | ||
90 | }; | 96 | }; |
91 | 97 | ||
92 | static const struct malidp_layer malidp550_layers[] = { | 98 | static const struct malidp_layer malidp550_layers[] = { |
93 | { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB }, | 99 | /* id, base address, fb pointer address base, stride offset, |
94 | { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 }, | 100 | * yuv2rgb matrix offset, mmu control register offset, rotation_features |
95 | { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB }, | 101 | */ |
96 | { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE, 0 }, | 102 | { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, |
103 | MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY }, | ||
104 | { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, | ||
105 | MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY }, | ||
106 | { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, | ||
107 | MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY }, | ||
108 | { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, | ||
109 | MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE }, | ||
110 | }; | ||
111 | |||
112 | static const struct malidp_layer malidp650_layers[] = { | ||
113 | /* id, base address, fb pointer address base, stride offset, | ||
114 | * yuv2rgb matrix offset, mmu control register offset, | ||
115 | * rotation_features | ||
116 | */ | ||
117 | { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, | ||
118 | MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, | ||
119 | MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY }, | ||
120 | { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, | ||
121 | MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL, | ||
122 | ROTATE_COMPRESSED }, | ||
123 | { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, | ||
124 | MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, | ||
125 | MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY }, | ||
126 | { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, | ||
127 | MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL, | ||
128 | ROTATE_NONE }, | ||
97 | }; | 129 | }; |
98 | 130 | ||
99 | #define SE_N_SCALING_COEFFS 96 | 131 | #define SE_N_SCALING_COEFFS 96 |
@@ -288,10 +320,6 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode * | |||
288 | 320 | ||
289 | static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt) | 321 | static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt) |
290 | { | 322 | { |
291 | /* RGB888 or BGR888 can't be rotated */ | ||
292 | if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888)) | ||
293 | return -EINVAL; | ||
294 | |||
295 | /* | 323 | /* |
296 | * Each layer needs enough rotation memory to fit 8 lines | 324 | * Each layer needs enough rotation memory to fit 8 lines |
297 | * worth of pixel data. Required size is then: | 325 | * worth of pixel data. Required size is then: |
@@ -579,10 +607,6 @@ static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 | |||
579 | { | 607 | { |
580 | u32 bytes_per_col; | 608 | u32 bytes_per_col; |
581 | 609 | ||
582 | /* raw RGB888 or BGR888 can't be rotated */ | ||
583 | if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888)) | ||
584 | return -EINVAL; | ||
585 | |||
586 | switch (fmt) { | 610 | switch (fmt) { |
587 | /* 8 lines at 4 bytes per pixel */ | 611 | /* 8 lines at 4 bytes per pixel */ |
588 | case DRM_FORMAT_ARGB2101010: | 612 | case DRM_FORMAT_ARGB2101010: |
@@ -853,8 +877,8 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = { | |||
853 | .dc_base = MALIDP550_DC_BASE, | 877 | .dc_base = MALIDP550_DC_BASE, |
854 | .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, | 878 | .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, |
855 | .features = MALIDP_REGMAP_HAS_CLEARIRQ, | 879 | .features = MALIDP_REGMAP_HAS_CLEARIRQ, |
856 | .n_layers = ARRAY_SIZE(malidp550_layers), | 880 | .n_layers = ARRAY_SIZE(malidp650_layers), |
857 | .layers = malidp550_layers, | 881 | .layers = malidp650_layers, |
858 | .de_irq_map = { | 882 | .de_irq_map = { |
859 | .irq_mask = MALIDP_DE_IRQ_UNDERRUN | | 883 | .irq_mask = MALIDP_DE_IRQ_UNDERRUN | |
860 | MALIDP650_DE_IRQ_DRIFT | | 884 | MALIDP650_DE_IRQ_DRIFT | |
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index 9fc94c08190f..40155e2ea9d9 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h | |||
@@ -36,6 +36,12 @@ enum { | |||
36 | SE_MEMWRITE = BIT(5), | 36 | SE_MEMWRITE = BIT(5), |
37 | }; | 37 | }; |
38 | 38 | ||
39 | enum rotation_features { | ||
40 | ROTATE_NONE, /* does not support rotation at all */ | ||
41 | ROTATE_ANY, /* supports rotation on any buffers */ | ||
42 | ROTATE_COMPRESSED, /* supports rotation only on compressed buffers */ | ||
43 | }; | ||
44 | |||
39 | struct malidp_format_id { | 45 | struct malidp_format_id { |
40 | u32 format; /* DRM fourcc */ | 46 | u32 format; /* DRM fourcc */ |
41 | u8 layer; /* bitmask of layers supporting it */ | 47 | u8 layer; /* bitmask of layers supporting it */ |
@@ -62,6 +68,8 @@ struct malidp_layer { | |||
62 | u16 ptr; /* address offset for the pointer register */ | 68 | u16 ptr; /* address offset for the pointer register */ |
63 | u16 stride_offset; /* offset to the first stride register. */ | 69 | u16 stride_offset; /* offset to the first stride register. */ |
64 | s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */ | 70 | s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */ |
71 | u16 mmu_ctrl_offset; /* offset to the MMU control register */ | ||
72 | enum rotation_features rot; /* type of rotation supported */ | ||
65 | }; | 73 | }; |
66 | 74 | ||
67 | enum malidp_scaling_coeff_set { | 75 | enum malidp_scaling_coeff_set { |
@@ -380,4 +388,9 @@ static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev) | |||
380 | 388 | ||
381 | #define MALIDP_GAMMA_LUT_SIZE 4096 | 389 | #define MALIDP_GAMMA_LUT_SIZE 4096 |
382 | 390 | ||
391 | #define AFBC_MOD_VALID_BITS (AFBC_FORMAT_MOD_BLOCK_SIZE_MASK | \ | ||
392 | AFBC_FORMAT_MOD_YTR | AFBC_FORMAT_MOD_SPLIT | \ | ||
393 | AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_CBR | \ | ||
394 | AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SC) | ||
395 | |||
383 | #endif /* __MALIDP_HW_H__ */ | 396 | #endif /* __MALIDP_HW_H__ */ |
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 49c37f6dd63e..837a24d56675 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c | |||
@@ -10,11 +10,14 @@ | |||
10 | * ARM Mali DP plane manipulation routines. | 10 | * ARM Mali DP plane manipulation routines. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/iommu.h> | ||
14 | |||
13 | #include <drm/drmP.h> | 15 | #include <drm/drmP.h> |
14 | #include <drm/drm_atomic.h> | 16 | #include <drm/drm_atomic.h> |
15 | #include <drm/drm_atomic_helper.h> | 17 | #include <drm/drm_atomic_helper.h> |
16 | #include <drm/drm_fb_cma_helper.h> | 18 | #include <drm/drm_fb_cma_helper.h> |
17 | #include <drm/drm_gem_cma_helper.h> | 19 | #include <drm/drm_gem_cma_helper.h> |
20 | #include <drm/drm_gem_framebuffer_helper.h> | ||
18 | #include <drm/drm_plane_helper.h> | 21 | #include <drm/drm_plane_helper.h> |
19 | #include <drm/drm_print.h> | 22 | #include <drm/drm_print.h> |
20 | 23 | ||
@@ -36,6 +39,7 @@ | |||
36 | #define LAYER_COMP_MASK (0x3 << 12) | 39 | #define LAYER_COMP_MASK (0x3 << 12) |
37 | #define LAYER_COMP_PIXEL (0x3 << 12) | 40 | #define LAYER_COMP_PIXEL (0x3 << 12) |
38 | #define LAYER_COMP_PLANE (0x2 << 12) | 41 | #define LAYER_COMP_PLANE (0x2 << 12) |
42 | #define LAYER_PMUL_ENABLE (0x1 << 14) | ||
39 | #define LAYER_ALPHA_OFFSET (16) | 43 | #define LAYER_ALPHA_OFFSET (16) |
40 | #define LAYER_ALPHA_MASK (0xff) | 44 | #define LAYER_ALPHA_MASK (0xff) |
41 | #define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) | 45 | #define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) |
@@ -56,6 +60,13 @@ | |||
56 | */ | 60 | */ |
57 | #define MALIDP_ALPHA_LUT 0xffaa5500 | 61 | #define MALIDP_ALPHA_LUT 0xffaa5500 |
58 | 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 | ||
69 | |||
59 | static void malidp_de_plane_destroy(struct drm_plane *plane) | 70 | static void malidp_de_plane_destroy(struct drm_plane *plane) |
60 | { | 71 | { |
61 | struct malidp_plane *mp = to_malidp_plane(plane); | 72 | struct malidp_plane *mp = to_malidp_plane(plane); |
@@ -100,6 +111,9 @@ drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) | |||
100 | state->format = m_state->format; | 111 | state->format = m_state->format; |
101 | state->n_planes = m_state->n_planes; | 112 | state->n_planes = m_state->n_planes; |
102 | 113 | ||
114 | state->mmu_prefetch_mode = m_state->mmu_prefetch_mode; | ||
115 | state->mmu_prefetch_pgsize = m_state->mmu_prefetch_pgsize; | ||
116 | |||
103 | return &state->base; | 117 | return &state->base; |
104 | } | 118 | } |
105 | 119 | ||
@@ -112,6 +126,12 @@ static void malidp_destroy_plane_state(struct drm_plane *plane, | |||
112 | kfree(m_state); | 126 | kfree(m_state); |
113 | } | 127 | } |
114 | 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 | |||
115 | static void malidp_plane_atomic_print_state(struct drm_printer *p, | 135 | static void malidp_plane_atomic_print_state(struct drm_printer *p, |
116 | const struct drm_plane_state *state) | 136 | const struct drm_plane_state *state) |
117 | { | 137 | { |
@@ -120,6 +140,9 @@ static void malidp_plane_atomic_print_state(struct drm_printer *p, | |||
120 | drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size); | 140 | drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size); |
121 | drm_printf(p, "\tformat_id=%u\n", ms->format); | 141 | drm_printf(p, "\tformat_id=%u\n", ms->format); |
122 | drm_printf(p, "\tn_planes=%u\n", ms->n_planes); | 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); | ||
123 | } | 146 | } |
124 | 147 | ||
125 | static const struct drm_plane_funcs malidp_de_plane_funcs = { | 148 | static const struct drm_plane_funcs malidp_de_plane_funcs = { |
@@ -173,6 +196,199 @@ static int malidp_se_check_scaling(struct malidp_plane *mp, | |||
173 | return 0; | 196 | return 0; |
174 | } | 197 | } |
175 | 198 | ||
199 | static u32 malidp_get_pgsize_bitmap(struct malidp_plane *mp) | ||
200 | { | ||
201 | u32 pgsize_bitmap = 0; | ||
202 | |||
203 | if (iommu_present(&platform_bus_type)) { | ||
204 | struct iommu_domain *mmu_dom = | ||
205 | iommu_get_domain_for_dev(mp->base.dev->dev); | ||
206 | |||
207 | if (mmu_dom) | ||
208 | pgsize_bitmap = mmu_dom->pgsize_bitmap; | ||
209 | } | ||
210 | |||
211 | return pgsize_bitmap; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * Check if the framebuffer is entirely made up of pages at least pgsize in | ||
216 | * size. Only a heuristic: assumes that each scatterlist entry has been aligned | ||
217 | * to the largest page size smaller than its length and that the MMU maps to | ||
218 | * the largest page size possible. | ||
219 | */ | ||
220 | static bool malidp_check_pages_threshold(struct malidp_plane_state *ms, | ||
221 | u32 pgsize) | ||
222 | { | ||
223 | int i; | ||
224 | |||
225 | for (i = 0; i < ms->n_planes; i++) { | ||
226 | struct drm_gem_object *obj; | ||
227 | struct drm_gem_cma_object *cma_obj; | ||
228 | struct sg_table *sgt; | ||
229 | struct scatterlist *sgl; | ||
230 | |||
231 | obj = drm_gem_fb_get_obj(ms->base.fb, i); | ||
232 | cma_obj = to_drm_gem_cma_obj(obj); | ||
233 | |||
234 | if (cma_obj->sgt) | ||
235 | sgt = cma_obj->sgt; | ||
236 | else | ||
237 | sgt = obj->dev->driver->gem_prime_get_sg_table(obj); | ||
238 | |||
239 | if (!sgt) | ||
240 | return false; | ||
241 | |||
242 | sgl = sgt->sgl; | ||
243 | |||
244 | while (sgl) { | ||
245 | if (sgl->length < pgsize) { | ||
246 | if (!cma_obj->sgt) | ||
247 | kfree(sgt); | ||
248 | return false; | ||
249 | } | ||
250 | |||
251 | sgl = sg_next(sgl); | ||
252 | } | ||
253 | if (!cma_obj->sgt) | ||
254 | kfree(sgt); | ||
255 | } | ||
256 | |||
257 | return true; | ||
258 | } | ||
259 | |||
260 | /* | ||
261 | * Check if it is possible to enable partial-frame MMU prefetch given the | ||
262 | * current format, AFBC state and rotation. | ||
263 | */ | ||
264 | static bool malidp_partial_prefetch_supported(u32 format, u64 modifier, | ||
265 | unsigned int rotation) | ||
266 | { | ||
267 | bool afbc, sparse; | ||
268 | |||
269 | /* rotation and horizontal flip not supported for partial prefetch */ | ||
270 | if (rotation & (DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | | ||
271 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X)) | ||
272 | return false; | ||
273 | |||
274 | afbc = modifier & DRM_FORMAT_MOD_ARM_AFBC(0); | ||
275 | sparse = modifier & AFBC_FORMAT_MOD_SPARSE; | ||
276 | |||
277 | switch (format) { | ||
278 | case DRM_FORMAT_ARGB2101010: | ||
279 | case DRM_FORMAT_RGBA1010102: | ||
280 | case DRM_FORMAT_BGRA1010102: | ||
281 | case DRM_FORMAT_ARGB8888: | ||
282 | case DRM_FORMAT_RGBA8888: | ||
283 | case DRM_FORMAT_BGRA8888: | ||
284 | case DRM_FORMAT_XRGB8888: | ||
285 | case DRM_FORMAT_XBGR8888: | ||
286 | case DRM_FORMAT_RGBX8888: | ||
287 | case DRM_FORMAT_BGRX8888: | ||
288 | case DRM_FORMAT_RGB888: | ||
289 | case DRM_FORMAT_RGBA5551: | ||
290 | case DRM_FORMAT_RGB565: | ||
291 | /* always supported */ | ||
292 | return true; | ||
293 | |||
294 | case DRM_FORMAT_ABGR2101010: | ||
295 | case DRM_FORMAT_ABGR8888: | ||
296 | case DRM_FORMAT_ABGR1555: | ||
297 | case DRM_FORMAT_BGR565: | ||
298 | /* supported, but if AFBC then must be sparse mode */ | ||
299 | return (!afbc) || (afbc && sparse); | ||
300 | |||
301 | case DRM_FORMAT_BGR888: | ||
302 | /* supported, but not for AFBC */ | ||
303 | return !afbc; | ||
304 | |||
305 | case DRM_FORMAT_YUYV: | ||
306 | case DRM_FORMAT_UYVY: | ||
307 | case DRM_FORMAT_NV12: | ||
308 | case DRM_FORMAT_YUV420: | ||
309 | /* not supported */ | ||
310 | return false; | ||
311 | |||
312 | default: | ||
313 | return false; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * Select the preferred MMU prefetch mode. Full-frame prefetch is preferred as | ||
319 | * long as the framebuffer is all large pages. Otherwise partial-frame prefetch | ||
320 | * is selected as long as it is supported for the current format. The selected | ||
321 | * page size for prefetch is returned in pgsize_bitmap. | ||
322 | */ | ||
323 | static enum mmu_prefetch_mode malidp_mmu_prefetch_select_mode | ||
324 | (struct malidp_plane_state *ms, u32 *pgsize_bitmap) | ||
325 | { | ||
326 | u32 pgsizes; | ||
327 | |||
328 | /* get the full-frame prefetch page size(s) supported by the MMU */ | ||
329 | pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_FULL_PGSIZES; | ||
330 | |||
331 | while (pgsizes) { | ||
332 | u32 largest_pgsize = 1 << __fls(pgsizes); | ||
333 | |||
334 | if (malidp_check_pages_threshold(ms, largest_pgsize)) { | ||
335 | *pgsize_bitmap = largest_pgsize; | ||
336 | return MALIDP_PREFETCH_MODE_FULL; | ||
337 | } | ||
338 | |||
339 | pgsizes -= largest_pgsize; | ||
340 | } | ||
341 | |||
342 | /* get the partial-frame prefetch page size(s) supported by the MMU */ | ||
343 | pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES; | ||
344 | |||
345 | if (malidp_partial_prefetch_supported(ms->base.fb->format->format, | ||
346 | ms->base.fb->modifier, | ||
347 | ms->base.rotation)) { | ||
348 | /* partial prefetch using the smallest page size */ | ||
349 | *pgsize_bitmap = 1 << __ffs(pgsizes); | ||
350 | return MALIDP_PREFETCH_MODE_PARTIAL; | ||
351 | } | ||
352 | *pgsize_bitmap = 0; | ||
353 | return MALIDP_PREFETCH_MODE_NONE; | ||
354 | } | ||
355 | |||
356 | static u32 malidp_calc_mmu_control_value(enum mmu_prefetch_mode mode, | ||
357 | u8 readahead, u8 n_planes, u32 pgsize) | ||
358 | { | ||
359 | u32 mmu_ctrl = 0; | ||
360 | |||
361 | if (mode != MALIDP_PREFETCH_MODE_NONE) { | ||
362 | mmu_ctrl |= MALIDP_MMU_CTRL_EN; | ||
363 | |||
364 | if (mode == MALIDP_PREFETCH_MODE_PARTIAL) { | ||
365 | mmu_ctrl |= MALIDP_MMU_CTRL_MODE; | ||
366 | mmu_ctrl |= MALIDP_MMU_CTRL_PP_NUM_REQ(readahead); | ||
367 | } | ||
368 | |||
369 | if (pgsize == SZ_64K || pgsize == SZ_2M) { | ||
370 | int i; | ||
371 | |||
372 | for (i = 0; i < n_planes; i++) | ||
373 | mmu_ctrl |= MALIDP_MMU_CTRL_PX_PS(i); | ||
374 | } | ||
375 | } | ||
376 | |||
377 | return mmu_ctrl; | ||
378 | } | ||
379 | |||
380 | static void malidp_de_prefetch_settings(struct malidp_plane *mp, | ||
381 | struct malidp_plane_state *ms) | ||
382 | { | ||
383 | if (!mp->layer->mmu_ctrl_offset) | ||
384 | return; | ||
385 | |||
386 | /* get the page sizes supported by the MMU */ | ||
387 | ms->mmu_prefetch_pgsize = malidp_get_pgsize_bitmap(mp); | ||
388 | ms->mmu_prefetch_mode = | ||
389 | malidp_mmu_prefetch_select_mode(ms, &ms->mmu_prefetch_pgsize); | ||
390 | } | ||
391 | |||
176 | static int malidp_de_plane_check(struct drm_plane *plane, | 392 | static int malidp_de_plane_check(struct drm_plane *plane, |
177 | struct drm_plane_state *state) | 393 | struct drm_plane_state *state) |
178 | { | 394 | { |
@@ -180,6 +396,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, | |||
180 | struct malidp_plane_state *ms = to_malidp_plane_state(state); | 396 | struct malidp_plane_state *ms = to_malidp_plane_state(state); |
181 | bool rotated = state->rotation & MALIDP_ROTATED_MASK; | 397 | bool rotated = state->rotation & MALIDP_ROTATED_MASK; |
182 | struct drm_framebuffer *fb; | 398 | struct drm_framebuffer *fb; |
399 | u16 pixel_alpha = state->pixel_blend_mode; | ||
183 | int i, ret; | 400 | int i, ret; |
184 | 401 | ||
185 | if (!state->crtc || !state->fb) | 402 | if (!state->crtc || !state->fb) |
@@ -223,11 +440,20 @@ static int malidp_de_plane_check(struct drm_plane *plane, | |||
223 | if (ret) | 440 | if (ret) |
224 | return ret; | 441 | return ret; |
225 | 442 | ||
226 | /* packed RGB888 / BGR888 can't be rotated or flipped */ | 443 | /* validate the rotation constraints for each layer */ |
227 | if (state->rotation != DRM_MODE_ROTATE_0 && | 444 | if (state->rotation != DRM_MODE_ROTATE_0) { |
228 | (fb->format->format == DRM_FORMAT_RGB888 || | 445 | if (mp->layer->rot == ROTATE_NONE) |
229 | fb->format->format == DRM_FORMAT_BGR888)) | 446 | return -EINVAL; |
230 | return -EINVAL; | 447 | if ((mp->layer->rot == ROTATE_COMPRESSED) && !(fb->modifier)) |
448 | return -EINVAL; | ||
449 | /* | ||
450 | * packed RGB888 / BGR888 can't be rotated or flipped | ||
451 | * unless they are stored in a compressed way | ||
452 | */ | ||
453 | if ((fb->format->format == DRM_FORMAT_RGB888 || | ||
454 | fb->format->format == DRM_FORMAT_BGR888) && !(fb->modifier)) | ||
455 | return -EINVAL; | ||
456 | } | ||
231 | 457 | ||
232 | ms->rotmem_size = 0; | 458 | ms->rotmem_size = 0; |
233 | if (state->rotation & MALIDP_ROTATED_MASK) { | 459 | if (state->rotation & MALIDP_ROTATED_MASK) { |
@@ -242,6 +468,14 @@ static int malidp_de_plane_check(struct drm_plane *plane, | |||
242 | ms->rotmem_size = val; | 468 | ms->rotmem_size = val; |
243 | } | 469 | } |
244 | 470 | ||
471 | /* HW can't support plane + pixel blending */ | ||
472 | if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) && | ||
473 | (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE) && | ||
474 | fb->format->has_alpha) | ||
475 | return -EINVAL; | ||
476 | |||
477 | malidp_de_prefetch_settings(mp, ms); | ||
478 | |||
245 | return 0; | 479 | return 0; |
246 | } | 480 | } |
247 | 481 | ||
@@ -318,22 +552,42 @@ static void malidp_de_set_color_encoding(struct malidp_plane *plane, | |||
318 | } | 552 | } |
319 | } | 553 | } |
320 | 554 | ||
555 | static void malidp_de_set_mmu_control(struct malidp_plane *mp, | ||
556 | struct malidp_plane_state *ms) | ||
557 | { | ||
558 | u32 mmu_ctrl; | ||
559 | |||
560 | /* check hardware supports MMU prefetch */ | ||
561 | if (!mp->layer->mmu_ctrl_offset) | ||
562 | return; | ||
563 | |||
564 | mmu_ctrl = malidp_calc_mmu_control_value(ms->mmu_prefetch_mode, | ||
565 | MALIDP_MMU_PREFETCH_READAHEAD, | ||
566 | ms->n_planes, | ||
567 | ms->mmu_prefetch_pgsize); | ||
568 | |||
569 | malidp_hw_write(mp->hwdev, mmu_ctrl, | ||
570 | mp->layer->base + mp->layer->mmu_ctrl_offset); | ||
571 | } | ||
572 | |||
321 | static void malidp_de_plane_update(struct drm_plane *plane, | 573 | static void malidp_de_plane_update(struct drm_plane *plane, |
322 | struct drm_plane_state *old_state) | 574 | struct drm_plane_state *old_state) |
323 | { | 575 | { |
324 | struct malidp_plane *mp; | 576 | struct malidp_plane *mp; |
325 | struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); | 577 | struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); |
578 | struct drm_plane_state *state = plane->state; | ||
579 | u16 pixel_alpha = state->pixel_blend_mode; | ||
580 | u8 plane_alpha = state->alpha >> 8; | ||
326 | u32 src_w, src_h, dest_w, dest_h, val; | 581 | u32 src_w, src_h, dest_w, dest_h, val; |
327 | int i; | 582 | int i; |
328 | bool format_has_alpha = plane->state->fb->format->has_alpha; | ||
329 | 583 | ||
330 | mp = to_malidp_plane(plane); | 584 | mp = to_malidp_plane(plane); |
331 | 585 | ||
332 | /* convert src values from Q16 fixed point to integer */ | 586 | /* convert src values from Q16 fixed point to integer */ |
333 | src_w = plane->state->src_w >> 16; | 587 | src_w = state->src_w >> 16; |
334 | src_h = plane->state->src_h >> 16; | 588 | src_h = state->src_h >> 16; |
335 | dest_w = plane->state->crtc_w; | 589 | dest_w = state->crtc_w; |
336 | dest_h = plane->state->crtc_h; | 590 | dest_h = state->crtc_h; |
337 | 591 | ||
338 | val = malidp_hw_read(mp->hwdev, mp->layer->base); | 592 | val = malidp_hw_read(mp->hwdev, mp->layer->base); |
339 | val = (val & ~LAYER_FORMAT_MASK) | ms->format; | 593 | val = (val & ~LAYER_FORMAT_MASK) | ms->format; |
@@ -342,14 +596,17 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
342 | for (i = 0; i < ms->n_planes; i++) { | 596 | for (i = 0; i < ms->n_planes; i++) { |
343 | /* calculate the offset for the layer's plane registers */ | 597 | /* calculate the offset for the layer's plane registers */ |
344 | u16 ptr = mp->layer->ptr + (i << 4); | 598 | u16 ptr = mp->layer->ptr + (i << 4); |
345 | dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb, | 599 | dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb, |
346 | plane->state, i); | 600 | state, i); |
347 | 601 | ||
348 | malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); | 602 | malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); |
349 | malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); | 603 | malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); |
350 | } | 604 | } |
605 | |||
606 | malidp_de_set_mmu_control(mp, ms); | ||
607 | |||
351 | malidp_de_set_plane_pitches(mp, ms->n_planes, | 608 | malidp_de_set_plane_pitches(mp, ms->n_planes, |
352 | plane->state->fb->pitches); | 609 | state->fb->pitches); |
353 | 610 | ||
354 | if ((plane->state->color_encoding != old_state->color_encoding) || | 611 | if ((plane->state->color_encoding != old_state->color_encoding) || |
355 | (plane->state->color_range != old_state->color_range)) | 612 | (plane->state->color_range != old_state->color_range)) |
@@ -362,52 +619,56 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
362 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), | 619 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h), |
363 | mp->layer->base + MALIDP_LAYER_COMP_SIZE); | 620 | mp->layer->base + MALIDP_LAYER_COMP_SIZE); |
364 | 621 | ||
365 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) | | 622 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) | |
366 | LAYER_V_VAL(plane->state->crtc_y), | 623 | LAYER_V_VAL(state->crtc_y), |
367 | mp->layer->base + MALIDP_LAYER_OFFSET); | 624 | mp->layer->base + MALIDP_LAYER_OFFSET); |
368 | 625 | ||
369 | if (mp->layer->id == DE_SMART) | 626 | if (mp->layer->id == DE_SMART) { |
627 | /* | ||
628 | * Enable the first rectangle in the SMART layer to be | ||
629 | * able to use it as a drm plane. | ||
630 | */ | ||
631 | malidp_hw_write(mp->hwdev, 1, | ||
632 | mp->layer->base + MALIDP550_LS_ENABLE); | ||
370 | malidp_hw_write(mp->hwdev, | 633 | malidp_hw_write(mp->hwdev, |
371 | LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), | 634 | LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), |
372 | mp->layer->base + MALIDP550_LS_R1_IN_SIZE); | 635 | mp->layer->base + MALIDP550_LS_R1_IN_SIZE); |
636 | } | ||
373 | 637 | ||
374 | /* first clear the rotation bits */ | 638 | /* first clear the rotation bits */ |
375 | val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL); | 639 | val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL); |
376 | val &= ~LAYER_ROT_MASK; | 640 | val &= ~LAYER_ROT_MASK; |
377 | 641 | ||
378 | /* setup the rotation and axis flip bits */ | 642 | /* setup the rotation and axis flip bits */ |
379 | if (plane->state->rotation & DRM_MODE_ROTATE_MASK) | 643 | if (state->rotation & DRM_MODE_ROTATE_MASK) |
380 | val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << | 644 | val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) << |
381 | LAYER_ROT_OFFSET; | 645 | LAYER_ROT_OFFSET; |
382 | if (plane->state->rotation & DRM_MODE_REFLECT_X) | 646 | if (state->rotation & DRM_MODE_REFLECT_X) |
383 | val |= LAYER_H_FLIP; | 647 | val |= LAYER_H_FLIP; |
384 | if (plane->state->rotation & DRM_MODE_REFLECT_Y) | 648 | if (state->rotation & DRM_MODE_REFLECT_Y) |
385 | val |= LAYER_V_FLIP; | 649 | val |= LAYER_V_FLIP; |
386 | 650 | ||
387 | val &= ~LAYER_COMP_MASK; | 651 | val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE | LAYER_ALPHA(0xff)); |
388 | if (format_has_alpha) { | ||
389 | |||
390 | /* | ||
391 | * always enable pixel alpha blending until we have a way | ||
392 | * to change blend modes | ||
393 | */ | ||
394 | val |= LAYER_COMP_PIXEL; | ||
395 | } else { | ||
396 | 652 | ||
397 | /* | 653 | if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) { |
398 | * do not enable pixel alpha blending as the color channel | ||
399 | * does not have any alpha information | ||
400 | */ | ||
401 | val |= LAYER_COMP_PLANE; | 654 | val |= LAYER_COMP_PLANE; |
402 | 655 | } else if (state->fb->format->has_alpha) { | |
403 | /* Set layer alpha coefficient to 0xff ie fully opaque */ | 656 | /* We only care about blend mode if the format has alpha */ |
404 | val |= LAYER_ALPHA(0xff); | 657 | switch (pixel_alpha) { |
658 | case DRM_MODE_BLEND_PREMULTI: | ||
659 | val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE; | ||
660 | break; | ||
661 | case DRM_MODE_BLEND_COVERAGE: | ||
662 | val |= LAYER_COMP_PIXEL; | ||
663 | break; | ||
664 | } | ||
405 | } | 665 | } |
666 | val |= LAYER_ALPHA(plane_alpha); | ||
406 | 667 | ||
407 | val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); | 668 | val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); |
408 | if (plane->state->crtc) { | 669 | if (state->crtc) { |
409 | struct malidp_crtc_state *m = | 670 | struct malidp_crtc_state *m = |
410 | to_malidp_crtc_state(plane->state->crtc->state); | 671 | to_malidp_crtc_state(state->crtc->state); |
411 | 672 | ||
412 | if (m->scaler_config.scale_enable && | 673 | if (m->scaler_config.scale_enable && |
413 | m->scaler_config.plane_src_id == mp->layer->id) | 674 | m->scaler_config.plane_src_id == mp->layer->id) |
@@ -446,6 +707,9 @@ int malidp_de_planes_init(struct drm_device *drm) | |||
446 | unsigned long crtcs = 1 << drm->mode_config.num_crtc; | 707 | unsigned long crtcs = 1 << drm->mode_config.num_crtc; |
447 | unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | | 708 | unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | |
448 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; | 709 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; |
710 | unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | | ||
711 | BIT(DRM_MODE_BLEND_PREMULTI) | | ||
712 | BIT(DRM_MODE_BLEND_COVERAGE); | ||
449 | u32 *formats; | 713 | u32 *formats; |
450 | int ret, i, j, n; | 714 | int ret, i, j, n; |
451 | 715 | ||
@@ -483,13 +747,10 @@ int malidp_de_planes_init(struct drm_device *drm) | |||
483 | plane->hwdev = malidp->dev; | 747 | plane->hwdev = malidp->dev; |
484 | plane->layer = &map->layers[i]; | 748 | plane->layer = &map->layers[i]; |
485 | 749 | ||
750 | drm_plane_create_alpha_property(&plane->base); | ||
751 | drm_plane_create_blend_mode_property(&plane->base, blend_caps); | ||
752 | |||
486 | if (id == DE_SMART) { | 753 | if (id == DE_SMART) { |
487 | /* | ||
488 | * Enable the first rectangle in the SMART layer to be | ||
489 | * able to use it as a drm plane. | ||
490 | */ | ||
491 | malidp_hw_write(malidp->dev, 1, | ||
492 | plane->layer->base + MALIDP550_LS_ENABLE); | ||
493 | /* Skip the features which the SMART layer doesn't have. */ | 754 | /* Skip the features which the SMART layer doesn't have. */ |
494 | continue; | 755 | continue; |
495 | } | 756 | } |
diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h index 6ffe849774f2..7ce3e141464d 100644 --- a/drivers/gpu/drm/arm/malidp_regs.h +++ b/drivers/gpu/drm/arm/malidp_regs.h | |||
@@ -247,6 +247,17 @@ | |||
247 | #define MALIDP550_CONFIG_VALID 0x0c014 | 247 | #define MALIDP550_CONFIG_VALID 0x0c014 |
248 | #define MALIDP550_CONFIG_ID 0x0ffd4 | 248 | #define MALIDP550_CONFIG_ID 0x0ffd4 |
249 | 249 | ||
250 | /* register offsets specific to DP650 */ | ||
251 | #define MALIDP650_DE_LV_MMU_CTRL 0x000D0 | ||
252 | #define MALIDP650_DE_LG_MMU_CTRL 0x00048 | ||
253 | #define MALIDP650_DE_LS_MMU_CTRL 0x00078 | ||
254 | |||
255 | /* bit masks to set the MMU control register */ | ||
256 | #define MALIDP_MMU_CTRL_EN (1 << 0) | ||
257 | #define MALIDP_MMU_CTRL_MODE (1 << 4) | ||
258 | #define MALIDP_MMU_CTRL_PX_PS(x) (1 << (8 + (x))) | ||
259 | #define MALIDP_MMU_CTRL_PP_NUM_REQ(x) (((x) & 0x7f) << 12) | ||
260 | |||
250 | /* | 261 | /* |
251 | * Starting with DP550 the register map blocks has been standardised to the | 262 | * Starting with DP550 the register map blocks has been standardised to the |
252 | * following layout: | 263 | * following layout: |