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 22static uint32_t size1_y, size2_y, size1_cbcr, size2_cbcr; 23static uint32_t af_size = 4228; 24static uint32_t awb_size = 8196; 25 26static 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 41static 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 59static 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 77static 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 91static 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 106static 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 133static 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 if (cmd_id > 1) { 138 printk(KERN_ERR "adsp: module %s: invalid VFE SCALE command id %d\n", module->name, cmd_id); 139 return -1; 140 } 141 return 0; 142} 143 144 145static uint32_t get_size(uint32_t hw) 146{ 147 uint32_t height, width; 148 uint32_t height_mask = 0x3ffc; 149 uint32_t width_mask = 0x3ffc000; 150 151 height = (hw & height_mask) >> 2; 152 width = (hw & width_mask) >> 14 ; 153 return height * width; 154} 155 156static int verify_vfe_command_table(struct msm_adsp_module *module, 157 void *cmd_data, size_t cmd_size) 158{ 159 uint32_t cmd_id = ((uint32_t *)cmd_data)[0]; 160 int i; 161 162 switch (cmd_id) { 163 case VFE_CMD_AXI_IP_CFG: 164 { 165 vfe_cmd_axi_ip_cfg *cmd = (vfe_cmd_axi_ip_cfg *)cmd_data; 166 uint32_t size; 167 if (cmd_size != sizeof(vfe_cmd_axi_ip_cfg)) { 168 printk(KERN_ERR "adsp: module %s: invalid VFE TABLE (VFE_CMD_AXI_IP_CFG) command size %d\n", 169 module->name, cmd_size); 170 return -1; 171 } 172 size = get_size(cmd->ip_cfg_part2); 173 174 for (i = 0; i < 8; i++) { 175 void **addr = (void **) 176 &cmd->ip_buf_addr[i]; 177 if (*addr && adsp_pmem_fixup(module, addr, size)) 178 return -1; 179 } 180 } 181 case VFE_CMD_AXI_OP_CFG: 182 { 183 vfe_cmd_axi_op_cfg *cmd = (vfe_cmd_axi_op_cfg *)cmd_data; 184 void **addr1_y, **addr2_y, **addr1_cbcr, **addr2_cbcr; 185 186 if (cmd_size != sizeof(vfe_cmd_axi_op_cfg)) { 187 printk(KERN_ERR "adsp: module %s: invalid VFE TABLE (VFE_CMD_AXI_OP_CFG) command size %d\n", 188 module->name, cmd_size); 189 return -1; 190 } 191 size1_y = get_size(cmd->op1_y_cfg_part2); 192 size1_cbcr = get_size(cmd->op1_cbcr_cfg_part2); 193 size2_y = get_size(cmd->op2_y_cfg_part2); 194 size2_cbcr = get_size(cmd->op2_cbcr_cfg_part2); 195 for (i = 0; i < 8; i++) { 196 addr1_y = (void **)(&cmd->op1_buf1_addr[2*i]); 197 addr1_cbcr = (void **)(&cmd->op1_buf1_addr[2*i+1]); 198 addr2_y = (void **)(&cmd->op2_buf1_addr[2*i]); 199 addr2_cbcr = (void **)(&cmd->op2_buf1_addr[2*i+1]); 200/* 201 printk("module %s: [%d] %p %p %p %p\n", 202 module->name, i, 203 *addr1_y, *addr1_cbcr, *addr2_y, *addr2_cbcr); 204*/ 205 if ((*addr1_y && adsp_pmem_fixup(module, addr1_y, size1_y)) || 206 (*addr1_cbcr && adsp_pmem_fixup(module, addr1_cbcr, size1_cbcr)) || 207 (*addr2_y && adsp_pmem_fixup(module, addr2_y, size2_y)) || 208 (*addr2_cbcr && adsp_pmem_fixup(module, addr2_cbcr, size2_cbcr))) 209 return -1; 210 } 211 } 212 default: 213 if (cmd_id > 4) { 214 printk(KERN_ERR "adsp: module %s: invalid VFE TABLE command id %d\n", 215 module->name, cmd_id); 216 return -1; 217 } 218 } 219 return 0; 220} 221 222int adsp_vfe_verify_cmd(struct msm_adsp_module *module, 223 unsigned int queue_id, void *cmd_data, 224 size_t cmd_size) 225{ 226 switch (queue_id) { 227 case QDSP_vfeCommandQueue: 228 return verify_vfe_command(module, cmd_data, cmd_size); 229 case QDSP_vfeCommandScaleQueue: 230 return verify_vfe_command_scale(module, cmd_data, cmd_size); 231 case QDSP_vfeCommandTableQueue: 232 return verify_vfe_command_table(module, cmd_data, cmd_size); 233 default: 234 printk(KERN_ERR "adsp: module %s: unknown queue id %d\n", 235 module->name, queue_id); 236 return -1; 237 } 238} 239