Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[pandora-kernel.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) 2011 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 #include "regs-mfc.h"
14 #include "s5p_mfc_cmd.h"
15 #include "s5p_mfc_common.h"
16 #include "s5p_mfc_debug.h"
17
18 /* This function is used to send a command to the MFC */
19 static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
20                                                 struct s5p_mfc_cmd_args *args)
21 {
22         int cur_cmd;
23         unsigned long timeout;
24
25         timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
26         /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
27         do {
28                 if (time_after(jiffies, timeout)) {
29                         mfc_err("Timeout while waiting for hardware\n");
30                         return -EIO;
31                 }
32                 cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
33         } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
34         mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
35         mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
36         mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
37         mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
38         /* Issue the command */
39         mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
40         return 0;
41 }
42
43 /* Initialize the MFC */
44 int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
45 {
46         struct s5p_mfc_cmd_args h2r_args;
47
48         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
49         h2r_args.arg[0] = dev->fw_size;
50         return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
51 }
52
53 /* Suspend the MFC hardware */
54 int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
55 {
56         struct s5p_mfc_cmd_args h2r_args;
57
58         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
59         return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
60 }
61
62 /* Wake up the MFC hardware */
63 int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
64 {
65         struct s5p_mfc_cmd_args h2r_args;
66
67         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
68         return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
69 }
70
71
72 int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
73 {
74         struct s5p_mfc_dev *dev = ctx->dev;
75         struct s5p_mfc_cmd_args h2r_args;
76         int ret;
77
78         /* Preparing decoding - getting instance number */
79         mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
80         dev->curr_ctx = ctx->num;
81         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
82         h2r_args.arg[0] = ctx->codec_mode;
83         h2r_args.arg[1] = 0; /* no crc & no pixelcache */
84         h2r_args.arg[2] = ctx->ctx_ofs;
85         h2r_args.arg[3] = ctx->ctx_size;
86         ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
87                                                                 &h2r_args);
88         if (ret) {
89                 mfc_err("Failed to create a new instance\n");
90                 ctx->state = MFCINST_ERROR;
91         }
92         return ret;
93 }
94
95 int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
96 {
97         struct s5p_mfc_dev *dev = ctx->dev;
98         struct s5p_mfc_cmd_args h2r_args;
99         int ret;
100
101         if (ctx->state == MFCINST_FREE) {
102                 mfc_err("Instance already returned\n");
103                 ctx->state = MFCINST_ERROR;
104                 return -EINVAL;
105         }
106         /* Closing decoding instance  */
107         mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
108         dev->curr_ctx = ctx->num;
109         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
110         h2r_args.arg[0] = ctx->inst_no;
111         ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
112                                                                 &h2r_args);
113         if (ret) {
114                 mfc_err("Failed to return an instance\n");
115                 ctx->state = MFCINST_ERROR;
116                 return -EINVAL;
117         }
118         return 0;
119 }
120