upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / s5p-mfc / s5p_mfc_cmd.c
1 /*
2  * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
3  *
4  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5  *              http://www.samsung.com/
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  */
12
13 #if 0
14
15 #include <linux/jiffies.h>
16
17 #if defined(CONFIG_ARCH_S5PV310)
18 #include <mach/regs-mfc.h>
19 #elif defined(CONFIG_ARCH_S5PV210)
20 #include <plat/regs-mfc.h>
21 #endif
22
23 #include "mfc_cmd.h"
24 #include "mfc_reg.h"
25 #include "mfc_log.h"
26 #include "mfc_dec.h"
27 #include "mfc_enc.h"
28 #include "mfc_mem.h"
29 #include "mfc_buf.h"
30
31 static unsigned int r2h_cmd;
32 static struct mfc_cmd_args r2h_args;
33
34 #undef MFC_PERF
35
36 #ifdef MFC_PERF
37 static int framecnt = 0;
38 struct timeval tv1, tv2;
39 #endif
40
41 irqreturn_t mfc_irq(int irq, void *dev_id)
42 {
43         struct mfc_dev *dev = (struct mfc_dev *)dev_id;
44
45         r2h_cmd = read_reg(MFC_RISC2HOST_CMD);
46         mfc_dbg("MFC IRQ: 0x%02x\n", r2h_cmd);
47
48         if (((r2h_cmd >= OPEN_CH_RET) && (r2h_cmd <= CLOSE_CH_RET)) ||
49             ((r2h_cmd >= SEQ_DONE_RET) && (r2h_cmd <= EDFU_INIT_RET)) ||
50             ( r2h_cmd == ERR_RET)) {
51                 memset(&r2h_args, 0, sizeof(struct mfc_cmd_args));
52
53                 r2h_args.arg[0] = read_reg(MFC_RISC2HOST_ARG1);
54                 r2h_args.arg[1] = read_reg(MFC_RISC2HOST_ARG2);
55                 r2h_args.arg[2] = read_reg(MFC_RISC2HOST_ARG3);
56                 r2h_args.arg[3] = read_reg(MFC_RISC2HOST_ARG4);
57
58                 if (r2h_cmd == ERR_RET)
59                         //mfc_dbg("F/W error code: %d", r2h_args.arg[1] & 0xFFFF);
60                         mfc_dbg("F/W error code: 0x%08x", r2h_args.arg[1]);
61         } else {
62                 mfc_err("Unknown R2H return value: 0x%02x\n", r2h_cmd);
63         }
64
65 #ifdef MFC_PERF
66         if (framecnt > 0) {
67                 do_gettimeofday(&tv2);
68
69                 mfc_info("%d, %ld", framecnt,
70                         (long)(((tv2.tv_sec * 1000000) + tv2.tv_usec) - ((tv1.tv_sec * 1000000) + tv1.tv_usec)));
71
72                 framecnt++;
73         }
74 #endif
75
76         /* FIXME: codec wait_queue processing */
77         dev->irq_sys = 1;
78         wake_up(&dev->wait_sys);
79
80         /*
81          * FIXME: check is codec command return or error
82          * move to mfc_wait_codec() ?
83          */
84         write_reg(0xFFFF, MFC_SI_RTN_CHID);
85
86         write_reg(0, MFC_RISC2HOST_CMD);
87         write_reg(0, MFC_RISC_HOST_INT);
88
89         return IRQ_HANDLED;
90 }
91
92 #if 0
93 static bool mfc_wait_codec(struct mfc_inst_ctx *ctx, enum mfc_r2h_ret ret)
94 {
95         /*
96         if (wait_event_timeout(dev->wait_codec[0], 0, timeout) == 0) {
97                 mfc_err("F/W timeout: 0x%02x\n", ret);
98
99                 return false;
100         }
101
102         if (r2h_cmd == ERR_RET)
103                 mfc_err("F/W error code: 0x%02x", r2h_args.arg[1] & 0xFFFF);
104
105                 return false;
106         }
107
108         if (r2h_cmd != ret) {
109                 mfc_err("F/W return (0x%02x) waiting for (0x%02x)\n",
110                         r2h_cmd, ret);
111
112                 return false;
113         }
114         */
115         return true;
116 }
117 #endif
118
119 static bool
120 mfc_wait_sys(struct mfc_dev *dev, enum mfc_r2h_ret ret, long timeout)
121 {
122         /* FIXME: MUST protect by spinlock_irq */
123         dev->irq_sys = 0;
124
125         if (wait_event_timeout(dev->wait_sys, dev->irq_sys, timeout) == 0) {
126                 mfc_err("F/W timeout: 0x%02x\n", ret);
127
128                 return false;
129         }
130
131         if (r2h_cmd == ERR_RET) {
132                 mfc_err("F/W error code: 0x%02x", r2h_args.arg[1] & 0xFFFF);
133
134                 return false;
135         }
136
137         if (r2h_cmd != ret) {
138                 mfc_err("F/W return (0x%02x) waiting for (0x%02x)\n",
139                         r2h_cmd, ret);
140
141                 return false;
142         }
143
144         return true;
145 }
146
147 static bool write_h2r_cmd(enum mfc_h2r_cmd cmd, struct mfc_cmd_args *args)
148 {
149         enum mfc_h2r_cmd pending_cmd;
150         unsigned long timeo = jiffies;
151
152         timeo += msecs_to_jiffies(H2R_CMD_TIMEOUT);
153
154         /* wait until host to risc command register becomes 'NOP' */
155         do {
156                 pending_cmd = read_reg(MFC_HOST2RISC_CMD);
157
158                 if (pending_cmd == H2R_NOP)
159                         break;
160
161                 schedule_timeout_uninterruptible(1);
162                 /* FiXME: cpu_relax() */
163         } while (time_before(jiffies, timeo));
164
165         if (pending_cmd != H2R_NOP)
166                 return false;
167
168         write_reg(args->arg[0], MFC_HOST2RISC_ARG1);
169         write_reg(args->arg[1], MFC_HOST2RISC_ARG2);
170         write_reg(args->arg[2], MFC_HOST2RISC_ARG3);
171         write_reg(args->arg[3], MFC_HOST2RISC_ARG4);
172
173         write_reg(cmd, MFC_HOST2RISC_CMD);
174
175         return true;
176 }
177
178 int s5p_mfc_cmd_fw_start(struct mfc_dev *dev)
179 {
180         /* release RISC reset */
181         write_reg(0x3FF, S5P_FIMV_SW_RESET);
182
183         if (mfc_wait_sys(dev, FW_STATUS_RET,
184                 msecs_to_jiffies(H2R_INT_TIMEOUT)) == false) {
185                 mfc_err("failed to check F/W\n");
186                 return MFC_FW_LOAD_FAIL;
187         }
188
189         return MFC_OK;
190 }
191
192 int mfc_cmd_sys_init(struct mfc_dev *dev)
193 {
194         struct mfc_cmd_args h2r_args;
195         unsigned int fw_version, fw_memsize;
196
197         memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
198         h2r_args.arg[0] = MFC_FW_SYSTEM_SIZE;
199
200         if (write_h2r_cmd(SYS_INIT, &h2r_args) == false)
201                 return MFC_CMD_FAIL;
202
203         if (mfc_wait_sys(dev, SYS_INIT_RET,
204                 msecs_to_jiffies(H2R_INT_TIMEOUT)) == false) {
205                 mfc_err("failed to init system\n");
206                 return MFC_FW_INIT_FAIL;
207         }
208
209         fw_version = read_reg(MFC_FW_VERSION);
210         fw_memsize = r2h_args.arg[0];
211
212         mfc_info("MFC F/W version: %02x-%02x-%02x, %dkB\n",
213                  (fw_version >> 16) & 0xff,
214                  (fw_version >> 8) & 0xff,
215                  (fw_version) & 0xff,
216                  (fw_memsize) >> 10);
217
218         return MFC_OK;
219 }
220
221 int mfc_cmd_sys_sleep(struct mfc_dev *dev)
222 {
223         struct mfc_cmd_args h2r_args;
224
225         memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
226
227         if (write_h2r_cmd(SLEEP, &h2r_args) == false)
228                 return MFC_CMD_FAIL;
229
230         if (mfc_wait_sys(dev, SLEEP_RET,
231                 msecs_to_jiffies(H2R_INT_TIMEOUT)) == false) {
232                 mfc_err("failed to sleep\n");
233                 return MFC_SLEEP_FAIL;
234         }
235
236         return MFC_OK;
237 }
238
239 int mfc_cmd_sys_wakeup(struct mfc_dev *dev)
240 {
241         struct mfc_cmd_args h2r_args;
242
243         memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
244
245         if (write_h2r_cmd(WAKEUP, &h2r_args) == false)
246                 return MFC_CMD_FAIL;
247
248         /* release RISC reset */
249         write_reg(0x3FF, MFC_SW_RESET);
250
251         if (mfc_wait_sys(dev, WAKEUP_RET,
252                 //msecs_to_jiffies(H2R_INT_TIMEOUT)) == false) {
253                 msecs_to_jiffies(20000)) == false) {
254                 mfc_err("failed to wakeup\n");
255                 return MFC_WAKEUP_FAIL;
256         }
257
258         return MFC_OK;
259 }
260
261 int mfc_cmd_inst_open(struct mfc_inst_ctx *ctx)
262 {
263         struct mfc_cmd_args h2r_args;
264         unsigned int crc = 0;
265         unsigned int pixelcache = 0;
266         struct mfc_dec_ctx *dec_ctx;
267         struct mfc_enc_ctx *enc_ctx;
268
269         if (ctx->type == DECODER) {
270                 dec_ctx = (struct mfc_dec_ctx *)ctx->c_priv;
271
272                 crc = dec_ctx->crc & 0x1;
273                 pixelcache = dec_ctx->pixelcache & 0x3;
274         } else {
275                 enc_ctx = (struct mfc_enc_ctx *)ctx->c_priv;
276
277                 pixelcache = enc_ctx->pixelcache & 0x3;
278         }
279
280         memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
281         h2r_args.arg[0] = ctx->codecid;
282         h2r_args.arg[1] = crc << 31 | pixelcache;
283         h2r_args.arg[2] = ctx->ctxbufofs;
284         h2r_args.arg[3] = ctx->ctxbufsize;
285
286         if (write_h2r_cmd(OPEN_CH, &h2r_args) == false)
287                 return MFC_CMD_FAIL;
288
289         if (mfc_wait_sys(ctx->dev, OPEN_CH_RET,
290                 msecs_to_jiffies(H2R_INT_TIMEOUT)) == false) {
291                 mfc_err("failed to open instance\n");
292                 return MFC_OPEN_FAIL;
293         }
294
295         ctx->cmd_id = r2h_args.arg[0];
296
297         mfc_dbg("inst id: %d, cmd id: %d, codec id: %d",
298                 ctx->id, ctx->cmd_id, ctx->codecid);
299
300 #ifdef MFC_PERF
301         framecnt = 0;
302 #endif
303
304         return ctx->cmd_id;
305 }
306
307 int mfc_cmd_inst_close(struct mfc_inst_ctx *ctx)
308 {
309         struct mfc_cmd_args h2r_args;
310
311         memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
312         h2r_args.arg[0] = ctx->cmd_id;
313
314         if (write_h2r_cmd(CLOSE_CH, &h2r_args) == false)
315                 return MFC_CMD_FAIL;
316
317         if (mfc_wait_sys(ctx->dev, CLOSE_CH_RET,
318                 msecs_to_jiffies(H2R_INT_TIMEOUT)) == false) {
319                 mfc_err("failed to close instance\n");
320                 return MFC_CLOSE_FAIL;
321         }
322
323         return MFC_OK;
324 }
325
326 int mfc_cmd_seq_start(struct mfc_inst_ctx *ctx)
327 {
328         /* all codec command pass the shared mem addrees */
329         write_reg(ctx->shmofs, MFC_SI_CH1_HOST_WR_ADR);
330
331         write_reg((SEQ_HEADER << 16 & 0x70000) | ctx->cmd_id,
332                   MFC_SI_CH1_INST_ID);
333
334         /* FIXME: close_instance ? */
335         /* FIXME: mfc_wait_codec */
336         if (mfc_wait_sys(ctx->dev, SEQ_DONE_RET,
337                 msecs_to_jiffies(CODEC_INT_TIMEOUT)) == false) {
338                 mfc_err("failed to init seq start\n");
339                 return MFC_DEC_INIT_FAIL;
340         }
341
342         return MFC_OK;
343 }
344
345 int mfc_cmd_init_buffers(struct mfc_inst_ctx *ctx)
346 {
347         /* all codec command pass the shared mem addrees */
348         write_reg(ctx->shmofs, MFC_SI_CH1_HOST_WR_ADR);
349
350         write_reg((INIT_BUFFERS << 16 & 0x70000) | ctx->cmd_id,
351                   MFC_SI_CH1_INST_ID);
352
353         /* FIXME: close_instance ? */
354         /* FIXME: mfc_wait_codec */
355         if (mfc_wait_sys(ctx->dev, INIT_BUFFERS_RET,
356                 msecs_to_jiffies(CODEC_INT_TIMEOUT)) == false) {
357                 mfc_err("failed to init buffers\n");
358                 return MFC_DEC_INIT_FAIL;
359         }
360
361 #ifdef MFC_PERF
362         framecnt = 1;
363 #endif
364
365         return MFC_OK;
366 }
367
368 int mfc_cmd_frame_start(struct mfc_inst_ctx *ctx)
369 {
370         struct mfc_dec_ctx *dec_ctx;
371
372         /* all codec command pass the shared mem addrees */
373         write_reg(ctx->shmofs, MFC_SI_CH1_HOST_WR_ADR);
374
375         if (ctx->type == DECODER) {
376                 dec_ctx = (struct mfc_dec_ctx *)ctx->c_priv;
377
378                 mfc_dbg("dec_ctx->lastframe: %d", dec_ctx->lastframe);
379
380                 if (dec_ctx->lastframe) {
381                         write_reg((LAST_SEQ << 16 & 0x70000) | ctx->cmd_id,
382                                   MFC_SI_CH1_INST_ID);
383                         dec_ctx->lastframe = 0;
384                 } else {
385                         write_reg((FRAME_START << 16 & 0x70000) | ctx->cmd_id,
386                                   MFC_SI_CH1_INST_ID);
387                 }
388         } else { /* == ENCODER */
389                 write_reg((FRAME_START << 16 & 0x70000) | ctx->cmd_id,
390                           MFC_SI_CH1_INST_ID);
391         }
392
393 #ifdef MFC_PERF
394         do_gettimeofday(&tv1);
395 #endif
396
397         /* FIXME: close_instance ? */
398         /* FIXME: mfc_wait_codec */
399         if (mfc_wait_sys(ctx->dev, FRAME_DONE_RET,
400                 msecs_to_jiffies(CODEC_INT_TIMEOUT)) == false) {
401                 mfc_err("failed to frame start\n");
402                 return MFC_DEC_EXE_TIME_OUT;
403         }
404
405         return MFC_OK;
406 }
407
408 #endif
409
410 #include "regs-mfc.h"
411
412 #include "s5p_mfc_common.h"
413 #include "s5p_mfc_debug.h"
414 #include "s5p_mfc_reg.h"
415 #include "s5p_mfc_cmd.h"
416 #include "s5p_mfc_mem.h"
417
418 static int s5p_mfc_cmd_host2risc(int cmd, struct s5p_mfc_cmd_args *args)
419 {
420         int cur_cmd;
421         unsigned long timeout;
422
423         timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
424
425         /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
426         do {
427                 if (time_after(jiffies, timeout)) {
428                         mfc_err("Timeout while waiting for hardware.\n");
429                         return -EIO;
430                 }
431
432                 cur_cmd = s5p_mfc_read_reg(S5P_FIMV_HOST2RISC_CMD);
433         } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
434
435         s5p_mfc_write_reg(args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
436         s5p_mfc_write_reg(args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
437         s5p_mfc_write_reg(args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
438         s5p_mfc_write_reg(args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
439
440         /* Issue the command */
441         s5p_mfc_write_reg(cmd, S5P_FIMV_HOST2RISC_CMD);
442
443         return 0;
444 }
445
446 int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
447 {
448         struct s5p_mfc_cmd_args h2r_args;
449         int ret;
450
451         mfc_debug_enter();
452
453         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
454         h2r_args.arg[0] = FIRMWARE_CODE_SIZE;
455
456         ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
457
458         mfc_debug_leave();
459
460         return ret;
461 }
462
463 int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
464 {
465         struct s5p_mfc_cmd_args h2r_args;
466         int ret;
467
468         mfc_debug_enter();
469
470         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
471
472         ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
473
474         mfc_debug_leave();
475
476         return ret;
477 }
478
479 int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
480 {
481         struct s5p_mfc_cmd_args h2r_args;
482         int ret;
483
484         mfc_debug_enter();
485
486         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
487
488         ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
489
490         mfc_debug_leave();
491
492         return ret;
493 }
494
495 /* Open a new instance and get its number */
496 int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
497 {
498         struct s5p_mfc_cmd_args h2r_args;
499         int ret;
500
501         mfc_debug_enter();
502
503         mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
504
505         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
506         h2r_args.arg[0] = ctx->codec_mode;
507         h2r_args.arg[1] = 0; /* no crc & no pixelcache */
508         h2r_args.arg[2] = ctx->context_ofs;
509         h2r_args.arg[3] = ctx->context_size;
510
511         ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_OPEN_INSTANCE, &h2r_args);
512
513         mfc_debug_leave();
514
515         return ret;
516 }
517
518 /* Close instance */
519 int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
520 {
521         struct s5p_mfc_cmd_args h2r_args;
522         int ret = 0;
523
524         mfc_debug_enter();
525
526         if (ctx->state != MFCINST_FREE) {
527                 memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
528                 h2r_args.arg[0] = ctx->inst_no;
529
530                 ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
531                                             &h2r_args);
532         } else {
533                 ret = -EINVAL;
534         }
535
536         mfc_debug_leave();
537
538         return ret;
539 }
540