mirror of https://gitee.com/openkylin/linux.git
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. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAlmXBm4THHRyZWRpbmdA bnZpZGlhLmNvbQAKCRDdI6zXfz6zoYDJD/9ILmkCZPmv/LnYjQ1vivHN2cwboj2K 0yM6fwHE2JrvavKaAt1DDxZElxzL4Gcihcg6ALIc0/RH9S82nz7eNMkwLgfLLPHl PFCv/rGkFkyQpqOXvUmLYBGL7uNo3GDfT3fE5fJ9ZfRWFLBaI6DgT6flzTZBsd0T vC+mExHBdobu9bsyR95NpHGjDPQoUK//m35p+vZixnyjhCbDM/+qKA/iSUE5kaEY S2huX/Gzl8jbi2d2Ax9dz905gYrDKl6y5qlGA3BGKpTPxOd/kYtc2eClSRHc1hno WT/9yFeTFyXjxarpY9nAT2NNfVn+crvB3vBwP97I6YKszBbGUOHGYqhBy7r0W+Fl MqMvlqTJgN4OlVL7pGiCkeDUKZyJ697EZqNdeYREiKwPtsmSiZcnxxk5BcTEzXBX cF0udAVfEK8MekjPDz1CWGbH2uMuXxsH+7VTKt3avVYlN8J9rIhZv9hGK6g/znyd 4N4eyzDxRtChhAcin1fQJosAzc8oTSEE21WQW2D8vme+t0Yx9Oiy7BG5uj+yLruu 0/l0TUEyyDozg2doBsnDzJdCFzcHZjo4fClYfZu/Ficwb9eEDOx85eif+rGEOclO ickwuGEOAjKuyrz4T0fkd6j3aMYUVRmXZ3L0gFD68jUKel00zjSpcL/JfEihwvd/ Nus3MYLH+IrFKQ== =ZaxL -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
3aadb888b1
|
@ -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
|
||||
|
|
|
@ -17,4 +17,6 @@ tegra-drm-y := \
|
|||
falcon.o \
|
||||
vic.o
|
||||
|
||||
tegra-drm-y += trace.o
|
||||
|
||||
obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -306,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;
|
||||
}
|
||||
|
@ -396,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 */
|
||||
|
@ -419,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;
|
||||
|
@ -447,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,
|
||||
|
@ -476,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
|
||||
|
@ -489,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;
|
||||
|
@ -508,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
|
||||
|
@ -547,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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
drm_gem_object_unreference_unlocked(gem);
|
||||
drm_gem_object_put_unlocked(gem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -860,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;
|
||||
}
|
||||
|
@ -900,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;
|
||||
}
|
||||
|
@ -925,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;
|
||||
}
|
||||
|
@ -947,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;
|
||||
}
|
||||
|
@ -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[] = {
|
||||
#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
|
||||
};
|
||||
|
||||
|
@ -1035,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;
|
||||
}
|
||||
|
@ -1057,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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -460,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;
|
||||
|
@ -499,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)
|
||||
|
@ -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)
|
||||
{
|
||||
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)
|
||||
|
@ -633,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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#define CREATE_TRACE_POINTS
|
||||
#include "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>
|
|
@ -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
|
||||
|
|
|
@ -44,9 +44,12 @@ struct host1x_subdev {
|
|||
* @np: device node
|
||||
*/
|
||||
static int host1x_subdev_add(struct host1x_device *device,
|
||||
struct host1x_driver *driver,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct host1x_subdev *subdev;
|
||||
struct device_node *child;
|
||||
int err;
|
||||
|
||||
subdev = kzalloc(sizeof(*subdev), GFP_KERNEL);
|
||||
if (!subdev)
|
||||
|
@ -59,6 +62,19 @@ static int host1x_subdev_add(struct host1x_device *device,
|
|||
list_add_tail(&subdev->list, &device->subdevs);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
if (of_match_node(driver->subdevs, np) &&
|
||||
of_device_is_available(np)) {
|
||||
err = host1x_subdev_add(device, np);
|
||||
err = host1x_subdev_add(device, driver, np);
|
||||
if (err < 0) {
|
||||
of_node_put(np);
|
||||
return err;
|
||||
|
|
|
@ -134,8 +134,8 @@ static int host1x_probe(struct platform_device *pdev)
|
|||
|
||||
syncpt_irq = platform_get_irq(pdev, 0);
|
||||
if (syncpt_irq < 0) {
|
||||
dev_err(&pdev->dev, "failed to get IRQ\n");
|
||||
return -ENXIO;
|
||||
dev_err(&pdev->dev, "failed to get IRQ: %d\n", syncpt_irq);
|
||||
return syncpt_irq;
|
||||
}
|
||||
|
||||
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
|
||||
|
|
|
@ -33,10 +33,10 @@ static void host1x_intr_syncpt_handle(struct host1x_syncpt *syncpt)
|
|||
unsigned int id = syncpt->id;
|
||||
struct host1x *host = syncpt->host;
|
||||
|
||||
host1x_sync_writel(host, BIT_MASK(id),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(BIT_WORD(id)));
|
||||
host1x_sync_writel(host, BIT_MASK(id),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(BIT_WORD(id)));
|
||||
host1x_sync_writel(host, BIT(id % 32),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32));
|
||||
host1x_sync_writel(host, BIT(id % 32),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32));
|
||||
|
||||
schedule_work(&syncpt->intr.work);
|
||||
}
|
||||
|
@ -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++) {
|
||||
reg = host1x_sync_readl(host,
|
||||
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));
|
||||
for_each_set_bit(id, ®, BITS_PER_LONG) {
|
||||
for_each_set_bit(id, ®, 32) {
|
||||
struct host1x_syncpt *syncpt =
|
||||
host->syncpt + (i * BITS_PER_LONG + id);
|
||||
host->syncpt + (i * 32 + id);
|
||||
host1x_intr_syncpt_handle(syncpt);
|
||||
}
|
||||
}
|
||||
|
@ -117,17 +117,17 @@ static void _host1x_intr_set_syncpt_threshold(struct host1x *host,
|
|||
static void _host1x_intr_enable_syncpt_intr(struct host1x *host,
|
||||
unsigned int id)
|
||||
{
|
||||
host1x_sync_writel(host, BIT_MASK(id),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(BIT_WORD(id)));
|
||||
host1x_sync_writel(host, BIT(id % 32),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id / 32));
|
||||
}
|
||||
|
||||
static void _host1x_intr_disable_syncpt_intr(struct host1x *host,
|
||||
unsigned int id)
|
||||
{
|
||||
host1x_sync_writel(host, BIT_MASK(id),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(BIT_WORD(id)));
|
||||
host1x_sync_writel(host, BIT_MASK(id),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(BIT_WORD(id)));
|
||||
host1x_sync_writel(host, BIT(id % 32),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32));
|
||||
host1x_sync_writel(host, BIT(id % 32),
|
||||
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32));
|
||||
}
|
||||
|
||||
static int _host1x_free_syncpt_irq(struct host1x *host)
|
||||
|
|
|
@ -89,7 +89,7 @@ static int syncpt_cpu_incr(struct host1x_syncpt *sp)
|
|||
host1x_syncpt_idle(sp))
|
||||
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));
|
||||
wmb();
|
||||
|
||||
|
|
|
@ -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);
|
||||
if (!phys_addr) {
|
||||
err = -EINVAL;
|
||||
goto unpin;
|
||||
}
|
||||
|
||||
job->addr_phys[job->num_unpins] = phys_addr;
|
||||
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)
|
|||
}
|
||||
|
||||
phys_addr = host1x_bo_pin(g->bo, &sgt);
|
||||
if (!phys_addr) {
|
||||
err = -EINVAL;
|
||||
goto unpin;
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) {
|
||||
for_each_sg(sgt->sgl, sg, sgt->nents, j)
|
||||
|
|
Loading…
Reference in New Issue