1 /* 2 * Support for Intel Camera Imaging ISP subsystem. 3 * Copyright (c) 2015, Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 */ 14 15 #include "hmm.h" 16 17 #include <assert_support.h> 18 #include "ia_css_debug.h" 19 #include "ia_css_sdis2.host.h" 20 21 const struct ia_css_dvs2_coefficients default_sdis2_config = { 22 .grid = { 0, 0, 0, 0, 0, 0, 0, 0 }, 23 .hor_coefs = { NULL, NULL, NULL, NULL }, 24 .ver_coefs = { NULL, NULL, NULL, NULL }, 25 }; 26 27 static void 28 fill_row(short *private, const short *public, unsigned int width, 29 unsigned int padding) 30 { 31 memcpy(private, public, width * sizeof(short)); 32 memset(&private[width], 0, padding * sizeof(short)); 33 } 34 35 void ia_css_sdis2_horicoef_vmem_encode( 36 struct sh_css_isp_sdis_hori_coef_tbl *to, 37 const struct ia_css_dvs2_coefficients *from, 38 unsigned int size) 39 { 40 unsigned int aligned_width = from->grid.aligned_width * 41 from->grid.bqs_per_grid_cell; 42 unsigned int width = from->grid.num_hor_coefs; 43 int padding = aligned_width - width; 44 unsigned int stride = size / IA_CSS_DVS2_NUM_COEF_TYPES / sizeof(short); 45 unsigned int total_bytes = aligned_width * IA_CSS_DVS2_NUM_COEF_TYPES * 46 sizeof(short); 47 short *private = (short *)to; 48 49 /* Copy the table, add padding */ 50 assert(padding >= 0); 51 assert(total_bytes <= size); 52 assert(size % (IA_CSS_DVS2_NUM_COEF_TYPES * ISP_VEC_NELEMS * sizeof( 53 short)) == 0); 54 fill_row(&private[0 * stride], from->hor_coefs.odd_real, width, padding); 55 fill_row(&private[1 * stride], from->hor_coefs.odd_imag, width, padding); 56 fill_row(&private[2 * stride], from->hor_coefs.even_real, width, padding); 57 fill_row(&private[3 * stride], from->hor_coefs.even_imag, width, padding); 58 } 59 60 void ia_css_sdis2_vertcoef_vmem_encode( 61 struct sh_css_isp_sdis_vert_coef_tbl *to, 62 const struct ia_css_dvs2_coefficients *from, 63 unsigned int size) 64 { 65 unsigned int aligned_height = from->grid.aligned_height * 66 from->grid.bqs_per_grid_cell; 67 unsigned int height = from->grid.num_ver_coefs; 68 int padding = aligned_height - height; 69 unsigned int stride = size / IA_CSS_DVS2_NUM_COEF_TYPES / sizeof(short); 70 unsigned int total_bytes = aligned_height * IA_CSS_DVS2_NUM_COEF_TYPES * 71 sizeof(short); 72 short *private = (short *)to; 73 74 /* Copy the table, add padding */ 75 assert(padding >= 0); 76 assert(total_bytes <= size); 77 assert(size % (IA_CSS_DVS2_NUM_COEF_TYPES * ISP_VEC_NELEMS * sizeof( 78 short)) == 0); 79 fill_row(&private[0 * stride], from->ver_coefs.odd_real, height, padding); 80 fill_row(&private[1 * stride], from->ver_coefs.odd_imag, height, padding); 81 fill_row(&private[2 * stride], from->ver_coefs.even_real, height, padding); 82 fill_row(&private[3 * stride], from->ver_coefs.even_imag, height, padding); 83 } 84 85 void ia_css_sdis2_horiproj_encode( 86 struct sh_css_isp_sdis_hori_proj_tbl *to, 87 const struct ia_css_dvs2_coefficients *from, 88 unsigned int size) 89 { 90 (void)to; 91 (void)from; 92 (void)size; 93 } 94 95 void ia_css_sdis2_vertproj_encode( 96 struct sh_css_isp_sdis_vert_proj_tbl *to, 97 const struct ia_css_dvs2_coefficients *from, 98 unsigned int size) 99 { 100 (void)to; 101 (void)from; 102 (void)size; 103 } 104 105 void ia_css_get_isp_dvs2_coefficients( 106 struct ia_css_stream *stream, 107 short *hor_coefs_odd_real, 108 short *hor_coefs_odd_imag, 109 short *hor_coefs_even_real, 110 short *hor_coefs_even_imag, 111 short *ver_coefs_odd_real, 112 short *ver_coefs_odd_imag, 113 short *ver_coefs_even_real, 114 short *ver_coefs_even_imag) 115 { 116 struct ia_css_isp_parameters *params; 117 unsigned int hor_num_3a, ver_num_3a; 118 unsigned int hor_num_isp, ver_num_isp; 119 struct ia_css_binary *dvs_binary; 120 121 IA_CSS_ENTER("void"); 122 123 assert(stream); 124 assert(hor_coefs_odd_real); 125 assert(hor_coefs_odd_imag); 126 assert(hor_coefs_even_real); 127 assert(hor_coefs_even_imag); 128 assert(ver_coefs_odd_real); 129 assert(ver_coefs_odd_imag); 130 assert(ver_coefs_even_real); 131 assert(ver_coefs_even_imag); 132 133 params = stream->isp_params_configs; 134 135 /* Only video pipe supports DVS */ 136 dvs_binary = ia_css_stream_get_dvs_binary(stream); 137 if (!dvs_binary) 138 return; 139 140 hor_num_3a = dvs_binary->dis.coef.dim.width; 141 ver_num_3a = dvs_binary->dis.coef.dim.height; 142 hor_num_isp = dvs_binary->dis.coef.pad.width; 143 ver_num_isp = dvs_binary->dis.coef.pad.height; 144 145 memcpy(hor_coefs_odd_real, params->dvs2_coefs.hor_coefs.odd_real, 146 hor_num_3a * sizeof(short)); 147 memcpy(hor_coefs_odd_imag, params->dvs2_coefs.hor_coefs.odd_imag, 148 hor_num_3a * sizeof(short)); 149 memcpy(hor_coefs_even_real, params->dvs2_coefs.hor_coefs.even_real, 150 hor_num_3a * sizeof(short)); 151 memcpy(hor_coefs_even_imag, params->dvs2_coefs.hor_coefs.even_imag, 152 hor_num_3a * sizeof(short)); 153 memcpy(ver_coefs_odd_real, params->dvs2_coefs.ver_coefs.odd_real, 154 ver_num_3a * sizeof(short)); 155 memcpy(ver_coefs_odd_imag, params->dvs2_coefs.ver_coefs.odd_imag, 156 ver_num_3a * sizeof(short)); 157 memcpy(ver_coefs_even_real, params->dvs2_coefs.ver_coefs.even_real, 158 ver_num_3a * sizeof(short)); 159 memcpy(ver_coefs_even_imag, params->dvs2_coefs.ver_coefs.even_imag, 160 ver_num_3a * sizeof(short)); 161 162 IA_CSS_LEAVE("void"); 163 } 164 165 void ia_css_sdis2_clear_coefficients( 166 struct ia_css_dvs2_coefficients *dvs2_coefs) 167 { 168 dvs2_coefs->hor_coefs.odd_real = NULL; 169 dvs2_coefs->hor_coefs.odd_imag = NULL; 170 dvs2_coefs->hor_coefs.even_real = NULL; 171 dvs2_coefs->hor_coefs.even_imag = NULL; 172 dvs2_coefs->ver_coefs.odd_real = NULL; 173 dvs2_coefs->ver_coefs.odd_imag = NULL; 174 dvs2_coefs->ver_coefs.even_real = NULL; 175 dvs2_coefs->ver_coefs.even_imag = NULL; 176 } 177 178 int 179 ia_css_get_dvs2_statistics( 180 struct ia_css_dvs2_statistics *host_stats, 181 const struct ia_css_isp_dvs_statistics *isp_stats) { 182 struct ia_css_isp_dvs_statistics_map *map; 183 int ret = 0; 184 185 IA_CSS_ENTER("host_stats=%p, isp_stats=%p", host_stats, isp_stats); 186 187 assert(host_stats); 188 assert(isp_stats); 189 190 map = ia_css_isp_dvs_statistics_map_allocate(isp_stats, NULL); 191 if (map) 192 { 193 hmm_load(isp_stats->data_ptr, map->data_ptr, isp_stats->size); 194 ia_css_translate_dvs2_statistics(host_stats, map); 195 ia_css_isp_dvs_statistics_map_free(map); 196 } else 197 { 198 IA_CSS_ERROR("out of memory"); 199 ret = -ENOMEM; 200 } 201 202 IA_CSS_LEAVE_ERR(ret); 203 return ret; 204 } 205 206 void 207 ia_css_translate_dvs2_statistics( 208 struct ia_css_dvs2_statistics *host_stats, 209 const struct ia_css_isp_dvs_statistics_map *isp_stats) 210 { 211 unsigned int size_bytes, table_width, table_size, height; 212 unsigned int src_offset = 0, dst_offset = 0; 213 s32 *htemp_ptr, *vtemp_ptr; 214 215 assert(host_stats); 216 assert(host_stats->hor_prod.odd_real); 217 assert(host_stats->hor_prod.odd_imag); 218 assert(host_stats->hor_prod.even_real); 219 assert(host_stats->hor_prod.even_imag); 220 assert(host_stats->ver_prod.odd_real); 221 assert(host_stats->ver_prod.odd_imag); 222 assert(host_stats->ver_prod.even_real); 223 assert(host_stats->ver_prod.even_imag); 224 assert(isp_stats); 225 assert(isp_stats->hor_proj); 226 assert(isp_stats->ver_proj); 227 228 IA_CSS_ENTER("hor_coefs.odd_real=%p, hor_coefs.odd_imag=%p, hor_coefs.even_real=%p, hor_coefs.even_imag=%p, ver_coefs.odd_real=%p, ver_coefs.odd_imag=%p, ver_coefs.even_real=%p, ver_coefs.even_imag=%p, haddr=%p, vaddr=%p", 229 host_stats->hor_prod.odd_real, host_stats->hor_prod.odd_imag, 230 host_stats->hor_prod.even_real, host_stats->hor_prod.even_imag, 231 host_stats->ver_prod.odd_real, host_stats->ver_prod.odd_imag, 232 host_stats->ver_prod.even_real, host_stats->ver_prod.even_imag, 233 isp_stats->hor_proj, isp_stats->ver_proj); 234 235 /* Host side: reflecting the true width in bytes */ 236 size_bytes = host_stats->grid.aligned_width * sizeof(*htemp_ptr); 237 238 /* DDR side: need to be aligned to the system bus width */ 239 /* statistics table width in terms of 32-bit words*/ 240 table_width = CEIL_MUL(size_bytes, 241 HIVE_ISP_DDR_WORD_BYTES) / sizeof(*htemp_ptr); 242 table_size = table_width * host_stats->grid.aligned_height; 243 244 htemp_ptr = isp_stats->hor_proj; /* horizontal stats */ 245 vtemp_ptr = isp_stats->ver_proj; /* vertical stats */ 246 for (height = 0; height < host_stats->grid.aligned_height; height++) { 247 /* hor stats */ 248 memcpy(host_stats->hor_prod.odd_real + dst_offset, 249 &htemp_ptr[0 * table_size + src_offset], size_bytes); 250 memcpy(host_stats->hor_prod.odd_imag + dst_offset, 251 &htemp_ptr[1 * table_size + src_offset], size_bytes); 252 memcpy(host_stats->hor_prod.even_real + dst_offset, 253 &htemp_ptr[2 * table_size + src_offset], size_bytes); 254 memcpy(host_stats->hor_prod.even_imag + dst_offset, 255 &htemp_ptr[3 * table_size + src_offset], size_bytes); 256 257 /* ver stats */ 258 memcpy(host_stats->ver_prod.odd_real + dst_offset, 259 &vtemp_ptr[0 * table_size + src_offset], size_bytes); 260 memcpy(host_stats->ver_prod.odd_imag + dst_offset, 261 &vtemp_ptr[1 * table_size + src_offset], size_bytes); 262 memcpy(host_stats->ver_prod.even_real + dst_offset, 263 &vtemp_ptr[2 * table_size + src_offset], size_bytes); 264 memcpy(host_stats->ver_prod.even_imag + dst_offset, 265 &vtemp_ptr[3 * table_size + src_offset], size_bytes); 266 267 src_offset += table_width; /* aligned table width */ 268 dst_offset += host_stats->grid.aligned_width; 269 } 270 271 IA_CSS_LEAVE("void"); 272 } 273 274 struct ia_css_isp_dvs_statistics * 275 ia_css_isp_dvs2_statistics_allocate( 276 const struct ia_css_dvs_grid_info *grid) 277 { 278 struct ia_css_isp_dvs_statistics *me; 279 int size; 280 281 assert(grid); 282 283 IA_CSS_ENTER("grid=%p", grid); 284 285 if (!grid->enable) 286 return NULL; 287 288 me = kvcalloc(1, sizeof(*me), GFP_KERNEL); 289 if (!me) 290 goto err; 291 292 /* on ISP 2 SDIS DMA model, every row of projection table width must be 293 aligned to HIVE_ISP_DDR_WORD_BYTES 294 */ 295 size = CEIL_MUL(sizeof(int) * grid->aligned_width, HIVE_ISP_DDR_WORD_BYTES) 296 * grid->aligned_height * IA_CSS_DVS2_NUM_COEF_TYPES; 297 298 me->size = 2 * size; 299 me->data_ptr = hmm_alloc(me->size, HMM_BO_PRIVATE, 0, NULL, 0); 300 if (me->data_ptr == mmgr_NULL) 301 goto err; 302 me->hor_proj = me->data_ptr; 303 me->hor_size = size; 304 me->ver_proj = me->data_ptr + size; 305 me->ver_size = size; 306 307 IA_CSS_LEAVE("return=%p", me); 308 return me; 309 err: 310 ia_css_isp_dvs2_statistics_free(me); 311 IA_CSS_LEAVE("return=%p", NULL); 312 313 return NULL; 314 } 315 316 void 317 ia_css_isp_dvs2_statistics_free(struct ia_css_isp_dvs_statistics *me) 318 { 319 if (me) { 320 hmm_free(me->data_ptr); 321 kvfree(me); 322 } 323 } 324 325 void ia_css_sdis2_horicoef_debug_dtrace( 326 const struct ia_css_dvs2_coefficients *config, unsigned int level) 327 { 328 (void)config; 329 (void)level; 330 } 331 332 void ia_css_sdis2_vertcoef_debug_dtrace( 333 const struct ia_css_dvs2_coefficients *config, unsigned int level) 334 { 335 (void)config; 336 (void)level; 337 } 338 339 void ia_css_sdis2_horiproj_debug_dtrace( 340 const struct ia_css_dvs2_coefficients *config, unsigned int level) 341 { 342 (void)config; 343 (void)level; 344 } 345 346 void ia_css_sdis2_vertproj_debug_dtrace( 347 const struct ia_css_dvs2_coefficients *config, unsigned int level) 348 { 349 (void)config; 350 (void)level; 351 } 352