b36753b52f3a8fc34be2ff182812cc87fd4b2c5d
[linux-3.10.git] / drivers / video / tegra / host / t124 / t124.c
1 /*
2  * drivers/video/tegra/host/t124/t124.c
3  *
4  * Tegra Graphics Init for T124 Architecture Chips
5  *
6  * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
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 #include <linux/slab.h>
21 #include <linux/tegra-powergate.h>
22
23 #include <mach/mc.h>
24
25 #include "dev.h"
26 #include "nvhost_job.h"
27 #include "class_ids.h"
28
29 #include "t124.h"
30 #include "host1x/host1x.h"
31
32 #include "hardware_t124.h"
33 #include "syncpt_t124.h"
34
35 #include "gk20a/gk20a.h"
36 #include "gk20a/gk20a_scale.h"
37 #include "vic03/vic03.h"
38 #include "msenc/msenc.h"
39 #include "tsec/tsec.h"
40 #include "vi/vi.h"
41 #include "isp/isp.h"
42 #include "gr3d/pod_scaling.h"
43 #include "gr3d/scale3d.h"
44
45 #include "nvhost_memmgr.h"
46 #include "chip_support.h"
47 #include "nvhost_scale.h"
48
49 static int t124_num_alloc_channels = 0;
50
51 #define HOST_EMC_FLOOR 300000000
52 #define VI_CLOCKGATE_DELAY 60
53 #define VI_POWERGATE_DELAY 500
54 #define ISP_CLOCKGATE_DELAY 60
55 #define ISP_POWERGATE_DELAY 500
56 #define TSEC_POWERGATE_DELAY 500
57
58 #define GK20A_DEV_NAME_SIZE 5
59
60 #define BIT64(nr) (1ULL << (nr))
61 #define NVSYNCPTS_CLIENT_MANAGED_T124 ( \
62         BIT64(NVSYNCPT_DISP0_A) | BIT64(NVSYNCPT_DISP1_A) | \
63         BIT64(NVSYNCPT_DISP0_B) | BIT64(NVSYNCPT_DISP1_B) | \
64         BIT64(NVSYNCPT_DISP0_C) | BIT64(NVSYNCPT_DISP1_C) | \
65         BIT(NVSYNCPT_DISP0_D) | \
66         BIT(NVSYNCPT_DISP0_H) | BIT(NVSYNCPT_DISP1_H) | \
67         BIT64(NVSYNCPT_DSI) | \
68         BIT64(NVSYNCPT_VBLANK0) | BIT64(NVSYNCPT_VBLANK1) | \
69         BIT64(NVSYNCPT_AVP_0))
70
71 /* Host1x driver matches module IDs while setting a
72  * particular clock, This ID is used for EMC module.
73  */
74 #define TEGRA_HOST1X_EMC_MODULE_ID 75
75
76 static struct resource tegra_host1x04_resources[] = {
77         {
78                 .start = TEGRA_HOST1X_BASE,
79                 .end = TEGRA_HOST1X_BASE + TEGRA_HOST1X_SIZE - 1,
80                 .flags = IORESOURCE_MEM,
81         },
82         {
83                 .start = INT_HOST1X_MPCORE_SYNCPT,
84                 .end = INT_HOST1X_MPCORE_SYNCPT,
85                 .flags = IORESOURCE_IRQ,
86         },
87         {
88                 .start = INT_HOST1X_MPCORE_GENERAL,
89                 .end = INT_HOST1X_MPCORE_GENERAL,
90                 .flags = IORESOURCE_IRQ,
91         },
92 };
93
94 static const char *s_syncpt_names[NV_HOST1X_SYNCPT_NB_PTS] = {
95         [NVSYNCPT_ISP_0_0]      = "ispa_memory",
96         [NVSYNCPT_ISP_0_1]      = "ispa_stats",
97         [NVSYNCPT_ISP_0_2]      = "ispa_stream",
98         [NVSYNCPT_ISP_0_3]      = "ispa_loadv",
99         [NVSYNCPT_ISP_1_0]      = "ispb_memory",
100         [NVSYNCPT_ISP_1_1]      = "ispb_stats",
101         [NVSYNCPT_ISP_1_2]      = "ispb_stream",
102         [NVSYNCPT_ISP_1_3]      = "ispb_loadv",
103         [NVSYNCPT_VI_0_0]       = "vi0_ispa",
104         [NVSYNCPT_VI_0_1]       = "vi0_ispb",
105         [NVSYNCPT_VI_0_2]       = "vi0_stream",
106         [NVSYNCPT_VI_0_3]       = "vi0_memory",
107         [NVSYNCPT_VI_0_4]       = "vi0_flash",
108         [NVSYNCPT_VI_1_0]       = "vi1_ispa",
109         [NVSYNCPT_VI_1_1]       = "vi1_ispb",
110         [NVSYNCPT_VI_1_2]       = "vi1_stream",
111         [NVSYNCPT_VI_1_3]       = "vi1_memory",
112         [NVSYNCPT_VI_1_4]       = "vi1_flash",
113         [NVSYNCPT_3D]           = "3d",
114         [NVSYNCPT_MPE]          = "mpe",
115         [NVSYNCPT_MPE_EBM_EOF]  = "mpe_ebm_eof",
116         [NVSYNCPT_MPE_WR_SAFE]  = "mpe_wr_safe",
117         [NVSYNCPT_VIC]          = "vic",
118         [NVSYNCPT_TSEC]         = "tsec",
119         [NVSYNCPT_DISP0_A]      = "disp0",
120         [NVSYNCPT_DISP1_A]      = "disp1",
121         [NVSYNCPT_AVP_0]        = "avp",
122         [NVSYNCPT_DISP0_B]      = "disp0b",
123         [NVSYNCPT_DISP1_B]      = "disp1b",
124         [NVSYNCPT_DISP0_C]      = "disp0c",
125         [NVSYNCPT_DISP1_C]      = "disp1c",
126         [NVSYNCPT_DISP0_D]      = "disp0d",
127         [NVSYNCPT_DISP0_H]      = "disp0h",
128         [NVSYNCPT_DISP1_H]      = "disp1h",
129         [NVSYNCPT_VBLANK0]      = "vblank0",
130         [NVSYNCPT_VBLANK1]      = "vblank1",
131         [NVSYNCPT_DSI]          = "dsi",
132 };
133
134 static struct host1x_device_info host1x04_info = {
135         .nb_channels    = T124_NVHOST_NUMCHANNELS,
136         .nb_pts         = NV_HOST1X_SYNCPT_NB_PTS,
137         .nb_mlocks      = NV_HOST1X_NB_MLOCKS,
138         .nb_bases       = NV_HOST1X_SYNCPT_NB_BASES,
139         .syncpt_names   = s_syncpt_names,
140         .client_managed = NVSYNCPTS_CLIENT_MANAGED_T124,
141 };
142
143 struct nvhost_device_data t124_host1x_info = {
144         .clocks         = {{"host1x", 81600000}, {"actmon", UINT_MAX} },
145         NVHOST_MODULE_NO_POWERGATE_IDS,
146         .private_data   = &host1x04_info,
147         .finalize_poweron = nvhost_host1x_finalize_poweron,
148         .prepare_poweroff = nvhost_host1x_prepare_poweroff,
149 };
150
151
152 static struct platform_device tegra_host1x04_device = {
153         .name           = "host1x",
154         .id             = -1,
155         .resource       = tegra_host1x04_resources,
156         .num_resources  = ARRAY_SIZE(tegra_host1x04_resources),
157         .dev            = {
158                 .platform_data = &t124_host1x_info,
159         },
160 };
161
162
163 static struct resource isp_resources[] = {
164         {
165                 .name = "regs",
166                 .start = TEGRA_ISP_BASE,
167                 .end = TEGRA_ISP_BASE + TEGRA_ISP_SIZE - 1,
168                 .flags = IORESOURCE_MEM,
169         }
170 };
171
172 static struct platform_device tegra_isp01b_device;
173 struct nvhost_device_data t124_isp_info = {
174         /* FIXME: control clocks from user space instead of hard-coding here */
175         .syncpts         = NV_ISP_0_SYNCPTS,
176         .moduleid        = NVHOST_MODULE_ISP,
177         .modulemutexes   = {NVMODMUTEX_ISP_0},
178         .exclusive       = true,
179         .keepalive       = true,
180         .powergate_ids   = {TEGRA_POWERGATE_VENC, -1},
181         .can_powergate   = true,
182         .clockgate_delay = ISP_CLOCKGATE_DELAY,
183         .powergate_delay = ISP_POWERGATE_DELAY,
184         .clocks          = {
185                 {"isp", UINT_MAX, 0, TEGRA_MC_CLIENT_ISP},
186                 {"emc", 0, TEGRA_HOST1X_EMC_MODULE_ID},
187                 {"sclk", 80000000} },
188         .finalize_poweron = nvhost_isp_t124_finalize_poweron,
189         .ctrl_ops         = &tegra_isp_ctrl_ops,
190         .alloc_hwctx_handler = nvhost_alloc_hwctx_handler,
191 };
192 static struct platform_device tegra_isp01_device = {
193         .name          = "isp",
194         .resource      = isp_resources,
195         .num_resources = ARRAY_SIZE(isp_resources),
196         .dev           = {
197                 .platform_data = &t124_isp_info,
198         },
199 };
200
201 static struct resource ispb_resources[] = {
202         {
203                 .name = "regs",
204                 .start = TEGRA_ISPB_BASE,
205                 .end = TEGRA_ISPB_BASE + TEGRA_ISPB_SIZE - 1,
206                 .flags = IORESOURCE_MEM,
207         }
208 };
209
210
211 struct nvhost_device_data t124_ispb_info = {
212         /* FIXME: control clocks from user space instead of hard-coding here */
213         .syncpts         = NV_ISP_1_SYNCPTS,
214         .moduleid        = (1 << 16) | NVHOST_MODULE_ISP,
215         .modulemutexes   = {NVMODMUTEX_ISP_1},
216         .exclusive       = true,
217         .keepalive       = true,
218         .powergate_ids   = {TEGRA_POWERGATE_VENC, -1},
219         .can_powergate   = true,
220         .clockgate_delay = ISP_CLOCKGATE_DELAY,
221         .powergate_delay = ISP_POWERGATE_DELAY,
222         .clocks          = {
223                 {"isp", UINT_MAX, 0, TEGRA_MC_CLIENT_ISPB},
224                 {"emc", 0, TEGRA_HOST1X_EMC_MODULE_ID},
225                 {"sclk", 80000000} },
226         .finalize_poweron = nvhost_isp_t124_finalize_poweron,
227         .ctrl_ops         = &tegra_isp_ctrl_ops,
228         .alloc_hwctx_handler = nvhost_alloc_hwctx_handler,
229 };
230
231 static struct platform_device tegra_isp01b_device = {
232         .name          = "isp",
233         .id            = 1, /* .1 on the dev node */
234         .resource      = ispb_resources,
235         .num_resources = ARRAY_SIZE(ispb_resources),
236         .dev  = {
237                 .platform_data = &t124_ispb_info,
238         },
239 };
240
241 static struct resource vi_resources[] = {
242         {
243                 .name = "regs",
244                 .start = TEGRA_VI_BASE,
245                 .end = TEGRA_VI_BASE + TEGRA_VI_SIZE - 1,
246                 .flags = IORESOURCE_MEM,
247         },
248 };
249
250 static struct platform_device tegra_vi01b_device;
251 struct nvhost_device_data t124_vi_info = {
252         /* FIXME: resolve powergating dependency with DIS */
253         /* FIXME: control clocks from user space instead of hard-coding here */
254         .syncpts          = NV_VI_0_SYNCPTS,
255         .moduleid         = NVHOST_MODULE_VI,
256         .modulemutexes    = {NVMODMUTEX_VI_0},
257         .exclusive        = true,
258         .keepalive       = true,
259         .powergate_ids    = {TEGRA_POWERGATE_VENC, -1},
260         .can_powergate    = true,
261         .clockgate_delay  = VI_CLOCKGATE_DELAY,
262         .powergate_delay  = VI_POWERGATE_DELAY,
263         .clocks           = {
264                 {"vi", UINT_MAX, 0},
265                 {"csi", 0},
266                 {"cilab", 102000000},
267                 {"emc", 0, TEGRA_HOST1X_EMC_MODULE_ID},
268                 {"sclk", 80000000} },
269         .init             = nvhost_vi_init,
270         .deinit           = nvhost_vi_deinit,
271         .prepare_poweroff = nvhost_vi_prepare_poweroff,
272         .finalize_poweron = nvhost_vi_finalize_poweron,
273         .ctrl_ops         = &tegra_vi_ctrl_ops,
274         .reset            = nvhost_vi_reset,
275         .slave         = &tegra_vi01b_device,
276         .alloc_hwctx_handler = nvhost_alloc_hwctx_handler,
277 };
278 EXPORT_SYMBOL(t124_vi_info);
279
280 static struct platform_device tegra_vi01_device = {
281         .name           = "vi",
282         .resource       = vi_resources,
283         .num_resources  = ARRAY_SIZE(vi_resources),
284         .dev            = {
285                 .platform_data = &t124_vi_info,
286         },
287 };
288
289 struct nvhost_device_data t124_vib_info = {
290         /* FIXME: resolve powergating dependency with DIS */
291         /* FIXME: control clocks from user space instead of hard-coding here */
292         .syncpts          = NV_VI_1_SYNCPTS,
293         .moduleid         = (1 << 16 | NVHOST_MODULE_VI),
294         .modulemutexes    = {NVMODMUTEX_VI_1},
295         .exclusive        = true,
296         .keepalive       = true,
297         .powergate_ids    = {TEGRA_POWERGATE_VENC, -1},
298         .can_powergate    = true,
299         .clockgate_delay  = VI_CLOCKGATE_DELAY,
300         .powergate_delay  = VI_POWERGATE_DELAY,
301         .clocks           = {
302                 {"vi", UINT_MAX},
303                 {"csi", 0},
304                 {"cilcd", 102000000},
305                 {"cile", 102000000},
306                 {"emc", 0, TEGRA_HOST1X_EMC_MODULE_ID},
307                 {"sclk", 80000000} },
308         .init             = nvhost_vi_init,
309         .deinit           = nvhost_vi_deinit,
310         .prepare_poweroff = nvhost_vi_prepare_poweroff,
311         .finalize_poweron = nvhost_vi_finalize_poweron,
312         .ctrl_ops         = &tegra_vi_ctrl_ops,
313         .master           = &tegra_vi01_device,
314         .reset            = nvhost_vi_reset,
315         .alloc_hwctx_handler = nvhost_alloc_hwctx_handler,
316 };
317
318 static struct platform_device tegra_vi01b_device = {
319         .name           = "vi",
320         .id             = 1, /* .1 on the dev node */
321         .dev            = {
322                 .platform_data = &t124_vib_info,
323         },
324 };
325
326 static struct resource msenc_resources[] = {
327         {
328                 .name = "regs",
329                 .start = TEGRA_MSENC_BASE,
330                 .end = TEGRA_MSENC_BASE + TEGRA_MSENC_SIZE - 1,
331                 .flags = IORESOURCE_MEM,
332         },
333 };
334
335 struct nvhost_device_data t124_msenc_info = {
336         .version        = NVHOST_ENCODE_MSENC_VER(3, 1),
337         .syncpts        = {NVSYNCPT_MSENC, NVSYNCPT_MSENC_SLICE},
338         .waitbases      = {NVWAITBASE_MSENC},
339         .class          = NV_VIDEO_ENCODE_MSENC_CLASS_ID,
340         .clocks         = {{"msenc", UINT_MAX, 0, TEGRA_MC_CLIENT_MSENC},
341                           {"emc", HOST_EMC_FLOOR} },
342         NVHOST_DEFAULT_CLOCKGATE_DELAY,
343         .moduleid       = NVHOST_MODULE_MSENC,
344         .powergate_ids  = { TEGRA_POWERGATE_MPE, -1 },
345         .powergate_delay = 100,
346         .can_powergate  = true,
347         .init           = nvhost_msenc_init,
348         .deinit         = nvhost_msenc_deinit,
349         .finalize_poweron = nvhost_msenc_finalize_poweron,
350         .scaling_init   = nvhost_scale_init,
351         .scaling_deinit = nvhost_scale_deinit,
352         .actmon_regs    = HOST1X_CHANNEL_ACTMON1_REG_BASE,
353         .actmon_enabled = true,
354 };
355
356 struct platform_device tegra_msenc03_device = {
357         .name          = "msenc",
358         .id            = -1,
359         .resource      = msenc_resources,
360         .num_resources = ARRAY_SIZE(msenc_resources),
361         .dev           = {
362                 .platform_data = &t124_msenc_info,
363         },
364 };
365
366 static struct resource tsec_resources[] = {
367         {
368                 .name = "regs",
369                 .start = TEGRA_TSEC_BASE,
370                 .end = TEGRA_TSEC_BASE + TEGRA_TSEC_SIZE - 1,
371                 .flags = IORESOURCE_MEM,
372         },
373 };
374
375 struct nvhost_device_data t124_tsec_info = {
376         .version       = NVHOST_ENCODE_TSEC_VER(1, 0),
377         .syncpts       = {NVSYNCPT_TSEC},
378         .waitbases     = {NVWAITBASE_TSEC},
379         .class         = NV_TSEC_CLASS_ID,
380         .exclusive     = true,
381         .clocks        = {{"tsec", UINT_MAX, 0, TEGRA_MC_CLIENT_TSEC},
382                          {"emc", HOST_EMC_FLOOR} },
383         NVHOST_MODULE_NO_POWERGATE_IDS,
384         NVHOST_DEFAULT_CLOCKGATE_DELAY,
385         .can_powergate    = true,
386         .powergate_delay = TSEC_POWERGATE_DELAY,
387         .keepalive       = true,
388         .moduleid      = NVHOST_MODULE_TSEC,
389         .init          = nvhost_tsec_init,
390         .deinit        = nvhost_tsec_deinit,
391         .finalize_poweron = nvhost_tsec_finalize_poweron,
392         .prepare_poweroff = nvhost_tsec_prepare_poweroff,
393 };
394
395 static struct platform_device tegra_tsec01_device = {
396         .name           = "tsec",
397         .id             = -1,
398         .resource       = tsec_resources,
399         .num_resources  = ARRAY_SIZE(tsec_resources),
400         .dev            = {
401                 .platform_data = &t124_tsec_info,
402         },
403 };
404
405 #ifdef CONFIG_ARCH_TEGRA_VIC
406 static struct resource vic03_resources[] = {
407         {
408         .name = "base",
409         .start = TEGRA_VIC_BASE,
410         .end = TEGRA_VIC_BASE + TEGRA_VIC_SIZE - 1,
411         .flags = IORESOURCE_MEM,
412         },
413 };
414
415 struct nvhost_device_data t124_vic_info = {
416         .syncpts                = {NVSYNCPT_VIC},
417         .modulemutexes          = {NVMODMUTEX_VIC},
418         .clocks                 = {{"vic03", UINT_MAX, 0, TEGRA_MC_CLIENT_VIC},
419                                   {"emc", UINT_MAX} },
420         .version = NVHOST_ENCODE_VIC_VER(3, 0),
421         NVHOST_MODULE_NO_POWERGATE_IDS,
422         NVHOST_DEFAULT_CLOCKGATE_DELAY,
423         .moduleid      = NVHOST_MODULE_VIC,
424         .alloc_hwctx_handler = nvhost_vic03_alloc_hwctx_handler,
425         .can_powergate          = true,
426         .powergate_delay        = 500,
427         .powergate_ids          = { TEGRA_POWERGATE_VIC, -1 },
428         .init                   = nvhost_vic03_init,
429         .deinit                 = nvhost_vic03_deinit,
430         .alloc_hwctx_handler    = nvhost_vic03_alloc_hwctx_handler,
431         .finalize_poweron       = nvhost_vic03_finalize_poweron,
432         .prepare_poweroff       = nvhost_vic03_prepare_poweroff,
433         .scaling_init           = nvhost_scale3d_init,
434         .scaling_deinit         = nvhost_scale3d_deinit,
435         .busy                   = nvhost_scale_notify_busy,
436         .idle                   = nvhost_scale_notify_idle,
437         .suspend_ndev           = nvhost_scale3d_suspend,
438         .scaling_post_cb        = &nvhost_scale3d_callback,
439         .devfreq_governor       = "nvhost_podgov",
440         .actmon_regs            = HOST1X_CHANNEL_ACTMON2_REG_BASE,
441         .actmon_enabled         = true,
442         .linear_emc             = true,
443 };
444
445 struct platform_device tegra_vic03_device = {
446         .name          = "vic03",
447         .num_resources = 1,
448         .resource      = vic03_resources,
449         .dev           = {
450                 .platform_data = &t124_vic_info,
451         },
452 };
453 #endif
454
455 #if defined(CONFIG_TEGRA_GK20A)
456 struct resource gk20a_resources[] = {
457         {
458         .start = TEGRA_GK20A_BAR0_BASE,
459         .end   = TEGRA_GK20A_BAR0_BASE + TEGRA_GK20A_BAR0_SIZE - 1,
460         .flags = IORESOURCE_MEM,
461         },
462         {
463         .start = TEGRA_GK20A_BAR1_BASE,
464         .end   = TEGRA_GK20A_BAR1_BASE + TEGRA_GK20A_BAR1_SIZE - 1,
465         .flags = IORESOURCE_MEM,
466         },
467 };
468
469 struct nvhost_device_data tegra_gk20a_info = {
470         .syncpts                = {NVSYNCPT_GK20A_BASE},
471         .syncpt_base            = NVSYNCPT_GK20A_BASE,
472         .class                  = NV_GRAPHICS_GPU_CLASS_ID,
473         .clocks                 = {{"PLLG_ref", UINT_MAX},
474                                    {"pwr", 204000000},
475                                    {"emc", UINT_MAX},
476                                    {} },
477         .powergate_ids          = { TEGRA_POWERGATE_GPU, -1 },
478         NVHOST_DEFAULT_CLOCKGATE_DELAY,
479         .powergate_delay        = 500,
480         .can_powergate          = true,
481         .alloc_hwctx_handler    = nvhost_gk20a_alloc_hwctx_handler,
482         .ctrl_ops               = &tegra_gk20a_ctrl_ops,
483         .dbg_ops                = &tegra_gk20a_dbg_gpu_ops,
484         .prof_ops                = &tegra_gk20a_prof_gpu_ops,
485         .as_ops                 = &tegra_gk20a_as_ops,
486         .moduleid               = NVHOST_MODULE_GPU,
487         .init                   = nvhost_gk20a_init,
488         .deinit                 = nvhost_gk20a_deinit,
489         .alloc_hwctx_handler    = nvhost_gk20a_alloc_hwctx_handler,
490         .prepare_poweroff       = nvhost_gk20a_prepare_poweroff,
491         .finalize_poweron       = nvhost_gk20a_finalize_poweron,
492 #ifdef CONFIG_TEGRA_GK20A_DEVFREQ
493         .busy                   = nvhost_gk20a_scale_notify_busy,
494         .idle                   = nvhost_gk20a_scale_notify_idle,
495         .scaling_init           = nvhost_gk20a_scale_init,
496         .scaling_deinit         = nvhost_gk20a_scale_deinit,
497         .suspend_ndev           = nvhost_scale3d_suspend,
498         .devfreq_governor       = "nvhost_podgov",
499         .scaling_post_cb        = nvhost_gk20a_scale_callback,
500         .gpu_edp_device         = true,
501 #endif
502 };
503
504 struct platform_device tegra_gk20a_device = {
505         .name           = "gk20a",
506         .resource       = gk20a_resources,
507         .num_resources  = 2, /* this is num ioresource_mem, not the sum */
508         .dev            = {
509                 .platform_data = &tegra_gk20a_info,
510         },
511 };
512 #endif
513
514 static struct platform_device *t124_devices[] = {
515         &tegra_isp01_device,
516         &tegra_isp01b_device,
517         &tegra_vi01_device,
518         &tegra_msenc03_device,
519         &tegra_tsec01_device,
520 #if defined(CONFIG_TEGRA_GK20A)
521         &tegra_gk20a_device,
522 #endif
523 #if defined(CONFIG_ARCH_TEGRA_VIC)
524         &tegra_vic03_device,
525 #endif
526 };
527
528
529 struct platform_device *tegra12_register_host1x_devices(void)
530 {
531         int i = 0;
532         struct platform_device *pdev;
533
534         nvhost_dbg_fn("");
535
536         /* register host1x device first */
537         platform_device_register(&tegra_host1x04_device);
538         tegra_host1x04_device.dev.parent = NULL;
539
540         /* register clients with host1x device as parent */
541         for (i = 0; i < ARRAY_SIZE(t124_devices); i++) {
542                 pdev = t124_devices[i];
543                 pdev->dev.parent = &tegra_host1x04_device.dev;
544                 platform_device_register(pdev);
545         }
546
547         return &tegra_host1x04_device;
548 }
549
550 #include "host1x/host1x_channel.c"
551
552 #if defined(CONFIG_TEGRA_GK20A)
553 static int t124_channel_alloc_obj(struct nvhost_hwctx *hwctx,
554                                  struct nvhost_alloc_obj_ctx_args *args)
555 {
556         nvhost_dbg_fn("");
557         return gk20a_alloc_obj_ctx(hwctx->priv, args);
558 }
559
560 static int t124_channel_free_obj(struct nvhost_hwctx *hwctx,
561                                 struct nvhost_free_obj_ctx_args *args)
562 {
563         nvhost_dbg_fn("");
564         return gk20a_free_obj_ctx(hwctx->priv, args);
565 }
566
567 static int t124_channel_alloc_gpfifo(struct nvhost_hwctx *hwctx,
568                                     struct nvhost_alloc_gpfifo_args *args)
569 {
570         nvhost_dbg_fn("");
571         return gk20a_alloc_channel_gpfifo(hwctx->priv, args);
572 }
573
574 static int t124_channel_set_error_notifier(struct nvhost_hwctx *hwctx,
575                     struct nvhost_set_error_notifier *args) {
576         return gk20a_init_error_notifier(hwctx, args->mem, args->offset);
577 }
578
579 static int t124_channel_submit_gpfifo(struct nvhost_hwctx *hwctx,
580                                      struct nvhost_gpfifo *gpfifo, u32 num_entries,
581                                      struct nvhost_fence *fence, u32 flags)
582 {
583         struct channel_gk20a *ch = hwctx->priv;
584         struct nvhost_channel *nvhost_ch = hwctx->channel;
585         void *completed_waiter = NULL;
586         int err, ret;
587
588         nvhost_dbg_fn("");
589
590         if (hwctx->has_timedout || !ch)
591                 return -ETIMEDOUT;
592
593         completed_waiter = nvhost_intr_alloc_waiter();
594         if (!completed_waiter)
595                 return -ENOMEM;
596
597         nvhost_module_busy(nvhost_ch->dev);
598
599         ret = gk20a_submit_channel_gpfifo(hwctx->priv, gpfifo, num_entries,
600                                         fence, flags);
601         if (!ret) {
602                 err = nvhost_intr_add_action(
603                         &nvhost_get_host(nvhost_ch->dev)->intr,
604                         fence->syncpt_id, fence->value,
605                         NVHOST_INTR_ACTION_GPFIFO_SUBMIT_COMPLETE,
606                         ch,
607                         completed_waiter,
608                         NULL);
609                 WARN(err, "Failed to set submit complete interrupt");
610         } else {
611                 pr_err("submit error %d\n", ret);
612                 kfree(completed_waiter);
613         }
614         return ret;
615 }
616
617 static int t124_channel_wait(struct nvhost_hwctx *hwctx,
618                             struct nvhost_wait_args *args)
619 {
620         nvhost_dbg_fn("");
621         return gk20a_channel_wait(hwctx->priv, args);
622 }
623
624 static int t124_channel_set_priority(struct nvhost_hwctx *hwctx,
625                             struct nvhost_set_priority_args *args)
626 {
627         nvhost_dbg_fn("");
628         return gk20a_channel_set_priority(hwctx->priv, args->priority);
629 }
630
631 #if defined(CONFIG_TEGRA_GPU_CYCLE_STATS)
632 static int t124_channel_cycle_stats(struct nvhost_hwctx *hwctx,
633                                 struct nvhost_cycle_stats_args *args)
634 {
635         nvhost_dbg_fn("");
636         return gk20a_channel_cycle_stats(hwctx->priv, args);
637 }
638 #endif
639
640 static int t124_channel_zcull_bind(struct nvhost_hwctx *hwctx,
641                             struct nvhost_zcull_bind_args *args)
642 {
643         nvhost_dbg_fn("");
644         return gk20a_channel_zcull_bind(hwctx->priv, args);
645 }
646 #endif /* CONFIG_TEGRA_GK20A */
647
648 static void t124_free_nvhost_channel(struct nvhost_channel *ch)
649 {
650         nvhost_dbg_fn("");
651         nvhost_free_channel_internal(ch, &t124_num_alloc_channels);
652 }
653
654 static struct nvhost_channel *t124_alloc_nvhost_channel(
655                 struct platform_device *dev)
656 {
657         struct nvhost_device_data *pdata = nvhost_get_devdata(dev);
658         struct nvhost_channel *ch;
659         nvhost_dbg_fn("");
660         ch = nvhost_alloc_channel_internal(pdata->index,
661                 nvhost_get_host(dev)->info.nb_channels,
662                 &t124_num_alloc_channels);
663         if (ch) {
664 #if defined(CONFIG_TEGRA_GK20A)
665                 if (strncmp(dev->name, "gk20a", GK20A_DEV_NAME_SIZE) == 0) {
666                         ch->ops.init          = host1x_channel_ops.init;
667                         ch->ops.alloc_obj     = t124_channel_alloc_obj;
668                         ch->ops.free_obj      = t124_channel_free_obj;
669                         ch->ops.alloc_gpfifo  = t124_channel_alloc_gpfifo;
670                         ch->ops.submit_gpfifo = t124_channel_submit_gpfifo;
671                         ch->ops.set_priority  = t124_channel_set_priority;
672                         ch->ops.wait          = t124_channel_wait;
673                         ch->ops.set_error_notifier =
674                                         t124_channel_set_error_notifier;
675
676 #if defined(CONFIG_TEGRA_GPU_CYCLE_STATS)
677                         ch->ops.cycle_stats   = t124_channel_cycle_stats;
678 #endif
679                         ch->ops.zcull.bind    = t124_channel_zcull_bind;
680                 } else
681 #endif
682                         ch->ops = host1x_channel_ops;
683
684         }
685         return ch;
686 }
687
688 int nvhost_init_t124_channel_support(struct nvhost_master *host,
689        struct nvhost_chip_support *op)
690 {
691         int i, num_channels;
692
693         /* Set indices dynamically as we can have
694          * missing/non-static devices above (e.g.: vic, gk20a).
695          */
696
697         for (num_channels = i = 0; i < ARRAY_SIZE(t124_devices); i++) {
698                 struct platform_device *dev = t124_devices[i];
699                 struct nvhost_device_data *pdata =
700                         (struct nvhost_device_data *)dev->dev.platform_data;
701                 pdata->index = num_channels++;
702                 nvhost_dbg_fn("assigned channel %d to %s",
703                               pdata->index, dev_name(&dev->dev));
704                 if (pdata->slave) {
705                         struct nvhost_device_data *slave_pdata =
706                                 (struct nvhost_device_data *)pdata->slave->dev.platform_data;
707                         slave_pdata->index = num_channels++;
708                         nvhost_dbg_fn("assigned channel %d to %s",
709                                       slave_pdata->index,
710                                       dev_name(&pdata->slave->dev));
711                 }
712         }
713         nvhost_dbg_fn("max channels=%d num channels=%zd",
714                       NV_HOST1X_CHANNELS, num_channels);
715         if (num_channels > T124_NVHOST_NUMCHANNELS) {
716                 WARN(-ENODEV, "too many channel devices");
717                 return -ENODEV;
718         }
719
720         op->nvhost_dev.alloc_nvhost_channel = t124_alloc_nvhost_channel;
721         op->nvhost_dev.free_nvhost_channel = t124_free_nvhost_channel;
722
723         return 0;
724 }
725
726 static void t124_remove_support(struct nvhost_chip_support *op)
727 {
728         kfree(op->priv);
729         op->priv = 0;
730 }
731
732 #include "host1x/host1x_cdma.c"
733 #include "host1x/host1x_syncpt.c"
734 #include "host1x/host1x_intr.c"
735 #include "host1x/host1x_actmon_t124.c"
736
737 int nvhost_init_t124_support(struct nvhost_master *host,
738        struct nvhost_chip_support *op)
739 {
740         int i = 0;
741         int err;
742         struct t124 *t124 = 0;
743
744         for (i = NVSYNCPT_GK20A_BASE; i <= NVSYNCPT_GK20A_LAST; i++)
745                 s_syncpt_names[i] = "gk20a";
746
747         /* don't worry about cleaning up on failure... "remove" does it. */
748         err = nvhost_init_t124_channel_support(host, op);
749         if (err)
750                 return err;
751
752         op->cdma = host1x_cdma_ops;
753         op->push_buffer = host1x_pushbuffer_ops;
754
755         err = nvhost_init_t124_debug_support(op);
756         if (err)
757                 return err;
758
759         host->sync_aperture = host->aperture + HOST1X_CHANNEL_SYNC_REG_BASE;
760         op->syncpt = host1x_syncpt_ops;
761         op->intr = host1x_intr_ops;
762         op->actmon = host1x_actmon_ops;
763
764         err = nvhost_memmgr_init(op);
765         if (err)
766                 return err;
767
768         t124 = kzalloc(sizeof(struct t124), GFP_KERNEL);
769         if (!t124) {
770                 err = -ENOMEM;
771                 goto err;
772         }
773
774         t124->host = host;
775         op->priv = t124;
776         op->remove_support = t124_remove_support;
777
778         return 0;
779
780 err:
781         kfree(t124);
782
783         op->priv = 0;
784         op->remove_support = 0;
785         return err;
786 }