video: tegra: refactor for multiple chip support
[linux-2.6.git] / drivers / video / tegra / host / nvhost_syncpt.c
index 9420308..88059b0 100644 (file)
 #include "nvhost_syncpt.h"
 #include "dev.h"
 
-#define client_managed(id) (BIT(id) & NVSYNCPTS_CLIENT_MANAGED)
-#define syncpt_to_dev(sp) container_of(sp, struct nvhost_master, syncpt)
-#define SYNCPT_CHECK_PERIOD 2*HZ
-
-static bool check_max(struct nvhost_syncpt *sp, u32 id, u32 real)
-{
-       u32 max;
-       if (client_managed(id))
-               return true;
-       smp_rmb();
-       max = (u32)atomic_read(&sp->max_val[id]);
-       return ((s32)(max - real) >= 0);
-}
-
-/**
- * Write the current syncpoint value back to hw.
- */
-static void reset_syncpt(struct nvhost_syncpt *sp, u32 id)
-{
-       struct nvhost_master *dev = syncpt_to_dev(sp);
-       int min;
-       smp_rmb();
-       min = atomic_read(&sp->min_val[id]);
-       writel(min, dev->sync_aperture + (HOST1X_SYNC_SYNCPT_0 + id * 4));
-}
-
-/**
- * Write the current waitbase value back to hw.
- */
-static void reset_syncpt_wait_base(struct nvhost_syncpt *sp, u32 id)
-{
-       struct nvhost_master *dev = syncpt_to_dev(sp);
-       writel(sp->base_val[id],
-               dev->sync_aperture + (HOST1X_SYNC_SYNCPT_BASE_0 + id * 4));
-}
-
-/**
- * Read waitbase value from hw.
- */
-static void read_syncpt_wait_base(struct nvhost_syncpt *sp, u32 id)
-{
-       struct nvhost_master *dev = syncpt_to_dev(sp);
-       sp->base_val[id] = readl(dev->sync_aperture +
-                               (HOST1X_SYNC_SYNCPT_BASE_0 + id * 4));
-}
 
 /**
  * Resets syncpoint and waitbase values to sw shadows
@@ -75,10 +30,12 @@ static void read_syncpt_wait_base(struct nvhost_syncpt *sp, u32 id)
 void nvhost_syncpt_reset(struct nvhost_syncpt *sp)
 {
        u32 i;
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++)
-               reset_syncpt(sp, i);
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_BASES; i++)
-               reset_syncpt_wait_base(sp, i);
+       BUG_ON(!(syncpt_op(sp).reset && syncpt_op(sp).reset_wait_base));
+
+       for (i = 0; i < sp->nb_pts; i++)
+               syncpt_op(sp).reset(sp, i);
+       for (i = 0; i < sp->nb_bases; i++)
+               syncpt_op(sp).reset_wait_base(sp, i);
        wmb();
 }
 
@@ -88,16 +45,17 @@ void nvhost_syncpt_reset(struct nvhost_syncpt *sp)
 void nvhost_syncpt_save(struct nvhost_syncpt *sp)
 {
        u32 i;
+       BUG_ON(!(syncpt_op(sp).update_min && syncpt_op(sp).read_wait_base));
 
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++) {
+       for (i = 0; i < sp->nb_pts; i++) {
                if (client_managed(i))
-                       nvhost_syncpt_update_min(sp, i);
+                       syncpt_op(sp).update_min(sp, i);
                else
                        BUG_ON(!nvhost_syncpt_min_eq_max(sp, i));
        }
 
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_BASES; i++)
-               read_syncpt_wait_base(sp, i);
+       for (i = 0; i < sp->nb_bases; i++)
+               syncpt_op(sp).read_wait_base(sp, i);
 }
 
 /**
@@ -105,19 +63,9 @@ void nvhost_syncpt_save(struct nvhost_syncpt *sp)
  */
 u32 nvhost_syncpt_update_min(struct nvhost_syncpt *sp, u32 id)
 {
-       struct nvhost_master *dev = syncpt_to_dev(sp);
-       void __iomem *sync_regs = dev->sync_aperture;
-       u32 old, live;
-
-       do {
-               smp_rmb();
-               old = (u32)atomic_read(&sp->min_val[id]);
-               live = readl(sync_regs + (HOST1X_SYNC_SYNCPT_0 + id * 4));
-       } while ((u32)atomic_cmpxchg(&sp->min_val[id], old, live) != old);
-
-       BUG_ON(!check_max(sp, id, live));
+       BUG_ON(!syncpt_op(sp).update_min);
 
-       return live;
+       return syncpt_op(sp).update_min(sp, id);
 }
 
 /**
@@ -126,9 +74,9 @@ u32 nvhost_syncpt_update_min(struct nvhost_syncpt *sp, u32 id)
 u32 nvhost_syncpt_read(struct nvhost_syncpt *sp, u32 id)
 {
        u32 val;
-
+       BUG_ON(!syncpt_op(sp).update_min);
        nvhost_module_busy(&syncpt_to_dev(sp)->mod);
-       val = nvhost_syncpt_update_min(sp, id);
+       val = syncpt_op(sp).update_min(sp, id);
        nvhost_module_idle(&syncpt_to_dev(sp)->mod);
        return val;
 }
@@ -139,11 +87,8 @@ u32 nvhost_syncpt_read(struct nvhost_syncpt *sp, u32 id)
  */
 void nvhost_syncpt_cpu_incr(struct nvhost_syncpt *sp, u32 id)
 {
-       struct nvhost_master *dev = syncpt_to_dev(sp);
-       BUG_ON(!nvhost_module_powered(&dev->mod));
-       BUG_ON(!client_managed(id) && nvhost_syncpt_min_eq_max(sp, id));
-       writel(BIT(id), dev->sync_aperture + HOST1X_SYNC_SYNCPT_CPU_INCR);
-       wmb();
+       BUG_ON(!syncpt_op(sp).cpu_incr);
+       syncpt_op(sp).cpu_incr(sp, id);
 }
 
 /**
@@ -169,8 +114,8 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id,
 
        if (value)
                *value = 0;
-
-       BUG_ON(!check_max(sp, id, thresh));
+       BUG_ON(!syncpt_op(sp).update_min);
+       BUG_ON(!nvhost_syncpt_check_max(sp, id, thresh));
 
        /* first check cache */
        if (nvhost_syncpt_min_cmp(sp, id, thresh)) {
@@ -184,7 +129,7 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id,
 
        if (client_managed(id) || !nvhost_syncpt_min_eq_max(sp, id)) {
                /* try to read from register */
-               u32 val = nvhost_syncpt_update_min(sp, id);
+               u32 val = syncpt_op(sp).update_min(sp, id);
                if ((s32)(val - thresh) >= 0) {
                        if (value)
                                *value = val;
@@ -225,8 +170,8 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id,
                if (timeout) {
                        dev_warn(&syncpt_to_dev(sp)->pdev->dev,
                                "syncpoint id %d (%s) stuck waiting %d\n",
-                               id, nvhost_syncpt_name(id), thresh);
-                       nvhost_syncpt_debug(sp);
+                                id, syncpt_op(sp).name(sp, id), thresh);
+                       syncpt_op(sp).debug(sp);
                }
        }
        nvhost_intr_put_ref(&(syncpt_to_dev(sp)->intr), ref);
@@ -236,98 +181,17 @@ done:
        return err;
 }
 
-static const char *s_syncpt_names[32] = {
-       "gfx_host", "", "", "", "", "", "", "", "", "", "",
-       "csi_vi_0", "csi_vi_1", "vi_isp_0", "vi_isp_1", "vi_isp_2", "vi_isp_3", "vi_isp_4",
-       "2d_0", "2d_1",
-       "", "",
-       "3d", "mpe", "disp0", "disp1", "vblank0", "vblank1", "mpe_ebm_eof", "mpe_wr_safe",
-       "2d_tinyblt", "dsi"
-};
-
-const char *nvhost_syncpt_name(u32 id)
-{
-       BUG_ON(id > ARRAY_SIZE(s_syncpt_names));
-       return s_syncpt_names[id];
-}
-
 void nvhost_syncpt_debug(struct nvhost_syncpt *sp)
 {
-       u32 i;
-       for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++) {
-               u32 max = nvhost_syncpt_read_max(sp, i);
-               if (!max)
-                       continue;
-               dev_info(&syncpt_to_dev(sp)->pdev->dev,
-                       "id %d (%s) min %d max %d\n",
-                       i, nvhost_syncpt_name(i),
-                       nvhost_syncpt_update_min(sp, i), max);
-
-       }
-}
-
-/* returns true, if a <= b < c using wrapping comparison */
-static inline bool nvhost_syncpt_is_between(u32 a, u32 b, u32 c)
-{
-       return b-a < c-a;
-}
-
-/* returns true, if syncpt >= threshold (mod 1 << 32) */
-static bool nvhost_syncpt_wrapping_comparison(u32 syncpt, u32 threshold)
-{
-       return nvhost_syncpt_is_between(threshold, syncpt,
-                                       (1UL<<31UL)+threshold);
+       syncpt_op(sp).debug(sp);
 }
 
 /* check for old WAITs to be removed (avoiding a wrap) */
-int nvhost_syncpt_wait_check(struct nvmap_client *nvmap,
-                       struct nvhost_syncpt *sp, u32 waitchk_mask,
-                       struct nvhost_waitchk *wait,
-                       struct nvhost_waitchk *waitend)
+int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp,
+                            struct nvmap_client *nvmap,
+                            u32 waitchk_mask,
+                            struct nvhost_waitchk *wait,
+                            struct nvhost_waitchk *waitend)
 {
-       u32 idx;
-       int err = 0;
-
-       /* get current syncpt values */
-       for (idx = 0; idx < NV_HOST1X_SYNCPT_NB_PTS; idx++) {
-               if (BIT(idx) & waitchk_mask)
-                       nvhost_syncpt_update_min(sp, idx);
-       }
-
-       BUG_ON(!wait && !waitend);
-
-       /* compare syncpt vs wait threshold */
-       while (wait != waitend) {
-               u32 syncpt, override;
-
-               BUG_ON(wait->syncpt_id > NV_HOST1X_SYNCPT_NB_PTS);
-
-               syncpt = atomic_read(&sp->min_val[wait->syncpt_id]);
-               if (nvhost_syncpt_wrapping_comparison(syncpt, wait->thresh)) {
-                       /*
-                        * NULL an already satisfied WAIT_SYNCPT host method,
-                        * by patching its args in the command stream. The
-                        * method data is changed to reference a reserved
-                        * (never given out or incr) NVSYNCPT_GRAPHICS_HOST
-                        * syncpt with a matching threshold value of 0, so
-                        * is guaranteed to be popped by the host HW.
-                        */
-                       dev_dbg(&syncpt_to_dev(sp)->pdev->dev,
-                           "drop WAIT id %d (%s) thresh 0x%x, syncpt 0x%x\n",
-                           wait->syncpt_id,
-                           nvhost_syncpt_name(wait->syncpt_id),
-                           wait->thresh, syncpt);
-
-                       /* patch the wait */
-                       override = nvhost_class_host_wait_syncpt(
-                                       NVSYNCPT_GRAPHICS_HOST, 0);
-                       err = nvmap_patch_word(nvmap,
-                                       (struct nvmap_handle *)wait->mem,
-                                       wait->offset, override);
-                       if (err)
-                               break;
-               }
-               wait++;
-       }
-       return err;
+       return syncpt_op(sp).wait_check(sp, nvmap, waitchk_mask, wait, waitend);
 }