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