diff options
Diffstat (limited to 'drivers/gpu/drm/tegra/drm.c')
| -rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 107 | 
1 files changed, 63 insertions, 44 deletions
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index f96c237b2242..8d37d6b00562 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -21,24 +21,21 @@  #include <drm/drm_prime.h>  #include <drm/drm_vblank.h> +#include "dc.h"  #include "drm.h"  #include "gem.h" +#include "uapi.h"  #define DRIVER_NAME "tegra"  #define DRIVER_DESC "NVIDIA Tegra graphics"  #define DRIVER_DATE "20120330" -#define DRIVER_MAJOR 0 +#define DRIVER_MAJOR 1  #define DRIVER_MINOR 0  #define DRIVER_PATCHLEVEL 0  #define CARVEOUT_SZ SZ_64M  #define CDMA_GATHER_FETCHES_MAX_NB 16383 -struct tegra_drm_file { -	struct idr contexts; -	struct mutex lock; -}; -  static int tegra_atomic_check(struct drm_device *drm,  			      struct drm_atomic_state *state)  { @@ -60,6 +57,17 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {  	.atomic_commit = drm_atomic_helper_commit,  }; +static void tegra_atomic_post_commit(struct drm_device *drm, +				     struct drm_atomic_state *old_state) +{ +	struct drm_crtc_state *old_crtc_state __maybe_unused; +	struct drm_crtc *crtc; +	unsigned int i; + +	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) +		tegra_crtc_atomic_post_commit(crtc, old_state); +} +  static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)  {  	struct drm_device *drm = old_state->dev; @@ -79,6 +87,8 @@ static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)  	} else {  		drm_atomic_helper_commit_tail_rpm(old_state);  	} + +	tegra_atomic_post_commit(drm, old_state);  }  static const struct drm_mode_config_helper_funcs @@ -94,7 +104,9 @@ static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)  	if (!fpriv)  		return -ENOMEM; -	idr_init_base(&fpriv->contexts, 1); +	idr_init_base(&fpriv->legacy_contexts, 1); +	xa_init_flags(&fpriv->contexts, XA_FLAGS_ALLOC1); +	xa_init(&fpriv->syncpoints);  	mutex_init(&fpriv->lock);  	filp->driver_priv = fpriv; @@ -107,20 +119,6 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)  	kfree(context);  } -static struct host1x_bo * -host1x_bo_lookup(struct drm_file *file, u32 handle) -{ -	struct drm_gem_object *gem; -	struct tegra_bo *bo; - -	gem = drm_gem_object_lookup(file, handle); -	if (!gem) -		return NULL; - -	bo = to_tegra_bo(gem); -	return &bo->base; -} -  static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,  				       struct drm_tegra_reloc __user *src,  				       struct drm_device *drm, @@ -151,11 +149,11 @@ static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,  	dest->flags = HOST1X_RELOC_READ | HOST1X_RELOC_WRITE; -	dest->cmdbuf.bo = host1x_bo_lookup(file, cmdbuf); +	dest->cmdbuf.bo = tegra_gem_lookup(file, cmdbuf);  	if (!dest->cmdbuf.bo)  		return -ENOENT; -	dest->target.bo = host1x_bo_lookup(file, target); +	dest->target.bo = tegra_gem_lookup(file, target);  	if (!dest->target.bo)  		return -ENOENT; @@ -193,7 +191,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,  		return -EINVAL;  	job = host1x_job_alloc(context->channel, args->num_cmdbufs, -			       args->num_relocs); +			       args->num_relocs, false);  	if (!job)  		return -ENOMEM; @@ -201,6 +199,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,  	job->client = client;  	job->class = client->class;  	job->serialize = true; +	job->syncpt_recovery = true;  	/*  	 * Track referenced BOs so that they can be unreferenced after the @@ -237,7 +236,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,  			goto fail;  		} -		bo = host1x_bo_lookup(file, cmdbuf.handle); +		bo = tegra_gem_lookup(file, cmdbuf.handle);  		if (!bo) {  			err = -ENOENT;  			goto fail; @@ -432,7 +431,7 @@ static int tegra_client_open(struct tegra_drm_file *fpriv,  	if (err < 0)  		return err; -	err = idr_alloc(&fpriv->contexts, context, 1, 0, GFP_KERNEL); +	err = idr_alloc(&fpriv->legacy_contexts, context, 1, 0, GFP_KERNEL);  	if (err < 0) {  		client->ops->close_channel(context);  		return err; @@ -487,13 +486,13 @@ static int tegra_close_channel(struct drm_device *drm, void *data,  	mutex_lock(&fpriv->lock); -	context = idr_find(&fpriv->contexts, args->context); +	context = idr_find(&fpriv->legacy_contexts, args->context);  	if (!context) {  		err = -EINVAL;  		goto unlock;  	} -	idr_remove(&fpriv->contexts, context->id); +	idr_remove(&fpriv->legacy_contexts, context->id);  	tegra_drm_context_free(context);  unlock: @@ -512,7 +511,7 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,  	mutex_lock(&fpriv->lock); -	context = idr_find(&fpriv->contexts, args->context); +	context = idr_find(&fpriv->legacy_contexts, args->context);  	if (!context) {  		err = -ENODEV;  		goto unlock; @@ -541,7 +540,7 @@ static int tegra_submit(struct drm_device *drm, void *data,  	mutex_lock(&fpriv->lock); -	context = idr_find(&fpriv->contexts, args->context); +	context = idr_find(&fpriv->legacy_contexts, args->context);  	if (!context) {  		err = -ENODEV;  		goto unlock; @@ -566,7 +565,7 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,  	mutex_lock(&fpriv->lock); -	context = idr_find(&fpriv->contexts, args->context); +	context = idr_find(&fpriv->legacy_contexts, args->context);  	if (!context) {  		err = -ENODEV;  		goto unlock; @@ -735,10 +734,25 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,  static const struct drm_ioctl_desc tegra_drm_ioctls[] = {  #ifdef CONFIG_DRM_TEGRA_STAGING -	DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, +	DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_OPEN, tegra_drm_ioctl_channel_open, +			  DRM_RENDER_ALLOW), +	DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_CLOSE, tegra_drm_ioctl_channel_close, +			  DRM_RENDER_ALLOW), +	DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_MAP, tegra_drm_ioctl_channel_map, +			  DRM_RENDER_ALLOW), +	DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_UNMAP, tegra_drm_ioctl_channel_unmap,  			  DRM_RENDER_ALLOW), -	DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, +	DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_SUBMIT, tegra_drm_ioctl_channel_submit,  			  DRM_RENDER_ALLOW), +	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPOINT_ALLOCATE, tegra_drm_ioctl_syncpoint_allocate, +			  DRM_RENDER_ALLOW), +	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPOINT_FREE, tegra_drm_ioctl_syncpoint_free, +			  DRM_RENDER_ALLOW), +	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPOINT_WAIT, tegra_drm_ioctl_syncpoint_wait, +			  DRM_RENDER_ALLOW), + +	DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_RENDER_ALLOW), +	DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_RENDER_ALLOW),  	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read,  			  DRM_RENDER_ALLOW),  	DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, @@ -792,10 +806,11 @@ static void tegra_drm_postclose(struct drm_device *drm, struct drm_file *file)  	struct tegra_drm_file *fpriv = file->driver_priv;  	mutex_lock(&fpriv->lock); -	idr_for_each(&fpriv->contexts, tegra_drm_context_cleanup, NULL); +	idr_for_each(&fpriv->legacy_contexts, tegra_drm_context_cleanup, NULL); +	tegra_drm_uapi_close_file(fpriv);  	mutex_unlock(&fpriv->lock); -	idr_destroy(&fpriv->contexts); +	idr_destroy(&fpriv->legacy_contexts);  	mutex_destroy(&fpriv->lock);  	kfree(fpriv);  } @@ -853,7 +868,7 @@ static void tegra_debugfs_init(struct drm_minor *minor)  static const struct drm_driver tegra_drm_driver = {  	.driver_features = DRIVER_MODESET | DRIVER_GEM | -			   DRIVER_ATOMIC | DRIVER_RENDER, +			   DRIVER_ATOMIC | DRIVER_RENDER | DRIVER_SYNCOBJ,  	.open = tegra_drm_open,  	.postclose = tegra_drm_postclose,  	.lastclose = drm_fb_helper_lastclose, @@ -883,6 +898,14 @@ static const struct drm_driver tegra_drm_driver = {  int tegra_drm_register_client(struct tegra_drm *tegra,  			      struct tegra_drm_client *client)  { +	/* +	 * When MLOCKs are implemented, change to allocate a shared channel +	 * only when MLOCKs are disabled. +	 */ +	client->shared_channel = host1x_channel_request(&client->base); +	if (!client->shared_channel) +		return -EBUSY; +  	mutex_lock(&tegra->clients_lock);  	list_add_tail(&client->list, &tegra->clients);  	client->drm = tegra; @@ -899,6 +922,9 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,  	client->drm = NULL;  	mutex_unlock(&tegra->clients_lock); +	if (client->shared_channel) +		host1x_channel_put(client->shared_channel); +  	return 0;  } @@ -1188,13 +1214,6 @@ static int host1x_drm_probe(struct host1x_device *dev)  			goto device;  	} -	/* -	 * We don't use the drm_irq_install() helpers provided by the DRM -	 * core, so we need to set this manually in order to allow the -	 * DRM_IOCTL_WAIT_VBLANK to operate correctly. -	 */ -	drm->irq_enabled = true; -  	/* syncpoints are used for full 32-bit hardware VBLANK counters */  	drm->max_vblank_count = 0xffffffff; @@ -1204,7 +1223,7 @@ static int host1x_drm_probe(struct host1x_device *dev)  	drm_mode_config_reset(drm); -	err = drm_aperture_remove_framebuffers(false, "tegradrmfb"); +	err = drm_aperture_remove_framebuffers(false, &tegra_drm_driver);  	if (err < 0)  		goto hub;  |