Commit 3aadb888 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm/tegra/for-4.14-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next

drm/tegra: Changes for v4.14-rc1

This contains a couple of fixes and improvements for host1x, with some
preparatory work for Tegra186 support.

The remainder is cleanup and minor bugfixes for Tegra DRM along with
enhancements to debuggability.

There have also been some enhancements to the kernel interfaces for
host1x job submissions and support for mmap'ing PRIME buffers directly,
all of which get the interfaces very close to ready for serious work.

* tag 'drm/tegra/for-4.14-rc1' of git://anongit.freedesktop.org/tegra/linux: (21 commits)
  drm/tegra: Prevent BOs from being freed during job submission
  drm/tegra: gem: Implement mmap() for PRIME buffers
  drm/tegra: Support render node
  drm/tegra: sor: Trace register accesses
  drm/tegra: dpaux: Trace register accesses
  drm/tegra: dsi: Trace register accesses
  drm/tegra: hdmi: Trace register accesses
  drm/tegra: dc: Trace register accesses
  drm/tegra: sor: Use unsigned int for register offsets
  drm/tegra: hdmi: Use unsigned int for register offsets
  drm/tegra: dsi: Use unsigned int for register offsets
  drm/tegra: dpaux: Use unsigned int for register offsets
  drm/tegra: dc: Use unsigned int for register offsets
  drm/tegra: Fix NULL deref in debugfs/iova
  drm/tegra: switch to drm_*_get(), drm_*_put() helpers
  drm/tegra: Set MODULE_FIRMWARE for the VIC
  drm/tegra: Add CONFIG_OF dependency
  gpu: host1x: Support sub-devices recursively
  gpu: host1x: fix error return code in host1x_probe()
  gpu: host1x: Fix bitshift/mask multipliers
  ...
parents e5fa05b9 ec73c4cf
...@@ -3,6 +3,7 @@ config DRM_TEGRA ...@@ -3,6 +3,7 @@ config DRM_TEGRA
depends on ARCH_TEGRA || (ARM && COMPILE_TEST) depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
depends on COMMON_CLK depends on COMMON_CLK
depends on DRM depends on DRM
depends on OF
select DRM_KMS_HELPER select DRM_KMS_HELPER
select DRM_MIPI_DSI select DRM_MIPI_DSI
select DRM_PANEL select DRM_PANEL
......
...@@ -17,4 +17,6 @@ tegra-drm-y := \ ...@@ -17,4 +17,6 @@ tegra-drm-y := \
falcon.o \ falcon.o \
vic.o vic.o
tegra-drm-y += trace.o
obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "dpaux.h" #include "dpaux.h"
#include "drm.h" #include "drm.h"
#include "trace.h"
static DEFINE_MUTEX(dpaux_lock); static DEFINE_MUTEX(dpaux_lock);
static LIST_HEAD(dpaux_list); static LIST_HEAD(dpaux_list);
...@@ -65,14 +66,19 @@ static inline struct tegra_dpaux *work_to_dpaux(struct work_struct *work) ...@@ -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, 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, 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)); writel(value, dpaux->regs + (offset << 2));
} }
......
...@@ -306,8 +306,6 @@ host1x_bo_lookup(struct drm_file *file, u32 handle) ...@@ -306,8 +306,6 @@ host1x_bo_lookup(struct drm_file *file, u32 handle)
if (!gem) if (!gem)
return NULL; return NULL;
drm_gem_object_unreference_unlocked(gem);
bo = to_tegra_bo(gem); bo = to_tegra_bo(gem);
return &bo->base; return &bo->base;
} }
...@@ -396,8 +394,10 @@ int tegra_drm_submit(struct tegra_drm_context *context, ...@@ -396,8 +394,10 @@ int tegra_drm_submit(struct tegra_drm_context *context,
(void __user *)(uintptr_t)args->waitchks; (void __user *)(uintptr_t)args->waitchks;
struct drm_tegra_syncpt syncpt; struct drm_tegra_syncpt syncpt;
struct host1x *host1x = dev_get_drvdata(drm->dev->parent); struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
struct drm_gem_object **refs;
struct host1x_syncpt *sp; struct host1x_syncpt *sp;
struct host1x_job *job; struct host1x_job *job;
unsigned int num_refs;
int err; int err;
/* We don't yet support other than one syncpt_incr struct per submit */ /* We don't yet support other than one syncpt_incr struct per submit */
...@@ -419,6 +419,21 @@ int tegra_drm_submit(struct tegra_drm_context *context, ...@@ -419,6 +419,21 @@ int tegra_drm_submit(struct tegra_drm_context *context,
job->class = context->client->base.class; job->class = context->client->base.class;
job->serialize = true; 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) { while (num_cmdbufs) {
struct drm_tegra_cmdbuf cmdbuf; struct drm_tegra_cmdbuf cmdbuf;
struct host1x_bo *bo; struct host1x_bo *bo;
...@@ -447,6 +462,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, ...@@ -447,6 +462,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
offset = (u64)cmdbuf.offset + (u64)cmdbuf.words * sizeof(u32); offset = (u64)cmdbuf.offset + (u64)cmdbuf.words * sizeof(u32);
obj = host1x_to_tegra_bo(bo); obj = host1x_to_tegra_bo(bo);
refs[num_refs++] = &obj->gem;
/* /*
* Gather buffer base address must be 4-bytes aligned, * Gather buffer base address must be 4-bytes aligned,
...@@ -476,6 +492,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, ...@@ -476,6 +492,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
reloc = &job->relocarray[num_relocs]; reloc = &job->relocarray[num_relocs];
obj = host1x_to_tegra_bo(reloc->cmdbuf.bo); obj = host1x_to_tegra_bo(reloc->cmdbuf.bo);
refs[num_refs++] = &obj->gem;
/* /*
* The unaligned cmdbuf offset will cause an unaligned write * The unaligned cmdbuf offset will cause an unaligned write
...@@ -489,6 +506,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, ...@@ -489,6 +506,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
} }
obj = host1x_to_tegra_bo(reloc->target.bo); obj = host1x_to_tegra_bo(reloc->target.bo);
refs[num_refs++] = &obj->gem;
if (reloc->target.offset >= obj->gem.size) { if (reloc->target.offset >= obj->gem.size) {
err = -EINVAL; err = -EINVAL;
...@@ -508,6 +526,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, ...@@ -508,6 +526,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
goto fail; goto fail;
obj = host1x_to_tegra_bo(wait->bo); obj = host1x_to_tegra_bo(wait->bo);
refs[num_refs++] = &obj->gem;
/* /*
* The unaligned offset will cause an unaligned write during * The unaligned offset will cause an unaligned write during
...@@ -547,17 +566,20 @@ int tegra_drm_submit(struct tegra_drm_context *context, ...@@ -547,17 +566,20 @@ int tegra_drm_submit(struct tegra_drm_context *context,
goto fail; goto fail;
err = host1x_job_submit(job); err = host1x_job_submit(job);
if (err) if (err) {
goto fail_submit; host1x_job_unpin(job);
goto fail;
}
args->fence = job->syncpt_end; args->fence = job->syncpt_end;
host1x_job_put(job);
return 0;
fail_submit:
host1x_job_unpin(job);
fail: fail:
while (num_refs--)
drm_gem_object_put_unlocked(refs[num_refs]);
kfree(refs);
put:
host1x_job_put(job); host1x_job_put(job);
return err; return err;
} }
...@@ -593,7 +615,7 @@ static int tegra_gem_mmap(struct drm_device *drm, void *data, ...@@ -593,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); 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; return 0;
} }
...@@ -860,7 +882,7 @@ static int tegra_gem_set_tiling(struct drm_device *drm, void *data, ...@@ -860,7 +882,7 @@ static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
bo->tiling.mode = mode; bo->tiling.mode = mode;
bo->tiling.value = value; bo->tiling.value = value;
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return 0; return 0;
} }
...@@ -900,7 +922,7 @@ static int tegra_gem_get_tiling(struct drm_device *drm, void *data, ...@@ -900,7 +922,7 @@ static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
break; break;
} }
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return err; return err;
} }
...@@ -925,7 +947,7 @@ static int tegra_gem_set_flags(struct drm_device *drm, void *data, ...@@ -925,7 +947,7 @@ static int tegra_gem_set_flags(struct drm_device *drm, void *data,
if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP) if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
bo->flags |= TEGRA_BO_BOTTOM_UP; bo->flags |= TEGRA_BO_BOTTOM_UP;
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return 0; return 0;
} }
...@@ -947,7 +969,7 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data, ...@@ -947,7 +969,7 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
if (bo->flags & TEGRA_BO_BOTTOM_UP) if (bo->flags & TEGRA_BO_BOTTOM_UP)
args->flags |= DRM_TEGRA_GEM_BOTTOM_UP; args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return 0; return 0;
} }
...@@ -955,20 +977,34 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data, ...@@ -955,20 +977,34 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
static const struct drm_ioctl_desc tegra_drm_ioctls[] = { static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
#ifdef CONFIG_DRM_TEGRA_STAGING #ifdef CONFIG_DRM_TEGRA_STAGING
DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, 0), DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create,
DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, 0), DRM_UNLOCKED | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, 0), DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap,
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, 0), DRM_UNLOCKED | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, 0), DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read,
DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, 0), DRM_UNLOCKED | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, 0), DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr,
DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, 0), DRM_UNLOCKED | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, 0), DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait,
DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, 0), DRM_UNLOCKED | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, 0), DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel,
DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, 0), DRM_UNLOCKED | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, 0), DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel,
DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, 0), 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 #endif
}; };
...@@ -1035,9 +1071,11 @@ static int tegra_debugfs_iova(struct seq_file *s, void *data) ...@@ -1035,9 +1071,11 @@ static int tegra_debugfs_iova(struct seq_file *s, void *data)
struct tegra_drm *tegra = drm->dev_private; struct tegra_drm *tegra = drm->dev_private;
struct drm_printer p = drm_seq_file_printer(s); struct drm_printer p = drm_seq_file_printer(s);
mutex_lock(&tegra->mm_lock); if (tegra->domain) {
drm_mm_print(&tegra->mm, &p); mutex_lock(&tegra->mm_lock);
mutex_unlock(&tegra->mm_lock); drm_mm_print(&tegra->mm, &p);
mutex_unlock(&tegra->mm_lock);
}
return 0; return 0;
} }
...@@ -1057,7 +1095,7 @@ static int tegra_debugfs_init(struct drm_minor *minor) ...@@ -1057,7 +1095,7 @@ static int tegra_debugfs_init(struct drm_minor *minor)
static struct drm_driver tegra_drm_driver = { static struct drm_driver tegra_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
DRIVER_ATOMIC, DRIVER_ATOMIC | DRIVER_RENDER,
.load = tegra_drm_load, .load = tegra_drm_load,
.unload = tegra_drm_unload, .unload = tegra_drm_unload,
.open = tegra_drm_open, .open = tegra_drm_open,
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <drm/drm_fixed.h> #include <drm/drm_fixed.h>
#include "gem.h" #include "gem.h"
#include "trace.h"
struct reset_control; struct reset_control;
...@@ -172,14 +173,19 @@ static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc) ...@@ -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, 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)); 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 { struct tegra_dc_window {
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "drm.h" #include "drm.h"
#include "dsi.h" #include "dsi.h"
#include "mipi-phy.h" #include "mipi-phy.h"
#include "trace.h"
struct tegra_dsi_state { struct tegra_dsi_state {
struct drm_connector_state base; struct drm_connector_state base;
...@@ -105,15 +106,20 @@ static struct tegra_dsi_state *tegra_dsi_get_state(struct tegra_dsi *dsi) ...@@ -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); 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, 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) static int tegra_dsi_show_regs(struct seq_file *s, void *data)
......
...@@ -88,7 +88,7 @@ static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) ...@@ -88,7 +88,7 @@ static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
if (bo->pages) if (bo->pages)
vunmap(bo->vaddr); 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, ...@@ -195,7 +195,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
unreference: unreference:
while (i--) while (i--)
drm_gem_object_unreference_unlocked(&planes[i]->gem); drm_gem_object_put_unlocked(&planes[i]->gem);
return ERR_PTR(err); return ERR_PTR(err);
} }
...@@ -242,7 +242,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, ...@@ -242,7 +242,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
info = drm_fb_helper_alloc_fbi(helper); info = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(info)) { if (IS_ERR(info)) {
dev_err(drm->dev, "failed to allocate framebuffer info\n"); 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); return PTR_ERR(info);
} }
...@@ -251,7 +251,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, ...@@ -251,7 +251,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
err = PTR_ERR(fbdev->fb); err = PTR_ERR(fbdev->fb);
dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n", dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n",
err); err);
drm_gem_object_unreference_unlocked(&bo->gem); drm_gem_object_put_unlocked(&bo->gem);
return PTR_ERR(fbdev->fb); return PTR_ERR(fbdev->fb);
} }
......
...@@ -24,7 +24,7 @@ static void tegra_bo_put(struct host1x_bo *bo) ...@@ -24,7 +24,7 @@ static void tegra_bo_put(struct host1x_bo *bo)
{ {
struct tegra_bo *obj = host1x_to_tegra_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) 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) ...@@ -95,7 +95,7 @@ static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
{ {
struct tegra_bo *obj = host1x_to_tegra_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; return bo;
} }
...@@ -325,7 +325,7 @@ struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, ...@@ -325,7 +325,7 @@ struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
return ERR_PTR(err); return ERR_PTR(err);
} }
drm_gem_object_unreference_unlocked(&bo->gem); drm_gem_object_put_unlocked(&bo->gem);
return bo; return bo;
} }
...@@ -460,30 +460,28 @@ const struct vm_operations_struct tegra_bo_vm_ops = { ...@@ -460,30 +460,28 @@ const struct vm_operations_struct tegra_bo_vm_ops = {
.close = drm_gem_vm_close, .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 = to_tegra_bo(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);
if (!bo->pages) { if (!bo->pages) {
unsigned long vm_pgoff = vma->vm_pgoff; 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_flags &= ~VM_PFNMAP;
vma->vm_pgoff = 0; 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); gem->size);
if (ret) { if (err < 0) {
drm_gem_vm_close(vma); drm_gem_vm_close(vma);
return ret; return err;
} }
vma->vm_pgoff = vm_pgoff; vma->vm_pgoff = vm_pgoff;
...@@ -499,6 +497,20 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -499,6 +497,20 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
return 0; 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 * static struct sg_table *
tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir) enum dma_data_direction dir)
...@@ -582,7 +594,14 @@ static void tegra_gem_prime_kunmap(struct dma_buf *buf, unsigned long page, ...@@ -582,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) 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) static void *tegra_gem_prime_vmap(struct dma_buf *buf)
...@@ -633,7 +652,7 @@ struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm, ...@@ -633,7 +652,7 @@ struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
struct drm_gem_object *gem = buf->priv; struct drm_gem_object *gem = buf->priv;
if (gem->dev == drm) { if (gem->dev == drm) {
drm_gem_object_reference(gem); drm_gem_object_get(gem);
return gem; return gem;
} }
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "hdmi.h" #include "hdmi.h"
#include "drm.h" #include "drm.h"
#include "dc.h" #include "dc.h"
#include "trace.h"
#define HDMI_ELD_BUFFER_SIZE 96 #define HDMI_ELD_BUFFER_SIZE 96
...@@ -100,14 +101,19 @@ enum { ...@@ -100,14 +101,19 @@ enum {
}; };
static inline u32 tegra_hdmi_readl(struct tegra_hdmi *hdmi, 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, 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)); writel(value, hdmi->regs + (offset << 2));
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "dc.h" #include "dc.h"
#include "drm.h" #include "drm.h"
#include "sor.h" #include "sor.h"
#include "trace.h"
#define SOR_REKEY 0x38 #define SOR_REKEY 0x38
...@@ -232,14 +233,19 @@ static inline struct tegra_sor *to_sor(struct tegra_output *output) ...@@ -232,14 +233,19 @@ static inline struct tegra_sor *to_sor(struct tegra_output *output)
return container_of(output, struct tegra_sor, 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, 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)); writel(value, sor->regs + (offset << 2));
} }
......
#define CREATE_TRACE_POINTS
#include "trace.h"
#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>
...@@ -258,12 +258,16 @@ static const struct tegra_drm_client_ops vic_ops = { ...@@ -258,12 +258,16 @@ static const struct tegra_drm_client_ops vic_ops = {
.submit = tegra_drm_submit, .submit = tegra_drm_submit,
}; };
#define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"
static const struct vic_config vic_t124_config = { 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 = { 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[] = { static const struct of_device_id vic_match[] = {
...@@ -394,3 +398,10 @@ struct platform_driver tegra_vic_driver = { ...@@ -394,3 +398,10 @@ struct platform_driver tegra_vic_driver = {
.probe = vic_probe, .probe = vic_probe,
.remove = vic_remove, .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
...@@ -44,9 +44,12 @@ struct host1x_subdev { ...@@ -44,9 +44,12 @@ struct host1x_subdev {
* @np: device node * @np: device node
*/ */
static int host1x_subdev_add(struct host1x_device *device, static int host1x_subdev_add(struct host1x_device *device,
struct host1x_driver *driver,
struct device_node *np) struct device_node *np)
{ {
struct host1x_subdev *subdev; struct host1x_subdev *subdev;
struct device_node *child;
int err;
subdev = kzalloc(sizeof(*subdev), GFP_KERNEL); subdev = kzalloc(sizeof(*subdev), GFP_KERNEL);
if (!subdev) if (!subdev)
...@@ -59,6 +62,19 @@ static int host1x_subdev_add(struct host1x_device *device, ...@@ -59,6 +62,19 @@ static int host1x_subdev_add(struct host1x_device *device,
list_add_tail(&subdev->list, &device->subdevs); list_add_tail(&subdev->list, &device->subdevs);
mutex_unlock(&device->subdevs_lock); mutex_unlock(&device->subdevs_lock);
/* recursively add children */
for_each_child_of_node(np, child) {
if (of_match_node(driver->subdevs, child) &&
of_device_is_available(child)) {
err = host1x_subdev_add(device, driver, child);
if (err < 0) {
/* XXX cleanup? */
of_node_put(child);
return err;
}
}
}
return 0; return 0;
} }
...@@ -87,7 +103,7 @@ static int host1x_device_parse_dt(struct host1x_device *device, ...@@ -87,7 +103,7 @@ static int host1x_device_parse_dt(struct host1x_device *device,
for_each_child_of_node(device->dev.parent->of_node, np) { for_each_child_of_node(device->dev.parent->of_node, np) {
if (of_match_node(driver->subdevs, np) && if (of_match_node(driver->subdevs, np) &&
of_device_is_available(np)) { of_device_is_available(np)) {
err = host1x_subdev_add(device, np); err = host1x_subdev_add(device, driver, np);
if (err < 0) { if (err < 0) {
of_node_put(np); of_node_put(np);
return err; return err;
......
...@@ -134,8 +134,8 @@ static int host1x_probe(struct platform_device *pdev) ...@@ -134,8 +134,8 @@ static int host1x_probe(struct platform_device *pdev)
syncpt_irq = platform_get_irq(pdev, 0); syncpt_irq = platform_get_irq(pdev, 0);
if (syncpt_irq < 0) { if (syncpt_irq < 0) {
dev_err(&pdev->dev, "failed to get IRQ\n"); dev_err(&pdev->dev, "failed to get IRQ: %d\n", syncpt_irq);
return -ENXIO; return syncpt_irq;
} }
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
......
...@@ -33,10 +33,10 @@ static void host1x_intr_syncpt_handle(struct host1x_syncpt *syncpt) ...@@ -33,10 +33,10 @@ static void host1x_intr_syncpt_handle(struct host1x_syncpt *syncpt)
unsigned int id = syncpt->id; unsigned int id = syncpt->id;
struct host1x *host = syncpt->host; struct host1x *host = syncpt->host;
host1x_sync_writel(host, BIT_MASK(id), host1x_sync_writel(host, BIT(id % 32),
HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(BIT_WORD(id))); HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32));
host1x_sync_writel(host, BIT_MASK(id), host1x_sync_writel(host, BIT(id % 32),
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(BIT_WORD(id))); HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32));
schedule_work(&syncpt->intr.work); schedule_work(&syncpt->intr.work);
} }
...@@ -50,9 +50,9 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id) ...@@ -50,9 +50,9 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)
for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) { for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) {
reg = host1x_sync_readl(host, reg = host1x_sync_readl(host,
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));
for_each_set_bit(id, &reg, BITS_PER_LONG) { for_each_set_bit(id, &reg, 32) {
struct host1x_syncpt *syncpt = struct host1x_syncpt *syncpt =
host->syncpt + (i * BITS_PER_LONG + id); host->syncpt + (i * 32 + id);
host1x_intr_syncpt_handle(syncpt); host1x_intr_syncpt_handle(syncpt);
} }
} }
...@@ -117,17 +117,17 @@ static void _host1x_intr_set_syncpt_threshold(struct host1x *host, ...@@ -117,17 +117,17 @@ static void _host1x_intr_set_syncpt_threshold(struct host1x *host,
static void _host1x_intr_enable_syncpt_intr(struct host1x *host, static void _host1x_intr_enable_syncpt_intr(struct host1x *host,
unsigned int id) unsigned int id)
{ {
host1x_sync_writel(host, BIT_MASK(id), host1x_sync_writel(host, BIT(id % 32),
HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(BIT_WORD(id))); HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id / 32));
} }
static void _host1x_intr_disable_syncpt_intr(struct host1x *host, static void _host1x_intr_disable_syncpt_intr(struct host1x *host,
unsigned int id) unsigned int id)
{ {
host1x_sync_writel(host, BIT_MASK(id), host1x_sync_writel(host, BIT(id % 32),
HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(BIT_WORD(id))); HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32));
host1x_sync_writel(host, BIT_MASK(id), host1x_sync_writel(host, BIT(id % 32),
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(BIT_WORD(id))); HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32));
} }
static int _host1x_free_syncpt_irq(struct host1x *host) static int _host1x_free_syncpt_irq(struct host1x *host)
......
...@@ -89,7 +89,7 @@ static int syncpt_cpu_incr(struct host1x_syncpt *sp) ...@@ -89,7 +89,7 @@ static int syncpt_cpu_incr(struct host1x_syncpt *sp)
host1x_syncpt_idle(sp)) host1x_syncpt_idle(sp))
return -EINVAL; return -EINVAL;
host1x_sync_writel(host, BIT_MASK(sp->id), host1x_sync_writel(host, BIT(sp->id % 32),
HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset)); HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset));
wmb(); wmb();
......
...@@ -197,10 +197,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) ...@@ -197,10 +197,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
} }
phys_addr = host1x_bo_pin(reloc->target.bo, &sgt); phys_addr = host1x_bo_pin(reloc->target.bo, &sgt);
if (!phys_addr) {
err = -EINVAL;
goto unpin;
}
job->addr_phys[job->num_unpins] = phys_addr; job->addr_phys[job->num_unpins] = phys_addr;
job->unpins[job->num_unpins].bo = reloc->target.bo; job->unpins[job->num_unpins].bo = reloc->target.bo;
...@@ -225,10 +221,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) ...@@ -225,10 +221,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
} }
phys_addr = host1x_bo_pin(g->bo, &sgt); phys_addr = host1x_bo_pin(g->bo, &sgt);
if (!phys_addr) {
err = -EINVAL;
goto unpin;
}
if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) { if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) {
for_each_sg(sgt->sgl, sg, sgt->nents, j) for_each_sg(sgt->sgl, sg, sgt->nents, j)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment