From: Thomas Zimmermann <tzimmermann@suse.de> To: airlied@linux.ie, daniel@ffwll.ch, b.zolnierkie@samsung.com Cc: linux-fbdev@vger.kernel.org, Thomas Zimmermann <tzimmermann@suse.de>, dri-devel@lists.freedesktop.org Subject: [PATCH 02/11] drm/fbdevdrm: Add fbdevdrm device Date: Tue, 26 Mar 2019 09:17:35 +0000 [thread overview] Message-ID: <20190326091744.11542-3-tzimmermann@suse.de> (raw) In-Reply-To: <20190326091744.11542-1-tzimmermann@suse.de> There's an fbdevdrm device for each supported fbdev device. The fbdevdrm driver listens for fb events, and creates and destroys fbdevdrm devices accordingly. Only hardware-specific fbdev drivers are supported. Generic drivers, such as vga16fb or vesafb are not handled. DRM-based fbdev drivers are also not supported. This prevents the situation where a DRM drivers enables framebuffer emulation and fbdevdrm creates a second DRM device for the same hardware. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/gpu/drm/fbdevdrm/Makefile | 3 +- drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c | 79 ++++++++++ drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h | 44 ++++++ drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c | 173 ++++++++++++++++++++- 4 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c create mode 100644 drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h diff --git a/drivers/gpu/drm/fbdevdrm/Makefile b/drivers/gpu/drm/fbdevdrm/Makefile index 65e6b43cf682..750940d38509 100644 --- a/drivers/gpu/drm/fbdevdrm/Makefile +++ b/drivers/gpu/drm/fbdevdrm/Makefile @@ -1,4 +1,5 @@ ccflags-y = -Iinclude/drm -fbdevdrm-y := fbdevdrm_drv.o +fbdevdrm-y := fbdevdrm_device.o \ + fbdevdrm_drv.o obj-$(CONFIG_DRM_FBDEVDRM) += fbdevdrm.o diff --git a/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c b/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c new file mode 100644 index 000000000000..0abf41cf05bb --- /dev/null +++ b/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * One purpose of this driver is to allow for easy conversion of framebuffer + * drivers to DRM. As a special exception to the GNU GPL, you are allowed to + * relicense this file under the terms of a license of your choice if you're + * porting a framebuffer driver. In order to do so, update the SPDX license + * identifier to the new license and remove this exception. + * + * If you add code to this file, please ensure that it's compatible with the + * stated exception. + */ + +#include "fbdevdrm_device.h" +#include <drm/drm_drv.h> +#include <drm/drm_modeset_helper.h> +#include <drm/drm_print.h> +#include <linux/fb.h> +#include <linux/pci.h> + +/* + * struct fbdrmdev_device + */ + +int fbdevdrm_device_init(struct fbdevdrm_device *fdev, struct drm_driver *drv, + struct fb_info *fb_info) +{ + int ret; + + ret = drm_dev_init(&fdev->dev, drv, fb_info->device); + if (ret) + return ret; + fdev->dev.dev_private = fdev; + fdev->dev.pdev = container_of(fb_info->device, struct pci_dev, dev); + fdev->fb_info = fb_info; + + INIT_LIST_HEAD(&fdev->device_list); + + return 0; +} + +void fbdevdrm_device_cleanup(struct fbdevdrm_device *fdev) +{ + struct drm_device *dev = &fdev->dev; + + if (!list_empty(&fdev->device_list)) { + DRM_ERROR("fbdevdrm: cleaned up device is still enqueued " + "in device list\n"); + } + + drm_dev_fini(dev); + dev->dev_private = NULL; +} + +struct fbdevdrm_device* fbdevdrm_device_create(struct drm_driver *drv, + struct fb_info *fb_info) +{ + struct fbdevdrm_device *fdev; + int ret; + + fdev = devm_kzalloc(fb_info->dev, sizeof(*fdev), GFP_KERNEL); + if (!fdev) + return ERR_PTR(-ENOMEM); + ret = fbdevdrm_device_init(fdev, drv, fb_info); + if (ret < 0) + goto err_devm_kfree; + return fdev; + +err_devm_kfree: + devm_kfree(fb_info->dev, fdev); + return ERR_PTR(ret); +} + +void fbdevdrm_device_destroy(struct fbdevdrm_device *fdev) +{ + struct device *dev = fdev->fb_info->dev; + + fbdevdrm_device_cleanup(fdev); + devm_kfree(dev, fdev); +} diff --git a/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h b/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h new file mode 100644 index 000000000000..85878f60bba4 --- /dev/null +++ b/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * One purpose of this driver is to allow for easy conversion of framebuffer + * drivers to DRM. As a special exception to the GNU GPL, you are allowed to + * relicense this file under the terms of a license of your choice if you're + * porting a framebuffer driver. In order to do so, update the SPDX license + * identifier to the new license and remove this exception. + * + * If you add code to this file, please ensure that it's compatible with the + * stated exception. + */ + +#ifndef FBDEVDRM_DEVICE_H +#define FBDEVDRM_DEVICE_H + +#include <drm/drm_device.h> +#include <linux/kernel.h> +#include <linux/list.h> + +struct drm_driver; +struct fb_info; + +struct fbdevdrm_device { + struct drm_device dev; + struct fb_info *fb_info; + + struct list_head device_list; /* entry in global device list */ +}; + +static inline struct fbdevdrm_device* fbdevdrm_device_of_device_list( + struct list_head *device_list) +{ + return list_entry(device_list, struct fbdevdrm_device, device_list); +} + +int fbdevdrm_device_init(struct fbdevdrm_device *fdev, struct drm_driver *drv, + struct fb_info *fb_info); +void fbdevdrm_device_cleanup(struct fbdevdrm_device *fdev); + +struct fbdevdrm_device* fbdevdrm_device_create(struct drm_driver *drv, + struct fb_info *fb_info); +void fbdevdrm_device_destroy(struct fbdevdrm_device *fdev); + +#endif diff --git a/drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c b/drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c index dcb263b0c386..5be902094dc6 100644 --- a/drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c +++ b/drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c @@ -10,8 +10,13 @@ * stated exception. */ +#include <drm/drm_drv.h> +#include <drm/drm_print.h> +#include <linux/console.h> /* for console_{un/lock}() */ #include <linux/fb.h> #include <linux/module.h> +#include <linux/mutex.h> +#include "fbdevdrm_device.h" /* DRM porting note: Here are some general information about the driver, * licensing and maintenance contact. If you're porting an fbdev driver @@ -29,18 +34,156 @@ #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 1 +/* + * DRM driver + */ + +static struct drm_driver fbdevdrm_drv = { + /* data fields */ + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, + .name = DRIVER_NAME, + .desc = DRIVER_DESCRIPTION, + .date = DRIVER_DATE +}; + +/* Device list */ + +static DEFINE_MUTEX(device_list_mutex); +static LIST_HEAD(device_list); + +static void device_list_add(struct fbdevdrm_device *fdev) +{ + mutex_lock(&device_list_mutex); + list_add(&fdev->device_list, &device_list); + mutex_unlock(&device_list_mutex); +} + +static struct fbdevdrm_device* device_list_del(struct fbdevdrm_device *fdev) +{ + mutex_lock(&device_list_mutex); + list_del(&fdev->device_list); + mutex_unlock(&device_list_mutex); + + return fdev; +} + +static struct fbdevdrm_device* device_list_find_by_fb_info( + const struct fb_info *fb_info) +{ + struct list_head *pos; + struct fbdevdrm_device *fdev = NULL; + + mutex_lock(&device_list_mutex); + list_for_each(pos, &device_list) { + struct fbdevdrm_device *pos_fdev + fbdevdrm_device_of_device_list(pos); + if (pos_fdev->fb_info = fb_info) { + fdev = pos_fdev; + goto out; + } + } +out: + mutex_unlock(&device_list_mutex); + return fdev; +} + /* Module entry points */ +static bool is_generic_driver(const struct fb_info *fb_info) +{ + /* DRM porting note: We don't want to bind to vga16fb, vesafb, or any + * other generic fbdev driver. Usually, these drivers have limited + * capabilitis. We only continue if the fix structure indicates a + * hardware-specific drivers . This test will also sort out drivers + * registered via DRM's fbdev emulation. If you're porting an fbdev + * driver to DRM, you can remove this test. The module's PCI device + * ids will contain this information. + */ + return !fb_info->fix.accel && + !!strcmp(fb_info->fix.id, "S3 Virge/DX"); +} + +static int on_fb_registered(struct fb_info *fb_info, void *data) +{ + struct fbdevdrm_device *fdev; + int ret; + + if (is_generic_driver(fb_info)) { + DRM_ERROR("fbdevdrm: not binding to %s\n", fb_info->fix.id); + return 0; + } + + fdev = fbdevdrm_device_create(&fbdevdrm_drv, fb_info); + if (IS_ERR(fdev)) + return PTR_ERR(fdev); + device_list_add(fdev); + + ret = drm_dev_register(&fdev->dev, 0); + if (ret) + goto err_device_list_del; + + return 0; + +err_device_list_del: + device_list_del(fdev); + fbdevdrm_device_destroy(fdev); + return ret; +} + +static int on_fb_unregistered(struct fb_info *fb_info, void *data) +{ + struct fbdevdrm_device *fdev; + + fdev = device_list_find_by_fb_info(fb_info); + if (!fdev) + return 0; + + device_list_del(fdev); + fbdevdrm_device_destroy(fdev); + + return 0; +} + static int fb_client_notifier_call(struct notifier_block *nb, unsigned long action, void *data) { + static const char* const event_name[] = { +#define EVENT_NAME(_ev) \ + [_ev] = #_ev + EVENT_NAME(FB_EVENT_MODE_CHANGE), + EVENT_NAME(FB_EVENT_SUSPEND), + EVENT_NAME(FB_EVENT_RESUME), + EVENT_NAME(FB_EVENT_MODE_DELETE), + EVENT_NAME(FB_EVENT_FB_REGISTERED), + EVENT_NAME(FB_EVENT_FB_UNREGISTERED), + EVENT_NAME(FB_EVENT_GET_CONSOLE_MAP), + EVENT_NAME(FB_EVENT_SET_CONSOLE_MAP), + EVENT_NAME(FB_EVENT_BLANK), + EVENT_NAME(FB_EVENT_NEW_MODELIST), + EVENT_NAME(FB_EVENT_MODE_CHANGE_ALL), + EVENT_NAME(FB_EVENT_CONBLANK), + EVENT_NAME(FB_EVENT_GET_REQ), + EVENT_NAME(FB_EVENT_FB_UNBIND), + EVENT_NAME(FB_EVENT_REMAP_ALL_CONSOLE), + EVENT_NAME(FB_EARLY_EVENT_BLANK), + EVENT_NAME(FB_R_EARLY_EVENT_BLANK) +#undef EVENT_NAME + }; + static int (* const on_event[])(struct fb_info*, void*) = { + [FB_EVENT_FB_REGISTERED] = on_fb_registered, + [FB_EVENT_FB_UNREGISTERED] = on_fb_unregistered }; const struct fb_event *event = data; - if ((action >= ARRAY_SIZE(on_event)) || !on_event[action]) + if ((action >= ARRAY_SIZE(on_event)) || !on_event[action]) { + DRM_ERROR("fbdevdrm: unhandled event %s\n", + event_name[action]); return 0; /* event not handled by us */ + } return on_event[action](event->info, event->data); } @@ -50,13 +193,39 @@ static struct notifier_block fb_client = { static int __init fbdevdrm_init(void) { - int ret; + int ret, i; ret = fb_register_client(&fb_client); if (ret < 0) return ret; + /* There might already be registered FB devices. We go + * through them manually to create a corresponding DRM + * device. For the event notifier, all the locking is + * performed by the fbdev framework. Here, we have to + * do it by ourselves. */ + + console_lock(); + + for_each_registered_fb(i) { + struct fb_info *fb_info = registered_fb[i]; + if (!lock_fb_info(fb_info)) { + ret = -ENODEV; + goto err_console_unlock; + } + ret = on_fb_registered(fb_info, NULL); + unlock_fb_info(fb_info); + if (ret < 0) + goto err_console_unlock; + } + + console_unlock(); + return 0; + +err_console_unlock: + console_unlock(); + return ret; } static void __exit fbdevdrm_exit(void) -- 2.21.0
WARNING: multiple messages have this Message-ID (diff)
From: Thomas Zimmermann <tzimmermann@suse.de> To: airlied@linux.ie, daniel@ffwll.ch, b.zolnierkie@samsung.com Cc: linux-fbdev@vger.kernel.org, Thomas Zimmermann <tzimmermann@suse.de>, dri-devel@lists.freedesktop.org Subject: [PATCH 02/11] drm/fbdevdrm: Add fbdevdrm device Date: Tue, 26 Mar 2019 10:17:35 +0100 [thread overview] Message-ID: <20190326091744.11542-3-tzimmermann@suse.de> (raw) In-Reply-To: <20190326091744.11542-1-tzimmermann@suse.de> There's an fbdevdrm device for each supported fbdev device. The fbdevdrm driver listens for fb events, and creates and destroys fbdevdrm devices accordingly. Only hardware-specific fbdev drivers are supported. Generic drivers, such as vga16fb or vesafb are not handled. DRM-based fbdev drivers are also not supported. This prevents the situation where a DRM drivers enables framebuffer emulation and fbdevdrm creates a second DRM device for the same hardware. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/gpu/drm/fbdevdrm/Makefile | 3 +- drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c | 79 ++++++++++ drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h | 44 ++++++ drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c | 173 ++++++++++++++++++++- 4 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c create mode 100644 drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h diff --git a/drivers/gpu/drm/fbdevdrm/Makefile b/drivers/gpu/drm/fbdevdrm/Makefile index 65e6b43cf682..750940d38509 100644 --- a/drivers/gpu/drm/fbdevdrm/Makefile +++ b/drivers/gpu/drm/fbdevdrm/Makefile @@ -1,4 +1,5 @@ ccflags-y = -Iinclude/drm -fbdevdrm-y := fbdevdrm_drv.o +fbdevdrm-y := fbdevdrm_device.o \ + fbdevdrm_drv.o obj-$(CONFIG_DRM_FBDEVDRM) += fbdevdrm.o diff --git a/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c b/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c new file mode 100644 index 000000000000..0abf41cf05bb --- /dev/null +++ b/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * One purpose of this driver is to allow for easy conversion of framebuffer + * drivers to DRM. As a special exception to the GNU GPL, you are allowed to + * relicense this file under the terms of a license of your choice if you're + * porting a framebuffer driver. In order to do so, update the SPDX license + * identifier to the new license and remove this exception. + * + * If you add code to this file, please ensure that it's compatible with the + * stated exception. + */ + +#include "fbdevdrm_device.h" +#include <drm/drm_drv.h> +#include <drm/drm_modeset_helper.h> +#include <drm/drm_print.h> +#include <linux/fb.h> +#include <linux/pci.h> + +/* + * struct fbdrmdev_device + */ + +int fbdevdrm_device_init(struct fbdevdrm_device *fdev, struct drm_driver *drv, + struct fb_info *fb_info) +{ + int ret; + + ret = drm_dev_init(&fdev->dev, drv, fb_info->device); + if (ret) + return ret; + fdev->dev.dev_private = fdev; + fdev->dev.pdev = container_of(fb_info->device, struct pci_dev, dev); + fdev->fb_info = fb_info; + + INIT_LIST_HEAD(&fdev->device_list); + + return 0; +} + +void fbdevdrm_device_cleanup(struct fbdevdrm_device *fdev) +{ + struct drm_device *dev = &fdev->dev; + + if (!list_empty(&fdev->device_list)) { + DRM_ERROR("fbdevdrm: cleaned up device is still enqueued " + "in device list\n"); + } + + drm_dev_fini(dev); + dev->dev_private = NULL; +} + +struct fbdevdrm_device* fbdevdrm_device_create(struct drm_driver *drv, + struct fb_info *fb_info) +{ + struct fbdevdrm_device *fdev; + int ret; + + fdev = devm_kzalloc(fb_info->dev, sizeof(*fdev), GFP_KERNEL); + if (!fdev) + return ERR_PTR(-ENOMEM); + ret = fbdevdrm_device_init(fdev, drv, fb_info); + if (ret < 0) + goto err_devm_kfree; + return fdev; + +err_devm_kfree: + devm_kfree(fb_info->dev, fdev); + return ERR_PTR(ret); +} + +void fbdevdrm_device_destroy(struct fbdevdrm_device *fdev) +{ + struct device *dev = fdev->fb_info->dev; + + fbdevdrm_device_cleanup(fdev); + devm_kfree(dev, fdev); +} diff --git a/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h b/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h new file mode 100644 index 000000000000..85878f60bba4 --- /dev/null +++ b/drivers/gpu/drm/fbdevdrm/fbdevdrm_device.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * One purpose of this driver is to allow for easy conversion of framebuffer + * drivers to DRM. As a special exception to the GNU GPL, you are allowed to + * relicense this file under the terms of a license of your choice if you're + * porting a framebuffer driver. In order to do so, update the SPDX license + * identifier to the new license and remove this exception. + * + * If you add code to this file, please ensure that it's compatible with the + * stated exception. + */ + +#ifndef FBDEVDRM_DEVICE_H +#define FBDEVDRM_DEVICE_H + +#include <drm/drm_device.h> +#include <linux/kernel.h> +#include <linux/list.h> + +struct drm_driver; +struct fb_info; + +struct fbdevdrm_device { + struct drm_device dev; + struct fb_info *fb_info; + + struct list_head device_list; /* entry in global device list */ +}; + +static inline struct fbdevdrm_device* fbdevdrm_device_of_device_list( + struct list_head *device_list) +{ + return list_entry(device_list, struct fbdevdrm_device, device_list); +} + +int fbdevdrm_device_init(struct fbdevdrm_device *fdev, struct drm_driver *drv, + struct fb_info *fb_info); +void fbdevdrm_device_cleanup(struct fbdevdrm_device *fdev); + +struct fbdevdrm_device* fbdevdrm_device_create(struct drm_driver *drv, + struct fb_info *fb_info); +void fbdevdrm_device_destroy(struct fbdevdrm_device *fdev); + +#endif diff --git a/drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c b/drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c index dcb263b0c386..5be902094dc6 100644 --- a/drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c +++ b/drivers/gpu/drm/fbdevdrm/fbdevdrm_drv.c @@ -10,8 +10,13 @@ * stated exception. */ +#include <drm/drm_drv.h> +#include <drm/drm_print.h> +#include <linux/console.h> /* for console_{un/lock}() */ #include <linux/fb.h> #include <linux/module.h> +#include <linux/mutex.h> +#include "fbdevdrm_device.h" /* DRM porting note: Here are some general information about the driver, * licensing and maintenance contact. If you're porting an fbdev driver @@ -29,18 +34,156 @@ #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 1 +/* + * DRM driver + */ + +static struct drm_driver fbdevdrm_drv = { + /* data fields */ + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, + .name = DRIVER_NAME, + .desc = DRIVER_DESCRIPTION, + .date = DRIVER_DATE +}; + +/* Device list */ + +static DEFINE_MUTEX(device_list_mutex); +static LIST_HEAD(device_list); + +static void device_list_add(struct fbdevdrm_device *fdev) +{ + mutex_lock(&device_list_mutex); + list_add(&fdev->device_list, &device_list); + mutex_unlock(&device_list_mutex); +} + +static struct fbdevdrm_device* device_list_del(struct fbdevdrm_device *fdev) +{ + mutex_lock(&device_list_mutex); + list_del(&fdev->device_list); + mutex_unlock(&device_list_mutex); + + return fdev; +} + +static struct fbdevdrm_device* device_list_find_by_fb_info( + const struct fb_info *fb_info) +{ + struct list_head *pos; + struct fbdevdrm_device *fdev = NULL; + + mutex_lock(&device_list_mutex); + list_for_each(pos, &device_list) { + struct fbdevdrm_device *pos_fdev = + fbdevdrm_device_of_device_list(pos); + if (pos_fdev->fb_info == fb_info) { + fdev = pos_fdev; + goto out; + } + } +out: + mutex_unlock(&device_list_mutex); + return fdev; +} + /* Module entry points */ +static bool is_generic_driver(const struct fb_info *fb_info) +{ + /* DRM porting note: We don't want to bind to vga16fb, vesafb, or any + * other generic fbdev driver. Usually, these drivers have limited + * capabilitis. We only continue if the fix structure indicates a + * hardware-specific drivers . This test will also sort out drivers + * registered via DRM's fbdev emulation. If you're porting an fbdev + * driver to DRM, you can remove this test. The module's PCI device + * ids will contain this information. + */ + return !fb_info->fix.accel && + !!strcmp(fb_info->fix.id, "S3 Virge/DX"); +} + +static int on_fb_registered(struct fb_info *fb_info, void *data) +{ + struct fbdevdrm_device *fdev; + int ret; + + if (is_generic_driver(fb_info)) { + DRM_ERROR("fbdevdrm: not binding to %s\n", fb_info->fix.id); + return 0; + } + + fdev = fbdevdrm_device_create(&fbdevdrm_drv, fb_info); + if (IS_ERR(fdev)) + return PTR_ERR(fdev); + device_list_add(fdev); + + ret = drm_dev_register(&fdev->dev, 0); + if (ret) + goto err_device_list_del; + + return 0; + +err_device_list_del: + device_list_del(fdev); + fbdevdrm_device_destroy(fdev); + return ret; +} + +static int on_fb_unregistered(struct fb_info *fb_info, void *data) +{ + struct fbdevdrm_device *fdev; + + fdev = device_list_find_by_fb_info(fb_info); + if (!fdev) + return 0; + + device_list_del(fdev); + fbdevdrm_device_destroy(fdev); + + return 0; +} + static int fb_client_notifier_call(struct notifier_block *nb, unsigned long action, void *data) { + static const char* const event_name[] = { +#define EVENT_NAME(_ev) \ + [_ev] = #_ev + EVENT_NAME(FB_EVENT_MODE_CHANGE), + EVENT_NAME(FB_EVENT_SUSPEND), + EVENT_NAME(FB_EVENT_RESUME), + EVENT_NAME(FB_EVENT_MODE_DELETE), + EVENT_NAME(FB_EVENT_FB_REGISTERED), + EVENT_NAME(FB_EVENT_FB_UNREGISTERED), + EVENT_NAME(FB_EVENT_GET_CONSOLE_MAP), + EVENT_NAME(FB_EVENT_SET_CONSOLE_MAP), + EVENT_NAME(FB_EVENT_BLANK), + EVENT_NAME(FB_EVENT_NEW_MODELIST), + EVENT_NAME(FB_EVENT_MODE_CHANGE_ALL), + EVENT_NAME(FB_EVENT_CONBLANK), + EVENT_NAME(FB_EVENT_GET_REQ), + EVENT_NAME(FB_EVENT_FB_UNBIND), + EVENT_NAME(FB_EVENT_REMAP_ALL_CONSOLE), + EVENT_NAME(FB_EARLY_EVENT_BLANK), + EVENT_NAME(FB_R_EARLY_EVENT_BLANK) +#undef EVENT_NAME + }; + static int (* const on_event[])(struct fb_info*, void*) = { + [FB_EVENT_FB_REGISTERED] = on_fb_registered, + [FB_EVENT_FB_UNREGISTERED] = on_fb_unregistered }; const struct fb_event *event = data; - if ((action >= ARRAY_SIZE(on_event)) || !on_event[action]) + if ((action >= ARRAY_SIZE(on_event)) || !on_event[action]) { + DRM_ERROR("fbdevdrm: unhandled event %s\n", + event_name[action]); return 0; /* event not handled by us */ + } return on_event[action](event->info, event->data); } @@ -50,13 +193,39 @@ static struct notifier_block fb_client = { static int __init fbdevdrm_init(void) { - int ret; + int ret, i; ret = fb_register_client(&fb_client); if (ret < 0) return ret; + /* There might already be registered FB devices. We go + * through them manually to create a corresponding DRM + * device. For the event notifier, all the locking is + * performed by the fbdev framework. Here, we have to + * do it by ourselves. */ + + console_lock(); + + for_each_registered_fb(i) { + struct fb_info *fb_info = registered_fb[i]; + if (!lock_fb_info(fb_info)) { + ret = -ENODEV; + goto err_console_unlock; + } + ret = on_fb_registered(fb_info, NULL); + unlock_fb_info(fb_info); + if (ret < 0) + goto err_console_unlock; + } + + console_unlock(); + return 0; + +err_console_unlock: + console_unlock(); + return ret; } static void __exit fbdevdrm_exit(void) -- 2.21.0 _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2019-03-26 9:17 UTC|newest] Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-03-26 9:17 [RFC][PATCH 00/11] DRM driver for fbdev devices Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 01/11] drm/fbdevdrm: Add driver skeleton Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann [this message] 2019-03-26 9:17 ` [PATCH 02/11] drm/fbdevdrm: Add fbdevdrm device Thomas Zimmermann 2019-03-26 16:03 ` Adam Jackson 2019-03-26 16:03 ` Adam Jackson 2019-03-27 7:55 ` Thomas Zimmermann 2019-03-27 7:55 ` Thomas Zimmermann 2019-03-27 8:03 ` Daniel Vetter 2019-03-27 8:03 ` Daniel Vetter 2019-03-26 9:17 ` [PATCH 03/11] drm/fbdevdrm: Add memory management Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 04/11] drm/fbdevdrm: Add file operations Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 05/11] drm/fbdevdrm: Add GEM and dumb interfaces Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 06/11] drm/fbdevdrm: Add modesetting infrastructure Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 07/11] drm/fbdevdrm: Add DRM <-> fbdev pixel-format conversion Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 16:29 ` Ville Syrjälä 2019-03-26 16:29 ` Ville Syrjälä 2019-03-27 8:28 ` Thomas Zimmermann 2019-03-27 8:28 ` Thomas Zimmermann 2019-03-27 10:00 ` Ville Syrjälä 2019-03-27 10:00 ` Ville Syrjälä 2019-03-26 9:17 ` [PATCH 08/11] drm/fbdevdrm: Add mode conversion DRM <-> fbdev Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 09/11] drm/fbdevdrm: Add primary plane Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 13:33 ` Mathieu Malaterre 2019-03-26 13:33 ` Mathieu Malaterre 2019-03-26 13:57 ` Thomas Zimmermann 2019-03-26 13:57 ` Thomas Zimmermann 2019-03-27 9:37 ` Thomas Zimmermann 2019-03-27 9:37 ` Thomas Zimmermann 2019-04-02 7:08 ` Mathieu Malaterre 2019-04-02 7:08 ` Mathieu Malaterre 2019-03-26 9:17 ` [PATCH 10/11] drm/fbdevdrm: Add CRTC Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 9:17 ` [PATCH 11/11] drm/fbdevdrm: Detect and validate display modes Thomas Zimmermann 2019-03-26 9:17 ` Thomas Zimmermann 2019-03-26 16:47 ` Ville Syrjälä 2019-03-26 16:47 ` Ville Syrjälä 2019-03-26 18:20 ` Daniel Vetter 2019-03-26 18:20 ` Daniel Vetter 2019-03-27 8:31 ` Thomas Zimmermann 2019-03-27 8:31 ` Thomas Zimmermann 2019-03-26 14:53 ` [RFC][PATCH 00/11] DRM driver for fbdev devices Daniel Vetter 2019-03-26 14:53 ` Daniel Vetter 2019-03-27 9:10 ` Thomas Zimmermann 2019-03-27 9:10 ` Thomas Zimmermann 2019-03-27 9:41 ` Daniel Vetter 2019-03-27 9:41 ` Daniel Vetter 2019-03-27 9:55 ` Michel Dänzer 2019-03-27 9:55 ` Michel Dänzer 2019-03-27 10:58 ` Daniel Vetter 2019-03-27 10:58 ` Daniel Vetter 2019-03-27 14:46 ` Thomas Zimmermann 2019-03-27 14:46 ` Thomas Zimmermann 2019-03-27 17:05 ` Daniel Vetter 2019-03-27 17:05 ` Daniel Vetter
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20190326091744.11542-3-tzimmermann@suse.de \ --to=tzimmermann@suse.de \ --cc=airlied@linux.ie \ --cc=b.zolnierkie@samsung.com \ --cc=daniel@ffwll.ch \ --cc=dri-devel@lists.freedesktop.org \ --cc=linux-fbdev@vger.kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.