1 /* 2 * Support for Clovertrail PNW Camera Imaging ISP subsystem. 3 * 4 * Copyright (c) 2013 Intel Corporation. All Rights Reserved. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License version 8 * 2 as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * 16 */ 17 18 #include <media/videobuf-vmalloc.h> 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 #include "atomisp_acc.h" 34 35 #include <asm/intel-mid.h> 36 37 #include "ia_css_debug.h" 38 #include "ia_css_isp_param.h" 39 #include "sh_css_hrt.h" 40 #include "ia_css_isys.h" 41 42 #include <linux/pm_runtime.h> 43 44 /* Assume max number of ACC stages */ 45 #define MAX_ACC_STAGES 20 46 47 /* Ideally, this should come from CSS headers */ 48 #define NO_LINK -1 49 50 /* 51 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting 52 * #4684168, if concurrency access happened, system may hard hang. 53 */ 54 static DEFINE_SPINLOCK(mmio_lock); 55 56 enum frame_info_type { 57 ATOMISP_CSS_VF_FRAME, 58 ATOMISP_CSS_SECOND_VF_FRAME, 59 ATOMISP_CSS_OUTPUT_FRAME, 60 ATOMISP_CSS_SECOND_OUTPUT_FRAME, 61 ATOMISP_CSS_RAW_FRAME, 62 }; 63 64 struct bayer_ds_factor { 65 unsigned int numerator; 66 unsigned int denominator; 67 }; 68 69 void atomisp_css_debug_dump_sp_sw_debug_info(void) 70 { 71 ia_css_debug_dump_sp_sw_debug_info(); 72 } 73 74 void atomisp_css_debug_dump_debug_info(const char *context) 75 { 76 ia_css_debug_dump_debug_info(context); 77 } 78 79 void atomisp_css_debug_set_dtrace_level(const unsigned int trace_level) 80 { 81 ia_css_debug_set_dtrace_level(trace_level); 82 } 83 84 unsigned int atomisp_css_debug_get_dtrace_level(void) 85 { 86 return dbg_level; 87 } 88 89 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data) 90 { 91 unsigned long flags; 92 93 spin_lock_irqsave(&mmio_lock, flags); 94 _hrt_master_port_store_8(addr, data); 95 spin_unlock_irqrestore(&mmio_lock, flags); 96 } 97 98 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data) 99 { 100 unsigned long flags; 101 102 spin_lock_irqsave(&mmio_lock, flags); 103 _hrt_master_port_store_16(addr, data); 104 spin_unlock_irqrestore(&mmio_lock, flags); 105 } 106 107 static void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data) 108 { 109 unsigned long flags; 110 111 spin_lock_irqsave(&mmio_lock, flags); 112 _hrt_master_port_store_32(addr, data); 113 spin_unlock_irqrestore(&mmio_lock, flags); 114 } 115 116 static uint8_t atomisp_css2_hw_load_8(hrt_address addr) 117 { 118 unsigned long flags; 119 u8 ret; 120 121 spin_lock_irqsave(&mmio_lock, flags); 122 ret = _hrt_master_port_load_8(addr); 123 spin_unlock_irqrestore(&mmio_lock, flags); 124 return ret; 125 } 126 127 static uint16_t atomisp_css2_hw_load_16(hrt_address addr) 128 { 129 unsigned long flags; 130 u16 ret; 131 132 spin_lock_irqsave(&mmio_lock, flags); 133 ret = _hrt_master_port_load_16(addr); 134 spin_unlock_irqrestore(&mmio_lock, flags); 135 return ret; 136 } 137 138 static uint32_t atomisp_css2_hw_load_32(hrt_address addr) 139 { 140 unsigned long flags; 141 u32 ret; 142 143 spin_lock_irqsave(&mmio_lock, flags); 144 ret = _hrt_master_port_load_32(addr); 145 spin_unlock_irqrestore(&mmio_lock, flags); 146 return ret; 147 } 148 149 static void atomisp_css2_hw_store(hrt_address addr, 150 const void *from, uint32_t n) 151 { 152 unsigned long flags; 153 unsigned int i; 154 unsigned int _to = (unsigned int)addr; 155 const char *_from = (const char *)from; 156 157 spin_lock_irqsave(&mmio_lock, flags); 158 for (i = 0; i < n; i++, _to++, _from++) 159 _hrt_master_port_store_8(_to, *_from); 160 spin_unlock_irqrestore(&mmio_lock, flags); 161 } 162 163 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n) 164 { 165 unsigned long flags; 166 unsigned int i; 167 char *_to = (char *)to; 168 unsigned int _from = (unsigned int)addr; 169 170 spin_lock_irqsave(&mmio_lock, flags); 171 for (i = 0; i < n; i++, _to++, _from++) 172 *_to = _hrt_master_port_load_8(_from); 173 spin_unlock_irqrestore(&mmio_lock, flags); 174 } 175 176 static int atomisp_css2_dbg_print(const char *fmt, va_list args) 177 { 178 vprintk(fmt, args); 179 return 0; 180 } 181 182 static int atomisp_css2_dbg_ftrace_print(const char *fmt, va_list args) 183 { 184 ftrace_vprintk(fmt, args); 185 return 0; 186 } 187 188 static int atomisp_css2_err_print(const char *fmt, va_list args) 189 { 190 vprintk(fmt, args); 191 return 0; 192 } 193 194 void atomisp_store_uint32(hrt_address addr, uint32_t data) 195 { 196 atomisp_css2_hw_store_32(addr, data); 197 } 198 199 void atomisp_load_uint32(hrt_address addr, uint32_t *data) 200 { 201 *data = atomisp_css2_hw_load_32(addr); 202 } 203 204 static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr) 205 { 206 if (!sh_mmu_mrfld.get_pd_base) { 207 dev_err(atomisp_dev, "get mmu base address failed.\n"); 208 return -EINVAL; 209 } 210 211 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu, 212 bo_device.mmu.base_address); 213 return 0; 214 } 215 216 static void atomisp_isp_parameters_clean_up( 217 struct ia_css_isp_config *config) 218 { 219 /* 220 * Set NULL to configs pointer to avoid they are set into isp again when 221 * some configs are changed and need to be updated later. 222 */ 223 memset(config, 0, sizeof(*config)); 224 } 225 226 static void __dump_pipe_config(struct atomisp_sub_device *asd, 227 struct atomisp_stream_env *stream_env, 228 unsigned int pipe_id) 229 { 230 struct atomisp_device *isp = asd->isp; 231 232 if (stream_env->pipes[pipe_id]) { 233 struct ia_css_pipe_config *p_config; 234 struct ia_css_pipe_extra_config *pe_config; 235 236 p_config = &stream_env->pipe_configs[pipe_id]; 237 pe_config = &stream_env->pipe_extra_configs[pipe_id]; 238 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id); 239 dev_dbg(isp->dev, 240 "pipe_config.pipe_mode:%d.\n", p_config->mode); 241 dev_dbg(isp->dev, 242 "pipe_config.output_info[0] w=%d, h=%d.\n", 243 p_config->output_info[0].res.width, 244 p_config->output_info[0].res.height); 245 dev_dbg(isp->dev, 246 "pipe_config.vf_pp_in_res w=%d, h=%d.\n", 247 p_config->vf_pp_in_res.width, 248 p_config->vf_pp_in_res.height); 249 dev_dbg(isp->dev, 250 "pipe_config.capt_pp_in_res w=%d, h=%d.\n", 251 p_config->capt_pp_in_res.width, 252 p_config->capt_pp_in_res.height); 253 dev_dbg(isp->dev, 254 "pipe_config.output.padded w=%d.\n", 255 p_config->output_info[0].padded_width); 256 dev_dbg(isp->dev, 257 "pipe_config.vf_output_info[0] w=%d, h=%d.\n", 258 p_config->vf_output_info[0].res.width, 259 p_config->vf_output_info[0].res.height); 260 dev_dbg(isp->dev, 261 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n", 262 p_config->bayer_ds_out_res.width, 263 p_config->bayer_ds_out_res.height); 264 dev_dbg(isp->dev, 265 "pipe_config.envelope w=%d, h=%d.\n", 266 p_config->dvs_envelope.width, 267 p_config->dvs_envelope.height); 268 dev_dbg(isp->dev, 269 "pipe_config.dvs_frame_delay=%d.\n", 270 p_config->dvs_frame_delay); 271 dev_dbg(isp->dev, 272 "pipe_config.isp_pipe_version:%d.\n", 273 p_config->isp_pipe_version); 274 dev_dbg(isp->dev, 275 "pipe_config.acc_extension=%p.\n", 276 p_config->acc_extension); 277 dev_dbg(isp->dev, 278 "pipe_config.acc_stages=%p.\n", 279 p_config->acc_stages); 280 dev_dbg(isp->dev, 281 "pipe_config.num_acc_stages=%d.\n", 282 p_config->num_acc_stages); 283 dev_dbg(isp->dev, 284 "pipe_config.acc_num_execs=%d.\n", 285 p_config->acc_num_execs); 286 dev_dbg(isp->dev, 287 "pipe_config.default_capture_config.capture_mode=%d.\n", 288 p_config->default_capture_config.mode); 289 dev_dbg(isp->dev, 290 "pipe_config.enable_dz=%d.\n", 291 p_config->enable_dz); 292 dev_dbg(isp->dev, 293 "pipe_config.default_capture_config.enable_xnr=%d.\n", 294 p_config->default_capture_config.enable_xnr); 295 dev_dbg(isp->dev, 296 "dumping pipe[%d] extra config:\n", pipe_id); 297 dev_dbg(isp->dev, 298 "pipe_extra_config.enable_raw_binning:%d.\n", 299 pe_config->enable_raw_binning); 300 dev_dbg(isp->dev, 301 "pipe_extra_config.enable_yuv_ds:%d.\n", 302 pe_config->enable_yuv_ds); 303 dev_dbg(isp->dev, 304 "pipe_extra_config.enable_high_speed:%d.\n", 305 pe_config->enable_high_speed); 306 dev_dbg(isp->dev, 307 "pipe_extra_config.enable_dvs_6axis:%d.\n", 308 pe_config->enable_dvs_6axis); 309 dev_dbg(isp->dev, 310 "pipe_extra_config.enable_reduced_pipe:%d.\n", 311 pe_config->enable_reduced_pipe); 312 dev_dbg(isp->dev, 313 "pipe_(extra_)config.enable_dz:%d.\n", 314 p_config->enable_dz); 315 dev_dbg(isp->dev, 316 "pipe_extra_config.disable_vf_pp:%d.\n", 317 pe_config->disable_vf_pp); 318 } 319 } 320 321 static void __dump_stream_config(struct atomisp_sub_device *asd, 322 struct atomisp_stream_env *stream_env) 323 { 324 struct atomisp_device *isp = asd->isp; 325 struct ia_css_stream_config *s_config; 326 int j; 327 bool valid_stream = false; 328 329 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { 330 if (stream_env->pipes[j]) { 331 __dump_pipe_config(asd, stream_env, j); 332 valid_stream = true; 333 } 334 } 335 if (!valid_stream) 336 return; 337 s_config = &stream_env->stream_config; 338 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode); 339 340 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR || 341 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { 342 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n", 343 s_config->source.port.port); 344 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n", 345 s_config->source.port.num_lanes); 346 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n", 347 s_config->source.port.timeout); 348 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n", 349 s_config->source.port.rxcount); 350 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n", 351 s_config->source.port.compression.type); 352 dev_dbg(isp->dev, 353 "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n", 354 s_config->source.port.compression. 355 compressed_bits_per_pixel); 356 dev_dbg(isp->dev, 357 "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n", 358 s_config->source.port.compression. 359 uncompressed_bits_per_pixel); 360 } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) { 361 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n", 362 s_config->source.tpg.id); 363 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n", 364 s_config->source.tpg.mode); 365 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n", 366 s_config->source.tpg.x_mask); 367 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n", 368 s_config->source.tpg.x_delta); 369 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n", 370 s_config->source.tpg.y_mask); 371 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n", 372 s_config->source.tpg.y_delta); 373 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n", 374 s_config->source.tpg.xy_mask); 375 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) { 376 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n", 377 s_config->source.prbs.id); 378 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n", 379 s_config->source.prbs.h_blank); 380 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n", 381 s_config->source.prbs.v_blank); 382 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n", 383 s_config->source.prbs.seed); 384 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n", 385 s_config->source.prbs.seed1); 386 } 387 388 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) { 389 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n", 390 j, 391 s_config->isys_config[j].input_res.width, 392 s_config->isys_config[j].input_res.height); 393 394 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n", 395 j, 396 s_config->isys_config[j].linked_isys_stream_id); 397 398 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n", 399 j, 400 s_config->isys_config[j].format); 401 402 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n", 403 j, 404 s_config->isys_config[j].valid); 405 } 406 407 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n", 408 s_config->input_config.input_res.width, 409 s_config->input_config.input_res.height); 410 411 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n", 412 s_config->input_config.effective_res.width, 413 s_config->input_config.effective_res.height); 414 415 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n", 416 s_config->input_config.format); 417 418 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n", 419 s_config->input_config.bayer_order); 420 421 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n", 422 s_config->pixels_per_clock); 423 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online); 424 dev_dbg(isp->dev, "stream_config.continuous=%d.\n", 425 s_config->continuous); 426 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n", 427 s_config->disable_cont_viewfinder); 428 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n", 429 s_config->channel_id); 430 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n", 431 s_config->init_num_cont_raw_buf); 432 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n", 433 s_config->target_num_cont_raw_buf); 434 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n", 435 s_config->left_padding); 436 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n", 437 s_config->sensor_binning_factor); 438 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n", 439 s_config->pixels_per_clock); 440 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n", 441 s_config->pack_raw_pixels); 442 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n", 443 s_config->flash_gpio_pin); 444 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n", 445 s_config->mipi_buffer_config.size_mem_words); 446 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n", 447 s_config->mipi_buffer_config.contiguous); 448 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n", 449 s_config->metadata_config.data_type); 450 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n", 451 s_config->metadata_config.resolution.width, 452 s_config->metadata_config.resolution.height); 453 } 454 455 static int __destroy_stream(struct atomisp_sub_device *asd, 456 struct atomisp_stream_env *stream_env, bool force) 457 { 458 struct atomisp_device *isp = asd->isp; 459 int i; 460 unsigned long timeout; 461 462 if (!stream_env->stream) 463 return 0; 464 465 if (!force) { 466 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 467 if (stream_env->update_pipe[i]) 468 break; 469 470 if (i == IA_CSS_PIPE_ID_NUM) 471 return 0; 472 } 473 474 if (stream_env->stream_state == CSS_STREAM_STARTED 475 && ia_css_stream_stop(stream_env->stream) != IA_CSS_SUCCESS) { 476 dev_err(isp->dev, "stop stream failed.\n"); 477 return -EINVAL; 478 } 479 480 if (stream_env->stream_state == CSS_STREAM_STARTED) { 481 timeout = jiffies + msecs_to_jiffies(40); 482 while (1) { 483 if (ia_css_stream_has_stopped(stream_env->stream)) 484 break; 485 486 if (time_after(jiffies, timeout)) { 487 dev_warn(isp->dev, "stop stream timeout.\n"); 488 break; 489 } 490 491 usleep_range(100, 200); 492 } 493 } 494 495 stream_env->stream_state = CSS_STREAM_STOPPED; 496 497 if (ia_css_stream_destroy(stream_env->stream) != IA_CSS_SUCCESS) { 498 dev_err(isp->dev, "destroy stream failed.\n"); 499 return -EINVAL; 500 } 501 stream_env->stream_state = CSS_STREAM_UNINIT; 502 stream_env->stream = NULL; 503 504 return 0; 505 } 506 507 static int __destroy_streams(struct atomisp_sub_device *asd, bool force) 508 { 509 int ret, i; 510 511 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 512 ret = __destroy_stream(asd, &asd->stream_env[i], force); 513 if (ret) 514 return ret; 515 } 516 asd->stream_prepared = false; 517 return 0; 518 } 519 520 static int __create_stream(struct atomisp_sub_device *asd, 521 struct atomisp_stream_env *stream_env) 522 { 523 int pipe_index = 0, i; 524 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM]; 525 526 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { 527 if (stream_env->pipes[i]) 528 multi_pipes[pipe_index++] = stream_env->pipes[i]; 529 } 530 if (pipe_index == 0) 531 return 0; 532 533 stream_env->stream_config.target_num_cont_raw_buf = 534 asd->continuous_raw_buffer_size->val; 535 stream_env->stream_config.channel_id = stream_env->ch_id; 536 stream_env->stream_config.ia_css_enable_raw_buffer_locking = 537 asd->enable_raw_buffer_lock->val; 538 539 __dump_stream_config(asd, stream_env); 540 if (ia_css_stream_create(&stream_env->stream_config, 541 pipe_index, multi_pipes, &stream_env->stream) != IA_CSS_SUCCESS) 542 return -EINVAL; 543 if (ia_css_stream_get_info(stream_env->stream, 544 &stream_env->stream_info) != IA_CSS_SUCCESS) { 545 ia_css_stream_destroy(stream_env->stream); 546 stream_env->stream = NULL; 547 return -EINVAL; 548 } 549 550 stream_env->stream_state = CSS_STREAM_CREATED; 551 return 0; 552 } 553 554 static int __create_streams(struct atomisp_sub_device *asd) 555 { 556 int ret, i; 557 558 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 559 ret = __create_stream(asd, &asd->stream_env[i]); 560 if (ret) 561 goto rollback; 562 } 563 asd->stream_prepared = true; 564 return 0; 565 rollback: 566 for (i--; i >= 0; i--) 567 __destroy_stream(asd, &asd->stream_env[i], true); 568 return ret; 569 } 570 571 static int __destroy_stream_pipes(struct atomisp_sub_device *asd, 572 struct atomisp_stream_env *stream_env, 573 bool force) 574 { 575 struct atomisp_device *isp = asd->isp; 576 int ret = 0; 577 int i; 578 579 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { 580 if (!stream_env->pipes[i] || 581 !(force || stream_env->update_pipe[i])) 582 continue; 583 if (ia_css_pipe_destroy(stream_env->pipes[i]) 584 != IA_CSS_SUCCESS) { 585 dev_err(isp->dev, 586 "destroy pipe[%d]failed.cannot recover.\n", i); 587 ret = -EINVAL; 588 } 589 stream_env->pipes[i] = NULL; 590 stream_env->update_pipe[i] = false; 591 } 592 return ret; 593 } 594 595 static int __destroy_pipes(struct atomisp_sub_device *asd, bool force) 596 { 597 struct atomisp_device *isp = asd->isp; 598 int i; 599 int ret = 0; 600 601 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 602 if (asd->stream_env[i].stream) { 603 dev_err(isp->dev, 604 "cannot destroy css pipes for stream[%d].\n", 605 i); 606 continue; 607 } 608 609 ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force); 610 if (ret) 611 return ret; 612 } 613 614 return 0; 615 } 616 617 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd) 618 { 619 __destroy_streams(asd, true); 620 __destroy_pipes(asd, true); 621 } 622 623 static void __apply_additional_pipe_config( 624 struct atomisp_sub_device *asd, 625 struct atomisp_stream_env *stream_env, 626 enum ia_css_pipe_id pipe_id) 627 { 628 struct atomisp_device *isp = asd->isp; 629 630 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) { 631 dev_err(isp->dev, 632 "wrong pipe_id for additional pipe config.\n"); 633 return; 634 } 635 636 /* apply default pipe config */ 637 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2; 638 stream_env->pipe_configs[pipe_id].enable_dz = 639 asd->disable_dz->val ? false : true; 640 /* apply isp 2.2 specific config for baytrail*/ 641 switch (pipe_id) { 642 case IA_CSS_PIPE_ID_CAPTURE: 643 /* enable capture pp/dz manually or digital zoom would 644 * fail*/ 645 if (stream_env->pipe_configs[pipe_id]. 646 default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW) 647 stream_env->pipe_configs[pipe_id].enable_dz = false; 648 649 if (atomisp_hw_is_isp2401) { 650 /* the isp default to use ISP2.2 and the camera hal will 651 * control whether use isp2.7 */ 652 if (asd->select_isp_version->val == ATOMISP_CSS_ISP_PIPE_VERSION_2_7) 653 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_7; 654 else 655 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_2; 656 } 657 break; 658 case IA_CSS_PIPE_ID_VIDEO: 659 /* enable reduced pipe to have binary 660 * video_dz_2_min selected*/ 661 stream_env->pipe_extra_configs[pipe_id] 662 .enable_reduced_pipe = true; 663 stream_env->pipe_configs[pipe_id] 664 .enable_dz = false; 665 if (ATOMISP_SOC_CAMERA(asd)) 666 stream_env->pipe_configs[pipe_id].enable_dz = true; 667 668 if (asd->params.video_dis_en) { 669 stream_env->pipe_extra_configs[pipe_id] 670 .enable_dvs_6axis = true; 671 stream_env->pipe_configs[pipe_id] 672 .dvs_frame_delay = 673 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; 674 } 675 break; 676 case IA_CSS_PIPE_ID_PREVIEW: 677 break; 678 case IA_CSS_PIPE_ID_YUVPP: 679 case IA_CSS_PIPE_ID_COPY: 680 if (ATOMISP_SOC_CAMERA(asd)) 681 stream_env->pipe_configs[pipe_id].enable_dz = true; 682 else 683 stream_env->pipe_configs[pipe_id].enable_dz = false; 684 break; 685 case IA_CSS_PIPE_ID_ACC: 686 stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC; 687 stream_env->pipe_configs[pipe_id].enable_dz = false; 688 break; 689 default: 690 break; 691 } 692 } 693 694 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd, 695 enum ia_css_pipe_id pipe_id) 696 { 697 if (!asd) 698 return false; 699 700 if (pipe_id == IA_CSS_PIPE_ID_ACC || pipe_id == IA_CSS_PIPE_ID_YUVPP) 701 return true; 702 703 if (asd->vfpp) { 704 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { 705 if (pipe_id == IA_CSS_PIPE_ID_VIDEO) 706 return true; 707 else 708 return false; 709 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { 710 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE) 711 return true; 712 else 713 return false; 714 } 715 } 716 717 if (!asd->run_mode) 718 return false; 719 720 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY) 721 return true; 722 723 switch (asd->run_mode->val) { 724 case ATOMISP_RUN_MODE_STILL_CAPTURE: 725 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE) 726 return true; 727 else 728 return false; 729 case ATOMISP_RUN_MODE_PREVIEW: 730 if (!asd->continuous_mode->val) { 731 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) 732 return true; 733 else 734 return false; 735 } 736 /* fall through to ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE */ 737 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE: 738 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || 739 pipe_id == IA_CSS_PIPE_ID_PREVIEW) 740 return true; 741 else 742 return false; 743 case ATOMISP_RUN_MODE_VIDEO: 744 if (!asd->continuous_mode->val) { 745 if (pipe_id == IA_CSS_PIPE_ID_VIDEO || 746 pipe_id == IA_CSS_PIPE_ID_YUVPP) 747 return true; 748 else 749 return false; 750 } 751 /* fall through to ATOMISP_RUN_MODE_SDV */ 752 case ATOMISP_RUN_MODE_SDV: 753 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || 754 pipe_id == IA_CSS_PIPE_ID_VIDEO) 755 return true; 756 else 757 return false; 758 } 759 760 return false; 761 } 762 763 static int __create_pipe(struct atomisp_sub_device *asd, 764 struct atomisp_stream_env *stream_env, 765 enum ia_css_pipe_id pipe_id) 766 { 767 struct atomisp_device *isp = asd->isp; 768 struct ia_css_pipe_extra_config extra_config; 769 enum ia_css_err ret; 770 771 if (pipe_id >= IA_CSS_PIPE_ID_NUM) 772 return -EINVAL; 773 774 if (pipe_id != IA_CSS_PIPE_ID_ACC && 775 !stream_env->pipe_configs[pipe_id].output_info[0].res.width) 776 return 0; 777 778 if (pipe_id == IA_CSS_PIPE_ID_ACC && 779 !stream_env->pipe_configs[pipe_id].acc_extension) 780 return 0; 781 782 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id)) 783 return 0; 784 785 ia_css_pipe_extra_config_defaults(&extra_config); 786 787 __apply_additional_pipe_config(asd, stream_env, pipe_id); 788 if (!memcmp(&extra_config, 789 &stream_env->pipe_extra_configs[pipe_id], 790 sizeof(extra_config))) 791 ret = ia_css_pipe_create( 792 &stream_env->pipe_configs[pipe_id], 793 &stream_env->pipes[pipe_id]); 794 else 795 ret = ia_css_pipe_create_extra( 796 &stream_env->pipe_configs[pipe_id], 797 &stream_env->pipe_extra_configs[pipe_id], 798 &stream_env->pipes[pipe_id]); 799 if (ret != IA_CSS_SUCCESS) 800 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id); 801 return ret; 802 } 803 804 static int __create_pipes(struct atomisp_sub_device *asd) 805 { 806 enum ia_css_err ret; 807 int i, j; 808 809 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 810 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { 811 ret = __create_pipe(asd, &asd->stream_env[i], j); 812 if (ret != IA_CSS_SUCCESS) 813 break; 814 } 815 if (j < IA_CSS_PIPE_ID_NUM) 816 goto pipe_err; 817 } 818 return 0; 819 pipe_err: 820 for (; i >= 0; i--) { 821 for (j--; j >= 0; j--) { 822 if (asd->stream_env[i].pipes[j]) { 823 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]); 824 asd->stream_env[i].pipes[j] = NULL; 825 } 826 } 827 j = IA_CSS_PIPE_ID_NUM; 828 } 829 return -EINVAL; 830 } 831 832 void atomisp_create_pipes_stream(struct atomisp_sub_device *asd) 833 { 834 __create_pipes(asd); 835 __create_streams(asd); 836 } 837 838 int atomisp_css_update_stream(struct atomisp_sub_device *asd) 839 { 840 int ret; 841 struct atomisp_device *isp = asd->isp; 842 843 if (__destroy_streams(asd, true) != IA_CSS_SUCCESS) 844 dev_warn(isp->dev, "destroy stream failed.\n"); 845 846 if (__destroy_pipes(asd, true) != IA_CSS_SUCCESS) 847 dev_warn(isp->dev, "destroy pipe failed.\n"); 848 849 ret = __create_pipes(asd); 850 if (ret != IA_CSS_SUCCESS) { 851 dev_err(isp->dev, "create pipe failed %d.\n", ret); 852 return -EIO; 853 } 854 855 ret = __create_streams(asd); 856 if (ret != IA_CSS_SUCCESS) { 857 dev_warn(isp->dev, "create stream failed %d.\n", ret); 858 __destroy_pipes(asd, true); 859 return -EIO; 860 } 861 862 return 0; 863 } 864 865 int atomisp_css_init(struct atomisp_device *isp) 866 { 867 unsigned int mmu_base_addr; 868 int ret; 869 enum ia_css_err err; 870 871 ret = hmm_get_mmu_base_addr(&mmu_base_addr); 872 if (ret) 873 return ret; 874 875 /* Init ISP */ 876 err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL, 877 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE); 878 if (err != IA_CSS_SUCCESS) { 879 dev_err(isp->dev, "css init failed --- bad firmware?\n"); 880 return -EINVAL; 881 } 882 ia_css_enable_isys_event_queue(true); 883 884 isp->css_initialized = true; 885 dev_dbg(isp->dev, "sh_css_init success\n"); 886 887 return 0; 888 } 889 890 static inline int __set_css_print_env(struct atomisp_device *isp, int opt) 891 { 892 int ret = 0; 893 894 if (opt == 0) 895 isp->css_env.isp_css_env.print_env.debug_print = NULL; 896 else if (opt == 1) 897 isp->css_env.isp_css_env.print_env.debug_print = 898 atomisp_css2_dbg_ftrace_print; 899 else if (opt == 2) 900 isp->css_env.isp_css_env.print_env.debug_print = 901 atomisp_css2_dbg_print; 902 else 903 ret = -EINVAL; 904 905 return ret; 906 } 907 908 int atomisp_css_check_firmware_version(struct atomisp_device *isp) 909 { 910 if (!sh_css_check_firmware_version(isp->dev, (void *)isp->firmware->data)) { 911 return -EINVAL; 912 } 913 return 0; 914 } 915 916 int atomisp_css_load_firmware(struct atomisp_device *isp) 917 { 918 enum ia_css_err err; 919 920 /* set css env */ 921 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data; 922 isp->css_env.isp_css_fw.bytes = isp->firmware->size; 923 924 isp->css_env.isp_css_env.hw_access_env.store_8 = 925 atomisp_css2_hw_store_8; 926 isp->css_env.isp_css_env.hw_access_env.store_16 = 927 atomisp_css2_hw_store_16; 928 isp->css_env.isp_css_env.hw_access_env.store_32 = 929 atomisp_css2_hw_store_32; 930 931 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8; 932 isp->css_env.isp_css_env.hw_access_env.load_16 = 933 atomisp_css2_hw_load_16; 934 isp->css_env.isp_css_env.hw_access_env.load_32 = 935 atomisp_css2_hw_load_32; 936 937 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load; 938 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store; 939 940 __set_css_print_env(isp, dbg_func); 941 942 isp->css_env.isp_css_env.print_env.error_print = atomisp_css2_err_print; 943 944 /* load isp fw into ISP memory */ 945 err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env, 946 &isp->css_env.isp_css_fw); 947 if (err != IA_CSS_SUCCESS) { 948 dev_err(isp->dev, "css load fw failed.\n"); 949 return -EINVAL; 950 } 951 952 return 0; 953 } 954 955 void atomisp_css_unload_firmware(struct atomisp_device *isp) 956 { 957 ia_css_unload_firmware(); 958 } 959 960 void atomisp_css_uninit(struct atomisp_device *isp) 961 { 962 struct atomisp_sub_device *asd; 963 unsigned int i; 964 965 for (i = 0; i < isp->num_of_streams; i++) { 966 asd = &isp->asd[i]; 967 atomisp_isp_parameters_clean_up(&asd->params.config); 968 asd->params.css_update_params_needed = false; 969 } 970 971 isp->css_initialized = false; 972 ia_css_uninit(); 973 } 974 975 void atomisp_css_suspend(struct atomisp_device *isp) 976 { 977 isp->css_initialized = false; 978 ia_css_uninit(); 979 } 980 981 int atomisp_css_resume(struct atomisp_device *isp) 982 { 983 unsigned int mmu_base_addr; 984 int ret; 985 986 ret = hmm_get_mmu_base_addr(&mmu_base_addr); 987 if (ret) { 988 dev_err(isp->dev, "get base address error.\n"); 989 return -EINVAL; 990 } 991 992 ret = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL, 993 mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE); 994 if (ret) { 995 dev_err(isp->dev, "re-init css failed.\n"); 996 return -EINVAL; 997 } 998 ia_css_enable_isys_event_queue(true); 999 1000 isp->css_initialized = true; 1001 return 0; 1002 } 1003 1004 int atomisp_css_irq_translate(struct atomisp_device *isp, 1005 unsigned int *infos) 1006 { 1007 int err; 1008 1009 err = ia_css_irq_translate(infos); 1010 if (err != IA_CSS_SUCCESS) { 1011 dev_warn(isp->dev, 1012 "%s:failed to translate irq (err = %d,infos = %d)\n", 1013 __func__, err, *infos); 1014 return -EINVAL; 1015 } 1016 1017 return 0; 1018 } 1019 1020 void atomisp_css_rx_get_irq_info(enum mipi_port_id port, 1021 unsigned int *infos) 1022 { 1023 #ifndef ISP2401_NEW_INPUT_SYSTEM 1024 ia_css_isys_rx_get_irq_info(port, infos); 1025 #else 1026 *infos = 0; 1027 #endif 1028 } 1029 1030 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port, 1031 unsigned int infos) 1032 { 1033 #ifndef ISP2401_NEW_INPUT_SYSTEM 1034 ia_css_isys_rx_clear_irq_info(port, infos); 1035 #endif 1036 } 1037 1038 int atomisp_css_irq_enable(struct atomisp_device *isp, 1039 enum ia_css_irq_info info, bool enable) 1040 { 1041 dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s.\n", 1042 __func__, info, 1043 enable ? "enable" : "disable"); 1044 if (ia_css_irq_enable(info, enable) != IA_CSS_SUCCESS) { 1045 dev_warn(isp->dev, "%s:Invalid irq info.\n", __func__); 1046 return -EINVAL; 1047 } 1048 1049 return 0; 1050 } 1051 1052 void atomisp_css_init_struct(struct atomisp_sub_device *asd) 1053 { 1054 int i, j; 1055 1056 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 1057 asd->stream_env[i].stream = NULL; 1058 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) { 1059 asd->stream_env[i].pipes[j] = NULL; 1060 asd->stream_env[i].update_pipe[j] = false; 1061 ia_css_pipe_config_defaults( 1062 &asd->stream_env[i].pipe_configs[j]); 1063 ia_css_pipe_extra_config_defaults( 1064 &asd->stream_env[i].pipe_extra_configs[j]); 1065 } 1066 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config); 1067 } 1068 } 1069 1070 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd, 1071 struct videobuf_vmalloc_memory *vm_mem, 1072 enum atomisp_input_stream_id stream_id, 1073 enum ia_css_buffer_type css_buf_type, 1074 enum ia_css_pipe_id css_pipe_id) 1075 { 1076 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; 1077 struct ia_css_buffer css_buf = {0}; 1078 enum ia_css_err err; 1079 1080 css_buf.type = css_buf_type; 1081 css_buf.data.frame = vm_mem->vaddr; 1082 1083 err = ia_css_pipe_enqueue_buffer( 1084 stream_env->pipes[css_pipe_id], &css_buf); 1085 if (err != IA_CSS_SUCCESS) 1086 return -EINVAL; 1087 1088 return 0; 1089 } 1090 1091 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd, 1092 struct atomisp_metadata_buf *metadata_buf, 1093 enum atomisp_input_stream_id stream_id, 1094 enum ia_css_pipe_id css_pipe_id) 1095 { 1096 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; 1097 struct ia_css_buffer buffer = {0}; 1098 struct atomisp_device *isp = asd->isp; 1099 1100 buffer.type = IA_CSS_BUFFER_TYPE_METADATA; 1101 buffer.data.metadata = metadata_buf->metadata; 1102 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id], 1103 &buffer)) { 1104 dev_err(isp->dev, "failed to q meta data buffer\n"); 1105 return -EINVAL; 1106 } 1107 1108 return 0; 1109 } 1110 1111 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd, 1112 struct atomisp_s3a_buf *s3a_buf, 1113 enum atomisp_input_stream_id stream_id, 1114 enum ia_css_pipe_id css_pipe_id) 1115 { 1116 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; 1117 struct ia_css_buffer buffer = {0}; 1118 struct atomisp_device *isp = asd->isp; 1119 1120 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS; 1121 buffer.data.stats_3a = s3a_buf->s3a_data; 1122 if (ia_css_pipe_enqueue_buffer( 1123 stream_env->pipes[css_pipe_id], 1124 &buffer)) { 1125 dev_dbg(isp->dev, "failed to q s3a stat buffer\n"); 1126 return -EINVAL; 1127 } 1128 1129 return 0; 1130 } 1131 1132 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, 1133 struct atomisp_dis_buf *dis_buf, 1134 enum atomisp_input_stream_id stream_id, 1135 enum ia_css_pipe_id css_pipe_id) 1136 { 1137 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id]; 1138 struct ia_css_buffer buffer = {0}; 1139 struct atomisp_device *isp = asd->isp; 1140 1141 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS; 1142 buffer.data.stats_dvs = dis_buf->dis_data; 1143 if (ia_css_pipe_enqueue_buffer( 1144 stream_env->pipes[css_pipe_id], 1145 &buffer)) { 1146 dev_dbg(isp->dev, "failed to q dvs stat buffer\n"); 1147 return -EINVAL; 1148 } 1149 1150 return 0; 1151 } 1152 1153 void atomisp_css_mmu_invalidate_cache(void) 1154 { 1155 ia_css_mmu_invalidate_cache(); 1156 } 1157 1158 void atomisp_css_mmu_invalidate_tlb(void) 1159 { 1160 ia_css_mmu_invalidate_cache(); 1161 } 1162 1163 int atomisp_css_start(struct atomisp_sub_device *asd, 1164 enum ia_css_pipe_id pipe_id, bool in_reset) 1165 { 1166 struct atomisp_device *isp = asd->isp; 1167 bool sp_is_started = false; 1168 int ret = 0, i = 0; 1169 1170 if (in_reset) { 1171 if (__destroy_streams(asd, true)) 1172 dev_warn(isp->dev, "destroy stream failed.\n"); 1173 1174 if (__destroy_pipes(asd, true)) 1175 dev_warn(isp->dev, "destroy pipe failed.\n"); 1176 1177 if (__create_pipes(asd)) { 1178 dev_err(isp->dev, "create pipe error.\n"); 1179 return -EINVAL; 1180 } 1181 if (__create_streams(asd)) { 1182 dev_err(isp->dev, "create stream error.\n"); 1183 ret = -EINVAL; 1184 goto stream_err; 1185 } 1186 /* in_reset == true, extension firmwares are reloaded after the recovery */ 1187 atomisp_acc_load_extensions(asd); 1188 } 1189 1190 /* 1191 * For dual steam case, it is possible that: 1192 * 1: for this stream, it is at the stage that: 1193 * - after set_fmt is called 1194 * - before stream on is called 1195 * 2: for the other stream, the stream off is called which css reset 1196 * has been done. 1197 * 1198 * Thus the stream created in set_fmt get destroyed and need to be 1199 * recreated in the next stream on. 1200 */ 1201 if (asd->stream_prepared == false) { 1202 if (__create_pipes(asd)) { 1203 dev_err(isp->dev, "create pipe error.\n"); 1204 return -EINVAL; 1205 } 1206 if (__create_streams(asd)) { 1207 dev_err(isp->dev, "create stream error.\n"); 1208 ret = -EINVAL; 1209 goto stream_err; 1210 } 1211 } 1212 /* 1213 * SP can only be started one time 1214 * if atomisp_subdev_streaming_count() tell there already has some 1215 * subdev at streamming, then SP should already be started previously, 1216 * so need to skip start sp procedure 1217 */ 1218 if (atomisp_streaming_count(isp)) { 1219 dev_dbg(isp->dev, "skip start sp\n"); 1220 } else { 1221 if (!sh_css_hrt_system_is_idle()) 1222 dev_err(isp->dev, "CSS HW not idle before starting SP\n"); 1223 if (ia_css_start_sp() != IA_CSS_SUCCESS) { 1224 dev_err(isp->dev, "start sp error.\n"); 1225 ret = -EINVAL; 1226 goto start_err; 1227 } else { 1228 sp_is_started = true; 1229 } 1230 } 1231 1232 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 1233 if (asd->stream_env[i].stream) { 1234 if (ia_css_stream_start(asd->stream_env[i] 1235 .stream) != IA_CSS_SUCCESS) { 1236 dev_err(isp->dev, "stream[%d] start error.\n", i); 1237 ret = -EINVAL; 1238 goto start_err; 1239 } else { 1240 asd->stream_env[i].stream_state = CSS_STREAM_STARTED; 1241 dev_dbg(isp->dev, "stream[%d] started.\n", i); 1242 } 1243 } 1244 } 1245 1246 return 0; 1247 1248 start_err: 1249 __destroy_streams(asd, true); 1250 stream_err: 1251 __destroy_pipes(asd, true); 1252 1253 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after 1254 * destroy all pipes 1255 */ 1256 /* 1257 * SP can not be stop if other streams are in use 1258 */ 1259 if ((atomisp_streaming_count(isp) == 0) && sp_is_started) 1260 ia_css_stop_sp(); 1261 1262 return ret; 1263 } 1264 1265 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd) 1266 { 1267 /* 1268 * FIXME! 1269 * for ISP2401 new input system, this api is under development. 1270 * Calling it would cause kernel panic. 1271 * 1272 * VIED BZ: 1458 1273 * 1274 * Check if it is Cherry Trail and also new input system 1275 */ 1276 if (asd->copy_mode) { 1277 dev_warn(asd->isp->dev, 1278 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n", 1279 __func__); 1280 return; 1281 } 1282 1283 ia_css_stream_set_isp_config( 1284 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 1285 &asd->params.config); 1286 atomisp_isp_parameters_clean_up(&asd->params.config); 1287 } 1288 1289 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd, 1290 struct ia_css_pipe *pipe) 1291 { 1292 enum ia_css_err ret; 1293 1294 if (!pipe) { 1295 atomisp_css_update_isp_params(asd); 1296 return; 1297 } 1298 1299 dev_dbg(asd->isp->dev, 1300 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n", 1301 __func__, asd->params.config.output_frame, 1302 asd->params.config.isp_config_id, pipe); 1303 1304 ret = ia_css_stream_set_isp_config_on_pipe( 1305 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 1306 &asd->params.config, pipe); 1307 if (ret != IA_CSS_SUCCESS) 1308 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n", 1309 __func__, ret); 1310 atomisp_isp_parameters_clean_up(&asd->params.config); 1311 } 1312 1313 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd, 1314 enum atomisp_input_stream_id stream_id, 1315 enum ia_css_pipe_id pipe_id, 1316 enum ia_css_buffer_type buf_type, 1317 struct atomisp_css_buffer *isp_css_buffer) 1318 { 1319 if (ia_css_pipe_enqueue_buffer( 1320 asd->stream_env[stream_id].pipes[pipe_id], 1321 &isp_css_buffer->css_buffer) 1322 != IA_CSS_SUCCESS) 1323 return -EINVAL; 1324 1325 return 0; 1326 } 1327 1328 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd, 1329 enum atomisp_input_stream_id stream_id, 1330 enum ia_css_pipe_id pipe_id, 1331 enum ia_css_buffer_type buf_type, 1332 struct atomisp_css_buffer *isp_css_buffer) 1333 { 1334 struct atomisp_device *isp = asd->isp; 1335 enum ia_css_err err; 1336 1337 err = ia_css_pipe_dequeue_buffer( 1338 asd->stream_env[stream_id].pipes[pipe_id], 1339 &isp_css_buffer->css_buffer); 1340 if (err != IA_CSS_SUCCESS) { 1341 dev_err(isp->dev, 1342 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err); 1343 return -EINVAL; 1344 } 1345 1346 return 0; 1347 } 1348 1349 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd, 1350 u16 stream_id, 1351 struct atomisp_s3a_buf *s3a_buf, 1352 struct atomisp_dis_buf *dis_buf, 1353 struct atomisp_metadata_buf *md_buf) 1354 { 1355 struct atomisp_device *isp = asd->isp; 1356 struct ia_css_dvs_grid_info *dvs_grid_info = 1357 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 1358 1359 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) { 1360 void *s3a_ptr; 1361 1362 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate( 1363 &asd->params.curr_grid_info.s3a_grid); 1364 if (!s3a_buf->s3a_data) { 1365 dev_err(isp->dev, "3a buf allocation failed.\n"); 1366 return -EINVAL; 1367 } 1368 1369 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true); 1370 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate( 1371 s3a_buf->s3a_data, s3a_ptr); 1372 } 1373 1374 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) { 1375 void *dvs_ptr; 1376 1377 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate( 1378 dvs_grid_info); 1379 if (!dis_buf->dis_data) { 1380 dev_err(isp->dev, "dvs buf allocation failed.\n"); 1381 if (s3a_buf) 1382 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data); 1383 return -EINVAL; 1384 } 1385 1386 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true); 1387 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate( 1388 dis_buf->dis_data, dvs_ptr); 1389 } 1390 1391 if (asd->stream_env[stream_id].stream_info. 1392 metadata_info.size && md_buf) { 1393 md_buf->metadata = ia_css_metadata_allocate( 1394 &asd->stream_env[stream_id].stream_info.metadata_info); 1395 if (!md_buf->metadata) { 1396 if (s3a_buf) 1397 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data); 1398 if (dis_buf) 1399 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data); 1400 dev_err(isp->dev, "metadata buf allocation failed.\n"); 1401 return -EINVAL; 1402 } 1403 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false); 1404 } 1405 1406 return 0; 1407 } 1408 1409 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf) 1410 { 1411 if (s3a_buf->s3a_data) 1412 hmm_vunmap(s3a_buf->s3a_data->data_ptr); 1413 1414 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map); 1415 s3a_buf->s3a_map = NULL; 1416 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data); 1417 } 1418 1419 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf) 1420 { 1421 if (dis_buf->dis_data) 1422 hmm_vunmap(dis_buf->dis_data->data_ptr); 1423 1424 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map); 1425 dis_buf->dvs_map = NULL; 1426 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data); 1427 } 1428 1429 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf) 1430 { 1431 if (metadata_buf->md_vptr) { 1432 hmm_vunmap(metadata_buf->metadata->address); 1433 metadata_buf->md_vptr = NULL; 1434 } 1435 ia_css_metadata_free(metadata_buf->metadata); 1436 } 1437 1438 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd) 1439 { 1440 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf; 1441 struct atomisp_dis_buf *dis_buf, *_dis_buf; 1442 struct atomisp_metadata_buf *md_buf, *_md_buf; 1443 struct ia_css_dvs_grid_info *dvs_grid_info = 1444 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 1445 unsigned int i; 1446 1447 /* 3A statistics use vmalloc, DIS use kmalloc */ 1448 if (dvs_grid_info && dvs_grid_info->enable) { 1449 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff); 1450 ia_css_dvs2_statistics_free(asd->params.dvs_stat); 1451 asd->params.css_param.dvs2_coeff = NULL; 1452 asd->params.dvs_stat = NULL; 1453 asd->params.dvs_hor_proj_bytes = 0; 1454 asd->params.dvs_ver_proj_bytes = 0; 1455 asd->params.dvs_hor_coef_bytes = 0; 1456 asd->params.dvs_ver_coef_bytes = 0; 1457 asd->params.dis_proj_data_valid = false; 1458 list_for_each_entry_safe(dis_buf, _dis_buf, 1459 &asd->dis_stats, list) { 1460 atomisp_css_free_dis_buffer(dis_buf); 1461 list_del(&dis_buf->list); 1462 kfree(dis_buf); 1463 } 1464 list_for_each_entry_safe(dis_buf, _dis_buf, 1465 &asd->dis_stats_in_css, list) { 1466 atomisp_css_free_dis_buffer(dis_buf); 1467 list_del(&dis_buf->list); 1468 kfree(dis_buf); 1469 } 1470 } 1471 if (asd->params.curr_grid_info.s3a_grid.enable) { 1472 ia_css_3a_statistics_free(asd->params.s3a_user_stat); 1473 asd->params.s3a_user_stat = NULL; 1474 asd->params.s3a_output_bytes = 0; 1475 list_for_each_entry_safe(s3a_buf, _s3a_buf, 1476 &asd->s3a_stats, list) { 1477 atomisp_css_free_3a_buffer(s3a_buf); 1478 list_del(&s3a_buf->list); 1479 kfree(s3a_buf); 1480 } 1481 list_for_each_entry_safe(s3a_buf, _s3a_buf, 1482 &asd->s3a_stats_in_css, list) { 1483 atomisp_css_free_3a_buffer(s3a_buf); 1484 list_del(&s3a_buf->list); 1485 kfree(s3a_buf); 1486 } 1487 list_for_each_entry_safe(s3a_buf, _s3a_buf, 1488 &asd->s3a_stats_ready, list) { 1489 atomisp_css_free_3a_buffer(s3a_buf); 1490 list_del(&s3a_buf->list); 1491 kfree(s3a_buf); 1492 } 1493 } 1494 1495 if (asd->params.css_param.dvs_6axis) { 1496 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis); 1497 asd->params.css_param.dvs_6axis = NULL; 1498 } 1499 1500 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 1501 list_for_each_entry_safe(md_buf, _md_buf, 1502 &asd->metadata[i], list) { 1503 atomisp_css_free_metadata_buffer(md_buf); 1504 list_del(&md_buf->list); 1505 kfree(md_buf); 1506 } 1507 list_for_each_entry_safe(md_buf, _md_buf, 1508 &asd->metadata_in_css[i], list) { 1509 atomisp_css_free_metadata_buffer(md_buf); 1510 list_del(&md_buf->list); 1511 kfree(md_buf); 1512 } 1513 list_for_each_entry_safe(md_buf, _md_buf, 1514 &asd->metadata_ready[i], list) { 1515 atomisp_css_free_metadata_buffer(md_buf); 1516 list_del(&md_buf->list); 1517 kfree(md_buf); 1518 } 1519 } 1520 asd->params.metadata_width_size = 0; 1521 atomisp_free_metadata_output_buf(asd); 1522 } 1523 1524 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd, 1525 enum ia_css_pipe_id pipe_id, 1526 int source_pad) 1527 { 1528 struct ia_css_pipe_info p_info; 1529 struct ia_css_grid_info old_info; 1530 struct atomisp_device *isp = asd->isp; 1531 int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); 1532 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 1533 stream_config.metadata_config.resolution.width; 1534 1535 memset(&p_info, 0, sizeof(struct ia_css_pipe_info)); 1536 memset(&old_info, 0, sizeof(struct ia_css_grid_info)); 1537 1538 if (ia_css_pipe_get_info( 1539 asd->stream_env[stream_index].pipes[pipe_id], 1540 &p_info) != IA_CSS_SUCCESS) { 1541 dev_err(isp->dev, "ia_css_pipe_get_info failed\n"); 1542 return -EINVAL; 1543 } 1544 1545 memcpy(&old_info, &asd->params.curr_grid_info, 1546 sizeof(struct ia_css_grid_info)); 1547 memcpy(&asd->params.curr_grid_info, &p_info.grid_info, 1548 sizeof(struct ia_css_grid_info)); 1549 /* 1550 * Record which css pipe enables s3a_grid. 1551 * Currently would have one css pipe that need it 1552 */ 1553 if (asd->params.curr_grid_info.s3a_grid.enable) { 1554 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM) 1555 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n", 1556 asd->params.s3a_enabled_pipe, pipe_id); 1557 asd->params.s3a_enabled_pipe = pipe_id; 1558 } 1559 1560 /* If the grid info has not changed and the buffers for 3A and 1561 * DIS statistics buffers are allocated or buffer size would be zero 1562 * then no need to do anything. */ 1563 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info)) 1564 && asd->params.s3a_user_stat && asd->params.dvs_stat) 1565 || asd->params.curr_grid_info.s3a_grid.width == 0 1566 || asd->params.curr_grid_info.s3a_grid.height == 0) 1567 && asd->params.metadata_width_size == md_width) { 1568 dev_dbg(isp->dev, 1569 "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n", 1570 !memcmp(&old_info, &asd->params.curr_grid_info, 1571 sizeof(old_info)), 1572 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat, 1573 asd->params.curr_grid_info.s3a_grid.width, 1574 asd->params.curr_grid_info.s3a_grid.height, 1575 asd->params.metadata_width_size); 1576 return -EINVAL; 1577 } 1578 asd->params.metadata_width_size = md_width; 1579 1580 return 0; 1581 } 1582 1583 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd) 1584 { 1585 if (!asd->params.curr_grid_info.s3a_grid.width || 1586 !asd->params.curr_grid_info.s3a_grid.height) 1587 return 0; 1588 1589 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate( 1590 &asd->params.curr_grid_info.s3a_grid); 1591 if (!asd->params.s3a_user_stat) 1592 return -ENOMEM; 1593 /* 3A statistics. These can be big, so we use vmalloc. */ 1594 asd->params.s3a_output_bytes = 1595 asd->params.curr_grid_info.s3a_grid.width * 1596 asd->params.curr_grid_info.s3a_grid.height * 1597 sizeof(*asd->params.s3a_user_stat->data); 1598 1599 return 0; 1600 } 1601 1602 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd) 1603 { 1604 struct ia_css_dvs_grid_info *dvs_grid = 1605 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 1606 1607 if (!dvs_grid) 1608 return 0; 1609 1610 if (!dvs_grid->enable) { 1611 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__); 1612 return 0; 1613 } 1614 1615 /* DIS coefficients. */ 1616 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate( 1617 dvs_grid); 1618 if (!asd->params.css_param.dvs2_coeff) 1619 return -ENOMEM; 1620 1621 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs * 1622 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real); 1623 1624 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs * 1625 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real); 1626 1627 /* DIS projections. */ 1628 asd->params.dis_proj_data_valid = false; 1629 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid); 1630 if (!asd->params.dvs_stat) 1631 return -ENOMEM; 1632 1633 asd->params.dvs_hor_proj_bytes = 1634 dvs_grid->aligned_height * dvs_grid->aligned_width * 1635 sizeof(*asd->params.dvs_stat->hor_prod.odd_real); 1636 1637 asd->params.dvs_ver_proj_bytes = 1638 dvs_grid->aligned_height * dvs_grid->aligned_width * 1639 sizeof(*asd->params.dvs_stat->ver_prod.odd_real); 1640 1641 return 0; 1642 } 1643 1644 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd) 1645 { 1646 int i; 1647 1648 /* We allocate the cpu-side buffer used for communication with user 1649 * space */ 1650 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 1651 asd->params.metadata_user[i] = kvmalloc( 1652 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 1653 stream_info.metadata_info.size, GFP_KERNEL); 1654 if (!asd->params.metadata_user[i]) { 1655 while (--i >= 0) { 1656 kvfree(asd->params.metadata_user[i]); 1657 asd->params.metadata_user[i] = NULL; 1658 } 1659 return -ENOMEM; 1660 } 1661 } 1662 1663 return 0; 1664 } 1665 1666 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd) 1667 { 1668 unsigned int i; 1669 1670 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 1671 if (asd->params.metadata_user[i]) { 1672 kvfree(asd->params.metadata_user[i]); 1673 asd->params.metadata_user[i] = NULL; 1674 } 1675 } 1676 } 1677 1678 void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd, 1679 struct atomisp_css_buffer *isp_css_buffer, 1680 struct ia_css_isp_dvs_statistics_map *dvs_map) 1681 { 1682 if (asd->params.dvs_stat) { 1683 if (dvs_map) 1684 ia_css_translate_dvs2_statistics( 1685 asd->params.dvs_stat, dvs_map); 1686 else 1687 ia_css_get_dvs2_statistics(asd->params.dvs_stat, 1688 isp_css_buffer->css_buffer.data.stats_dvs); 1689 } 1690 } 1691 1692 int atomisp_css_dequeue_event(struct atomisp_css_event *current_event) 1693 { 1694 if (ia_css_dequeue_event(¤t_event->event) != IA_CSS_SUCCESS) 1695 return -EINVAL; 1696 1697 return 0; 1698 } 1699 1700 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd, 1701 struct atomisp_css_event *current_event) 1702 { 1703 /* 1704 * FIXME! 1705 * Pipe ID reported in CSS event is not correct for new system's 1706 * copy pipe. 1707 * VIED BZ: 1463 1708 */ 1709 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe, 1710 ¤t_event->pipe); 1711 if (asd && asd->copy_mode && 1712 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE) 1713 current_event->pipe = IA_CSS_PIPE_ID_COPY; 1714 } 1715 1716 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd, 1717 enum atomisp_input_stream_id stream_id, 1718 struct v4l2_mbus_framefmt *ffmt, 1719 int isys_stream) 1720 { 1721 struct ia_css_stream_config *s_config = 1722 &asd->stream_env[stream_id].stream_config; 1723 1724 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH) 1725 return -EINVAL; 1726 1727 s_config->isys_config[isys_stream].input_res.width = ffmt->width; 1728 s_config->isys_config[isys_stream].input_res.height = ffmt->height; 1729 return 0; 1730 } 1731 1732 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd, 1733 enum atomisp_input_stream_id stream_id, 1734 struct v4l2_mbus_framefmt *ffmt) 1735 { 1736 struct ia_css_stream_config *s_config = 1737 &asd->stream_env[stream_id].stream_config; 1738 1739 s_config->input_config.input_res.width = ffmt->width; 1740 s_config->input_config.input_res.height = ffmt->height; 1741 return 0; 1742 } 1743 1744 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd, 1745 enum atomisp_input_stream_id stream_id, 1746 unsigned int bin_factor) 1747 { 1748 asd->stream_env[stream_id] 1749 .stream_config.sensor_binning_factor = bin_factor; 1750 } 1751 1752 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd, 1753 enum atomisp_input_stream_id stream_id, 1754 enum ia_css_bayer_order bayer_order) 1755 { 1756 struct ia_css_stream_config *s_config = 1757 &asd->stream_env[stream_id].stream_config; 1758 s_config->input_config.bayer_order = bayer_order; 1759 } 1760 1761 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd, 1762 enum atomisp_input_stream_id stream_id, 1763 int link, 1764 int isys_stream) 1765 { 1766 struct ia_css_stream_config *s_config = 1767 &asd->stream_env[stream_id].stream_config; 1768 1769 s_config->isys_config[isys_stream].linked_isys_stream_id = link; 1770 } 1771 1772 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd, 1773 enum atomisp_input_stream_id stream_id, 1774 bool valid, 1775 int isys_stream) 1776 { 1777 struct ia_css_stream_config *s_config = 1778 &asd->stream_env[stream_id].stream_config; 1779 1780 s_config->isys_config[isys_stream].valid = valid; 1781 } 1782 1783 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd, 1784 enum atomisp_input_stream_id stream_id, 1785 enum atomisp_input_format format, 1786 int isys_stream) 1787 { 1788 struct ia_css_stream_config *s_config = 1789 &asd->stream_env[stream_id].stream_config; 1790 1791 s_config->isys_config[isys_stream].format = format; 1792 } 1793 1794 void atomisp_css_input_set_format(struct atomisp_sub_device *asd, 1795 enum atomisp_input_stream_id stream_id, 1796 enum atomisp_input_format format) 1797 { 1798 struct ia_css_stream_config *s_config = 1799 &asd->stream_env[stream_id].stream_config; 1800 1801 s_config->input_config.format = format; 1802 } 1803 1804 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd, 1805 enum atomisp_input_stream_id stream_id, 1806 struct v4l2_mbus_framefmt *ffmt) 1807 { 1808 int i; 1809 struct ia_css_stream_config *s_config = 1810 &asd->stream_env[stream_id].stream_config; 1811 /* 1812 * Set all isys configs to not valid. 1813 * Currently we support only one stream per channel 1814 */ 1815 for (i = IA_CSS_STREAM_ISYS_STREAM_0; 1816 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) 1817 s_config->isys_config[i].valid = false; 1818 1819 atomisp_css_isys_set_resolution(asd, stream_id, ffmt, 1820 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 1821 atomisp_css_isys_set_format(asd, stream_id, 1822 s_config->input_config.format, 1823 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 1824 atomisp_css_isys_set_link(asd, stream_id, NO_LINK, 1825 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 1826 atomisp_css_isys_set_valid(asd, stream_id, true, 1827 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 1828 1829 return 0; 1830 } 1831 1832 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd, 1833 enum atomisp_input_stream_id stream_id, 1834 enum atomisp_input_format input_format) 1835 { 1836 struct ia_css_stream_config *s_config = 1837 &asd->stream_env[stream_id].stream_config; 1838 1839 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width = 1840 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width; 1841 1842 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height = 1843 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2; 1844 1845 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id 1846 = IA_CSS_STREAM_ISYS_STREAM_0; 1847 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format = 1848 ATOMISP_INPUT_FORMAT_USER_DEF1; 1849 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format = 1850 ATOMISP_INPUT_FORMAT_USER_DEF2; 1851 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true; 1852 return 0; 1853 } 1854 1855 void atomisp_css_isys_two_stream_cfg_update_stream1( 1856 struct atomisp_sub_device *asd, 1857 enum atomisp_input_stream_id stream_id, 1858 enum atomisp_input_format input_format, 1859 unsigned int width, unsigned int height) 1860 { 1861 struct ia_css_stream_config *s_config = 1862 &asd->stream_env[stream_id].stream_config; 1863 1864 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width = 1865 width; 1866 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height = 1867 height; 1868 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format = 1869 input_format; 1870 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true; 1871 } 1872 1873 void atomisp_css_isys_two_stream_cfg_update_stream2( 1874 struct atomisp_sub_device *asd, 1875 enum atomisp_input_stream_id stream_id, 1876 enum atomisp_input_format input_format, 1877 unsigned int width, unsigned int height) 1878 { 1879 struct ia_css_stream_config *s_config = 1880 &asd->stream_env[stream_id].stream_config; 1881 1882 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width = 1883 width; 1884 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height = 1885 height; 1886 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id 1887 = IA_CSS_STREAM_ISYS_STREAM_0; 1888 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format = 1889 input_format; 1890 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true; 1891 } 1892 1893 int atomisp_css_input_set_effective_resolution( 1894 struct atomisp_sub_device *asd, 1895 enum atomisp_input_stream_id stream_id, 1896 unsigned int width, unsigned int height) 1897 { 1898 struct ia_css_stream_config *s_config = 1899 &asd->stream_env[stream_id].stream_config; 1900 s_config->input_config.effective_res.width = width; 1901 s_config->input_config.effective_res.height = height; 1902 return 0; 1903 } 1904 1905 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd, 1906 unsigned int dvs_w, unsigned int dvs_h) 1907 { 1908 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1909 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w; 1910 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1911 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h; 1912 } 1913 1914 void atomisp_css_input_set_two_pixels_per_clock( 1915 struct atomisp_sub_device *asd, 1916 bool two_ppc) 1917 { 1918 int i; 1919 1920 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1921 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1)) 1922 return; 1923 1924 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1925 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1); 1926 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 1927 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1928 .update_pipe[i] = true; 1929 } 1930 1931 void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd, 1932 bool enable) 1933 { 1934 struct atomisp_stream_env *stream_env = 1935 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 1936 unsigned int pipe; 1937 1938 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) 1939 pipe = IA_CSS_PIPE_ID_VIDEO; 1940 else 1941 pipe = IA_CSS_PIPE_ID_PREVIEW; 1942 1943 stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable; 1944 stream_env->update_pipe[pipe] = true; 1945 if (enable) 1946 stream_env->pipe_configs[pipe].output_info[0].padded_width = 1947 stream_env->stream_config.input_config.effective_res.width; 1948 } 1949 1950 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable) 1951 { 1952 int i; 1953 1954 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 1955 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1956 .pipe_configs[i].enable_dz = enable; 1957 } 1958 1959 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd, 1960 enum ia_css_capture_mode mode) 1961 { 1962 struct atomisp_stream_env *stream_env = 1963 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 1964 1965 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE] 1966 .default_capture_config.mode == mode) 1967 return; 1968 1969 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]. 1970 default_capture_config.mode = mode; 1971 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true; 1972 } 1973 1974 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd, 1975 enum ia_css_input_mode mode) 1976 { 1977 int i; 1978 struct atomisp_device *isp = asd->isp; 1979 unsigned int size_mem_words; 1980 1981 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) 1982 asd->stream_env[i].stream_config.mode = mode; 1983 1984 if (isp->inputs[asd->input_curr].type == TEST_PATTERN) { 1985 struct ia_css_stream_config *s_config = 1986 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config; 1987 s_config->mode = IA_CSS_INPUT_MODE_TPG; 1988 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD; 1989 s_config->source.tpg.x_mask = (1 << 4) - 1; 1990 s_config->source.tpg.x_delta = -2; 1991 s_config->source.tpg.y_mask = (1 << 4) - 1; 1992 s_config->source.tpg.y_delta = 3; 1993 s_config->source.tpg.xy_mask = (1 << 8) - 1; 1994 return; 1995 } 1996 1997 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 1998 return; 1999 2000 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 2001 /* 2002 * TODO: sensor needs to export the embedded_data_size_words 2003 * information to atomisp for each setting. 2004 * Here using a large safe value. 2005 */ 2006 struct ia_css_stream_config *s_config = 2007 &asd->stream_env[i].stream_config; 2008 2009 if (s_config->input_config.input_res.width == 0) 2010 continue; 2011 2012 if (ia_css_mipi_frame_calculate_size( 2013 s_config->input_config.input_res.width, 2014 s_config->input_config.input_res.height, 2015 s_config->input_config.format, 2016 true, 2017 0x13000, 2018 &size_mem_words) != IA_CSS_SUCCESS) { 2019 if (intel_mid_identify_cpu() == 2020 INTEL_MID_CPU_CHIP_TANGIER) 2021 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2; 2022 else 2023 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1; 2024 dev_warn(asd->isp->dev, 2025 "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n", 2026 size_mem_words); 2027 } 2028 s_config->mipi_buffer_config.size_mem_words = size_mem_words; 2029 s_config->mipi_buffer_config.nof_mipi_buffers = 2; 2030 } 2031 } 2032 2033 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd, 2034 unsigned short stream_index, bool enable) 2035 { 2036 struct atomisp_stream_env *stream_env = 2037 &asd->stream_env[stream_index]; 2038 2039 if (stream_env->stream_config.online == !!enable) 2040 return; 2041 2042 stream_env->stream_config.online = !!enable; 2043 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true; 2044 } 2045 2046 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd, 2047 unsigned short stream_index, bool enable) 2048 { 2049 struct atomisp_stream_env *stream_env = 2050 &asd->stream_env[stream_index]; 2051 int i; 2052 2053 if (stream_env->stream_config.online != !!enable) { 2054 stream_env->stream_config.online = !!enable; 2055 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 2056 stream_env->update_pipe[i] = true; 2057 } 2058 } 2059 2060 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd, 2061 bool enable) 2062 { 2063 struct atomisp_stream_env *stream_env = 2064 &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO]; 2065 int i; 2066 2067 if (stream_env->stream_config.online != enable) { 2068 stream_env->stream_config.online = enable; 2069 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 2070 stream_env->update_pipe[i] = true; 2071 } 2072 } 2073 2074 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd, 2075 bool enable) 2076 { 2077 struct atomisp_stream_env *stream_env = 2078 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2079 int i; 2080 2081 /* 2082 * To SOC camera, there is only one YUVPP pipe in any case 2083 * including ZSL/SDV/continuous viewfinder, so always set 2084 * stream_config.continuous to 0. 2085 */ 2086 if (ATOMISP_USE_YUVPP(asd)) { 2087 stream_env->stream_config.continuous = 0; 2088 stream_env->stream_config.online = 1; 2089 return; 2090 } 2091 2092 if (stream_env->stream_config.continuous != !!enable) { 2093 stream_env->stream_config.continuous = !!enable; 2094 stream_env->stream_config.pack_raw_pixels = true; 2095 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 2096 stream_env->update_pipe[i] = true; 2097 } 2098 } 2099 2100 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd, 2101 bool enable) 2102 { 2103 struct atomisp_stream_env *stream_env = 2104 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2105 int i; 2106 2107 if (stream_env->stream_config.disable_cont_viewfinder != !enable) { 2108 stream_env->stream_config.disable_cont_viewfinder = !enable; 2109 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 2110 stream_env->update_pipe[i] = true; 2111 } 2112 } 2113 2114 int atomisp_css_input_configure_port( 2115 struct atomisp_sub_device *asd, 2116 enum mipi_port_id port, 2117 unsigned int num_lanes, 2118 unsigned int timeout, 2119 unsigned int mipi_freq, 2120 enum atomisp_input_format metadata_format, 2121 unsigned int metadata_width, 2122 unsigned int metadata_height) 2123 { 2124 int i; 2125 struct atomisp_stream_env *stream_env; 2126 /* 2127 * Calculate rx_count as follows: 2128 * Input: mipi_freq : CSI-2 bus frequency in Hz 2129 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus 2130 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds 2131 * max = 145e-9 + 10 * UI 2132 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks 2133 * rxcount = rxcount0 - 2 : adjust for better results 2134 * The formula below is simplified version of the above with 2135 * 10-bit fixed points for improved accuracy. 2136 */ 2137 const unsigned int rxcount = 2138 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U; 2139 2140 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 2141 stream_env = &asd->stream_env[i]; 2142 stream_env->stream_config.source.port.port = port; 2143 stream_env->stream_config.source.port.num_lanes = num_lanes; 2144 stream_env->stream_config.source.port.timeout = timeout; 2145 if (mipi_freq) 2146 stream_env->stream_config.source.port.rxcount = rxcount; 2147 stream_env->stream_config. 2148 metadata_config.data_type = metadata_format; 2149 stream_env->stream_config. 2150 metadata_config.resolution.width = metadata_width; 2151 stream_env->stream_config. 2152 metadata_config.resolution.height = metadata_height; 2153 } 2154 2155 return 0; 2156 } 2157 2158 int atomisp_css_frame_allocate(struct ia_css_frame **frame, 2159 unsigned int width, unsigned int height, 2160 enum ia_css_frame_format format, 2161 unsigned int padded_width, 2162 unsigned int raw_bit_depth) 2163 { 2164 if (ia_css_frame_allocate(frame, width, height, format, 2165 padded_width, raw_bit_depth) != IA_CSS_SUCCESS) 2166 return -ENOMEM; 2167 2168 return 0; 2169 } 2170 2171 int atomisp_css_frame_allocate_from_info(struct ia_css_frame **frame, 2172 const struct ia_css_frame_info *info) 2173 { 2174 if (ia_css_frame_allocate_from_info(frame, info) != IA_CSS_SUCCESS) 2175 return -ENOMEM; 2176 2177 return 0; 2178 } 2179 2180 void atomisp_css_frame_free(struct ia_css_frame *frame) 2181 { 2182 ia_css_frame_free(frame); 2183 } 2184 2185 int atomisp_css_frame_map(struct ia_css_frame **frame, 2186 const struct ia_css_frame_info *info, 2187 const void __user *data, uint16_t attribute, 2188 unsigned int pgnr) 2189 { 2190 if (ia_css_frame_map(frame, info, data, attribute, pgnr) 2191 != IA_CSS_SUCCESS) 2192 return -ENOMEM; 2193 2194 return 0; 2195 } 2196 2197 int atomisp_css_set_black_frame(struct atomisp_sub_device *asd, 2198 const struct ia_css_frame *raw_black_frame) 2199 { 2200 if (sh_css_set_black_frame( 2201 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 2202 raw_black_frame) != IA_CSS_SUCCESS) 2203 return -ENOMEM; 2204 2205 return 0; 2206 } 2207 2208 int atomisp_css_allocate_continuous_frames(bool init_time, 2209 struct atomisp_sub_device *asd) 2210 { 2211 if (ia_css_alloc_continuous_frame_remain( 2212 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) 2213 != IA_CSS_SUCCESS) 2214 return -EINVAL; 2215 return 0; 2216 } 2217 2218 void atomisp_css_update_continuous_frames(struct atomisp_sub_device *asd) 2219 { 2220 ia_css_update_continuous_frames( 2221 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream); 2222 } 2223 2224 int atomisp_css_stop(struct atomisp_sub_device *asd, 2225 enum ia_css_pipe_id pipe_id, bool in_reset) 2226 { 2227 struct atomisp_device *isp = asd->isp; 2228 struct atomisp_s3a_buf *s3a_buf; 2229 struct atomisp_dis_buf *dis_buf; 2230 struct atomisp_metadata_buf *md_buf; 2231 unsigned long irqflags; 2232 unsigned int i; 2233 2234 /* if is called in atomisp_reset(), force destroy stream */ 2235 if (__destroy_streams(asd, true)) 2236 dev_err(isp->dev, "destroy stream failed.\n"); 2237 2238 /* if is called in atomisp_reset(), force destroy all pipes */ 2239 if (__destroy_pipes(asd, true)) 2240 dev_err(isp->dev, "destroy pipes failed.\n"); 2241 2242 atomisp_init_raw_buffer_bitmap(asd); 2243 2244 /* 2245 * SP can not be stop if other streams are in use 2246 */ 2247 if (atomisp_streaming_count(isp) == 0) 2248 ia_css_stop_sp(); 2249 2250 if (!in_reset) { 2251 struct atomisp_stream_env *stream_env; 2252 int i, j; 2253 2254 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { 2255 stream_env = &asd->stream_env[i]; 2256 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) { 2257 ia_css_pipe_config_defaults( 2258 &stream_env->pipe_configs[j]); 2259 ia_css_pipe_extra_config_defaults( 2260 &stream_env->pipe_extra_configs[j]); 2261 } 2262 ia_css_stream_config_defaults( 2263 &stream_env->stream_config); 2264 } 2265 atomisp_isp_parameters_clean_up(&asd->params.config); 2266 asd->params.css_update_params_needed = false; 2267 } 2268 2269 /* move stats buffers to free queue list */ 2270 while (!list_empty(&asd->s3a_stats_in_css)) { 2271 s3a_buf = list_entry(asd->s3a_stats_in_css.next, 2272 struct atomisp_s3a_buf, list); 2273 list_del(&s3a_buf->list); 2274 list_add_tail(&s3a_buf->list, &asd->s3a_stats); 2275 } 2276 while (!list_empty(&asd->s3a_stats_ready)) { 2277 s3a_buf = list_entry(asd->s3a_stats_ready.next, 2278 struct atomisp_s3a_buf, list); 2279 list_del(&s3a_buf->list); 2280 list_add_tail(&s3a_buf->list, &asd->s3a_stats); 2281 } 2282 2283 spin_lock_irqsave(&asd->dis_stats_lock, irqflags); 2284 while (!list_empty(&asd->dis_stats_in_css)) { 2285 dis_buf = list_entry(asd->dis_stats_in_css.next, 2286 struct atomisp_dis_buf, list); 2287 list_del(&dis_buf->list); 2288 list_add_tail(&dis_buf->list, &asd->dis_stats); 2289 } 2290 asd->params.dis_proj_data_valid = false; 2291 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags); 2292 2293 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 2294 while (!list_empty(&asd->metadata_in_css[i])) { 2295 md_buf = list_entry(asd->metadata_in_css[i].next, 2296 struct atomisp_metadata_buf, list); 2297 list_del(&md_buf->list); 2298 list_add_tail(&md_buf->list, &asd->metadata[i]); 2299 } 2300 while (!list_empty(&asd->metadata_ready[i])) { 2301 md_buf = list_entry(asd->metadata_ready[i].next, 2302 struct atomisp_metadata_buf, list); 2303 list_del(&md_buf->list); 2304 list_add_tail(&md_buf->list, &asd->metadata[i]); 2305 } 2306 } 2307 2308 atomisp_flush_params_queue(&asd->video_out_capture); 2309 atomisp_flush_params_queue(&asd->video_out_vf); 2310 atomisp_flush_params_queue(&asd->video_out_preview); 2311 atomisp_flush_params_queue(&asd->video_out_video_capture); 2312 atomisp_free_css_parameters(&asd->params.css_param); 2313 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param)); 2314 return 0; 2315 } 2316 2317 int atomisp_css_continuous_set_num_raw_frames( 2318 struct atomisp_sub_device *asd, 2319 int num_frames) 2320 { 2321 if (asd->enable_raw_buffer_lock->val) { 2322 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2323 .stream_config.init_num_cont_raw_buf = 2324 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN; 2325 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 2326 asd->params.video_dis_en) 2327 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2328 .stream_config.init_num_cont_raw_buf += 2329 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; 2330 } else { 2331 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2332 .stream_config.init_num_cont_raw_buf = 2333 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES; 2334 } 2335 2336 if (asd->params.video_dis_en) 2337 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2338 .stream_config.init_num_cont_raw_buf += 2339 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; 2340 2341 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2342 .stream_config.target_num_cont_raw_buf = num_frames; 2343 return 0; 2344 } 2345 2346 void atomisp_css_disable_vf_pp(struct atomisp_sub_device *asd, 2347 bool disable) 2348 { 2349 int i; 2350 2351 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 2352 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2353 .pipe_extra_configs[i].disable_vf_pp = !!disable; 2354 } 2355 2356 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode( 2357 struct atomisp_sub_device *asd, 2358 enum ia_css_pipe_id pipe_id) 2359 { 2360 struct atomisp_device *isp = asd->isp; 2361 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info( 2362 isp->inputs[asd->input_curr].camera); 2363 2364 switch (pipe_id) { 2365 case IA_CSS_PIPE_ID_COPY: 2366 /* Currently only YUVPP mode supports YUV420_Legacy format. 2367 * Revert this when other pipe modes can support 2368 * YUV420_Legacy format. 2369 */ 2370 if (mipi_info && mipi_info->input_format == 2371 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) 2372 return IA_CSS_PIPE_MODE_YUVPP; 2373 return IA_CSS_PIPE_MODE_COPY; 2374 case IA_CSS_PIPE_ID_PREVIEW: 2375 return IA_CSS_PIPE_MODE_PREVIEW; 2376 case IA_CSS_PIPE_ID_CAPTURE: 2377 return IA_CSS_PIPE_MODE_CAPTURE; 2378 case IA_CSS_PIPE_ID_VIDEO: 2379 return IA_CSS_PIPE_MODE_VIDEO; 2380 case IA_CSS_PIPE_ID_ACC: 2381 return IA_CSS_PIPE_MODE_ACC; 2382 case IA_CSS_PIPE_ID_YUVPP: 2383 return IA_CSS_PIPE_MODE_YUVPP; 2384 default: 2385 WARN_ON(1); 2386 return IA_CSS_PIPE_MODE_PREVIEW; 2387 } 2388 } 2389 2390 static void __configure_output(struct atomisp_sub_device *asd, 2391 unsigned int stream_index, 2392 unsigned int width, unsigned int height, 2393 unsigned int min_width, 2394 enum ia_css_frame_format format, 2395 enum ia_css_pipe_id pipe_id) 2396 { 2397 struct atomisp_device *isp = asd->isp; 2398 struct atomisp_stream_env *stream_env = 2399 &asd->stream_env[stream_index]; 2400 struct ia_css_stream_config *s_config = &stream_env->stream_config; 2401 2402 stream_env->pipe_configs[pipe_id].mode = 2403 __pipe_id_to_pipe_mode(asd, pipe_id); 2404 stream_env->update_pipe[pipe_id] = true; 2405 2406 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width; 2407 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height; 2408 stream_env->pipe_configs[pipe_id].output_info[0].format = format; 2409 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width; 2410 2411 /* isp binary 2.2 specific setting*/ 2412 if (width > s_config->input_config.effective_res.width || 2413 height > s_config->input_config.effective_res.height) { 2414 s_config->input_config.effective_res.width = width; 2415 s_config->input_config.effective_res.height = height; 2416 } 2417 2418 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n", 2419 pipe_id, width, height, format); 2420 } 2421 2422 static void __configure_video_preview_output(struct atomisp_sub_device *asd, 2423 unsigned int stream_index, 2424 unsigned int width, unsigned int height, 2425 unsigned int min_width, 2426 enum ia_css_frame_format format, 2427 enum ia_css_pipe_id pipe_id) 2428 { 2429 struct atomisp_device *isp = asd->isp; 2430 struct atomisp_stream_env *stream_env = 2431 &asd->stream_env[stream_index]; 2432 struct ia_css_frame_info *css_output_info; 2433 struct ia_css_stream_config *stream_config = &stream_env->stream_config; 2434 2435 stream_env->pipe_configs[pipe_id].mode = 2436 __pipe_id_to_pipe_mode(asd, pipe_id); 2437 stream_env->update_pipe[pipe_id] = true; 2438 2439 /* 2440 * second_output will be as video main output in SDV mode 2441 * with SOC camera. output will be as video main output in 2442 * normal video mode. 2443 */ 2444 if (asd->continuous_mode->val) 2445 css_output_info = &stream_env->pipe_configs[pipe_id]. 2446 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; 2447 else 2448 css_output_info = &stream_env->pipe_configs[pipe_id]. 2449 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; 2450 2451 css_output_info->res.width = width; 2452 css_output_info->res.height = height; 2453 css_output_info->format = format; 2454 css_output_info->padded_width = min_width; 2455 2456 /* isp binary 2.2 specific setting*/ 2457 if (width > stream_config->input_config.effective_res.width || 2458 height > stream_config->input_config.effective_res.height) { 2459 stream_config->input_config.effective_res.width = width; 2460 stream_config->input_config.effective_res.height = height; 2461 } 2462 2463 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n", 2464 pipe_id, width, height, format); 2465 } 2466 2467 /* 2468 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv 2469 * downscaling input resolution. 2470 */ 2471 static void __configure_capture_pp_input(struct atomisp_sub_device *asd, 2472 unsigned int width, unsigned int height, 2473 enum ia_css_pipe_id pipe_id) 2474 { 2475 struct atomisp_device *isp = asd->isp; 2476 struct atomisp_stream_env *stream_env = 2477 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2478 struct ia_css_stream_config *stream_config = &stream_env->stream_config; 2479 struct ia_css_pipe_config *pipe_configs = 2480 &stream_env->pipe_configs[pipe_id]; 2481 struct ia_css_pipe_extra_config *pipe_extra_configs = 2482 &stream_env->pipe_extra_configs[pipe_id]; 2483 unsigned int hor_ds_factor = 0, ver_ds_factor = 0; 2484 2485 if (width == 0 && height == 0) 2486 return; 2487 2488 if (width * 9 / 10 < pipe_configs->output_info[0].res.width || 2489 height * 9 / 10 < pipe_configs->output_info[0].res.height) 2490 return; 2491 /* here just copy the calculation in css */ 2492 hor_ds_factor = CEIL_DIV(width >> 1, 2493 pipe_configs->output_info[0].res.width); 2494 ver_ds_factor = CEIL_DIV(height >> 1, 2495 pipe_configs->output_info[0].res.height); 2496 2497 if ((asd->isp->media_dev.hw_revision < 2498 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) || 2499 IS_CHT) && hor_ds_factor != ver_ds_factor) { 2500 dev_warn(asd->isp->dev, 2501 "Cropping for capture due to FW limitation"); 2502 return; 2503 } 2504 2505 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id); 2506 stream_env->update_pipe[pipe_id] = true; 2507 2508 pipe_extra_configs->enable_yuv_ds = true; 2509 2510 pipe_configs->capt_pp_in_res.width = 2511 stream_config->input_config.effective_res.width; 2512 pipe_configs->capt_pp_in_res.height = 2513 stream_config->input_config.effective_res.height; 2514 2515 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n", 2516 pipe_id, width, height); 2517 } 2518 2519 /* 2520 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and 2521 * yuv downscaling, which needs addtional configurations. 2522 */ 2523 static void __configure_preview_pp_input(struct atomisp_sub_device *asd, 2524 unsigned int width, unsigned int height, 2525 enum ia_css_pipe_id pipe_id) 2526 { 2527 struct atomisp_device *isp = asd->isp; 2528 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height; 2529 struct atomisp_stream_env *stream_env = 2530 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2531 struct ia_css_stream_config *stream_config = &stream_env->stream_config; 2532 struct ia_css_pipe_config *pipe_configs = 2533 &stream_env->pipe_configs[pipe_id]; 2534 struct ia_css_pipe_extra_config *pipe_extra_configs = 2535 &stream_env->pipe_extra_configs[pipe_id]; 2536 struct ia_css_resolution *bayer_ds_out_res = 2537 &pipe_configs->bayer_ds_out_res; 2538 struct ia_css_resolution *vf_pp_in_res = 2539 &pipe_configs->vf_pp_in_res; 2540 struct ia_css_resolution *effective_res = 2541 &stream_config->input_config.effective_res; 2542 2543 const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} }; 2544 /* 2545 * BZ201033: YUV decimation factor of 4 causes couple of rightmost 2546 * columns to be shaded. Remove this factor to work around the CSS bug. 2547 * const unsigned int yuv_dec_fct[] = {4, 2}; 2548 */ 2549 const unsigned int yuv_dec_fct[] = { 2 }; 2550 unsigned int i; 2551 2552 if (width == 0 && height == 0) 2553 return; 2554 2555 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id); 2556 stream_env->update_pipe[pipe_id] = true; 2557 2558 out_width = pipe_configs->output_info[0].res.width; 2559 out_height = pipe_configs->output_info[0].res.height; 2560 2561 /* 2562 * The ISP could do bayer downscaling, yuv decimation and yuv 2563 * downscaling: 2564 * 1: Bayer Downscaling: between effective resolution and 2565 * bayer_ds_res_out; 2566 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res; 2567 * 3: YUV Downscaling: between vf_pp_in_res and final vf output 2568 * 2569 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25 2570 * Rule for YUV Decimation: support factor 2, 4 2571 * Rule for YUV Downscaling: arbitrary value below 2 2572 * 2573 * General rule of factor distribution among these stages: 2574 * 1: try to do Bayer downscaling first if not in online mode. 2575 * 2: try to do maximum of 2 for YUV downscaling 2576 * 3: the remainling for YUV decimation 2577 * 2578 * Note: 2579 * Do not configure bayer_ds_out_res if: 2580 * online == 1 or continuous == 0 or raw_binning = 0 2581 */ 2582 if (stream_config->online || !stream_config->continuous || 2583 !pipe_extra_configs->enable_raw_binning) { 2584 bayer_ds_out_res->width = 0; 2585 bayer_ds_out_res->height = 0; 2586 } else { 2587 bayer_ds_out_res->width = effective_res->width; 2588 bayer_ds_out_res->height = effective_res->height; 2589 2590 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) { 2591 if (effective_res->width >= out_width * 2592 bds_fct[i].numerator / bds_fct[i].denominator && 2593 effective_res->height >= out_height * 2594 bds_fct[i].numerator / bds_fct[i].denominator) { 2595 bayer_ds_out_res->width = 2596 effective_res->width * 2597 bds_fct[i].denominator / 2598 bds_fct[i].numerator; 2599 bayer_ds_out_res->height = 2600 effective_res->height * 2601 bds_fct[i].denominator / 2602 bds_fct[i].numerator; 2603 break; 2604 } 2605 } 2606 } 2607 /* 2608 * calculate YUV Decimation, YUV downscaling facor: 2609 * YUV Downscaling factor must not exceed 2. 2610 * YUV Decimation factor could be 2, 4. 2611 */ 2612 /* first decide the yuv_ds input resolution */ 2613 if (bayer_ds_out_res->width == 0) { 2614 yuv_ds_in_width = effective_res->width; 2615 yuv_ds_in_height = effective_res->height; 2616 } else { 2617 yuv_ds_in_width = bayer_ds_out_res->width; 2618 yuv_ds_in_height = bayer_ds_out_res->height; 2619 } 2620 2621 vf_pp_in_res->width = yuv_ds_in_width; 2622 vf_pp_in_res->height = yuv_ds_in_height; 2623 2624 /* find out the yuv decimation factor */ 2625 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) { 2626 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] && 2627 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) { 2628 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i]; 2629 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i]; 2630 break; 2631 } 2632 } 2633 2634 if (vf_pp_in_res->width == out_width && 2635 vf_pp_in_res->height == out_height) { 2636 pipe_extra_configs->enable_yuv_ds = false; 2637 vf_pp_in_res->width = 0; 2638 vf_pp_in_res->height = 0; 2639 } else { 2640 pipe_extra_configs->enable_yuv_ds = true; 2641 } 2642 2643 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n", 2644 pipe_id, width, height); 2645 } 2646 2647 /* 2648 * For CSS2.1, offline video pipe could support bayer decimation, and 2649 * yuv downscaling, which needs addtional configurations. 2650 */ 2651 static void __configure_video_pp_input(struct atomisp_sub_device *asd, 2652 unsigned int width, unsigned int height, 2653 enum ia_css_pipe_id pipe_id) 2654 { 2655 struct atomisp_device *isp = asd->isp; 2656 int out_width, out_height; 2657 struct atomisp_stream_env *stream_env = 2658 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2659 struct ia_css_stream_config *stream_config = &stream_env->stream_config; 2660 struct ia_css_pipe_config *pipe_configs = 2661 &stream_env->pipe_configs[pipe_id]; 2662 struct ia_css_pipe_extra_config *pipe_extra_configs = 2663 &stream_env->pipe_extra_configs[pipe_id]; 2664 struct ia_css_resolution *bayer_ds_out_res = 2665 &pipe_configs->bayer_ds_out_res; 2666 struct ia_css_resolution *effective_res = 2667 &stream_config->input_config.effective_res; 2668 2669 const struct bayer_ds_factor bds_factors[] = { 2670 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2} 2671 }; 2672 unsigned int i; 2673 2674 if (width == 0 && height == 0) 2675 return; 2676 2677 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id); 2678 stream_env->update_pipe[pipe_id] = true; 2679 2680 pipe_extra_configs->enable_yuv_ds = false; 2681 2682 /* 2683 * If DVS is enabled, video binary will take care the dvs envelope 2684 * and usually the bayer_ds_out_res should be larger than 120% of 2685 * destination resolution, the extra 20% will be cropped as DVS 2686 * envelope. But, if the bayer_ds_out_res is less than 120% of the 2687 * destination. The ISP can still work, but DVS quality is not good. 2688 */ 2689 /* taking at least 10% as envelope */ 2690 if (asd->params.video_dis_en) { 2691 out_width = pipe_configs->output_info[0].res.width * 110 / 100; 2692 out_height = pipe_configs->output_info[0].res.height * 110 / 100; 2693 } else { 2694 out_width = pipe_configs->output_info[0].res.width; 2695 out_height = pipe_configs->output_info[0].res.height; 2696 } 2697 2698 /* 2699 * calculate bayer decimate factor: 2700 * 1: only 1.5, 2, 4 and 8 get supported 2701 * 2: Do not configure bayer_ds_out_res if: 2702 * online == 1 or continuous == 0 or raw_binning = 0 2703 */ 2704 if (stream_config->online || !stream_config->continuous) { 2705 bayer_ds_out_res->width = 0; 2706 bayer_ds_out_res->height = 0; 2707 goto done; 2708 } 2709 2710 pipe_extra_configs->enable_raw_binning = true; 2711 bayer_ds_out_res->width = effective_res->width; 2712 bayer_ds_out_res->height = effective_res->height; 2713 2714 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor); 2715 i++) { 2716 if (effective_res->width >= out_width * 2717 bds_factors[i].numerator / bds_factors[i].denominator && 2718 effective_res->height >= out_height * 2719 bds_factors[i].numerator / bds_factors[i].denominator) { 2720 bayer_ds_out_res->width = effective_res->width * 2721 bds_factors[i].denominator / 2722 bds_factors[i].numerator; 2723 bayer_ds_out_res->height = effective_res->height * 2724 bds_factors[i].denominator / 2725 bds_factors[i].numerator; 2726 break; 2727 } 2728 } 2729 2730 /* 2731 * DVS is cropped from BDS output, so we do not really need to set the 2732 * envelope to 20% of output resolution here. always set it to 12x12 2733 * per firmware requirement. 2734 */ 2735 pipe_configs->dvs_envelope.width = 12; 2736 pipe_configs->dvs_envelope.height = 12; 2737 2738 done: 2739 if (pipe_id == IA_CSS_PIPE_ID_YUVPP) 2740 stream_config->left_padding = -1; 2741 else 2742 stream_config->left_padding = 12; 2743 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n", 2744 pipe_id, width, height); 2745 } 2746 2747 static void __configure_vf_output(struct atomisp_sub_device *asd, 2748 unsigned int width, unsigned int height, 2749 unsigned int min_width, 2750 enum ia_css_frame_format format, 2751 enum ia_css_pipe_id pipe_id) 2752 { 2753 struct atomisp_device *isp = asd->isp; 2754 struct atomisp_stream_env *stream_env = 2755 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2756 stream_env->pipe_configs[pipe_id].mode = 2757 __pipe_id_to_pipe_mode(asd, pipe_id); 2758 stream_env->update_pipe[pipe_id] = true; 2759 2760 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width; 2761 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height; 2762 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format; 2763 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width = 2764 min_width; 2765 dev_dbg(isp->dev, 2766 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n", 2767 pipe_id, width, height, format); 2768 } 2769 2770 static void __configure_video_vf_output(struct atomisp_sub_device *asd, 2771 unsigned int width, unsigned int height, 2772 unsigned int min_width, 2773 enum ia_css_frame_format format, 2774 enum ia_css_pipe_id pipe_id) 2775 { 2776 struct atomisp_device *isp = asd->isp; 2777 struct atomisp_stream_env *stream_env = 2778 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2779 struct ia_css_frame_info *css_output_info; 2780 2781 stream_env->pipe_configs[pipe_id].mode = 2782 __pipe_id_to_pipe_mode(asd, pipe_id); 2783 stream_env->update_pipe[pipe_id] = true; 2784 2785 /* 2786 * second_vf_output will be as video viewfinder in SDV mode 2787 * with SOC camera. vf_output will be as video viewfinder in 2788 * normal video mode. 2789 */ 2790 if (asd->continuous_mode->val) 2791 css_output_info = &stream_env->pipe_configs[pipe_id]. 2792 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; 2793 else 2794 css_output_info = &stream_env->pipe_configs[pipe_id]. 2795 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; 2796 2797 css_output_info->res.width = width; 2798 css_output_info->res.height = height; 2799 css_output_info->format = format; 2800 css_output_info->padded_width = min_width; 2801 dev_dbg(isp->dev, 2802 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n", 2803 pipe_id, width, height, format); 2804 } 2805 2806 static int __get_frame_info(struct atomisp_sub_device *asd, 2807 unsigned int stream_index, 2808 struct ia_css_frame_info *info, 2809 enum frame_info_type type, 2810 enum ia_css_pipe_id pipe_id) 2811 { 2812 struct atomisp_device *isp = asd->isp; 2813 enum ia_css_err ret; 2814 struct ia_css_pipe_info p_info; 2815 2816 /* FIXME! No need to destroy/recreate all streams */ 2817 if (__destroy_streams(asd, true)) 2818 dev_warn(isp->dev, "destroy stream failed.\n"); 2819 2820 if (__destroy_pipes(asd, true)) 2821 dev_warn(isp->dev, "destroy pipe failed.\n"); 2822 2823 if (__create_pipes(asd)) 2824 return -EINVAL; 2825 2826 if (__create_streams(asd)) 2827 goto stream_err; 2828 2829 ret = ia_css_pipe_get_info( 2830 asd->stream_env[stream_index] 2831 .pipes[pipe_id], &p_info); 2832 if (ret == IA_CSS_SUCCESS) { 2833 switch (type) { 2834 case ATOMISP_CSS_VF_FRAME: 2835 *info = p_info.vf_output_info[0]; 2836 dev_dbg(isp->dev, "getting vf frame info.\n"); 2837 break; 2838 case ATOMISP_CSS_SECOND_VF_FRAME: 2839 *info = p_info.vf_output_info[1]; 2840 dev_dbg(isp->dev, "getting second vf frame info.\n"); 2841 break; 2842 case ATOMISP_CSS_OUTPUT_FRAME: 2843 *info = p_info.output_info[0]; 2844 dev_dbg(isp->dev, "getting main frame info.\n"); 2845 break; 2846 case ATOMISP_CSS_SECOND_OUTPUT_FRAME: 2847 *info = p_info.output_info[1]; 2848 dev_dbg(isp->dev, "getting second main frame info.\n"); 2849 break; 2850 case ATOMISP_CSS_RAW_FRAME: 2851 *info = p_info.raw_output_info; 2852 dev_dbg(isp->dev, "getting raw frame info.\n"); 2853 } 2854 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n", 2855 info->res.width, info->res.height, p_info.num_invalid_frames); 2856 return 0; 2857 } 2858 2859 stream_err: 2860 __destroy_pipes(asd, true); 2861 return -EINVAL; 2862 } 2863 2864 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd, 2865 uint16_t source_pad) 2866 { 2867 struct atomisp_device *isp = asd->isp; 2868 /* 2869 * to SOC camera, use yuvpp pipe. 2870 */ 2871 if (ATOMISP_USE_YUVPP(asd)) 2872 return IA_CSS_PIPE_ID_YUVPP; 2873 2874 switch (source_pad) { 2875 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: 2876 if (asd->yuvpp_mode) 2877 return IA_CSS_PIPE_ID_YUVPP; 2878 if (asd->copy_mode) 2879 return IA_CSS_PIPE_ID_COPY; 2880 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO 2881 || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) 2882 return IA_CSS_PIPE_ID_VIDEO; 2883 else 2884 return IA_CSS_PIPE_ID_CAPTURE; 2885 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: 2886 if (asd->copy_mode) 2887 return IA_CSS_PIPE_ID_COPY; 2888 return IA_CSS_PIPE_ID_CAPTURE; 2889 case ATOMISP_SUBDEV_PAD_SOURCE_VF: 2890 if (!atomisp_is_mbuscode_raw( 2891 asd->fmt[asd->capture_pad].fmt.code)) 2892 return IA_CSS_PIPE_ID_CAPTURE; 2893 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: 2894 if (asd->yuvpp_mode) 2895 return IA_CSS_PIPE_ID_YUVPP; 2896 if (asd->copy_mode) 2897 return IA_CSS_PIPE_ID_COPY; 2898 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) 2899 return IA_CSS_PIPE_ID_VIDEO; 2900 else 2901 return IA_CSS_PIPE_ID_PREVIEW; 2902 } 2903 dev_warn(isp->dev, 2904 "invalid source pad:%d, return default preview pipe index.\n", 2905 source_pad); 2906 return IA_CSS_PIPE_ID_PREVIEW; 2907 } 2908 2909 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, 2910 u16 source_pad, 2911 struct ia_css_frame_info *frame_info) 2912 { 2913 struct ia_css_pipe_info info; 2914 int pipe_index = atomisp_get_pipe_index(asd, source_pad); 2915 int stream_index; 2916 struct atomisp_device *isp = asd->isp; 2917 2918 if (ATOMISP_SOC_CAMERA(asd)) 2919 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); 2920 else { 2921 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ? 2922 ATOMISP_INPUT_STREAM_VIDEO : 2923 atomisp_source_pad_to_stream_id(asd, source_pad); 2924 } 2925 2926 if (IA_CSS_SUCCESS != ia_css_pipe_get_info(asd->stream_env[stream_index] 2927 .pipes[pipe_index], &info)) { 2928 dev_err(isp->dev, "ia_css_pipe_get_info FAILED"); 2929 return -EINVAL; 2930 } 2931 2932 switch (source_pad) { 2933 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: 2934 *frame_info = info.output_info[0]; 2935 break; 2936 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: 2937 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val) 2938 *frame_info = info. 2939 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; 2940 else 2941 *frame_info = info. 2942 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; 2943 break; 2944 case ATOMISP_SUBDEV_PAD_SOURCE_VF: 2945 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW) 2946 *frame_info = info.output_info[0]; 2947 else 2948 *frame_info = info.vf_output_info[0]; 2949 break; 2950 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: 2951 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 2952 (pipe_index == IA_CSS_PIPE_ID_VIDEO || 2953 pipe_index == IA_CSS_PIPE_ID_YUVPP)) 2954 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val) 2955 *frame_info = info. 2956 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; 2957 else 2958 *frame_info = info. 2959 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; 2960 else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val) 2961 *frame_info = 2962 info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX]; 2963 else 2964 *frame_info = 2965 info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; 2966 2967 break; 2968 default: 2969 frame_info = NULL; 2970 break; 2971 } 2972 return frame_info ? 0 : -EINVAL; 2973 } 2974 2975 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd, 2976 unsigned int stream_index, 2977 unsigned int width, unsigned int height, 2978 unsigned int padded_width, 2979 enum ia_css_frame_format format) 2980 { 2981 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY]. 2982 default_capture_config.mode = 2983 IA_CSS_CAPTURE_MODE_RAW; 2984 2985 __configure_output(asd, stream_index, width, height, padded_width, 2986 format, IA_CSS_PIPE_ID_COPY); 2987 return 0; 2988 } 2989 2990 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd, 2991 unsigned int stream_index, 2992 unsigned int width, unsigned int height, 2993 unsigned int padded_width, 2994 enum ia_css_frame_format format) 2995 { 2996 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP]. 2997 default_capture_config.mode = 2998 IA_CSS_CAPTURE_MODE_RAW; 2999 3000 __configure_output(asd, stream_index, width, height, padded_width, 3001 format, IA_CSS_PIPE_ID_YUVPP); 3002 return 0; 3003 } 3004 3005 int atomisp_css_yuvpp_configure_viewfinder( 3006 struct atomisp_sub_device *asd, 3007 unsigned int stream_index, 3008 unsigned int width, unsigned int height, 3009 unsigned int min_width, 3010 enum ia_css_frame_format format) 3011 { 3012 struct atomisp_stream_env *stream_env = 3013 &asd->stream_env[stream_index]; 3014 enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP; 3015 3016 stream_env->pipe_configs[pipe_id].mode = 3017 __pipe_id_to_pipe_mode(asd, pipe_id); 3018 stream_env->update_pipe[pipe_id] = true; 3019 3020 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width; 3021 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height; 3022 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format; 3023 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width = 3024 min_width; 3025 return 0; 3026 } 3027 3028 int atomisp_css_yuvpp_get_output_frame_info( 3029 struct atomisp_sub_device *asd, 3030 unsigned int stream_index, 3031 struct ia_css_frame_info *info) 3032 { 3033 return __get_frame_info(asd, stream_index, info, 3034 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP); 3035 } 3036 3037 int atomisp_css_yuvpp_get_viewfinder_frame_info( 3038 struct atomisp_sub_device *asd, 3039 unsigned int stream_index, 3040 struct ia_css_frame_info *info) 3041 { 3042 return __get_frame_info(asd, stream_index, info, 3043 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP); 3044 } 3045 3046 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd, 3047 unsigned int width, unsigned int height, 3048 unsigned int min_width, 3049 enum ia_css_frame_format format) 3050 { 3051 /* 3052 * to SOC camera, use yuvpp pipe. 3053 */ 3054 if (ATOMISP_USE_YUVPP(asd)) 3055 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, 3056 height, 3057 min_width, format, IA_CSS_PIPE_ID_YUVPP); 3058 else 3059 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, 3060 min_width, format, IA_CSS_PIPE_ID_PREVIEW); 3061 return 0; 3062 } 3063 3064 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd, 3065 unsigned int width, unsigned int height, 3066 unsigned int min_width, 3067 enum ia_css_frame_format format) 3068 { 3069 enum ia_css_pipe_id pipe_id; 3070 3071 /* 3072 * to SOC camera, use yuvpp pipe. 3073 */ 3074 if (ATOMISP_USE_YUVPP(asd)) 3075 pipe_id = IA_CSS_PIPE_ID_YUVPP; 3076 else 3077 pipe_id = IA_CSS_PIPE_ID_CAPTURE; 3078 3079 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, 3080 min_width, format, pipe_id); 3081 return 0; 3082 } 3083 3084 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd, 3085 unsigned int width, unsigned int height, 3086 unsigned int min_width, 3087 enum ia_css_frame_format format) 3088 { 3089 /* 3090 * to SOC camera, use yuvpp pipe. 3091 */ 3092 if (ATOMISP_USE_YUVPP(asd)) 3093 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, 3094 height, 3095 min_width, format, IA_CSS_PIPE_ID_YUVPP); 3096 else 3097 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height, 3098 min_width, format, IA_CSS_PIPE_ID_VIDEO); 3099 return 0; 3100 } 3101 3102 int atomisp_css_video_configure_viewfinder( 3103 struct atomisp_sub_device *asd, 3104 unsigned int width, unsigned int height, 3105 unsigned int min_width, 3106 enum ia_css_frame_format format) 3107 { 3108 /* 3109 * to SOC camera, video will use yuvpp pipe. 3110 */ 3111 if (ATOMISP_USE_YUVPP(asd)) 3112 __configure_video_vf_output(asd, width, height, min_width, format, 3113 IA_CSS_PIPE_ID_YUVPP); 3114 else 3115 __configure_vf_output(asd, width, height, min_width, format, 3116 IA_CSS_PIPE_ID_VIDEO); 3117 return 0; 3118 } 3119 3120 int atomisp_css_capture_configure_viewfinder( 3121 struct atomisp_sub_device *asd, 3122 unsigned int width, unsigned int height, 3123 unsigned int min_width, 3124 enum ia_css_frame_format format) 3125 { 3126 enum ia_css_pipe_id pipe_id; 3127 3128 /* 3129 * to SOC camera, video will use yuvpp pipe. 3130 */ 3131 if (ATOMISP_USE_YUVPP(asd)) 3132 pipe_id = IA_CSS_PIPE_ID_YUVPP; 3133 else 3134 pipe_id = IA_CSS_PIPE_ID_CAPTURE; 3135 3136 __configure_vf_output(asd, width, height, min_width, format, 3137 pipe_id); 3138 return 0; 3139 } 3140 3141 int atomisp_css_video_get_viewfinder_frame_info( 3142 struct atomisp_sub_device *asd, 3143 struct ia_css_frame_info *info) 3144 { 3145 enum ia_css_pipe_id pipe_id; 3146 enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME; 3147 3148 if (ATOMISP_USE_YUVPP(asd)) { 3149 pipe_id = IA_CSS_PIPE_ID_YUVPP; 3150 if (asd->continuous_mode->val) 3151 frame_type = ATOMISP_CSS_SECOND_VF_FRAME; 3152 } else { 3153 pipe_id = IA_CSS_PIPE_ID_VIDEO; 3154 } 3155 3156 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 3157 frame_type, pipe_id); 3158 } 3159 3160 int atomisp_css_capture_get_viewfinder_frame_info( 3161 struct atomisp_sub_device *asd, 3162 struct ia_css_frame_info *info) 3163 { 3164 enum ia_css_pipe_id pipe_id; 3165 3166 if (ATOMISP_USE_YUVPP(asd)) 3167 pipe_id = IA_CSS_PIPE_ID_YUVPP; 3168 else 3169 pipe_id = IA_CSS_PIPE_ID_CAPTURE; 3170 3171 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 3172 ATOMISP_CSS_VF_FRAME, pipe_id); 3173 } 3174 3175 int atomisp_css_capture_get_output_raw_frame_info( 3176 struct atomisp_sub_device *asd, 3177 struct ia_css_frame_info *info) 3178 { 3179 if (ATOMISP_USE_YUVPP(asd)) 3180 return 0; 3181 3182 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 3183 ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE); 3184 } 3185 3186 int atomisp_css_copy_get_output_frame_info( 3187 struct atomisp_sub_device *asd, 3188 unsigned int stream_index, 3189 struct ia_css_frame_info *info) 3190 { 3191 return __get_frame_info(asd, stream_index, info, 3192 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY); 3193 } 3194 3195 int atomisp_css_preview_get_output_frame_info( 3196 struct atomisp_sub_device *asd, 3197 struct ia_css_frame_info *info) 3198 { 3199 enum ia_css_pipe_id pipe_id; 3200 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME; 3201 3202 if (ATOMISP_USE_YUVPP(asd)) { 3203 pipe_id = IA_CSS_PIPE_ID_YUVPP; 3204 if (asd->continuous_mode->val) 3205 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME; 3206 } else { 3207 pipe_id = IA_CSS_PIPE_ID_PREVIEW; 3208 } 3209 3210 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 3211 frame_type, pipe_id); 3212 } 3213 3214 int atomisp_css_capture_get_output_frame_info( 3215 struct atomisp_sub_device *asd, 3216 struct ia_css_frame_info *info) 3217 { 3218 enum ia_css_pipe_id pipe_id; 3219 3220 if (ATOMISP_USE_YUVPP(asd)) 3221 pipe_id = IA_CSS_PIPE_ID_YUVPP; 3222 else 3223 pipe_id = IA_CSS_PIPE_ID_CAPTURE; 3224 3225 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 3226 ATOMISP_CSS_OUTPUT_FRAME, pipe_id); 3227 } 3228 3229 int atomisp_css_video_get_output_frame_info( 3230 struct atomisp_sub_device *asd, 3231 struct ia_css_frame_info *info) 3232 { 3233 enum ia_css_pipe_id pipe_id; 3234 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME; 3235 3236 if (ATOMISP_USE_YUVPP(asd)) { 3237 pipe_id = IA_CSS_PIPE_ID_YUVPP; 3238 if (asd->continuous_mode->val) 3239 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME; 3240 } else { 3241 pipe_id = IA_CSS_PIPE_ID_VIDEO; 3242 } 3243 3244 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info, 3245 frame_type, pipe_id); 3246 } 3247 3248 int atomisp_css_preview_configure_pp_input( 3249 struct atomisp_sub_device *asd, 3250 unsigned int width, unsigned int height) 3251 { 3252 struct atomisp_stream_env *stream_env = 3253 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 3254 __configure_preview_pp_input(asd, width, height, 3255 ATOMISP_USE_YUVPP(asd) ? 3256 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW); 3257 3258 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]. 3259 capt_pp_in_res.width) 3260 __configure_capture_pp_input(asd, width, height, 3261 ATOMISP_USE_YUVPP(asd) ? 3262 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE); 3263 return 0; 3264 } 3265 3266 int atomisp_css_capture_configure_pp_input( 3267 struct atomisp_sub_device *asd, 3268 unsigned int width, unsigned int height) 3269 { 3270 __configure_capture_pp_input(asd, width, height, 3271 ATOMISP_USE_YUVPP(asd) ? 3272 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE); 3273 return 0; 3274 } 3275 3276 int atomisp_css_video_configure_pp_input( 3277 struct atomisp_sub_device *asd, 3278 unsigned int width, unsigned int height) 3279 { 3280 struct atomisp_stream_env *stream_env = 3281 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 3282 3283 __configure_video_pp_input(asd, width, height, 3284 ATOMISP_USE_YUVPP(asd) ? 3285 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO); 3286 3287 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]. 3288 capt_pp_in_res.width) 3289 __configure_capture_pp_input(asd, width, height, 3290 ATOMISP_USE_YUVPP(asd) ? 3291 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE); 3292 return 0; 3293 } 3294 3295 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd, 3296 int num_captures, unsigned int skip, int offset) 3297 { 3298 enum ia_css_err ret; 3299 3300 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n", 3301 __func__, num_captures, skip, offset); 3302 3303 ret = ia_css_stream_capture( 3304 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3305 num_captures, skip, offset); 3306 if (ret != IA_CSS_SUCCESS) 3307 return -EINVAL; 3308 3309 return 0; 3310 } 3311 3312 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id) 3313 { 3314 enum ia_css_err ret; 3315 3316 ret = ia_css_stream_capture_frame( 3317 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3318 exp_id); 3319 if (ret == IA_CSS_ERR_QUEUE_IS_FULL) { 3320 /* capture cmd queue is full */ 3321 return -EBUSY; 3322 } else if (ret != IA_CSS_SUCCESS) { 3323 return -EIO; 3324 } 3325 3326 return 0; 3327 } 3328 3329 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id) 3330 { 3331 enum ia_css_err ret; 3332 3333 ret = ia_css_unlock_raw_frame( 3334 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3335 exp_id); 3336 if (ret == IA_CSS_ERR_QUEUE_IS_FULL) 3337 return -EAGAIN; 3338 else if (ret != IA_CSS_SUCCESS) 3339 return -EIO; 3340 3341 return 0; 3342 } 3343 3344 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd, 3345 bool enable) 3346 { 3347 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 3348 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE] 3349 .default_capture_config.enable_xnr = enable; 3350 asd->params.capture_config.enable_xnr = enable; 3351 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 3352 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true; 3353 3354 return 0; 3355 } 3356 3357 void atomisp_css_send_input_frame(struct atomisp_sub_device *asd, 3358 unsigned short *data, unsigned int width, 3359 unsigned int height) 3360 { 3361 ia_css_stream_send_input_frame( 3362 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3363 data, width, height); 3364 } 3365 3366 bool atomisp_css_isp_has_started(void) 3367 { 3368 return ia_css_isp_has_started(); 3369 } 3370 3371 void atomisp_css_request_flash(struct atomisp_sub_device *asd) 3372 { 3373 ia_css_stream_request_flash( 3374 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream); 3375 } 3376 3377 void atomisp_css_set_wb_config(struct atomisp_sub_device *asd, 3378 struct ia_css_wb_config *wb_config) 3379 { 3380 asd->params.config.wb_config = wb_config; 3381 } 3382 3383 void atomisp_css_set_ob_config(struct atomisp_sub_device *asd, 3384 struct ia_css_ob_config *ob_config) 3385 { 3386 asd->params.config.ob_config = ob_config; 3387 } 3388 3389 void atomisp_css_set_dp_config(struct atomisp_sub_device *asd, 3390 struct ia_css_dp_config *dp_config) 3391 { 3392 asd->params.config.dp_config = dp_config; 3393 } 3394 3395 void atomisp_css_set_de_config(struct atomisp_sub_device *asd, 3396 struct ia_css_de_config *de_config) 3397 { 3398 asd->params.config.de_config = de_config; 3399 } 3400 3401 void atomisp_css_set_dz_config(struct atomisp_sub_device *asd, 3402 struct ia_css_dz_config *dz_config) 3403 { 3404 asd->params.config.dz_config = dz_config; 3405 } 3406 3407 void atomisp_css_set_default_de_config(struct atomisp_sub_device *asd) 3408 { 3409 asd->params.config.de_config = NULL; 3410 } 3411 3412 void atomisp_css_set_ce_config(struct atomisp_sub_device *asd, 3413 struct ia_css_ce_config *ce_config) 3414 { 3415 asd->params.config.ce_config = ce_config; 3416 } 3417 3418 void atomisp_css_set_nr_config(struct atomisp_sub_device *asd, 3419 struct ia_css_nr_config *nr_config) 3420 { 3421 asd->params.config.nr_config = nr_config; 3422 } 3423 3424 void atomisp_css_set_ee_config(struct atomisp_sub_device *asd, 3425 struct ia_css_ee_config *ee_config) 3426 { 3427 asd->params.config.ee_config = ee_config; 3428 } 3429 3430 void atomisp_css_set_tnr_config(struct atomisp_sub_device *asd, 3431 struct ia_css_tnr_config *tnr_config) 3432 { 3433 asd->params.config.tnr_config = tnr_config; 3434 } 3435 3436 void atomisp_css_set_cc_config(struct atomisp_sub_device *asd, 3437 struct ia_css_cc_config *cc_config) 3438 { 3439 asd->params.config.cc_config = cc_config; 3440 } 3441 3442 void atomisp_css_set_macc_table(struct atomisp_sub_device *asd, 3443 struct ia_css_macc_table *macc_table) 3444 { 3445 asd->params.config.macc_table = macc_table; 3446 } 3447 3448 void atomisp_css_set_macc_config(struct atomisp_sub_device *asd, 3449 struct ia_css_macc_config *macc_config) 3450 { 3451 asd->params.config.macc_config = macc_config; 3452 } 3453 3454 void atomisp_css_set_ecd_config(struct atomisp_sub_device *asd, 3455 struct ia_css_ecd_config *ecd_config) 3456 { 3457 asd->params.config.ecd_config = ecd_config; 3458 } 3459 3460 void atomisp_css_set_ynr_config(struct atomisp_sub_device *asd, 3461 struct ia_css_ynr_config *ynr_config) 3462 { 3463 asd->params.config.ynr_config = ynr_config; 3464 } 3465 3466 void atomisp_css_set_fc_config(struct atomisp_sub_device *asd, 3467 struct ia_css_fc_config *fc_config) 3468 { 3469 asd->params.config.fc_config = fc_config; 3470 } 3471 3472 void atomisp_css_set_ctc_config(struct atomisp_sub_device *asd, 3473 struct ia_css_ctc_config *ctc_config) 3474 { 3475 asd->params.config.ctc_config = ctc_config; 3476 } 3477 3478 void atomisp_css_set_cnr_config(struct atomisp_sub_device *asd, 3479 struct ia_css_cnr_config *cnr_config) 3480 { 3481 asd->params.config.cnr_config = cnr_config; 3482 } 3483 3484 void atomisp_css_set_aa_config(struct atomisp_sub_device *asd, 3485 struct ia_css_aa_config *aa_config) 3486 { 3487 asd->params.config.aa_config = aa_config; 3488 } 3489 3490 void atomisp_css_set_baa_config(struct atomisp_sub_device *asd, 3491 struct ia_css_aa_config *baa_config) 3492 { 3493 asd->params.config.baa_config = baa_config; 3494 } 3495 3496 void atomisp_css_set_anr_config(struct atomisp_sub_device *asd, 3497 struct ia_css_anr_config *anr_config) 3498 { 3499 asd->params.config.anr_config = anr_config; 3500 } 3501 3502 void atomisp_css_set_xnr_config(struct atomisp_sub_device *asd, 3503 struct ia_css_xnr_config *xnr_config) 3504 { 3505 asd->params.config.xnr_config = xnr_config; 3506 } 3507 3508 void atomisp_css_set_yuv2rgb_cc_config(struct atomisp_sub_device *asd, 3509 struct ia_css_cc_config *yuv2rgb_cc_config) 3510 { 3511 asd->params.config.yuv2rgb_cc_config = yuv2rgb_cc_config; 3512 } 3513 3514 void atomisp_css_set_rgb2yuv_cc_config(struct atomisp_sub_device *asd, 3515 struct ia_css_cc_config *rgb2yuv_cc_config) 3516 { 3517 asd->params.config.rgb2yuv_cc_config = rgb2yuv_cc_config; 3518 } 3519 3520 void atomisp_css_set_xnr_table(struct atomisp_sub_device *asd, 3521 struct ia_css_xnr_table *xnr_table) 3522 { 3523 asd->params.config.xnr_table = xnr_table; 3524 } 3525 3526 void atomisp_css_set_r_gamma_table(struct atomisp_sub_device *asd, 3527 struct ia_css_rgb_gamma_table *r_gamma_table) 3528 { 3529 asd->params.config.r_gamma_table = r_gamma_table; 3530 } 3531 3532 void atomisp_css_set_g_gamma_table(struct atomisp_sub_device *asd, 3533 struct ia_css_rgb_gamma_table *g_gamma_table) 3534 { 3535 asd->params.config.g_gamma_table = g_gamma_table; 3536 } 3537 3538 void atomisp_css_set_b_gamma_table(struct atomisp_sub_device *asd, 3539 struct ia_css_rgb_gamma_table *b_gamma_table) 3540 { 3541 asd->params.config.b_gamma_table = b_gamma_table; 3542 } 3543 3544 void atomisp_css_set_gamma_table(struct atomisp_sub_device *asd, 3545 struct ia_css_gamma_table *gamma_table) 3546 { 3547 asd->params.config.gamma_table = gamma_table; 3548 } 3549 3550 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd, 3551 struct ia_css_ctc_table *ctc_table) 3552 { 3553 int i; 3554 u16 *vamem_ptr = ctc_table->data.vamem_1; 3555 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE; 3556 bool valid = false; 3557 3558 /* workaround: if ctc_table is all 0, do not apply it */ 3559 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) { 3560 vamem_ptr = ctc_table->data.vamem_2; 3561 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE; 3562 } 3563 3564 for (i = 0; i < data_size; i++) { 3565 if (*(vamem_ptr + i)) { 3566 valid = true; 3567 break; 3568 } 3569 } 3570 3571 if (valid) 3572 asd->params.config.ctc_table = ctc_table; 3573 else 3574 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n"); 3575 } 3576 3577 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd, 3578 struct ia_css_anr_thres *anr_thres) 3579 { 3580 asd->params.config.anr_thres = anr_thres; 3581 } 3582 3583 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd, 3584 struct ia_css_dvs_6axis_config *dvs_6axis) 3585 { 3586 asd->params.config.dvs_6axis_config = dvs_6axis; 3587 } 3588 3589 void atomisp_css_set_gc_config(struct atomisp_sub_device *asd, 3590 struct ia_css_gc_config *gc_config) 3591 { 3592 asd->params.config.gc_config = gc_config; 3593 } 3594 3595 void atomisp_css_set_3a_config(struct atomisp_sub_device *asd, 3596 struct ia_css_3a_config *s3a_config) 3597 { 3598 asd->params.config.s3a_config = s3a_config; 3599 } 3600 3601 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd, 3602 struct atomisp_dis_vector *vector) 3603 { 3604 if (!asd->params.config.motion_vector) 3605 asd->params.config.motion_vector = &asd->params.css_param.motion_vector; 3606 3607 memset(asd->params.config.motion_vector, 3608 0, sizeof(struct ia_css_vector)); 3609 asd->params.css_param.motion_vector.x = vector->x; 3610 asd->params.css_param.motion_vector.y = vector->y; 3611 } 3612 3613 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd, 3614 struct atomisp_dvs_grid_info *atomgrid) 3615 { 3616 struct ia_css_dvs_grid_info *cur = 3617 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 3618 3619 if (!cur) { 3620 dev_err(asd->isp->dev, "dvs grid not available!\n"); 3621 return -EINVAL; 3622 } 3623 3624 if (sizeof(*cur) != sizeof(*atomgrid)) { 3625 dev_err(asd->isp->dev, "dvs grid mis-match!\n"); 3626 return -EINVAL; 3627 } 3628 3629 if (!cur->enable) { 3630 dev_err(asd->isp->dev, "dvs not enabled!\n"); 3631 return -EINVAL; 3632 } 3633 3634 return memcmp(atomgrid, cur, sizeof(*cur)); 3635 } 3636 3637 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd, 3638 struct ia_css_dvs2_coefficients *coefs) 3639 { 3640 asd->params.config.dvs2_coefs = coefs; 3641 } 3642 3643 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd, 3644 struct atomisp_dis_coefficients *coefs) 3645 { 3646 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0) 3647 /* If the grid info in the argument differs from the current 3648 grid info, we tell the caller to reset the grid size and 3649 try again. */ 3650 return -EAGAIN; 3651 3652 if (!coefs->hor_coefs.odd_real || 3653 !coefs->hor_coefs.odd_imag || 3654 !coefs->hor_coefs.even_real || 3655 !coefs->hor_coefs.even_imag || 3656 !coefs->ver_coefs.odd_real || 3657 !coefs->ver_coefs.odd_imag || 3658 !coefs->ver_coefs.even_real || 3659 !coefs->ver_coefs.even_imag || 3660 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real || 3661 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag || 3662 !asd->params.css_param.dvs2_coeff->hor_coefs.even_real || 3663 !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag || 3664 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real || 3665 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag || 3666 !asd->params.css_param.dvs2_coeff->ver_coefs.even_real || 3667 !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag) 3668 return -EINVAL; 3669 3670 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real, 3671 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes)) 3672 return -EFAULT; 3673 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag, 3674 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes)) 3675 return -EFAULT; 3676 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real, 3677 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes)) 3678 return -EFAULT; 3679 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag, 3680 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes)) 3681 return -EFAULT; 3682 3683 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real, 3684 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes)) 3685 return -EFAULT; 3686 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag, 3687 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes)) 3688 return -EFAULT; 3689 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real, 3690 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes)) 3691 return -EFAULT; 3692 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag, 3693 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes)) 3694 return -EFAULT; 3695 3696 asd->params.css_param.update_flag.dvs2_coefs = 3697 (struct atomisp_dvs2_coefficients *) 3698 asd->params.css_param.dvs2_coeff; 3699 /* FIXME! */ 3700 /* asd->params.dis_proj_data_valid = false; */ 3701 asd->params.css_update_params_needed = true; 3702 3703 return 0; 3704 } 3705 3706 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd, 3707 unsigned int zoom) 3708 { 3709 struct atomisp_device *isp = asd->isp; 3710 3711 if (zoom == asd->params.css_param.dz_config.dx && 3712 zoom == asd->params.css_param.dz_config.dy) { 3713 dev_dbg(isp->dev, "same zoom scale. skipped.\n"); 3714 return; 3715 } 3716 3717 memset(&asd->params.css_param.dz_config, 0, 3718 sizeof(struct ia_css_dz_config)); 3719 asd->params.css_param.dz_config.dx = zoom; 3720 asd->params.css_param.dz_config.dy = zoom; 3721 3722 asd->params.css_param.update_flag.dz_config = 3723 (struct atomisp_dz_config *)&asd->params.css_param.dz_config; 3724 asd->params.css_update_params_needed = true; 3725 } 3726 3727 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd, 3728 struct ia_css_formats_config *formats_config) 3729 { 3730 asd->params.config.formats_config = formats_config; 3731 } 3732 3733 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd, 3734 struct atomisp_wb_config *config) 3735 { 3736 struct ia_css_wb_config wb_config; 3737 struct ia_css_isp_config isp_config; 3738 struct atomisp_device *isp = asd->isp; 3739 3740 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3741 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3742 __func__); 3743 return -EINVAL; 3744 } 3745 memset(&wb_config, 0, sizeof(struct ia_css_wb_config)); 3746 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3747 isp_config.wb_config = &wb_config; 3748 ia_css_stream_get_isp_config( 3749 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3750 &isp_config); 3751 memcpy(config, &wb_config, sizeof(*config)); 3752 3753 return 0; 3754 } 3755 3756 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd, 3757 struct atomisp_ob_config *config) 3758 { 3759 struct ia_css_ob_config ob_config; 3760 struct ia_css_isp_config isp_config; 3761 struct atomisp_device *isp = asd->isp; 3762 3763 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3764 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3765 __func__); 3766 return -EINVAL; 3767 } 3768 memset(&ob_config, 0, sizeof(struct ia_css_ob_config)); 3769 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3770 isp_config.ob_config = &ob_config; 3771 ia_css_stream_get_isp_config( 3772 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3773 &isp_config); 3774 memcpy(config, &ob_config, sizeof(*config)); 3775 3776 return 0; 3777 } 3778 3779 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd, 3780 struct atomisp_dp_config *config) 3781 { 3782 struct ia_css_dp_config dp_config; 3783 struct ia_css_isp_config isp_config; 3784 struct atomisp_device *isp = asd->isp; 3785 3786 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3787 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3788 __func__); 3789 return -EINVAL; 3790 } 3791 memset(&dp_config, 0, sizeof(struct ia_css_dp_config)); 3792 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3793 isp_config.dp_config = &dp_config; 3794 ia_css_stream_get_isp_config( 3795 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3796 &isp_config); 3797 memcpy(config, &dp_config, sizeof(*config)); 3798 3799 return 0; 3800 } 3801 3802 int atomisp_css_get_de_config(struct atomisp_sub_device *asd, 3803 struct atomisp_de_config *config) 3804 { 3805 struct ia_css_de_config de_config; 3806 struct ia_css_isp_config isp_config; 3807 struct atomisp_device *isp = asd->isp; 3808 3809 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3810 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3811 __func__); 3812 return -EINVAL; 3813 } 3814 memset(&de_config, 0, sizeof(struct ia_css_de_config)); 3815 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3816 isp_config.de_config = &de_config; 3817 ia_css_stream_get_isp_config( 3818 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3819 &isp_config); 3820 memcpy(config, &de_config, sizeof(*config)); 3821 3822 return 0; 3823 } 3824 3825 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd, 3826 struct atomisp_nr_config *config) 3827 { 3828 struct ia_css_nr_config nr_config; 3829 struct ia_css_isp_config isp_config; 3830 struct atomisp_device *isp = asd->isp; 3831 3832 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3833 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3834 __func__); 3835 return -EINVAL; 3836 } 3837 memset(&nr_config, 0, sizeof(struct ia_css_nr_config)); 3838 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3839 3840 isp_config.nr_config = &nr_config; 3841 ia_css_stream_get_isp_config( 3842 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3843 &isp_config); 3844 memcpy(config, &nr_config, sizeof(*config)); 3845 3846 return 0; 3847 } 3848 3849 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd, 3850 struct atomisp_ee_config *config) 3851 { 3852 struct ia_css_ee_config ee_config; 3853 struct ia_css_isp_config isp_config; 3854 struct atomisp_device *isp = asd->isp; 3855 3856 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3857 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3858 __func__); 3859 return -EINVAL; 3860 } 3861 memset(&ee_config, 0, sizeof(struct ia_css_ee_config)); 3862 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3863 isp_config.ee_config = &ee_config; 3864 ia_css_stream_get_isp_config( 3865 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3866 &isp_config); 3867 memcpy(config, &ee_config, sizeof(*config)); 3868 3869 return 0; 3870 } 3871 3872 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd, 3873 struct atomisp_tnr_config *config) 3874 { 3875 struct ia_css_tnr_config tnr_config; 3876 struct ia_css_isp_config isp_config; 3877 struct atomisp_device *isp = asd->isp; 3878 3879 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3880 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3881 __func__); 3882 return -EINVAL; 3883 } 3884 memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config)); 3885 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3886 isp_config.tnr_config = &tnr_config; 3887 ia_css_stream_get_isp_config( 3888 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3889 &isp_config); 3890 memcpy(config, &tnr_config, sizeof(*config)); 3891 3892 return 0; 3893 } 3894 3895 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd, 3896 struct atomisp_ctc_table *config) 3897 { 3898 struct ia_css_ctc_table *tab; 3899 struct ia_css_isp_config isp_config; 3900 struct atomisp_device *isp = asd->isp; 3901 3902 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3903 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3904 __func__); 3905 return -EINVAL; 3906 } 3907 3908 tab = vzalloc(sizeof(struct ia_css_ctc_table)); 3909 if (!tab) 3910 return -ENOMEM; 3911 3912 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3913 isp_config.ctc_table = tab; 3914 ia_css_stream_get_isp_config( 3915 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3916 &isp_config); 3917 memcpy(config, tab, sizeof(*tab)); 3918 vfree(tab); 3919 3920 return 0; 3921 } 3922 3923 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd, 3924 struct atomisp_gamma_table *config) 3925 { 3926 struct ia_css_gamma_table *tab; 3927 struct ia_css_isp_config isp_config; 3928 struct atomisp_device *isp = asd->isp; 3929 3930 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3931 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3932 __func__); 3933 return -EINVAL; 3934 } 3935 3936 tab = vzalloc(sizeof(struct ia_css_gamma_table)); 3937 if (!tab) 3938 return -ENOMEM; 3939 3940 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3941 isp_config.gamma_table = tab; 3942 ia_css_stream_get_isp_config( 3943 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3944 &isp_config); 3945 memcpy(config, tab, sizeof(*tab)); 3946 vfree(tab); 3947 3948 return 0; 3949 } 3950 3951 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd, 3952 struct atomisp_gc_config *config) 3953 { 3954 struct ia_css_gc_config gc_config; 3955 struct ia_css_isp_config isp_config; 3956 struct atomisp_device *isp = asd->isp; 3957 3958 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3959 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3960 __func__); 3961 return -EINVAL; 3962 } 3963 memset(&gc_config, 0, sizeof(struct ia_css_gc_config)); 3964 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3965 isp_config.gc_config = &gc_config; 3966 ia_css_stream_get_isp_config( 3967 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3968 &isp_config); 3969 /* Get gamma correction params from current setup */ 3970 memcpy(config, &gc_config, sizeof(*config)); 3971 3972 return 0; 3973 } 3974 3975 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd, 3976 struct atomisp_3a_config *config) 3977 { 3978 struct ia_css_3a_config s3a_config; 3979 struct ia_css_isp_config isp_config; 3980 struct atomisp_device *isp = asd->isp; 3981 3982 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3983 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 3984 __func__); 3985 return -EINVAL; 3986 } 3987 memset(&s3a_config, 0, sizeof(struct ia_css_3a_config)); 3988 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 3989 isp_config.s3a_config = &s3a_config; 3990 ia_css_stream_get_isp_config( 3991 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3992 &isp_config); 3993 /* Get white balance from current setup */ 3994 memcpy(config, &s3a_config, sizeof(*config)); 3995 3996 return 0; 3997 } 3998 3999 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd, 4000 struct atomisp_formats_config *config) 4001 { 4002 struct ia_css_formats_config formats_config; 4003 struct ia_css_isp_config isp_config; 4004 struct atomisp_device *isp = asd->isp; 4005 4006 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 4007 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 4008 __func__); 4009 return -EINVAL; 4010 } 4011 memset(&formats_config, 0, sizeof(formats_config)); 4012 memset(&isp_config, 0, sizeof(isp_config)); 4013 isp_config.formats_config = &formats_config; 4014 ia_css_stream_get_isp_config( 4015 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 4016 &isp_config); 4017 /* Get narrow gamma from current setup */ 4018 memcpy(config, &formats_config, sizeof(*config)); 4019 4020 return 0; 4021 } 4022 4023 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd, 4024 unsigned int *zoom) 4025 { 4026 struct ia_css_dz_config dz_config; /** Digital Zoom */ 4027 struct ia_css_isp_config isp_config; 4028 struct atomisp_device *isp = asd->isp; 4029 4030 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 4031 dev_err(isp->dev, "%s called after streamoff, skipping.\n", 4032 __func__); 4033 return -EINVAL; 4034 } 4035 memset(&dz_config, 0, sizeof(struct ia_css_dz_config)); 4036 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 4037 isp_config.dz_config = &dz_config; 4038 ia_css_stream_get_isp_config( 4039 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 4040 &isp_config); 4041 *zoom = dz_config.dx; 4042 4043 return 0; 4044 } 4045 4046 /* 4047 * Function to set/get image stablization statistics 4048 */ 4049 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd, 4050 struct atomisp_dis_statistics *stats) 4051 { 4052 struct atomisp_device *isp = asd->isp; 4053 struct atomisp_dis_buf *dis_buf; 4054 unsigned long flags; 4055 4056 if (!asd->params.dvs_stat->hor_prod.odd_real || 4057 !asd->params.dvs_stat->hor_prod.odd_imag || 4058 !asd->params.dvs_stat->hor_prod.even_real || 4059 !asd->params.dvs_stat->hor_prod.even_imag || 4060 !asd->params.dvs_stat->ver_prod.odd_real || 4061 !asd->params.dvs_stat->ver_prod.odd_imag || 4062 !asd->params.dvs_stat->ver_prod.even_real || 4063 !asd->params.dvs_stat->ver_prod.even_imag) 4064 return -EINVAL; 4065 4066 /* isp needs to be streaming to get DIS statistics */ 4067 spin_lock_irqsave(&isp->lock, flags); 4068 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) { 4069 spin_unlock_irqrestore(&isp->lock, flags); 4070 return -EINVAL; 4071 } 4072 spin_unlock_irqrestore(&isp->lock, flags); 4073 4074 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0) 4075 /* If the grid info in the argument differs from the current 4076 grid info, we tell the caller to reset the grid size and 4077 try again. */ 4078 return -EAGAIN; 4079 4080 spin_lock_irqsave(&asd->dis_stats_lock, flags); 4081 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) { 4082 spin_unlock_irqrestore(&asd->dis_stats_lock, flags); 4083 dev_err(isp->dev, "dis statistics is not valid.\n"); 4084 return -EAGAIN; 4085 } 4086 4087 dis_buf = list_entry(asd->dis_stats.next, 4088 struct atomisp_dis_buf, list); 4089 list_del_init(&dis_buf->list); 4090 spin_unlock_irqrestore(&asd->dis_stats_lock, flags); 4091 4092 if (dis_buf->dvs_map) 4093 ia_css_translate_dvs2_statistics( 4094 asd->params.dvs_stat, dis_buf->dvs_map); 4095 else 4096 ia_css_get_dvs2_statistics(asd->params.dvs_stat, 4097 dis_buf->dis_data); 4098 stats->exp_id = dis_buf->dis_data->exp_id; 4099 4100 spin_lock_irqsave(&asd->dis_stats_lock, flags); 4101 list_add_tail(&dis_buf->list, &asd->dis_stats); 4102 spin_unlock_irqrestore(&asd->dis_stats_lock, flags); 4103 4104 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real, 4105 asd->params.dvs_stat->ver_prod.odd_real, 4106 asd->params.dvs_ver_proj_bytes)) 4107 return -EFAULT; 4108 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag, 4109 asd->params.dvs_stat->ver_prod.odd_imag, 4110 asd->params.dvs_ver_proj_bytes)) 4111 return -EFAULT; 4112 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real, 4113 asd->params.dvs_stat->ver_prod.even_real, 4114 asd->params.dvs_ver_proj_bytes)) 4115 return -EFAULT; 4116 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag, 4117 asd->params.dvs_stat->ver_prod.even_imag, 4118 asd->params.dvs_ver_proj_bytes)) 4119 return -EFAULT; 4120 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real, 4121 asd->params.dvs_stat->hor_prod.odd_real, 4122 asd->params.dvs_hor_proj_bytes)) 4123 return -EFAULT; 4124 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag, 4125 asd->params.dvs_stat->hor_prod.odd_imag, 4126 asd->params.dvs_hor_proj_bytes)) 4127 return -EFAULT; 4128 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real, 4129 asd->params.dvs_stat->hor_prod.even_real, 4130 asd->params.dvs_hor_proj_bytes)) 4131 return -EFAULT; 4132 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag, 4133 asd->params.dvs_stat->hor_prod.even_imag, 4134 asd->params.dvs_hor_proj_bytes)) 4135 return -EFAULT; 4136 4137 return 0; 4138 } 4139 4140 struct ia_css_shading_table *atomisp_css_shading_table_alloc( 4141 unsigned int width, unsigned int height) 4142 { 4143 return ia_css_shading_table_alloc(width, height); 4144 } 4145 4146 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd, 4147 struct ia_css_shading_table *table) 4148 { 4149 asd->params.config.shading_table = table; 4150 } 4151 4152 void atomisp_css_shading_table_free(struct ia_css_shading_table *table) 4153 { 4154 ia_css_shading_table_free(table); 4155 } 4156 4157 struct ia_css_morph_table *atomisp_css_morph_table_allocate( 4158 unsigned int width, unsigned int height) 4159 { 4160 return ia_css_morph_table_allocate(width, height); 4161 } 4162 4163 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd, 4164 struct ia_css_morph_table *table) 4165 { 4166 asd->params.config.morph_table = table; 4167 } 4168 4169 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd, 4170 struct ia_css_morph_table *table) 4171 { 4172 struct ia_css_isp_config isp_config; 4173 struct atomisp_device *isp = asd->isp; 4174 4175 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 4176 dev_err(isp->dev, 4177 "%s called after streamoff, skipping.\n", __func__); 4178 return; 4179 } 4180 memset(table, 0, sizeof(struct ia_css_morph_table)); 4181 memset(&isp_config, 0, sizeof(struct ia_css_isp_config)); 4182 isp_config.morph_table = table; 4183 ia_css_stream_get_isp_config( 4184 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 4185 &isp_config); 4186 } 4187 4188 void atomisp_css_morph_table_free(struct ia_css_morph_table *table) 4189 { 4190 ia_css_morph_table_free(table); 4191 } 4192 4193 void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp, 4194 unsigned int overlap) 4195 { 4196 /* CSS 2.0 doesn't support this API. */ 4197 dev_dbg(isp->dev, "set cont prev start time is not supported.\n"); 4198 return; 4199 } 4200 4201 void atomisp_css_acc_done(struct atomisp_sub_device *asd) 4202 { 4203 complete(&asd->acc.acc_done); 4204 } 4205 4206 int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd) 4207 { 4208 int ret = 0; 4209 struct atomisp_device *isp = asd->isp; 4210 4211 /* Unlock the isp mutex taken in IOCTL handler before sleeping! */ 4212 rt_mutex_unlock(&isp->mutex); 4213 if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done, 4214 ATOMISP_ISP_TIMEOUT_DURATION) == 0) { 4215 dev_err(isp->dev, "<%s: completion timeout\n", __func__); 4216 atomisp_css_debug_dump_sp_sw_debug_info(); 4217 atomisp_css_debug_dump_debug_info(__func__); 4218 ret = -EIO; 4219 } 4220 rt_mutex_lock(&isp->mutex); 4221 4222 return ret; 4223 } 4224 4225 /* Set the ACC binary arguments */ 4226 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw) 4227 { 4228 unsigned int mem; 4229 4230 for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) { 4231 if (acc_fw->args[mem].length == 0) 4232 continue; 4233 4234 ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers, 4235 IA_CSS_PARAM_CLASS_PARAM, mem, 4236 acc_fw->args[mem].css_ptr, 4237 acc_fw->args[mem].length); 4238 } 4239 4240 return 0; 4241 } 4242 4243 /* Load acc binary extension */ 4244 int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd, 4245 struct ia_css_fw_info *fw, 4246 enum ia_css_pipe_id pipe_id, 4247 unsigned int type) 4248 { 4249 struct ia_css_fw_info **hd; 4250 4251 fw->next = NULL; 4252 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 4253 .pipe_configs[pipe_id].acc_extension); 4254 while (*hd) 4255 hd = &(*hd)->next; 4256 *hd = fw; 4257 4258 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 4259 .update_pipe[pipe_id] = true; 4260 return 0; 4261 } 4262 4263 /* Unload acc binary extension */ 4264 void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd, 4265 struct ia_css_fw_info *fw, 4266 enum ia_css_pipe_id pipe_id) 4267 { 4268 struct ia_css_fw_info **hd; 4269 4270 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 4271 .pipe_configs[pipe_id].acc_extension); 4272 while (*hd && *hd != fw) 4273 hd = &(*hd)->next; 4274 if (!*hd) { 4275 dev_err(asd->isp->dev, "did not find acc fw for removal\n"); 4276 return; 4277 } 4278 *hd = fw->next; 4279 fw->next = NULL; 4280 4281 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 4282 .update_pipe[pipe_id] = true; 4283 } 4284 4285 int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd) 4286 { 4287 struct atomisp_device *isp = asd->isp; 4288 struct ia_css_pipe_config *pipe_config; 4289 struct atomisp_stream_env *stream_env = 4290 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 4291 4292 if (stream_env->acc_stream) { 4293 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) { 4294 if (ia_css_stream_stop(stream_env->acc_stream) 4295 != IA_CSS_SUCCESS) { 4296 dev_err(isp->dev, "stop acc_stream failed.\n"); 4297 return -EBUSY; 4298 } 4299 } 4300 4301 if (ia_css_stream_destroy(stream_env->acc_stream) 4302 != IA_CSS_SUCCESS) { 4303 dev_err(isp->dev, "destroy acc_stream failed.\n"); 4304 return -EBUSY; 4305 } 4306 stream_env->acc_stream = NULL; 4307 } 4308 4309 pipe_config = &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]; 4310 ia_css_pipe_config_defaults(pipe_config); 4311 asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES * 4312 sizeof(void *), GFP_KERNEL); 4313 if (!asd->acc.acc_stages) 4314 return -ENOMEM; 4315 pipe_config->acc_stages = asd->acc.acc_stages; 4316 pipe_config->mode = IA_CSS_PIPE_MODE_ACC; 4317 pipe_config->num_acc_stages = 0; 4318 4319 /* 4320 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe, 4321 * because pipe configuration will soon be changed by 4322 * atomisp_css_load_acc_binary() 4323 */ 4324 return 0; 4325 } 4326 4327 int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd) 4328 { 4329 struct atomisp_device *isp = asd->isp; 4330 struct atomisp_stream_env *stream_env = 4331 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 4332 struct ia_css_pipe_config *pipe_config = 4333 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]; 4334 4335 if (ia_css_pipe_create(pipe_config, 4336 &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != IA_CSS_SUCCESS) { 4337 dev_err(isp->dev, "%s: ia_css_pipe_create failed\n", 4338 __func__); 4339 return -EBADE; 4340 } 4341 4342 memset(&stream_env->acc_stream_config, 0, 4343 sizeof(struct ia_css_stream_config)); 4344 if (ia_css_stream_create(&stream_env->acc_stream_config, 1, 4345 &stream_env->pipes[IA_CSS_PIPE_ID_ACC], 4346 &stream_env->acc_stream) != IA_CSS_SUCCESS) { 4347 dev_err(isp->dev, "%s: create acc_stream error.\n", __func__); 4348 return -EINVAL; 4349 } 4350 stream_env->acc_stream_state = CSS_STREAM_CREATED; 4351 4352 init_completion(&asd->acc.acc_done); 4353 asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC]; 4354 4355 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false); 4356 4357 if (ia_css_start_sp() != IA_CSS_SUCCESS) { 4358 dev_err(isp->dev, "start sp error.\n"); 4359 return -EIO; 4360 } 4361 4362 if (ia_css_stream_start(stream_env->acc_stream) 4363 != IA_CSS_SUCCESS) { 4364 dev_err(isp->dev, "acc_stream start error.\n"); 4365 return -EIO; 4366 } 4367 4368 stream_env->acc_stream_state = CSS_STREAM_STARTED; 4369 return 0; 4370 } 4371 4372 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd) 4373 { 4374 struct atomisp_stream_env *stream_env = 4375 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 4376 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) { 4377 ia_css_stream_stop(stream_env->acc_stream); 4378 stream_env->acc_stream_state = CSS_STREAM_STOPPED; 4379 } 4380 return 0; 4381 } 4382 4383 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd) 4384 { 4385 struct atomisp_stream_env *stream_env = 4386 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 4387 if (stream_env->acc_stream) { 4388 if (ia_css_stream_destroy(stream_env->acc_stream) 4389 != IA_CSS_SUCCESS) 4390 dev_warn(asd->isp->dev, 4391 "destroy acc_stream failed.\n"); 4392 stream_env->acc_stream = NULL; 4393 } 4394 4395 if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) { 4396 if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC]) 4397 != IA_CSS_SUCCESS) 4398 dev_warn(asd->isp->dev, 4399 "destroy ACC pipe failed.\n"); 4400 stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL; 4401 stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false; 4402 ia_css_pipe_config_defaults( 4403 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]); 4404 ia_css_pipe_extra_config_defaults( 4405 &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]); 4406 } 4407 asd->acc.pipeline = NULL; 4408 4409 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after 4410 * destroy all pipes 4411 */ 4412 ia_css_stop_sp(); 4413 4414 kfree(asd->acc.acc_stages); 4415 asd->acc.acc_stages = NULL; 4416 4417 atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false); 4418 } 4419 4420 int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd, 4421 struct ia_css_fw_info *fw, 4422 unsigned int index) 4423 { 4424 struct ia_css_pipe_config *pipe_config = 4425 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 4426 .pipe_configs[IA_CSS_PIPE_ID_ACC]; 4427 4428 if (index >= MAX_ACC_STAGES) { 4429 dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n", 4430 __func__, index); 4431 return -ENOMEM; 4432 } 4433 4434 pipe_config->acc_stages[index] = fw; 4435 pipe_config->num_acc_stages = index + 1; 4436 pipe_config->acc_num_execs = 1; 4437 4438 return 0; 4439 } 4440 4441 static struct atomisp_sub_device *__get_atomisp_subdev( 4442 struct ia_css_pipe *css_pipe, 4443 struct atomisp_device *isp, 4444 enum atomisp_input_stream_id *stream_id) 4445 { 4446 int i, j, k; 4447 struct atomisp_sub_device *asd; 4448 struct atomisp_stream_env *stream_env; 4449 4450 for (i = 0; i < isp->num_of_streams; i++) { 4451 asd = &isp->asd[i]; 4452 if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED && 4453 !asd->acc.pipeline) 4454 continue; 4455 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) { 4456 stream_env = &asd->stream_env[j]; 4457 for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) { 4458 if (stream_env->pipes[k] && 4459 stream_env->pipes[k] == css_pipe) { 4460 *stream_id = j; 4461 return asd; 4462 } 4463 } 4464 } 4465 } 4466 4467 return NULL; 4468 } 4469 4470 int atomisp_css_isr_thread(struct atomisp_device *isp, 4471 bool *frame_done_found, 4472 bool *css_pipe_done) 4473 { 4474 enum atomisp_input_stream_id stream_id = 0; 4475 struct atomisp_css_event current_event; 4476 struct atomisp_sub_device *asd; 4477 bool reset_wdt_timer[MAX_STREAM_NUM] = {false}; 4478 int i; 4479 4480 while (!atomisp_css_dequeue_event(¤t_event)) { 4481 if (current_event.event.type == 4482 IA_CSS_EVENT_TYPE_FW_ASSERT) { 4483 /* 4484 * Received FW assertion signal, 4485 * trigger WDT to recover 4486 */ 4487 dev_err(isp->dev, 4488 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n", 4489 __func__, 4490 current_event.event.fw_assert_module_id, 4491 current_event.event.fw_assert_line_no); 4492 for (i = 0; i < isp->num_of_streams; i++) 4493 atomisp_wdt_stop(&isp->asd[i], 0); 4494 4495 if (!atomisp_hw_is_isp2401) 4496 atomisp_wdt(&isp->asd[0].wdt); 4497 else 4498 queue_work(isp->wdt_work_queue, &isp->wdt_work); 4499 4500 return -EINVAL; 4501 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) { 4502 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n", 4503 __func__, current_event.event.fw_warning, 4504 current_event.event.exp_id); 4505 continue; 4506 } 4507 4508 asd = __get_atomisp_subdev(current_event.event.pipe, 4509 isp, &stream_id); 4510 if (!asd) { 4511 if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER) 4512 dev_dbg(isp->dev, 4513 "event: Timer event."); 4514 else 4515 dev_warn(isp->dev, "%s:no subdev.event:%d", 4516 __func__, 4517 current_event.event.type); 4518 continue; 4519 } 4520 4521 atomisp_css_temp_pipe_to_pipe_id(asd, ¤t_event); 4522 switch (current_event.event.type) { 4523 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE: 4524 frame_done_found[asd->index] = true; 4525 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, 4526 current_event.pipe, true, stream_id); 4527 4528 if (!atomisp_hw_is_isp2401) 4529 reset_wdt_timer[asd->index] = true; /* ISP running */ 4530 4531 break; 4532 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE: 4533 frame_done_found[asd->index] = true; 4534 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME, 4535 current_event.pipe, true, stream_id); 4536 4537 if (!atomisp_hw_is_isp2401) 4538 reset_wdt_timer[asd->index] = true; /* ISP running */ 4539 4540 break; 4541 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE: 4542 atomisp_buf_done(asd, 0, 4543 IA_CSS_BUFFER_TYPE_3A_STATISTICS, 4544 current_event.pipe, 4545 false, stream_id); 4546 break; 4547 case IA_CSS_EVENT_TYPE_METADATA_DONE: 4548 atomisp_buf_done(asd, 0, 4549 IA_CSS_BUFFER_TYPE_METADATA, 4550 current_event.pipe, 4551 false, stream_id); 4552 break; 4553 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE: 4554 atomisp_buf_done(asd, 0, 4555 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, 4556 current_event.pipe, true, stream_id); 4557 4558 if (!atomisp_hw_is_isp2401) 4559 reset_wdt_timer[asd->index] = true; /* ISP running */ 4560 4561 break; 4562 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE: 4563 atomisp_buf_done(asd, 0, 4564 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME, 4565 current_event.pipe, true, stream_id); 4566 if (!atomisp_hw_is_isp2401) 4567 reset_wdt_timer[asd->index] = true; /* ISP running */ 4568 4569 break; 4570 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE: 4571 atomisp_buf_done(asd, 0, 4572 IA_CSS_BUFFER_TYPE_DIS_STATISTICS, 4573 current_event.pipe, 4574 false, stream_id); 4575 break; 4576 case IA_CSS_EVENT_TYPE_PIPELINE_DONE: 4577 css_pipe_done[asd->index] = true; 4578 break; 4579 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE: 4580 atomisp_acc_done(asd, current_event.event.fw_handle); 4581 break; 4582 default: 4583 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n", 4584 current_event.event.type); 4585 break; 4586 } 4587 } 4588 4589 if (atomisp_hw_is_isp2401) 4590 return 0; 4591 4592 /* ISP2400: If there are no buffers queued then delete wdt timer. */ 4593 for (i = 0; i < isp->num_of_streams; i++) { 4594 asd = &isp->asd[i]; 4595 if (!asd) 4596 continue; 4597 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 4598 continue; 4599 if (!atomisp_buffers_queued(asd)) 4600 atomisp_wdt_stop(asd, false); 4601 else if (reset_wdt_timer[i]) 4602 /* SOF irq should not reset wdt timer. */ 4603 atomisp_wdt_refresh(asd, 4604 ATOMISP_WDT_KEEP_CURRENT_DELAY); 4605 } 4606 4607 return 0; 4608 } 4609 4610 bool atomisp_css_valid_sof(struct atomisp_device *isp) 4611 { 4612 unsigned int i, j; 4613 4614 /* Loop for each css stream */ 4615 for (i = 0; i < isp->num_of_streams; i++) { 4616 struct atomisp_sub_device *asd = &isp->asd[i]; 4617 /* Loop for each css vc stream */ 4618 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) { 4619 if (asd->stream_env[j].stream && 4620 asd->stream_env[j].stream_config.mode == 4621 IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 4622 return false; 4623 } 4624 } 4625 4626 return true; 4627 } 4628 4629 int atomisp_css_debug_dump_isp_binary(void) 4630 { 4631 ia_css_debug_dump_isp_binary(); 4632 return 0; 4633 } 4634 4635 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced) 4636 { 4637 sh_css_dump_sp_raw_copy_linecount(reduced); 4638 return 0; 4639 } 4640 4641 int atomisp_css_dump_blob_infor(void) 4642 { 4643 struct ia_css_blob_descr *bd = sh_css_blob_info; 4644 unsigned int i, nm = sh_css_num_binaries; 4645 4646 if (nm == 0) 4647 return -EPERM; 4648 if (!bd) 4649 return -EPERM; 4650 4651 for (i = 1; i < sh_css_num_binaries; i++) 4652 dev_dbg(atomisp_dev, "Num%d binary id is %d, name is %s\n", i, 4653 bd[i - 1].header.info.isp.sp.id, bd[i - 1].name); 4654 4655 return 0; 4656 } 4657 4658 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd, 4659 uint32_t isp_config_id) 4660 { 4661 asd->params.config.isp_config_id = isp_config_id; 4662 } 4663 4664 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd, 4665 struct ia_css_frame *output_frame) 4666 { 4667 asd->params.config.output_frame = output_frame; 4668 } 4669 4670 int atomisp_get_css_dbgfunc(void) 4671 { 4672 return dbg_func; 4673 } 4674 4675 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt) 4676 { 4677 int ret; 4678 4679 ret = __set_css_print_env(isp, opt); 4680 if (ret == 0) 4681 dbg_func = opt; 4682 4683 return ret; 4684 } 4685 4686 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable) 4687 { 4688 ia_css_en_dz_capt_pipe( 4689 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 4690 enable); 4691 } 4692 4693 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info( 4694 struct ia_css_grid_info *grid_info) 4695 { 4696 if (!grid_info) 4697 return NULL; 4698 4699 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED 4700 return &grid_info->dvs_grid.dvs_grid_info; 4701 #else 4702 return &grid_info->dvs_grid; 4703 #endif 4704 } 4705