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