1 // SPDX-License-Identifier: GPL-2.0
3 * Support for Clovertrail PNW Camera Imaging ISP subsystem.
5 * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
19 #include <media/videobuf-vmalloc.h>
20 #include <media/v4l2-dev.h>
21 #include <media/v4l2-event.h>
23 #include "mmu/isp_mmu.h"
24 #include "mmu/sh_mmu_mrfld.h"
25 #include "hmm/hmm_bo.h"
28 #include "atomisp_compat.h"
29 #include "atomisp_internal.h"
30 #include "atomisp_cmd.h"
31 #include "atomisp-regs.h"
32 #include "atomisp_fops.h"
33 #include "atomisp_ioctl.h"
34 #include "atomisp_acc.h"
36 #include <asm/intel-mid.h>
38 #include "ia_css_debug.h"
39 #include "ia_css_isp_param.h"
40 #include "sh_css_hrt.h"
41 #include "ia_css_isys.h"
43 #include <linux/pm_runtime.h>
45 /* Assume max number of ACC stages */
46 #define MAX_ACC_STAGES 20
48 /* Ideally, this should come from CSS headers */
52 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
53 * #4684168, if concurrency access happened, system may hard hang.
55 static DEFINE_SPINLOCK(mmio_lock);
57 enum frame_info_type {
59 ATOMISP_CSS_SECOND_VF_FRAME,
60 ATOMISP_CSS_OUTPUT_FRAME,
61 ATOMISP_CSS_SECOND_OUTPUT_FRAME,
62 ATOMISP_CSS_RAW_FRAME,
65 struct bayer_ds_factor {
66 unsigned int numerator;
67 unsigned int denominator;
70 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
74 spin_lock_irqsave(&mmio_lock, flags);
75 _hrt_master_port_store_8(addr, data);
76 spin_unlock_irqrestore(&mmio_lock, flags);
79 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
83 spin_lock_irqsave(&mmio_lock, flags);
84 _hrt_master_port_store_16(addr, data);
85 spin_unlock_irqrestore(&mmio_lock, flags);
88 void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
92 spin_lock_irqsave(&mmio_lock, flags);
93 _hrt_master_port_store_32(addr, data);
94 spin_unlock_irqrestore(&mmio_lock, flags);
97 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
102 spin_lock_irqsave(&mmio_lock, flags);
103 ret = _hrt_master_port_load_8(addr);
104 spin_unlock_irqrestore(&mmio_lock, flags);
108 static uint16_t atomisp_css2_hw_load_16(hrt_address addr)
113 spin_lock_irqsave(&mmio_lock, flags);
114 ret = _hrt_master_port_load_16(addr);
115 spin_unlock_irqrestore(&mmio_lock, flags);
119 static uint32_t atomisp_css2_hw_load_32(hrt_address addr)
124 spin_lock_irqsave(&mmio_lock, flags);
125 ret = _hrt_master_port_load_32(addr);
126 spin_unlock_irqrestore(&mmio_lock, flags);
130 static void atomisp_css2_hw_store(hrt_address addr,
131 const void *from, uint32_t n)
135 unsigned int _to = (unsigned int)addr;
136 const char *_from = (const char *)from;
138 spin_lock_irqsave(&mmio_lock, flags);
139 for (i = 0; i < n; i++, _to++, _from++)
140 _hrt_master_port_store_8(_to, *_from);
141 spin_unlock_irqrestore(&mmio_lock, flags);
144 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
148 char *_to = (char *)to;
149 unsigned int _from = (unsigned int)addr;
151 spin_lock_irqsave(&mmio_lock, flags);
152 for (i = 0; i < n; i++, _to++, _from++)
153 *_to = _hrt_master_port_load_8(_from);
154 spin_unlock_irqrestore(&mmio_lock, flags);
157 static int atomisp_css2_dbg_print(const char *fmt, va_list args)
163 static int atomisp_css2_dbg_ftrace_print(const char *fmt, va_list args)
165 ftrace_vprintk(fmt, args);
169 static int atomisp_css2_err_print(const char *fmt, va_list args)
175 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
177 *data = atomisp_css2_hw_load_32(addr);
180 static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr)
182 if (!sh_mmu_mrfld.get_pd_base) {
183 dev_err(atomisp_dev, "get mmu base address failed.\n");
187 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
188 bo_device.mmu.base_address);
192 static void __dump_pipe_config(struct atomisp_sub_device *asd,
193 struct atomisp_stream_env *stream_env,
194 unsigned int pipe_id)
196 struct atomisp_device *isp = asd->isp;
198 if (stream_env->pipes[pipe_id]) {
199 struct ia_css_pipe_config *p_config;
200 struct ia_css_pipe_extra_config *pe_config;
202 p_config = &stream_env->pipe_configs[pipe_id];
203 pe_config = &stream_env->pipe_extra_configs[pipe_id];
204 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
206 "pipe_config.pipe_mode:%d.\n", p_config->mode);
208 "pipe_config.output_info[0] w=%d, h=%d.\n",
209 p_config->output_info[0].res.width,
210 p_config->output_info[0].res.height);
212 "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
213 p_config->vf_pp_in_res.width,
214 p_config->vf_pp_in_res.height);
216 "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
217 p_config->capt_pp_in_res.width,
218 p_config->capt_pp_in_res.height);
220 "pipe_config.output.padded w=%d.\n",
221 p_config->output_info[0].padded_width);
223 "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
224 p_config->vf_output_info[0].res.width,
225 p_config->vf_output_info[0].res.height);
227 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
228 p_config->bayer_ds_out_res.width,
229 p_config->bayer_ds_out_res.height);
231 "pipe_config.envelope w=%d, h=%d.\n",
232 p_config->dvs_envelope.width,
233 p_config->dvs_envelope.height);
235 "pipe_config.dvs_frame_delay=%d.\n",
236 p_config->dvs_frame_delay);
238 "pipe_config.isp_pipe_version:%d.\n",
239 p_config->isp_pipe_version);
241 "pipe_config.acc_extension=%p.\n",
242 p_config->acc_extension);
244 "pipe_config.acc_stages=%p.\n",
245 p_config->acc_stages);
247 "pipe_config.num_acc_stages=%d.\n",
248 p_config->num_acc_stages);
250 "pipe_config.acc_num_execs=%d.\n",
251 p_config->acc_num_execs);
253 "pipe_config.default_capture_config.capture_mode=%d.\n",
254 p_config->default_capture_config.mode);
256 "pipe_config.enable_dz=%d.\n",
257 p_config->enable_dz);
259 "pipe_config.default_capture_config.enable_xnr=%d.\n",
260 p_config->default_capture_config.enable_xnr);
262 "dumping pipe[%d] extra config:\n", pipe_id);
264 "pipe_extra_config.enable_raw_binning:%d.\n",
265 pe_config->enable_raw_binning);
267 "pipe_extra_config.enable_yuv_ds:%d.\n",
268 pe_config->enable_yuv_ds);
270 "pipe_extra_config.enable_high_speed:%d.\n",
271 pe_config->enable_high_speed);
273 "pipe_extra_config.enable_dvs_6axis:%d.\n",
274 pe_config->enable_dvs_6axis);
276 "pipe_extra_config.enable_reduced_pipe:%d.\n",
277 pe_config->enable_reduced_pipe);
279 "pipe_(extra_)config.enable_dz:%d.\n",
280 p_config->enable_dz);
282 "pipe_extra_config.disable_vf_pp:%d.\n",
283 pe_config->disable_vf_pp);
287 static void __dump_stream_config(struct atomisp_sub_device *asd,
288 struct atomisp_stream_env *stream_env)
290 struct atomisp_device *isp = asd->isp;
291 struct ia_css_stream_config *s_config;
293 bool valid_stream = false;
295 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
296 if (stream_env->pipes[j]) {
297 __dump_pipe_config(asd, stream_env, j);
303 s_config = &stream_env->stream_config;
304 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
306 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
307 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
308 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
309 s_config->source.port.port);
310 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
311 s_config->source.port.num_lanes);
312 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
313 s_config->source.port.timeout);
314 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
315 s_config->source.port.rxcount);
316 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
317 s_config->source.port.compression.type);
319 "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
320 s_config->source.port.compression.
321 compressed_bits_per_pixel);
323 "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
324 s_config->source.port.compression.
325 uncompressed_bits_per_pixel);
326 } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
327 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
328 s_config->source.tpg.id);
329 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
330 s_config->source.tpg.mode);
331 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
332 s_config->source.tpg.x_mask);
333 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
334 s_config->source.tpg.x_delta);
335 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
336 s_config->source.tpg.y_mask);
337 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
338 s_config->source.tpg.y_delta);
339 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
340 s_config->source.tpg.xy_mask);
341 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
342 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
343 s_config->source.prbs.id);
344 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
345 s_config->source.prbs.h_blank);
346 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
347 s_config->source.prbs.v_blank);
348 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
349 s_config->source.prbs.seed);
350 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
351 s_config->source.prbs.seed1);
354 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
355 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
357 s_config->isys_config[j].input_res.width,
358 s_config->isys_config[j].input_res.height);
360 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
362 s_config->isys_config[j].linked_isys_stream_id);
364 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
366 s_config->isys_config[j].format);
368 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
370 s_config->isys_config[j].valid);
373 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
374 s_config->input_config.input_res.width,
375 s_config->input_config.input_res.height);
377 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
378 s_config->input_config.effective_res.width,
379 s_config->input_config.effective_res.height);
381 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
382 s_config->input_config.format);
384 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
385 s_config->input_config.bayer_order);
387 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
388 s_config->pixels_per_clock);
389 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
390 dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
391 s_config->continuous);
392 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
393 s_config->disable_cont_viewfinder);
394 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
395 s_config->channel_id);
396 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
397 s_config->init_num_cont_raw_buf);
398 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
399 s_config->target_num_cont_raw_buf);
400 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
401 s_config->left_padding);
402 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
403 s_config->sensor_binning_factor);
404 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
405 s_config->pixels_per_clock);
406 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
407 s_config->pack_raw_pixels);
408 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
409 s_config->flash_gpio_pin);
410 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
411 s_config->mipi_buffer_config.size_mem_words);
412 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
413 s_config->mipi_buffer_config.contiguous);
414 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
415 s_config->metadata_config.data_type);
416 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
417 s_config->metadata_config.resolution.width,
418 s_config->metadata_config.resolution.height);
421 static int __destroy_stream(struct atomisp_sub_device *asd,
422 struct atomisp_stream_env *stream_env, bool force)
424 struct atomisp_device *isp = asd->isp;
426 unsigned long timeout;
428 if (!stream_env->stream)
432 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
433 if (stream_env->update_pipe[i])
436 if (i == IA_CSS_PIPE_ID_NUM)
440 if (stream_env->stream_state == CSS_STREAM_STARTED
441 && ia_css_stream_stop(stream_env->stream) != 0) {
442 dev_err(isp->dev, "stop stream failed.\n");
446 if (stream_env->stream_state == CSS_STREAM_STARTED) {
447 timeout = jiffies + msecs_to_jiffies(40);
449 if (ia_css_stream_has_stopped(stream_env->stream))
452 if (time_after(jiffies, timeout)) {
453 dev_warn(isp->dev, "stop stream timeout.\n");
457 usleep_range(100, 200);
461 stream_env->stream_state = CSS_STREAM_STOPPED;
463 if (ia_css_stream_destroy(stream_env->stream)) {
464 dev_err(isp->dev, "destroy stream failed.\n");
467 stream_env->stream_state = CSS_STREAM_UNINIT;
468 stream_env->stream = NULL;
473 static int __destroy_streams(struct atomisp_sub_device *asd, bool force)
477 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
478 ret = __destroy_stream(asd, &asd->stream_env[i], force);
482 asd->stream_prepared = false;
486 static int __create_stream(struct atomisp_sub_device *asd,
487 struct atomisp_stream_env *stream_env)
489 int pipe_index = 0, i;
490 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
492 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
493 if (stream_env->pipes[i])
494 multi_pipes[pipe_index++] = stream_env->pipes[i];
499 stream_env->stream_config.target_num_cont_raw_buf =
500 asd->continuous_raw_buffer_size->val;
501 stream_env->stream_config.channel_id = stream_env->ch_id;
502 stream_env->stream_config.ia_css_enable_raw_buffer_locking =
503 asd->enable_raw_buffer_lock->val;
505 __dump_stream_config(asd, stream_env);
506 if (ia_css_stream_create(&stream_env->stream_config,
507 pipe_index, multi_pipes, &stream_env->stream) != 0)
509 if (ia_css_stream_get_info(stream_env->stream,
510 &stream_env->stream_info) != 0) {
511 ia_css_stream_destroy(stream_env->stream);
512 stream_env->stream = NULL;
516 stream_env->stream_state = CSS_STREAM_CREATED;
520 static int __create_streams(struct atomisp_sub_device *asd)
524 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
525 ret = __create_stream(asd, &asd->stream_env[i]);
529 asd->stream_prepared = true;
532 for (i--; i >= 0; i--)
533 __destroy_stream(asd, &asd->stream_env[i], true);
537 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
538 struct atomisp_stream_env *stream_env,
541 struct atomisp_device *isp = asd->isp;
545 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
546 if (!stream_env->pipes[i] ||
547 !(force || stream_env->update_pipe[i]))
549 if (ia_css_pipe_destroy(stream_env->pipes[i])
552 "destroy pipe[%d]failed.cannot recover.\n", i);
555 stream_env->pipes[i] = NULL;
556 stream_env->update_pipe[i] = false;
561 static int __destroy_pipes(struct atomisp_sub_device *asd, bool force)
563 struct atomisp_device *isp = asd->isp;
567 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
568 if (asd->stream_env[i].stream) {
570 "cannot destroy css pipes for stream[%d].\n",
575 ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force);
583 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
585 __destroy_streams(asd, true);
586 __destroy_pipes(asd, true);
589 static void __apply_additional_pipe_config(
590 struct atomisp_sub_device *asd,
591 struct atomisp_stream_env *stream_env,
592 enum ia_css_pipe_id pipe_id)
594 struct atomisp_device *isp = asd->isp;
596 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
598 "wrong pipe_id for additional pipe config.\n");
602 /* apply default pipe config */
603 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
604 stream_env->pipe_configs[pipe_id].enable_dz =
605 asd->disable_dz->val ? false : true;
606 /* apply isp 2.2 specific config for baytrail*/
608 case IA_CSS_PIPE_ID_CAPTURE:
609 /* enable capture pp/dz manually or digital zoom would
611 if (stream_env->pipe_configs[pipe_id].
612 default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW)
613 stream_env->pipe_configs[pipe_id].enable_dz = false;
616 /* the isp default to use ISP2.2 and the camera hal will
617 * control whether use isp2.7 */
618 if (asd->select_isp_version->val == ATOMISP_CSS_ISP_PIPE_VERSION_2_7)
619 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_7;
621 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_2;
624 case IA_CSS_PIPE_ID_VIDEO:
625 /* enable reduced pipe to have binary
626 * video_dz_2_min selected*/
627 stream_env->pipe_extra_configs[pipe_id]
628 .enable_reduced_pipe = true;
629 stream_env->pipe_configs[pipe_id]
631 if (ATOMISP_SOC_CAMERA(asd))
632 stream_env->pipe_configs[pipe_id].enable_dz = true;
634 if (asd->params.video_dis_en) {
635 stream_env->pipe_extra_configs[pipe_id]
636 .enable_dvs_6axis = true;
637 stream_env->pipe_configs[pipe_id]
639 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
642 case IA_CSS_PIPE_ID_PREVIEW:
644 case IA_CSS_PIPE_ID_YUVPP:
645 case IA_CSS_PIPE_ID_COPY:
646 if (ATOMISP_SOC_CAMERA(asd))
647 stream_env->pipe_configs[pipe_id].enable_dz = true;
649 stream_env->pipe_configs[pipe_id].enable_dz = false;
651 case IA_CSS_PIPE_ID_ACC:
652 stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC;
653 stream_env->pipe_configs[pipe_id].enable_dz = false;
660 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
661 enum ia_css_pipe_id pipe_id)
666 if (pipe_id == IA_CSS_PIPE_ID_ACC || pipe_id == IA_CSS_PIPE_ID_YUVPP)
670 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
671 if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
675 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
676 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
686 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
689 switch (asd->run_mode->val) {
690 case ATOMISP_RUN_MODE_STILL_CAPTURE:
691 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
695 case ATOMISP_RUN_MODE_PREVIEW:
696 if (!asd->continuous_mode->val) {
697 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
703 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
704 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
705 pipe_id == IA_CSS_PIPE_ID_PREVIEW)
710 case ATOMISP_RUN_MODE_VIDEO:
711 if (!asd->continuous_mode->val) {
712 if (pipe_id == IA_CSS_PIPE_ID_VIDEO ||
713 pipe_id == IA_CSS_PIPE_ID_YUVPP)
719 case ATOMISP_RUN_MODE_SDV:
720 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
721 pipe_id == IA_CSS_PIPE_ID_VIDEO)
730 static int __create_pipe(struct atomisp_sub_device *asd,
731 struct atomisp_stream_env *stream_env,
732 enum ia_css_pipe_id pipe_id)
734 struct atomisp_device *isp = asd->isp;
735 struct ia_css_pipe_extra_config extra_config;
738 if (pipe_id >= IA_CSS_PIPE_ID_NUM)
741 if (pipe_id != IA_CSS_PIPE_ID_ACC &&
742 !stream_env->pipe_configs[pipe_id].output_info[0].res.width)
745 if (pipe_id == IA_CSS_PIPE_ID_ACC &&
746 !stream_env->pipe_configs[pipe_id].acc_extension)
749 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
752 ia_css_pipe_extra_config_defaults(&extra_config);
754 __apply_additional_pipe_config(asd, stream_env, pipe_id);
755 if (!memcmp(&extra_config,
756 &stream_env->pipe_extra_configs[pipe_id],
757 sizeof(extra_config)))
758 ret = ia_css_pipe_create(
759 &stream_env->pipe_configs[pipe_id],
760 &stream_env->pipes[pipe_id]);
762 ret = ia_css_pipe_create_extra(
763 &stream_env->pipe_configs[pipe_id],
764 &stream_env->pipe_extra_configs[pipe_id],
765 &stream_env->pipes[pipe_id]);
767 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
771 static int __create_pipes(struct atomisp_sub_device *asd)
776 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
777 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
778 ret = __create_pipe(asd, &asd->stream_env[i], j);
782 if (j < IA_CSS_PIPE_ID_NUM)
787 for (; i >= 0; i--) {
788 for (j--; j >= 0; j--) {
789 if (asd->stream_env[i].pipes[j]) {
790 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
791 asd->stream_env[i].pipes[j] = NULL;
794 j = IA_CSS_PIPE_ID_NUM;
799 void atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
802 __create_streams(asd);
805 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
808 struct atomisp_device *isp = asd->isp;
810 if (__destroy_streams(asd, true))
811 dev_warn(isp->dev, "destroy stream failed.\n");
813 if (__destroy_pipes(asd, true))
814 dev_warn(isp->dev, "destroy pipe failed.\n");
816 ret = __create_pipes(asd);
818 dev_err(isp->dev, "create pipe failed %d.\n", ret);
822 ret = __create_streams(asd);
824 dev_warn(isp->dev, "create stream failed %d.\n", ret);
825 __destroy_pipes(asd, true);
832 int atomisp_css_init(struct atomisp_device *isp)
834 unsigned int mmu_base_addr;
838 ret = hmm_get_mmu_base_addr(&mmu_base_addr);
843 err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
844 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
846 dev_err(isp->dev, "css init failed --- bad firmware?\n");
849 ia_css_enable_isys_event_queue(true);
851 isp->css_initialized = true;
852 dev_dbg(isp->dev, "sh_css_init success\n");
857 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
862 isp->css_env.isp_css_env.print_env.debug_print = NULL;
864 isp->css_env.isp_css_env.print_env.debug_print =
865 atomisp_css2_dbg_ftrace_print;
867 isp->css_env.isp_css_env.print_env.debug_print =
868 atomisp_css2_dbg_print;
875 int atomisp_css_load_firmware(struct atomisp_device *isp)
880 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
881 isp->css_env.isp_css_fw.bytes = isp->firmware->size;
883 isp->css_env.isp_css_env.hw_access_env.store_8 =
884 atomisp_css2_hw_store_8;
885 isp->css_env.isp_css_env.hw_access_env.store_16 =
886 atomisp_css2_hw_store_16;
887 isp->css_env.isp_css_env.hw_access_env.store_32 =
888 atomisp_css2_hw_store_32;
890 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
891 isp->css_env.isp_css_env.hw_access_env.load_16 =
892 atomisp_css2_hw_load_16;
893 isp->css_env.isp_css_env.hw_access_env.load_32 =
894 atomisp_css2_hw_load_32;
896 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
897 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
899 __set_css_print_env(isp, dbg_func);
901 isp->css_env.isp_css_env.print_env.error_print = atomisp_css2_err_print;
903 /* load isp fw into ISP memory */
904 err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env,
905 &isp->css_env.isp_css_fw);
907 dev_err(isp->dev, "css load fw failed.\n");
914 void atomisp_css_uninit(struct atomisp_device *isp)
916 struct atomisp_sub_device *asd;
919 for (i = 0; i < isp->num_of_streams; i++) {
921 memset(&asd->params.config, 0, sizeof(asd->params.config));
922 asd->params.css_update_params_needed = false;
925 isp->css_initialized = false;
929 void atomisp_css_suspend(struct atomisp_device *isp)
931 isp->css_initialized = false;
935 int atomisp_css_resume(struct atomisp_device *isp)
937 unsigned int mmu_base_addr;
940 ret = hmm_get_mmu_base_addr(&mmu_base_addr);
942 dev_err(isp->dev, "get base address error.\n");
946 ret = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
947 mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
949 dev_err(isp->dev, "re-init css failed.\n");
952 ia_css_enable_isys_event_queue(true);
954 isp->css_initialized = true;
958 int atomisp_css_irq_translate(struct atomisp_device *isp,
963 err = ia_css_irq_translate(infos);
966 "%s:failed to translate irq (err = %d,infos = %d)\n",
967 __func__, err, *infos);
974 void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
977 #ifndef ISP2401_NEW_INPUT_SYSTEM
978 ia_css_isys_rx_get_irq_info(port, infos);
984 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
987 #ifndef ISP2401_NEW_INPUT_SYSTEM
988 ia_css_isys_rx_clear_irq_info(port, infos);
992 int atomisp_css_irq_enable(struct atomisp_device *isp,
993 enum ia_css_irq_info info, bool enable)
995 dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s.\n",
997 enable ? "enable" : "disable");
998 if (ia_css_irq_enable(info, enable)) {
999 dev_warn(isp->dev, "%s:Invalid irq info: 0x%08x when %s.\n",
1001 enable ? "enabling" : "disabling");
1008 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
1012 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1013 asd->stream_env[i].stream = NULL;
1014 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
1015 asd->stream_env[i].pipes[j] = NULL;
1016 asd->stream_env[i].update_pipe[j] = false;
1017 ia_css_pipe_config_defaults(
1018 &asd->stream_env[i].pipe_configs[j]);
1019 ia_css_pipe_extra_config_defaults(
1020 &asd->stream_env[i].pipe_extra_configs[j]);
1022 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
1026 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
1027 struct videobuf_vmalloc_memory *vm_mem,
1028 enum atomisp_input_stream_id stream_id,
1029 enum ia_css_buffer_type css_buf_type,
1030 enum ia_css_pipe_id css_pipe_id)
1032 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1033 struct ia_css_buffer css_buf = {0};
1036 css_buf.type = css_buf_type;
1037 css_buf.data.frame = vm_mem->vaddr;
1039 err = ia_css_pipe_enqueue_buffer(
1040 stream_env->pipes[css_pipe_id], &css_buf);
1047 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
1048 struct atomisp_metadata_buf *metadata_buf,
1049 enum atomisp_input_stream_id stream_id,
1050 enum ia_css_pipe_id css_pipe_id)
1052 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1053 struct ia_css_buffer buffer = {0};
1054 struct atomisp_device *isp = asd->isp;
1056 buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
1057 buffer.data.metadata = metadata_buf->metadata;
1058 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
1060 dev_err(isp->dev, "failed to q meta data buffer\n");
1067 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
1068 struct atomisp_s3a_buf *s3a_buf,
1069 enum atomisp_input_stream_id stream_id,
1070 enum ia_css_pipe_id css_pipe_id)
1072 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1073 struct ia_css_buffer buffer = {0};
1074 struct atomisp_device *isp = asd->isp;
1076 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
1077 buffer.data.stats_3a = s3a_buf->s3a_data;
1078 if (ia_css_pipe_enqueue_buffer(
1079 stream_env->pipes[css_pipe_id],
1081 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
1088 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
1089 struct atomisp_dis_buf *dis_buf,
1090 enum atomisp_input_stream_id stream_id,
1091 enum ia_css_pipe_id css_pipe_id)
1093 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1094 struct ia_css_buffer buffer = {0};
1095 struct atomisp_device *isp = asd->isp;
1097 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
1098 buffer.data.stats_dvs = dis_buf->dis_data;
1099 if (ia_css_pipe_enqueue_buffer(
1100 stream_env->pipes[css_pipe_id],
1102 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
1109 int atomisp_css_start(struct atomisp_sub_device *asd,
1110 enum ia_css_pipe_id pipe_id, bool in_reset)
1112 struct atomisp_device *isp = asd->isp;
1113 bool sp_is_started = false;
1117 if (__destroy_streams(asd, true))
1118 dev_warn(isp->dev, "destroy stream failed.\n");
1120 if (__destroy_pipes(asd, true))
1121 dev_warn(isp->dev, "destroy pipe failed.\n");
1123 if (__create_pipes(asd)) {
1124 dev_err(isp->dev, "create pipe error.\n");
1127 if (__create_streams(asd)) {
1128 dev_err(isp->dev, "create stream error.\n");
1132 /* in_reset == true, extension firmwares are reloaded after the recovery */
1133 atomisp_acc_load_extensions(asd);
1137 * For dual steam case, it is possible that:
1138 * 1: for this stream, it is at the stage that:
1139 * - after set_fmt is called
1140 * - before stream on is called
1141 * 2: for the other stream, the stream off is called which css reset
1144 * Thus the stream created in set_fmt get destroyed and need to be
1145 * recreated in the next stream on.
1147 if (asd->stream_prepared == false) {
1148 if (__create_pipes(asd)) {
1149 dev_err(isp->dev, "create pipe error.\n");
1152 if (__create_streams(asd)) {
1153 dev_err(isp->dev, "create stream error.\n");
1159 * SP can only be started one time
1160 * if atomisp_subdev_streaming_count() tell there already has some
1161 * subdev at streamming, then SP should already be started previously,
1162 * so need to skip start sp procedure
1164 if (atomisp_streaming_count(isp)) {
1165 dev_dbg(isp->dev, "skip start sp\n");
1167 if (!sh_css_hrt_system_is_idle())
1168 dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1169 if (ia_css_start_sp()) {
1170 dev_err(isp->dev, "start sp error.\n");
1174 sp_is_started = true;
1178 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1179 if (asd->stream_env[i].stream) {
1180 if (ia_css_stream_start(asd->stream_env[i]
1182 dev_err(isp->dev, "stream[%d] start error.\n", i);
1186 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1187 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1195 __destroy_streams(asd, true);
1197 __destroy_pipes(asd, true);
1199 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1203 * SP can not be stop if other streams are in use
1205 if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1211 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1215 * for ISP2401 new input system, this api is under development.
1216 * Calling it would cause kernel panic.
1220 * Check if it is Cherry Trail and also new input system
1222 if (asd->copy_mode) {
1223 dev_warn(asd->isp->dev,
1224 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1229 ia_css_stream_set_isp_config(
1230 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1231 &asd->params.config);
1232 memset(&asd->params.config, 0, sizeof(asd->params.config));
1235 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1236 struct ia_css_pipe *pipe)
1241 atomisp_css_update_isp_params(asd);
1245 dev_dbg(asd->isp->dev,
1246 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1247 __func__, asd->params.config.output_frame,
1248 asd->params.config.isp_config_id, pipe);
1250 ret = ia_css_stream_set_isp_config_on_pipe(
1251 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1252 &asd->params.config, pipe);
1254 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1256 memset(&asd->params.config, 0, sizeof(asd->params.config));
1259 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1260 enum atomisp_input_stream_id stream_id,
1261 enum ia_css_pipe_id pipe_id,
1262 enum ia_css_buffer_type buf_type,
1263 struct atomisp_css_buffer *isp_css_buffer)
1265 if (ia_css_pipe_enqueue_buffer(
1266 asd->stream_env[stream_id].pipes[pipe_id],
1267 &isp_css_buffer->css_buffer)
1274 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1275 enum atomisp_input_stream_id stream_id,
1276 enum ia_css_pipe_id pipe_id,
1277 enum ia_css_buffer_type buf_type,
1278 struct atomisp_css_buffer *isp_css_buffer)
1280 struct atomisp_device *isp = asd->isp;
1283 err = ia_css_pipe_dequeue_buffer(
1284 asd->stream_env[stream_id].pipes[pipe_id],
1285 &isp_css_buffer->css_buffer);
1288 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1295 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd,
1297 struct atomisp_s3a_buf *s3a_buf,
1298 struct atomisp_dis_buf *dis_buf,
1299 struct atomisp_metadata_buf *md_buf)
1301 struct atomisp_device *isp = asd->isp;
1302 struct ia_css_dvs_grid_info *dvs_grid_info =
1303 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1305 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1308 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1309 &asd->params.curr_grid_info.s3a_grid);
1310 if (!s3a_buf->s3a_data) {
1311 dev_err(isp->dev, "3a buf allocation failed.\n");
1315 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1316 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1317 s3a_buf->s3a_data, s3a_ptr);
1320 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1323 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1325 if (!dis_buf->dis_data) {
1326 dev_err(isp->dev, "dvs buf allocation failed.\n");
1328 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1332 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1333 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1334 dis_buf->dis_data, dvs_ptr);
1337 if (asd->stream_env[stream_id].stream_info.
1338 metadata_info.size && md_buf) {
1339 md_buf->metadata = ia_css_metadata_allocate(
1340 &asd->stream_env[stream_id].stream_info.metadata_info);
1341 if (!md_buf->metadata) {
1343 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1345 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1346 dev_err(isp->dev, "metadata buf allocation failed.\n");
1349 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1355 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1357 if (s3a_buf->s3a_data)
1358 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1360 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1361 s3a_buf->s3a_map = NULL;
1362 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1365 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1367 if (dis_buf->dis_data)
1368 hmm_vunmap(dis_buf->dis_data->data_ptr);
1370 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1371 dis_buf->dvs_map = NULL;
1372 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1375 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1377 if (metadata_buf->md_vptr) {
1378 hmm_vunmap(metadata_buf->metadata->address);
1379 metadata_buf->md_vptr = NULL;
1381 ia_css_metadata_free(metadata_buf->metadata);
1384 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1386 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1387 struct atomisp_dis_buf *dis_buf, *_dis_buf;
1388 struct atomisp_metadata_buf *md_buf, *_md_buf;
1389 struct ia_css_dvs_grid_info *dvs_grid_info =
1390 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1393 /* 3A statistics use vmalloc, DIS use kmalloc */
1394 if (dvs_grid_info && dvs_grid_info->enable) {
1395 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1396 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1397 asd->params.css_param.dvs2_coeff = NULL;
1398 asd->params.dvs_stat = NULL;
1399 asd->params.dvs_hor_proj_bytes = 0;
1400 asd->params.dvs_ver_proj_bytes = 0;
1401 asd->params.dvs_hor_coef_bytes = 0;
1402 asd->params.dvs_ver_coef_bytes = 0;
1403 asd->params.dis_proj_data_valid = false;
1404 list_for_each_entry_safe(dis_buf, _dis_buf,
1405 &asd->dis_stats, list) {
1406 atomisp_css_free_dis_buffer(dis_buf);
1407 list_del(&dis_buf->list);
1410 list_for_each_entry_safe(dis_buf, _dis_buf,
1411 &asd->dis_stats_in_css, list) {
1412 atomisp_css_free_dis_buffer(dis_buf);
1413 list_del(&dis_buf->list);
1417 if (asd->params.curr_grid_info.s3a_grid.enable) {
1418 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1419 asd->params.s3a_user_stat = NULL;
1420 asd->params.s3a_output_bytes = 0;
1421 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1422 &asd->s3a_stats, list) {
1423 atomisp_css_free_3a_buffer(s3a_buf);
1424 list_del(&s3a_buf->list);
1427 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1428 &asd->s3a_stats_in_css, list) {
1429 atomisp_css_free_3a_buffer(s3a_buf);
1430 list_del(&s3a_buf->list);
1433 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1434 &asd->s3a_stats_ready, list) {
1435 atomisp_css_free_3a_buffer(s3a_buf);
1436 list_del(&s3a_buf->list);
1441 if (asd->params.css_param.dvs_6axis) {
1442 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1443 asd->params.css_param.dvs_6axis = NULL;
1446 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1447 list_for_each_entry_safe(md_buf, _md_buf,
1448 &asd->metadata[i], list) {
1449 atomisp_css_free_metadata_buffer(md_buf);
1450 list_del(&md_buf->list);
1453 list_for_each_entry_safe(md_buf, _md_buf,
1454 &asd->metadata_in_css[i], list) {
1455 atomisp_css_free_metadata_buffer(md_buf);
1456 list_del(&md_buf->list);
1459 list_for_each_entry_safe(md_buf, _md_buf,
1460 &asd->metadata_ready[i], list) {
1461 atomisp_css_free_metadata_buffer(md_buf);
1462 list_del(&md_buf->list);
1466 asd->params.metadata_width_size = 0;
1467 atomisp_free_metadata_output_buf(asd);
1470 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1471 enum ia_css_pipe_id pipe_id,
1474 struct ia_css_pipe_info p_info;
1475 struct ia_css_grid_info old_info;
1476 struct atomisp_device *isp = asd->isp;
1477 int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
1478 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1479 stream_config.metadata_config.resolution.width;
1481 memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1482 memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1484 if (ia_css_pipe_get_info(
1485 asd->stream_env[stream_index].pipes[pipe_id],
1487 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1491 memcpy(&old_info, &asd->params.curr_grid_info,
1492 sizeof(struct ia_css_grid_info));
1493 memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1494 sizeof(struct ia_css_grid_info));
1496 * Record which css pipe enables s3a_grid.
1497 * Currently would have one css pipe that need it
1499 if (asd->params.curr_grid_info.s3a_grid.enable) {
1500 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM)
1501 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1502 asd->params.s3a_enabled_pipe, pipe_id);
1503 asd->params.s3a_enabled_pipe = pipe_id;
1506 /* If the grid info has not changed and the buffers for 3A and
1507 * DIS statistics buffers are allocated or buffer size would be zero
1508 * then no need to do anything. */
1509 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1510 && asd->params.s3a_user_stat && asd->params.dvs_stat)
1511 || asd->params.curr_grid_info.s3a_grid.width == 0
1512 || asd->params.curr_grid_info.s3a_grid.height == 0)
1513 && asd->params.metadata_width_size == md_width) {
1515 "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1516 !memcmp(&old_info, &asd->params.curr_grid_info,
1518 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1519 asd->params.curr_grid_info.s3a_grid.width,
1520 asd->params.curr_grid_info.s3a_grid.height,
1521 asd->params.metadata_width_size);
1524 asd->params.metadata_width_size = md_width;
1529 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1531 if (!asd->params.curr_grid_info.s3a_grid.width ||
1532 !asd->params.curr_grid_info.s3a_grid.height)
1535 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1536 &asd->params.curr_grid_info.s3a_grid);
1537 if (!asd->params.s3a_user_stat)
1539 /* 3A statistics. These can be big, so we use vmalloc. */
1540 asd->params.s3a_output_bytes =
1541 asd->params.curr_grid_info.s3a_grid.width *
1542 asd->params.curr_grid_info.s3a_grid.height *
1543 sizeof(*asd->params.s3a_user_stat->data);
1548 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1550 struct ia_css_dvs_grid_info *dvs_grid =
1551 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1556 if (!dvs_grid->enable) {
1557 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1561 /* DIS coefficients. */
1562 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1564 if (!asd->params.css_param.dvs2_coeff)
1567 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1568 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1570 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1571 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1573 /* DIS projections. */
1574 asd->params.dis_proj_data_valid = false;
1575 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1576 if (!asd->params.dvs_stat)
1579 asd->params.dvs_hor_proj_bytes =
1580 dvs_grid->aligned_height * dvs_grid->aligned_width *
1581 sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1583 asd->params.dvs_ver_proj_bytes =
1584 dvs_grid->aligned_height * dvs_grid->aligned_width *
1585 sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1590 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1594 /* We allocate the cpu-side buffer used for communication with user
1596 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1597 asd->params.metadata_user[i] = kvmalloc(
1598 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1599 stream_info.metadata_info.size, GFP_KERNEL);
1600 if (!asd->params.metadata_user[i]) {
1602 kvfree(asd->params.metadata_user[i]);
1603 asd->params.metadata_user[i] = NULL;
1612 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1616 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1617 if (asd->params.metadata_user[i]) {
1618 kvfree(asd->params.metadata_user[i]);
1619 asd->params.metadata_user[i] = NULL;
1624 void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd,
1625 struct atomisp_css_buffer *isp_css_buffer,
1626 struct ia_css_isp_dvs_statistics_map *dvs_map)
1628 if (asd->params.dvs_stat) {
1630 ia_css_translate_dvs2_statistics(
1631 asd->params.dvs_stat, dvs_map);
1633 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
1634 isp_css_buffer->css_buffer.data.stats_dvs);
1638 int atomisp_css_dequeue_event(struct atomisp_css_event *current_event)
1640 if (ia_css_dequeue_event(¤t_event->event))
1646 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1647 struct atomisp_css_event *current_event)
1651 * Pipe ID reported in CSS event is not correct for new system's
1655 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1656 ¤t_event->pipe);
1657 if (asd && asd->copy_mode &&
1658 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1659 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1662 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1663 enum atomisp_input_stream_id stream_id,
1664 struct v4l2_mbus_framefmt *ffmt,
1667 struct ia_css_stream_config *s_config =
1668 &asd->stream_env[stream_id].stream_config;
1670 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1673 s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1674 s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1678 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1679 enum atomisp_input_stream_id stream_id,
1680 struct v4l2_mbus_framefmt *ffmt)
1682 struct ia_css_stream_config *s_config =
1683 &asd->stream_env[stream_id].stream_config;
1685 s_config->input_config.input_res.width = ffmt->width;
1686 s_config->input_config.input_res.height = ffmt->height;
1690 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1691 enum atomisp_input_stream_id stream_id,
1692 unsigned int bin_factor)
1694 asd->stream_env[stream_id]
1695 .stream_config.sensor_binning_factor = bin_factor;
1698 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1699 enum atomisp_input_stream_id stream_id,
1700 enum ia_css_bayer_order bayer_order)
1702 struct ia_css_stream_config *s_config =
1703 &asd->stream_env[stream_id].stream_config;
1704 s_config->input_config.bayer_order = bayer_order;
1707 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1708 enum atomisp_input_stream_id stream_id,
1712 struct ia_css_stream_config *s_config =
1713 &asd->stream_env[stream_id].stream_config;
1715 s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1718 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1719 enum atomisp_input_stream_id stream_id,
1723 struct ia_css_stream_config *s_config =
1724 &asd->stream_env[stream_id].stream_config;
1726 s_config->isys_config[isys_stream].valid = valid;
1729 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1730 enum atomisp_input_stream_id stream_id,
1731 enum atomisp_input_format format,
1734 struct ia_css_stream_config *s_config =
1735 &asd->stream_env[stream_id].stream_config;
1737 s_config->isys_config[isys_stream].format = format;
1740 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1741 enum atomisp_input_stream_id stream_id,
1742 enum atomisp_input_format format)
1744 struct ia_css_stream_config *s_config =
1745 &asd->stream_env[stream_id].stream_config;
1747 s_config->input_config.format = format;
1750 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1751 enum atomisp_input_stream_id stream_id,
1752 struct v4l2_mbus_framefmt *ffmt)
1755 struct ia_css_stream_config *s_config =
1756 &asd->stream_env[stream_id].stream_config;
1758 * Set all isys configs to not valid.
1759 * Currently we support only one stream per channel
1761 for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1762 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1763 s_config->isys_config[i].valid = false;
1765 atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1766 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1767 atomisp_css_isys_set_format(asd, stream_id,
1768 s_config->input_config.format,
1769 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1770 atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1771 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1772 atomisp_css_isys_set_valid(asd, stream_id, true,
1773 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1778 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1779 enum atomisp_input_stream_id stream_id,
1780 enum atomisp_input_format input_format)
1782 struct ia_css_stream_config *s_config =
1783 &asd->stream_env[stream_id].stream_config;
1785 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1786 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1788 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1789 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1791 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1792 = IA_CSS_STREAM_ISYS_STREAM_0;
1793 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1794 ATOMISP_INPUT_FORMAT_USER_DEF1;
1795 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1796 ATOMISP_INPUT_FORMAT_USER_DEF2;
1797 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1801 void atomisp_css_isys_two_stream_cfg_update_stream1(
1802 struct atomisp_sub_device *asd,
1803 enum atomisp_input_stream_id stream_id,
1804 enum atomisp_input_format input_format,
1805 unsigned int width, unsigned int height)
1807 struct ia_css_stream_config *s_config =
1808 &asd->stream_env[stream_id].stream_config;
1810 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1812 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1814 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1816 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1819 void atomisp_css_isys_two_stream_cfg_update_stream2(
1820 struct atomisp_sub_device *asd,
1821 enum atomisp_input_stream_id stream_id,
1822 enum atomisp_input_format input_format,
1823 unsigned int width, unsigned int height)
1825 struct ia_css_stream_config *s_config =
1826 &asd->stream_env[stream_id].stream_config;
1828 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1830 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1832 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1833 = IA_CSS_STREAM_ISYS_STREAM_0;
1834 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1836 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1839 int atomisp_css_input_set_effective_resolution(
1840 struct atomisp_sub_device *asd,
1841 enum atomisp_input_stream_id stream_id,
1842 unsigned int width, unsigned int height)
1844 struct ia_css_stream_config *s_config =
1845 &asd->stream_env[stream_id].stream_config;
1846 s_config->input_config.effective_res.width = width;
1847 s_config->input_config.effective_res.height = height;
1851 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1852 unsigned int dvs_w, unsigned int dvs_h)
1854 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1855 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1856 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1857 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1860 void atomisp_css_input_set_two_pixels_per_clock(
1861 struct atomisp_sub_device *asd,
1866 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1867 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1870 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1871 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1872 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1873 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1874 .update_pipe[i] = true;
1877 void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
1880 struct atomisp_stream_env *stream_env =
1881 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1884 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
1885 pipe = IA_CSS_PIPE_ID_VIDEO;
1887 pipe = IA_CSS_PIPE_ID_PREVIEW;
1889 stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable;
1890 stream_env->update_pipe[pipe] = true;
1892 stream_env->pipe_configs[pipe].output_info[0].padded_width =
1893 stream_env->stream_config.input_config.effective_res.width;
1896 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1900 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1901 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1902 .pipe_configs[i].enable_dz = enable;
1905 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1906 enum ia_css_capture_mode mode)
1908 struct atomisp_stream_env *stream_env =
1909 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1911 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1912 .default_capture_config.mode == mode)
1915 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1916 default_capture_config.mode = mode;
1917 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1920 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
1921 enum ia_css_input_mode mode)
1924 struct atomisp_device *isp = asd->isp;
1925 unsigned int size_mem_words;
1927 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
1928 asd->stream_env[i].stream_config.mode = mode;
1930 if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
1931 struct ia_css_stream_config *s_config =
1932 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
1933 s_config->mode = IA_CSS_INPUT_MODE_TPG;
1934 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
1935 s_config->source.tpg.x_mask = (1 << 4) - 1;
1936 s_config->source.tpg.x_delta = -2;
1937 s_config->source.tpg.y_mask = (1 << 4) - 1;
1938 s_config->source.tpg.y_delta = 3;
1939 s_config->source.tpg.xy_mask = (1 << 8) - 1;
1943 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1946 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1948 * TODO: sensor needs to export the embedded_data_size_words
1949 * information to atomisp for each setting.
1950 * Here using a large safe value.
1952 struct ia_css_stream_config *s_config =
1953 &asd->stream_env[i].stream_config;
1955 if (s_config->input_config.input_res.width == 0)
1958 if (ia_css_mipi_frame_calculate_size(
1959 s_config->input_config.input_res.width,
1960 s_config->input_config.input_res.height,
1961 s_config->input_config.format,
1964 &size_mem_words) != 0) {
1965 if (intel_mid_identify_cpu() ==
1966 INTEL_MID_CPU_CHIP_TANGIER)
1967 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
1969 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
1970 dev_warn(asd->isp->dev,
1971 "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n",
1974 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
1975 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
1979 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
1980 unsigned short stream_index, bool enable)
1982 struct atomisp_stream_env *stream_env =
1983 &asd->stream_env[stream_index];
1985 if (stream_env->stream_config.online == !!enable)
1988 stream_env->stream_config.online = !!enable;
1989 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1992 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
1993 unsigned short stream_index, bool enable)
1995 struct atomisp_stream_env *stream_env =
1996 &asd->stream_env[stream_index];
1999 if (stream_env->stream_config.online != !!enable) {
2000 stream_env->stream_config.online = !!enable;
2001 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2002 stream_env->update_pipe[i] = true;
2006 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
2009 struct atomisp_stream_env *stream_env =
2010 &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
2013 if (stream_env->stream_config.online != enable) {
2014 stream_env->stream_config.online = enable;
2015 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2016 stream_env->update_pipe[i] = true;
2020 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
2023 struct atomisp_stream_env *stream_env =
2024 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2028 * To SOC camera, there is only one YUVPP pipe in any case
2029 * including ZSL/SDV/continuous viewfinder, so always set
2030 * stream_config.continuous to 0.
2032 if (ATOMISP_USE_YUVPP(asd)) {
2033 stream_env->stream_config.continuous = 0;
2034 stream_env->stream_config.online = 1;
2038 if (stream_env->stream_config.continuous != !!enable) {
2039 stream_env->stream_config.continuous = !!enable;
2040 stream_env->stream_config.pack_raw_pixels = true;
2041 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2042 stream_env->update_pipe[i] = true;
2046 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
2049 struct atomisp_stream_env *stream_env =
2050 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2053 if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
2054 stream_env->stream_config.disable_cont_viewfinder = !enable;
2055 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2056 stream_env->update_pipe[i] = true;
2060 int atomisp_css_input_configure_port(
2061 struct atomisp_sub_device *asd,
2062 enum mipi_port_id port,
2063 unsigned int num_lanes,
2064 unsigned int timeout,
2065 unsigned int mipi_freq,
2066 enum atomisp_input_format metadata_format,
2067 unsigned int metadata_width,
2068 unsigned int metadata_height)
2071 struct atomisp_stream_env *stream_env;
2073 * Calculate rx_count as follows:
2074 * Input: mipi_freq : CSI-2 bus frequency in Hz
2075 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus
2076 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds
2077 * max = 145e-9 + 10 * UI
2078 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
2079 * rxcount = rxcount0 - 2 : adjust for better results
2080 * The formula below is simplified version of the above with
2081 * 10-bit fixed points for improved accuracy.
2083 const unsigned int rxcount =
2084 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
2086 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2087 stream_env = &asd->stream_env[i];
2088 stream_env->stream_config.source.port.port = port;
2089 stream_env->stream_config.source.port.num_lanes = num_lanes;
2090 stream_env->stream_config.source.port.timeout = timeout;
2092 stream_env->stream_config.source.port.rxcount = rxcount;
2093 stream_env->stream_config.
2094 metadata_config.data_type = metadata_format;
2095 stream_env->stream_config.
2096 metadata_config.resolution.width = metadata_width;
2097 stream_env->stream_config.
2098 metadata_config.resolution.height = metadata_height;
2104 int atomisp_css_stop(struct atomisp_sub_device *asd,
2105 enum ia_css_pipe_id pipe_id, bool in_reset)
2107 struct atomisp_device *isp = asd->isp;
2108 struct atomisp_s3a_buf *s3a_buf;
2109 struct atomisp_dis_buf *dis_buf;
2110 struct atomisp_metadata_buf *md_buf;
2111 unsigned long irqflags;
2114 /* if is called in atomisp_reset(), force destroy stream */
2115 if (__destroy_streams(asd, true))
2116 dev_err(isp->dev, "destroy stream failed.\n");
2118 /* if is called in atomisp_reset(), force destroy all pipes */
2119 if (__destroy_pipes(asd, true))
2120 dev_err(isp->dev, "destroy pipes failed.\n");
2122 atomisp_init_raw_buffer_bitmap(asd);
2125 * SP can not be stop if other streams are in use
2127 if (atomisp_streaming_count(isp) == 0)
2131 struct atomisp_stream_env *stream_env;
2134 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2135 stream_env = &asd->stream_env[i];
2136 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
2137 ia_css_pipe_config_defaults(
2138 &stream_env->pipe_configs[j]);
2139 ia_css_pipe_extra_config_defaults(
2140 &stream_env->pipe_extra_configs[j]);
2142 ia_css_stream_config_defaults(
2143 &stream_env->stream_config);
2145 memset(&asd->params.config, 0, sizeof(asd->params.config));
2146 asd->params.css_update_params_needed = false;
2149 /* move stats buffers to free queue list */
2150 while (!list_empty(&asd->s3a_stats_in_css)) {
2151 s3a_buf = list_entry(asd->s3a_stats_in_css.next,
2152 struct atomisp_s3a_buf, list);
2153 list_del(&s3a_buf->list);
2154 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2156 while (!list_empty(&asd->s3a_stats_ready)) {
2157 s3a_buf = list_entry(asd->s3a_stats_ready.next,
2158 struct atomisp_s3a_buf, list);
2159 list_del(&s3a_buf->list);
2160 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2163 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
2164 while (!list_empty(&asd->dis_stats_in_css)) {
2165 dis_buf = list_entry(asd->dis_stats_in_css.next,
2166 struct atomisp_dis_buf, list);
2167 list_del(&dis_buf->list);
2168 list_add_tail(&dis_buf->list, &asd->dis_stats);
2170 asd->params.dis_proj_data_valid = false;
2171 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
2173 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
2174 while (!list_empty(&asd->metadata_in_css[i])) {
2175 md_buf = list_entry(asd->metadata_in_css[i].next,
2176 struct atomisp_metadata_buf, list);
2177 list_del(&md_buf->list);
2178 list_add_tail(&md_buf->list, &asd->metadata[i]);
2180 while (!list_empty(&asd->metadata_ready[i])) {
2181 md_buf = list_entry(asd->metadata_ready[i].next,
2182 struct atomisp_metadata_buf, list);
2183 list_del(&md_buf->list);
2184 list_add_tail(&md_buf->list, &asd->metadata[i]);
2188 atomisp_flush_params_queue(&asd->video_out_capture);
2189 atomisp_flush_params_queue(&asd->video_out_vf);
2190 atomisp_flush_params_queue(&asd->video_out_preview);
2191 atomisp_flush_params_queue(&asd->video_out_video_capture);
2192 atomisp_free_css_parameters(&asd->params.css_param);
2193 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
2197 int atomisp_css_continuous_set_num_raw_frames(
2198 struct atomisp_sub_device *asd,
2201 if (asd->enable_raw_buffer_lock->val) {
2202 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2203 .stream_config.init_num_cont_raw_buf =
2204 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
2205 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2206 asd->params.video_dis_en)
2207 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2208 .stream_config.init_num_cont_raw_buf +=
2209 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2211 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2212 .stream_config.init_num_cont_raw_buf =
2213 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
2216 if (asd->params.video_dis_en)
2217 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2218 .stream_config.init_num_cont_raw_buf +=
2219 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2221 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2222 .stream_config.target_num_cont_raw_buf = num_frames;
2226 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2227 struct atomisp_sub_device *asd,
2228 enum ia_css_pipe_id pipe_id)
2230 struct atomisp_device *isp = asd->isp;
2231 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2232 isp->inputs[asd->input_curr].camera);
2235 case IA_CSS_PIPE_ID_COPY:
2236 /* Currently only YUVPP mode supports YUV420_Legacy format.
2237 * Revert this when other pipe modes can support
2238 * YUV420_Legacy format.
2240 if (mipi_info && mipi_info->input_format ==
2241 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2242 return IA_CSS_PIPE_MODE_YUVPP;
2243 return IA_CSS_PIPE_MODE_COPY;
2244 case IA_CSS_PIPE_ID_PREVIEW:
2245 return IA_CSS_PIPE_MODE_PREVIEW;
2246 case IA_CSS_PIPE_ID_CAPTURE:
2247 return IA_CSS_PIPE_MODE_CAPTURE;
2248 case IA_CSS_PIPE_ID_VIDEO:
2249 return IA_CSS_PIPE_MODE_VIDEO;
2250 case IA_CSS_PIPE_ID_ACC:
2251 return IA_CSS_PIPE_MODE_ACC;
2252 case IA_CSS_PIPE_ID_YUVPP:
2253 return IA_CSS_PIPE_MODE_YUVPP;
2256 return IA_CSS_PIPE_MODE_PREVIEW;
2260 static void __configure_output(struct atomisp_sub_device *asd,
2261 unsigned int stream_index,
2262 unsigned int width, unsigned int height,
2263 unsigned int min_width,
2264 enum ia_css_frame_format format,
2265 enum ia_css_pipe_id pipe_id)
2267 struct atomisp_device *isp = asd->isp;
2268 struct atomisp_stream_env *stream_env =
2269 &asd->stream_env[stream_index];
2270 struct ia_css_stream_config *s_config = &stream_env->stream_config;
2272 stream_env->pipe_configs[pipe_id].mode =
2273 __pipe_id_to_pipe_mode(asd, pipe_id);
2274 stream_env->update_pipe[pipe_id] = true;
2276 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2277 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2278 stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2279 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2281 /* isp binary 2.2 specific setting*/
2282 if (width > s_config->input_config.effective_res.width ||
2283 height > s_config->input_config.effective_res.height) {
2284 s_config->input_config.effective_res.width = width;
2285 s_config->input_config.effective_res.height = height;
2288 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2289 pipe_id, width, height, format);
2292 static void __configure_video_preview_output(struct atomisp_sub_device *asd,
2293 unsigned int stream_index,
2294 unsigned int width, unsigned int height,
2295 unsigned int min_width,
2296 enum ia_css_frame_format format,
2297 enum ia_css_pipe_id pipe_id)
2299 struct atomisp_device *isp = asd->isp;
2300 struct atomisp_stream_env *stream_env =
2301 &asd->stream_env[stream_index];
2302 struct ia_css_frame_info *css_output_info;
2303 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2305 stream_env->pipe_configs[pipe_id].mode =
2306 __pipe_id_to_pipe_mode(asd, pipe_id);
2307 stream_env->update_pipe[pipe_id] = true;
2310 * second_output will be as video main output in SDV mode
2311 * with SOC camera. output will be as video main output in
2312 * normal video mode.
2314 if (asd->continuous_mode->val)
2315 css_output_info = &stream_env->pipe_configs[pipe_id].
2316 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2318 css_output_info = &stream_env->pipe_configs[pipe_id].
2319 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2321 css_output_info->res.width = width;
2322 css_output_info->res.height = height;
2323 css_output_info->format = format;
2324 css_output_info->padded_width = min_width;
2326 /* isp binary 2.2 specific setting*/
2327 if (width > stream_config->input_config.effective_res.width ||
2328 height > stream_config->input_config.effective_res.height) {
2329 stream_config->input_config.effective_res.width = width;
2330 stream_config->input_config.effective_res.height = height;
2333 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2334 pipe_id, width, height, format);
2338 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2339 * downscaling input resolution.
2341 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2342 unsigned int width, unsigned int height,
2343 enum ia_css_pipe_id pipe_id)
2345 struct atomisp_device *isp = asd->isp;
2346 struct atomisp_stream_env *stream_env =
2347 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2348 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2349 struct ia_css_pipe_config *pipe_configs =
2350 &stream_env->pipe_configs[pipe_id];
2351 struct ia_css_pipe_extra_config *pipe_extra_configs =
2352 &stream_env->pipe_extra_configs[pipe_id];
2353 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2355 if (width == 0 && height == 0)
2358 if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2359 height * 9 / 10 < pipe_configs->output_info[0].res.height)
2361 /* here just copy the calculation in css */
2362 hor_ds_factor = CEIL_DIV(width >> 1,
2363 pipe_configs->output_info[0].res.width);
2364 ver_ds_factor = CEIL_DIV(height >> 1,
2365 pipe_configs->output_info[0].res.height);
2367 if ((asd->isp->media_dev.hw_revision <
2368 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2369 IS_CHT) && hor_ds_factor != ver_ds_factor) {
2370 dev_warn(asd->isp->dev,
2371 "Cropping for capture due to FW limitation");
2375 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2376 stream_env->update_pipe[pipe_id] = true;
2378 pipe_extra_configs->enable_yuv_ds = true;
2380 pipe_configs->capt_pp_in_res.width =
2381 stream_config->input_config.effective_res.width;
2382 pipe_configs->capt_pp_in_res.height =
2383 stream_config->input_config.effective_res.height;
2385 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2386 pipe_id, width, height);
2390 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2391 * yuv downscaling, which needs addtional configurations.
2393 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2394 unsigned int width, unsigned int height,
2395 enum ia_css_pipe_id pipe_id)
2397 struct atomisp_device *isp = asd->isp;
2398 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2399 struct atomisp_stream_env *stream_env =
2400 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2401 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2402 struct ia_css_pipe_config *pipe_configs =
2403 &stream_env->pipe_configs[pipe_id];
2404 struct ia_css_pipe_extra_config *pipe_extra_configs =
2405 &stream_env->pipe_extra_configs[pipe_id];
2406 struct ia_css_resolution *bayer_ds_out_res =
2407 &pipe_configs->bayer_ds_out_res;
2408 struct ia_css_resolution *vf_pp_in_res =
2409 &pipe_configs->vf_pp_in_res;
2410 struct ia_css_resolution *effective_res =
2411 &stream_config->input_config.effective_res;
2413 const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2415 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2416 * columns to be shaded. Remove this factor to work around the CSS bug.
2417 * const unsigned int yuv_dec_fct[] = {4, 2};
2419 const unsigned int yuv_dec_fct[] = { 2 };
2422 if (width == 0 && height == 0)
2425 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2426 stream_env->update_pipe[pipe_id] = true;
2428 out_width = pipe_configs->output_info[0].res.width;
2429 out_height = pipe_configs->output_info[0].res.height;
2432 * The ISP could do bayer downscaling, yuv decimation and yuv
2434 * 1: Bayer Downscaling: between effective resolution and
2436 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2437 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2439 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2440 * Rule for YUV Decimation: support factor 2, 4
2441 * Rule for YUV Downscaling: arbitrary value below 2
2443 * General rule of factor distribution among these stages:
2444 * 1: try to do Bayer downscaling first if not in online mode.
2445 * 2: try to do maximum of 2 for YUV downscaling
2446 * 3: the remainling for YUV decimation
2449 * Do not configure bayer_ds_out_res if:
2450 * online == 1 or continuous == 0 or raw_binning = 0
2452 if (stream_config->online || !stream_config->continuous ||
2453 !pipe_extra_configs->enable_raw_binning) {
2454 bayer_ds_out_res->width = 0;
2455 bayer_ds_out_res->height = 0;
2457 bayer_ds_out_res->width = effective_res->width;
2458 bayer_ds_out_res->height = effective_res->height;
2460 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2461 if (effective_res->width >= out_width *
2462 bds_fct[i].numerator / bds_fct[i].denominator &&
2463 effective_res->height >= out_height *
2464 bds_fct[i].numerator / bds_fct[i].denominator) {
2465 bayer_ds_out_res->width =
2466 effective_res->width *
2467 bds_fct[i].denominator /
2468 bds_fct[i].numerator;
2469 bayer_ds_out_res->height =
2470 effective_res->height *
2471 bds_fct[i].denominator /
2472 bds_fct[i].numerator;
2478 * calculate YUV Decimation, YUV downscaling facor:
2479 * YUV Downscaling factor must not exceed 2.
2480 * YUV Decimation factor could be 2, 4.
2482 /* first decide the yuv_ds input resolution */
2483 if (bayer_ds_out_res->width == 0) {
2484 yuv_ds_in_width = effective_res->width;
2485 yuv_ds_in_height = effective_res->height;
2487 yuv_ds_in_width = bayer_ds_out_res->width;
2488 yuv_ds_in_height = bayer_ds_out_res->height;
2491 vf_pp_in_res->width = yuv_ds_in_width;
2492 vf_pp_in_res->height = yuv_ds_in_height;
2494 /* find out the yuv decimation factor */
2495 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2496 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2497 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2498 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2499 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2504 if (vf_pp_in_res->width == out_width &&
2505 vf_pp_in_res->height == out_height) {
2506 pipe_extra_configs->enable_yuv_ds = false;
2507 vf_pp_in_res->width = 0;
2508 vf_pp_in_res->height = 0;
2510 pipe_extra_configs->enable_yuv_ds = true;
2513 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2514 pipe_id, width, height);
2518 * For CSS2.1, offline video pipe could support bayer decimation, and
2519 * yuv downscaling, which needs addtional configurations.
2521 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2522 unsigned int width, unsigned int height,
2523 enum ia_css_pipe_id pipe_id)
2525 struct atomisp_device *isp = asd->isp;
2526 int out_width, out_height;
2527 struct atomisp_stream_env *stream_env =
2528 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2529 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2530 struct ia_css_pipe_config *pipe_configs =
2531 &stream_env->pipe_configs[pipe_id];
2532 struct ia_css_pipe_extra_config *pipe_extra_configs =
2533 &stream_env->pipe_extra_configs[pipe_id];
2534 struct ia_css_resolution *bayer_ds_out_res =
2535 &pipe_configs->bayer_ds_out_res;
2536 struct ia_css_resolution *effective_res =
2537 &stream_config->input_config.effective_res;
2539 const struct bayer_ds_factor bds_factors[] = {
2540 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
2544 if (width == 0 && height == 0)
2547 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2548 stream_env->update_pipe[pipe_id] = true;
2550 pipe_extra_configs->enable_yuv_ds = false;
2553 * If DVS is enabled, video binary will take care the dvs envelope
2554 * and usually the bayer_ds_out_res should be larger than 120% of
2555 * destination resolution, the extra 20% will be cropped as DVS
2556 * envelope. But, if the bayer_ds_out_res is less than 120% of the
2557 * destination. The ISP can still work, but DVS quality is not good.
2559 /* taking at least 10% as envelope */
2560 if (asd->params.video_dis_en) {
2561 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2562 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2564 out_width = pipe_configs->output_info[0].res.width;
2565 out_height = pipe_configs->output_info[0].res.height;
2569 * calculate bayer decimate factor:
2570 * 1: only 1.5, 2, 4 and 8 get supported
2571 * 2: Do not configure bayer_ds_out_res if:
2572 * online == 1 or continuous == 0 or raw_binning = 0
2574 if (stream_config->online || !stream_config->continuous) {
2575 bayer_ds_out_res->width = 0;
2576 bayer_ds_out_res->height = 0;
2580 pipe_extra_configs->enable_raw_binning = true;
2581 bayer_ds_out_res->width = effective_res->width;
2582 bayer_ds_out_res->height = effective_res->height;
2584 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2586 if (effective_res->width >= out_width *
2587 bds_factors[i].numerator / bds_factors[i].denominator &&
2588 effective_res->height >= out_height *
2589 bds_factors[i].numerator / bds_factors[i].denominator) {
2590 bayer_ds_out_res->width = effective_res->width *
2591 bds_factors[i].denominator /
2592 bds_factors[i].numerator;
2593 bayer_ds_out_res->height = effective_res->height *
2594 bds_factors[i].denominator /
2595 bds_factors[i].numerator;
2601 * DVS is cropped from BDS output, so we do not really need to set the
2602 * envelope to 20% of output resolution here. always set it to 12x12
2603 * per firmware requirement.
2605 pipe_configs->dvs_envelope.width = 12;
2606 pipe_configs->dvs_envelope.height = 12;
2609 if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2610 stream_config->left_padding = -1;
2612 stream_config->left_padding = 12;
2613 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2614 pipe_id, width, height);
2617 static void __configure_vf_output(struct atomisp_sub_device *asd,
2618 unsigned int width, unsigned int height,
2619 unsigned int min_width,
2620 enum ia_css_frame_format format,
2621 enum ia_css_pipe_id pipe_id)
2623 struct atomisp_device *isp = asd->isp;
2624 struct atomisp_stream_env *stream_env =
2625 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2626 stream_env->pipe_configs[pipe_id].mode =
2627 __pipe_id_to_pipe_mode(asd, pipe_id);
2628 stream_env->update_pipe[pipe_id] = true;
2630 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2631 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2632 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2633 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2636 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2637 pipe_id, width, height, format);
2640 static void __configure_video_vf_output(struct atomisp_sub_device *asd,
2641 unsigned int width, unsigned int height,
2642 unsigned int min_width,
2643 enum ia_css_frame_format format,
2644 enum ia_css_pipe_id pipe_id)
2646 struct atomisp_device *isp = asd->isp;
2647 struct atomisp_stream_env *stream_env =
2648 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2649 struct ia_css_frame_info *css_output_info;
2651 stream_env->pipe_configs[pipe_id].mode =
2652 __pipe_id_to_pipe_mode(asd, pipe_id);
2653 stream_env->update_pipe[pipe_id] = true;
2656 * second_vf_output will be as video viewfinder in SDV mode
2657 * with SOC camera. vf_output will be as video viewfinder in
2658 * normal video mode.
2660 if (asd->continuous_mode->val)
2661 css_output_info = &stream_env->pipe_configs[pipe_id].
2662 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2664 css_output_info = &stream_env->pipe_configs[pipe_id].
2665 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2667 css_output_info->res.width = width;
2668 css_output_info->res.height = height;
2669 css_output_info->format = format;
2670 css_output_info->padded_width = min_width;
2672 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2673 pipe_id, width, height, format);
2676 static int __get_frame_info(struct atomisp_sub_device *asd,
2677 unsigned int stream_index,
2678 struct ia_css_frame_info *info,
2679 enum frame_info_type type,
2680 enum ia_css_pipe_id pipe_id)
2682 struct atomisp_device *isp = asd->isp;
2684 struct ia_css_pipe_info p_info;
2686 /* FIXME! No need to destroy/recreate all streams */
2687 if (__destroy_streams(asd, true))
2688 dev_warn(isp->dev, "destroy stream failed.\n");
2690 if (__destroy_pipes(asd, true))
2691 dev_warn(isp->dev, "destroy pipe failed.\n");
2693 if (__create_pipes(asd))
2696 if (__create_streams(asd))
2699 ret = ia_css_pipe_get_info(
2700 asd->stream_env[stream_index]
2701 .pipes[pipe_id], &p_info);
2704 case ATOMISP_CSS_VF_FRAME:
2705 *info = p_info.vf_output_info[0];
2706 dev_dbg(isp->dev, "getting vf frame info.\n");
2708 case ATOMISP_CSS_SECOND_VF_FRAME:
2709 *info = p_info.vf_output_info[1];
2710 dev_dbg(isp->dev, "getting second vf frame info.\n");
2712 case ATOMISP_CSS_OUTPUT_FRAME:
2713 *info = p_info.output_info[0];
2714 dev_dbg(isp->dev, "getting main frame info.\n");
2716 case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2717 *info = p_info.output_info[1];
2718 dev_dbg(isp->dev, "getting second main frame info.\n");
2720 case ATOMISP_CSS_RAW_FRAME:
2721 *info = p_info.raw_output_info;
2722 dev_dbg(isp->dev, "getting raw frame info.\n");
2724 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2725 info->res.width, info->res.height, p_info.num_invalid_frames);
2730 __destroy_pipes(asd, true);
2734 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2735 uint16_t source_pad)
2737 struct atomisp_device *isp = asd->isp;
2739 * to SOC camera, use yuvpp pipe.
2741 if (ATOMISP_USE_YUVPP(asd))
2742 return IA_CSS_PIPE_ID_YUVPP;
2744 switch (source_pad) {
2745 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2746 if (asd->yuvpp_mode)
2747 return IA_CSS_PIPE_ID_YUVPP;
2749 return IA_CSS_PIPE_ID_COPY;
2750 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2751 || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2752 return IA_CSS_PIPE_ID_VIDEO;
2754 return IA_CSS_PIPE_ID_CAPTURE;
2755 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2757 return IA_CSS_PIPE_ID_COPY;
2759 return IA_CSS_PIPE_ID_CAPTURE;
2760 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2761 if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) {
2762 return IA_CSS_PIPE_ID_CAPTURE;
2765 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2766 if (asd->yuvpp_mode)
2767 return IA_CSS_PIPE_ID_YUVPP;
2769 return IA_CSS_PIPE_ID_COPY;
2770 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2771 return IA_CSS_PIPE_ID_VIDEO;
2773 return IA_CSS_PIPE_ID_PREVIEW;
2776 "invalid source pad:%d, return default preview pipe index.\n",
2778 return IA_CSS_PIPE_ID_PREVIEW;
2781 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2783 struct ia_css_frame_info *frame_info)
2785 struct ia_css_pipe_info info;
2786 int pipe_index = atomisp_get_pipe_index(asd, source_pad);
2788 struct atomisp_device *isp = asd->isp;
2790 if (ATOMISP_SOC_CAMERA(asd))
2791 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
2793 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2794 ATOMISP_INPUT_STREAM_VIDEO :
2795 atomisp_source_pad_to_stream_id(asd, source_pad);
2798 if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index]
2799 .pipes[pipe_index], &info)) {
2800 dev_err(isp->dev, "ia_css_pipe_get_info FAILED");
2804 switch (source_pad) {
2805 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2806 *frame_info = info.output_info[0];
2808 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2809 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2811 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2814 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2816 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2817 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
2818 *frame_info = info.output_info[0];
2820 *frame_info = info.vf_output_info[0];
2822 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2823 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2824 (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
2825 pipe_index == IA_CSS_PIPE_ID_YUVPP))
2826 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2828 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2831 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2832 else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2834 info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2837 info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2844 return frame_info ? 0 : -EINVAL;
2847 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2848 unsigned int stream_index,
2849 unsigned int width, unsigned int height,
2850 unsigned int padded_width,
2851 enum ia_css_frame_format format)
2853 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
2854 default_capture_config.mode =
2855 IA_CSS_CAPTURE_MODE_RAW;
2857 __configure_output(asd, stream_index, width, height, padded_width,
2858 format, IA_CSS_PIPE_ID_COPY);
2862 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
2863 unsigned int stream_index,
2864 unsigned int width, unsigned int height,
2865 unsigned int padded_width,
2866 enum ia_css_frame_format format)
2868 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
2869 default_capture_config.mode =
2870 IA_CSS_CAPTURE_MODE_RAW;
2872 __configure_output(asd, stream_index, width, height, padded_width,
2873 format, IA_CSS_PIPE_ID_YUVPP);
2877 int atomisp_css_yuvpp_configure_viewfinder(
2878 struct atomisp_sub_device *asd,
2879 unsigned int stream_index,
2880 unsigned int width, unsigned int height,
2881 unsigned int min_width,
2882 enum ia_css_frame_format format)
2884 struct atomisp_stream_env *stream_env =
2885 &asd->stream_env[stream_index];
2886 enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP;
2888 stream_env->pipe_configs[pipe_id].mode =
2889 __pipe_id_to_pipe_mode(asd, pipe_id);
2890 stream_env->update_pipe[pipe_id] = true;
2892 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2893 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2894 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2895 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2900 int atomisp_css_yuvpp_get_output_frame_info(
2901 struct atomisp_sub_device *asd,
2902 unsigned int stream_index,
2903 struct ia_css_frame_info *info)
2905 return __get_frame_info(asd, stream_index, info,
2906 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
2909 int atomisp_css_yuvpp_get_viewfinder_frame_info(
2910 struct atomisp_sub_device *asd,
2911 unsigned int stream_index,
2912 struct ia_css_frame_info *info)
2914 return __get_frame_info(asd, stream_index, info,
2915 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
2918 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
2919 unsigned int width, unsigned int height,
2920 unsigned int min_width,
2921 enum ia_css_frame_format format)
2924 * to SOC camera, use yuvpp pipe.
2926 if (ATOMISP_USE_YUVPP(asd))
2927 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
2929 min_width, format, IA_CSS_PIPE_ID_YUVPP);
2931 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2932 min_width, format, IA_CSS_PIPE_ID_PREVIEW);
2936 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
2937 unsigned int width, unsigned int height,
2938 unsigned int min_width,
2939 enum ia_css_frame_format format)
2941 enum ia_css_pipe_id pipe_id;
2944 * to SOC camera, use yuvpp pipe.
2946 if (ATOMISP_USE_YUVPP(asd))
2947 pipe_id = IA_CSS_PIPE_ID_YUVPP;
2949 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
2951 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2952 min_width, format, pipe_id);
2956 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
2957 unsigned int width, unsigned int height,
2958 unsigned int min_width,
2959 enum ia_css_frame_format format)
2962 * to SOC camera, use yuvpp pipe.
2964 if (ATOMISP_USE_YUVPP(asd))
2965 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
2967 min_width, format, IA_CSS_PIPE_ID_YUVPP);
2969 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2970 min_width, format, IA_CSS_PIPE_ID_VIDEO);
2974 int atomisp_css_video_configure_viewfinder(
2975 struct atomisp_sub_device *asd,
2976 unsigned int width, unsigned int height,
2977 unsigned int min_width,
2978 enum ia_css_frame_format format)
2981 * to SOC camera, video will use yuvpp pipe.
2983 if (ATOMISP_USE_YUVPP(asd))
2984 __configure_video_vf_output(asd, width, height, min_width, format,
2985 IA_CSS_PIPE_ID_YUVPP);
2987 __configure_vf_output(asd, width, height, min_width, format,
2988 IA_CSS_PIPE_ID_VIDEO);
2992 int atomisp_css_capture_configure_viewfinder(
2993 struct atomisp_sub_device *asd,
2994 unsigned int width, unsigned int height,
2995 unsigned int min_width,
2996 enum ia_css_frame_format format)
2998 enum ia_css_pipe_id pipe_id;
3001 * to SOC camera, video will use yuvpp pipe.
3003 if (ATOMISP_USE_YUVPP(asd))
3004 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3006 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3008 __configure_vf_output(asd, width, height, min_width, format,
3013 int atomisp_css_video_get_viewfinder_frame_info(
3014 struct atomisp_sub_device *asd,
3015 struct ia_css_frame_info *info)
3017 enum ia_css_pipe_id pipe_id;
3018 enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME;
3020 if (ATOMISP_USE_YUVPP(asd)) {
3021 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3022 if (asd->continuous_mode->val)
3023 frame_type = ATOMISP_CSS_SECOND_VF_FRAME;
3025 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3028 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3029 frame_type, pipe_id);
3032 int atomisp_css_capture_get_viewfinder_frame_info(
3033 struct atomisp_sub_device *asd,
3034 struct ia_css_frame_info *info)
3036 enum ia_css_pipe_id pipe_id;
3038 if (ATOMISP_USE_YUVPP(asd))
3039 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3041 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3043 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3044 ATOMISP_CSS_VF_FRAME, pipe_id);
3047 int atomisp_css_capture_get_output_raw_frame_info(
3048 struct atomisp_sub_device *asd,
3049 struct ia_css_frame_info *info)
3051 if (ATOMISP_USE_YUVPP(asd))
3054 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3055 ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE);
3058 int atomisp_css_copy_get_output_frame_info(
3059 struct atomisp_sub_device *asd,
3060 unsigned int stream_index,
3061 struct ia_css_frame_info *info)
3063 return __get_frame_info(asd, stream_index, info,
3064 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
3067 int atomisp_css_preview_get_output_frame_info(
3068 struct atomisp_sub_device *asd,
3069 struct ia_css_frame_info *info)
3071 enum ia_css_pipe_id pipe_id;
3072 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3074 if (ATOMISP_USE_YUVPP(asd)) {
3075 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3076 if (asd->continuous_mode->val)
3077 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3079 pipe_id = IA_CSS_PIPE_ID_PREVIEW;
3082 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3083 frame_type, pipe_id);
3086 int atomisp_css_capture_get_output_frame_info(
3087 struct atomisp_sub_device *asd,
3088 struct ia_css_frame_info *info)
3090 enum ia_css_pipe_id pipe_id;
3092 if (ATOMISP_USE_YUVPP(asd))
3093 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3095 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3097 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3098 ATOMISP_CSS_OUTPUT_FRAME, pipe_id);
3101 int atomisp_css_video_get_output_frame_info(
3102 struct atomisp_sub_device *asd,
3103 struct ia_css_frame_info *info)
3105 enum ia_css_pipe_id pipe_id;
3106 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3108 if (ATOMISP_USE_YUVPP(asd)) {
3109 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3110 if (asd->continuous_mode->val)
3111 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3113 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3116 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3117 frame_type, pipe_id);
3120 int atomisp_css_preview_configure_pp_input(
3121 struct atomisp_sub_device *asd,
3122 unsigned int width, unsigned int height)
3124 struct atomisp_stream_env *stream_env =
3125 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3126 __configure_preview_pp_input(asd, width, height,
3127 ATOMISP_USE_YUVPP(asd) ?
3128 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW);
3130 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3131 capt_pp_in_res.width)
3132 __configure_capture_pp_input(asd, width, height,
3133 ATOMISP_USE_YUVPP(asd) ?
3134 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3138 int atomisp_css_capture_configure_pp_input(
3139 struct atomisp_sub_device *asd,
3140 unsigned int width, unsigned int height)
3142 __configure_capture_pp_input(asd, width, height,
3143 ATOMISP_USE_YUVPP(asd) ?
3144 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3148 int atomisp_css_video_configure_pp_input(
3149 struct atomisp_sub_device *asd,
3150 unsigned int width, unsigned int height)
3152 struct atomisp_stream_env *stream_env =
3153 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3155 __configure_video_pp_input(asd, width, height,
3156 ATOMISP_USE_YUVPP(asd) ?
3157 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO);
3159 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3160 capt_pp_in_res.width)
3161 __configure_capture_pp_input(asd, width, height,
3162 ATOMISP_USE_YUVPP(asd) ?
3163 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3167 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
3168 int num_captures, unsigned int skip, int offset)
3172 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
3173 __func__, num_captures, skip, offset);
3175 ret = ia_css_stream_capture(
3176 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3177 num_captures, skip, offset);
3184 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
3188 ret = ia_css_stream_capture_frame(
3189 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3191 if (ret == -ENOBUFS) {
3192 /* capture cmd queue is full */
3201 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
3205 ret = ia_css_unlock_raw_frame(
3206 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3208 if (ret == -ENOBUFS)
3216 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
3219 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3220 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
3221 .default_capture_config.enable_xnr = enable;
3222 asd->params.capture_config.enable_xnr = enable;
3223 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3224 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
3229 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
3230 struct ia_css_ctc_table *ctc_table)
3233 u16 *vamem_ptr = ctc_table->data.vamem_1;
3234 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
3237 /* workaround: if ctc_table is all 0, do not apply it */
3238 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
3239 vamem_ptr = ctc_table->data.vamem_2;
3240 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
3243 for (i = 0; i < data_size; i++) {
3244 if (*(vamem_ptr + i)) {
3251 asd->params.config.ctc_table = ctc_table;
3253 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
3256 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
3257 struct ia_css_anr_thres *anr_thres)
3259 asd->params.config.anr_thres = anr_thres;
3262 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
3263 struct ia_css_dvs_6axis_config *dvs_6axis)
3265 asd->params.config.dvs_6axis_config = dvs_6axis;
3268 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
3269 struct atomisp_dis_vector *vector)
3271 if (!asd->params.config.motion_vector)
3272 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
3274 memset(asd->params.config.motion_vector,
3275 0, sizeof(struct ia_css_vector));
3276 asd->params.css_param.motion_vector.x = vector->x;
3277 asd->params.css_param.motion_vector.y = vector->y;
3280 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
3281 struct atomisp_dvs_grid_info *atomgrid)
3283 struct ia_css_dvs_grid_info *cur =
3284 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
3287 dev_err(asd->isp->dev, "dvs grid not available!\n");
3291 if (sizeof(*cur) != sizeof(*atomgrid)) {
3292 dev_err(asd->isp->dev, "dvs grid mis-match!\n");
3297 dev_err(asd->isp->dev, "dvs not enabled!\n");
3301 return memcmp(atomgrid, cur, sizeof(*cur));
3304 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
3305 struct ia_css_dvs2_coefficients *coefs)
3307 asd->params.config.dvs2_coefs = coefs;
3310 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
3311 struct atomisp_dis_coefficients *coefs)
3313 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
3314 /* If the grid info in the argument differs from the current
3315 grid info, we tell the caller to reset the grid size and
3319 if (!coefs->hor_coefs.odd_real ||
3320 !coefs->hor_coefs.odd_imag ||
3321 !coefs->hor_coefs.even_real ||
3322 !coefs->hor_coefs.even_imag ||
3323 !coefs->ver_coefs.odd_real ||
3324 !coefs->ver_coefs.odd_imag ||
3325 !coefs->ver_coefs.even_real ||
3326 !coefs->ver_coefs.even_imag ||
3327 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real ||
3328 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag ||
3329 !asd->params.css_param.dvs2_coeff->hor_coefs.even_real ||
3330 !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag ||
3331 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real ||
3332 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag ||
3333 !asd->params.css_param.dvs2_coeff->ver_coefs.even_real ||
3334 !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag)
3337 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
3338 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
3340 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
3341 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
3343 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
3344 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
3346 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
3347 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
3350 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
3351 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
3353 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
3354 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
3356 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
3357 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
3359 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
3360 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
3363 asd->params.css_param.update_flag.dvs2_coefs =
3364 (struct atomisp_dis_coefficients *)
3365 asd->params.css_param.dvs2_coeff;
3367 /* asd->params.dis_proj_data_valid = false; */
3368 asd->params.css_update_params_needed = true;
3373 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
3376 struct atomisp_device *isp = asd->isp;
3378 if (zoom == asd->params.css_param.dz_config.dx &&
3379 zoom == asd->params.css_param.dz_config.dy) {
3380 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
3384 memset(&asd->params.css_param.dz_config, 0,
3385 sizeof(struct ia_css_dz_config));
3386 asd->params.css_param.dz_config.dx = zoom;
3387 asd->params.css_param.dz_config.dy = zoom;
3389 asd->params.css_param.update_flag.dz_config =
3390 (struct atomisp_dz_config *)&asd->params.css_param.dz_config;
3391 asd->params.css_update_params_needed = true;
3394 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
3395 struct ia_css_formats_config *formats_config)
3397 asd->params.config.formats_config = formats_config;
3400 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
3401 struct atomisp_wb_config *config)
3403 struct ia_css_wb_config wb_config;
3404 struct ia_css_isp_config isp_config;
3405 struct atomisp_device *isp = asd->isp;
3407 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3408 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3412 memset(&wb_config, 0, sizeof(struct ia_css_wb_config));
3413 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3414 isp_config.wb_config = &wb_config;
3415 ia_css_stream_get_isp_config(
3416 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3418 memcpy(config, &wb_config, sizeof(*config));
3423 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
3424 struct atomisp_ob_config *config)
3426 struct ia_css_ob_config ob_config;
3427 struct ia_css_isp_config isp_config;
3428 struct atomisp_device *isp = asd->isp;
3430 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3431 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3435 memset(&ob_config, 0, sizeof(struct ia_css_ob_config));
3436 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3437 isp_config.ob_config = &ob_config;
3438 ia_css_stream_get_isp_config(
3439 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3441 memcpy(config, &ob_config, sizeof(*config));
3446 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
3447 struct atomisp_dp_config *config)
3449 struct ia_css_dp_config dp_config;
3450 struct ia_css_isp_config isp_config;
3451 struct atomisp_device *isp = asd->isp;
3453 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3454 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3458 memset(&dp_config, 0, sizeof(struct ia_css_dp_config));
3459 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3460 isp_config.dp_config = &dp_config;
3461 ia_css_stream_get_isp_config(
3462 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3464 memcpy(config, &dp_config, sizeof(*config));
3469 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3470 struct atomisp_de_config *config)
3472 struct ia_css_de_config de_config;
3473 struct ia_css_isp_config isp_config;
3474 struct atomisp_device *isp = asd->isp;
3476 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3477 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3481 memset(&de_config, 0, sizeof(struct ia_css_de_config));
3482 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3483 isp_config.de_config = &de_config;
3484 ia_css_stream_get_isp_config(
3485 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3487 memcpy(config, &de_config, sizeof(*config));
3492 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3493 struct atomisp_nr_config *config)
3495 struct ia_css_nr_config nr_config;
3496 struct ia_css_isp_config isp_config;
3497 struct atomisp_device *isp = asd->isp;
3499 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3500 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3504 memset(&nr_config, 0, sizeof(struct ia_css_nr_config));
3505 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3507 isp_config.nr_config = &nr_config;
3508 ia_css_stream_get_isp_config(
3509 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3511 memcpy(config, &nr_config, sizeof(*config));
3516 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3517 struct atomisp_ee_config *config)
3519 struct ia_css_ee_config ee_config;
3520 struct ia_css_isp_config isp_config;
3521 struct atomisp_device *isp = asd->isp;
3523 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3524 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3528 memset(&ee_config, 0, sizeof(struct ia_css_ee_config));
3529 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3530 isp_config.ee_config = &ee_config;
3531 ia_css_stream_get_isp_config(
3532 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3534 memcpy(config, &ee_config, sizeof(*config));
3539 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3540 struct atomisp_tnr_config *config)
3542 struct ia_css_tnr_config tnr_config;
3543 struct ia_css_isp_config isp_config;
3544 struct atomisp_device *isp = asd->isp;
3546 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3547 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3551 memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config));
3552 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3553 isp_config.tnr_config = &tnr_config;
3554 ia_css_stream_get_isp_config(
3555 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3557 memcpy(config, &tnr_config, sizeof(*config));
3562 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3563 struct atomisp_ctc_table *config)
3565 struct ia_css_ctc_table *tab;
3566 struct ia_css_isp_config isp_config;
3567 struct atomisp_device *isp = asd->isp;
3569 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3570 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3575 tab = vzalloc(sizeof(struct ia_css_ctc_table));
3579 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3580 isp_config.ctc_table = tab;
3581 ia_css_stream_get_isp_config(
3582 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3584 memcpy(config, tab, sizeof(*tab));
3590 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
3591 struct atomisp_gamma_table *config)
3593 struct ia_css_gamma_table *tab;
3594 struct ia_css_isp_config isp_config;
3595 struct atomisp_device *isp = asd->isp;
3597 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3598 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3603 tab = vzalloc(sizeof(struct ia_css_gamma_table));
3607 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3608 isp_config.gamma_table = tab;
3609 ia_css_stream_get_isp_config(
3610 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3612 memcpy(config, tab, sizeof(*tab));
3618 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
3619 struct atomisp_gc_config *config)
3621 struct ia_css_gc_config gc_config;
3622 struct ia_css_isp_config isp_config;
3623 struct atomisp_device *isp = asd->isp;
3625 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3626 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3630 memset(&gc_config, 0, sizeof(struct ia_css_gc_config));
3631 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3632 isp_config.gc_config = &gc_config;
3633 ia_css_stream_get_isp_config(
3634 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3636 /* Get gamma correction params from current setup */
3637 memcpy(config, &gc_config, sizeof(*config));
3642 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
3643 struct atomisp_3a_config *config)
3645 struct ia_css_3a_config s3a_config;
3646 struct ia_css_isp_config isp_config;
3647 struct atomisp_device *isp = asd->isp;
3649 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3650 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3654 memset(&s3a_config, 0, sizeof(struct ia_css_3a_config));
3655 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3656 isp_config.s3a_config = &s3a_config;
3657 ia_css_stream_get_isp_config(
3658 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3660 /* Get white balance from current setup */
3661 memcpy(config, &s3a_config, sizeof(*config));
3666 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
3667 struct atomisp_formats_config *config)
3669 struct ia_css_formats_config formats_config;
3670 struct ia_css_isp_config isp_config;
3671 struct atomisp_device *isp = asd->isp;
3673 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3674 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3678 memset(&formats_config, 0, sizeof(formats_config));
3679 memset(&isp_config, 0, sizeof(isp_config));
3680 isp_config.formats_config = &formats_config;
3681 ia_css_stream_get_isp_config(
3682 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3684 /* Get narrow gamma from current setup */
3685 memcpy(config, &formats_config, sizeof(*config));
3690 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
3693 struct ia_css_dz_config dz_config; /** Digital Zoom */
3694 struct ia_css_isp_config isp_config;
3695 struct atomisp_device *isp = asd->isp;
3697 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3698 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3702 memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
3703 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3704 isp_config.dz_config = &dz_config;
3705 ia_css_stream_get_isp_config(
3706 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3708 *zoom = dz_config.dx;
3714 * Function to set/get image stablization statistics
3716 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
3717 struct atomisp_dis_statistics *stats)
3719 struct atomisp_device *isp = asd->isp;
3720 struct atomisp_dis_buf *dis_buf;
3721 unsigned long flags;
3723 if (!asd->params.dvs_stat->hor_prod.odd_real ||
3724 !asd->params.dvs_stat->hor_prod.odd_imag ||
3725 !asd->params.dvs_stat->hor_prod.even_real ||
3726 !asd->params.dvs_stat->hor_prod.even_imag ||
3727 !asd->params.dvs_stat->ver_prod.odd_real ||
3728 !asd->params.dvs_stat->ver_prod.odd_imag ||
3729 !asd->params.dvs_stat->ver_prod.even_real ||
3730 !asd->params.dvs_stat->ver_prod.even_imag)
3733 /* isp needs to be streaming to get DIS statistics */
3734 spin_lock_irqsave(&isp->lock, flags);
3735 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) {
3736 spin_unlock_irqrestore(&isp->lock, flags);
3739 spin_unlock_irqrestore(&isp->lock, flags);
3741 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
3742 /* If the grid info in the argument differs from the current
3743 grid info, we tell the caller to reset the grid size and
3747 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3748 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
3749 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3750 dev_err(isp->dev, "dis statistics is not valid.\n");
3754 dis_buf = list_entry(asd->dis_stats.next,
3755 struct atomisp_dis_buf, list);
3756 list_del_init(&dis_buf->list);
3757 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3759 if (dis_buf->dvs_map)
3760 ia_css_translate_dvs2_statistics(
3761 asd->params.dvs_stat, dis_buf->dvs_map);
3763 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
3765 stats->exp_id = dis_buf->dis_data->exp_id;
3767 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3768 list_add_tail(&dis_buf->list, &asd->dis_stats);
3769 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3771 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
3772 asd->params.dvs_stat->ver_prod.odd_real,
3773 asd->params.dvs_ver_proj_bytes))
3775 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
3776 asd->params.dvs_stat->ver_prod.odd_imag,
3777 asd->params.dvs_ver_proj_bytes))
3779 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
3780 asd->params.dvs_stat->ver_prod.even_real,
3781 asd->params.dvs_ver_proj_bytes))
3783 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
3784 asd->params.dvs_stat->ver_prod.even_imag,
3785 asd->params.dvs_ver_proj_bytes))
3787 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
3788 asd->params.dvs_stat->hor_prod.odd_real,
3789 asd->params.dvs_hor_proj_bytes))
3791 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
3792 asd->params.dvs_stat->hor_prod.odd_imag,
3793 asd->params.dvs_hor_proj_bytes))
3795 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
3796 asd->params.dvs_stat->hor_prod.even_real,
3797 asd->params.dvs_hor_proj_bytes))
3799 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
3800 asd->params.dvs_stat->hor_prod.even_imag,
3801 asd->params.dvs_hor_proj_bytes))
3807 struct ia_css_shading_table *atomisp_css_shading_table_alloc(
3808 unsigned int width, unsigned int height)
3810 return ia_css_shading_table_alloc(width, height);
3813 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
3814 struct ia_css_shading_table *table)
3816 asd->params.config.shading_table = table;
3819 void atomisp_css_shading_table_free(struct ia_css_shading_table *table)
3821 ia_css_shading_table_free(table);
3824 struct ia_css_morph_table *atomisp_css_morph_table_allocate(
3825 unsigned int width, unsigned int height)
3827 return ia_css_morph_table_allocate(width, height);
3830 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
3831 struct ia_css_morph_table *table)
3833 asd->params.config.morph_table = table;
3836 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
3837 struct ia_css_morph_table *table)
3839 struct ia_css_isp_config isp_config;
3840 struct atomisp_device *isp = asd->isp;
3842 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3844 "%s called after streamoff, skipping.\n", __func__);
3847 memset(table, 0, sizeof(struct ia_css_morph_table));
3848 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3849 isp_config.morph_table = table;
3850 ia_css_stream_get_isp_config(
3851 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3855 void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
3857 ia_css_morph_table_free(table);
3860 void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp,
3861 unsigned int overlap)
3863 /* CSS 2.0 doesn't support this API. */
3864 dev_dbg(isp->dev, "set cont prev start time is not supported.\n");
3868 void atomisp_css_acc_done(struct atomisp_sub_device *asd)
3870 complete(&asd->acc.acc_done);
3873 int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd)
3876 struct atomisp_device *isp = asd->isp;
3878 /* Unlock the isp mutex taken in IOCTL handler before sleeping! */
3879 rt_mutex_unlock(&isp->mutex);
3880 if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done,
3881 ATOMISP_ISP_TIMEOUT_DURATION) == 0) {
3882 dev_err(isp->dev, "<%s: completion timeout\n", __func__);
3883 ia_css_debug_dump_sp_sw_debug_info();
3884 ia_css_debug_dump_debug_info(__func__);
3887 rt_mutex_lock(&isp->mutex);
3892 /* Set the ACC binary arguments */
3893 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw)
3897 for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) {
3898 if (acc_fw->args[mem].length == 0)
3901 ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers,
3902 IA_CSS_PARAM_CLASS_PARAM, mem,
3903 acc_fw->args[mem].css_ptr,
3904 acc_fw->args[mem].length);
3910 /* Load acc binary extension */
3911 int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd,
3912 struct ia_css_fw_info *fw,
3913 enum ia_css_pipe_id pipe_id,
3916 struct ia_css_fw_info **hd;
3919 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3920 .pipe_configs[pipe_id].acc_extension);
3925 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3926 .update_pipe[pipe_id] = true;
3930 /* Unload acc binary extension */
3931 void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd,
3932 struct ia_css_fw_info *fw,
3933 enum ia_css_pipe_id pipe_id)
3935 struct ia_css_fw_info **hd;
3937 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3938 .pipe_configs[pipe_id].acc_extension);
3939 while (*hd && *hd != fw)
3942 dev_err(asd->isp->dev, "did not find acc fw for removal\n");
3948 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3949 .update_pipe[pipe_id] = true;
3952 int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd)
3954 struct atomisp_device *isp = asd->isp;
3955 struct ia_css_pipe_config *pipe_config;
3956 struct atomisp_stream_env *stream_env =
3957 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3959 if (stream_env->acc_stream) {
3960 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
3961 if (ia_css_stream_stop(stream_env->acc_stream)
3963 dev_err(isp->dev, "stop acc_stream failed.\n");
3968 if (ia_css_stream_destroy(stream_env->acc_stream)
3970 dev_err(isp->dev, "destroy acc_stream failed.\n");
3973 stream_env->acc_stream = NULL;
3976 pipe_config = &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
3977 ia_css_pipe_config_defaults(pipe_config);
3978 asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES *
3979 sizeof(void *), GFP_KERNEL);
3980 if (!asd->acc.acc_stages)
3982 pipe_config->acc_stages = asd->acc.acc_stages;
3983 pipe_config->mode = IA_CSS_PIPE_MODE_ACC;
3984 pipe_config->num_acc_stages = 0;
3987 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe,
3988 * because pipe configuration will soon be changed by
3989 * atomisp_css_load_acc_binary()
3994 int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd)
3996 struct atomisp_device *isp = asd->isp;
3997 struct atomisp_stream_env *stream_env =
3998 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3999 struct ia_css_pipe_config *pipe_config =
4000 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
4002 if (ia_css_pipe_create(pipe_config,
4003 &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != 0) {
4004 dev_err(isp->dev, "%s: ia_css_pipe_create failed\n",
4009 memset(&stream_env->acc_stream_config, 0,
4010 sizeof(struct ia_css_stream_config));
4011 if (ia_css_stream_create(&stream_env->acc_stream_config, 1,
4012 &stream_env->pipes[IA_CSS_PIPE_ID_ACC],
4013 &stream_env->acc_stream) != 0) {
4014 dev_err(isp->dev, "%s: create acc_stream error.\n", __func__);
4017 stream_env->acc_stream_state = CSS_STREAM_CREATED;
4019 init_completion(&asd->acc.acc_done);
4020 asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC];
4022 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
4024 if (ia_css_start_sp()) {
4025 dev_err(isp->dev, "start sp error.\n");
4029 if (ia_css_stream_start(stream_env->acc_stream)
4031 dev_err(isp->dev, "acc_stream start error.\n");
4035 stream_env->acc_stream_state = CSS_STREAM_STARTED;
4039 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd)
4041 struct atomisp_stream_env *stream_env =
4042 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4043 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4044 ia_css_stream_stop(stream_env->acc_stream);
4045 stream_env->acc_stream_state = CSS_STREAM_STOPPED;
4050 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd)
4052 struct atomisp_stream_env *stream_env =
4053 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4054 if (stream_env->acc_stream) {
4055 if (ia_css_stream_destroy(stream_env->acc_stream)
4057 dev_warn(asd->isp->dev,
4058 "destroy acc_stream failed.\n");
4059 stream_env->acc_stream = NULL;
4062 if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) {
4063 if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC])
4065 dev_warn(asd->isp->dev,
4066 "destroy ACC pipe failed.\n");
4067 stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL;
4068 stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false;
4069 ia_css_pipe_config_defaults(
4070 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]);
4071 ia_css_pipe_extra_config_defaults(
4072 &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]);
4074 asd->acc.pipeline = NULL;
4076 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
4081 kfree(asd->acc.acc_stages);
4082 asd->acc.acc_stages = NULL;
4084 atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false);
4087 int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd,
4088 struct ia_css_fw_info *fw,
4091 struct ia_css_pipe_config *pipe_config =
4092 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4093 .pipe_configs[IA_CSS_PIPE_ID_ACC];
4095 if (index >= MAX_ACC_STAGES) {
4096 dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n",
4101 pipe_config->acc_stages[index] = fw;
4102 pipe_config->num_acc_stages = index + 1;
4103 pipe_config->acc_num_execs = 1;
4108 static struct atomisp_sub_device *__get_atomisp_subdev(
4109 struct ia_css_pipe *css_pipe,
4110 struct atomisp_device *isp,
4111 enum atomisp_input_stream_id *stream_id)
4114 struct atomisp_sub_device *asd;
4115 struct atomisp_stream_env *stream_env;
4117 for (i = 0; i < isp->num_of_streams; i++) {
4119 if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED &&
4122 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4123 stream_env = &asd->stream_env[j];
4124 for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
4125 if (stream_env->pipes[k] &&
4126 stream_env->pipes[k] == css_pipe) {
4137 int atomisp_css_isr_thread(struct atomisp_device *isp,
4138 bool *frame_done_found,
4139 bool *css_pipe_done)
4141 enum atomisp_input_stream_id stream_id = 0;
4142 struct atomisp_css_event current_event;
4143 struct atomisp_sub_device *asd;
4144 bool reset_wdt_timer[MAX_STREAM_NUM] = {false};
4147 while (!atomisp_css_dequeue_event(¤t_event)) {
4148 if (current_event.event.type ==
4149 IA_CSS_EVENT_TYPE_FW_ASSERT) {
4151 * Received FW assertion signal,
4152 * trigger WDT to recover
4155 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
4157 current_event.event.fw_assert_module_id,
4158 current_event.event.fw_assert_line_no);
4159 for (i = 0; i < isp->num_of_streams; i++)
4160 atomisp_wdt_stop(&isp->asd[i], 0);
4163 atomisp_wdt(&isp->asd[0].wdt);
4165 queue_work(isp->wdt_work_queue, &isp->wdt_work);
4168 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4169 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
4170 __func__, current_event.event.fw_warning,
4171 current_event.event.exp_id);
4175 asd = __get_atomisp_subdev(current_event.event.pipe,
4178 if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
4180 "event: Timer event.");
4182 dev_warn(isp->dev, "%s:no subdev.event:%d",
4184 current_event.event.type);
4188 atomisp_css_temp_pipe_to_pipe_id(asd, ¤t_event);
4189 switch (current_event.event.type) {
4190 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
4191 dev_dbg(isp->dev, "event: Output frame done");
4192 frame_done_found[asd->index] = true;
4193 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
4194 current_event.pipe, true, stream_id);
4197 reset_wdt_timer[asd->index] = true; /* ISP running */
4200 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
4201 dev_dbg(isp->dev, "event: Second output frame done");
4202 frame_done_found[asd->index] = true;
4203 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
4204 current_event.pipe, true, stream_id);
4207 reset_wdt_timer[asd->index] = true; /* ISP running */
4210 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
4211 dev_dbg(isp->dev, "event: 3A stats frame done");
4212 atomisp_buf_done(asd, 0,
4213 IA_CSS_BUFFER_TYPE_3A_STATISTICS,
4217 case IA_CSS_EVENT_TYPE_METADATA_DONE:
4218 dev_dbg(isp->dev, "event: metadata frame done");
4219 atomisp_buf_done(asd, 0,
4220 IA_CSS_BUFFER_TYPE_METADATA,
4224 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
4225 dev_dbg(isp->dev, "event: VF output frame done");
4226 atomisp_buf_done(asd, 0,
4227 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
4228 current_event.pipe, true, stream_id);
4231 reset_wdt_timer[asd->index] = true; /* ISP running */
4234 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
4235 dev_dbg(isp->dev, "event: second VF output frame done");
4236 atomisp_buf_done(asd, 0,
4237 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
4238 current_event.pipe, true, stream_id);
4240 reset_wdt_timer[asd->index] = true; /* ISP running */
4243 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
4244 dev_dbg(isp->dev, "event: dis stats frame done");
4245 atomisp_buf_done(asd, 0,
4246 IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
4250 case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
4251 dev_dbg(isp->dev, "event: pipeline done");
4252 css_pipe_done[asd->index] = true;
4254 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
4255 dev_dbg(isp->dev, "event: acc stage done");
4256 atomisp_acc_done(asd, current_event.event.fw_handle);
4259 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
4260 current_event.event.type);
4268 /* ISP2400: If there are no buffers queued then delete wdt timer. */
4269 for (i = 0; i < isp->num_of_streams; i++) {
4273 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
4275 if (!atomisp_buffers_queued(asd))
4276 atomisp_wdt_stop(asd, false);
4277 else if (reset_wdt_timer[i])
4278 /* SOF irq should not reset wdt timer. */
4279 atomisp_wdt_refresh(asd,
4280 ATOMISP_WDT_KEEP_CURRENT_DELAY);
4286 bool atomisp_css_valid_sof(struct atomisp_device *isp)
4290 /* Loop for each css stream */
4291 for (i = 0; i < isp->num_of_streams; i++) {
4292 struct atomisp_sub_device *asd = &isp->asd[i];
4293 /* Loop for each css vc stream */
4294 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4295 if (asd->stream_env[j].stream &&
4296 asd->stream_env[j].stream_config.mode ==
4297 IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
4305 int atomisp_css_debug_dump_isp_binary(void)
4307 ia_css_debug_dump_isp_binary();
4311 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
4313 sh_css_dump_sp_raw_copy_linecount(reduced);
4317 static const char * const fw_type_name[] = {
4318 [ia_css_sp_firmware] = "SP",
4319 [ia_css_isp_firmware] = "ISP",
4320 [ia_css_bootloader_firmware] = "BootLoader",
4321 [ia_css_acc_firmware] = "accel",
4324 static const char * const fw_acc_type_name[] = {
4325 [IA_CSS_ACC_NONE] = "Normal",
4326 [IA_CSS_ACC_OUTPUT] = "Accel stage on output",
4327 [IA_CSS_ACC_VIEWFINDER] = "Accel stage on viewfinder",
4328 [IA_CSS_ACC_STANDALONE] = "Stand-alone acceleration",
4331 int atomisp_css_dump_blob_infor(void)
4333 struct ia_css_blob_descr *bd = sh_css_blob_info;
4334 unsigned int i, nm = sh_css_num_binaries;
4342 * The sh_css_load_firmware function discard the initial
4345 for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) {
4346 switch (bd[i].header.type) {
4347 case ia_css_isp_firmware:
4348 dev_dbg(atomisp_dev,
4349 "Num%2d type %s (%s), binary id is %2d, name is %s\n",
4351 fw_type_name[bd[i].header.type],
4352 fw_acc_type_name[bd[i].header.info.isp.type],
4353 bd[i].header.info.isp.sp.id,
4357 dev_dbg(atomisp_dev,
4358 "Num%2d type %s, name is %s\n",
4359 i + NUM_OF_SPS, fw_type_name[bd[i].header.type],
4367 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
4368 uint32_t isp_config_id)
4370 asd->params.config.isp_config_id = isp_config_id;
4373 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
4374 struct ia_css_frame *output_frame)
4376 asd->params.config.output_frame = output_frame;
4379 int atomisp_get_css_dbgfunc(void)
4384 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
4388 ret = __set_css_print_env(isp, opt);
4395 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
4397 ia_css_en_dz_capt_pipe(
4398 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4402 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
4403 struct ia_css_grid_info *grid_info)
4408 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
4409 return &grid_info->dvs_grid.dvs_grid_info;
4411 return &grid_info->dvs_grid;