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