diff options
Diffstat (limited to 'drivers/gpu/drm/exynos')
| -rw-r--r-- | drivers/gpu/drm/exynos/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 181 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.h | 20 | 
6 files changed, 98 insertions, 121 deletions
| diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 0cb92d651ff1..7ca7e1dab52c 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -7,6 +7,7 @@ config DRM_EXYNOS  	select DRM_DISPLAY_HELPER if DRM_EXYNOS_DP  	select DRM_KMS_HELPER  	select VIDEOMODE_HELPERS +	select FB_IO_HELPERS if DRM_FBDEV_EMULATION  	select SND_SOC_HDMI_CODEC if SND_SOC  	help  	  Choose this option if you have a Samsung SoC Exynos chipset. diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 16c539657f73..6b73fb7a83c3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -16,7 +16,6 @@  #include <drm/drm_atomic.h>  #include <drm/drm_atomic_helper.h>  #include <drm/drm_drv.h> -#include <drm/drm_fb_helper.h>  #include <drm/drm_file.h>  #include <drm/drm_fourcc.h>  #include <drm/drm_ioctl.h> @@ -108,7 +107,6 @@ static const struct drm_driver exynos_drm_driver = {  	.driver_features	= DRIVER_MODESET | DRIVER_GEM  				  | DRIVER_ATOMIC | DRIVER_RENDER,  	.open			= exynos_drm_open, -	.lastclose		= drm_fb_helper_lastclose,  	.postclose		= exynos_drm_postclose,  	.dumb_create		= exynos_drm_gem_dumb_create,  	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd, @@ -288,19 +286,15 @@ static int exynos_drm_bind(struct device *dev)  	/* init kms poll for handling hpd */  	drm_kms_helper_poll_init(drm); -	ret = exynos_drm_fbdev_init(drm); -	if (ret) -		goto err_cleanup_poll; -  	/* register the DRM device */  	ret = drm_dev_register(drm, 0);  	if (ret < 0) -		goto err_cleanup_fbdev; +		goto err_cleanup_poll; + +	exynos_drm_fbdev_setup(drm);  	return 0; -err_cleanup_fbdev: -	exynos_drm_fbdev_fini(drm);  err_cleanup_poll:  	drm_kms_helper_poll_fini(drm);  err_unbind_all: @@ -321,7 +315,6 @@ static void exynos_drm_unbind(struct device *dev)  	drm_dev_unregister(drm); -	exynos_drm_fbdev_fini(drm);  	drm_kms_helper_poll_fini(drm);  	component_unbind_all(drm->dev, drm); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 6ae9056e7a18..81d501efd013 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -197,8 +197,6 @@ struct drm_exynos_file_private {   * @wait: wait an atomic commit to finish   */  struct exynos_drm_private { -	struct drm_fb_helper *fb_helper; -  	struct device *g2d_dev;  	struct device *dma_dev;  	void *mapping; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 97f2dee2db29..fc1c5608db96 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -11,7 +11,6 @@  #include <drm/drm_atomic.h>  #include <drm/drm_atomic_helper.h>  #include <drm/drm_crtc.h> -#include <drm/drm_fb_helper.h>  #include <drm/drm_framebuffer.h>  #include <drm/drm_fourcc.h>  #include <drm/drm_gem_framebuffer_helper.h> @@ -157,7 +156,6 @@ static struct drm_mode_config_helper_funcs exynos_drm_mode_config_helpers = {  static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {  	.fb_create = exynos_user_fb_create, -	.output_poll_changed = drm_fb_helper_output_poll_changed,  	.atomic_check = drm_atomic_helper_check,  	.atomic_commit = drm_atomic_helper_commit,  }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 4929ffe5a09a..fdf65587f1fe 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -8,16 +8,14 @@   *	Seung-Woo Kim <[email protected]>   */ -#include <linux/console.h> -#include <linux/dma-mapping.h> -#include <linux/vmalloc.h> +#include <linux/fb.h> -#include <drm/drm_crtc.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_drv.h>  #include <drm/drm_fb_helper.h> -#include <drm/drm_fourcc.h>  #include <drm/drm_framebuffer.h> +#include <drm/drm_gem_framebuffer_helper.h>  #include <drm/drm_prime.h> -#include <drm/drm_probe_helper.h>  #include <drm/exynos_drm.h>  #include "exynos_drm_drv.h" @@ -27,33 +25,35 @@  #define MAX_CONNECTOR		4  #define PREFERRED_BPP		32 -#define to_exynos_fbdev(x)	container_of(x, struct exynos_drm_fbdev,\ -				drm_fb_helper) +static int exynos_drm_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ +	struct drm_fb_helper *helper = info->par; +	struct drm_gem_object *obj = drm_gem_fb_get_obj(helper->fb, 0); -struct exynos_drm_fbdev { -	struct drm_fb_helper	drm_fb_helper; -	struct exynos_drm_gem	*exynos_gem; -}; +	return drm_gem_prime_mmap(obj, vma); +} -static int exynos_drm_fb_mmap(struct fb_info *info, -			struct vm_area_struct *vma) +static void exynos_drm_fb_destroy(struct fb_info *info)  { -	struct drm_fb_helper *helper = info->par; -	struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper); -	struct exynos_drm_gem *exynos_gem = exynos_fbd->exynos_gem; +	struct drm_fb_helper *fb_helper = info->par; +	struct drm_framebuffer *fb = fb_helper->fb; -	return drm_gem_prime_mmap(&exynos_gem->base, vma); +	drm_fb_helper_fini(fb_helper); + +	drm_framebuffer_remove(fb); + +	drm_client_release(&fb_helper->client); +	drm_fb_helper_unprepare(fb_helper); +	kfree(fb_helper);  }  static const struct fb_ops exynos_drm_fb_ops = {  	.owner		= THIS_MODULE, +	__FB_DEFAULT_IO_OPS_RDWR,  	DRM_FB_HELPER_DEFAULT_OPS, +	__FB_DEFAULT_IO_OPS_DRAW,  	.fb_mmap        = exynos_drm_fb_mmap, -	.fb_read	= drm_fb_helper_cfb_read, -	.fb_write	= drm_fb_helper_cfb_write, -	.fb_fillrect	= drm_fb_helper_cfb_fillrect, -	.fb_copyarea	= drm_fb_helper_cfb_copyarea, -	.fb_imageblit	= drm_fb_helper_cfb_imageblit, +	.fb_destroy	= exynos_drm_fb_destroy,  };  static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, @@ -89,7 +89,6 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,  static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,  				    struct drm_fb_helper_surface_size *sizes)  { -	struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper);  	struct exynos_drm_gem *exynos_gem;  	struct drm_device *dev = helper->dev;  	struct drm_mode_fb_cmd2 mode_cmd = { 0 }; @@ -113,8 +112,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,  	if (IS_ERR(exynos_gem))  		return PTR_ERR(exynos_gem); -	exynos_fbdev->exynos_gem = exynos_gem; -  	helper->fb =  		exynos_drm_framebuffer_init(dev, &mode_cmd, &exynos_gem, 1);  	if (IS_ERR(helper->fb)) { @@ -127,19 +124,13 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,  	if (ret < 0)  		goto err_destroy_framebuffer; -	return ret; +	return 0;  err_destroy_framebuffer:  	drm_framebuffer_cleanup(helper->fb); +	helper->fb = NULL;  err_destroy_gem:  	exynos_drm_gem_destroy(exynos_gem); - -	/* -	 * if failed, all resources allocated above would be released by -	 * drm_mode_config_cleanup() when drm_load() had been called prior -	 * to any specific driver such as fimd or hdmi driver. -	 */ -  	return ret;  } @@ -147,80 +138,92 @@ static const struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {  	.fb_probe =	exynos_drm_fbdev_create,  }; -int exynos_drm_fbdev_init(struct drm_device *dev) +/* + * struct drm_client + */ + +static void exynos_drm_fbdev_client_unregister(struct drm_client_dev *client)  { -	struct exynos_drm_fbdev *fbdev; -	struct exynos_drm_private *private = dev->dev_private; -	struct drm_fb_helper *helper; -	int ret; +	struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); + +	if (fb_helper->info) { +		drm_fb_helper_unregister_info(fb_helper); +	} else { +		drm_client_release(&fb_helper->client); +		drm_fb_helper_unprepare(fb_helper); +		kfree(fb_helper); +	} +} -	if (!dev->mode_config.num_crtc) -		return 0; +static int exynos_drm_fbdev_client_restore(struct drm_client_dev *client) +{ +	drm_fb_helper_lastclose(client->dev); -	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); -	if (!fbdev) -		return -ENOMEM; +	return 0; +} -	private->fb_helper = helper = &fbdev->drm_fb_helper; +static int exynos_drm_fbdev_client_hotplug(struct drm_client_dev *client) +{ +	struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); +	struct drm_device *dev = client->dev; +	int ret; -	drm_fb_helper_prepare(dev, helper, PREFERRED_BPP, &exynos_drm_fb_helper_funcs); +	if (dev->fb_helper) +		return drm_fb_helper_hotplug_event(dev->fb_helper); -	ret = drm_fb_helper_init(dev, helper); -	if (ret < 0) { -		DRM_DEV_ERROR(dev->dev, -			      "failed to initialize drm fb helper.\n"); -		goto err_init; -	} +	ret = drm_fb_helper_init(dev, fb_helper); +	if (ret) +		goto err_drm_err; -	ret = drm_fb_helper_initial_config(helper); -	if (ret < 0) { -		DRM_DEV_ERROR(dev->dev, -			      "failed to set up hw configuration.\n"); -		goto err_setup; -	} +	if (!drm_drv_uses_atomic_modeset(dev)) +		drm_helper_disable_unused_functions(dev); -	return 0; +	ret = drm_fb_helper_initial_config(fb_helper); +	if (ret) +		goto err_drm_fb_helper_fini; -err_setup: -	drm_fb_helper_fini(helper); -err_init: -	drm_fb_helper_unprepare(helper); -	private->fb_helper = NULL; -	kfree(fbdev); +	return 0; +err_drm_fb_helper_fini: +	drm_fb_helper_fini(fb_helper); +err_drm_err: +	drm_err(dev, "Failed to setup fbdev emulation (ret=%d)\n", ret);  	return ret;  } -static void exynos_drm_fbdev_destroy(struct drm_device *dev, -				      struct drm_fb_helper *fb_helper) +static const struct drm_client_funcs exynos_drm_fbdev_client_funcs = { +	.owner		= THIS_MODULE, +	.unregister	= exynos_drm_fbdev_client_unregister, +	.restore	= exynos_drm_fbdev_client_restore, +	.hotplug	= exynos_drm_fbdev_client_hotplug, +}; + +void exynos_drm_fbdev_setup(struct drm_device *dev)  { -	struct drm_framebuffer *fb; +	struct drm_fb_helper *fb_helper; +	int ret; -	/* release drm framebuffer and real buffer */ -	if (fb_helper->fb && fb_helper->fb->funcs) { -		fb = fb_helper->fb; -		if (fb) -			drm_framebuffer_remove(fb); -	} +	drm_WARN(dev, !dev->registered, "Device has not been registered.\n"); +	drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n"); -	drm_fb_helper_unregister_info(fb_helper); +	fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL); +	if (!fb_helper) +		return; +	drm_fb_helper_prepare(dev, fb_helper, PREFERRED_BPP, &exynos_drm_fb_helper_funcs); -	drm_fb_helper_fini(fb_helper); -} +	ret = drm_client_init(dev, &fb_helper->client, "fbdev", &exynos_drm_fbdev_client_funcs); +	if (ret) +		goto err_drm_client_init; -void exynos_drm_fbdev_fini(struct drm_device *dev) -{ -	struct exynos_drm_private *private = dev->dev_private; -	struct exynos_drm_fbdev *fbdev; +	ret = exynos_drm_fbdev_client_hotplug(&fb_helper->client); +	if (ret) +		drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); -	if (!private || !private->fb_helper) -		return; +	drm_client_register(&fb_helper->client); -	fbdev = to_exynos_fbdev(private->fb_helper); +	return; -	exynos_drm_fbdev_destroy(dev, private->fb_helper); -	drm_fb_helper_unprepare(private->fb_helper); -	kfree(fbdev); -	private->fb_helper = NULL; +err_drm_client_init: +	drm_fb_helper_unprepare(fb_helper); +	kfree(fb_helper);  } - diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h index 3b1e98e84580..1e1dea627cd9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h @@ -12,27 +12,11 @@  #define _EXYNOS_DRM_FBDEV_H_  #ifdef CONFIG_DRM_FBDEV_EMULATION - -int exynos_drm_fbdev_init(struct drm_device *dev); -void exynos_drm_fbdev_fini(struct drm_device *dev); - +void exynos_drm_fbdev_setup(struct drm_device *dev);  #else - -static inline int exynos_drm_fbdev_init(struct drm_device *dev) -{ -	return 0; -} - -static inline void exynos_drm_fbdev_fini(struct drm_device *dev) +static inline void exynos_drm_fbdev_setup(struct drm_device *dev)  {  } - -static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev) -{ -} - -#define exynos_drm_output_poll_changed (NULL) -  #endif  #endif |