From patchwork Fri Sep 2 08:22:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Herrmann X-Patchwork-Id: 9310563 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E6F9960756 for ; Fri, 2 Sep 2016 08:23:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D87AD2970C for ; Fri, 2 Sep 2016 08:23:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CD7D92970E; Fri, 2 Sep 2016 08:23:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 038012970C for ; Fri, 2 Sep 2016 08:23:31 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5A4116EA3D; Fri, 2 Sep 2016 08:23:30 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wm0-x242.google.com (mail-wm0-x242.google.com [IPv6:2a00:1450:400c:c09::242]) by gabe.freedesktop.org (Postfix) with ESMTPS id 15FB46EA38 for ; Fri, 2 Sep 2016 08:23:28 +0000 (UTC) Received: by mail-wm0-x242.google.com with SMTP id c133so1847849wmd.2 for ; Fri, 02 Sep 2016 01:23:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ulmc2MHxtQBNT9EfLJpDSYXeVIJwHuhKDG3RviD9sKI=; b=BcmK+UGuqIvga6rW2+Td4kmzT5a1AglJl7w+BKVU9KCL5VgiXyz16Df+2d1oJcAmzp SyThiAhPDK7xFQa1TkVhk/4LaCTyzTc4Ox4dnZDj2QAph6zIXYo4UOrMWSCOkM+dc6P3 vgOAZzr8HB4U+OjBt1lBITJ72jISRsB7AsO6elZGsHx/BLcbmaWtaElWguxd4UzLYYIh OZrmRIfryBRlzO24w5sKIgc9sFzBm7VKAE1kK11UcuLmKdDGQ3ReDlnA/CKb/3t7x3VZ rXQEzOW4Brw+aNUJo4JZ45sU0pgFBuOfI+EHhSUTN+gWGSiDK5ohem0bBiSOY3HUVIDm /sLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ulmc2MHxtQBNT9EfLJpDSYXeVIJwHuhKDG3RviD9sKI=; b=g9c7QIXP5t870ZsR8MaQkt/LHboFfDfEyzy/n9iSKJIIjRQfifw1mnchhbarw0DH+P 8ZnHG5cY0mdioINef/6fDNyN/9oh68oIUzhti47IF49SCgbx0S3Fh9A5ae+mFMcgEGLj HdClwZvSVayCuTQz7v7MZKhjC8nb7lxYLmpefUGyu7w1V2+WTQEWPtOsfwpjeJNYEzkG Br1XUSK70adnEN168KnpT5Tc2IDOZwbeutdyxtoeert4t7pt6kg7AXtdv25gODmgu197 7YyHOwJSRLlf0hjF/MebN6vkKrg5HydBYJlkth4DxjAfs4kW4RBqR1T3lUF8a5MQhInu MPPA== X-Gm-Message-State: AE9vXwPrEguf33UeW5d9i+1CYLl7wrG11j8Cp/y7eKvs65lKPZhcyF6KXEujoEOr22u4Sw== X-Received: by 10.194.109.161 with SMTP id ht1mr3809265wjb.190.1472804606475; Fri, 02 Sep 2016 01:23:26 -0700 (PDT) Received: from localhost.localdomain ([37.120.93.201]) by smtp.gmail.com with ESMTPSA id gg10sm9325662wjd.4.2016.09.02.01.23.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Sep 2016 01:23:25 -0700 (PDT) From: David Herrmann To: dri-devel@lists.freedesktop.org Subject: [PATCH v5 7/7] drm/simpledrm: add fbdev fallback support Date: Fri, 2 Sep 2016 10:22:45 +0200 Message-Id: <20160902082245.7119-8-dh.herrmann@gmail.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20160902082245.7119-1-dh.herrmann@gmail.com> References: <20160902082245.7119-1-dh.herrmann@gmail.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Create a simple fbdev device during SimpleDRM setup so legacy user-space and fbcon can use it. Signed-off-by: David Herrmann --- drivers/gpu/drm/simpledrm/Makefile | 1 + drivers/gpu/drm/simpledrm/simpledrm.h | 8 ++ drivers/gpu/drm/simpledrm/simpledrm_drv.c | 13 +++ drivers/gpu/drm/simpledrm/simpledrm_fbdev.c | 143 ++++++++++++++++++++++++++++ drivers/gpu/drm/simpledrm/simpledrm_kms.c | 55 ++++++----- 5 files changed, 196 insertions(+), 24 deletions(-) create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c diff --git a/drivers/gpu/drm/simpledrm/Makefile b/drivers/gpu/drm/simpledrm/Makefile index d7b179d..e368d14 100644 --- a/drivers/gpu/drm/simpledrm/Makefile +++ b/drivers/gpu/drm/simpledrm/Makefile @@ -1,6 +1,7 @@ simpledrm-y := \ simpledrm_damage.o \ simpledrm_drv.o \ + simpledrm_fbdev.o \ simpledrm_gem.o \ simpledrm_kms.o \ simpledrm_of.o diff --git a/drivers/gpu/drm/simpledrm/simpledrm.h b/drivers/gpu/drm/simpledrm/simpledrm.h index ed6d725..d7a2045 100644 --- a/drivers/gpu/drm/simpledrm/simpledrm.h +++ b/drivers/gpu/drm/simpledrm/simpledrm.h @@ -19,6 +19,7 @@ #include struct clk; +struct drm_fb_helper; struct regulator; struct simplefb_format; @@ -49,6 +50,7 @@ struct sdrm_device { atomic_t n_used; struct drm_device *ddev; struct sdrm_hw *hw; + struct drm_fb_helper *fbdev; size_t n_clks; size_t n_regulators; @@ -66,6 +68,9 @@ void sdrm_of_unbind(struct sdrm_device *sdrm); int sdrm_kms_bind(struct sdrm_device *sdrm); void sdrm_kms_unbind(struct sdrm_device *sdrm); +void sdrm_fbdev_bind(struct sdrm_device *sdrm); +void sdrm_fbdev_unbind(struct sdrm_device *sdrm); + void sdrm_dirty(struct sdrm_fb *fb, u32 x, u32 y, u32 width, u32 height); struct sdrm_bo *sdrm_bo_new(struct drm_device *ddev, size_t size); @@ -80,4 +85,7 @@ int sdrm_dumb_map_offset(struct drm_file *dfile, uint32_t handle, uint64_t *offset); +struct sdrm_fb *sdrm_fb_new(struct sdrm_bo *bo, + const struct drm_mode_fb_cmd2 *cmd); + #endif /* __SDRM_SIMPLEDRM_H */ diff --git a/drivers/gpu/drm/simpledrm/simpledrm_drv.c b/drivers/gpu/drm/simpledrm/simpledrm_drv.c index d569120..6aefe49 100644 --- a/drivers/gpu/drm/simpledrm/simpledrm_drv.c +++ b/drivers/gpu/drm/simpledrm/simpledrm_drv.c @@ -9,6 +9,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include @@ -210,6 +211,7 @@ error: static void sdrm_device_unbind(struct sdrm_device *sdrm) { if (sdrm) { + sdrm_fbdev_unbind(sdrm); sdrm_kms_unbind(sdrm); sdrm_hw_unbind(sdrm->hw); sdrm_of_unbind(sdrm); @@ -232,6 +234,8 @@ static int sdrm_device_bind(struct sdrm_device *sdrm) if (r < 0) goto error; + sdrm_fbdev_bind(sdrm); + return 0; error: @@ -253,6 +257,14 @@ static void sdrm_device_release(struct sdrm_device *sdrm) } } +static void sdrm_device_lastclose(struct drm_device *ddev) +{ + struct sdrm_device *sdrm = ddev->dev_private; + + if (sdrm->fbdev) + drm_fb_helper_restore_fbdev_mode_unlocked(sdrm->fbdev); +} + static int sdrm_fop_open(struct inode *inode, struct file *file) { struct drm_device *ddev; @@ -411,6 +423,7 @@ static const struct file_operations sdrm_drm_fops = { static struct drm_driver sdrm_drm_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &sdrm_drm_fops, + .lastclose = sdrm_device_lastclose, .gem_free_object = sdrm_bo_free, diff --git a/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c b/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c new file mode 100644 index 0000000..17e4e83 --- /dev/null +++ b/drivers/gpu/drm/simpledrm/simpledrm_fbdev.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012-2016 Red Hat, Inc. + * Copyright (C) 2016 Noralf Trønnes + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include +#include "simpledrm.h" + +static int sdrm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + return -ENODEV; +} + +static struct fb_ops sdrm_fbdev_ops = { + .owner = THIS_MODULE, + .fb_fillrect = drm_fb_helper_sys_fillrect, + .fb_copyarea = drm_fb_helper_sys_copyarea, + .fb_imageblit = drm_fb_helper_sys_imageblit, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_setcmap = drm_fb_helper_setcmap, + .fb_mmap = sdrm_fbdev_mmap, +}; + +static int sdrm_fbdev_probe(struct drm_fb_helper *fbdev, + struct drm_fb_helper_surface_size *sizes) +{ + struct sdrm_device *sdrm = fbdev->dev->dev_private; + struct drm_mode_fb_cmd2 cmd = { + .width = sdrm->hw->width, + .height = sdrm->hw->height, + .pitches[0] = sdrm->hw->stride, + .pixel_format = sdrm->hw->format, + }; + struct fb_info *fbi; + struct sdrm_bo *bo; + struct sdrm_fb *fb; + int r; + + fbi = drm_fb_helper_alloc_fbi(fbdev); + if (IS_ERR(fbi)) + return PTR_ERR(fbi); + + bo = sdrm_bo_new(sdrm->ddev, + PAGE_ALIGN(sdrm->hw->height * sdrm->hw->stride)); + if (!bo) { + r = -ENOMEM; + goto error; + } + + fb = sdrm_fb_new(bo, &cmd); + drm_gem_object_unreference_unlocked(&bo->base); + if (IS_ERR(fb)) { + r = PTR_ERR(fb); + goto error; + } + + fbdev->fb = &fb->base; + fbi->par = fbdev; + fbi->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE; + fbi->fbops = &sdrm_fbdev_ops; + + drm_fb_helper_fill_fix(fbi, fb->base.pitches[0], fb->base.depth); + drm_fb_helper_fill_var(fbi, fbdev, fb->base.width, fb->base.height); + + strncpy(fbi->fix.id, "simpledrmfb", sizeof(fbi->fix.id) - 1); + fbi->screen_base = bo->vmapping; + fbi->fix.smem_len = bo->base.size; + + return 0; + +error: + drm_fb_helper_release_fbi(fbdev); + return r; +} + +static const struct drm_fb_helper_funcs sdrm_fbdev_funcs = { + .fb_probe = sdrm_fbdev_probe, +}; + +void sdrm_fbdev_bind(struct sdrm_device *sdrm) +{ + struct drm_fb_helper *fbdev; + int r; + + fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); + if (!fbdev) + return; + + drm_fb_helper_prepare(sdrm->ddev, fbdev, &sdrm_fbdev_funcs); + + r = drm_fb_helper_init(sdrm->ddev, fbdev, 1, 1); + if (r < 0) + goto error; + + r = drm_fb_helper_single_add_all_connectors(fbdev); + if (r < 0) + goto error; + + r = drm_fb_helper_initial_config(fbdev, + sdrm->ddev->mode_config.preferred_depth); + if (r < 0) + goto error; + + if (!fbdev->fbdev) + goto error; + + sdrm->fbdev = fbdev; + return; + +error: + drm_fb_helper_fini(fbdev); + kfree(fbdev); +} + +void sdrm_fbdev_unbind(struct sdrm_device *sdrm) +{ + struct drm_fb_helper *fbdev = sdrm->fbdev; + + if (!fbdev) + return; + + sdrm->fbdev = NULL; + drm_fb_helper_unregister_fbi(fbdev); + cancel_work_sync(&fbdev->dirty_work); + drm_fb_helper_release_fbi(fbdev); + drm_framebuffer_unreference(fbdev->fb); + fbdev->fb = NULL; + drm_fb_helper_fini(fbdev); + kfree(fbdev); +} diff --git a/drivers/gpu/drm/simpledrm/simpledrm_kms.c b/drivers/gpu/drm/simpledrm/simpledrm_kms.c index 00101c9..8f67fe5 100644 --- a/drivers/gpu/drm/simpledrm/simpledrm_kms.c +++ b/drivers/gpu/drm/simpledrm/simpledrm_kms.c @@ -169,53 +169,60 @@ static const struct drm_framebuffer_funcs sdrm_fb_ops = { .destroy = sdrm_fb_destroy, }; -static struct drm_framebuffer * -sdrm_fb_create(struct drm_device *ddev, - struct drm_file *dfile, - const struct drm_mode_fb_cmd2 *cmd) +struct sdrm_fb *sdrm_fb_new(struct sdrm_bo *bo, + const struct drm_mode_fb_cmd2 *cmd) { - struct drm_gem_object *dobj; - struct sdrm_fb *fb = NULL; - struct sdrm_bo *bo; + struct sdrm_fb *fb; int r; if (cmd->flags) return ERR_PTR(-EINVAL); - dobj = drm_gem_object_lookup(dfile, cmd->handles[0]); - if (!dobj) - return ERR_PTR(-EINVAL); - - bo = container_of(dobj, struct sdrm_bo, base); - r = sdrm_bo_vmap(bo); if (r < 0) - goto error; + return ERR_PTR(r); fb = kzalloc(sizeof(*fb), GFP_KERNEL); - if (!fb) { - r = -ENOMEM; - goto error; - } + if (!fb) + return ERR_PTR(r); + drm_gem_object_reference(&bo->base); fb->bo = bo; drm_helper_mode_fill_fb_struct(&fb->base, cmd); - r = drm_framebuffer_init(ddev, &fb->base, &sdrm_fb_ops); + r = drm_framebuffer_init(bo->base.dev, &fb->base, &sdrm_fb_ops); if (r < 0) goto error; - DRM_DEBUG_KMS("[FB:%d] pixel_format: %s\n", fb->base.base.id, - drm_get_format_name(fb->base.pixel_format)); - - return &fb->base; + return fb; error: + drm_gem_object_unreference_unlocked(&bo->base); kfree(fb); - drm_gem_object_unreference_unlocked(dobj); return ERR_PTR(r); } +static struct drm_framebuffer * +sdrm_fb_create(struct drm_device *ddev, + struct drm_file *dfile, + const struct drm_mode_fb_cmd2 *cmd) +{ + struct drm_gem_object *dobj; + struct sdrm_fb *fb; + + dobj = drm_gem_object_lookup(dfile, cmd->handles[0]); + if (!dobj) + return ERR_PTR(-EINVAL); + + fb = sdrm_fb_new(container_of(dobj, struct sdrm_bo, base), cmd); + drm_gem_object_unreference_unlocked(dobj); + + if (IS_ERR(fb)) + return ERR_CAST(fb); + + return &fb->base; +} + static const struct drm_mode_config_funcs sdrm_mode_config_ops = { .fb_create = sdrm_fb_create, .atomic_check = drm_atomic_helper_check,