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