int exynos_drm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
- struct exynos_drm_gem *exynos_gem;
struct drm_device *dev = helper->dev;
struct fb_info *info = helper->info;
+ u32 fourcc, pitch;
+ u64 size;
+ const struct drm_format_info *format;
+ struct exynos_drm_gem *exynos_gem;
+ struct drm_gem_object *obj;
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
- unsigned long size;
int ret;
DRM_DEV_DEBUG_KMS(dev->dev,
sizes->surface_width, sizes->surface_height,
sizes->surface_bpp);
- mode_cmd.width = sizes->surface_width;
- mode_cmd.height = sizes->surface_height;
- mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3);
- mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
- sizes->surface_depth);
-
- size = mode_cmd.pitches[0] * mode_cmd.height;
+ fourcc = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
+ if (fourcc == DRM_FORMAT_INVALID)
+ return -EINVAL;
+ format = drm_get_format_info(dev, fourcc, DRM_FORMAT_MOD_LINEAR);
+ if (!format)
+ return -EINVAL;
+ pitch = drm_format_info_min_pitch(format, 0, sizes->surface_width);
+ if (!pitch)
+ return -EINVAL;
+ if (check_mul_overflow(pitch, sizes->surface_height, &size))
+ return -EINVAL;
+ size = ALIGN(size, PAGE_SIZE);
+ if (size < PAGE_SIZE)
+ return -EINVAL;
exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_WC, size, true);
if (IS_ERR(exynos_gem))
return PTR_ERR(exynos_gem);
+ obj = &exynos_gem->base;
+
+ mode_cmd.width = sizes->surface_width;
+ mode_cmd.height = sizes->surface_height;
+ mode_cmd.pixel_format = fourcc;
+ mode_cmd.pitches[0] = pitch;
+ mode_cmd.modifier[0] = DRM_FORMAT_MOD_LINEAR;
- helper->fb =
- exynos_drm_framebuffer_init(dev,
- drm_get_format_info(dev, mode_cmd.pixel_format,
- mode_cmd.modifier[0]),
- &mode_cmd, &exynos_gem, 1);
+ helper->fb = exynos_drm_framebuffer_init(dev, format, &mode_cmd, &exynos_gem, 1);
if (IS_ERR(helper->fb)) {
DRM_DEV_ERROR(dev->dev, "failed to create drm framebuffer.\n");
ret = PTR_ERR(helper->fb);
info->flags |= FBINFO_VIRTFB;
info->screen_buffer = exynos_gem->kvaddr;
- info->screen_size = size;
- info->fix.smem_len = size;
+ info->screen_size = obj->size;
+ info->fix.smem_len = obj->size;
return 0;