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.
18 #include <media/videobuf-vmalloc.h>
19 #include <media/v4l2-dev.h>
20 #include <media/v4l2-event.h>
22 #include "mmu/isp_mmu.h"
23 #include "mmu/sh_mmu_mrfld.h"
24 #include "hmm/hmm_bo.h"
27 #include "atomisp_compat.h"
28 #include "atomisp_internal.h"
29 #include "atomisp_cmd.h"
30 #include "atomisp-regs.h"
31 #include "atomisp_fops.h"
32 #include "atomisp_ioctl.h"
33 #include "atomisp_acc.h"
35 #include <asm/intel-mid.h>
37 #include "ia_css_debug.h"
38 #include "ia_css_isp_param.h"
39 #include "sh_css_hrt.h"
40 #include "ia_css_isys.h"
42 #include <linux/pm_runtime.h>
44 /* Assume max number of ACC stages */
45 #define MAX_ACC_STAGES 20
47 /* Ideally, this should come from CSS headers */
51 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
52 * #4684168, if concurrency access happened, system may hard hang.
54 static DEFINE_SPINLOCK(mmio_lock);
56 enum frame_info_type {
58 ATOMISP_CSS_SECOND_VF_FRAME,
59 ATOMISP_CSS_OUTPUT_FRAME,
60 ATOMISP_CSS_SECOND_OUTPUT_FRAME,
61 ATOMISP_CSS_RAW_FRAME,
64 struct bayer_ds_factor {
65 unsigned int numerator;
66 unsigned int denominator;
69 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
73 spin_lock_irqsave(&mmio_lock, flags);
74 _hrt_master_port_store_8(addr, data);
75 spin_unlock_irqrestore(&mmio_lock, flags);
78 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
82 spin_lock_irqsave(&mmio_lock, flags);
83 _hrt_master_port_store_16(addr, data);
84 spin_unlock_irqrestore(&mmio_lock, flags);
87 void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
91 spin_lock_irqsave(&mmio_lock, flags);
92 _hrt_master_port_store_32(addr, data);
93 spin_unlock_irqrestore(&mmio_lock, flags);
96 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
101 spin_lock_irqsave(&mmio_lock, flags);
102 ret = _hrt_master_port_load_8(addr);
103 spin_unlock_irqrestore(&mmio_lock, flags);
107 static uint16_t atomisp_css2_hw_load_16(hrt_address addr)
112 spin_lock_irqsave(&mmio_lock, flags);
113 ret = _hrt_master_port_load_16(addr);
114 spin_unlock_irqrestore(&mmio_lock, flags);
118 static uint32_t atomisp_css2_hw_load_32(hrt_address addr)
123 spin_lock_irqsave(&mmio_lock, flags);
124 ret = _hrt_master_port_load_32(addr);
125 spin_unlock_irqrestore(&mmio_lock, flags);
129 static void atomisp_css2_hw_store(hrt_address addr,
130 const void *from, uint32_t n)
134 unsigned int _to = (unsigned int)addr;
135 const char *_from = (const char *)from;
137 spin_lock_irqsave(&mmio_lock, flags);
138 for (i = 0; i < n; i++, _to++, _from++)
139 _hrt_master_port_store_8(_to, *_from);
140 spin_unlock_irqrestore(&mmio_lock, flags);
143 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
147 char *_to = (char *)to;
148 unsigned int _from = (unsigned int)addr;
150 spin_lock_irqsave(&mmio_lock, flags);
151 for (i = 0; i < n; i++, _to++, _from++)
152 *_to = _hrt_master_port_load_8(_from);
153 spin_unlock_irqrestore(&mmio_lock, flags);
156 static int atomisp_css2_dbg_print(const char *fmt, va_list args)
162 static int atomisp_css2_dbg_ftrace_print(const char *fmt, va_list args)
164 ftrace_vprintk(fmt, args);
168 static int atomisp_css2_err_print(const char *fmt, va_list args)
174 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
176 *data = atomisp_css2_hw_load_32(addr);
179 static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr)
181 if (!sh_mmu_mrfld.get_pd_base) {
182 dev_err(atomisp_dev, "get mmu base address failed.\n");
186 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
187 bo_device.mmu.base_address);
191 static void __dump_pipe_config(struct atomisp_sub_device *asd,
192 struct atomisp_stream_env *stream_env,
193 unsigned int pipe_id)
195 struct atomisp_device *isp = asd->isp;
197 if (stream_env->pipes[pipe_id]) {
198 struct ia_css_pipe_config *p_config;
199 struct ia_css_pipe_extra_config *pe_config;
201 p_config = &stream_env->pipe_configs[pipe_id];
202 pe_config = &stream_env->pipe_extra_configs[pipe_id];
203 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
205 "pipe_config.pipe_mode:%d.\n", p_config->mode);
207 "pipe_config.output_info[0] w=%d, h=%d.\n",
208 p_config->output_info[0].res.width,
209 p_config->output_info[0].res.height);
211 "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
212 p_config->vf_pp_in_res.width,
213 p_config->vf_pp_in_res.height);
215 "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
216 p_config->capt_pp_in_res.width,
217 p_config->capt_pp_in_res.height);
219 "pipe_config.output.padded w=%d.\n",
220 p_config->output_info[0].padded_width);
222 "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
223 p_config->vf_output_info[0].res.width,
224 p_config->vf_output_info[0].res.height);
226 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
227 p_config->bayer_ds_out_res.width,
228 p_config->bayer_ds_out_res.height);
230 "pipe_config.envelope w=%d, h=%d.\n",
231 p_config->dvs_envelope.width,
232 p_config->dvs_envelope.height);
234 "pipe_config.dvs_frame_delay=%d.\n",
235 p_config->dvs_frame_delay);
237 "pipe_config.isp_pipe_version:%d.\n",
238 p_config->isp_pipe_version);
240 "pipe_config.acc_extension=%p.\n",
241 p_config->acc_extension);
243 "pipe_config.acc_stages=%p.\n",
244 p_config->acc_stages);
246 "pipe_config.num_acc_stages=%d.\n",
247 p_config->num_acc_stages);
249 "pipe_config.acc_num_execs=%d.\n",
250 p_config->acc_num_execs);
252 "pipe_config.default_capture_config.capture_mode=%d.\n",
253 p_config->default_capture_config.mode);
255 "pipe_config.enable_dz=%d.\n",
256 p_config->enable_dz);
258 "pipe_config.default_capture_config.enable_xnr=%d.\n",
259 p_config->default_capture_config.enable_xnr);
261 "dumping pipe[%d] extra config:\n", pipe_id);
263 "pipe_extra_config.enable_raw_binning:%d.\n",
264 pe_config->enable_raw_binning);
266 "pipe_extra_config.enable_yuv_ds:%d.\n",
267 pe_config->enable_yuv_ds);
269 "pipe_extra_config.enable_high_speed:%d.\n",
270 pe_config->enable_high_speed);
272 "pipe_extra_config.enable_dvs_6axis:%d.\n",
273 pe_config->enable_dvs_6axis);
275 "pipe_extra_config.enable_reduced_pipe:%d.\n",
276 pe_config->enable_reduced_pipe);
278 "pipe_(extra_)config.enable_dz:%d.\n",
279 p_config->enable_dz);
281 "pipe_extra_config.disable_vf_pp:%d.\n",
282 pe_config->disable_vf_pp);
286 static void __dump_stream_config(struct atomisp_sub_device *asd,
287 struct atomisp_stream_env *stream_env)
289 struct atomisp_device *isp = asd->isp;
290 struct ia_css_stream_config *s_config;
292 bool valid_stream = false;
294 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
295 if (stream_env->pipes[j]) {
296 __dump_pipe_config(asd, stream_env, j);
302 s_config = &stream_env->stream_config;
303 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
305 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
306 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
307 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
308 s_config->source.port.port);
309 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
310 s_config->source.port.num_lanes);
311 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
312 s_config->source.port.timeout);
313 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
314 s_config->source.port.rxcount);
315 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
316 s_config->source.port.compression.type);
318 "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
319 s_config->source.port.compression.
320 compressed_bits_per_pixel);
322 "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
323 s_config->source.port.compression.
324 uncompressed_bits_per_pixel);
325 } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
326 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
327 s_config->source.tpg.id);
328 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
329 s_config->source.tpg.mode);
330 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
331 s_config->source.tpg.x_mask);
332 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
333 s_config->source.tpg.x_delta);
334 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
335 s_config->source.tpg.y_mask);
336 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
337 s_config->source.tpg.y_delta);
338 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
339 s_config->source.tpg.xy_mask);
340 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
341 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
342 s_config->source.prbs.id);
343 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
344 s_config->source.prbs.h_blank);
345 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
346 s_config->source.prbs.v_blank);
347 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
348 s_config->source.prbs.seed);
349 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
350 s_config->source.prbs.seed1);
353 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
354 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
356 s_config->isys_config[j].input_res.width,
357 s_config->isys_config[j].input_res.height);
359 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
361 s_config->isys_config[j].linked_isys_stream_id);
363 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
365 s_config->isys_config[j].format);
367 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
369 s_config->isys_config[j].valid);
372 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
373 s_config->input_config.input_res.width,
374 s_config->input_config.input_res.height);
376 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
377 s_config->input_config.effective_res.width,
378 s_config->input_config.effective_res.height);
380 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
381 s_config->input_config.format);
383 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
384 s_config->input_config.bayer_order);
386 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
387 s_config->pixels_per_clock);
388 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
389 dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
390 s_config->continuous);
391 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
392 s_config->disable_cont_viewfinder);
393 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
394 s_config->channel_id);
395 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
396 s_config->init_num_cont_raw_buf);
397 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
398 s_config->target_num_cont_raw_buf);
399 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
400 s_config->left_padding);
401 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
402 s_config->sensor_binning_factor);
403 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
404 s_config->pixels_per_clock);
405 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
406 s_config->pack_raw_pixels);
407 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
408 s_config->flash_gpio_pin);
409 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
410 s_config->mipi_buffer_config.size_mem_words);
411 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
412 s_config->mipi_buffer_config.contiguous);
413 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
414 s_config->metadata_config.data_type);
415 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
416 s_config->metadata_config.resolution.width,
417 s_config->metadata_config.resolution.height);
420 static int __destroy_stream(struct atomisp_sub_device *asd,
421 struct atomisp_stream_env *stream_env, bool force)
423 struct atomisp_device *isp = asd->isp;
425 unsigned long timeout;
427 if (!stream_env->stream)
431 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
432 if (stream_env->update_pipe[i])
435 if (i == IA_CSS_PIPE_ID_NUM)
439 if (stream_env->stream_state == CSS_STREAM_STARTED
440 && ia_css_stream_stop(stream_env->stream) != 0) {
441 dev_err(isp->dev, "stop stream failed.\n");
445 if (stream_env->stream_state == CSS_STREAM_STARTED) {
446 timeout = jiffies + msecs_to_jiffies(40);
448 if (ia_css_stream_has_stopped(stream_env->stream))
451 if (time_after(jiffies, timeout)) {
452 dev_warn(isp->dev, "stop stream timeout.\n");
456 usleep_range(100, 200);
460 stream_env->stream_state = CSS_STREAM_STOPPED;
462 if (ia_css_stream_destroy(stream_env->stream)) {
463 dev_err(isp->dev, "destroy stream failed.\n");
466 stream_env->stream_state = CSS_STREAM_UNINIT;
467 stream_env->stream = NULL;
472 static int __destroy_streams(struct atomisp_sub_device *asd, bool force)
476 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
477 ret = __destroy_stream(asd, &asd->stream_env[i], force);
481 asd->stream_prepared = false;
485 static int __create_stream(struct atomisp_sub_device *asd,
486 struct atomisp_stream_env *stream_env)
488 int pipe_index = 0, i;
489 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
491 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
492 if (stream_env->pipes[i])
493 multi_pipes[pipe_index++] = stream_env->pipes[i];
498 stream_env->stream_config.target_num_cont_raw_buf =
499 asd->continuous_raw_buffer_size->val;
500 stream_env->stream_config.channel_id = stream_env->ch_id;
501 stream_env->stream_config.ia_css_enable_raw_buffer_locking =
502 asd->enable_raw_buffer_lock->val;
504 __dump_stream_config(asd, stream_env);
505 if (ia_css_stream_create(&stream_env->stream_config,
506 pipe_index, multi_pipes, &stream_env->stream) != 0)
508 if (ia_css_stream_get_info(stream_env->stream,
509 &stream_env->stream_info) != 0) {
510 ia_css_stream_destroy(stream_env->stream);
511 stream_env->stream = NULL;
515 stream_env->stream_state = CSS_STREAM_CREATED;
519 static int __create_streams(struct atomisp_sub_device *asd)
523 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
524 ret = __create_stream(asd, &asd->stream_env[i]);
528 asd->stream_prepared = true;
531 for (i--; i >= 0; i--)
532 __destroy_stream(asd, &asd->stream_env[i], true);
536 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
537 struct atomisp_stream_env *stream_env,
540 struct atomisp_device *isp = asd->isp;
544 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
545 if (!stream_env->pipes[i] ||
546 !(force || stream_env->update_pipe[i]))
548 if (ia_css_pipe_destroy(stream_env->pipes[i])
551 "destroy pipe[%d]failed.cannot recover.\n", i);
554 stream_env->pipes[i] = NULL;
555 stream_env->update_pipe[i] = false;
560 static int __destroy_pipes(struct atomisp_sub_device *asd, bool force)
562 struct atomisp_device *isp = asd->isp;
566 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
567 if (asd->stream_env[i].stream) {
569 "cannot destroy css pipes for stream[%d].\n",
574 ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force);
582 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
584 __destroy_streams(asd, true);
585 __destroy_pipes(asd, true);
588 static void __apply_additional_pipe_config(
589 struct atomisp_sub_device *asd,
590 struct atomisp_stream_env *stream_env,
591 enum ia_css_pipe_id pipe_id)
593 struct atomisp_device *isp = asd->isp;
595 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
597 "wrong pipe_id for additional pipe config.\n");
601 /* apply default pipe config */
602 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
603 stream_env->pipe_configs[pipe_id].enable_dz =
604 asd->disable_dz->val ? false : true;
605 /* apply isp 2.2 specific config for baytrail*/
607 case IA_CSS_PIPE_ID_CAPTURE:
608 /* enable capture pp/dz manually or digital zoom would
610 if (stream_env->pipe_configs[pipe_id].
611 default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW)
612 stream_env->pipe_configs[pipe_id].enable_dz = false;
614 if (atomisp_hw_is_isp2401) {
615 /* the isp default to use ISP2.2 and the camera hal will
616 * control whether use isp2.7 */
617 if (asd->select_isp_version->val == ATOMISP_CSS_ISP_PIPE_VERSION_2_7)
618 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_7;
620 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_2;
623 case IA_CSS_PIPE_ID_VIDEO:
624 /* enable reduced pipe to have binary
625 * video_dz_2_min selected*/
626 stream_env->pipe_extra_configs[pipe_id]
627 .enable_reduced_pipe = true;
628 stream_env->pipe_configs[pipe_id]
630 if (ATOMISP_SOC_CAMERA(asd))
631 stream_env->pipe_configs[pipe_id].enable_dz = true;
633 if (asd->params.video_dis_en) {
634 stream_env->pipe_extra_configs[pipe_id]
635 .enable_dvs_6axis = true;
636 stream_env->pipe_configs[pipe_id]
638 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
641 case IA_CSS_PIPE_ID_PREVIEW:
643 case IA_CSS_PIPE_ID_YUVPP:
644 case IA_CSS_PIPE_ID_COPY:
645 if (ATOMISP_SOC_CAMERA(asd))
646 stream_env->pipe_configs[pipe_id].enable_dz = true;
648 stream_env->pipe_configs[pipe_id].enable_dz = false;
650 case IA_CSS_PIPE_ID_ACC:
651 stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC;
652 stream_env->pipe_configs[pipe_id].enable_dz = false;
659 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
660 enum ia_css_pipe_id pipe_id)
665 if (pipe_id == IA_CSS_PIPE_ID_ACC || pipe_id == IA_CSS_PIPE_ID_YUVPP)
669 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
670 if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
674 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
675 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
685 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
688 switch (asd->run_mode->val) {
689 case ATOMISP_RUN_MODE_STILL_CAPTURE:
690 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
694 case ATOMISP_RUN_MODE_PREVIEW:
695 if (!asd->continuous_mode->val) {
696 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
701 /* fall through to ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE */
702 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
703 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
704 pipe_id == IA_CSS_PIPE_ID_PREVIEW)
708 case ATOMISP_RUN_MODE_VIDEO:
709 if (!asd->continuous_mode->val) {
710 if (pipe_id == IA_CSS_PIPE_ID_VIDEO ||
711 pipe_id == IA_CSS_PIPE_ID_YUVPP)
716 /* fall through to ATOMISP_RUN_MODE_SDV */
717 case ATOMISP_RUN_MODE_SDV:
718 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
719 pipe_id == IA_CSS_PIPE_ID_VIDEO)
728 static int __create_pipe(struct atomisp_sub_device *asd,
729 struct atomisp_stream_env *stream_env,
730 enum ia_css_pipe_id pipe_id)
732 struct atomisp_device *isp = asd->isp;
733 struct ia_css_pipe_extra_config extra_config;
736 if (pipe_id >= IA_CSS_PIPE_ID_NUM)
739 if (pipe_id != IA_CSS_PIPE_ID_ACC &&
740 !stream_env->pipe_configs[pipe_id].output_info[0].res.width)
743 if (pipe_id == IA_CSS_PIPE_ID_ACC &&
744 !stream_env->pipe_configs[pipe_id].acc_extension)
747 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
750 ia_css_pipe_extra_config_defaults(&extra_config);
752 __apply_additional_pipe_config(asd, stream_env, pipe_id);
753 if (!memcmp(&extra_config,
754 &stream_env->pipe_extra_configs[pipe_id],
755 sizeof(extra_config)))
756 ret = ia_css_pipe_create(
757 &stream_env->pipe_configs[pipe_id],
758 &stream_env->pipes[pipe_id]);
760 ret = ia_css_pipe_create_extra(
761 &stream_env->pipe_configs[pipe_id],
762 &stream_env->pipe_extra_configs[pipe_id],
763 &stream_env->pipes[pipe_id]);
765 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
769 static int __create_pipes(struct atomisp_sub_device *asd)
774 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
775 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
776 ret = __create_pipe(asd, &asd->stream_env[i], j);
780 if (j < IA_CSS_PIPE_ID_NUM)
785 for (; i >= 0; i--) {
786 for (j--; j >= 0; j--) {
787 if (asd->stream_env[i].pipes[j]) {
788 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
789 asd->stream_env[i].pipes[j] = NULL;
792 j = IA_CSS_PIPE_ID_NUM;
797 void atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
800 __create_streams(asd);
803 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
806 struct atomisp_device *isp = asd->isp;
808 if (__destroy_streams(asd, true))
809 dev_warn(isp->dev, "destroy stream failed.\n");
811 if (__destroy_pipes(asd, true))
812 dev_warn(isp->dev, "destroy pipe failed.\n");
814 ret = __create_pipes(asd);
816 dev_err(isp->dev, "create pipe failed %d.\n", ret);
820 ret = __create_streams(asd);
822 dev_warn(isp->dev, "create stream failed %d.\n", ret);
823 __destroy_pipes(asd, true);
830 int atomisp_css_init(struct atomisp_device *isp)
832 unsigned int mmu_base_addr;
836 ret = hmm_get_mmu_base_addr(&mmu_base_addr);
841 err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
842 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
844 dev_err(isp->dev, "css init failed --- bad firmware?\n");
847 ia_css_enable_isys_event_queue(true);
849 isp->css_initialized = true;
850 dev_dbg(isp->dev, "sh_css_init success\n");
855 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
860 isp->css_env.isp_css_env.print_env.debug_print = NULL;
862 isp->css_env.isp_css_env.print_env.debug_print =
863 atomisp_css2_dbg_ftrace_print;
865 isp->css_env.isp_css_env.print_env.debug_print =
866 atomisp_css2_dbg_print;
873 int atomisp_css_load_firmware(struct atomisp_device *isp)
878 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
879 isp->css_env.isp_css_fw.bytes = isp->firmware->size;
881 isp->css_env.isp_css_env.hw_access_env.store_8 =
882 atomisp_css2_hw_store_8;
883 isp->css_env.isp_css_env.hw_access_env.store_16 =
884 atomisp_css2_hw_store_16;
885 isp->css_env.isp_css_env.hw_access_env.store_32 =
886 atomisp_css2_hw_store_32;
888 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
889 isp->css_env.isp_css_env.hw_access_env.load_16 =
890 atomisp_css2_hw_load_16;
891 isp->css_env.isp_css_env.hw_access_env.load_32 =
892 atomisp_css2_hw_load_32;
894 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
895 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
897 __set_css_print_env(isp, dbg_func);
899 isp->css_env.isp_css_env.print_env.error_print = atomisp_css2_err_print;
901 /* load isp fw into ISP memory */
902 err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env,
903 &isp->css_env.isp_css_fw);
905 dev_err(isp->dev, "css load fw failed.\n");
912 void atomisp_css_uninit(struct atomisp_device *isp)
914 struct atomisp_sub_device *asd;
917 for (i = 0; i < isp->num_of_streams; i++) {
919 memset(&asd->params.config, 0, sizeof(asd->params.config));
920 asd->params.css_update_params_needed = false;
923 isp->css_initialized = false;
927 void atomisp_css_suspend(struct atomisp_device *isp)
929 isp->css_initialized = false;
933 int atomisp_css_resume(struct atomisp_device *isp)
935 unsigned int mmu_base_addr;
938 ret = hmm_get_mmu_base_addr(&mmu_base_addr);
940 dev_err(isp->dev, "get base address error.\n");
944 ret = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
945 mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
947 dev_err(isp->dev, "re-init css failed.\n");
950 ia_css_enable_isys_event_queue(true);
952 isp->css_initialized = true;
956 int atomisp_css_irq_translate(struct atomisp_device *isp,
961 err = ia_css_irq_translate(infos);
964 "%s:failed to translate irq (err = %d,infos = %d)\n",
965 __func__, err, *infos);
972 void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
975 #ifndef ISP2401_NEW_INPUT_SYSTEM
976 ia_css_isys_rx_get_irq_info(port, infos);
982 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
985 #ifndef ISP2401_NEW_INPUT_SYSTEM
986 ia_css_isys_rx_clear_irq_info(port, infos);
990 int atomisp_css_irq_enable(struct atomisp_device *isp,
991 enum ia_css_irq_info info, bool enable)
993 dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s.\n",
995 enable ? "enable" : "disable");
996 if (ia_css_irq_enable(info, enable)) {
997 dev_warn(isp->dev, "%s:Invalid irq info: 0x%08x when %s.\n",
999 enable ? "enabling" : "disabling");
1006 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
1010 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1011 asd->stream_env[i].stream = NULL;
1012 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
1013 asd->stream_env[i].pipes[j] = NULL;
1014 asd->stream_env[i].update_pipe[j] = false;
1015 ia_css_pipe_config_defaults(
1016 &asd->stream_env[i].pipe_configs[j]);
1017 ia_css_pipe_extra_config_defaults(
1018 &asd->stream_env[i].pipe_extra_configs[j]);
1020 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
1024 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
1025 struct videobuf_vmalloc_memory *vm_mem,
1026 enum atomisp_input_stream_id stream_id,
1027 enum ia_css_buffer_type css_buf_type,
1028 enum ia_css_pipe_id css_pipe_id)
1030 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1031 struct ia_css_buffer css_buf = {0};
1034 css_buf.type = css_buf_type;
1035 css_buf.data.frame = vm_mem->vaddr;
1037 err = ia_css_pipe_enqueue_buffer(
1038 stream_env->pipes[css_pipe_id], &css_buf);
1045 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
1046 struct atomisp_metadata_buf *metadata_buf,
1047 enum atomisp_input_stream_id stream_id,
1048 enum ia_css_pipe_id css_pipe_id)
1050 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1051 struct ia_css_buffer buffer = {0};
1052 struct atomisp_device *isp = asd->isp;
1054 buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
1055 buffer.data.metadata = metadata_buf->metadata;
1056 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
1058 dev_err(isp->dev, "failed to q meta data buffer\n");
1065 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
1066 struct atomisp_s3a_buf *s3a_buf,
1067 enum atomisp_input_stream_id stream_id,
1068 enum ia_css_pipe_id css_pipe_id)
1070 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1071 struct ia_css_buffer buffer = {0};
1072 struct atomisp_device *isp = asd->isp;
1074 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
1075 buffer.data.stats_3a = s3a_buf->s3a_data;
1076 if (ia_css_pipe_enqueue_buffer(
1077 stream_env->pipes[css_pipe_id],
1079 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
1086 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
1087 struct atomisp_dis_buf *dis_buf,
1088 enum atomisp_input_stream_id stream_id,
1089 enum ia_css_pipe_id css_pipe_id)
1091 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1092 struct ia_css_buffer buffer = {0};
1093 struct atomisp_device *isp = asd->isp;
1095 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
1096 buffer.data.stats_dvs = dis_buf->dis_data;
1097 if (ia_css_pipe_enqueue_buffer(
1098 stream_env->pipes[css_pipe_id],
1100 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
1107 int atomisp_css_start(struct atomisp_sub_device *asd,
1108 enum ia_css_pipe_id pipe_id, bool in_reset)
1110 struct atomisp_device *isp = asd->isp;
1111 bool sp_is_started = false;
1115 if (__destroy_streams(asd, true))
1116 dev_warn(isp->dev, "destroy stream failed.\n");
1118 if (__destroy_pipes(asd, true))
1119 dev_warn(isp->dev, "destroy pipe failed.\n");
1121 if (__create_pipes(asd)) {
1122 dev_err(isp->dev, "create pipe error.\n");
1125 if (__create_streams(asd)) {
1126 dev_err(isp->dev, "create stream error.\n");
1130 /* in_reset == true, extension firmwares are reloaded after the recovery */
1131 atomisp_acc_load_extensions(asd);
1135 * For dual steam case, it is possible that:
1136 * 1: for this stream, it is at the stage that:
1137 * - after set_fmt is called
1138 * - before stream on is called
1139 * 2: for the other stream, the stream off is called which css reset
1142 * Thus the stream created in set_fmt get destroyed and need to be
1143 * recreated in the next stream on.
1145 if (asd->stream_prepared == false) {
1146 if (__create_pipes(asd)) {
1147 dev_err(isp->dev, "create pipe error.\n");
1150 if (__create_streams(asd)) {
1151 dev_err(isp->dev, "create stream error.\n");
1157 * SP can only be started one time
1158 * if atomisp_subdev_streaming_count() tell there already has some
1159 * subdev at streamming, then SP should already be started previously,
1160 * so need to skip start sp procedure
1162 if (atomisp_streaming_count(isp)) {
1163 dev_dbg(isp->dev, "skip start sp\n");
1165 if (!sh_css_hrt_system_is_idle())
1166 dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1167 if (ia_css_start_sp()) {
1168 dev_err(isp->dev, "start sp error.\n");
1172 sp_is_started = true;
1176 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1177 if (asd->stream_env[i].stream) {
1178 if (ia_css_stream_start(asd->stream_env[i]
1180 dev_err(isp->dev, "stream[%d] start error.\n", i);
1184 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1185 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1193 __destroy_streams(asd, true);
1195 __destroy_pipes(asd, true);
1197 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1201 * SP can not be stop if other streams are in use
1203 if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1209 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1213 * for ISP2401 new input system, this api is under development.
1214 * Calling it would cause kernel panic.
1218 * Check if it is Cherry Trail and also new input system
1220 if (asd->copy_mode) {
1221 dev_warn(asd->isp->dev,
1222 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1227 ia_css_stream_set_isp_config(
1228 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1229 &asd->params.config);
1230 memset(&asd->params.config, 0, sizeof(asd->params.config));
1233 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1234 struct ia_css_pipe *pipe)
1239 atomisp_css_update_isp_params(asd);
1243 dev_dbg(asd->isp->dev,
1244 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1245 __func__, asd->params.config.output_frame,
1246 asd->params.config.isp_config_id, pipe);
1248 ret = ia_css_stream_set_isp_config_on_pipe(
1249 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1250 &asd->params.config, pipe);
1252 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1254 memset(&asd->params.config, 0, sizeof(asd->params.config));
1257 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1258 enum atomisp_input_stream_id stream_id,
1259 enum ia_css_pipe_id pipe_id,
1260 enum ia_css_buffer_type buf_type,
1261 struct atomisp_css_buffer *isp_css_buffer)
1263 if (ia_css_pipe_enqueue_buffer(
1264 asd->stream_env[stream_id].pipes[pipe_id],
1265 &isp_css_buffer->css_buffer)
1272 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1273 enum atomisp_input_stream_id stream_id,
1274 enum ia_css_pipe_id pipe_id,
1275 enum ia_css_buffer_type buf_type,
1276 struct atomisp_css_buffer *isp_css_buffer)
1278 struct atomisp_device *isp = asd->isp;
1281 err = ia_css_pipe_dequeue_buffer(
1282 asd->stream_env[stream_id].pipes[pipe_id],
1283 &isp_css_buffer->css_buffer);
1286 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1293 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd,
1295 struct atomisp_s3a_buf *s3a_buf,
1296 struct atomisp_dis_buf *dis_buf,
1297 struct atomisp_metadata_buf *md_buf)
1299 struct atomisp_device *isp = asd->isp;
1300 struct ia_css_dvs_grid_info *dvs_grid_info =
1301 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1303 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1306 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1307 &asd->params.curr_grid_info.s3a_grid);
1308 if (!s3a_buf->s3a_data) {
1309 dev_err(isp->dev, "3a buf allocation failed.\n");
1313 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1314 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1315 s3a_buf->s3a_data, s3a_ptr);
1318 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1321 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1323 if (!dis_buf->dis_data) {
1324 dev_err(isp->dev, "dvs buf allocation failed.\n");
1326 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1330 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1331 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1332 dis_buf->dis_data, dvs_ptr);
1335 if (asd->stream_env[stream_id].stream_info.
1336 metadata_info.size && md_buf) {
1337 md_buf->metadata = ia_css_metadata_allocate(
1338 &asd->stream_env[stream_id].stream_info.metadata_info);
1339 if (!md_buf->metadata) {
1341 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1343 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1344 dev_err(isp->dev, "metadata buf allocation failed.\n");
1347 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1353 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1355 if (s3a_buf->s3a_data)
1356 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1358 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1359 s3a_buf->s3a_map = NULL;
1360 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1363 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1365 if (dis_buf->dis_data)
1366 hmm_vunmap(dis_buf->dis_data->data_ptr);
1368 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1369 dis_buf->dvs_map = NULL;
1370 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1373 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1375 if (metadata_buf->md_vptr) {
1376 hmm_vunmap(metadata_buf->metadata->address);
1377 metadata_buf->md_vptr = NULL;
1379 ia_css_metadata_free(metadata_buf->metadata);
1382 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1384 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1385 struct atomisp_dis_buf *dis_buf, *_dis_buf;
1386 struct atomisp_metadata_buf *md_buf, *_md_buf;
1387 struct ia_css_dvs_grid_info *dvs_grid_info =
1388 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1391 /* 3A statistics use vmalloc, DIS use kmalloc */
1392 if (dvs_grid_info && dvs_grid_info->enable) {
1393 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1394 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1395 asd->params.css_param.dvs2_coeff = NULL;
1396 asd->params.dvs_stat = NULL;
1397 asd->params.dvs_hor_proj_bytes = 0;
1398 asd->params.dvs_ver_proj_bytes = 0;
1399 asd->params.dvs_hor_coef_bytes = 0;
1400 asd->params.dvs_ver_coef_bytes = 0;
1401 asd->params.dis_proj_data_valid = false;
1402 list_for_each_entry_safe(dis_buf, _dis_buf,
1403 &asd->dis_stats, list) {
1404 atomisp_css_free_dis_buffer(dis_buf);
1405 list_del(&dis_buf->list);
1408 list_for_each_entry_safe(dis_buf, _dis_buf,
1409 &asd->dis_stats_in_css, list) {
1410 atomisp_css_free_dis_buffer(dis_buf);
1411 list_del(&dis_buf->list);
1415 if (asd->params.curr_grid_info.s3a_grid.enable) {
1416 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1417 asd->params.s3a_user_stat = NULL;
1418 asd->params.s3a_output_bytes = 0;
1419 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1420 &asd->s3a_stats, list) {
1421 atomisp_css_free_3a_buffer(s3a_buf);
1422 list_del(&s3a_buf->list);
1425 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1426 &asd->s3a_stats_in_css, list) {
1427 atomisp_css_free_3a_buffer(s3a_buf);
1428 list_del(&s3a_buf->list);
1431 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1432 &asd->s3a_stats_ready, list) {
1433 atomisp_css_free_3a_buffer(s3a_buf);
1434 list_del(&s3a_buf->list);
1439 if (asd->params.css_param.dvs_6axis) {
1440 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1441 asd->params.css_param.dvs_6axis = NULL;
1444 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1445 list_for_each_entry_safe(md_buf, _md_buf,
1446 &asd->metadata[i], list) {
1447 atomisp_css_free_metadata_buffer(md_buf);
1448 list_del(&md_buf->list);
1451 list_for_each_entry_safe(md_buf, _md_buf,
1452 &asd->metadata_in_css[i], list) {
1453 atomisp_css_free_metadata_buffer(md_buf);
1454 list_del(&md_buf->list);
1457 list_for_each_entry_safe(md_buf, _md_buf,
1458 &asd->metadata_ready[i], list) {
1459 atomisp_css_free_metadata_buffer(md_buf);
1460 list_del(&md_buf->list);
1464 asd->params.metadata_width_size = 0;
1465 atomisp_free_metadata_output_buf(asd);
1468 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1469 enum ia_css_pipe_id pipe_id,
1472 struct ia_css_pipe_info p_info;
1473 struct ia_css_grid_info old_info;
1474 struct atomisp_device *isp = asd->isp;
1475 int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
1476 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1477 stream_config.metadata_config.resolution.width;
1479 memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1480 memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1482 if (ia_css_pipe_get_info(
1483 asd->stream_env[stream_index].pipes[pipe_id],
1485 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1489 memcpy(&old_info, &asd->params.curr_grid_info,
1490 sizeof(struct ia_css_grid_info));
1491 memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1492 sizeof(struct ia_css_grid_info));
1494 * Record which css pipe enables s3a_grid.
1495 * Currently would have one css pipe that need it
1497 if (asd->params.curr_grid_info.s3a_grid.enable) {
1498 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM)
1499 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1500 asd->params.s3a_enabled_pipe, pipe_id);
1501 asd->params.s3a_enabled_pipe = pipe_id;
1504 /* If the grid info has not changed and the buffers for 3A and
1505 * DIS statistics buffers are allocated or buffer size would be zero
1506 * then no need to do anything. */
1507 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1508 && asd->params.s3a_user_stat && asd->params.dvs_stat)
1509 || asd->params.curr_grid_info.s3a_grid.width == 0
1510 || asd->params.curr_grid_info.s3a_grid.height == 0)
1511 && asd->params.metadata_width_size == md_width) {
1513 "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1514 !memcmp(&old_info, &asd->params.curr_grid_info,
1516 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1517 asd->params.curr_grid_info.s3a_grid.width,
1518 asd->params.curr_grid_info.s3a_grid.height,
1519 asd->params.metadata_width_size);
1522 asd->params.metadata_width_size = md_width;
1527 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1529 if (!asd->params.curr_grid_info.s3a_grid.width ||
1530 !asd->params.curr_grid_info.s3a_grid.height)
1533 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1534 &asd->params.curr_grid_info.s3a_grid);
1535 if (!asd->params.s3a_user_stat)
1537 /* 3A statistics. These can be big, so we use vmalloc. */
1538 asd->params.s3a_output_bytes =
1539 asd->params.curr_grid_info.s3a_grid.width *
1540 asd->params.curr_grid_info.s3a_grid.height *
1541 sizeof(*asd->params.s3a_user_stat->data);
1546 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1548 struct ia_css_dvs_grid_info *dvs_grid =
1549 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1554 if (!dvs_grid->enable) {
1555 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1559 /* DIS coefficients. */
1560 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1562 if (!asd->params.css_param.dvs2_coeff)
1565 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1566 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1568 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1569 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1571 /* DIS projections. */
1572 asd->params.dis_proj_data_valid = false;
1573 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1574 if (!asd->params.dvs_stat)
1577 asd->params.dvs_hor_proj_bytes =
1578 dvs_grid->aligned_height * dvs_grid->aligned_width *
1579 sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1581 asd->params.dvs_ver_proj_bytes =
1582 dvs_grid->aligned_height * dvs_grid->aligned_width *
1583 sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1588 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1592 /* We allocate the cpu-side buffer used for communication with user
1594 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1595 asd->params.metadata_user[i] = kvmalloc(
1596 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1597 stream_info.metadata_info.size, GFP_KERNEL);
1598 if (!asd->params.metadata_user[i]) {
1600 kvfree(asd->params.metadata_user[i]);
1601 asd->params.metadata_user[i] = NULL;
1610 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1614 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1615 if (asd->params.metadata_user[i]) {
1616 kvfree(asd->params.metadata_user[i]);
1617 asd->params.metadata_user[i] = NULL;
1622 void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd,
1623 struct atomisp_css_buffer *isp_css_buffer,
1624 struct ia_css_isp_dvs_statistics_map *dvs_map)
1626 if (asd->params.dvs_stat) {
1628 ia_css_translate_dvs2_statistics(
1629 asd->params.dvs_stat, dvs_map);
1631 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
1632 isp_css_buffer->css_buffer.data.stats_dvs);
1636 int atomisp_css_dequeue_event(struct atomisp_css_event *current_event)
1638 if (ia_css_dequeue_event(¤t_event->event))
1644 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1645 struct atomisp_css_event *current_event)
1649 * Pipe ID reported in CSS event is not correct for new system's
1653 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1654 ¤t_event->pipe);
1655 if (asd && asd->copy_mode &&
1656 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1657 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1660 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1661 enum atomisp_input_stream_id stream_id,
1662 struct v4l2_mbus_framefmt *ffmt,
1665 struct ia_css_stream_config *s_config =
1666 &asd->stream_env[stream_id].stream_config;
1668 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1671 s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1672 s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1676 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1677 enum atomisp_input_stream_id stream_id,
1678 struct v4l2_mbus_framefmt *ffmt)
1680 struct ia_css_stream_config *s_config =
1681 &asd->stream_env[stream_id].stream_config;
1683 s_config->input_config.input_res.width = ffmt->width;
1684 s_config->input_config.input_res.height = ffmt->height;
1688 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1689 enum atomisp_input_stream_id stream_id,
1690 unsigned int bin_factor)
1692 asd->stream_env[stream_id]
1693 .stream_config.sensor_binning_factor = bin_factor;
1696 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1697 enum atomisp_input_stream_id stream_id,
1698 enum ia_css_bayer_order bayer_order)
1700 struct ia_css_stream_config *s_config =
1701 &asd->stream_env[stream_id].stream_config;
1702 s_config->input_config.bayer_order = bayer_order;
1705 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1706 enum atomisp_input_stream_id stream_id,
1710 struct ia_css_stream_config *s_config =
1711 &asd->stream_env[stream_id].stream_config;
1713 s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1716 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1717 enum atomisp_input_stream_id stream_id,
1721 struct ia_css_stream_config *s_config =
1722 &asd->stream_env[stream_id].stream_config;
1724 s_config->isys_config[isys_stream].valid = valid;
1727 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1728 enum atomisp_input_stream_id stream_id,
1729 enum atomisp_input_format format,
1732 struct ia_css_stream_config *s_config =
1733 &asd->stream_env[stream_id].stream_config;
1735 s_config->isys_config[isys_stream].format = format;
1738 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1739 enum atomisp_input_stream_id stream_id,
1740 enum atomisp_input_format format)
1742 struct ia_css_stream_config *s_config =
1743 &asd->stream_env[stream_id].stream_config;
1745 s_config->input_config.format = format;
1748 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1749 enum atomisp_input_stream_id stream_id,
1750 struct v4l2_mbus_framefmt *ffmt)
1753 struct ia_css_stream_config *s_config =
1754 &asd->stream_env[stream_id].stream_config;
1756 * Set all isys configs to not valid.
1757 * Currently we support only one stream per channel
1759 for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1760 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1761 s_config->isys_config[i].valid = false;
1763 atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1764 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1765 atomisp_css_isys_set_format(asd, stream_id,
1766 s_config->input_config.format,
1767 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1768 atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1769 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1770 atomisp_css_isys_set_valid(asd, stream_id, true,
1771 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1776 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1777 enum atomisp_input_stream_id stream_id,
1778 enum atomisp_input_format input_format)
1780 struct ia_css_stream_config *s_config =
1781 &asd->stream_env[stream_id].stream_config;
1783 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1784 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1786 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1787 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1789 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1790 = IA_CSS_STREAM_ISYS_STREAM_0;
1791 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1792 ATOMISP_INPUT_FORMAT_USER_DEF1;
1793 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1794 ATOMISP_INPUT_FORMAT_USER_DEF2;
1795 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1799 void atomisp_css_isys_two_stream_cfg_update_stream1(
1800 struct atomisp_sub_device *asd,
1801 enum atomisp_input_stream_id stream_id,
1802 enum atomisp_input_format input_format,
1803 unsigned int width, unsigned int height)
1805 struct ia_css_stream_config *s_config =
1806 &asd->stream_env[stream_id].stream_config;
1808 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1810 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1812 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1814 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1817 void atomisp_css_isys_two_stream_cfg_update_stream2(
1818 struct atomisp_sub_device *asd,
1819 enum atomisp_input_stream_id stream_id,
1820 enum atomisp_input_format input_format,
1821 unsigned int width, unsigned int height)
1823 struct ia_css_stream_config *s_config =
1824 &asd->stream_env[stream_id].stream_config;
1826 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1828 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1830 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1831 = IA_CSS_STREAM_ISYS_STREAM_0;
1832 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1834 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1837 int atomisp_css_input_set_effective_resolution(
1838 struct atomisp_sub_device *asd,
1839 enum atomisp_input_stream_id stream_id,
1840 unsigned int width, unsigned int height)
1842 struct ia_css_stream_config *s_config =
1843 &asd->stream_env[stream_id].stream_config;
1844 s_config->input_config.effective_res.width = width;
1845 s_config->input_config.effective_res.height = height;
1849 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1850 unsigned int dvs_w, unsigned int dvs_h)
1852 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1853 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1854 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1855 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1858 void atomisp_css_input_set_two_pixels_per_clock(
1859 struct atomisp_sub_device *asd,
1864 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1865 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1868 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1869 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1870 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1871 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1872 .update_pipe[i] = true;
1875 void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
1878 struct atomisp_stream_env *stream_env =
1879 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1882 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
1883 pipe = IA_CSS_PIPE_ID_VIDEO;
1885 pipe = IA_CSS_PIPE_ID_PREVIEW;
1887 stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable;
1888 stream_env->update_pipe[pipe] = true;
1890 stream_env->pipe_configs[pipe].output_info[0].padded_width =
1891 stream_env->stream_config.input_config.effective_res.width;
1894 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1898 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1899 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1900 .pipe_configs[i].enable_dz = enable;
1903 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1904 enum ia_css_capture_mode mode)
1906 struct atomisp_stream_env *stream_env =
1907 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1909 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1910 .default_capture_config.mode == mode)
1913 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1914 default_capture_config.mode = mode;
1915 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1918 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
1919 enum ia_css_input_mode mode)
1922 struct atomisp_device *isp = asd->isp;
1923 unsigned int size_mem_words;
1925 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
1926 asd->stream_env[i].stream_config.mode = mode;
1928 if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
1929 struct ia_css_stream_config *s_config =
1930 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
1931 s_config->mode = IA_CSS_INPUT_MODE_TPG;
1932 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
1933 s_config->source.tpg.x_mask = (1 << 4) - 1;
1934 s_config->source.tpg.x_delta = -2;
1935 s_config->source.tpg.y_mask = (1 << 4) - 1;
1936 s_config->source.tpg.y_delta = 3;
1937 s_config->source.tpg.xy_mask = (1 << 8) - 1;
1941 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1944 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1946 * TODO: sensor needs to export the embedded_data_size_words
1947 * information to atomisp for each setting.
1948 * Here using a large safe value.
1950 struct ia_css_stream_config *s_config =
1951 &asd->stream_env[i].stream_config;
1953 if (s_config->input_config.input_res.width == 0)
1956 if (ia_css_mipi_frame_calculate_size(
1957 s_config->input_config.input_res.width,
1958 s_config->input_config.input_res.height,
1959 s_config->input_config.format,
1962 &size_mem_words) != 0) {
1963 if (intel_mid_identify_cpu() ==
1964 INTEL_MID_CPU_CHIP_TANGIER)
1965 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
1967 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
1968 dev_warn(asd->isp->dev,
1969 "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n",
1972 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
1973 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
1977 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
1978 unsigned short stream_index, bool enable)
1980 struct atomisp_stream_env *stream_env =
1981 &asd->stream_env[stream_index];
1983 if (stream_env->stream_config.online == !!enable)
1986 stream_env->stream_config.online = !!enable;
1987 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1990 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
1991 unsigned short stream_index, bool enable)
1993 struct atomisp_stream_env *stream_env =
1994 &asd->stream_env[stream_index];
1997 if (stream_env->stream_config.online != !!enable) {
1998 stream_env->stream_config.online = !!enable;
1999 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2000 stream_env->update_pipe[i] = true;
2004 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
2007 struct atomisp_stream_env *stream_env =
2008 &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
2011 if (stream_env->stream_config.online != enable) {
2012 stream_env->stream_config.online = enable;
2013 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2014 stream_env->update_pipe[i] = true;
2018 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
2021 struct atomisp_stream_env *stream_env =
2022 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2026 * To SOC camera, there is only one YUVPP pipe in any case
2027 * including ZSL/SDV/continuous viewfinder, so always set
2028 * stream_config.continuous to 0.
2030 if (ATOMISP_USE_YUVPP(asd)) {
2031 stream_env->stream_config.continuous = 0;
2032 stream_env->stream_config.online = 1;
2036 if (stream_env->stream_config.continuous != !!enable) {
2037 stream_env->stream_config.continuous = !!enable;
2038 stream_env->stream_config.pack_raw_pixels = true;
2039 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2040 stream_env->update_pipe[i] = true;
2044 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
2047 struct atomisp_stream_env *stream_env =
2048 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2051 if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
2052 stream_env->stream_config.disable_cont_viewfinder = !enable;
2053 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2054 stream_env->update_pipe[i] = true;
2058 int atomisp_css_input_configure_port(
2059 struct atomisp_sub_device *asd,
2060 enum mipi_port_id port,
2061 unsigned int num_lanes,
2062 unsigned int timeout,
2063 unsigned int mipi_freq,
2064 enum atomisp_input_format metadata_format,
2065 unsigned int metadata_width,
2066 unsigned int metadata_height)
2069 struct atomisp_stream_env *stream_env;
2071 * Calculate rx_count as follows:
2072 * Input: mipi_freq : CSI-2 bus frequency in Hz
2073 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus
2074 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds
2075 * max = 145e-9 + 10 * UI
2076 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
2077 * rxcount = rxcount0 - 2 : adjust for better results
2078 * The formula below is simplified version of the above with
2079 * 10-bit fixed points for improved accuracy.
2081 const unsigned int rxcount =
2082 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
2084 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2085 stream_env = &asd->stream_env[i];
2086 stream_env->stream_config.source.port.port = port;
2087 stream_env->stream_config.source.port.num_lanes = num_lanes;
2088 stream_env->stream_config.source.port.timeout = timeout;
2090 stream_env->stream_config.source.port.rxcount = rxcount;
2091 stream_env->stream_config.
2092 metadata_config.data_type = metadata_format;
2093 stream_env->stream_config.
2094 metadata_config.resolution.width = metadata_width;
2095 stream_env->stream_config.
2096 metadata_config.resolution.height = metadata_height;
2102 int atomisp_css_frame_allocate(struct ia_css_frame **frame,
2103 unsigned int width, unsigned int height,
2104 enum ia_css_frame_format format,
2105 unsigned int padded_width,
2106 unsigned int raw_bit_depth)
2108 if (ia_css_frame_allocate(frame, width, height, format,
2109 padded_width, raw_bit_depth) != 0)
2115 int atomisp_css_frame_allocate_from_info(struct ia_css_frame **frame,
2116 const struct ia_css_frame_info *info)
2118 if (ia_css_frame_allocate_from_info(frame, info))
2124 void atomisp_css_frame_free(struct ia_css_frame *frame)
2126 ia_css_frame_free(frame);
2129 int atomisp_css_frame_map(struct ia_css_frame **frame,
2130 const struct ia_css_frame_info *info,
2131 const void __user *data, uint16_t attribute,
2134 if (ia_css_frame_map(frame, info, data, attribute, pgnr)
2141 int atomisp_css_set_black_frame(struct atomisp_sub_device *asd,
2142 const struct ia_css_frame *raw_black_frame)
2144 if (sh_css_set_black_frame(
2145 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2146 raw_black_frame) != 0)
2152 int atomisp_css_allocate_continuous_frames(bool init_time,
2153 struct atomisp_sub_device *asd)
2155 if (ia_css_alloc_continuous_frame_remain(
2156 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream)
2162 void atomisp_css_update_continuous_frames(struct atomisp_sub_device *asd)
2164 ia_css_update_continuous_frames(
2165 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream);
2168 int atomisp_css_stop(struct atomisp_sub_device *asd,
2169 enum ia_css_pipe_id pipe_id, bool in_reset)
2171 struct atomisp_device *isp = asd->isp;
2172 struct atomisp_s3a_buf *s3a_buf;
2173 struct atomisp_dis_buf *dis_buf;
2174 struct atomisp_metadata_buf *md_buf;
2175 unsigned long irqflags;
2178 /* if is called in atomisp_reset(), force destroy stream */
2179 if (__destroy_streams(asd, true))
2180 dev_err(isp->dev, "destroy stream failed.\n");
2182 /* if is called in atomisp_reset(), force destroy all pipes */
2183 if (__destroy_pipes(asd, true))
2184 dev_err(isp->dev, "destroy pipes failed.\n");
2186 atomisp_init_raw_buffer_bitmap(asd);
2189 * SP can not be stop if other streams are in use
2191 if (atomisp_streaming_count(isp) == 0)
2195 struct atomisp_stream_env *stream_env;
2198 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2199 stream_env = &asd->stream_env[i];
2200 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
2201 ia_css_pipe_config_defaults(
2202 &stream_env->pipe_configs[j]);
2203 ia_css_pipe_extra_config_defaults(
2204 &stream_env->pipe_extra_configs[j]);
2206 ia_css_stream_config_defaults(
2207 &stream_env->stream_config);
2209 memset(&asd->params.config, 0, sizeof(asd->params.config));
2210 asd->params.css_update_params_needed = false;
2213 /* move stats buffers to free queue list */
2214 while (!list_empty(&asd->s3a_stats_in_css)) {
2215 s3a_buf = list_entry(asd->s3a_stats_in_css.next,
2216 struct atomisp_s3a_buf, list);
2217 list_del(&s3a_buf->list);
2218 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2220 while (!list_empty(&asd->s3a_stats_ready)) {
2221 s3a_buf = list_entry(asd->s3a_stats_ready.next,
2222 struct atomisp_s3a_buf, list);
2223 list_del(&s3a_buf->list);
2224 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2227 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
2228 while (!list_empty(&asd->dis_stats_in_css)) {
2229 dis_buf = list_entry(asd->dis_stats_in_css.next,
2230 struct atomisp_dis_buf, list);
2231 list_del(&dis_buf->list);
2232 list_add_tail(&dis_buf->list, &asd->dis_stats);
2234 asd->params.dis_proj_data_valid = false;
2235 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
2237 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
2238 while (!list_empty(&asd->metadata_in_css[i])) {
2239 md_buf = list_entry(asd->metadata_in_css[i].next,
2240 struct atomisp_metadata_buf, list);
2241 list_del(&md_buf->list);
2242 list_add_tail(&md_buf->list, &asd->metadata[i]);
2244 while (!list_empty(&asd->metadata_ready[i])) {
2245 md_buf = list_entry(asd->metadata_ready[i].next,
2246 struct atomisp_metadata_buf, list);
2247 list_del(&md_buf->list);
2248 list_add_tail(&md_buf->list, &asd->metadata[i]);
2252 atomisp_flush_params_queue(&asd->video_out_capture);
2253 atomisp_flush_params_queue(&asd->video_out_vf);
2254 atomisp_flush_params_queue(&asd->video_out_preview);
2255 atomisp_flush_params_queue(&asd->video_out_video_capture);
2256 atomisp_free_css_parameters(&asd->params.css_param);
2257 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
2261 int atomisp_css_continuous_set_num_raw_frames(
2262 struct atomisp_sub_device *asd,
2265 if (asd->enable_raw_buffer_lock->val) {
2266 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2267 .stream_config.init_num_cont_raw_buf =
2268 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
2269 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2270 asd->params.video_dis_en)
2271 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2272 .stream_config.init_num_cont_raw_buf +=
2273 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2275 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2276 .stream_config.init_num_cont_raw_buf =
2277 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
2280 if (asd->params.video_dis_en)
2281 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2282 .stream_config.init_num_cont_raw_buf +=
2283 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2285 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2286 .stream_config.target_num_cont_raw_buf = num_frames;
2290 void atomisp_css_disable_vf_pp(struct atomisp_sub_device *asd,
2295 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2296 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2297 .pipe_extra_configs[i].disable_vf_pp = !!disable;
2300 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2301 struct atomisp_sub_device *asd,
2302 enum ia_css_pipe_id pipe_id)
2304 struct atomisp_device *isp = asd->isp;
2305 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2306 isp->inputs[asd->input_curr].camera);
2309 case IA_CSS_PIPE_ID_COPY:
2310 /* Currently only YUVPP mode supports YUV420_Legacy format.
2311 * Revert this when other pipe modes can support
2312 * YUV420_Legacy format.
2314 if (mipi_info && mipi_info->input_format ==
2315 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2316 return IA_CSS_PIPE_MODE_YUVPP;
2317 return IA_CSS_PIPE_MODE_COPY;
2318 case IA_CSS_PIPE_ID_PREVIEW:
2319 return IA_CSS_PIPE_MODE_PREVIEW;
2320 case IA_CSS_PIPE_ID_CAPTURE:
2321 return IA_CSS_PIPE_MODE_CAPTURE;
2322 case IA_CSS_PIPE_ID_VIDEO:
2323 return IA_CSS_PIPE_MODE_VIDEO;
2324 case IA_CSS_PIPE_ID_ACC:
2325 return IA_CSS_PIPE_MODE_ACC;
2326 case IA_CSS_PIPE_ID_YUVPP:
2327 return IA_CSS_PIPE_MODE_YUVPP;
2330 return IA_CSS_PIPE_MODE_PREVIEW;
2334 static void __configure_output(struct atomisp_sub_device *asd,
2335 unsigned int stream_index,
2336 unsigned int width, unsigned int height,
2337 unsigned int min_width,
2338 enum ia_css_frame_format format,
2339 enum ia_css_pipe_id pipe_id)
2341 struct atomisp_device *isp = asd->isp;
2342 struct atomisp_stream_env *stream_env =
2343 &asd->stream_env[stream_index];
2344 struct ia_css_stream_config *s_config = &stream_env->stream_config;
2346 stream_env->pipe_configs[pipe_id].mode =
2347 __pipe_id_to_pipe_mode(asd, pipe_id);
2348 stream_env->update_pipe[pipe_id] = true;
2350 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2351 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2352 stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2353 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2355 /* isp binary 2.2 specific setting*/
2356 if (width > s_config->input_config.effective_res.width ||
2357 height > s_config->input_config.effective_res.height) {
2358 s_config->input_config.effective_res.width = width;
2359 s_config->input_config.effective_res.height = height;
2362 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2363 pipe_id, width, height, format);
2366 static void __configure_video_preview_output(struct atomisp_sub_device *asd,
2367 unsigned int stream_index,
2368 unsigned int width, unsigned int height,
2369 unsigned int min_width,
2370 enum ia_css_frame_format format,
2371 enum ia_css_pipe_id pipe_id)
2373 struct atomisp_device *isp = asd->isp;
2374 struct atomisp_stream_env *stream_env =
2375 &asd->stream_env[stream_index];
2376 struct ia_css_frame_info *css_output_info;
2377 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2379 stream_env->pipe_configs[pipe_id].mode =
2380 __pipe_id_to_pipe_mode(asd, pipe_id);
2381 stream_env->update_pipe[pipe_id] = true;
2384 * second_output will be as video main output in SDV mode
2385 * with SOC camera. output will be as video main output in
2386 * normal video mode.
2388 if (asd->continuous_mode->val)
2389 css_output_info = &stream_env->pipe_configs[pipe_id].
2390 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2392 css_output_info = &stream_env->pipe_configs[pipe_id].
2393 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2395 css_output_info->res.width = width;
2396 css_output_info->res.height = height;
2397 css_output_info->format = format;
2398 css_output_info->padded_width = min_width;
2400 /* isp binary 2.2 specific setting*/
2401 if (width > stream_config->input_config.effective_res.width ||
2402 height > stream_config->input_config.effective_res.height) {
2403 stream_config->input_config.effective_res.width = width;
2404 stream_config->input_config.effective_res.height = height;
2407 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2408 pipe_id, width, height, format);
2412 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2413 * downscaling input resolution.
2415 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2416 unsigned int width, unsigned int height,
2417 enum ia_css_pipe_id pipe_id)
2419 struct atomisp_device *isp = asd->isp;
2420 struct atomisp_stream_env *stream_env =
2421 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2422 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2423 struct ia_css_pipe_config *pipe_configs =
2424 &stream_env->pipe_configs[pipe_id];
2425 struct ia_css_pipe_extra_config *pipe_extra_configs =
2426 &stream_env->pipe_extra_configs[pipe_id];
2427 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2429 if (width == 0 && height == 0)
2432 if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2433 height * 9 / 10 < pipe_configs->output_info[0].res.height)
2435 /* here just copy the calculation in css */
2436 hor_ds_factor = CEIL_DIV(width >> 1,
2437 pipe_configs->output_info[0].res.width);
2438 ver_ds_factor = CEIL_DIV(height >> 1,
2439 pipe_configs->output_info[0].res.height);
2441 if ((asd->isp->media_dev.hw_revision <
2442 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2443 IS_CHT) && hor_ds_factor != ver_ds_factor) {
2444 dev_warn(asd->isp->dev,
2445 "Cropping for capture due to FW limitation");
2449 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2450 stream_env->update_pipe[pipe_id] = true;
2452 pipe_extra_configs->enable_yuv_ds = true;
2454 pipe_configs->capt_pp_in_res.width =
2455 stream_config->input_config.effective_res.width;
2456 pipe_configs->capt_pp_in_res.height =
2457 stream_config->input_config.effective_res.height;
2459 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2460 pipe_id, width, height);
2464 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2465 * yuv downscaling, which needs addtional configurations.
2467 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2468 unsigned int width, unsigned int height,
2469 enum ia_css_pipe_id pipe_id)
2471 struct atomisp_device *isp = asd->isp;
2472 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2473 struct atomisp_stream_env *stream_env =
2474 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2475 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2476 struct ia_css_pipe_config *pipe_configs =
2477 &stream_env->pipe_configs[pipe_id];
2478 struct ia_css_pipe_extra_config *pipe_extra_configs =
2479 &stream_env->pipe_extra_configs[pipe_id];
2480 struct ia_css_resolution *bayer_ds_out_res =
2481 &pipe_configs->bayer_ds_out_res;
2482 struct ia_css_resolution *vf_pp_in_res =
2483 &pipe_configs->vf_pp_in_res;
2484 struct ia_css_resolution *effective_res =
2485 &stream_config->input_config.effective_res;
2487 const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2489 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2490 * columns to be shaded. Remove this factor to work around the CSS bug.
2491 * const unsigned int yuv_dec_fct[] = {4, 2};
2493 const unsigned int yuv_dec_fct[] = { 2 };
2496 if (width == 0 && height == 0)
2499 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2500 stream_env->update_pipe[pipe_id] = true;
2502 out_width = pipe_configs->output_info[0].res.width;
2503 out_height = pipe_configs->output_info[0].res.height;
2506 * The ISP could do bayer downscaling, yuv decimation and yuv
2508 * 1: Bayer Downscaling: between effective resolution and
2510 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2511 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2513 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2514 * Rule for YUV Decimation: support factor 2, 4
2515 * Rule for YUV Downscaling: arbitrary value below 2
2517 * General rule of factor distribution among these stages:
2518 * 1: try to do Bayer downscaling first if not in online mode.
2519 * 2: try to do maximum of 2 for YUV downscaling
2520 * 3: the remainling for YUV decimation
2523 * Do not configure bayer_ds_out_res if:
2524 * online == 1 or continuous == 0 or raw_binning = 0
2526 if (stream_config->online || !stream_config->continuous ||
2527 !pipe_extra_configs->enable_raw_binning) {
2528 bayer_ds_out_res->width = 0;
2529 bayer_ds_out_res->height = 0;
2531 bayer_ds_out_res->width = effective_res->width;
2532 bayer_ds_out_res->height = effective_res->height;
2534 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2535 if (effective_res->width >= out_width *
2536 bds_fct[i].numerator / bds_fct[i].denominator &&
2537 effective_res->height >= out_height *
2538 bds_fct[i].numerator / bds_fct[i].denominator) {
2539 bayer_ds_out_res->width =
2540 effective_res->width *
2541 bds_fct[i].denominator /
2542 bds_fct[i].numerator;
2543 bayer_ds_out_res->height =
2544 effective_res->height *
2545 bds_fct[i].denominator /
2546 bds_fct[i].numerator;
2552 * calculate YUV Decimation, YUV downscaling facor:
2553 * YUV Downscaling factor must not exceed 2.
2554 * YUV Decimation factor could be 2, 4.
2556 /* first decide the yuv_ds input resolution */
2557 if (bayer_ds_out_res->width == 0) {
2558 yuv_ds_in_width = effective_res->width;
2559 yuv_ds_in_height = effective_res->height;
2561 yuv_ds_in_width = bayer_ds_out_res->width;
2562 yuv_ds_in_height = bayer_ds_out_res->height;
2565 vf_pp_in_res->width = yuv_ds_in_width;
2566 vf_pp_in_res->height = yuv_ds_in_height;
2568 /* find out the yuv decimation factor */
2569 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2570 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2571 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2572 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2573 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2578 if (vf_pp_in_res->width == out_width &&
2579 vf_pp_in_res->height == out_height) {
2580 pipe_extra_configs->enable_yuv_ds = false;
2581 vf_pp_in_res->width = 0;
2582 vf_pp_in_res->height = 0;
2584 pipe_extra_configs->enable_yuv_ds = true;
2587 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2588 pipe_id, width, height);
2592 * For CSS2.1, offline video pipe could support bayer decimation, and
2593 * yuv downscaling, which needs addtional configurations.
2595 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2596 unsigned int width, unsigned int height,
2597 enum ia_css_pipe_id pipe_id)
2599 struct atomisp_device *isp = asd->isp;
2600 int out_width, out_height;
2601 struct atomisp_stream_env *stream_env =
2602 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2603 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2604 struct ia_css_pipe_config *pipe_configs =
2605 &stream_env->pipe_configs[pipe_id];
2606 struct ia_css_pipe_extra_config *pipe_extra_configs =
2607 &stream_env->pipe_extra_configs[pipe_id];
2608 struct ia_css_resolution *bayer_ds_out_res =
2609 &pipe_configs->bayer_ds_out_res;
2610 struct ia_css_resolution *effective_res =
2611 &stream_config->input_config.effective_res;
2613 const struct bayer_ds_factor bds_factors[] = {
2614 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
2618 if (width == 0 && height == 0)
2621 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2622 stream_env->update_pipe[pipe_id] = true;
2624 pipe_extra_configs->enable_yuv_ds = false;
2627 * If DVS is enabled, video binary will take care the dvs envelope
2628 * and usually the bayer_ds_out_res should be larger than 120% of
2629 * destination resolution, the extra 20% will be cropped as DVS
2630 * envelope. But, if the bayer_ds_out_res is less than 120% of the
2631 * destination. The ISP can still work, but DVS quality is not good.
2633 /* taking at least 10% as envelope */
2634 if (asd->params.video_dis_en) {
2635 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2636 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2638 out_width = pipe_configs->output_info[0].res.width;
2639 out_height = pipe_configs->output_info[0].res.height;
2643 * calculate bayer decimate factor:
2644 * 1: only 1.5, 2, 4 and 8 get supported
2645 * 2: Do not configure bayer_ds_out_res if:
2646 * online == 1 or continuous == 0 or raw_binning = 0
2648 if (stream_config->online || !stream_config->continuous) {
2649 bayer_ds_out_res->width = 0;
2650 bayer_ds_out_res->height = 0;
2654 pipe_extra_configs->enable_raw_binning = true;
2655 bayer_ds_out_res->width = effective_res->width;
2656 bayer_ds_out_res->height = effective_res->height;
2658 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2660 if (effective_res->width >= out_width *
2661 bds_factors[i].numerator / bds_factors[i].denominator &&
2662 effective_res->height >= out_height *
2663 bds_factors[i].numerator / bds_factors[i].denominator) {
2664 bayer_ds_out_res->width = effective_res->width *
2665 bds_factors[i].denominator /
2666 bds_factors[i].numerator;
2667 bayer_ds_out_res->height = effective_res->height *
2668 bds_factors[i].denominator /
2669 bds_factors[i].numerator;
2675 * DVS is cropped from BDS output, so we do not really need to set the
2676 * envelope to 20% of output resolution here. always set it to 12x12
2677 * per firmware requirement.
2679 pipe_configs->dvs_envelope.width = 12;
2680 pipe_configs->dvs_envelope.height = 12;
2683 if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2684 stream_config->left_padding = -1;
2686 stream_config->left_padding = 12;
2687 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2688 pipe_id, width, height);
2691 static void __configure_vf_output(struct atomisp_sub_device *asd,
2692 unsigned int width, unsigned int height,
2693 unsigned int min_width,
2694 enum ia_css_frame_format format,
2695 enum ia_css_pipe_id pipe_id)
2697 struct atomisp_device *isp = asd->isp;
2698 struct atomisp_stream_env *stream_env =
2699 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2700 stream_env->pipe_configs[pipe_id].mode =
2701 __pipe_id_to_pipe_mode(asd, pipe_id);
2702 stream_env->update_pipe[pipe_id] = true;
2704 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2705 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2706 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2707 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2710 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2711 pipe_id, width, height, format);
2714 static void __configure_video_vf_output(struct atomisp_sub_device *asd,
2715 unsigned int width, unsigned int height,
2716 unsigned int min_width,
2717 enum ia_css_frame_format format,
2718 enum ia_css_pipe_id pipe_id)
2720 struct atomisp_device *isp = asd->isp;
2721 struct atomisp_stream_env *stream_env =
2722 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2723 struct ia_css_frame_info *css_output_info;
2725 stream_env->pipe_configs[pipe_id].mode =
2726 __pipe_id_to_pipe_mode(asd, pipe_id);
2727 stream_env->update_pipe[pipe_id] = true;
2730 * second_vf_output will be as video viewfinder in SDV mode
2731 * with SOC camera. vf_output will be as video viewfinder in
2732 * normal video mode.
2734 if (asd->continuous_mode->val)
2735 css_output_info = &stream_env->pipe_configs[pipe_id].
2736 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2738 css_output_info = &stream_env->pipe_configs[pipe_id].
2739 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2741 css_output_info->res.width = width;
2742 css_output_info->res.height = height;
2743 css_output_info->format = format;
2744 css_output_info->padded_width = min_width;
2746 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2747 pipe_id, width, height, format);
2750 static int __get_frame_info(struct atomisp_sub_device *asd,
2751 unsigned int stream_index,
2752 struct ia_css_frame_info *info,
2753 enum frame_info_type type,
2754 enum ia_css_pipe_id pipe_id)
2756 struct atomisp_device *isp = asd->isp;
2758 struct ia_css_pipe_info p_info;
2760 /* FIXME! No need to destroy/recreate all streams */
2761 if (__destroy_streams(asd, true))
2762 dev_warn(isp->dev, "destroy stream failed.\n");
2764 if (__destroy_pipes(asd, true))
2765 dev_warn(isp->dev, "destroy pipe failed.\n");
2767 if (__create_pipes(asd))
2770 if (__create_streams(asd))
2773 ret = ia_css_pipe_get_info(
2774 asd->stream_env[stream_index]
2775 .pipes[pipe_id], &p_info);
2778 case ATOMISP_CSS_VF_FRAME:
2779 *info = p_info.vf_output_info[0];
2780 dev_dbg(isp->dev, "getting vf frame info.\n");
2782 case ATOMISP_CSS_SECOND_VF_FRAME:
2783 *info = p_info.vf_output_info[1];
2784 dev_dbg(isp->dev, "getting second vf frame info.\n");
2786 case ATOMISP_CSS_OUTPUT_FRAME:
2787 *info = p_info.output_info[0];
2788 dev_dbg(isp->dev, "getting main frame info.\n");
2790 case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2791 *info = p_info.output_info[1];
2792 dev_dbg(isp->dev, "getting second main frame info.\n");
2794 case ATOMISP_CSS_RAW_FRAME:
2795 *info = p_info.raw_output_info;
2796 dev_dbg(isp->dev, "getting raw frame info.\n");
2798 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2799 info->res.width, info->res.height, p_info.num_invalid_frames);
2804 __destroy_pipes(asd, true);
2808 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2809 uint16_t source_pad)
2811 struct atomisp_device *isp = asd->isp;
2813 * to SOC camera, use yuvpp pipe.
2815 if (ATOMISP_USE_YUVPP(asd))
2816 return IA_CSS_PIPE_ID_YUVPP;
2818 switch (source_pad) {
2819 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2820 if (asd->yuvpp_mode)
2821 return IA_CSS_PIPE_ID_YUVPP;
2823 return IA_CSS_PIPE_ID_COPY;
2824 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2825 || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2826 return IA_CSS_PIPE_ID_VIDEO;
2828 return IA_CSS_PIPE_ID_CAPTURE;
2829 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2831 return IA_CSS_PIPE_ID_COPY;
2832 return IA_CSS_PIPE_ID_CAPTURE;
2833 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2834 if (!atomisp_is_mbuscode_raw(
2835 asd->fmt[asd->capture_pad].fmt.code))
2836 return IA_CSS_PIPE_ID_CAPTURE;
2837 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2838 if (asd->yuvpp_mode)
2839 return IA_CSS_PIPE_ID_YUVPP;
2841 return IA_CSS_PIPE_ID_COPY;
2842 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2843 return IA_CSS_PIPE_ID_VIDEO;
2845 return IA_CSS_PIPE_ID_PREVIEW;
2848 "invalid source pad:%d, return default preview pipe index.\n",
2850 return IA_CSS_PIPE_ID_PREVIEW;
2853 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2855 struct ia_css_frame_info *frame_info)
2857 struct ia_css_pipe_info info;
2858 int pipe_index = atomisp_get_pipe_index(asd, source_pad);
2860 struct atomisp_device *isp = asd->isp;
2862 if (ATOMISP_SOC_CAMERA(asd))
2863 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
2865 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2866 ATOMISP_INPUT_STREAM_VIDEO :
2867 atomisp_source_pad_to_stream_id(asd, source_pad);
2870 if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index]
2871 .pipes[pipe_index], &info)) {
2872 dev_err(isp->dev, "ia_css_pipe_get_info FAILED");
2876 switch (source_pad) {
2877 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2878 *frame_info = info.output_info[0];
2880 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2881 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2883 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2886 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2888 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2889 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
2890 *frame_info = info.output_info[0];
2892 *frame_info = info.vf_output_info[0];
2894 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2895 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2896 (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
2897 pipe_index == IA_CSS_PIPE_ID_YUVPP))
2898 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2900 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2903 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2904 else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2906 info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2909 info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2916 return frame_info ? 0 : -EINVAL;
2919 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2920 unsigned int stream_index,
2921 unsigned int width, unsigned int height,
2922 unsigned int padded_width,
2923 enum ia_css_frame_format format)
2925 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
2926 default_capture_config.mode =
2927 IA_CSS_CAPTURE_MODE_RAW;
2929 __configure_output(asd, stream_index, width, height, padded_width,
2930 format, IA_CSS_PIPE_ID_COPY);
2934 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
2935 unsigned int stream_index,
2936 unsigned int width, unsigned int height,
2937 unsigned int padded_width,
2938 enum ia_css_frame_format format)
2940 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
2941 default_capture_config.mode =
2942 IA_CSS_CAPTURE_MODE_RAW;
2944 __configure_output(asd, stream_index, width, height, padded_width,
2945 format, IA_CSS_PIPE_ID_YUVPP);
2949 int atomisp_css_yuvpp_configure_viewfinder(
2950 struct atomisp_sub_device *asd,
2951 unsigned int stream_index,
2952 unsigned int width, unsigned int height,
2953 unsigned int min_width,
2954 enum ia_css_frame_format format)
2956 struct atomisp_stream_env *stream_env =
2957 &asd->stream_env[stream_index];
2958 enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP;
2960 stream_env->pipe_configs[pipe_id].mode =
2961 __pipe_id_to_pipe_mode(asd, pipe_id);
2962 stream_env->update_pipe[pipe_id] = true;
2964 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2965 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2966 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2967 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2972 int atomisp_css_yuvpp_get_output_frame_info(
2973 struct atomisp_sub_device *asd,
2974 unsigned int stream_index,
2975 struct ia_css_frame_info *info)
2977 return __get_frame_info(asd, stream_index, info,
2978 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
2981 int atomisp_css_yuvpp_get_viewfinder_frame_info(
2982 struct atomisp_sub_device *asd,
2983 unsigned int stream_index,
2984 struct ia_css_frame_info *info)
2986 return __get_frame_info(asd, stream_index, info,
2987 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
2990 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
2991 unsigned int width, unsigned int height,
2992 unsigned int min_width,
2993 enum ia_css_frame_format format)
2996 * to SOC camera, use yuvpp pipe.
2998 if (ATOMISP_USE_YUVPP(asd))
2999 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
3001 min_width, format, IA_CSS_PIPE_ID_YUVPP);
3003 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3004 min_width, format, IA_CSS_PIPE_ID_PREVIEW);
3008 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
3009 unsigned int width, unsigned int height,
3010 unsigned int min_width,
3011 enum ia_css_frame_format format)
3013 enum ia_css_pipe_id pipe_id;
3016 * to SOC camera, use yuvpp pipe.
3018 if (ATOMISP_USE_YUVPP(asd))
3019 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3021 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3023 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3024 min_width, format, pipe_id);
3028 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
3029 unsigned int width, unsigned int height,
3030 unsigned int min_width,
3031 enum ia_css_frame_format format)
3034 * to SOC camera, use yuvpp pipe.
3036 if (ATOMISP_USE_YUVPP(asd))
3037 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
3039 min_width, format, IA_CSS_PIPE_ID_YUVPP);
3041 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3042 min_width, format, IA_CSS_PIPE_ID_VIDEO);
3046 int atomisp_css_video_configure_viewfinder(
3047 struct atomisp_sub_device *asd,
3048 unsigned int width, unsigned int height,
3049 unsigned int min_width,
3050 enum ia_css_frame_format format)
3053 * to SOC camera, video will use yuvpp pipe.
3055 if (ATOMISP_USE_YUVPP(asd))
3056 __configure_video_vf_output(asd, width, height, min_width, format,
3057 IA_CSS_PIPE_ID_YUVPP);
3059 __configure_vf_output(asd, width, height, min_width, format,
3060 IA_CSS_PIPE_ID_VIDEO);
3064 int atomisp_css_capture_configure_viewfinder(
3065 struct atomisp_sub_device *asd,
3066 unsigned int width, unsigned int height,
3067 unsigned int min_width,
3068 enum ia_css_frame_format format)
3070 enum ia_css_pipe_id pipe_id;
3073 * to SOC camera, video will use yuvpp pipe.
3075 if (ATOMISP_USE_YUVPP(asd))
3076 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3078 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3080 __configure_vf_output(asd, width, height, min_width, format,
3085 int atomisp_css_video_get_viewfinder_frame_info(
3086 struct atomisp_sub_device *asd,
3087 struct ia_css_frame_info *info)
3089 enum ia_css_pipe_id pipe_id;
3090 enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME;
3092 if (ATOMISP_USE_YUVPP(asd)) {
3093 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3094 if (asd->continuous_mode->val)
3095 frame_type = ATOMISP_CSS_SECOND_VF_FRAME;
3097 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3100 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3101 frame_type, pipe_id);
3104 int atomisp_css_capture_get_viewfinder_frame_info(
3105 struct atomisp_sub_device *asd,
3106 struct ia_css_frame_info *info)
3108 enum ia_css_pipe_id pipe_id;
3110 if (ATOMISP_USE_YUVPP(asd))
3111 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3113 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3115 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3116 ATOMISP_CSS_VF_FRAME, pipe_id);
3119 int atomisp_css_capture_get_output_raw_frame_info(
3120 struct atomisp_sub_device *asd,
3121 struct ia_css_frame_info *info)
3123 if (ATOMISP_USE_YUVPP(asd))
3126 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3127 ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE);
3130 int atomisp_css_copy_get_output_frame_info(
3131 struct atomisp_sub_device *asd,
3132 unsigned int stream_index,
3133 struct ia_css_frame_info *info)
3135 return __get_frame_info(asd, stream_index, info,
3136 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
3139 int atomisp_css_preview_get_output_frame_info(
3140 struct atomisp_sub_device *asd,
3141 struct ia_css_frame_info *info)
3143 enum ia_css_pipe_id pipe_id;
3144 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3146 if (ATOMISP_USE_YUVPP(asd)) {
3147 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3148 if (asd->continuous_mode->val)
3149 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3151 pipe_id = IA_CSS_PIPE_ID_PREVIEW;
3154 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3155 frame_type, pipe_id);
3158 int atomisp_css_capture_get_output_frame_info(
3159 struct atomisp_sub_device *asd,
3160 struct ia_css_frame_info *info)
3162 enum ia_css_pipe_id pipe_id;
3164 if (ATOMISP_USE_YUVPP(asd))
3165 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3167 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3169 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3170 ATOMISP_CSS_OUTPUT_FRAME, pipe_id);
3173 int atomisp_css_video_get_output_frame_info(
3174 struct atomisp_sub_device *asd,
3175 struct ia_css_frame_info *info)
3177 enum ia_css_pipe_id pipe_id;
3178 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3180 if (ATOMISP_USE_YUVPP(asd)) {
3181 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3182 if (asd->continuous_mode->val)
3183 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3185 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3188 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3189 frame_type, pipe_id);
3192 int atomisp_css_preview_configure_pp_input(
3193 struct atomisp_sub_device *asd,
3194 unsigned int width, unsigned int height)
3196 struct atomisp_stream_env *stream_env =
3197 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3198 __configure_preview_pp_input(asd, width, height,
3199 ATOMISP_USE_YUVPP(asd) ?
3200 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW);
3202 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3203 capt_pp_in_res.width)
3204 __configure_capture_pp_input(asd, width, height,
3205 ATOMISP_USE_YUVPP(asd) ?
3206 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3210 int atomisp_css_capture_configure_pp_input(
3211 struct atomisp_sub_device *asd,
3212 unsigned int width, unsigned int height)
3214 __configure_capture_pp_input(asd, width, height,
3215 ATOMISP_USE_YUVPP(asd) ?
3216 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3220 int atomisp_css_video_configure_pp_input(
3221 struct atomisp_sub_device *asd,
3222 unsigned int width, unsigned int height)
3224 struct atomisp_stream_env *stream_env =
3225 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3227 __configure_video_pp_input(asd, width, height,
3228 ATOMISP_USE_YUVPP(asd) ?
3229 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO);
3231 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3232 capt_pp_in_res.width)
3233 __configure_capture_pp_input(asd, width, height,
3234 ATOMISP_USE_YUVPP(asd) ?
3235 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3239 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
3240 int num_captures, unsigned int skip, int offset)
3244 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
3245 __func__, num_captures, skip, offset);
3247 ret = ia_css_stream_capture(
3248 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3249 num_captures, skip, offset);
3256 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
3260 ret = ia_css_stream_capture_frame(
3261 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3263 if (ret == -ENOBUFS) {
3264 /* capture cmd queue is full */
3273 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
3277 ret = ia_css_unlock_raw_frame(
3278 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3280 if (ret == -ENOBUFS)
3288 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
3291 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3292 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
3293 .default_capture_config.enable_xnr = enable;
3294 asd->params.capture_config.enable_xnr = enable;
3295 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3296 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
3301 void atomisp_css_send_input_frame(struct atomisp_sub_device *asd,
3302 unsigned short *data, unsigned int width,
3303 unsigned int height)
3305 ia_css_stream_send_input_frame(
3306 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3307 data, width, height);
3310 bool atomisp_css_isp_has_started(void)
3312 return ia_css_isp_has_started();
3315 void atomisp_css_request_flash(struct atomisp_sub_device *asd)
3317 ia_css_stream_request_flash(
3318 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream);
3321 void atomisp_css_set_wb_config(struct atomisp_sub_device *asd,
3322 struct ia_css_wb_config *wb_config)
3324 asd->params.config.wb_config = wb_config;
3327 void atomisp_css_set_ob_config(struct atomisp_sub_device *asd,
3328 struct ia_css_ob_config *ob_config)
3330 asd->params.config.ob_config = ob_config;
3333 void atomisp_css_set_dp_config(struct atomisp_sub_device *asd,
3334 struct ia_css_dp_config *dp_config)
3336 asd->params.config.dp_config = dp_config;
3339 void atomisp_css_set_de_config(struct atomisp_sub_device *asd,
3340 struct ia_css_de_config *de_config)
3342 asd->params.config.de_config = de_config;
3345 void atomisp_css_set_dz_config(struct atomisp_sub_device *asd,
3346 struct ia_css_dz_config *dz_config)
3348 asd->params.config.dz_config = dz_config;
3351 void atomisp_css_set_default_de_config(struct atomisp_sub_device *asd)
3353 asd->params.config.de_config = NULL;
3356 void atomisp_css_set_ce_config(struct atomisp_sub_device *asd,
3357 struct ia_css_ce_config *ce_config)
3359 asd->params.config.ce_config = ce_config;
3362 void atomisp_css_set_nr_config(struct atomisp_sub_device *asd,
3363 struct ia_css_nr_config *nr_config)
3365 asd->params.config.nr_config = nr_config;
3368 void atomisp_css_set_ee_config(struct atomisp_sub_device *asd,
3369 struct ia_css_ee_config *ee_config)
3371 asd->params.config.ee_config = ee_config;
3374 void atomisp_css_set_tnr_config(struct atomisp_sub_device *asd,
3375 struct ia_css_tnr_config *tnr_config)
3377 asd->params.config.tnr_config = tnr_config;
3380 void atomisp_css_set_cc_config(struct atomisp_sub_device *asd,
3381 struct ia_css_cc_config *cc_config)
3383 asd->params.config.cc_config = cc_config;
3386 void atomisp_css_set_macc_table(struct atomisp_sub_device *asd,
3387 struct ia_css_macc_table *macc_table)
3389 asd->params.config.macc_table = macc_table;
3392 void atomisp_css_set_macc_config(struct atomisp_sub_device *asd,
3393 struct ia_css_macc_config *macc_config)
3395 asd->params.config.macc_config = macc_config;
3398 void atomisp_css_set_ecd_config(struct atomisp_sub_device *asd,
3399 struct ia_css_ecd_config *ecd_config)
3401 asd->params.config.ecd_config = ecd_config;
3404 void atomisp_css_set_ynr_config(struct atomisp_sub_device *asd,
3405 struct ia_css_ynr_config *ynr_config)
3407 asd->params.config.ynr_config = ynr_config;
3410 void atomisp_css_set_fc_config(struct atomisp_sub_device *asd,
3411 struct ia_css_fc_config *fc_config)
3413 asd->params.config.fc_config = fc_config;
3416 void atomisp_css_set_ctc_config(struct atomisp_sub_device *asd,
3417 struct ia_css_ctc_config *ctc_config)
3419 asd->params.config.ctc_config = ctc_config;
3422 void atomisp_css_set_cnr_config(struct atomisp_sub_device *asd,
3423 struct ia_css_cnr_config *cnr_config)
3425 asd->params.config.cnr_config = cnr_config;
3428 void atomisp_css_set_aa_config(struct atomisp_sub_device *asd,
3429 struct ia_css_aa_config *aa_config)
3431 asd->params.config.aa_config = aa_config;
3434 void atomisp_css_set_baa_config(struct atomisp_sub_device *asd,
3435 struct ia_css_aa_config *baa_config)
3437 asd->params.config.baa_config = baa_config;
3440 void atomisp_css_set_anr_config(struct atomisp_sub_device *asd,
3441 struct ia_css_anr_config *anr_config)
3443 asd->params.config.anr_config = anr_config;
3446 void atomisp_css_set_xnr_config(struct atomisp_sub_device *asd,
3447 struct ia_css_xnr_config *xnr_config)
3449 asd->params.config.xnr_config = xnr_config;
3452 void atomisp_css_set_yuv2rgb_cc_config(struct atomisp_sub_device *asd,
3453 struct ia_css_cc_config *yuv2rgb_cc_config)
3455 asd->params.config.yuv2rgb_cc_config = yuv2rgb_cc_config;
3458 void atomisp_css_set_rgb2yuv_cc_config(struct atomisp_sub_device *asd,
3459 struct ia_css_cc_config *rgb2yuv_cc_config)
3461 asd->params.config.rgb2yuv_cc_config = rgb2yuv_cc_config;
3464 void atomisp_css_set_xnr_table(struct atomisp_sub_device *asd,
3465 struct ia_css_xnr_table *xnr_table)
3467 asd->params.config.xnr_table = xnr_table;
3470 void atomisp_css_set_r_gamma_table(struct atomisp_sub_device *asd,
3471 struct ia_css_rgb_gamma_table *r_gamma_table)
3473 asd->params.config.r_gamma_table = r_gamma_table;
3476 void atomisp_css_set_g_gamma_table(struct atomisp_sub_device *asd,
3477 struct ia_css_rgb_gamma_table *g_gamma_table)
3479 asd->params.config.g_gamma_table = g_gamma_table;
3482 void atomisp_css_set_b_gamma_table(struct atomisp_sub_device *asd,
3483 struct ia_css_rgb_gamma_table *b_gamma_table)
3485 asd->params.config.b_gamma_table = b_gamma_table;
3488 void atomisp_css_set_gamma_table(struct atomisp_sub_device *asd,
3489 struct ia_css_gamma_table *gamma_table)
3491 asd->params.config.gamma_table = gamma_table;
3494 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
3495 struct ia_css_ctc_table *ctc_table)
3498 u16 *vamem_ptr = ctc_table->data.vamem_1;
3499 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
3502 /* workaround: if ctc_table is all 0, do not apply it */
3503 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
3504 vamem_ptr = ctc_table->data.vamem_2;
3505 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
3508 for (i = 0; i < data_size; i++) {
3509 if (*(vamem_ptr + i)) {
3516 asd->params.config.ctc_table = ctc_table;
3518 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
3521 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
3522 struct ia_css_anr_thres *anr_thres)
3524 asd->params.config.anr_thres = anr_thres;
3527 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
3528 struct ia_css_dvs_6axis_config *dvs_6axis)
3530 asd->params.config.dvs_6axis_config = dvs_6axis;
3533 void atomisp_css_set_gc_config(struct atomisp_sub_device *asd,
3534 struct ia_css_gc_config *gc_config)
3536 asd->params.config.gc_config = gc_config;
3539 void atomisp_css_set_3a_config(struct atomisp_sub_device *asd,
3540 struct ia_css_3a_config *s3a_config)
3542 asd->params.config.s3a_config = s3a_config;
3545 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
3546 struct atomisp_dis_vector *vector)
3548 if (!asd->params.config.motion_vector)
3549 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
3551 memset(asd->params.config.motion_vector,
3552 0, sizeof(struct ia_css_vector));
3553 asd->params.css_param.motion_vector.x = vector->x;
3554 asd->params.css_param.motion_vector.y = vector->y;
3557 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
3558 struct atomisp_dvs_grid_info *atomgrid)
3560 struct ia_css_dvs_grid_info *cur =
3561 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
3564 dev_err(asd->isp->dev, "dvs grid not available!\n");
3568 if (sizeof(*cur) != sizeof(*atomgrid)) {
3569 dev_err(asd->isp->dev, "dvs grid mis-match!\n");
3574 dev_err(asd->isp->dev, "dvs not enabled!\n");
3578 return memcmp(atomgrid, cur, sizeof(*cur));
3581 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
3582 struct ia_css_dvs2_coefficients *coefs)
3584 asd->params.config.dvs2_coefs = coefs;
3587 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
3588 struct atomisp_dis_coefficients *coefs)
3590 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
3591 /* If the grid info in the argument differs from the current
3592 grid info, we tell the caller to reset the grid size and
3596 if (!coefs->hor_coefs.odd_real ||
3597 !coefs->hor_coefs.odd_imag ||
3598 !coefs->hor_coefs.even_real ||
3599 !coefs->hor_coefs.even_imag ||
3600 !coefs->ver_coefs.odd_real ||
3601 !coefs->ver_coefs.odd_imag ||
3602 !coefs->ver_coefs.even_real ||
3603 !coefs->ver_coefs.even_imag ||
3604 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real ||
3605 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag ||
3606 !asd->params.css_param.dvs2_coeff->hor_coefs.even_real ||
3607 !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag ||
3608 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real ||
3609 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag ||
3610 !asd->params.css_param.dvs2_coeff->ver_coefs.even_real ||
3611 !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag)
3614 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
3615 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
3617 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
3618 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
3620 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
3621 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
3623 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
3624 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
3627 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
3628 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
3630 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
3631 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
3633 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
3634 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
3636 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
3637 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
3640 asd->params.css_param.update_flag.dvs2_coefs =
3641 (struct atomisp_dvs2_coefficients *)
3642 asd->params.css_param.dvs2_coeff;
3644 /* asd->params.dis_proj_data_valid = false; */
3645 asd->params.css_update_params_needed = true;
3650 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
3653 struct atomisp_device *isp = asd->isp;
3655 if (zoom == asd->params.css_param.dz_config.dx &&
3656 zoom == asd->params.css_param.dz_config.dy) {
3657 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
3661 memset(&asd->params.css_param.dz_config, 0,
3662 sizeof(struct ia_css_dz_config));
3663 asd->params.css_param.dz_config.dx = zoom;
3664 asd->params.css_param.dz_config.dy = zoom;
3666 asd->params.css_param.update_flag.dz_config =
3667 (struct atomisp_dz_config *)&asd->params.css_param.dz_config;
3668 asd->params.css_update_params_needed = true;
3671 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
3672 struct ia_css_formats_config *formats_config)
3674 asd->params.config.formats_config = formats_config;
3677 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
3678 struct atomisp_wb_config *config)
3680 struct ia_css_wb_config wb_config;
3681 struct ia_css_isp_config isp_config;
3682 struct atomisp_device *isp = asd->isp;
3684 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3685 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3689 memset(&wb_config, 0, sizeof(struct ia_css_wb_config));
3690 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3691 isp_config.wb_config = &wb_config;
3692 ia_css_stream_get_isp_config(
3693 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3695 memcpy(config, &wb_config, sizeof(*config));
3700 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
3701 struct atomisp_ob_config *config)
3703 struct ia_css_ob_config ob_config;
3704 struct ia_css_isp_config isp_config;
3705 struct atomisp_device *isp = asd->isp;
3707 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3708 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3712 memset(&ob_config, 0, sizeof(struct ia_css_ob_config));
3713 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3714 isp_config.ob_config = &ob_config;
3715 ia_css_stream_get_isp_config(
3716 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3718 memcpy(config, &ob_config, sizeof(*config));
3723 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
3724 struct atomisp_dp_config *config)
3726 struct ia_css_dp_config dp_config;
3727 struct ia_css_isp_config isp_config;
3728 struct atomisp_device *isp = asd->isp;
3730 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3731 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3735 memset(&dp_config, 0, sizeof(struct ia_css_dp_config));
3736 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3737 isp_config.dp_config = &dp_config;
3738 ia_css_stream_get_isp_config(
3739 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3741 memcpy(config, &dp_config, sizeof(*config));
3746 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3747 struct atomisp_de_config *config)
3749 struct ia_css_de_config de_config;
3750 struct ia_css_isp_config isp_config;
3751 struct atomisp_device *isp = asd->isp;
3753 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3754 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3758 memset(&de_config, 0, sizeof(struct ia_css_de_config));
3759 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3760 isp_config.de_config = &de_config;
3761 ia_css_stream_get_isp_config(
3762 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3764 memcpy(config, &de_config, sizeof(*config));
3769 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3770 struct atomisp_nr_config *config)
3772 struct ia_css_nr_config nr_config;
3773 struct ia_css_isp_config isp_config;
3774 struct atomisp_device *isp = asd->isp;
3776 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3777 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3781 memset(&nr_config, 0, sizeof(struct ia_css_nr_config));
3782 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3784 isp_config.nr_config = &nr_config;
3785 ia_css_stream_get_isp_config(
3786 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3788 memcpy(config, &nr_config, sizeof(*config));
3793 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3794 struct atomisp_ee_config *config)
3796 struct ia_css_ee_config ee_config;
3797 struct ia_css_isp_config isp_config;
3798 struct atomisp_device *isp = asd->isp;
3800 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3801 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3805 memset(&ee_config, 0, sizeof(struct ia_css_ee_config));
3806 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3807 isp_config.ee_config = &ee_config;
3808 ia_css_stream_get_isp_config(
3809 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3811 memcpy(config, &ee_config, sizeof(*config));
3816 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3817 struct atomisp_tnr_config *config)
3819 struct ia_css_tnr_config tnr_config;
3820 struct ia_css_isp_config isp_config;
3821 struct atomisp_device *isp = asd->isp;
3823 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3824 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3828 memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config));
3829 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3830 isp_config.tnr_config = &tnr_config;
3831 ia_css_stream_get_isp_config(
3832 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3834 memcpy(config, &tnr_config, sizeof(*config));
3839 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3840 struct atomisp_ctc_table *config)
3842 struct ia_css_ctc_table *tab;
3843 struct ia_css_isp_config isp_config;
3844 struct atomisp_device *isp = asd->isp;
3846 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3847 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3852 tab = vzalloc(sizeof(struct ia_css_ctc_table));
3856 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3857 isp_config.ctc_table = tab;
3858 ia_css_stream_get_isp_config(
3859 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3861 memcpy(config, tab, sizeof(*tab));
3867 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
3868 struct atomisp_gamma_table *config)
3870 struct ia_css_gamma_table *tab;
3871 struct ia_css_isp_config isp_config;
3872 struct atomisp_device *isp = asd->isp;
3874 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3875 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3880 tab = vzalloc(sizeof(struct ia_css_gamma_table));
3884 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3885 isp_config.gamma_table = tab;
3886 ia_css_stream_get_isp_config(
3887 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3889 memcpy(config, tab, sizeof(*tab));
3895 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
3896 struct atomisp_gc_config *config)
3898 struct ia_css_gc_config gc_config;
3899 struct ia_css_isp_config isp_config;
3900 struct atomisp_device *isp = asd->isp;
3902 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3903 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3907 memset(&gc_config, 0, sizeof(struct ia_css_gc_config));
3908 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3909 isp_config.gc_config = &gc_config;
3910 ia_css_stream_get_isp_config(
3911 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3913 /* Get gamma correction params from current setup */
3914 memcpy(config, &gc_config, sizeof(*config));
3919 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
3920 struct atomisp_3a_config *config)
3922 struct ia_css_3a_config s3a_config;
3923 struct ia_css_isp_config isp_config;
3924 struct atomisp_device *isp = asd->isp;
3926 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3927 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3931 memset(&s3a_config, 0, sizeof(struct ia_css_3a_config));
3932 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3933 isp_config.s3a_config = &s3a_config;
3934 ia_css_stream_get_isp_config(
3935 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3937 /* Get white balance from current setup */
3938 memcpy(config, &s3a_config, sizeof(*config));
3943 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
3944 struct atomisp_formats_config *config)
3946 struct ia_css_formats_config formats_config;
3947 struct ia_css_isp_config isp_config;
3948 struct atomisp_device *isp = asd->isp;
3950 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3951 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3955 memset(&formats_config, 0, sizeof(formats_config));
3956 memset(&isp_config, 0, sizeof(isp_config));
3957 isp_config.formats_config = &formats_config;
3958 ia_css_stream_get_isp_config(
3959 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3961 /* Get narrow gamma from current setup */
3962 memcpy(config, &formats_config, sizeof(*config));
3967 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
3970 struct ia_css_dz_config dz_config; /** Digital Zoom */
3971 struct ia_css_isp_config isp_config;
3972 struct atomisp_device *isp = asd->isp;
3974 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3975 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3979 memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
3980 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3981 isp_config.dz_config = &dz_config;
3982 ia_css_stream_get_isp_config(
3983 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3985 *zoom = dz_config.dx;
3991 * Function to set/get image stablization statistics
3993 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
3994 struct atomisp_dis_statistics *stats)
3996 struct atomisp_device *isp = asd->isp;
3997 struct atomisp_dis_buf *dis_buf;
3998 unsigned long flags;
4000 if (!asd->params.dvs_stat->hor_prod.odd_real ||
4001 !asd->params.dvs_stat->hor_prod.odd_imag ||
4002 !asd->params.dvs_stat->hor_prod.even_real ||
4003 !asd->params.dvs_stat->hor_prod.even_imag ||
4004 !asd->params.dvs_stat->ver_prod.odd_real ||
4005 !asd->params.dvs_stat->ver_prod.odd_imag ||
4006 !asd->params.dvs_stat->ver_prod.even_real ||
4007 !asd->params.dvs_stat->ver_prod.even_imag)
4010 /* isp needs to be streaming to get DIS statistics */
4011 spin_lock_irqsave(&isp->lock, flags);
4012 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) {
4013 spin_unlock_irqrestore(&isp->lock, flags);
4016 spin_unlock_irqrestore(&isp->lock, flags);
4018 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
4019 /* If the grid info in the argument differs from the current
4020 grid info, we tell the caller to reset the grid size and
4024 spin_lock_irqsave(&asd->dis_stats_lock, flags);
4025 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
4026 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4027 dev_err(isp->dev, "dis statistics is not valid.\n");
4031 dis_buf = list_entry(asd->dis_stats.next,
4032 struct atomisp_dis_buf, list);
4033 list_del_init(&dis_buf->list);
4034 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4036 if (dis_buf->dvs_map)
4037 ia_css_translate_dvs2_statistics(
4038 asd->params.dvs_stat, dis_buf->dvs_map);
4040 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
4042 stats->exp_id = dis_buf->dis_data->exp_id;
4044 spin_lock_irqsave(&asd->dis_stats_lock, flags);
4045 list_add_tail(&dis_buf->list, &asd->dis_stats);
4046 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4048 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
4049 asd->params.dvs_stat->ver_prod.odd_real,
4050 asd->params.dvs_ver_proj_bytes))
4052 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
4053 asd->params.dvs_stat->ver_prod.odd_imag,
4054 asd->params.dvs_ver_proj_bytes))
4056 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
4057 asd->params.dvs_stat->ver_prod.even_real,
4058 asd->params.dvs_ver_proj_bytes))
4060 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
4061 asd->params.dvs_stat->ver_prod.even_imag,
4062 asd->params.dvs_ver_proj_bytes))
4064 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
4065 asd->params.dvs_stat->hor_prod.odd_real,
4066 asd->params.dvs_hor_proj_bytes))
4068 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
4069 asd->params.dvs_stat->hor_prod.odd_imag,
4070 asd->params.dvs_hor_proj_bytes))
4072 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
4073 asd->params.dvs_stat->hor_prod.even_real,
4074 asd->params.dvs_hor_proj_bytes))
4076 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
4077 asd->params.dvs_stat->hor_prod.even_imag,
4078 asd->params.dvs_hor_proj_bytes))
4084 struct ia_css_shading_table *atomisp_css_shading_table_alloc(
4085 unsigned int width, unsigned int height)
4087 return ia_css_shading_table_alloc(width, height);
4090 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
4091 struct ia_css_shading_table *table)
4093 asd->params.config.shading_table = table;
4096 void atomisp_css_shading_table_free(struct ia_css_shading_table *table)
4098 ia_css_shading_table_free(table);
4101 struct ia_css_morph_table *atomisp_css_morph_table_allocate(
4102 unsigned int width, unsigned int height)
4104 return ia_css_morph_table_allocate(width, height);
4107 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
4108 struct ia_css_morph_table *table)
4110 asd->params.config.morph_table = table;
4113 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
4114 struct ia_css_morph_table *table)
4116 struct ia_css_isp_config isp_config;
4117 struct atomisp_device *isp = asd->isp;
4119 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4121 "%s called after streamoff, skipping.\n", __func__);
4124 memset(table, 0, sizeof(struct ia_css_morph_table));
4125 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4126 isp_config.morph_table = table;
4127 ia_css_stream_get_isp_config(
4128 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4132 void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
4134 ia_css_morph_table_free(table);
4137 void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp,
4138 unsigned int overlap)
4140 /* CSS 2.0 doesn't support this API. */
4141 dev_dbg(isp->dev, "set cont prev start time is not supported.\n");
4145 void atomisp_css_acc_done(struct atomisp_sub_device *asd)
4147 complete(&asd->acc.acc_done);
4150 int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd)
4153 struct atomisp_device *isp = asd->isp;
4155 /* Unlock the isp mutex taken in IOCTL handler before sleeping! */
4156 rt_mutex_unlock(&isp->mutex);
4157 if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done,
4158 ATOMISP_ISP_TIMEOUT_DURATION) == 0) {
4159 dev_err(isp->dev, "<%s: completion timeout\n", __func__);
4160 ia_css_debug_dump_sp_sw_debug_info();
4161 ia_css_debug_dump_debug_info(__func__);
4164 rt_mutex_lock(&isp->mutex);
4169 /* Set the ACC binary arguments */
4170 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw)
4174 for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) {
4175 if (acc_fw->args[mem].length == 0)
4178 ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers,
4179 IA_CSS_PARAM_CLASS_PARAM, mem,
4180 acc_fw->args[mem].css_ptr,
4181 acc_fw->args[mem].length);
4187 /* Load acc binary extension */
4188 int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd,
4189 struct ia_css_fw_info *fw,
4190 enum ia_css_pipe_id pipe_id,
4193 struct ia_css_fw_info **hd;
4196 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4197 .pipe_configs[pipe_id].acc_extension);
4202 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4203 .update_pipe[pipe_id] = true;
4207 /* Unload acc binary extension */
4208 void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd,
4209 struct ia_css_fw_info *fw,
4210 enum ia_css_pipe_id pipe_id)
4212 struct ia_css_fw_info **hd;
4214 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4215 .pipe_configs[pipe_id].acc_extension);
4216 while (*hd && *hd != fw)
4219 dev_err(asd->isp->dev, "did not find acc fw for removal\n");
4225 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4226 .update_pipe[pipe_id] = true;
4229 int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd)
4231 struct atomisp_device *isp = asd->isp;
4232 struct ia_css_pipe_config *pipe_config;
4233 struct atomisp_stream_env *stream_env =
4234 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4236 if (stream_env->acc_stream) {
4237 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4238 if (ia_css_stream_stop(stream_env->acc_stream)
4240 dev_err(isp->dev, "stop acc_stream failed.\n");
4245 if (ia_css_stream_destroy(stream_env->acc_stream)
4247 dev_err(isp->dev, "destroy acc_stream failed.\n");
4250 stream_env->acc_stream = NULL;
4253 pipe_config = &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
4254 ia_css_pipe_config_defaults(pipe_config);
4255 asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES *
4256 sizeof(void *), GFP_KERNEL);
4257 if (!asd->acc.acc_stages)
4259 pipe_config->acc_stages = asd->acc.acc_stages;
4260 pipe_config->mode = IA_CSS_PIPE_MODE_ACC;
4261 pipe_config->num_acc_stages = 0;
4264 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe,
4265 * because pipe configuration will soon be changed by
4266 * atomisp_css_load_acc_binary()
4271 int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd)
4273 struct atomisp_device *isp = asd->isp;
4274 struct atomisp_stream_env *stream_env =
4275 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4276 struct ia_css_pipe_config *pipe_config =
4277 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
4279 if (ia_css_pipe_create(pipe_config,
4280 &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != 0) {
4281 dev_err(isp->dev, "%s: ia_css_pipe_create failed\n",
4286 memset(&stream_env->acc_stream_config, 0,
4287 sizeof(struct ia_css_stream_config));
4288 if (ia_css_stream_create(&stream_env->acc_stream_config, 1,
4289 &stream_env->pipes[IA_CSS_PIPE_ID_ACC],
4290 &stream_env->acc_stream) != 0) {
4291 dev_err(isp->dev, "%s: create acc_stream error.\n", __func__);
4294 stream_env->acc_stream_state = CSS_STREAM_CREATED;
4296 init_completion(&asd->acc.acc_done);
4297 asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC];
4299 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
4301 if (ia_css_start_sp()) {
4302 dev_err(isp->dev, "start sp error.\n");
4306 if (ia_css_stream_start(stream_env->acc_stream)
4308 dev_err(isp->dev, "acc_stream start error.\n");
4312 stream_env->acc_stream_state = CSS_STREAM_STARTED;
4316 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd)
4318 struct atomisp_stream_env *stream_env =
4319 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4320 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4321 ia_css_stream_stop(stream_env->acc_stream);
4322 stream_env->acc_stream_state = CSS_STREAM_STOPPED;
4327 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd)
4329 struct atomisp_stream_env *stream_env =
4330 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4331 if (stream_env->acc_stream) {
4332 if (ia_css_stream_destroy(stream_env->acc_stream)
4334 dev_warn(asd->isp->dev,
4335 "destroy acc_stream failed.\n");
4336 stream_env->acc_stream = NULL;
4339 if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) {
4340 if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC])
4342 dev_warn(asd->isp->dev,
4343 "destroy ACC pipe failed.\n");
4344 stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL;
4345 stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false;
4346 ia_css_pipe_config_defaults(
4347 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]);
4348 ia_css_pipe_extra_config_defaults(
4349 &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]);
4351 asd->acc.pipeline = NULL;
4353 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
4358 kfree(asd->acc.acc_stages);
4359 asd->acc.acc_stages = NULL;
4361 atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false);
4364 int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd,
4365 struct ia_css_fw_info *fw,
4368 struct ia_css_pipe_config *pipe_config =
4369 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4370 .pipe_configs[IA_CSS_PIPE_ID_ACC];
4372 if (index >= MAX_ACC_STAGES) {
4373 dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n",
4378 pipe_config->acc_stages[index] = fw;
4379 pipe_config->num_acc_stages = index + 1;
4380 pipe_config->acc_num_execs = 1;
4385 static struct atomisp_sub_device *__get_atomisp_subdev(
4386 struct ia_css_pipe *css_pipe,
4387 struct atomisp_device *isp,
4388 enum atomisp_input_stream_id *stream_id)
4391 struct atomisp_sub_device *asd;
4392 struct atomisp_stream_env *stream_env;
4394 for (i = 0; i < isp->num_of_streams; i++) {
4396 if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED &&
4399 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4400 stream_env = &asd->stream_env[j];
4401 for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
4402 if (stream_env->pipes[k] &&
4403 stream_env->pipes[k] == css_pipe) {
4414 int atomisp_css_isr_thread(struct atomisp_device *isp,
4415 bool *frame_done_found,
4416 bool *css_pipe_done)
4418 enum atomisp_input_stream_id stream_id = 0;
4419 struct atomisp_css_event current_event;
4420 struct atomisp_sub_device *asd;
4421 bool reset_wdt_timer[MAX_STREAM_NUM] = {false};
4424 while (!atomisp_css_dequeue_event(¤t_event)) {
4425 if (current_event.event.type ==
4426 IA_CSS_EVENT_TYPE_FW_ASSERT) {
4428 * Received FW assertion signal,
4429 * trigger WDT to recover
4432 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
4434 current_event.event.fw_assert_module_id,
4435 current_event.event.fw_assert_line_no);
4436 for (i = 0; i < isp->num_of_streams; i++)
4437 atomisp_wdt_stop(&isp->asd[i], 0);
4439 if (!atomisp_hw_is_isp2401)
4440 atomisp_wdt(&isp->asd[0].wdt);
4442 queue_work(isp->wdt_work_queue, &isp->wdt_work);
4445 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4446 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
4447 __func__, current_event.event.fw_warning,
4448 current_event.event.exp_id);
4452 asd = __get_atomisp_subdev(current_event.event.pipe,
4455 if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
4457 "event: Timer event.");
4459 dev_warn(isp->dev, "%s:no subdev.event:%d",
4461 current_event.event.type);
4465 atomisp_css_temp_pipe_to_pipe_id(asd, ¤t_event);
4466 switch (current_event.event.type) {
4467 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
4468 dev_dbg(isp->dev, "event: Output frame done");
4469 frame_done_found[asd->index] = true;
4470 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
4471 current_event.pipe, true, stream_id);
4473 if (!atomisp_hw_is_isp2401)
4474 reset_wdt_timer[asd->index] = true; /* ISP running */
4477 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
4478 dev_dbg(isp->dev, "event: Second output frame done");
4479 frame_done_found[asd->index] = true;
4480 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
4481 current_event.pipe, true, stream_id);
4483 if (!atomisp_hw_is_isp2401)
4484 reset_wdt_timer[asd->index] = true; /* ISP running */
4487 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
4488 dev_dbg(isp->dev, "event: 3A stats frame done");
4489 atomisp_buf_done(asd, 0,
4490 IA_CSS_BUFFER_TYPE_3A_STATISTICS,
4494 case IA_CSS_EVENT_TYPE_METADATA_DONE:
4495 dev_dbg(isp->dev, "event: metadata frame done");
4496 atomisp_buf_done(asd, 0,
4497 IA_CSS_BUFFER_TYPE_METADATA,
4501 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
4502 dev_dbg(isp->dev, "event: VF output frame done");
4503 atomisp_buf_done(asd, 0,
4504 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
4505 current_event.pipe, true, stream_id);
4507 if (!atomisp_hw_is_isp2401)
4508 reset_wdt_timer[asd->index] = true; /* ISP running */
4511 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
4512 dev_dbg(isp->dev, "event: second VF output frame done");
4513 atomisp_buf_done(asd, 0,
4514 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
4515 current_event.pipe, true, stream_id);
4516 if (!atomisp_hw_is_isp2401)
4517 reset_wdt_timer[asd->index] = true; /* ISP running */
4520 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
4521 dev_dbg(isp->dev, "event: dis stats frame done");
4522 atomisp_buf_done(asd, 0,
4523 IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
4527 case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
4528 dev_dbg(isp->dev, "event: pipeline done");
4529 css_pipe_done[asd->index] = true;
4531 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
4532 dev_dbg(isp->dev, "event: acc stage done");
4533 atomisp_acc_done(asd, current_event.event.fw_handle);
4536 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
4537 current_event.event.type);
4542 if (atomisp_hw_is_isp2401)
4545 /* ISP2400: If there are no buffers queued then delete wdt timer. */
4546 for (i = 0; i < isp->num_of_streams; i++) {
4550 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
4552 if (!atomisp_buffers_queued(asd))
4553 atomisp_wdt_stop(asd, false);
4554 else if (reset_wdt_timer[i])
4555 /* SOF irq should not reset wdt timer. */
4556 atomisp_wdt_refresh(asd,
4557 ATOMISP_WDT_KEEP_CURRENT_DELAY);
4563 bool atomisp_css_valid_sof(struct atomisp_device *isp)
4567 /* Loop for each css stream */
4568 for (i = 0; i < isp->num_of_streams; i++) {
4569 struct atomisp_sub_device *asd = &isp->asd[i];
4570 /* Loop for each css vc stream */
4571 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4572 if (asd->stream_env[j].stream &&
4573 asd->stream_env[j].stream_config.mode ==
4574 IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
4582 int atomisp_css_debug_dump_isp_binary(void)
4584 ia_css_debug_dump_isp_binary();
4588 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
4590 sh_css_dump_sp_raw_copy_linecount(reduced);
4594 int atomisp_css_dump_blob_infor(void)
4596 struct ia_css_blob_descr *bd = sh_css_blob_info;
4597 unsigned int i, nm = sh_css_num_binaries;
4604 for (i = 1; i < sh_css_num_binaries; i++)
4605 dev_dbg(atomisp_dev, "Num%d binary id is %d, name is %s\n", i,
4606 bd[i - 1].header.info.isp.sp.id, bd[i - 1].name);
4611 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
4612 uint32_t isp_config_id)
4614 asd->params.config.isp_config_id = isp_config_id;
4617 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
4618 struct ia_css_frame *output_frame)
4620 asd->params.config.output_frame = output_frame;
4623 int atomisp_get_css_dbgfunc(void)
4628 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
4632 ret = __set_css_print_env(isp, opt);
4639 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
4641 ia_css_en_dz_capt_pipe(
4642 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4646 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
4647 struct ia_css_grid_info *grid_info)
4652 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
4653 return &grid_info->dvs_grid.dvs_grid_info;
4655 return &grid_info->dvs_grid;