]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/dream/qdsp5/adsp_vfe_verify_cmd.c
927d50a730fff5cccbe8b057fc4f5d1666a614f3
[net-next-2.6.git] / drivers / staging / dream / qdsp5 / adsp_vfe_verify_cmd.c
1 /* arch/arm/mach-msm/qdsp5/adsp_vfe_verify_cmd.c
2  *
3  * Verification code for aDSP VFE packets from userspace.
4  *
5  * Copyright (c) 2008 QUALCOMM Incorporated
6  * Copyright (C) 2008 Google, Inc.
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  */
18
19 #include <mach/qdsp5/qdsp5vfecmdi.h>
20 #include "adsp.h"
21
22 static uint32_t size1_y, size2_y, size1_cbcr, size2_cbcr;
23 static uint32_t af_size = 4228;
24 static uint32_t awb_size = 8196;
25
26 static inline int verify_cmd_op_ack(struct msm_adsp_module *module,
27                                     void *cmd_data, size_t cmd_size)
28 {
29         vfe_cmd_op1_ack *cmd = (vfe_cmd_op1_ack *)cmd_data;
30         void **addr_y = (void **)&cmd->op1_buf_y_addr;
31         void **addr_cbcr = (void **)(&cmd->op1_buf_cbcr_addr);
32
33         if (cmd_size != sizeof(vfe_cmd_op1_ack))
34                 return -1;
35         if ((*addr_y && adsp_pmem_fixup(module, addr_y, size1_y)) ||
36             (*addr_cbcr && adsp_pmem_fixup(module, addr_cbcr, size1_cbcr)))
37                 return -1;
38         return 0;
39 }
40
41 static inline int verify_cmd_stats_autofocus_cfg(struct msm_adsp_module *module,
42                                                  void *cmd_data, size_t cmd_size)
43 {
44         int i;
45         vfe_cmd_stats_autofocus_cfg *cmd =
46                 (vfe_cmd_stats_autofocus_cfg *)cmd_data;
47
48         if (cmd_size != sizeof(vfe_cmd_stats_autofocus_cfg))
49                 return -1;
50
51         for (i = 0; i < 3; i++) {
52                 void **addr = (void **)(&cmd->af_stats_op_buf[i]);
53                 if (*addr && adsp_pmem_fixup(module, addr, af_size))
54                         return -1;
55         }
56         return 0;
57 }
58
59 static inline int verify_cmd_stats_wb_exp_cfg(struct msm_adsp_module *module,
60                                               void *cmd_data, size_t cmd_size)
61 {
62         vfe_cmd_stats_wb_exp_cfg *cmd =
63                 (vfe_cmd_stats_wb_exp_cfg *)cmd_data;
64         int i;
65
66         if (cmd_size != sizeof(vfe_cmd_stats_wb_exp_cfg))
67                 return -1;
68
69         for (i = 0; i < 3; i++) {
70                 void **addr = (void **)(&cmd->wb_exp_stats_op_buf[i]);
71                 if (*addr && adsp_pmem_fixup(module, addr, awb_size))
72                         return -1;
73         }
74         return 0;
75 }
76
77 static inline int verify_cmd_stats_af_ack(struct msm_adsp_module *module,
78                                           void *cmd_data, size_t cmd_size)
79 {
80         vfe_cmd_stats_af_ack *cmd = (vfe_cmd_stats_af_ack *)cmd_data;
81         void **addr = (void **)&cmd->af_stats_op_buf;
82
83         if (cmd_size != sizeof(vfe_cmd_stats_af_ack))
84                 return -1;
85
86         if (*addr && adsp_pmem_fixup(module, addr, af_size))
87                 return -1;
88         return 0;
89 }
90
91 static inline int verify_cmd_stats_wb_exp_ack(struct msm_adsp_module *module,
92                                               void *cmd_data, size_t cmd_size)
93 {
94         vfe_cmd_stats_wb_exp_ack *cmd =
95                 (vfe_cmd_stats_wb_exp_ack *)cmd_data;
96         void **addr = (void **)&cmd->wb_exp_stats_op_buf;
97
98         if (cmd_size != sizeof(vfe_cmd_stats_wb_exp_ack))
99                 return -1;
100
101         if (*addr && adsp_pmem_fixup(module, addr, awb_size))
102                 return -1;
103         return 0;
104 }
105
106 static int verify_vfe_command(struct msm_adsp_module *module,
107                               void *cmd_data, size_t cmd_size)
108 {
109         uint32_t cmd_id = ((uint32_t *)cmd_data)[0];
110         switch (cmd_id) {
111         case VFE_CMD_OP1_ACK:
112                 return verify_cmd_op_ack(module, cmd_data, cmd_size);
113         case VFE_CMD_OP2_ACK:
114                 return verify_cmd_op_ack(module, cmd_data, cmd_size);
115         case VFE_CMD_STATS_AUTOFOCUS_CFG:
116                 return verify_cmd_stats_autofocus_cfg(module, cmd_data,
117                                                       cmd_size);
118         case VFE_CMD_STATS_WB_EXP_CFG:
119                 return verify_cmd_stats_wb_exp_cfg(module, cmd_data, cmd_size);
120         case VFE_CMD_STATS_AF_ACK:
121                 return verify_cmd_stats_af_ack(module, cmd_data, cmd_size);
122         case VFE_CMD_STATS_WB_EXP_ACK:
123                 return verify_cmd_stats_wb_exp_ack(module, cmd_data, cmd_size);
124         default:
125                 if (cmd_id > 29) {
126                         printk(KERN_ERR "adsp: module %s: invalid VFE command id %d\n", module->name, cmd_id);
127                         return -1;
128                 }
129         }
130         return 0;
131 }
132
133 static int verify_vfe_command_scale(struct msm_adsp_module *module,
134                                     void *cmd_data, size_t cmd_size)
135 {
136         uint32_t cmd_id = ((uint32_t *)cmd_data)[0];
137         // FIXME: check the size
138         if (cmd_id > 1) {
139                 printk(KERN_ERR "adsp: module %s: invalid VFE SCALE command id %d\n", module->name, cmd_id);
140                 return -1;
141         }
142         return 0;
143 }
144
145
146 static uint32_t get_size(uint32_t hw)
147 {
148         uint32_t height, width;
149         uint32_t height_mask = 0x3ffc;
150         uint32_t width_mask = 0x3ffc000;
151
152         height = (hw & height_mask) >> 2;
153         width = (hw & width_mask) >> 14 ;
154         return height * width;
155 }
156
157 static int verify_vfe_command_table(struct msm_adsp_module *module,
158                                     void *cmd_data, size_t cmd_size)
159 {
160         uint32_t cmd_id = ((uint32_t *)cmd_data)[0];
161         int i;
162
163         switch (cmd_id) {
164         case VFE_CMD_AXI_IP_CFG:
165         {
166                 vfe_cmd_axi_ip_cfg *cmd = (vfe_cmd_axi_ip_cfg *)cmd_data;
167                 uint32_t size;
168                 if (cmd_size != sizeof(vfe_cmd_axi_ip_cfg)) {
169                         printk(KERN_ERR "adsp: module %s: invalid VFE TABLE (VFE_CMD_AXI_IP_CFG) command size %d\n",
170                                 module->name, cmd_size);
171                         return -1;
172                 }
173                 size = get_size(cmd->ip_cfg_part2);
174
175                 for (i = 0; i < 8; i++) {
176                         void **addr = (void **)
177                                 &cmd->ip_buf_addr[i];
178                         if (*addr && adsp_pmem_fixup(module, addr, size))
179                                 return -1;
180                 }
181         }
182         case VFE_CMD_AXI_OP_CFG:
183         {
184                 vfe_cmd_axi_op_cfg *cmd = (vfe_cmd_axi_op_cfg *)cmd_data;
185                 void **addr1_y, **addr2_y, **addr1_cbcr, **addr2_cbcr;
186
187                 if (cmd_size != sizeof(vfe_cmd_axi_op_cfg)) {
188                         printk(KERN_ERR "adsp: module %s: invalid VFE TABLE (VFE_CMD_AXI_OP_CFG) command size %d\n",
189                                 module->name, cmd_size);
190                         return -1;
191                 }
192                 size1_y = get_size(cmd->op1_y_cfg_part2);
193                 size1_cbcr = get_size(cmd->op1_cbcr_cfg_part2);
194                 size2_y = get_size(cmd->op2_y_cfg_part2);
195                 size2_cbcr = get_size(cmd->op2_cbcr_cfg_part2);
196                 for (i = 0; i < 8; i++) {
197                         addr1_y = (void **)(&cmd->op1_buf1_addr[2*i]);
198                         addr1_cbcr = (void **)(&cmd->op1_buf1_addr[2*i+1]);
199                         addr2_y = (void **)(&cmd->op2_buf1_addr[2*i]);
200                         addr2_cbcr = (void **)(&cmd->op2_buf1_addr[2*i+1]);
201 /*
202                         printk("module %s: [%d] %p %p %p %p\n",
203                                 module->name, i,
204                                 *addr1_y, *addr1_cbcr, *addr2_y, *addr2_cbcr);
205 */
206                         if ((*addr1_y && adsp_pmem_fixup(module, addr1_y, size1_y)) ||
207                             (*addr1_cbcr && adsp_pmem_fixup(module, addr1_cbcr, size1_cbcr)) ||
208                             (*addr2_y && adsp_pmem_fixup(module, addr2_y, size2_y)) ||
209                             (*addr2_cbcr && adsp_pmem_fixup(module, addr2_cbcr, size2_cbcr)))
210                                 return -1;
211                 }
212         }
213         default:
214                 if (cmd_id > 4) {
215                         printk(KERN_ERR "adsp: module %s: invalid VFE TABLE command id %d\n",
216                                 module->name, cmd_id);
217                         return -1;
218                 }
219         }
220         return 0;
221 }
222
223 int adsp_vfe_verify_cmd(struct msm_adsp_module *module,
224                         unsigned int queue_id, void *cmd_data,
225                         size_t cmd_size)
226 {
227         switch (queue_id) {
228         case QDSP_vfeCommandQueue:
229                 return verify_vfe_command(module, cmd_data, cmd_size);
230         case QDSP_vfeCommandScaleQueue:
231                 return verify_vfe_command_scale(module, cmd_data, cmd_size);
232         case QDSP_vfeCommandTableQueue:
233                 return verify_vfe_command_table(module, cmd_data, cmd_size);
234         default:
235                 printk(KERN_ERR "adsp: module %s: unknown queue id %d\n",
236                         module->name, queue_id);
237                 return -1;
238         }
239 }