summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/syncpt.c
diff options
context:
space:
mode:
authorArto Merilainen <amerilainen@nvidia.com>2013-10-14 14:21:53 +0200
committerThierry Reding <treding@nvidia.com>2013-10-31 09:55:48 +0100
commitf5a954fed9b3eb04973ede72c50c66157fa9e15b (patch)
treed9d6faeb5b2bafbc5a4143feb10e27d975ec1da4 /drivers/gpu/host1x/syncpt.c
parentgpu: host1x: Add 'flags' field to syncpt request (diff)
downloadlinux-f5a954fed9b3eb04973ede72c50c66157fa9e15b.tar.xz
linux-f5a954fed9b3eb04973ede72c50c66157fa9e15b.zip
gpu: host1x: Add syncpoint base support
This patch adds support for hardware syncpoint bases. This creates a simple mechanism to stall the command FIFO until an operation is completed. Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/host1x/syncpt.c')
-rw-r--r--drivers/gpu/host1x/syncpt.c55
1 files changed, 53 insertions, 2 deletions
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 5b88ba4c974e..159c479829c9 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -30,6 +30,29 @@
#define SYNCPT_CHECK_PERIOD (2 * HZ)
#define MAX_STUCK_CHECK_COUNT 15
+static struct host1x_syncpt_base *
+host1x_syncpt_base_request(struct host1x *host)
+{
+ struct host1x_syncpt_base *bases = host->bases;
+ unsigned int i;
+
+ for (i = 0; i < host->info->nb_bases; i++)
+ if (!bases[i].requested)
+ break;
+
+ if (i >= host->info->nb_bases)
+ return NULL;
+
+ bases[i].requested = true;
+ return &bases[i];
+}
+
+static void host1x_syncpt_base_free(struct host1x_syncpt_base *base)
+{
+ if (base)
+ base->requested = false;
+}
+
static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
struct device *dev,
unsigned long flags)
@@ -44,6 +67,12 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
if (i >= host->info->nb_pts)
return NULL;
+ if (flags & HOST1X_SYNCPT_HAS_BASE) {
+ sp->base = host1x_syncpt_base_request(host);
+ if (!sp->base)
+ return NULL;
+ }
+
name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id,
dev ? dev_name(dev) : NULL);
if (!name)
@@ -307,20 +336,30 @@ int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr)
int host1x_syncpt_init(struct host1x *host)
{
+ struct host1x_syncpt_base *bases;
struct host1x_syncpt *syncpt;
int i;
syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts,
- GFP_KERNEL);
+ GFP_KERNEL);
if (!syncpt)
return -ENOMEM;
- for (i = 0; i < host->info->nb_pts; ++i) {
+ bases = devm_kzalloc(host->dev, sizeof(*bases) * host->info->nb_bases,
+ GFP_KERNEL);
+ if (!bases)
+ return -ENOMEM;
+
+ for (i = 0; i < host->info->nb_pts; i++) {
syncpt[i].id = i;
syncpt[i].host = host;
}
+ for (i = 0; i < host->info->nb_bases; i++)
+ bases[i].id = i;
+
host->syncpt = syncpt;
+ host->bases = bases;
host1x_syncpt_restore(host);
@@ -344,7 +383,9 @@ void host1x_syncpt_free(struct host1x_syncpt *sp)
if (!sp)
return;
+ host1x_syncpt_base_free(sp->base);
kfree(sp->name);
+ sp->base = NULL;
sp->dev = NULL;
sp->name = NULL;
sp->client_managed = false;
@@ -398,3 +439,13 @@ struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id)
return NULL;
return host->syncpt + id;
}
+
+struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp)
+{
+ return sp ? sp->base : NULL;
+}
+
+u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base)
+{
+ return base->id;
+}