diff options
-rw-r--r-- | arch/arm/mach-tegra/include/mach/nvhost.h | 4 | ||||
-rw-r--r-- | drivers/video/tegra/host/dev.c | 14 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_channel.c | 38 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_channel.h | 3 |
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); |