Commit | Line | Data |
---|---|---|
af935746 | 1 | /* |
43a1ea1f | 2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c |
af935746 KD |
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" | |
43a1ea1f | 14 | #include "s5p_mfc_cmd.h" |
af935746 KD |
15 | #include "s5p_mfc_common.h" |
16 | #include "s5p_mfc_debug.h" | |
8492ec69 | 17 | #include "s5p_mfc_cmd_v5.h" |
af935746 KD |
18 | |
19 | /* This function is used to send a command to the MFC */ | |
4294dcf7 | 20 | static int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd, |
43a1ea1f | 21 | struct s5p_mfc_cmd_args *args) |
af935746 KD |
22 | { |
23 | int cur_cmd; | |
24 | unsigned long timeout; | |
25 | ||
26 | timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); | |
27 | /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */ | |
28 | do { | |
29 | if (time_after(jiffies, timeout)) { | |
30 | mfc_err("Timeout while waiting for hardware\n"); | |
31 | return -EIO; | |
32 | } | |
33 | cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD); | |
34 | } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY); | |
35 | mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1); | |
36 | mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2); | |
37 | mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3); | |
38 | mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4); | |
39 | /* Issue the command */ | |
40 | mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD); | |
41 | return 0; | |
42 | } | |
43 | ||
44 | /* Initialize the MFC */ | |
4294dcf7 | 45 | static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev) |
af935746 KD |
46 | { |
47 | struct s5p_mfc_cmd_args h2r_args; | |
48 | ||
49 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | |
50 | h2r_args.arg[0] = dev->fw_size; | |
43a1ea1f AK |
51 | return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT, |
52 | &h2r_args); | |
af935746 KD |
53 | } |
54 | ||
55 | /* Suspend the MFC hardware */ | |
4294dcf7 | 56 | static int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev) |
af935746 KD |
57 | { |
58 | struct s5p_mfc_cmd_args h2r_args; | |
59 | ||
60 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | |
43a1ea1f | 61 | return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args); |
af935746 KD |
62 | } |
63 | ||
64 | /* Wake up the MFC hardware */ | |
4294dcf7 | 65 | static int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev) |
af935746 KD |
66 | { |
67 | struct s5p_mfc_cmd_args h2r_args; | |
68 | ||
69 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | |
43a1ea1f AK |
70 | return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP, |
71 | &h2r_args); | |
af935746 KD |
72 | } |
73 | ||
74 | ||
4294dcf7 | 75 | static int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx) |
af935746 KD |
76 | { |
77 | struct s5p_mfc_dev *dev = ctx->dev; | |
78 | struct s5p_mfc_cmd_args h2r_args; | |
79 | int ret; | |
80 | ||
81 | /* Preparing decoding - getting instance number */ | |
82 | mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode); | |
83 | dev->curr_ctx = ctx->num; | |
84 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | |
43a1ea1f AK |
85 | switch (ctx->codec_mode) { |
86 | case S5P_MFC_CODEC_H264_DEC: | |
87 | h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC; | |
88 | break; | |
89 | case S5P_MFC_CODEC_VC1_DEC: | |
90 | h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC; | |
91 | break; | |
92 | case S5P_MFC_CODEC_MPEG4_DEC: | |
93 | h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC; | |
94 | break; | |
95 | case S5P_MFC_CODEC_MPEG2_DEC: | |
96 | h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC; | |
97 | break; | |
98 | case S5P_MFC_CODEC_H263_DEC: | |
99 | h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC; | |
100 | break; | |
101 | case S5P_MFC_CODEC_VC1RCV_DEC: | |
102 | h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC; | |
103 | break; | |
104 | case S5P_MFC_CODEC_H264_ENC: | |
105 | h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC; | |
106 | break; | |
107 | case S5P_MFC_CODEC_MPEG4_ENC: | |
108 | h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC; | |
109 | break; | |
110 | case S5P_MFC_CODEC_H263_ENC: | |
111 | h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC; | |
112 | break; | |
113 | default: | |
114 | h2r_args.arg[0] = S5P_FIMV_CODEC_NONE; | |
2028c71d | 115 | } |
af935746 | 116 | h2r_args.arg[1] = 0; /* no crc & no pixelcache */ |
8f532a7f AK |
117 | h2r_args.arg[2] = ctx->ctx.ofs; |
118 | h2r_args.arg[3] = ctx->ctx.size; | |
43a1ea1f | 119 | ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE, |
af935746 KD |
120 | &h2r_args); |
121 | if (ret) { | |
122 | mfc_err("Failed to create a new instance\n"); | |
123 | ctx->state = MFCINST_ERROR; | |
124 | } | |
125 | return ret; | |
126 | } | |
127 | ||
4294dcf7 | 128 | static int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx) |
af935746 KD |
129 | { |
130 | struct s5p_mfc_dev *dev = ctx->dev; | |
131 | struct s5p_mfc_cmd_args h2r_args; | |
132 | int ret; | |
133 | ||
134 | if (ctx->state == MFCINST_FREE) { | |
135 | mfc_err("Instance already returned\n"); | |
136 | ctx->state = MFCINST_ERROR; | |
137 | return -EINVAL; | |
138 | } | |
139 | /* Closing decoding instance */ | |
140 | mfc_debug(2, "Returning instance number %d\n", ctx->inst_no); | |
141 | dev->curr_ctx = ctx->num; | |
142 | memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); | |
143 | h2r_args.arg[0] = ctx->inst_no; | |
43a1ea1f | 144 | ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE, |
af935746 KD |
145 | &h2r_args); |
146 | if (ret) { | |
147 | mfc_err("Failed to return an instance\n"); | |
148 | ctx->state = MFCINST_ERROR; | |
149 | return -EINVAL; | |
150 | } | |
151 | return 0; | |
152 | } | |
153 | ||
43a1ea1f AK |
154 | /* Initialize cmd function pointers for MFC v5 */ |
155 | static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = { | |
156 | .cmd_host2risc = s5p_mfc_cmd_host2risc_v5, | |
157 | .sys_init_cmd = s5p_mfc_sys_init_cmd_v5, | |
158 | .sleep_cmd = s5p_mfc_sleep_cmd_v5, | |
159 | .wakeup_cmd = s5p_mfc_wakeup_cmd_v5, | |
160 | .open_inst_cmd = s5p_mfc_open_inst_cmd_v5, | |
161 | .close_inst_cmd = s5p_mfc_close_inst_cmd_v5, | |
162 | }; | |
163 | ||
164 | struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void) | |
165 | { | |
166 | return &s5p_mfc_cmds_v5; | |
167 | } |