diff options
-rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_planes.c | 238 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_regs.h | 11 |
5 files changed, 296 insertions, 9 deletions
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..c874ef4ac005 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c | |||
@@ -84,16 +84,45 @@ 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 |
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 }, | ||
92 | { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, | ||
93 | MALIDP_DE_LG_STRIDE, 0, 0 }, | ||
94 | { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, | ||
95 | MALIDP_DE_LG_STRIDE, 0, 0 }, | ||
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 |
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 }, | ||
104 | { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, | ||
105 | MALIDP_DE_LG_STRIDE, 0, 0 }, | ||
106 | { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, | ||
107 | MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0 }, | ||
108 | { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, | ||
109 | MALIDP550_DE_LS_R1_STRIDE, 0, 0 }, | ||
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 | */ | ||
116 | { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, | ||
117 | MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, | ||
118 | MALIDP650_DE_LV_MMU_CTRL }, | ||
119 | { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, | ||
120 | MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL }, | ||
121 | { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, | ||
122 | MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, | ||
123 | MALIDP650_DE_LV_MMU_CTRL }, | ||
124 | { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, | ||
125 | MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL }, | ||
97 | }; | 126 | }; |
98 | 127 | ||
99 | #define SE_N_SCALING_COEFFS 96 | 128 | #define SE_N_SCALING_COEFFS 96 |
@@ -853,8 +882,8 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = { | |||
853 | .dc_base = MALIDP550_DC_BASE, | 882 | .dc_base = MALIDP550_DC_BASE, |
854 | .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, | 883 | .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH, |
855 | .features = MALIDP_REGMAP_HAS_CLEARIRQ, | 884 | .features = MALIDP_REGMAP_HAS_CLEARIRQ, |
856 | .n_layers = ARRAY_SIZE(malidp550_layers), | 885 | .n_layers = ARRAY_SIZE(malidp650_layers), |
857 | .layers = malidp550_layers, | 886 | .layers = malidp650_layers, |
858 | .de_irq_map = { | 887 | .de_irq_map = { |
859 | .irq_mask = MALIDP_DE_IRQ_UNDERRUN | | 888 | .irq_mask = MALIDP_DE_IRQ_UNDERRUN | |
860 | MALIDP650_DE_IRQ_DRIFT | | 889 | MALIDP650_DE_IRQ_DRIFT | |
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index 9fc94c08190f..0d7f9ea0ade8 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h | |||
@@ -62,6 +62,7 @@ struct malidp_layer { | |||
62 | u16 ptr; /* address offset for the pointer register */ | 62 | u16 ptr; /* address offset for the pointer register */ |
63 | u16 stride_offset; /* offset to the first stride register. */ | 63 | u16 stride_offset; /* offset to the first stride register. */ |
64 | s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */ | 64 | s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */ |
65 | u16 mmu_ctrl_offset; /* offset to the MMU control register */ | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | enum malidp_scaling_coeff_set { | 68 | enum malidp_scaling_coeff_set { |
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 39416bcd880e..76aafc296e1b 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 | ||
@@ -57,6 +60,13 @@ | |||
57 | */ | 60 | */ |
58 | #define MALIDP_ALPHA_LUT 0xffaa5500 | 61 | #define MALIDP_ALPHA_LUT 0xffaa5500 |
59 | 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 | |||
60 | static void malidp_de_plane_destroy(struct drm_plane *plane) | 70 | static void malidp_de_plane_destroy(struct drm_plane *plane) |
61 | { | 71 | { |
62 | struct malidp_plane *mp = to_malidp_plane(plane); | 72 | struct malidp_plane *mp = to_malidp_plane(plane); |
@@ -101,6 +111,9 @@ drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) | |||
101 | state->format = m_state->format; | 111 | state->format = m_state->format; |
102 | state->n_planes = m_state->n_planes; | 112 | state->n_planes = m_state->n_planes; |
103 | 113 | ||
114 | state->mmu_prefetch_mode = m_state->mmu_prefetch_mode; | ||
115 | state->mmu_prefetch_pgsize = m_state->mmu_prefetch_pgsize; | ||
116 | |||
104 | return &state->base; | 117 | return &state->base; |
105 | } | 118 | } |
106 | 119 | ||
@@ -113,6 +126,12 @@ static void malidp_destroy_plane_state(struct drm_plane *plane, | |||
113 | kfree(m_state); | 126 | kfree(m_state); |
114 | } | 127 | } |
115 | 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 | |||
116 | static void malidp_plane_atomic_print_state(struct drm_printer *p, | 135 | static void malidp_plane_atomic_print_state(struct drm_printer *p, |
117 | const struct drm_plane_state *state) | 136 | const struct drm_plane_state *state) |
118 | { | 137 | { |
@@ -121,6 +140,9 @@ static void malidp_plane_atomic_print_state(struct drm_printer *p, | |||
121 | drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size); | 140 | drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size); |
122 | drm_printf(p, "\tformat_id=%u\n", ms->format); | 141 | drm_printf(p, "\tformat_id=%u\n", ms->format); |
123 | 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); | ||
124 | } | 146 | } |
125 | 147 | ||
126 | static const struct drm_plane_funcs malidp_de_plane_funcs = { | 148 | static const struct drm_plane_funcs malidp_de_plane_funcs = { |
@@ -174,6 +196,199 @@ static int malidp_se_check_scaling(struct malidp_plane *mp, | |||
174 | return 0; | 196 | return 0; |
175 | } | 197 | } |
176 | 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 | |||
177 | static int malidp_de_plane_check(struct drm_plane *plane, | 392 | static int malidp_de_plane_check(struct drm_plane *plane, |
178 | struct drm_plane_state *state) | 393 | struct drm_plane_state *state) |
179 | { | 394 | { |
@@ -250,6 +465,8 @@ static int malidp_de_plane_check(struct drm_plane *plane, | |||
250 | fb->format->has_alpha) | 465 | fb->format->has_alpha) |
251 | return -EINVAL; | 466 | return -EINVAL; |
252 | 467 | ||
468 | malidp_de_prefetch_settings(mp, ms); | ||
469 | |||
253 | return 0; | 470 | return 0; |
254 | } | 471 | } |
255 | 472 | ||
@@ -326,6 +543,24 @@ static void malidp_de_set_color_encoding(struct malidp_plane *plane, | |||
326 | } | 543 | } |
327 | } | 544 | } |
328 | 545 | ||
546 | static void malidp_de_set_mmu_control(struct malidp_plane *mp, | ||
547 | struct malidp_plane_state *ms) | ||
548 | { | ||
549 | u32 mmu_ctrl; | ||
550 | |||
551 | /* check hardware supports MMU prefetch */ | ||
552 | if (!mp->layer->mmu_ctrl_offset) | ||
553 | return; | ||
554 | |||
555 | mmu_ctrl = malidp_calc_mmu_control_value(ms->mmu_prefetch_mode, | ||
556 | MALIDP_MMU_PREFETCH_READAHEAD, | ||
557 | ms->n_planes, | ||
558 | ms->mmu_prefetch_pgsize); | ||
559 | |||
560 | malidp_hw_write(mp->hwdev, mmu_ctrl, | ||
561 | mp->layer->base + mp->layer->mmu_ctrl_offset); | ||
562 | } | ||
563 | |||
329 | static void malidp_de_plane_update(struct drm_plane *plane, | 564 | static void malidp_de_plane_update(struct drm_plane *plane, |
330 | struct drm_plane_state *old_state) | 565 | struct drm_plane_state *old_state) |
331 | { | 566 | { |
@@ -358,6 +593,9 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
358 | malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); | 593 | malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr); |
359 | malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); | 594 | malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4); |
360 | } | 595 | } |
596 | |||
597 | malidp_de_set_mmu_control(mp, ms); | ||
598 | |||
361 | malidp_de_set_plane_pitches(mp, ms->n_planes, | 599 | malidp_de_set_plane_pitches(mp, ms->n_planes, |
362 | state->fb->pitches); | 600 | state->fb->pitches); |
363 | 601 | ||
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: |