struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, struct drm_file *file, struct drm_mode_fb_cmd2 *cmd) { unsigned int hsub, vsub, i; struct mtk_drm_fb *mtk_fb; struct drm_gem_object *gem[MAX_FB_OBJ]; int err; hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format); vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format); for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) { unsigned int width = cmd->width / (i ? hsub : 1); unsigned int height = cmd->height / (i ? vsub : 1); unsigned int size, bpp; gem[i] = drm_gem_object_lookup(dev, file, cmd->handles[i]); if (!gem[i]) { err = -ENOENT; goto unreference; } bpp = drm_format_plane_cpp(cmd->pixel_format, i); size = (height - 1) * cmd->pitches[i] + width * bpp; size += cmd->offsets[i]; if (gem[i]->size < size) { err = -EINVAL; goto unreference; } } mtk_fb = mtk_drm_framebuffer_init(dev, cmd, gem); return &mtk_fb->base; unreference: while (i--) drm_gem_object_unreference_unlocked(gem[i]); return ERR_PTR(err); }
struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *cmd) { struct mtk_drm_fb *mtk_fb; struct drm_gem_object *gem; unsigned int width = cmd->width; unsigned int height = cmd->height; unsigned int size, bpp; int ret; if (drm_format_num_planes(cmd->pixel_format) != 1) return ERR_PTR(-EINVAL); gem = drm_gem_object_lookup(file, cmd->handles[0]); if (!gem) return ERR_PTR(-ENOENT); bpp = drm_format_plane_cpp(cmd->pixel_format, 0); size = (height - 1) * cmd->pitches[0] + width * bpp; size += cmd->offsets[0]; if (gem->size < size) { ret = -EINVAL; goto unreference; } mtk_fb = mtk_drm_framebuffer_init(dev, cmd, gem); if (IS_ERR(mtk_fb)) { ret = PTR_ERR(mtk_fb); goto unreference; } return &mtk_fb->base; unreference: drm_gem_object_unreference_unlocked(gem); return ERR_PTR(ret); }
static int mtk_fbdev_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = helper->dev; struct drm_mode_fb_cmd2 mode = { 0 }; struct mtk_drm_fb *mtk_fb; struct mtk_drm_gem_obj *mtk_gem; struct drm_gem_object *gem; struct fb_info *info; struct drm_framebuffer *fb; unsigned long offset; size_t size; int err; mode.width = sizes->surface_width; mode.height = sizes->surface_height; mode.pitches[0] = sizes->surface_width * ((sizes->surface_bpp + 7) / 8); mode.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); mode.height = mode.height;/* << 1; for fb use? */ size = mode.pitches[0] * mode.height; dev_info(dev->dev, "mtk_fbdev_probe %dx%d bpp %d pitch %d size %zu\n", mode.width, mode.height, sizes->surface_bpp, mode.pitches[0], size); mtk_gem = mtk_drm_gem_create(dev, size, true); if (IS_ERR(mtk_gem)) { err = PTR_ERR(mtk_gem); goto fini; } gem = &mtk_gem->base; mtk_fb = mtk_drm_framebuffer_init(dev, &mode, &gem); if (IS_ERR(mtk_fb)) { dev_err(dev->dev, "failed to allocate DRM framebuffer\n"); err = PTR_ERR(mtk_fb); goto free; } fb = &mtk_fb->base; info = framebuffer_alloc(0, dev->dev); if (!info) { dev_err(dev->dev, "failed to allocate framebuffer info\n"); err = PTR_ERR(info); goto release; } helper->fb = fb; helper->fbdev = info; info->par = helper; info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &mediatek_fb_ops; err = fb_alloc_cmap(&info->cmap, 256, 0); if (err < 0) { dev_err(dev->dev, "failed to allocate color map: %d\n", err); goto destroy; } drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, helper, fb->width, fb->height); offset = info->var.xoffset * (fb->bits_per_pixel + 7) / 8; offset += info->var.yoffset * fb->pitches[0]; strcpy(info->fix.id, "mtk"); /* dev->mode_config.fb_base = (resource_size_t)bo->paddr; */ info->var.yres = info->var.yres_virtual;/* >> 1; for fb use? */ info->fix.smem_start = mtk_gem->dma_addr + offset; info->fix.smem_len = size; info->screen_base = mtk_gem->kvaddr + offset; info->screen_size = size; return 0; destroy: drm_framebuffer_unregister_private(fb); mtk_drm_fb_destroy(fb); release: framebuffer_release(info); free: mtk_drm_gem_free_object(&mtk_gem->base); fini: dev_err(dev->dev, "mtk_fbdev_probe fail\n"); return err; }