On Fri, Sep 18, 2015 at 06:12:02PM +0200, Philipp Zabel wrote:
From: CK Hu ck.hu@mediatek.com
Add Mediatek legacy framebuffer support.
Signed-off-by: CK Hu ck.hu@mediatek.com Signed-off-by: YT Shen yt.shen@mediatek.com
drivers/gpu/drm/mediatek/Kconfig | 12 +++ drivers/gpu/drm/mediatek/mtk_drm_drv.c | 13 +++ drivers/gpu/drm/mediatek/mtk_drm_fb.c | 192 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_drm_fb.h | 1 + 4 files changed, 218 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index 5343cf1..fa581fb 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -14,3 +14,15 @@ config DRM_MEDIATEK This driver provides kernel mode setting and buffer management to userspace.
+config DRM_MEDIATEK_FBDEV
- bool "Enable legacy fbdev support for Mediatek DRM"
- depends on DRM_MEDIATEK
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select DRM_KMS_FB_HELPER
- help
Choose this option if you have a need for the legacy
fbdev support. Note that this support also provides
the Linux console on top of the Mediatek DRM mode
setting driver.
With the new Kconfig for fbdev emulation in 4.3 and the module option to disable it queued up for 4.4 driver-private Kconfig entries for fbdev aren't needed any more. -Daniel
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index fc071fe..b67c582 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -46,6 +46,9 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = { .fb_create = mtk_drm_mode_fb_create, .atomic_check = drm_atomic_helper_check, .atomic_commit = mtk_atomic_commit, +#ifdef CONFIG_DRM_MEDIATEK_FBDEV
- .output_poll_changed = mtk_drm_mode_output_poll_changed,
+#endif };
static const enum mtk_ddp_comp_type mtk_ddp_main[] = { @@ -140,6 +143,12 @@ static int mtk_drm_kms_init(struct drm_device *dev) drm_kms_helper_poll_init(dev); drm_mode_config_reset(dev);
+#ifdef CONFIG_DRM_MEDIATEK_FBDEV
- err = mtk_fbdev_create(dev);
- if (err)
goto err_larb_get;
+#endif
- return 0;
err_larb_get: @@ -160,6 +169,10 @@ static void mtk_drm_kms_deinit(struct drm_device *dev) { drm_kms_helper_poll_fini(dev);
+#ifdef CONFIG_DRM_MEDIATEK_FBDEV
- mtk_fbdev_destroy(dev);
+#endif
- drm_vblank_cleanup(dev); drm_mode_config_cleanup(dev);
} diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c index dfa931b..9295ad3 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c @@ -102,6 +102,198 @@ static struct mtk_drm_fb *mtk_drm_framebuffer_init(struct drm_device *dev, return mtk_fb; }
+#ifdef CONFIG_DRM_MEDIATEK_FBDEV +static int mtk_drm_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{
- struct drm_fb_helper *helper = info->par;
- struct mtk_drm_fb *mtk_fb = to_mtk_fb(helper->fb);
- return mtk_drm_gem_mmap_buf(mtk_fb->gem_obj[0], vma);
+}
+static struct fb_ops mtk_fb_ops = {
- .owner = THIS_MODULE,
- .fb_fillrect = sys_fillrect,
- .fb_copyarea = sys_copyarea,
- .fb_imageblit = sys_imageblit,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_pan_display = drm_fb_helper_pan_display,
- .fb_setcmap = drm_fb_helper_setcmap,
- .fb_mmap = mtk_drm_fb_mmap,
+};
+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 = &mtk_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;
+}
+static const struct drm_fb_helper_funcs mtk_drm_fb_helper_funcs = {
- .fb_probe = mtk_fbdev_probe,
+};
+int mtk_fbdev_create(struct drm_device *dev) +{
- struct mtk_drm_private *priv = dev->dev_private;
- struct drm_fb_helper *fbdev;
- int ret;
- fbdev = devm_kzalloc(dev->dev, sizeof(*fbdev), GFP_KERNEL);
- if (!fbdev)
return -ENOMEM;
- drm_fb_helper_prepare(dev, fbdev, &mtk_drm_fb_helper_funcs);
- ret = drm_fb_helper_init(dev, fbdev, dev->mode_config.num_crtc,
dev->mode_config.num_connector);
- if (ret) {
dev_err(dev->dev, "failed to initialize DRM FB helper\n");
goto fini;
- }
- ret = drm_fb_helper_single_add_all_connectors(fbdev);
- if (ret) {
dev_err(dev->dev, "failed to add connectors\n");
goto fini;
- }
- ret = drm_fb_helper_initial_config(fbdev, FBDEV_BPP);
- if (ret) {
dev_err(dev->dev, "failed to set initial configuration\n");
goto fini;
- }
- priv->fb_helper = fbdev;
- return 0;
+fini:
- drm_fb_helper_fini(fbdev);
- return ret;
+}
+void mtk_fbdev_destroy(struct drm_device *dev) +{
- struct mtk_drm_private *priv = dev->dev_private;
- struct drm_fb_helper *helper = priv->fb_helper;
- struct fb_info *info = helper->fbdev;
- if (info) {
int err;
err = unregister_framebuffer(info);
if (err < 0)
DRM_DEBUG_KMS("failed to unregister framebuffer\n");
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
- }
- if (helper->fb) {
drm_framebuffer_unregister_private(helper->fb);
mtk_drm_fb_destroy(helper->fb);
- }
- drm_fb_helper_fini(helper);
+}
+void mtk_drm_mode_output_poll_changed(struct drm_device *dev) +{
- struct mtk_drm_private *priv = dev->dev_private;
- if (priv->fb_helper)
drm_fb_helper_hotplug_event(priv->fb_helper);
+} +#endif
struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, struct drm_file *file, struct drm_mode_fb_cmd2 *cmd) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.h b/drivers/gpu/drm/mediatek/mtk_drm_fb.h index 9ce7307..acbfecf 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.h @@ -15,6 +15,7 @@ #define MTK_DRM_FB_H
#define MAX_FB_OBJ 3 +#define FBDEV_BPP 16
struct drm_gem_object *mtk_fb_get_gem_obj(struct drm_framebuffer *fb, unsigned int plane); -- 2.5.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel