mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	drm-misc-next for v4.21:
Core Changes: - Merge drm_info.c into drm_debugfs.c - Complete the fake drm_crtc_commit's hw_done/flip_done sooner. - Remove deprecated drm_obj_ref/unref functions. All drivers use get/put now. - Decrease stack use of drm_gem_prime_mmap. - Improve documentation for dumb callbacks. Driver Changes: - Add edid support to virtio. - Wait on implicit fence in meson and sun4i. - Add support for BGRX8888 to sun4i. - Preparation patches for sun4i driver to start supporting linear and tiled YUV formats. - Add support for HDMI 1.4 4k modes to meson, and support for VIC alternate timings. - Drop custom dumb_map in vkms. - Small fixes and cleanups to v3d. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAlv+YOEACgkQ/lWMcqZw E8OJvw//fc+j9sJLScvrahLDNZVMh4pTvQCOySmxIPVAhjLZIkRjdvR9Ou51tbL+ qSm3tDexHEPniR8xmuTYjPZtJP6o4e4NLqUzWYdZb0U+oK3QMuJKDD3uK+6BwM8P CyAa4VxV9F17oN+d0aFpoPTHheRVt3egyvREqLHoiAJYtp01cm+f/FFKZSe+o3p/ QLi0tJ5unXg6AZFoomYbZirE/jp6t8m+cjRkYOafE57+2qpMEJ8RA5G0D1UxCgP2 imGW6n4N7rmB1bNbtTvFEDGIffE+W9AkVQkJ2YXUfQldtmUKgLA9OG47DIdDb1Xa P7RWVjHJejhvu9URcFmQcrjoCtKURPcPTuLZEQHvae1sUxwwMUvtpKUM7TBGYo2I G/nQLkMLmK9yfJRyo2OHRHTClduU3X7FXzbJhbL3cUMx0beWjCQmRDjM9ywfSJR3 lrJIlnQ3voCp0IZWj86RG0idpd3RIjE8Aaqz/m4bSmqMCqmlepnZzIpZcFB7gXbM k0xiK4LUFO1VbFsMoRaqrP1zXduY+nbLhfiDiIDs34v0ZVqNooJpLYilRI/lvmXt vzApnxgwRePW0vz67Lagqq+ZUXJXptirmGw7bnvfT90cOKlRLi5CDZTRwCOuUNPL 9kUgXj8EoX9+7p9M14TrEx9tV0MZIwbP8nlS9Ty0Kx4s240mbYg= =JNy2 -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2018-11-28' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v4.21: Core Changes: - Merge drm_info.c into drm_debugfs.c - Complete the fake drm_crtc_commit's hw_done/flip_done sooner. - Remove deprecated drm_obj_ref/unref functions. All drivers use get/put now. - Decrease stack use of drm_gem_prime_mmap. - Improve documentation for dumb callbacks. Driver Changes: - Add edid support to virtio. - Wait on implicit fence in meson and sun4i. - Add support for BGRX8888 to sun4i. - Preparation patches for sun4i driver to start supporting linear and tiled YUV formats. - Add support for HDMI 1.4 4k modes to meson, and support for VIC alternate timings. - Drop custom dumb_map in vkms. - Small fixes and cleanups to v3d. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/151a3270-b1be-ed75-bd58-6b29d741f592@linux.intel.com
This commit is contained in:
		
						commit
						61647c77cb
					
				
					 45 changed files with 703 additions and 522 deletions
				
			
		|  | @ -28,22 +28,16 @@ them, but also all the virtual ones used by KVM, so everyone qualifies). | |||
| 
 | ||||
| Contact: Daniel Vetter, Thierry Reding, respective driver maintainers | ||||
| 
 | ||||
| Switch from reference/unreference to get/put | ||||
| -------------------------------------------- | ||||
| 
 | ||||
| For some reason DRM core uses ``reference``/``unreference`` suffixes for | ||||
| refcounting functions, but kernel uses ``get``/``put`` (e.g. | ||||
| ``kref_get``/``put()``). It would be good to switch over for consistency, and | ||||
| it's shorter. Needs to be done in 3 steps for each pair of functions: | ||||
| Remove custom dumb_map_offset implementations | ||||
| --------------------------------------------- | ||||
| 
 | ||||
| * Create new ``get``/``put`` functions, define the old names as compatibility | ||||
|   wrappers | ||||
| * Switch over each file/driver using a cocci-generated spatch. | ||||
| * Once all users of the old names are gone, remove them. | ||||
| All GEM based drivers should be using drm_gem_create_mmap_offset() instead. | ||||
| Audit each individual driver, make sure it'll work with the generic | ||||
| implementation (there's lots of outdated locking leftovers in various | ||||
| implementations), and then remove it. | ||||
| 
 | ||||
| This way drivers/patches in the progress of getting merged won't break. | ||||
| 
 | ||||
| Contact: Daniel Vetter | ||||
| Contact: Daniel Vetter, respective driver maintainers | ||||
| 
 | ||||
| Convert existing KMS drivers to atomic modesetting | ||||
| -------------------------------------------------- | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \ | |||
| 		drm_scatter.o drm_pci.o \
 | ||||
| 		drm_sysfs.o drm_hashtab.o drm_mm.o \
 | ||||
| 		drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \
 | ||||
| 		drm_info.o drm_encoder_slave.o \
 | ||||
| 		drm_encoder_slave.o \
 | ||||
| 		drm_trace_points.o drm_prime.o \
 | ||||
| 		drm_rect.o drm_vma_manager.o drm_flip_work.o \
 | ||||
| 		drm_modeset_lock.o drm_atomic.o drm_bridge.o \
 | ||||
|  |  | |||
|  | @ -190,7 +190,7 @@ static int arcpgu_probe(struct platform_device *pdev) | |||
| 	arcpgu_unload(drm); | ||||
| 
 | ||||
| err_unref: | ||||
| 	drm_dev_unref(drm); | ||||
| 	drm_dev_put(drm); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  | @ -201,7 +201,7 @@ static int arcpgu_remove(struct platform_device *pdev) | |||
| 
 | ||||
| 	drm_dev_unregister(drm); | ||||
| 	arcpgu_unload(drm); | ||||
| 	drm_dev_unref(drm); | ||||
| 	drm_dev_put(drm); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -379,7 +379,7 @@ static void tc358764_detach(struct drm_bridge *bridge) | |||
| 	drm_fb_helper_remove_one_connector(drm->fb_helper, &ctx->connector); | ||||
| 	drm_panel_detach(ctx->panel); | ||||
| 	ctx->panel = NULL; | ||||
| 	drm_connector_unreference(&ctx->connector); | ||||
| 	drm_connector_put(&ctx->connector); | ||||
| } | ||||
| 
 | ||||
| static const struct drm_bridge_funcs tc358764_bridge_funcs = { | ||||
|  |  | |||
|  | @ -1460,6 +1460,9 @@ void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, | |||
| 			DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n", | ||||
| 				  crtc->base.id, crtc->name); | ||||
| 	} | ||||
| 
 | ||||
| 	if (old_state->fake_commit) | ||||
| 		complete_all(&old_state->fake_commit->flip_done); | ||||
| } | ||||
| EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done); | ||||
| 
 | ||||
|  | @ -2217,8 +2220,10 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) | |||
| 		spin_unlock(&crtc->commit_lock); | ||||
| 	} | ||||
| 
 | ||||
| 	if (old_state->fake_commit) | ||||
| 	if (old_state->fake_commit) { | ||||
| 		complete_all(&old_state->fake_commit->cleanup_done); | ||||
| 		WARN_ON(!try_wait_for_completion(&old_state->fake_commit->hw_done)); | ||||
| 	} | ||||
| } | ||||
| EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done); | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,6 +32,8 @@ | |||
| #include <drm/drm_debugfs.h> | ||||
| #include <drm/drm_edid.h> | ||||
| #include <drm/drm_atomic.h> | ||||
| #include <drm/drm_auth.h> | ||||
| #include <drm/drm_gem.h> | ||||
| #include <drm/drmP.h> | ||||
| 
 | ||||
| #include "drm_internal.h" | ||||
|  | @ -43,6 +45,93 @@ | |||
|  * Initialization, etc. | ||||
|  **************************************************/ | ||||
| 
 | ||||
| static int drm_name_info(struct seq_file *m, void *data) | ||||
| { | ||||
| 	struct drm_info_node *node = (struct drm_info_node *) m->private; | ||||
| 	struct drm_minor *minor = node->minor; | ||||
| 	struct drm_device *dev = minor->dev; | ||||
| 	struct drm_master *master; | ||||
| 
 | ||||
| 	mutex_lock(&dev->master_mutex); | ||||
| 	master = dev->master; | ||||
| 	seq_printf(m, "%s", dev->driver->name); | ||||
| 	if (dev->dev) | ||||
| 		seq_printf(m, " dev=%s", dev_name(dev->dev)); | ||||
| 	if (master && master->unique) | ||||
| 		seq_printf(m, " master=%s", master->unique); | ||||
| 	if (dev->unique) | ||||
| 		seq_printf(m, " unique=%s", dev->unique); | ||||
| 	seq_printf(m, "\n"); | ||||
| 	mutex_unlock(&dev->master_mutex); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int drm_clients_info(struct seq_file *m, void *data) | ||||
| { | ||||
| 	struct drm_info_node *node = (struct drm_info_node *) m->private; | ||||
| 	struct drm_device *dev = node->minor->dev; | ||||
| 	struct drm_file *priv; | ||||
| 	kuid_t uid; | ||||
| 
 | ||||
| 	seq_printf(m, | ||||
| 		   "%20s %5s %3s master a %5s %10s\n", | ||||
| 		   "command", | ||||
| 		   "pid", | ||||
| 		   "dev", | ||||
| 		   "uid", | ||||
| 		   "magic"); | ||||
| 
 | ||||
| 	/* dev->filelist is sorted youngest first, but we want to present
 | ||||
| 	 * oldest first (i.e. kernel, servers, clients), so walk backwardss. | ||||
| 	 */ | ||||
| 	mutex_lock(&dev->filelist_mutex); | ||||
| 	list_for_each_entry_reverse(priv, &dev->filelist, lhead) { | ||||
| 		struct task_struct *task; | ||||
| 
 | ||||
| 		rcu_read_lock(); /* locks pid_task()->comm */ | ||||
| 		task = pid_task(priv->pid, PIDTYPE_PID); | ||||
| 		uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID; | ||||
| 		seq_printf(m, "%20s %5d %3d   %c    %c %5d %10u\n", | ||||
| 			   task ? task->comm : "<unknown>", | ||||
| 			   pid_vnr(priv->pid), | ||||
| 			   priv->minor->index, | ||||
| 			   drm_is_current_master(priv) ? 'y' : 'n', | ||||
| 			   priv->authenticated ? 'y' : 'n', | ||||
| 			   from_kuid_munged(seq_user_ns(m), uid), | ||||
| 			   priv->magic); | ||||
| 		rcu_read_unlock(); | ||||
| 	} | ||||
| 	mutex_unlock(&dev->filelist_mutex); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int drm_gem_one_name_info(int id, void *ptr, void *data) | ||||
| { | ||||
| 	struct drm_gem_object *obj = ptr; | ||||
| 	struct seq_file *m = data; | ||||
| 
 | ||||
| 	seq_printf(m, "%6d %8zd %7d %8d\n", | ||||
| 		   obj->name, obj->size, | ||||
| 		   obj->handle_count, | ||||
| 		   kref_read(&obj->refcount)); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int drm_gem_name_info(struct seq_file *m, void *data) | ||||
| { | ||||
| 	struct drm_info_node *node = (struct drm_info_node *) m->private; | ||||
| 	struct drm_device *dev = node->minor->dev; | ||||
| 
 | ||||
| 	seq_printf(m, "  name     size handles refcount\n"); | ||||
| 
 | ||||
| 	mutex_lock(&dev->object_name_lock); | ||||
| 	idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); | ||||
| 	mutex_unlock(&dev->object_name_lock); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct drm_info_list drm_debugfs_list[] = { | ||||
| 	{"name", drm_name_info, 0}, | ||||
| 	{"clients", drm_clients_info, 0}, | ||||
|  |  | |||
|  | @ -704,19 +704,6 @@ void drm_dev_put(struct drm_device *dev) | |||
| } | ||||
| EXPORT_SYMBOL(drm_dev_put); | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_dev_unref - Drop reference of a DRM device | ||||
|  * @dev: device to drop reference of or NULL | ||||
|  * | ||||
|  * This is a compatibility alias for drm_dev_put() and should not be used by new | ||||
|  * code. | ||||
|  */ | ||||
| void drm_dev_unref(struct drm_device *dev) | ||||
| { | ||||
| 	drm_dev_put(dev); | ||||
| } | ||||
| EXPORT_SYMBOL(drm_dev_unref); | ||||
| 
 | ||||
| static int create_compat_control_link(struct drm_device *dev) | ||||
| { | ||||
| 	struct drm_minor *minor; | ||||
|  |  | |||
|  | @ -1,137 +0,0 @@ | |||
| /**
 | ||||
|  * \file drm_info.c | ||||
|  * DRM info file implementations | ||||
|  * | ||||
|  * \author Ben Gamari <bgamari@gmail.com> | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Created: Sun Dec 21 13:09:50 2008 by bgamari@gmail.com | ||||
|  * | ||||
|  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||||
|  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||||
|  * Copyright 2008 Ben Gamari <bgamari@gmail.com> | ||||
|  * All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice (including the next | ||||
|  * paragraph) shall be included in all copies or substantial portions of the | ||||
|  * Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | ||||
|  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||||
|  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||||
|  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||||
|  * OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/seq_file.h> | ||||
| #include <drm/drmP.h> | ||||
| #include <drm/drm_gem.h> | ||||
| 
 | ||||
| #include "drm_internal.h" | ||||
| #include "drm_legacy.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Called when "/proc/dri/.../name" is read. | ||||
|  * | ||||
|  * Prints the device name together with the bus id if available. | ||||
|  */ | ||||
| int drm_name_info(struct seq_file *m, void *data) | ||||
| { | ||||
| 	struct drm_info_node *node = (struct drm_info_node *) m->private; | ||||
| 	struct drm_minor *minor = node->minor; | ||||
| 	struct drm_device *dev = minor->dev; | ||||
| 	struct drm_master *master; | ||||
| 
 | ||||
| 	mutex_lock(&dev->master_mutex); | ||||
| 	master = dev->master; | ||||
| 	seq_printf(m, "%s", dev->driver->name); | ||||
| 	if (dev->dev) | ||||
| 		seq_printf(m, " dev=%s", dev_name(dev->dev)); | ||||
| 	if (master && master->unique) | ||||
| 		seq_printf(m, " master=%s", master->unique); | ||||
| 	if (dev->unique) | ||||
| 		seq_printf(m, " unique=%s", dev->unique); | ||||
| 	seq_printf(m, "\n"); | ||||
| 	mutex_unlock(&dev->master_mutex); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Called when "/proc/dri/.../clients" is read. | ||||
|  * | ||||
|  */ | ||||
| int drm_clients_info(struct seq_file *m, void *data) | ||||
| { | ||||
| 	struct drm_info_node *node = (struct drm_info_node *) m->private; | ||||
| 	struct drm_device *dev = node->minor->dev; | ||||
| 	struct drm_file *priv; | ||||
| 	kuid_t uid; | ||||
| 
 | ||||
| 	seq_printf(m, | ||||
| 		   "%20s %5s %3s master a %5s %10s\n", | ||||
| 		   "command", | ||||
| 		   "pid", | ||||
| 		   "dev", | ||||
| 		   "uid", | ||||
| 		   "magic"); | ||||
| 
 | ||||
| 	/* dev->filelist is sorted youngest first, but we want to present
 | ||||
| 	 * oldest first (i.e. kernel, servers, clients), so walk backwardss. | ||||
| 	 */ | ||||
| 	mutex_lock(&dev->filelist_mutex); | ||||
| 	list_for_each_entry_reverse(priv, &dev->filelist, lhead) { | ||||
| 		struct task_struct *task; | ||||
| 
 | ||||
| 		rcu_read_lock(); /* locks pid_task()->comm */ | ||||
| 		task = pid_task(priv->pid, PIDTYPE_PID); | ||||
| 		uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID; | ||||
| 		seq_printf(m, "%20s %5d %3d   %c    %c %5d %10u\n", | ||||
| 			   task ? task->comm : "<unknown>", | ||||
| 			   pid_vnr(priv->pid), | ||||
| 			   priv->minor->index, | ||||
| 			   drm_is_current_master(priv) ? 'y' : 'n', | ||||
| 			   priv->authenticated ? 'y' : 'n', | ||||
| 			   from_kuid_munged(seq_user_ns(m), uid), | ||||
| 			   priv->magic); | ||||
| 		rcu_read_unlock(); | ||||
| 	} | ||||
| 	mutex_unlock(&dev->filelist_mutex); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int drm_gem_one_name_info(int id, void *ptr, void *data) | ||||
| { | ||||
| 	struct drm_gem_object *obj = ptr; | ||||
| 	struct seq_file *m = data; | ||||
| 
 | ||||
| 	seq_printf(m, "%6d %8zd %7d %8d\n", | ||||
| 		   obj->name, obj->size, | ||||
| 		   obj->handle_count, | ||||
| 		   kref_read(&obj->refcount)); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int drm_gem_name_info(struct seq_file *m, void *data) | ||||
| { | ||||
| 	struct drm_info_node *node = (struct drm_info_node *) m->private; | ||||
| 	struct drm_device *dev = node->minor->dev; | ||||
| 
 | ||||
| 	seq_printf(m, "  name     size handles refcount\n"); | ||||
| 
 | ||||
| 	mutex_lock(&dev->object_name_lock); | ||||
| 	idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); | ||||
| 	mutex_unlock(&dev->object_name_lock); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -56,11 +56,6 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr | |||
| struct drm_minor *drm_minor_acquire(unsigned int minor_id); | ||||
| void drm_minor_release(struct drm_minor *minor); | ||||
| 
 | ||||
| /* drm_info.c */ | ||||
| int drm_name_info(struct seq_file *m, void *data); | ||||
| int drm_clients_info(struct seq_file *m, void* data); | ||||
| int drm_gem_name_info(struct seq_file *m, void *data); | ||||
| 
 | ||||
| /* drm_vblank.c */ | ||||
| void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe); | ||||
| void drm_vblank_cleanup(struct drm_device *dev); | ||||
|  |  | |||
|  | @ -663,24 +663,33 @@ EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); | |||
|  */ | ||||
| int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) | ||||
| { | ||||
| 	/* Used by drm_gem_mmap() to lookup the GEM object */ | ||||
| 	struct drm_file priv = { | ||||
| 		.minor = obj->dev->primary, | ||||
| 	}; | ||||
| 	struct file fil = { | ||||
| 		.private_data = &priv, | ||||
| 	}; | ||||
| 	struct drm_file *priv; | ||||
| 	struct file *fil; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	ret = drm_vma_node_allow(&obj->vma_node, &priv); | ||||
| 	priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||||
| 	fil = kzalloc(sizeof(*fil), GFP_KERNEL); | ||||
| 	if (!priv || !fil) { | ||||
| 		ret = -ENOMEM; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Used by drm_gem_mmap() to lookup the GEM object */ | ||||
| 	priv->minor = obj->dev->primary; | ||||
| 	fil->private_data = priv; | ||||
| 
 | ||||
| 	ret = drm_vma_node_allow(&obj->vma_node, priv); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 		goto out; | ||||
| 
 | ||||
| 	vma->vm_pgoff += drm_vma_node_start(&obj->vma_node); | ||||
| 
 | ||||
| 	ret = obj->dev->driver->fops->mmap(&fil, vma); | ||||
| 	ret = obj->dev->driver->fops->mmap(fil, vma); | ||||
| 
 | ||||
| 	drm_vma_node_revoke(&obj->vma_node, &priv); | ||||
| 	drm_vma_node_revoke(&obj->vma_node, priv); | ||||
| out: | ||||
| 	kfree(priv); | ||||
| 	kfree(fil); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  |  | |||
|  | @ -550,7 +550,7 @@ static int etnaviv_bind(struct device *dev) | |||
| out_bind: | ||||
| 	kfree(priv); | ||||
| out_unref: | ||||
| 	drm_dev_unref(drm); | ||||
| 	drm_dev_put(drm); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  | @ -567,7 +567,7 @@ static void etnaviv_unbind(struct device *dev) | |||
| 	drm->dev_private = NULL; | ||||
| 	kfree(priv); | ||||
| 
 | ||||
| 	drm_dev_unref(drm); | ||||
| 	drm_dev_put(drm); | ||||
| } | ||||
| 
 | ||||
| static const struct component_master_ops etnaviv_master_ops = { | ||||
|  |  | |||
|  | @ -594,17 +594,7 @@ dw_hdmi_mode_valid(struct drm_connector *connector, | |||
| 	dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__, | ||||
| 		vclk_freq, venc_freq, hdmi_freq); | ||||
| 
 | ||||
| 	/* Finally filter by configurable vclk frequencies for VIC modes */ | ||||
| 	switch (vclk_freq) { | ||||
| 	case 54000: | ||||
| 	case 74250: | ||||
| 	case 148500: | ||||
| 	case 297000: | ||||
| 	case 594000: | ||||
| 		return MODE_OK; | ||||
| 	} | ||||
| 
 | ||||
| 	return MODE_CLOCK_RANGE; | ||||
| 	return meson_vclk_vic_supported_freq(vclk_freq); | ||||
| } | ||||
| 
 | ||||
| /* Encoder */ | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ | |||
| #include <drm/drm_plane_helper.h> | ||||
| #include <drm/drm_gem_cma_helper.h> | ||||
| #include <drm/drm_fb_cma_helper.h> | ||||
| #include <drm/drm_gem_framebuffer_helper.h> | ||||
| #include <drm/drm_rect.h> | ||||
| 
 | ||||
| #include "meson_overlay.h" | ||||
|  | @ -532,6 +533,7 @@ static const struct drm_plane_helper_funcs meson_overlay_helper_funcs = { | |||
| 	.atomic_check	= meson_overlay_atomic_check, | ||||
| 	.atomic_disable	= meson_overlay_atomic_disable, | ||||
| 	.atomic_update	= meson_overlay_atomic_update, | ||||
| 	.prepare_fb	= drm_gem_fb_prepare_fb, | ||||
| }; | ||||
| 
 | ||||
| static const struct drm_plane_funcs meson_overlay_funcs = { | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ | |||
| #include <drm/drm_plane_helper.h> | ||||
| #include <drm/drm_gem_cma_helper.h> | ||||
| #include <drm/drm_fb_cma_helper.h> | ||||
| #include <drm/drm_gem_framebuffer_helper.h> | ||||
| #include <drm/drm_rect.h> | ||||
| 
 | ||||
| #include "meson_plane.h" | ||||
|  | @ -322,6 +323,7 @@ static const struct drm_plane_helper_funcs meson_plane_helper_funcs = { | |||
| 	.atomic_check	= meson_plane_atomic_check, | ||||
| 	.atomic_disable	= meson_plane_atomic_disable, | ||||
| 	.atomic_update	= meson_plane_atomic_update, | ||||
| 	.prepare_fb	= drm_gem_fb_prepare_fb, | ||||
| }; | ||||
| 
 | ||||
| static const struct drm_plane_funcs meson_plane_funcs = { | ||||
|  |  | |||
|  | @ -117,6 +117,8 @@ | |||
| #define HDMI_PLL_RESET		BIT(28) | ||||
| #define HDMI_PLL_LOCK		BIT(31) | ||||
| 
 | ||||
| #define FREQ_1000_1001(_freq)	DIV_ROUND_CLOSEST(_freq * 1000, 1001) | ||||
| 
 | ||||
| /* VID PLL Dividers */ | ||||
| enum { | ||||
| 	VID_PLL_DIV_1 = 0, | ||||
|  | @ -323,7 +325,7 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv) | |||
| enum { | ||||
| /* PLL	O1 O2 O3 VP DV     EN TX */ | ||||
| /* 4320 /4 /4 /1 /5 /1  => /2 /2 */ | ||||
| 	MESON_VCLK_HDMI_ENCI_54000 = 1, | ||||
| 	MESON_VCLK_HDMI_ENCI_54000 = 0, | ||||
| /* 4320 /4 /4 /1 /5 /1  => /1 /2 */ | ||||
| 	MESON_VCLK_HDMI_DDR_54000, | ||||
| /* 2970 /4 /1 /1 /5 /1  => /1 /2 */ | ||||
|  | @ -339,6 +341,7 @@ enum { | |||
| }; | ||||
| 
 | ||||
| struct meson_vclk_params { | ||||
| 	unsigned int pixel_freq; | ||||
| 	unsigned int pll_base_freq; | ||||
| 	unsigned int pll_od1; | ||||
| 	unsigned int pll_od2; | ||||
|  | @ -347,6 +350,7 @@ struct meson_vclk_params { | |||
| 	unsigned int vclk_div; | ||||
| } params[] = { | ||||
| 	[MESON_VCLK_HDMI_ENCI_54000] = { | ||||
| 		.pixel_freq = 54000, | ||||
| 		.pll_base_freq = 4320000, | ||||
| 		.pll_od1 = 4, | ||||
| 		.pll_od2 = 4, | ||||
|  | @ -355,6 +359,7 @@ struct meson_vclk_params { | |||
| 		.vclk_div = 1, | ||||
| 	}, | ||||
| 	[MESON_VCLK_HDMI_DDR_54000] = { | ||||
| 		.pixel_freq = 54000, | ||||
| 		.pll_base_freq = 4320000, | ||||
| 		.pll_od1 = 4, | ||||
| 		.pll_od2 = 4, | ||||
|  | @ -363,6 +368,7 @@ struct meson_vclk_params { | |||
| 		.vclk_div = 1, | ||||
| 	}, | ||||
| 	[MESON_VCLK_HDMI_DDR_148500] = { | ||||
| 		.pixel_freq = 148500, | ||||
| 		.pll_base_freq = 2970000, | ||||
| 		.pll_od1 = 4, | ||||
| 		.pll_od2 = 1, | ||||
|  | @ -371,6 +377,7 @@ struct meson_vclk_params { | |||
| 		.vclk_div = 1, | ||||
| 	}, | ||||
| 	[MESON_VCLK_HDMI_74250] = { | ||||
| 		.pixel_freq = 74250, | ||||
| 		.pll_base_freq = 2970000, | ||||
| 		.pll_od1 = 2, | ||||
| 		.pll_od2 = 2, | ||||
|  | @ -379,6 +386,7 @@ struct meson_vclk_params { | |||
| 		.vclk_div = 1, | ||||
| 	}, | ||||
| 	[MESON_VCLK_HDMI_148500] = { | ||||
| 		.pixel_freq = 148500, | ||||
| 		.pll_base_freq = 2970000, | ||||
| 		.pll_od1 = 1, | ||||
| 		.pll_od2 = 2, | ||||
|  | @ -387,6 +395,7 @@ struct meson_vclk_params { | |||
| 		.vclk_div = 1, | ||||
| 	}, | ||||
| 	[MESON_VCLK_HDMI_297000] = { | ||||
| 		.pixel_freq = 297000, | ||||
| 		.pll_base_freq = 2970000, | ||||
| 		.pll_od1 = 1, | ||||
| 		.pll_od2 = 1, | ||||
|  | @ -395,6 +404,7 @@ struct meson_vclk_params { | |||
| 		.vclk_div = 2, | ||||
| 	}, | ||||
| 	[MESON_VCLK_HDMI_594000] = { | ||||
| 		.pixel_freq = 594000, | ||||
| 		.pll_base_freq = 5940000, | ||||
| 		.pll_od1 = 1, | ||||
| 		.pll_od2 = 1, | ||||
|  | @ -402,6 +412,7 @@ struct meson_vclk_params { | |||
| 		.vid_pll_div = VID_PLL_DIV_5, | ||||
| 		.vclk_div = 1, | ||||
| 	}, | ||||
| 	{ /* sentinel */ }, | ||||
| }; | ||||
| 
 | ||||
| static inline unsigned int pll_od_to_reg(unsigned int od) | ||||
|  | @ -626,12 +637,37 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv, | |||
| 		  pll_freq); | ||||
| } | ||||
| 
 | ||||
| enum drm_mode_status | ||||
| meson_vclk_vic_supported_freq(unsigned int freq) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	DRM_DEBUG_DRIVER("freq = %d\n", freq); | ||||
| 
 | ||||
| 	for (i = 0 ; params[i].pixel_freq ; ++i) { | ||||
| 		DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n", | ||||
| 				 i, params[i].pixel_freq, | ||||
| 				 FREQ_1000_1001(params[i].pixel_freq)); | ||||
| 		/* Match strict frequency */ | ||||
| 		if (freq == params[i].pixel_freq) | ||||
| 			return MODE_OK; | ||||
| 		/* Match 1000/1001 variant */ | ||||
| 		if (freq == FREQ_1000_1001(params[i].pixel_freq)) | ||||
| 			return MODE_OK; | ||||
| 	} | ||||
| 
 | ||||
| 	return MODE_CLOCK_RANGE; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq); | ||||
| 
 | ||||
| static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq, | ||||
| 			   unsigned int od1, unsigned int od2, unsigned int od3, | ||||
| 			   unsigned int vid_pll_div, unsigned int vclk_div, | ||||
| 			   unsigned int hdmi_tx_div, unsigned int venc_div, | ||||
| 			   bool hdmi_use_enci) | ||||
| 			   bool hdmi_use_enci, bool vic_alternate_clock) | ||||
| { | ||||
| 	unsigned int m = 0, frac = 0; | ||||
| 
 | ||||
| 	/* Set HDMI-TX sys clock */ | ||||
| 	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, | ||||
| 			   CTS_HDMI_SYS_SEL_MASK, 0); | ||||
|  | @ -646,34 +682,38 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq, | |||
| 	} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) { | ||||
| 		switch (pll_base_freq) { | ||||
| 		case 2970000: | ||||
| 			meson_hdmi_pll_set_params(priv, 0x3d, 0xe00, | ||||
| 						  od1, od2, od3); | ||||
| 			m = 0x3d; | ||||
| 			frac = vic_alternate_clock ? 0xd02 : 0xe00; | ||||
| 			break; | ||||
| 		case 4320000: | ||||
| 			meson_hdmi_pll_set_params(priv, 0x5a, 0, | ||||
| 						  od1, od2, od3); | ||||
| 			m = vic_alternate_clock ? 0x59 : 0x5a; | ||||
| 			frac = vic_alternate_clock ? 0xe8f : 0; | ||||
| 			break; | ||||
| 		case 5940000: | ||||
| 			meson_hdmi_pll_set_params(priv, 0x7b, 0xc00, | ||||
| 						  od1, od2, od3); | ||||
| 			m = 0x7b; | ||||
| 			frac = vic_alternate_clock ? 0xa05 : 0xc00; | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3); | ||||
| 	} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || | ||||
| 		   meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { | ||||
| 		switch (pll_base_freq) { | ||||
| 		case 2970000: | ||||
| 			meson_hdmi_pll_set_params(priv, 0x7b, 0x300, | ||||
| 						  od1, od2, od3); | ||||
| 			m = 0x7b; | ||||
| 			frac = vic_alternate_clock ? 0x281 : 0x300; | ||||
| 			break; | ||||
| 		case 4320000: | ||||
| 			meson_hdmi_pll_set_params(priv, 0xb4, 0, | ||||
| 						  od1, od2, od3); | ||||
| 			m = vic_alternate_clock ? 0xb3 : 0xb4; | ||||
| 			frac = vic_alternate_clock ? 0x347 : 0; | ||||
| 			break; | ||||
| 		case 5940000: | ||||
| 			meson_hdmi_pll_set_params(priv, 0xf7, 0x200, | ||||
| 						  od1, od2, od3); | ||||
| 			m = 0xf7; | ||||
| 			frac = vic_alternate_clock ? 0x102 : 0x200; | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Setup vid_pll divider */ | ||||
|  | @ -826,6 +866,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, | |||
| 		      unsigned int vclk_freq, unsigned int venc_freq, | ||||
| 		      unsigned int dac_freq, bool hdmi_use_enci) | ||||
| { | ||||
| 	bool vic_alternate_clock = false; | ||||
| 	unsigned int freq; | ||||
| 	unsigned int hdmi_tx_div; | ||||
| 	unsigned int venc_div; | ||||
|  | @ -843,7 +884,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, | |||
| 		 * - encp encoder | ||||
| 		 */ | ||||
| 		meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0, | ||||
| 			       VID_PLL_DIV_5, 2, 1, 1, false); | ||||
| 			       VID_PLL_DIV_5, 2, 1, 1, false, false); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -863,31 +904,35 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	switch (vclk_freq) { | ||||
| 	case 54000: | ||||
| 		if (hdmi_use_enci) | ||||
| 			freq = MESON_VCLK_HDMI_ENCI_54000; | ||||
| 		else | ||||
| 			freq = MESON_VCLK_HDMI_DDR_54000; | ||||
| 		break; | ||||
| 	case 74250: | ||||
| 		freq = MESON_VCLK_HDMI_74250; | ||||
| 		break; | ||||
| 	case 148500: | ||||
| 		if (dac_freq != 148500) | ||||
| 			freq = MESON_VCLK_HDMI_DDR_148500; | ||||
| 		else | ||||
| 			freq = MESON_VCLK_HDMI_148500; | ||||
| 		break; | ||||
| 	case 297000: | ||||
| 		freq = MESON_VCLK_HDMI_297000; | ||||
| 		break; | ||||
| 	case 594000: | ||||
| 		freq = MESON_VCLK_HDMI_594000; | ||||
| 		break; | ||||
| 	default: | ||||
| 		pr_err("Fatal Error, invalid HDMI vclk freq %d\n", | ||||
| 		       vclk_freq); | ||||
| 	for (freq = 0 ; params[freq].pixel_freq ; ++freq) { | ||||
| 		if (vclk_freq == params[freq].pixel_freq || | ||||
| 		    vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) { | ||||
| 			if (vclk_freq != params[freq].pixel_freq) | ||||
| 				vic_alternate_clock = true; | ||||
| 			else | ||||
| 				vic_alternate_clock = false; | ||||
| 
 | ||||
| 			if (freq == MESON_VCLK_HDMI_ENCI_54000 && | ||||
| 			    !hdmi_use_enci) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (freq == MESON_VCLK_HDMI_DDR_54000 && | ||||
| 			    hdmi_use_enci) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (freq == MESON_VCLK_HDMI_DDR_148500 && | ||||
| 			    dac_freq == vclk_freq) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (freq == MESON_VCLK_HDMI_148500 && | ||||
| 			    dac_freq != vclk_freq) | ||||
| 				continue; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (!params[freq].pixel_freq) { | ||||
| 		pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -895,6 +940,6 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, | |||
| 		       params[freq].pll_od1, params[freq].pll_od2, | ||||
| 		       params[freq].pll_od3, params[freq].vid_pll_div, | ||||
| 		       params[freq].vclk_div, hdmi_tx_div, venc_div, | ||||
| 		       hdmi_use_enci); | ||||
| 		       hdmi_use_enci, vic_alternate_clock); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(meson_vclk_setup); | ||||
|  |  | |||
|  | @ -32,6 +32,8 @@ enum { | |||
| 
 | ||||
| enum drm_mode_status | ||||
| meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq); | ||||
| enum drm_mode_status | ||||
| meson_vclk_vic_supported_freq(unsigned int freq); | ||||
| 
 | ||||
| void meson_vclk_setup(struct meson_drm *priv, unsigned int target, | ||||
| 		      unsigned int vclk_freq, unsigned int venc_freq, | ||||
|  |  | |||
|  | @ -697,6 +697,132 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = { | |||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = { | ||||
| 	.encp = { | ||||
| 		.dvi_settings = 0x1, | ||||
| 		.video_mode = 0x4040, | ||||
| 		.video_mode_adv = 0x8, | ||||
| 		/* video_sync_mode */ | ||||
| 		/* video_yc_dly */ | ||||
| 		/* video_rgb_ctrl */ | ||||
| 		.video_filt_ctrl = 0x1000, | ||||
| 		.video_filt_ctrl_present = true, | ||||
| 		/* video_ofld_voav_ofst */ | ||||
| 		.yfp1_htime = 140, | ||||
| 		.yfp2_htime = 140+3840, | ||||
| 		.max_pxcnt = 3840+1660-1, | ||||
| 		.hspuls_begin = 2156+1920, | ||||
| 		.hspuls_end = 44, | ||||
| 		.hspuls_switch = 44, | ||||
| 		.vspuls_begin = 140, | ||||
| 		.vspuls_end = 2059+1920, | ||||
| 		.vspuls_bline = 0, | ||||
| 		.vspuls_eline = 4, | ||||
| 		.havon_begin = 148, | ||||
| 		.havon_end = 3987, | ||||
| 		.vavon_bline = 89, | ||||
| 		.vavon_eline = 2248, | ||||
| 		/* eqpuls_begin */ | ||||
| 		/* eqpuls_end */ | ||||
| 		/* eqpuls_bline */ | ||||
| 		/* eqpuls_eline */ | ||||
| 		.hso_begin = 44, | ||||
| 		.hso_end = 2156+1920, | ||||
| 		.vso_begin = 2100+1920, | ||||
| 		.vso_end = 2164+1920, | ||||
| 		.vso_bline = 51, | ||||
| 		.vso_eline = 53, | ||||
| 		.vso_eline_present = true, | ||||
| 		/* sy_val */ | ||||
| 		/* sy2_val */ | ||||
| 		.max_lncnt = 2249, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = { | ||||
| 	.encp = { | ||||
| 		.dvi_settings = 0x1, | ||||
| 		.video_mode = 0x4040, | ||||
| 		.video_mode_adv = 0x8, | ||||
| 		/* video_sync_mode */ | ||||
| 		/* video_yc_dly */ | ||||
| 		/* video_rgb_ctrl */ | ||||
| 		.video_filt_ctrl = 0x1000, | ||||
| 		.video_filt_ctrl_present = true, | ||||
| 		/* video_ofld_voav_ofst */ | ||||
| 		.yfp1_htime = 140, | ||||
| 		.yfp2_htime = 140+3840, | ||||
| 		.max_pxcnt = 3840+1440-1, | ||||
| 		.hspuls_begin = 2156+1920, | ||||
| 		.hspuls_end = 44, | ||||
| 		.hspuls_switch = 44, | ||||
| 		.vspuls_begin = 140, | ||||
| 		.vspuls_end = 2059+1920, | ||||
| 		.vspuls_bline = 0, | ||||
| 		.vspuls_eline = 4, | ||||
| 		.havon_begin = 148, | ||||
| 		.havon_end = 3987, | ||||
| 		.vavon_bline = 89, | ||||
| 		.vavon_eline = 2248, | ||||
| 		/* eqpuls_begin */ | ||||
| 		/* eqpuls_end */ | ||||
| 		/* eqpuls_bline */ | ||||
| 		/* eqpuls_eline */ | ||||
| 		.hso_begin = 44, | ||||
| 		.hso_end = 2156+1920, | ||||
| 		.vso_begin = 2100+1920, | ||||
| 		.vso_end = 2164+1920, | ||||
| 		.vso_bline = 51, | ||||
| 		.vso_eline = 53, | ||||
| 		.vso_eline_present = true, | ||||
| 		/* sy_val */ | ||||
| 		/* sy2_val */ | ||||
| 		.max_lncnt = 2249, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = { | ||||
| 	.encp = { | ||||
| 		.dvi_settings = 0x1, | ||||
| 		.video_mode = 0x4040, | ||||
| 		.video_mode_adv = 0x8, | ||||
| 		/* video_sync_mode */ | ||||
| 		/* video_yc_dly */ | ||||
| 		/* video_rgb_ctrl */ | ||||
| 		.video_filt_ctrl = 0x1000, | ||||
| 		.video_filt_ctrl_present = true, | ||||
| 		/* video_ofld_voav_ofst */ | ||||
| 		.yfp1_htime = 140, | ||||
| 		.yfp2_htime = 140+3840, | ||||
| 		.max_pxcnt = 3840+560-1, | ||||
| 		.hspuls_begin = 2156+1920, | ||||
| 		.hspuls_end = 44, | ||||
| 		.hspuls_switch = 44, | ||||
| 		.vspuls_begin = 140, | ||||
| 		.vspuls_end = 2059+1920, | ||||
| 		.vspuls_bline = 0, | ||||
| 		.vspuls_eline = 4, | ||||
| 		.havon_begin = 148, | ||||
| 		.havon_end = 3987, | ||||
| 		.vavon_bline = 89, | ||||
| 		.vavon_eline = 2248, | ||||
| 		/* eqpuls_begin */ | ||||
| 		/* eqpuls_end */ | ||||
| 		/* eqpuls_bline */ | ||||
| 		/* eqpuls_eline */ | ||||
| 		.hso_begin = 44, | ||||
| 		.hso_end = 2156+1920, | ||||
| 		.vso_begin = 2100+1920, | ||||
| 		.vso_end = 2164+1920, | ||||
| 		.vso_bline = 51, | ||||
| 		.vso_eline = 53, | ||||
| 		.vso_eline_present = true, | ||||
| 		/* sy_val */ | ||||
| 		/* sy2_val */ | ||||
| 		.max_lncnt = 2249, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| struct meson_hdmi_venc_vic_mode { | ||||
| 	unsigned int vic; | ||||
| 	union meson_hdmi_venc_mode *mode; | ||||
|  | @ -717,6 +843,9 @@ struct meson_hdmi_venc_vic_mode { | |||
| 	{ 34, &meson_hdmi_encp_mode_1080p30 }, | ||||
| 	{ 31, &meson_hdmi_encp_mode_1080p50 }, | ||||
| 	{ 16, &meson_hdmi_encp_mode_1080p60 }, | ||||
| 	{ 93, &meson_hdmi_encp_mode_2160p24 }, | ||||
| 	{ 94, &meson_hdmi_encp_mode_2160p25 }, | ||||
| 	{ 95, &meson_hdmi_encp_mode_2160p30 }, | ||||
| 	{ 0, NULL}, /* sentinel */ | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -417,7 +417,7 @@ static int mxsfb_probe(struct platform_device *pdev) | |||
| err_unload: | ||||
| 	mxsfb_unload(drm); | ||||
| err_free: | ||||
| 	drm_dev_unref(drm); | ||||
| 	drm_dev_put(drm); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  | @ -428,7 +428,7 @@ static int mxsfb_remove(struct platform_device *pdev) | |||
| 
 | ||||
| 	drm_dev_unregister(drm); | ||||
| 	mxsfb_unload(drm); | ||||
| 	drm_dev_unref(drm); | ||||
| 	drm_dev_put(drm); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -48,8 +48,12 @@ static const u32 sunxi_rgb2yuv_coef[12] = { | |||
| /*
 | ||||
|  * These coefficients are taken from the A33 BSP from Allwinner. | ||||
|  * | ||||
|  * The formula is for each component, each coefficient being multiplied by | ||||
|  * 1024 and each constant being multiplied by 16: | ||||
|  * The first three values of each row are coded as 13-bit signed fixed-point | ||||
|  * numbers, with 10 bits for the fractional part. The fourth value is a | ||||
|  * constant coded as a 14-bit signed fixed-point number with 4 bits for the | ||||
|  * fractional part. | ||||
|  * | ||||
|  * The values in table order give the following colorspace translation: | ||||
|  * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135 | ||||
|  * R = 1.164 * Y + 1.596 * V - 222 | ||||
|  * B = 1.164 * Y + 2.018 * U + 276 | ||||
|  | @ -155,6 +159,36 @@ static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const uint32_t sun4i_backend_formats[] = { | ||||
| 	DRM_FORMAT_ARGB1555, | ||||
| 	DRM_FORMAT_ARGB4444, | ||||
| 	DRM_FORMAT_ARGB8888, | ||||
| 	DRM_FORMAT_BGRX8888, | ||||
| 	DRM_FORMAT_RGB565, | ||||
| 	DRM_FORMAT_RGB888, | ||||
| 	DRM_FORMAT_RGBA4444, | ||||
| 	DRM_FORMAT_RGBA5551, | ||||
| 	DRM_FORMAT_UYVY, | ||||
| 	DRM_FORMAT_VYUY, | ||||
| 	DRM_FORMAT_XRGB8888, | ||||
| 	DRM_FORMAT_YUYV, | ||||
| 	DRM_FORMAT_YVYU, | ||||
| }; | ||||
| 
 | ||||
| bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier) | ||||
| { | ||||
| 	unsigned int i; | ||||
| 
 | ||||
| 	if (modifier != DRM_FORMAT_MOD_LINEAR) | ||||
| 		return false; | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(sun4i_backend_formats); i++) | ||||
| 		if (sun4i_backend_formats[i] == fmt) | ||||
| 			return true; | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, | ||||
| 				     int layer, struct drm_plane *plane) | ||||
| { | ||||
|  | @ -395,6 +429,15 @@ int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer, | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void sun4i_backend_cleanup_layer(struct sun4i_backend *backend, | ||||
| 				 int layer) | ||||
| { | ||||
| 	regmap_update_bits(backend->engine.regs, | ||||
| 			   SUN4I_BACKEND_ATTCTL_REG0(layer), | ||||
| 			   SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN | | ||||
| 			   SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0); | ||||
| } | ||||
| 
 | ||||
| static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state) | ||||
| { | ||||
| 	u16 src_h = state->src_h >> 16; | ||||
|  | @ -413,11 +456,50 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) | |||
| { | ||||
| 	struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); | ||||
| 	struct sun4i_backend *backend = layer->backend; | ||||
| 	uint32_t format = state->fb->format->format; | ||||
| 	uint64_t modifier = state->fb->modifier; | ||||
| 
 | ||||
| 	if (IS_ERR(backend->frontend)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	return sun4i_backend_plane_uses_scaler(state); | ||||
| 	if (!sun4i_frontend_format_is_supported(format, modifier)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (!sun4i_backend_format_is_supported(format, modifier)) | ||||
| 		return true; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * TODO: The backend alone allows 2x and 4x integer scaling, including | ||||
| 	 * support for an alpha component (which the frontend doesn't support). | ||||
| 	 * Use the backend directly instead of the frontend in this case, with | ||||
| 	 * another test to return false. | ||||
| 	 */ | ||||
| 
 | ||||
| 	if (sun4i_backend_plane_uses_scaler(state)) | ||||
| 		return true; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Here the format is supported by both the frontend and the backend | ||||
| 	 * and no frontend scaling is required, so use the backend directly. | ||||
| 	 */ | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static bool sun4i_backend_plane_is_supported(struct drm_plane_state *state, | ||||
| 					     bool *uses_frontend) | ||||
| { | ||||
| 	if (sun4i_backend_plane_uses_frontend(state)) { | ||||
| 		*uses_frontend = true; | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	*uses_frontend = false; | ||||
| 
 | ||||
| 	/* Scaling is not supported without the frontend. */ | ||||
| 	if (sun4i_backend_plane_uses_scaler(state)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void sun4i_backend_atomic_begin(struct sunxi_engine *engine, | ||||
|  | @ -460,14 +542,19 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, | |||
| 		struct drm_framebuffer *fb = plane_state->fb; | ||||
| 		struct drm_format_name_buf format_name; | ||||
| 
 | ||||
| 		if (sun4i_backend_plane_uses_frontend(plane_state)) { | ||||
| 		if (!sun4i_backend_plane_is_supported(plane_state, | ||||
| 						      &layer_state->uses_frontend)) | ||||
| 			return -EINVAL; | ||||
| 
 | ||||
| 		if (layer_state->uses_frontend) { | ||||
| 			DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", | ||||
| 					 plane->index); | ||||
| 
 | ||||
| 			layer_state->uses_frontend = true; | ||||
| 			num_frontend_planes++; | ||||
| 		} else { | ||||
| 			layer_state->uses_frontend = false; | ||||
| 			if (fb->format->is_yuv) { | ||||
| 				DRM_DEBUG_DRIVER("Plane FB format is YUV\n"); | ||||
| 				num_yuv_planes++; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		DRM_DEBUG_DRIVER("Plane FB format is %s\n", | ||||
|  | @ -476,11 +563,6 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, | |||
| 		if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE)) | ||||
| 			num_alpha_planes++; | ||||
| 
 | ||||
| 		if (fb->format->is_yuv) { | ||||
| 			DRM_DEBUG_DRIVER("Plane FB format is YUV\n"); | ||||
| 			num_yuv_planes++; | ||||
| 		} | ||||
| 
 | ||||
| 		DRM_DEBUG_DRIVER("Plane zpos is %d\n", | ||||
| 				 plane_state->normalized_zpos); | ||||
| 
 | ||||
|  |  | |||
|  | @ -198,6 +198,7 @@ engine_to_sun4i_backend(struct sunxi_engine *engine) | |||
| 
 | ||||
| void sun4i_backend_layer_enable(struct sun4i_backend *backend, | ||||
| 				int layer, bool enable); | ||||
| bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier); | ||||
| int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, | ||||
| 				     int layer, struct drm_plane *plane); | ||||
| int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, | ||||
|  | @ -208,5 +209,7 @@ int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend, | |||
| 					int layer, uint32_t in_fmt); | ||||
| int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, | ||||
| 				    int layer, struct drm_plane *plane); | ||||
| void sun4i_backend_cleanup_layer(struct sun4i_backend *backend, | ||||
| 				 int layer); | ||||
| 
 | ||||
| #endif /* _SUN4I_BACKEND_H_ */ | ||||
|  |  | |||
|  | @ -28,6 +28,16 @@ | |||
| #include "sun4i_tcon.h" | ||||
| #include "sun8i_tcon_top.h" | ||||
| 
 | ||||
| static int drm_sun4i_gem_dumb_create(struct drm_file *file_priv, | ||||
| 				     struct drm_device *drm, | ||||
| 				     struct drm_mode_create_dumb *args) | ||||
| { | ||||
| 	/* The hardware only allows even pitches for YUV buffers. */ | ||||
| 	args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), 2); | ||||
| 
 | ||||
| 	return drm_gem_cma_dumb_create_internal(file_priv, drm, args); | ||||
| } | ||||
| 
 | ||||
| DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); | ||||
| 
 | ||||
| static struct drm_driver sun4i_drv_driver = { | ||||
|  | @ -42,7 +52,7 @@ static struct drm_driver sun4i_drv_driver = { | |||
| 	.minor			= 0, | ||||
| 
 | ||||
| 	/* GEM Operations */ | ||||
| 	.dumb_create		= drm_gem_cma_dumb_create, | ||||
| 	.dumb_create		= drm_sun4i_gem_dumb_create, | ||||
| 	.gem_free_object_unlocked = drm_gem_cma_free_object, | ||||
| 	.gem_vm_ops		= &drm_gem_cma_vm_ops, | ||||
| 
 | ||||
|  |  | |||
|  | @ -107,8 +107,34 @@ EXPORT_SYMBOL(sun4i_frontend_update_buffer); | |||
| static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) | ||||
| { | ||||
| 	switch (fmt) { | ||||
| 	case DRM_FORMAT_ARGB8888: | ||||
| 		*val = 5; | ||||
| 	case DRM_FORMAT_XRGB8888: | ||||
| 		*val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB; | ||||
| 		return 0; | ||||
| 
 | ||||
| 	default: | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val) | ||||
| { | ||||
| 	if (drm_format_num_planes(fmt) == 1) | ||||
| 		*val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED; | ||||
| 	else | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val) | ||||
| { | ||||
| 	switch (fmt) { | ||||
| 	case DRM_FORMAT_BGRX8888: | ||||
| 		*val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX; | ||||
| 		return 0; | ||||
| 
 | ||||
| 	case DRM_FORMAT_XRGB8888: | ||||
| 		*val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB; | ||||
| 		return 0; | ||||
| 
 | ||||
| 	default: | ||||
|  | @ -119,9 +145,12 @@ static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) | |||
| static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) | ||||
| { | ||||
| 	switch (fmt) { | ||||
| 	case DRM_FORMAT_BGRX8888: | ||||
| 		*val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888; | ||||
| 		return 0; | ||||
| 
 | ||||
| 	case DRM_FORMAT_XRGB8888: | ||||
| 	case DRM_FORMAT_ARGB8888: | ||||
| 		*val = 2; | ||||
| 		*val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888; | ||||
| 		return 0; | ||||
| 
 | ||||
| 	default: | ||||
|  | @ -129,22 +158,54 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static const uint32_t sun4i_frontend_formats[] = { | ||||
| 	DRM_FORMAT_BGRX8888, | ||||
| 	DRM_FORMAT_XRGB8888, | ||||
| }; | ||||
| 
 | ||||
| bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier) | ||||
| { | ||||
| 	unsigned int i; | ||||
| 
 | ||||
| 	if (modifier != DRM_FORMAT_MOD_LINEAR) | ||||
| 		return false; | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++) | ||||
| 		if (sun4i_frontend_formats[i] == fmt) | ||||
| 			return true; | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| EXPORT_SYMBOL(sun4i_frontend_format_is_supported); | ||||
| 
 | ||||
| int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, | ||||
| 				  struct drm_plane *plane, uint32_t out_fmt) | ||||
| { | ||||
| 	struct drm_plane_state *state = plane->state; | ||||
| 	struct drm_framebuffer *fb = state->fb; | ||||
| 	uint32_t format = fb->format->format; | ||||
| 	u32 out_fmt_val; | ||||
| 	u32 in_fmt_val; | ||||
| 	u32 in_fmt_val, in_mod_val, in_ps_val; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	ret = sun4i_frontend_drm_format_to_input_fmt(fb->format->format, | ||||
| 						     &in_fmt_val); | ||||
| 	ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val); | ||||
| 	if (ret) { | ||||
| 		DRM_DEBUG_DRIVER("Invalid input format\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = sun4i_frontend_drm_format_to_input_mode(format, &in_mod_val); | ||||
| 	if (ret) { | ||||
| 		DRM_DEBUG_DRIVER("Invalid input mode\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = sun4i_frontend_drm_format_to_input_sequence(format, &in_ps_val); | ||||
| 	if (ret) { | ||||
| 		DRM_DEBUG_DRIVER("Invalid pixel sequence\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val); | ||||
| 	if (ret) { | ||||
| 		DRM_DEBUG_DRIVER("Invalid output format\n"); | ||||
|  | @ -162,10 +223,12 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, | |||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400); | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400); | ||||
| 
 | ||||
| 	regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG, | ||||
| 			   SUN4I_FRONTEND_BYPASS_CSC_EN, | ||||
| 			   SUN4I_FRONTEND_BYPASS_CSC_EN); | ||||
| 
 | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG, | ||||
| 		     SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) | | ||||
| 		     SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) | | ||||
| 		     SUN4I_FRONTEND_INPUT_FMT_PS(1)); | ||||
| 		     in_mod_val | in_fmt_val | in_ps_val); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * TODO: It look like the A31 and A80 at least will need the | ||||
|  | @ -173,7 +236,7 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, | |||
| 	 * ARGB8888). | ||||
| 	 */ | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG, | ||||
| 		     SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(out_fmt_val)); | ||||
| 		     out_fmt_val); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -183,16 +246,24 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, | |||
| 				 struct drm_plane *plane) | ||||
| { | ||||
| 	struct drm_plane_state *state = plane->state; | ||||
| 	struct drm_framebuffer *fb = state->fb; | ||||
| 	uint32_t luma_width, luma_height; | ||||
| 	uint32_t chroma_width, chroma_height; | ||||
| 
 | ||||
| 	/* Set height and width */ | ||||
| 	DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n", | ||||
| 			 state->crtc_w, state->crtc_h); | ||||
| 
 | ||||
| 	luma_width = state->src_w >> 16; | ||||
| 	luma_height = state->src_h >> 16; | ||||
| 
 | ||||
| 	chroma_width = DIV_ROUND_UP(luma_width, fb->format->hsub); | ||||
| 	chroma_height = DIV_ROUND_UP(luma_height, fb->format->vsub); | ||||
| 
 | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG, | ||||
| 		     SUN4I_FRONTEND_INSIZE(state->src_h >> 16, | ||||
| 					   state->src_w >> 16)); | ||||
| 		     SUN4I_FRONTEND_INSIZE(luma_height, luma_width)); | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG, | ||||
| 		     SUN4I_FRONTEND_INSIZE(state->src_h >> 16, | ||||
| 					   state->src_w >> 16)); | ||||
| 		     SUN4I_FRONTEND_INSIZE(chroma_height, chroma_width)); | ||||
| 
 | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG, | ||||
| 		     SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); | ||||
|  | @ -200,14 +271,14 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, | |||
| 		     SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); | ||||
| 
 | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG, | ||||
| 		     state->src_w / state->crtc_w); | ||||
| 		     (luma_width << 16) / state->crtc_w); | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG, | ||||
| 		     state->src_w / state->crtc_w); | ||||
| 		     (chroma_width << 16) / state->crtc_w); | ||||
| 
 | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG, | ||||
| 		     state->src_h / state->crtc_h); | ||||
| 		     (luma_height << 16) / state->crtc_h); | ||||
| 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG, | ||||
| 		     state->src_h / state->crtc_h); | ||||
| 		     (chroma_height << 16) / state->crtc_h); | ||||
| 
 | ||||
| 	regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG, | ||||
| 			  SUN4I_FRONTEND_FRM_CTRL_REG_RDY, | ||||
|  | @ -339,10 +410,6 @@ static int sun4i_frontend_runtime_resume(struct device *dev) | |||
| 			   SUN4I_FRONTEND_EN_EN, | ||||
| 			   SUN4I_FRONTEND_EN_EN); | ||||
| 
 | ||||
| 	regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG, | ||||
| 			   SUN4I_FRONTEND_BYPASS_CSC_EN, | ||||
| 			   SUN4I_FRONTEND_BYPASS_CSC_EN); | ||||
| 
 | ||||
| 	sun4i_frontend_scaler_init(frontend); | ||||
| 
 | ||||
| 	return 0; | ||||
|  |  | |||
|  | @ -26,12 +26,14 @@ | |||
| #define SUN4I_FRONTEND_LINESTRD0_REG		0x040 | ||||
| 
 | ||||
| #define SUN4I_FRONTEND_INPUT_FMT_REG		0x04c | ||||
| #define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(mod)		((mod) << 8) | ||||
| #define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(fmt)		((fmt) << 4) | ||||
| #define SUN4I_FRONTEND_INPUT_FMT_PS(ps)			(ps) | ||||
| #define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED	(1 << 8) | ||||
| #define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB		(5 << 4) | ||||
| #define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX		0 | ||||
| #define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB		1 | ||||
| 
 | ||||
| #define SUN4I_FRONTEND_OUTPUT_FMT_REG		0x05c | ||||
| #define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(fmt)		(fmt) | ||||
| #define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888	1 | ||||
| #define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888	2 | ||||
| 
 | ||||
| #define SUN4I_FRONTEND_CH0_INSIZE_REG		0x100 | ||||
| #define SUN4I_FRONTEND_INSIZE(h, w)			((((h) - 1) << 16) | (((w) - 1))) | ||||
|  | @ -95,5 +97,6 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, | |||
| 				 struct drm_plane *plane); | ||||
| int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, | ||||
| 				  struct drm_plane *plane, uint32_t out_fmt); | ||||
| bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier); | ||||
| 
 | ||||
| #endif /* _SUN4I_FRONTEND_H_ */ | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| 
 | ||||
| #include <drm/drm_atomic_helper.h> | ||||
| #include <drm/drm_plane_helper.h> | ||||
| #include <drm/drm_gem_framebuffer_helper.h> | ||||
| #include <drm/drmP.h> | ||||
| 
 | ||||
| #include "sun4i_backend.h" | ||||
|  | @ -92,14 +93,16 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, | |||
| 	struct sun4i_backend *backend = layer->backend; | ||||
| 	struct sun4i_frontend *frontend = backend->frontend; | ||||
| 
 | ||||
| 	sun4i_backend_cleanup_layer(backend, layer->id); | ||||
| 
 | ||||
| 	if (layer_state->uses_frontend) { | ||||
| 		sun4i_frontend_init(frontend); | ||||
| 		sun4i_frontend_update_coord(frontend, plane); | ||||
| 		sun4i_frontend_update_buffer(frontend, plane); | ||||
| 		sun4i_frontend_update_formats(frontend, plane, | ||||
| 					      DRM_FORMAT_ARGB8888); | ||||
| 					      DRM_FORMAT_XRGB8888); | ||||
| 		sun4i_backend_update_layer_frontend(backend, layer->id, | ||||
| 						    DRM_FORMAT_ARGB8888); | ||||
| 						    DRM_FORMAT_XRGB8888); | ||||
| 		sun4i_frontend_enable(frontend); | ||||
| 	} else { | ||||
| 		sun4i_backend_update_layer_formats(backend, layer->id, plane); | ||||
|  | @ -112,6 +115,7 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, | |||
| } | ||||
| 
 | ||||
| static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = { | ||||
| 	.prepare_fb	= drm_gem_fb_prepare_fb, | ||||
| 	.atomic_disable	= sun4i_backend_layer_atomic_disable, | ||||
| 	.atomic_update	= sun4i_backend_layer_atomic_update, | ||||
| }; | ||||
|  | @ -125,10 +129,11 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = { | |||
| 	.update_plane		= drm_atomic_helper_update_plane, | ||||
| }; | ||||
| 
 | ||||
| static const uint32_t sun4i_backend_layer_formats[] = { | ||||
| static const uint32_t sun4i_layer_formats[] = { | ||||
| 	DRM_FORMAT_ARGB8888, | ||||
| 	DRM_FORMAT_ARGB4444, | ||||
| 	DRM_FORMAT_ARGB1555, | ||||
| 	DRM_FORMAT_BGRX8888, | ||||
| 	DRM_FORMAT_RGBA5551, | ||||
| 	DRM_FORMAT_RGBA4444, | ||||
| 	DRM_FORMAT_RGB888, | ||||
|  | @ -154,8 +159,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | |||
| 	/* possible crtcs are set later */ | ||||
| 	ret = drm_universal_plane_init(drm, &layer->plane, 0, | ||||
| 				       &sun4i_backend_layer_funcs, | ||||
| 				       sun4i_backend_layer_formats, | ||||
| 				       ARRAY_SIZE(sun4i_backend_layer_formats), | ||||
| 				       sun4i_layer_formats, | ||||
| 				       ARRAY_SIZE(sun4i_layer_formats), | ||||
| 				       NULL, type, NULL); | ||||
| 	if (ret) { | ||||
| 		dev_err(drm->dev, "Couldn't initialize layer\n"); | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ | |||
| #include <drm/drm_crtc_helper.h> | ||||
| #include <drm/drm_fb_cma_helper.h> | ||||
| #include <drm/drm_gem_cma_helper.h> | ||||
| #include <drm/drm_gem_framebuffer_helper.h> | ||||
| #include <drm/drm_plane_helper.h> | ||||
| #include <drm/drmP.h> | ||||
| 
 | ||||
|  | @ -300,6 +301,7 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane, | |||
| } | ||||
| 
 | ||||
| static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { | ||||
| 	.prepare_fb	= drm_gem_fb_prepare_fb, | ||||
| 	.atomic_check	= sun8i_ui_layer_atomic_check, | ||||
| 	.atomic_disable	= sun8i_ui_layer_atomic_disable, | ||||
| 	.atomic_update	= sun8i_ui_layer_atomic_update, | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| #include <drm/drm_crtc_helper.h> | ||||
| #include <drm/drm_fb_cma_helper.h> | ||||
| #include <drm/drm_gem_cma_helper.h> | ||||
| #include <drm/drm_gem_framebuffer_helper.h> | ||||
| #include <drm/drm_plane_helper.h> | ||||
| #include <drm/drmP.h> | ||||
| 
 | ||||
|  | @ -336,6 +337,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, | |||
| } | ||||
| 
 | ||||
| static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { | ||||
| 	.prepare_fb	= drm_gem_fb_prepare_fb, | ||||
| 	.atomic_check	= sun8i_vi_layer_atomic_check, | ||||
| 	.atomic_disable	= sun8i_vi_layer_atomic_disable, | ||||
| 	.atomic_update	= sun8i_vi_layer_atomic_update, | ||||
|  |  | |||
|  | @ -249,7 +249,7 @@ static int tve200_probe(struct platform_device *pdev) | |||
| clk_disable: | ||||
| 	clk_disable_unprepare(priv->pclk); | ||||
| dev_unref: | ||||
| 	drm_dev_unref(drm); | ||||
| 	drm_dev_put(drm); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
|  | @ -263,7 +263,7 @@ static int tve200_remove(struct platform_device *pdev) | |||
| 		drm_panel_bridge_remove(priv->bridge); | ||||
| 	drm_mode_config_cleanup(drm); | ||||
| 	clk_disable_unprepare(priv->pclk); | ||||
| 	drm_dev_unref(drm); | ||||
| 	drm_dev_put(drm); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -210,14 +210,11 @@ static void | |||
| v3d_attach_object_fences(struct v3d_exec_info *exec) | ||||
| { | ||||
| 	struct dma_fence *out_fence = exec->render_done_fence; | ||||
| 	struct v3d_bo *bo; | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < exec->bo_count; i++) { | ||||
| 		bo = to_v3d_bo(&exec->bo[i]->base); | ||||
| 
 | ||||
| 		/* XXX: Use shared fences for read-only objects. */ | ||||
| 		reservation_object_add_excl_fence(bo->resv, out_fence); | ||||
| 		reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -228,11 +225,8 @@ v3d_unlock_bo_reservations(struct drm_device *dev, | |||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < exec->bo_count; i++) { | ||||
| 		struct v3d_bo *bo = to_v3d_bo(&exec->bo[i]->base); | ||||
| 
 | ||||
| 		ww_mutex_unlock(&bo->resv->lock); | ||||
| 	} | ||||
| 	for (i = 0; i < exec->bo_count; i++) | ||||
| 		ww_mutex_unlock(&exec->bo[i]->resv->lock); | ||||
| 
 | ||||
| 	ww_acquire_fini(acquire_ctx); | ||||
| } | ||||
|  | @ -251,13 +245,13 @@ v3d_lock_bo_reservations(struct drm_device *dev, | |||
| { | ||||
| 	int contended_lock = -1; | ||||
| 	int i, ret; | ||||
| 	struct v3d_bo *bo; | ||||
| 
 | ||||
| 	ww_acquire_init(acquire_ctx, &reservation_ww_class); | ||||
| 
 | ||||
| retry: | ||||
| 	if (contended_lock != -1) { | ||||
| 		bo = to_v3d_bo(&exec->bo[contended_lock]->base); | ||||
| 		struct v3d_bo *bo = exec->bo[contended_lock]; | ||||
| 
 | ||||
| 		ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock, | ||||
| 						       acquire_ctx); | ||||
| 		if (ret) { | ||||
|  | @ -270,19 +264,16 @@ v3d_lock_bo_reservations(struct drm_device *dev, | |||
| 		if (i == contended_lock) | ||||
| 			continue; | ||||
| 
 | ||||
| 		bo = to_v3d_bo(&exec->bo[i]->base); | ||||
| 
 | ||||
| 		ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx); | ||||
| 		ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock, | ||||
| 						  acquire_ctx); | ||||
| 		if (ret) { | ||||
| 			int j; | ||||
| 
 | ||||
| 			for (j = 0; j < i; j++) { | ||||
| 				bo = to_v3d_bo(&exec->bo[j]->base); | ||||
| 				ww_mutex_unlock(&bo->resv->lock); | ||||
| 			} | ||||
| 			for (j = 0; j < i; j++) | ||||
| 				ww_mutex_unlock(&exec->bo[j]->resv->lock); | ||||
| 
 | ||||
| 			if (contended_lock != -1 && contended_lock >= i) { | ||||
| 				bo = to_v3d_bo(&exec->bo[contended_lock]->base); | ||||
| 				struct v3d_bo *bo = exec->bo[contended_lock]; | ||||
| 
 | ||||
| 				ww_mutex_unlock(&bo->resv->lock); | ||||
| 			} | ||||
|  | @ -303,9 +294,7 @@ v3d_lock_bo_reservations(struct drm_device *dev, | |||
| 	 * before we commit the CL to the hardware. | ||||
| 	 */ | ||||
| 	for (i = 0; i < exec->bo_count; i++) { | ||||
| 		bo = to_v3d_bo(&exec->bo[i]->base); | ||||
| 
 | ||||
| 		ret = reservation_object_reserve_shared(bo->resv, 1); | ||||
| 		ret = reservation_object_reserve_shared(exec->bo[i]->resv, 1); | ||||
| 		if (ret) { | ||||
| 			v3d_unlock_bo_reservations(dev, exec, acquire_ctx); | ||||
| 			return ret; | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ v3d_job_free(struct drm_sched_job *sched_job) | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns the fences that the bin job depends on, one by one. | ||||
|  * Returns the fences that the bin or render job depends on, one by one. | ||||
|  * v3d_job_run() won't be called until all of them have been signaled. | ||||
|  */ | ||||
| static struct dma_fence * | ||||
|  |  | |||
|  | @ -169,6 +169,12 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector) | |||
| 	struct drm_display_mode *mode = NULL; | ||||
| 	int count, width, height; | ||||
| 
 | ||||
| 	if (output->edid) { | ||||
| 		count = drm_add_edid_modes(connector, output->edid); | ||||
| 		if (count) | ||||
| 			return count; | ||||
| 	} | ||||
| 
 | ||||
| 	width  = le32_to_cpu(output->info.r.width); | ||||
| 	height = le32_to_cpu(output->info.r.height); | ||||
| 	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); | ||||
|  | @ -287,6 +293,8 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index) | |||
| 	drm_connector_init(dev, connector, &virtio_gpu_connector_funcs, | ||||
| 			   DRM_MODE_CONNECTOR_VIRTUAL); | ||||
| 	drm_connector_helper_add(connector, &virtio_gpu_conn_helper_funcs); | ||||
| 	if (vgdev->has_edid) | ||||
| 		drm_connector_attach_edid_property(connector); | ||||
| 
 | ||||
| 	drm_encoder_init(dev, encoder, &virtio_gpu_enc_funcs, | ||||
| 			 DRM_MODE_ENCODER_VIRTUAL, NULL); | ||||
|  | @ -378,6 +386,10 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) | |||
| 
 | ||||
| void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0 ; i < vgdev->num_scanouts; ++i) | ||||
| 		kfree(vgdev->outputs[i].edid); | ||||
| 	virtio_gpu_fbdev_fini(vgdev); | ||||
| 	drm_mode_config_cleanup(vgdev->ddev); | ||||
| } | ||||
|  |  | |||
|  | @ -80,6 +80,7 @@ static unsigned int features[] = { | |||
| 	 */ | ||||
| 	VIRTIO_GPU_F_VIRGL, | ||||
| #endif | ||||
| 	VIRTIO_GPU_F_EDID, | ||||
| }; | ||||
| static struct virtio_driver virtio_gpu_driver = { | ||||
| 	.feature_table = features, | ||||
|  |  | |||
|  | @ -115,6 +115,7 @@ struct virtio_gpu_output { | |||
| 	struct drm_encoder enc; | ||||
| 	struct virtio_gpu_display_one info; | ||||
| 	struct virtio_gpu_update_cursor cursor; | ||||
| 	struct edid *edid; | ||||
| 	int cur_x; | ||||
| 	int cur_y; | ||||
| 	bool enabled; | ||||
|  | @ -201,6 +202,7 @@ struct virtio_gpu_device { | |||
| 	struct ida	ctx_id_ida; | ||||
| 
 | ||||
| 	bool has_virgl_3d; | ||||
| 	bool has_edid; | ||||
| 
 | ||||
| 	struct work_struct config_changed_work; | ||||
| 
 | ||||
|  | @ -291,6 +293,7 @@ int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx); | |||
| int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, | ||||
| 			      int idx, int version, | ||||
| 			      struct virtio_gpu_drv_cap_cache **cache_p); | ||||
| int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev); | ||||
| void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, | ||||
| 				   uint32_t nlen, const char *name); | ||||
| void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev, | ||||
|  |  | |||
|  | @ -44,6 +44,8 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work) | |||
| 	virtio_cread(vgdev->vdev, struct virtio_gpu_config, | ||||
| 		     events_read, &events_read); | ||||
| 	if (events_read & VIRTIO_GPU_EVENT_DISPLAY) { | ||||
| 		if (vgdev->has_edid) | ||||
| 			virtio_gpu_cmd_get_edids(vgdev); | ||||
| 		virtio_gpu_cmd_get_display_info(vgdev); | ||||
| 		drm_helper_hpd_irq_event(vgdev->ddev); | ||||
| 		events_clear |= VIRTIO_GPU_EVENT_DISPLAY; | ||||
|  | @ -156,6 +158,10 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) | |||
| #else | ||||
| 	DRM_INFO("virgl 3d acceleration not supported by guest\n"); | ||||
| #endif | ||||
| 	if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_EDID)) { | ||||
| 		vgdev->has_edid = true; | ||||
| 		DRM_INFO("EDID support available.\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); | ||||
| 	if (ret) { | ||||
|  | @ -201,6 +207,8 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 
 | ||||
| 	if (num_capsets) | ||||
| 		virtio_gpu_get_capsets(vgdev, num_capsets); | ||||
| 	if (vgdev->has_edid) | ||||
| 		virtio_gpu_cmd_get_edids(vgdev); | ||||
| 	virtio_gpu_cmd_get_display_info(vgdev); | ||||
| 	wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, | ||||
| 			   5 * HZ); | ||||
|  |  | |||
|  | @ -584,6 +584,45 @@ static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev, | |||
| 	wake_up(&vgdev->resp_wq); | ||||
| } | ||||
| 
 | ||||
| static int virtio_get_edid_block(void *data, u8 *buf, | ||||
| 				 unsigned int block, size_t len) | ||||
| { | ||||
| 	struct virtio_gpu_resp_edid *resp = data; | ||||
| 	size_t start = block * EDID_LENGTH; | ||||
| 
 | ||||
| 	if (start + len > le32_to_cpu(resp->size)) | ||||
| 		return -1; | ||||
| 	memcpy(buf, resp->edid + start, len); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void virtio_gpu_cmd_get_edid_cb(struct virtio_gpu_device *vgdev, | ||||
| 				       struct virtio_gpu_vbuffer *vbuf) | ||||
| { | ||||
| 	struct virtio_gpu_cmd_get_edid *cmd = | ||||
| 		(struct virtio_gpu_cmd_get_edid *)vbuf->buf; | ||||
| 	struct virtio_gpu_resp_edid *resp = | ||||
| 		(struct virtio_gpu_resp_edid *)vbuf->resp_buf; | ||||
| 	uint32_t scanout = le32_to_cpu(cmd->scanout); | ||||
| 	struct virtio_gpu_output *output; | ||||
| 	struct edid *new_edid, *old_edid; | ||||
| 
 | ||||
| 	if (scanout >= vgdev->num_scanouts) | ||||
| 		return; | ||||
| 	output = vgdev->outputs + scanout; | ||||
| 
 | ||||
| 	new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp); | ||||
| 
 | ||||
| 	spin_lock(&vgdev->display_info_lock); | ||||
| 	old_edid = output->edid; | ||||
| 	output->edid = new_edid; | ||||
| 	drm_connector_update_edid_property(&output->conn, output->edid); | ||||
| 	spin_unlock(&vgdev->display_info_lock); | ||||
| 
 | ||||
| 	kfree(old_edid); | ||||
| 	wake_up(&vgdev->resp_wq); | ||||
| } | ||||
| 
 | ||||
| int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev) | ||||
| { | ||||
| 	struct virtio_gpu_ctrl_hdr *cmd_p; | ||||
|  | @ -686,6 +725,34 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev) | ||||
| { | ||||
| 	struct virtio_gpu_cmd_get_edid *cmd_p; | ||||
| 	struct virtio_gpu_vbuffer *vbuf; | ||||
| 	void *resp_buf; | ||||
| 	int scanout; | ||||
| 
 | ||||
| 	if (WARN_ON(!vgdev->has_edid)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	for (scanout = 0; scanout < vgdev->num_scanouts; scanout++) { | ||||
| 		resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_edid), | ||||
| 				   GFP_KERNEL); | ||||
| 		if (!resp_buf) | ||||
| 			return -ENOMEM; | ||||
| 
 | ||||
| 		cmd_p = virtio_gpu_alloc_cmd_resp | ||||
| 			(vgdev, &virtio_gpu_cmd_get_edid_cb, &vbuf, | ||||
| 			 sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_edid), | ||||
| 			 resp_buf); | ||||
| 		cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_EDID); | ||||
| 		cmd_p->scanout = cpu_to_le32(scanout); | ||||
| 		virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, | ||||
| 				   uint32_t nlen, const char *name) | ||||
| { | ||||
|  |  | |||
|  | @ -68,7 +68,6 @@ static struct drm_driver vkms_driver = { | |||
| 	.release		= vkms_release, | ||||
| 	.fops			= &vkms_driver_fops, | ||||
| 	.dumb_create		= vkms_dumb_create, | ||||
| 	.dumb_map_offset	= vkms_dumb_map, | ||||
| 	.gem_vm_ops		= &vkms_gem_vm_ops, | ||||
| 	.gem_free_object_unlocked = vkms_gem_free_object, | ||||
| 	.get_vblank_timestamp	= vkms_get_vblank_timestamp, | ||||
|  |  | |||
|  | @ -127,9 +127,6 @@ vm_fault_t vkms_gem_fault(struct vm_fault *vmf); | |||
| int vkms_dumb_create(struct drm_file *file, struct drm_device *dev, | ||||
| 		     struct drm_mode_create_dumb *args); | ||||
| 
 | ||||
| int vkms_dumb_map(struct drm_file *file, struct drm_device *dev, | ||||
| 		  u32 handle, u64 *offset); | ||||
| 
 | ||||
| void vkms_gem_free_object(struct drm_gem_object *obj); | ||||
| 
 | ||||
| int vkms_gem_vmap(struct drm_gem_object *obj); | ||||
|  |  | |||
|  | @ -153,32 +153,6 @@ int vkms_dumb_create(struct drm_file *file, struct drm_device *dev, | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int vkms_dumb_map(struct drm_file *file, struct drm_device *dev, | ||||
| 		  u32 handle, u64 *offset) | ||||
| { | ||||
| 	struct drm_gem_object *obj; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	obj = drm_gem_object_lookup(file, handle); | ||||
| 	if (!obj) | ||||
| 		return -ENOENT; | ||||
| 
 | ||||
| 	if (!obj->filp) { | ||||
| 		ret = -EINVAL; | ||||
| 		goto unref; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = drm_gem_create_mmap_offset(obj); | ||||
| 	if (ret) | ||||
| 		goto unref; | ||||
| 
 | ||||
| 	*offset = drm_vma_node_offset_addr(&obj->vma_node); | ||||
| unref: | ||||
| 	drm_gem_object_put_unlocked(obj); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static struct page **_get_pages(struct vkms_gem_object *vkms_obj) | ||||
| { | ||||
| 	struct drm_gem_object *gem_obj = &vkms_obj->gem; | ||||
|  |  | |||
|  | @ -279,7 +279,6 @@ static struct drm_driver driver = { | |||
| 	.gem_free_object_unlocked = vbox_gem_free_object, | ||||
| 	.dumb_create = vbox_dumb_create, | ||||
| 	.dumb_map_offset = vbox_dumb_mmap_offset, | ||||
| 	.dumb_destroy = drm_gem_dumb_destroy, | ||||
| 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd, | ||||
| 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle, | ||||
| 	.gem_prime_export = drm_gem_prime_export, | ||||
|  |  | |||
|  | @ -1210,30 +1210,6 @@ static inline void drm_connector_put(struct drm_connector *connector) | |||
| 	drm_mode_object_put(&connector->base); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_connector_reference - acquire a connector reference | ||||
|  * @connector: DRM connector | ||||
|  * | ||||
|  * This is a compatibility alias for drm_connector_get() and should not be | ||||
|  * used by new code. | ||||
|  */ | ||||
| static inline void drm_connector_reference(struct drm_connector *connector) | ||||
| { | ||||
| 	drm_connector_get(connector); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_connector_unreference - release a connector reference | ||||
|  * @connector: DRM connector | ||||
|  * | ||||
|  * This is a compatibility alias for drm_connector_put() and should not be | ||||
|  * used by new code. | ||||
|  */ | ||||
| static inline void drm_connector_unreference(struct drm_connector *connector) | ||||
| { | ||||
| 	drm_connector_put(connector); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_connector_is_unregistered - has the connector been unregistered from | ||||
|  * userspace? | ||||
|  |  | |||
|  | @ -527,8 +527,10 @@ struct drm_driver { | |||
| 	 * @dumb_map_offset: | ||||
| 	 * | ||||
| 	 * Allocate an offset in the drm device node's address space to be able to | ||||
| 	 * memory map a dumb buffer. GEM-based drivers must use | ||||
| 	 * drm_gem_create_mmap_offset() to implement this. | ||||
| 	 * memory map a dumb buffer. | ||||
| 	 * | ||||
| 	 * The default implementation is drm_gem_create_mmap_offset(). GEM based | ||||
| 	 * drivers must not overwrite this. | ||||
| 	 * | ||||
| 	 * Called by the user via ioctl. | ||||
| 	 * | ||||
|  | @ -548,6 +550,9 @@ struct drm_driver { | |||
| 	 * | ||||
| 	 * Called by the user via ioctl. | ||||
| 	 * | ||||
| 	 * The default implementation is drm_gem_dumb_destroy(). GEM based drivers | ||||
| 	 * must not overwrite this. | ||||
| 	 * | ||||
| 	 * Returns: | ||||
| 	 * | ||||
| 	 * Zero on success, negative errno on failure. | ||||
|  | @ -625,7 +630,6 @@ void drm_dev_unregister(struct drm_device *dev); | |||
| 
 | ||||
| void drm_dev_get(struct drm_device *dev); | ||||
| void drm_dev_put(struct drm_device *dev); | ||||
| void drm_dev_unref(struct drm_device *dev); | ||||
| void drm_put_dev(struct drm_device *dev); | ||||
| bool drm_dev_enter(struct drm_device *dev, int *idx); | ||||
| void drm_dev_exit(int idx); | ||||
|  |  | |||
|  | @ -240,30 +240,6 @@ static inline void drm_framebuffer_put(struct drm_framebuffer *fb) | |||
| 	drm_mode_object_put(&fb->base); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_framebuffer_reference - acquire a framebuffer reference | ||||
|  * @fb: DRM framebuffer | ||||
|  * | ||||
|  * This is a compatibility alias for drm_framebuffer_get() and should not be | ||||
|  * used by new code. | ||||
|  */ | ||||
| static inline void drm_framebuffer_reference(struct drm_framebuffer *fb) | ||||
| { | ||||
| 	drm_framebuffer_get(fb); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_framebuffer_unreference - release a framebuffer reference | ||||
|  * @fb: DRM framebuffer | ||||
|  * | ||||
|  * This is a compatibility alias for drm_framebuffer_put() and should not be | ||||
|  * used by new code. | ||||
|  */ | ||||
| static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb) | ||||
| { | ||||
| 	drm_framebuffer_put(fb); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_framebuffer_read_refcount - read the framebuffer reference count. | ||||
|  * @fb: framebuffer | ||||
|  |  | |||
|  | @ -348,56 +348,6 @@ __drm_gem_object_put(struct drm_gem_object *obj) | |||
| void drm_gem_object_put_unlocked(struct drm_gem_object *obj); | ||||
| void drm_gem_object_put(struct drm_gem_object *obj); | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_gem_object_reference - acquire a GEM buffer object reference | ||||
|  * @obj: GEM buffer object | ||||
|  * | ||||
|  * This is a compatibility alias for drm_gem_object_get() and should not be | ||||
|  * used by new code. | ||||
|  */ | ||||
| static inline void drm_gem_object_reference(struct drm_gem_object *obj) | ||||
| { | ||||
| 	drm_gem_object_get(obj); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * __drm_gem_object_unreference - raw function to release a GEM buffer object | ||||
|  *                                reference | ||||
|  * @obj: GEM buffer object | ||||
|  * | ||||
|  * This is a compatibility alias for __drm_gem_object_put() and should not be | ||||
|  * used by new code. | ||||
|  */ | ||||
| static inline void __drm_gem_object_unreference(struct drm_gem_object *obj) | ||||
| { | ||||
| 	__drm_gem_object_put(obj); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_gem_object_unreference_unlocked - release a GEM buffer object reference | ||||
|  * @obj: GEM buffer object | ||||
|  * | ||||
|  * This is a compatibility alias for drm_gem_object_put_unlocked() and should | ||||
|  * not be used by new code. | ||||
|  */ | ||||
| static inline void | ||||
| drm_gem_object_unreference_unlocked(struct drm_gem_object *obj) | ||||
| { | ||||
| 	drm_gem_object_put_unlocked(obj); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_gem_object_unreference - release a GEM buffer object reference | ||||
|  * @obj: GEM buffer object | ||||
|  * | ||||
|  * This is a compatibility alias for drm_gem_object_put() and should not be | ||||
|  * used by new code. | ||||
|  */ | ||||
| static inline void drm_gem_object_unreference(struct drm_gem_object *obj) | ||||
| { | ||||
| 	drm_gem_object_put(obj); | ||||
| } | ||||
| 
 | ||||
| int drm_gem_handle_create(struct drm_file *file_priv, | ||||
| 			  struct drm_gem_object *obj, | ||||
| 			  u32 *handlep); | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ struct drm_v3d_submit_cl { | |||
| 	 */ | ||||
| 	__u32 bcl_start; | ||||
| 
 | ||||
| 	 /** End address of the BCL (first byte after the BCL) */ | ||||
| 	/** End address of the BCL (first byte after the BCL) */ | ||||
| 	__u32 bcl_end; | ||||
| 
 | ||||
| 	/* Offset of the render command list.
 | ||||
|  | @ -82,7 +82,7 @@ struct drm_v3d_submit_cl { | |||
| 	 */ | ||||
| 	__u32 rcl_start; | ||||
| 
 | ||||
| 	 /** End address of the RCL (first byte after the RCL) */ | ||||
| 	/** End address of the RCL (first byte after the RCL) */ | ||||
| 	__u32 rcl_end; | ||||
| 
 | ||||
| 	/** An optional sync object to wait on before starting the BCL. */ | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ | |||
| #include <linux/types.h> | ||||
| 
 | ||||
| #define VIRTIO_GPU_F_VIRGL 0 | ||||
| #define VIRTIO_GPU_F_EDID  1 | ||||
| 
 | ||||
| enum virtio_gpu_ctrl_type { | ||||
| 	VIRTIO_GPU_UNDEFINED = 0, | ||||
|  | @ -56,6 +57,7 @@ enum virtio_gpu_ctrl_type { | |||
| 	VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING, | ||||
| 	VIRTIO_GPU_CMD_GET_CAPSET_INFO, | ||||
| 	VIRTIO_GPU_CMD_GET_CAPSET, | ||||
| 	VIRTIO_GPU_CMD_GET_EDID, | ||||
| 
 | ||||
| 	/* 3d commands */ | ||||
| 	VIRTIO_GPU_CMD_CTX_CREATE = 0x0200, | ||||
|  | @ -76,6 +78,7 @@ enum virtio_gpu_ctrl_type { | |||
| 	VIRTIO_GPU_RESP_OK_DISPLAY_INFO, | ||||
| 	VIRTIO_GPU_RESP_OK_CAPSET_INFO, | ||||
| 	VIRTIO_GPU_RESP_OK_CAPSET, | ||||
| 	VIRTIO_GPU_RESP_OK_EDID, | ||||
| 
 | ||||
| 	/* error responses */ | ||||
| 	VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200, | ||||
|  | @ -291,6 +294,21 @@ struct virtio_gpu_resp_capset { | |||
| 	__u8 capset_data[]; | ||||
| }; | ||||
| 
 | ||||
| /* VIRTIO_GPU_CMD_GET_EDID */ | ||||
| struct virtio_gpu_cmd_get_edid { | ||||
| 	struct virtio_gpu_ctrl_hdr hdr; | ||||
| 	__le32 scanout; | ||||
| 	__le32 padding; | ||||
| }; | ||||
| 
 | ||||
| /* VIRTIO_GPU_RESP_OK_EDID */ | ||||
| struct virtio_gpu_resp_edid { | ||||
| 	struct virtio_gpu_ctrl_hdr hdr; | ||||
| 	__le32 size; | ||||
| 	__le32 padding; | ||||
| 	__u8 edid[1024]; | ||||
| }; | ||||
| 
 | ||||
| #define VIRTIO_GPU_EVENT_DISPLAY (1 << 0) | ||||
| 
 | ||||
| struct virtio_gpu_config { | ||||
|  |  | |||
|  | @ -1,78 +0,0 @@ | |||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /// | ||||
| /// Use drm_*_get() and drm_*_put() helpers instead of drm_*_reference() and | ||||
| /// drm_*_unreference() helpers. | ||||
| /// | ||||
| // Confidence: High | ||||
| // Copyright: (C) 2017 NVIDIA Corporation | ||||
| // Options: --no-includes --include-headers | ||||
| // | ||||
| 
 | ||||
| virtual patch | ||||
| virtual report | ||||
| 
 | ||||
| @depends on patch@ | ||||
| expression object; | ||||
| @@ | ||||
| 
 | ||||
| ( | ||||
| - drm_connector_reference(object) | ||||
| + drm_connector_get(object) | ||||
| | | ||||
| - drm_connector_unreference(object) | ||||
| + drm_connector_put(object) | ||||
| | | ||||
| - drm_framebuffer_reference(object) | ||||
| + drm_framebuffer_get(object) | ||||
| | | ||||
| - drm_framebuffer_unreference(object) | ||||
| + drm_framebuffer_put(object) | ||||
| | | ||||
| - drm_gem_object_reference(object) | ||||
| + drm_gem_object_get(object) | ||||
| | | ||||
| - drm_gem_object_unreference(object) | ||||
| + drm_gem_object_put(object) | ||||
| | | ||||
| - __drm_gem_object_unreference(object) | ||||
| + __drm_gem_object_put(object) | ||||
| | | ||||
| - drm_gem_object_unreference_unlocked(object) | ||||
| + drm_gem_object_put_unlocked(object) | ||||
| | | ||||
| - drm_dev_unref(object) | ||||
| + drm_dev_put(object) | ||||
| ) | ||||
| 
 | ||||
| @r depends on report@ | ||||
| expression object; | ||||
| position p; | ||||
| @@ | ||||
| 
 | ||||
| ( | ||||
| drm_connector_unreference@p(object) | ||||
| | | ||||
| drm_connector_reference@p(object) | ||||
| | | ||||
| drm_framebuffer_unreference@p(object) | ||||
| | | ||||
| drm_framebuffer_reference@p(object) | ||||
| | | ||||
| drm_gem_object_unreference@p(object) | ||||
| | | ||||
| drm_gem_object_reference@p(object) | ||||
| | | ||||
| __drm_gem_object_unreference(object) | ||||
| | | ||||
| drm_gem_object_unreference_unlocked(object) | ||||
| | | ||||
| drm_dev_unref@p(object) | ||||
| ) | ||||
| 
 | ||||
| @script:python depends on report@ | ||||
| object << r.object; | ||||
| p << r.p; | ||||
| @@ | ||||
| 
 | ||||
| msg="WARNING: use get/put helpers to reference and dereference %s" % (object) | ||||
| coccilib.report.print_report(p[0], msg) | ||||
		Loading…
	
		Reference in a new issue
	
	 Dave Airlie
						Dave Airlie