/* * drivers/video/tegra/host/t20/t20.c * * Tegra Graphics Init for T20 Architecture Chips * * Copyright (c) 2011-2012, NVIDIA Corporation. * * 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 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, see . */ #include #include #include "dev.h" #include "t20.h" #include "host1x/host1x_channel.h" #include "host1x/host1x_syncpt.h" #include "host1x/host1x_hardware.h" #include "host1x/host1x_cdma.h" #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) #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) #define NVHOST_NUMCHANNELS (NV_HOST1X_CHANNELS - 1) struct nvhost_device t20_devices[] = { { /* channel 0 */ .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, }, { /* channel 1 */ .name = "gr3d", .id = -1, .index = 1, .syncpts = BIT(NVSYNCPT_3D), .waitbases = BIT(NVWAITBASE_3D), .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, .moduleid = NVHOST_MODULE_NONE, }, { /* channel 2 */ .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, }, { /* channel 3 */ .name = "isp", .id = -1, .index = 3, .syncpts = 0, NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_ISP, }, { /* channel 4 */ .name = "vi", .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, }, { /* channel 5 */ .name = "mpe", .id = -1, .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, .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, .moduleid = NVHOST_MODULE_MPE, }, { /* channel 6 */ .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 inline void __iomem *t20_channel_aperture(void __iomem *p, int ndx) { p += NV_HOST1X_CHANNEL0_BASE; 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); 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, 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) { host->nb_channels = NVHOST_NUMCHANNELS; host->op.channel.init = t20_channel_init; host->op.channel.submit = host1x_channel_submit; host->op.channel.read3dreg = host1x_channel_read_3d_reg; return 0; } struct nvhost_device *t20_get_nvhost_device(struct nvhost_master *host, char *name) { int i; for (i = 0; i < host->nb_channels; i++) { if (strcmp(t20_devices[i].name, name) == 0) return &t20_devices[i]; } return NULL; } int nvhost_init_t20_support(struct nvhost_master *host) { 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 = host1x_init_cdma_support(host); if (err) return err; err = nvhost_init_t20_debug_support(host); if (err) return err; err = host1x_init_syncpt_support(host); if (err) return err; err = nvhost_init_t20_intr_support(host); if (err) return err; host->op.nvhost_dev.get_nvhost_device = t20_get_nvhost_device; return 0; }