aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorAyan Kumar Halder <ayan.halder@arm.com>2018-07-10 09:18:55 -0400
committerLiviu Dudau <Liviu.Dudau@arm.com>2018-10-02 07:12:19 -0400
commit3dae1c0919d8c46710187df4fa1a43622289a1f5 (patch)
tree86bfea52daa180d71cf1fd197c6471e6eb1a4b7a /drivers/gpu/drm
parent66da13a519b33143932df5dc89973781c027c827 (diff)
drm/arm/malidp: Implemented the size validation for AFBC framebuffers
AFBC buffers include additional metadata which increases the required allocation size. Implement the appropriate size validation and sanity checking for AFBC buffers. Added malidp specific function for framebuffer creation. This checks if the framebuffer has AFBC modifiers and if so, it verifies the necessary constraints on the size, alignment, offsets and pitch. Changes from v2: - Replaced DRM_ERROR() with DRM_DEBUG_KMS() in malidp_verify_afbc_framebuffer_caps() and malidp_verify_afbc_framebuffer_size() Signed-off-by: Ayan Kumar halder <ayan.halder@arm.com> Reviewed-by: Brian Starkey <brian.starkey@arm.com> Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c128
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.h5
2 files changed, 132 insertions, 1 deletions
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
41static void malidp_write_gamma_table(struct malidp_hw_device *hwdev, 42static 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
262static bool
263malidp_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
310static bool
311malidp_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
365static bool
366malidp_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
375struct drm_framebuffer *
376malidp_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
261static const struct drm_mode_config_funcs malidp_mode_config_funcs = { 387static 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_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
index 3ab133d49bba..40155e2ea9d9 100644
--- a/drivers/gpu/drm/arm/malidp_hw.h
+++ b/drivers/gpu/drm/arm/malidp_hw.h
@@ -388,4 +388,9 @@ static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev)
388 388
389#define MALIDP_GAMMA_LUT_SIZE 4096 389#define MALIDP_GAMMA_LUT_SIZE 4096
390 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
391#endif /* __MALIDP_HW_H__ */ 396#endif /* __MALIDP_HW_H__ */