d2294b3340adf4fcb9b7870661dfaceca3ec5656
[linux-2.6.git] / drivers / video / tegra / host / mpe / mpe.c
1 /*
2  * drivers/video/tegra/host/mpe/mpe.c
3  *
4  * Tegra Graphics Host MPE
5  *
6  * Copyright (c) 2010-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 "nvhost_hwctx.h"
22 #include "nvhost_channel.h"
23 #include "dev.h"
24 #include "host1x/host1x_hardware.h"
25 #include "host1x/host1x_channel.h"
26 #include "host1x/host1x_syncpt.h"
27 #include "host1x/host1x_hwctx.h"
28 #include "t20/t20.h"
29 #include "chip_support.h"
30 #include "nvhost_memmgr.h"
31
32 #include <linux/slab.h>
33 #include <linux/export.h>
34 #include <linux/resource.h>
35 #include <linux/module.h>
36
37 #include <mach/iomap.h>
38 #include <mach/hardware.h>
39
40 #include "bus_client.h"
41
42 enum {
43         HWCTX_REGINFO_NORMAL = 0,
44         HWCTX_REGINFO_STASH,
45         HWCTX_REGINFO_CALCULATE,
46         HWCTX_REGINFO_WRITEBACK
47 };
48
49 const struct hwctx_reginfo ctxsave_regs_mpe[] = {
50         HWCTX_REGINFO(0x124,  1, STASH),
51         HWCTX_REGINFO(0x123,  1, STASH),
52         HWCTX_REGINFO(0x103,  1, STASH),
53         HWCTX_REGINFO(0x074,  1, STASH),
54         HWCTX_REGINFO(0x021,  1, NORMAL),
55         HWCTX_REGINFO(0x020,  1, STASH),
56         HWCTX_REGINFO(0x024,  2, NORMAL),
57         HWCTX_REGINFO(0x0e6,  1, NORMAL),
58         HWCTX_REGINFO(0x3fc,  1, NORMAL),
59         HWCTX_REGINFO(0x3d0,  1, NORMAL),
60         HWCTX_REGINFO(0x3d4,  1, NORMAL),
61         HWCTX_REGINFO(0x013,  1, NORMAL),
62         HWCTX_REGINFO(0x022,  1, NORMAL),
63         HWCTX_REGINFO(0x030,  4, NORMAL),
64         HWCTX_REGINFO(0x023,  1, NORMAL),
65         HWCTX_REGINFO(0x070,  1, NORMAL),
66         HWCTX_REGINFO(0x0a0,  9, NORMAL),
67         HWCTX_REGINFO(0x071,  1, NORMAL),
68         HWCTX_REGINFO(0x100,  4, NORMAL),
69         HWCTX_REGINFO(0x104,  2, NORMAL),
70         HWCTX_REGINFO(0x108,  9, NORMAL),
71         HWCTX_REGINFO(0x112,  2, NORMAL),
72         HWCTX_REGINFO(0x114,  1, STASH),
73         HWCTX_REGINFO(0x014,  1, NORMAL),
74         HWCTX_REGINFO(0x072,  1, NORMAL),
75         HWCTX_REGINFO(0x200,  1, NORMAL),
76         HWCTX_REGINFO(0x0d1,  1, NORMAL),
77         HWCTX_REGINFO(0x0d0,  1, NORMAL),
78         HWCTX_REGINFO(0x0c0,  1, NORMAL),
79         HWCTX_REGINFO(0x0c3,  2, NORMAL),
80         HWCTX_REGINFO(0x0d2,  1, NORMAL),
81         HWCTX_REGINFO(0x0d8,  1, NORMAL),
82         HWCTX_REGINFO(0x0e0,  2, NORMAL),
83         HWCTX_REGINFO(0x07f,  2, NORMAL),
84         HWCTX_REGINFO(0x084,  8, NORMAL),
85         HWCTX_REGINFO(0x0d3,  1, NORMAL),
86         HWCTX_REGINFO(0x040, 13, NORMAL),
87         HWCTX_REGINFO(0x050,  6, NORMAL),
88         HWCTX_REGINFO(0x058,  1, NORMAL),
89         HWCTX_REGINFO(0x057,  1, NORMAL),
90         HWCTX_REGINFO(0x111,  1, NORMAL),
91         HWCTX_REGINFO(0x130,  3, NORMAL),
92         HWCTX_REGINFO(0x201,  1, NORMAL),
93         HWCTX_REGINFO(0x068,  2, NORMAL),
94         HWCTX_REGINFO(0x08c,  1, NORMAL),
95         HWCTX_REGINFO(0x0cf,  1, NORMAL),
96         HWCTX_REGINFO(0x082,  2, NORMAL),
97         HWCTX_REGINFO(0x075,  1, NORMAL),
98         HWCTX_REGINFO(0x0e8,  1, NORMAL),
99         HWCTX_REGINFO(0x056,  1, NORMAL),
100         HWCTX_REGINFO(0x057,  1, NORMAL),
101         HWCTX_REGINFO(0x073,  1, CALCULATE),
102         HWCTX_REGINFO(0x074,  1, NORMAL),
103         HWCTX_REGINFO(0x075,  1, NORMAL),
104         HWCTX_REGINFO(0x076,  1, STASH),
105         HWCTX_REGINFO(0x11a,  9, NORMAL),
106         HWCTX_REGINFO(0x123,  1, NORMAL),
107         HWCTX_REGINFO(0x124,  1, NORMAL),
108         HWCTX_REGINFO(0x12a,  5, NORMAL),
109         HWCTX_REGINFO(0x12f,  1, STASH),
110         HWCTX_REGINFO(0x125,  2, NORMAL),
111         HWCTX_REGINFO(0x034,  1, NORMAL),
112         HWCTX_REGINFO(0x133,  2, NORMAL),
113         HWCTX_REGINFO(0x127,  1, NORMAL),
114         HWCTX_REGINFO(0x106,  1, WRITEBACK),
115         HWCTX_REGINFO(0x107,  1, WRITEBACK)
116 };
117
118 #define NR_STASHES 8
119 #define NR_WRITEBACKS 2
120
121 #define RC_RAM_LOAD_CMD 0x115
122 #define RC_RAM_LOAD_DATA 0x116
123 #define RC_RAM_READ_CMD 0x128
124 #define RC_RAM_READ_DATA 0x129
125 #define RC_RAM_SIZE 692
126
127 #define IRFR_RAM_LOAD_CMD 0xc5
128 #define IRFR_RAM_LOAD_DATA 0xc6
129 #define IRFR_RAM_READ_CMD 0xcd
130 #define IRFR_RAM_READ_DATA 0xce
131 #define IRFR_RAM_SIZE 408
132
133 struct mpe_save_info {
134         u32 in[NR_STASHES];
135         u32 out[NR_WRITEBACKS];
136         unsigned in_pos;
137         unsigned out_pos;
138         u32 h264_mode;
139 };
140
141 /*** restore ***/
142
143 static unsigned int restore_size;
144
145 static void restore_begin(struct host1x_hwctx_handler *h, u32 *ptr)
146 {
147         /* set class to host */
148         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
149                                         NV_CLASS_HOST_INCR_SYNCPT_BASE, 1);
150         /* increment sync point base */
151         ptr[1] = nvhost_class_host_incr_syncpt_base(h->waitbase, 1);
152         /* set class to MPE */
153         ptr[2] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0);
154 }
155 #define RESTORE_BEGIN_SIZE 3
156
157 static void restore_ram(u32 *ptr, unsigned words,
158                         unsigned cmd_reg, unsigned data_reg)
159 {
160         ptr[0] = nvhost_opcode_imm(cmd_reg, words);
161         ptr[1] = nvhost_opcode_nonincr(data_reg, words);
162 }
163 #define RESTORE_RAM_SIZE 2
164
165 static void restore_end(struct host1x_hwctx_handler *h, u32 *ptr)
166 {
167         /* syncpt increment to track restore gather. */
168         ptr[0] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE,
169                         h->syncpt);
170 }
171 #define RESTORE_END_SIZE 1
172
173 static u32 *setup_restore_regs(u32 *ptr,
174                         const struct hwctx_reginfo *regs,
175                         unsigned int nr_regs)
176 {
177         const struct hwctx_reginfo *rend = regs + nr_regs;
178
179         for ( ; regs != rend; ++regs) {
180                 u32 offset = regs->offset;
181                 u32 count = regs->count;
182                 *ptr++ = nvhost_opcode_incr(offset, count);
183                 ptr += count;
184         }
185         return ptr;
186 }
187
188 static u32 *setup_restore_ram(u32 *ptr, unsigned words,
189                         unsigned cmd_reg, unsigned data_reg)
190 {
191         restore_ram(ptr, words, cmd_reg, data_reg);
192         return ptr + (RESTORE_RAM_SIZE + words);
193 }
194
195 static void setup_restore(struct host1x_hwctx_handler *h, u32 *ptr)
196 {
197         restore_begin(h, ptr);
198         ptr += RESTORE_BEGIN_SIZE;
199
200         ptr = setup_restore_regs(ptr, ctxsave_regs_mpe,
201                                 ARRAY_SIZE(ctxsave_regs_mpe));
202
203         ptr = setup_restore_ram(ptr, RC_RAM_SIZE,
204                         RC_RAM_LOAD_CMD, RC_RAM_LOAD_DATA);
205
206         ptr = setup_restore_ram(ptr, IRFR_RAM_SIZE,
207                         IRFR_RAM_LOAD_CMD, IRFR_RAM_LOAD_DATA);
208
209         restore_end(h, ptr);
210
211         wmb();
212 }
213
214 /*** save ***/
215
216 struct save_info {
217         u32 *ptr;
218         unsigned int save_count;
219         unsigned int restore_count;
220 };
221
222 static void __init save_begin(struct host1x_hwctx_handler *h, u32 *ptr)
223 {
224         /* MPE: when done, increment syncpt to base+1 */
225         ptr[0] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0);
226         ptr[1] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE, h->syncpt);
227         /* host: wait for syncpt base+1 */
228         ptr[2] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
229                                         NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1);
230         ptr[3] = nvhost_class_host_wait_syncpt_base(h->syncpt, h->waitbase, 1);
231         /* host: signal context read thread to start reading */
232         ptr[4] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_IMMEDIATE, h->syncpt);
233 }
234 #define SAVE_BEGIN_SIZE 5
235
236 static void __init save_direct(u32 *ptr, u32 start_reg, u32 count)
237 {
238         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
239                                         NV_CLASS_HOST_INDOFF, 1);
240         ptr[1] = nvhost_class_host_indoff_reg_read(NV_HOST_MODULE_MPE,
241                                                 start_reg, true);
242         ptr[2] = nvhost_opcode_nonincr(NV_CLASS_HOST_INDDATA, count);
243 }
244 #define SAVE_DIRECT_SIZE 3
245
246 static void __init save_set_ram_cmd(u32 *ptr, u32 cmd_reg, u32 count)
247 {
248         ptr[0] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID,
249                                         cmd_reg, 1);
250         ptr[1] = count;
251 }
252 #define SAVE_SET_RAM_CMD_SIZE 2
253
254 static void __init save_read_ram_data_nasty(u32 *ptr, u32 data_reg)
255 {
256         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
257                                         NV_CLASS_HOST_INDOFF, 1);
258         ptr[1] = nvhost_class_host_indoff_reg_read(NV_HOST_MODULE_MPE,
259                                                 data_reg, false);
260         ptr[2] = nvhost_opcode_imm(NV_CLASS_HOST_INDDATA, 0);
261         /* write junk data to avoid 'cached problem with register memory' */
262         ptr[3] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID,
263                                         data_reg, 1);
264         ptr[4] = 0x99;
265 }
266 #define SAVE_READ_RAM_DATA_NASTY_SIZE 5
267
268 static void __init save_end(struct host1x_hwctx_handler *h, u32 *ptr)
269 {
270         /* Wait for context read service to finish (cpu incr 3) */
271         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
272                                         NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1);
273         ptr[1] = nvhost_class_host_wait_syncpt_base(h->syncpt, h->waitbase, 3);
274         /* Advance syncpoint base */
275         ptr[2] = nvhost_opcode_nonincr(NV_CLASS_HOST_INCR_SYNCPT_BASE, 1);
276         ptr[3] = nvhost_class_host_incr_syncpt_base(h->waitbase, 3);
277         /* set class back to the unit */
278         ptr[4] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0);
279 }
280 #define SAVE_END_SIZE 5
281
282 static void __init setup_save_regs(struct save_info *info,
283                         const struct hwctx_reginfo *regs,
284                         unsigned int nr_regs)
285 {
286         const struct hwctx_reginfo *rend = regs + nr_regs;
287         u32 *ptr = info->ptr;
288         unsigned int save_count = info->save_count;
289         unsigned int restore_count = info->restore_count;
290
291         for ( ; regs != rend; ++regs) {
292                 u32 offset = regs->offset;
293                 u32 count = regs->count;
294                 if (regs->type != HWCTX_REGINFO_WRITEBACK) {
295                         if (ptr) {
296                                 save_direct(ptr, offset, count);
297                                 ptr += SAVE_DIRECT_SIZE;
298                                 memset(ptr, 0, count * 4);
299                                 ptr += count;
300                         }
301                         save_count += (SAVE_DIRECT_SIZE + count);
302                 }
303                 restore_count += (1 + count);
304         }
305
306         info->ptr = ptr;
307         info->save_count = save_count;
308         info->restore_count = restore_count;
309 }
310
311 static void __init setup_save_ram_nasty(struct save_info *info, unsigned words,
312                                         unsigned cmd_reg, unsigned data_reg)
313 {
314         u32 *ptr = info->ptr;
315         unsigned int save_count = info->save_count;
316         unsigned int restore_count = info->restore_count;
317         unsigned i;
318
319         if (ptr) {
320                 save_set_ram_cmd(ptr, cmd_reg, words);
321                 ptr += SAVE_SET_RAM_CMD_SIZE;
322                 for (i = words; i; --i) {
323                         save_read_ram_data_nasty(ptr, data_reg);
324                         ptr += SAVE_READ_RAM_DATA_NASTY_SIZE;
325                 }
326         }
327
328         save_count += SAVE_SET_RAM_CMD_SIZE;
329         save_count += words * SAVE_READ_RAM_DATA_NASTY_SIZE;
330         restore_count += (RESTORE_RAM_SIZE + words);
331
332         info->ptr = ptr;
333         info->save_count = save_count;
334         info->restore_count = restore_count;
335 }
336
337 static void __init setup_save(struct host1x_hwctx_handler *h, u32 *ptr)
338 {
339         struct save_info info = {
340                 ptr,
341                 SAVE_BEGIN_SIZE,
342                 RESTORE_BEGIN_SIZE
343         };
344
345         if (info.ptr) {
346                 save_begin(h, info.ptr);
347                 info.ptr += SAVE_BEGIN_SIZE;
348         }
349
350         setup_save_regs(&info, ctxsave_regs_mpe,
351                         ARRAY_SIZE(ctxsave_regs_mpe));
352
353         setup_save_ram_nasty(&info, RC_RAM_SIZE,
354                         RC_RAM_READ_CMD, RC_RAM_READ_DATA);
355
356         setup_save_ram_nasty(&info, IRFR_RAM_SIZE,
357                         IRFR_RAM_READ_CMD, IRFR_RAM_READ_DATA);
358
359         if (info.ptr) {
360                 save_end(h, info.ptr);
361                 info.ptr += SAVE_END_SIZE;
362         }
363
364         wmb();
365
366         h->save_size = info.save_count + SAVE_END_SIZE;
367         restore_size = info.restore_count + RESTORE_END_SIZE;
368 }
369
370 static u32 calculate_mpe(u32 word, struct mpe_save_info *msi)
371 {
372         u32 buffer_full_read = msi->in[0] & 0x01ffffff;
373         u32 byte_len = msi->in[1];
374         u32 drain = (msi->in[2] >> 2) & 0x007fffff;
375         u32 rep_frame = msi->in[3] & 0x0000ffff;
376         u32 h264_mode = (msi->in[4] >> 11) & 1;
377         int new_buffer_full;
378
379         if (h264_mode)
380                 byte_len >>= 3;
381         new_buffer_full = buffer_full_read + byte_len - (drain * 4);
382         msi->out[0] = max(0, new_buffer_full);
383         msi->out[1] = rep_frame;
384         if (rep_frame == 0)
385                 word &= 0xffff0000;
386         return word;
387 }
388
389 static u32 *save_regs(u32 *ptr, unsigned int *pending,
390                 struct nvhost_channel *channel,
391                 const struct hwctx_reginfo *regs,
392                 unsigned int nr_regs,
393                 struct mpe_save_info *msi)
394 {
395         const struct hwctx_reginfo *rend = regs + nr_regs;
396
397         for ( ; regs != rend; ++regs) {
398                 u32 count = regs->count;
399                 ++ptr; /* restore incr */
400                 if (regs->type == HWCTX_REGINFO_NORMAL) {
401                         host1x_drain_read_fifo(channel->aperture,
402                                                 ptr, count, pending);
403                         ptr += count;
404                 } else {
405                         u32 word;
406                         if (regs->type == HWCTX_REGINFO_WRITEBACK) {
407                                 BUG_ON(msi->out_pos >= NR_WRITEBACKS);
408                                 word = msi->out[msi->out_pos++];
409                         } else {
410                                 host1x_drain_read_fifo(channel->aperture,
411                                                         &word, 1, pending);
412                                 if (regs->type == HWCTX_REGINFO_STASH) {
413                                         BUG_ON(msi->in_pos >= NR_STASHES);
414                                         msi->in[msi->in_pos++] = word;
415                                 } else {
416                                         word = calculate_mpe(word, msi);
417                                 }
418                         }
419                         *ptr++ = word;
420                 }
421         }
422         return ptr;
423 }
424
425 static u32 *save_ram(u32 *ptr, unsigned int *pending,
426                 struct nvhost_channel *channel,
427                 unsigned words, unsigned cmd_reg, unsigned data_reg)
428 {
429         int err = 0;
430         ptr += RESTORE_RAM_SIZE;
431         err = host1x_drain_read_fifo(channel->aperture, ptr, words, pending);
432         WARN_ON(err);
433         return ptr + words;
434 }
435
436 /*** ctxmpe ***/
437
438 static struct nvhost_hwctx *ctxmpe_alloc(struct nvhost_hwctx_handler *h,
439                 struct nvhost_channel *ch)
440 {
441         struct mem_mgr *memmgr = nvhost_get_host(ch->dev)->memmgr;
442         struct host1x_hwctx_handler *p = to_host1x_hwctx_handler(h);
443         struct host1x_hwctx *ctx;
444
445         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
446         if (!ctx)
447                 return NULL;
448         ctx->restore = mem_op().alloc(memmgr, restore_size * 4, 32,
449                                 mem_mgr_flag_write_combine);
450         if (IS_ERR_OR_NULL(ctx->restore)) {
451                 kfree(ctx);
452                 return NULL;
453         }
454
455         ctx->restore_virt = mem_op().mmap(ctx->restore);
456         if (!ctx->restore_virt) {
457                 mem_op().put(memmgr, ctx->restore);
458                 kfree(ctx);
459                 return NULL;
460         }
461
462         kref_init(&ctx->hwctx.ref);
463         ctx->hwctx.h = &p->h;
464         ctx->hwctx.channel = ch;
465         ctx->hwctx.valid = false;
466         ctx->save_incrs = 3;
467         ctx->save_thresh = 2;
468         ctx->save_slots = p->save_slots;
469         ctx->restore_phys = mem_op().pin(memmgr, ctx->restore);
470         ctx->restore_size = restore_size;
471         ctx->restore_incrs = 1;
472
473         setup_restore(p, ctx->restore_virt);
474
475         return &ctx->hwctx;
476 }
477
478 static void ctxmpe_get(struct nvhost_hwctx *ctx)
479 {
480         kref_get(&ctx->ref);
481 }
482
483 static void ctxmpe_free(struct kref *ref)
484 {
485         struct nvhost_hwctx *nctx = container_of(ref, struct nvhost_hwctx, ref);
486         struct host1x_hwctx *ctx = to_host1x_hwctx(nctx);
487         struct mem_mgr *memmgr = nvhost_get_host(nctx->channel->dev)->memmgr;
488
489         if (ctx->restore_virt)
490                 mem_op().munmap(ctx->restore, ctx->restore_virt);
491         mem_op().unpin(memmgr, ctx->restore);
492         mem_op().put(memmgr, ctx->restore);
493         kfree(ctx);
494 }
495
496 static void ctxmpe_put(struct nvhost_hwctx *ctx)
497 {
498         kref_put(&ctx->ref, ctxmpe_free);
499 }
500
501 static void ctxmpe_save_push(struct nvhost_hwctx *nctx,
502                 struct nvhost_cdma *cdma)
503 {
504         struct host1x_hwctx *ctx = to_host1x_hwctx(nctx);
505         struct host1x_hwctx_handler *h = host1x_hwctx_handler(ctx);
506         nvhost_cdma_push_gather(cdma,
507                         nvhost_get_host(nctx->channel->dev)->memmgr,
508                         h->save_buf,
509                         0,
510                         nvhost_opcode_gather(h->save_size),
511                         h->save_phys);
512 }
513
514 static void ctxmpe_save_service(struct nvhost_hwctx *nctx)
515 {
516         struct host1x_hwctx *ctx = to_host1x_hwctx(nctx);
517         struct host1x_hwctx_handler *h = host1x_hwctx_handler(ctx);
518
519         u32 *ptr = (u32 *)ctx->restore_virt + RESTORE_BEGIN_SIZE;
520         unsigned int pending = 0;
521         struct mpe_save_info msi;
522
523         msi.in_pos = 0;
524         msi.out_pos = 0;
525
526         ptr = save_regs(ptr, &pending, nctx->channel,
527                         ctxsave_regs_mpe, ARRAY_SIZE(ctxsave_regs_mpe), &msi);
528
529         ptr = save_ram(ptr, &pending, nctx->channel,
530                 RC_RAM_SIZE, RC_RAM_READ_CMD, RC_RAM_READ_DATA);
531
532         ptr = save_ram(ptr, &pending, nctx->channel,
533                 IRFR_RAM_SIZE, IRFR_RAM_READ_CMD, IRFR_RAM_READ_DATA);
534
535         wmb();
536         nvhost_syncpt_cpu_incr(&nvhost_get_host(nctx->channel->dev)->syncpt,
537                         h->syncpt);
538 }
539
540 struct nvhost_hwctx_handler *nvhost_mpe_ctxhandler_init(u32 syncpt,
541         u32 waitbase, struct nvhost_channel *ch)
542 {
543         struct mem_mgr *memmgr;
544         u32 *save_ptr;
545         struct host1x_hwctx_handler *p;
546
547         p = kmalloc(sizeof(*p), GFP_KERNEL);
548         if (!p)
549                 return NULL;
550
551         memmgr = nvhost_get_host(ch->dev)->memmgr;
552
553         p->syncpt = syncpt;
554         p->waitbase = waitbase;
555
556         setup_save(p, NULL);
557
558         p->save_buf = mem_op().alloc(memmgr, p->save_size * 4, 32,
559                                 mem_mgr_flag_write_combine);
560         if (IS_ERR(p->save_buf)) {
561                 p->save_buf = NULL;
562                 return NULL;
563         }
564
565         save_ptr = mem_op().mmap(p->save_buf);
566         if (!save_ptr) {
567                 mem_op().put(memmgr, p->save_buf);
568                 p->save_buf = NULL;
569                 return NULL;
570         }
571
572         p->save_phys = mem_op().pin(memmgr, p->save_buf);
573         p->save_slots = 1;
574
575         setup_save(p, save_ptr);
576
577         p->h.alloc = ctxmpe_alloc;
578         p->h.save_push = ctxmpe_save_push;
579         p->h.save_service = ctxmpe_save_service;
580         p->h.get = ctxmpe_get;
581         p->h.put = ctxmpe_put;
582
583         return &p->h;
584 }
585
586 int nvhost_mpe_prepare_power_off(struct nvhost_device *dev)
587 {
588         return host1x_save_context(dev, NVSYNCPT_MPE);
589 }
590
591 enum mpe_ip_ver {
592         mpe_01,
593         mpe_02,
594 };
595
596 struct mpe_desc {
597         int (*prepare_poweroff)(struct nvhost_device *dev);
598         struct nvhost_hwctx_handler *(*alloc_hwctx_handler)(u32 syncpt,
599                         u32 waitbase, struct nvhost_channel *ch);
600 };
601
602 static const struct mpe_desc mpe[] = {
603         [mpe_01] = {
604                 .prepare_poweroff = nvhost_mpe_prepare_power_off,
605                 .alloc_hwctx_handler = nvhost_mpe_ctxhandler_init,
606         },
607         [mpe_02] = {
608                 .prepare_poweroff = nvhost_mpe_prepare_power_off,
609                 .alloc_hwctx_handler = nvhost_mpe_ctxhandler_init,
610         },
611 };
612
613 static struct nvhost_device_id mpe_id[] = {
614         { "mpe01", mpe_01 },
615         { "mpe02", mpe_02 },
616         { },
617 };
618
619 MODULE_DEVICE_TABLE(nvhost, mpe_id);
620
621 static int __devinit mpe_probe(struct nvhost_device *dev,
622         struct nvhost_device_id *id_table)
623 {
624         int err = 0;
625         int index = 0;
626         struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
627
628         index = id_table->driver_data;
629
630         drv->prepare_poweroff           = mpe[index].prepare_poweroff;
631         drv->alloc_hwctx_handler        = mpe[index].alloc_hwctx_handler;
632
633         /* reset device name so that consistent device name can be
634          * found in clock tree */
635         dev->name = "mpe";
636
637         err = nvhost_client_device_get_resources(dev);
638         if (err)
639                 return err;
640
641         return nvhost_client_device_init(dev);
642 }
643
644 static int __exit mpe_remove(struct nvhost_device *dev)
645 {
646         /* Add clean-up */
647         return 0;
648 }
649
650 static int mpe_suspend(struct nvhost_device *dev, pm_message_t state)
651 {
652         return nvhost_client_device_suspend(dev);
653 }
654
655 static int mpe_resume(struct nvhost_device *dev)
656 {
657         dev_info(&dev->dev, "resuming\n");
658         return 0;
659 }
660
661 static struct resource mpe_resources = {
662         .name = "regs",
663         .start = TEGRA_MPE_BASE,
664         .end = TEGRA_MPE_BASE + TEGRA_MPE_SIZE - 1,
665         .flags = IORESOURCE_MEM,
666 };
667
668 struct nvhost_device *mpe_device;
669
670 static struct nvhost_driver mpe_driver = {
671         .probe = mpe_probe,
672         .remove = __exit_p(mpe_remove),
673 #ifdef CONFIG_PM
674         .suspend = mpe_suspend,
675         .resume = mpe_resume,
676 #endif
677         .driver = {
678                 .owner = THIS_MODULE,
679                 .name = "mpe",
680         },
681         .id_table = mpe_id,
682 };
683
684 static int __init mpe_init(void)
685 {
686         int err;
687
688         mpe_device = nvhost_get_device("mpe");
689         if (!mpe_device)
690                 return -ENXIO;
691
692         /* use ARRAY_SIZE macro if resources are more than 1 */
693         mpe_device->resource = &mpe_resources;
694         mpe_device->num_resources = 1;
695         err = nvhost_device_register(mpe_device);
696         if (err)
697                 return err;
698
699         return nvhost_driver_register(&mpe_driver);
700 }
701
702 static void __exit mpe_exit(void)
703 {
704         nvhost_driver_unregister(&mpe_driver);
705 }
706
707 module_init(mpe_init);
708 module_exit(mpe_exit);