video: tegra: host: Register devices in SoC files
[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 <linux/nvhost_ioctl.h>
23 #include <mach/powergate.h>
24 #include <mach/iomap.h>
25 #include "t20.h"
26 #include "host1x/host1x_syncpt.h"
27 #include "host1x/host1x_hardware.h"
28 #include "gr3d/gr3d.h"
29 #include "gr3d/gr3d_t20.h"
30 #include "mpe/mpe.h"
31 #include "host1x/host1x.h"
32 #include "nvhost_hwctx.h"
33 #include "nvhost_channel.h"
34 #include "host1x/host1x_channel.h"
35 #include "host1x/host1x_cdma.h"
36 #include "chip_support.h"
37 #include "nvmap.h"
38 #include "nvhost_memmgr.h"
39
40 #define NVMODMUTEX_2D_FULL      (1)
41 #define NVMODMUTEX_2D_SIMPLE    (2)
42 #define NVMODMUTEX_2D_SB_A      (3)
43 #define NVMODMUTEX_2D_SB_B      (4)
44 #define NVMODMUTEX_3D           (5)
45 #define NVMODMUTEX_DISPLAYA     (6)
46 #define NVMODMUTEX_DISPLAYB     (7)
47 #define NVMODMUTEX_VI           (8)
48 #define NVMODMUTEX_DSI          (9)
49
50 #define T20_NVHOST_NUMCHANNELS  (NV_HOST1X_CHANNELS - 1)
51
52 static int t20_num_alloc_channels = 0;
53
54 static struct nvhost_device tegra_display01_device = {
55         .name           = "display",
56         .id             = -1,
57         .index          = 0,
58         .syncpts        = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) |
59                           BIT(NVSYNCPT_DISP0_B) | BIT(NVSYNCPT_DISP1_B) |
60                           BIT(NVSYNCPT_DISP0_C) | BIT(NVSYNCPT_DISP1_C) |
61                           BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1),
62         .modulemutexes  = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB),
63         NVHOST_MODULE_NO_POWERGATE_IDS,
64         NVHOST_DEFAULT_CLOCKGATE_DELAY,
65         .moduleid       = NVHOST_MODULE_NONE,
66 };
67
68 static struct nvhost_device tegra_gr3d01_device = {
69         .name           = "gr3d01",
70         .id             = -1,
71         .index          = 1,
72         .syncpts        = BIT(NVSYNCPT_3D),
73         .waitbases      = BIT(NVWAITBASE_3D),
74         .modulemutexes  = BIT(NVMODMUTEX_3D),
75         .class          = NV_GRAPHICS_3D_CLASS_ID,
76         .clocks         = {{"gr3d", UINT_MAX}, {"emc", UINT_MAX}, {} },
77         .powergate_ids  = {TEGRA_POWERGATE_3D, -1},
78         NVHOST_DEFAULT_CLOCKGATE_DELAY,
79         .moduleid       = NVHOST_MODULE_NONE,
80 };
81
82 static struct nvhost_device tegra_gr2d01_device = {
83         .name           = "gr2d",
84         .id             = -1,
85         .index          = 2,
86         .syncpts        = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1),
87         .waitbases      = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1),
88         .modulemutexes  = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) |
89                           BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B),
90         .clocks         = { {"gr2d", UINT_MAX},
91                             {"epp", UINT_MAX},
92                             {"emc", UINT_MAX} },
93         NVHOST_MODULE_NO_POWERGATE_IDS,
94         .clockgate_delay = 0,
95         .moduleid       = NVHOST_MODULE_NONE,
96 };
97
98 static struct resource isp_resources_t20[] = {
99         {
100                 .name = "regs",
101                 .start = TEGRA_ISP_BASE,
102                 .end = TEGRA_ISP_BASE + TEGRA_ISP_SIZE - 1,
103                 .flags = IORESOURCE_MEM,
104         }
105 };
106
107 static struct nvhost_device tegra_isp01_device = {
108         .name           = "isp",
109         .id             = -1,
110         .resource = isp_resources_t20,
111         .num_resources = ARRAY_SIZE(isp_resources_t20),
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 static struct resource vi_resources[] = {
120         {
121                 .name = "regs",
122                 .start = TEGRA_VI_BASE,
123                 .end = TEGRA_VI_BASE + TEGRA_VI_SIZE - 1,
124                 .flags = IORESOURCE_MEM,
125         },
126 };
127
128 static struct nvhost_device tegra_vi01_device = {
129         .name           = "vi",
130         .resource = vi_resources,
131         .num_resources = ARRAY_SIZE(vi_resources),
132         .id             = -1,
133         .index          = 4,
134         .syncpts        = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) |
135                           BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) |
136                           BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) |
137                           BIT(NVSYNCPT_VI_ISP_4),
138         .modulemutexes  = BIT(NVMODMUTEX_VI),
139         .exclusive      = true,
140         NVHOST_MODULE_NO_POWERGATE_IDS,
141         NVHOST_DEFAULT_CLOCKGATE_DELAY,
142         .moduleid       = NVHOST_MODULE_VI,
143 };
144
145 static struct resource tegra_mpe01_resources[] = {
146         {
147                 .name = "regs",
148                 .start = TEGRA_MPE_BASE,
149                 .end = TEGRA_MPE_BASE + TEGRA_MPE_SIZE - 1,
150                 .flags = IORESOURCE_MEM,
151         },
152 };
153
154 static struct nvhost_device tegra_mpe01_device = {
155         .name           = "mpe01",
156         .id             = -1,
157         .resource       = tegra_mpe01_resources,
158         .num_resources  = ARRAY_SIZE(tegra_mpe01_resources),
159         .index          = 5,
160         .syncpts        = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) |
161                           BIT(NVSYNCPT_MPE_WR_SAFE),
162         .waitbases      = BIT(NVWAITBASE_MPE),
163         .class          = NV_VIDEO_ENCODE_MPEG_CLASS_ID,
164         .waitbasesync   = true,
165         .keepalive      = true,
166         .clocks         = { {"mpe", UINT_MAX},
167                             {"emc", UINT_MAX} },
168         .powergate_ids  = {TEGRA_POWERGATE_MPE, -1},
169         NVHOST_DEFAULT_CLOCKGATE_DELAY,
170         .moduleid       = NVHOST_MODULE_MPE,
171 };
172
173 static struct nvhost_device tegra_dsi01_device = {
174         .name           = "dsi",
175         .id             = -1,
176         .index          = 6,
177         .syncpts        = BIT(NVSYNCPT_DSI),
178         .modulemutexes  = BIT(NVMODMUTEX_DSI),
179         NVHOST_MODULE_NO_POWERGATE_IDS,
180         NVHOST_DEFAULT_CLOCKGATE_DELAY,
181         .moduleid       = NVHOST_MODULE_NONE,
182 };
183
184 static struct nvhost_device *t20_devices[] = {
185         &tegra_host1x01_device,
186         &tegra_display01_device,
187         &tegra_gr3d01_device,
188         &tegra_gr2d01_device,
189         &tegra_isp01_device,
190         &tegra_vi01_device,
191         &tegra_mpe01_device,
192         &tegra_dsi01_device,
193 };
194
195 int tegra2_register_host1x_devices(void)
196 {
197         return nvhost_add_devices(t20_devices, ARRAY_SIZE(t20_devices));
198 }
199
200 static inline void __iomem *t20_channel_aperture(void __iomem *p, int ndx)
201 {
202         p += NV_HOST1X_CHANNEL0_BASE;
203         p += ndx * NV_HOST1X_CHANNEL_MAP_SIZE_BYTES;
204         return p;
205 }
206
207 static inline int t20_nvhost_hwctx_handler_init(struct nvhost_channel *ch)
208 {
209         int err = 0;
210         unsigned long syncpts = ch->dev->syncpts;
211         unsigned long waitbases = ch->dev->waitbases;
212         u32 syncpt = find_first_bit(&syncpts, BITS_PER_LONG);
213         u32 waitbase = find_first_bit(&waitbases, BITS_PER_LONG);
214         struct nvhost_driver *drv = to_nvhost_driver(ch->dev->dev.driver);
215
216         if (drv->alloc_hwctx_handler) {
217                 ch->ctxhandler = drv->alloc_hwctx_handler(syncpt,
218                                 waitbase, ch);
219                 if (!ch->ctxhandler)
220                         err = -ENOMEM;
221         }
222
223         return err;
224 }
225
226 static int t20_channel_init(struct nvhost_channel *ch,
227         struct nvhost_master *dev, int index)
228 {
229         ch->chid = index;
230         mutex_init(&ch->reflock);
231         mutex_init(&ch->submitlock);
232
233         ch->aperture = t20_channel_aperture(dev->aperture, index);
234
235         return t20_nvhost_hwctx_handler_init(ch);
236 }
237
238 int nvhost_init_t20_channel_support(struct nvhost_master *host,
239         struct nvhost_chip_support *op)
240 {
241         op->channel.init = t20_channel_init;
242         op->channel.submit = host1x_channel_submit;
243         op->channel.read3dreg = host1x_channel_read_3d_reg;
244
245         return 0;
246 }
247
248 static void t20_free_nvhost_channel(struct nvhost_channel *ch)
249 {
250         nvhost_free_channel_internal(ch, &t20_num_alloc_channels);
251 }
252
253 static struct nvhost_channel *t20_alloc_nvhost_channel(int chindex)
254 {
255         return nvhost_alloc_channel_internal(chindex,
256                 T20_NVHOST_NUMCHANNELS, &t20_num_alloc_channels);
257 }
258
259 int nvhost_init_t20_support(struct nvhost_master *host,
260         struct nvhost_chip_support *op)
261 {
262         int err;
263
264         /* don't worry about cleaning up on failure... "remove" does it. */
265         err = nvhost_init_t20_channel_support(host, op);
266         if (err)
267                 return err;
268         err = host1x_init_cdma_support(op);
269         if (err)
270                 return err;
271         err = nvhost_init_t20_debug_support(op);
272         if (err)
273                 return err;
274         err = host1x_init_syncpt_support(host, op);
275         if (err)
276                 return err;
277         err = nvhost_init_t20_intr_support(op);
278         if (err)
279                 return err;
280         err = nvhost_memmgr_init(op);
281
282         op->nvhost_dev.alloc_nvhost_channel = t20_alloc_nvhost_channel;
283         op->nvhost_dev.free_nvhost_channel = t20_free_nvhost_channel;
284
285         return 0;
286 }