From: Noralf Trønnes Date: Wed, 15 Nov 2017 14:19:41 +0000 (+0100) Subject: drm/cma-helper: Add drm_fb_cma_fbdev_init/fini() X-Git-Tag: v4.16-rc1~31^2~28^2~15 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=41b676e03f1c7983a94694cbd90d27c9a12cb9b9;p=uclinux-h8%2Flinux.git drm/cma-helper: Add drm_fb_cma_fbdev_init/fini() Add functions drm_fb_cma_fbdev_init(), drm_fb_cma_fbdev_fini() and drm_fb_cma_fbdev_init_with_funcs(). These functions relies on the fact that the drm_fb_helper struct is stored in dev->drm_fb_helper_private so drivers don't need to store it. Cc: Laurent Pinchart Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171115142001.45358-3-noralf@tronnes.org --- diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 35b56dfba929..186d00adfb5f 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #define DEFAULT_FBDEFIO_DELAY_MS 50 @@ -42,7 +43,7 @@ struct drm_fbdev_cma { * callback function to create a cma backed framebuffer. * * An fbdev framebuffer backed by cma is also available by calling - * drm_fbdev_cma_init(). drm_fbdev_cma_fini() tears it down. + * drm_fb_cma_fbdev_init(). drm_fb_cma_fbdev_fini() tears it down. * If the &drm_framebuffer_funcs.dirty callback is set, fb_deferred_io will be * set up automatically. &drm_framebuffer_funcs.dirty is called by * drm_fb_helper_deferred_io() in process context (&struct delayed_work). @@ -68,7 +69,7 @@ struct drm_fbdev_cma { * * Initialize:: * - * fbdev = drm_fbdev_cma_init_with_funcs(dev, 16, + * fbdev = drm_fb_cma_fbdev_init_with_funcs(dev, 16, * dev->mode_config.num_crtc, * dev->mode_config.num_connector, * &driver_fb_funcs); @@ -256,7 +257,7 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper, fbi->screen_size = size; fbi->fix.smem_len = size; - if (fbdev_cma->fb_funcs->dirty) { + if (fb->funcs->dirty) { ret = drm_fbdev_cma_defio_init(fbi, obj); if (ret) goto err_cma_destroy; @@ -278,6 +279,118 @@ static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = { }; /** + * drm_fb_cma_fbdev_init_with_funcs() - Allocate and initialize 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. + * @max_conn_count: Maximum number of connectors. + * @dev->mode_config.num_connector is used if this is zero. + * @funcs: Framebuffer functions, in particular a custom dirty() callback. + * Can be NULL. + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_fb_cma_fbdev_init_with_funcs(struct drm_device *dev, + unsigned int preferred_bpp, unsigned int max_conn_count, + const struct drm_framebuffer_funcs *funcs) +{ + struct drm_fbdev_cma *fbdev_cma; + struct drm_fb_helper *fb_helper; + int ret; + + if (!preferred_bpp) + preferred_bpp = dev->mode_config.preferred_depth; + if (!preferred_bpp) + preferred_bpp = 32; + + if (!max_conn_count) + max_conn_count = dev->mode_config.num_connector; + + fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL); + if (!fbdev_cma) + return -ENOMEM; + + fbdev_cma->fb_funcs = funcs; + fb_helper = &fbdev_cma->fb_helper; + + drm_fb_helper_prepare(dev, fb_helper, &drm_fb_cma_helper_funcs); + + ret = drm_fb_helper_init(dev, fb_helper, max_conn_count); + if (ret < 0) { + DRM_DEV_ERROR(dev->dev, "Failed to initialize fbdev helper.\n"); + goto err_free; + } + + ret = drm_fb_helper_single_add_all_connectors(fb_helper); + if (ret < 0) { + DRM_DEV_ERROR(dev->dev, "Failed to add connectors.\n"); + goto err_drm_fb_helper_fini; + } + + ret = drm_fb_helper_initial_config(fb_helper, preferred_bpp); + if (ret < 0) { + DRM_DEV_ERROR(dev->dev, "Failed to set fbdev configuration.\n"); + goto err_drm_fb_helper_fini; + } + + return 0; + +err_drm_fb_helper_fini: + drm_fb_helper_fini(fb_helper); +err_free: + kfree(fbdev_cma); + + return ret; +} +EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init_with_funcs); + +/** + * drm_fb_cma_fbdev_init() - Allocate and initialize 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. + * @max_conn_count: Maximum number of connectors. + * @dev->mode_config.num_connector is used if this is zero. + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp, + unsigned int max_conn_count) +{ + return drm_fb_cma_fbdev_init_with_funcs(dev, preferred_bpp, + max_conn_count, NULL); +} +EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init); + +/** + * drm_fb_cma_fbdev_fini() - Teardown fbdev emulation + * @dev: DRM device + */ +void drm_fb_cma_fbdev_fini(struct drm_device *dev) +{ + struct drm_fb_helper *fb_helper = dev->fb_helper; + + if (!fb_helper) + return; + + /* Unregister if it hasn't been done already */ + if (fb_helper->fbdev && fb_helper->fbdev->dev) + drm_fb_helper_unregister_fbi(fb_helper); + + if (fb_helper->fbdev) + drm_fbdev_cma_defio_fini(fb_helper->fbdev); + + if (fb_helper->fb) + drm_framebuffer_remove(fb_helper->fb); + + drm_fb_helper_fini(fb_helper); + kfree(to_fbdev_cma(fb_helper)); +} +EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_fini); + +/** * drm_fbdev_cma_init_with_funcs() - Allocate and initializes a drm_fbdev_cma struct * @dev: DRM device * @preferred_bpp: Preferred bits per pixel for the device diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h index 65def43eb231..d532f88a8d55 100644 --- a/include/drm/drm_fb_cma_helper.h +++ b/include/drm/drm_fb_cma_helper.h @@ -16,6 +16,13 @@ struct drm_mode_fb_cmd2; struct drm_plane; struct drm_plane_state; +int drm_fb_cma_fbdev_init_with_funcs(struct drm_device *dev, + unsigned int preferred_bpp, unsigned int max_conn_count, + const struct drm_framebuffer_funcs *funcs); +int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp, + unsigned int max_conn_count); +void drm_fb_cma_fbdev_fini(struct drm_device *dev); + struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev, unsigned int preferred_bpp, unsigned int max_conn_count, const struct drm_framebuffer_funcs *funcs);