2 * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
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.
15 #include <linux/jiffies.h>
17 #if defined(CONFIG_ARCH_S5PV310)
18 #include <mach/regs-mfc.h>
19 #elif defined(CONFIG_ARCH_S5PV210)
20 #include <plat/regs-mfc.h>
31 static unsigned int r2h_cmd;
32 static struct mfc_cmd_args r2h_args;
37 static int framecnt = 0;
38 struct timeval tv1, tv2;
41 irqreturn_t mfc_irq(int irq, void *dev_id)
43 struct mfc_dev *dev = (struct mfc_dev *)dev_id;
45 r2h_cmd = read_reg(MFC_RISC2HOST_CMD);
46 mfc_dbg("MFC IRQ: 0x%02x\n", r2h_cmd);
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));
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);
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]);
62 mfc_err("Unknown R2H return value: 0x%02x\n", r2h_cmd);
67 do_gettimeofday(&tv2);
69 mfc_info("%d, %ld", framecnt,
70 (long)(((tv2.tv_sec * 1000000) + tv2.tv_usec) - ((tv1.tv_sec * 1000000) + tv1.tv_usec)));
76 /* FIXME: codec wait_queue processing */
78 wake_up(&dev->wait_sys);
81 * FIXME: check is codec command return or error
82 * move to mfc_wait_codec() ?
84 write_reg(0xFFFF, MFC_SI_RTN_CHID);
86 write_reg(0, MFC_RISC2HOST_CMD);
87 write_reg(0, MFC_RISC_HOST_INT);
93 static bool mfc_wait_codec(struct mfc_inst_ctx *ctx, enum mfc_r2h_ret ret)
96 if (wait_event_timeout(dev->wait_codec[0], 0, timeout) == 0) {
97 mfc_err("F/W timeout: 0x%02x\n", ret);
102 if (r2h_cmd == ERR_RET)
103 mfc_err("F/W error code: 0x%02x", r2h_args.arg[1] & 0xFFFF);
108 if (r2h_cmd != ret) {
109 mfc_err("F/W return (0x%02x) waiting for (0x%02x)\n",
120 mfc_wait_sys(struct mfc_dev *dev, enum mfc_r2h_ret ret, long timeout)
122 /* FIXME: MUST protect by spinlock_irq */
125 if (wait_event_timeout(dev->wait_sys, dev->irq_sys, timeout) == 0) {
126 mfc_err("F/W timeout: 0x%02x\n", ret);
131 if (r2h_cmd == ERR_RET) {
132 mfc_err("F/W error code: 0x%02x", r2h_args.arg[1] & 0xFFFF);
137 if (r2h_cmd != ret) {
138 mfc_err("F/W return (0x%02x) waiting for (0x%02x)\n",
147 static bool write_h2r_cmd(enum mfc_h2r_cmd cmd, struct mfc_cmd_args *args)
149 enum mfc_h2r_cmd pending_cmd;
150 unsigned long timeo = jiffies;
152 timeo += msecs_to_jiffies(H2R_CMD_TIMEOUT);
154 /* wait until host to risc command register becomes 'NOP' */
156 pending_cmd = read_reg(MFC_HOST2RISC_CMD);
158 if (pending_cmd == H2R_NOP)
161 schedule_timeout_uninterruptible(1);
162 /* FiXME: cpu_relax() */
163 } while (time_before(jiffies, timeo));
165 if (pending_cmd != H2R_NOP)
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);
173 write_reg(cmd, MFC_HOST2RISC_CMD);
178 int s5p_mfc_cmd_fw_start(struct mfc_dev *dev)
180 /* release RISC reset */
181 write_reg(0x3FF, S5P_FIMV_SW_RESET);
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;
192 int mfc_cmd_sys_init(struct mfc_dev *dev)
194 struct mfc_cmd_args h2r_args;
195 unsigned int fw_version, fw_memsize;
197 memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
198 h2r_args.arg[0] = MFC_FW_SYSTEM_SIZE;
200 if (write_h2r_cmd(SYS_INIT, &h2r_args) == false)
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;
209 fw_version = read_reg(MFC_FW_VERSION);
210 fw_memsize = r2h_args.arg[0];
212 mfc_info("MFC F/W version: %02x-%02x-%02x, %dkB\n",
213 (fw_version >> 16) & 0xff,
214 (fw_version >> 8) & 0xff,
221 int mfc_cmd_sys_sleep(struct mfc_dev *dev)
223 struct mfc_cmd_args h2r_args;
225 memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
227 if (write_h2r_cmd(SLEEP, &h2r_args) == false)
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;
239 int mfc_cmd_sys_wakeup(struct mfc_dev *dev)
241 struct mfc_cmd_args h2r_args;
243 memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
245 if (write_h2r_cmd(WAKEUP, &h2r_args) == false)
248 /* release RISC reset */
249 write_reg(0x3FF, MFC_SW_RESET);
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;
261 int mfc_cmd_inst_open(struct mfc_inst_ctx *ctx)
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;
269 if (ctx->type == DECODER) {
270 dec_ctx = (struct mfc_dec_ctx *)ctx->c_priv;
272 crc = dec_ctx->crc & 0x1;
273 pixelcache = dec_ctx->pixelcache & 0x3;
275 enc_ctx = (struct mfc_enc_ctx *)ctx->c_priv;
277 pixelcache = enc_ctx->pixelcache & 0x3;
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;
286 if (write_h2r_cmd(OPEN_CH, &h2r_args) == false)
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;
295 ctx->cmd_id = r2h_args.arg[0];
297 mfc_dbg("inst id: %d, cmd id: %d, codec id: %d",
298 ctx->id, ctx->cmd_id, ctx->codecid);
307 int mfc_cmd_inst_close(struct mfc_inst_ctx *ctx)
309 struct mfc_cmd_args h2r_args;
311 memset(&h2r_args, 0, sizeof(struct mfc_cmd_args));
312 h2r_args.arg[0] = ctx->cmd_id;
314 if (write_h2r_cmd(CLOSE_CH, &h2r_args) == false)
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;
326 int mfc_cmd_seq_start(struct mfc_inst_ctx *ctx)
328 /* all codec command pass the shared mem addrees */
329 write_reg(ctx->shmofs, MFC_SI_CH1_HOST_WR_ADR);
331 write_reg((SEQ_HEADER << 16 & 0x70000) | ctx->cmd_id,
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;
345 int mfc_cmd_init_buffers(struct mfc_inst_ctx *ctx)
347 /* all codec command pass the shared mem addrees */
348 write_reg(ctx->shmofs, MFC_SI_CH1_HOST_WR_ADR);
350 write_reg((INIT_BUFFERS << 16 & 0x70000) | ctx->cmd_id,
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;
368 int mfc_cmd_frame_start(struct mfc_inst_ctx *ctx)
370 struct mfc_dec_ctx *dec_ctx;
372 /* all codec command pass the shared mem addrees */
373 write_reg(ctx->shmofs, MFC_SI_CH1_HOST_WR_ADR);
375 if (ctx->type == DECODER) {
376 dec_ctx = (struct mfc_dec_ctx *)ctx->c_priv;
378 mfc_dbg("dec_ctx->lastframe: %d", dec_ctx->lastframe);
380 if (dec_ctx->lastframe) {
381 write_reg((LAST_SEQ << 16 & 0x70000) | ctx->cmd_id,
383 dec_ctx->lastframe = 0;
385 write_reg((FRAME_START << 16 & 0x70000) | ctx->cmd_id,
388 } else { /* == ENCODER */
389 write_reg((FRAME_START << 16 & 0x70000) | ctx->cmd_id,
394 do_gettimeofday(&tv1);
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;
410 #include "regs-mfc.h"
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"
418 static int s5p_mfc_cmd_host2risc(int cmd, struct s5p_mfc_cmd_args *args)
421 unsigned long timeout;
423 timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
425 /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
427 if (time_after(jiffies, timeout)) {
428 mfc_err("Timeout while waiting for hardware.\n");
432 cur_cmd = s5p_mfc_read_reg(S5P_FIMV_HOST2RISC_CMD);
433 } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
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);
440 /* Issue the command */
441 s5p_mfc_write_reg(cmd, S5P_FIMV_HOST2RISC_CMD);
446 int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
448 struct s5p_mfc_cmd_args h2r_args;
453 memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
454 h2r_args.arg[0] = FIRMWARE_CODE_SIZE;
456 ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
463 int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
465 struct s5p_mfc_cmd_args h2r_args;
470 memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
472 ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
479 int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
481 struct s5p_mfc_cmd_args h2r_args;
486 memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
488 ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
495 /* Open a new instance and get its number */
496 int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
498 struct s5p_mfc_cmd_args h2r_args;
503 mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
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;
511 ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_OPEN_INSTANCE, &h2r_args);
519 int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
521 struct s5p_mfc_cmd_args h2r_args;
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;
530 ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,