diff options
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r-- | drivers/gpu/drm/tegra/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 114 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dpaux.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 239 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dsi.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/fb.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.c | 83 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gr2d.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gr3d.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/hdmi.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/rgb.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/sor.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/trace.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/trace.h | 68 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/vic.c | 19 |
18 files changed, 464 insertions, 165 deletions
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index 2db29d67193d..dc58ab140151 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig @@ -3,6 +3,7 @@ config DRM_TEGRA depends on ARCH_TEGRA || (ARM && COMPILE_TEST) depends on COMMON_CLK depends on DRM + depends on OF select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile index 6af3a9ad6565..8927784396e8 100644 --- a/drivers/gpu/drm/tegra/Makefile +++ b/drivers/gpu/drm/tegra/Makefile @@ -17,4 +17,6 @@ tegra-drm-y := \ falcon.o \ vic.o +tegra-drm-y += trace.o + obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 95b373f739f2..4df39112e38e 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -30,6 +30,7 @@ struct tegra_dc_soc_info { bool supports_block_linear; unsigned int pitch_align; bool has_powergate; + bool broken_reset; }; struct tegra_plane { @@ -485,12 +486,25 @@ static int tegra_plane_state_add(struct tegra_plane *plane, { struct drm_crtc_state *crtc_state; struct tegra_dc_state *tegra; + struct drm_rect clip; + int err; /* Propagate errors from allocation or locking failures. */ crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); + clip.x1 = 0; + clip.y1 = 0; + clip.x2 = crtc_state->mode.hdisplay; + clip.y2 = crtc_state->mode.vdisplay; + + /* Check plane state for visibility and calculate clipping bounds */ + err = drm_plane_helper_check_state(state, &clip, 0, INT_MAX, + true, true); + if (err < 0) + return err; + tegra = to_dc_state(crtc_state); tegra->planes |= WIN_A_ACT_REQ << plane->index; @@ -545,6 +559,23 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, return 0; } +static void tegra_dc_disable_window(struct tegra_dc *dc, int index) +{ + unsigned long flags; + u32 value; + + spin_lock_irqsave(&dc->lock, flags); + + value = WINDOW_A_SELECT << index; + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); + + value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS); + value &= ~WIN_ENABLE; + tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); + + spin_unlock_irqrestore(&dc->lock, flags); +} + static void tegra_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { @@ -559,15 +590,18 @@ static void tegra_plane_atomic_update(struct drm_plane *plane, if (!plane->state->crtc || !plane->state->fb) return; + if (!plane->state->visible) + return tegra_dc_disable_window(dc, p->index); + memset(&window, 0, sizeof(window)); - window.src.x = plane->state->src_x >> 16; - window.src.y = plane->state->src_y >> 16; - window.src.w = plane->state->src_w >> 16; - window.src.h = plane->state->src_h >> 16; - window.dst.x = plane->state->crtc_x; - window.dst.y = plane->state->crtc_y; - window.dst.w = plane->state->crtc_w; - window.dst.h = plane->state->crtc_h; + window.src.x = plane->state->src.x1 >> 16; + window.src.y = plane->state->src.y1 >> 16; + window.src.w = drm_rect_width(&plane->state->src) >> 16; + window.src.h = drm_rect_height(&plane->state->src) >> 16; + window.dst.x = plane->state->dst.x1; + window.dst.y = plane->state->dst.y1; + window.dst.w = drm_rect_width(&plane->state->dst); + window.dst.h = drm_rect_height(&plane->state->dst); window.bits_per_pixel = fb->format->cpp[0] * 8; window.bottom_up = tegra_fb_is_bottom_up(fb); @@ -598,8 +632,6 @@ static void tegra_plane_atomic_disable(struct drm_plane *plane, { struct tegra_plane *p = to_tegra_plane(plane); struct tegra_dc *dc; - unsigned long flags; - u32 value; /* rien ne va plus */ if (!old_state || !old_state->crtc) @@ -607,16 +639,7 @@ static void tegra_plane_atomic_disable(struct drm_plane *plane, dc = to_tegra_dc(old_state->crtc); - spin_lock_irqsave(&dc->lock, flags); - - value = WINDOW_A_SELECT << p->index; - tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); - - value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS); - value &= ~WIN_ENABLE; - tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); - - spin_unlock_irqrestore(&dc->lock, flags); + tegra_dc_disable_window(dc, p->index); } static const struct drm_plane_helper_funcs tegra_primary_plane_helper_funcs = { @@ -655,8 +678,8 @@ static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm, err = drm_universal_plane_init(drm, &plane->base, possible_crtcs, &tegra_primary_plane_funcs, formats, - num_formats, DRM_PLANE_TYPE_PRIMARY, - NULL); + num_formats, NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); if (err < 0) { kfree(plane); return ERR_PTR(err); @@ -821,8 +844,8 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm, err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe, &tegra_cursor_plane_funcs, formats, - num_formats, DRM_PLANE_TYPE_CURSOR, - NULL); + num_formats, NULL, + DRM_PLANE_TYPE_CURSOR, NULL); if (err < 0) { kfree(plane); return ERR_PTR(err); @@ -883,8 +906,8 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, err = drm_universal_plane_init(drm, &plane->base, 1 << dc->pipe, &tegra_overlay_plane_funcs, formats, - num_formats, DRM_PLANE_TYPE_OVERLAY, - NULL); + num_formats, NULL, + DRM_PLANE_TYPE_OVERLAY, NULL); if (err < 0) { kfree(plane); return ERR_PTR(err); @@ -1176,7 +1199,8 @@ static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout) return -ETIMEDOUT; } -static void tegra_crtc_disable(struct drm_crtc *crtc) +static void tegra_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct tegra_dc *dc = to_tegra_dc(crtc); u32 value; @@ -1220,7 +1244,8 @@ static void tegra_crtc_disable(struct drm_crtc *crtc) pm_runtime_put_sync(dc->dev); } -static void tegra_crtc_enable(struct drm_crtc *crtc) +static void tegra_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { struct drm_display_mode *mode = &crtc->state->adjusted_mode; struct tegra_dc_state *state = to_dc_state(crtc->state); @@ -1328,11 +1353,11 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { - .disable = tegra_crtc_disable, - .enable = tegra_crtc_enable, .atomic_check = tegra_crtc_atomic_check, .atomic_begin = tegra_crtc_atomic_begin, .atomic_flush = tegra_crtc_atomic_flush, + .atomic_enable = tegra_crtc_atomic_enable, + .atomic_disable = tegra_crtc_atomic_disable, }; static irqreturn_t tegra_dc_irq(int irq, void *data) @@ -1856,6 +1881,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = { .supports_block_linear = false, .pitch_align = 8, .has_powergate = false, + .broken_reset = true, }; static const struct tegra_dc_soc_info tegra30_dc_soc_info = { @@ -1865,6 +1891,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = { .supports_block_linear = false, .pitch_align = 8, .has_powergate = false, + .broken_reset = false, }; static const struct tegra_dc_soc_info tegra114_dc_soc_info = { @@ -1874,6 +1901,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = { .supports_block_linear = false, .pitch_align = 64, .has_powergate = true, + .broken_reset = false, }; static const struct tegra_dc_soc_info tegra124_dc_soc_info = { @@ -1883,6 +1911,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = { .supports_block_linear = true, .pitch_align = 64, .has_powergate = true, + .broken_reset = false, }; static const struct tegra_dc_soc_info tegra210_dc_soc_info = { @@ -1892,6 +1921,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = { .supports_block_linear = true, .pitch_align = 64, .has_powergate = true, + .broken_reset = false, }; static const struct of_device_id tegra_dc_of_match[] = { @@ -1989,7 +2019,8 @@ static int tegra_dc_probe(struct platform_device *pdev) return PTR_ERR(dc->rst); } - reset_control_assert(dc->rst); + if (!dc->soc->broken_reset) + reset_control_assert(dc->rst); if (dc->soc->has_powergate) { if (dc->pipe == 0) @@ -2063,10 +2094,12 @@ static int tegra_dc_suspend(struct device *dev) struct tegra_dc *dc = dev_get_drvdata(dev); int err; - err = reset_control_assert(dc->rst); - if (err < 0) { - dev_err(dev, "failed to assert reset: %d\n", err); - return err; + if (!dc->soc->broken_reset) { + err = reset_control_assert(dc->rst); + if (err < 0) { + dev_err(dev, "failed to assert reset: %d\n", err); + return err; + } } if (dc->soc->has_powergate) @@ -2096,10 +2129,13 @@ static int tegra_dc_resume(struct device *dev) return err; } - err = reset_control_deassert(dc->rst); - if (err < 0) { - dev_err(dev, "failed to deassert reset: %d\n", err); - return err; + if (!dc->soc->broken_reset) { + err = reset_control_deassert(dc->rst); + if (err < 0) { + dev_err(dev, + "failed to deassert reset: %d\n", err); + return err; + } } } diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 2fde44c3a1b3..e4da041ba89b 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -25,6 +25,7 @@ #include "dpaux.h" #include "drm.h" +#include "trace.h" static DEFINE_MUTEX(dpaux_lock); static LIST_HEAD(dpaux_list); @@ -65,14 +66,19 @@ static inline struct tegra_dpaux *work_to_dpaux(struct work_struct *work) } static inline u32 tegra_dpaux_readl(struct tegra_dpaux *dpaux, - unsigned long offset) + unsigned int offset) { - return readl(dpaux->regs + (offset << 2)); + u32 value = readl(dpaux->regs + (offset << 2)); + + trace_dpaux_readl(dpaux->dev, offset, value); + + return value; } static inline void tegra_dpaux_writel(struct tegra_dpaux *dpaux, - u32 value, unsigned long offset) + u32 value, unsigned int offset) { + trace_dpaux_writel(dpaux->dev, offset, value); writel(value, dpaux->regs + (offset << 2)); } diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 81f86a67c10d..597d563d636a 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -26,6 +26,7 @@ #define DRIVER_PATCHLEVEL 0 #define CARVEOUT_SZ SZ_64M +#define CDMA_GATHER_FETCHES_MAX_NB 16383 struct tegra_drm_file { struct idr contexts; @@ -99,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm, * the software side now. */ - drm_atomic_helper_swap_state(state, true); + err = drm_atomic_helper_swap_state(state, true); + if (err) { + mutex_unlock(&tegra->commit.lock); + drm_atomic_helper_cleanup_planes(drm, state); + return err; + } drm_atomic_state_get(state); if (nonblock) @@ -213,12 +219,10 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) err = tegra_drm_fb_init(drm); if (err < 0) - goto vblank; + goto device; return 0; -vblank: - drm_vblank_cleanup(drm); device: host1x_device_exit(device); fbdev: @@ -247,7 +251,6 @@ static void tegra_drm_unload(struct drm_device *drm) drm_kms_helper_poll_fini(drm); tegra_drm_fb_exit(drm); drm_mode_config_cleanup(drm); - drm_vblank_cleanup(drm); err = host1x_device_exit(device); if (err < 0) @@ -303,8 +306,6 @@ host1x_bo_lookup(struct drm_file *file, u32 handle) if (!gem) return NULL; - drm_gem_object_unreference_unlocked(gem); - bo = to_tegra_bo(gem); return &bo->base; } @@ -348,6 +349,36 @@ static int host1x_reloc_copy_from_user(struct host1x_reloc *dest, return 0; } +static int host1x_waitchk_copy_from_user(struct host1x_waitchk *dest, + struct drm_tegra_waitchk __user *src, + struct drm_file *file) +{ + u32 cmdbuf; + int err; + + err = get_user(cmdbuf, &src->handle); + if (err < 0) + return err; + + err = get_user(dest->offset, &src->offset); + if (err < 0) + return err; + + err = get_user(dest->syncpt_id, &src->syncpt); + if (err < 0) + return err; + + err = get_user(dest->thresh, &src->thresh); + if (err < 0) + return err; + + dest->bo = host1x_bo_lookup(file, cmdbuf); + if (!dest->bo) + return -ENOENT; + + return 0; +} + int tegra_drm_submit(struct tegra_drm_context *context, struct drm_tegra_submit *args, struct drm_device *drm, struct drm_file *file) @@ -362,13 +393,21 @@ int tegra_drm_submit(struct tegra_drm_context *context, struct drm_tegra_waitchk __user *waitchks = (void __user *)(uintptr_t)args->waitchks; struct drm_tegra_syncpt syncpt; + struct host1x *host1x = dev_get_drvdata(drm->dev->parent); + struct drm_gem_object **refs; + struct host1x_syncpt *sp; struct host1x_job *job; + unsigned int num_refs; int err; /* We don't yet support other than one syncpt_incr struct per submit */ if (args->num_syncpts != 1) return -EINVAL; + /* We don't yet support waitchks */ + if (args->num_waitchks != 0) + return -EINVAL; + job = host1x_job_alloc(context->channel, args->num_cmdbufs, args->num_relocs, args->num_waitchks); if (!job) @@ -380,21 +419,61 @@ int tegra_drm_submit(struct tegra_drm_context *context, job->class = context->client->base.class; job->serialize = true; + /* + * Track referenced BOs so that they can be unreferenced after the + * submission is complete. + */ + num_refs = num_cmdbufs + num_relocs * 2 + num_waitchks; + + refs = kmalloc_array(num_refs, sizeof(*refs), GFP_KERNEL); + if (!refs) { + err = -ENOMEM; + goto put; + } + + /* reuse as an iterator later */ + num_refs = 0; + while (num_cmdbufs) { struct drm_tegra_cmdbuf cmdbuf; struct host1x_bo *bo; + struct tegra_bo *obj; + u64 offset; if (copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf))) { err = -EFAULT; goto fail; } + /* + * The maximum number of CDMA gather fetches is 16383, a higher + * value means the words count is malformed. + */ + if (cmdbuf.words > CDMA_GATHER_FETCHES_MAX_NB) { + err = -EINVAL; + goto fail; + } + bo = host1x_bo_lookup(file, cmdbuf.handle); if (!bo) { err = -ENOENT; goto fail; } + offset = (u64)cmdbuf.offset + (u64)cmdbuf.words * sizeof(u32); + obj = host1x_to_tegra_bo(bo); + refs[num_refs++] = &obj->gem; + + /* + * Gather buffer base address must be 4-bytes aligned, + * unaligned offset is malformed and cause commands stream + * corruption on the buffer address relocation. + */ + if (offset & 3 || offset >= obj->gem.size) { + err = -EINVAL; + goto fail; + } + host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset); num_cmdbufs--; cmdbufs++; @@ -402,17 +481,62 @@ int tegra_drm_submit(struct tegra_drm_context *context, /* copy and resolve relocations from submit */ while (num_relocs--) { + struct host1x_reloc *reloc; + struct tegra_bo *obj; + err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs], &relocs[num_relocs], drm, file); if (err < 0) goto fail; + + reloc = &job->relocarray[num_relocs]; + obj = host1x_to_tegra_bo(reloc->cmdbuf.bo); + refs[num_refs++] = &obj->gem; + + /* + * The unaligned cmdbuf offset will cause an unaligned write + * during of the relocations patching, corrupting the commands + * stream. + */ + if (reloc->cmdbuf.offset & 3 || + reloc->cmdbuf.offset >= obj->gem.size) { + err = -EINVAL; + goto fail; + } + + obj = host1x_to_tegra_bo(reloc->target.bo); + refs[num_refs++] = &obj->gem; + + if (reloc->target.offset >= obj->gem.size) { + err = -EINVAL; + goto fail; + } } - if (copy_from_user(job->waitchk, waitchks, - sizeof(*waitchks) * num_waitchks)) { - err = -EFAULT; - goto fail; + /* copy and resolve waitchks from submit */ + while (num_waitchks--) { + struct host1x_waitchk *wait = &job->waitchk[num_waitchks]; + struct tegra_bo *obj; + + err = host1x_waitchk_copy_from_user(wait, + &waitchks[num_waitchks], + file); + if (err < 0) + goto fail; + + obj = host1x_to_tegra_bo(wait->bo); + refs[num_refs++] = &obj->gem; + + /* + * The unaligned offset will cause an unaligned write during + * of the waitchks patching, corrupting the commands stream. + */ + if (wait->offset & 3 || + wait->offset >= obj->gem.size) { + err = -EINVAL; + goto fail; + } } if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts, @@ -421,7 +545,15 @@ int tegra_drm_submit(struct tegra_drm_context *context, goto fail; } + /* check whether syncpoint ID is valid */ + sp = host1x_syncpt_get(host1x, syncpt.id); + if (!sp) { + err = -ENOENT; + goto fail; + } + job->is_addr_reg = context->client->ops->is_addr_reg; + job->is_valid_class = context->client->ops->is_valid_class; job->syncpt_incrs = syncpt.incrs; job->syncpt_id = syncpt.id; job->timeout = 10000; @@ -434,17 +566,20 @@ int tegra_drm_submit(struct tegra_drm_context *context, goto fail; err = host1x_job_submit(job); - if (err) - goto fail_submit; + if (err) { + host1x_job_unpin(job); + goto fail; + } args->fence = job->syncpt_end; - host1x_job_put(job); - return 0; - -fail_submit: - host1x_job_unpin(job); fail: + while (num_refs--) + drm_gem_object_put_unlocked(refs[num_refs]); + + kfree(refs); + +put: host1x_job_put(job); return err; } @@ -480,7 +615,7 @@ static int tegra_gem_mmap(struct drm_device *drm, void *data, args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node); - drm_gem_object_unreference_unlocked(gem); + drm_gem_object_put_unlocked(gem); return 0; } @@ -747,7 +882,7 @@ static int tegra_gem_set_tiling(struct drm_device *drm, void *data, bo->tiling.mode = mode; bo->tiling.value = value; - drm_gem_object_unreference_unlocked(gem); + drm_gem_object_put_unlocked(gem); return 0; } @@ -787,7 +922,7 @@ static int tegra_gem_get_tiling(struct drm_device *drm, void *data, break; } - drm_gem_object_unreference_unlocked(gem); + drm_gem_object_put_unlocked(gem); return err; } @@ -812,7 +947,7 @@ static int tegra_gem_set_flags(struct drm_device *drm, void *data, if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP) bo->flags |= TEGRA_BO_BOTTOM_UP; - drm_gem_object_unreference_unlocked(gem); + drm_gem_object_put_unlocked(gem); return 0; } @@ -834,7 +969,7 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data, if (bo->flags & TEGRA_BO_BOTTOM_UP) args->flags |= DRM_TEGRA_GEM_BOTTOM_UP; - drm_gem_object_unreference_unlocked(gem); + drm_gem_object_put_unlocked(gem); return 0; } @@ -842,20 +977,34 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data, static const struct drm_ioctl_desc tegra_drm_ioctls[] = { #ifdef CONFIG_DRM_TEGRA_STAGING - DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, 0), - DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, 0), - DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, 0), - DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, 0), - DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, 0), - DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, 0), - DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, 0), - DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, 0), - DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, 0), - DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, 0), - DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, 0), - DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, 0), - DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, 0), - DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, 0), + DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, + DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, + DRM_UNLOCKED | DRM_RENDER_ALLOW), #endif }; @@ -880,7 +1029,7 @@ static int tegra_drm_context_cleanup(int id, void *p, void *data) return 0; } -static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file) +static void tegra_drm_postclose(struct drm_device *drm, struct drm_file *file) { struct tegra_drm_file *fpriv = file->driver_priv; @@ -922,9 +1071,11 @@ static int tegra_debugfs_iova(struct seq_file *s, void *data) struct tegra_drm *tegra = drm->dev_private; struct drm_printer p = drm_seq_file_printer(s); - mutex_lock(&tegra->mm_lock); - drm_mm_print(&tegra->mm, &p); - mutex_unlock(&tegra->mm_lock); + if (tegra->domain) { + mutex_lock(&tegra->mm_lock); + drm_mm_print(&tegra->mm, &p); + mutex_unlock(&tegra->mm_lock); + } return 0; } @@ -944,11 +1095,11 @@ static int tegra_debugfs_init(struct drm_minor *minor) static struct drm_driver tegra_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | - DRIVER_ATOMIC, + DRIVER_ATOMIC | DRIVER_RENDER, .load = tegra_drm_load, .unload = tegra_drm_unload, .open = tegra_drm_open, - .preclose = tegra_drm_preclose, + .postclose = tegra_drm_postclose, .lastclose = tegra_drm_lastclose, #if defined(CONFIG_DEBUG_FS) @@ -964,8 +1115,6 @@ static struct drm_driver tegra_drm_driver = { .gem_prime_import = tegra_gem_prime_import, .dumb_create = tegra_bo_dumb_create, - .dumb_map_offset = tegra_bo_dumb_map_offset, - .dumb_destroy = drm_gem_dumb_destroy, .ioctls = tegra_drm_ioctls, .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls), diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 85aa2e3d9d4e..063f5d397526 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -23,6 +23,7 @@ #include <drm/drm_fixed.h> #include "gem.h" +#include "trace.h" struct reset_control; @@ -83,6 +84,7 @@ struct tegra_drm_client_ops { struct tegra_drm_context *context); void (*close_channel)(struct tegra_drm_context *context); int (*is_addr_reg)(struct device *dev, u32 class, u32 offset); + int (*is_valid_class)(u32 class); int (*submit)(struct tegra_drm_context *context, struct drm_tegra_submit *args, struct drm_device *drm, struct drm_file *file); @@ -171,14 +173,19 @@ static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc) } static inline void tegra_dc_writel(struct tegra_dc *dc, u32 value, - unsigned long offset) + unsigned int offset) { + trace_dc_writel(dc->dev, offset, value); writel(value, dc->regs + (offset << 2)); } -static inline u32 tegra_dc_readl(struct tegra_dc *dc, unsigned long offset) +static inline u32 tegra_dc_readl(struct tegra_dc *dc, unsigned int offset) { - return readl(dc->regs + (offset << 2)); + u32 value = readl(dc->regs + (offset << 2)); + + trace_dc_readl(dc->dev, offset, value); + + return value; } struct tegra_dc_window { diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index 3dea1216bafd..046649ec9441 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -28,6 +28,7 @@ #include "drm.h" #include "dsi.h" #include "mipi-phy.h" +#include "trace.h" struct tegra_dsi_state { struct drm_connector_state base; @@ -105,15 +106,20 @@ static struct tegra_dsi_state *tegra_dsi_get_state(struct tegra_dsi *dsi) return to_dsi_state(dsi->output.connector.state); } -static inline u32 tegra_dsi_readl(struct tegra_dsi *dsi, unsigned long reg) +static inline u32 tegra_dsi_readl(struct tegra_dsi *dsi, unsigned int offset) { - return readl(dsi->regs + (reg << 2)); + u32 value = readl(dsi->regs + (offset << 2)); + + trace_dsi_readl(dsi->dev, offset, value); + + return value; } static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value, - unsigned long reg) + unsigned int offset) { - writel(value, dsi->regs + (reg << 2)); + trace_dsi_writel(dsi->dev, offset, value); + writel(value, dsi->regs + (offset << 2)); } static int tegra_dsi_show_regs(struct seq_file *s, void *data) @@ -815,7 +821,6 @@ tegra_dsi_connector_duplicate_state(struct drm_connector *connector) } static const struct drm_connector_funcs tegra_dsi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, .reset = tegra_dsi_connector_reset, .detect = tegra_output_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 25acb73ee728..80540c1c66dc 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -88,7 +88,7 @@ static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) if (bo->pages) vunmap(bo->vaddr); - drm_gem_object_unreference_unlocked(&bo->gem); + drm_gem_object_put_unlocked(&bo->gem); } } @@ -195,7 +195,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, unreference: while (i--) - drm_gem_object_unreference_unlocked(&planes[i]->gem); + drm_gem_object_put_unlocked(&planes[i]->gem); return ERR_PTR(err); } @@ -242,7 +242,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { dev_err(drm->dev, "failed to allocate framebuffer info\n"); - drm_gem_object_unreference_unlocked(&bo->gem); + drm_gem_object_put_unlocked(&bo->gem); return PTR_ERR(info); } @@ -251,7 +251,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, err = PTR_ERR(fbdev->fb); dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n", err); - drm_gem_object_unreference_unlocked(&bo->gem); + drm_gem_object_put_unlocked(&bo->gem); return PTR_ERR(fbdev->fb); } diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 424569b53e57..ab1e53d434e8 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -20,16 +20,11 @@ #include "drm.h" #include "gem.h" -static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) -{ - return container_of(bo, struct tegra_bo, base); -} - static void tegra_bo_put(struct host1x_bo *bo) { struct tegra_bo *obj = host1x_to_tegra_bo(bo); - drm_gem_object_unreference_unlocked(&obj->gem); + drm_gem_object_put_unlocked(&obj->gem); } static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt) @@ -100,7 +95,7 @@ static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo) { struct tegra_bo *obj = host1x_to_tegra_bo(bo); - drm_gem_object_reference(&obj->gem); + drm_gem_object_get(&obj->gem); return bo; } @@ -330,7 +325,7 @@ struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, return ERR_PTR(err); } - drm_gem_object_unreference_unlocked(&bo->gem); + drm_gem_object_put_unlocked(&bo->gem); return bo; } @@ -428,27 +423,6 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, return 0; } -int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm, - u32 handle, u64 *offset) -{ - struct drm_gem_object *gem; - struct tegra_bo *bo; - - gem = drm_gem_object_lookup(file, handle); - if (!gem) { - dev_err(drm->dev, "failed to lookup GEM object\n"); - return -EINVAL; - } - - bo = to_tegra_bo(gem); - - *offset = drm_vma_node_offset_addr(&bo->gem.vma_node); - - drm_gem_object_unreference_unlocked(gem); - - return 0; -} - static int tegra_bo_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; @@ -486,30 +460,28 @@ const struct vm_operations_struct tegra_bo_vm_ops = { .close = drm_gem_vm_close, }; -int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma) +static int tegra_gem_mmap(struct drm_gem_object *gem, + struct vm_area_struct *vma) { - struct drm_gem_object *gem; - struct tegra_bo *bo; - int ret; - - ret = drm_gem_mmap(file, vma); - if (ret) - return ret; - - gem = vma->vm_private_data; - bo = to_tegra_bo(gem); + struct tegra_bo *bo = to_tegra_bo(gem); if (!bo->pages) { unsigned long vm_pgoff = vma->vm_pgoff; + int err; + /* + * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), + * and set the vm_pgoff (used as a fake buffer offset by DRM) + * to 0 as we want to map the whole buffer. + */ vma->vm_flags &= ~VM_PFNMAP; vma->vm_pgoff = 0; - ret = dma_mmap_wc(gem->dev->dev, vma, bo->vaddr, bo->paddr, + err = dma_mmap_wc(gem->dev->dev, vma, bo->vaddr, bo->paddr, gem->size); - if (ret) { + if (err < 0) { drm_gem_vm_close(vma); - return ret; + return err; } vma->vm_pgoff = vm_pgoff; @@ -525,6 +497,20 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma) return 0; } +int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct drm_gem_object *gem; + int err; + + err = drm_gem_mmap(file, vma); + if (err < 0) + return err; + + gem = vma->vm_private_data; + + return tegra_gem_mmap(gem, vma); +} + static struct sg_table * tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, enum dma_data_direction dir) @@ -608,7 +594,14 @@ static void tegra_gem_prime_kunmap(struct dma_buf *buf, unsigned long page, static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma) { - return -EINVAL; + struct drm_gem_object *gem = buf->priv; + int err; + + err = drm_gem_mmap_obj(gem, gem->size, vma); + if (err < 0) + return err; + + return tegra_gem_mmap(gem, vma); } static void *tegra_gem_prime_vmap(struct dma_buf *buf) @@ -659,7 +652,7 @@ struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm, struct drm_gem_object *gem = buf->priv; if (gem->dev == drm) { - drm_gem_object_reference(gem); + drm_gem_object_get(gem); return gem; } } diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h index 6c5f12ac0087..8eb9fd24ef0e 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h @@ -52,6 +52,11 @@ static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem) return container_of(gem, struct tegra_bo, gem); } +static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) +{ + return container_of(bo, struct tegra_bo, base); +} + struct tegra_bo *tegra_bo_create(struct drm_device *drm, size_t size, unsigned long flags); struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, @@ -62,8 +67,6 @@ struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, void tegra_bo_free_object(struct drm_gem_object *gem); int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, struct drm_mode_create_dumb *args); -int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm, - u32 handle, u64 *offset); int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma); diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c index 02cd3e37a6ec..6ea070da7718 100644 --- a/drivers/gpu/drm/tegra/gr2d.c +++ b/drivers/gpu/drm/tegra/gr2d.c @@ -38,7 +38,7 @@ static int gr2d_init(struct host1x_client *client) client->syncpts[0] = host1x_syncpt_request(client->dev, flags); if (!client->syncpts[0]) { - host1x_channel_free(gr2d->channel); + host1x_channel_put(gr2d->channel); return -ENOMEM; } @@ -57,7 +57,7 @@ static int gr2d_exit(struct host1x_client *client) return err; host1x_syncpt_free(client->syncpts[0]); - host1x_channel_free(gr2d->channel); + host1x_channel_put(gr2d->channel); return 0; } @@ -109,10 +109,17 @@ static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset) return 0; } +static int gr2d_is_valid_class(u32 class) +{ + return (class == HOST1X_CLASS_GR2D || + class == HOST1X_CLASS_GR2D_SB); +} + static const struct tegra_drm_client_ops gr2d_ops = { .open_channel = gr2d_open_channel, .close_channel = gr2d_close_channel, .is_addr_reg = gr2d_is_addr_reg, + .is_valid_class = gr2d_is_valid_class, .submit = tegra_drm_submit, }; diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index 13f0d1b7cd98..cee2ab645cde 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -48,7 +48,7 @@ static int gr3d_init(struct host1x_client *client) client->syncpts[0] = host1x_syncpt_request(client->dev, flags); if (!client->syncpts[0]) { - host1x_channel_free(gr3d->channel); + host1x_channel_put(gr3d->channel); return -ENOMEM; } @@ -67,7 +67,7 @@ static int gr3d_exit(struct host1x_client *client) return err; host1x_syncpt_free(client->syncpts[0]); - host1x_channel_free(gr3d->channel); + host1x_channel_put(gr3d->channel); return 0; } diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index cda0491ed6bf..5b9d83b71943 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -24,6 +24,7 @@ #include "hdmi.h" #include "drm.h" #include "dc.h" +#include "trace.h" #define HDMI_ELD_BUFFER_SIZE 96 @@ -100,14 +101,19 @@ enum { }; static inline u32 tegra_hdmi_readl(struct tegra_hdmi *hdmi, - unsigned long offset) + unsigned int offset) { - return readl(hdmi->regs + (offset << 2)); + u32 value = readl(hdmi->regs + (offset << 2)); + + trace_hdmi_readl(hdmi->dev, offset, value); + + return value; } static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, u32 value, - unsigned long offset) + unsigned int offset) { + trace_hdmi_writel(hdmi->dev, offset, value); writel(value, hdmi->regs + (offset << 2)); } @@ -734,7 +740,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, u8 buffer[17]; ssize_t err; - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err); return; @@ -902,7 +908,6 @@ tegra_hdmi_connector_detect(struct drm_connector *connector, bool force) } static const struct drm_connector_funcs tegra_hdmi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, .reset = drm_atomic_helper_connector_reset, .detect = tegra_hdmi_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index a131b44e2d6f..78ec5193741d 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -88,7 +88,6 @@ static void tegra_dc_write_regs(struct tegra_dc *dc, } static const struct drm_connector_funcs tegra_rgb_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, .reset = drm_atomic_helper_connector_reset, .detect = tegra_output_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index a8f528925009..7ab1d1dc7cd7 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -26,6 +26,7 @@ #include "dc.h" #include "drm.h" #include "sor.h" +#include "trace.h" #define SOR_REKEY 0x38 @@ -232,14 +233,19 @@ static inline struct tegra_sor *to_sor(struct tegra_output *output) return container_of(output, struct tegra_sor, output); } -static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned long offset) +static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned int offset) { - return readl(sor->regs + (offset << 2)); + u32 value = readl(sor->regs + (offset << 2)); + + trace_sor_readl(sor->dev, offset, value); + + return value; } static inline void tegra_sor_writel(struct tegra_sor *sor, u32 value, - unsigned long offset) + unsigned int offset) { + trace_sor_writel(sor->dev, offset, value); writel(value, sor->regs + (offset << 2)); } @@ -1340,7 +1346,6 @@ tegra_sor_connector_duplicate_state(struct drm_connector *connector) } static const struct drm_connector_funcs tegra_sor_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, .reset = tegra_sor_connector_reset, .detect = tegra_sor_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, @@ -1904,7 +1909,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor, value &= ~INFOFRAME_CTRL_ENABLE; tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL); - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false); if (err < 0) { dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err); return err; diff --git a/drivers/gpu/drm/tegra/trace.c b/drivers/gpu/drm/tegra/trace.c new file mode 100644 index 000000000000..006f65c72a34 --- /dev/null +++ b/drivers/gpu/drm/tegra/trace.c @@ -0,0 +1,2 @@ +#define CREATE_TRACE_POINTS +#include "trace.h" diff --git a/drivers/gpu/drm/tegra/trace.h b/drivers/gpu/drm/tegra/trace.h new file mode 100644 index 000000000000..e9b7cdad5c4c --- /dev/null +++ b/drivers/gpu/drm/tegra/trace.h @@ -0,0 +1,68 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM tegra + +#if !defined(DRM_TEGRA_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define DRM_TEGRA_TRACE_H 1 + +#include <linux/device.h> +#include <linux/tracepoint.h> + +DECLARE_EVENT_CLASS(register_access, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value), + TP_STRUCT__entry( + __field(struct device *, dev) + __field(unsigned int, offset) + __field(u32, value) + ), + TP_fast_assign( + __entry->dev = dev; + __entry->offset = offset; + __entry->value = value; + ), + TP_printk("%s %04x %08x", dev_name(__entry->dev), __entry->offset, + __entry->value) +); + +DEFINE_EVENT(register_access, dc_writel, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); +DEFINE_EVENT(register_access, dc_readl, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); + +DEFINE_EVENT(register_access, hdmi_writel, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); +DEFINE_EVENT(register_access, hdmi_readl, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); + +DEFINE_EVENT(register_access, dsi_writel, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); +DEFINE_EVENT(register_access, dsi_readl, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); + +DEFINE_EVENT(register_access, dpaux_writel, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); +DEFINE_EVENT(register_access, dpaux_readl, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); + +DEFINE_EVENT(register_access, sor_writel, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); +DEFINE_EVENT(register_access, sor_readl, + TP_PROTO(struct device *dev, unsigned int offset, u32 value), + TP_ARGS(dev, offset, value)); + +#endif /* DRM_TEGRA_TRACE_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE trace +#include <trace/define_trace.h> diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c index cd804e404a11..2448229fa653 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c @@ -182,7 +182,7 @@ static int vic_init(struct host1x_client *client) free_syncpt: host1x_syncpt_free(client->syncpts[0]); free_channel: - host1x_channel_free(vic->channel); + host1x_channel_put(vic->channel); detach_device: if (tegra->domain) iommu_detach_device(tegra->domain, vic->dev); @@ -203,7 +203,7 @@ static int vic_exit(struct host1x_client *client) return err; host1x_syncpt_free(client->syncpts[0]); - host1x_channel_free(vic->channel); + host1x_channel_put(vic->channel); if (vic->domain) { iommu_detach_device(vic->domain, vic->dev); @@ -258,12 +258,16 @@ static const struct tegra_drm_client_ops vic_ops = { .submit = tegra_drm_submit, }; +#define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin" + static const struct vic_config vic_t124_config = { - .firmware = "nvidia/tegra124/vic03_ucode.bin", + .firmware = NVIDIA_TEGRA_124_VIC_FIRMWARE, }; +#define NVIDIA_TEGRA_210_VIC_FIRMWARE "nvidia/tegra210/vic04_ucode.bin" + static const struct vic_config vic_t210_config = { - .firmware = "nvidia/tegra210/vic04_ucode.bin", + .firmware = NVIDIA_TEGRA_210_VIC_FIRMWARE, }; static const struct of_device_id vic_match[] = { @@ -394,3 +398,10 @@ struct platform_driver tegra_vic_driver = { .probe = vic_probe, .remove = vic_remove, }; + +#if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) +MODULE_FIRMWARE(NVIDIA_TEGRA_124_VIC_FIRMWARE); +#endif +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) +MODULE_FIRMWARE(NVIDIA_TEGRA_210_VIC_FIRMWARE); +#endif |