2 * Support for Clovertrail PNW Camera Imaging ISP subsystem.
4 * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 #include <media/videobuf-vmalloc.h>
23 #include <media/v4l2-dev.h>
24 #include <media/v4l2-event.h>
26 #include "mmu/isp_mmu.h"
27 #include "mmu/sh_mmu_mrfld.h"
28 #include "hmm/hmm_bo.h"
31 #include "atomisp_compat.h"
32 #include "atomisp_internal.h"
33 #include "atomisp_cmd.h"
34 #include "atomisp-regs.h"
35 #include "atomisp_fops.h"
36 #include "atomisp_ioctl.h"
37 #include "atomisp_acc.h"
39 #include "hrt/hive_isp_css_mm_hrt.h"
41 #include <asm/intel-mid.h>
43 #include "ia_css_debug.h"
44 #include "ia_css_isp_param.h"
45 #include "sh_css_hrt.h"
46 #include "ia_css_isys.h"
48 #include <linux/pm_runtime.h>
50 /* Assume max number of ACC stages */
51 #define MAX_ACC_STAGES 20
53 /* Ideally, this should come from CSS headers */
57 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
58 * #4684168, if concurrency access happened, system may hard hang.
60 static DEFINE_SPINLOCK(mmio_lock);
62 enum frame_info_type {
64 ATOMISP_CSS_SECOND_VF_FRAME,
65 ATOMISP_CSS_OUTPUT_FRAME,
66 ATOMISP_CSS_SECOND_OUTPUT_FRAME,
67 ATOMISP_CSS_RAW_FRAME,
70 struct bayer_ds_factor {
71 unsigned int numerator;
72 unsigned int denominator;
75 void atomisp_css_debug_dump_sp_sw_debug_info(void)
77 ia_css_debug_dump_sp_sw_debug_info();
80 void atomisp_css_debug_dump_debug_info(const char *context)
82 ia_css_debug_dump_debug_info(context);
85 void atomisp_css_debug_set_dtrace_level(const unsigned int trace_level)
87 ia_css_debug_set_dtrace_level(trace_level);
90 unsigned int atomisp_css_debug_get_dtrace_level(void)
92 return ia_css_debug_trace_level;
95 void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
99 spin_lock_irqsave(&mmio_lock, flags);
100 _hrt_master_port_store_8(addr, data);
101 spin_unlock_irqrestore(&mmio_lock, flags);
104 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
108 spin_lock_irqsave(&mmio_lock, flags);
109 _hrt_master_port_store_16(addr, data);
110 spin_unlock_irqrestore(&mmio_lock, flags);
113 static void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
117 spin_lock_irqsave(&mmio_lock, flags);
118 _hrt_master_port_store_32(addr, data);
119 spin_unlock_irqrestore(&mmio_lock, flags);
122 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
127 spin_lock_irqsave(&mmio_lock, flags);
128 ret = _hrt_master_port_load_8(addr);
129 spin_unlock_irqrestore(&mmio_lock, flags);
133 uint16_t atomisp_css2_hw_load_16(hrt_address addr)
138 spin_lock_irqsave(&mmio_lock, flags);
139 ret = _hrt_master_port_load_16(addr);
140 spin_unlock_irqrestore(&mmio_lock, flags);
143 uint32_t atomisp_css2_hw_load_32(hrt_address addr)
148 spin_lock_irqsave(&mmio_lock, flags);
149 ret = _hrt_master_port_load_32(addr);
150 spin_unlock_irqrestore(&mmio_lock, flags);
154 static void atomisp_css2_hw_store(hrt_address addr,
155 const void *from, uint32_t n)
159 unsigned int _to = (unsigned int)addr;
160 const char *_from = (const char *)from;
162 spin_lock_irqsave(&mmio_lock, flags);
163 for (i = 0; i < n; i++, _to++, _from++)
164 _hrt_master_port_store_8(_to , *_from);
165 spin_unlock_irqrestore(&mmio_lock, flags);
168 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
172 char *_to = (char *)to;
173 unsigned int _from = (unsigned int)addr;
175 spin_lock_irqsave(&mmio_lock, flags);
176 for (i = 0; i < n; i++, _to++, _from++)
177 *_to = _hrt_master_port_load_8(_from);
178 spin_unlock_irqrestore(&mmio_lock, flags);
181 static int atomisp_css2_dbg_print(const char *fmt, va_list args)
187 static int atomisp_css2_dbg_ftrace_print(const char *fmt, va_list args)
189 ftrace_vprintk(fmt, args);
193 static int atomisp_css2_err_print(const char *fmt, va_list args)
199 void atomisp_store_uint32(hrt_address addr, uint32_t data)
201 atomisp_css2_hw_store_32(addr, data);
204 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
206 *data = atomisp_css2_hw_load_32(addr);
208 static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr)
210 if (sh_mmu_mrfld.get_pd_base == NULL) {
211 dev_err(atomisp_dev, "get mmu base address failed.\n");
215 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
216 bo_device.mmu.base_address);
220 static void atomisp_isp_parameters_clean_up(
221 struct atomisp_css_isp_config *config)
224 * Set NULL to configs pointer to avoid they are set into isp again when
225 * some configs are changed and need to be updated later.
227 memset(config, 0, sizeof(*config));
230 static void __dump_pipe_config(struct atomisp_sub_device *asd,
231 struct atomisp_stream_env *stream_env,
232 unsigned int pipe_id)
234 struct atomisp_device *isp = asd->isp;
235 if (stream_env->pipes[pipe_id]) {
236 struct ia_css_pipe_config *p_config;
237 struct ia_css_pipe_extra_config *pe_config;
238 p_config = &stream_env->pipe_configs[pipe_id];
239 pe_config = &stream_env->pipe_extra_configs[pipe_id];
240 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
242 "pipe_config.pipe_mode:%d.\n", p_config->mode);
244 "pipe_config.output_info[0] w=%d, h=%d.\n",
245 p_config->output_info[0].res.width,
246 p_config->output_info[0].res.height);
248 "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
249 p_config->vf_pp_in_res.width,
250 p_config->vf_pp_in_res.height);
252 "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
253 p_config->capt_pp_in_res.width,
254 p_config->capt_pp_in_res.height);
256 "pipe_config.output.padded w=%d.\n",
257 p_config->output_info[0].padded_width);
259 "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
260 p_config->vf_output_info[0].res.width,
261 p_config->vf_output_info[0].res.height);
263 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
264 p_config->bayer_ds_out_res.width,
265 p_config->bayer_ds_out_res.height);
267 "pipe_config.envelope w=%d, h=%d.\n",
268 p_config->dvs_envelope.width,
269 p_config->dvs_envelope.height);
271 "pipe_config.dvs_frame_delay=%d.\n",
272 p_config->dvs_frame_delay);
274 "pipe_config.isp_pipe_version:%d.\n",
275 p_config->isp_pipe_version);
277 "pipe_config.acc_extension=%p.\n",
278 p_config->acc_extension);
280 "pipe_config.acc_stages=%p.\n",
281 p_config->acc_stages);
283 "pipe_config.num_acc_stages=%d.\n",
284 p_config->num_acc_stages);
286 "pipe_config.acc_num_execs=%d.\n",
287 p_config->acc_num_execs);
289 "pipe_config.default_capture_config.capture_mode=%d.\n",
290 p_config->default_capture_config.mode);
292 "pipe_config.enable_dz=%d.\n",
293 p_config->enable_dz);
295 "pipe_config.default_capture_config.enable_xnr=%d.\n",
296 p_config->default_capture_config.enable_xnr);
298 "dumping pipe[%d] extra config:\n", pipe_id);
300 "pipe_extra_config.enable_raw_binning:%d.\n",
301 pe_config->enable_raw_binning);
303 "pipe_extra_config.enable_yuv_ds:%d.\n",
304 pe_config->enable_yuv_ds);
306 "pipe_extra_config.enable_high_speed:%d.\n",
307 pe_config->enable_high_speed);
309 "pipe_extra_config.enable_dvs_6axis:%d.\n",
310 pe_config->enable_dvs_6axis);
312 "pipe_extra_config.enable_reduced_pipe:%d.\n",
313 pe_config->enable_reduced_pipe);
315 "pipe_(extra_)config.enable_dz:%d.\n",
316 p_config->enable_dz);
318 "pipe_extra_config.disable_vf_pp:%d.\n",
319 pe_config->disable_vf_pp);
323 static void __dump_stream_config(struct atomisp_sub_device *asd,
324 struct atomisp_stream_env *stream_env)
326 struct atomisp_device *isp = asd->isp;
327 struct ia_css_stream_config *s_config;
329 bool valid_stream = false;
331 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
332 if (stream_env->pipes[j]) {
333 __dump_pipe_config(asd, stream_env, j);
339 s_config = &stream_env->stream_config;
340 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
342 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
343 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
344 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
345 s_config->source.port.port);
346 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
347 s_config->source.port.num_lanes);
348 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
349 s_config->source.port.timeout);
350 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
351 s_config->source.port.rxcount);
352 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
353 s_config->source.port.compression.type);
354 dev_dbg(isp->dev, "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
355 s_config->source.port.compression.
356 compressed_bits_per_pixel);
357 dev_dbg(isp->dev, "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
358 s_config->source.port.compression.
359 uncompressed_bits_per_pixel);
360 } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
361 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
362 s_config->source.tpg.id);
363 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
364 s_config->source.tpg.mode);
365 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
366 s_config->source.tpg.x_mask);
367 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
368 s_config->source.tpg.x_delta);
369 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
370 s_config->source.tpg.y_mask);
371 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
372 s_config->source.tpg.y_delta);
373 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
374 s_config->source.tpg.xy_mask);
375 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
376 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
377 s_config->source.prbs.id);
378 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
379 s_config->source.prbs.h_blank);
380 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
381 s_config->source.prbs.v_blank);
382 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
383 s_config->source.prbs.seed);
384 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
385 s_config->source.prbs.seed1);
388 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
389 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
391 s_config->isys_config[j].input_res.width,
392 s_config->isys_config[j].input_res.height);
394 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
396 s_config->isys_config[j].linked_isys_stream_id);
398 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
400 s_config->isys_config[j].format);
402 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
404 s_config->isys_config[j].valid);
407 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
408 s_config->input_config.input_res.width,
409 s_config->input_config.input_res.height);
411 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
412 s_config->input_config.effective_res.width,
413 s_config->input_config.effective_res.height);
415 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
416 s_config->input_config.format);
418 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
419 s_config->input_config.bayer_order);
421 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
422 s_config->pixels_per_clock);
423 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
424 dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
425 s_config->continuous);
426 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
427 s_config->disable_cont_viewfinder);
428 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
429 s_config->channel_id);
430 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
431 s_config->init_num_cont_raw_buf);
432 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
433 s_config->target_num_cont_raw_buf);
434 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
435 s_config->left_padding);
436 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
437 s_config->sensor_binning_factor);
438 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
439 s_config->pixels_per_clock);
440 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
441 s_config->pack_raw_pixels);
442 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
443 s_config->flash_gpio_pin);
444 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
445 s_config->mipi_buffer_config.size_mem_words);
446 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
447 s_config->mipi_buffer_config.contiguous);
448 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
449 s_config->metadata_config.data_type);
450 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
451 s_config->metadata_config.resolution.width,
452 s_config->metadata_config.resolution.height);
455 static int __destroy_stream(struct atomisp_sub_device *asd,
456 struct atomisp_stream_env *stream_env, bool force)
458 struct atomisp_device *isp = asd->isp;
460 unsigned long timeout;
462 if (!stream_env->stream)
466 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
467 if (stream_env->update_pipe[i])
470 if (i == IA_CSS_PIPE_ID_NUM)
474 if (stream_env->stream_state == CSS_STREAM_STARTED
475 && ia_css_stream_stop(stream_env->stream) != IA_CSS_SUCCESS) {
476 dev_err(isp->dev, "stop stream failed.\n");
480 if (stream_env->stream_state == CSS_STREAM_STARTED) {
481 timeout = jiffies + msecs_to_jiffies(40);
483 if (ia_css_stream_has_stopped(stream_env->stream))
486 if (time_after(jiffies, timeout)) {
487 dev_warn(isp->dev, "stop stream timeout.\n");
491 usleep_range(100, 200);
495 stream_env->stream_state = CSS_STREAM_STOPPED;
497 if (ia_css_stream_destroy(stream_env->stream) != IA_CSS_SUCCESS) {
498 dev_err(isp->dev, "destroy stream failed.\n");
501 stream_env->stream_state = CSS_STREAM_UNINIT;
502 stream_env->stream = NULL;
507 static int __destroy_streams(struct atomisp_sub_device *asd, bool force)
510 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
511 ret = __destroy_stream(asd, &asd->stream_env[i], force);
515 asd->stream_prepared = false;
518 static int __create_stream(struct atomisp_sub_device *asd,
519 struct atomisp_stream_env *stream_env)
521 int pipe_index = 0, i;
522 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
524 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
525 if (stream_env->pipes[i])
526 multi_pipes[pipe_index++] = stream_env->pipes[i];
531 stream_env->stream_config.target_num_cont_raw_buf =
532 asd->continuous_raw_buffer_size->val;
533 stream_env->stream_config.channel_id = stream_env->ch_id;
534 stream_env->stream_config.ia_css_enable_raw_buffer_locking =
535 asd->enable_raw_buffer_lock->val;
537 __dump_stream_config(asd, stream_env);
538 if (ia_css_stream_create(&stream_env->stream_config,
539 pipe_index, multi_pipes, &stream_env->stream) != IA_CSS_SUCCESS)
541 if (ia_css_stream_get_info(stream_env->stream,
542 &stream_env->stream_info) != IA_CSS_SUCCESS) {
543 ia_css_stream_destroy(stream_env->stream);
544 stream_env->stream = NULL;
548 stream_env->stream_state = CSS_STREAM_CREATED;
552 static int __create_streams(struct atomisp_sub_device *asd)
556 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
557 ret = __create_stream(asd, &asd->stream_env[i]);
561 asd->stream_prepared = true;
564 for (i--; i >= 0; i--)
565 __destroy_stream(asd, &asd->stream_env[i], true);
569 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
570 struct atomisp_stream_env *stream_env,
573 struct atomisp_device *isp = asd->isp;
576 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
577 if (!stream_env->pipes[i] ||
578 !(force || stream_env->update_pipe[i]))
580 if (ia_css_pipe_destroy(stream_env->pipes[i])
583 "destroy pipe[%d]failed.cannot recover.\n", i);
586 stream_env->pipes[i] = NULL;
587 stream_env->update_pipe[i] = false;
592 static int __destroy_pipes(struct atomisp_sub_device *asd, bool force)
594 struct atomisp_device *isp = asd->isp;
598 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
599 if (asd->stream_env[i].stream) {
602 "cannot destroy css pipes for stream[%d].\n",
607 ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force);
615 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
617 __destroy_streams(asd, true);
618 __destroy_pipes(asd, true);
621 static void __apply_additional_pipe_config(
622 struct atomisp_sub_device *asd,
623 struct atomisp_stream_env *stream_env,
624 enum ia_css_pipe_id pipe_id)
626 struct atomisp_device *isp = asd->isp;
628 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
630 "wrong pipe_id for additional pipe config.\n");
634 /* apply default pipe config */
635 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
636 stream_env->pipe_configs[pipe_id].enable_dz =
637 asd->disable_dz->val ? false : true;
638 /* apply isp 2.2 specific config for baytrail*/
640 case IA_CSS_PIPE_ID_CAPTURE:
641 /* enable capture pp/dz manually or digital zoom would
643 if (stream_env->pipe_configs[pipe_id].
644 default_capture_config.mode == CSS_CAPTURE_MODE_RAW)
645 stream_env->pipe_configs[pipe_id].enable_dz = false;
648 /* the isp default to use ISP2.2 and the camera hal will
649 * control whether use isp2.7 */
650 if (asd->select_isp_version->val ==
651 ATOMISP_CSS_ISP_PIPE_VERSION_2_7)
652 stream_env->pipe_configs[pipe_id].isp_pipe_version =
653 SH_CSS_ISP_PIPE_VERSION_2_7;
655 stream_env->pipe_configs[pipe_id].isp_pipe_version =
656 SH_CSS_ISP_PIPE_VERSION_2_2;
659 case IA_CSS_PIPE_ID_VIDEO:
660 /* enable reduced pipe to have binary
661 * video_dz_2_min selected*/
662 stream_env->pipe_extra_configs[pipe_id]
663 .enable_reduced_pipe = true;
664 stream_env->pipe_configs[pipe_id]
666 if (ATOMISP_SOC_CAMERA(asd))
667 stream_env->pipe_configs[pipe_id].enable_dz = true;
669 if (asd->params.video_dis_en) {
670 stream_env->pipe_extra_configs[pipe_id]
671 .enable_dvs_6axis = true;
672 stream_env->pipe_configs[pipe_id]
674 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
677 case IA_CSS_PIPE_ID_PREVIEW:
679 case IA_CSS_PIPE_ID_YUVPP:
680 case IA_CSS_PIPE_ID_COPY:
681 if (ATOMISP_SOC_CAMERA(asd))
682 stream_env->pipe_configs[pipe_id].enable_dz = true;
684 stream_env->pipe_configs[pipe_id].enable_dz = false;
686 case IA_CSS_PIPE_ID_ACC:
687 stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC;
688 stream_env->pipe_configs[pipe_id].enable_dz = false;
695 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
696 enum ia_css_pipe_id pipe_id)
701 if (pipe_id == CSS_PIPE_ID_ACC || pipe_id == CSS_PIPE_ID_YUVPP)
705 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
706 if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
710 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
711 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
721 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
724 switch (asd->run_mode->val) {
725 case ATOMISP_RUN_MODE_STILL_CAPTURE:
726 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
730 case ATOMISP_RUN_MODE_PREVIEW:
731 if (!asd->continuous_mode->val) {
732 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
737 /* fall through to ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE */
738 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
739 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
740 pipe_id == IA_CSS_PIPE_ID_PREVIEW)
744 case ATOMISP_RUN_MODE_VIDEO:
745 if (!asd->continuous_mode->val) {
746 if (pipe_id == IA_CSS_PIPE_ID_VIDEO ||
747 pipe_id == IA_CSS_PIPE_ID_YUVPP)
752 /* fall through to ATOMISP_RUN_MODE_SDV */
753 case ATOMISP_RUN_MODE_SDV:
754 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
755 pipe_id == IA_CSS_PIPE_ID_VIDEO)
764 static int __create_pipe(struct atomisp_sub_device *asd,
765 struct atomisp_stream_env *stream_env,
766 enum ia_css_pipe_id pipe_id)
768 struct atomisp_device *isp = asd->isp;
769 struct ia_css_pipe_extra_config extra_config;
772 if (pipe_id >= IA_CSS_PIPE_ID_NUM)
775 if (pipe_id != CSS_PIPE_ID_ACC &&
776 !stream_env->pipe_configs[pipe_id].output_info[0].res.width)
779 if (pipe_id == CSS_PIPE_ID_ACC &&
780 !stream_env->pipe_configs[pipe_id].acc_extension)
783 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
786 ia_css_pipe_extra_config_defaults(&extra_config);
788 __apply_additional_pipe_config(asd, stream_env, pipe_id);
789 if (!memcmp(&extra_config,
790 &stream_env->pipe_extra_configs[pipe_id],
791 sizeof(extra_config)))
792 ret = ia_css_pipe_create(
793 &stream_env->pipe_configs[pipe_id],
794 &stream_env->pipes[pipe_id]);
796 ret = ia_css_pipe_create_extra(
797 &stream_env->pipe_configs[pipe_id],
798 &stream_env->pipe_extra_configs[pipe_id],
799 &stream_env->pipes[pipe_id]);
800 if (ret != IA_CSS_SUCCESS)
801 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
805 static int __create_pipes(struct atomisp_sub_device *asd)
810 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
811 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
812 ret = __create_pipe(asd, &asd->stream_env[i], j);
813 if (ret != IA_CSS_SUCCESS)
816 if (j < IA_CSS_PIPE_ID_NUM)
821 for (; i >= 0; i--) {
822 for (j--; j >= 0; j--) {
823 if (asd->stream_env[i].pipes[j]) {
824 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
825 asd->stream_env[i].pipes[j] = NULL;
828 j = IA_CSS_PIPE_ID_NUM;
833 void atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
836 __create_streams(asd);
839 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
842 struct atomisp_device *isp = asd->isp;
844 if (__destroy_streams(asd, true) != IA_CSS_SUCCESS)
845 dev_warn(isp->dev, "destroy stream failed.\n");
847 if (__destroy_pipes(asd, true) != IA_CSS_SUCCESS)
848 dev_warn(isp->dev, "destroy pipe failed.\n");
850 ret = __create_pipes(asd);
851 if (ret != IA_CSS_SUCCESS) {
852 dev_err(isp->dev, "create pipe failed %d.\n", ret);
856 ret = __create_streams(asd);
857 if (ret != IA_CSS_SUCCESS) {
858 dev_warn(isp->dev, "create stream failed %d.\n", ret);
859 __destroy_pipes(asd, true);
866 int atomisp_css_init(struct atomisp_device *isp)
868 unsigned int mmu_base_addr;
872 ret = hmm_get_mmu_base_addr(&mmu_base_addr);
877 err = ia_css_init(&isp->css_env.isp_css_env, NULL,
878 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
879 if (err != IA_CSS_SUCCESS) {
880 dev_err(isp->dev, "css init failed --- bad firmware?\n");
883 ia_css_enable_isys_event_queue(true);
885 isp->css_initialized = true;
886 dev_dbg(isp->dev, "sh_css_init success\n");
891 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
896 isp->css_env.isp_css_env.print_env.debug_print = NULL;
898 isp->css_env.isp_css_env.print_env.debug_print =
899 atomisp_css2_dbg_ftrace_print;
901 isp->css_env.isp_css_env.print_env.debug_print =
902 atomisp_css2_dbg_print;
909 int atomisp_css_check_firmware_version(struct atomisp_device *isp)
911 if (!sh_css_check_firmware_version((void *)isp->firmware->data)) {
912 dev_err(isp->dev, "Fw version check failed.\n");
918 int atomisp_css_load_firmware(struct atomisp_device *isp)
923 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
924 isp->css_env.isp_css_fw.bytes = isp->firmware->size;
926 isp->css_env.isp_css_env.hw_access_env.store_8 =
927 atomisp_css2_hw_store_8;
928 isp->css_env.isp_css_env.hw_access_env.store_16 =
929 atomisp_css2_hw_store_16;
930 isp->css_env.isp_css_env.hw_access_env.store_32 =
931 atomisp_css2_hw_store_32;
933 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
934 isp->css_env.isp_css_env.hw_access_env.load_16 =
935 atomisp_css2_hw_load_16;
936 isp->css_env.isp_css_env.hw_access_env.load_32 =
937 atomisp_css2_hw_load_32;
939 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
940 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
942 __set_css_print_env(isp, dbg_func);
944 isp->css_env.isp_css_env.print_env.error_print = atomisp_css2_err_print;
946 /* load isp fw into ISP memory */
947 err = ia_css_load_firmware(&isp->css_env.isp_css_env,
948 &isp->css_env.isp_css_fw);
949 if (err != IA_CSS_SUCCESS) {
950 dev_err(isp->dev, "css load fw failed.\n");
957 void atomisp_css_unload_firmware(struct atomisp_device *isp)
959 ia_css_unload_firmware();
962 void atomisp_css_uninit(struct atomisp_device *isp)
964 struct atomisp_sub_device *asd;
967 for (i = 0; i < isp->num_of_streams; i++) {
969 atomisp_isp_parameters_clean_up(&asd->params.config);
970 asd->params.css_update_params_needed = false;
973 isp->css_initialized = false;
977 void atomisp_css_suspend(struct atomisp_device *isp)
979 isp->css_initialized = false;
983 int atomisp_css_resume(struct atomisp_device *isp)
985 unsigned int mmu_base_addr;
988 ret = hmm_get_mmu_base_addr(&mmu_base_addr);
990 dev_err(isp->dev, "get base address error.\n");
994 ret = ia_css_init(&isp->css_env.isp_css_env, NULL,
995 mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
997 dev_err(isp->dev, "re-init css failed.\n");
1000 ia_css_enable_isys_event_queue(true);
1002 isp->css_initialized = true;
1006 int atomisp_css_irq_translate(struct atomisp_device *isp,
1007 unsigned int *infos)
1011 err = ia_css_irq_translate(infos);
1012 if (err != IA_CSS_SUCCESS) {
1014 "%s:failed to translate irq (err = %d,infos = %d)\n",
1015 __func__, err, *infos);
1022 void atomisp_css_rx_get_irq_info(enum ia_css_csi2_port port,
1023 unsigned int *infos)
1025 #ifndef ISP2401_NEW_INPUT_SYSTEM
1026 ia_css_isys_rx_get_irq_info(port, infos);
1032 void atomisp_css_rx_clear_irq_info(enum ia_css_csi2_port port,
1035 #ifndef ISP2401_NEW_INPUT_SYSTEM
1036 ia_css_isys_rx_clear_irq_info(port, infos);
1040 int atomisp_css_irq_enable(struct atomisp_device *isp,
1041 enum atomisp_css_irq_info info, bool enable)
1043 if (ia_css_irq_enable(info, enable) != IA_CSS_SUCCESS) {
1044 dev_warn(isp->dev, "%s:Invalid irq info.\n", __func__);
1051 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
1054 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1055 asd->stream_env[i].stream = NULL;
1056 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
1057 asd->stream_env[i].pipes[j] = NULL;
1058 asd->stream_env[i].update_pipe[j] = false;
1059 ia_css_pipe_config_defaults(
1060 &asd->stream_env[i].pipe_configs[j]);
1061 ia_css_pipe_extra_config_defaults(
1062 &asd->stream_env[i].pipe_extra_configs[j]);
1064 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
1068 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
1069 struct videobuf_vmalloc_memory *vm_mem,
1070 enum atomisp_input_stream_id stream_id,
1071 enum atomisp_css_buffer_type css_buf_type,
1072 enum atomisp_css_pipe_id css_pipe_id)
1074 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1075 struct ia_css_buffer css_buf = {0};
1076 enum ia_css_err err;
1078 css_buf.type = css_buf_type;
1079 css_buf.data.frame = vm_mem->vaddr;
1081 err = ia_css_pipe_enqueue_buffer(
1082 stream_env->pipes[css_pipe_id], &css_buf);
1083 if (err != IA_CSS_SUCCESS)
1089 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
1090 struct atomisp_metadata_buf *metadata_buf,
1091 enum atomisp_input_stream_id stream_id,
1092 enum atomisp_css_pipe_id css_pipe_id)
1094 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1095 struct ia_css_buffer buffer = {0};
1096 struct atomisp_device *isp = asd->isp;
1098 buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
1099 buffer.data.metadata = metadata_buf->metadata;
1100 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
1102 dev_err(isp->dev, "failed to q meta data buffer\n");
1109 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
1110 struct atomisp_s3a_buf *s3a_buf,
1111 enum atomisp_input_stream_id stream_id,
1112 enum atomisp_css_pipe_id css_pipe_id)
1114 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1115 struct ia_css_buffer buffer = {0};
1116 struct atomisp_device *isp = asd->isp;
1118 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
1119 buffer.data.stats_3a = s3a_buf->s3a_data;
1120 if (ia_css_pipe_enqueue_buffer(
1121 stream_env->pipes[css_pipe_id],
1123 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
1130 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
1131 struct atomisp_dis_buf *dis_buf,
1132 enum atomisp_input_stream_id stream_id,
1133 enum atomisp_css_pipe_id css_pipe_id)
1135 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1136 struct ia_css_buffer buffer = {0};
1137 struct atomisp_device *isp = asd->isp;
1139 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
1140 buffer.data.stats_dvs = dis_buf->dis_data;
1141 if (ia_css_pipe_enqueue_buffer(
1142 stream_env->pipes[css_pipe_id],
1144 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
1151 void atomisp_css_mmu_invalidate_cache(void)
1153 ia_css_mmu_invalidate_cache();
1156 void atomisp_css_mmu_invalidate_tlb(void)
1158 ia_css_mmu_invalidate_cache();
1161 void atomisp_css_mmu_set_page_table_base_index(unsigned long base_index)
1166 * Check whether currently running MIPI buffer size fulfill
1167 * the requirement of the stream to be run
1169 bool __need_realloc_mipi_buffer(struct atomisp_device *isp)
1173 for (i = 0; i < isp->num_of_streams; i++) {
1174 struct atomisp_sub_device *asd = &isp->asd[i];
1176 if (asd->streaming !=
1177 ATOMISP_DEVICE_STREAMING_ENABLED)
1179 if (asd->mipi_frame_size < isp->mipi_frame_size)
1186 int atomisp_css_start(struct atomisp_sub_device *asd,
1187 enum atomisp_css_pipe_id pipe_id, bool in_reset)
1189 struct atomisp_device *isp = asd->isp;
1190 bool sp_is_started = false;
1193 if (__destroy_streams(asd, true))
1194 dev_warn(isp->dev, "destroy stream failed.\n");
1196 if (__destroy_pipes(asd, true))
1197 dev_warn(isp->dev, "destroy pipe failed.\n");
1199 if (__create_pipes(asd)) {
1200 dev_err(isp->dev, "create pipe error.\n");
1203 if (__create_streams(asd)) {
1204 dev_err(isp->dev, "create stream error.\n");
1208 /* in_reset == true, extension firmwares are reloaded after the recovery */
1209 atomisp_acc_load_extensions(asd);
1213 * For dual steam case, it is possible that:
1214 * 1: for this stream, it is at the stage that:
1215 * - after set_fmt is called
1216 * - before stream on is called
1217 * 2: for the other stream, the stream off is called which css reset
1220 * Thus the stream created in set_fmt get destroyed and need to be
1221 * recreated in the next stream on.
1223 if (asd->stream_prepared == false) {
1224 if (__create_pipes(asd)) {
1225 dev_err(isp->dev, "create pipe error.\n");
1228 if (__create_streams(asd)) {
1229 dev_err(isp->dev, "create stream error.\n");
1235 * SP can only be started one time
1236 * if atomisp_subdev_streaming_count() tell there already has some
1237 * subdev at streamming, then SP should already be started previously,
1238 * so need to skip start sp procedure
1240 if (atomisp_streaming_count(isp)) {
1241 dev_dbg(isp->dev, "skip start sp\n");
1243 if (!sh_css_hrt_system_is_idle())
1244 dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1245 if (ia_css_start_sp() != IA_CSS_SUCCESS) {
1246 dev_err(isp->dev, "start sp error.\n");
1250 sp_is_started = true;
1254 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1255 if (asd->stream_env[i].stream) {
1256 if (ia_css_stream_start(asd->stream_env[i]
1257 .stream) != IA_CSS_SUCCESS) {
1258 dev_err(isp->dev, "stream[%d] start error.\n", i);
1262 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1263 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1271 __destroy_streams(asd, true);
1273 __destroy_pipes(asd, true);
1275 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1279 * SP can not be stop if other streams are in use
1281 if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1287 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1291 * for ISP2401 new input system, this api is under development.
1292 * Calling it would cause kernel panic.
1296 * Check if it is Cherry Trail and also new input system
1298 if (asd->copy_mode) {
1299 dev_warn(asd->isp->dev,
1300 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1305 ia_css_stream_set_isp_config(
1306 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1307 &asd->params.config);
1308 atomisp_isp_parameters_clean_up(&asd->params.config);
1312 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1313 struct ia_css_pipe *pipe)
1315 enum ia_css_err ret;
1318 atomisp_css_update_isp_params(asd);
1322 dev_dbg(asd->isp->dev, "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1323 __func__, asd->params.config.output_frame,
1324 asd->params.config.isp_config_id, pipe);
1326 ret = ia_css_stream_set_isp_config_on_pipe(
1327 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1328 &asd->params.config, pipe);
1329 if (ret != IA_CSS_SUCCESS)
1330 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1332 atomisp_isp_parameters_clean_up(&asd->params.config);
1335 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1336 enum atomisp_input_stream_id stream_id,
1337 enum atomisp_css_pipe_id pipe_id,
1338 enum atomisp_css_buffer_type buf_type,
1339 struct atomisp_css_buffer *isp_css_buffer)
1341 if (ia_css_pipe_enqueue_buffer(
1342 asd->stream_env[stream_id].pipes[pipe_id],
1343 &isp_css_buffer->css_buffer)
1350 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1351 enum atomisp_input_stream_id stream_id,
1352 enum atomisp_css_pipe_id pipe_id,
1353 enum atomisp_css_buffer_type buf_type,
1354 struct atomisp_css_buffer *isp_css_buffer)
1356 struct atomisp_device *isp = asd->isp;
1357 enum ia_css_err err;
1359 err = ia_css_pipe_dequeue_buffer(
1360 asd->stream_env[stream_id].pipes[pipe_id],
1361 &isp_css_buffer->css_buffer);
1362 if (err != IA_CSS_SUCCESS) {
1364 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1371 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd,
1373 struct atomisp_s3a_buf *s3a_buf,
1374 struct atomisp_dis_buf *dis_buf,
1375 struct atomisp_metadata_buf *md_buf)
1377 struct atomisp_device *isp = asd->isp;
1378 struct atomisp_css_dvs_grid_info *dvs_grid_info =
1379 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1381 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1384 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1385 &asd->params.curr_grid_info.s3a_grid);
1386 if (!s3a_buf->s3a_data) {
1387 dev_err(isp->dev, "3a buf allocation failed.\n");
1391 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1392 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1393 s3a_buf->s3a_data, s3a_ptr);
1396 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1399 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1401 if (!dis_buf->dis_data) {
1402 dev_err(isp->dev, "dvs buf allocation failed.\n");
1404 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1408 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1409 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1410 dis_buf->dis_data, dvs_ptr);
1413 if (asd->stream_env[stream_id].stream_info.
1414 metadata_info.size && md_buf) {
1415 md_buf->metadata = ia_css_metadata_allocate(
1416 &asd->stream_env[stream_id].stream_info.metadata_info);
1417 if (!md_buf->metadata) {
1419 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1421 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1422 dev_err(isp->dev, "metadata buf allocation failed.\n");
1425 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1431 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1433 if (s3a_buf->s3a_data)
1434 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1436 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1437 s3a_buf->s3a_map = NULL;
1438 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1441 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1443 if (dis_buf->dis_data)
1444 hmm_vunmap(dis_buf->dis_data->data_ptr);
1446 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1447 dis_buf->dvs_map = NULL;
1448 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1451 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1453 if (metadata_buf->md_vptr) {
1454 hmm_vunmap(metadata_buf->metadata->address);
1455 metadata_buf->md_vptr = NULL;
1457 ia_css_metadata_free(metadata_buf->metadata);
1460 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1462 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1463 struct atomisp_dis_buf *dis_buf, *_dis_buf;
1464 struct atomisp_metadata_buf *md_buf, *_md_buf;
1465 struct atomisp_css_dvs_grid_info *dvs_grid_info =
1466 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1469 /* 3A statistics use vmalloc, DIS use kmalloc */
1470 if (dvs_grid_info && dvs_grid_info->enable) {
1471 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1472 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1473 asd->params.css_param.dvs2_coeff = NULL;
1474 asd->params.dvs_stat = NULL;
1475 asd->params.dvs_hor_proj_bytes = 0;
1476 asd->params.dvs_ver_proj_bytes = 0;
1477 asd->params.dvs_hor_coef_bytes = 0;
1478 asd->params.dvs_ver_coef_bytes = 0;
1479 asd->params.dis_proj_data_valid = false;
1480 list_for_each_entry_safe(dis_buf, _dis_buf,
1481 &asd->dis_stats, list) {
1482 atomisp_css_free_dis_buffer(dis_buf);
1483 list_del(&dis_buf->list);
1486 list_for_each_entry_safe(dis_buf, _dis_buf,
1487 &asd->dis_stats_in_css, list) {
1488 atomisp_css_free_dis_buffer(dis_buf);
1489 list_del(&dis_buf->list);
1493 if (asd->params.curr_grid_info.s3a_grid.enable) {
1494 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1495 asd->params.s3a_user_stat = NULL;
1496 asd->params.s3a_output_bytes = 0;
1497 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1498 &asd->s3a_stats, list) {
1499 atomisp_css_free_3a_buffer(s3a_buf);
1500 list_del(&s3a_buf->list);
1503 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1504 &asd->s3a_stats_in_css, list) {
1505 atomisp_css_free_3a_buffer(s3a_buf);
1506 list_del(&s3a_buf->list);
1509 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1510 &asd->s3a_stats_ready, list) {
1511 atomisp_css_free_3a_buffer(s3a_buf);
1512 list_del(&s3a_buf->list);
1517 if (asd->params.css_param.dvs_6axis) {
1518 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1519 asd->params.css_param.dvs_6axis = NULL;
1522 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1523 list_for_each_entry_safe(md_buf, _md_buf,
1524 &asd->metadata[i], list) {
1525 atomisp_css_free_metadata_buffer(md_buf);
1526 list_del(&md_buf->list);
1529 list_for_each_entry_safe(md_buf, _md_buf,
1530 &asd->metadata_in_css[i], list) {
1531 atomisp_css_free_metadata_buffer(md_buf);
1532 list_del(&md_buf->list);
1535 list_for_each_entry_safe(md_buf, _md_buf,
1536 &asd->metadata_ready[i], list) {
1537 atomisp_css_free_metadata_buffer(md_buf);
1538 list_del(&md_buf->list);
1542 asd->params.metadata_width_size = 0;
1543 atomisp_free_metadata_output_buf(asd);
1546 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1547 enum atomisp_css_pipe_id pipe_id,
1550 struct ia_css_pipe_info p_info;
1551 struct ia_css_grid_info old_info;
1552 struct atomisp_device *isp = asd->isp;
1553 int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
1554 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1555 stream_config.metadata_config.resolution.width;
1557 memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1558 memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1560 if (ia_css_pipe_get_info(
1561 asd->stream_env[stream_index].pipes[pipe_id],
1562 &p_info) != IA_CSS_SUCCESS) {
1563 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1567 memcpy(&old_info, &asd->params.curr_grid_info,
1568 sizeof(struct ia_css_grid_info));
1569 memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1570 sizeof(struct ia_css_grid_info));
1572 * Record which css pipe enables s3a_grid.
1573 * Currently would have one css pipe that need it
1575 if (asd->params.curr_grid_info.s3a_grid.enable) {
1576 if (asd->params.s3a_enabled_pipe != CSS_PIPE_ID_NUM)
1577 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1578 asd->params.s3a_enabled_pipe, pipe_id);
1579 asd->params.s3a_enabled_pipe = pipe_id;
1582 /* If the grid info has not changed and the buffers for 3A and
1583 * DIS statistics buffers are allocated or buffer size would be zero
1584 * then no need to do anything. */
1585 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1586 && asd->params.s3a_user_stat && asd->params.dvs_stat)
1587 || asd->params.curr_grid_info.s3a_grid.width == 0
1588 || asd->params.curr_grid_info.s3a_grid.height == 0)
1589 && asd->params.metadata_width_size == md_width) {
1591 "grid info change escape. memcmp=%d, s3a_user_stat=%d,"
1592 "dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1593 !memcmp(&old_info, &asd->params.curr_grid_info,
1595 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1596 asd->params.curr_grid_info.s3a_grid.width,
1597 asd->params.curr_grid_info.s3a_grid.height,
1598 asd->params.metadata_width_size);
1601 asd->params.metadata_width_size = md_width;
1606 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1608 if (!asd->params.curr_grid_info.s3a_grid.width ||
1609 !asd->params.curr_grid_info.s3a_grid.height)
1612 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1613 &asd->params.curr_grid_info.s3a_grid);
1614 if (!asd->params.s3a_user_stat)
1616 /* 3A statistics. These can be big, so we use vmalloc. */
1617 asd->params.s3a_output_bytes =
1618 asd->params.curr_grid_info.s3a_grid.width *
1619 asd->params.curr_grid_info.s3a_grid.height *
1620 sizeof(*asd->params.s3a_user_stat->data);
1625 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1627 struct atomisp_css_dvs_grid_info *dvs_grid =
1628 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1633 if (!dvs_grid->enable) {
1634 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1638 /* DIS coefficients. */
1639 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1641 if (!asd->params.css_param.dvs2_coeff)
1644 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1645 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1647 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1648 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1650 /* DIS projections. */
1651 asd->params.dis_proj_data_valid = false;
1652 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1653 if (!asd->params.dvs_stat)
1656 asd->params.dvs_hor_proj_bytes =
1657 dvs_grid->aligned_height * dvs_grid->aligned_width *
1658 sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1660 asd->params.dvs_ver_proj_bytes =
1661 dvs_grid->aligned_height * dvs_grid->aligned_width *
1662 sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1667 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1671 /* We allocate the cpu-side buffer used for communication with user
1673 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1674 asd->params.metadata_user[i] = kvmalloc(
1675 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1676 stream_info.metadata_info.size, GFP_KERNEL);
1677 if (!asd->params.metadata_user[i]) {
1679 kvfree(asd->params.metadata_user[i]);
1680 asd->params.metadata_user[i] = NULL;
1689 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1693 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1694 if (asd->params.metadata_user[i]) {
1695 kvfree(asd->params.metadata_user[i]);
1696 asd->params.metadata_user[i] = NULL;
1701 void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd,
1702 struct atomisp_css_buffer *isp_css_buffer,
1703 struct ia_css_isp_dvs_statistics_map *dvs_map)
1705 if (asd->params.dvs_stat) {
1707 ia_css_translate_dvs2_statistics(
1708 asd->params.dvs_stat, dvs_map);
1710 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
1711 isp_css_buffer->css_buffer.data.stats_dvs);
1716 int atomisp_css_dequeue_event(struct atomisp_css_event *current_event)
1718 if (ia_css_dequeue_event(¤t_event->event) != IA_CSS_SUCCESS)
1724 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1725 struct atomisp_css_event *current_event)
1729 * Pipe ID reported in CSS event is not correct for new system's
1733 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1734 ¤t_event->pipe);
1735 if (asd && asd->copy_mode &&
1736 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1737 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1740 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1741 enum atomisp_input_stream_id stream_id,
1742 struct v4l2_mbus_framefmt *ffmt,
1745 struct ia_css_stream_config *s_config =
1746 &asd->stream_env[stream_id].stream_config;
1748 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1751 s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1752 s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1756 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1757 enum atomisp_input_stream_id stream_id,
1758 struct v4l2_mbus_framefmt *ffmt)
1760 struct ia_css_stream_config *s_config =
1761 &asd->stream_env[stream_id].stream_config;
1763 s_config->input_config.input_res.width = ffmt->width;
1764 s_config->input_config.input_res.height = ffmt->height;
1768 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1769 enum atomisp_input_stream_id stream_id,
1770 unsigned int bin_factor)
1772 asd->stream_env[stream_id]
1773 .stream_config.sensor_binning_factor = bin_factor;
1776 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1777 enum atomisp_input_stream_id stream_id,
1778 enum atomisp_css_bayer_order bayer_order)
1780 struct ia_css_stream_config *s_config =
1781 &asd->stream_env[stream_id].stream_config;
1782 s_config->input_config.bayer_order = bayer_order;
1785 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1786 enum atomisp_input_stream_id stream_id,
1790 struct ia_css_stream_config *s_config =
1791 &asd->stream_env[stream_id].stream_config;
1793 s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1796 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1797 enum atomisp_input_stream_id stream_id,
1801 struct ia_css_stream_config *s_config =
1802 &asd->stream_env[stream_id].stream_config;
1804 s_config->isys_config[isys_stream].valid = valid;
1807 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1808 enum atomisp_input_stream_id stream_id,
1809 enum atomisp_css_stream_format format,
1813 struct ia_css_stream_config *s_config =
1814 &asd->stream_env[stream_id].stream_config;
1816 s_config->isys_config[isys_stream].format = format;
1819 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1820 enum atomisp_input_stream_id stream_id,
1821 enum atomisp_css_stream_format format)
1824 struct ia_css_stream_config *s_config =
1825 &asd->stream_env[stream_id].stream_config;
1827 s_config->input_config.format = format;
1830 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1831 enum atomisp_input_stream_id stream_id,
1832 struct v4l2_mbus_framefmt *ffmt)
1835 struct ia_css_stream_config *s_config =
1836 &asd->stream_env[stream_id].stream_config;
1838 * Set all isys configs to not valid.
1839 * Currently we support only one stream per channel
1841 for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1842 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1843 s_config->isys_config[i].valid = false;
1845 atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1846 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1847 atomisp_css_isys_set_format(asd, stream_id,
1848 s_config->input_config.format,
1849 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1850 atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1851 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1852 atomisp_css_isys_set_valid(asd, stream_id, true,
1853 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1858 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1859 enum atomisp_input_stream_id stream_id,
1860 enum atomisp_css_stream_format input_format)
1862 struct ia_css_stream_config *s_config =
1863 &asd->stream_env[stream_id].stream_config;
1865 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1866 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1868 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1869 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1871 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1872 = IA_CSS_STREAM_ISYS_STREAM_0;
1873 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1874 IA_CSS_STREAM_FORMAT_USER_DEF1;
1875 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1876 IA_CSS_STREAM_FORMAT_USER_DEF2;
1877 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1881 void atomisp_css_isys_two_stream_cfg_update_stream1(
1882 struct atomisp_sub_device *asd,
1883 enum atomisp_input_stream_id stream_id,
1884 enum atomisp_css_stream_format input_format,
1885 unsigned int width, unsigned int height)
1887 struct ia_css_stream_config *s_config =
1888 &asd->stream_env[stream_id].stream_config;
1890 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1892 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1894 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1896 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1899 void atomisp_css_isys_two_stream_cfg_update_stream2(
1900 struct atomisp_sub_device *asd,
1901 enum atomisp_input_stream_id stream_id,
1902 enum atomisp_css_stream_format input_format,
1903 unsigned int width, unsigned int height)
1905 struct ia_css_stream_config *s_config =
1906 &asd->stream_env[stream_id].stream_config;
1908 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1910 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1912 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1913 = IA_CSS_STREAM_ISYS_STREAM_0;
1914 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1916 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1919 int atomisp_css_input_set_effective_resolution(
1920 struct atomisp_sub_device *asd,
1921 enum atomisp_input_stream_id stream_id,
1922 unsigned int width, unsigned int height)
1924 struct ia_css_stream_config *s_config =
1925 &asd->stream_env[stream_id].stream_config;
1926 s_config->input_config.effective_res.width = width;
1927 s_config->input_config.effective_res.height = height;
1931 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1932 unsigned int dvs_w, unsigned int dvs_h)
1934 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1935 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1936 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1937 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1940 void atomisp_css_input_set_two_pixels_per_clock(
1941 struct atomisp_sub_device *asd,
1946 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1947 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1950 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1951 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1952 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1953 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1954 .update_pipe[i] = true;
1957 void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
1960 struct atomisp_stream_env *stream_env =
1961 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1964 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
1965 pipe = IA_CSS_PIPE_ID_VIDEO;
1967 pipe = IA_CSS_PIPE_ID_PREVIEW;
1969 stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable;
1970 stream_env->update_pipe[pipe] = true;
1972 stream_env->pipe_configs[pipe].output_info[0].padded_width =
1973 stream_env->stream_config.input_config.effective_res.width;
1976 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1979 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1980 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1981 .pipe_configs[i].enable_dz = enable;
1984 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1985 enum atomisp_css_capture_mode mode)
1987 struct atomisp_stream_env *stream_env =
1988 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1990 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1991 .default_capture_config.mode == mode)
1994 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1995 default_capture_config.mode = mode;
1996 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1999 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
2000 enum atomisp_css_input_mode mode)
2003 struct atomisp_device *isp = asd->isp;
2004 unsigned int size_mem_words;
2005 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
2006 asd->stream_env[i].stream_config.mode = mode;
2008 if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
2009 struct ia_css_stream_config *s_config =
2010 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
2011 s_config->mode = IA_CSS_INPUT_MODE_TPG;
2012 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
2013 s_config->source.tpg.x_mask = (1 << 4) - 1;
2014 s_config->source.tpg.x_delta = -2;
2015 s_config->source.tpg.y_mask = (1 << 4) - 1;
2016 s_config->source.tpg.y_delta = 3;
2017 s_config->source.tpg.xy_mask = (1 << 8) - 1;
2021 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
2024 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2026 * TODO: sensor needs to export the embedded_data_size_words
2027 * information to atomisp for each setting.
2028 * Here using a large safe value.
2030 struct ia_css_stream_config *s_config =
2031 &asd->stream_env[i].stream_config;
2033 if (s_config->input_config.input_res.width == 0)
2036 if (ia_css_mipi_frame_calculate_size(
2037 s_config->input_config.input_res.width,
2038 s_config->input_config.input_res.height,
2039 s_config->input_config.format,
2042 &size_mem_words) != IA_CSS_SUCCESS) {
2043 if (intel_mid_identify_cpu() ==
2044 INTEL_MID_CPU_CHIP_TANGIER)
2045 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
2047 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
2048 dev_warn(asd->isp->dev,
2049 "ia_css_mipi_frame_calculate_size failed,"
2050 "applying pre-defined MIPI buffer size %u.\n",
2053 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
2054 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
2058 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
2059 unsigned short stream_index, bool enable)
2061 struct atomisp_stream_env *stream_env =
2062 &asd->stream_env[stream_index];
2064 if (stream_env->stream_config.online == !!enable)
2067 stream_env->stream_config.online = !!enable;
2068 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
2071 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
2072 unsigned short stream_index, bool enable)
2074 struct atomisp_stream_env *stream_env =
2075 &asd->stream_env[stream_index];
2078 if (stream_env->stream_config.online != !!enable) {
2079 stream_env->stream_config.online = !!enable;
2080 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2081 stream_env->update_pipe[i] = true;
2085 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
2088 struct atomisp_stream_env *stream_env =
2089 &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
2092 if (stream_env->stream_config.online != enable) {
2093 stream_env->stream_config.online = enable;
2094 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2095 stream_env->update_pipe[i] = true;
2099 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
2102 struct atomisp_stream_env *stream_env =
2103 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2107 * To SOC camera, there is only one YUVPP pipe in any case
2108 * including ZSL/SDV/continuous viewfinder, so always set
2109 * stream_config.continuous to 0.
2111 if (ATOMISP_USE_YUVPP(asd)) {
2112 stream_env->stream_config.continuous = 0;
2113 stream_env->stream_config.online = 1;
2117 if (stream_env->stream_config.continuous != !!enable) {
2118 stream_env->stream_config.continuous = !!enable;
2119 stream_env->stream_config.pack_raw_pixels = true;
2120 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2121 stream_env->update_pipe[i] = true;
2125 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
2128 struct atomisp_stream_env *stream_env =
2129 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2132 if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
2133 stream_env->stream_config.disable_cont_viewfinder = !enable;
2134 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2135 stream_env->update_pipe[i] = true;
2139 int atomisp_css_input_configure_port(
2140 struct atomisp_sub_device *asd,
2141 mipi_port_ID_t port,
2142 unsigned int num_lanes,
2143 unsigned int timeout,
2144 unsigned int mipi_freq,
2145 enum atomisp_css_stream_format metadata_format,
2146 unsigned int metadata_width,
2147 unsigned int metadata_height)
2150 struct atomisp_stream_env *stream_env;
2152 * Calculate rx_count as follows:
2153 * Input: mipi_freq : CSI-2 bus frequency in Hz
2154 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus
2155 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds
2156 * max = 145e-9 + 10 * UI
2157 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
2158 * rxcount = rxcount0 - 2 : adjust for better results
2159 * The formula below is simplified version of the above with
2160 * 10-bit fixed points for improved accuracy.
2162 const unsigned int rxcount =
2163 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
2165 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2166 stream_env = &asd->stream_env[i];
2167 stream_env->stream_config.source.port.port = port;
2168 stream_env->stream_config.source.port.num_lanes = num_lanes;
2169 stream_env->stream_config.source.port.timeout = timeout;
2171 stream_env->stream_config.source.port.rxcount = rxcount;
2172 stream_env->stream_config.
2173 metadata_config.data_type = metadata_format;
2174 stream_env->stream_config.
2175 metadata_config.resolution.width = metadata_width;
2176 stream_env->stream_config.
2177 metadata_config.resolution.height = metadata_height;
2183 int atomisp_css_frame_allocate(struct atomisp_css_frame **frame,
2184 unsigned int width, unsigned int height,
2185 enum atomisp_css_frame_format format,
2186 unsigned int padded_width,
2187 unsigned int raw_bit_depth)
2189 if (ia_css_frame_allocate(frame, width, height, format,
2190 padded_width, raw_bit_depth) != IA_CSS_SUCCESS)
2196 int atomisp_css_frame_allocate_from_info(struct atomisp_css_frame **frame,
2197 const struct atomisp_css_frame_info *info)
2199 if (ia_css_frame_allocate_from_info(frame, info) != IA_CSS_SUCCESS)
2205 void atomisp_css_frame_free(struct atomisp_css_frame *frame)
2207 ia_css_frame_free(frame);
2210 int atomisp_css_frame_map(struct atomisp_css_frame **frame,
2211 const struct atomisp_css_frame_info *info,
2212 const void *data, uint16_t attribute,
2215 if (ia_css_frame_map(frame, info, data, attribute, context)
2222 int atomisp_css_set_black_frame(struct atomisp_sub_device *asd,
2223 const struct atomisp_css_frame *raw_black_frame)
2225 if (sh_css_set_black_frame(
2226 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2227 raw_black_frame) != IA_CSS_SUCCESS)
2233 int atomisp_css_allocate_continuous_frames(bool init_time,
2234 struct atomisp_sub_device *asd)
2236 if (ia_css_alloc_continuous_frame_remain(
2237 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream)
2243 void atomisp_css_update_continuous_frames(struct atomisp_sub_device *asd)
2245 ia_css_update_continuous_frames(
2246 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream);
2249 int atomisp_css_stop(struct atomisp_sub_device *asd,
2250 enum atomisp_css_pipe_id pipe_id, bool in_reset)
2252 struct atomisp_device *isp = asd->isp;
2253 struct atomisp_s3a_buf *s3a_buf;
2254 struct atomisp_dis_buf *dis_buf;
2255 struct atomisp_metadata_buf *md_buf;
2256 unsigned long irqflags;
2259 /* if is called in atomisp_reset(), force destroy stream */
2260 if (__destroy_streams(asd, true))
2261 dev_err(isp->dev, "destroy stream failed.\n");
2263 /* if is called in atomisp_reset(), force destroy all pipes */
2264 if (__destroy_pipes(asd, true))
2265 dev_err(isp->dev, "destroy pipes failed.\n");
2267 atomisp_init_raw_buffer_bitmap(asd);
2270 * SP can not be stop if other streams are in use
2272 if (atomisp_streaming_count(isp) == 0)
2276 struct atomisp_stream_env *stream_env;
2278 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2279 stream_env = &asd->stream_env[i];
2280 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
2281 ia_css_pipe_config_defaults(
2282 &stream_env->pipe_configs[j]);
2283 ia_css_pipe_extra_config_defaults(
2284 &stream_env->pipe_extra_configs[j]);
2286 ia_css_stream_config_defaults(
2287 &stream_env->stream_config);
2289 atomisp_isp_parameters_clean_up(&asd->params.config);
2290 asd->params.css_update_params_needed = false;
2293 /* move stats buffers to free queue list */
2294 while (!list_empty(&asd->s3a_stats_in_css)) {
2295 s3a_buf = list_entry(asd->s3a_stats_in_css.next,
2296 struct atomisp_s3a_buf, list);
2297 list_del(&s3a_buf->list);
2298 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2300 while (!list_empty(&asd->s3a_stats_ready)) {
2301 s3a_buf = list_entry(asd->s3a_stats_ready.next,
2302 struct atomisp_s3a_buf, list);
2303 list_del(&s3a_buf->list);
2304 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2307 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
2308 while (!list_empty(&asd->dis_stats_in_css)) {
2309 dis_buf = list_entry(asd->dis_stats_in_css.next,
2310 struct atomisp_dis_buf, list);
2311 list_del(&dis_buf->list);
2312 list_add_tail(&dis_buf->list, &asd->dis_stats);
2314 asd->params.dis_proj_data_valid = false;
2315 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
2317 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
2318 while (!list_empty(&asd->metadata_in_css[i])) {
2319 md_buf = list_entry(asd->metadata_in_css[i].next,
2320 struct atomisp_metadata_buf, list);
2321 list_del(&md_buf->list);
2322 list_add_tail(&md_buf->list, &asd->metadata[i]);
2324 while (!list_empty(&asd->metadata_ready[i])) {
2325 md_buf = list_entry(asd->metadata_ready[i].next,
2326 struct atomisp_metadata_buf, list);
2327 list_del(&md_buf->list);
2328 list_add_tail(&md_buf->list, &asd->metadata[i]);
2332 atomisp_flush_params_queue(&asd->video_out_capture);
2333 atomisp_flush_params_queue(&asd->video_out_vf);
2334 atomisp_flush_params_queue(&asd->video_out_preview);
2335 atomisp_flush_params_queue(&asd->video_out_video_capture);
2336 atomisp_free_css_parameters(&asd->params.css_param);
2337 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
2341 int atomisp_css_continuous_set_num_raw_frames(
2342 struct atomisp_sub_device *asd,
2345 if (asd->enable_raw_buffer_lock->val) {
2346 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2347 .stream_config.init_num_cont_raw_buf =
2348 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
2349 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2350 asd->params.video_dis_en)
2351 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2352 .stream_config.init_num_cont_raw_buf +=
2353 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2355 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2356 .stream_config.init_num_cont_raw_buf =
2357 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
2360 if (asd->params.video_dis_en)
2361 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2362 .stream_config.init_num_cont_raw_buf +=
2363 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2365 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2366 .stream_config.target_num_cont_raw_buf = num_frames;
2370 void atomisp_css_disable_vf_pp(struct atomisp_sub_device *asd,
2375 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2376 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2377 .pipe_extra_configs[i].disable_vf_pp = !!disable;
2380 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2381 struct atomisp_sub_device *asd,
2382 enum ia_css_pipe_id pipe_id)
2384 struct atomisp_device *isp = asd->isp;
2385 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2386 isp->inputs[asd->input_curr].camera);
2389 case IA_CSS_PIPE_ID_COPY:
2390 /* Currently only YUVPP mode supports YUV420_Legacy format.
2391 * Revert this when other pipe modes can support
2392 * YUV420_Legacy format.
2394 if (mipi_info && mipi_info->input_format ==
2395 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2396 return IA_CSS_PIPE_MODE_YUVPP;
2397 return IA_CSS_PIPE_MODE_COPY;
2398 case IA_CSS_PIPE_ID_PREVIEW:
2399 return IA_CSS_PIPE_MODE_PREVIEW;
2400 case IA_CSS_PIPE_ID_CAPTURE:
2401 return IA_CSS_PIPE_MODE_CAPTURE;
2402 case IA_CSS_PIPE_ID_VIDEO:
2403 return IA_CSS_PIPE_MODE_VIDEO;
2404 case IA_CSS_PIPE_ID_ACC:
2405 return IA_CSS_PIPE_MODE_ACC;
2406 case IA_CSS_PIPE_ID_YUVPP:
2407 return IA_CSS_PIPE_MODE_YUVPP;
2410 return IA_CSS_PIPE_MODE_PREVIEW;
2415 static void __configure_output(struct atomisp_sub_device *asd,
2416 unsigned int stream_index,
2417 unsigned int width, unsigned int height,
2418 unsigned int min_width,
2419 enum ia_css_frame_format format,
2420 enum ia_css_pipe_id pipe_id)
2422 struct atomisp_device *isp = asd->isp;
2423 struct atomisp_stream_env *stream_env =
2424 &asd->stream_env[stream_index];
2425 struct ia_css_stream_config *s_config = &stream_env->stream_config;
2427 stream_env->pipe_configs[pipe_id].mode =
2428 __pipe_id_to_pipe_mode(asd, pipe_id);
2429 stream_env->update_pipe[pipe_id] = true;
2431 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2432 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2433 stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2434 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2436 /* isp binary 2.2 specific setting*/
2437 if (width > s_config->input_config.effective_res.width ||
2438 height > s_config->input_config.effective_res.height) {
2439 s_config->input_config.effective_res.width = width;
2440 s_config->input_config.effective_res.height = height;
2443 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2444 pipe_id, width, height, format);
2447 static void __configure_video_preview_output(struct atomisp_sub_device *asd,
2448 unsigned int stream_index,
2449 unsigned int width, unsigned int height,
2450 unsigned int min_width,
2451 enum ia_css_frame_format format,
2452 enum ia_css_pipe_id pipe_id)
2454 struct atomisp_device *isp = asd->isp;
2455 struct atomisp_stream_env *stream_env =
2456 &asd->stream_env[stream_index];
2457 struct ia_css_frame_info *css_output_info;
2458 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2460 stream_env->pipe_configs[pipe_id].mode =
2461 __pipe_id_to_pipe_mode(asd, pipe_id);
2462 stream_env->update_pipe[pipe_id] = true;
2465 * second_output will be as video main output in SDV mode
2466 * with SOC camera. output will be as video main output in
2467 * normal video mode.
2469 if (asd->continuous_mode->val)
2470 css_output_info = &stream_env->pipe_configs[pipe_id].
2471 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2473 css_output_info = &stream_env->pipe_configs[pipe_id].
2474 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2476 css_output_info->res.width = width;
2477 css_output_info->res.height = height;
2478 css_output_info->format = format;
2479 css_output_info->padded_width = min_width;
2481 /* isp binary 2.2 specific setting*/
2482 if (width > stream_config->input_config.effective_res.width ||
2483 height > stream_config->input_config.effective_res.height) {
2484 stream_config->input_config.effective_res.width = width;
2485 stream_config->input_config.effective_res.height = height;
2488 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2489 pipe_id, width, height, format);
2493 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2494 * downscaling input resolution.
2496 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2497 unsigned int width, unsigned int height,
2498 enum ia_css_pipe_id pipe_id)
2500 struct atomisp_device *isp = asd->isp;
2501 struct atomisp_stream_env *stream_env =
2502 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2503 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2504 struct ia_css_pipe_config *pipe_configs =
2505 &stream_env->pipe_configs[pipe_id];
2506 struct ia_css_pipe_extra_config *pipe_extra_configs =
2507 &stream_env->pipe_extra_configs[pipe_id];
2508 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2510 if (width == 0 && height == 0)
2513 if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2514 height * 9 / 10 < pipe_configs->output_info[0].res.height)
2516 /* here just copy the calculation in css */
2517 hor_ds_factor = CEIL_DIV(width >> 1,
2518 pipe_configs->output_info[0].res.width);
2519 ver_ds_factor = CEIL_DIV(height >> 1,
2520 pipe_configs->output_info[0].res.height);
2522 if ((asd->isp->media_dev.hw_revision <
2523 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2524 IS_CHT) && hor_ds_factor != ver_ds_factor) {
2525 dev_warn(asd->isp->dev,
2526 "Cropping for capture due to FW limitation");
2530 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2531 stream_env->update_pipe[pipe_id] = true;
2533 pipe_extra_configs->enable_yuv_ds = true;
2535 pipe_configs->capt_pp_in_res.width =
2536 stream_config->input_config.effective_res.width;
2537 pipe_configs->capt_pp_in_res.height =
2538 stream_config->input_config.effective_res.height;
2540 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2541 pipe_id, width, height);
2545 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2546 * yuv downscaling, which needs addtional configurations.
2548 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2549 unsigned int width, unsigned int height,
2550 enum ia_css_pipe_id pipe_id)
2552 struct atomisp_device *isp = asd->isp;
2553 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2554 struct atomisp_stream_env *stream_env =
2555 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2556 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2557 struct ia_css_pipe_config *pipe_configs =
2558 &stream_env->pipe_configs[pipe_id];
2559 struct ia_css_pipe_extra_config *pipe_extra_configs =
2560 &stream_env->pipe_extra_configs[pipe_id];
2561 struct ia_css_resolution *bayer_ds_out_res =
2562 &pipe_configs->bayer_ds_out_res;
2563 struct ia_css_resolution *vf_pp_in_res =
2564 &pipe_configs->vf_pp_in_res;
2565 struct ia_css_resolution *effective_res =
2566 &stream_config->input_config.effective_res;
2568 const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2570 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2571 * columns to be shaded. Remove this factor to work around the CSS bug.
2572 * const unsigned int yuv_dec_fct[] = {4, 2};
2574 const unsigned int yuv_dec_fct[] = { 2 };
2577 if (width == 0 && height == 0)
2580 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2581 stream_env->update_pipe[pipe_id] = true;
2583 out_width = pipe_configs->output_info[0].res.width;
2584 out_height = pipe_configs->output_info[0].res.height;
2587 * The ISP could do bayer downscaling, yuv decimation and yuv
2589 * 1: Bayer Downscaling: between effective resolution and
2591 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2592 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2594 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2595 * Rule for YUV Decimation: support factor 2, 4
2596 * Rule for YUV Downscaling: arbitary value below 2
2598 * General rule of factor distribution among these stages:
2599 * 1: try to do Bayer downscaling first if not in online mode.
2600 * 2: try to do maximum of 2 for YUV downscaling
2601 * 3: the remainling for YUV decimation
2604 * Do not configure bayer_ds_out_res if:
2605 * online == 1 or continuous == 0 or raw_binning = 0
2607 if (stream_config->online || !stream_config->continuous ||
2608 !pipe_extra_configs->enable_raw_binning) {
2609 bayer_ds_out_res->width = 0;
2610 bayer_ds_out_res->height = 0;
2612 bayer_ds_out_res->width = effective_res->width;
2613 bayer_ds_out_res->height = effective_res->height;
2615 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2616 if (effective_res->width >= out_width *
2617 bds_fct[i].numerator / bds_fct[i].denominator &&
2618 effective_res->height >= out_height *
2619 bds_fct[i].numerator / bds_fct[i].denominator) {
2620 bayer_ds_out_res->width =
2621 effective_res->width *
2622 bds_fct[i].denominator /
2623 bds_fct[i].numerator;
2624 bayer_ds_out_res->height =
2625 effective_res->height *
2626 bds_fct[i].denominator /
2627 bds_fct[i].numerator;
2633 * calculate YUV Decimation, YUV downscaling facor:
2634 * YUV Downscaling factor must not exceed 2.
2635 * YUV Decimation factor could be 2, 4.
2637 /* first decide the yuv_ds input resolution */
2638 if (bayer_ds_out_res->width == 0) {
2639 yuv_ds_in_width = effective_res->width;
2640 yuv_ds_in_height = effective_res->height;
2642 yuv_ds_in_width = bayer_ds_out_res->width;
2643 yuv_ds_in_height = bayer_ds_out_res->height;
2646 vf_pp_in_res->width = yuv_ds_in_width;
2647 vf_pp_in_res->height = yuv_ds_in_height;
2649 /* find out the yuv decimation factor */
2650 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2651 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2652 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2653 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2654 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2659 if (vf_pp_in_res->width == out_width &&
2660 vf_pp_in_res->height == out_height) {
2661 pipe_extra_configs->enable_yuv_ds = false;
2662 vf_pp_in_res->width = 0;
2663 vf_pp_in_res->height = 0;
2665 pipe_extra_configs->enable_yuv_ds = true;
2668 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2669 pipe_id, width, height);
2673 * For CSS2.1, offline video pipe could support bayer decimation, and
2674 * yuv downscaling, which needs addtional configurations.
2676 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2677 unsigned int width, unsigned int height,
2678 enum ia_css_pipe_id pipe_id)
2680 struct atomisp_device *isp = asd->isp;
2681 int out_width, out_height;
2682 struct atomisp_stream_env *stream_env =
2683 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2684 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2685 struct ia_css_pipe_config *pipe_configs =
2686 &stream_env->pipe_configs[pipe_id];
2687 struct ia_css_pipe_extra_config *pipe_extra_configs =
2688 &stream_env->pipe_extra_configs[pipe_id];
2689 struct ia_css_resolution *bayer_ds_out_res =
2690 &pipe_configs->bayer_ds_out_res;
2691 struct ia_css_resolution *effective_res =
2692 &stream_config->input_config.effective_res;
2694 const struct bayer_ds_factor bds_factors[] = {
2695 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2} };
2698 if (width == 0 && height == 0)
2701 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2702 stream_env->update_pipe[pipe_id] = true;
2704 pipe_extra_configs->enable_yuv_ds = false;
2707 * If DVS is enabled, video binary will take care the dvs envelope
2708 * and usually the bayer_ds_out_res should be larger than 120% of
2709 * destination resolution, the extra 20% will be cropped as DVS
2710 * envelope. But, if the bayer_ds_out_res is less than 120% of the
2711 * destination. The ISP can still work, but DVS quality is not good.
2713 /* taking at least 10% as envelope */
2714 if (asd->params.video_dis_en) {
2715 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2716 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2718 out_width = pipe_configs->output_info[0].res.width;
2719 out_height = pipe_configs->output_info[0].res.height;
2723 * calculate bayer decimate factor:
2724 * 1: only 1.5, 2, 4 and 8 get supported
2725 * 2: Do not configure bayer_ds_out_res if:
2726 * online == 1 or continuous == 0 or raw_binning = 0
2728 if (stream_config->online || !stream_config->continuous) {
2729 bayer_ds_out_res->width = 0;
2730 bayer_ds_out_res->height = 0;
2734 pipe_extra_configs->enable_raw_binning = true;
2735 bayer_ds_out_res->width = effective_res->width;
2736 bayer_ds_out_res->height = effective_res->height;
2738 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2740 if (effective_res->width >= out_width *
2741 bds_factors[i].numerator / bds_factors[i].denominator &&
2742 effective_res->height >= out_height *
2743 bds_factors[i].numerator / bds_factors[i].denominator) {
2744 bayer_ds_out_res->width = effective_res->width *
2745 bds_factors[i].denominator /
2746 bds_factors[i].numerator;
2747 bayer_ds_out_res->height = effective_res->height *
2748 bds_factors[i].denominator /
2749 bds_factors[i].numerator;
2755 * DVS is cropped from BDS output, so we do not really need to set the
2756 * envelope to 20% of output resolution here. always set it to 12x12
2757 * per firmware requirement.
2759 pipe_configs->dvs_envelope.width = 12;
2760 pipe_configs->dvs_envelope.height = 12;
2763 if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2764 stream_config->left_padding = -1;
2766 stream_config->left_padding = 12;
2767 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2768 pipe_id, width, height);
2771 static void __configure_vf_output(struct atomisp_sub_device *asd,
2772 unsigned int width, unsigned int height,
2773 unsigned int min_width,
2774 enum atomisp_css_frame_format format,
2775 enum ia_css_pipe_id pipe_id)
2777 struct atomisp_device *isp = asd->isp;
2778 struct atomisp_stream_env *stream_env =
2779 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2780 stream_env->pipe_configs[pipe_id].mode =
2781 __pipe_id_to_pipe_mode(asd, pipe_id);
2782 stream_env->update_pipe[pipe_id] = true;
2784 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2785 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2786 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2787 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2790 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2791 pipe_id, width, height, format);
2794 static void __configure_video_vf_output(struct atomisp_sub_device *asd,
2795 unsigned int width, unsigned int height,
2796 unsigned int min_width,
2797 enum atomisp_css_frame_format format,
2798 enum ia_css_pipe_id pipe_id)
2800 struct atomisp_device *isp = asd->isp;
2801 struct atomisp_stream_env *stream_env =
2802 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2803 struct ia_css_frame_info *css_output_info;
2804 stream_env->pipe_configs[pipe_id].mode =
2805 __pipe_id_to_pipe_mode(asd, pipe_id);
2806 stream_env->update_pipe[pipe_id] = true;
2809 * second_vf_output will be as video viewfinder in SDV mode
2810 * with SOC camera. vf_output will be as video viewfinder in
2811 * normal video mode.
2813 if (asd->continuous_mode->val)
2814 css_output_info = &stream_env->pipe_configs[pipe_id].
2815 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2817 css_output_info = &stream_env->pipe_configs[pipe_id].
2818 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2820 css_output_info->res.width = width;
2821 css_output_info->res.height = height;
2822 css_output_info->format = format;
2823 css_output_info->padded_width = min_width;
2825 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2826 pipe_id, width, height, format);
2829 static int __get_frame_info(struct atomisp_sub_device *asd,
2830 unsigned int stream_index,
2831 struct atomisp_css_frame_info *info,
2832 enum frame_info_type type,
2833 enum ia_css_pipe_id pipe_id)
2835 struct atomisp_device *isp = asd->isp;
2836 enum ia_css_err ret;
2837 struct ia_css_pipe_info p_info;
2839 /* FIXME! No need to destroy/recreate all streams */
2840 if (__destroy_streams(asd, true))
2841 dev_warn(isp->dev, "destroy stream failed.\n");
2843 if (__destroy_pipes(asd, true))
2844 dev_warn(isp->dev, "destroy pipe failed.\n");
2846 if (__create_pipes(asd))
2849 if (__create_streams(asd))
2852 ret = ia_css_pipe_get_info(
2853 asd->stream_env[stream_index]
2854 .pipes[pipe_id], &p_info);
2855 if (ret == IA_CSS_SUCCESS) {
2857 case ATOMISP_CSS_VF_FRAME:
2858 *info = p_info.vf_output_info[0];
2859 dev_dbg(isp->dev, "getting vf frame info.\n");
2861 case ATOMISP_CSS_SECOND_VF_FRAME:
2862 *info = p_info.vf_output_info[1];
2863 dev_dbg(isp->dev, "getting second vf frame info.\n");
2865 case ATOMISP_CSS_OUTPUT_FRAME:
2866 *info = p_info.output_info[0];
2867 dev_dbg(isp->dev, "getting main frame info.\n");
2869 case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2870 *info = p_info.output_info[1];
2871 dev_dbg(isp->dev, "getting second main frame info.\n");
2873 case ATOMISP_CSS_RAW_FRAME:
2874 *info = p_info.raw_output_info;
2875 dev_dbg(isp->dev, "getting raw frame info.\n");
2877 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2878 info->res.width, info->res.height, p_info.num_invalid_frames);
2883 __destroy_pipes(asd, true);
2887 unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2888 uint16_t source_pad)
2890 struct atomisp_device *isp = asd->isp;
2892 * to SOC camera, use yuvpp pipe.
2894 if (ATOMISP_USE_YUVPP(asd))
2895 return IA_CSS_PIPE_ID_YUVPP;
2897 switch (source_pad) {
2898 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2899 if (asd->yuvpp_mode)
2900 return IA_CSS_PIPE_ID_YUVPP;
2902 return IA_CSS_PIPE_ID_COPY;
2903 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2904 || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2905 return IA_CSS_PIPE_ID_VIDEO;
2907 return IA_CSS_PIPE_ID_CAPTURE;
2908 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2910 return IA_CSS_PIPE_ID_COPY;
2911 return IA_CSS_PIPE_ID_CAPTURE;
2912 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2913 if (!atomisp_is_mbuscode_raw(
2914 asd->fmt[asd->capture_pad].fmt.code))
2915 return IA_CSS_PIPE_ID_CAPTURE;
2916 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2917 if (asd->yuvpp_mode)
2918 return IA_CSS_PIPE_ID_YUVPP;
2920 return IA_CSS_PIPE_ID_COPY;
2921 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2922 return IA_CSS_PIPE_ID_VIDEO;
2924 return IA_CSS_PIPE_ID_PREVIEW;
2927 "invalid source pad:%d, return default preview pipe index.\n",
2929 return IA_CSS_PIPE_ID_PREVIEW;
2932 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2933 uint16_t source_pad,
2934 struct atomisp_css_frame_info *frame_info)
2936 struct ia_css_pipe_info info;
2937 int pipe_index = atomisp_get_pipe_index(asd, source_pad);
2939 struct atomisp_device *isp = asd->isp;
2941 if (ATOMISP_SOC_CAMERA(asd))
2942 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
2944 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2945 ATOMISP_INPUT_STREAM_VIDEO :
2946 atomisp_source_pad_to_stream_id(asd, source_pad);
2949 if (IA_CSS_SUCCESS != ia_css_pipe_get_info(asd->stream_env[stream_index]
2950 .pipes[pipe_index], &info)) {
2951 dev_err(isp->dev, "ia_css_pipe_get_info FAILED");
2955 switch (source_pad) {
2956 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2957 *frame_info = info.output_info[0];
2959 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2960 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2962 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2965 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2967 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2968 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
2969 *frame_info = info.output_info[0];
2971 *frame_info = info.vf_output_info[0];
2973 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2974 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2975 (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
2976 pipe_index == IA_CSS_PIPE_ID_YUVPP))
2977 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2979 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2982 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2983 else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2985 info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2988 info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2995 return frame_info ? 0 : -EINVAL;
2998 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2999 unsigned int stream_index,
3000 unsigned int width, unsigned int height,
3001 unsigned int padded_width,
3002 enum atomisp_css_frame_format format)
3004 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
3005 default_capture_config.mode =
3006 CSS_CAPTURE_MODE_RAW;
3008 __configure_output(asd, stream_index, width, height, padded_width,
3009 format, IA_CSS_PIPE_ID_COPY);
3013 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
3014 unsigned int stream_index,
3015 unsigned int width, unsigned int height,
3016 unsigned int padded_width,
3017 enum atomisp_css_frame_format format)
3019 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
3020 default_capture_config.mode =
3021 CSS_CAPTURE_MODE_RAW;
3023 __configure_output(asd, stream_index, width, height, padded_width,
3024 format, IA_CSS_PIPE_ID_YUVPP);
3028 int atomisp_css_yuvpp_configure_viewfinder(
3029 struct atomisp_sub_device *asd,
3030 unsigned int stream_index,
3031 unsigned int width, unsigned int height,
3032 unsigned int min_width,
3033 enum atomisp_css_frame_format format)
3035 struct atomisp_stream_env *stream_env =
3036 &asd->stream_env[stream_index];
3037 enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP;
3039 stream_env->pipe_configs[pipe_id].mode =
3040 __pipe_id_to_pipe_mode(asd, pipe_id);
3041 stream_env->update_pipe[pipe_id] = true;
3043 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
3044 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
3045 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
3046 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
3051 int atomisp_css_yuvpp_get_output_frame_info(
3052 struct atomisp_sub_device *asd,
3053 unsigned int stream_index,
3054 struct atomisp_css_frame_info *info)
3056 return __get_frame_info(asd, stream_index, info,
3057 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
3060 int atomisp_css_yuvpp_get_viewfinder_frame_info(
3061 struct atomisp_sub_device *asd,
3062 unsigned int stream_index,
3063 struct atomisp_css_frame_info *info)
3065 return __get_frame_info(asd, stream_index, info,
3066 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
3069 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
3070 unsigned int width, unsigned int height,
3071 unsigned int min_width,
3072 enum atomisp_css_frame_format format)
3075 * to SOC camera, use yuvpp pipe.
3077 if (ATOMISP_USE_YUVPP(asd))
3078 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3079 min_width, format, IA_CSS_PIPE_ID_YUVPP);
3081 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3082 min_width, format, IA_CSS_PIPE_ID_PREVIEW);
3086 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
3087 unsigned int width, unsigned int height,
3088 unsigned int min_width,
3089 enum atomisp_css_frame_format format)
3091 enum ia_css_pipe_id pipe_id;
3094 * to SOC camera, use yuvpp pipe.
3096 if (ATOMISP_USE_YUVPP(asd))
3097 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3099 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3101 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3102 min_width, format, pipe_id);
3106 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
3107 unsigned int width, unsigned int height,
3108 unsigned int min_width,
3109 enum atomisp_css_frame_format format)
3112 * to SOC camera, use yuvpp pipe.
3114 if (ATOMISP_USE_YUVPP(asd))
3115 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3116 min_width, format, IA_CSS_PIPE_ID_YUVPP);
3118 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3119 min_width, format, IA_CSS_PIPE_ID_VIDEO);
3123 int atomisp_css_video_configure_viewfinder(
3124 struct atomisp_sub_device *asd,
3125 unsigned int width, unsigned int height,
3126 unsigned int min_width,
3127 enum atomisp_css_frame_format format)
3130 * to SOC camera, video will use yuvpp pipe.
3132 if (ATOMISP_USE_YUVPP(asd))
3133 __configure_video_vf_output(asd, width, height, min_width, format,
3134 IA_CSS_PIPE_ID_YUVPP);
3136 __configure_vf_output(asd, width, height, min_width, format,
3137 IA_CSS_PIPE_ID_VIDEO);
3141 int atomisp_css_capture_configure_viewfinder(
3142 struct atomisp_sub_device *asd,
3143 unsigned int width, unsigned int height,
3144 unsigned int min_width,
3145 enum atomisp_css_frame_format format)
3147 enum ia_css_pipe_id pipe_id;
3150 * to SOC camera, video will use yuvpp pipe.
3152 if (ATOMISP_USE_YUVPP(asd))
3153 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3155 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3157 __configure_vf_output(asd, width, height, min_width, format,
3162 int atomisp_css_video_get_viewfinder_frame_info(
3163 struct atomisp_sub_device *asd,
3164 struct atomisp_css_frame_info *info)
3166 enum ia_css_pipe_id pipe_id;
3167 enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME;
3169 if (ATOMISP_USE_YUVPP(asd)) {
3170 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3171 if (asd->continuous_mode->val)
3172 frame_type = ATOMISP_CSS_SECOND_VF_FRAME;
3174 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3177 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3178 frame_type, pipe_id);
3181 int atomisp_css_capture_get_viewfinder_frame_info(
3182 struct atomisp_sub_device *asd,
3183 struct atomisp_css_frame_info *info)
3185 enum ia_css_pipe_id pipe_id;
3187 if (ATOMISP_USE_YUVPP(asd))
3188 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3190 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3192 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3193 ATOMISP_CSS_VF_FRAME, pipe_id);
3196 int atomisp_css_capture_get_output_raw_frame_info(
3197 struct atomisp_sub_device *asd,
3198 struct atomisp_css_frame_info *info)
3200 if (ATOMISP_USE_YUVPP(asd))
3203 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3204 ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE);
3207 int atomisp_css_copy_get_output_frame_info(
3208 struct atomisp_sub_device *asd,
3209 unsigned int stream_index,
3210 struct atomisp_css_frame_info *info)
3212 return __get_frame_info(asd, stream_index, info,
3213 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
3216 int atomisp_css_preview_get_output_frame_info(
3217 struct atomisp_sub_device *asd,
3218 struct atomisp_css_frame_info *info)
3220 enum ia_css_pipe_id pipe_id;
3221 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3223 if (ATOMISP_USE_YUVPP(asd)) {
3224 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3225 if (asd->continuous_mode->val)
3226 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3228 pipe_id = IA_CSS_PIPE_ID_PREVIEW;
3231 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3232 frame_type, pipe_id);
3235 int atomisp_css_capture_get_output_frame_info(
3236 struct atomisp_sub_device *asd,
3237 struct atomisp_css_frame_info *info)
3239 enum ia_css_pipe_id pipe_id;
3241 if (ATOMISP_USE_YUVPP(asd))
3242 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3244 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3246 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3247 ATOMISP_CSS_OUTPUT_FRAME, pipe_id);
3250 int atomisp_css_video_get_output_frame_info(
3251 struct atomisp_sub_device *asd,
3252 struct atomisp_css_frame_info *info)
3254 enum ia_css_pipe_id pipe_id;
3255 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3257 if (ATOMISP_USE_YUVPP(asd)) {
3258 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3259 if (asd->continuous_mode->val)
3260 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3262 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3265 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3266 frame_type, pipe_id);
3269 int atomisp_css_preview_configure_pp_input(
3270 struct atomisp_sub_device *asd,
3271 unsigned int width, unsigned int height)
3273 struct atomisp_stream_env *stream_env =
3274 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3275 __configure_preview_pp_input(asd, width, height,
3276 ATOMISP_USE_YUVPP(asd) ?
3277 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW);
3279 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3280 capt_pp_in_res.width)
3281 __configure_capture_pp_input(asd, width, height,
3282 ATOMISP_USE_YUVPP(asd) ?
3283 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3287 int atomisp_css_capture_configure_pp_input(
3288 struct atomisp_sub_device *asd,
3289 unsigned int width, unsigned int height)
3291 __configure_capture_pp_input(asd, width, height,
3292 ATOMISP_USE_YUVPP(asd) ?
3293 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3297 int atomisp_css_video_configure_pp_input(
3298 struct atomisp_sub_device *asd,
3299 unsigned int width, unsigned int height)
3301 struct atomisp_stream_env *stream_env =
3302 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3304 __configure_video_pp_input(asd, width, height,
3305 ATOMISP_USE_YUVPP(asd) ?
3306 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO);
3308 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3309 capt_pp_in_res.width)
3310 __configure_capture_pp_input(asd, width, height,
3311 ATOMISP_USE_YUVPP(asd) ?
3312 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3316 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
3317 int num_captures, unsigned int skip, int offset)
3319 enum ia_css_err ret;
3322 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
3323 __func__, num_captures, skip, offset);
3325 ret = ia_css_stream_capture(
3326 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3327 num_captures, skip, offset);
3328 if (ret != IA_CSS_SUCCESS)
3334 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
3336 enum ia_css_err ret;
3338 ret = ia_css_stream_capture_frame(
3339 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3341 if (ret == IA_CSS_ERR_QUEUE_IS_FULL) {
3342 /* capture cmd queue is full */
3344 } else if (ret != IA_CSS_SUCCESS) {
3351 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
3353 enum ia_css_err ret;
3355 ret = ia_css_unlock_raw_frame(
3356 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3358 if (ret == IA_CSS_ERR_QUEUE_IS_FULL)
3360 else if (ret != IA_CSS_SUCCESS)
3366 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
3369 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3370 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
3371 .default_capture_config.enable_xnr = enable;
3372 asd->params.capture_config.enable_xnr = enable;
3373 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3374 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
3379 void atomisp_css_send_input_frame(struct atomisp_sub_device *asd,
3380 unsigned short *data, unsigned int width,
3381 unsigned int height)
3383 ia_css_stream_send_input_frame(
3384 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3385 data, width, height);
3388 bool atomisp_css_isp_has_started(void)
3390 return ia_css_isp_has_started();
3393 void atomisp_css_request_flash(struct atomisp_sub_device *asd)
3395 ia_css_stream_request_flash(
3396 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream);
3399 void atomisp_css_set_wb_config(struct atomisp_sub_device *asd,
3400 struct atomisp_css_wb_config *wb_config)
3402 asd->params.config.wb_config = wb_config;
3405 void atomisp_css_set_ob_config(struct atomisp_sub_device *asd,
3406 struct atomisp_css_ob_config *ob_config)
3408 asd->params.config.ob_config = ob_config;
3411 void atomisp_css_set_dp_config(struct atomisp_sub_device *asd,
3412 struct atomisp_css_dp_config *dp_config)
3414 asd->params.config.dp_config = dp_config;
3417 void atomisp_css_set_de_config(struct atomisp_sub_device *asd,
3418 struct atomisp_css_de_config *de_config)
3420 asd->params.config.de_config = de_config;
3423 void atomisp_css_set_dz_config(struct atomisp_sub_device *asd,
3424 struct atomisp_css_dz_config *dz_config)
3426 asd->params.config.dz_config = dz_config;
3429 void atomisp_css_set_default_de_config(struct atomisp_sub_device *asd)
3431 asd->params.config.de_config = NULL;
3434 void atomisp_css_set_ce_config(struct atomisp_sub_device *asd,
3435 struct atomisp_css_ce_config *ce_config)
3437 asd->params.config.ce_config = ce_config;
3440 void atomisp_css_set_nr_config(struct atomisp_sub_device *asd,
3441 struct atomisp_css_nr_config *nr_config)
3443 asd->params.config.nr_config = nr_config;
3446 void atomisp_css_set_ee_config(struct atomisp_sub_device *asd,
3447 struct atomisp_css_ee_config *ee_config)
3449 asd->params.config.ee_config = ee_config;
3452 void atomisp_css_set_tnr_config(struct atomisp_sub_device *asd,
3453 struct atomisp_css_tnr_config *tnr_config)
3455 asd->params.config.tnr_config = tnr_config;
3458 void atomisp_css_set_cc_config(struct atomisp_sub_device *asd,
3459 struct atomisp_css_cc_config *cc_config)
3461 asd->params.config.cc_config = cc_config;
3464 void atomisp_css_set_macc_table(struct atomisp_sub_device *asd,
3465 struct atomisp_css_macc_table *macc_table)
3467 asd->params.config.macc_table = macc_table;
3470 void atomisp_css_set_macc_config(struct atomisp_sub_device *asd,
3471 struct atomisp_css_macc_config *macc_config)
3473 asd->params.config.macc_config = macc_config;
3476 void atomisp_css_set_ecd_config(struct atomisp_sub_device *asd,
3477 struct atomisp_css_ecd_config *ecd_config)
3479 asd->params.config.ecd_config = ecd_config;
3482 void atomisp_css_set_ynr_config(struct atomisp_sub_device *asd,
3483 struct atomisp_css_ynr_config *ynr_config)
3485 asd->params.config.ynr_config = ynr_config;
3488 void atomisp_css_set_fc_config(struct atomisp_sub_device *asd,
3489 struct atomisp_css_fc_config *fc_config)
3491 asd->params.config.fc_config = fc_config;
3494 void atomisp_css_set_ctc_config(struct atomisp_sub_device *asd,
3495 struct atomisp_css_ctc_config *ctc_config)
3497 asd->params.config.ctc_config = ctc_config;
3500 void atomisp_css_set_cnr_config(struct atomisp_sub_device *asd,
3501 struct atomisp_css_cnr_config *cnr_config)
3503 asd->params.config.cnr_config = cnr_config;
3506 void atomisp_css_set_aa_config(struct atomisp_sub_device *asd,
3507 struct atomisp_css_aa_config *aa_config)
3509 asd->params.config.aa_config = aa_config;
3512 void atomisp_css_set_baa_config(struct atomisp_sub_device *asd,
3513 struct atomisp_css_baa_config *baa_config)
3515 asd->params.config.baa_config = baa_config;
3518 void atomisp_css_set_anr_config(struct atomisp_sub_device *asd,
3519 struct atomisp_css_anr_config *anr_config)
3521 asd->params.config.anr_config = anr_config;
3524 void atomisp_css_set_xnr_config(struct atomisp_sub_device *asd,
3525 struct atomisp_css_xnr_config *xnr_config)
3527 asd->params.config.xnr_config = xnr_config;
3530 void atomisp_css_set_yuv2rgb_cc_config(struct atomisp_sub_device *asd,
3531 struct atomisp_css_cc_config *yuv2rgb_cc_config)
3533 asd->params.config.yuv2rgb_cc_config = yuv2rgb_cc_config;
3536 void atomisp_css_set_rgb2yuv_cc_config(struct atomisp_sub_device *asd,
3537 struct atomisp_css_cc_config *rgb2yuv_cc_config)
3539 asd->params.config.rgb2yuv_cc_config = rgb2yuv_cc_config;
3542 void atomisp_css_set_xnr_table(struct atomisp_sub_device *asd,
3543 struct atomisp_css_xnr_table *xnr_table)
3545 asd->params.config.xnr_table = xnr_table;
3548 void atomisp_css_set_r_gamma_table(struct atomisp_sub_device *asd,
3549 struct atomisp_css_rgb_gamma_table *r_gamma_table)
3551 asd->params.config.r_gamma_table = r_gamma_table;
3554 void atomisp_css_set_g_gamma_table(struct atomisp_sub_device *asd,
3555 struct atomisp_css_rgb_gamma_table *g_gamma_table)
3557 asd->params.config.g_gamma_table = g_gamma_table;
3560 void atomisp_css_set_b_gamma_table(struct atomisp_sub_device *asd,
3561 struct atomisp_css_rgb_gamma_table *b_gamma_table)
3563 asd->params.config.b_gamma_table = b_gamma_table;
3566 void atomisp_css_set_gamma_table(struct atomisp_sub_device *asd,
3567 struct atomisp_css_gamma_table *gamma_table)
3569 asd->params.config.gamma_table = gamma_table;
3572 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
3573 struct atomisp_css_ctc_table *ctc_table)
3576 uint16_t *vamem_ptr = ctc_table->data.vamem_1;
3577 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
3580 /* workaround: if ctc_table is all 0, do not apply it */
3581 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
3582 vamem_ptr = ctc_table->data.vamem_2;
3583 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
3586 for (i = 0; i < data_size; i++) {
3587 if (*(vamem_ptr + i)) {
3594 asd->params.config.ctc_table = ctc_table;
3596 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
3599 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
3600 struct atomisp_css_anr_thres *anr_thres)
3602 asd->params.config.anr_thres = anr_thres;
3605 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
3606 struct atomisp_css_dvs_6axis *dvs_6axis)
3608 asd->params.config.dvs_6axis_config = dvs_6axis;
3611 void atomisp_css_set_gc_config(struct atomisp_sub_device *asd,
3612 struct atomisp_css_gc_config *gc_config)
3614 asd->params.config.gc_config = gc_config;
3617 void atomisp_css_set_3a_config(struct atomisp_sub_device *asd,
3618 struct atomisp_css_3a_config *s3a_config)
3620 asd->params.config.s3a_config = s3a_config;
3623 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
3624 struct atomisp_dis_vector *vector)
3626 if (!asd->params.config.motion_vector)
3627 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
3629 memset(asd->params.config.motion_vector,
3630 0, sizeof(struct ia_css_vector));
3631 asd->params.css_param.motion_vector.x = vector->x;
3632 asd->params.css_param.motion_vector.y = vector->y;
3635 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
3636 struct atomisp_dvs_grid_info *atomgrid)
3638 struct atomisp_css_dvs_grid_info *cur =
3639 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
3642 dev_err(asd->isp->dev, "dvs grid not available!\n");
3646 if (sizeof(*cur) != sizeof(*atomgrid)) {
3647 dev_err(asd->isp->dev, "dvs grid mis-match!\n");
3652 dev_err(asd->isp->dev, "dvs not enabled!\n");
3656 return memcmp(atomgrid, cur, sizeof(*cur));
3659 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
3660 struct ia_css_dvs2_coefficients *coefs)
3662 asd->params.config.dvs2_coefs = coefs;
3665 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
3666 struct atomisp_dis_coefficients *coefs)
3668 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
3669 /* If the grid info in the argument differs from the current
3670 grid info, we tell the caller to reset the grid size and
3674 if (coefs->hor_coefs.odd_real == NULL ||
3675 coefs->hor_coefs.odd_imag == NULL ||
3676 coefs->hor_coefs.even_real == NULL ||
3677 coefs->hor_coefs.even_imag == NULL ||
3678 coefs->ver_coefs.odd_real == NULL ||
3679 coefs->ver_coefs.odd_imag == NULL ||
3680 coefs->ver_coefs.even_real == NULL ||
3681 coefs->ver_coefs.even_imag == NULL ||
3682 asd->params.css_param.dvs2_coeff->hor_coefs.odd_real == NULL ||
3683 asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag == NULL ||
3684 asd->params.css_param.dvs2_coeff->hor_coefs.even_real == NULL ||
3685 asd->params.css_param.dvs2_coeff->hor_coefs.even_imag == NULL ||
3686 asd->params.css_param.dvs2_coeff->ver_coefs.odd_real == NULL ||
3687 asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag == NULL ||
3688 asd->params.css_param.dvs2_coeff->ver_coefs.even_real == NULL ||
3689 asd->params.css_param.dvs2_coeff->ver_coefs.even_imag == NULL)
3692 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
3693 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
3695 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
3696 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
3698 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
3699 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
3701 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
3702 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
3705 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
3706 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
3708 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
3709 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
3711 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
3712 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
3714 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
3715 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
3718 asd->params.css_param.update_flag.dvs2_coefs =
3719 (struct atomisp_dvs2_coefficients *)
3720 asd->params.css_param.dvs2_coeff;
3722 /* asd->params.dis_proj_data_valid = false; */
3723 asd->params.css_update_params_needed = true;
3728 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
3731 struct atomisp_device *isp = asd->isp;
3733 if (zoom == asd->params.css_param.dz_config.dx &&
3734 zoom == asd->params.css_param.dz_config.dy) {
3735 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
3739 memset(&asd->params.css_param.dz_config, 0,
3740 sizeof(struct ia_css_dz_config));
3741 asd->params.css_param.dz_config.dx = zoom;
3742 asd->params.css_param.dz_config.dy = zoom;
3744 asd->params.css_param.update_flag.dz_config =
3745 (struct atomisp_dz_config *) &asd->params.css_param.dz_config;
3746 asd->params.css_update_params_needed = true;
3749 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
3750 struct atomisp_css_formats_config *formats_config)
3752 asd->params.config.formats_config = formats_config;
3755 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
3756 struct atomisp_wb_config *config)
3758 struct atomisp_css_wb_config wb_config;
3759 struct ia_css_isp_config isp_config;
3760 struct atomisp_device *isp = asd->isp;
3762 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3763 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3767 memset(&wb_config, 0, sizeof(struct atomisp_css_wb_config));
3768 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3769 isp_config.wb_config = &wb_config;
3770 ia_css_stream_get_isp_config(
3771 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3773 memcpy(config, &wb_config, sizeof(*config));
3778 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
3779 struct atomisp_ob_config *config)
3781 struct atomisp_css_ob_config ob_config;
3782 struct ia_css_isp_config isp_config;
3783 struct atomisp_device *isp = asd->isp;
3785 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3786 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3790 memset(&ob_config, 0, sizeof(struct atomisp_css_ob_config));
3791 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3792 isp_config.ob_config = &ob_config;
3793 ia_css_stream_get_isp_config(
3794 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3796 memcpy(config, &ob_config, sizeof(*config));
3801 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
3802 struct atomisp_dp_config *config)
3804 struct atomisp_css_dp_config dp_config;
3805 struct ia_css_isp_config isp_config;
3806 struct atomisp_device *isp = asd->isp;
3808 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3809 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3813 memset(&dp_config, 0, sizeof(struct atomisp_css_dp_config));
3814 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3815 isp_config.dp_config = &dp_config;
3816 ia_css_stream_get_isp_config(
3817 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3819 memcpy(config, &dp_config, sizeof(*config));
3824 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3825 struct atomisp_de_config *config)
3827 struct atomisp_css_de_config de_config;
3828 struct ia_css_isp_config isp_config;
3829 struct atomisp_device *isp = asd->isp;
3831 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3832 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3836 memset(&de_config, 0, sizeof(struct atomisp_css_de_config));
3837 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3838 isp_config.de_config = &de_config;
3839 ia_css_stream_get_isp_config(
3840 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3842 memcpy(config, &de_config, sizeof(*config));
3847 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3848 struct atomisp_nr_config *config)
3850 struct atomisp_css_nr_config nr_config;
3851 struct ia_css_isp_config isp_config;
3852 struct atomisp_device *isp = asd->isp;
3854 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3855 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3859 memset(&nr_config, 0, sizeof(struct atomisp_css_nr_config));
3860 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3862 isp_config.nr_config = &nr_config;
3863 ia_css_stream_get_isp_config(
3864 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3866 memcpy(config, &nr_config, sizeof(*config));
3871 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3872 struct atomisp_ee_config *config)
3874 struct atomisp_css_ee_config ee_config;
3875 struct ia_css_isp_config isp_config;
3876 struct atomisp_device *isp = asd->isp;
3878 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3879 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3883 memset(&ee_config, 0, sizeof(struct atomisp_css_ee_config));
3884 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3885 isp_config.ee_config = &ee_config;
3886 ia_css_stream_get_isp_config(
3887 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3889 memcpy(config, &ee_config, sizeof(*config));
3894 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3895 struct atomisp_tnr_config *config)
3897 struct atomisp_css_tnr_config tnr_config;
3898 struct ia_css_isp_config isp_config;
3899 struct atomisp_device *isp = asd->isp;
3901 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3902 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3906 memset(&tnr_config, 0, sizeof(struct atomisp_css_tnr_config));
3907 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3908 isp_config.tnr_config = &tnr_config;
3909 ia_css_stream_get_isp_config(
3910 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3912 memcpy(config, &tnr_config, sizeof(*config));
3917 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3918 struct atomisp_ctc_table *config)
3920 struct atomisp_css_ctc_table *tab;
3921 struct ia_css_isp_config isp_config;
3922 struct atomisp_device *isp = asd->isp;
3924 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3925 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3930 tab = vzalloc(sizeof(struct atomisp_css_ctc_table));
3934 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3935 isp_config.ctc_table = tab;
3936 ia_css_stream_get_isp_config(
3937 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3939 memcpy(config, tab, sizeof(*tab));
3945 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
3946 struct atomisp_gamma_table *config)
3948 struct atomisp_css_gamma_table *tab;
3949 struct ia_css_isp_config isp_config;
3950 struct atomisp_device *isp = asd->isp;
3952 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3953 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3958 tab = vzalloc(sizeof(struct atomisp_css_gamma_table));
3962 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3963 isp_config.gamma_table = tab;
3964 ia_css_stream_get_isp_config(
3965 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3967 memcpy(config, tab, sizeof(*tab));
3973 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
3974 struct atomisp_gc_config *config)
3976 struct atomisp_css_gc_config gc_config;
3977 struct ia_css_isp_config isp_config;
3978 struct atomisp_device *isp = asd->isp;
3980 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3981 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3985 memset(&gc_config, 0, sizeof(struct atomisp_css_gc_config));
3986 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3987 isp_config.gc_config = &gc_config;
3988 ia_css_stream_get_isp_config(
3989 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3991 /* Get gamma correction params from current setup */
3992 memcpy(config, &gc_config, sizeof(*config));
3997 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
3998 struct atomisp_3a_config *config)
4000 struct atomisp_css_3a_config s3a_config;
4001 struct ia_css_isp_config isp_config;
4002 struct atomisp_device *isp = asd->isp;
4004 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4005 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4009 memset(&s3a_config, 0, sizeof(struct atomisp_css_3a_config));
4010 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4011 isp_config.s3a_config = &s3a_config;
4012 ia_css_stream_get_isp_config(
4013 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4015 /* Get white balance from current setup */
4016 memcpy(config, &s3a_config, sizeof(*config));
4021 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
4022 struct atomisp_formats_config *config)
4024 struct atomisp_css_formats_config formats_config;
4025 struct ia_css_isp_config isp_config;
4026 struct atomisp_device *isp = asd->isp;
4028 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4029 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4033 memset(&formats_config, 0, sizeof(formats_config));
4034 memset(&isp_config, 0, sizeof(isp_config));
4035 isp_config.formats_config = &formats_config;
4036 ia_css_stream_get_isp_config(
4037 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4039 /* Get narrow gamma from current setup */
4040 memcpy(config, &formats_config, sizeof(*config));
4045 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
4048 struct ia_css_dz_config dz_config; /**< Digital Zoom */
4049 struct ia_css_isp_config isp_config;
4050 struct atomisp_device *isp = asd->isp;
4052 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4053 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4057 memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
4058 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4059 isp_config.dz_config = &dz_config;
4060 ia_css_stream_get_isp_config(
4061 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4063 *zoom = dz_config.dx;
4070 * Function to set/get image stablization statistics
4072 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
4073 struct atomisp_dis_statistics *stats)
4075 struct atomisp_device *isp = asd->isp;
4076 struct atomisp_dis_buf *dis_buf;
4077 unsigned long flags;
4079 if (asd->params.dvs_stat->hor_prod.odd_real == NULL ||
4080 asd->params.dvs_stat->hor_prod.odd_imag == NULL ||
4081 asd->params.dvs_stat->hor_prod.even_real == NULL ||
4082 asd->params.dvs_stat->hor_prod.even_imag == NULL ||
4083 asd->params.dvs_stat->ver_prod.odd_real == NULL ||
4084 asd->params.dvs_stat->ver_prod.odd_imag == NULL ||
4085 asd->params.dvs_stat->ver_prod.even_real == NULL ||
4086 asd->params.dvs_stat->ver_prod.even_imag == NULL)
4089 /* isp needs to be streaming to get DIS statistics */
4090 spin_lock_irqsave(&isp->lock, flags);
4091 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) {
4092 spin_unlock_irqrestore(&isp->lock, flags);
4095 spin_unlock_irqrestore(&isp->lock, flags);
4097 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
4098 /* If the grid info in the argument differs from the current
4099 grid info, we tell the caller to reset the grid size and
4103 spin_lock_irqsave(&asd->dis_stats_lock, flags);
4104 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
4105 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4106 dev_err(isp->dev, "dis statistics is not valid.\n");
4110 dis_buf = list_entry(asd->dis_stats.next,
4111 struct atomisp_dis_buf, list);
4112 list_del_init(&dis_buf->list);
4113 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4115 if (dis_buf->dvs_map)
4116 ia_css_translate_dvs2_statistics(
4117 asd->params.dvs_stat, dis_buf->dvs_map);
4119 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
4121 stats->exp_id = dis_buf->dis_data->exp_id;
4123 spin_lock_irqsave(&asd->dis_stats_lock, flags);
4124 list_add_tail(&dis_buf->list, &asd->dis_stats);
4125 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4127 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
4128 asd->params.dvs_stat->ver_prod.odd_real,
4129 asd->params.dvs_ver_proj_bytes))
4131 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
4132 asd->params.dvs_stat->ver_prod.odd_imag,
4133 asd->params.dvs_ver_proj_bytes))
4135 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
4136 asd->params.dvs_stat->ver_prod.even_real,
4137 asd->params.dvs_ver_proj_bytes))
4139 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
4140 asd->params.dvs_stat->ver_prod.even_imag,
4141 asd->params.dvs_ver_proj_bytes))
4143 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
4144 asd->params.dvs_stat->hor_prod.odd_real,
4145 asd->params.dvs_hor_proj_bytes))
4147 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
4148 asd->params.dvs_stat->hor_prod.odd_imag,
4149 asd->params.dvs_hor_proj_bytes))
4151 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
4152 asd->params.dvs_stat->hor_prod.even_real,
4153 asd->params.dvs_hor_proj_bytes))
4155 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
4156 asd->params.dvs_stat->hor_prod.even_imag,
4157 asd->params.dvs_hor_proj_bytes))
4163 struct atomisp_css_shading_table *atomisp_css_shading_table_alloc(
4164 unsigned int width, unsigned int height)
4166 return ia_css_shading_table_alloc(width, height);
4169 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
4170 struct atomisp_css_shading_table *table)
4172 asd->params.config.shading_table = table;
4175 void atomisp_css_shading_table_free(struct atomisp_css_shading_table *table)
4177 ia_css_shading_table_free(table);
4180 struct atomisp_css_morph_table *atomisp_css_morph_table_allocate(
4181 unsigned int width, unsigned int height)
4183 return ia_css_morph_table_allocate(width, height);
4186 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
4187 struct atomisp_css_morph_table *table)
4189 asd->params.config.morph_table = table;
4192 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
4193 struct atomisp_css_morph_table *table)
4195 struct ia_css_isp_config isp_config;
4196 struct atomisp_device *isp = asd->isp;
4198 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4200 "%s called after streamoff, skipping.\n", __func__);
4203 memset(table, 0, sizeof(struct atomisp_css_morph_table));
4204 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4205 isp_config.morph_table = table;
4206 ia_css_stream_get_isp_config(
4207 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4211 void atomisp_css_morph_table_free(struct atomisp_css_morph_table *table)
4213 ia_css_morph_table_free(table);
4216 void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp,
4217 unsigned int overlap)
4219 /* CSS 2.0 doesn't support this API. */
4220 dev_dbg(isp->dev, "set cont prev start time is not supported.\n");
4224 void atomisp_css_acc_done(struct atomisp_sub_device *asd)
4226 complete(&asd->acc.acc_done);
4229 int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd)
4232 struct atomisp_device *isp = asd->isp;
4234 /* Unlock the isp mutex taken in IOCTL handler before sleeping! */
4235 rt_mutex_unlock(&isp->mutex);
4236 if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done,
4237 ATOMISP_ISP_TIMEOUT_DURATION) == 0) {
4238 dev_err(isp->dev, "<%s: completion timeout\n", __func__);
4239 atomisp_css_debug_dump_sp_sw_debug_info();
4240 atomisp_css_debug_dump_debug_info(__func__);
4243 rt_mutex_lock(&isp->mutex);
4248 /* Set the ACC binary arguments */
4249 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw)
4253 for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) {
4254 if (acc_fw->args[mem].length == 0)
4257 ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers,
4258 IA_CSS_PARAM_CLASS_PARAM, mem,
4259 acc_fw->args[mem].css_ptr,
4260 acc_fw->args[mem].length);
4266 /* Load acc binary extension */
4267 int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd,
4268 struct atomisp_css_fw_info *fw,
4269 enum atomisp_css_pipe_id pipe_id,
4272 struct atomisp_css_fw_info **hd;
4275 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4276 .pipe_configs[pipe_id].acc_extension);
4281 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4282 .update_pipe[pipe_id] = true;
4286 /* Unload acc binary extension */
4287 void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd,
4288 struct atomisp_css_fw_info *fw,
4289 enum atomisp_css_pipe_id pipe_id)
4291 struct atomisp_css_fw_info **hd;
4293 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4294 .pipe_configs[pipe_id].acc_extension);
4295 while (*hd && *hd != fw)
4298 dev_err(asd->isp->dev, "did not find acc fw for removal\n");
4304 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4305 .update_pipe[pipe_id] = true;
4308 int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd)
4310 struct atomisp_device *isp = asd->isp;
4311 struct ia_css_pipe_config *pipe_config;
4312 struct atomisp_stream_env *stream_env =
4313 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4315 if (stream_env->acc_stream) {
4316 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4317 if (ia_css_stream_stop(stream_env->acc_stream)
4318 != IA_CSS_SUCCESS) {
4319 dev_err(isp->dev, "stop acc_stream failed.\n");
4324 if (ia_css_stream_destroy(stream_env->acc_stream)
4325 != IA_CSS_SUCCESS) {
4326 dev_err(isp->dev, "destroy acc_stream failed.\n");
4329 stream_env->acc_stream = NULL;
4332 pipe_config = &stream_env->pipe_configs[CSS_PIPE_ID_ACC];
4333 ia_css_pipe_config_defaults(pipe_config);
4334 asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES *
4335 sizeof(void *), GFP_KERNEL);
4336 if (!asd->acc.acc_stages)
4338 pipe_config->acc_stages = asd->acc.acc_stages;
4339 pipe_config->mode = IA_CSS_PIPE_MODE_ACC;
4340 pipe_config->num_acc_stages = 0;
4343 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe,
4344 * because pipe configuration will soon be changed by
4345 * atomisp_css_load_acc_binary()
4350 int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd)
4352 struct atomisp_device *isp = asd->isp;
4353 struct atomisp_stream_env *stream_env =
4354 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4355 struct ia_css_pipe_config *pipe_config =
4356 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
4358 if (ia_css_pipe_create(pipe_config,
4359 &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != IA_CSS_SUCCESS) {
4360 dev_err(isp->dev, "%s: ia_css_pipe_create failed\n",
4365 memset(&stream_env->acc_stream_config, 0,
4366 sizeof(struct ia_css_stream_config));
4367 if (ia_css_stream_create(&stream_env->acc_stream_config, 1,
4368 &stream_env->pipes[IA_CSS_PIPE_ID_ACC],
4369 &stream_env->acc_stream) != IA_CSS_SUCCESS) {
4370 dev_err(isp->dev, "%s: create acc_stream error.\n", __func__);
4373 stream_env->acc_stream_state = CSS_STREAM_CREATED;
4375 init_completion(&asd->acc.acc_done);
4376 asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC];
4378 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
4380 if (ia_css_start_sp() != IA_CSS_SUCCESS) {
4381 dev_err(isp->dev, "start sp error.\n");
4385 if (ia_css_stream_start(stream_env->acc_stream)
4386 != IA_CSS_SUCCESS) {
4387 dev_err(isp->dev, "acc_stream start error.\n");
4391 stream_env->acc_stream_state = CSS_STREAM_STARTED;
4395 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd)
4397 struct atomisp_stream_env *stream_env =
4398 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4399 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4400 ia_css_stream_stop(stream_env->acc_stream);
4401 stream_env->acc_stream_state = CSS_STREAM_STOPPED;
4406 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd)
4408 struct atomisp_stream_env *stream_env =
4409 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4410 if (stream_env->acc_stream) {
4411 if (ia_css_stream_destroy(stream_env->acc_stream)
4413 dev_warn(asd->isp->dev,
4414 "destroy acc_stream failed.\n");
4415 stream_env->acc_stream = NULL;
4418 if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) {
4419 if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC])
4421 dev_warn(asd->isp->dev,
4422 "destroy ACC pipe failed.\n");
4423 stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL;
4424 stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false;
4425 ia_css_pipe_config_defaults(
4426 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]);
4427 ia_css_pipe_extra_config_defaults(
4428 &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]);
4430 asd->acc.pipeline = NULL;
4432 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
4437 kfree(asd->acc.acc_stages);
4438 asd->acc.acc_stages = NULL;
4440 atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false);
4443 int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd,
4444 struct atomisp_css_fw_info *fw,
4447 struct ia_css_pipe_config *pipe_config =
4448 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4449 .pipe_configs[IA_CSS_PIPE_ID_ACC];
4451 if (index >= MAX_ACC_STAGES) {
4452 dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n",
4457 pipe_config->acc_stages[index] = fw;
4458 pipe_config->num_acc_stages = index + 1;
4459 pipe_config->acc_num_execs = 1;
4464 static struct atomisp_sub_device *__get_atomisp_subdev(
4465 struct ia_css_pipe *css_pipe,
4466 struct atomisp_device *isp,
4467 enum atomisp_input_stream_id *stream_id) {
4469 struct atomisp_sub_device *asd;
4470 struct atomisp_stream_env *stream_env;
4472 for (i = 0; i < isp->num_of_streams; i++) {
4474 if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED &&
4477 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4478 stream_env = &asd->stream_env[j];
4479 for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
4480 if (stream_env->pipes[k] &&
4481 stream_env->pipes[k] == css_pipe) {
4492 int atomisp_css_isr_thread(struct atomisp_device *isp,
4493 bool *frame_done_found,
4494 bool *css_pipe_done)
4496 enum atomisp_input_stream_id stream_id = 0;
4497 struct atomisp_css_event current_event;
4498 struct atomisp_sub_device *asd = &isp->asd[0];
4500 bool reset_wdt_timer[MAX_STREAM_NUM] = {false};
4504 while (!atomisp_css_dequeue_event(¤t_event)) {
4505 if (current_event.event.type ==
4506 IA_CSS_EVENT_TYPE_FW_ASSERT) {
4508 * Received FW assertion signal,
4509 * trigger WDT to recover
4511 dev_err(isp->dev, "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
4513 current_event.event.fw_assert_module_id,
4514 current_event.event.fw_assert_line_no);
4515 for (i = 0; i < isp->num_of_streams; i++)
4516 atomisp_wdt_stop(&isp->asd[i], 0);
4518 atomisp_wdt((unsigned long)isp);
4520 queue_work(isp->wdt_work_queue, &isp->wdt_work);
4523 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4524 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
4525 __func__, current_event.event.fw_warning,
4526 current_event.event.exp_id);
4530 asd = __get_atomisp_subdev(current_event.event.pipe,
4533 if (current_event.event.type == CSS_EVENT_TIMER)
4535 "event: Timer event.");
4537 dev_warn(isp->dev, "%s:no subdev.event:%d",
4539 current_event.event.type);
4543 atomisp_css_temp_pipe_to_pipe_id(asd, ¤t_event);
4544 switch (current_event.event.type) {
4545 case CSS_EVENT_OUTPUT_FRAME_DONE:
4546 frame_done_found[asd->index] = true;
4547 atomisp_buf_done(asd, 0, CSS_BUFFER_TYPE_OUTPUT_FRAME,
4548 current_event.pipe, true, stream_id);
4550 reset_wdt_timer[asd->index] = true; /* ISP running */
4553 case CSS_EVENT_SEC_OUTPUT_FRAME_DONE:
4554 frame_done_found[asd->index] = true;
4555 atomisp_buf_done(asd, 0, CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
4556 current_event.pipe, true, stream_id);
4558 reset_wdt_timer[asd->index] = true; /* ISP running */
4561 case CSS_EVENT_3A_STATISTICS_DONE:
4562 atomisp_buf_done(asd, 0,
4563 CSS_BUFFER_TYPE_3A_STATISTICS,
4567 case CSS_EVENT_METADATA_DONE:
4568 atomisp_buf_done(asd, 0,
4569 CSS_BUFFER_TYPE_METADATA,
4573 case CSS_EVENT_VF_OUTPUT_FRAME_DONE:
4574 atomisp_buf_done(asd, 0,
4575 CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
4576 current_event.pipe, true, stream_id);
4578 reset_wdt_timer[asd->index] = true; /* ISP running */
4581 case CSS_EVENT_SEC_VF_OUTPUT_FRAME_DONE:
4582 atomisp_buf_done(asd, 0,
4583 CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
4584 current_event.pipe, true, stream_id);
4586 reset_wdt_timer[asd->index] = true; /* ISP running */
4589 case CSS_EVENT_DIS_STATISTICS_DONE:
4590 atomisp_buf_done(asd, 0,
4591 CSS_BUFFER_TYPE_DIS_STATISTICS,
4595 case CSS_EVENT_PIPELINE_DONE:
4596 css_pipe_done[asd->index] = true;
4598 case CSS_EVENT_ACC_STAGE_COMPLETE:
4599 atomisp_acc_done(asd, current_event.event.fw_handle);
4602 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
4603 current_event.event.type);
4608 /* If there are no buffers queued then
4609 * delete wdt timer. */
4610 for (i = 0; i < isp->num_of_streams; i++) {
4614 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
4616 if (!atomisp_buffers_queued(asd))
4617 atomisp_wdt_stop(asd, false);
4618 else if (reset_wdt_timer[i])
4619 /* SOF irq should not reset wdt timer. */
4620 atomisp_wdt_refresh(asd,
4621 ATOMISP_WDT_KEEP_CURRENT_DELAY);
4628 bool atomisp_css_valid_sof(struct atomisp_device *isp)
4632 /* Loop for each css stream */
4633 for (i = 0; i < isp->num_of_streams; i++) {
4634 struct atomisp_sub_device *asd = &isp->asd[i];
4635 /* Loop for each css vc stream */
4636 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4637 if (asd->stream_env[j].stream &&
4638 asd->stream_env[j].stream_config.mode ==
4639 IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
4647 int atomisp_css_debug_dump_isp_binary(void)
4649 ia_css_debug_dump_isp_binary();
4653 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
4655 sh_css_dump_sp_raw_copy_linecount(reduced);
4659 int atomisp_css_dump_blob_infor(void)
4661 struct ia_css_blob_descr *bd = sh_css_blob_info;
4662 unsigned i, nm = sh_css_num_binaries;
4669 for (i = 1; i < sh_css_num_binaries; i++)
4670 dev_dbg(atomisp_dev, "Num%d binary id is %d, name is %s\n", i,
4671 bd[i-1].header.info.isp.sp.id, bd[i-1].name);
4676 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
4677 uint32_t isp_config_id)
4679 asd->params.config.isp_config_id = isp_config_id;
4682 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
4683 struct atomisp_css_frame *output_frame)
4685 asd->params.config.output_frame = output_frame;
4688 int atomisp_get_css_dbgfunc(void)
4693 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
4697 ret = __set_css_print_env(isp, opt);
4703 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
4705 ia_css_en_dz_capt_pipe(
4706 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4710 struct atomisp_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
4711 struct atomisp_css_grid_info *grid_info)
4716 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
4717 return &grid_info->dvs_grid.dvs_grid_info;
4719 return &grid_info->dvs_grid;