aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/tegra/host/gr3d/gr3d.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra/host/gr3d/gr3d.c')
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d.c211
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
37void 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
51void nvhost_3dctx_restore_direct(u32 *ptr, u32 start_reg, u32 count)
52{
53 ptr[0] = nvhost_opcode_incr(start_reg, count);
54}
55
56void 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
63void 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
72struct 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
109fail:
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
120void nvhost_3dctx_get(struct nvhost_hwctx *ctx)
121{
122 kref_get(&ctx->ref);
123}
124
125void 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
143void nvhost_3dctx_put(struct nvhost_hwctx *ctx)
144{
145 kref_put(&ctx->ref, nvhost_3dctx_free);
146}
147
148int nvhost_gr3d_prepare_power_off(struct nvhost_device *dev)
149{
150 return host1x_save_context(dev, NVSYNCPT_3D);
151}
152
153static int __devinit gr3d_probe(struct nvhost_device *dev)
154{
155 return nvhost_client_device_init(dev);
156}
157
158static int __exit gr3d_remove(struct nvhost_device *dev)
159{
160 /* Add clean-up */
161 return 0;
162}
163
164static int gr3d_suspend(struct nvhost_device *dev, pm_message_t state)
165{
166 return nvhost_client_device_suspend(dev);
167}
168
169static int gr3d_resume(struct nvhost_device *dev)
170{
171 dev_info(&dev->dev, "resuming\n");
172 return 0;
173}
174
175struct nvhost_device *gr3d_device;
176
177static 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
190static 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
205static void __exit gr3d_exit(void)
206{
207 nvhost_driver_unregister(&gr3d_driver);
208}
209
210module_init(gr3d_init);
211module_exit(gr3d_exit);