summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/include/mach/nvhost.h4
-rw-r--r--drivers/video/tegra/host/dev.c14
-rw-r--r--drivers/video/tegra/host/nvhost_channel.c38
-rw-r--r--drivers/video/tegra/host/nvhost_channel.h3
4 files changed, 47 insertions, 12 deletions
diff --git a/arch/arm/mach-tegra/include/mach/nvhost.h b/arch/arm/mach-tegra/include/mach/nvhost.h
index c72666ae0d37..fc0336a42b50 100644
--- a/arch/arm/mach-tegra/include/mach/nvhost.h
+++ b/arch/arm/mach-tegra/include/mach/nvhost.h
@@ -114,8 +114,10 @@ struct nvhost_set_nvmap_fd_args {
_IOR(NVHOST_IOCTL_MAGIC, 4, struct nvhost_get_param_args)
#define NVHOST_IOCTL_CHANNEL_SET_NVMAP_FD \
_IOW(NVHOST_IOCTL_MAGIC, 5, struct nvhost_set_nvmap_fd_args)
+#define NVHOST_IOCTL_CHANNEL_NULL_KICKOFF \
+ _IOR(NVHOST_IOCTL_MAGIC, 6, struct nvhost_get_param_args)
#define NVHOST_IOCTL_CHANNEL_LAST \
- _IOC_NR(NVHOST_IOCTL_CHANNEL_SET_NVMAP_FD)
+ _IOC_NR(NVHOST_IOCTL_CHANNEL_NULL_KICKOFF)
#define NVHOST_IOCTL_CHANNEL_MAX_ARG_SIZE sizeof(struct nvhost_get_param_args)
struct nvhost_ctrl_syncpt_read_args {
diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c
index c9c88b0171a7..8b577cc9045f 100644
--- a/drivers/video/tegra/host/dev.c
+++ b/drivers/video/tegra/host/dev.c
@@ -210,7 +210,8 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
}
static int nvhost_ioctl_channel_flush(struct nvhost_channel_userctx *ctx,
- struct nvhost_get_param_args *args)
+ struct nvhost_get_param_args *args,
+ int null_kickoff)
{
struct nvhost_cpuinterrupt ctxsw;
int gather_idx = 2;
@@ -218,6 +219,7 @@ static int nvhost_ioctl_channel_flush(struct nvhost_channel_userctx *ctx,
u32 syncval;
int num_unpin;
int err;
+ int nulled_incrs = null_kickoff ? ctx->syncpt_incrs : 0;
if (ctx->relocs_pending || ctx->cmdbufs_pending) {
reset_submit(ctx);
@@ -300,9 +302,10 @@ static int nvhost_ioctl_channel_flush(struct nvhost_channel_userctx *ctx,
ctxsw.syncpt_val += syncval - ctx->syncpt_incrs;
nvhost_channel_submit(ctx->ch, ctx->nvmap, &ctx->gathers[gather_idx],
- ctx->num_gathers - gather_idx, &ctxsw, num_intrs,
+ (null_kickoff ? 2 : ctx->num_gathers) - gather_idx, &ctxsw, num_intrs,
ctx->unpinarray, num_unpin,
- ctx->syncpt_id, syncval);
+ ctx->syncpt_id, syncval,
+ nulled_incrs);
/* schedule a submit complete interrupt */
nvhost_intr_add_action(&ctx->ch->dev->intr, ctx->syncpt_id, syncval,
@@ -334,7 +337,10 @@ static long nvhost_channelctl(struct file *filp,
switch (cmd) {
case NVHOST_IOCTL_CHANNEL_FLUSH:
- err = nvhost_ioctl_channel_flush(priv, (void *)buf);
+ err = nvhost_ioctl_channel_flush(priv, (void *)buf, 0);
+ break;
+ case NVHOST_IOCTL_CHANNEL_NULL_KICKOFF:
+ err = nvhost_ioctl_channel_flush(priv, (void *)buf, 1);
break;
case NVHOST_IOCTL_CHANNEL_GET_SYNCPOINTS:
((struct nvhost_get_param_args *)buf)->value =
diff --git a/drivers/video/tegra/host/nvhost_channel.c b/drivers/video/tegra/host/nvhost_channel.c
index 949e67ffb653..70fb173d7f41 100644
--- a/drivers/video/tegra/host/nvhost_channel.c
+++ b/drivers/video/tegra/host/nvhost_channel.c
@@ -168,11 +168,12 @@ void nvhost_channel_suspend(struct nvhost_channel *ch)
}
void nvhost_channel_submit(struct nvhost_channel *ch,
- struct nvmap_client *user_nvmap,
- struct nvhost_op_pair *ops, int num_pairs,
- struct nvhost_cpuinterrupt *intrs, int num_intrs,
- struct nvmap_handle **unpins, int num_unpins,
- u32 syncpt_id, u32 syncpt_val)
+ struct nvmap_client *user_nvmap,
+ struct nvhost_op_pair *ops, int num_pairs,
+ struct nvhost_cpuinterrupt *intrs, int num_intrs,
+ struct nvmap_handle **unpins, int num_unpins,
+ u32 syncpt_id, u32 syncpt_val,
+ int num_nulled_incrs)
{
int i;
struct nvhost_op_pair* p;
@@ -190,6 +191,31 @@ void nvhost_channel_submit(struct nvhost_channel *ch,
for (i = 0, p = ops; i < num_pairs; i++, p++)
nvhost_cdma_push(&ch->cdma, p->op1, p->op2);
+ /* extra work to do for null kickoff */
+ if (num_nulled_incrs) {
+ u32 incr;
+ u32 op_incr;
+
+ /* TODO ideally we'd also perform host waits here */
+
+ /* push increments that correspond to nulled out commands */
+ op_incr = nvhost_opcode_imm(0, 0x100 | syncpt_id);
+ for (incr = 0; incr < (num_nulled_incrs >> 1); incr++)
+ nvhost_cdma_push(&ch->cdma, op_incr, op_incr);
+ if (num_nulled_incrs & 1)
+ nvhost_cdma_push(&ch->cdma, op_incr, NVHOST_OPCODE_NOOP);
+
+ /* for 3d, waitbase needs to be incremented after each submit */
+ if (ch->desc->class == NV_GRAPHICS_3D_CLASS_ID) {
+ u32 op1 = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
+ NV_CLASS_HOST_INCR_SYNCPT_BASE, 1);
+ u32 op2 = nvhost_class_host_incr_syncpt_base(NVWAITBASE_3D,
+ num_nulled_incrs);
+
+ nvhost_cdma_push(&ch->cdma, op1, op2);
+ }
+ }
+
/* end CDMA submit & stash pinned hMems into sync queue for later cleanup */
nvhost_cdma_end(user_nvmap, &ch->cdma, syncpt_id, syncpt_val,
unpins, num_unpins);
@@ -228,7 +254,7 @@ static void power_3d(struct nvhost_module *mod, enum nvhost_power_action action)
nvhost_channel_submit(ch, ch->dev->nvmap,
&save, 1, &ctxsw, 1, NULL, 0,
- NVSYNCPT_3D, syncval);
+ NVSYNCPT_3D, syncval, 0);
nvhost_intr_add_action(&ch->dev->intr, NVSYNCPT_3D,
syncval,
diff --git a/drivers/video/tegra/host/nvhost_channel.h b/drivers/video/tegra/host/nvhost_channel.h
index c62d7397a192..59ba06543a48 100644
--- a/drivers/video/tegra/host/nvhost_channel.h
+++ b/drivers/video/tegra/host/nvhost_channel.h
@@ -80,7 +80,8 @@ void nvhost_channel_submit(struct nvhost_channel *ch,
struct nvhost_op_pair *ops, int num_pairs,
struct nvhost_cpuinterrupt *intrs, int num_intrs,
struct nvmap_handle **unpins, int num_unpins,
- u32 syncpt_id, u32 syncpt_val);
+ u32 syncpt_id, u32 syncpt_val,
+ int num_nulled_incrs);
struct nvhost_channel *nvhost_getchannel(struct nvhost_channel *ch);
void nvhost_putchannel(struct nvhost_channel *ch, struct nvhost_hwctx *ctx);