video: tegra: host: refactor for upstreaming
[linux-2.6.git] / drivers / video / tegra / host / t20 / t20.c
1 /*
2  * drivers/video/tegra/host/t20/t20.c
3  *
4  * Tegra Graphics Init for T20 Architecture Chips
5  *
6  * Copyright (c) 2011-2012, NVIDIA Corporation.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms and conditions of the GNU General Public License,
10  * version 2, as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <linux/slab.h>
22 #include <mach/powergate.h>
23 #include "dev.h"
24 #include "t20.h"
25 #include "host1x/host1x_channel.h"
26 #include "host1x/host1x_syncpt.h"
27 #include "host1x/host1x_hardware.h"
28 #include "host1x/host1x_cdma.h"
29 #include "gr3d/gr3d.h"
30 #include "gr3d/gr3d_t20.h"
31 #include "mpe/mpe.h"
32 #include "nvhost_hwctx.h"
33
34 #define NVMODMUTEX_2D_FULL      (1)
35 #define NVMODMUTEX_2D_SIMPLE    (2)
36 #define NVMODMUTEX_2D_SB_A      (3)
37 #define NVMODMUTEX_2D_SB_B      (4)
38 #define NVMODMUTEX_3D           (5)
39 #define NVMODMUTEX_DISPLAYA     (6)
40 #define NVMODMUTEX_DISPLAYB     (7)
41 #define NVMODMUTEX_VI           (8)
42 #define NVMODMUTEX_DSI          (9)
43
44 #define NVHOST_NUMCHANNELS      (NV_HOST1X_CHANNELS - 1)
45
46 struct nvhost_device t20_devices[] = {
47 {
48         /* channel 0 */
49         .name           = "display",
50         .id             = -1,
51         .index          = 0,
52         .syncpts        = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) |
53                           BIT(NVSYNCPT_DISP0_B) | BIT(NVSYNCPT_DISP1_B) |
54                           BIT(NVSYNCPT_DISP0_C) | BIT(NVSYNCPT_DISP1_C) |
55                           BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1),
56         .modulemutexes  = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB),
57         NVHOST_MODULE_NO_POWERGATE_IDS,
58         NVHOST_DEFAULT_CLOCKGATE_DELAY,
59         .moduleid       = NVHOST_MODULE_NONE,
60 },
61 {
62         /* channel 1 */
63         .name           = "gr3d",
64         .id             = -1,
65         .index          = 1,
66         .syncpts        = BIT(NVSYNCPT_3D),
67         .waitbases      = BIT(NVWAITBASE_3D),
68         .modulemutexes  = BIT(NVMODMUTEX_3D),
69         .class          = NV_GRAPHICS_3D_CLASS_ID,
70         .prepare_poweroff = nvhost_gr3d_prepare_power_off,
71         .alloc_hwctx_handler = nvhost_gr3d_t20_ctxhandler_init,
72         .clocks         = {{"gr3d", UINT_MAX}, {"emc", UINT_MAX}, {} },
73         .powergate_ids  = {TEGRA_POWERGATE_3D, -1},
74         NVHOST_DEFAULT_CLOCKGATE_DELAY,
75         .moduleid       = NVHOST_MODULE_NONE,
76 },
77 {
78         /* channel 2 */
79         .name           = "gr2d",
80         .id             = -1,
81         .index          = 2,
82         .syncpts        = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1),
83         .waitbases      = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1),
84         .modulemutexes  = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) |
85                           BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B),
86         .clocks         = { {"gr2d", UINT_MAX},
87                             {"epp", UINT_MAX},
88                             {"emc", UINT_MAX} },
89         NVHOST_MODULE_NO_POWERGATE_IDS,
90         .clockgate_delay = 0,
91         .moduleid       = NVHOST_MODULE_NONE,
92 },
93 {
94         /* channel 3 */
95         .name           = "isp",
96         .id             = -1,
97         .index          = 3,
98         .syncpts        = 0,
99         NVHOST_MODULE_NO_POWERGATE_IDS,
100         NVHOST_DEFAULT_CLOCKGATE_DELAY,
101         .moduleid       = NVHOST_MODULE_ISP,
102 },
103 {
104         /* channel 4 */
105         .name           = "vi",
106         .id             = -1,
107         .index          = 4,
108         .syncpts        = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) |
109                           BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) |
110                           BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) |
111                           BIT(NVSYNCPT_VI_ISP_4),
112         .modulemutexes  = BIT(NVMODMUTEX_VI),
113         .exclusive      = true,
114         NVHOST_MODULE_NO_POWERGATE_IDS,
115         NVHOST_DEFAULT_CLOCKGATE_DELAY,
116         .moduleid       = NVHOST_MODULE_VI,
117 },
118 {
119         /* channel 5 */
120         .name           = "mpe",
121         .id             = -1,
122         .index          = 5,
123         .syncpts        = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) |
124                           BIT(NVSYNCPT_MPE_WR_SAFE),
125         .waitbases      = BIT(NVWAITBASE_MPE),
126         .class          = NV_VIDEO_ENCODE_MPEG_CLASS_ID,
127         .waitbasesync   = true,
128         .keepalive      = true,
129         .prepare_poweroff = nvhost_mpe_prepare_power_off,
130         .alloc_hwctx_handler = nvhost_mpe_ctxhandler_init,
131         .clocks         = { {"mpe", UINT_MAX},
132                             {"emc", UINT_MAX} },
133         .powergate_ids  = {TEGRA_POWERGATE_MPE, -1},
134         NVHOST_DEFAULT_CLOCKGATE_DELAY,
135         .moduleid       = NVHOST_MODULE_MPE,
136 },
137 {
138         /* channel 6 */
139         .name           = "dsi",
140         .id             = -1,
141         .index          = 6,
142         .syncpts        = BIT(NVSYNCPT_DSI),
143         .modulemutexes  = BIT(NVMODMUTEX_DSI),
144         NVHOST_MODULE_NO_POWERGATE_IDS,
145         NVHOST_DEFAULT_CLOCKGATE_DELAY,
146         .moduleid       = NVHOST_MODULE_NONE,
147 } };
148
149
150 static inline void __iomem *t20_channel_aperture(void __iomem *p, int ndx)
151 {
152         p += NV_HOST1X_CHANNEL0_BASE;
153         p += ndx * NV_HOST1X_CHANNEL_MAP_SIZE_BYTES;
154         return p;
155 }
156
157 static inline int t20_nvhost_hwctx_handler_init(struct nvhost_channel *ch)
158 {
159         int err = 0;
160         unsigned long syncpts = ch->dev->syncpts;
161         unsigned long waitbases = ch->dev->waitbases;
162         u32 syncpt = find_first_bit(&syncpts, BITS_PER_LONG);
163         u32 waitbase = find_first_bit(&waitbases, BITS_PER_LONG);
164
165         if (ch->dev->alloc_hwctx_handler) {
166                 ch->ctxhandler = ch->dev->alloc_hwctx_handler(syncpt,
167                                 waitbase, ch);
168                 if (!ch->ctxhandler)
169                         err = -ENOMEM;
170         }
171
172         return err;
173 }
174
175 static int t20_channel_init(struct nvhost_channel *ch,
176         struct nvhost_master *dev, int index)
177 {
178         ch->chid = index;
179         mutex_init(&ch->reflock);
180         mutex_init(&ch->submitlock);
181
182         ch->aperture = t20_channel_aperture(dev->aperture, index);
183
184         return t20_nvhost_hwctx_handler_init(ch);
185 }
186
187 int nvhost_init_t20_channel_support(struct nvhost_master *host)
188 {
189         host->nb_channels =  NVHOST_NUMCHANNELS;
190
191         host->op.channel.init = t20_channel_init;
192         host->op.channel.submit = host1x_channel_submit;
193         host->op.channel.read3dreg = host1x_channel_read_3d_reg;
194
195         return 0;
196 }
197
198 struct nvhost_device *t20_get_nvhost_device(struct nvhost_master *host,
199         char *name)
200 {
201         int i;
202
203         for (i = 0; i < host->nb_channels; i++) {
204                 if (strcmp(t20_devices[i].name, name) == 0)
205                         return &t20_devices[i];
206         }
207
208         return NULL;
209 }
210
211 int nvhost_init_t20_support(struct nvhost_master *host)
212 {
213         int err;
214
215         /* don't worry about cleaning up on failure... "remove" does it. */
216         err = nvhost_init_t20_channel_support(host);
217         if (err)
218                 return err;
219         err = host1x_init_cdma_support(host);
220         if (err)
221                 return err;
222         err = nvhost_init_t20_debug_support(host);
223         if (err)
224                 return err;
225         err = host1x_init_syncpt_support(host);
226         if (err)
227                 return err;
228         err = nvhost_init_t20_intr_support(host);
229         if (err)
230                 return err;
231         host->op.nvhost_dev.get_nvhost_device = t20_get_nvhost_device;
232         return 0;
233 }