Generic fbdev emulation used to access framebuffers as if they were located in system memory. Depending on the whether the framebuffer is in I/O or system memory, the fbdev emulation now calls the correct functions for accessing each. This change allows to support generic fbdev emulation on systems that treat both memory areas differently. Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> --- drivers/gpu/drm/drm_fb_helper.c | 110 ++++++++++++++++++++++++++++++-- include/drm/drm_fb_helper.h | 14 ++++ 2 files changed, 118 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index eff75fad7cab..174e6d97223f 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -771,6 +771,45 @@ void drm_fb_helper_sys_imageblit(struct fb_info *info, } EXPORT_SYMBOL(drm_fb_helper_sys_imageblit); +/** + * drm_fb_helper_cfb_read - wrapper around fb_cfb_read + * @info: fb_info struct pointer + * @buf: userspace buffer to read from framebuffer memory + * @count: number of bytes to read from framebuffer memory + * @ppos: read offset within framebuffer memory + * + * A wrapper around fb_cfb_read implemented by fbdev core + */ +ssize_t drm_fb_helper_cfb_read(struct fb_info *info, char __user *buf, + size_t count, loff_t *ppos) +{ + return fb_cfb_read(info, buf, count, ppos); +} +EXPORT_SYMBOL(drm_fb_helper_cfb_read); + +/** + * drm_fb_helper_cfb_write - wrapper around fb_cfb_write + * @info: fb_info struct pointer + * @buf: userspace buffer to write to framebuffer memory + * @count: number of bytes to write to framebuffer memory + * @ppos: write offset within framebuffer memory + * + * A wrapper around fb_cfb_write implemented by fbdev core + */ +ssize_t drm_fb_helper_cfb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) +{ + ssize_t ret; + + ret = fb_cfb_write(info, buf, count, ppos); + if (ret > 0) + drm_fb_helper_dirty(info, 0, 0, info->var.xres, + info->var.yres); + + return ret; +} +EXPORT_SYMBOL(drm_fb_helper_cfb_write); + /** * drm_fb_helper_cfb_fillrect - wrapper around cfb_fillrect * @info: fbdev registered by the helper @@ -2122,6 +2161,59 @@ static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) return -ENODEV; } +static ssize_t drm_fbdev_fb_read(struct fb_info *info, char __user *buf, + size_t count, loff_t *ppos) +{ + struct drm_fb_helper *fb_helper = info->par; + + if (fb_helper->screen_buffer_is_iomem) + return drm_fb_helper_cfb_read(info, buf, count, ppos); + return drm_fb_helper_sys_read(info, buf, count, ppos); +} + +static ssize_t drm_fbdev_fb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct drm_fb_helper *fb_helper = info->par; + + if (fb_helper->screen_buffer_is_iomem) + return drm_fb_helper_cfb_write(info, buf, count, ppos); + return drm_fb_helper_sys_write(info, buf, count, ppos); +} + +static void drm_fbdev_fb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + struct drm_fb_helper *fb_helper = info->par; + + if (fb_helper->screen_buffer_is_iomem) + drm_fb_helper_cfb_fillrect(info, rect); + else + drm_fb_helper_sys_fillrect(info, rect); +} + +static void drm_fbdev_fb_copyarea(struct fb_info *info, + const struct fb_copyarea *region) +{ + struct drm_fb_helper *fb_helper = info->par; + + if (fb_helper->screen_buffer_is_iomem) + drm_fb_helper_cfb_copyarea(info, region); + else + drm_fb_helper_sys_copyarea(info, region); +} + +static void drm_fbdev_fb_imageblit(struct fb_info *info, + const struct fb_image *image) +{ + struct drm_fb_helper *fb_helper = info->par; + + if (fb_helper->screen_buffer_is_iomem) + drm_fb_helper_cfb_imageblit(info, image); + else + drm_fb_helper_sys_imageblit(info, image); +} + static struct fb_ops drm_fbdev_fb_ops = { .owner = THIS_MODULE, DRM_FB_HELPER_DEFAULT_OPS, @@ -2129,11 +2221,11 @@ static struct fb_ops drm_fbdev_fb_ops = { .fb_release = drm_fbdev_fb_release, .fb_destroy = drm_fbdev_fb_destroy, .fb_mmap = drm_fbdev_fb_mmap, - .fb_read = drm_fb_helper_sys_read, - .fb_write = drm_fb_helper_sys_write, - .fb_fillrect = drm_fb_helper_sys_fillrect, - .fb_copyarea = drm_fb_helper_sys_copyarea, - .fb_imageblit = drm_fb_helper_sys_imageblit, + .fb_read = drm_fbdev_fb_read, + .fb_write = drm_fbdev_fb_write, + .fb_fillrect = drm_fbdev_fb_fillrect, + .fb_copyarea = drm_fbdev_fb_copyarea, + .fb_imageblit = drm_fbdev_fb_imageblit, }; static struct fb_deferred_io drm_fbdev_defio = { @@ -2209,10 +2301,15 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper, fbi->screen_buffer = shadow; fbi->fbdefio = &drm_fbdev_defio; + /* The shadowfb is always in system memory. */ + fb_helper->screen_buffer_is_iomem = false; + fb_deferred_io_init(fbi); } else { + bool is_iomem; + /* buffer is mapped for HW framebuffer */ - vaddr = drm_client_buffer_vmap(fb_helper->buffer, NULL); + vaddr = drm_client_buffer_vmap(fb_helper->buffer, &is_iomem); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); @@ -2223,6 +2320,7 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper, fbi->fix.smem_start = page_to_phys(virt_to_page(fbi->screen_buffer)); #endif + fb_helper->screen_buffer_is_iomem = is_iomem; } return 0; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 2338e9f94a03..afceae8db4af 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -155,6 +155,15 @@ struct drm_fb_helper { */ struct list_head kernel_fb_list; + /** + * @screen_buffer_is_iomem + * + * True if info->screen_buffer refers to I/O memory, false otherwise. + * Depending on this flag, fb_ops should either use sys to cfb + * functions. + */ + bool screen_buffer_is_iomem; + /** * @delayed_hotplug: * @@ -248,6 +257,11 @@ void drm_fb_helper_sys_copyarea(struct fb_info *info, void drm_fb_helper_sys_imageblit(struct fb_info *info, const struct fb_image *image); +ssize_t drm_fb_helper_cfb_read(struct fb_info *info, char __user *buf, + size_t count, loff_t *ppos); +ssize_t drm_fb_helper_cfb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos); + void drm_fb_helper_cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); void drm_fb_helper_cfb_copyarea(struct fb_info *info, -- 2.23.0 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel