From patchwork Wed Nov 6 09:31:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11229761 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E1B3916B1 for ; Wed, 6 Nov 2019 09:31:38 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C614E2075C for ; Wed, 6 Nov 2019 09:31:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C614E2075C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B28DC6EC79; Wed, 6 Nov 2019 09:31:29 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx1.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6CCE66EC78 for ; Wed, 6 Nov 2019 09:31:28 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 22637B421; Wed, 6 Nov 2019 09:31:26 +0000 (UTC) From: Thomas Zimmermann To: daniel@ffwll.ch, christian.koenig@amd.com, noralf@tronnes.org Subject: [PATCH 7/8] drm/fb-helper: Select between fb_{sys, cfb}_read() and _write() Date: Wed, 6 Nov 2019 10:31:20 +0100 Message-Id: <20191106093121.21762-8-tzimmermann@suse.de> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191106093121.21762-1-tzimmermann@suse.de> References: <20191106093121.21762-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" 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 --- 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,