aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/gcx/gccore/gcmain.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/gcx/gccore/gcmain.c')
-rw-r--r--drivers/misc/gcx/gccore/gcmain.c230
1 files changed, 148 insertions, 82 deletions
diff --git a/drivers/misc/gcx/gccore/gcmain.c b/drivers/misc/gcx/gccore/gcmain.c
index 6c7f0db..2754f11 100644
--- a/drivers/misc/gcx/gccore/gcmain.c
+++ b/drivers/misc/gcx/gccore/gcmain.c
@@ -31,6 +31,7 @@
#define GCZONE_COMMIT (1 << 3)
#define GCZONE_MAPPING (1 << 4)
#define GCZONE_PROBE (1 << 5)
+#define GCZONE_CALLBACK (1 << 6)
GCDBG_FILTERDEF(core, GCZONE_NONE,
"init",
@@ -38,7 +39,8 @@ GCDBG_FILTERDEF(core, GCZONE_NONE,
"power",
"commit",
"mapping",
- "probe")
+ "probe",
+ "callback")
#if !defined(GC_ENABLE_SUSPEND)
@@ -58,8 +60,8 @@ static struct gccorecontext g_context;
*/
static enum gcerror find_context(struct gccorecontext *gccorecontext,
- bool fromuser,
- struct gcmmucontext **gcmmucontext)
+ bool fromuser,
+ struct gcmmucontext **gcmmucontext)
{
enum gcerror gcerror = GCERR_NONE;
struct list_head *ctxhead;
@@ -444,10 +446,29 @@ void gcpwr_reset(struct gccorecontext *gccorecontext)
/*******************************************************************************
- * Command buffer submission.
+ * Public API.
*/
-void gc_commit(struct gccommit *gccommit, bool fromuser)
+void gc_caps(struct gcicaps *gcicaps)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+
+ /* Copy capabilities. */
+ gcicaps->gcmodel = gccorecontext->gcmodel;
+ gcicaps->gcrevision = gccorecontext->gcrevision;
+ gcicaps->gcdate = gccorecontext->gcdate;
+ gcicaps->gctime = gccorecontext->gctime;
+ gcicaps->gcfeatures = gccorecontext->gcfeatures;
+ gcicaps->gcfeatures0 = gccorecontext->gcfeatures0;
+ gcicaps->gcfeatures1 = gccorecontext->gcfeatures1;
+ gcicaps->gcfeatures2 = gccorecontext->gcfeatures2;
+ gcicaps->gcfeatures3 = gccorecontext->gcfeatures3;
+
+ /* Success. */
+ gcicaps->gcerror = GCERR_NONE;
+}
+
+void gc_commit(struct gcicommit *gcicommit, bool fromuser)
{
struct gccorecontext *gccorecontext = &g_context;
struct gcmmucontext *gcmmucontext;
@@ -464,31 +485,31 @@ void gc_commit(struct gccommit *gccommit, bool fromuser)
GCLOCK(&gccorecontext->mmucontextlock);
/* Validate pipe values. */
- if ((gccommit->entrypipe != GCPIPE_2D) &&
- (gccommit->entrypipe != GCPIPE_3D)) {
- gccommit->gcerror = GCERR_CMD_ENTRY_PIPE;
+ if ((gcicommit->entrypipe != GCPIPE_2D) &&
+ (gcicommit->entrypipe != GCPIPE_3D)) {
+ gcicommit->gcerror = GCERR_CMD_ENTRY_PIPE;
goto exit;
}
- if ((gccommit->exitpipe != GCPIPE_2D) &&
- (gccommit->exitpipe != GCPIPE_3D)) {
- gccommit->gcerror = GCERR_CMD_EXIT_PIPE;
+ if ((gcicommit->exitpipe != GCPIPE_2D) &&
+ (gcicommit->exitpipe != GCPIPE_3D)) {
+ gcicommit->gcerror = GCERR_CMD_EXIT_PIPE;
goto exit;
}
/* Locate the client entry. */
- gccommit->gcerror = find_context(gccorecontext, fromuser,
- &gcmmucontext);
- if (gccommit->gcerror != GCERR_NONE)
+ gcicommit->gcerror = find_context(gccorecontext, fromuser,
+ &gcmmucontext);
+ if (gcicommit->gcerror != GCERR_NONE)
goto exit;
/* Set the master table. */
- gccommit->gcerror = gcmmu_set_master(gccorecontext, gcmmucontext);
- if (gccommit->gcerror != GCERR_NONE)
+ gcicommit->gcerror = gcmmu_set_master(gccorecontext, gcmmucontext);
+ if (gcicommit->gcerror != GCERR_NONE)
goto exit;
/* Set the correct graphics pipe. */
- if (gccorecontext->gcpipe != gccommit->entrypipe) {
+ if (gccorecontext->gcpipe != gcicommit->entrypipe) {
static struct gcregpipeselect gcregpipeselect[] = {
/* GCPIPE_UNKNOWN */
{ 0, 0 },
@@ -501,21 +522,22 @@ void gc_commit(struct gccommit *gccommit, bool fromuser)
};
GCDBG(GCZONE_COMMIT, "allocating space for pipe switch.\n");
- gccommit->gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+ gcicommit->gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
sizeof(struct gcmopipesel),
(void **) &gcmopipesel, NULL);
- if (gccommit->gcerror != GCERR_NONE)
+ if (gcicommit->gcerror != GCERR_NONE)
goto exit;
gcmopipesel->pipesel_ldst = gcmopipesel_pipesel_ldst;
- gcmopipesel->pipesel.reg = gcregpipeselect[gccommit->entrypipe];
+ gcmopipesel->pipesel.reg
+ = gcregpipeselect[gcicommit->entrypipe];
}
/* Update the current pipe. */
- gccorecontext->gcpipe = gccommit->exitpipe;
+ gccorecontext->gcpipe = gcicommit->exitpipe;
/* Go through all buffers one at a time. */
- list_for_each(head, &gccommit->buffer) {
+ list_for_each(head, &gcicommit->buffer) {
gcbuffer = list_entry(head, struct gcbuffer, link);
GCDBG(GCZONE_COMMIT, "gcbuffer = 0x%08X\n",
(unsigned int) gcbuffer);
@@ -532,11 +554,11 @@ void gc_commit(struct gccommit *gccommit, bool fromuser)
/* Reserve command buffer space. */
GCDBG(GCZONE_COMMIT, "allocating command buffer space.\n");
- gccommit->gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
+ gcicommit->gcerror = gcqueue_alloc(gccorecontext, gcmmucontext,
buffersize,
(void **) &logical,
&address);
- if (gccommit->gcerror != GCERR_NONE)
+ if (gcicommit->gcerror != GCERR_NONE)
goto exit;
if (fromuser) {
@@ -544,7 +566,7 @@ void gc_commit(struct gccommit *gccommit, bool fromuser)
if (copy_from_user(logical, gcbuffer->head,
buffersize)) {
GCERR("failed to read data.\n");
- gccommit->gcerror = GCERR_USER_READ;
+ gcicommit->gcerror = GCERR_USER_READ;
goto exit;
}
} else {
@@ -552,45 +574,45 @@ void gc_commit(struct gccommit *gccommit, bool fromuser)
}
/* Process fixups. */
- gccommit->gcerror = gcmmu_fixup(&gcbuffer->fixup, logical);
- if (gccommit->gcerror != GCERR_NONE)
+ gcicommit->gcerror = gcmmu_fixup(&gcbuffer->fixup, logical);
+ if (gcicommit->gcerror != GCERR_NONE)
goto exit;
}
/* Add the callback. */
- if (gccommit->callback != NULL) {
- gccommit->gcerror = gcqueue_callback(gccorecontext,
+ if (gcicommit->callback != NULL) {
+ gcicommit->gcerror = gcqueue_callback(gccorecontext,
gcmmucontext,
- gccommit->callback,
- gccommit->callbackparam);
- if (gccommit->gcerror != GCERR_NONE)
+ gcicommit->callback,
+ gcicommit->callbackparam);
+ if (gcicommit->gcerror != GCERR_NONE)
goto exit;
}
/* Process unmappings. */
- list_for_each(head, &gccommit->unmap) {
+ list_for_each(head, &gcicommit->unmap) {
gcschedunmap = list_entry(head, struct gcschedunmap, link);
- gccommit->gcerror = gcqueue_schedunmap(gccorecontext,
+ gcicommit->gcerror = gcqueue_schedunmap(gccorecontext,
gcmmucontext,
gcschedunmap->handle);
- if (gccommit->gcerror != GCERR_NONE)
+ if (gcicommit->gcerror != GCERR_NONE)
goto exit;
}
/* Execute the buffer. */
- gccommit->gcerror = gcqueue_execute(gccorecontext, false,
- gccommit->asynchronous);
+ gcicommit->gcerror = gcqueue_execute(gccorecontext, false,
+ gcicommit->asynchronous);
exit:
GCUNLOCK(&gccorecontext->mmucontextlock);
GCEXITARG(GCZONE_COMMIT, "gc%s = 0x%08X\n",
- (gccommit->gcerror == GCERR_NONE) ? "result" : "error",
- gccommit->gcerror);
+ (gcicommit->gcerror == GCERR_NONE) ? "result" : "error",
+ gcicommit->gcerror);
}
EXPORT_SYMBOL(gc_commit);
-void gc_map(struct gcmap *gcmap, bool fromuser)
+void gc_map(struct gcimap *gcimap, bool fromuser)
{
struct gccorecontext *gccorecontext = &g_context;
struct gcmmucontext *gcmmucontext;
@@ -602,40 +624,42 @@ void gc_map(struct gcmap *gcmap, bool fromuser)
GCLOCK(&gccorecontext->mmucontextlock);
/* Locate the client entry. */
- gcmap->gcerror = find_context(gccorecontext, fromuser, &gcmmucontext);
- if (gcmap->gcerror != GCERR_NONE)
+ gcimap->gcerror = find_context(gccorecontext,
+ fromuser,
+ &gcmmucontext);
+ if (gcimap->gcerror != GCERR_NONE)
goto exit;
GCDBG(GCZONE_MAPPING, "map client buffer\n");
/* Initialize the mapping parameters. */
- if (gcmap->pagearray == NULL) {
- mem.base = ((u32) gcmap->buf.logical) & ~(PAGE_SIZE - 1);
- mem.offset = ((u32) gcmap->buf.logical) & (PAGE_SIZE - 1);
+ if (gcimap->pagearray == NULL) {
+ mem.base = ((u32) gcimap->buf.logical) & ~(PAGE_SIZE - 1);
+ mem.offset = ((u32) gcimap->buf.logical) & (PAGE_SIZE - 1);
mem.pages = NULL;
GCDBG(GCZONE_MAPPING, " logical = 0x%08X\n",
- (unsigned int) gcmap->buf.logical);
+ (unsigned int) gcimap->buf.logical);
} else {
mem.base = 0;
- mem.offset = gcmap->buf.offset;
- mem.pages = gcmap->pagearray;
+ mem.offset = gcimap->buf.offset;
+ mem.pages = gcimap->pagearray;
GCDBG(GCZONE_MAPPING, " pagearray = 0x%08X\n",
- (unsigned int) gcmap->pagearray);
+ (unsigned int) gcimap->pagearray);
}
- GCDBG(GCZONE_MAPPING, " size = %d\n", gcmap->size);
+ GCDBG(GCZONE_MAPPING, " size = %d\n", gcimap->size);
- mem.count = DIV_ROUND_UP(gcmap->size + mem.offset, PAGE_SIZE);
- mem.pagesize = gcmap->pagesize ? gcmap->pagesize : PAGE_SIZE;
+ mem.count = DIV_ROUND_UP(gcimap->size + mem.offset, PAGE_SIZE);
+ mem.pagesize = gcimap->pagesize ? gcimap->pagesize : PAGE_SIZE;
/* Map the buffer. */
- gcmap->gcerror = gcmmu_map(gccorecontext, gcmmucontext, &mem, &mapped);
- if (gcmap->gcerror != GCERR_NONE)
+ gcimap->gcerror = gcmmu_map(gccorecontext, gcmmucontext, &mem, &mapped);
+ if (gcimap->gcerror != GCERR_NONE)
goto exit;
- gcmap->handle = (unsigned int) mapped;
+ gcimap->handle = (unsigned int) mapped;
GCDBG(GCZONE_MAPPING, " mapped address = 0x%08X\n", mapped->address);
GCDBG(GCZONE_MAPPING, " handle = 0x%08X\n", (unsigned int) mapped);
@@ -644,12 +668,12 @@ exit:
GCUNLOCK(&gccorecontext->mmucontextlock);
GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
- (gcmap->gcerror == GCERR_NONE) ? "result" : "error",
- gcmap->gcerror);
+ (gcimap->gcerror == GCERR_NONE) ? "result" : "error",
+ gcimap->gcerror);
}
EXPORT_SYMBOL(gc_map);
-void gc_unmap(struct gcmap *gcmap, bool fromuser)
+void gc_unmap(struct gcimap *gcimap, bool fromuser)
{
struct gccorecontext *gccorecontext = &g_context;
struct gcmmucontext *gcmmucontext;
@@ -659,36 +683,71 @@ void gc_unmap(struct gcmap *gcmap, bool fromuser)
GCLOCK(&gccorecontext->mmucontextlock);
/* Locate the client entry. */
- gcmap->gcerror = find_context(gccorecontext, fromuser, &gcmmucontext);
- if (gcmap->gcerror != GCERR_NONE)
+ gcimap->gcerror = find_context(gccorecontext,
+ fromuser,
+ &gcmmucontext);
+ if (gcimap->gcerror != GCERR_NONE)
goto exit;
GCDBG(GCZONE_MAPPING, "unmap client buffer\n");
- GCDBG(GCZONE_MAPPING, " handle = 0x%08X\n", gcmap->handle);
+ GCDBG(GCZONE_MAPPING, " handle = 0x%08X\n", gcimap->handle);
/* Schedule unmapping. */
- gcmap->gcerror = gcqueue_schedunmap(gccorecontext, gcmmucontext,
- gcmap->handle);
- if (gcmap->gcerror != GCERR_NONE)
+ gcimap->gcerror = gcqueue_schedunmap(gccorecontext, gcmmucontext,
+ gcimap->handle);
+ if (gcimap->gcerror != GCERR_NONE)
goto exit;
/* Execute the buffer. */
- gcmap->gcerror = gcqueue_execute(gccorecontext, false, false);
- if (gcmap->gcerror != GCERR_NONE)
+ gcimap->gcerror = gcqueue_execute(gccorecontext, false, false);
+ if (gcimap->gcerror != GCERR_NONE)
goto exit;
/* Invalidate the handle. */
- gcmap->handle = ~0U;
+ gcimap->handle = ~0U;
exit:
GCUNLOCK(&gccorecontext->mmucontextlock);
GCEXITARG(GCZONE_MAPPING, "gc%s = 0x%08X\n",
- (gcmap->gcerror == GCERR_NONE) ? "result" : "error",
- gcmap->gcerror);
+ (gcimap->gcerror == GCERR_NONE) ? "result" : "error",
+ gcimap->gcerror);
}
EXPORT_SYMBOL(gc_unmap);
+void gc_callback(struct gcicallbackarm *gcicallbackarm, bool fromuser)
+{
+ struct gccorecontext *gccorecontext = &g_context;
+ struct gcmmucontext *gcmmucontext;
+
+ GCENTER(GCZONE_CALLBACK);
+
+ GCLOCK(&gccorecontext->mmucontextlock);
+
+ /* Locate the client entry. */
+ gcicallbackarm->gcerror = find_context(gccorecontext, fromuser,
+ &gcmmucontext);
+ if (gcicallbackarm->gcerror != GCERR_NONE)
+ goto exit;
+
+ /* Schedule callback. */
+ gcicallbackarm->gcerror
+ = gcqueue_callback(gccorecontext,
+ gcmmucontext,
+ gcicallbackarm->callback,
+ gcicallbackarm->callbackparam);
+ if (gcicallbackarm->gcerror != GCERR_NONE)
+ goto exit;
+
+exit:
+ GCUNLOCK(&gccorecontext->mmucontextlock);
+
+ GCEXITARG(GCZONE_CALLBACK, "gc%s = 0x%08X\n",
+ (gcicallbackarm->gcerror == GCERR_NONE) ? "result" : "error",
+ gcicallbackarm->gcerror);
+}
+EXPORT_SYMBOL(gc_callback);
+
void gc_release(void)
{
struct gccorecontext *gccorecontext = &g_context;
@@ -768,7 +827,7 @@ static int gc_probe(struct platform_device *pdev)
GCENTER(GCZONE_PROBE);
gccorecontext->plat = (struct omap_gcx_platform_data *)
- pdev->dev.platform_data;
+ pdev->dev.platform_data;
gccorecontext->regbase = gccorecontext->plat->regbase;
gccorecontext->irqline = platform_get_irq(pdev, pdev->id);
gccorecontext->device = &pdev->dev;
@@ -780,19 +839,26 @@ static int gc_probe(struct platform_device *pdev)
pm_runtime_get_sync(gccorecontext->device);
+ gccorecontext->gcmodel = gc_read_reg(GC_CHIP_ID_Address);
+ gccorecontext->gcrevision = gc_read_reg(GC_CHIP_REV_Address);
+ gccorecontext->gcdate = gc_read_reg(GC_CHIP_DATE_Address);
+ gccorecontext->gctime = gc_read_reg(GC_CHIP_TIME_Address);
+ gccorecontext->gcfeatures.raw = gc_read_reg(GC_FEATURES_Address);
+ gccorecontext->gcfeatures0.raw = gc_read_reg(GC_FEATURES0_Address);
+ gccorecontext->gcfeatures1.raw = gc_read_reg(GC_FEATURES1_Address);
+ gccorecontext->gcfeatures2.raw = gc_read_reg(GC_FEATURES2_Address);
+ gccorecontext->gcfeatures3.raw = gc_read_reg(GC_FEATURES3_Address);
+
GCDBG(GCZONE_PROBE, "GPU IDENTITY:\n");
- GCDBG(GCZONE_PROBE, " model=%X\n",
- gc_read_reg(GC_CHIP_ID_Address));
- GCDBG(GCZONE_PROBE, " revision=%X\n",
- gc_read_reg(GC_CHIP_REV_Address));
- GCDBG(GCZONE_PROBE, " date=%X\n",
- gc_read_reg(GC_CHIP_DATE_Address));
- GCDBG(GCZONE_PROBE, " time=%X\n",
- gc_read_reg(GC_CHIP_TIME_Address));
- GCDBG(GCZONE_PROBE, " chipFeatures=0x%08X\n",
- gc_read_reg(GC_FEATURES_Address));
- GCDBG(GCZONE_PROBE, " minorFeatures=0x%08X\n",
- gc_read_reg(GC_MINOR_FEATURES0_Address));
+ GCDBG(GCZONE_PROBE, " model=%X\n", gccorecontext->gcmodel);
+ GCDBG(GCZONE_PROBE, " revision=%X\n", gccorecontext->gcrevision);
+ GCDBG(GCZONE_PROBE, " date=%X\n", gccorecontext->gcdate);
+ GCDBG(GCZONE_PROBE, " time=%X\n", gccorecontext->gctime);
+ GCDBG(GCZONE_PROBE, " features=0x%08X\n", gccorecontext->gcfeatures);
+ GCDBG(GCZONE_PROBE, " features0=0x%08X\n", gccorecontext->gcfeatures0);
+ GCDBG(GCZONE_PROBE, " features1=0x%08X\n", gccorecontext->gcfeatures1);
+ GCDBG(GCZONE_PROBE, " features2=0x%08X\n", gccorecontext->gcfeatures2);
+ GCDBG(GCZONE_PROBE, " features3=0x%08X\n", gccorecontext->gcfeatures3);
pm_runtime_put_sync(gccorecontext->device);