video: tegra: host: Move device data to nvhost_device
[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-2011, NVIDIA Corporation.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  */
22
23 #include "nvhost_hwctx.h"
24 #include "dev.h"
25 #include "host1x/host1x_hardware.h"
26 #include "host1x/host1x_channel.h"
27 #include "host1x/host1x_syncpt.h"
28 #include "t20/t20.h"
29 #include <linux/slab.h>
30
31 enum {
32         HWCTX_REGINFO_NORMAL = 0,
33         HWCTX_REGINFO_STASH,
34         HWCTX_REGINFO_CALCULATE,
35         HWCTX_REGINFO_WRITEBACK
36 };
37
38 const struct hwctx_reginfo ctxsave_regs_mpe[] = {
39         HWCTX_REGINFO(0x124,  1, STASH),
40         HWCTX_REGINFO(0x123,  1, STASH),
41         HWCTX_REGINFO(0x103,  1, STASH),
42         HWCTX_REGINFO(0x074,  1, STASH),
43         HWCTX_REGINFO(0x021,  1, NORMAL),
44         HWCTX_REGINFO(0x020,  1, STASH),
45         HWCTX_REGINFO(0x024,  2, NORMAL),
46         HWCTX_REGINFO(0x0e6,  1, NORMAL),
47         HWCTX_REGINFO(0x3fc,  1, NORMAL),
48         HWCTX_REGINFO(0x3d0,  1, NORMAL),
49         HWCTX_REGINFO(0x3d4,  1, NORMAL),
50         HWCTX_REGINFO(0x013,  1, NORMAL),
51         HWCTX_REGINFO(0x022,  1, NORMAL),
52         HWCTX_REGINFO(0x030,  4, NORMAL),
53         HWCTX_REGINFO(0x023,  1, NORMAL),
54         HWCTX_REGINFO(0x070,  1, NORMAL),
55         HWCTX_REGINFO(0x0a0,  9, NORMAL),
56         HWCTX_REGINFO(0x071,  1, NORMAL),
57         HWCTX_REGINFO(0x100,  4, NORMAL),
58         HWCTX_REGINFO(0x104,  2, NORMAL),
59         HWCTX_REGINFO(0x108,  9, NORMAL),
60         HWCTX_REGINFO(0x112,  2, NORMAL),
61         HWCTX_REGINFO(0x114,  1, STASH),
62         HWCTX_REGINFO(0x014,  1, NORMAL),
63         HWCTX_REGINFO(0x072,  1, NORMAL),
64         HWCTX_REGINFO(0x200,  1, NORMAL),
65         HWCTX_REGINFO(0x0d1,  1, NORMAL),
66         HWCTX_REGINFO(0x0d0,  1, NORMAL),
67         HWCTX_REGINFO(0x0c0,  1, NORMAL),
68         HWCTX_REGINFO(0x0c3,  2, NORMAL),
69         HWCTX_REGINFO(0x0d2,  1, NORMAL),
70         HWCTX_REGINFO(0x0d8,  1, NORMAL),
71         HWCTX_REGINFO(0x0e0,  2, NORMAL),
72         HWCTX_REGINFO(0x07f,  2, NORMAL),
73         HWCTX_REGINFO(0x084,  8, NORMAL),
74         HWCTX_REGINFO(0x0d3,  1, NORMAL),
75         HWCTX_REGINFO(0x040, 13, NORMAL),
76         HWCTX_REGINFO(0x050,  6, NORMAL),
77         HWCTX_REGINFO(0x058,  1, NORMAL),
78         HWCTX_REGINFO(0x057,  1, NORMAL),
79         HWCTX_REGINFO(0x111,  1, NORMAL),
80         HWCTX_REGINFO(0x130,  3, NORMAL),
81         HWCTX_REGINFO(0x201,  1, NORMAL),
82         HWCTX_REGINFO(0x068,  2, NORMAL),
83         HWCTX_REGINFO(0x08c,  1, NORMAL),
84         HWCTX_REGINFO(0x0cf,  1, NORMAL),
85         HWCTX_REGINFO(0x082,  2, NORMAL),
86         HWCTX_REGINFO(0x075,  1, NORMAL),
87         HWCTX_REGINFO(0x0e8,  1, NORMAL),
88         HWCTX_REGINFO(0x056,  1, NORMAL),
89         HWCTX_REGINFO(0x057,  1, NORMAL),
90         HWCTX_REGINFO(0x073,  1, CALCULATE),
91         HWCTX_REGINFO(0x074,  1, NORMAL),
92         HWCTX_REGINFO(0x075,  1, NORMAL),
93         HWCTX_REGINFO(0x076,  1, STASH),
94         HWCTX_REGINFO(0x11a,  9, NORMAL),
95         HWCTX_REGINFO(0x123,  1, NORMAL),
96         HWCTX_REGINFO(0x124,  1, NORMAL),
97         HWCTX_REGINFO(0x12a,  5, NORMAL),
98         HWCTX_REGINFO(0x12f,  1, STASH),
99         HWCTX_REGINFO(0x125,  2, NORMAL),
100         HWCTX_REGINFO(0x034,  1, NORMAL),
101         HWCTX_REGINFO(0x133,  2, NORMAL),
102         HWCTX_REGINFO(0x127,  1, NORMAL),
103         HWCTX_REGINFO(0x106,  1, WRITEBACK),
104         HWCTX_REGINFO(0x107,  1, WRITEBACK)
105 };
106
107 #define NR_STASHES 8
108 #define NR_WRITEBACKS 2
109
110 #define RC_RAM_LOAD_CMD 0x115
111 #define RC_RAM_LOAD_DATA 0x116
112 #define RC_RAM_READ_CMD 0x128
113 #define RC_RAM_READ_DATA 0x129
114 #define RC_RAM_SIZE 692
115
116 #define IRFR_RAM_LOAD_CMD 0xc5
117 #define IRFR_RAM_LOAD_DATA 0xc6
118 #define IRFR_RAM_READ_CMD 0xcd
119 #define IRFR_RAM_READ_DATA 0xce
120 #define IRFR_RAM_SIZE 408
121
122 struct mpe_save_info {
123         u32 in[NR_STASHES];
124         u32 out[NR_WRITEBACKS];
125         unsigned in_pos;
126         unsigned out_pos;
127         u32 h264_mode;
128 };
129
130
131 /*** restore ***/
132
133 static unsigned int restore_size;
134
135 static void restore_begin(u32 *ptr)
136 {
137         /* set class to host */
138         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
139                                         NV_CLASS_HOST_INCR_SYNCPT_BASE, 1);
140         /* increment sync point base */
141         ptr[1] = nvhost_class_host_incr_syncpt_base(NVWAITBASE_MPE, 1);
142         /* set class to MPE */
143         ptr[2] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0);
144 }
145 #define RESTORE_BEGIN_SIZE 3
146
147 static void restore_ram(u32 *ptr, unsigned words,
148                         unsigned cmd_reg, unsigned data_reg)
149 {
150         ptr[0] = nvhost_opcode_imm(cmd_reg, words);
151         ptr[1] = nvhost_opcode_nonincr(data_reg, words);
152 }
153 #define RESTORE_RAM_SIZE 2
154
155 static void restore_end(u32 *ptr)
156 {
157         /* syncpt increment to track restore gather. */
158         ptr[0] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE,
159                         NVSYNCPT_MPE);
160 }
161 #define RESTORE_END_SIZE 1
162
163 static u32 *setup_restore_regs(u32 *ptr,
164                         const struct hwctx_reginfo *regs,
165                         unsigned int nr_regs)
166 {
167         const struct hwctx_reginfo *rend = regs + nr_regs;
168
169         for ( ; regs != rend; ++regs) {
170                 u32 offset = regs->offset;
171                 u32 count = regs->count;
172                 *ptr++ = nvhost_opcode_incr(offset, count);
173                 ptr += count;
174         }
175         return ptr;
176 }
177
178 static u32 *setup_restore_ram(u32 *ptr, unsigned words,
179                         unsigned cmd_reg, unsigned data_reg)
180 {
181         restore_ram(ptr, words, cmd_reg, data_reg);
182         return ptr + (RESTORE_RAM_SIZE + words);
183 }
184
185 static void setup_restore(u32 *ptr)
186 {
187         restore_begin(ptr);
188         ptr += RESTORE_BEGIN_SIZE;
189
190         ptr = setup_restore_regs(ptr, ctxsave_regs_mpe,
191                                 ARRAY_SIZE(ctxsave_regs_mpe));
192
193         ptr = setup_restore_ram(ptr, RC_RAM_SIZE,
194                         RC_RAM_LOAD_CMD, RC_RAM_LOAD_DATA);
195
196         ptr = setup_restore_ram(ptr, IRFR_RAM_SIZE,
197                         IRFR_RAM_LOAD_CMD, IRFR_RAM_LOAD_DATA);
198
199         restore_end(ptr);
200
201         wmb();
202 }
203
204
205 /*** save ***/
206
207 /* the same context save command sequence is used for all contexts. */
208 static struct nvmap_handle_ref *save_buf;
209 static phys_addr_t save_phys;
210 static unsigned int save_size;
211
212 struct save_info {
213         u32 *ptr;
214         unsigned int save_count;
215         unsigned int restore_count;
216 };
217
218 static void __init save_begin(u32 *ptr)
219 {
220         /* MPE: when done, increment syncpt to base+1 */
221         ptr[0] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0);
222         ptr[1] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_OP_DONE,
223                         NVSYNCPT_MPE);
224         /* host: wait for syncpt base+1 */
225         ptr[2] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
226                                         NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1);
227         ptr[3] = nvhost_class_host_wait_syncpt_base(NVSYNCPT_MPE,
228                                                 NVWAITBASE_MPE, 1);
229         /* host: signal context read thread to start reading */
230         ptr[4] = nvhost_opcode_imm_incr_syncpt(NV_SYNCPT_IMMEDIATE,
231                         NVSYNCPT_MPE);
232 }
233 #define SAVE_BEGIN_SIZE 5
234
235 static void __init save_direct(u32 *ptr, u32 start_reg, u32 count)
236 {
237         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
238                                         NV_CLASS_HOST_INDOFF, 1);
239         ptr[1] = nvhost_class_host_indoff_reg_read(NV_HOST_MODULE_MPE,
240                                                 start_reg, true);
241         ptr[2] = nvhost_opcode_nonincr(NV_CLASS_HOST_INDDATA, count);
242 }
243 #define SAVE_DIRECT_SIZE 3
244
245 static void __init save_set_ram_cmd(u32 *ptr, u32 cmd_reg, u32 count)
246 {
247         ptr[0] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID,
248                                         cmd_reg, 1);
249         ptr[1] = count;
250 }
251 #define SAVE_SET_RAM_CMD_SIZE 2
252
253 static void __init save_read_ram_data_nasty(u32 *ptr, u32 data_reg)
254 {
255         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
256                                         NV_CLASS_HOST_INDOFF, 1);
257         ptr[1] = nvhost_class_host_indoff_reg_read(NV_HOST_MODULE_MPE,
258                                                 data_reg, false);
259         ptr[2] = nvhost_opcode_imm(NV_CLASS_HOST_INDDATA, 0);
260         /* write junk data to avoid 'cached problem with register memory' */
261         ptr[3] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID,
262                                         data_reg, 1);
263         ptr[4] = 0x99;
264 }
265 #define SAVE_READ_RAM_DATA_NASTY_SIZE 5
266
267 static void __init save_end(u32 *ptr)
268 {
269         /* Wait for context read service to finish (cpu incr 3) */
270         ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
271                                         NV_CLASS_HOST_WAIT_SYNCPT_BASE, 1);
272         ptr[1] = nvhost_class_host_wait_syncpt_base(NVSYNCPT_MPE,
273                                                 NVWAITBASE_MPE, 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(NVWAITBASE_MPE, 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(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(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(info.ptr);
361                 info.ptr += SAVE_END_SIZE;
362         }
363
364         wmb();
365
366         save_size = info.save_count + SAVE_END_SIZE;
367         restore_size = info.restore_count + RESTORE_END_SIZE;
368 }
369
370
371 static u32 calculate_mpe(u32 word, struct mpe_save_info *msi)
372 {
373         u32 buffer_full_read = msi->in[0] & 0x01ffffff;
374         u32 byte_len = msi->in[1];
375         u32 drain = (msi->in[2] >> 2) & 0x007fffff;
376         u32 rep_frame = msi->in[3] & 0x0000ffff;
377         u32 h264_mode = (msi->in[4] >> 11) & 1;
378         int new_buffer_full;
379
380         if (h264_mode)
381                 byte_len >>= 3;
382         new_buffer_full = buffer_full_read + byte_len - (drain * 4);
383         msi->out[0] = max(0, new_buffer_full);
384         msi->out[1] = rep_frame;
385         if (rep_frame == 0)
386                 word &= 0xffff0000;
387         return word;
388 }
389
390 static u32 *save_regs(u32 *ptr, unsigned int *pending,
391                 struct nvhost_channel *channel,
392                 const struct hwctx_reginfo *regs,
393                 unsigned int nr_regs,
394                 struct mpe_save_info *msi)
395 {
396         const struct hwctx_reginfo *rend = regs + nr_regs;
397
398         for ( ; regs != rend; ++regs) {
399                 u32 count = regs->count;
400                 ++ptr; /* restore incr */
401                 if (regs->type == HWCTX_REGINFO_NORMAL) {
402                         host1x_drain_read_fifo(channel->aperture,
403                                                 ptr, count, pending);
404                         ptr += count;
405                 } else {
406                         u32 word;
407                         if (regs->type == HWCTX_REGINFO_WRITEBACK) {
408                                 BUG_ON(msi->out_pos >= NR_WRITEBACKS);
409                                 word = msi->out[msi->out_pos++];
410                         } else {
411                                 host1x_drain_read_fifo(channel->aperture,
412                                                         &word, 1, pending);
413                                 if (regs->type == HWCTX_REGINFO_STASH) {
414                                         BUG_ON(msi->in_pos >= NR_STASHES);
415                                         msi->in[msi->in_pos++] = word;
416                                 } else {
417                                         word = calculate_mpe(word, msi);
418                                 }
419                         }
420                         *ptr++ = word;
421                 }
422         }
423         return ptr;
424 }
425
426 static u32 *save_ram(u32 *ptr, unsigned int *pending,
427                 struct nvhost_channel *channel,
428                 unsigned words, unsigned cmd_reg, unsigned data_reg)
429 {
430         int err = 0;
431         ptr += RESTORE_RAM_SIZE;
432         err = host1x_drain_read_fifo(channel->aperture, ptr, words, pending);
433         WARN_ON(err);
434         return ptr + words;
435 }
436
437
438 /*** ctxmpe ***/
439
440 static struct nvhost_hwctx *ctxmpe_alloc(struct nvhost_channel *ch)
441 {
442         struct nvmap_client *nvmap = ch->dev->host->nvmap;
443         struct nvhost_hwctx *ctx;
444
445         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
446         if (!ctx)
447                 return NULL;
448         ctx->restore = nvmap_alloc(nvmap, restore_size * 4, 32,
449                                 NVMAP_HANDLE_WRITE_COMBINE);
450         if (IS_ERR_OR_NULL(ctx->restore)) {
451                 kfree(ctx);
452                 return NULL;
453         }
454
455         ctx->restore_virt = nvmap_mmap(ctx->restore);
456         if (!ctx->restore_virt) {
457                 nvmap_free(nvmap, ctx->restore);
458                 kfree(ctx);
459                 return NULL;
460         }
461
462         kref_init(&ctx->ref);
463         ctx->channel = ch;
464         ctx->valid = false;
465         ctx->save = save_buf;
466         ctx->save_incrs = 3;
467         ctx->save_thresh = 2;
468         ctx->restore_phys = nvmap_pin(nvmap, ctx->restore);
469         ctx->restore_size = restore_size;
470         ctx->restore_incrs = 1;
471
472         setup_restore(ctx->restore_virt);
473
474         return ctx;
475 }
476
477 static void ctxmpe_get(struct nvhost_hwctx *ctx)
478 {
479         kref_get(&ctx->ref);
480 }
481
482 static void ctxmpe_free(struct kref *ref)
483 {
484         struct nvhost_hwctx *ctx = container_of(ref, struct nvhost_hwctx, ref);
485         struct nvmap_client *nvmap = ctx->channel->dev->host->nvmap;
486
487         if (ctx->restore_virt)
488                 nvmap_munmap(ctx->restore, ctx->restore_virt);
489         nvmap_unpin(nvmap, ctx->restore);
490         nvmap_free(nvmap, ctx->restore);
491         kfree(ctx);
492 }
493
494 static void ctxmpe_put(struct nvhost_hwctx *ctx)
495 {
496         kref_put(&ctx->ref, ctxmpe_free);
497 }
498
499 static void ctxmpe_save_push(struct nvhost_cdma *cdma, struct nvhost_hwctx *ctx)
500 {
501         nvhost_cdma_push(cdma,
502                         nvhost_opcode_gather(save_size),
503                         save_phys);
504 }
505
506 static void ctxmpe_save_service(struct nvhost_hwctx *ctx)
507 {
508         u32 *ptr = (u32 *)ctx->restore_virt + RESTORE_BEGIN_SIZE;
509         unsigned int pending = 0;
510         struct mpe_save_info msi;
511
512         msi.in_pos = 0;
513         msi.out_pos = 0;
514
515         ptr = save_regs(ptr, &pending, ctx->channel,
516                         ctxsave_regs_mpe, ARRAY_SIZE(ctxsave_regs_mpe), &msi);
517
518         ptr = save_ram(ptr, &pending, ctx->channel,
519                 RC_RAM_SIZE, RC_RAM_READ_CMD, RC_RAM_READ_DATA);
520
521         ptr = save_ram(ptr, &pending, ctx->channel,
522                 IRFR_RAM_SIZE, IRFR_RAM_READ_CMD, IRFR_RAM_READ_DATA);
523
524         wmb();
525         nvhost_syncpt_cpu_incr(&ctx->channel->dev->host->syncpt, NVSYNCPT_MPE);
526 }
527
528 int __init nvhost_mpe_ctxhandler_init(struct nvhost_hwctx_handler *h)
529 {
530         struct nvhost_channel *ch;
531         struct nvmap_client *nvmap;
532         u32 *save_ptr;
533
534         ch = container_of(h, struct nvhost_channel, ctxhandler);
535         nvmap = ch->dev->host->nvmap;
536
537         setup_save(NULL);
538
539         save_buf = nvmap_alloc(nvmap, save_size * 4, 32,
540                                 NVMAP_HANDLE_WRITE_COMBINE);
541         if (IS_ERR(save_buf)) {
542                 int err = PTR_ERR(save_buf);
543                 save_buf = NULL;
544                 return err;
545         }
546
547         save_ptr = nvmap_mmap(save_buf);
548         if (!save_ptr) {
549                 nvmap_free(nvmap, save_buf);
550                 save_buf = NULL;
551                 return -ENOMEM;
552         }
553
554         save_phys = nvmap_pin(nvmap, save_buf);
555
556         setup_save(save_ptr);
557
558         h->alloc = ctxmpe_alloc;
559         h->save_push = ctxmpe_save_push;
560         h->save_service = ctxmpe_save_service;
561         h->get = ctxmpe_get;
562         h->put = ctxmpe_put;
563
564         return 0;
565 }
566
567 int nvhost_mpe_prepare_power_off(struct nvhost_device *dev)
568 {
569         return host1x_save_context(dev, NVSYNCPT_MPE);
570 }