1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Support for Clovertrail PNW Camera Imaging ISP subsystem. 4 * 5 * Copyright (c) 2013 Intel Corporation. All Rights Reserved. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License version 9 * 2 as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * 17 */ 18 19 #include <media/v4l2-dev.h> 20 #include <media/v4l2-event.h> 21 22 #include "mmu/isp_mmu.h" 23 #include "mmu/sh_mmu_mrfld.h" 24 #include "hmm/hmm_bo.h" 25 #include "hmm/hmm.h" 26 27 #include "atomisp_compat.h" 28 #include "atomisp_internal.h" 29 #include "atomisp_cmd.h" 30 #include "atomisp-regs.h" 31 #include "atomisp_fops.h" 32 #include "atomisp_ioctl.h" 33 34 #include "ia_css_debug.h" 35 #include "ia_css_isp_param.h" 36 #include "sh_css_hrt.h" 37 #include "ia_css_isys.h" 38 39 #include <linux/io.h> 40 #include <linux/pm_runtime.h> 41 42 /* Assume max number of ACC stages */ 43 #define MAX_ACC_STAGES 20 44 45 /* Ideally, this should come from CSS headers */ 46 #define NO_LINK -1 47 48 /* 49 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting 50 * #4684168, if concurrency access happened, system may hard hang. 51 */ 52 static DEFINE_SPINLOCK(mmio_lock); 53 54 enum frame_info_type { 55 ATOMISP_CSS_VF_FRAME, 56 ATOMISP_CSS_SECOND_VF_FRAME, 57 ATOMISP_CSS_OUTPUT_FRAME, 58 ATOMISP_CSS_SECOND_OUTPUT_FRAME, 59 ATOMISP_CSS_RAW_FRAME, 60 }; 61 62 struct bayer_ds_factor { 63 unsigned int numerator; 64 unsigned int denominator; 65 }; 66 atomisp_css2_hw_store_8(hrt_address addr,uint8_t data)67 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data) 68 { 69 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); 70 unsigned long flags; 71 72 spin_lock_irqsave(&mmio_lock, flags); 73 writeb(data, isp->base + (addr & 0x003FFFFF)); 74 spin_unlock_irqrestore(&mmio_lock, flags); 75 } 76 atomisp_css2_hw_store_16(hrt_address addr,uint16_t data)77 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data) 78 { 79 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); 80 unsigned long flags; 81 82 spin_lock_irqsave(&mmio_lock, flags); 83 writew(data, isp->base + (addr & 0x003FFFFF)); 84 spin_unlock_irqrestore(&mmio_lock, flags); 85 } 86 atomisp_css2_hw_store_32(hrt_address addr,uint32_t data)87 void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data) 88 { 89 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); 90 unsigned long flags; 91 92 spin_lock_irqsave(&mmio_lock, flags); 93 writel(data, isp->base + (addr & 0x003FFFFF)); 94 spin_unlock_irqrestore(&mmio_lock, flags); 95 } 96 atomisp_css2_hw_load_8(hrt_address addr)97 static uint8_t atomisp_css2_hw_load_8(hrt_address addr) 98 { 99 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); 100 unsigned long flags; 101 u8 ret; 102 103 spin_lock_irqsave(&mmio_lock, flags); 104 ret = readb(isp->base + (addr & 0x003FFFFF)); 105 spin_unlock_irqrestore(&mmio_lock, flags); 106 return ret; 107 } 108 atomisp_css2_hw_load_16(hrt_address addr)109 static uint16_t atomisp_css2_hw_load_16(hrt_address addr) 110 { 111 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); 112 unsigned long flags; 113 u16 ret; 114 115 spin_lock_irqsave(&mmio_lock, flags); 116 ret = readw(isp->base + (addr & 0x003FFFFF)); 117 spin_unlock_irqrestore(&mmio_lock, flags); 118 return ret; 119 } 120 atomisp_css2_hw_load_32(hrt_address addr)121 static uint32_t atomisp_css2_hw_load_32(hrt_address addr) 122 { 123 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); 124 unsigned long flags; 125 u32 ret; 126 127 spin_lock_irqsave(&mmio_lock, flags); 128 ret = readl(isp->base + (addr & 0x003FFFFF)); 129 spin_unlock_irqrestore(&mmio_lock, flags); 130 return ret; 131 } 132 atomisp_css2_hw_store(hrt_address addr,const void * from,uint32_t n)133 static void atomisp_css2_hw_store(hrt_address addr, const void *from, uint32_t n) 134 { 135 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); 136 unsigned long flags; 137 unsigned int i; 138 139 addr &= 0x003FFFFF; 140 spin_lock_irqsave(&mmio_lock, flags); 141 for (i = 0; i < n; i++, from++) 142 writeb(*(s8 *)from, isp->base + addr + i); 143 144 spin_unlock_irqrestore(&mmio_lock, flags); 145 } 146 atomisp_css2_hw_load(hrt_address addr,void * to,uint32_t n)147 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n) 148 { 149 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); 150 unsigned long flags; 151 unsigned int i; 152 153 addr &= 0x003FFFFF; 154 spin_lock_irqsave(&mmio_lock, flags); 155 for (i = 0; i < n; i++, to++) 156 *(s8 *)to = readb(isp->base + addr + i); 157 spin_unlock_irqrestore(&mmio_lock, flags); 158 } 159 atomisp_vprintk(const char * fmt,va_list args)160 static int __printf(1, 0) atomisp_vprintk(const char *fmt, va_list args) 161 { 162 vprintk(fmt, args); 163 return 0; 164 } 165 atomisp_load_uint32(hrt_address addr,uint32_t * data)166 void atomisp_load_uint32(hrt_address addr, uint32_t *data) 167 { 168 *data = atomisp_css2_hw_load_32(addr); 169 } 170 hmm_get_mmu_base_addr(struct device * dev,unsigned int * mmu_base_addr)171 static int hmm_get_mmu_base_addr(struct device *dev, unsigned int *mmu_base_addr) 172 { 173 if (!sh_mmu_mrfld.get_pd_base) { 174 dev_err(dev, "get mmu base address failed.\n"); 175 return -EINVAL; 176 } 177 178 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu, 179 bo_device.mmu.base_address); 180 return 0; 181 } 182 __dump_pipe_config(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env,unsigned int pipe_id)183 static void __dump_pipe_config(struct atomisp_sub_device *asd, 184 struct atomisp_stream_env *stream_env, 185 unsigned int pipe_id) 186 { 187 struct atomisp_device *isp = asd->isp; 188 189 if (stream_env->pipes[pipe_id]) { 190 struct ia_css_pipe_config *p_config; 191 struct ia_css_pipe_extra_config *pe_config; 192 193 p_config = &stream_env->pipe_configs[pipe_id]; 194 pe_config = &stream_env->pipe_extra_configs[pipe_id]; 195 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id); 196 dev_dbg(isp->dev, 197 "pipe_config.pipe_mode:%d.\n", p_config->mode); 198 dev_dbg(isp->dev, 199 "pipe_config.output_info[0] w=%d, h=%d.\n", 200 p_config->output_info[0].res.width, 201 p_config->output_info[0].res.height); 202 dev_dbg(isp->dev, 203 "pipe_config.vf_pp_in_res w=%d, h=%d.\n", 204 p_config->vf_pp_in_res.width, 205 p_config->vf_pp_in_res.height); 206 dev_dbg(isp->dev, 207 "pipe_config.capt_pp_in_res w=%d, h=%d.\n", 208 p_config->capt_pp_in_res.width, 209 p_config->capt_pp_in_res.height); 210 dev_dbg(isp->dev, 211 "pipe_config.output.padded w=%d.\n", 212 p_config->output_info[0].padded_width); 213 dev_dbg(isp->dev, 214 "pipe_config.vf_output_info[0] w=%d, h=%d.\n", 215 p_config->vf_output_info[0].res.width, 216 p_config->vf_output_info[0].res.height); 217 dev_dbg(isp->dev, 218 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n", 219 p_config->bayer_ds_out_res.width, 220 p_config->bayer_ds_out_res.height); 221 dev_dbg(isp->dev, 222 "pipe_config.envelope w=%d, h=%d.\n", 223 p_config->dvs_envelope.width, 224 p_config->dvs_envelope.height); 225 dev_dbg(isp->dev, 226 "pipe_config.dvs_frame_delay=%d.\n", 227 p_config->dvs_frame_delay); 228 dev_dbg(isp->dev, 229 "pipe_config.isp_pipe_version:%d.\n", 230 p_config->isp_pipe_version); 231 dev_dbg(isp->dev, 232 "pipe_config.default_capture_config.capture_mode=%d.\n", 233 p_config->default_capture_config.mode); 234 dev_dbg(isp->dev, 235 "pipe_config.enable_dz=%d.\n", 236 p_config->enable_dz); 237 dev_dbg(isp->dev, 238 "pipe_config.default_capture_config.enable_xnr=%d.\n", 239 p_config->default_capture_config.enable_xnr); 240 dev_dbg(isp->dev, 241 "dumping pipe[%d] extra config:\n", pipe_id); 242 dev_dbg(isp->dev, 243 "pipe_extra_config.enable_raw_binning:%d.\n", 244 pe_config->enable_raw_binning); 245 dev_dbg(isp->dev, 246 "pipe_extra_config.enable_yuv_ds:%d.\n", 247 pe_config->enable_yuv_ds); 248 dev_dbg(isp->dev, 249 "pipe_extra_config.enable_high_speed:%d.\n", 250 pe_config->enable_high_speed); 251 dev_dbg(isp->dev, 252 "pipe_extra_config.enable_dvs_6axis:%d.\n", 253 pe_config->enable_dvs_6axis); 254 dev_dbg(isp->dev, 255 "pipe_extra_config.enable_reduced_pipe:%d.\n", 256 pe_config->enable_reduced_pipe); 257 dev_dbg(isp->dev, 258 "pipe_(extra_)config.enable_dz:%d.\n", 259 p_config->enable_dz); 260 dev_dbg(isp->dev, 261 "pipe_extra_config.disable_vf_pp:%d.\n", 262 pe_config->disable_vf_pp); 263 } 264 } 265 __dump_stream_config(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env)266 static void __dump_stream_config(struct atomisp_sub_device *asd, 267 struct atomisp_stream_env *stream_env) 268 { 269 struct atomisp_device *isp = asd->isp; 270 struct ia_css_stream_config *s_config; 271 int j; 272 bool valid_stream = false; 273 274 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { 275 if (stream_env->pipes[j]) { 276 __dump_pipe_config(asd, stream_env, j); 277 valid_stream = true; 278 } 279 } 280 if (!valid_stream) 281 return; 282 s_config = &stream_env->stream_config; 283 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode); 284 285 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR || 286 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { 287 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n", 288 s_config->source.port.port); 289 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n", 290 s_config->source.port.num_lanes); 291 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n", 292 s_config->source.port.timeout); 293 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n", 294 s_config->source.port.rxcount); 295 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n", 296 s_config->source.port.compression.type); 297 dev_dbg(isp->dev, 298 "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n", 299 s_config->source.port.compression. 300 compressed_bits_per_pixel); 301 dev_dbg(isp->dev, 302 "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n", 303 s_config->source.port.compression. 304 uncompressed_bits_per_pixel); 305 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) { 306 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n", 307 s_config->source.prbs.id); 308 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n", 309 s_config->source.prbs.h_blank); 310 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n", 311 s_config->source.prbs.v_blank); 312 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n", 313 s_config->source.prbs.seed); 314 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n", 315 s_config->source.prbs.seed1); 316 } 317 318 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) { 319 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n", 320 j, 321 s_config->isys_config[j].input_res.width, 322 s_config->isys_config[j].input_res.height); 323 324 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n", 325 j, 326 s_config->isys_config[j].linked_isys_stream_id); 327 328 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n", 329 j, 330 s_config->isys_config[j].format); 331 332 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n", 333 j, 334 s_config->isys_config[j].valid); 335 } 336 337 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n", 338 s_config->input_config.input_res.width, 339 s_config->input_config.input_res.height); 340 341 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n", 342 s_config->input_config.effective_res.width, 343 s_config->input_config.effective_res.height); 344 345 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n", 346 s_config->input_config.format); 347 348 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n", 349 s_config->input_config.bayer_order); 350 351 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n", 352 s_config->pixels_per_clock); 353 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online); 354 dev_dbg(isp->dev, "stream_config.continuous=%d.\n", 355 s_config->continuous); 356 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n", 357 s_config->disable_cont_viewfinder); 358 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n", 359 s_config->channel_id); 360 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n", 361 s_config->init_num_cont_raw_buf); 362 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n", 363 s_config->target_num_cont_raw_buf); 364 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n", 365 s_config->left_padding); 366 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n", 367 s_config->sensor_binning_factor); 368 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n", 369 s_config->pixels_per_clock); 370 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n", 371 s_config->pack_raw_pixels); 372 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n", 373 s_config->flash_gpio_pin); 374 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n", 375 s_config->mipi_buffer_config.size_mem_words); 376 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n", 377 s_config->mipi_buffer_config.contiguous); 378 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n", 379 s_config->metadata_config.data_type); 380 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n", 381 s_config->metadata_config.resolution.width, 382 s_config->metadata_config.resolution.height); 383 } 384 __destroy_stream(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env)385 static int __destroy_stream(struct atomisp_sub_device *asd, 386 struct atomisp_stream_env *stream_env) 387 { 388 struct atomisp_device *isp = asd->isp; 389 unsigned long timeout; 390 391 if (!stream_env->stream) 392 return 0; 393 394 if (stream_env->stream_state == CSS_STREAM_STARTED 395 && ia_css_stream_stop(stream_env->stream) != 0) { 396 dev_err(isp->dev, "stop stream failed.\n"); 397 return -EINVAL; 398 } 399 400 if (stream_env->stream_state == CSS_STREAM_STARTED) { 401 timeout = jiffies + msecs_to_jiffies(40); 402 while (1) { 403 if (ia_css_stream_has_stopped(stream_env->stream)) 404 break; 405 406 if (time_after(jiffies, timeout)) { 407 dev_warn(isp->dev, "stop stream timeout.\n"); 408 break; 409 } 410 411 usleep_range(100, 200); 412 } 413 } 414 415 stream_env->stream_state = CSS_STREAM_STOPPED; 416 417 if (ia_css_stream_destroy(stream_env->stream)) { 418 dev_err(isp->dev, "destroy stream failed.\n"); 419 return -EINVAL; 420 } 421 stream_env->stream_state = CSS_STREAM_UNINIT; 422 stream_env->stream = NULL; 423 424 return 0; 425 } 426 __destroy_streams(struct atomisp_sub_device * asd)427 static int __destroy_streams(struct atomisp_sub_device *asd) 428 { 429 int ret, i; 430 431 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 432 ret = __destroy_stream(asd, &asd->stream_env[i]); 433 if (ret) 434 return ret; 435 } 436 asd->stream_prepared = false; 437 return 0; 438 } 439 __create_stream(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env)440 static int __create_stream(struct atomisp_sub_device *asd, 441 struct atomisp_stream_env *stream_env) 442 { 443 int pipe_index = 0, i; 444 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM]; 445 446 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { 447 if (stream_env->pipes[i]) 448 multi_pipes[pipe_index++] = stream_env->pipes[i]; 449 } 450 if (pipe_index == 0) 451 return 0; 452 453 stream_env->stream_config.target_num_cont_raw_buf = 454 asd->continuous_raw_buffer_size->val; 455 stream_env->stream_config.channel_id = stream_env->ch_id; 456 stream_env->stream_config.ia_css_enable_raw_buffer_locking = 457 asd->enable_raw_buffer_lock->val; 458 459 __dump_stream_config(asd, stream_env); 460 if (ia_css_stream_create(&stream_env->stream_config, 461 pipe_index, multi_pipes, &stream_env->stream) != 0) 462 return -EINVAL; 463 if (ia_css_stream_get_info(stream_env->stream, 464 &stream_env->stream_info) != 0) { 465 ia_css_stream_destroy(stream_env->stream); 466 stream_env->stream = NULL; 467 return -EINVAL; 468 } 469 470 stream_env->stream_state = CSS_STREAM_CREATED; 471 return 0; 472 } 473 __create_streams(struct atomisp_sub_device * asd)474 static int __create_streams(struct atomisp_sub_device *asd) 475 { 476 int ret, i; 477 478 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 479 ret = __create_stream(asd, &asd->stream_env[i]); 480 if (ret) 481 goto rollback; 482 } 483 asd->stream_prepared = true; 484 return 0; 485 rollback: 486 for (i--; i >= 0; i--) 487 __destroy_stream(asd, &asd->stream_env[i]); 488 return ret; 489 } 490 __destroy_stream_pipes(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env)491 static int __destroy_stream_pipes(struct atomisp_sub_device *asd, 492 struct atomisp_stream_env *stream_env) 493 { 494 struct atomisp_device *isp = asd->isp; 495 int ret = 0; 496 int i; 497 498 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { 499 if (!stream_env->pipes[i]) 500 continue; 501 if (ia_css_pipe_destroy(stream_env->pipes[i]) 502 != 0) { 503 dev_err(isp->dev, 504 "destroy pipe[%d]failed.cannot recover.\n", i); 505 ret = -EINVAL; 506 } 507 stream_env->pipes[i] = NULL; 508 stream_env->update_pipe[i] = false; 509 } 510 return ret; 511 } 512 __destroy_pipes(struct atomisp_sub_device * asd)513 static int __destroy_pipes(struct atomisp_sub_device *asd) 514 { 515 struct atomisp_device *isp = asd->isp; 516 int i; 517 int ret = 0; 518 519 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 520 if (asd->stream_env[i].stream) { 521 dev_err(isp->dev, 522 "cannot destroy css pipes for stream[%d].\n", 523 i); 524 continue; 525 } 526 527 ret = __destroy_stream_pipes(asd, &asd->stream_env[i]); 528 if (ret) 529 return ret; 530 } 531 532 return 0; 533 } 534 atomisp_destroy_pipes_stream(struct atomisp_sub_device * asd)535 void atomisp_destroy_pipes_stream(struct atomisp_sub_device *asd) 536 { 537 if (__destroy_streams(asd)) 538 dev_warn(asd->isp->dev, "destroy stream failed.\n"); 539 540 if (__destroy_pipes(asd)) 541 dev_warn(asd->isp->dev, "destroy pipe failed.\n"); 542 } 543 __apply_additional_pipe_config(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env,enum ia_css_pipe_id pipe_id)544 static void __apply_additional_pipe_config( 545 struct atomisp_sub_device *asd, 546 struct atomisp_stream_env *stream_env, 547 enum ia_css_pipe_id pipe_id) 548 { 549 struct atomisp_device *isp = asd->isp; 550 551 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) { 552 dev_err(isp->dev, 553 "wrong pipe_id for additional pipe config.\n"); 554 return; 555 } 556 557 /* apply default pipe config */ 558 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2; 559 stream_env->pipe_configs[pipe_id].enable_dz = 560 asd->disable_dz->val ? false : true; 561 /* apply isp 2.2 specific config for baytrail*/ 562 switch (pipe_id) { 563 case IA_CSS_PIPE_ID_CAPTURE: 564 /* enable capture pp/dz manually or digital zoom would 565 * fail*/ 566 if (stream_env->pipe_configs[pipe_id]. 567 default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW) 568 stream_env->pipe_configs[pipe_id].enable_dz = false; 569 break; 570 case IA_CSS_PIPE_ID_VIDEO: 571 /* enable reduced pipe to have binary 572 * video_dz_2_min selected*/ 573 stream_env->pipe_extra_configs[pipe_id] 574 .enable_reduced_pipe = true; 575 stream_env->pipe_configs[pipe_id] 576 .enable_dz = false; 577 578 if (asd->params.video_dis_en) { 579 stream_env->pipe_extra_configs[pipe_id] 580 .enable_dvs_6axis = true; 581 stream_env->pipe_configs[pipe_id] 582 .dvs_frame_delay = 583 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; 584 } 585 break; 586 case IA_CSS_PIPE_ID_PREVIEW: 587 break; 588 case IA_CSS_PIPE_ID_YUVPP: 589 case IA_CSS_PIPE_ID_COPY: 590 stream_env->pipe_configs[pipe_id].enable_dz = false; 591 break; 592 default: 593 break; 594 } 595 } 596 is_pipe_valid_to_current_run_mode(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id)597 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd, 598 enum ia_css_pipe_id pipe_id) 599 { 600 if (pipe_id == IA_CSS_PIPE_ID_YUVPP) 601 return true; 602 603 if (asd->vfpp) { 604 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { 605 if (pipe_id == IA_CSS_PIPE_ID_VIDEO) 606 return true; 607 else 608 return false; 609 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { 610 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE) 611 return true; 612 else 613 return false; 614 } 615 } 616 617 if (!asd->run_mode) 618 return false; 619 620 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY) 621 return true; 622 623 switch (asd->run_mode->val) { 624 case ATOMISP_RUN_MODE_STILL_CAPTURE: 625 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE) 626 return true; 627 628 return false; 629 case ATOMISP_RUN_MODE_PREVIEW: 630 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 631 return true; 632 633 return false; 634 case ATOMISP_RUN_MODE_VIDEO: 635 if (pipe_id == IA_CSS_PIPE_ID_VIDEO || pipe_id == IA_CSS_PIPE_ID_YUVPP) 636 return true; 637 638 return false; 639 } 640 641 return false; 642 } 643 __create_pipe(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env,enum ia_css_pipe_id pipe_id)644 static int __create_pipe(struct atomisp_sub_device *asd, 645 struct atomisp_stream_env *stream_env, 646 enum ia_css_pipe_id pipe_id) 647 { 648 struct atomisp_device *isp = asd->isp; 649 struct ia_css_pipe_extra_config extra_config; 650 int ret; 651 652 if (pipe_id >= IA_CSS_PIPE_ID_NUM) 653 return -EINVAL; 654 655 if (!stream_env->pipe_configs[pipe_id].output_info[0].res.width) 656 return 0; 657 658 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id)) 659 return 0; 660 661 ia_css_pipe_extra_config_defaults(&extra_config); 662 663 __apply_additional_pipe_config(asd, stream_env, pipe_id); 664 if (!memcmp(&extra_config, 665 &stream_env->pipe_extra_configs[pipe_id], 666 sizeof(extra_config))) 667 ret = ia_css_pipe_create( 668 &stream_env->pipe_configs[pipe_id], 669 &stream_env->pipes[pipe_id]); 670 else 671 ret = ia_css_pipe_create_extra( 672 &stream_env->pipe_configs[pipe_id], 673 &stream_env->pipe_extra_configs[pipe_id], 674 &stream_env->pipes[pipe_id]); 675 if (ret) 676 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id); 677 return ret; 678 } 679 __create_pipes(struct atomisp_sub_device * asd)680 static int __create_pipes(struct atomisp_sub_device *asd) 681 { 682 int ret; 683 int i, j; 684 685 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 686 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { 687 ret = __create_pipe(asd, &asd->stream_env[i], j); 688 if (ret) 689 break; 690 } 691 if (j < IA_CSS_PIPE_ID_NUM) 692 goto pipe_err; 693 } 694 return 0; 695 pipe_err: 696 for (; i >= 0; i--) { 697 for (j--; j >= 0; j--) { 698 if (asd->stream_env[i].pipes[j]) { 699 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]); 700 asd->stream_env[i].pipes[j] = NULL; 701 } 702 } 703 j = IA_CSS_PIPE_ID_NUM; 704 } 705 return -EINVAL; 706 } 707 atomisp_create_pipes_stream(struct atomisp_sub_device * asd)708 int atomisp_create_pipes_stream(struct atomisp_sub_device *asd) 709 { 710 int ret; 711 712 ret = __create_pipes(asd); 713 if (ret) { 714 dev_err(asd->isp->dev, "create pipe failed %d.\n", ret); 715 return ret; 716 } 717 718 ret = __create_streams(asd); 719 if (ret) { 720 dev_warn(asd->isp->dev, "create stream failed %d.\n", ret); 721 __destroy_pipes(asd); 722 return ret; 723 } 724 725 return 0; 726 } 727 atomisp_css_update_stream(struct atomisp_sub_device * asd)728 int atomisp_css_update_stream(struct atomisp_sub_device *asd) 729 { 730 atomisp_destroy_pipes_stream(asd); 731 return atomisp_create_pipes_stream(asd); 732 } 733 atomisp_css_init(struct atomisp_device * isp)734 int atomisp_css_init(struct atomisp_device *isp) 735 { 736 unsigned int mmu_base_addr; 737 int ret; 738 int err; 739 740 ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr); 741 if (ret) 742 return ret; 743 744 /* Init ISP */ 745 err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, 746 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE); 747 if (err) { 748 dev_err(isp->dev, "css init failed --- bad firmware?\n"); 749 return -EINVAL; 750 } 751 ia_css_enable_isys_event_queue(true); 752 753 isp->css_initialized = true; 754 dev_dbg(isp->dev, "sh_css_init success\n"); 755 756 return 0; 757 } 758 __set_css_print_env(struct atomisp_device * isp,int opt)759 static inline int __set_css_print_env(struct atomisp_device *isp, int opt) 760 { 761 int ret = 0; 762 763 if (opt == 0) 764 isp->css_env.isp_css_env.print_env.debug_print = NULL; 765 else if (opt == 1) 766 isp->css_env.isp_css_env.print_env.debug_print = atomisp_vprintk; 767 else 768 ret = -EINVAL; 769 770 return ret; 771 } 772 atomisp_css_load_firmware(struct atomisp_device * isp)773 int atomisp_css_load_firmware(struct atomisp_device *isp) 774 { 775 int err; 776 777 /* set css env */ 778 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data; 779 isp->css_env.isp_css_fw.bytes = isp->firmware->size; 780 781 isp->css_env.isp_css_env.hw_access_env.store_8 = 782 atomisp_css2_hw_store_8; 783 isp->css_env.isp_css_env.hw_access_env.store_16 = 784 atomisp_css2_hw_store_16; 785 isp->css_env.isp_css_env.hw_access_env.store_32 = 786 atomisp_css2_hw_store_32; 787 788 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8; 789 isp->css_env.isp_css_env.hw_access_env.load_16 = 790 atomisp_css2_hw_load_16; 791 isp->css_env.isp_css_env.hw_access_env.load_32 = 792 atomisp_css2_hw_load_32; 793 794 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load; 795 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store; 796 797 __set_css_print_env(isp, dbg_func); 798 799 isp->css_env.isp_css_env.print_env.error_print = atomisp_vprintk; 800 801 /* load isp fw into ISP memory */ 802 err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env, 803 &isp->css_env.isp_css_fw); 804 if (err) { 805 dev_err(isp->dev, "css load fw failed.\n"); 806 return -EINVAL; 807 } 808 809 return 0; 810 } 811 atomisp_css_uninit(struct atomisp_device * isp)812 void atomisp_css_uninit(struct atomisp_device *isp) 813 { 814 isp->css_initialized = false; 815 ia_css_uninit(); 816 } 817 atomisp_css_irq_translate(struct atomisp_device * isp,unsigned int * infos)818 int atomisp_css_irq_translate(struct atomisp_device *isp, 819 unsigned int *infos) 820 { 821 int err; 822 823 err = ia_css_irq_translate(infos); 824 if (err) { 825 dev_warn(isp->dev, 826 "%s:failed to translate irq (err = %d,infos = %d)\n", 827 __func__, err, *infos); 828 return -EINVAL; 829 } 830 831 return 0; 832 } 833 atomisp_css_rx_get_irq_info(enum mipi_port_id port,unsigned int * infos)834 void atomisp_css_rx_get_irq_info(enum mipi_port_id port, 835 unsigned int *infos) 836 { 837 if (IS_ISP2401) 838 *infos = 0; 839 else 840 ia_css_isys_rx_get_irq_info(port, infos); 841 } 842 atomisp_css_rx_clear_irq_info(enum mipi_port_id port,unsigned int infos)843 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port, 844 unsigned int infos) 845 { 846 if (!IS_ISP2401) 847 ia_css_isys_rx_clear_irq_info(port, infos); 848 } 849 atomisp_css_irq_enable(struct atomisp_device * isp,enum ia_css_irq_info info,bool enable)850 int atomisp_css_irq_enable(struct atomisp_device *isp, 851 enum ia_css_irq_info info, bool enable) 852 { 853 dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s (%d).\n", 854 __func__, info, 855 enable ? "enable" : "disable", enable); 856 if (ia_css_irq_enable(info, enable)) { 857 dev_warn(isp->dev, "%s:Invalid irq info: 0x%08x when %s.\n", 858 __func__, info, 859 enable ? "enabling" : "disabling"); 860 return -EINVAL; 861 } 862 863 return 0; 864 } 865 atomisp_css_init_struct(struct atomisp_sub_device * asd)866 void atomisp_css_init_struct(struct atomisp_sub_device *asd) 867 { 868 int i, j; 869 870 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 871 asd->stream_env[i].stream = NULL; 872 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) { 873 asd->stream_env[i].pipes[j] = NULL; 874 asd->stream_env[i].update_pipe[j] = false; 875 ia_css_pipe_config_defaults( 876 &asd->stream_env[i].pipe_configs[j]); 877 ia_css_pipe_extra_config_defaults( 878 &asd->stream_env[i].pipe_extra_configs[j]); 879 } 880 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config); 881 } 882 } 883 atomisp_q_video_buffer_to_css(struct atomisp_sub_device * asd,struct ia_css_frame * frame,enum atomisp_input_stream_id stream_id,enum ia_css_buffer_type css_buf_type,enum ia_css_pipe_id css_pipe_id)884 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd, 885 struct ia_css_frame *frame, 886 enum atomisp_input_stream_id stream_id, 887 enum ia_css_buffer_type css_buf_type, 888 enum ia_css_pipe_id css_pipe_id) 889 { 890 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; 891 struct ia_css_buffer css_buf = {0}; 892 int err; 893 894 css_buf.type = css_buf_type; 895 css_buf.data.frame = frame; 896 897 err = ia_css_pipe_enqueue_buffer( 898 stream_env->pipes[css_pipe_id], &css_buf); 899 if (err) 900 return -EINVAL; 901 902 return 0; 903 } 904 atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device * asd,struct atomisp_metadata_buf * metadata_buf,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id css_pipe_id)905 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd, 906 struct atomisp_metadata_buf *metadata_buf, 907 enum atomisp_input_stream_id stream_id, 908 enum ia_css_pipe_id css_pipe_id) 909 { 910 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; 911 struct ia_css_buffer buffer = {0}; 912 struct atomisp_device *isp = asd->isp; 913 914 buffer.type = IA_CSS_BUFFER_TYPE_METADATA; 915 buffer.data.metadata = metadata_buf->metadata; 916 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id], 917 &buffer)) { 918 dev_err(isp->dev, "failed to q meta data buffer\n"); 919 return -EINVAL; 920 } 921 922 return 0; 923 } 924 atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device * asd,struct atomisp_s3a_buf * s3a_buf,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id css_pipe_id)925 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd, 926 struct atomisp_s3a_buf *s3a_buf, 927 enum atomisp_input_stream_id stream_id, 928 enum ia_css_pipe_id css_pipe_id) 929 { 930 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; 931 struct ia_css_buffer buffer = {0}; 932 struct atomisp_device *isp = asd->isp; 933 934 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS; 935 buffer.data.stats_3a = s3a_buf->s3a_data; 936 if (ia_css_pipe_enqueue_buffer( 937 stream_env->pipes[css_pipe_id], 938 &buffer)) { 939 dev_dbg(isp->dev, "failed to q s3a stat buffer\n"); 940 return -EINVAL; 941 } 942 943 return 0; 944 } 945 atomisp_q_dis_buffer_to_css(struct atomisp_sub_device * asd,struct atomisp_dis_buf * dis_buf,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id css_pipe_id)946 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, 947 struct atomisp_dis_buf *dis_buf, 948 enum atomisp_input_stream_id stream_id, 949 enum ia_css_pipe_id css_pipe_id) 950 { 951 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; 952 struct ia_css_buffer buffer = {0}; 953 struct atomisp_device *isp = asd->isp; 954 955 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS; 956 buffer.data.stats_dvs = dis_buf->dis_data; 957 if (ia_css_pipe_enqueue_buffer( 958 stream_env->pipes[css_pipe_id], 959 &buffer)) { 960 dev_dbg(isp->dev, "failed to q dvs stat buffer\n"); 961 return -EINVAL; 962 } 963 964 return 0; 965 } 966 atomisp_css_start(struct atomisp_sub_device * asd)967 int atomisp_css_start(struct atomisp_sub_device *asd) 968 { 969 struct atomisp_device *isp = asd->isp; 970 bool sp_is_started = false; 971 int ret = 0, i = 0; 972 973 if (!sh_css_hrt_system_is_idle()) 974 dev_err(isp->dev, "CSS HW not idle before starting SP\n"); 975 976 if (ia_css_start_sp()) { 977 dev_err(isp->dev, "start sp error.\n"); 978 ret = -EINVAL; 979 goto start_err; 980 } 981 982 sp_is_started = true; 983 984 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 985 if (asd->stream_env[i].stream) { 986 if (ia_css_stream_start(asd->stream_env[i] 987 .stream) != 0) { 988 dev_err(isp->dev, "stream[%d] start error.\n", i); 989 ret = -EINVAL; 990 goto start_err; 991 } else { 992 asd->stream_env[i].stream_state = CSS_STREAM_STARTED; 993 dev_dbg(isp->dev, "stream[%d] started.\n", i); 994 } 995 } 996 } 997 998 return 0; 999 1000 start_err: 1001 /* 1002 * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after 1003 * destroying all pipes. 1004 */ 1005 if (sp_is_started) { 1006 atomisp_destroy_pipes_stream(asd); 1007 ia_css_stop_sp(); 1008 atomisp_create_pipes_stream(asd); 1009 } 1010 1011 return ret; 1012 } 1013 atomisp_css_update_isp_params(struct atomisp_sub_device * asd)1014 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd) 1015 { 1016 /* 1017 * FIXME! 1018 * for ISP2401 new input system, this api is under development. 1019 * Calling it would cause kernel panic. 1020 * 1021 * VIED BZ: 1458 1022 * 1023 * Check if it is Cherry Trail and also new input system 1024 */ 1025 if (asd->copy_mode) { 1026 dev_warn(asd->isp->dev, 1027 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n", 1028 __func__); 1029 return; 1030 } 1031 1032 ia_css_stream_set_isp_config( 1033 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 1034 &asd->params.config); 1035 memset(&asd->params.config, 0, sizeof(asd->params.config)); 1036 } 1037 atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device * asd,struct ia_css_pipe * pipe)1038 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd, 1039 struct ia_css_pipe *pipe) 1040 { 1041 int ret; 1042 1043 if (!pipe) { 1044 atomisp_css_update_isp_params(asd); 1045 return; 1046 } 1047 1048 dev_dbg(asd->isp->dev, 1049 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n", 1050 __func__, asd->params.config.output_frame, 1051 asd->params.config.isp_config_id, pipe); 1052 1053 ret = ia_css_stream_set_isp_config_on_pipe( 1054 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 1055 &asd->params.config, pipe); 1056 if (ret) 1057 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n", 1058 __func__, ret); 1059 memset(&asd->params.config, 0, sizeof(asd->params.config)); 1060 } 1061 atomisp_css_queue_buffer(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id pipe_id,enum ia_css_buffer_type buf_type,struct atomisp_css_buffer * isp_css_buffer)1062 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd, 1063 enum atomisp_input_stream_id stream_id, 1064 enum ia_css_pipe_id pipe_id, 1065 enum ia_css_buffer_type buf_type, 1066 struct atomisp_css_buffer *isp_css_buffer) 1067 { 1068 if (ia_css_pipe_enqueue_buffer( 1069 asd->stream_env[stream_id].pipes[pipe_id], 1070 &isp_css_buffer->css_buffer) 1071 != 0) 1072 return -EINVAL; 1073 1074 return 0; 1075 } 1076 atomisp_css_dequeue_buffer(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id pipe_id,enum ia_css_buffer_type buf_type,struct atomisp_css_buffer * isp_css_buffer)1077 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd, 1078 enum atomisp_input_stream_id stream_id, 1079 enum ia_css_pipe_id pipe_id, 1080 enum ia_css_buffer_type buf_type, 1081 struct atomisp_css_buffer *isp_css_buffer) 1082 { 1083 struct atomisp_device *isp = asd->isp; 1084 int err; 1085 1086 err = ia_css_pipe_dequeue_buffer( 1087 asd->stream_env[stream_id].pipes[pipe_id], 1088 &isp_css_buffer->css_buffer); 1089 if (err) { 1090 dev_err(isp->dev, 1091 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err); 1092 return -EINVAL; 1093 } 1094 1095 return 0; 1096 } 1097 atomisp_css_allocate_stat_buffers(struct atomisp_sub_device * asd,u16 stream_id,struct atomisp_s3a_buf * s3a_buf,struct atomisp_dis_buf * dis_buf,struct atomisp_metadata_buf * md_buf)1098 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd, 1099 u16 stream_id, 1100 struct atomisp_s3a_buf *s3a_buf, 1101 struct atomisp_dis_buf *dis_buf, 1102 struct atomisp_metadata_buf *md_buf) 1103 { 1104 struct atomisp_device *isp = asd->isp; 1105 struct ia_css_dvs_grid_info *dvs_grid_info = 1106 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 1107 1108 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) { 1109 void *s3a_ptr; 1110 1111 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate( 1112 &asd->params.curr_grid_info.s3a_grid); 1113 if (!s3a_buf->s3a_data) { 1114 dev_err(isp->dev, "3a buf allocation failed.\n"); 1115 return -EINVAL; 1116 } 1117 1118 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true); 1119 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate( 1120 s3a_buf->s3a_data, s3a_ptr); 1121 } 1122 1123 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) { 1124 void *dvs_ptr; 1125 1126 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate( 1127 dvs_grid_info); 1128 if (!dis_buf->dis_data) { 1129 dev_err(isp->dev, "dvs buf allocation failed.\n"); 1130 if (s3a_buf) 1131 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data); 1132 return -EINVAL; 1133 } 1134 1135 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true); 1136 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate( 1137 dis_buf->dis_data, dvs_ptr); 1138 } 1139 1140 if (asd->stream_env[stream_id].stream_info. 1141 metadata_info.size && md_buf) { 1142 md_buf->metadata = ia_css_metadata_allocate( 1143 &asd->stream_env[stream_id].stream_info.metadata_info); 1144 if (!md_buf->metadata) { 1145 if (s3a_buf) 1146 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data); 1147 if (dis_buf) 1148 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data); 1149 dev_err(isp->dev, "metadata buf allocation failed.\n"); 1150 return -EINVAL; 1151 } 1152 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false); 1153 } 1154 1155 return 0; 1156 } 1157 atomisp_css_free_3a_buffer(struct atomisp_s3a_buf * s3a_buf)1158 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf) 1159 { 1160 if (s3a_buf->s3a_data) 1161 hmm_vunmap(s3a_buf->s3a_data->data_ptr); 1162 1163 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map); 1164 s3a_buf->s3a_map = NULL; 1165 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data); 1166 } 1167 atomisp_css_free_dis_buffer(struct atomisp_dis_buf * dis_buf)1168 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf) 1169 { 1170 if (dis_buf->dis_data) 1171 hmm_vunmap(dis_buf->dis_data->data_ptr); 1172 1173 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map); 1174 dis_buf->dvs_map = NULL; 1175 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data); 1176 } 1177 atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf * metadata_buf)1178 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf) 1179 { 1180 if (metadata_buf->md_vptr) { 1181 hmm_vunmap(metadata_buf->metadata->address); 1182 metadata_buf->md_vptr = NULL; 1183 } 1184 ia_css_metadata_free(metadata_buf->metadata); 1185 } 1186 atomisp_css_free_stat_buffers(struct atomisp_sub_device * asd)1187 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd) 1188 { 1189 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf; 1190 struct atomisp_dis_buf *dis_buf, *_dis_buf; 1191 struct atomisp_metadata_buf *md_buf, *_md_buf; 1192 struct ia_css_dvs_grid_info *dvs_grid_info = 1193 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 1194 unsigned int i; 1195 1196 /* 3A statistics use vmalloc, DIS use kmalloc */ 1197 if (dvs_grid_info && dvs_grid_info->enable) { 1198 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff); 1199 ia_css_dvs2_statistics_free(asd->params.dvs_stat); 1200 asd->params.css_param.dvs2_coeff = NULL; 1201 asd->params.dvs_stat = NULL; 1202 asd->params.dvs_hor_proj_bytes = 0; 1203 asd->params.dvs_ver_proj_bytes = 0; 1204 asd->params.dvs_hor_coef_bytes = 0; 1205 asd->params.dvs_ver_coef_bytes = 0; 1206 asd->params.dis_proj_data_valid = false; 1207 list_for_each_entry_safe(dis_buf, _dis_buf, 1208 &asd->dis_stats, list) { 1209 atomisp_css_free_dis_buffer(dis_buf); 1210 list_del(&dis_buf->list); 1211 kfree(dis_buf); 1212 } 1213 list_for_each_entry_safe(dis_buf, _dis_buf, 1214 &asd->dis_stats_in_css, list) { 1215 atomisp_css_free_dis_buffer(dis_buf); 1216 list_del(&dis_buf->list); 1217 kfree(dis_buf); 1218 } 1219 } 1220 if (asd->params.curr_grid_info.s3a_grid.enable) { 1221 ia_css_3a_statistics_free(asd->params.s3a_user_stat); 1222 asd->params.s3a_user_stat = NULL; 1223 asd->params.s3a_output_bytes = 0; 1224 list_for_each_entry_safe(s3a_buf, _s3a_buf, 1225 &asd->s3a_stats, list) { 1226 atomisp_css_free_3a_buffer(s3a_buf); 1227 list_del(&s3a_buf->list); 1228 kfree(s3a_buf); 1229 } 1230 list_for_each_entry_safe(s3a_buf, _s3a_buf, 1231 &asd->s3a_stats_in_css, list) { 1232 atomisp_css_free_3a_buffer(s3a_buf); 1233 list_del(&s3a_buf->list); 1234 kfree(s3a_buf); 1235 } 1236 list_for_each_entry_safe(s3a_buf, _s3a_buf, 1237 &asd->s3a_stats_ready, list) { 1238 atomisp_css_free_3a_buffer(s3a_buf); 1239 list_del(&s3a_buf->list); 1240 kfree(s3a_buf); 1241 } 1242 } 1243 1244 if (asd->params.css_param.dvs_6axis) { 1245 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis); 1246 asd->params.css_param.dvs_6axis = NULL; 1247 } 1248 1249 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 1250 list_for_each_entry_safe(md_buf, _md_buf, 1251 &asd->metadata[i], list) { 1252 atomisp_css_free_metadata_buffer(md_buf); 1253 list_del(&md_buf->list); 1254 kfree(md_buf); 1255 } 1256 list_for_each_entry_safe(md_buf, _md_buf, 1257 &asd->metadata_in_css[i], list) { 1258 atomisp_css_free_metadata_buffer(md_buf); 1259 list_del(&md_buf->list); 1260 kfree(md_buf); 1261 } 1262 list_for_each_entry_safe(md_buf, _md_buf, 1263 &asd->metadata_ready[i], list) { 1264 atomisp_css_free_metadata_buffer(md_buf); 1265 list_del(&md_buf->list); 1266 kfree(md_buf); 1267 } 1268 } 1269 asd->params.metadata_width_size = 0; 1270 atomisp_free_metadata_output_buf(asd); 1271 } 1272 atomisp_css_get_grid_info(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id)1273 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd, 1274 enum ia_css_pipe_id pipe_id) 1275 { 1276 struct ia_css_pipe_info p_info; 1277 struct ia_css_grid_info old_info; 1278 struct atomisp_device *isp = asd->isp; 1279 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 1280 stream_config.metadata_config.resolution.width; 1281 1282 memset(&p_info, 0, sizeof(struct ia_css_pipe_info)); 1283 memset(&old_info, 0, sizeof(struct ia_css_grid_info)); 1284 1285 if (ia_css_pipe_get_info( 1286 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipes[pipe_id], 1287 &p_info) != 0) { 1288 dev_err(isp->dev, "ia_css_pipe_get_info failed\n"); 1289 return -EINVAL; 1290 } 1291 1292 memcpy(&old_info, &asd->params.curr_grid_info, 1293 sizeof(struct ia_css_grid_info)); 1294 memcpy(&asd->params.curr_grid_info, &p_info.grid_info, 1295 sizeof(struct ia_css_grid_info)); 1296 /* 1297 * Record which css pipe enables s3a_grid. 1298 * Currently would have one css pipe that need it 1299 */ 1300 if (asd->params.curr_grid_info.s3a_grid.enable) { 1301 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM) 1302 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n", 1303 asd->params.s3a_enabled_pipe, pipe_id); 1304 asd->params.s3a_enabled_pipe = pipe_id; 1305 } 1306 1307 /* If the grid info has not changed and the buffers for 3A and 1308 * DIS statistics buffers are allocated or buffer size would be zero 1309 * then no need to do anything. */ 1310 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info)) 1311 && asd->params.s3a_user_stat && asd->params.dvs_stat) 1312 || asd->params.curr_grid_info.s3a_grid.width == 0 1313 || asd->params.curr_grid_info.s3a_grid.height == 0) 1314 && asd->params.metadata_width_size == md_width) { 1315 dev_dbg(isp->dev, 1316 "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n", 1317 !memcmp(&old_info, &asd->params.curr_grid_info, 1318 sizeof(old_info)), 1319 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat, 1320 asd->params.curr_grid_info.s3a_grid.width, 1321 asd->params.curr_grid_info.s3a_grid.height, 1322 asd->params.metadata_width_size); 1323 return -EINVAL; 1324 } 1325 asd->params.metadata_width_size = md_width; 1326 1327 return 0; 1328 } 1329 atomisp_alloc_3a_output_buf(struct atomisp_sub_device * asd)1330 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd) 1331 { 1332 if (!asd->params.curr_grid_info.s3a_grid.width || 1333 !asd->params.curr_grid_info.s3a_grid.height) 1334 return 0; 1335 1336 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate( 1337 &asd->params.curr_grid_info.s3a_grid); 1338 if (!asd->params.s3a_user_stat) 1339 return -ENOMEM; 1340 /* 3A statistics. These can be big, so we use vmalloc. */ 1341 asd->params.s3a_output_bytes = 1342 asd->params.curr_grid_info.s3a_grid.width * 1343 asd->params.curr_grid_info.s3a_grid.height * 1344 sizeof(*asd->params.s3a_user_stat->data); 1345 1346 return 0; 1347 } 1348 atomisp_alloc_dis_coef_buf(struct atomisp_sub_device * asd)1349 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd) 1350 { 1351 struct ia_css_dvs_grid_info *dvs_grid = 1352 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 1353 1354 if (!dvs_grid) 1355 return 0; 1356 1357 if (!dvs_grid->enable) { 1358 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__); 1359 return 0; 1360 } 1361 1362 /* DIS coefficients. */ 1363 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate( 1364 dvs_grid); 1365 if (!asd->params.css_param.dvs2_coeff) 1366 return -ENOMEM; 1367 1368 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs * 1369 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real); 1370 1371 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs * 1372 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real); 1373 1374 /* DIS projections. */ 1375 asd->params.dis_proj_data_valid = false; 1376 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid); 1377 if (!asd->params.dvs_stat) 1378 return -ENOMEM; 1379 1380 asd->params.dvs_hor_proj_bytes = 1381 dvs_grid->aligned_height * dvs_grid->aligned_width * 1382 sizeof(*asd->params.dvs_stat->hor_prod.odd_real); 1383 1384 asd->params.dvs_ver_proj_bytes = 1385 dvs_grid->aligned_height * dvs_grid->aligned_width * 1386 sizeof(*asd->params.dvs_stat->ver_prod.odd_real); 1387 1388 return 0; 1389 } 1390 atomisp_alloc_metadata_output_buf(struct atomisp_sub_device * asd)1391 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd) 1392 { 1393 int i; 1394 1395 /* We allocate the cpu-side buffer used for communication with user 1396 * space */ 1397 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 1398 asd->params.metadata_user[i] = kvmalloc( 1399 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 1400 stream_info.metadata_info.size, GFP_KERNEL); 1401 if (!asd->params.metadata_user[i]) { 1402 while (--i >= 0) { 1403 kvfree(asd->params.metadata_user[i]); 1404 asd->params.metadata_user[i] = NULL; 1405 } 1406 return -ENOMEM; 1407 } 1408 } 1409 1410 return 0; 1411 } 1412 atomisp_free_metadata_output_buf(struct atomisp_sub_device * asd)1413 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd) 1414 { 1415 unsigned int i; 1416 1417 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 1418 if (asd->params.metadata_user[i]) { 1419 kvfree(asd->params.metadata_user[i]); 1420 asd->params.metadata_user[i] = NULL; 1421 } 1422 } 1423 } 1424 atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device * asd,struct atomisp_css_event * current_event)1425 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd, 1426 struct atomisp_css_event *current_event) 1427 { 1428 /* 1429 * FIXME! 1430 * Pipe ID reported in CSS event is not correct for new system's 1431 * copy pipe. 1432 * VIED BZ: 1463 1433 */ 1434 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe, 1435 ¤t_event->pipe); 1436 if (asd && asd->copy_mode && 1437 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE) 1438 current_event->pipe = IA_CSS_PIPE_ID_COPY; 1439 } 1440 atomisp_css_isys_set_resolution(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,struct v4l2_mbus_framefmt * ffmt,int isys_stream)1441 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd, 1442 enum atomisp_input_stream_id stream_id, 1443 struct v4l2_mbus_framefmt *ffmt, 1444 int isys_stream) 1445 { 1446 struct ia_css_stream_config *s_config = 1447 &asd->stream_env[stream_id].stream_config; 1448 1449 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH) 1450 return -EINVAL; 1451 1452 s_config->isys_config[isys_stream].input_res.width = ffmt->width; 1453 s_config->isys_config[isys_stream].input_res.height = ffmt->height; 1454 return 0; 1455 } 1456 atomisp_css_input_set_resolution(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,struct v4l2_mbus_framefmt * ffmt)1457 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd, 1458 enum atomisp_input_stream_id stream_id, 1459 struct v4l2_mbus_framefmt *ffmt) 1460 { 1461 struct ia_css_stream_config *s_config = 1462 &asd->stream_env[stream_id].stream_config; 1463 1464 s_config->input_config.input_res.width = ffmt->width; 1465 s_config->input_config.input_res.height = ffmt->height; 1466 return 0; 1467 } 1468 atomisp_css_input_set_binning_factor(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,unsigned int bin_factor)1469 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd, 1470 enum atomisp_input_stream_id stream_id, 1471 unsigned int bin_factor) 1472 { 1473 asd->stream_env[stream_id] 1474 .stream_config.sensor_binning_factor = bin_factor; 1475 } 1476 atomisp_css_input_set_bayer_order(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum ia_css_bayer_order bayer_order)1477 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd, 1478 enum atomisp_input_stream_id stream_id, 1479 enum ia_css_bayer_order bayer_order) 1480 { 1481 struct ia_css_stream_config *s_config = 1482 &asd->stream_env[stream_id].stream_config; 1483 s_config->input_config.bayer_order = bayer_order; 1484 } 1485 atomisp_css_isys_set_link(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,int link,int isys_stream)1486 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd, 1487 enum atomisp_input_stream_id stream_id, 1488 int link, 1489 int isys_stream) 1490 { 1491 struct ia_css_stream_config *s_config = 1492 &asd->stream_env[stream_id].stream_config; 1493 1494 s_config->isys_config[isys_stream].linked_isys_stream_id = link; 1495 } 1496 atomisp_css_isys_set_valid(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,bool valid,int isys_stream)1497 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd, 1498 enum atomisp_input_stream_id stream_id, 1499 bool valid, 1500 int isys_stream) 1501 { 1502 struct ia_css_stream_config *s_config = 1503 &asd->stream_env[stream_id].stream_config; 1504 1505 s_config->isys_config[isys_stream].valid = valid; 1506 } 1507 atomisp_css_isys_set_format(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum atomisp_input_format format,int isys_stream)1508 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd, 1509 enum atomisp_input_stream_id stream_id, 1510 enum atomisp_input_format format, 1511 int isys_stream) 1512 { 1513 struct ia_css_stream_config *s_config = 1514 &asd->stream_env[stream_id].stream_config; 1515 1516 s_config->isys_config[isys_stream].format = format; 1517 } 1518 atomisp_css_input_set_format(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum atomisp_input_format format)1519 void atomisp_css_input_set_format(struct atomisp_sub_device *asd, 1520 enum atomisp_input_stream_id stream_id, 1521 enum atomisp_input_format format) 1522 { 1523 struct ia_css_stream_config *s_config = 1524 &asd->stream_env[stream_id].stream_config; 1525 1526 s_config->input_config.format = format; 1527 } 1528 atomisp_css_set_default_isys_config(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,struct v4l2_mbus_framefmt * ffmt)1529 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd, 1530 enum atomisp_input_stream_id stream_id, 1531 struct v4l2_mbus_framefmt *ffmt) 1532 { 1533 int i; 1534 struct ia_css_stream_config *s_config = 1535 &asd->stream_env[stream_id].stream_config; 1536 /* 1537 * Set all isys configs to not valid. 1538 * Currently we support only one stream per channel 1539 */ 1540 for (i = IA_CSS_STREAM_ISYS_STREAM_0; 1541 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) 1542 s_config->isys_config[i].valid = false; 1543 1544 atomisp_css_isys_set_resolution(asd, stream_id, ffmt, 1545 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 1546 atomisp_css_isys_set_format(asd, stream_id, 1547 s_config->input_config.format, 1548 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 1549 atomisp_css_isys_set_link(asd, stream_id, NO_LINK, 1550 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 1551 atomisp_css_isys_set_valid(asd, stream_id, true, 1552 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 1553 1554 return 0; 1555 } 1556 atomisp_css_isys_two_stream_cfg_update_stream1(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum atomisp_input_format input_format,unsigned int width,unsigned int height)1557 void atomisp_css_isys_two_stream_cfg_update_stream1( 1558 struct atomisp_sub_device *asd, 1559 enum atomisp_input_stream_id stream_id, 1560 enum atomisp_input_format input_format, 1561 unsigned int width, unsigned int height) 1562 { 1563 struct ia_css_stream_config *s_config = 1564 &asd->stream_env[stream_id].stream_config; 1565 1566 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width = 1567 width; 1568 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height = 1569 height; 1570 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format = 1571 input_format; 1572 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true; 1573 } 1574 atomisp_css_isys_two_stream_cfg_update_stream2(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum atomisp_input_format input_format,unsigned int width,unsigned int height)1575 void atomisp_css_isys_two_stream_cfg_update_stream2( 1576 struct atomisp_sub_device *asd, 1577 enum atomisp_input_stream_id stream_id, 1578 enum atomisp_input_format input_format, 1579 unsigned int width, unsigned int height) 1580 { 1581 struct ia_css_stream_config *s_config = 1582 &asd->stream_env[stream_id].stream_config; 1583 1584 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width = 1585 width; 1586 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height = 1587 height; 1588 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id 1589 = IA_CSS_STREAM_ISYS_STREAM_0; 1590 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format = 1591 input_format; 1592 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true; 1593 } 1594 atomisp_css_input_set_effective_resolution(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,unsigned int width,unsigned int height)1595 int atomisp_css_input_set_effective_resolution( 1596 struct atomisp_sub_device *asd, 1597 enum atomisp_input_stream_id stream_id, 1598 unsigned int width, unsigned int height) 1599 { 1600 struct ia_css_stream_config *s_config = 1601 &asd->stream_env[stream_id].stream_config; 1602 s_config->input_config.effective_res.width = width; 1603 s_config->input_config.effective_res.height = height; 1604 return 0; 1605 } 1606 atomisp_css_video_set_dis_envelope(struct atomisp_sub_device * asd,unsigned int dvs_w,unsigned int dvs_h)1607 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd, 1608 unsigned int dvs_w, unsigned int dvs_h) 1609 { 1610 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1611 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w; 1612 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1613 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h; 1614 } 1615 atomisp_css_input_set_two_pixels_per_clock(struct atomisp_sub_device * asd,bool two_ppc)1616 void atomisp_css_input_set_two_pixels_per_clock( 1617 struct atomisp_sub_device *asd, 1618 bool two_ppc) 1619 { 1620 int i; 1621 1622 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1623 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1)) 1624 return; 1625 1626 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1627 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1); 1628 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 1629 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1630 .update_pipe[i] = true; 1631 } 1632 atomisp_css_enable_dz(struct atomisp_sub_device * asd,bool enable)1633 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable) 1634 { 1635 int i; 1636 1637 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 1638 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1639 .pipe_configs[i].enable_dz = enable; 1640 } 1641 atomisp_css_capture_set_mode(struct atomisp_sub_device * asd,enum ia_css_capture_mode mode)1642 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd, 1643 enum ia_css_capture_mode mode) 1644 { 1645 struct atomisp_stream_env *stream_env = 1646 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 1647 1648 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE] 1649 .default_capture_config.mode == mode) 1650 return; 1651 1652 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]. 1653 default_capture_config.mode = mode; 1654 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true; 1655 } 1656 atomisp_css_input_set_mode(struct atomisp_sub_device * asd,enum ia_css_input_mode mode)1657 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd, 1658 enum ia_css_input_mode mode) 1659 { 1660 unsigned int size_mem_words; 1661 int i; 1662 1663 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) 1664 asd->stream_env[i].stream_config.mode = mode; 1665 1666 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 1667 return; 1668 1669 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 1670 /* 1671 * TODO: sensor needs to export the embedded_data_size_words 1672 * information to atomisp for each setting. 1673 * Here using a large safe value. 1674 */ 1675 struct ia_css_stream_config *s_config = 1676 &asd->stream_env[i].stream_config; 1677 1678 if (s_config->input_config.input_res.width == 0) 1679 continue; 1680 1681 if (ia_css_mipi_frame_calculate_size( 1682 s_config->input_config.input_res.width, 1683 s_config->input_config.input_res.height, 1684 s_config->input_config.format, 1685 true, 1686 0x13000, 1687 &size_mem_words) != 0) { 1688 if (IS_MRFD) 1689 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2; 1690 else 1691 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1; 1692 dev_warn(asd->isp->dev, 1693 "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n", 1694 size_mem_words); 1695 } 1696 s_config->mipi_buffer_config.size_mem_words = size_mem_words; 1697 s_config->mipi_buffer_config.nof_mipi_buffers = 2; 1698 } 1699 } 1700 atomisp_css_capture_enable_online(struct atomisp_sub_device * asd,unsigned short stream_index,bool enable)1701 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd, 1702 unsigned short stream_index, bool enable) 1703 { 1704 struct atomisp_stream_env *stream_env = 1705 &asd->stream_env[stream_index]; 1706 1707 if (stream_env->stream_config.online == !!enable) 1708 return; 1709 1710 stream_env->stream_config.online = !!enable; 1711 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true; 1712 } 1713 atomisp_css_preview_enable_online(struct atomisp_sub_device * asd,unsigned short stream_index,bool enable)1714 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd, 1715 unsigned short stream_index, bool enable) 1716 { 1717 struct atomisp_stream_env *stream_env = 1718 &asd->stream_env[stream_index]; 1719 int i; 1720 1721 if (stream_env->stream_config.online != !!enable) { 1722 stream_env->stream_config.online = !!enable; 1723 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 1724 stream_env->update_pipe[i] = true; 1725 } 1726 } 1727 atomisp_css_input_configure_port(struct atomisp_sub_device * asd,enum mipi_port_id port,unsigned int num_lanes,unsigned int timeout,unsigned int mipi_freq,enum atomisp_input_format metadata_format,unsigned int metadata_width,unsigned int metadata_height)1728 int atomisp_css_input_configure_port( 1729 struct atomisp_sub_device *asd, 1730 enum mipi_port_id port, 1731 unsigned int num_lanes, 1732 unsigned int timeout, 1733 unsigned int mipi_freq, 1734 enum atomisp_input_format metadata_format, 1735 unsigned int metadata_width, 1736 unsigned int metadata_height) 1737 { 1738 int i; 1739 struct atomisp_stream_env *stream_env; 1740 /* 1741 * Calculate rx_count as follows: 1742 * Input: mipi_freq : CSI-2 bus frequency in Hz 1743 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus 1744 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds 1745 * max = 145e-9 + 10 * UI 1746 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks 1747 * rxcount = rxcount0 - 2 : adjust for better results 1748 * The formula below is simplified version of the above with 1749 * 10-bit fixed points for improved accuracy. 1750 */ 1751 const unsigned int rxcount = 1752 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U; 1753 1754 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 1755 stream_env = &asd->stream_env[i]; 1756 stream_env->stream_config.source.port.port = port; 1757 stream_env->stream_config.source.port.num_lanes = num_lanes; 1758 stream_env->stream_config.source.port.timeout = timeout; 1759 if (mipi_freq) 1760 stream_env->stream_config.source.port.rxcount = rxcount; 1761 stream_env->stream_config. 1762 metadata_config.data_type = metadata_format; 1763 stream_env->stream_config. 1764 metadata_config.resolution.width = metadata_width; 1765 stream_env->stream_config. 1766 metadata_config.resolution.height = metadata_height; 1767 } 1768 1769 return 0; 1770 } 1771 atomisp_css_stop(struct atomisp_sub_device * asd,bool in_reset)1772 void atomisp_css_stop(struct atomisp_sub_device *asd, bool in_reset) 1773 { 1774 unsigned long irqflags; 1775 unsigned int i; 1776 1777 /* 1778 * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after 1779 * destroying all pipes. 1780 */ 1781 atomisp_destroy_pipes_stream(asd); 1782 1783 atomisp_init_raw_buffer_bitmap(asd); 1784 1785 ia_css_stop_sp(); 1786 1787 if (!in_reset) { 1788 struct atomisp_stream_env *stream_env; 1789 int i, j; 1790 1791 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 1792 stream_env = &asd->stream_env[i]; 1793 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { 1794 ia_css_pipe_config_defaults( 1795 &stream_env->pipe_configs[j]); 1796 ia_css_pipe_extra_config_defaults( 1797 &stream_env->pipe_extra_configs[j]); 1798 } 1799 ia_css_stream_config_defaults( 1800 &stream_env->stream_config); 1801 } 1802 memset(&asd->params.config, 0, sizeof(asd->params.config)); 1803 asd->params.css_update_params_needed = false; 1804 } 1805 1806 /* move stats buffers to free queue list */ 1807 list_splice_init(&asd->s3a_stats_in_css, &asd->s3a_stats); 1808 list_splice_init(&asd->s3a_stats_ready, &asd->s3a_stats); 1809 1810 spin_lock_irqsave(&asd->dis_stats_lock, irqflags); 1811 list_splice_init(&asd->dis_stats_in_css, &asd->dis_stats); 1812 asd->params.dis_proj_data_valid = false; 1813 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags); 1814 1815 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 1816 list_splice_init(&asd->metadata_in_css[i], &asd->metadata[i]); 1817 list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]); 1818 } 1819 1820 atomisp_flush_params_queue(&asd->video_out); 1821 atomisp_free_css_parameters(&asd->params.css_param); 1822 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param)); 1823 } 1824 atomisp_css_continuous_set_num_raw_frames(struct atomisp_sub_device * asd,int num_frames)1825 void atomisp_css_continuous_set_num_raw_frames( 1826 struct atomisp_sub_device *asd, 1827 int num_frames) 1828 { 1829 if (asd->enable_raw_buffer_lock->val) { 1830 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1831 .stream_config.init_num_cont_raw_buf = 1832 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN; 1833 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 1834 asd->params.video_dis_en) 1835 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1836 .stream_config.init_num_cont_raw_buf += 1837 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; 1838 } else { 1839 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1840 .stream_config.init_num_cont_raw_buf = 1841 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES; 1842 } 1843 1844 if (asd->params.video_dis_en) 1845 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1846 .stream_config.init_num_cont_raw_buf += 1847 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; 1848 1849 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1850 .stream_config.target_num_cont_raw_buf = num_frames; 1851 } 1852 __pipe_id_to_pipe_mode(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id)1853 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode( 1854 struct atomisp_sub_device *asd, 1855 enum ia_css_pipe_id pipe_id) 1856 { 1857 struct atomisp_device *isp = asd->isp; 1858 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info( 1859 isp->inputs[asd->input_curr].camera); 1860 1861 switch (pipe_id) { 1862 case IA_CSS_PIPE_ID_COPY: 1863 /* Currently only YUVPP mode supports YUV420_Legacy format. 1864 * Revert this when other pipe modes can support 1865 * YUV420_Legacy format. 1866 */ 1867 if (mipi_info && mipi_info->input_format == 1868 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) 1869 return IA_CSS_PIPE_MODE_YUVPP; 1870 return IA_CSS_PIPE_MODE_COPY; 1871 case IA_CSS_PIPE_ID_PREVIEW: 1872 return IA_CSS_PIPE_MODE_PREVIEW; 1873 case IA_CSS_PIPE_ID_CAPTURE: 1874 return IA_CSS_PIPE_MODE_CAPTURE; 1875 case IA_CSS_PIPE_ID_VIDEO: 1876 return IA_CSS_PIPE_MODE_VIDEO; 1877 case IA_CSS_PIPE_ID_YUVPP: 1878 return IA_CSS_PIPE_MODE_YUVPP; 1879 default: 1880 WARN_ON(1); 1881 return IA_CSS_PIPE_MODE_PREVIEW; 1882 } 1883 } 1884 __configure_output(struct atomisp_sub_device * asd,unsigned int stream_index,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format,enum ia_css_pipe_id pipe_id)1885 static void __configure_output(struct atomisp_sub_device *asd, 1886 unsigned int stream_index, 1887 unsigned int width, unsigned int height, 1888 unsigned int min_width, 1889 enum ia_css_frame_format format, 1890 enum ia_css_pipe_id pipe_id) 1891 { 1892 struct atomisp_device *isp = asd->isp; 1893 struct atomisp_stream_env *stream_env = 1894 &asd->stream_env[stream_index]; 1895 struct ia_css_stream_config *s_config = &stream_env->stream_config; 1896 1897 stream_env->pipe_configs[pipe_id].mode = 1898 __pipe_id_to_pipe_mode(asd, pipe_id); 1899 stream_env->update_pipe[pipe_id] = true; 1900 1901 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width; 1902 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height; 1903 stream_env->pipe_configs[pipe_id].output_info[0].format = format; 1904 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width; 1905 1906 /* isp binary 2.2 specific setting*/ 1907 if (width > s_config->input_config.effective_res.width || 1908 height > s_config->input_config.effective_res.height) { 1909 s_config->input_config.effective_res.width = width; 1910 s_config->input_config.effective_res.height = height; 1911 } 1912 1913 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n", 1914 pipe_id, width, height, format); 1915 } 1916 1917 /* 1918 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv 1919 * downscaling input resolution. 1920 */ __configure_capture_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,enum ia_css_pipe_id pipe_id)1921 static void __configure_capture_pp_input(struct atomisp_sub_device *asd, 1922 unsigned int width, unsigned int height, 1923 enum ia_css_pipe_id pipe_id) 1924 { 1925 struct atomisp_device *isp = asd->isp; 1926 struct atomisp_stream_env *stream_env = 1927 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 1928 struct ia_css_stream_config *stream_config = &stream_env->stream_config; 1929 struct ia_css_pipe_config *pipe_configs = 1930 &stream_env->pipe_configs[pipe_id]; 1931 struct ia_css_pipe_extra_config *pipe_extra_configs = 1932 &stream_env->pipe_extra_configs[pipe_id]; 1933 unsigned int hor_ds_factor = 0, ver_ds_factor = 0; 1934 1935 if (width == 0 && height == 0) 1936 return; 1937 1938 if (width * 9 / 10 < pipe_configs->output_info[0].res.width || 1939 height * 9 / 10 < pipe_configs->output_info[0].res.height) 1940 return; 1941 /* here just copy the calculation in css */ 1942 hor_ds_factor = CEIL_DIV(width >> 1, 1943 pipe_configs->output_info[0].res.width); 1944 ver_ds_factor = CEIL_DIV(height >> 1, 1945 pipe_configs->output_info[0].res.height); 1946 1947 if ((asd->isp->media_dev.hw_revision < 1948 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) || 1949 IS_CHT) && hor_ds_factor != ver_ds_factor) { 1950 dev_warn(asd->isp->dev, 1951 "Cropping for capture due to FW limitation"); 1952 return; 1953 } 1954 1955 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id); 1956 stream_env->update_pipe[pipe_id] = true; 1957 1958 pipe_extra_configs->enable_yuv_ds = true; 1959 1960 pipe_configs->capt_pp_in_res.width = 1961 stream_config->input_config.effective_res.width; 1962 pipe_configs->capt_pp_in_res.height = 1963 stream_config->input_config.effective_res.height; 1964 1965 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n", 1966 pipe_id, width, height); 1967 } 1968 1969 /* 1970 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and 1971 * yuv downscaling, which needs addtional configurations. 1972 */ __configure_preview_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,enum ia_css_pipe_id pipe_id)1973 static void __configure_preview_pp_input(struct atomisp_sub_device *asd, 1974 unsigned int width, unsigned int height, 1975 enum ia_css_pipe_id pipe_id) 1976 { 1977 struct atomisp_device *isp = asd->isp; 1978 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height; 1979 struct atomisp_stream_env *stream_env = 1980 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 1981 struct ia_css_stream_config *stream_config = &stream_env->stream_config; 1982 struct ia_css_pipe_config *pipe_configs = 1983 &stream_env->pipe_configs[pipe_id]; 1984 struct ia_css_pipe_extra_config *pipe_extra_configs = 1985 &stream_env->pipe_extra_configs[pipe_id]; 1986 struct ia_css_resolution *bayer_ds_out_res = 1987 &pipe_configs->bayer_ds_out_res; 1988 struct ia_css_resolution *vf_pp_in_res = 1989 &pipe_configs->vf_pp_in_res; 1990 struct ia_css_resolution *effective_res = 1991 &stream_config->input_config.effective_res; 1992 1993 static const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} }; 1994 /* 1995 * BZ201033: YUV decimation factor of 4 causes couple of rightmost 1996 * columns to be shaded. Remove this factor to work around the CSS bug. 1997 * const unsigned int yuv_dec_fct[] = {4, 2}; 1998 */ 1999 static const unsigned int yuv_dec_fct[] = { 2 }; 2000 unsigned int i; 2001 2002 if (width == 0 && height == 0) 2003 return; 2004 2005 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id); 2006 stream_env->update_pipe[pipe_id] = true; 2007 2008 out_width = pipe_configs->output_info[0].res.width; 2009 out_height = pipe_configs->output_info[0].res.height; 2010 2011 /* 2012 * The ISP could do bayer downscaling, yuv decimation and yuv 2013 * downscaling: 2014 * 1: Bayer Downscaling: between effective resolution and 2015 * bayer_ds_res_out; 2016 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res; 2017 * 3: YUV Downscaling: between vf_pp_in_res and final vf output 2018 * 2019 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25 2020 * Rule for YUV Decimation: support factor 2, 4 2021 * Rule for YUV Downscaling: arbitrary value below 2 2022 * 2023 * General rule of factor distribution among these stages: 2024 * 1: try to do Bayer downscaling first if not in online mode. 2025 * 2: try to do maximum of 2 for YUV downscaling 2026 * 3: the remainling for YUV decimation 2027 * 2028 * Note: 2029 * Do not configure bayer_ds_out_res if: 2030 * online == 1 or continuous == 0 or raw_binning = 0 2031 */ 2032 if (stream_config->online || !stream_config->continuous || 2033 !pipe_extra_configs->enable_raw_binning) { 2034 bayer_ds_out_res->width = 0; 2035 bayer_ds_out_res->height = 0; 2036 } else { 2037 bayer_ds_out_res->width = effective_res->width; 2038 bayer_ds_out_res->height = effective_res->height; 2039 2040 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) { 2041 if (effective_res->width >= out_width * 2042 bds_fct[i].numerator / bds_fct[i].denominator && 2043 effective_res->height >= out_height * 2044 bds_fct[i].numerator / bds_fct[i].denominator) { 2045 bayer_ds_out_res->width = 2046 effective_res->width * 2047 bds_fct[i].denominator / 2048 bds_fct[i].numerator; 2049 bayer_ds_out_res->height = 2050 effective_res->height * 2051 bds_fct[i].denominator / 2052 bds_fct[i].numerator; 2053 break; 2054 } 2055 } 2056 } 2057 /* 2058 * calculate YUV Decimation, YUV downscaling facor: 2059 * YUV Downscaling factor must not exceed 2. 2060 * YUV Decimation factor could be 2, 4. 2061 */ 2062 /* first decide the yuv_ds input resolution */ 2063 if (bayer_ds_out_res->width == 0) { 2064 yuv_ds_in_width = effective_res->width; 2065 yuv_ds_in_height = effective_res->height; 2066 } else { 2067 yuv_ds_in_width = bayer_ds_out_res->width; 2068 yuv_ds_in_height = bayer_ds_out_res->height; 2069 } 2070 2071 vf_pp_in_res->width = yuv_ds_in_width; 2072 vf_pp_in_res->height = yuv_ds_in_height; 2073 2074 /* find out the yuv decimation factor */ 2075 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) { 2076 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] && 2077 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) { 2078 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i]; 2079 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i]; 2080 break; 2081 } 2082 } 2083 2084 if (vf_pp_in_res->width == out_width && 2085 vf_pp_in_res->height == out_height) { 2086 pipe_extra_configs->enable_yuv_ds = false; 2087 vf_pp_in_res->width = 0; 2088 vf_pp_in_res->height = 0; 2089 } else { 2090 pipe_extra_configs->enable_yuv_ds = true; 2091 } 2092 2093 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n", 2094 pipe_id, width, height); 2095 } 2096 2097 /* 2098 * For CSS2.1, offline video pipe could support bayer decimation, and 2099 * yuv downscaling, which needs addtional configurations. 2100 */ __configure_video_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,enum ia_css_pipe_id pipe_id)2101 static void __configure_video_pp_input(struct atomisp_sub_device *asd, 2102 unsigned int width, unsigned int height, 2103 enum ia_css_pipe_id pipe_id) 2104 { 2105 struct atomisp_device *isp = asd->isp; 2106 int out_width, out_height; 2107 struct atomisp_stream_env *stream_env = 2108 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2109 struct ia_css_stream_config *stream_config = &stream_env->stream_config; 2110 struct ia_css_pipe_config *pipe_configs = 2111 &stream_env->pipe_configs[pipe_id]; 2112 struct ia_css_pipe_extra_config *pipe_extra_configs = 2113 &stream_env->pipe_extra_configs[pipe_id]; 2114 struct ia_css_resolution *bayer_ds_out_res = 2115 &pipe_configs->bayer_ds_out_res; 2116 struct ia_css_resolution *effective_res = 2117 &stream_config->input_config.effective_res; 2118 2119 static const struct bayer_ds_factor bds_factors[] = { 2120 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2} 2121 }; 2122 unsigned int i; 2123 2124 if (width == 0 && height == 0) 2125 return; 2126 2127 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id); 2128 stream_env->update_pipe[pipe_id] = true; 2129 2130 pipe_extra_configs->enable_yuv_ds = false; 2131 2132 /* 2133 * If DVS is enabled, video binary will take care the dvs envelope 2134 * and usually the bayer_ds_out_res should be larger than 120% of 2135 * destination resolution, the extra 20% will be cropped as DVS 2136 * envelope. But, if the bayer_ds_out_res is less than 120% of the 2137 * destination. The ISP can still work, but DVS quality is not good. 2138 */ 2139 /* taking at least 10% as envelope */ 2140 if (asd->params.video_dis_en) { 2141 out_width = pipe_configs->output_info[0].res.width * 110 / 100; 2142 out_height = pipe_configs->output_info[0].res.height * 110 / 100; 2143 } else { 2144 out_width = pipe_configs->output_info[0].res.width; 2145 out_height = pipe_configs->output_info[0].res.height; 2146 } 2147 2148 /* 2149 * calculate bayer decimate factor: 2150 * 1: only 1.5, 2, 4 and 8 get supported 2151 * 2: Do not configure bayer_ds_out_res if: 2152 * online == 1 or continuous == 0 or raw_binning = 0 2153 */ 2154 if (stream_config->online || !stream_config->continuous) { 2155 bayer_ds_out_res->width = 0; 2156 bayer_ds_out_res->height = 0; 2157 goto done; 2158 } 2159 2160 pipe_extra_configs->enable_raw_binning = true; 2161 bayer_ds_out_res->width = effective_res->width; 2162 bayer_ds_out_res->height = effective_res->height; 2163 2164 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor); 2165 i++) { 2166 if (effective_res->width >= out_width * 2167 bds_factors[i].numerator / bds_factors[i].denominator && 2168 effective_res->height >= out_height * 2169 bds_factors[i].numerator / bds_factors[i].denominator) { 2170 bayer_ds_out_res->width = effective_res->width * 2171 bds_factors[i].denominator / 2172 bds_factors[i].numerator; 2173 bayer_ds_out_res->height = effective_res->height * 2174 bds_factors[i].denominator / 2175 bds_factors[i].numerator; 2176 break; 2177 } 2178 } 2179 2180 /* 2181 * DVS is cropped from BDS output, so we do not really need to set the 2182 * envelope to 20% of output resolution here. always set it to 12x12 2183 * per firmware requirement. 2184 */ 2185 pipe_configs->dvs_envelope.width = 12; 2186 pipe_configs->dvs_envelope.height = 12; 2187 2188 done: 2189 if (pipe_id == IA_CSS_PIPE_ID_YUVPP) 2190 stream_config->left_padding = -1; 2191 else 2192 stream_config->left_padding = 12; 2193 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n", 2194 pipe_id, width, height); 2195 } 2196 __configure_vf_output(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format,enum ia_css_pipe_id pipe_id)2197 static void __configure_vf_output(struct atomisp_sub_device *asd, 2198 unsigned int width, unsigned int height, 2199 unsigned int min_width, 2200 enum ia_css_frame_format format, 2201 enum ia_css_pipe_id pipe_id) 2202 { 2203 struct atomisp_device *isp = asd->isp; 2204 struct atomisp_stream_env *stream_env = 2205 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2206 stream_env->pipe_configs[pipe_id].mode = 2207 __pipe_id_to_pipe_mode(asd, pipe_id); 2208 stream_env->update_pipe[pipe_id] = true; 2209 2210 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width; 2211 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height; 2212 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format; 2213 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width = 2214 min_width; 2215 dev_dbg(isp->dev, 2216 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n", 2217 pipe_id, width, height, format); 2218 } 2219 __get_frame_info(struct atomisp_sub_device * asd,unsigned int stream_index,struct ia_css_frame_info * info,enum frame_info_type type,enum ia_css_pipe_id pipe_id)2220 static int __get_frame_info(struct atomisp_sub_device *asd, 2221 unsigned int stream_index, 2222 struct ia_css_frame_info *info, 2223 enum frame_info_type type, 2224 enum ia_css_pipe_id pipe_id) 2225 { 2226 struct atomisp_device *isp = asd->isp; 2227 int ret; 2228 struct ia_css_pipe_info p_info; 2229 2230 /* FIXME! No need to destroy/recreate all streams */ 2231 ret = atomisp_css_update_stream(asd); 2232 if (ret) 2233 return ret; 2234 2235 ret = ia_css_pipe_get_info(asd->stream_env[stream_index].pipes[pipe_id], 2236 &p_info); 2237 if (ret) { 2238 dev_err(isp->dev, "can't get info from pipe\n"); 2239 goto get_info_err; 2240 } 2241 2242 switch (type) { 2243 case ATOMISP_CSS_VF_FRAME: 2244 *info = p_info.vf_output_info[0]; 2245 dev_dbg(isp->dev, "getting vf frame info.\n"); 2246 break; 2247 case ATOMISP_CSS_SECOND_VF_FRAME: 2248 *info = p_info.vf_output_info[1]; 2249 dev_dbg(isp->dev, "getting second vf frame info.\n"); 2250 break; 2251 case ATOMISP_CSS_OUTPUT_FRAME: 2252 *info = p_info.output_info[0]; 2253 dev_dbg(isp->dev, "getting main frame info.\n"); 2254 break; 2255 case ATOMISP_CSS_SECOND_OUTPUT_FRAME: 2256 *info = p_info.output_info[1]; 2257 dev_dbg(isp->dev, "getting second main frame info.\n"); 2258 break; 2259 default: 2260 case ATOMISP_CSS_RAW_FRAME: 2261 *info = p_info.raw_output_info; 2262 dev_dbg(isp->dev, "getting raw frame info.\n"); 2263 break; 2264 } 2265 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n", 2266 info->res.width, info->res.height, p_info.num_invalid_frames); 2267 2268 return 0; 2269 2270 get_info_err: 2271 atomisp_destroy_pipes_stream(asd); 2272 return -EINVAL; 2273 } 2274 atomisp_get_pipe_index(struct atomisp_sub_device * asd)2275 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd) 2276 { 2277 if (asd->copy_mode) 2278 return IA_CSS_PIPE_ID_COPY; 2279 2280 switch (asd->run_mode->val) { 2281 case ATOMISP_RUN_MODE_VIDEO: 2282 return IA_CSS_PIPE_ID_VIDEO; 2283 case ATOMISP_RUN_MODE_STILL_CAPTURE: 2284 return IA_CSS_PIPE_ID_CAPTURE; 2285 case ATOMISP_RUN_MODE_PREVIEW: 2286 return IA_CSS_PIPE_ID_PREVIEW; 2287 } 2288 2289 dev_warn(asd->isp->dev, "cannot determine pipe-index return default preview pipe\n"); 2290 return IA_CSS_PIPE_ID_PREVIEW; 2291 } 2292 atomisp_get_css_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * frame_info)2293 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, 2294 struct ia_css_frame_info *frame_info) 2295 { 2296 struct ia_css_pipe_info info; 2297 int pipe_index = atomisp_get_pipe_index(asd); 2298 int stream_index; 2299 struct atomisp_device *isp = asd->isp; 2300 2301 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ? 2302 ATOMISP_INPUT_STREAM_VIDEO : 2303 ATOMISP_INPUT_STREAM_GENERAL; 2304 2305 if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index] 2306 .pipes[pipe_index], &info)) { 2307 dev_dbg(isp->dev, "ia_css_pipe_get_info FAILED"); 2308 return -EINVAL; 2309 } 2310 2311 *frame_info = info.output_info[0]; 2312 return 0; 2313 } 2314 atomisp_css_copy_configure_output(struct atomisp_sub_device * asd,unsigned int stream_index,unsigned int width,unsigned int height,unsigned int padded_width,enum ia_css_frame_format format)2315 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd, 2316 unsigned int stream_index, 2317 unsigned int width, unsigned int height, 2318 unsigned int padded_width, 2319 enum ia_css_frame_format format) 2320 { 2321 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY]. 2322 default_capture_config.mode = 2323 IA_CSS_CAPTURE_MODE_RAW; 2324 2325 __configure_output(asd, stream_index, width, height, padded_width, 2326 format, IA_CSS_PIPE_ID_COPY); 2327 return 0; 2328 } 2329 atomisp_css_preview_configure_output(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2330 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd, 2331 unsigned int width, unsigned int height, 2332 unsigned int min_width, 2333 enum ia_css_frame_format format) 2334 { 2335 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, 2336 min_width, format, IA_CSS_PIPE_ID_PREVIEW); 2337 return 0; 2338 } 2339 atomisp_css_capture_configure_output(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2340 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd, 2341 unsigned int width, unsigned int height, 2342 unsigned int min_width, 2343 enum ia_css_frame_format format) 2344 { 2345 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, 2346 min_width, format, IA_CSS_PIPE_ID_CAPTURE); 2347 return 0; 2348 } 2349 atomisp_css_video_configure_output(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2350 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd, 2351 unsigned int width, unsigned int height, 2352 unsigned int min_width, 2353 enum ia_css_frame_format format) 2354 { 2355 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, 2356 min_width, format, IA_CSS_PIPE_ID_VIDEO); 2357 return 0; 2358 } 2359 atomisp_css_video_configure_viewfinder(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2360 int atomisp_css_video_configure_viewfinder( 2361 struct atomisp_sub_device *asd, 2362 unsigned int width, unsigned int height, 2363 unsigned int min_width, 2364 enum ia_css_frame_format format) 2365 { 2366 __configure_vf_output(asd, width, height, min_width, format, 2367 IA_CSS_PIPE_ID_VIDEO); 2368 return 0; 2369 } 2370 atomisp_css_capture_configure_viewfinder(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2371 int atomisp_css_capture_configure_viewfinder( 2372 struct atomisp_sub_device *asd, 2373 unsigned int width, unsigned int height, 2374 unsigned int min_width, 2375 enum ia_css_frame_format format) 2376 { 2377 __configure_vf_output(asd, width, height, min_width, format, IA_CSS_PIPE_ID_CAPTURE); 2378 return 0; 2379 } 2380 atomisp_css_video_get_viewfinder_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)2381 int atomisp_css_video_get_viewfinder_frame_info( 2382 struct atomisp_sub_device *asd, 2383 struct ia_css_frame_info *info) 2384 { 2385 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 2386 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_VIDEO); 2387 } 2388 atomisp_css_capture_get_viewfinder_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)2389 int atomisp_css_capture_get_viewfinder_frame_info( 2390 struct atomisp_sub_device *asd, 2391 struct ia_css_frame_info *info) 2392 { 2393 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 2394 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_CAPTURE); 2395 } 2396 atomisp_css_copy_get_output_frame_info(struct atomisp_sub_device * asd,unsigned int stream_index,struct ia_css_frame_info * info)2397 int atomisp_css_copy_get_output_frame_info( 2398 struct atomisp_sub_device *asd, 2399 unsigned int stream_index, 2400 struct ia_css_frame_info *info) 2401 { 2402 return __get_frame_info(asd, stream_index, info, 2403 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY); 2404 } 2405 atomisp_css_preview_get_output_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)2406 int atomisp_css_preview_get_output_frame_info( 2407 struct atomisp_sub_device *asd, 2408 struct ia_css_frame_info *info) 2409 { 2410 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 2411 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_PREVIEW); 2412 } 2413 atomisp_css_capture_get_output_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)2414 int atomisp_css_capture_get_output_frame_info( 2415 struct atomisp_sub_device *asd, 2416 struct ia_css_frame_info *info) 2417 { 2418 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 2419 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_CAPTURE); 2420 } 2421 atomisp_css_video_get_output_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)2422 int atomisp_css_video_get_output_frame_info( 2423 struct atomisp_sub_device *asd, 2424 struct ia_css_frame_info *info) 2425 { 2426 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 2427 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_VIDEO); 2428 } 2429 atomisp_css_preview_configure_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height)2430 int atomisp_css_preview_configure_pp_input( 2431 struct atomisp_sub_device *asd, 2432 unsigned int width, unsigned int height) 2433 { 2434 struct atomisp_stream_env *stream_env = 2435 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2436 __configure_preview_pp_input(asd, width, height, IA_CSS_PIPE_ID_PREVIEW); 2437 2438 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]. 2439 capt_pp_in_res.width) 2440 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE); 2441 2442 return 0; 2443 } 2444 atomisp_css_capture_configure_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height)2445 int atomisp_css_capture_configure_pp_input( 2446 struct atomisp_sub_device *asd, 2447 unsigned int width, unsigned int height) 2448 { 2449 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE); 2450 return 0; 2451 } 2452 atomisp_css_video_configure_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height)2453 int atomisp_css_video_configure_pp_input( 2454 struct atomisp_sub_device *asd, 2455 unsigned int width, unsigned int height) 2456 { 2457 struct atomisp_stream_env *stream_env = 2458 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2459 2460 __configure_video_pp_input(asd, width, height, IA_CSS_PIPE_ID_VIDEO); 2461 2462 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]. 2463 capt_pp_in_res.width) 2464 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE); 2465 2466 return 0; 2467 } 2468 atomisp_css_offline_capture_configure(struct atomisp_sub_device * asd,int num_captures,unsigned int skip,int offset)2469 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd, 2470 int num_captures, unsigned int skip, int offset) 2471 { 2472 int ret; 2473 2474 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n", 2475 __func__, num_captures, skip, offset); 2476 2477 ret = ia_css_stream_capture( 2478 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2479 num_captures, skip, offset); 2480 if (ret) 2481 return -EINVAL; 2482 2483 return 0; 2484 } 2485 atomisp_css_exp_id_capture(struct atomisp_sub_device * asd,int exp_id)2486 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id) 2487 { 2488 int ret; 2489 2490 ret = ia_css_stream_capture_frame( 2491 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2492 exp_id); 2493 if (ret == -ENOBUFS) { 2494 /* capture cmd queue is full */ 2495 return -EBUSY; 2496 } else if (ret) { 2497 return -EIO; 2498 } 2499 2500 return 0; 2501 } 2502 atomisp_css_exp_id_unlock(struct atomisp_sub_device * asd,int exp_id)2503 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id) 2504 { 2505 int ret; 2506 2507 ret = ia_css_unlock_raw_frame( 2508 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2509 exp_id); 2510 if (ret == -ENOBUFS) 2511 return -EAGAIN; 2512 else if (ret) 2513 return -EIO; 2514 2515 return 0; 2516 } 2517 atomisp_css_capture_enable_xnr(struct atomisp_sub_device * asd,bool enable)2518 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd, 2519 bool enable) 2520 { 2521 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2522 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE] 2523 .default_capture_config.enable_xnr = enable; 2524 asd->params.capture_config.enable_xnr = enable; 2525 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2526 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true; 2527 2528 return 0; 2529 } 2530 atomisp_css_set_ctc_table(struct atomisp_sub_device * asd,struct ia_css_ctc_table * ctc_table)2531 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd, 2532 struct ia_css_ctc_table *ctc_table) 2533 { 2534 int i; 2535 u16 *vamem_ptr = ctc_table->data.vamem_1; 2536 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE; 2537 bool valid = false; 2538 2539 /* workaround: if ctc_table is all 0, do not apply it */ 2540 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) { 2541 vamem_ptr = ctc_table->data.vamem_2; 2542 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE; 2543 } 2544 2545 for (i = 0; i < data_size; i++) { 2546 if (*(vamem_ptr + i)) { 2547 valid = true; 2548 break; 2549 } 2550 } 2551 2552 if (valid) 2553 asd->params.config.ctc_table = ctc_table; 2554 else 2555 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n"); 2556 } 2557 atomisp_css_set_anr_thres(struct atomisp_sub_device * asd,struct ia_css_anr_thres * anr_thres)2558 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd, 2559 struct ia_css_anr_thres *anr_thres) 2560 { 2561 asd->params.config.anr_thres = anr_thres; 2562 } 2563 atomisp_css_set_dvs_6axis(struct atomisp_sub_device * asd,struct ia_css_dvs_6axis_config * dvs_6axis)2564 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd, 2565 struct ia_css_dvs_6axis_config *dvs_6axis) 2566 { 2567 asd->params.config.dvs_6axis_config = dvs_6axis; 2568 } 2569 atomisp_css_video_set_dis_vector(struct atomisp_sub_device * asd,struct atomisp_dis_vector * vector)2570 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd, 2571 struct atomisp_dis_vector *vector) 2572 { 2573 if (!asd->params.config.motion_vector) 2574 asd->params.config.motion_vector = &asd->params.css_param.motion_vector; 2575 2576 memset(asd->params.config.motion_vector, 2577 0, sizeof(struct ia_css_vector)); 2578 asd->params.css_param.motion_vector.x = vector->x; 2579 asd->params.css_param.motion_vector.y = vector->y; 2580 } 2581 atomisp_compare_dvs_grid(struct atomisp_sub_device * asd,struct atomisp_dvs_grid_info * atomgrid)2582 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd, 2583 struct atomisp_dvs_grid_info *atomgrid) 2584 { 2585 struct ia_css_dvs_grid_info *cur = 2586 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 2587 2588 if (!cur) { 2589 dev_err(asd->isp->dev, "dvs grid not available!\n"); 2590 return -EINVAL; 2591 } 2592 2593 if (sizeof(*cur) != sizeof(*atomgrid)) { 2594 dev_err(asd->isp->dev, "dvs grid mismatch!\n"); 2595 return -EINVAL; 2596 } 2597 2598 if (!cur->enable) { 2599 dev_err(asd->isp->dev, "dvs not enabled!\n"); 2600 return -EINVAL; 2601 } 2602 2603 return memcmp(atomgrid, cur, sizeof(*cur)); 2604 } 2605 atomisp_css_set_dvs2_coefs(struct atomisp_sub_device * asd,struct ia_css_dvs2_coefficients * coefs)2606 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd, 2607 struct ia_css_dvs2_coefficients *coefs) 2608 { 2609 asd->params.config.dvs2_coefs = coefs; 2610 } 2611 atomisp_css_set_dis_coefs(struct atomisp_sub_device * asd,struct atomisp_dis_coefficients * coefs)2612 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd, 2613 struct atomisp_dis_coefficients *coefs) 2614 { 2615 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0) 2616 /* If the grid info in the argument differs from the current 2617 grid info, we tell the caller to reset the grid size and 2618 try again. */ 2619 return -EAGAIN; 2620 2621 if (!coefs->hor_coefs.odd_real || 2622 !coefs->hor_coefs.odd_imag || 2623 !coefs->hor_coefs.even_real || 2624 !coefs->hor_coefs.even_imag || 2625 !coefs->ver_coefs.odd_real || 2626 !coefs->ver_coefs.odd_imag || 2627 !coefs->ver_coefs.even_real || 2628 !coefs->ver_coefs.even_imag || 2629 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real || 2630 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag || 2631 !asd->params.css_param.dvs2_coeff->hor_coefs.even_real || 2632 !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag || 2633 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real || 2634 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag || 2635 !asd->params.css_param.dvs2_coeff->ver_coefs.even_real || 2636 !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag) 2637 return -EINVAL; 2638 2639 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real, 2640 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes)) 2641 return -EFAULT; 2642 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag, 2643 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes)) 2644 return -EFAULT; 2645 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real, 2646 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes)) 2647 return -EFAULT; 2648 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag, 2649 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes)) 2650 return -EFAULT; 2651 2652 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real, 2653 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes)) 2654 return -EFAULT; 2655 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag, 2656 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes)) 2657 return -EFAULT; 2658 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real, 2659 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes)) 2660 return -EFAULT; 2661 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag, 2662 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes)) 2663 return -EFAULT; 2664 2665 asd->params.css_param.update_flag.dvs2_coefs = 2666 (struct atomisp_dis_coefficients *) 2667 asd->params.css_param.dvs2_coeff; 2668 /* FIXME! */ 2669 /* asd->params.dis_proj_data_valid = false; */ 2670 asd->params.css_update_params_needed = true; 2671 2672 return 0; 2673 } 2674 atomisp_css_set_zoom_factor(struct atomisp_sub_device * asd,unsigned int zoom)2675 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd, 2676 unsigned int zoom) 2677 { 2678 struct atomisp_device *isp = asd->isp; 2679 2680 if (zoom == asd->params.css_param.dz_config.dx && 2681 zoom == asd->params.css_param.dz_config.dy) { 2682 dev_dbg(isp->dev, "same zoom scale. skipped.\n"); 2683 return; 2684 } 2685 2686 memset(&asd->params.css_param.dz_config, 0, 2687 sizeof(struct ia_css_dz_config)); 2688 asd->params.css_param.dz_config.dx = zoom; 2689 asd->params.css_param.dz_config.dy = zoom; 2690 2691 asd->params.css_param.update_flag.dz_config = 2692 (struct atomisp_dz_config *)&asd->params.css_param.dz_config; 2693 asd->params.css_update_params_needed = true; 2694 } 2695 atomisp_css_set_formats_config(struct atomisp_sub_device * asd,struct ia_css_formats_config * formats_config)2696 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd, 2697 struct ia_css_formats_config *formats_config) 2698 { 2699 asd->params.config.formats_config = formats_config; 2700 } 2701 atomisp_css_get_wb_config(struct atomisp_sub_device * asd,struct atomisp_wb_config * config)2702 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd, 2703 struct atomisp_wb_config *config) 2704 { 2705 struct ia_css_wb_config wb_config; 2706 struct ia_css_isp_config isp_config; 2707 struct atomisp_device *isp = asd->isp; 2708 2709 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2710 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2711 __func__); 2712 return -EINVAL; 2713 } 2714 memset(&wb_config, 0, sizeof(struct ia_css_wb_config)); 2715 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2716 isp_config.wb_config = &wb_config; 2717 ia_css_stream_get_isp_config( 2718 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2719 &isp_config); 2720 memcpy(config, &wb_config, sizeof(*config)); 2721 2722 return 0; 2723 } 2724 atomisp_css_get_ob_config(struct atomisp_sub_device * asd,struct atomisp_ob_config * config)2725 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd, 2726 struct atomisp_ob_config *config) 2727 { 2728 struct ia_css_ob_config ob_config; 2729 struct ia_css_isp_config isp_config; 2730 struct atomisp_device *isp = asd->isp; 2731 2732 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2733 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2734 __func__); 2735 return -EINVAL; 2736 } 2737 memset(&ob_config, 0, sizeof(struct ia_css_ob_config)); 2738 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2739 isp_config.ob_config = &ob_config; 2740 ia_css_stream_get_isp_config( 2741 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2742 &isp_config); 2743 memcpy(config, &ob_config, sizeof(*config)); 2744 2745 return 0; 2746 } 2747 atomisp_css_get_dp_config(struct atomisp_sub_device * asd,struct atomisp_dp_config * config)2748 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd, 2749 struct atomisp_dp_config *config) 2750 { 2751 struct ia_css_dp_config dp_config; 2752 struct ia_css_isp_config isp_config; 2753 struct atomisp_device *isp = asd->isp; 2754 2755 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2756 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2757 __func__); 2758 return -EINVAL; 2759 } 2760 memset(&dp_config, 0, sizeof(struct ia_css_dp_config)); 2761 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2762 isp_config.dp_config = &dp_config; 2763 ia_css_stream_get_isp_config( 2764 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2765 &isp_config); 2766 memcpy(config, &dp_config, sizeof(*config)); 2767 2768 return 0; 2769 } 2770 atomisp_css_get_de_config(struct atomisp_sub_device * asd,struct atomisp_de_config * config)2771 int atomisp_css_get_de_config(struct atomisp_sub_device *asd, 2772 struct atomisp_de_config *config) 2773 { 2774 struct ia_css_de_config de_config; 2775 struct ia_css_isp_config isp_config; 2776 struct atomisp_device *isp = asd->isp; 2777 2778 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2779 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2780 __func__); 2781 return -EINVAL; 2782 } 2783 memset(&de_config, 0, sizeof(struct ia_css_de_config)); 2784 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2785 isp_config.de_config = &de_config; 2786 ia_css_stream_get_isp_config( 2787 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2788 &isp_config); 2789 memcpy(config, &de_config, sizeof(*config)); 2790 2791 return 0; 2792 } 2793 atomisp_css_get_nr_config(struct atomisp_sub_device * asd,struct atomisp_nr_config * config)2794 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd, 2795 struct atomisp_nr_config *config) 2796 { 2797 struct ia_css_nr_config nr_config; 2798 struct ia_css_isp_config isp_config; 2799 struct atomisp_device *isp = asd->isp; 2800 2801 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2802 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2803 __func__); 2804 return -EINVAL; 2805 } 2806 memset(&nr_config, 0, sizeof(struct ia_css_nr_config)); 2807 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2808 2809 isp_config.nr_config = &nr_config; 2810 ia_css_stream_get_isp_config( 2811 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2812 &isp_config); 2813 memcpy(config, &nr_config, sizeof(*config)); 2814 2815 return 0; 2816 } 2817 atomisp_css_get_ee_config(struct atomisp_sub_device * asd,struct atomisp_ee_config * config)2818 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd, 2819 struct atomisp_ee_config *config) 2820 { 2821 struct ia_css_ee_config ee_config; 2822 struct ia_css_isp_config isp_config; 2823 struct atomisp_device *isp = asd->isp; 2824 2825 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2826 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2827 __func__); 2828 return -EINVAL; 2829 } 2830 memset(&ee_config, 0, sizeof(struct ia_css_ee_config)); 2831 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2832 isp_config.ee_config = &ee_config; 2833 ia_css_stream_get_isp_config( 2834 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2835 &isp_config); 2836 memcpy(config, &ee_config, sizeof(*config)); 2837 2838 return 0; 2839 } 2840 atomisp_css_get_tnr_config(struct atomisp_sub_device * asd,struct atomisp_tnr_config * config)2841 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd, 2842 struct atomisp_tnr_config *config) 2843 { 2844 struct ia_css_tnr_config tnr_config; 2845 struct ia_css_isp_config isp_config; 2846 struct atomisp_device *isp = asd->isp; 2847 2848 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2849 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2850 __func__); 2851 return -EINVAL; 2852 } 2853 memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config)); 2854 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2855 isp_config.tnr_config = &tnr_config; 2856 ia_css_stream_get_isp_config( 2857 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2858 &isp_config); 2859 memcpy(config, &tnr_config, sizeof(*config)); 2860 2861 return 0; 2862 } 2863 atomisp_css_get_ctc_table(struct atomisp_sub_device * asd,struct atomisp_ctc_table * config)2864 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd, 2865 struct atomisp_ctc_table *config) 2866 { 2867 struct ia_css_ctc_table *tab; 2868 struct ia_css_isp_config isp_config; 2869 struct atomisp_device *isp = asd->isp; 2870 2871 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2872 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2873 __func__); 2874 return -EINVAL; 2875 } 2876 2877 tab = vzalloc(sizeof(struct ia_css_ctc_table)); 2878 if (!tab) 2879 return -ENOMEM; 2880 2881 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2882 isp_config.ctc_table = tab; 2883 ia_css_stream_get_isp_config( 2884 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2885 &isp_config); 2886 memcpy(config, tab, sizeof(*tab)); 2887 vfree(tab); 2888 2889 return 0; 2890 } 2891 atomisp_css_get_gamma_table(struct atomisp_sub_device * asd,struct atomisp_gamma_table * config)2892 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd, 2893 struct atomisp_gamma_table *config) 2894 { 2895 struct ia_css_gamma_table *tab; 2896 struct ia_css_isp_config isp_config; 2897 struct atomisp_device *isp = asd->isp; 2898 2899 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2900 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2901 __func__); 2902 return -EINVAL; 2903 } 2904 2905 tab = vzalloc(sizeof(struct ia_css_gamma_table)); 2906 if (!tab) 2907 return -ENOMEM; 2908 2909 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2910 isp_config.gamma_table = tab; 2911 ia_css_stream_get_isp_config( 2912 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2913 &isp_config); 2914 memcpy(config, tab, sizeof(*tab)); 2915 vfree(tab); 2916 2917 return 0; 2918 } 2919 atomisp_css_get_gc_config(struct atomisp_sub_device * asd,struct atomisp_gc_config * config)2920 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd, 2921 struct atomisp_gc_config *config) 2922 { 2923 struct ia_css_gc_config gc_config; 2924 struct ia_css_isp_config isp_config; 2925 struct atomisp_device *isp = asd->isp; 2926 2927 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2928 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2929 __func__); 2930 return -EINVAL; 2931 } 2932 memset(&gc_config, 0, sizeof(struct ia_css_gc_config)); 2933 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2934 isp_config.gc_config = &gc_config; 2935 ia_css_stream_get_isp_config( 2936 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2937 &isp_config); 2938 /* Get gamma correction params from current setup */ 2939 memcpy(config, &gc_config, sizeof(*config)); 2940 2941 return 0; 2942 } 2943 atomisp_css_get_3a_config(struct atomisp_sub_device * asd,struct atomisp_3a_config * config)2944 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd, 2945 struct atomisp_3a_config *config) 2946 { 2947 struct ia_css_3a_config s3a_config; 2948 struct ia_css_isp_config isp_config; 2949 struct atomisp_device *isp = asd->isp; 2950 2951 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2952 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2953 __func__); 2954 return -EINVAL; 2955 } 2956 memset(&s3a_config, 0, sizeof(struct ia_css_3a_config)); 2957 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 2958 isp_config.s3a_config = &s3a_config; 2959 ia_css_stream_get_isp_config( 2960 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2961 &isp_config); 2962 /* Get white balance from current setup */ 2963 memcpy(config, &s3a_config, sizeof(*config)); 2964 2965 return 0; 2966 } 2967 atomisp_css_get_formats_config(struct atomisp_sub_device * asd,struct atomisp_formats_config * config)2968 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd, 2969 struct atomisp_formats_config *config) 2970 { 2971 struct ia_css_formats_config formats_config; 2972 struct ia_css_isp_config isp_config; 2973 struct atomisp_device *isp = asd->isp; 2974 2975 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 2976 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 2977 __func__); 2978 return -EINVAL; 2979 } 2980 memset(&formats_config, 0, sizeof(formats_config)); 2981 memset(&isp_config, 0, sizeof(isp_config)); 2982 isp_config.formats_config = &formats_config; 2983 ia_css_stream_get_isp_config( 2984 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2985 &isp_config); 2986 /* Get narrow gamma from current setup */ 2987 memcpy(config, &formats_config, sizeof(*config)); 2988 2989 return 0; 2990 } 2991 atomisp_css_get_zoom_factor(struct atomisp_sub_device * asd,unsigned int * zoom)2992 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd, 2993 unsigned int *zoom) 2994 { 2995 struct ia_css_dz_config dz_config; /** Digital Zoom */ 2996 struct ia_css_isp_config isp_config; 2997 struct atomisp_device *isp = asd->isp; 2998 2999 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3000 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3001 __func__); 3002 return -EINVAL; 3003 } 3004 memset(&dz_config, 0, sizeof(struct ia_css_dz_config)); 3005 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3006 isp_config.dz_config = &dz_config; 3007 ia_css_stream_get_isp_config( 3008 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3009 &isp_config); 3010 *zoom = dz_config.dx; 3011 3012 return 0; 3013 } 3014 3015 /* 3016 * Function to set/get image stablization statistics 3017 */ atomisp_css_get_dis_stat(struct atomisp_sub_device * asd,struct atomisp_dis_statistics * stats)3018 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd, 3019 struct atomisp_dis_statistics *stats) 3020 { 3021 struct atomisp_device *isp = asd->isp; 3022 struct atomisp_dis_buf *dis_buf; 3023 unsigned long flags; 3024 3025 lockdep_assert_held(&isp->mutex); 3026 3027 if (!asd->params.dvs_stat->hor_prod.odd_real || 3028 !asd->params.dvs_stat->hor_prod.odd_imag || 3029 !asd->params.dvs_stat->hor_prod.even_real || 3030 !asd->params.dvs_stat->hor_prod.even_imag || 3031 !asd->params.dvs_stat->ver_prod.odd_real || 3032 !asd->params.dvs_stat->ver_prod.odd_imag || 3033 !asd->params.dvs_stat->ver_prod.even_real || 3034 !asd->params.dvs_stat->ver_prod.even_imag) 3035 return -EINVAL; 3036 3037 /* isp needs to be streaming to get DIS statistics */ 3038 if (!asd->streaming) 3039 return -EINVAL; 3040 3041 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0) 3042 /* If the grid info in the argument differs from the current 3043 grid info, we tell the caller to reset the grid size and 3044 try again. */ 3045 return -EAGAIN; 3046 3047 spin_lock_irqsave(&asd->dis_stats_lock, flags); 3048 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) { 3049 spin_unlock_irqrestore(&asd->dis_stats_lock, flags); 3050 dev_err(isp->dev, "dis statistics is not valid.\n"); 3051 return -EAGAIN; 3052 } 3053 3054 dis_buf = list_entry(asd->dis_stats.next, 3055 struct atomisp_dis_buf, list); 3056 list_del_init(&dis_buf->list); 3057 spin_unlock_irqrestore(&asd->dis_stats_lock, flags); 3058 3059 if (dis_buf->dvs_map) 3060 ia_css_translate_dvs2_statistics( 3061 asd->params.dvs_stat, dis_buf->dvs_map); 3062 else 3063 ia_css_get_dvs2_statistics(asd->params.dvs_stat, 3064 dis_buf->dis_data); 3065 stats->exp_id = dis_buf->dis_data->exp_id; 3066 3067 spin_lock_irqsave(&asd->dis_stats_lock, flags); 3068 list_add_tail(&dis_buf->list, &asd->dis_stats); 3069 spin_unlock_irqrestore(&asd->dis_stats_lock, flags); 3070 3071 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real, 3072 asd->params.dvs_stat->ver_prod.odd_real, 3073 asd->params.dvs_ver_proj_bytes)) 3074 return -EFAULT; 3075 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag, 3076 asd->params.dvs_stat->ver_prod.odd_imag, 3077 asd->params.dvs_ver_proj_bytes)) 3078 return -EFAULT; 3079 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real, 3080 asd->params.dvs_stat->ver_prod.even_real, 3081 asd->params.dvs_ver_proj_bytes)) 3082 return -EFAULT; 3083 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag, 3084 asd->params.dvs_stat->ver_prod.even_imag, 3085 asd->params.dvs_ver_proj_bytes)) 3086 return -EFAULT; 3087 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real, 3088 asd->params.dvs_stat->hor_prod.odd_real, 3089 asd->params.dvs_hor_proj_bytes)) 3090 return -EFAULT; 3091 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag, 3092 asd->params.dvs_stat->hor_prod.odd_imag, 3093 asd->params.dvs_hor_proj_bytes)) 3094 return -EFAULT; 3095 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real, 3096 asd->params.dvs_stat->hor_prod.even_real, 3097 asd->params.dvs_hor_proj_bytes)) 3098 return -EFAULT; 3099 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag, 3100 asd->params.dvs_stat->hor_prod.even_imag, 3101 asd->params.dvs_hor_proj_bytes)) 3102 return -EFAULT; 3103 3104 return 0; 3105 } 3106 atomisp_css_shading_table_alloc(unsigned int width,unsigned int height)3107 struct ia_css_shading_table *atomisp_css_shading_table_alloc( 3108 unsigned int width, unsigned int height) 3109 { 3110 return ia_css_shading_table_alloc(width, height); 3111 } 3112 atomisp_css_set_shading_table(struct atomisp_sub_device * asd,struct ia_css_shading_table * table)3113 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd, 3114 struct ia_css_shading_table *table) 3115 { 3116 asd->params.config.shading_table = table; 3117 } 3118 atomisp_css_shading_table_free(struct ia_css_shading_table * table)3119 void atomisp_css_shading_table_free(struct ia_css_shading_table *table) 3120 { 3121 ia_css_shading_table_free(table); 3122 } 3123 atomisp_css_morph_table_allocate(unsigned int width,unsigned int height)3124 struct ia_css_morph_table *atomisp_css_morph_table_allocate( 3125 unsigned int width, unsigned int height) 3126 { 3127 return ia_css_morph_table_allocate(width, height); 3128 } 3129 atomisp_css_set_morph_table(struct atomisp_sub_device * asd,struct ia_css_morph_table * table)3130 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd, 3131 struct ia_css_morph_table *table) 3132 { 3133 asd->params.config.morph_table = table; 3134 } 3135 atomisp_css_get_morph_table(struct atomisp_sub_device * asd,struct ia_css_morph_table * table)3136 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd, 3137 struct ia_css_morph_table *table) 3138 { 3139 struct ia_css_isp_config isp_config; 3140 struct atomisp_device *isp = asd->isp; 3141 3142 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3143 dev_err(isp->dev, 3144 "%s called after streamoff, skipping.\n", __func__); 3145 return; 3146 } 3147 memset(table, 0, sizeof(struct ia_css_morph_table)); 3148 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3149 isp_config.morph_table = table; 3150 ia_css_stream_get_isp_config( 3151 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3152 &isp_config); 3153 } 3154 atomisp_css_morph_table_free(struct ia_css_morph_table * table)3155 void atomisp_css_morph_table_free(struct ia_css_morph_table *table) 3156 { 3157 ia_css_morph_table_free(table); 3158 } 3159 atomisp_css_isr_get_stream_id(struct ia_css_pipe * css_pipe,struct atomisp_device * isp,enum atomisp_input_stream_id * stream_id)3160 static bool atomisp_css_isr_get_stream_id(struct ia_css_pipe *css_pipe, 3161 struct atomisp_device *isp, 3162 enum atomisp_input_stream_id *stream_id) 3163 { 3164 struct atomisp_stream_env *stream_env; 3165 int i, j; 3166 3167 if (!isp->asd.streaming) 3168 return false; 3169 3170 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 3171 stream_env = &isp->asd.stream_env[i]; 3172 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { 3173 if (stream_env->pipes[j] && stream_env->pipes[j] == css_pipe) { 3174 *stream_id = i; 3175 return true; 3176 } 3177 } 3178 } 3179 3180 return false; 3181 } 3182 atomisp_css_isr_thread(struct atomisp_device * isp)3183 int atomisp_css_isr_thread(struct atomisp_device *isp) 3184 { 3185 enum atomisp_input_stream_id stream_id = 0; 3186 struct atomisp_css_event current_event; 3187 3188 lockdep_assert_held(&isp->mutex); 3189 3190 while (!ia_css_dequeue_psys_event(¤t_event.event)) { 3191 if (current_event.event.type == 3192 IA_CSS_EVENT_TYPE_FW_ASSERT) { 3193 /* 3194 * Received FW assertion signal, 3195 * trigger WDT to recover 3196 */ 3197 dev_err(isp->dev, 3198 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n", 3199 __func__, 3200 current_event.event.fw_assert_module_id, 3201 current_event.event.fw_assert_line_no); 3202 3203 queue_work(system_long_wq, &isp->assert_recovery_work); 3204 return -EINVAL; 3205 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) { 3206 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n", 3207 __func__, current_event.event.fw_warning, 3208 current_event.event.exp_id); 3209 continue; 3210 } 3211 3212 if (!atomisp_css_isr_get_stream_id(current_event.event.pipe, isp, &stream_id)) { 3213 if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER) 3214 dev_dbg(isp->dev, 3215 "event: Timer event."); 3216 else 3217 dev_warn(isp->dev, "%s:no subdev.event:%d", 3218 __func__, 3219 current_event.event.type); 3220 continue; 3221 } 3222 3223 atomisp_css_temp_pipe_to_pipe_id(&isp->asd, ¤t_event); 3224 switch (current_event.event.type) { 3225 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE: 3226 dev_dbg(isp->dev, "event: Output frame done"); 3227 atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, 3228 current_event.pipe, true, stream_id); 3229 break; 3230 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE: 3231 dev_dbg(isp->dev, "event: Second output frame done"); 3232 atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME, 3233 current_event.pipe, true, stream_id); 3234 break; 3235 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE: 3236 dev_dbg(isp->dev, "event: 3A stats frame done"); 3237 atomisp_buf_done(&isp->asd, 0, 3238 IA_CSS_BUFFER_TYPE_3A_STATISTICS, 3239 current_event.pipe, 3240 false, stream_id); 3241 break; 3242 case IA_CSS_EVENT_TYPE_METADATA_DONE: 3243 dev_dbg(isp->dev, "event: metadata frame done"); 3244 atomisp_buf_done(&isp->asd, 0, 3245 IA_CSS_BUFFER_TYPE_METADATA, 3246 current_event.pipe, 3247 false, stream_id); 3248 break; 3249 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE: 3250 dev_dbg(isp->dev, "event: VF output frame done"); 3251 atomisp_buf_done(&isp->asd, 0, 3252 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, 3253 current_event.pipe, true, stream_id); 3254 break; 3255 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE: 3256 dev_dbg(isp->dev, "event: second VF output frame done"); 3257 atomisp_buf_done(&isp->asd, 0, 3258 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME, 3259 current_event.pipe, true, stream_id); 3260 break; 3261 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE: 3262 dev_dbg(isp->dev, "event: dis stats frame done"); 3263 atomisp_buf_done(&isp->asd, 0, 3264 IA_CSS_BUFFER_TYPE_DIS_STATISTICS, 3265 current_event.pipe, 3266 false, stream_id); 3267 break; 3268 case IA_CSS_EVENT_TYPE_PIPELINE_DONE: 3269 dev_dbg(isp->dev, "event: pipeline done"); 3270 break; 3271 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE: 3272 dev_warn(isp->dev, "unexpected event: acc stage done"); 3273 break; 3274 default: 3275 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n", 3276 current_event.event.type); 3277 break; 3278 } 3279 } 3280 3281 return 0; 3282 } 3283 atomisp_css_valid_sof(struct atomisp_device * isp)3284 bool atomisp_css_valid_sof(struct atomisp_device *isp) 3285 { 3286 unsigned int i; 3287 3288 /* Loop for each css vc stream */ 3289 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 3290 if (!isp->asd.stream_env[i].stream) 3291 continue; 3292 3293 dev_dbg(isp->dev, "stream #%d: mode: %d\n", 3294 i, isp->asd.stream_env[i].stream_config.mode); 3295 if (isp->asd.stream_env[i].stream_config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 3296 return false; 3297 } 3298 3299 return true; 3300 } 3301 atomisp_css_debug_dump_isp_binary(void)3302 int atomisp_css_debug_dump_isp_binary(void) 3303 { 3304 ia_css_debug_dump_isp_binary(); 3305 return 0; 3306 } 3307 atomisp_css_dump_sp_raw_copy_linecount(bool reduced)3308 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced) 3309 { 3310 sh_css_dump_sp_raw_copy_linecount(reduced); 3311 return 0; 3312 } 3313 3314 static const char * const fw_type_name[] = { 3315 [ia_css_sp_firmware] = "SP", 3316 [ia_css_isp_firmware] = "ISP", 3317 [ia_css_bootloader_firmware] = "BootLoader", 3318 [ia_css_acc_firmware] = "accel", 3319 }; 3320 3321 static const char * const fw_acc_type_name[] = { 3322 [IA_CSS_ACC_NONE] = "Normal", 3323 [IA_CSS_ACC_OUTPUT] = "Accel stage on output", 3324 [IA_CSS_ACC_VIEWFINDER] = "Accel stage on viewfinder", 3325 [IA_CSS_ACC_STANDALONE] = "Stand-alone acceleration", 3326 }; 3327 atomisp_css_dump_blob_infor(struct atomisp_device * isp)3328 int atomisp_css_dump_blob_infor(struct atomisp_device *isp) 3329 { 3330 struct ia_css_blob_descr *bd = sh_css_blob_info; 3331 unsigned int i, nm = sh_css_num_binaries; 3332 3333 if (nm == 0) 3334 return -EPERM; 3335 if (!bd) 3336 return -EPERM; 3337 3338 /* 3339 * The sh_css_load_firmware function discard the initial 3340 * "SPS" binaries 3341 */ 3342 for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) { 3343 switch (bd[i].header.type) { 3344 case ia_css_isp_firmware: 3345 dev_dbg(isp->dev, "Num%2d type %s (%s), binary id is %2d, name is %s\n", 3346 i + NUM_OF_SPS, 3347 fw_type_name[bd[i].header.type], 3348 fw_acc_type_name[bd[i].header.info.isp.type], 3349 bd[i].header.info.isp.sp.id, 3350 bd[i].name); 3351 break; 3352 default: 3353 dev_dbg(isp->dev, "Num%2d type %s, name is %s\n", 3354 i + NUM_OF_SPS, fw_type_name[bd[i].header.type], 3355 bd[i].name); 3356 } 3357 } 3358 3359 return 0; 3360 } 3361 atomisp_css_set_isp_config_id(struct atomisp_sub_device * asd,uint32_t isp_config_id)3362 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd, 3363 uint32_t isp_config_id) 3364 { 3365 asd->params.config.isp_config_id = isp_config_id; 3366 } 3367 atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device * asd,struct ia_css_frame * output_frame)3368 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd, 3369 struct ia_css_frame *output_frame) 3370 { 3371 asd->params.config.output_frame = output_frame; 3372 } 3373 atomisp_get_css_dbgfunc(void)3374 int atomisp_get_css_dbgfunc(void) 3375 { 3376 return dbg_func; 3377 } 3378 atomisp_set_css_dbgfunc(struct atomisp_device * isp,int opt)3379 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt) 3380 { 3381 int ret; 3382 3383 ret = __set_css_print_env(isp, opt); 3384 if (ret == 0) 3385 dbg_func = opt; 3386 3387 return ret; 3388 } 3389 atomisp_en_dz_capt_pipe(struct atomisp_sub_device * asd,bool enable)3390 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable) 3391 { 3392 ia_css_en_dz_capt_pipe( 3393 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3394 enable); 3395 } 3396 atomisp_css_get_dvs_grid_info(struct ia_css_grid_info * grid_info)3397 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info( 3398 struct ia_css_grid_info *grid_info) 3399 { 3400 if (!grid_info) 3401 return NULL; 3402 3403 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED 3404 return &grid_info->dvs_grid.dvs_grid_info; 3405 #else 3406 return &grid_info->dvs_grid; 3407 #endif 3408 } 3409