diff options
| author | Dmitry Torokhov <[email protected]> | 2023-05-01 15:20:08 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-05-01 15:20:08 -0700 | 
| commit | 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e (patch) | |
| tree | d57f3a63479a07b4e0cece029886e76e04feb984 /drivers/gpu/drm/drm_fbdev_generic.c | |
| parent | 5dc63e56a9cf8df0b59c234a505a1653f1bdf885 (diff) | |
| parent | 53bea86b5712c7491bb3dae12e271666df0a308c (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.4 merge window.
Diffstat (limited to 'drivers/gpu/drm/drm_fbdev_generic.c')
| -rw-r--r-- | drivers/gpu/drm/drm_fbdev_generic.c | 141 | 
1 files changed, 55 insertions, 86 deletions
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c index ab8695669279..4d6325e91565 100644 --- a/drivers/gpu/drm/drm_fbdev_generic.c +++ b/drivers/gpu/drm/drm_fbdev_generic.c @@ -43,20 +43,18 @@ static int drm_fbdev_fb_release(struct fb_info *info, int user)  	return 0;  } -static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper) +static void drm_fbdev_fb_destroy(struct fb_info *info)  { -	struct fb_info *fbi = fb_helper->info; +	struct drm_fb_helper *fb_helper = info->par;  	void *shadow = NULL;  	if (!fb_helper->dev)  		return; -	if (fbi) { -		if (fbi->fbdefio) -			fb_deferred_io_cleanup(fbi); -		if (drm_fbdev_use_shadow_fb(fb_helper)) -			shadow = fbi->screen_buffer; -	} +	if (info->fbdefio) +		fb_deferred_io_cleanup(info); +	if (drm_fbdev_use_shadow_fb(fb_helper)) +		shadow = info->screen_buffer;  	drm_fb_helper_fini(fb_helper); @@ -66,22 +64,10 @@ static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper)  		drm_client_buffer_vunmap(fb_helper->buffer);  	drm_client_framebuffer_delete(fb_helper->buffer); -} - -static void drm_fbdev_release(struct drm_fb_helper *fb_helper) -{ -	drm_fbdev_cleanup(fb_helper);  	drm_client_release(&fb_helper->client); -	kfree(fb_helper); -} -/* - * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of - * unregister_framebuffer() or fb_release(). - */ -static void drm_fbdev_fb_destroy(struct fb_info *info) -{ -	drm_fbdev_release(info->par); +	drm_fb_helper_unprepare(fb_helper); +	kfree(fb_helper);  }  static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) @@ -171,11 +157,6 @@ static const struct fb_ops drm_fbdev_fb_ops = {  	.fb_imageblit	= drm_fbdev_fb_imageblit,  }; -static struct fb_deferred_io drm_fbdev_defio = { -	.delay		= HZ / 20, -	.deferred_io	= drm_fb_helper_deferred_io, -}; -  /*   * This function uses the client API to create a framebuffer backed by a dumb buffer.   */ @@ -186,7 +167,7 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper,  	struct drm_device *dev = fb_helper->dev;  	struct drm_client_buffer *buffer;  	struct drm_framebuffer *fb; -	struct fb_info *fbi; +	struct fb_info *info;  	u32 format;  	struct iosys_map map;  	int ret; @@ -205,35 +186,41 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper,  	fb_helper->fb = buffer->fb;  	fb = buffer->fb; -	fbi = drm_fb_helper_alloc_info(fb_helper); -	if (IS_ERR(fbi)) -		return PTR_ERR(fbi); +	info = drm_fb_helper_alloc_info(fb_helper); +	if (IS_ERR(info)) +		return PTR_ERR(info); -	fbi->fbops = &drm_fbdev_fb_ops; -	fbi->screen_size = sizes->surface_height * fb->pitches[0]; -	fbi->fix.smem_len = fbi->screen_size; -	fbi->flags = FBINFO_DEFAULT; +	info->fbops = &drm_fbdev_fb_ops; +	info->screen_size = sizes->surface_height * fb->pitches[0]; +	info->fix.smem_len = info->screen_size; +	info->flags = FBINFO_DEFAULT; -	drm_fb_helper_fill_info(fbi, fb_helper, sizes); +	drm_fb_helper_fill_info(info, fb_helper, sizes);  	if (drm_fbdev_use_shadow_fb(fb_helper)) { -		fbi->screen_buffer = vzalloc(fbi->screen_size); -		if (!fbi->screen_buffer) +		info->screen_buffer = vzalloc(info->screen_size); +		if (!info->screen_buffer)  			return -ENOMEM; -		fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST; +		info->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST; + +		/* Set a default deferred I/O handler */ +		fb_helper->fbdefio.delay = HZ / 20; +		fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io; -		fbi->fbdefio = &drm_fbdev_defio; -		fb_deferred_io_init(fbi); +		info->fbdefio = &fb_helper->fbdefio; +		ret = fb_deferred_io_init(info); +		if (ret) +			return ret;  	} else {  		/* buffer is mapped for HW framebuffer */  		ret = drm_client_buffer_vmap(fb_helper->buffer, &map);  		if (ret)  			return ret;  		if (map.is_iomem) { -			fbi->screen_base = map.vaddr_iomem; +			info->screen_base = map.vaddr_iomem;  		} else { -			fbi->screen_buffer = map.vaddr; -			fbi->flags |= FBINFO_VIRTFB; +			info->screen_buffer = map.vaddr; +			info->flags |= FBINFO_VIRTFB;  		}  		/* @@ -242,10 +229,10 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper,  		 * case.  		 */  #if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM) -		if (fb_helper->hint_leak_smem_start && fbi->fix.smem_start == 0 && +		if (fb_helper->hint_leak_smem_start && info->fix.smem_start == 0 &&  		    !drm_WARN_ON_ONCE(dev, map.is_iomem)) -			fbi->fix.smem_start = -				page_to_phys(virt_to_page(fbi->screen_buffer)); +			info->fix.smem_start = +				page_to_phys(virt_to_page(info->screen_buffer));  #endif  	} @@ -362,11 +349,13 @@ static void drm_fbdev_client_unregister(struct drm_client_dev *client)  {  	struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); -	if (fb_helper->info) -		/* drm_fbdev_fb_destroy() takes care of cleanup */ +	if (fb_helper->info) {  		drm_fb_helper_unregister_info(fb_helper); -	else -		drm_fbdev_release(fb_helper); +	} else { +		drm_client_release(&fb_helper->client); +		drm_fb_helper_unprepare(fb_helper); +		kfree(fb_helper); +	}  }  static int drm_fbdev_client_restore(struct drm_client_dev *client) @@ -382,41 +371,26 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)  	struct drm_device *dev = client->dev;  	int ret; -	/* Setup is not retried if it has failed */ -	if (!fb_helper->dev && fb_helper->funcs) -		return 0; -  	if (dev->fb_helper)  		return drm_fb_helper_hotplug_event(dev->fb_helper); -	if (!dev->mode_config.num_connector) { -		drm_dbg_kms(dev, "No connectors found, will not create framebuffer!\n"); -		return 0; -	} - -	drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs); -  	ret = drm_fb_helper_init(dev, fb_helper);  	if (ret) -		goto err; +		goto err_drm_err;  	if (!drm_drv_uses_atomic_modeset(dev))  		drm_helper_disable_unused_functions(dev); -	ret = drm_fb_helper_initial_config(fb_helper, fb_helper->preferred_bpp); +	ret = drm_fb_helper_initial_config(fb_helper);  	if (ret) -		goto err_cleanup; +		goto err_drm_fb_helper_fini;  	return 0; -err_cleanup: -	drm_fbdev_cleanup(fb_helper); -err: -	fb_helper->dev = NULL; -	fb_helper->info = NULL; - +err_drm_fb_helper_fini: +	drm_fb_helper_fini(fb_helper); +err_drm_err:  	drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret); -  	return ret;  } @@ -431,7 +405,6 @@ static const struct drm_client_funcs drm_fbdev_client_funcs = {   * drm_fbdev_generic_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. @@ -466,29 +439,25 @@ void drm_fbdev_generic_setup(struct drm_device *dev,  	fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);  	if (!fb_helper)  		return; +	drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fb_helper_generic_funcs);  	ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);  	if (ret) { -		kfree(fb_helper);  		drm_err(dev, "Failed to register client: %d\n", ret); -		return; +		goto err_drm_client_init;  	} -	/* -	 * FIXME: This mixes up depth with bpp, which results in a glorious -	 * mess, resulting in some drivers picking wrong fbdev defaults and -	 * others wrong preferred_depth defaults. -	 */ -	if (!preferred_bpp) -		preferred_bpp = dev->mode_config.preferred_depth; -	if (!preferred_bpp) -		preferred_bpp = 32; -	fb_helper->preferred_bpp = preferred_bpp; -  	ret = drm_fbdev_client_hotplug(&fb_helper->client);  	if (ret)  		drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);  	drm_client_register(&fb_helper->client); + +	return; + +err_drm_client_init: +	drm_fb_helper_unprepare(fb_helper); +	kfree(fb_helper); +	return;  }  EXPORT_SYMBOL(drm_fbdev_generic_setup);  |