5e299d4fdeabddb04b2b652c2f6db4ce51dad1c0
[linux-2.6.git] / drivers / video / tegra / host / t30 / t30.c
1 /*
2  * drivers/video/tegra/host/t30/t30.c
3  *
4  * Tegra Graphics Init for T30 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/mutex.h>
22 #include <linux/kernel.h>
23 #include <linux/nvhost_ioctl.h>
24 #include <mach/powergate.h>
25 #include <mach/iomap.h>
26 #include "dev.h"
27 #include "t20/t20.h"
28 #include "t30.h"
29 #include "gr3d/gr3d.h"
30 #include "gr3d/gr3d_t30.h"
31 #include "gr3d/scale3d.h"
32 #include "mpe/mpe.h"
33 #include "host1x/host1x_hardware.h"
34 #include "host1x/host1x_syncpt.h"
35 #include "chip_support.h"
36 #include "nvhost_channel.h"
37 #include "host1x/host1x_cdma.h"
38 #include "nvmap.h"
39 #include "nvhost_memmgr.h"
40
41 #define NVMODMUTEX_2D_FULL      (1)
42 #define NVMODMUTEX_2D_SIMPLE    (2)
43 #define NVMODMUTEX_2D_SB_A      (3)
44 #define NVMODMUTEX_2D_SB_B      (4)
45 #define NVMODMUTEX_3D           (5)
46 #define NVMODMUTEX_DISPLAYA     (6)
47 #define NVMODMUTEX_DISPLAYB     (7)
48 #define NVMODMUTEX_VI           (8)
49 #define NVMODMUTEX_DSI          (9)
50
51 #define NVHOST_CHANNEL_BASE     0
52
53 #define T30_NVHOST_NUMCHANNELS  (NV_HOST1X_CHANNELS - 1)
54
55 static int t30_num_alloc_channels = 0;
56
57 struct nvhost_device t30_devices[] = {
58 {
59         /* channel 0 */
60         .name           = "display",
61         .id             = -1,
62         .index          = 0,
63         .syncpts        = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) |
64                           BIT(NVSYNCPT_DISP0_B) | BIT(NVSYNCPT_DISP1_B) |
65                           BIT(NVSYNCPT_DISP0_C) | BIT(NVSYNCPT_DISP1_C) |
66                           BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1),
67         .modulemutexes  = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB),
68         NVHOST_MODULE_NO_POWERGATE_IDS,
69         NVHOST_DEFAULT_CLOCKGATE_DELAY,
70         .moduleid       = NVHOST_MODULE_NONE,
71 },
72 {
73         /* channel 1 */
74         .name           = "gr3d02",
75         .id             = -1,
76         .index          = 1,
77         .syncpts        = BIT(NVSYNCPT_3D),
78         .waitbases      = BIT(NVWAITBASE_3D),
79         .modulemutexes  = BIT(NVMODMUTEX_3D),
80         .class          = NV_GRAPHICS_3D_CLASS_ID,
81         .clocks         = { {"gr3d", UINT_MAX},
82                             {"gr3d2", UINT_MAX},
83                             {"emc", UINT_MAX} },
84         .powergate_ids = { TEGRA_POWERGATE_3D,
85                            TEGRA_POWERGATE_3D1 },
86         NVHOST_DEFAULT_CLOCKGATE_DELAY,
87         .can_powergate = true,
88         .powerup_reset = true,
89         .powergate_delay = 250,
90         .moduleid       = NVHOST_MODULE_NONE,
91 },
92 {
93         /* channel 2 */
94         .name           = "gr2d",
95         .id             = -1,
96         .index          = 2,
97         .syncpts        = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1),
98         .waitbases      = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1),
99         .modulemutexes  = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) |
100                           BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B),
101         .clocks         = { {"gr2d", 0},
102                             {"epp", 0},
103                             {"emc", 300000000} },
104         NVHOST_MODULE_NO_POWERGATE_IDS,
105         .clockgate_delay = 0,
106         .moduleid       = NVHOST_MODULE_NONE,
107 },
108 {
109         /* channel 3 */
110         .name           = "isp",
111         .id             = -1,
112         .index          = 3,
113         .syncpts        = 0,
114         NVHOST_MODULE_NO_POWERGATE_IDS,
115         NVHOST_DEFAULT_CLOCKGATE_DELAY,
116         .moduleid       = NVHOST_MODULE_ISP,
117 },
118 {
119         /* channel 4 */
120         .name           = "vi",
121         .id             = -1,
122         .index          = 4,
123         .syncpts        = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) |
124                           BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) |
125                           BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) |
126                           BIT(NVSYNCPT_VI_ISP_4),
127         .modulemutexes  = BIT(NVMODMUTEX_VI),
128         .exclusive      = true,
129         NVHOST_MODULE_NO_POWERGATE_IDS,
130         NVHOST_DEFAULT_CLOCKGATE_DELAY,
131         .moduleid       = NVHOST_MODULE_VI,
132 },
133 {
134         /* channel 5 */
135         .name           = "mpe02",
136         .id             = -1,
137         .index          = 5,
138         .syncpts        = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) |
139                           BIT(NVSYNCPT_MPE_WR_SAFE),
140         .waitbases      = BIT(NVWAITBASE_MPE),
141         .class          = NV_VIDEO_ENCODE_MPEG_CLASS_ID,
142         .waitbasesync   = true,
143         .keepalive      = true,
144         .clocks         = { {"mpe", UINT_MAX},
145                             {"emc", UINT_MAX} },
146         .powergate_ids  = {TEGRA_POWERGATE_MPE, -1},
147         NVHOST_DEFAULT_CLOCKGATE_DELAY,
148         .can_powergate  = true,
149         .powergate_delay = 100,
150         .moduleid       = NVHOST_MODULE_MPE,
151 },
152 {
153         /* channel 6 */
154         .name           = "dsi",
155         .id             = -1,
156         .index          = 6,
157         .syncpts        = BIT(NVSYNCPT_DSI),
158         .modulemutexes  = BIT(NVMODMUTEX_DSI),
159         NVHOST_MODULE_NO_POWERGATE_IDS,
160         NVHOST_DEFAULT_CLOCKGATE_DELAY,
161         .moduleid       = NVHOST_MODULE_NONE,
162 } };
163
164 static inline int t30_nvhost_hwctx_handler_init(struct nvhost_channel *ch)
165 {
166         int err = 0;
167         unsigned long syncpts = ch->dev->syncpts;
168         unsigned long waitbases = ch->dev->waitbases;
169         u32 syncpt = find_first_bit(&syncpts, BITS_PER_LONG);
170         u32 waitbase = find_first_bit(&waitbases, BITS_PER_LONG);
171         struct nvhost_driver *drv = to_nvhost_driver(ch->dev->dev.driver);
172
173         if (drv->alloc_hwctx_handler) {
174                 ch->ctxhandler = drv->alloc_hwctx_handler(syncpt,
175                                 waitbase, ch);
176                 if (!ch->ctxhandler)
177                         err = -ENOMEM;
178         }
179
180         return err;
181 }
182
183 static inline void __iomem *t30_channel_aperture(void __iomem *p, int ndx)
184 {
185         ndx += NVHOST_CHANNEL_BASE;
186         p += NV_HOST1X_CHANNEL0_BASE;
187         p += ndx * NV_HOST1X_CHANNEL_MAP_SIZE_BYTES;
188         return p;
189 }
190
191 static int t30_channel_init(struct nvhost_channel *ch,
192                             struct nvhost_master *dev, int index)
193 {
194         ch->chid = index;
195         mutex_init(&ch->reflock);
196         mutex_init(&ch->submitlock);
197
198         ch->aperture = t30_channel_aperture(dev->aperture, index);
199
200         return t30_nvhost_hwctx_handler_init(ch);
201 }
202
203 int nvhost_init_t30_channel_support(struct nvhost_master *host,
204         struct nvhost_chip_support *op)
205 {
206         int result = nvhost_init_t20_channel_support(host, op);
207         op->channel.init = t30_channel_init;
208
209         return result;
210 }
211
212 int nvhost_init_t30_debug_support(struct nvhost_chip_support *op)
213 {
214         nvhost_init_t20_debug_support(op);
215         op->debug.debug_init = nvhost_scale3d_debug_init;
216
217         return 0;
218 }
219
220 static void t30_free_nvhost_channel(struct nvhost_channel *ch)
221 {
222         nvhost_free_channel_internal(ch, &t30_num_alloc_channels);
223 }
224
225 static struct nvhost_channel *t30_alloc_nvhost_channel(int chindex)
226 {
227         return nvhost_alloc_channel_internal(chindex,
228                 T30_NVHOST_NUMCHANNELS, &t30_num_alloc_channels);
229 }
230
231 struct nvhost_device *t30_get_nvhost_device(char *name)
232 {
233         int i;
234
235         for (i = 0; i < ARRAY_SIZE(t30_devices); i++) {
236                 if (strncmp(t30_devices[i].name, name, strlen(name)) == 0)
237                         return &t30_devices[i];
238         }
239
240         return NULL;
241 }
242
243 int nvhost_init_t30_support(struct nvhost_master *host,
244         struct nvhost_chip_support *op)
245 {
246         int err;
247
248         /* don't worry about cleaning up on failure... "remove" does it. */
249         err = nvhost_init_t30_channel_support(host, op);
250         if (err)
251                 return err;
252         err = host1x_init_cdma_support(op);
253         if (err)
254                 return err;
255         err = nvhost_init_t30_debug_support(op);
256         if (err)
257                 return err;
258         err = host1x_init_syncpt_support(host, op);
259         if (err)
260                 return err;
261         err = nvhost_init_t20_intr_support(op);
262         if (err)
263                 return err;
264         err = nvhost_memmgr_init(op);
265         if (err)
266                 return err;
267
268         op->nvhost_dev.get_nvhost_device = t30_get_nvhost_device;
269         op->nvhost_dev.alloc_nvhost_channel = t30_alloc_nvhost_channel;
270         op->nvhost_dev.free_nvhost_channel = t30_free_nvhost_channel;
271
272         return 0;
273 }