video: tegra: host: Remove version from dev name
[linux-2.6.git] / drivers / video / tegra / host / t20 / t20.c
index a663f45..93e73e5 100644 (file)
  *
  * Tegra Graphics Init for T20 Architecture Chips
  *
- * Copyright (c) 2011, NVIDIA Corporation.
+ * Copyright (c) 2011-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 free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
+ * This program is distributed in the hope 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/slab.h>
-#include "../dev.h"
-
+#include <linux/nvhost_ioctl.h>
+#include <mach/powergate.h>
+#include <mach/iomap.h>
 #include "t20.h"
+#include "host1x/host1x_syncpt.h"
+#include "host1x/host1x_hardware.h"
+#include "gr3d/gr3d.h"
+#include "gr3d/gr3d_t20.h"
+#include "mpe/mpe.h"
+#include "host1x/host1x.h"
+#include "nvhost_hwctx.h"
+#include "nvhost_channel.h"
+#include "host1x/host1x_channel.h"
+#include "host1x/host1x_cdma.h"
+#include "chip_support.h"
+#include "nvmap.h"
+#include "nvhost_memmgr.h"
+
+#define NVMODMUTEX_2D_FULL     (1)
+#define NVMODMUTEX_2D_SIMPLE   (2)
+#define NVMODMUTEX_2D_SB_A     (3)
+#define NVMODMUTEX_2D_SB_B     (4)
+#define NVMODMUTEX_3D          (5)
+#define NVMODMUTEX_DISPLAYA    (6)
+#define NVMODMUTEX_DISPLAYB    (7)
+#define NVMODMUTEX_VI          (8)
+#define NVMODMUTEX_DSI         (9)
+
+static int t20_num_alloc_channels = 0;
+
+static struct resource tegra_host1x01_resources[] = {
+       {
+               .start = TEGRA_HOST1X_BASE,
+               .end = TEGRA_HOST1X_BASE + TEGRA_HOST1X_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = INT_SYNCPT_THRESH_BASE,
+               .end = INT_SYNCPT_THRESH_BASE + INT_SYNCPT_THRESH_NR - 1,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = INT_HOST1X_MPCORE_GENERAL,
+               .end = INT_HOST1X_MPCORE_GENERAL,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static const char *s_syncpt_names[32] = {
+       "gfx_host",
+       "", "", "", "", "", "", "",
+       "disp0_a", "disp1_a", "avp_0",
+       "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",
+       "disp0_b", "disp1_b",
+       "3d",
+       "mpe",
+       "disp0_c", "disp1_c",
+       "vblank0", "vblank1",
+       "mpe_ebm_eof", "mpe_wr_safe",
+       "2d_tinyblt",
+       "dsi"
+};
+
+static struct host1x_device_info host1x01_info = {
+       .nb_channels    = 8,
+       .nb_pts         = 32,
+       .nb_mlocks      = 16,
+       .nb_bases       = 8,
+       .syncpt_names   = s_syncpt_names,
+       .client_managed = NVSYNCPTS_CLIENT_MANAGED,
+};
+
+static struct nvhost_device tegra_host1x01_device = {
+       .dev            = {.platform_data = &host1x01_info},
+       .name           = "host1x",
+       .id             = -1,
+       .resource       = tegra_host1x01_resources,
+       .num_resources  = ARRAY_SIZE(tegra_host1x01_resources),
+       .clocks         = {{"host1x", UINT_MAX}, {} },
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+};
+
+static struct nvhost_device tegra_display01_device = {
+       .name           = "display",
+       .id             = -1,
+       .index          = 0,
+       .syncpts        = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) |
+                         BIT(NVSYNCPT_DISP0_B) | BIT(NVSYNCPT_DISP1_B) |
+                         BIT(NVSYNCPT_DISP0_C) | BIT(NVSYNCPT_DISP1_C) |
+                         BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1),
+       .modulemutexes  = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB),
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid       = NVHOST_MODULE_NONE,
+};
+
+static struct nvhost_device tegra_gr3d01_device = {
+       .name           = "gr3d",
+       .version        = 1,
+       .id             = -1,
+       .index          = 1,
+       .syncpts        = BIT(NVSYNCPT_3D),
+       .waitbases      = BIT(NVWAITBASE_3D),
+       .modulemutexes  = BIT(NVMODMUTEX_3D),
+       .class          = NV_GRAPHICS_3D_CLASS_ID,
+       .clocks         = {{"gr3d", UINT_MAX}, {"emc", UINT_MAX}, {} },
+       .powergate_ids  = {TEGRA_POWERGATE_3D, -1},
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid       = NVHOST_MODULE_NONE,
+};
+
+static struct nvhost_device tegra_gr2d01_device = {
+       .name           = "gr2d",
+       .id             = -1,
+       .index          = 2,
+       .syncpts        = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1),
+       .waitbases      = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1),
+       .modulemutexes  = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) |
+                         BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B),
+       .clocks         = { {"gr2d", UINT_MAX},
+                           {"epp", UINT_MAX},
+                           {"emc", UINT_MAX} },
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       .clockgate_delay = 0,
+       .moduleid       = NVHOST_MODULE_NONE,
+};
+
+static struct resource isp_resources_t20[] = {
+       {
+               .name = "regs",
+               .start = TEGRA_ISP_BASE,
+               .end = TEGRA_ISP_BASE + TEGRA_ISP_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       }
+};
+
+static struct nvhost_device tegra_isp01_device = {
+       .name           = "isp",
+       .id             = -1,
+       .resource = isp_resources_t20,
+       .num_resources = ARRAY_SIZE(isp_resources_t20),
+       .index          = 3,
+       .syncpts        = 0,
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid       = NVHOST_MODULE_ISP,
+};
+
+static struct resource vi_resources[] = {
+       {
+               .name = "regs",
+               .start = TEGRA_VI_BASE,
+               .end = TEGRA_VI_BASE + TEGRA_VI_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct nvhost_device tegra_vi01_device = {
+       .name           = "vi",
+       .resource = vi_resources,
+       .num_resources = ARRAY_SIZE(vi_resources),
+       .id             = -1,
+       .index          = 4,
+       .syncpts        = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) |
+                         BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) |
+                         BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) |
+                         BIT(NVSYNCPT_VI_ISP_4),
+       .modulemutexes  = BIT(NVMODMUTEX_VI),
+       .exclusive      = true,
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid       = NVHOST_MODULE_VI,
+};
+
+static struct resource tegra_mpe01_resources[] = {
+       {
+               .name = "regs",
+               .start = TEGRA_MPE_BASE,
+               .end = TEGRA_MPE_BASE + TEGRA_MPE_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+};
 
-int nvhost_init_t20_support(struct nvhost_master *host)
+static struct nvhost_device tegra_mpe01_device = {
+       .name           = "mpe",
+       .version        = 1,
+       .id             = -1,
+       .resource       = tegra_mpe01_resources,
+       .num_resources  = ARRAY_SIZE(tegra_mpe01_resources),
+       .index          = 5,
+       .syncpts        = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) |
+                         BIT(NVSYNCPT_MPE_WR_SAFE),
+       .waitbases      = BIT(NVWAITBASE_MPE),
+       .class          = NV_VIDEO_ENCODE_MPEG_CLASS_ID,
+       .waitbasesync   = true,
+       .keepalive      = true,
+       .clocks         = { {"mpe", UINT_MAX},
+                           {"emc", UINT_MAX} },
+       .powergate_ids  = {TEGRA_POWERGATE_MPE, -1},
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid       = NVHOST_MODULE_MPE,
+};
+
+static struct nvhost_device tegra_dsi01_device = {
+       .name           = "dsi",
+       .id             = -1,
+       .index          = 6,
+       .syncpts        = BIT(NVSYNCPT_DSI),
+       .modulemutexes  = BIT(NVMODMUTEX_DSI),
+       NVHOST_MODULE_NO_POWERGATE_IDS,
+       NVHOST_DEFAULT_CLOCKGATE_DELAY,
+       .moduleid       = NVHOST_MODULE_NONE,
+};
+
+static struct nvhost_device *t20_devices[] = {
+       &tegra_host1x01_device,
+       &tegra_display01_device,
+       &tegra_gr3d01_device,
+       &tegra_gr2d01_device,
+       &tegra_isp01_device,
+       &tegra_vi01_device,
+       &tegra_mpe01_device,
+       &tegra_dsi01_device,
+};
+
+int tegra2_register_host1x_devices(void)
+{
+       return nvhost_add_devices(t20_devices, ARRAY_SIZE(t20_devices));
+}
+
+static inline void __iomem *t20_channel_aperture(void __iomem *p, int ndx)
+{
+       p += ndx * NV_HOST1X_CHANNEL_MAP_SIZE_BYTES;
+       return p;
+}
+
+static inline int t20_nvhost_hwctx_handler_init(struct nvhost_channel *ch)
+{
+       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);
+       struct nvhost_driver *drv = to_nvhost_driver(ch->dev->dev.driver);
+
+       if (drv->alloc_hwctx_handler) {
+               ch->ctxhandler = drv->alloc_hwctx_handler(syncpt,
+                               waitbase, ch);
+               if (!ch->ctxhandler)
+                       err = -ENOMEM;
+       }
+
+       return err;
+}
+
+static int t20_channel_init(struct nvhost_channel *ch,
+       struct nvhost_master *dev, int index)
+{
+       ch->chid = index;
+       mutex_init(&ch->reflock);
+       mutex_init(&ch->submitlock);
+
+       ch->aperture = t20_channel_aperture(dev->aperture, index);
+
+       return t20_nvhost_hwctx_handler_init(ch);
+}
+
+int nvhost_init_t20_channel_support(struct nvhost_master *host,
+       struct nvhost_chip_support *op)
+{
+       op->channel.init = t20_channel_init;
+       op->channel.submit = host1x_channel_submit;
+       op->channel.read3dreg = host1x_channel_read_3d_reg;
+
+       return 0;
+}
+
+static void t20_free_nvhost_channel(struct nvhost_channel *ch)
+{
+       nvhost_free_channel_internal(ch, &t20_num_alloc_channels);
+}
+
+static struct nvhost_channel *t20_alloc_nvhost_channel(
+               struct nvhost_device *dev)
+{
+       return nvhost_alloc_channel_internal(dev->index,
+               nvhost_get_host(dev)->info.nb_channels,
+               &t20_num_alloc_channels);
+}
+
+int nvhost_init_t20_support(struct nvhost_master *host,
+       struct nvhost_chip_support *op)
 {
        int err;
 
        /* don't worry about cleaning up on failure... "remove" does it. */
-       err = nvhost_init_t20_channel_support(host);
-       if (err)
-               return err;
-       err = nvhost_init_t20_cdma_support(host);
+       err = nvhost_init_t20_channel_support(host, op);
        if (err)
                return err;
-       err = nvhost_init_t20_debug_support(host);
+       err = host1x_init_cdma_support(op);
        if (err)
                return err;
-       err = nvhost_init_t20_syncpt_support(host);
+       err = nvhost_init_t20_debug_support(op);
        if (err)
                return err;
-       err = nvhost_init_t20_intr_support(host);
+       err = host1x_init_syncpt_support(host, op);
        if (err)
                return err;
-       err = nvhost_init_t20_cpuaccess_support(host);
+       err = nvhost_init_t20_intr_support(op);
        if (err)
                return err;
-       return 0;
-}
+       err = nvhost_memmgr_init(op);
 
-int nvhost_t20_save_context(struct nvhost_module *mod, u32 syncpt_id)
-{
-       struct nvhost_channel *ch =
-                       container_of(mod, struct nvhost_channel, mod);
-       struct nvhost_hwctx *hwctx_to_save;
-       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
-       u32 syncpt_incrs, syncpt_val;
-       int err = 0;
-       void *ref;
-       void *ctx_waiter = NULL, *wakeup_waiter = NULL;
-
-       ctx_waiter = nvhost_intr_alloc_waiter();
-       wakeup_waiter = nvhost_intr_alloc_waiter();
-       if (!ctx_waiter || !wakeup_waiter) {
-               err = -ENOMEM;
-               goto done;
-       }
+       op->nvhost_dev.alloc_nvhost_channel = t20_alloc_nvhost_channel;
+       op->nvhost_dev.free_nvhost_channel = t20_free_nvhost_channel;
 
-       if (mod->desc->busy)
-               mod->desc->busy(mod);
-
-       mutex_lock(&ch->submitlock);
-       hwctx_to_save = ch->cur_ctx;
-       if (!hwctx_to_save) {
-               mutex_unlock(&ch->submitlock);
-               goto done;
-       }
-
-       err = nvhost_cdma_begin(&ch->cdma, hwctx_to_save->timeout);
-       if (err) {
-               mutex_unlock(&ch->submitlock);
-               goto done;
-       }
-
-       hwctx_to_save->valid = true;
-       ch->ctxhandler.get(hwctx_to_save);
-       ch->cur_ctx = NULL;
-
-       syncpt_incrs = hwctx_to_save->save_incrs;
-       syncpt_val = nvhost_syncpt_incr_max(&ch->dev->syncpt,
-                                       syncpt_id, syncpt_incrs);
-
-       ch->ctxhandler.save_push(&ch->cdma, hwctx_to_save);
-       nvhost_cdma_end(&ch->cdma, ch->dev->nvmap, syncpt_id, syncpt_val,
-                       NULL, 0, hwctx_to_save->timeout);
-
-       err = nvhost_intr_add_action(&ch->dev->intr, syncpt_id,
-                       syncpt_val - syncpt_incrs + hwctx_to_save->save_thresh,
-                       NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save,
-                       ctx_waiter,
-                       NULL);
-       ctx_waiter = NULL;
-       WARN(err, "Failed to set context save interrupt");
-
-       err = nvhost_intr_add_action(&ch->dev->intr, syncpt_id, syncpt_val,
-                       NVHOST_INTR_ACTION_WAKEUP, &wq,
-                       wakeup_waiter,
-                       &ref);
-       wakeup_waiter = NULL;
-       WARN(err, "Failed to set wakeup interrupt");
-       wait_event(wq,
-               nvhost_syncpt_min_cmp(&ch->dev->syncpt,
-                               syncpt_id, syncpt_val));
-
-       nvhost_intr_put_ref(&ch->dev->intr, ref);
-
-       nvhost_cdma_update(&ch->cdma);
-
-       mutex_unlock(&ch->submitlock);
-
-done:
-       kfree(ctx_waiter);
-       kfree(wakeup_waiter);
-       return err;
+       return 0;
 }