diff options
author | Dan Willemsen <dwillemsen@nvidia.com> | 2010-08-11 10:55:17 +0300 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-01-25 15:26:37 -0800 |
commit | c2aece97469747851ab911591b549721a37c194f (patch) | |
tree | 782621673fddd6a66ff7c3def52dc3a4c145abcc /drivers/video/tegra/host/nvhost_channel.c | |
parent | f32916a170d98f56172ab2896b290a4fa955d1ef (diff) |
nvhost: Reimplement null kickoff functionality.
For each channel submit where null kickoff is requested, we don't
place the user's commands in the pushbuffer. All necessary context
switches, syncpoint increments and waitbase increments do happen
though.
Update: Add NULL_KICKOFF ioctl to use instead of FLIP, this prevents
kernel ABI breakage.
Bug 717235
Previous Id: I51c323729ea57993a5b52fb395ab90cb8608ee6b
Previously Reviewed: http://git-master/r/5091
Change-Id: I4f92db457aff6e1c3a8d454255c4b051c4663360
Reviewed-on: http://git-master/r/15882
Reviewed-by: Daniel Willemsen <dwillemsen@nvidia.com>
Tested-by: Daniel Willemsen <dwillemsen@nvidia.com>
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Diffstat (limited to 'drivers/video/tegra/host/nvhost_channel.c')
-rw-r--r-- | drivers/video/tegra/host/nvhost_channel.c | 38 |
1 files changed, 32 insertions, 6 deletions
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, |