1/* arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c 2 * 3 * Verificion code for aDSP VENC 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#include <linux/io.h> 19 20#define ADSP_DEBUG_MSGS 0 21#if ADSP_DEBUG_MSGS 22#define DLOG(fmt,args...) \ 23 do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \ 24 ##args); } \ 25 while (0) 26#else 27#define DLOG(x...) do {} while (0) 28#endif 29 30#include <mach/qdsp5/qdsp5venccmdi.h> 31#include "adsp.h" 32 33 34static unsigned short x_dimension, y_dimension; 35 36static inline void *high_low_short_to_ptr(unsigned short high, 37 unsigned short low) 38{ 39 return (void *)((((unsigned long)high) << 16) | ((unsigned long)low)); 40} 41 42static inline void ptr_to_high_low_short(void *ptr, unsigned short *high, 43 unsigned short *low) 44{ 45 *high = (unsigned short)((((unsigned long)ptr) >> 16) & 0xffff); 46 *low = (unsigned short)((unsigned long)ptr & 0xffff); 47} 48 49static int pmem_fixup_high_low(unsigned short *high, 50 unsigned short *low, 51 unsigned short size_high, 52 unsigned short size_low, 53 struct msm_adsp_module *module, 54 unsigned long *addr, unsigned long *size) 55{ 56 void *phys_addr; 57 unsigned long phys_size; 58 unsigned long kvaddr; 59 60 phys_addr = high_low_short_to_ptr(*high, *low); 61 phys_size = (unsigned long)high_low_short_to_ptr(size_high, size_low); 62 DLOG("virt %x %x\n", phys_addr, phys_size); 63 if (adsp_pmem_fixup_kvaddr(module, &phys_addr, &kvaddr, phys_size)) { 64 DLOG("ah%x al%x sh%x sl%x addr %x size %x\n", 65 *high, *low, size_high, size_low, phys_addr, phys_size); 66 return -1; 67 } 68 ptr_to_high_low_short(phys_addr, high, low); 69 DLOG("phys %x %x\n", phys_addr, phys_size); 70 if (addr) 71 *addr = kvaddr; 72 if (size) 73 *size = phys_size; 74 return 0; 75} 76 77static int verify_venc_cmd(struct msm_adsp_module *module, 78 void *cmd_data, size_t cmd_size) 79{ 80 unsigned short cmd_id = ((unsigned short *)cmd_data)[0]; 81 unsigned long frame_buf_size, luma_buf_size, chroma_buf_size; 82 unsigned short frame_buf_size_high, frame_buf_size_low; 83 unsigned short luma_buf_size_high, luma_buf_size_low; 84 unsigned short chroma_buf_size_high, chroma_buf_size_low; 85 videnc_cmd_cfg *config_cmd; 86 videnc_cmd_frame_start *frame_cmd; 87 videnc_cmd_dis *dis_cmd; 88 89 DLOG("cmd_size %d cmd_id %d cmd_data %x\n", cmd_size, cmd_id, cmd_data); 90 switch (cmd_id) { 91 case VIDENC_CMD_ACTIVE: 92 if (cmd_size < sizeof(videnc_cmd_active)) 93 return -1; 94 break; 95 case VIDENC_CMD_IDLE: 96 if (cmd_size < sizeof(videnc_cmd_idle)) 97 return -1; 98 x_dimension = y_dimension = 0; 99 break; 100 case VIDENC_CMD_STATUS_QUERY: 101 if (cmd_size < sizeof(videnc_cmd_status_query)) 102 return -1; 103 break; 104 case VIDENC_CMD_RC_CFG: 105 if (cmd_size < sizeof(videnc_cmd_rc_cfg)) 106 return -1; 107 break; 108 case VIDENC_CMD_INTRA_REFRESH: 109 if (cmd_size < sizeof(videnc_cmd_intra_refresh)) 110 return -1; 111 break; 112 case VIDENC_CMD_DIGITAL_ZOOM: 113 if (cmd_size < sizeof(videnc_cmd_digital_zoom)) 114 return -1; 115 break; 116 case VIDENC_CMD_DIS_CFG: 117 if (cmd_size < sizeof(videnc_cmd_dis_cfg)) 118 return -1; 119 break; 120 case VIDENC_CMD_CFG: 121 if (cmd_size < sizeof(videnc_cmd_cfg)) 122 return -1; 123 config_cmd = (videnc_cmd_cfg *)cmd_data; 124 x_dimension = ((config_cmd->venc_frame_dim) & 0xFF00)>>8; 125 x_dimension = x_dimension*16; 126 y_dimension = (config_cmd->venc_frame_dim) & 0xFF; 127 y_dimension = y_dimension * 16; 128 break; 129 case VIDENC_CMD_FRAME_START: 130 if (cmd_size < sizeof(videnc_cmd_frame_start)) 131 return -1; 132 frame_cmd = (videnc_cmd_frame_start *)cmd_data; 133 luma_buf_size = x_dimension * y_dimension; 134 chroma_buf_size = luma_buf_size>>1; 135 frame_buf_size = luma_buf_size + chroma_buf_size; 136 ptr_to_high_low_short((void *)luma_buf_size, 137 &luma_buf_size_high, 138 &luma_buf_size_low); 139 ptr_to_high_low_short((void *)chroma_buf_size, 140 &chroma_buf_size_high, 141 &chroma_buf_size_low); 142 ptr_to_high_low_short((void *)frame_buf_size, 143 &frame_buf_size_high, 144 &frame_buf_size_low); 145 /* Address of raw Y data. */ 146 if (pmem_fixup_high_low(&frame_cmd->input_luma_addr_high, 147 &frame_cmd->input_luma_addr_low, 148 luma_buf_size_high, 149 luma_buf_size_low, 150 module, 151 NULL, NULL)) 152 return -1; 153 /* Address of raw CbCr data */ 154 if (pmem_fixup_high_low(&frame_cmd->input_chroma_addr_high, 155 &frame_cmd->input_chroma_addr_low, 156 chroma_buf_size_high, 157 chroma_buf_size_low, 158 module, 159 NULL, NULL)) 160 return -1; 161 /* Reference VOP */ 162 if (pmem_fixup_high_low(&frame_cmd->ref_vop_buf_ptr_high, 163 &frame_cmd->ref_vop_buf_ptr_low, 164 frame_buf_size_high, 165 frame_buf_size_low, 166 module, 167 NULL, NULL)) 168 return -1; 169 /* Encoded Packet Address */ 170 if (pmem_fixup_high_low(&frame_cmd->enc_pkt_buf_ptr_high, 171 &frame_cmd->enc_pkt_buf_ptr_low, 172 frame_cmd->enc_pkt_buf_size_high, 173 frame_cmd->enc_pkt_buf_size_low, 174 module, 175 NULL, NULL)) 176 return -1; 177 /* Unfiltered VOP Buffer Address */ 178 if (pmem_fixup_high_low( 179 &frame_cmd->unfilt_recon_vop_buf_ptr_high, 180 &frame_cmd->unfilt_recon_vop_buf_ptr_low, 181 frame_buf_size_high, 182 frame_buf_size_low, 183 module, 184 NULL, NULL)) 185 return -1; 186 /* Filtered VOP Buffer Address */ 187 if (pmem_fixup_high_low(&frame_cmd->filt_recon_vop_buf_ptr_high, 188 &frame_cmd->filt_recon_vop_buf_ptr_low, 189 frame_buf_size_high, 190 frame_buf_size_low, 191 module, 192 NULL, NULL)) 193 return -1; 194 break; 195 case VIDENC_CMD_DIS: 196 if (cmd_size < sizeof(videnc_cmd_dis)) 197 return -1; 198 dis_cmd = (videnc_cmd_dis *)cmd_data; 199 luma_buf_size = x_dimension * y_dimension; 200 ptr_to_high_low_short((void *)luma_buf_size, 201 &luma_buf_size_high, 202 &luma_buf_size_low); 203 /* Prev VFE Luma Output Address */ 204 if (pmem_fixup_high_low(&dis_cmd->vfe_out_prev_luma_addr_high, 205 &dis_cmd->vfe_out_prev_luma_addr_low, 206 luma_buf_size_high, 207 luma_buf_size_low, 208 module, 209 NULL, NULL)) 210 return -1; 211 break; 212 default: 213 printk(KERN_INFO "adsp_video:unknown encoder video command %u\n", 214 cmd_id); 215 return 0; 216 } 217 218 return 0; 219} 220 221 222int adsp_videoenc_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_mpuVEncCmdQueue: 228 DLOG("\n"); 229 return verify_venc_cmd(module, cmd_data, cmd_size); 230 default: 231 printk(KERN_INFO "unknown video queue %u\n", queue_id); 232 return 0; 233 } 234} 235