video: tegra: host: Remove version from dev name
[linux-2.6.git] / drivers / video / tegra / host / gr3d / gr3d.c
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 <linux/slab.h>
22 #include <mach/gpufuse.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 "gr3d_t20.h"
32 #include "gr3d_t30.h"
33 #include "scale3d.h"
34 #include "bus_client.h"
35 #include "nvhost_channel.h"
36 #include "nvhost_memmgr.h"
37 #include "chip_support.h"
38
39 void nvhost_3dctx_restore_begin(struct host1x_hwctx_handler *p, u32 *ptr)
40 {
41         /* set class to host */
42         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
43                                         host1x_uclass_incr_syncpt_base_r(), 1);
44         /* increment sync point base */
45         ptr[1] = nvhost_class_host_incr_syncpt_base(p->waitbase,
46                         p->restore_incrs);
47         /* set class to 3D */
48         ptr[2] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0);
49         /* program PSEQ_QUAD_ID */
50         ptr[3] = nvhost_opcode_imm(AR3D_PSEQ_QUAD_ID, 0);
51 }
52
53 void nvhost_3dctx_restore_direct(u32 *ptr, u32 start_reg, u32 count)
54 {
55         ptr[0] = nvhost_opcode_incr(start_reg, count);
56 }
57
58 void nvhost_3dctx_restore_indirect(u32 *ptr, u32 offset_reg, u32 offset,
59                         u32 data_reg, u32 count)
60 {
61         ptr[0] = nvhost_opcode_imm(offset_reg, offset);
62         ptr[1] = nvhost_opcode_nonincr(data_reg, count);
63 }
64
65 void nvhost_3dctx_restore_end(struct host1x_hwctx_handler *p, u32 *ptr)
66 {
67         /* syncpt increment to track restore gather. */
68         ptr[0] = nvhost_opcode_imm_incr_syncpt(
69                         host1x_uclass_incr_syncpt_cond_op_done_v(), p->syncpt);
70 }
71
72 /*** ctx3d ***/
73 struct host1x_hwctx *nvhost_3dctx_alloc_common(struct host1x_hwctx_handler *p,
74                 struct nvhost_channel *ch, bool map_restore)
75 {
76         struct mem_mgr *memmgr = nvhost_get_host(ch->dev)->memmgr;
77         struct host1x_hwctx *ctx;
78
79         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
80         if (!ctx)
81                 return NULL;
82         ctx->restore = mem_op().alloc(memmgr, p->restore_size * 4, 32,
83                 map_restore ? mem_mgr_flag_write_combine
84                             : mem_mgr_flag_uncacheable);
85         if (IS_ERR_OR_NULL(ctx->restore))
86                 goto fail;
87
88         if (map_restore) {
89                 ctx->restore_virt = mem_op().mmap(ctx->restore);
90                 if (!ctx->restore_virt)
91                         goto fail;
92         } else
93                 ctx->restore_virt = NULL;
94
95         kref_init(&ctx->hwctx.ref);
96         ctx->hwctx.h = &p->h;
97         ctx->hwctx.channel = ch;
98         ctx->hwctx.valid = false;
99         ctx->save_incrs = p->save_incrs;
100         ctx->save_thresh = p->save_thresh;
101         ctx->save_slots = p->save_slots;
102         ctx->restore_phys = mem_op().pin(memmgr, ctx->restore);
103         if (IS_ERR_VALUE(ctx->restore_phys))
104                 goto fail;
105
106         ctx->restore_size = p->restore_size;
107         ctx->restore_incrs = p->restore_incrs;
108         return ctx;
109
110 fail:
111         if (map_restore && ctx->restore_virt) {
112                 mem_op().munmap(ctx->restore, ctx->restore_virt);
113                 ctx->restore_virt = NULL;
114         }
115         mem_op().put(memmgr, ctx->restore);
116         ctx->restore = NULL;
117         kfree(ctx);
118         return NULL;
119 }
120
121 void nvhost_3dctx_get(struct nvhost_hwctx *ctx)
122 {
123         kref_get(&ctx->ref);
124 }
125
126 void nvhost_3dctx_free(struct kref *ref)
127 {
128         struct nvhost_hwctx *nctx = container_of(ref, struct nvhost_hwctx, ref);
129         struct host1x_hwctx *ctx = to_host1x_hwctx(nctx);
130         struct mem_mgr *memmgr = nvhost_get_host(nctx->channel->dev)->memmgr;
131
132         if (ctx->restore_virt) {
133                 mem_op().munmap(ctx->restore, ctx->restore_virt);
134                 ctx->restore_virt = NULL;
135         }
136         mem_op().unpin(memmgr, ctx->restore);
137         ctx->restore_phys = 0;
138         mem_op().put(memmgr, 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         struct nvhost_hwctx *cur_ctx = dev->channel->cur_ctx;
151         int err = 0;
152         if (cur_ctx)
153                 err = host1x_save_context(dev,
154                         to_host1x_hwctx_handler(cur_ctx->h)->syncpt);
155
156         return err;
157 }
158
159 enum gr3d_ip_ver {
160         gr3d_01 = 1,
161         gr3d_02,
162 };
163
164 struct gr3d_desc {
165         void (*finalize_poweron)(struct nvhost_device *dev);
166         void (*busy)(struct nvhost_device *);
167         void (*idle)(struct nvhost_device *);
168         void (*suspend_ndev)(struct nvhost_device *);
169         void (*init)(struct nvhost_device *dev);
170         void (*deinit)(struct nvhost_device *dev);
171         int (*prepare_poweroff)(struct nvhost_device *dev);
172         struct nvhost_hwctx_handler *(*alloc_hwctx_handler)(u32 syncpt,
173                         u32 waitbase, struct nvhost_channel *ch);
174 };
175
176 static const struct gr3d_desc gr3d[] = {
177         [gr3d_01] = {
178                 .finalize_poweron = NULL,
179                 .busy = NULL,
180                 .idle = NULL,
181                 .suspend_ndev = NULL,
182                 .init = NULL,
183                 .deinit = NULL,
184                 .prepare_poweroff = nvhost_gr3d_prepare_power_off,
185                 .alloc_hwctx_handler = nvhost_gr3d_t20_ctxhandler_init,
186         },
187         [gr3d_02] = {
188                 .finalize_poweron = NULL,
189                 .busy = nvhost_scale3d_notify_busy,
190                 .idle = nvhost_scale3d_notify_idle,
191                 .suspend_ndev = nvhost_scale3d_suspend,
192                 .init = nvhost_scale3d_init,
193                 .deinit = nvhost_scale3d_deinit,
194                 .prepare_poweroff = nvhost_gr3d_prepare_power_off,
195                 .alloc_hwctx_handler = nvhost_gr3d_t30_ctxhandler_init,
196         },
197 };
198
199 static struct nvhost_device_id gr3d_id[] = {
200         { "gr3d", gr3d_01 },
201         { "gr3d", gr3d_02 },
202         { },
203 };
204
205 MODULE_DEVICE_TABLE(nvhost, gr3d_id);
206
207 static int __devinit gr3d_probe(struct nvhost_device *dev,
208         struct nvhost_device_id *id_table)
209 {
210         int index = 0;
211         struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
212
213         index = id_table->version;
214
215         drv->finalize_poweron           = gr3d[index].finalize_poweron;
216         drv->busy                       = gr3d[index].busy;
217         drv->idle                       = gr3d[index].idle;
218         drv->suspend_ndev               = gr3d[index].suspend_ndev;
219         drv->init                       = gr3d[index].init;
220         drv->deinit                     = gr3d[index].deinit;
221         drv->prepare_poweroff           = gr3d[index].prepare_poweroff;
222         drv->alloc_hwctx_handler        = gr3d[index].alloc_hwctx_handler;
223
224         nvhost_set_register_sets(tegra_gpu_register_sets());
225         return nvhost_client_device_init(dev);
226 }
227
228 static int __exit gr3d_remove(struct nvhost_device *dev)
229 {
230         /* Add clean-up */
231         return 0;
232 }
233
234 static int gr3d_suspend(struct nvhost_device *dev, pm_message_t state)
235 {
236         return nvhost_client_device_suspend(dev);
237 }
238
239 static int gr3d_resume(struct nvhost_device *dev)
240 {
241         dev_info(&dev->dev, "resuming\n");
242         return 0;
243 }
244
245 static struct nvhost_driver gr3d_driver = {
246         .probe = gr3d_probe,
247         .remove = __exit_p(gr3d_remove),
248 #ifdef CONFIG_PM
249         .suspend = gr3d_suspend,
250         .resume = gr3d_resume,
251 #endif
252         .driver = {
253                 .owner = THIS_MODULE,
254                 .name = "gr3d",
255         },
256         .id_table = gr3d_id,
257 };
258
259 static int __init gr3d_init(void)
260 {
261         return nvhost_driver_register(&gr3d_driver);
262 }
263
264 static void __exit gr3d_exit(void)
265 {
266         nvhost_driver_unregister(&gr3d_driver);
267 }
268
269 module_init(gr3d_init);
270 module_exit(gr3d_exit);