diff options
-rw-r--r-- | drivers/video/tegra/host/dev.c | 6 | ||||
-rw-r--r-- | drivers/video/tegra/host/gr3d/gr3d.c | 49 | ||||
-rw-r--r-- | drivers/video/tegra/host/gr3d/gr3d.h | 16 | ||||
-rw-r--r-- | drivers/video/tegra/host/gr3d/gr3d_t20.c | 129 | ||||
-rw-r--r-- | drivers/video/tegra/host/gr3d/gr3d_t20.h | 4 | ||||
-rw-r--r-- | drivers/video/tegra/host/gr3d/gr3d_t30.c | 121 | ||||
-rw-r--r-- | drivers/video/tegra/host/gr3d/gr3d_t30.h | 4 | ||||
-rw-r--r-- | drivers/video/tegra/host/host1x/host1x_cdma.c | 3 | ||||
-rw-r--r-- | drivers/video/tegra/host/host1x/host1x_channel.c | 95 | ||||
-rw-r--r-- | drivers/video/tegra/host/host1x/host1x_hwctx.h | 65 | ||||
-rw-r--r-- | drivers/video/tegra/host/mpe/mpe.c | 144 | ||||
-rw-r--r-- | drivers/video/tegra/host/mpe/mpe.h | 4 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_channel.c | 1 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_channel.h | 2 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_hwctx.h | 21 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_intr.c | 8 | ||||
-rw-r--r-- | drivers/video/tegra/host/t20/t20.c | 28 | ||||
-rw-r--r-- | drivers/video/tegra/host/t30/t30.c | 28 | ||||
-rw-r--r-- | include/linux/nvhost.h | 3 |
19 files changed, 424 insertions, 307 deletions
diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c index 38efa0975a2e..4ab0f1e0c106 100644 --- a/drivers/video/tegra/host/dev.c +++ b/drivers/video/tegra/host/dev.c @@ -125,7 +125,7 @@ static int nvhost_channelrelease(struct inode *inode, struct file *filp) nvhost_putchannel(priv->ch, priv->hwctx); if (priv->hwctx) - priv->ch->ctxhandler.put(priv->hwctx); + priv->ch->ctxhandler->put(priv->hwctx); if (priv->job) nvhost_job_put(priv->job); @@ -155,8 +155,8 @@ static int nvhost_channelopen(struct inode *inode, struct file *filp) priv->ch = ch; nvhost_module_add_client(ch->dev, priv); - if (ch->ctxhandler.alloc) { - priv->hwctx = ch->ctxhandler.alloc(ch); + if (ch->ctxhandler && ch->ctxhandler->alloc) { + priv->hwctx = ch->ctxhandler->alloc(ch->ctxhandler, ch); if (!priv->hwctx) goto fail; } diff --git a/drivers/video/tegra/host/gr3d/gr3d.c b/drivers/video/tegra/host/gr3d/gr3d.c index c26387f43c97..6e7f87ea0cd6 100644 --- a/drivers/video/tegra/host/gr3d/gr3d.c +++ b/drivers/video/tegra/host/gr3d/gr3d.c @@ -30,21 +30,14 @@ #include "dev.h" #include "gr3d.h" -unsigned int nvhost_3dctx_restore_size; -unsigned int nvhost_3dctx_restore_incrs; -struct nvmap_handle_ref *nvhost_3dctx_save_buf; -unsigned int nvhost_3dctx_save_incrs; -unsigned int nvhost_3dctx_save_thresh; -unsigned int nvhost_3dctx_save_slots; - -void nvhost_3dctx_restore_begin(u32 *ptr) +void nvhost_3dctx_restore_begin(struct host1x_hwctx_handler *p, u32 *ptr) { /* set class to host */ ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, NV_CLASS_HOST_INCR_SYNCPT_BASE, 1); /* increment sync point base */ - ptr[1] = nvhost_class_host_incr_syncpt_base(NVWAITBASE_3D, - nvhost_3dctx_restore_incrs); + ptr[1] = nvhost_class_host_incr_syncpt_base(p->waitbase, + p->restore_incrs); /* set class to 3D */ ptr[2] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0); /* program PSEQ_QUAD_ID */ @@ -63,25 +56,25 @@ void nvhost_3dctx_restore_indirect(u32 *ptr, u32 offset_reg, u32 offset, ptr[1] = nvhost_opcode_nonincr(data_reg, count); } -void nvhost_3dctx_restore_end(u32 *ptr) +void nvhost_3dctx_restore_end(struct host1x_hwctx_handler *p, u32 *ptr) { /* syncpt increment to track restore gather. */ ptr[0] = nvhost_opcode_imm_incr_syncpt( - NV_SYNCPT_OP_DONE, NVSYNCPT_3D); + NV_SYNCPT_OP_DONE, p->syncpt); } /*** ctx3d ***/ -struct nvhost_hwctx *nvhost_3dctx_alloc_common(struct nvhost_channel *ch, - bool map_restore) +struct host1x_hwctx *nvhost_3dctx_alloc_common(struct host1x_hwctx_handler *p, + struct nvhost_channel *ch, bool map_restore) { struct nvmap_client *nvmap = nvhost_get_host(ch->dev)->nvmap; - struct nvhost_hwctx *ctx; + struct host1x_hwctx *ctx; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return NULL; - ctx->restore = nvmap_alloc(nvmap, nvhost_3dctx_restore_size * 4, 32, + ctx->restore = nvmap_alloc(nvmap, p->restore_size * 4, 32, map_restore ? NVMAP_HANDLE_WRITE_COMBINE : NVMAP_HANDLE_UNCACHEABLE); if (IS_ERR_OR_NULL(ctx->restore)) @@ -94,19 +87,19 @@ struct nvhost_hwctx *nvhost_3dctx_alloc_common(struct nvhost_channel *ch, } else ctx->restore_virt = NULL; - kref_init(&ctx->ref); - ctx->channel = ch; - ctx->valid = false; - ctx->save = nvhost_3dctx_save_buf; - ctx->save_incrs = nvhost_3dctx_save_incrs; - ctx->save_thresh = nvhost_3dctx_save_thresh; - ctx->save_slots = nvhost_3dctx_save_slots; + kref_init(&ctx->hwctx.ref); + ctx->hwctx.h = &p->h; + ctx->hwctx.channel = ch; + ctx->hwctx.valid = false; + ctx->save_incrs = p->save_incrs; + ctx->save_thresh = p->save_thresh; + ctx->save_slots = p->save_slots; ctx->restore_phys = nvmap_pin(nvmap, ctx->restore); if (IS_ERR_VALUE(ctx->restore_phys)) goto fail; - ctx->restore_size = nvhost_3dctx_restore_size; - ctx->restore_incrs = nvhost_3dctx_restore_incrs; + ctx->restore_size = p->restore_size; + ctx->restore_incrs = p->restore_incrs; return ctx; fail: @@ -127,8 +120,10 @@ void nvhost_3dctx_get(struct nvhost_hwctx *ctx) void nvhost_3dctx_free(struct kref *ref) { - struct nvhost_hwctx *ctx = container_of(ref, struct nvhost_hwctx, ref); - struct nvmap_client *nvmap = nvhost_get_host(ctx->channel->dev)->nvmap; + struct nvhost_hwctx *nctx = container_of(ref, struct nvhost_hwctx, ref); + struct host1x_hwctx *ctx = to_host1x_hwctx(nctx); + struct nvmap_client *nvmap = + nvhost_get_host(nctx->channel->dev)->nvmap; if (ctx->restore_virt) { nvmap_munmap(ctx->restore, ctx->restore_virt); diff --git a/drivers/video/tegra/host/gr3d/gr3d.h b/drivers/video/tegra/host/gr3d/gr3d.h index 00c25ea0c32c..3855b237b702 100644 --- a/drivers/video/tegra/host/gr3d/gr3d.h +++ b/drivers/video/tegra/host/gr3d/gr3d.h @@ -21,6 +21,7 @@ #ifndef __NVHOST_GR3D_GR3D_H #define __NVHOST_GR3D_GR3D_H +#include "host1x/host1x_hwctx.h" #include <linux/types.h> /* Registers of 3D unit */ @@ -32,25 +33,18 @@ #define AR3D_GSHIM_READ_SELECT 0xb01 #define AR3D_GLOBAL_MEMORY_OUTPUT_READS 0xe40 -/* Internal variables used by common 3D context switch functions */ -extern unsigned int nvhost_3dctx_restore_size; -extern unsigned int nvhost_3dctx_restore_incrs; -extern struct nvmap_handle_ref *nvhost_3dctx_save_buf; -extern unsigned int nvhost_3dctx_save_incrs; -extern unsigned int nvhost_3dctx_save_thresh; -extern unsigned int nvhost_3dctx_save_slots; - struct nvhost_hwctx; struct nvhost_channel; struct kref; /* Functions used commonly by all 3D context switch modules */ -void nvhost_3dctx_restore_begin(u32 *ptr); +void nvhost_3dctx_restore_begin(struct host1x_hwctx_handler *h, u32 *ptr); void nvhost_3dctx_restore_direct(u32 *ptr, u32 start_reg, u32 count); void nvhost_3dctx_restore_indirect(u32 *ptr, u32 offset_reg, u32 offset, u32 data_reg, u32 count); -void nvhost_3dctx_restore_end(u32 *ptr); -struct nvhost_hwctx *nvhost_3dctx_alloc_common( +void nvhost_3dctx_restore_end(struct host1x_hwctx_handler *h, u32 *ptr); +struct host1x_hwctx *nvhost_3dctx_alloc_common( + struct host1x_hwctx_handler *p, struct nvhost_channel *ch, bool map_restore); void nvhost_3dctx_get(struct nvhost_hwctx *ctx); void nvhost_3dctx_free(struct kref *ref); diff --git a/drivers/video/tegra/host/gr3d/gr3d_t20.c b/drivers/video/tegra/host/gr3d/gr3d_t20.c index b067c3ec2459..90892aa1e7ee 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t20.c +++ b/drivers/video/tegra/host/gr3d/gr3d_t20.c @@ -66,9 +66,6 @@ static const struct hwctx_reginfo ctxsave_regs_3d_global[] = { }; /* the same context save command sequence is used for all contexts. */ -static phys_addr_t save_phys; -static unsigned int save_size; - #define SAVE_BEGIN_V0_SIZE 5 #define SAVE_DIRECT_V0_SIZE 3 #define SAVE_INDIRECT_V0_SIZE 5 @@ -117,46 +114,48 @@ static u32 *setup_restore_regs_v0(u32 *ptr, return ptr; } -static void setup_restore_v0(u32 *ptr) +static void setup_restore_v0(struct host1x_hwctx_handler *h, u32 *ptr) { - nvhost_3dctx_restore_begin(ptr); + nvhost_3dctx_restore_begin(h, ptr); ptr += RESTORE_BEGIN_SIZE; ptr = setup_restore_regs_v0(ptr, ctxsave_regs_3d_global, ARRAY_SIZE(ctxsave_regs_3d_global)); - nvhost_3dctx_restore_end(ptr); + nvhost_3dctx_restore_end(h, ptr); wmb(); } /*** v0 saver ***/ -static void save_push_v0(struct nvhost_cdma *cdma, - struct nvhost_hwctx *ctx) +static void save_push_v0(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma) { + struct host1x_hwctx *ctx = to_host1x_hwctx(nctx); + struct host1x_hwctx_handler *p = host1x_hwctx_handler(ctx); + nvhost_cdma_push_gather(cdma, (void *)NVHOST_CDMA_PUSH_GATHER_CTXSAVE, (void *)NVHOST_CDMA_PUSH_GATHER_CTXSAVE, - nvhost_opcode_gather(save_size), - save_phys); + nvhost_opcode_gather(p->save_size), + p->save_phys); } -static void __init save_begin_v0(u32 *ptr) +static void __init save_begin_v0(struct host1x_hwctx_handler *h, u32 *ptr) { /* 3d: when done, increment syncpt to base+1 */ ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0); ptr[1] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, - NVSYNCPT_3D); /* incr 1 */ + h->syncpt); /* incr 1 */ /* host: wait for syncpt base+1 */ ptr[2] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1); - ptr[3] = nvhost_class_host_wait_syncpt_base(NVSYNCPT_3D, - NVWAITBASE_3D, 1); + ptr[3] = nvhost_class_host_wait_syncpt_base(h->syncpt, + h->waitbase, 1); /* host: signal context read thread to start reading */ ptr[4] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_IMMEDIATE, - NVSYNCPT_3D); /* incr 2 */ + h->syncpt); /* incr 2 */ } static void __init save_direct_v0(u32 *ptr, u32 start_reg, u32 count) @@ -180,16 +179,16 @@ static void __init save_indirect_v0(u32 *ptr, u32 offset_reg, u32 offset, ptr[4] = nvhost_opcode_nonincr(NV_CLASS_HOST_INDDATA, count); } -static void __init save_end_v0(u32 *ptr) +static void __init save_end_v0(struct host1x_hwctx_handler *h, u32 *ptr) { /* Wait for context read service to finish (cpu incr 3) */ ptr[0] = nvhost_opcode_nonincr(NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1); - ptr[1] = nvhost_class_host_wait_syncpt_base(NVSYNCPT_3D, - NVWAITBASE_3D, nvhost_3dctx_save_incrs); + ptr[1] = nvhost_class_host_wait_syncpt_base(h->syncpt, + h->waitbase, h->save_incrs); /* Advance syncpoint base */ ptr[2] = nvhost_opcode_nonincr(NV_CLASS_HOST_INCR_SYNCPT_BASE, 1); ptr[3] = nvhost_class_host_incr_syncpt_base(NVWAITBASE_3D, - nvhost_3dctx_save_incrs); + h->save_incrs); /* set class back to the unit */ ptr[4] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0); } @@ -281,7 +280,7 @@ static void __init setup_save_regs(struct save_info *info, info->restore_count = restore_count; } -static void __init setup_save(u32 *ptr) +static void __init setup_save(struct host1x_hwctx_handler *h, u32 *ptr) { struct save_info info = { ptr, @@ -292,7 +291,7 @@ static void __init setup_save(u32 *ptr) }; if (info.ptr) { - save_begin_v0(info.ptr); + save_begin_v0(h, info.ptr); info.ptr += SAVE_BEGIN_V0_SIZE; } @@ -302,83 +301,95 @@ static void __init setup_save(u32 *ptr) ARRAY_SIZE(ctxsave_regs_3d_global)); if (info.ptr) { - save_end_v0(info.ptr); + save_end_v0(h, info.ptr); info.ptr += SAVE_END_V0_SIZE; } wmb(); - save_size = info.save_count + SAVE_END_V0_SIZE; - nvhost_3dctx_restore_size = info.restore_count + RESTORE_END_SIZE; - nvhost_3dctx_save_incrs = info.save_incrs; - nvhost_3dctx_save_thresh = - nvhost_3dctx_save_incrs - SAVE_THRESH_OFFSET; - nvhost_3dctx_restore_incrs = info.restore_incrs; + h->save_size = info.save_count + SAVE_END_V0_SIZE; + h->restore_size = info.restore_count + RESTORE_END_SIZE; + h->save_incrs = info.save_incrs; + h->save_thresh = h->save_incrs - SAVE_THRESH_OFFSET; + h->restore_incrs = info.restore_incrs; } /*** ctx3d ***/ -static struct nvhost_hwctx *ctx3d_alloc_v0(struct nvhost_channel *ch) +static struct nvhost_hwctx *ctx3d_alloc_v0(struct nvhost_hwctx_handler *h, + struct nvhost_channel *ch) { - struct nvhost_hwctx *ctx = nvhost_3dctx_alloc_common(ch, true); - if (ctx) - setup_restore_v0(ctx->restore_virt); - return ctx; + struct host1x_hwctx_handler *p = to_host1x_hwctx_handler(h); + struct host1x_hwctx *ctx = + nvhost_3dctx_alloc_common(p, ch, true); + if (ctx) { + setup_restore_v0(p, ctx->restore_virt); + return &ctx->hwctx; + } else + return NULL; } -static void ctx3d_save_service(struct nvhost_hwctx *ctx) +static void ctx3d_save_service(struct nvhost_hwctx *nctx) { + struct host1x_hwctx *ctx = to_host1x_hwctx(nctx); + u32 *ptr = (u32 *)ctx->restore_virt + RESTORE_BEGIN_SIZE; unsigned int pending = 0; - ptr = save_regs_v0(ptr, &pending, ctx->channel->aperture, + ptr = save_regs_v0(ptr, &pending, nctx->channel->aperture, ctxsave_regs_3d_global, ARRAY_SIZE(ctxsave_regs_3d_global)); wmb(); - nvhost_syncpt_cpu_incr(&nvhost_get_host(ctx->channel->dev)->syncpt, - NVSYNCPT_3D); + nvhost_syncpt_cpu_incr(&nvhost_get_host(nctx->channel->dev)->syncpt, + host1x_hwctx_handler(ctx)->syncpt); } -int __init nvhost_gr3d_t20_ctxhandler_init(struct nvhost_hwctx_handler *h) +struct nvhost_hwctx_handler * __init nvhost_gr3d_t20_ctxhandler_init( + u32 syncpt, u32 waitbase, + struct nvhost_channel *ch) { - struct nvhost_channel *ch; struct nvmap_client *nvmap; u32 *save_ptr; + struct host1x_hwctx_handler *p; - ch = container_of(h, struct nvhost_channel, ctxhandler); + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; nvmap = nvhost_get_host(ch->dev)->nvmap; - setup_save(NULL); + p->syncpt = syncpt; + p->waitbase = waitbase; + + setup_save(p, NULL); - nvhost_3dctx_save_buf = nvmap_alloc(nvmap, save_size * sizeof(u32), 32, + p->save_buf = nvmap_alloc(nvmap, p->save_size * sizeof(u32), 32, NVMAP_HANDLE_WRITE_COMBINE); - if (IS_ERR(nvhost_3dctx_save_buf)) { - int err = PTR_ERR(nvhost_3dctx_save_buf); - nvhost_3dctx_save_buf = NULL; - return err; + if (IS_ERR(p->save_buf)) { + p->save_buf = NULL; + return NULL; } - nvhost_3dctx_save_slots = 1; + p->save_slots = 1; - save_ptr = nvmap_mmap(nvhost_3dctx_save_buf); + save_ptr = nvmap_mmap(p->save_buf); if (!save_ptr) { - nvmap_free(nvmap, nvhost_3dctx_save_buf); - nvhost_3dctx_save_buf = NULL; - return -ENOMEM; + nvmap_free(nvmap, p->save_buf); + p->save_buf = NULL; + return NULL; } - save_phys = nvmap_pin(nvmap, nvhost_3dctx_save_buf); + p->save_phys = nvmap_pin(nvmap, p->save_buf); - setup_save(save_ptr); + setup_save(p, save_ptr); - h->alloc = ctx3d_alloc_v0; - h->save_push = save_push_v0; - h->save_service = ctx3d_save_service; - h->get = nvhost_3dctx_get; - h->put = nvhost_3dctx_put; + p->h.alloc = ctx3d_alloc_v0; + p->h.save_push = save_push_v0; + p->h.save_service = ctx3d_save_service; + p->h.get = nvhost_3dctx_get; + p->h.put = nvhost_3dctx_put; - return 0; + return &p->h; } diff --git a/drivers/video/tegra/host/gr3d/gr3d_t20.h b/drivers/video/tegra/host/gr3d/gr3d_t20.h index 6141084557b2..5fe6d50d0c30 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t20.h +++ b/drivers/video/tegra/host/gr3d/gr3d_t20.h @@ -23,6 +23,8 @@ struct nvhost_hwctx_handler; -int nvhost_gr3d_t20_ctxhandler_init(struct nvhost_hwctx_handler *h); +struct nvhost_hwctx_handler *nvhost_gr3d_t20_ctxhandler_init( + u32 syncpt, u32 waitbase, + struct nvhost_channel *ch); #endif diff --git a/drivers/video/tegra/host/gr3d/gr3d_t30.c b/drivers/video/tegra/host/gr3d/gr3d_t30.c index 05a009e9f56b..6a7c1470c199 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t30.c +++ b/drivers/video/tegra/host/gr3d/gr3d_t30.c @@ -84,10 +84,6 @@ static const struct hwctx_reginfo ctxsave_regs_3d_perset[] = { static unsigned int restore_set1_offset; -/* the same context save command sequence is used for all contexts. */ -static phys_addr_t save_phys; -static unsigned int save_size; - #define SAVE_BEGIN_V1_SIZE (1 + RESTORE_BEGIN_SIZE) #define SAVE_DIRECT_V1_SIZE (4 + RESTORE_DIRECT_SIZE) #define SAVE_INDIRECT_V1_SIZE (6 + RESTORE_INDIRECT_SIZE) @@ -109,19 +105,21 @@ struct save_info { /*** v1 saver ***/ -static void save_push_v1(struct nvhost_cdma *cdma, - struct nvhost_hwctx *ctx) +static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma) { + struct host1x_hwctx *ctx = to_host1x_hwctx(nctx); + struct host1x_hwctx_handler *p = host1x_hwctx_handler(ctx); + /* wait for 3d idle */ nvhost_cdma_push(cdma, nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0), nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, - NVSYNCPT_3D)); + p->syncpt)); nvhost_cdma_push(cdma, nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1), - nvhost_class_host_wait_syncpt_base(NVSYNCPT_3D, - NVWAITBASE_3D, 1)); + nvhost_class_host_wait_syncpt_base(p->syncpt, + p->waitbase, 1)); /* back to 3d */ nvhost_cdma_push(cdma, nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0), @@ -147,15 +145,15 @@ static void save_push_v1(struct nvhost_cdma *cdma, nvhost_cdma_push_gather(cdma, (void *)NVHOST_CDMA_PUSH_GATHER_CTXSAVE, (void *)NVHOST_CDMA_PUSH_GATHER_CTXSAVE, - nvhost_opcode_gather(save_size), - save_phys); + nvhost_opcode_gather(p->save_size), + p->save_phys); } -static void __init save_begin_v1(u32 *ptr) +static void __init save_begin_v1(struct host1x_hwctx_handler *p, u32 *ptr) { ptr[0] = nvhost_opcode_nonincr(AR3D_DW_MEMORY_OUTPUT_DATA, RESTORE_BEGIN_SIZE); - nvhost_3dctx_restore_begin(ptr + 1); + nvhost_3dctx_restore_begin(p, ptr + 1); ptr += RESTORE_BEGIN_SIZE; } @@ -190,34 +188,34 @@ static void __init save_indirect_v1(u32 *ptr, u32 offset_reg, u32 offset, ptr[5] = nvhost_opcode_nonincr(NV_CLASS_HOST_INDDATA, count); } -static void __init save_end_v1(u32 *ptr) +static void __init save_end_v1(struct host1x_hwctx_handler *p, u32 *ptr) { /* write end of restore buffer */ ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, AR3D_DW_MEMORY_OUTPUT_DATA, 1); - nvhost_3dctx_restore_end(ptr + 1); + nvhost_3dctx_restore_end(p, ptr + 1); ptr += RESTORE_END_SIZE; /* reset to dual reg if necessary */ ptr[1] = nvhost_opcode_imm(AR3D_GSHIM_WRITE_MASK, (1 << register_sets) - 1); /* op_done syncpt incr to flush FDC */ - ptr[2] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, NVSYNCPT_3D); + ptr[2] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, p->syncpt); /* host wait for that syncpt incr, and advance the wait base */ ptr[3] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, NV_CLASS_HOST_WAIT_SYNCPT_BASE, nvhost_mask2( NV_CLASS_HOST_WAIT_SYNCPT_BASE, NV_CLASS_HOST_INCR_SYNCPT_BASE)); - ptr[4] = nvhost_class_host_wait_syncpt_base(NVSYNCPT_3D, - NVWAITBASE_3D, nvhost_3dctx_save_incrs - 1); - ptr[5] = nvhost_class_host_incr_syncpt_base(NVWAITBASE_3D, - nvhost_3dctx_save_incrs); + ptr[4] = nvhost_class_host_wait_syncpt_base(p->syncpt, + p->waitbase, p->save_incrs - 1); + ptr[5] = nvhost_class_host_incr_syncpt_base(p->waitbase, + p->save_incrs); /* set class back to 3d */ ptr[6] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0); /* send reg reads back to host */ ptr[7] = nvhost_opcode_imm(AR3D_GLOBAL_MEMORY_OUTPUT_READS, 0); /* final syncpt increment to release waiters */ - ptr[8] = nvhost_opcode_imm(0, NVSYNCPT_3D); + ptr[8] = nvhost_opcode_imm(0, p->syncpt); } /*** save ***/ @@ -303,7 +301,7 @@ static void __init switch_gpu(struct save_info *info, info->restore_count += 1; } -static void __init setup_save(u32 *ptr) +static void __init setup_save(struct host1x_hwctx_handler *p, u32 *ptr) { struct save_info info = { ptr, @@ -317,7 +315,7 @@ static void __init setup_save(u32 *ptr) BUG_ON(register_sets > 2); if (info.ptr) { - save_begin_v1(info.ptr); + save_begin_v1(p, info.ptr); info.ptr += SAVE_BEGIN_V1_SIZE; } @@ -355,70 +353,83 @@ static void __init setup_save(u32 *ptr) switch_gpu(&info, 0, 2, 3); if (info.ptr) { - save_end_v1(info.ptr); + save_end_v1(p, info.ptr); info.ptr += SAVE_END_V1_SIZE; } wmb(); - save_size = info.save_count + save_end_size; - nvhost_3dctx_restore_size = info.restore_count + RESTORE_END_SIZE; - nvhost_3dctx_save_incrs = info.save_incrs; - nvhost_3dctx_save_thresh = nvhost_3dctx_save_incrs - - SAVE_THRESH_OFFSET; - nvhost_3dctx_restore_incrs = info.restore_incrs; + p->save_size = info.save_count + save_end_size; + p->restore_size = info.restore_count + RESTORE_END_SIZE; + p->save_incrs = info.save_incrs; + p->save_thresh = p->save_incrs - SAVE_THRESH_OFFSET; + p->restore_incrs = info.restore_incrs; } /*** ctx3d ***/ -static struct nvhost_hwctx *ctx3d_alloc_v1(struct nvhost_channel *ch) +static struct nvhost_hwctx *ctx3d_alloc_v1(struct nvhost_hwctx_handler *h, + struct nvhost_channel *ch) { - return nvhost_3dctx_alloc_common(ch, false); + struct host1x_hwctx_handler *p = to_host1x_hwctx_handler(h); + struct host1x_hwctx *ctx = nvhost_3dctx_alloc_common(p, ch, false); + + if (ctx) + return &ctx->hwctx; + else + return NULL; } -int __init nvhost_gr3d_t30_ctxhandler_init(struct nvhost_hwctx_handler *h) +struct nvhost_hwctx_handler *__init nvhost_gr3d_t30_ctxhandler_init( + u32 syncpt, u32 waitbase, + struct nvhost_channel *ch) { - struct nvhost_channel *ch; struct nvmap_client *nvmap; u32 *save_ptr; + struct host1x_hwctx_handler *p; + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; - ch = container_of(h, struct nvhost_channel, ctxhandler); nvmap = nvhost_get_host(ch->dev)->nvmap; register_sets = tegra_gpu_register_sets(); BUG_ON(register_sets == 0 || register_sets > 2); - setup_save(NULL); + p->syncpt = syncpt; + p->waitbase = waitbase; + + setup_save(p, NULL); - nvhost_3dctx_save_buf = nvmap_alloc(nvmap, save_size * 4, 32, + p->save_buf = nvmap_alloc(nvmap, p->save_size * 4, 32, NVMAP_HANDLE_WRITE_COMBINE); - if (IS_ERR(nvhost_3dctx_save_buf)) { - int err = PTR_ERR(nvhost_3dctx_save_buf); - nvhost_3dctx_save_buf = NULL; - return err; + if (IS_ERR(p->save_buf)) { + p->save_buf = NULL; + return NULL; } - nvhost_3dctx_save_slots = 6; + p->save_slots = 6; if (register_sets == 2) - nvhost_3dctx_save_slots += 2; + p->save_slots += 2; - save_ptr = nvmap_mmap(nvhost_3dctx_save_buf); + save_ptr = nvmap_mmap(p->save_buf); if (!save_ptr) { - nvmap_free(nvmap, nvhost_3dctx_save_buf); - nvhost_3dctx_save_buf = NULL; - return -ENOMEM; + nvmap_free(nvmap, p->save_buf); + p->save_buf = NULL; + return NULL; } - save_phys = nvmap_pin(nvmap, nvhost_3dctx_save_buf); + p->save_phys = nvmap_pin(nvmap, p->save_buf); - setup_save(save_ptr); + setup_save(p, save_ptr); - h->alloc = ctx3d_alloc_v1; - h->save_push = save_push_v1; - h->save_service = NULL; - h->get = nvhost_3dctx_get; - h->put = nvhost_3dctx_put; + p->h.alloc = ctx3d_alloc_v1; + p->h.save_push = save_push_v1; + p->h.save_service = NULL; + p->h.get = nvhost_3dctx_get; + p->h.put = nvhost_3dctx_put; - return 0; + return &p->h; } diff --git a/drivers/video/tegra/host/gr3d/gr3d_t30.h b/drivers/video/tegra/host/gr3d/gr3d_t30.h index 409f1afeb837..d1b787e14b44 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t30.h +++ b/drivers/video/tegra/host/gr3d/gr3d_t30.h @@ -23,6 +23,8 @@ struct nvhost_hwctx_handler; -int nvhost_gr3d_t30_ctxhandler_init(struct nvhost_hwctx_handler *h); +struct nvhost_hwctx_handler *nvhost_gr3d_t30_ctxhandler_init( + u32 syncpt, u32 waitbase, + struct nvhost_channel *ch); #endif diff --git a/drivers/video/tegra/host/host1x/host1x_cdma.c b/drivers/video/tegra/host/host1x/host1x_cdma.c index c670e08ecdae..09552753943e 100644 --- a/drivers/video/tegra/host/host1x/host1x_cdma.c +++ b/drivers/video/tegra/host/host1x/host1x_cdma.c @@ -26,6 +26,7 @@ #include "host1x_hardware.h" #include "host1x_syncpt.h" #include "host1x_cdma.h" +#include "host1x_hwctx.h" static inline u32 host1x_channel_dmactrl(int stop, int get_rst, int init_get) { @@ -336,7 +337,7 @@ static void cdma_timeout_pb_incr(struct nvhost_cdma *cdma, u32 getptr, struct nvhost_master *dev = cdma_to_dev(cdma); struct syncpt_buffer *sb = &cdma->syncpt_buffer; struct push_buffer *pb = &cdma->push_buffer; - struct nvhost_hwctx *hwctx = cdma->timeout.ctx; + struct host1x_hwctx *hwctx = to_host1x_hwctx(cdma->timeout.ctx); u32 getidx, *p; /* should have enough slots to incr to desired count */ diff --git a/drivers/video/tegra/host/host1x/host1x_channel.c b/drivers/video/tegra/host/host1x/host1x_channel.c index 7142ceaa71a2..34ae8879ba18 100644 --- a/drivers/video/tegra/host/host1x/host1x_channel.c +++ b/drivers/video/tegra/host/host1x/host1x_channel.c @@ -27,6 +27,7 @@ #include "host1x_syncpt.h" #include "host1x_channel.h" #include "host1x_hardware.h" +#include "host1x_hwctx.h" #include "nvhost_intr.h" #define NV_FIFO_READ_TIMEOUT 200000 @@ -48,7 +49,7 @@ static void sync_waitbases(struct nvhost_channel *ch, u32 syncpt_val) int host1x_channel_submit(struct nvhost_job *job) { - struct nvhost_hwctx *hwctx_to_save = NULL; + struct host1x_hwctx *hwctx_to_save = NULL; struct nvhost_channel *channel = job->ch; struct nvhost_syncpt *sp = &nvhost_get_host(job->ch->dev)->syncpt; u32 user_syncpt_incrs = job->syncpt_incrs; @@ -125,9 +126,10 @@ int host1x_channel_submit(struct nvhost_job *job) if (channel->cur_ctx != job->hwctx) { trace_nvhost_channel_context_switch(channel->dev->name, channel->cur_ctx, job->hwctx); - hwctx_to_save = channel->cur_ctx; + hwctx_to_save = channel->cur_ctx ? + to_host1x_hwctx(channel->cur_ctx) : NULL; if (hwctx_to_save && - hwctx_to_save->has_timedout) { + hwctx_to_save->hwctx.has_timedout) { hwctx_to_save = NULL; dev_dbg(&channel->dev->dev, "%s: skip save of timed out context (0x%p)\n", @@ -135,12 +137,13 @@ int host1x_channel_submit(struct nvhost_job *job) } if (hwctx_to_save) { job->syncpt_incrs += hwctx_to_save->save_incrs; - hwctx_to_save->valid = true; - channel->ctxhandler.get(hwctx_to_save); + hwctx_to_save->hwctx.valid = true; + channel->ctxhandler->get(&hwctx_to_save->hwctx); } channel->cur_ctx = job->hwctx; if (need_restore) - job->syncpt_incrs += channel->cur_ctx->restore_incrs; + job->syncpt_incrs += + to_host1x_hwctx(job->hwctx)->restore_incrs; } /* get absolute sync value */ @@ -155,16 +158,19 @@ int host1x_channel_submit(struct nvhost_job *job) /* push save buffer (pre-gather setup depends on unit) */ if (hwctx_to_save) - channel->ctxhandler.save_push(&channel->cdma, hwctx_to_save); + channel->ctxhandler->save_push(&hwctx_to_save->hwctx, + &channel->cdma); /* gather restore buffer */ if (need_restore) { + struct host1x_hwctx *cur_ctx = + to_host1x_hwctx(channel->cur_ctx); nvhost_cdma_push_gather(&channel->cdma, nvhost_get_host(channel->dev)->nvmap, - nvmap_ref_to_handle(channel->cur_ctx->restore), - nvhost_opcode_gather(channel->cur_ctx->restore_size), - channel->cur_ctx->restore_phys); - channel->ctxhandler.get(channel->cur_ctx); + nvmap_ref_to_handle(cur_ctx->restore), + nvhost_opcode_gather(cur_ctx->restore_size), + cur_ctx->restore_phys); + channel->ctxhandler->get(channel->cur_ctx); } /* add a setclass for modules that require it (unless ctxsw added it) */ @@ -225,7 +231,7 @@ int host1x_channel_submit(struct nvhost_job *job) job->syncpt_id, syncval - job->syncpt_incrs + hwctx_to_save->save_thresh, - NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save, + NVHOST_INTR_ACTION_CTXSAVE, &hwctx_to_save->hwctx, ctxsave_waiter, NULL); ctxsave_waiter = NULL; @@ -269,7 +275,9 @@ int host1x_channel_read_3d_reg( u32 offset, u32 *value) { - struct nvhost_hwctx *hwctx_to_save = NULL; + struct host1x_hwctx *hwctx_to_save = NULL; + struct nvhost_hwctx_handler *h = hwctx->h; + struct host1x_hwctx_handler *p = to_host1x_hwctx_handler(h); bool need_restore = false; u32 syncpt_incrs = 4; unsigned int pending = 0; @@ -311,23 +319,25 @@ int host1x_channel_read_3d_reg( /* context switch */ if (channel->cur_ctx != hwctx) { - hwctx_to_save = channel->cur_ctx; + hwctx_to_save = channel->cur_ctx ? + to_host1x_hwctx(channel->cur_ctx) : NULL; if (hwctx_to_save) { syncpt_incrs += hwctx_to_save->save_incrs; - hwctx_to_save->valid = true; - channel->ctxhandler.get(hwctx_to_save); + hwctx_to_save->hwctx.valid = true; + channel->ctxhandler->get(&hwctx_to_save->hwctx); } channel->cur_ctx = hwctx; if (channel->cur_ctx && channel->cur_ctx->valid) { need_restore = true; - syncpt_incrs += channel->cur_ctx->restore_incrs; + syncpt_incrs += to_host1x_hwctx(channel->cur_ctx) + ->restore_incrs; } } syncval = nvhost_syncpt_incr_max(&nvhost_get_host(channel->dev)->syncpt, - NVSYNCPT_3D, syncpt_incrs); + p->syncpt, syncpt_incrs); - job->syncpt_id = NVSYNCPT_3D; + job->syncpt_id = p->syncpt; job->syncpt_incrs = syncpt_incrs; job->syncpt_end = syncval; @@ -336,23 +346,25 @@ int host1x_channel_read_3d_reg( /* push save buffer (pre-gather setup depends on unit) */ if (hwctx_to_save) - channel->ctxhandler.save_push(&channel->cdma, hwctx_to_save); + h->save_push(&hwctx_to_save->hwctx, &channel->cdma); /* gather restore buffer */ if (need_restore) nvhost_cdma_push(&channel->cdma, - nvhost_opcode_gather(channel->cur_ctx->restore_size), - channel->cur_ctx->restore_phys); + nvhost_opcode_gather(to_host1x_hwctx(channel->cur_ctx) + ->restore_size), + to_host1x_hwctx(channel->cur_ctx)->restore_phys); /* Switch to 3D - wait for it to complete what it was doing */ nvhost_cdma_push(&channel->cdma, nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0), - nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, NVSYNCPT_3D)); + nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, + p->syncpt)); nvhost_cdma_push(&channel->cdma, nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1), - nvhost_class_host_wait_syncpt_base(NVSYNCPT_3D, - NVWAITBASE_3D, 1)); + nvhost_class_host_wait_syncpt_base(p->syncpt, + p->waitbase, 1)); /* Tell 3D to send register value to FIFO */ nvhost_cdma_push(&channel->cdma, nvhost_opcode_nonincr(NV_CLASS_HOST_INDOFF, 1), @@ -364,21 +376,21 @@ int host1x_channel_read_3d_reg( /* Increment syncpt to indicate that FIFO can be read */ nvhost_cdma_push(&channel->cdma, nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_IMMEDIATE, - NVSYNCPT_3D), + p->syncpt), NVHOST_OPCODE_NOOP); /* Wait for value to be read from FIFO */ nvhost_cdma_push(&channel->cdma, nvhost_opcode_nonincr(NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1), - nvhost_class_host_wait_syncpt_base(NVSYNCPT_3D, - NVWAITBASE_3D, 3)); + nvhost_class_host_wait_syncpt_base(p->syncpt, + p->waitbase, 3)); /* Indicate submit complete */ nvhost_cdma_push(&channel->cdma, nvhost_opcode_nonincr(NV_CLASS_HOST_INCR_SYNCPT_BASE, 1), - nvhost_class_host_incr_syncpt_base(NVWAITBASE_3D, 4)); + nvhost_class_host_incr_syncpt_base(p->waitbase, 4)); nvhost_cdma_push(&channel->cdma, NVHOST_OPCODE_NOOP, nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_IMMEDIATE, - NVSYNCPT_3D)); + p->syncpt)); /* end CDMA submit */ nvhost_cdma_end(&channel->cdma, job); @@ -392,8 +404,10 @@ int host1x_channel_read_3d_reg( if (hwctx_to_save) { err = nvhost_intr_add_action( &nvhost_get_host(channel->dev)->intr, - NVSYNCPT_3D, - syncval - syncpt_incrs + hwctx_to_save->save_incrs - 1, + p->syncpt, + syncval - syncpt_incrs + + hwctx_to_save->save_incrs + - 1, NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save, ctx_waiter, NULL); @@ -403,7 +417,7 @@ int host1x_channel_read_3d_reg( /* Wait for FIFO to be ready */ err = nvhost_intr_add_action(&nvhost_get_host(channel->dev)->intr, - NVSYNCPT_3D, syncval - 2, + p->syncpt, syncval - 2, NVHOST_INTR_ACTION_WAKEUP, &wq, read_waiter, &ref); @@ -411,7 +425,7 @@ int host1x_channel_read_3d_reg( WARN(err, "Failed to set wakeup interrupt"); wait_event(wq, nvhost_syncpt_min_cmp(&nvhost_get_host(channel->dev)->syncpt, - NVSYNCPT_3D, syncval - 2)); + p->syncpt, syncval - 2)); nvhost_intr_put_ref(&nvhost_get_host(channel->dev)->intr, ref); /* Read the register value from FIFO */ @@ -420,11 +434,11 @@ int host1x_channel_read_3d_reg( /* Indicate we've read the value */ nvhost_syncpt_cpu_incr(&nvhost_get_host(channel->dev)->syncpt, - NVSYNCPT_3D); + p->syncpt); /* Schedule a submit complete interrupt */ err = nvhost_intr_add_action(&nvhost_get_host(channel->dev)->intr, - NVSYNCPT_3D, syncval, + p->syncpt, syncval, NVHOST_INTR_ACTION_SUBMIT_COMPLETE, channel, completed_waiter, NULL); completed_waiter = NULL; @@ -520,10 +534,10 @@ int host1x_save_context(struct nvhost_device *dev, u32 syncpt_id) } hwctx_to_save->valid = true; - ch->ctxhandler.get(hwctx_to_save); + ch->ctxhandler->get(hwctx_to_save); ch->cur_ctx = NULL; - syncpt_incrs = hwctx_to_save->save_incrs; + syncpt_incrs = to_host1x_hwctx(hwctx_to_save)->save_incrs; syncpt_val = nvhost_syncpt_incr_max(&nvhost_get_host(ch->dev)->syncpt, syncpt_id, syncpt_incrs); @@ -537,13 +551,14 @@ int host1x_save_context(struct nvhost_device *dev, u32 syncpt_id) goto done; } - ch->ctxhandler.save_push(&ch->cdma, hwctx_to_save); + ch->ctxhandler->save_push(hwctx_to_save, &ch->cdma); nvhost_cdma_end(&ch->cdma, job); nvhost_job_put(job); job = NULL; err = nvhost_intr_add_action(&nvhost_get_host(ch->dev)->intr, syncpt_id, - syncpt_val - syncpt_incrs + hwctx_to_save->save_thresh, + syncpt_val - syncpt_incrs + + to_host1x_hwctx(hwctx_to_save)->save_thresh, NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save, ctx_waiter, NULL); diff --git a/drivers/video/tegra/host/host1x/host1x_hwctx.h b/drivers/video/tegra/host/host1x/host1x_hwctx.h new file mode 100644 index 000000000000..7587642d0e14 --- /dev/null +++ b/drivers/video/tegra/host/host1x/host1x_hwctx.h @@ -0,0 +1,65 @@ +/* + * drivers/video/tegra/host/host1x/host1x_hwctx.h + * + * Tegra Graphics Host HOST1X Hardware Context Interface + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __NVHOST_HOST1X_HWCTX_H +#define __NVHOST_HOST1X_HWCTX_H + +#include <linux/kref.h> + +struct nvhost_hwctx_handler; +struct nvhost_channel; + +#define to_host1x_hwctx_handler(handler) \ + container_of((handler), struct host1x_hwctx_handler, h) +#define to_host1x_hwctx(h) container_of((h), struct host1x_hwctx, hwctx) +#define host1x_hwctx_handler(_hwctx) to_host1x_hwctx_handler((_hwctx)->hwctx.h) + +struct host1x_hwctx { + struct nvhost_hwctx hwctx; + + u32 save_incrs; + u32 save_thresh; + u32 save_slots; + + struct nvmap_handle_ref *restore; + u32 *restore_virt; + phys_addr_t restore_phys; + u32 restore_size; + u32 restore_incrs; +}; + +struct host1x_hwctx_handler { + struct nvhost_hwctx_handler h; + + u32 syncpt; + u32 waitbase; + u32 restore_size; + u32 restore_incrs; + struct nvmap_handle_ref *save_buf; + u32 save_incrs; + u32 save_thresh; + u32 save_slots; + phys_addr_t save_phys; + u32 save_size; +}; + +#endif diff --git a/drivers/video/tegra/host/mpe/mpe.c b/drivers/video/tegra/host/mpe/mpe.c index 0f39500ed2e0..a5459e885de4 100644 --- a/drivers/video/tegra/host/mpe/mpe.c +++ b/drivers/video/tegra/host/mpe/mpe.c @@ -23,6 +23,7 @@ #include "host1x/host1x_hardware.h" #include "host1x/host1x_channel.h" #include "host1x/host1x_syncpt.h" +#include "host1x/host1x_hwctx.h" #include "t20/t20.h" #include <linux/slab.h> @@ -130,13 +131,13 @@ struct mpe_save_info { static unsigned int restore_size; -static void restore_begin(u32 *ptr) +static void restore_begin(struct host1x_hwctx_handler *h, u32 *ptr) { /* set class to host */ ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, NV_CLASS_HOST_INCR_SYNCPT_BASE, 1); /* increment sync point base */ - ptr[1] = nvhost_class_host_incr_syncpt_base(NVWAITBASE_MPE, 1); + ptr[1] = nvhost_class_host_incr_syncpt_base(h->waitbase, 1); /* set class to MPE */ ptr[2] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0); } @@ -150,11 +151,11 @@ static void restore_ram(u32 *ptr, unsigned words, } #define RESTORE_RAM_SIZE 2 -static void restore_end(u32 *ptr) +static void restore_end(struct host1x_hwctx_handler *h, u32 *ptr) { /* syncpt increment to track restore gather. */ ptr[0] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, - NVSYNCPT_MPE); + h->syncpt); } #define RESTORE_END_SIZE 1 @@ -180,9 +181,9 @@ static u32 *setup_restore_ram(u32 *ptr, unsigned words, return ptr + (RESTORE_RAM_SIZE + words); } -static void setup_restore(u32 *ptr) +static void setup_restore(struct host1x_hwctx_handler *h, u32 *ptr) { - restore_begin(ptr); + restore_begin(h, ptr); ptr += RESTORE_BEGIN_SIZE; ptr = setup_restore_regs(ptr, ctxsave_regs_mpe, @@ -194,39 +195,30 @@ static void setup_restore(u32 *ptr) ptr = setup_restore_ram(ptr, IRFR_RAM_SIZE, IRFR_RAM_LOAD_CMD, IRFR_RAM_LOAD_DATA); - restore_end(ptr); + restore_end(h, ptr); wmb(); } /*** save ***/ - -/* the same context save command sequence is used for all contexts. */ -static struct nvmap_handle_ref *save_buf; -static phys_addr_t save_phys; -static unsigned int save_size; - struct save_info { u32 *ptr; unsigned int save_count; unsigned int restore_count; }; -static void __init save_begin(u32 *ptr) +static void __init save_begin(struct host1x_hwctx_handler *h, u32 *ptr) { /* MPE: when done, increment syncpt to base+1 */ ptr[0] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0); - ptr[1] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, - NVSYNCPT_MPE); + ptr[1] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, h->syncpt); /* host: wait for syncpt base+1 */ ptr[2] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1); - ptr[3] = nvhost_class_host_wait_syncpt_base(NVSYNCPT_MPE, - NVWAITBASE_MPE, 1); + ptr[3] = nvhost_class_host_wait_syncpt_base(h->syncpt, h->waitbase, 1); /* host: signal context read thread to start reading */ - ptr[4] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_IMMEDIATE, - NVSYNCPT_MPE); + ptr[4] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_IMMEDIATE, h->syncpt); } #define SAVE_BEGIN_SIZE 5 @@ -262,16 +254,15 @@ static void __init save_read_ram_data_nasty(u32 *ptr, u32 data_reg) } #define SAVE_READ_RAM_DATA_NASTY_SIZE 5 -static void __init save_end(u32 *ptr) +static void __init save_end(struct host1x_hwctx_handler *h, u32 *ptr) { /* Wait for context read service to finish (cpu incr 3) */ ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1); - ptr[1] = nvhost_class_host_wait_syncpt_base(NVSYNCPT_MPE, - NVWAITBASE_MPE, 3); + ptr[1] = nvhost_class_host_wait_syncpt_base(h->syncpt, h->waitbase, 3); /* Advance syncpoint base */ ptr[2] = nvhost_opcode_nonincr(NV_CLASS_HOST_INCR_SYNCPT_BASE, 1); - ptr[3] = nvhost_class_host_incr_syncpt_base(NVWAITBASE_MPE, 3); + ptr[3] = nvhost_class_host_incr_syncpt_base(h->waitbase, 3); /* set class back to the unit */ ptr[4] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0); } @@ -332,7 +323,7 @@ static void __init setup_save_ram_nasty(struct save_info *info, unsigned words, info->restore_count = restore_count; } -static void __init setup_save(u32 *ptr) +static void __init setup_save(struct host1x_hwctx_handler *h, u32 *ptr) { struct save_info info = { ptr, @@ -341,7 +332,7 @@ static void __init setup_save(u32 *ptr) }; if (info.ptr) { - save_begin(info.ptr); + save_begin(h, info.ptr); info.ptr += SAVE_BEGIN_SIZE; } @@ -355,13 +346,13 @@ static void __init setup_save(u32 *ptr) IRFR_RAM_READ_CMD, IRFR_RAM_READ_DATA); if (info.ptr) { - save_end(info.ptr); + save_end(h, info.ptr); info.ptr += SAVE_END_SIZE; } wmb(); - save_size = info.save_count + SAVE_END_SIZE; + h->save_size = info.save_count + SAVE_END_SIZE; restore_size = info.restore_count + RESTORE_END_SIZE; } @@ -435,10 +426,12 @@ static u32 *save_ram(u32 *ptr, unsigned int *pending, /*** ctxmpe ***/ -static struct nvhost_hwctx *ctxmpe_alloc(struct nvhost_channel *ch) +static struct nvhost_hwctx *ctxmpe_alloc(struct nvhost_hwctx_handler *h, + struct nvhost_channel *ch) { struct nvmap_client *nvmap = nvhost_get_host(ch->dev)->nvmap; - struct nvhost_hwctx *ctx; + struct host1x_hwctx_handler *p = to_host1x_hwctx_handler(h); + struct host1x_hwctx *ctx; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -457,19 +450,19 @@ static struct nvhost_hwctx *ctxmpe_alloc(struct nvhost_channel *ch) return NULL; } - kref_init(&ctx->ref); - ctx->channel = ch; - ctx->valid = false; - ctx->save = save_buf; + kref_init(&ctx->hwctx.ref); + ctx->hwctx.h = &p->h; + ctx->hwctx.channel = ch; + ctx->hwctx.valid = false; ctx->save_incrs = 3; ctx->save_thresh = 2; ctx->restore_phys = nvmap_pin(nvmap, ctx->restore); ctx->restore_size = restore_size; ctx->restore_incrs = 1; - setup_restore(ctx->restore_virt); + setup_restore(p, ctx->restore_virt); - return ctx; + return &ctx->hwctx; } static void ctxmpe_get(struct nvhost_hwctx *ctx) @@ -479,8 +472,10 @@ static void ctxmpe_get(struct nvhost_hwctx *ctx) static void ctxmpe_free(struct kref *ref) { - struct nvhost_hwctx *ctx = container_of(ref, struct nvhost_hwctx, ref); - struct nvmap_client *nvmap = nvhost_get_host(ctx->channel->dev)->nvmap; + struct nvhost_hwctx *nctx = container_of(ref, struct nvhost_hwctx, ref); + struct host1x_hwctx *ctx = to_host1x_hwctx(nctx); + struct nvmap_client *nvmap = + nvhost_get_host(nctx->channel->dev)->nvmap; if (ctx->restore_virt) nvmap_munmap(ctx->restore, ctx->restore_virt); @@ -494,15 +489,21 @@ static void ctxmpe_put(struct nvhost_hwctx *ctx) kref_put(&ctx->ref, ctxmpe_free); } -static void ctxmpe_save_push(struct nvhost_cdma *cdma, struct nvhost_hwctx *ctx) +static void ctxmpe_save_push(struct nvhost_hwctx *nctx, + struct nvhost_cdma *cdma) { + struct host1x_hwctx *ctx = to_host1x_hwctx(nctx); + struct host1x_hwctx_handler *h = host1x_hwctx_handler(ctx); nvhost_cdma_push(cdma, - nvhost_opcode_gather(save_size), - save_phys); + nvhost_opcode_gather(h->save_size), + h->save_phys); } -static void ctxmpe_save_service(struct nvhost_hwctx *ctx) +static void ctxmpe_save_service(struct nvhost_hwctx *nctx) { + struct host1x_hwctx *ctx = to_host1x_hwctx(nctx); + struct host1x_hwctx_handler *h = host1x_hwctx_handler(ctx); + u32 *ptr = (u32 *)ctx->restore_virt + RESTORE_BEGIN_SIZE; unsigned int pending = 0; struct mpe_save_info msi; @@ -510,57 +511,64 @@ static void ctxmpe_save_service(struct nvhost_hwctx *ctx) msi.in_pos = 0; msi.out_pos = 0; - ptr = save_regs(ptr, &pending, ctx->channel, + ptr = save_regs(ptr, &pending, nctx->channel, ctxsave_regs_mpe, ARRAY_SIZE(ctxsave_regs_mpe), &msi); - ptr = save_ram(ptr, &pending, ctx->channel, + ptr = save_ram(ptr, &pending, nctx->channel, RC_RAM_SIZE, RC_RAM_READ_CMD, RC_RAM_READ_DATA); - ptr = save_ram(ptr, &pending, ctx->channel, + ptr = save_ram(ptr, &pending, nctx->channel, IRFR_RAM_SIZE, IRFR_RAM_READ_CMD, IRFR_RAM_READ_DATA); wmb(); - nvhost_syncpt_cpu_incr(&nvhost_get_host(ctx->channel->dev)->syncpt, - NVSYNCPT_MPE); + nvhost_syncpt_cpu_incr(&nvhost_get_host(nctx->channel->dev)->syncpt, + h->syncpt); } -int __init nvhost_mpe_ctxhandler_init(struct nvhost_hwctx_handler *h) +struct nvhost_hwctx_handler * __init nvhost_mpe_ctxhandler_init( + u32 syncpt, u32 waitbase, + struct nvhost_channel *ch) { - struct nvhost_channel *ch; struct nvmap_client *nvmap; u32 *save_ptr; + struct host1x_hwctx_handler *p; + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; - ch = container_of(h, struct nvhost_channel, ctxhandler); nvmap = nvhost_get_host(ch->dev)->nvmap; - setup_save(NULL); + p->syncpt = syncpt; + p->waitbase = waitbase; + + setup_save(p, NULL); - save_buf = nvmap_alloc(nvmap, save_size * 4, 32, + p->save_buf = nvmap_alloc(nvmap, p->save_size * 4, 32, NVMAP_HANDLE_WRITE_COMBINE); - if (IS_ERR(save_buf)) { - int err = PTR_ERR(save_buf); - save_buf = NULL; - return err; + if (IS_ERR(p->save_buf)) { + p->save_buf = NULL; + return NULL; } - save_ptr = nvmap_mmap(save_buf); + save_ptr = nvmap_mmap(p->save_buf); if (!save_ptr) { - nvmap_free(nvmap, save_buf); - save_buf = NULL; - return -ENOMEM; + nvmap_free(nvmap, p->save_buf); + p->save_buf = NULL; + return NULL; } - save_phys = nvmap_pin(nvmap, save_buf); + p->save_phys = nvmap_pin(nvmap, p->save_buf); - setup_save(save_ptr); + setup_save(p, save_ptr); - h->alloc = ctxmpe_alloc; - h->save_push = ctxmpe_save_push; - h->save_service = ctxmpe_save_service; - h->get = ctxmpe_get; - h->put = ctxmpe_put; + p->h.alloc = ctxmpe_alloc; + p->h.save_push = ctxmpe_save_push; + p->h.save_service = ctxmpe_save_service; + p->h.get = ctxmpe_get; + p->h.put = ctxmpe_put; - return 0; + return &p->h; } int nvhost_mpe_prepare_power_off(struct nvhost_device *dev) diff --git a/drivers/video/tegra/host/mpe/mpe.h b/drivers/video/tegra/host/mpe/mpe.h index 8ec7f7b1ff8c..1bc2a8a04c1a 100644 --- a/drivers/video/tegra/host/mpe/mpe.h +++ b/drivers/video/tegra/host/mpe/mpe.h @@ -24,7 +24,9 @@ struct nvhost_hwctx_handler; struct nvhost_device; -int nvhost_mpe_ctxhandler_init(struct nvhost_hwctx_handler *h); +struct nvhost_hwctx_handler *nvhost_mpe_ctxhandler_init( + u32 syncpt, u32 waitbase, + struct nvhost_channel *ch); int nvhost_mpe_prepare_power_off(struct nvhost_device *dev); #endif diff --git a/drivers/video/tegra/host/nvhost_channel.c b/drivers/video/tegra/host/nvhost_channel.c index c4834b5c9aa6..a7c033081341 100644 --- a/drivers/video/tegra/host/nvhost_channel.c +++ b/drivers/video/tegra/host/nvhost_channel.c @@ -20,7 +20,6 @@ #include "nvhost_channel.h" #include "dev.h" -#include "nvhost_hwctx.h" #include "nvhost_job.h" #include <trace/events/nvhost.h> #include <linux/nvhost_ioctl.h> diff --git a/drivers/video/tegra/host/nvhost_channel.h b/drivers/video/tegra/host/nvhost_channel.h index 260ae82242f6..7b946c8ee853 100644 --- a/drivers/video/tegra/host/nvhost_channel.h +++ b/drivers/video/tegra/host/nvhost_channel.h @@ -56,7 +56,7 @@ struct nvhost_channel { struct device *node; struct nvhost_device *dev; struct cdev cdev; - struct nvhost_hwctx_handler ctxhandler; + struct nvhost_hwctx_handler *ctxhandler; struct nvhost_cdma cdma; }; diff --git a/drivers/video/tegra/host/nvhost_hwctx.h b/drivers/video/tegra/host/nvhost_hwctx.h index a2fef66d7c05..02a3976f01ce 100644 --- a/drivers/video/tegra/host/nvhost_hwctx.h +++ b/drivers/video/tegra/host/nvhost_hwctx.h @@ -32,30 +32,21 @@ struct nvhost_cdma; struct nvhost_hwctx { struct kref ref; - + struct nvhost_hwctx_handler *h; struct nvhost_channel *channel; bool valid; - - struct nvmap_handle_ref *save; - u32 save_incrs; - u32 save_thresh; - u32 save_slots; - - struct nvmap_handle_ref *restore; - u32 *restore_virt; - phys_addr_t restore_phys; - u32 restore_size; - u32 restore_incrs; - bool has_timedout; }; struct nvhost_hwctx_handler { - struct nvhost_hwctx * (*alloc) (struct nvhost_channel *ch); + struct nvhost_hwctx * (*alloc) (struct nvhost_hwctx_handler *h, + struct nvhost_channel *ch); void (*get) (struct nvhost_hwctx *ctx); void (*put) (struct nvhost_hwctx *ctx); - void (*save_push) (struct nvhost_cdma *cdma, struct nvhost_hwctx *ctx); + void (*save_push) (struct nvhost_hwctx *ctx, + struct nvhost_cdma *cdma); void (*save_service) (struct nvhost_hwctx *ctx); + void *priv; }; diff --git a/drivers/video/tegra/host/nvhost_intr.c b/drivers/video/tegra/host/nvhost_intr.c index fe3948dbadf4..0fc6652c7c77 100644 --- a/drivers/video/tegra/host/nvhost_intr.c +++ b/drivers/video/tegra/host/nvhost_intr.c @@ -142,9 +142,9 @@ static void action_ctxsave(struct nvhost_waitlist *waiter) struct nvhost_hwctx *hwctx = waiter->data; struct nvhost_channel *channel = hwctx->channel; - if (channel->ctxhandler.save_service) - channel->ctxhandler.save_service(hwctx); - channel->ctxhandler.put(hwctx); + if (channel->ctxhandler->save_service) + channel->ctxhandler->save_service(hwctx); + channel->ctxhandler->put(hwctx); } static void action_ctxrestore(struct nvhost_waitlist *waiter) @@ -152,7 +152,7 @@ static void action_ctxrestore(struct nvhost_waitlist *waiter) struct nvhost_hwctx *hwctx = waiter->data; struct nvhost_channel *channel = hwctx->channel; - channel->ctxhandler.put(hwctx); + channel->ctxhandler->put(hwctx); } static void action_wakeup(struct nvhost_waitlist *waiter) diff --git a/drivers/video/tegra/host/t20/t20.c b/drivers/video/tegra/host/t20/t20.c index cbc6f71556bd..227e2b77469e 100644 --- a/drivers/video/tegra/host/t20/t20.c +++ b/drivers/video/tegra/host/t20/t20.c @@ -29,6 +29,7 @@ #include "gr3d/gr3d.h" #include "gr3d/gr3d_t20.h" #include "mpe/mpe.h" +#include "nvhost_hwctx.h" #define NVMODMUTEX_2D_FULL (1) #define NVMODMUTEX_2D_SIMPLE (2) @@ -65,6 +66,7 @@ struct nvhost_device devices[] = { .modulemutexes = BIT(NVMODMUTEX_3D), .class = NV_GRAPHICS_3D_CLASS_ID, .prepare_poweroff = nvhost_gr3d_prepare_power_off, + .alloc_hwctx_handler = nvhost_gr3d_t20_ctxhandler_init, .clocks = {{"gr3d", UINT_MAX}, {"emc", UINT_MAX}, {} }, .powergate_ids = {TEGRA_POWERGATE_3D, -1}, NVHOST_DEFAULT_CLOCKGATE_DELAY, @@ -119,6 +121,7 @@ struct nvhost_device devices[] = { .waitbasesync = true, .keepalive = true, .prepare_poweroff = nvhost_mpe_prepare_power_off, + .alloc_hwctx_handler = nvhost_mpe_ctxhandler_init, .clocks = {{"mpe", UINT_MAX}, {"emc", UINT_MAX}, {} }, .powergate_ids = {TEGRA_POWERGATE_MPE, -1}, NVHOST_DEFAULT_CLOCKGATE_DELAY, @@ -142,15 +145,22 @@ static inline void __iomem *t20_channel_aperture(void __iomem *p, int ndx) return p; } -static inline int t20_nvhost_hwctx_handler_init( - struct nvhost_hwctx_handler *h, - const char *module) +static inline int t20_nvhost_hwctx_handler_init(struct nvhost_channel *ch) { - if (strcmp(module, "gr3d") == 0) - return nvhost_gr3d_t20_ctxhandler_init(h); - else if (strcmp(module, "mpe") == 0) - return nvhost_mpe_ctxhandler_init(h); - return 0; + int err = 0; + unsigned long syncpts = ch->dev->syncpts; + unsigned long waitbases = ch->dev->waitbases; + u32 syncpt = find_first_bit(&syncpts, BITS_PER_LONG); + u32 waitbase = find_first_bit(&waitbases, BITS_PER_LONG); + + if (ch->dev->alloc_hwctx_handler) { + ch->ctxhandler = ch->dev->alloc_hwctx_handler(syncpt, + waitbase, ch); + if (!ch->ctxhandler) + err = -ENOMEM; + } + + return err; } static int t20_channel_init(struct nvhost_channel *ch, @@ -164,7 +174,7 @@ static int t20_channel_init(struct nvhost_channel *ch, nvhost_device_register(ch->dev); ch->aperture = t20_channel_aperture(dev->aperture, index); - return t20_nvhost_hwctx_handler_init(&ch->ctxhandler, ch->dev->name); + return t20_nvhost_hwctx_handler_init(ch); } int nvhost_init_t20_channel_support(struct nvhost_master *host) diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c index 88a44ab30605..484f077d63d9 100644 --- a/drivers/video/tegra/host/t30/t30.c +++ b/drivers/video/tegra/host/t30/t30.c @@ -75,6 +75,7 @@ static struct nvhost_device devices[] = { .init = nvhost_scale3d_init, .deinit = nvhost_scale3d_deinit, .suspend = nvhost_scale3d_suspend, + .alloc_hwctx_handler = nvhost_gr3d_t30_ctxhandler_init, .clocks = {{"gr3d", UINT_MAX}, {"gr3d2", UINT_MAX}, {"emc", UINT_MAX} }, @@ -134,6 +135,7 @@ static struct nvhost_device devices[] = { .waitbasesync = true, .keepalive = true, .prepare_poweroff = nvhost_mpe_prepare_power_off, + .alloc_hwctx_handler = nvhost_mpe_ctxhandler_init, .clocks = {{"mpe", UINT_MAX}, {"emc", UINT_MAX}, {} }, .powergate_ids = {TEGRA_POWERGATE_MPE, -1}, NVHOST_DEFAULT_CLOCKGATE_DELAY, @@ -154,16 +156,22 @@ static struct nvhost_device devices[] = { #define NVHOST_CHANNEL_BASE 0 -static inline int t30_nvhost_hwctx_handler_init( - struct nvhost_hwctx_handler *h, - const char *module) +static inline int t30_nvhost_hwctx_handler_init(struct nvhost_channel *ch) { - if (strcmp(module, "gr3d") == 0) - return nvhost_gr3d_t30_ctxhandler_init(h); - else if (strcmp(module, "mpe") == 0) - return nvhost_mpe_ctxhandler_init(h); - - return 0; + int err = 0; + unsigned long syncpts = ch->dev->syncpts; + unsigned long waitbases = ch->dev->waitbases; + u32 syncpt = find_first_bit(&syncpts, BITS_PER_LONG); + u32 waitbase = find_first_bit(&waitbases, BITS_PER_LONG); + + if (ch->dev->alloc_hwctx_handler) { + ch->ctxhandler = ch->dev->alloc_hwctx_handler(syncpt, + waitbase, ch); + if (!ch->ctxhandler) + err = -ENOMEM; + } + + return err; } static inline void __iomem *t30_channel_aperture(void __iomem *p, int ndx) @@ -185,7 +193,7 @@ static int t30_channel_init(struct nvhost_channel *ch, nvhost_device_register(ch->dev); ch->aperture = t30_channel_aperture(dev->aperture, index); - return t30_nvhost_hwctx_handler_init(&ch->ctxhandler, ch->dev->name); + return t30_nvhost_hwctx_handler_init(ch); } int nvhost_init_t30_channel_support(struct nvhost_master *host) diff --git a/include/linux/nvhost.h b/include/linux/nvhost.h index 80f257ac6684..bc1d9d76b9a3 100644 --- a/include/linux/nvhost.h +++ b/include/linux/nvhost.h @@ -81,6 +81,9 @@ struct nvhost_device { struct nvhost_channel *channel; /* Channel assigned for the module */ + /* Allocates a context handler for the device */ + struct nvhost_hwctx_handler *(*alloc_hwctx_handler)(u32 syncpt, + u32 waitbase, struct nvhost_channel *ch); /* Preparing for power off. Used for context save. */ int (*prepare_poweroff)(struct nvhost_device *dev); /* Finalize power on. Can be used for context restore. */ |