Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -17,4 +17,6 @@ tegra-drm-y := \
	falcon.o \
	vic.o

tegra-drm-y += trace.o

obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
+9 −3
Original line number Diff line number Diff line
@@ -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));
}

+70 −32
Original line number Diff line number Diff line
@@ -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);

	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,
+9 −3
Original line number Diff line number Diff line
@@ -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 {
Loading