^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2012 Avionic Design GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2012-2016 NVIDIA CORPORATION. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/host1x.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/iommu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <drm/drm_atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <drm/drm_atomic_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <drm/drm_debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <drm/drm_drv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <drm/drm_fourcc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <drm/drm_ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <drm/drm_prime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <drm/drm_vblank.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "drm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "gem.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define DRIVER_NAME "tegra"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define DRIVER_DESC "NVIDIA Tegra graphics"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define DRIVER_DATE "20120330"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DRIVER_MAJOR 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define DRIVER_MINOR 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DRIVER_PATCHLEVEL 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define CARVEOUT_SZ SZ_64M
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define CDMA_GATHER_FETCHES_MAX_NB 16383
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct tegra_drm_file {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct idr contexts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int tegra_atomic_check(struct drm_device *drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct drm_atomic_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) err = drm_atomic_helper_check(drm, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return tegra_display_hub_atomic_check(drm, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .fb_create = tegra_fb_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #ifdef CONFIG_DRM_FBDEV_EMULATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .output_poll_changed = drm_fb_helper_output_poll_changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .atomic_check = tegra_atomic_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .atomic_commit = drm_atomic_helper_commit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct drm_device *drm = old_state->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct tegra_drm *tegra = drm->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (tegra->hub) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) drm_atomic_helper_commit_modeset_disables(drm, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) tegra_display_hub_atomic_commit(drm, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) drm_atomic_helper_commit_planes(drm, old_state, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) drm_atomic_helper_commit_modeset_enables(drm, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) drm_atomic_helper_commit_hw_done(old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) drm_atomic_helper_wait_for_vblanks(drm, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) drm_atomic_helper_cleanup_planes(drm, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) drm_atomic_helper_commit_tail_rpm(old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static const struct drm_mode_config_helper_funcs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) tegra_drm_mode_config_helpers = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .atomic_commit_tail = tegra_atomic_commit_tail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct tegra_drm_file *fpriv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!fpriv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) idr_init_base(&fpriv->contexts, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) mutex_init(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) filp->driver_priv = fpriv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void tegra_drm_context_free(struct tegra_drm_context *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) context->client->ops->close_channel(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) kfree(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static struct host1x_bo *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) host1x_bo_lookup(struct drm_file *file, u32 handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct drm_gem_object *gem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct tegra_bo *bo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) gem = drm_gem_object_lookup(file, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!gem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) bo = to_tegra_bo(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return &bo->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct drm_tegra_reloc __user *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct drm_device *drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) u32 cmdbuf, target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) err = get_user(cmdbuf, &src->cmdbuf.handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) err = get_user(dest->cmdbuf.offset, &src->cmdbuf.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) err = get_user(target, &src->target.handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) err = get_user(dest->target.offset, &src->target.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) err = get_user(dest->shift, &src->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dest->flags = HOST1X_RELOC_READ | HOST1X_RELOC_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) dest->cmdbuf.bo = host1x_bo_lookup(file, cmdbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!dest->cmdbuf.bo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dest->target.bo = host1x_bo_lookup(file, target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!dest->target.bo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int tegra_drm_submit(struct tegra_drm_context *context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct drm_tegra_submit *args, struct drm_device *drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct host1x_client *client = &context->client->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned int num_cmdbufs = args->num_cmdbufs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int num_relocs = args->num_relocs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct drm_tegra_cmdbuf __user *user_cmdbufs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct drm_tegra_reloc __user *user_relocs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct drm_tegra_syncpt __user *user_syncpt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct drm_tegra_syncpt syncpt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct drm_gem_object **refs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct host1x_syncpt *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct host1x_job *job;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) unsigned int num_refs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) user_cmdbufs = u64_to_user_ptr(args->cmdbufs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) user_relocs = u64_to_user_ptr(args->relocs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) user_syncpt = u64_to_user_ptr(args->syncpts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* We don't yet support other than one syncpt_incr struct per submit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (args->num_syncpts != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /* We don't yet support waitchks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (args->num_waitchks != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) job = host1x_job_alloc(context->channel, args->num_cmdbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) args->num_relocs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (!job)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) job->num_relocs = args->num_relocs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) job->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) job->class = client->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) job->serialize = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * Track referenced BOs so that they can be unreferenced after the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * submission is complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) num_refs = num_cmdbufs + num_relocs * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) refs = kmalloc_array(num_refs, sizeof(*refs), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (!refs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* reuse as an iterator later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) num_refs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) while (num_cmdbufs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct drm_tegra_cmdbuf cmdbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct host1x_bo *bo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct tegra_bo *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u64 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (copy_from_user(&cmdbuf, user_cmdbufs, sizeof(cmdbuf))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * The maximum number of CDMA gather fetches is 16383, a higher
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * value means the words count is malformed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (cmdbuf.words > CDMA_GATHER_FETCHES_MAX_NB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) bo = host1x_bo_lookup(file, cmdbuf.handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (!bo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) offset = (u64)cmdbuf.offset + (u64)cmdbuf.words * sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) obj = host1x_to_tegra_bo(bo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) refs[num_refs++] = &obj->gem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * Gather buffer base address must be 4-bytes aligned,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * unaligned offset is malformed and cause commands stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * corruption on the buffer address relocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (offset & 3 || offset > obj->gem.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) num_cmdbufs--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) user_cmdbufs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* copy and resolve relocations from submit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) while (num_relocs--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct host1x_reloc *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct tegra_bo *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) err = host1x_reloc_copy_from_user(&job->relocs[num_relocs],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) &user_relocs[num_relocs], drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) reloc = &job->relocs[num_relocs];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) obj = host1x_to_tegra_bo(reloc->cmdbuf.bo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) refs[num_refs++] = &obj->gem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * The unaligned cmdbuf offset will cause an unaligned write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * during of the relocations patching, corrupting the commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * stream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (reloc->cmdbuf.offset & 3 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) reloc->cmdbuf.offset >= obj->gem.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) obj = host1x_to_tegra_bo(reloc->target.bo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) refs[num_refs++] = &obj->gem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (reloc->target.offset >= obj->gem.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (copy_from_user(&syncpt, user_syncpt, sizeof(syncpt))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* check whether syncpoint ID is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) sp = host1x_syncpt_get(host1x, syncpt.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (!sp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) job->is_addr_reg = context->client->ops->is_addr_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) job->is_valid_class = context->client->ops->is_valid_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) job->syncpt_incrs = syncpt.incrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) job->syncpt_id = syncpt.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) job->timeout = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (args->timeout && args->timeout < 10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) job->timeout = args->timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) err = host1x_job_pin(job, context->client->base.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) err = host1x_job_submit(job);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) host1x_job_unpin(job);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) args->fence = job->syncpt_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) while (num_refs--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) drm_gem_object_put(refs[num_refs]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) kfree(refs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) host1x_job_put(job);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) #ifdef CONFIG_DRM_TEGRA_STAGING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static int tegra_gem_create(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct drm_tegra_gem_create *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct tegra_bo *bo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) bo = tegra_bo_create_with_handle(file, drm, args->size, args->flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) &args->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (IS_ERR(bo))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return PTR_ERR(bo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static int tegra_gem_mmap(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct drm_tegra_gem_mmap *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct drm_gem_object *gem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct tegra_bo *bo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) gem = drm_gem_object_lookup(file, args->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (!gem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) bo = to_tegra_bo(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) drm_gem_object_put(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int tegra_syncpt_read(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct host1x *host = dev_get_drvdata(drm->dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct drm_tegra_syncpt_read *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct host1x_syncpt *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) sp = host1x_syncpt_get(host, args->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (!sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) args->value = host1x_syncpt_read_min(sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static int tegra_syncpt_incr(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct drm_tegra_syncpt_incr *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct host1x_syncpt *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) sp = host1x_syncpt_get(host1x, args->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (!sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return host1x_syncpt_incr(sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static int tegra_syncpt_wait(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct drm_tegra_syncpt_wait *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct host1x_syncpt *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) sp = host1x_syncpt_get(host1x, args->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (!sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return host1x_syncpt_wait(sp, args->thresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) msecs_to_jiffies(args->timeout),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) &args->value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static int tegra_client_open(struct tegra_drm_file *fpriv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) struct tegra_drm_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct tegra_drm_context *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) err = client->ops->open_channel(client, context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) err = idr_alloc(&fpriv->contexts, context, 1, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) client->ops->close_channel(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) context->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) context->id = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static int tegra_open_channel(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct tegra_drm_file *fpriv = file->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct tegra_drm *tegra = drm->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct drm_tegra_open_channel *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct tegra_drm_context *context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct tegra_drm_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) int err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) context = kzalloc(sizeof(*context), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (!context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) mutex_lock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) list_for_each_entry(client, &tegra->clients, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (client->base.class == args->client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) err = tegra_client_open(fpriv, client, context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) args->context = context->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) kfree(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) mutex_unlock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static int tegra_close_channel(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct tegra_drm_file *fpriv = file->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct drm_tegra_close_channel *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct tegra_drm_context *context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) mutex_lock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) context = idr_find(&fpriv->contexts, args->context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (!context) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) idr_remove(&fpriv->contexts, context->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) tegra_drm_context_free(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) mutex_unlock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) static int tegra_get_syncpt(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct tegra_drm_file *fpriv = file->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct drm_tegra_get_syncpt *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct tegra_drm_context *context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct host1x_syncpt *syncpt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) mutex_lock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) context = idr_find(&fpriv->contexts, args->context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (!context) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (args->index >= context->client->base.num_syncpts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) syncpt = context->client->base.syncpts[args->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) args->id = host1x_syncpt_id(syncpt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) mutex_unlock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int tegra_submit(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct tegra_drm_file *fpriv = file->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct drm_tegra_submit *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct tegra_drm_context *context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mutex_lock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) context = idr_find(&fpriv->contexts, args->context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (!context) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) err = context->client->ops->submit(context, args, drm, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) mutex_unlock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct tegra_drm_file *fpriv = file->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct drm_tegra_get_syncpt_base *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct tegra_drm_context *context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct host1x_syncpt_base *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct host1x_syncpt *syncpt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mutex_lock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) context = idr_find(&fpriv->contexts, args->context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (!context) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (args->syncpt >= context->client->base.num_syncpts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) syncpt = context->client->base.syncpts[args->syncpt];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) base = host1x_syncpt_get_base(syncpt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (!base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) args->id = host1x_syncpt_base_id(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) mutex_unlock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct drm_tegra_gem_set_tiling *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) enum tegra_bo_tiling_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct drm_gem_object *gem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) unsigned long value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct tegra_bo *bo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) switch (args->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) case DRM_TEGRA_GEM_TILING_MODE_PITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) mode = TEGRA_BO_TILING_MODE_PITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (args->value != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) case DRM_TEGRA_GEM_TILING_MODE_TILED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) mode = TEGRA_BO_TILING_MODE_TILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (args->value != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) case DRM_TEGRA_GEM_TILING_MODE_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) mode = TEGRA_BO_TILING_MODE_BLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (args->value > 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) value = args->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) gem = drm_gem_object_lookup(file, args->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (!gem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) bo = to_tegra_bo(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) bo->tiling.mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) bo->tiling.value = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) drm_gem_object_put(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct drm_tegra_gem_get_tiling *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct drm_gem_object *gem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct tegra_bo *bo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) gem = drm_gem_object_lookup(file, args->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (!gem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) bo = to_tegra_bo(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) switch (bo->tiling.mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) case TEGRA_BO_TILING_MODE_PITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) args->value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) case TEGRA_BO_TILING_MODE_TILED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) args->value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) case TEGRA_BO_TILING_MODE_BLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) args->value = bo->tiling.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) drm_gem_object_put(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) static int tegra_gem_set_flags(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct drm_tegra_gem_set_flags *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct drm_gem_object *gem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct tegra_bo *bo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (args->flags & ~DRM_TEGRA_GEM_FLAGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) gem = drm_gem_object_lookup(file, args->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (!gem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) bo = to_tegra_bo(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) bo->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) bo->flags |= TEGRA_BO_BOTTOM_UP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) drm_gem_object_put(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static int tegra_gem_get_flags(struct drm_device *drm, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct drm_tegra_gem_get_flags *args = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct drm_gem_object *gem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct tegra_bo *bo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) gem = drm_gem_object_lookup(file, args->handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (!gem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) bo = to_tegra_bo(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) args->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (bo->flags & TEGRA_BO_BOTTOM_UP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) drm_gem_object_put(gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) #ifdef CONFIG_DRM_TEGRA_STAGING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) DRM_RENDER_ALLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static const struct file_operations tegra_drm_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) .open = drm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) .release = drm_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .unlocked_ioctl = drm_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .mmap = tegra_drm_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .poll = drm_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .read = drm_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .compat_ioctl = drm_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .llseek = noop_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) static int tegra_drm_context_cleanup(int id, void *p, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) struct tegra_drm_context *context = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) tegra_drm_context_free(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static void tegra_drm_postclose(struct drm_device *drm, struct drm_file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct tegra_drm_file *fpriv = file->driver_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) mutex_lock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) idr_for_each(&fpriv->contexts, tegra_drm_context_cleanup, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) mutex_unlock(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) idr_destroy(&fpriv->contexts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) mutex_destroy(&fpriv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) kfree(fpriv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static int tegra_debugfs_framebuffers(struct seq_file *s, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct drm_info_node *node = (struct drm_info_node *)s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct drm_device *drm = node->minor->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct drm_framebuffer *fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) mutex_lock(&drm->mode_config.fb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) list_for_each_entry(fb, &drm->mode_config.fb_list, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) fb->base.id, fb->width, fb->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) fb->format->depth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) fb->format->cpp[0] * 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) drm_framebuffer_read_refcount(fb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) mutex_unlock(&drm->mode_config.fb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static int tegra_debugfs_iova(struct seq_file *s, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct drm_info_node *node = (struct drm_info_node *)s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct drm_device *drm = node->minor->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct tegra_drm *tegra = drm->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) struct drm_printer p = drm_seq_file_printer(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) mutex_lock(&tegra->mm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) drm_mm_print(&tegra->mm, &p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) mutex_unlock(&tegra->mm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static struct drm_info_list tegra_debugfs_list[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) { "framebuffers", tegra_debugfs_framebuffers, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) { "iova", tegra_debugfs_iova, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static void tegra_debugfs_init(struct drm_minor *minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) drm_debugfs_create_files(tegra_debugfs_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) ARRAY_SIZE(tegra_debugfs_list),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) minor->debugfs_root, minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) static struct drm_driver tegra_drm_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) .driver_features = DRIVER_MODESET | DRIVER_GEM |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) DRIVER_ATOMIC | DRIVER_RENDER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) .open = tegra_drm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .postclose = tegra_drm_postclose,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .lastclose = drm_fb_helper_lastclose,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) #if defined(CONFIG_DEBUG_FS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .debugfs_init = tegra_debugfs_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .gem_free_object_unlocked = tegra_bo_free_object,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .gem_vm_ops = &tegra_bo_vm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) .gem_prime_export = tegra_gem_prime_export,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) .gem_prime_import = tegra_gem_prime_import,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) .dumb_create = tegra_bo_dumb_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .ioctls = tegra_drm_ioctls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .fops = &tegra_drm_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .desc = DRIVER_DESC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .date = DRIVER_DATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) .major = DRIVER_MAJOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) .minor = DRIVER_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) .patchlevel = DRIVER_PATCHLEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) int tegra_drm_register_client(struct tegra_drm *tegra,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct tegra_drm_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) mutex_lock(&tegra->clients_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) list_add_tail(&client->list, &tegra->clients);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) client->drm = tegra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) mutex_unlock(&tegra->clients_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) int tegra_drm_unregister_client(struct tegra_drm *tegra,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct tegra_drm_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) mutex_lock(&tegra->clients_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) list_del_init(&client->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) client->drm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) mutex_unlock(&tegra->clients_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int host1x_client_iommu_attach(struct host1x_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) struct iommu_domain *domain = iommu_get_domain_for_dev(client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct drm_device *drm = dev_get_drvdata(client->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) struct tegra_drm *tegra = drm->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct iommu_group *group = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * If the host1x client is already attached to an IOMMU domain that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * not the shared IOMMU domain, don't try to attach it to a different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * domain. This allows using the IOMMU-backed DMA API.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (domain && domain != tegra->domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) group = iommu_group_get(client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (!group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (domain != tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) err = iommu_attach_group(tegra->domain, group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) iommu_group_put(group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) tegra->use_explicit_iommu = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) client->group = group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) void host1x_client_iommu_detach(struct host1x_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct drm_device *drm = dev_get_drvdata(client->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct tegra_drm *tegra = drm->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) struct iommu_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (client->group) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * Devices that are part of the same group may no longer be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * attached to a domain at this point because their group may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) * have been detached by an earlier client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) domain = iommu_get_domain_for_dev(client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) iommu_detach_group(tegra->domain, client->group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) iommu_group_put(client->group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) client->group = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct iova *alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) void *virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) gfp_t gfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (tegra->domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) size = iova_align(&tegra->carveout.domain, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) size = PAGE_ALIGN(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) gfp = GFP_KERNEL | __GFP_ZERO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (!tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) * Many units only support 32-bit addresses, even on 64-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * SoCs. If there is no IOMMU to translate into a 32-bit IO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * virtual address space, force allocations to be in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * lower 32-bit range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) gfp |= GFP_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) virt = (void *)__get_free_pages(gfp, get_order(size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (!virt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (!tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * If IOMMU is disabled, devices address physical memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * directly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) *dma = virt_to_phys(virt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) alloc = alloc_iova(&tegra->carveout.domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) size >> tegra->carveout.shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) tegra->carveout.limit, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (!alloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) goto free_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *dma = iova_dma_addr(&tegra->carveout.domain, alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) err = iommu_map(tegra->domain, *dma, virt_to_phys(virt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) size, IOMMU_READ | IOMMU_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) goto free_iova;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) free_iova:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) __free_iova(&tegra->carveout.domain, alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) free_pages:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) free_pages((unsigned long)virt, get_order(size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) dma_addr_t dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (tegra->domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) size = iova_align(&tegra->carveout.domain, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) size = PAGE_ALIGN(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) iommu_unmap(tegra->domain, dma, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) free_iova(&tegra->carveout.domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) iova_pfn(&tegra->carveout.domain, dma));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) free_pages((unsigned long)virt, get_order(size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static bool host1x_drm_wants_iommu(struct host1x_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct host1x *host1x = dev_get_drvdata(dev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) struct iommu_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) * If the Tegra DRM clients are backed by an IOMMU, push buffers are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * likely to be allocated beyond the 32-bit boundary if sufficient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) * system memory is available. This is problematic on earlier Tegra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) * generations where host1x supports a maximum of 32 address bits in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) * the GATHER opcode. In this case, unless host1x is behind an IOMMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) * as well it won't be able to process buffers allocated beyond the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) * 32-bit boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) * The DMA API will use bounce buffers in this case, so that could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * perhaps still be made to work, even if less efficient, but there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * is another catch: in order to perform cache maintenance on pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * allocated for discontiguous buffers we need to map and unmap the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * SG table representing these buffers. This is fine for something
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * small like a push buffer, but it exhausts the bounce buffer pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * (typically on the order of a few MiB) for framebuffers (many MiB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * for any modern resolution).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) * Work around this by making sure that Tegra DRM clients only use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * an IOMMU if the parent host1x also uses an IOMMU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * Note that there's still a small gap here that we don't cover: if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * the DMA API is backed by an IOMMU there's no way to control which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * device is attached to an IOMMU and which isn't, except via wiring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) * up the device tree appropriately. This is considered an problem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) * of integration, so care must be taken for the DT to be consistent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) domain = iommu_get_domain_for_dev(dev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * Tegra20 and Tegra30 don't support addressing memory beyond the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * 32-bit boundary, so the regular GATHER opcodes will always be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) * sufficient and whether or not the host1x is attached to an IOMMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) * doesn't matter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (!domain && host1x_get_dma_mask(host1x) <= DMA_BIT_MASK(32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return domain != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static int host1x_drm_probe(struct host1x_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) struct drm_driver *driver = &tegra_drm_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) struct tegra_drm *tegra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) struct drm_device *drm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) drm = drm_dev_alloc(driver, &dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (IS_ERR(drm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return PTR_ERR(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (!tegra) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) goto put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (host1x_drm_wants_iommu(dev) && iommu_present(&platform_bus_type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) tegra->domain = iommu_domain_alloc(&platform_bus_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (!tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) err = iova_cache_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) goto domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) mutex_init(&tegra->clients_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) INIT_LIST_HEAD(&tegra->clients);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) dev_set_drvdata(&dev->dev, drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) drm->dev_private = tegra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) tegra->drm = drm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) drm_mode_config_init(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) drm->mode_config.min_width = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) drm->mode_config.min_height = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) drm->mode_config.max_width = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) drm->mode_config.max_height = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) drm->mode_config.normalize_zpos = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) drm->mode_config.funcs = &tegra_drm_mode_config_funcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) drm->mode_config.helper_private = &tegra_drm_mode_config_helpers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) err = tegra_drm_fb_prepare(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) goto config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) drm_kms_helper_poll_init(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) err = host1x_device_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) goto fbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (tegra->use_explicit_iommu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) u64 carveout_start, carveout_end, gem_start, gem_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) u64 dma_mask = dma_get_mask(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) dma_addr_t start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) unsigned long order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) start = tegra->domain->geometry.aperture_start & dma_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) end = tegra->domain->geometry.aperture_end & dma_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) gem_start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) gem_end = end - CARVEOUT_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) carveout_start = gem_end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) carveout_end = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) order = __ffs(tegra->domain->pgsize_bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) init_iova_domain(&tegra->carveout.domain, 1UL << order,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) carveout_start >> order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) tegra->carveout.shift = iova_shift(&tegra->carveout.domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) tegra->carveout.limit = carveout_end >> tegra->carveout.shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) drm_mm_init(&tegra->mm, gem_start, gem_end - gem_start + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) mutex_init(&tegra->mm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) DRM_DEBUG_DRIVER("IOMMU apertures:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) DRM_DEBUG_DRIVER(" GEM: %#llx-%#llx\n", gem_start, gem_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) DRM_DEBUG_DRIVER(" Carveout: %#llx-%#llx\n", carveout_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) carveout_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) } else if (tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) iommu_domain_free(tegra->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) tegra->domain = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) iova_cache_put();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (tegra->hub) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) err = tegra_display_hub_prepare(tegra->hub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) goto device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) * We don't use the drm_irq_install() helpers provided by the DRM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * core, so we need to set this manually in order to allow the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) * DRM_IOCTL_WAIT_VBLANK to operate correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) drm->irq_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /* syncpoints are used for full 32-bit hardware VBLANK counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) drm->max_vblank_count = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) err = drm_vblank_init(drm, drm->mode_config.num_crtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) goto hub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) drm_mode_config_reset(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) err = drm_fb_helper_remove_conflicting_framebuffers(NULL, "tegradrmfb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) goto hub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) err = tegra_drm_fb_init(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) goto hub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) err = drm_dev_register(drm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) goto fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) tegra_drm_fb_exit(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) hub:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (tegra->hub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) tegra_display_hub_cleanup(tegra->hub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) mutex_destroy(&tegra->mm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) drm_mm_takedown(&tegra->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) put_iova_domain(&tegra->carveout.domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) iova_cache_put();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) host1x_device_exit(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) fbdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) drm_kms_helper_poll_fini(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) tegra_drm_fb_free(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) config:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) drm_mode_config_cleanup(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) domain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (tegra->domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) iommu_domain_free(tegra->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) kfree(tegra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) drm_dev_put(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) static int host1x_drm_remove(struct host1x_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) struct drm_device *drm = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) struct tegra_drm *tegra = drm->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) drm_dev_unregister(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) drm_kms_helper_poll_fini(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) tegra_drm_fb_exit(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) drm_atomic_helper_shutdown(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) drm_mode_config_cleanup(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (tegra->hub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) tegra_display_hub_cleanup(tegra->hub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) err = host1x_device_exit(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) dev_err(&dev->dev, "host1x device cleanup failed: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (tegra->domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) mutex_destroy(&tegra->mm_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) drm_mm_takedown(&tegra->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) put_iova_domain(&tegra->carveout.domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) iova_cache_put();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) iommu_domain_free(tegra->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) kfree(tegra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) drm_dev_put(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) static int host1x_drm_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) struct drm_device *drm = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) return drm_mode_config_helper_suspend(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) static int host1x_drm_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) struct drm_device *drm = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return drm_mode_config_helper_resume(drm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) static SIMPLE_DEV_PM_OPS(host1x_drm_pm_ops, host1x_drm_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) host1x_drm_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) static const struct of_device_id host1x_drm_subdevs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) { .compatible = "nvidia,tegra20-dc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) { .compatible = "nvidia,tegra20-hdmi", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) { .compatible = "nvidia,tegra20-gr2d", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) { .compatible = "nvidia,tegra20-gr3d", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) { .compatible = "nvidia,tegra30-dc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) { .compatible = "nvidia,tegra30-hdmi", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) { .compatible = "nvidia,tegra30-gr2d", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) { .compatible = "nvidia,tegra30-gr3d", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) { .compatible = "nvidia,tegra114-dsi", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) { .compatible = "nvidia,tegra114-hdmi", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) { .compatible = "nvidia,tegra114-gr3d", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) { .compatible = "nvidia,tegra124-dc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) { .compatible = "nvidia,tegra124-sor", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) { .compatible = "nvidia,tegra124-hdmi", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) { .compatible = "nvidia,tegra124-dsi", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) { .compatible = "nvidia,tegra124-vic", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) { .compatible = "nvidia,tegra132-dsi", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) { .compatible = "nvidia,tegra210-dc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) { .compatible = "nvidia,tegra210-dsi", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) { .compatible = "nvidia,tegra210-sor", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) { .compatible = "nvidia,tegra210-sor1", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) { .compatible = "nvidia,tegra210-vic", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) { .compatible = "nvidia,tegra186-display", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) { .compatible = "nvidia,tegra186-dc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) { .compatible = "nvidia,tegra186-sor", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) { .compatible = "nvidia,tegra186-sor1", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) { .compatible = "nvidia,tegra186-vic", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) { .compatible = "nvidia,tegra194-display", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) { .compatible = "nvidia,tegra194-dc", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) { .compatible = "nvidia,tegra194-sor", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) { .compatible = "nvidia,tegra194-vic", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) static struct host1x_driver host1x_drm_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) .name = "drm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) .pm = &host1x_drm_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) .probe = host1x_drm_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) .remove = host1x_drm_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) .subdevs = host1x_drm_subdevs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) static struct platform_driver * const drivers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) &tegra_display_hub_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) &tegra_dc_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) &tegra_hdmi_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) &tegra_dsi_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) &tegra_dpaux_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) &tegra_sor_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) &tegra_gr2d_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) &tegra_gr3d_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) &tegra_vic_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) static int __init host1x_drm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) err = host1x_driver_register(&host1x_drm_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) err = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) goto unregister_host1x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) unregister_host1x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) host1x_driver_unregister(&host1x_drm_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) module_init(host1x_drm_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) static void __exit host1x_drm_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) host1x_driver_unregister(&host1x_drm_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) module_exit(host1x_drm_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) MODULE_LICENSE("GPL v2");