diff options
Diffstat (limited to 'drivers/video/tegra/host/gr3d/gr3d.c')
-rw-r--r-- | drivers/video/tegra/host/gr3d/gr3d.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/drivers/video/tegra/host/gr3d/gr3d.c b/drivers/video/tegra/host/gr3d/gr3d.c new file mode 100644 index 00000000000..f387d54e585 --- /dev/null +++ b/drivers/video/tegra/host/gr3d/gr3d.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * drivers/video/tegra/host/gr3d/gr3d.c | ||
3 | * | ||
4 | * Tegra Graphics Host 3D | ||
5 | * | ||
6 | * Copyright (c) 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 <mach/nvmap.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | #include "t20/t20.h" | ||
25 | #include "host1x/host1x_channel.h" | ||
26 | #include "host1x/host1x_hardware.h" | ||
27 | #include "host1x/host1x_syncpt.h" | ||
28 | #include "nvhost_hwctx.h" | ||
29 | #include "dev.h" | ||
30 | #include "gr3d.h" | ||
31 | #include "bus_client.h" | ||
32 | |||
33 | #ifndef TEGRA_POWERGATE_3D1 | ||
34 | #define TEGRA_POWERGATE_3D1 -1 | ||
35 | #endif | ||
36 | |||
37 | void nvhost_3dctx_restore_begin(struct host1x_hwctx_handler *p, u32 *ptr) | ||
38 | { | ||
39 | /* set class to host */ | ||
40 | ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, | ||
41 | NV_CLASS_HOST_INCR_SYNCPT_BASE, 1); | ||
42 | /* increment sync point base */ | ||
43 | ptr[1] = nvhost_class_host_incr_syncpt_base(p->waitbase, | ||
44 | p->restore_incrs); | ||
45 | /* set class to 3D */ | ||
46 | ptr[2] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0); | ||
47 | /* program PSEQ_QUAD_ID */ | ||
48 | ptr[3] = nvhost_opcode_imm(AR3D_PSEQ_QUAD_ID, 0); | ||
49 | } | ||
50 | |||
51 | void nvhost_3dctx_restore_direct(u32 *ptr, u32 start_reg, u32 count) | ||
52 | { | ||
53 | ptr[0] = nvhost_opcode_incr(start_reg, count); | ||
54 | } | ||
55 | |||
56 | void nvhost_3dctx_restore_indirect(u32 *ptr, u32 offset_reg, u32 offset, | ||
57 | u32 data_reg, u32 count) | ||
58 | { | ||
59 | ptr[0] = nvhost_opcode_imm(offset_reg, offset); | ||
60 | ptr[1] = nvhost_opcode_nonincr(data_reg, count); | ||
61 | } | ||
62 | |||
63 | void nvhost_3dctx_restore_end(struct host1x_hwctx_handler *p, u32 *ptr) | ||
64 | { | ||
65 | /* syncpt increment to track restore gather. */ | ||
66 | ptr[0] = nvhost_opcode_imm_incr_syncpt( | ||
67 | NV_SYNCPT_OP_DONE, p->syncpt); | ||
68 | } | ||
69 | |||
70 | /*** ctx3d ***/ | ||
71 | |||
72 | struct host1x_hwctx *nvhost_3dctx_alloc_common(struct host1x_hwctx_handler *p, | ||
73 | struct nvhost_channel *ch, bool map_restore) | ||
74 | { | ||
75 | struct nvmap_client *nvmap = nvhost_get_host(ch->dev)->nvmap; | ||
76 | struct host1x_hwctx *ctx; | ||
77 | |||
78 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | ||
79 | if (!ctx) | ||
80 | return NULL; | ||
81 | ctx->restore = nvmap_alloc(nvmap, p->restore_size * 4, 32, | ||
82 | map_restore ? NVMAP_HANDLE_WRITE_COMBINE | ||
83 | : NVMAP_HANDLE_UNCACHEABLE, 0); | ||
84 | if (IS_ERR_OR_NULL(ctx->restore)) | ||
85 | goto fail; | ||
86 | |||
87 | if (map_restore) { | ||
88 | ctx->restore_virt = nvmap_mmap(ctx->restore); | ||
89 | if (!ctx->restore_virt) | ||
90 | goto fail; | ||
91 | } else | ||
92 | ctx->restore_virt = NULL; | ||
93 | |||
94 | kref_init(&ctx->hwctx.ref); | ||
95 | ctx->hwctx.h = &p->h; | ||
96 | ctx->hwctx.channel = ch; | ||
97 | ctx->hwctx.valid = false; | ||
98 | ctx->save_incrs = p->save_incrs; | ||
99 | ctx->save_thresh = p->save_thresh; | ||
100 | ctx->save_slots = p->save_slots; | ||
101 | ctx->restore_phys = nvmap_pin(nvmap, ctx->restore); | ||
102 | if (IS_ERR_VALUE(ctx->restore_phys)) | ||
103 | goto fail; | ||
104 | |||
105 | ctx->restore_size = p->restore_size; | ||
106 | ctx->restore_incrs = p->restore_incrs; | ||
107 | return ctx; | ||
108 | |||
109 | fail: | ||
110 | if (map_restore && ctx->restore_virt) { | ||
111 | nvmap_munmap(ctx->restore, ctx->restore_virt); | ||
112 | ctx->restore_virt = NULL; | ||
113 | } | ||
114 | nvmap_free(nvmap, ctx->restore); | ||
115 | ctx->restore = NULL; | ||
116 | kfree(ctx); | ||
117 | return NULL; | ||
118 | } | ||
119 | |||
120 | void nvhost_3dctx_get(struct nvhost_hwctx *ctx) | ||
121 | { | ||
122 | kref_get(&ctx->ref); | ||
123 | } | ||
124 | |||
125 | void nvhost_3dctx_free(struct kref *ref) | ||
126 | { | ||
127 | struct nvhost_hwctx *nctx = container_of(ref, struct nvhost_hwctx, ref); | ||
128 | struct host1x_hwctx *ctx = to_host1x_hwctx(nctx); | ||
129 | struct nvmap_client *nvmap = | ||
130 | nvhost_get_host(nctx->channel->dev)->nvmap; | ||
131 | |||
132 | if (ctx->restore_virt) { | ||
133 | nvmap_munmap(ctx->restore, ctx->restore_virt); | ||
134 | ctx->restore_virt = NULL; | ||
135 | } | ||
136 | nvmap_unpin(nvmap, ctx->restore); | ||
137 | ctx->restore_phys = 0; | ||
138 | nvmap_free(nvmap, ctx->restore); | ||
139 | ctx->restore = NULL; | ||
140 | kfree(ctx); | ||
141 | } | ||
142 | |||
143 | void nvhost_3dctx_put(struct nvhost_hwctx *ctx) | ||
144 | { | ||
145 | kref_put(&ctx->ref, nvhost_3dctx_free); | ||
146 | } | ||
147 | |||
148 | int nvhost_gr3d_prepare_power_off(struct nvhost_device *dev) | ||
149 | { | ||
150 | return host1x_save_context(dev, NVSYNCPT_3D); | ||
151 | } | ||
152 | |||
153 | static int __devinit gr3d_probe(struct nvhost_device *dev) | ||
154 | { | ||
155 | return nvhost_client_device_init(dev); | ||
156 | } | ||
157 | |||
158 | static int __exit gr3d_remove(struct nvhost_device *dev) | ||
159 | { | ||
160 | /* Add clean-up */ | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int gr3d_suspend(struct nvhost_device *dev, pm_message_t state) | ||
165 | { | ||
166 | return nvhost_client_device_suspend(dev); | ||
167 | } | ||
168 | |||
169 | static int gr3d_resume(struct nvhost_device *dev) | ||
170 | { | ||
171 | dev_info(&dev->dev, "resuming\n"); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | struct nvhost_device *gr3d_device; | ||
176 | |||
177 | static struct nvhost_driver gr3d_driver = { | ||
178 | .probe = gr3d_probe, | ||
179 | .remove = __exit_p(gr3d_remove), | ||
180 | #ifdef CONFIG_PM | ||
181 | .suspend = gr3d_suspend, | ||
182 | .resume = gr3d_resume, | ||
183 | #endif | ||
184 | .driver = { | ||
185 | .owner = THIS_MODULE, | ||
186 | .name = "gr3d", | ||
187 | } | ||
188 | }; | ||
189 | |||
190 | static int __init gr3d_init(void) | ||
191 | { | ||
192 | int err; | ||
193 | |||
194 | gr3d_device = nvhost_get_device("gr3d"); | ||
195 | if (!gr3d_device) | ||
196 | return -ENXIO; | ||
197 | |||
198 | err = nvhost_device_register(gr3d_device); | ||
199 | if (err) | ||
200 | return err; | ||
201 | |||
202 | return nvhost_driver_register(&gr3d_driver); | ||
203 | } | ||
204 | |||
205 | static void __exit gr3d_exit(void) | ||
206 | { | ||
207 | nvhost_driver_unregister(&gr3d_driver); | ||
208 | } | ||
209 | |||
210 | module_init(gr3d_init); | ||
211 | module_exit(gr3d_exit); | ||