video: tegra: host: add DT support
[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-2013, 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
21 #include <linux/slab.h>
22 #include <linux/export.h>
23 #include <linux/module.h>
24 #include <linux/scatterlist.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/of.h>
27 #include <linux/of_device.h>
28 #include <linux/of_platform.h>
29 #include <mach/gpufuse.h>
30
31 #include "t20/t20.h"
32 #include "t30/t30.h"
33 #include "t114/t114.h"
34 #include "host1x/host1x01_hardware.h"
35 #include "nvhost_hwctx.h"
36 #include "dev.h"
37 #include "gr3d.h"
38 #include "gr3d_t20.h"
39 #include "gr3d_t30.h"
40 #include "gr3d_t114.h"
41 #include "scale3d_actmon.h"
42 #include "scale3d.h"
43 #include "bus_client.h"
44 #include "nvhost_channel.h"
45 #include "nvhost_memmgr.h"
46 #include "chip_support.h"
47 #include "pod_scaling.h"
48 #include "class_ids.h"
49
50 void nvhost_3dctx_restore_begin(struct host1x_hwctx_handler *p, u32 *ptr)
51 {
52         /* set class to host */
53         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
54                                         host1x_uclass_incr_syncpt_base_r(), 1);
55         /* increment sync point base */
56         ptr[1] = nvhost_class_host_incr_syncpt_base(p->waitbase,
57                         p->restore_incrs);
58         /* set class to 3D */
59         ptr[2] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0);
60         /* program PSEQ_QUAD_ID */
61         ptr[3] = nvhost_opcode_imm(AR3D_PSEQ_QUAD_ID, 0);
62 }
63
64 void nvhost_3dctx_restore_direct(u32 *ptr, u32 start_reg, u32 count)
65 {
66         ptr[0] = nvhost_opcode_incr(start_reg, count);
67 }
68
69 void nvhost_3dctx_restore_indirect(u32 *ptr, u32 offset_reg, u32 offset,
70                         u32 data_reg, u32 count)
71 {
72         ptr[0] = nvhost_opcode_imm(offset_reg, offset);
73         ptr[1] = nvhost_opcode_nonincr(data_reg, count);
74 }
75
76 void nvhost_3dctx_restore_end(struct host1x_hwctx_handler *p, u32 *ptr)
77 {
78         /* syncpt increment to track restore gather. */
79         ptr[0] = nvhost_opcode_imm_incr_syncpt(
80                         host1x_uclass_incr_syncpt_cond_op_done_v(), p->syncpt);
81 }
82
83 /*** ctx3d ***/
84 struct host1x_hwctx *nvhost_3dctx_alloc_common(struct host1x_hwctx_handler *p,
85                 struct nvhost_channel *ch, bool map_restore)
86 {
87         struct mem_mgr *memmgr = nvhost_get_host(ch->dev)->memmgr;
88         struct host1x_hwctx *ctx;
89
90         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
91         if (!ctx)
92                 return NULL;
93         ctx->restore = mem_op().alloc(memmgr, p->restore_size * 4, 32,
94                 map_restore ? mem_mgr_flag_write_combine
95                             : mem_mgr_flag_uncacheable);
96         if (IS_ERR_OR_NULL(ctx->restore))
97                 goto fail_alloc;
98
99         if (map_restore) {
100                 ctx->restore_virt = mem_op().mmap(ctx->restore);
101                 if (IS_ERR_OR_NULL(ctx->restore_virt))
102                         goto fail_mmap;
103         } else
104                 ctx->restore_virt = NULL;
105
106         ctx->restore_sgt = mem_op().pin(memmgr, ctx->restore);
107         if (IS_ERR_OR_NULL(ctx->restore_sgt))
108                 goto fail_pin;
109         ctx->restore_phys = sg_dma_address(ctx->restore_sgt->sgl);
110
111         kref_init(&ctx->hwctx.ref);
112         ctx->hwctx.h = &p->h;
113         ctx->hwctx.channel = ch;
114         ctx->hwctx.valid = false;
115         ctx->save_incrs = p->save_incrs;
116         ctx->save_thresh = p->save_thresh;
117         ctx->save_slots = p->save_slots;
118
119         ctx->restore_size = p->restore_size;
120         ctx->restore_incrs = p->restore_incrs;
121         return ctx;
122
123 fail_pin:
124         if (map_restore)
125                 mem_op().munmap(ctx->restore, ctx->restore_virt);
126 fail_mmap:
127         mem_op().put(memmgr, ctx->restore);
128 fail_alloc:
129         kfree(ctx);
130         return NULL;
131 }
132
133 void nvhost_3dctx_get(struct nvhost_hwctx *ctx)
134 {
135         kref_get(&ctx->ref);
136 }
137
138 void nvhost_3dctx_free(struct kref *ref)
139 {
140         struct nvhost_hwctx *nctx = container_of(ref, struct nvhost_hwctx, ref);
141         struct host1x_hwctx *ctx = to_host1x_hwctx(nctx);
142         struct mem_mgr *memmgr = nvhost_get_host(nctx->channel->dev)->memmgr;
143
144         if (ctx->restore_virt)
145                 mem_op().munmap(ctx->restore, ctx->restore_virt);
146
147         mem_op().unpin(memmgr, ctx->restore, ctx->restore_sgt);
148         mem_op().put(memmgr, ctx->restore);
149         kfree(ctx);
150 }
151
152 void nvhost_3dctx_put(struct nvhost_hwctx *ctx)
153 {
154         kref_put(&ctx->ref, nvhost_3dctx_free);
155 }
156
157 int nvhost_gr3d_prepare_power_off(struct platform_device *dev)
158 {
159         struct nvhost_device_data *pdata = platform_get_drvdata(dev);
160         return nvhost_channel_save_context(pdata->channel);
161 }
162
163 static struct of_device_id tegra_gr3d_of_match[] __devinitdata = {
164         { .compatible = "nvidia,tegra20-gr3d",
165                 .data = (struct nvhost_device_data *)&t20_gr3d_info },
166         { .compatible = "nvidia,tegra30-gr3d",
167                 .data = (struct nvhost_device_data *)&t30_gr3d_info },
168         { .compatible = "nvidia,tegra114-gr3d",
169                 .data = (struct nvhost_device_data *)&t11_gr3d_info },
170         { },
171 };
172 static int __devinit gr3d_probe(struct platform_device *dev)
173 {
174         int err = 0;
175         struct nvhost_device_data *pdata = NULL;
176
177         if (dev->dev.of_node) {
178                 const struct of_device_id *match;
179
180                 match = of_match_device(tegra_gr3d_of_match, &dev->dev);
181                 if (match)
182                         pdata = (struct nvhost_device_data *)match->data;
183         } else
184                 pdata = (struct nvhost_device_data *)dev->dev.platform_data;
185
186         WARN_ON(!pdata);
187         if (!pdata) {
188                 dev_info(&dev->dev, "no platform data\n");
189                 return -ENODATA;
190         }
191
192         pdata->pdev = dev;
193         platform_set_drvdata(dev, pdata);
194
195         err = nvhost_client_device_init(dev);
196         if (err)
197                 return err;
198
199         pm_runtime_use_autosuspend(&dev->dev);
200         pm_runtime_set_autosuspend_delay(&dev->dev, 100);
201         pm_runtime_enable(&dev->dev);
202
203         return 0;
204 }
205
206 static int __exit gr3d_remove(struct platform_device *dev)
207 {
208         /* Add clean-up */
209         return 0;
210 }
211
212 #ifdef CONFIG_PM
213 static int gr3d_suspend(struct platform_device *dev, pm_message_t state)
214 {
215         return nvhost_client_device_suspend(dev);
216 }
217
218 static int gr3d_resume(struct platform_device *dev)
219 {
220         dev_info(&dev->dev, "resuming\n");
221         return 0;
222 }
223 #endif
224
225 static struct platform_driver gr3d_driver = {
226         .probe = gr3d_probe,
227         .remove = __exit_p(gr3d_remove),
228 #ifdef CONFIG_PM
229         .suspend = gr3d_suspend,
230         .resume = gr3d_resume,
231 #endif
232         .driver = {
233                 .owner = THIS_MODULE,
234                 .name = "gr3d",
235 #ifdef CONFIG_OF
236                 .of_match_table = tegra_gr3d_of_match,
237 #endif
238         },
239 };
240
241 static int __init gr3d_init(void)
242 {
243         return platform_driver_register(&gr3d_driver);
244 }
245
246 static void __exit gr3d_exit(void)
247 {
248         platform_driver_unregister(&gr3d_driver);
249 }
250
251 module_init(gr3d_init);
252 module_exit(gr3d_exit);