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 | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dpaux.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 116 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 12 | ||||
-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 | 78 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.h | 2 | ||||
-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 | 15 |
16 files changed, 265 insertions, 119 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 c875f11786b9..4df39112e38e 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -678,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); @@ -844,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); @@ -906,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); @@ -1199,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; @@ -1243,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); @@ -1351,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) 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 518f4b69ea53..597d563d636a 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -100,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) @@ -214,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: @@ -248,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) @@ -304,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; } @@ -394,8 +394,10 @@ int tegra_drm_submit(struct tegra_drm_context *context, (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 */ @@ -417,6 +419,21 @@ 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; @@ -445,6 +462,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, 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, @@ -474,6 +492,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, 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 @@ -487,6 +506,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, } obj = host1x_to_tegra_bo(reloc->target.bo); + refs[num_refs++] = &obj->gem; if (reloc->target.offset >= obj->gem.size) { err = -EINVAL; @@ -506,6 +526,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, goto fail; obj = host1x_to_tegra_bo(wait->bo); + refs[num_refs++] = &obj->gem; /* * The unaligned offset will cause an unaligned write during @@ -545,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; } @@ -591,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; } @@ -858,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; } @@ -898,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; } @@ -923,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; } @@ -945,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; } @@ -953,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 }; @@ -1033,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; } @@ -1055,7 +1095,7 @@ 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, @@ -1075,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 6d6da01282f3..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; @@ -172,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 7a39a355678a..ab1e53d434e8 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -24,7 +24,7 @@ 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) @@ -95,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; } @@ -325,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; } @@ -423,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; @@ -481,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; @@ -520,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) @@ -603,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) @@ -654,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 8b32a6fd586d..8eb9fd24ef0e 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h @@ -67,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/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 47cb1aaa58b1..2448229fa653 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c @@ -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 |