From patchwork Wed May 23 14:34:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10421435 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 2E1C86032A for ; Wed, 23 May 2018 14:40:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 106D029026 for ; Wed, 23 May 2018 14:40:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0DF6E290DA; Wed, 23 May 2018 14:40:09 +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=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable 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 BA5B129026 for ; Wed, 23 May 2018 14:40:03 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B55D66E4E0; Wed, 23 May 2018 14:40:02 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5D56A6E4D2 for ; Wed, 23 May 2018 14:40:01 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:46268 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1fLUqb-0002Bg-3Z; Wed, 23 May 2018 16:34:37 +0200 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Date: Wed, 23 May 2018 16:34:11 +0200 Message-Id: <20180523143411.64070-10-noralf@tronnes.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180523143411.64070-1-noralf@tronnes.org> References: <20180523143411.64070-1-noralf@tronnes.org> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 9/9] drm/fb-helper: Finish the generic fbdev emulation X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= , laurent.pinchart@ideasonboard.com Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP This adds a drm_fbdev_generic_setup() function that sets up generic fbdev emulation with client callbacks for lastclose, hotplug and remove/unregister. Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 123 ++++++++++++++++++++++++++++++++++++++++ include/drm/drm_fb_helper.h | 7 +++ 2 files changed, 130 insertions(+) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 444c2b4040ea..bc826457eb84 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -68,6 +68,9 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); * helper functions used by many drivers to implement the kernel mode setting * interfaces. * + * Drivers that support a dumb buffer with a virtual address and mmap support, + * should try and use the generic fbdev emulation using drm_fbdev_generic_setup(). + * * Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it * down by calling drm_fb_helper_fbdev_teardown(). * @@ -3092,6 +3095,126 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper, } EXPORT_SYMBOL(drm_fb_helper_generic_probe); +static const struct drm_fb_helper_funcs drm_fb_helper_generic_funcs = { + .fb_probe = drm_fb_helper_generic_probe, +}; + +static int drm_fbdev_client_remove(struct drm_client_dev *client) +{ + struct drm_fb_helper *fb_helper = client->private; + + /* Maybe setup was tried but failed */ + if (!fb_helper) + return 0; + + /* Maybe drm_fb_helper_fbdev_setup() hasn't run yet */ + if (!fb_helper->dev) { + kfree(fb_helper); + return 0; + } + + /* Maybe drm_fb_helper_generic_probe() hasn't run yet */ + if (!fb_helper->fbdev) { + drm_fb_helper_fini(fb_helper); + kfree(fb_helper); + return 0; + } + + unregister_framebuffer(fb_helper->fbdev); + + /* + * If userspace is closed the client is now freed by drm_fbdev_fb_destroy(), + * otherwise it will be freed on the last close. + * Return 1 to tell that freeing is taken care of. + */ + return 1; +} + +static int drm_fbdev_client_lastclose(struct drm_client_dev *client) +{ + drm_fb_helper_restore_fbdev_mode_unlocked(client->private); + + return 0; +} + +static int drm_fbdev_client_hotplug(struct drm_client_dev *client) +{ + struct drm_fb_helper *fb_helper = client->private; + struct drm_device *dev = client->dev; + int ret; + + if (dev->fb_helper) + return drm_fb_helper_hotplug_event(dev->fb_helper); + + if (!dev->mode_config.num_connector || !fb_helper) + return 0; + + ret = drm_fb_helper_fbdev_setup(dev, fb_helper, &drm_fb_helper_generic_funcs, + fb_helper->preferred_bpp, 0); + if (ret) { + /* Setup is tried only once */ + client->private = NULL; + kfree(fb_helper); + return ret; + } + + return 0; +} + +static const struct drm_client_funcs drm_fbdev_client_funcs = { + .name = "fbdev", + .remove = drm_fbdev_client_remove, + .lastclose = drm_fbdev_client_lastclose, + .hotplug = drm_fbdev_client_hotplug, +}; + +/** + * drm_fb_helper_generic_fbdev_setup() - Setup generic fbdev emulation + * @dev: DRM device + * @preferred_bpp: Preferred bits per pixel for the device. + * @dev->mode_config.preferred_depth is used if this is zero. + * + * This function sets up generic fbdev emulation for drivers that supports + * dumb buffers with a virtual address and that can be mmap'ed. + * + * Restore, hotplug events and teardown are all taken care of. Drivers that does + * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves. + * Simple drivers might use drm_mode_config_helper_suspend(). + * + * This function is safe to call even when there are no connectors present. + * Setup will be retried on the next hotplug event. + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) +{ + struct drm_fb_helper *fb_helper; + struct drm_client_dev *client; + + if (!drm_fbdev_emulation) + return 0; + + fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); + if (!fb_helper) + return -ENOMEM; + + client = drm_client_new(dev, &drm_fbdev_client_funcs); + if (IS_ERR(client)) { + kfree(fb_helper); + return PTR_ERR(client); + } + + client->private = fb_helper; + fb_helper->client = client; + fb_helper->preferred_bpp = preferred_bpp; + + drm_fbdev_client_hotplug(client); + + return 0; +} +EXPORT_SYMBOL(drm_fbdev_generic_setup); + /* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT) * but the module doesn't depend on any fb console symbols. At least * attempt to load fbcon to avoid leaving the system without a usable console. diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index bb38469a9502..884eabbc54d5 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -349,6 +349,7 @@ void drm_fb_helper_output_poll_changed(struct drm_device *dev); int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper, struct drm_fb_helper_surface_size *sizes); +int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp); #else static inline void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, @@ -590,6 +591,12 @@ drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper, return 0; } +static inline int +drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) +{ + return 0; +} + #endif static inline int