summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/tegra/host/dev.c6
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d.c49
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d.h16
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t20.c129
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t20.h4
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t30.c121
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t30.h4
-rw-r--r--drivers/video/tegra/host/host1x/host1x_cdma.c3
-rw-r--r--drivers/video/tegra/host/host1x/host1x_channel.c95
-rw-r--r--drivers/video/tegra/host/host1x/host1x_hwctx.h65
-rw-r--r--drivers/video/tegra/host/mpe/mpe.c144
-rw-r--r--drivers/video/tegra/host/mpe/mpe.h4
-rw-r--r--drivers/video/tegra/host/nvhost_channel.c1
-rw-r--r--drivers/video/tegra/host/nvhost_channel.h2
-rw-r--r--drivers/video/tegra/host/nvhost_hwctx.h21
-rw-r--r--drivers/video/tegra/host/nvhost_intr.c8
-rw-r--r--drivers/video/tegra/host/t20/t20.c28
-rw-r--r--drivers/video/tegra/host/t30/t30.c28
-rw-r--r--include/linux/nvhost.h3
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. */