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 "ia_css_debug.h"
37 #include "ia_css_isp_param.h"
38 #include "sh_css_hrt.h"
39 #include "ia_css_isys.h"
42 #include <linux/pm_runtime.h>
44 /* Assume max number of ACC stages */
45 #define MAX_ACC_STAGES 20
47 /* Ideally, this should come from CSS headers */
51 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
52 * #4684168, if concurrency access happened, system may hard hang.
54 static DEFINE_SPINLOCK(mmio_lock);
56 enum frame_info_type {
58 ATOMISP_CSS_SECOND_VF_FRAME,
59 ATOMISP_CSS_OUTPUT_FRAME,
60 ATOMISP_CSS_SECOND_OUTPUT_FRAME,
61 ATOMISP_CSS_RAW_FRAME,
64 struct bayer_ds_factor {
65 unsigned int numerator;
66 unsigned int denominator;
69 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
71 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
74 spin_lock_irqsave(&mmio_lock, flags);
75 writeb(data, isp->base + (addr & 0x003FFFFF));
76 spin_unlock_irqrestore(&mmio_lock, flags);
79 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
81 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
84 spin_lock_irqsave(&mmio_lock, flags);
85 writew(data, isp->base + (addr & 0x003FFFFF));
86 spin_unlock_irqrestore(&mmio_lock, flags);
89 void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
91 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
94 spin_lock_irqsave(&mmio_lock, flags);
95 writel(data, isp->base + (addr & 0x003FFFFF));
96 spin_unlock_irqrestore(&mmio_lock, flags);
99 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
101 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
105 spin_lock_irqsave(&mmio_lock, flags);
106 ret = readb(isp->base + (addr & 0x003FFFFF));
107 spin_unlock_irqrestore(&mmio_lock, flags);
111 static uint16_t atomisp_css2_hw_load_16(hrt_address addr)
113 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
117 spin_lock_irqsave(&mmio_lock, flags);
118 ret = readw(isp->base + (addr & 0x003FFFFF));
119 spin_unlock_irqrestore(&mmio_lock, flags);
123 static uint32_t atomisp_css2_hw_load_32(hrt_address addr)
125 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
129 spin_lock_irqsave(&mmio_lock, flags);
130 ret = readl(isp->base + (addr & 0x003FFFFF));
131 spin_unlock_irqrestore(&mmio_lock, flags);
135 static void atomisp_css2_hw_store(hrt_address addr, const void *from, uint32_t n)
137 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
142 spin_lock_irqsave(&mmio_lock, flags);
143 for (i = 0; i < n; i++, from++)
144 writeb(*(s8 *)from, isp->base + addr + i);
146 spin_unlock_irqrestore(&mmio_lock, flags);
149 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
151 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
156 spin_lock_irqsave(&mmio_lock, flags);
157 for (i = 0; i < n; i++, to++)
158 *(s8 *)to = readb(isp->base + addr + i);
159 spin_unlock_irqrestore(&mmio_lock, flags);
162 static int atomisp_css2_dbg_print(const char *fmt, va_list args)
168 static int atomisp_css2_dbg_ftrace_print(const char *fmt, va_list args)
170 ftrace_vprintk(fmt, args);
174 static int atomisp_css2_err_print(const char *fmt, va_list args)
180 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
182 *data = atomisp_css2_hw_load_32(addr);
185 static int hmm_get_mmu_base_addr(struct device *dev, unsigned int *mmu_base_addr)
187 if (!sh_mmu_mrfld.get_pd_base) {
188 dev_err(dev, "get mmu base address failed.\n");
192 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
193 bo_device.mmu.base_address);
197 static void __dump_pipe_config(struct atomisp_sub_device *asd,
198 struct atomisp_stream_env *stream_env,
199 unsigned int pipe_id)
201 struct atomisp_device *isp = asd->isp;
203 if (stream_env->pipes[pipe_id]) {
204 struct ia_css_pipe_config *p_config;
205 struct ia_css_pipe_extra_config *pe_config;
207 p_config = &stream_env->pipe_configs[pipe_id];
208 pe_config = &stream_env->pipe_extra_configs[pipe_id];
209 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
211 "pipe_config.pipe_mode:%d.\n", p_config->mode);
213 "pipe_config.output_info[0] w=%d, h=%d.\n",
214 p_config->output_info[0].res.width,
215 p_config->output_info[0].res.height);
217 "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
218 p_config->vf_pp_in_res.width,
219 p_config->vf_pp_in_res.height);
221 "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
222 p_config->capt_pp_in_res.width,
223 p_config->capt_pp_in_res.height);
225 "pipe_config.output.padded w=%d.\n",
226 p_config->output_info[0].padded_width);
228 "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
229 p_config->vf_output_info[0].res.width,
230 p_config->vf_output_info[0].res.height);
232 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
233 p_config->bayer_ds_out_res.width,
234 p_config->bayer_ds_out_res.height);
236 "pipe_config.envelope w=%d, h=%d.\n",
237 p_config->dvs_envelope.width,
238 p_config->dvs_envelope.height);
240 "pipe_config.dvs_frame_delay=%d.\n",
241 p_config->dvs_frame_delay);
243 "pipe_config.isp_pipe_version:%d.\n",
244 p_config->isp_pipe_version);
246 "pipe_config.acc_extension=%p.\n",
247 p_config->acc_extension);
249 "pipe_config.acc_stages=%p.\n",
250 p_config->acc_stages);
252 "pipe_config.num_acc_stages=%d.\n",
253 p_config->num_acc_stages);
255 "pipe_config.acc_num_execs=%d.\n",
256 p_config->acc_num_execs);
258 "pipe_config.default_capture_config.capture_mode=%d.\n",
259 p_config->default_capture_config.mode);
261 "pipe_config.enable_dz=%d.\n",
262 p_config->enable_dz);
264 "pipe_config.default_capture_config.enable_xnr=%d.\n",
265 p_config->default_capture_config.enable_xnr);
267 "dumping pipe[%d] extra config:\n", pipe_id);
269 "pipe_extra_config.enable_raw_binning:%d.\n",
270 pe_config->enable_raw_binning);
272 "pipe_extra_config.enable_yuv_ds:%d.\n",
273 pe_config->enable_yuv_ds);
275 "pipe_extra_config.enable_high_speed:%d.\n",
276 pe_config->enable_high_speed);
278 "pipe_extra_config.enable_dvs_6axis:%d.\n",
279 pe_config->enable_dvs_6axis);
281 "pipe_extra_config.enable_reduced_pipe:%d.\n",
282 pe_config->enable_reduced_pipe);
284 "pipe_(extra_)config.enable_dz:%d.\n",
285 p_config->enable_dz);
287 "pipe_extra_config.disable_vf_pp:%d.\n",
288 pe_config->disable_vf_pp);
292 static void __dump_stream_config(struct atomisp_sub_device *asd,
293 struct atomisp_stream_env *stream_env)
295 struct atomisp_device *isp = asd->isp;
296 struct ia_css_stream_config *s_config;
298 bool valid_stream = false;
300 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
301 if (stream_env->pipes[j]) {
302 __dump_pipe_config(asd, stream_env, j);
308 s_config = &stream_env->stream_config;
309 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
311 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
312 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
313 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
314 s_config->source.port.port);
315 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
316 s_config->source.port.num_lanes);
317 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
318 s_config->source.port.timeout);
319 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
320 s_config->source.port.rxcount);
321 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
322 s_config->source.port.compression.type);
324 "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
325 s_config->source.port.compression.
326 compressed_bits_per_pixel);
328 "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
329 s_config->source.port.compression.
330 uncompressed_bits_per_pixel);
331 } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
332 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
333 s_config->source.tpg.id);
334 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
335 s_config->source.tpg.mode);
336 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
337 s_config->source.tpg.x_mask);
338 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
339 s_config->source.tpg.x_delta);
340 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
341 s_config->source.tpg.y_mask);
342 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
343 s_config->source.tpg.y_delta);
344 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
345 s_config->source.tpg.xy_mask);
346 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
347 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
348 s_config->source.prbs.id);
349 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
350 s_config->source.prbs.h_blank);
351 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
352 s_config->source.prbs.v_blank);
353 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
354 s_config->source.prbs.seed);
355 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
356 s_config->source.prbs.seed1);
359 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
360 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
362 s_config->isys_config[j].input_res.width,
363 s_config->isys_config[j].input_res.height);
365 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
367 s_config->isys_config[j].linked_isys_stream_id);
369 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
371 s_config->isys_config[j].format);
373 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
375 s_config->isys_config[j].valid);
378 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
379 s_config->input_config.input_res.width,
380 s_config->input_config.input_res.height);
382 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
383 s_config->input_config.effective_res.width,
384 s_config->input_config.effective_res.height);
386 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
387 s_config->input_config.format);
389 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
390 s_config->input_config.bayer_order);
392 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
393 s_config->pixels_per_clock);
394 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
395 dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
396 s_config->continuous);
397 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
398 s_config->disable_cont_viewfinder);
399 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
400 s_config->channel_id);
401 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
402 s_config->init_num_cont_raw_buf);
403 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
404 s_config->target_num_cont_raw_buf);
405 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
406 s_config->left_padding);
407 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
408 s_config->sensor_binning_factor);
409 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
410 s_config->pixels_per_clock);
411 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
412 s_config->pack_raw_pixels);
413 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
414 s_config->flash_gpio_pin);
415 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
416 s_config->mipi_buffer_config.size_mem_words);
417 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
418 s_config->mipi_buffer_config.contiguous);
419 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
420 s_config->metadata_config.data_type);
421 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
422 s_config->metadata_config.resolution.width,
423 s_config->metadata_config.resolution.height);
426 static int __destroy_stream(struct atomisp_sub_device *asd,
427 struct atomisp_stream_env *stream_env, bool force)
429 struct atomisp_device *isp = asd->isp;
431 unsigned long timeout;
433 if (!stream_env->stream)
437 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
438 if (stream_env->update_pipe[i])
441 if (i == IA_CSS_PIPE_ID_NUM)
445 if (stream_env->stream_state == CSS_STREAM_STARTED
446 && ia_css_stream_stop(stream_env->stream) != 0) {
447 dev_err(isp->dev, "stop stream failed.\n");
451 if (stream_env->stream_state == CSS_STREAM_STARTED) {
452 timeout = jiffies + msecs_to_jiffies(40);
454 if (ia_css_stream_has_stopped(stream_env->stream))
457 if (time_after(jiffies, timeout)) {
458 dev_warn(isp->dev, "stop stream timeout.\n");
462 usleep_range(100, 200);
466 stream_env->stream_state = CSS_STREAM_STOPPED;
468 if (ia_css_stream_destroy(stream_env->stream)) {
469 dev_err(isp->dev, "destroy stream failed.\n");
472 stream_env->stream_state = CSS_STREAM_UNINIT;
473 stream_env->stream = NULL;
478 static int __destroy_streams(struct atomisp_sub_device *asd, bool force)
482 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
483 ret = __destroy_stream(asd, &asd->stream_env[i], force);
487 asd->stream_prepared = false;
491 static int __create_stream(struct atomisp_sub_device *asd,
492 struct atomisp_stream_env *stream_env)
494 int pipe_index = 0, i;
495 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
497 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
498 if (stream_env->pipes[i])
499 multi_pipes[pipe_index++] = stream_env->pipes[i];
504 stream_env->stream_config.target_num_cont_raw_buf =
505 asd->continuous_raw_buffer_size->val;
506 stream_env->stream_config.channel_id = stream_env->ch_id;
507 stream_env->stream_config.ia_css_enable_raw_buffer_locking =
508 asd->enable_raw_buffer_lock->val;
510 __dump_stream_config(asd, stream_env);
511 if (ia_css_stream_create(&stream_env->stream_config,
512 pipe_index, multi_pipes, &stream_env->stream) != 0)
514 if (ia_css_stream_get_info(stream_env->stream,
515 &stream_env->stream_info) != 0) {
516 ia_css_stream_destroy(stream_env->stream);
517 stream_env->stream = NULL;
521 stream_env->stream_state = CSS_STREAM_CREATED;
525 static int __create_streams(struct atomisp_sub_device *asd)
529 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
530 ret = __create_stream(asd, &asd->stream_env[i]);
534 asd->stream_prepared = true;
537 for (i--; i >= 0; i--)
538 __destroy_stream(asd, &asd->stream_env[i], true);
542 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
543 struct atomisp_stream_env *stream_env,
546 struct atomisp_device *isp = asd->isp;
550 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
551 if (!stream_env->pipes[i] ||
552 !(force || stream_env->update_pipe[i]))
554 if (ia_css_pipe_destroy(stream_env->pipes[i])
557 "destroy pipe[%d]failed.cannot recover.\n", i);
560 stream_env->pipes[i] = NULL;
561 stream_env->update_pipe[i] = false;
566 static int __destroy_pipes(struct atomisp_sub_device *asd, bool force)
568 struct atomisp_device *isp = asd->isp;
572 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
573 if (asd->stream_env[i].stream) {
575 "cannot destroy css pipes for stream[%d].\n",
580 ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force);
588 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
590 __destroy_streams(asd, true);
591 __destroy_pipes(asd, true);
594 static void __apply_additional_pipe_config(
595 struct atomisp_sub_device *asd,
596 struct atomisp_stream_env *stream_env,
597 enum ia_css_pipe_id pipe_id)
599 struct atomisp_device *isp = asd->isp;
601 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
603 "wrong pipe_id for additional pipe config.\n");
607 /* apply default pipe config */
608 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
609 stream_env->pipe_configs[pipe_id].enable_dz =
610 asd->disable_dz->val ? false : true;
611 /* apply isp 2.2 specific config for baytrail*/
613 case IA_CSS_PIPE_ID_CAPTURE:
614 /* enable capture pp/dz manually or digital zoom would
616 if (stream_env->pipe_configs[pipe_id].
617 default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW)
618 stream_env->pipe_configs[pipe_id].enable_dz = false;
621 /* the isp default to use ISP2.2 and the camera hal will
622 * control whether use isp2.7 */
623 if (asd->select_isp_version->val == ATOMISP_CSS_ISP_PIPE_VERSION_2_7)
624 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_7;
626 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_2;
629 case IA_CSS_PIPE_ID_VIDEO:
630 /* enable reduced pipe to have binary
631 * video_dz_2_min selected*/
632 stream_env->pipe_extra_configs[pipe_id]
633 .enable_reduced_pipe = true;
634 stream_env->pipe_configs[pipe_id]
636 if (ATOMISP_SOC_CAMERA(asd))
637 stream_env->pipe_configs[pipe_id].enable_dz = true;
639 if (asd->params.video_dis_en) {
640 stream_env->pipe_extra_configs[pipe_id]
641 .enable_dvs_6axis = true;
642 stream_env->pipe_configs[pipe_id]
644 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
647 case IA_CSS_PIPE_ID_PREVIEW:
649 case IA_CSS_PIPE_ID_YUVPP:
650 case IA_CSS_PIPE_ID_COPY:
651 if (ATOMISP_SOC_CAMERA(asd))
652 stream_env->pipe_configs[pipe_id].enable_dz = true;
654 stream_env->pipe_configs[pipe_id].enable_dz = false;
656 case IA_CSS_PIPE_ID_ACC:
657 stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC;
658 stream_env->pipe_configs[pipe_id].enable_dz = false;
665 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
666 enum ia_css_pipe_id pipe_id)
671 if (pipe_id == IA_CSS_PIPE_ID_ACC || pipe_id == IA_CSS_PIPE_ID_YUVPP)
675 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
676 if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
680 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
681 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
691 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
694 switch (asd->run_mode->val) {
695 case ATOMISP_RUN_MODE_STILL_CAPTURE:
696 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
700 case ATOMISP_RUN_MODE_PREVIEW:
701 if (!asd->continuous_mode->val) {
702 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
708 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
709 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
710 pipe_id == IA_CSS_PIPE_ID_PREVIEW)
715 case ATOMISP_RUN_MODE_VIDEO:
716 if (!asd->continuous_mode->val) {
717 if (pipe_id == IA_CSS_PIPE_ID_VIDEO ||
718 pipe_id == IA_CSS_PIPE_ID_YUVPP)
724 case ATOMISP_RUN_MODE_SDV:
725 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
726 pipe_id == IA_CSS_PIPE_ID_VIDEO)
735 static int __create_pipe(struct atomisp_sub_device *asd,
736 struct atomisp_stream_env *stream_env,
737 enum ia_css_pipe_id pipe_id)
739 struct atomisp_device *isp = asd->isp;
740 struct ia_css_pipe_extra_config extra_config;
743 if (pipe_id >= IA_CSS_PIPE_ID_NUM)
746 if (pipe_id != IA_CSS_PIPE_ID_ACC &&
747 !stream_env->pipe_configs[pipe_id].output_info[0].res.width)
750 if (pipe_id == IA_CSS_PIPE_ID_ACC &&
751 !stream_env->pipe_configs[pipe_id].acc_extension)
754 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
757 ia_css_pipe_extra_config_defaults(&extra_config);
759 __apply_additional_pipe_config(asd, stream_env, pipe_id);
760 if (!memcmp(&extra_config,
761 &stream_env->pipe_extra_configs[pipe_id],
762 sizeof(extra_config)))
763 ret = ia_css_pipe_create(
764 &stream_env->pipe_configs[pipe_id],
765 &stream_env->pipes[pipe_id]);
767 ret = ia_css_pipe_create_extra(
768 &stream_env->pipe_configs[pipe_id],
769 &stream_env->pipe_extra_configs[pipe_id],
770 &stream_env->pipes[pipe_id]);
772 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
776 static int __create_pipes(struct atomisp_sub_device *asd)
781 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
782 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
783 ret = __create_pipe(asd, &asd->stream_env[i], j);
787 if (j < IA_CSS_PIPE_ID_NUM)
792 for (; i >= 0; i--) {
793 for (j--; j >= 0; j--) {
794 if (asd->stream_env[i].pipes[j]) {
795 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
796 asd->stream_env[i].pipes[j] = NULL;
799 j = IA_CSS_PIPE_ID_NUM;
804 void atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
807 __create_streams(asd);
810 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
813 struct atomisp_device *isp = asd->isp;
815 if (__destroy_streams(asd, true))
816 dev_warn(isp->dev, "destroy stream failed.\n");
818 if (__destroy_pipes(asd, true))
819 dev_warn(isp->dev, "destroy pipe failed.\n");
821 ret = __create_pipes(asd);
823 dev_err(isp->dev, "create pipe failed %d.\n", ret);
827 ret = __create_streams(asd);
829 dev_warn(isp->dev, "create stream failed %d.\n", ret);
830 __destroy_pipes(asd, true);
837 int atomisp_css_init(struct atomisp_device *isp)
839 unsigned int mmu_base_addr;
843 ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
848 err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
849 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
851 dev_err(isp->dev, "css init failed --- bad firmware?\n");
854 ia_css_enable_isys_event_queue(true);
856 isp->css_initialized = true;
857 dev_dbg(isp->dev, "sh_css_init success\n");
862 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
867 isp->css_env.isp_css_env.print_env.debug_print = NULL;
869 isp->css_env.isp_css_env.print_env.debug_print =
870 atomisp_css2_dbg_ftrace_print;
872 isp->css_env.isp_css_env.print_env.debug_print =
873 atomisp_css2_dbg_print;
880 int atomisp_css_load_firmware(struct atomisp_device *isp)
885 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
886 isp->css_env.isp_css_fw.bytes = isp->firmware->size;
888 isp->css_env.isp_css_env.hw_access_env.store_8 =
889 atomisp_css2_hw_store_8;
890 isp->css_env.isp_css_env.hw_access_env.store_16 =
891 atomisp_css2_hw_store_16;
892 isp->css_env.isp_css_env.hw_access_env.store_32 =
893 atomisp_css2_hw_store_32;
895 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
896 isp->css_env.isp_css_env.hw_access_env.load_16 =
897 atomisp_css2_hw_load_16;
898 isp->css_env.isp_css_env.hw_access_env.load_32 =
899 atomisp_css2_hw_load_32;
901 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
902 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
904 __set_css_print_env(isp, dbg_func);
906 isp->css_env.isp_css_env.print_env.error_print = atomisp_css2_err_print;
908 /* load isp fw into ISP memory */
909 err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env,
910 &isp->css_env.isp_css_fw);
912 dev_err(isp->dev, "css load fw failed.\n");
919 void atomisp_css_uninit(struct atomisp_device *isp)
921 struct atomisp_sub_device *asd;
924 for (i = 0; i < isp->num_of_streams; i++) {
926 memset(&asd->params.config, 0, sizeof(asd->params.config));
927 asd->params.css_update_params_needed = false;
930 isp->css_initialized = false;
934 void atomisp_css_suspend(struct atomisp_device *isp)
936 isp->css_initialized = false;
940 int atomisp_css_resume(struct atomisp_device *isp)
942 unsigned int mmu_base_addr;
945 ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
947 dev_err(isp->dev, "get base address error.\n");
951 ret = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
952 mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
954 dev_err(isp->dev, "re-init css failed.\n");
957 ia_css_enable_isys_event_queue(true);
959 isp->css_initialized = true;
963 int atomisp_css_irq_translate(struct atomisp_device *isp,
968 err = ia_css_irq_translate(infos);
971 "%s:failed to translate irq (err = %d,infos = %d)\n",
972 __func__, err, *infos);
979 void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
982 #ifndef ISP2401_NEW_INPUT_SYSTEM
983 ia_css_isys_rx_get_irq_info(port, infos);
989 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
992 #ifndef ISP2401_NEW_INPUT_SYSTEM
993 ia_css_isys_rx_clear_irq_info(port, infos);
997 int atomisp_css_irq_enable(struct atomisp_device *isp,
998 enum ia_css_irq_info info, bool enable)
1000 dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s (%d).\n",
1002 enable ? "enable" : "disable", enable);
1003 if (ia_css_irq_enable(info, enable)) {
1004 dev_warn(isp->dev, "%s:Invalid irq info: 0x%08x when %s.\n",
1006 enable ? "enabling" : "disabling");
1013 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
1017 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1018 asd->stream_env[i].stream = NULL;
1019 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
1020 asd->stream_env[i].pipes[j] = NULL;
1021 asd->stream_env[i].update_pipe[j] = false;
1022 ia_css_pipe_config_defaults(
1023 &asd->stream_env[i].pipe_configs[j]);
1024 ia_css_pipe_extra_config_defaults(
1025 &asd->stream_env[i].pipe_extra_configs[j]);
1027 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
1031 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
1032 struct videobuf_vmalloc_memory *vm_mem,
1033 enum atomisp_input_stream_id stream_id,
1034 enum ia_css_buffer_type css_buf_type,
1035 enum ia_css_pipe_id css_pipe_id)
1037 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1038 struct ia_css_buffer css_buf = {0};
1041 css_buf.type = css_buf_type;
1042 css_buf.data.frame = vm_mem->vaddr;
1044 err = ia_css_pipe_enqueue_buffer(
1045 stream_env->pipes[css_pipe_id], &css_buf);
1052 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
1053 struct atomisp_metadata_buf *metadata_buf,
1054 enum atomisp_input_stream_id stream_id,
1055 enum ia_css_pipe_id css_pipe_id)
1057 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1058 struct ia_css_buffer buffer = {0};
1059 struct atomisp_device *isp = asd->isp;
1061 buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
1062 buffer.data.metadata = metadata_buf->metadata;
1063 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
1065 dev_err(isp->dev, "failed to q meta data buffer\n");
1072 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
1073 struct atomisp_s3a_buf *s3a_buf,
1074 enum atomisp_input_stream_id stream_id,
1075 enum ia_css_pipe_id css_pipe_id)
1077 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1078 struct ia_css_buffer buffer = {0};
1079 struct atomisp_device *isp = asd->isp;
1081 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
1082 buffer.data.stats_3a = s3a_buf->s3a_data;
1083 if (ia_css_pipe_enqueue_buffer(
1084 stream_env->pipes[css_pipe_id],
1086 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
1093 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
1094 struct atomisp_dis_buf *dis_buf,
1095 enum atomisp_input_stream_id stream_id,
1096 enum ia_css_pipe_id css_pipe_id)
1098 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1099 struct ia_css_buffer buffer = {0};
1100 struct atomisp_device *isp = asd->isp;
1102 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
1103 buffer.data.stats_dvs = dis_buf->dis_data;
1104 if (ia_css_pipe_enqueue_buffer(
1105 stream_env->pipes[css_pipe_id],
1107 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
1114 int atomisp_css_start(struct atomisp_sub_device *asd,
1115 enum ia_css_pipe_id pipe_id, bool in_reset)
1117 struct atomisp_device *isp = asd->isp;
1118 bool sp_is_started = false;
1122 if (__destroy_streams(asd, true))
1123 dev_warn(isp->dev, "destroy stream failed.\n");
1125 if (__destroy_pipes(asd, true))
1126 dev_warn(isp->dev, "destroy pipe failed.\n");
1128 if (__create_pipes(asd)) {
1129 dev_err(isp->dev, "create pipe error.\n");
1132 if (__create_streams(asd)) {
1133 dev_err(isp->dev, "create stream error.\n");
1137 /* in_reset == true, extension firmwares are reloaded after the recovery */
1138 atomisp_acc_load_extensions(asd);
1142 * For dual steam case, it is possible that:
1143 * 1: for this stream, it is at the stage that:
1144 * - after set_fmt is called
1145 * - before stream on is called
1146 * 2: for the other stream, the stream off is called which css reset
1149 * Thus the stream created in set_fmt get destroyed and need to be
1150 * recreated in the next stream on.
1152 if (asd->stream_prepared == false) {
1153 if (__create_pipes(asd)) {
1154 dev_err(isp->dev, "create pipe error.\n");
1157 if (__create_streams(asd)) {
1158 dev_err(isp->dev, "create stream error.\n");
1164 * SP can only be started one time
1165 * if atomisp_subdev_streaming_count() tell there already has some
1166 * subdev at streamming, then SP should already be started previously,
1167 * so need to skip start sp procedure
1169 if (atomisp_streaming_count(isp)) {
1170 dev_dbg(isp->dev, "skip start sp\n");
1172 if (!sh_css_hrt_system_is_idle())
1173 dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1174 if (ia_css_start_sp()) {
1175 dev_err(isp->dev, "start sp error.\n");
1179 sp_is_started = true;
1183 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1184 if (asd->stream_env[i].stream) {
1185 if (ia_css_stream_start(asd->stream_env[i]
1187 dev_err(isp->dev, "stream[%d] start error.\n", i);
1191 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1192 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1200 __destroy_streams(asd, true);
1202 __destroy_pipes(asd, true);
1204 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1208 * SP can not be stop if other streams are in use
1210 if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1216 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1220 * for ISP2401 new input system, this api is under development.
1221 * Calling it would cause kernel panic.
1225 * Check if it is Cherry Trail and also new input system
1227 if (asd->copy_mode) {
1228 dev_warn(asd->isp->dev,
1229 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1234 ia_css_stream_set_isp_config(
1235 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1236 &asd->params.config);
1237 memset(&asd->params.config, 0, sizeof(asd->params.config));
1240 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1241 struct ia_css_pipe *pipe)
1246 atomisp_css_update_isp_params(asd);
1250 dev_dbg(asd->isp->dev,
1251 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1252 __func__, asd->params.config.output_frame,
1253 asd->params.config.isp_config_id, pipe);
1255 ret = ia_css_stream_set_isp_config_on_pipe(
1256 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1257 &asd->params.config, pipe);
1259 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1261 memset(&asd->params.config, 0, sizeof(asd->params.config));
1264 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1265 enum atomisp_input_stream_id stream_id,
1266 enum ia_css_pipe_id pipe_id,
1267 enum ia_css_buffer_type buf_type,
1268 struct atomisp_css_buffer *isp_css_buffer)
1270 if (ia_css_pipe_enqueue_buffer(
1271 asd->stream_env[stream_id].pipes[pipe_id],
1272 &isp_css_buffer->css_buffer)
1279 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1280 enum atomisp_input_stream_id stream_id,
1281 enum ia_css_pipe_id pipe_id,
1282 enum ia_css_buffer_type buf_type,
1283 struct atomisp_css_buffer *isp_css_buffer)
1285 struct atomisp_device *isp = asd->isp;
1288 err = ia_css_pipe_dequeue_buffer(
1289 asd->stream_env[stream_id].pipes[pipe_id],
1290 &isp_css_buffer->css_buffer);
1293 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1300 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd,
1302 struct atomisp_s3a_buf *s3a_buf,
1303 struct atomisp_dis_buf *dis_buf,
1304 struct atomisp_metadata_buf *md_buf)
1306 struct atomisp_device *isp = asd->isp;
1307 struct ia_css_dvs_grid_info *dvs_grid_info =
1308 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1310 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1313 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1314 &asd->params.curr_grid_info.s3a_grid);
1315 if (!s3a_buf->s3a_data) {
1316 dev_err(isp->dev, "3a buf allocation failed.\n");
1320 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1321 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1322 s3a_buf->s3a_data, s3a_ptr);
1325 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1328 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1330 if (!dis_buf->dis_data) {
1331 dev_err(isp->dev, "dvs buf allocation failed.\n");
1333 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1337 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1338 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1339 dis_buf->dis_data, dvs_ptr);
1342 if (asd->stream_env[stream_id].stream_info.
1343 metadata_info.size && md_buf) {
1344 md_buf->metadata = ia_css_metadata_allocate(
1345 &asd->stream_env[stream_id].stream_info.metadata_info);
1346 if (!md_buf->metadata) {
1348 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1350 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1351 dev_err(isp->dev, "metadata buf allocation failed.\n");
1354 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1360 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1362 if (s3a_buf->s3a_data)
1363 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1365 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1366 s3a_buf->s3a_map = NULL;
1367 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1370 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1372 if (dis_buf->dis_data)
1373 hmm_vunmap(dis_buf->dis_data->data_ptr);
1375 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1376 dis_buf->dvs_map = NULL;
1377 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1380 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1382 if (metadata_buf->md_vptr) {
1383 hmm_vunmap(metadata_buf->metadata->address);
1384 metadata_buf->md_vptr = NULL;
1386 ia_css_metadata_free(metadata_buf->metadata);
1389 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1391 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1392 struct atomisp_dis_buf *dis_buf, *_dis_buf;
1393 struct atomisp_metadata_buf *md_buf, *_md_buf;
1394 struct ia_css_dvs_grid_info *dvs_grid_info =
1395 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1398 /* 3A statistics use vmalloc, DIS use kmalloc */
1399 if (dvs_grid_info && dvs_grid_info->enable) {
1400 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1401 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1402 asd->params.css_param.dvs2_coeff = NULL;
1403 asd->params.dvs_stat = NULL;
1404 asd->params.dvs_hor_proj_bytes = 0;
1405 asd->params.dvs_ver_proj_bytes = 0;
1406 asd->params.dvs_hor_coef_bytes = 0;
1407 asd->params.dvs_ver_coef_bytes = 0;
1408 asd->params.dis_proj_data_valid = false;
1409 list_for_each_entry_safe(dis_buf, _dis_buf,
1410 &asd->dis_stats, list) {
1411 atomisp_css_free_dis_buffer(dis_buf);
1412 list_del(&dis_buf->list);
1415 list_for_each_entry_safe(dis_buf, _dis_buf,
1416 &asd->dis_stats_in_css, list) {
1417 atomisp_css_free_dis_buffer(dis_buf);
1418 list_del(&dis_buf->list);
1422 if (asd->params.curr_grid_info.s3a_grid.enable) {
1423 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1424 asd->params.s3a_user_stat = NULL;
1425 asd->params.s3a_output_bytes = 0;
1426 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1427 &asd->s3a_stats, list) {
1428 atomisp_css_free_3a_buffer(s3a_buf);
1429 list_del(&s3a_buf->list);
1432 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1433 &asd->s3a_stats_in_css, list) {
1434 atomisp_css_free_3a_buffer(s3a_buf);
1435 list_del(&s3a_buf->list);
1438 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1439 &asd->s3a_stats_ready, list) {
1440 atomisp_css_free_3a_buffer(s3a_buf);
1441 list_del(&s3a_buf->list);
1446 if (asd->params.css_param.dvs_6axis) {
1447 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1448 asd->params.css_param.dvs_6axis = NULL;
1451 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1452 list_for_each_entry_safe(md_buf, _md_buf,
1453 &asd->metadata[i], list) {
1454 atomisp_css_free_metadata_buffer(md_buf);
1455 list_del(&md_buf->list);
1458 list_for_each_entry_safe(md_buf, _md_buf,
1459 &asd->metadata_in_css[i], list) {
1460 atomisp_css_free_metadata_buffer(md_buf);
1461 list_del(&md_buf->list);
1464 list_for_each_entry_safe(md_buf, _md_buf,
1465 &asd->metadata_ready[i], list) {
1466 atomisp_css_free_metadata_buffer(md_buf);
1467 list_del(&md_buf->list);
1471 asd->params.metadata_width_size = 0;
1472 atomisp_free_metadata_output_buf(asd);
1475 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1476 enum ia_css_pipe_id pipe_id,
1479 struct ia_css_pipe_info p_info;
1480 struct ia_css_grid_info old_info;
1481 struct atomisp_device *isp = asd->isp;
1482 int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
1483 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1484 stream_config.metadata_config.resolution.width;
1486 memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1487 memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1489 if (ia_css_pipe_get_info(
1490 asd->stream_env[stream_index].pipes[pipe_id],
1492 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1496 memcpy(&old_info, &asd->params.curr_grid_info,
1497 sizeof(struct ia_css_grid_info));
1498 memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1499 sizeof(struct ia_css_grid_info));
1501 * Record which css pipe enables s3a_grid.
1502 * Currently would have one css pipe that need it
1504 if (asd->params.curr_grid_info.s3a_grid.enable) {
1505 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM)
1506 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1507 asd->params.s3a_enabled_pipe, pipe_id);
1508 asd->params.s3a_enabled_pipe = pipe_id;
1511 /* If the grid info has not changed and the buffers for 3A and
1512 * DIS statistics buffers are allocated or buffer size would be zero
1513 * then no need to do anything. */
1514 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1515 && asd->params.s3a_user_stat && asd->params.dvs_stat)
1516 || asd->params.curr_grid_info.s3a_grid.width == 0
1517 || asd->params.curr_grid_info.s3a_grid.height == 0)
1518 && asd->params.metadata_width_size == md_width) {
1520 "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1521 !memcmp(&old_info, &asd->params.curr_grid_info,
1523 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1524 asd->params.curr_grid_info.s3a_grid.width,
1525 asd->params.curr_grid_info.s3a_grid.height,
1526 asd->params.metadata_width_size);
1529 asd->params.metadata_width_size = md_width;
1534 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1536 if (!asd->params.curr_grid_info.s3a_grid.width ||
1537 !asd->params.curr_grid_info.s3a_grid.height)
1540 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1541 &asd->params.curr_grid_info.s3a_grid);
1542 if (!asd->params.s3a_user_stat)
1544 /* 3A statistics. These can be big, so we use vmalloc. */
1545 asd->params.s3a_output_bytes =
1546 asd->params.curr_grid_info.s3a_grid.width *
1547 asd->params.curr_grid_info.s3a_grid.height *
1548 sizeof(*asd->params.s3a_user_stat->data);
1553 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1555 struct ia_css_dvs_grid_info *dvs_grid =
1556 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1561 if (!dvs_grid->enable) {
1562 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1566 /* DIS coefficients. */
1567 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1569 if (!asd->params.css_param.dvs2_coeff)
1572 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1573 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1575 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1576 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1578 /* DIS projections. */
1579 asd->params.dis_proj_data_valid = false;
1580 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1581 if (!asd->params.dvs_stat)
1584 asd->params.dvs_hor_proj_bytes =
1585 dvs_grid->aligned_height * dvs_grid->aligned_width *
1586 sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1588 asd->params.dvs_ver_proj_bytes =
1589 dvs_grid->aligned_height * dvs_grid->aligned_width *
1590 sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1595 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1599 /* We allocate the cpu-side buffer used for communication with user
1601 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1602 asd->params.metadata_user[i] = kvmalloc(
1603 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1604 stream_info.metadata_info.size, GFP_KERNEL);
1605 if (!asd->params.metadata_user[i]) {
1607 kvfree(asd->params.metadata_user[i]);
1608 asd->params.metadata_user[i] = NULL;
1617 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1621 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1622 if (asd->params.metadata_user[i]) {
1623 kvfree(asd->params.metadata_user[i]);
1624 asd->params.metadata_user[i] = NULL;
1629 void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd,
1630 struct atomisp_css_buffer *isp_css_buffer,
1631 struct ia_css_isp_dvs_statistics_map *dvs_map)
1633 if (asd->params.dvs_stat) {
1635 ia_css_translate_dvs2_statistics(
1636 asd->params.dvs_stat, dvs_map);
1638 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
1639 isp_css_buffer->css_buffer.data.stats_dvs);
1643 int atomisp_css_dequeue_event(struct atomisp_css_event *current_event)
1645 if (ia_css_dequeue_event(¤t_event->event))
1651 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1652 struct atomisp_css_event *current_event)
1656 * Pipe ID reported in CSS event is not correct for new system's
1660 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1661 ¤t_event->pipe);
1662 if (asd && asd->copy_mode &&
1663 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1664 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1667 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1668 enum atomisp_input_stream_id stream_id,
1669 struct v4l2_mbus_framefmt *ffmt,
1672 struct ia_css_stream_config *s_config =
1673 &asd->stream_env[stream_id].stream_config;
1675 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1678 s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1679 s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1683 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1684 enum atomisp_input_stream_id stream_id,
1685 struct v4l2_mbus_framefmt *ffmt)
1687 struct ia_css_stream_config *s_config =
1688 &asd->stream_env[stream_id].stream_config;
1690 s_config->input_config.input_res.width = ffmt->width;
1691 s_config->input_config.input_res.height = ffmt->height;
1695 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1696 enum atomisp_input_stream_id stream_id,
1697 unsigned int bin_factor)
1699 asd->stream_env[stream_id]
1700 .stream_config.sensor_binning_factor = bin_factor;
1703 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1704 enum atomisp_input_stream_id stream_id,
1705 enum ia_css_bayer_order bayer_order)
1707 struct ia_css_stream_config *s_config =
1708 &asd->stream_env[stream_id].stream_config;
1709 s_config->input_config.bayer_order = bayer_order;
1712 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1713 enum atomisp_input_stream_id stream_id,
1717 struct ia_css_stream_config *s_config =
1718 &asd->stream_env[stream_id].stream_config;
1720 s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1723 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1724 enum atomisp_input_stream_id stream_id,
1728 struct ia_css_stream_config *s_config =
1729 &asd->stream_env[stream_id].stream_config;
1731 s_config->isys_config[isys_stream].valid = valid;
1734 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1735 enum atomisp_input_stream_id stream_id,
1736 enum atomisp_input_format format,
1739 struct ia_css_stream_config *s_config =
1740 &asd->stream_env[stream_id].stream_config;
1742 s_config->isys_config[isys_stream].format = format;
1745 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1746 enum atomisp_input_stream_id stream_id,
1747 enum atomisp_input_format format)
1749 struct ia_css_stream_config *s_config =
1750 &asd->stream_env[stream_id].stream_config;
1752 s_config->input_config.format = format;
1755 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1756 enum atomisp_input_stream_id stream_id,
1757 struct v4l2_mbus_framefmt *ffmt)
1760 struct ia_css_stream_config *s_config =
1761 &asd->stream_env[stream_id].stream_config;
1763 * Set all isys configs to not valid.
1764 * Currently we support only one stream per channel
1766 for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1767 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1768 s_config->isys_config[i].valid = false;
1770 atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1771 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1772 atomisp_css_isys_set_format(asd, stream_id,
1773 s_config->input_config.format,
1774 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1775 atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1776 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1777 atomisp_css_isys_set_valid(asd, stream_id, true,
1778 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1783 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1784 enum atomisp_input_stream_id stream_id,
1785 enum atomisp_input_format input_format)
1787 struct ia_css_stream_config *s_config =
1788 &asd->stream_env[stream_id].stream_config;
1790 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1791 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1793 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1794 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1796 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1797 = IA_CSS_STREAM_ISYS_STREAM_0;
1798 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1799 ATOMISP_INPUT_FORMAT_USER_DEF1;
1800 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1801 ATOMISP_INPUT_FORMAT_USER_DEF2;
1802 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1806 void atomisp_css_isys_two_stream_cfg_update_stream1(
1807 struct atomisp_sub_device *asd,
1808 enum atomisp_input_stream_id stream_id,
1809 enum atomisp_input_format input_format,
1810 unsigned int width, unsigned int height)
1812 struct ia_css_stream_config *s_config =
1813 &asd->stream_env[stream_id].stream_config;
1815 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1817 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1819 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1821 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1824 void atomisp_css_isys_two_stream_cfg_update_stream2(
1825 struct atomisp_sub_device *asd,
1826 enum atomisp_input_stream_id stream_id,
1827 enum atomisp_input_format input_format,
1828 unsigned int width, unsigned int height)
1830 struct ia_css_stream_config *s_config =
1831 &asd->stream_env[stream_id].stream_config;
1833 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1835 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1837 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1838 = IA_CSS_STREAM_ISYS_STREAM_0;
1839 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1841 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1844 int atomisp_css_input_set_effective_resolution(
1845 struct atomisp_sub_device *asd,
1846 enum atomisp_input_stream_id stream_id,
1847 unsigned int width, unsigned int height)
1849 struct ia_css_stream_config *s_config =
1850 &asd->stream_env[stream_id].stream_config;
1851 s_config->input_config.effective_res.width = width;
1852 s_config->input_config.effective_res.height = height;
1856 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1857 unsigned int dvs_w, unsigned int dvs_h)
1859 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1860 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1861 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1862 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1865 void atomisp_css_input_set_two_pixels_per_clock(
1866 struct atomisp_sub_device *asd,
1871 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1872 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1875 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1876 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1877 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1878 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1879 .update_pipe[i] = true;
1882 void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
1885 struct atomisp_stream_env *stream_env =
1886 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1889 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
1890 pipe = IA_CSS_PIPE_ID_VIDEO;
1892 pipe = IA_CSS_PIPE_ID_PREVIEW;
1894 stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable;
1895 stream_env->update_pipe[pipe] = true;
1897 stream_env->pipe_configs[pipe].output_info[0].padded_width =
1898 stream_env->stream_config.input_config.effective_res.width;
1901 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1905 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1906 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1907 .pipe_configs[i].enable_dz = enable;
1910 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1911 enum ia_css_capture_mode mode)
1913 struct atomisp_stream_env *stream_env =
1914 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1916 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1917 .default_capture_config.mode == mode)
1920 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1921 default_capture_config.mode = mode;
1922 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1925 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
1926 enum ia_css_input_mode mode)
1929 struct atomisp_device *isp = asd->isp;
1930 unsigned int size_mem_words;
1932 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
1933 asd->stream_env[i].stream_config.mode = mode;
1935 if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
1936 struct ia_css_stream_config *s_config =
1937 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
1938 s_config->mode = IA_CSS_INPUT_MODE_TPG;
1939 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
1940 s_config->source.tpg.x_mask = (1 << 4) - 1;
1941 s_config->source.tpg.x_delta = -2;
1942 s_config->source.tpg.y_mask = (1 << 4) - 1;
1943 s_config->source.tpg.y_delta = 3;
1944 s_config->source.tpg.xy_mask = (1 << 8) - 1;
1948 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1951 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1953 * TODO: sensor needs to export the embedded_data_size_words
1954 * information to atomisp for each setting.
1955 * Here using a large safe value.
1957 struct ia_css_stream_config *s_config =
1958 &asd->stream_env[i].stream_config;
1960 if (s_config->input_config.input_res.width == 0)
1963 if (ia_css_mipi_frame_calculate_size(
1964 s_config->input_config.input_res.width,
1965 s_config->input_config.input_res.height,
1966 s_config->input_config.format,
1969 &size_mem_words) != 0) {
1971 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
1973 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
1974 dev_warn(asd->isp->dev,
1975 "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n",
1978 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
1979 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
1983 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
1984 unsigned short stream_index, bool enable)
1986 struct atomisp_stream_env *stream_env =
1987 &asd->stream_env[stream_index];
1989 if (stream_env->stream_config.online == !!enable)
1992 stream_env->stream_config.online = !!enable;
1993 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1996 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
1997 unsigned short stream_index, bool enable)
1999 struct atomisp_stream_env *stream_env =
2000 &asd->stream_env[stream_index];
2003 if (stream_env->stream_config.online != !!enable) {
2004 stream_env->stream_config.online = !!enable;
2005 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2006 stream_env->update_pipe[i] = true;
2010 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
2013 struct atomisp_stream_env *stream_env =
2014 &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
2017 if (stream_env->stream_config.online != enable) {
2018 stream_env->stream_config.online = enable;
2019 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2020 stream_env->update_pipe[i] = true;
2024 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
2027 struct atomisp_stream_env *stream_env =
2028 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2032 * To SOC camera, there is only one YUVPP pipe in any case
2033 * including ZSL/SDV/continuous viewfinder, so always set
2034 * stream_config.continuous to 0.
2036 if (ATOMISP_USE_YUVPP(asd)) {
2037 stream_env->stream_config.continuous = 0;
2038 stream_env->stream_config.online = 1;
2042 if (stream_env->stream_config.continuous != !!enable) {
2043 stream_env->stream_config.continuous = !!enable;
2044 stream_env->stream_config.pack_raw_pixels = true;
2045 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2046 stream_env->update_pipe[i] = true;
2050 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
2053 struct atomisp_stream_env *stream_env =
2054 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2057 if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
2058 stream_env->stream_config.disable_cont_viewfinder = !enable;
2059 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2060 stream_env->update_pipe[i] = true;
2064 int atomisp_css_input_configure_port(
2065 struct atomisp_sub_device *asd,
2066 enum mipi_port_id port,
2067 unsigned int num_lanes,
2068 unsigned int timeout,
2069 unsigned int mipi_freq,
2070 enum atomisp_input_format metadata_format,
2071 unsigned int metadata_width,
2072 unsigned int metadata_height)
2075 struct atomisp_stream_env *stream_env;
2077 * Calculate rx_count as follows:
2078 * Input: mipi_freq : CSI-2 bus frequency in Hz
2079 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus
2080 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds
2081 * max = 145e-9 + 10 * UI
2082 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
2083 * rxcount = rxcount0 - 2 : adjust for better results
2084 * The formula below is simplified version of the above with
2085 * 10-bit fixed points for improved accuracy.
2087 const unsigned int rxcount =
2088 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
2090 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2091 stream_env = &asd->stream_env[i];
2092 stream_env->stream_config.source.port.port = port;
2093 stream_env->stream_config.source.port.num_lanes = num_lanes;
2094 stream_env->stream_config.source.port.timeout = timeout;
2096 stream_env->stream_config.source.port.rxcount = rxcount;
2097 stream_env->stream_config.
2098 metadata_config.data_type = metadata_format;
2099 stream_env->stream_config.
2100 metadata_config.resolution.width = metadata_width;
2101 stream_env->stream_config.
2102 metadata_config.resolution.height = metadata_height;
2108 int atomisp_css_stop(struct atomisp_sub_device *asd,
2109 enum ia_css_pipe_id pipe_id, bool in_reset)
2111 struct atomisp_device *isp = asd->isp;
2112 struct atomisp_s3a_buf *s3a_buf;
2113 struct atomisp_dis_buf *dis_buf;
2114 struct atomisp_metadata_buf *md_buf;
2115 unsigned long irqflags;
2118 /* if is called in atomisp_reset(), force destroy stream */
2119 if (__destroy_streams(asd, true))
2120 dev_err(isp->dev, "destroy stream failed.\n");
2122 /* if is called in atomisp_reset(), force destroy all pipes */
2123 if (__destroy_pipes(asd, true))
2124 dev_err(isp->dev, "destroy pipes failed.\n");
2126 atomisp_init_raw_buffer_bitmap(asd);
2129 * SP can not be stop if other streams are in use
2131 if (atomisp_streaming_count(isp) == 0)
2135 struct atomisp_stream_env *stream_env;
2138 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2139 stream_env = &asd->stream_env[i];
2140 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
2141 ia_css_pipe_config_defaults(
2142 &stream_env->pipe_configs[j]);
2143 ia_css_pipe_extra_config_defaults(
2144 &stream_env->pipe_extra_configs[j]);
2146 ia_css_stream_config_defaults(
2147 &stream_env->stream_config);
2149 memset(&asd->params.config, 0, sizeof(asd->params.config));
2150 asd->params.css_update_params_needed = false;
2153 /* move stats buffers to free queue list */
2154 while (!list_empty(&asd->s3a_stats_in_css)) {
2155 s3a_buf = list_entry(asd->s3a_stats_in_css.next,
2156 struct atomisp_s3a_buf, list);
2157 list_del(&s3a_buf->list);
2158 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2160 while (!list_empty(&asd->s3a_stats_ready)) {
2161 s3a_buf = list_entry(asd->s3a_stats_ready.next,
2162 struct atomisp_s3a_buf, list);
2163 list_del(&s3a_buf->list);
2164 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2167 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
2168 while (!list_empty(&asd->dis_stats_in_css)) {
2169 dis_buf = list_entry(asd->dis_stats_in_css.next,
2170 struct atomisp_dis_buf, list);
2171 list_del(&dis_buf->list);
2172 list_add_tail(&dis_buf->list, &asd->dis_stats);
2174 asd->params.dis_proj_data_valid = false;
2175 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
2177 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
2178 while (!list_empty(&asd->metadata_in_css[i])) {
2179 md_buf = list_entry(asd->metadata_in_css[i].next,
2180 struct atomisp_metadata_buf, list);
2181 list_del(&md_buf->list);
2182 list_add_tail(&md_buf->list, &asd->metadata[i]);
2184 while (!list_empty(&asd->metadata_ready[i])) {
2185 md_buf = list_entry(asd->metadata_ready[i].next,
2186 struct atomisp_metadata_buf, list);
2187 list_del(&md_buf->list);
2188 list_add_tail(&md_buf->list, &asd->metadata[i]);
2192 atomisp_flush_params_queue(&asd->video_out_capture);
2193 atomisp_flush_params_queue(&asd->video_out_vf);
2194 atomisp_flush_params_queue(&asd->video_out_preview);
2195 atomisp_flush_params_queue(&asd->video_out_video_capture);
2196 atomisp_free_css_parameters(&asd->params.css_param);
2197 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
2201 int atomisp_css_continuous_set_num_raw_frames(
2202 struct atomisp_sub_device *asd,
2205 if (asd->enable_raw_buffer_lock->val) {
2206 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2207 .stream_config.init_num_cont_raw_buf =
2208 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
2209 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2210 asd->params.video_dis_en)
2211 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2212 .stream_config.init_num_cont_raw_buf +=
2213 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2215 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2216 .stream_config.init_num_cont_raw_buf =
2217 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
2220 if (asd->params.video_dis_en)
2221 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2222 .stream_config.init_num_cont_raw_buf +=
2223 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2225 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2226 .stream_config.target_num_cont_raw_buf = num_frames;
2230 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2231 struct atomisp_sub_device *asd,
2232 enum ia_css_pipe_id pipe_id)
2234 struct atomisp_device *isp = asd->isp;
2235 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2236 isp->inputs[asd->input_curr].camera);
2239 case IA_CSS_PIPE_ID_COPY:
2240 /* Currently only YUVPP mode supports YUV420_Legacy format.
2241 * Revert this when other pipe modes can support
2242 * YUV420_Legacy format.
2244 if (mipi_info && mipi_info->input_format ==
2245 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2246 return IA_CSS_PIPE_MODE_YUVPP;
2247 return IA_CSS_PIPE_MODE_COPY;
2248 case IA_CSS_PIPE_ID_PREVIEW:
2249 return IA_CSS_PIPE_MODE_PREVIEW;
2250 case IA_CSS_PIPE_ID_CAPTURE:
2251 return IA_CSS_PIPE_MODE_CAPTURE;
2252 case IA_CSS_PIPE_ID_VIDEO:
2253 return IA_CSS_PIPE_MODE_VIDEO;
2254 case IA_CSS_PIPE_ID_ACC:
2255 return IA_CSS_PIPE_MODE_ACC;
2256 case IA_CSS_PIPE_ID_YUVPP:
2257 return IA_CSS_PIPE_MODE_YUVPP;
2260 return IA_CSS_PIPE_MODE_PREVIEW;
2264 static void __configure_output(struct atomisp_sub_device *asd,
2265 unsigned int stream_index,
2266 unsigned int width, unsigned int height,
2267 unsigned int min_width,
2268 enum ia_css_frame_format format,
2269 enum ia_css_pipe_id pipe_id)
2271 struct atomisp_device *isp = asd->isp;
2272 struct atomisp_stream_env *stream_env =
2273 &asd->stream_env[stream_index];
2274 struct ia_css_stream_config *s_config = &stream_env->stream_config;
2276 stream_env->pipe_configs[pipe_id].mode =
2277 __pipe_id_to_pipe_mode(asd, pipe_id);
2278 stream_env->update_pipe[pipe_id] = true;
2280 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2281 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2282 stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2283 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2285 /* isp binary 2.2 specific setting*/
2286 if (width > s_config->input_config.effective_res.width ||
2287 height > s_config->input_config.effective_res.height) {
2288 s_config->input_config.effective_res.width = width;
2289 s_config->input_config.effective_res.height = height;
2292 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2293 pipe_id, width, height, format);
2296 static void __configure_video_preview_output(struct atomisp_sub_device *asd,
2297 unsigned int stream_index,
2298 unsigned int width, unsigned int height,
2299 unsigned int min_width,
2300 enum ia_css_frame_format format,
2301 enum ia_css_pipe_id pipe_id)
2303 struct atomisp_device *isp = asd->isp;
2304 struct atomisp_stream_env *stream_env =
2305 &asd->stream_env[stream_index];
2306 struct ia_css_frame_info *css_output_info;
2307 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2309 stream_env->pipe_configs[pipe_id].mode =
2310 __pipe_id_to_pipe_mode(asd, pipe_id);
2311 stream_env->update_pipe[pipe_id] = true;
2314 * second_output will be as video main output in SDV mode
2315 * with SOC camera. output will be as video main output in
2316 * normal video mode.
2318 if (asd->continuous_mode->val)
2319 css_output_info = &stream_env->pipe_configs[pipe_id].
2320 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2322 css_output_info = &stream_env->pipe_configs[pipe_id].
2323 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2325 css_output_info->res.width = width;
2326 css_output_info->res.height = height;
2327 css_output_info->format = format;
2328 css_output_info->padded_width = min_width;
2330 /* isp binary 2.2 specific setting*/
2331 if (width > stream_config->input_config.effective_res.width ||
2332 height > stream_config->input_config.effective_res.height) {
2333 stream_config->input_config.effective_res.width = width;
2334 stream_config->input_config.effective_res.height = height;
2337 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2338 pipe_id, width, height, format);
2342 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2343 * downscaling input resolution.
2345 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2346 unsigned int width, unsigned int height,
2347 enum ia_css_pipe_id pipe_id)
2349 struct atomisp_device *isp = asd->isp;
2350 struct atomisp_stream_env *stream_env =
2351 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2352 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2353 struct ia_css_pipe_config *pipe_configs =
2354 &stream_env->pipe_configs[pipe_id];
2355 struct ia_css_pipe_extra_config *pipe_extra_configs =
2356 &stream_env->pipe_extra_configs[pipe_id];
2357 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2359 if (width == 0 && height == 0)
2362 if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2363 height * 9 / 10 < pipe_configs->output_info[0].res.height)
2365 /* here just copy the calculation in css */
2366 hor_ds_factor = CEIL_DIV(width >> 1,
2367 pipe_configs->output_info[0].res.width);
2368 ver_ds_factor = CEIL_DIV(height >> 1,
2369 pipe_configs->output_info[0].res.height);
2371 if ((asd->isp->media_dev.hw_revision <
2372 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2373 IS_CHT) && hor_ds_factor != ver_ds_factor) {
2374 dev_warn(asd->isp->dev,
2375 "Cropping for capture due to FW limitation");
2379 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2380 stream_env->update_pipe[pipe_id] = true;
2382 pipe_extra_configs->enable_yuv_ds = true;
2384 pipe_configs->capt_pp_in_res.width =
2385 stream_config->input_config.effective_res.width;
2386 pipe_configs->capt_pp_in_res.height =
2387 stream_config->input_config.effective_res.height;
2389 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2390 pipe_id, width, height);
2394 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2395 * yuv downscaling, which needs addtional configurations.
2397 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2398 unsigned int width, unsigned int height,
2399 enum ia_css_pipe_id pipe_id)
2401 struct atomisp_device *isp = asd->isp;
2402 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2403 struct atomisp_stream_env *stream_env =
2404 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2405 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2406 struct ia_css_pipe_config *pipe_configs =
2407 &stream_env->pipe_configs[pipe_id];
2408 struct ia_css_pipe_extra_config *pipe_extra_configs =
2409 &stream_env->pipe_extra_configs[pipe_id];
2410 struct ia_css_resolution *bayer_ds_out_res =
2411 &pipe_configs->bayer_ds_out_res;
2412 struct ia_css_resolution *vf_pp_in_res =
2413 &pipe_configs->vf_pp_in_res;
2414 struct ia_css_resolution *effective_res =
2415 &stream_config->input_config.effective_res;
2417 static const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2419 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2420 * columns to be shaded. Remove this factor to work around the CSS bug.
2421 * const unsigned int yuv_dec_fct[] = {4, 2};
2423 static const unsigned int yuv_dec_fct[] = { 2 };
2426 if (width == 0 && height == 0)
2429 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2430 stream_env->update_pipe[pipe_id] = true;
2432 out_width = pipe_configs->output_info[0].res.width;
2433 out_height = pipe_configs->output_info[0].res.height;
2436 * The ISP could do bayer downscaling, yuv decimation and yuv
2438 * 1: Bayer Downscaling: between effective resolution and
2440 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2441 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2443 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2444 * Rule for YUV Decimation: support factor 2, 4
2445 * Rule for YUV Downscaling: arbitrary value below 2
2447 * General rule of factor distribution among these stages:
2448 * 1: try to do Bayer downscaling first if not in online mode.
2449 * 2: try to do maximum of 2 for YUV downscaling
2450 * 3: the remainling for YUV decimation
2453 * Do not configure bayer_ds_out_res if:
2454 * online == 1 or continuous == 0 or raw_binning = 0
2456 if (stream_config->online || !stream_config->continuous ||
2457 !pipe_extra_configs->enable_raw_binning) {
2458 bayer_ds_out_res->width = 0;
2459 bayer_ds_out_res->height = 0;
2461 bayer_ds_out_res->width = effective_res->width;
2462 bayer_ds_out_res->height = effective_res->height;
2464 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2465 if (effective_res->width >= out_width *
2466 bds_fct[i].numerator / bds_fct[i].denominator &&
2467 effective_res->height >= out_height *
2468 bds_fct[i].numerator / bds_fct[i].denominator) {
2469 bayer_ds_out_res->width =
2470 effective_res->width *
2471 bds_fct[i].denominator /
2472 bds_fct[i].numerator;
2473 bayer_ds_out_res->height =
2474 effective_res->height *
2475 bds_fct[i].denominator /
2476 bds_fct[i].numerator;
2482 * calculate YUV Decimation, YUV downscaling facor:
2483 * YUV Downscaling factor must not exceed 2.
2484 * YUV Decimation factor could be 2, 4.
2486 /* first decide the yuv_ds input resolution */
2487 if (bayer_ds_out_res->width == 0) {
2488 yuv_ds_in_width = effective_res->width;
2489 yuv_ds_in_height = effective_res->height;
2491 yuv_ds_in_width = bayer_ds_out_res->width;
2492 yuv_ds_in_height = bayer_ds_out_res->height;
2495 vf_pp_in_res->width = yuv_ds_in_width;
2496 vf_pp_in_res->height = yuv_ds_in_height;
2498 /* find out the yuv decimation factor */
2499 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2500 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2501 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2502 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2503 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2508 if (vf_pp_in_res->width == out_width &&
2509 vf_pp_in_res->height == out_height) {
2510 pipe_extra_configs->enable_yuv_ds = false;
2511 vf_pp_in_res->width = 0;
2512 vf_pp_in_res->height = 0;
2514 pipe_extra_configs->enable_yuv_ds = true;
2517 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2518 pipe_id, width, height);
2522 * For CSS2.1, offline video pipe could support bayer decimation, and
2523 * yuv downscaling, which needs addtional configurations.
2525 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2526 unsigned int width, unsigned int height,
2527 enum ia_css_pipe_id pipe_id)
2529 struct atomisp_device *isp = asd->isp;
2530 int out_width, out_height;
2531 struct atomisp_stream_env *stream_env =
2532 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2533 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2534 struct ia_css_pipe_config *pipe_configs =
2535 &stream_env->pipe_configs[pipe_id];
2536 struct ia_css_pipe_extra_config *pipe_extra_configs =
2537 &stream_env->pipe_extra_configs[pipe_id];
2538 struct ia_css_resolution *bayer_ds_out_res =
2539 &pipe_configs->bayer_ds_out_res;
2540 struct ia_css_resolution *effective_res =
2541 &stream_config->input_config.effective_res;
2543 static const struct bayer_ds_factor bds_factors[] = {
2544 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
2548 if (width == 0 && height == 0)
2551 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2552 stream_env->update_pipe[pipe_id] = true;
2554 pipe_extra_configs->enable_yuv_ds = false;
2557 * If DVS is enabled, video binary will take care the dvs envelope
2558 * and usually the bayer_ds_out_res should be larger than 120% of
2559 * destination resolution, the extra 20% will be cropped as DVS
2560 * envelope. But, if the bayer_ds_out_res is less than 120% of the
2561 * destination. The ISP can still work, but DVS quality is not good.
2563 /* taking at least 10% as envelope */
2564 if (asd->params.video_dis_en) {
2565 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2566 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2568 out_width = pipe_configs->output_info[0].res.width;
2569 out_height = pipe_configs->output_info[0].res.height;
2573 * calculate bayer decimate factor:
2574 * 1: only 1.5, 2, 4 and 8 get supported
2575 * 2: Do not configure bayer_ds_out_res if:
2576 * online == 1 or continuous == 0 or raw_binning = 0
2578 if (stream_config->online || !stream_config->continuous) {
2579 bayer_ds_out_res->width = 0;
2580 bayer_ds_out_res->height = 0;
2584 pipe_extra_configs->enable_raw_binning = true;
2585 bayer_ds_out_res->width = effective_res->width;
2586 bayer_ds_out_res->height = effective_res->height;
2588 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2590 if (effective_res->width >= out_width *
2591 bds_factors[i].numerator / bds_factors[i].denominator &&
2592 effective_res->height >= out_height *
2593 bds_factors[i].numerator / bds_factors[i].denominator) {
2594 bayer_ds_out_res->width = effective_res->width *
2595 bds_factors[i].denominator /
2596 bds_factors[i].numerator;
2597 bayer_ds_out_res->height = effective_res->height *
2598 bds_factors[i].denominator /
2599 bds_factors[i].numerator;
2605 * DVS is cropped from BDS output, so we do not really need to set the
2606 * envelope to 20% of output resolution here. always set it to 12x12
2607 * per firmware requirement.
2609 pipe_configs->dvs_envelope.width = 12;
2610 pipe_configs->dvs_envelope.height = 12;
2613 if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2614 stream_config->left_padding = -1;
2616 stream_config->left_padding = 12;
2617 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2618 pipe_id, width, height);
2621 static void __configure_vf_output(struct atomisp_sub_device *asd,
2622 unsigned int width, unsigned int height,
2623 unsigned int min_width,
2624 enum ia_css_frame_format format,
2625 enum ia_css_pipe_id pipe_id)
2627 struct atomisp_device *isp = asd->isp;
2628 struct atomisp_stream_env *stream_env =
2629 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2630 stream_env->pipe_configs[pipe_id].mode =
2631 __pipe_id_to_pipe_mode(asd, pipe_id);
2632 stream_env->update_pipe[pipe_id] = true;
2634 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2635 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2636 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2637 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2640 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2641 pipe_id, width, height, format);
2644 static void __configure_video_vf_output(struct atomisp_sub_device *asd,
2645 unsigned int width, unsigned int height,
2646 unsigned int min_width,
2647 enum ia_css_frame_format format,
2648 enum ia_css_pipe_id pipe_id)
2650 struct atomisp_device *isp = asd->isp;
2651 struct atomisp_stream_env *stream_env =
2652 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2653 struct ia_css_frame_info *css_output_info;
2655 stream_env->pipe_configs[pipe_id].mode =
2656 __pipe_id_to_pipe_mode(asd, pipe_id);
2657 stream_env->update_pipe[pipe_id] = true;
2660 * second_vf_output will be as video viewfinder in SDV mode
2661 * with SOC camera. vf_output will be as video viewfinder in
2662 * normal video mode.
2664 if (asd->continuous_mode->val)
2665 css_output_info = &stream_env->pipe_configs[pipe_id].
2666 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2668 css_output_info = &stream_env->pipe_configs[pipe_id].
2669 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2671 css_output_info->res.width = width;
2672 css_output_info->res.height = height;
2673 css_output_info->format = format;
2674 css_output_info->padded_width = min_width;
2676 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2677 pipe_id, width, height, format);
2680 static int __get_frame_info(struct atomisp_sub_device *asd,
2681 unsigned int stream_index,
2682 struct ia_css_frame_info *info,
2683 enum frame_info_type type,
2684 enum ia_css_pipe_id pipe_id)
2686 struct atomisp_device *isp = asd->isp;
2688 struct ia_css_pipe_info p_info;
2690 /* FIXME! No need to destroy/recreate all streams */
2691 if (__destroy_streams(asd, true))
2692 dev_warn(isp->dev, "destroy stream failed.\n");
2694 if (__destroy_pipes(asd, true))
2695 dev_warn(isp->dev, "destroy pipe failed.\n");
2697 if (__create_pipes(asd))
2700 if (__create_streams(asd))
2703 ret = ia_css_pipe_get_info(
2704 asd->stream_env[stream_index]
2705 .pipes[pipe_id], &p_info);
2708 case ATOMISP_CSS_VF_FRAME:
2709 *info = p_info.vf_output_info[0];
2710 dev_dbg(isp->dev, "getting vf frame info.\n");
2712 case ATOMISP_CSS_SECOND_VF_FRAME:
2713 *info = p_info.vf_output_info[1];
2714 dev_dbg(isp->dev, "getting second vf frame info.\n");
2716 case ATOMISP_CSS_OUTPUT_FRAME:
2717 *info = p_info.output_info[0];
2718 dev_dbg(isp->dev, "getting main frame info.\n");
2720 case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2721 *info = p_info.output_info[1];
2722 dev_dbg(isp->dev, "getting second main frame info.\n");
2724 case ATOMISP_CSS_RAW_FRAME:
2725 *info = p_info.raw_output_info;
2726 dev_dbg(isp->dev, "getting raw frame info.\n");
2728 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2729 info->res.width, info->res.height, p_info.num_invalid_frames);
2734 __destroy_pipes(asd, true);
2738 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2739 uint16_t source_pad)
2741 struct atomisp_device *isp = asd->isp;
2743 * to SOC camera, use yuvpp pipe.
2745 if (ATOMISP_USE_YUVPP(asd))
2746 return IA_CSS_PIPE_ID_YUVPP;
2748 switch (source_pad) {
2749 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2750 if (asd->yuvpp_mode)
2751 return IA_CSS_PIPE_ID_YUVPP;
2753 return IA_CSS_PIPE_ID_COPY;
2754 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2755 || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2756 return IA_CSS_PIPE_ID_VIDEO;
2758 return IA_CSS_PIPE_ID_CAPTURE;
2759 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2761 return IA_CSS_PIPE_ID_COPY;
2763 return IA_CSS_PIPE_ID_CAPTURE;
2764 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2765 if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) {
2766 return IA_CSS_PIPE_ID_CAPTURE;
2769 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2770 if (asd->yuvpp_mode)
2771 return IA_CSS_PIPE_ID_YUVPP;
2773 return IA_CSS_PIPE_ID_COPY;
2774 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2775 return IA_CSS_PIPE_ID_VIDEO;
2777 return IA_CSS_PIPE_ID_PREVIEW;
2780 "invalid source pad:%d, return default preview pipe index.\n",
2782 return IA_CSS_PIPE_ID_PREVIEW;
2785 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2787 struct ia_css_frame_info *frame_info)
2789 struct ia_css_pipe_info info;
2790 int pipe_index = atomisp_get_pipe_index(asd, source_pad);
2792 struct atomisp_device *isp = asd->isp;
2794 if (ATOMISP_SOC_CAMERA(asd))
2795 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
2797 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2798 ATOMISP_INPUT_STREAM_VIDEO :
2799 atomisp_source_pad_to_stream_id(asd, source_pad);
2802 if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index]
2803 .pipes[pipe_index], &info)) {
2804 dev_err(isp->dev, "ia_css_pipe_get_info FAILED");
2808 switch (source_pad) {
2809 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2810 *frame_info = info.output_info[0];
2812 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2813 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2815 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2818 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2820 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2821 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
2822 *frame_info = info.output_info[0];
2824 *frame_info = info.vf_output_info[0];
2826 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2827 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2828 (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
2829 pipe_index == IA_CSS_PIPE_ID_YUVPP))
2830 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2832 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2835 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2836 else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2838 info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2841 info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2848 return frame_info ? 0 : -EINVAL;
2851 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2852 unsigned int stream_index,
2853 unsigned int width, unsigned int height,
2854 unsigned int padded_width,
2855 enum ia_css_frame_format format)
2857 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
2858 default_capture_config.mode =
2859 IA_CSS_CAPTURE_MODE_RAW;
2861 __configure_output(asd, stream_index, width, height, padded_width,
2862 format, IA_CSS_PIPE_ID_COPY);
2866 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
2867 unsigned int stream_index,
2868 unsigned int width, unsigned int height,
2869 unsigned int padded_width,
2870 enum ia_css_frame_format format)
2872 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
2873 default_capture_config.mode =
2874 IA_CSS_CAPTURE_MODE_RAW;
2876 __configure_output(asd, stream_index, width, height, padded_width,
2877 format, IA_CSS_PIPE_ID_YUVPP);
2881 int atomisp_css_yuvpp_configure_viewfinder(
2882 struct atomisp_sub_device *asd,
2883 unsigned int stream_index,
2884 unsigned int width, unsigned int height,
2885 unsigned int min_width,
2886 enum ia_css_frame_format format)
2888 struct atomisp_stream_env *stream_env =
2889 &asd->stream_env[stream_index];
2890 enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP;
2892 stream_env->pipe_configs[pipe_id].mode =
2893 __pipe_id_to_pipe_mode(asd, pipe_id);
2894 stream_env->update_pipe[pipe_id] = true;
2896 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2897 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2898 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2899 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2904 int atomisp_css_yuvpp_get_output_frame_info(
2905 struct atomisp_sub_device *asd,
2906 unsigned int stream_index,
2907 struct ia_css_frame_info *info)
2909 return __get_frame_info(asd, stream_index, info,
2910 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
2913 int atomisp_css_yuvpp_get_viewfinder_frame_info(
2914 struct atomisp_sub_device *asd,
2915 unsigned int stream_index,
2916 struct ia_css_frame_info *info)
2918 return __get_frame_info(asd, stream_index, info,
2919 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
2922 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
2923 unsigned int width, unsigned int height,
2924 unsigned int min_width,
2925 enum ia_css_frame_format format)
2928 * to SOC camera, use yuvpp pipe.
2930 if (ATOMISP_USE_YUVPP(asd))
2931 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
2933 min_width, format, IA_CSS_PIPE_ID_YUVPP);
2935 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2936 min_width, format, IA_CSS_PIPE_ID_PREVIEW);
2940 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
2941 unsigned int width, unsigned int height,
2942 unsigned int min_width,
2943 enum ia_css_frame_format format)
2945 enum ia_css_pipe_id pipe_id;
2948 * to SOC camera, use yuvpp pipe.
2950 if (ATOMISP_USE_YUVPP(asd))
2951 pipe_id = IA_CSS_PIPE_ID_YUVPP;
2953 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
2955 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2956 min_width, format, pipe_id);
2960 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
2961 unsigned int width, unsigned int height,
2962 unsigned int min_width,
2963 enum ia_css_frame_format format)
2966 * to SOC camera, use yuvpp pipe.
2968 if (ATOMISP_USE_YUVPP(asd))
2969 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
2971 min_width, format, IA_CSS_PIPE_ID_YUVPP);
2973 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2974 min_width, format, IA_CSS_PIPE_ID_VIDEO);
2978 int atomisp_css_video_configure_viewfinder(
2979 struct atomisp_sub_device *asd,
2980 unsigned int width, unsigned int height,
2981 unsigned int min_width,
2982 enum ia_css_frame_format format)
2985 * to SOC camera, video will use yuvpp pipe.
2987 if (ATOMISP_USE_YUVPP(asd))
2988 __configure_video_vf_output(asd, width, height, min_width, format,
2989 IA_CSS_PIPE_ID_YUVPP);
2991 __configure_vf_output(asd, width, height, min_width, format,
2992 IA_CSS_PIPE_ID_VIDEO);
2996 int atomisp_css_capture_configure_viewfinder(
2997 struct atomisp_sub_device *asd,
2998 unsigned int width, unsigned int height,
2999 unsigned int min_width,
3000 enum ia_css_frame_format format)
3002 enum ia_css_pipe_id pipe_id;
3005 * to SOC camera, video will use yuvpp pipe.
3007 if (ATOMISP_USE_YUVPP(asd))
3008 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3010 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3012 __configure_vf_output(asd, width, height, min_width, format,
3017 int atomisp_css_video_get_viewfinder_frame_info(
3018 struct atomisp_sub_device *asd,
3019 struct ia_css_frame_info *info)
3021 enum ia_css_pipe_id pipe_id;
3022 enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME;
3024 if (ATOMISP_USE_YUVPP(asd)) {
3025 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3026 if (asd->continuous_mode->val)
3027 frame_type = ATOMISP_CSS_SECOND_VF_FRAME;
3029 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3032 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3033 frame_type, pipe_id);
3036 int atomisp_css_capture_get_viewfinder_frame_info(
3037 struct atomisp_sub_device *asd,
3038 struct ia_css_frame_info *info)
3040 enum ia_css_pipe_id pipe_id;
3042 if (ATOMISP_USE_YUVPP(asd))
3043 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3045 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3047 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3048 ATOMISP_CSS_VF_FRAME, pipe_id);
3051 int atomisp_css_capture_get_output_raw_frame_info(
3052 struct atomisp_sub_device *asd,
3053 struct ia_css_frame_info *info)
3055 if (ATOMISP_USE_YUVPP(asd))
3058 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3059 ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE);
3062 int atomisp_css_copy_get_output_frame_info(
3063 struct atomisp_sub_device *asd,
3064 unsigned int stream_index,
3065 struct ia_css_frame_info *info)
3067 return __get_frame_info(asd, stream_index, info,
3068 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
3071 int atomisp_css_preview_get_output_frame_info(
3072 struct atomisp_sub_device *asd,
3073 struct ia_css_frame_info *info)
3075 enum ia_css_pipe_id pipe_id;
3076 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3078 if (ATOMISP_USE_YUVPP(asd)) {
3079 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3080 if (asd->continuous_mode->val)
3081 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3083 pipe_id = IA_CSS_PIPE_ID_PREVIEW;
3086 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3087 frame_type, pipe_id);
3090 int atomisp_css_capture_get_output_frame_info(
3091 struct atomisp_sub_device *asd,
3092 struct ia_css_frame_info *info)
3094 enum ia_css_pipe_id pipe_id;
3096 if (ATOMISP_USE_YUVPP(asd))
3097 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3099 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3101 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3102 ATOMISP_CSS_OUTPUT_FRAME, pipe_id);
3105 int atomisp_css_video_get_output_frame_info(
3106 struct atomisp_sub_device *asd,
3107 struct ia_css_frame_info *info)
3109 enum ia_css_pipe_id pipe_id;
3110 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3112 if (ATOMISP_USE_YUVPP(asd)) {
3113 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3114 if (asd->continuous_mode->val)
3115 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3117 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3120 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3121 frame_type, pipe_id);
3124 int atomisp_css_preview_configure_pp_input(
3125 struct atomisp_sub_device *asd,
3126 unsigned int width, unsigned int height)
3128 struct atomisp_stream_env *stream_env =
3129 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3130 __configure_preview_pp_input(asd, width, height,
3131 ATOMISP_USE_YUVPP(asd) ?
3132 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW);
3134 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3135 capt_pp_in_res.width)
3136 __configure_capture_pp_input(asd, width, height,
3137 ATOMISP_USE_YUVPP(asd) ?
3138 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3142 int atomisp_css_capture_configure_pp_input(
3143 struct atomisp_sub_device *asd,
3144 unsigned int width, unsigned int height)
3146 __configure_capture_pp_input(asd, width, height,
3147 ATOMISP_USE_YUVPP(asd) ?
3148 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3152 int atomisp_css_video_configure_pp_input(
3153 struct atomisp_sub_device *asd,
3154 unsigned int width, unsigned int height)
3156 struct atomisp_stream_env *stream_env =
3157 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3159 __configure_video_pp_input(asd, width, height,
3160 ATOMISP_USE_YUVPP(asd) ?
3161 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO);
3163 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3164 capt_pp_in_res.width)
3165 __configure_capture_pp_input(asd, width, height,
3166 ATOMISP_USE_YUVPP(asd) ?
3167 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3171 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
3172 int num_captures, unsigned int skip, int offset)
3176 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
3177 __func__, num_captures, skip, offset);
3179 ret = ia_css_stream_capture(
3180 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3181 num_captures, skip, offset);
3188 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
3192 ret = ia_css_stream_capture_frame(
3193 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3195 if (ret == -ENOBUFS) {
3196 /* capture cmd queue is full */
3205 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
3209 ret = ia_css_unlock_raw_frame(
3210 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3212 if (ret == -ENOBUFS)
3220 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
3223 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3224 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
3225 .default_capture_config.enable_xnr = enable;
3226 asd->params.capture_config.enable_xnr = enable;
3227 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3228 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
3233 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
3234 struct ia_css_ctc_table *ctc_table)
3237 u16 *vamem_ptr = ctc_table->data.vamem_1;
3238 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
3241 /* workaround: if ctc_table is all 0, do not apply it */
3242 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
3243 vamem_ptr = ctc_table->data.vamem_2;
3244 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
3247 for (i = 0; i < data_size; i++) {
3248 if (*(vamem_ptr + i)) {
3255 asd->params.config.ctc_table = ctc_table;
3257 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
3260 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
3261 struct ia_css_anr_thres *anr_thres)
3263 asd->params.config.anr_thres = anr_thres;
3266 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
3267 struct ia_css_dvs_6axis_config *dvs_6axis)
3269 asd->params.config.dvs_6axis_config = dvs_6axis;
3272 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
3273 struct atomisp_dis_vector *vector)
3275 if (!asd->params.config.motion_vector)
3276 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
3278 memset(asd->params.config.motion_vector,
3279 0, sizeof(struct ia_css_vector));
3280 asd->params.css_param.motion_vector.x = vector->x;
3281 asd->params.css_param.motion_vector.y = vector->y;
3284 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
3285 struct atomisp_dvs_grid_info *atomgrid)
3287 struct ia_css_dvs_grid_info *cur =
3288 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
3291 dev_err(asd->isp->dev, "dvs grid not available!\n");
3295 if (sizeof(*cur) != sizeof(*atomgrid)) {
3296 dev_err(asd->isp->dev, "dvs grid mis-match!\n");
3301 dev_err(asd->isp->dev, "dvs not enabled!\n");
3305 return memcmp(atomgrid, cur, sizeof(*cur));
3308 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
3309 struct ia_css_dvs2_coefficients *coefs)
3311 asd->params.config.dvs2_coefs = coefs;
3314 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
3315 struct atomisp_dis_coefficients *coefs)
3317 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
3318 /* If the grid info in the argument differs from the current
3319 grid info, we tell the caller to reset the grid size and
3323 if (!coefs->hor_coefs.odd_real ||
3324 !coefs->hor_coefs.odd_imag ||
3325 !coefs->hor_coefs.even_real ||
3326 !coefs->hor_coefs.even_imag ||
3327 !coefs->ver_coefs.odd_real ||
3328 !coefs->ver_coefs.odd_imag ||
3329 !coefs->ver_coefs.even_real ||
3330 !coefs->ver_coefs.even_imag ||
3331 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real ||
3332 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag ||
3333 !asd->params.css_param.dvs2_coeff->hor_coefs.even_real ||
3334 !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag ||
3335 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real ||
3336 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag ||
3337 !asd->params.css_param.dvs2_coeff->ver_coefs.even_real ||
3338 !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag)
3341 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
3342 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
3344 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
3345 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
3347 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
3348 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
3350 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
3351 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
3354 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
3355 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
3357 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
3358 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
3360 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
3361 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
3363 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
3364 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
3367 asd->params.css_param.update_flag.dvs2_coefs =
3368 (struct atomisp_dis_coefficients *)
3369 asd->params.css_param.dvs2_coeff;
3371 /* asd->params.dis_proj_data_valid = false; */
3372 asd->params.css_update_params_needed = true;
3377 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
3380 struct atomisp_device *isp = asd->isp;
3382 if (zoom == asd->params.css_param.dz_config.dx &&
3383 zoom == asd->params.css_param.dz_config.dy) {
3384 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
3388 memset(&asd->params.css_param.dz_config, 0,
3389 sizeof(struct ia_css_dz_config));
3390 asd->params.css_param.dz_config.dx = zoom;
3391 asd->params.css_param.dz_config.dy = zoom;
3393 asd->params.css_param.update_flag.dz_config =
3394 (struct atomisp_dz_config *)&asd->params.css_param.dz_config;
3395 asd->params.css_update_params_needed = true;
3398 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
3399 struct ia_css_formats_config *formats_config)
3401 asd->params.config.formats_config = formats_config;
3404 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
3405 struct atomisp_wb_config *config)
3407 struct ia_css_wb_config wb_config;
3408 struct ia_css_isp_config isp_config;
3409 struct atomisp_device *isp = asd->isp;
3411 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3412 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3416 memset(&wb_config, 0, sizeof(struct ia_css_wb_config));
3417 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3418 isp_config.wb_config = &wb_config;
3419 ia_css_stream_get_isp_config(
3420 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3422 memcpy(config, &wb_config, sizeof(*config));
3427 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
3428 struct atomisp_ob_config *config)
3430 struct ia_css_ob_config ob_config;
3431 struct ia_css_isp_config isp_config;
3432 struct atomisp_device *isp = asd->isp;
3434 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3435 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3439 memset(&ob_config, 0, sizeof(struct ia_css_ob_config));
3440 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3441 isp_config.ob_config = &ob_config;
3442 ia_css_stream_get_isp_config(
3443 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3445 memcpy(config, &ob_config, sizeof(*config));
3450 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
3451 struct atomisp_dp_config *config)
3453 struct ia_css_dp_config dp_config;
3454 struct ia_css_isp_config isp_config;
3455 struct atomisp_device *isp = asd->isp;
3457 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3458 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3462 memset(&dp_config, 0, sizeof(struct ia_css_dp_config));
3463 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3464 isp_config.dp_config = &dp_config;
3465 ia_css_stream_get_isp_config(
3466 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3468 memcpy(config, &dp_config, sizeof(*config));
3473 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3474 struct atomisp_de_config *config)
3476 struct ia_css_de_config de_config;
3477 struct ia_css_isp_config isp_config;
3478 struct atomisp_device *isp = asd->isp;
3480 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3481 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3485 memset(&de_config, 0, sizeof(struct ia_css_de_config));
3486 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3487 isp_config.de_config = &de_config;
3488 ia_css_stream_get_isp_config(
3489 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3491 memcpy(config, &de_config, sizeof(*config));
3496 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3497 struct atomisp_nr_config *config)
3499 struct ia_css_nr_config nr_config;
3500 struct ia_css_isp_config isp_config;
3501 struct atomisp_device *isp = asd->isp;
3503 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3504 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3508 memset(&nr_config, 0, sizeof(struct ia_css_nr_config));
3509 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3511 isp_config.nr_config = &nr_config;
3512 ia_css_stream_get_isp_config(
3513 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3515 memcpy(config, &nr_config, sizeof(*config));
3520 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3521 struct atomisp_ee_config *config)
3523 struct ia_css_ee_config ee_config;
3524 struct ia_css_isp_config isp_config;
3525 struct atomisp_device *isp = asd->isp;
3527 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3528 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3532 memset(&ee_config, 0, sizeof(struct ia_css_ee_config));
3533 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3534 isp_config.ee_config = &ee_config;
3535 ia_css_stream_get_isp_config(
3536 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3538 memcpy(config, &ee_config, sizeof(*config));
3543 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3544 struct atomisp_tnr_config *config)
3546 struct ia_css_tnr_config tnr_config;
3547 struct ia_css_isp_config isp_config;
3548 struct atomisp_device *isp = asd->isp;
3550 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3551 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3555 memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config));
3556 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3557 isp_config.tnr_config = &tnr_config;
3558 ia_css_stream_get_isp_config(
3559 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3561 memcpy(config, &tnr_config, sizeof(*config));
3566 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3567 struct atomisp_ctc_table *config)
3569 struct ia_css_ctc_table *tab;
3570 struct ia_css_isp_config isp_config;
3571 struct atomisp_device *isp = asd->isp;
3573 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3574 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3579 tab = vzalloc(sizeof(struct ia_css_ctc_table));
3583 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3584 isp_config.ctc_table = tab;
3585 ia_css_stream_get_isp_config(
3586 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3588 memcpy(config, tab, sizeof(*tab));
3594 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
3595 struct atomisp_gamma_table *config)
3597 struct ia_css_gamma_table *tab;
3598 struct ia_css_isp_config isp_config;
3599 struct atomisp_device *isp = asd->isp;
3601 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3602 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3607 tab = vzalloc(sizeof(struct ia_css_gamma_table));
3611 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3612 isp_config.gamma_table = tab;
3613 ia_css_stream_get_isp_config(
3614 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3616 memcpy(config, tab, sizeof(*tab));
3622 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
3623 struct atomisp_gc_config *config)
3625 struct ia_css_gc_config gc_config;
3626 struct ia_css_isp_config isp_config;
3627 struct atomisp_device *isp = asd->isp;
3629 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3630 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3634 memset(&gc_config, 0, sizeof(struct ia_css_gc_config));
3635 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3636 isp_config.gc_config = &gc_config;
3637 ia_css_stream_get_isp_config(
3638 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3640 /* Get gamma correction params from current setup */
3641 memcpy(config, &gc_config, sizeof(*config));
3646 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
3647 struct atomisp_3a_config *config)
3649 struct ia_css_3a_config s3a_config;
3650 struct ia_css_isp_config isp_config;
3651 struct atomisp_device *isp = asd->isp;
3653 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3654 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3658 memset(&s3a_config, 0, sizeof(struct ia_css_3a_config));
3659 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3660 isp_config.s3a_config = &s3a_config;
3661 ia_css_stream_get_isp_config(
3662 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3664 /* Get white balance from current setup */
3665 memcpy(config, &s3a_config, sizeof(*config));
3670 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
3671 struct atomisp_formats_config *config)
3673 struct ia_css_formats_config formats_config;
3674 struct ia_css_isp_config isp_config;
3675 struct atomisp_device *isp = asd->isp;
3677 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3678 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3682 memset(&formats_config, 0, sizeof(formats_config));
3683 memset(&isp_config, 0, sizeof(isp_config));
3684 isp_config.formats_config = &formats_config;
3685 ia_css_stream_get_isp_config(
3686 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3688 /* Get narrow gamma from current setup */
3689 memcpy(config, &formats_config, sizeof(*config));
3694 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
3697 struct ia_css_dz_config dz_config; /** Digital Zoom */
3698 struct ia_css_isp_config isp_config;
3699 struct atomisp_device *isp = asd->isp;
3701 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3702 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3706 memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
3707 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3708 isp_config.dz_config = &dz_config;
3709 ia_css_stream_get_isp_config(
3710 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3712 *zoom = dz_config.dx;
3718 * Function to set/get image stablization statistics
3720 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
3721 struct atomisp_dis_statistics *stats)
3723 struct atomisp_device *isp = asd->isp;
3724 struct atomisp_dis_buf *dis_buf;
3725 unsigned long flags;
3727 if (!asd->params.dvs_stat->hor_prod.odd_real ||
3728 !asd->params.dvs_stat->hor_prod.odd_imag ||
3729 !asd->params.dvs_stat->hor_prod.even_real ||
3730 !asd->params.dvs_stat->hor_prod.even_imag ||
3731 !asd->params.dvs_stat->ver_prod.odd_real ||
3732 !asd->params.dvs_stat->ver_prod.odd_imag ||
3733 !asd->params.dvs_stat->ver_prod.even_real ||
3734 !asd->params.dvs_stat->ver_prod.even_imag)
3737 /* isp needs to be streaming to get DIS statistics */
3738 spin_lock_irqsave(&isp->lock, flags);
3739 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) {
3740 spin_unlock_irqrestore(&isp->lock, flags);
3743 spin_unlock_irqrestore(&isp->lock, flags);
3745 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
3746 /* If the grid info in the argument differs from the current
3747 grid info, we tell the caller to reset the grid size and
3751 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3752 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
3753 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3754 dev_err(isp->dev, "dis statistics is not valid.\n");
3758 dis_buf = list_entry(asd->dis_stats.next,
3759 struct atomisp_dis_buf, list);
3760 list_del_init(&dis_buf->list);
3761 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3763 if (dis_buf->dvs_map)
3764 ia_css_translate_dvs2_statistics(
3765 asd->params.dvs_stat, dis_buf->dvs_map);
3767 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
3769 stats->exp_id = dis_buf->dis_data->exp_id;
3771 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3772 list_add_tail(&dis_buf->list, &asd->dis_stats);
3773 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3775 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
3776 asd->params.dvs_stat->ver_prod.odd_real,
3777 asd->params.dvs_ver_proj_bytes))
3779 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
3780 asd->params.dvs_stat->ver_prod.odd_imag,
3781 asd->params.dvs_ver_proj_bytes))
3783 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
3784 asd->params.dvs_stat->ver_prod.even_real,
3785 asd->params.dvs_ver_proj_bytes))
3787 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
3788 asd->params.dvs_stat->ver_prod.even_imag,
3789 asd->params.dvs_ver_proj_bytes))
3791 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
3792 asd->params.dvs_stat->hor_prod.odd_real,
3793 asd->params.dvs_hor_proj_bytes))
3795 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
3796 asd->params.dvs_stat->hor_prod.odd_imag,
3797 asd->params.dvs_hor_proj_bytes))
3799 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
3800 asd->params.dvs_stat->hor_prod.even_real,
3801 asd->params.dvs_hor_proj_bytes))
3803 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
3804 asd->params.dvs_stat->hor_prod.even_imag,
3805 asd->params.dvs_hor_proj_bytes))
3811 struct ia_css_shading_table *atomisp_css_shading_table_alloc(
3812 unsigned int width, unsigned int height)
3814 return ia_css_shading_table_alloc(width, height);
3817 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
3818 struct ia_css_shading_table *table)
3820 asd->params.config.shading_table = table;
3823 void atomisp_css_shading_table_free(struct ia_css_shading_table *table)
3825 ia_css_shading_table_free(table);
3828 struct ia_css_morph_table *atomisp_css_morph_table_allocate(
3829 unsigned int width, unsigned int height)
3831 return ia_css_morph_table_allocate(width, height);
3834 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
3835 struct ia_css_morph_table *table)
3837 asd->params.config.morph_table = table;
3840 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
3841 struct ia_css_morph_table *table)
3843 struct ia_css_isp_config isp_config;
3844 struct atomisp_device *isp = asd->isp;
3846 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3848 "%s called after streamoff, skipping.\n", __func__);
3851 memset(table, 0, sizeof(struct ia_css_morph_table));
3852 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3853 isp_config.morph_table = table;
3854 ia_css_stream_get_isp_config(
3855 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3859 void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
3861 ia_css_morph_table_free(table);
3864 void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp,
3865 unsigned int overlap)
3867 /* CSS 2.0 doesn't support this API. */
3868 dev_dbg(isp->dev, "set cont prev start time is not supported.\n");
3872 void atomisp_css_acc_done(struct atomisp_sub_device *asd)
3874 complete(&asd->acc.acc_done);
3877 int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd)
3880 struct atomisp_device *isp = asd->isp;
3882 /* Unlock the isp mutex taken in IOCTL handler before sleeping! */
3883 rt_mutex_unlock(&isp->mutex);
3884 if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done,
3885 ATOMISP_ISP_TIMEOUT_DURATION) == 0) {
3886 dev_err(isp->dev, "<%s: completion timeout\n", __func__);
3887 ia_css_debug_dump_sp_sw_debug_info();
3888 ia_css_debug_dump_debug_info(__func__);
3891 rt_mutex_lock(&isp->mutex);
3896 /* Set the ACC binary arguments */
3897 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw)
3901 for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) {
3902 if (acc_fw->args[mem].length == 0)
3905 ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers,
3906 IA_CSS_PARAM_CLASS_PARAM, mem,
3907 acc_fw->args[mem].css_ptr,
3908 acc_fw->args[mem].length);
3914 /* Load acc binary extension */
3915 int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd,
3916 struct ia_css_fw_info *fw,
3917 enum ia_css_pipe_id pipe_id,
3920 struct ia_css_fw_info **hd;
3923 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3924 .pipe_configs[pipe_id].acc_extension);
3929 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3930 .update_pipe[pipe_id] = true;
3934 /* Unload acc binary extension */
3935 void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd,
3936 struct ia_css_fw_info *fw,
3937 enum ia_css_pipe_id pipe_id)
3939 struct ia_css_fw_info **hd;
3941 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3942 .pipe_configs[pipe_id].acc_extension);
3943 while (*hd && *hd != fw)
3946 dev_err(asd->isp->dev, "did not find acc fw for removal\n");
3952 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3953 .update_pipe[pipe_id] = true;
3956 int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd)
3958 struct atomisp_device *isp = asd->isp;
3959 struct ia_css_pipe_config *pipe_config;
3960 struct atomisp_stream_env *stream_env =
3961 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3963 if (stream_env->acc_stream) {
3964 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
3965 if (ia_css_stream_stop(stream_env->acc_stream)
3967 dev_err(isp->dev, "stop acc_stream failed.\n");
3972 if (ia_css_stream_destroy(stream_env->acc_stream)
3974 dev_err(isp->dev, "destroy acc_stream failed.\n");
3977 stream_env->acc_stream = NULL;
3980 pipe_config = &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
3981 ia_css_pipe_config_defaults(pipe_config);
3982 asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES *
3983 sizeof(void *), GFP_KERNEL);
3984 if (!asd->acc.acc_stages)
3986 pipe_config->acc_stages = asd->acc.acc_stages;
3987 pipe_config->mode = IA_CSS_PIPE_MODE_ACC;
3988 pipe_config->num_acc_stages = 0;
3991 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe,
3992 * because pipe configuration will soon be changed by
3993 * atomisp_css_load_acc_binary()
3998 int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd)
4000 struct atomisp_device *isp = asd->isp;
4001 struct atomisp_stream_env *stream_env =
4002 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4003 struct ia_css_pipe_config *pipe_config =
4004 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
4006 if (ia_css_pipe_create(pipe_config,
4007 &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != 0) {
4008 dev_err(isp->dev, "%s: ia_css_pipe_create failed\n",
4013 memset(&stream_env->acc_stream_config, 0,
4014 sizeof(struct ia_css_stream_config));
4015 if (ia_css_stream_create(&stream_env->acc_stream_config, 1,
4016 &stream_env->pipes[IA_CSS_PIPE_ID_ACC],
4017 &stream_env->acc_stream) != 0) {
4018 dev_err(isp->dev, "%s: create acc_stream error.\n", __func__);
4021 stream_env->acc_stream_state = CSS_STREAM_CREATED;
4023 init_completion(&asd->acc.acc_done);
4024 asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC];
4026 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
4028 if (ia_css_start_sp()) {
4029 dev_err(isp->dev, "start sp error.\n");
4033 if (ia_css_stream_start(stream_env->acc_stream)
4035 dev_err(isp->dev, "acc_stream start error.\n");
4039 stream_env->acc_stream_state = CSS_STREAM_STARTED;
4043 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd)
4045 struct atomisp_stream_env *stream_env =
4046 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4047 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4048 ia_css_stream_stop(stream_env->acc_stream);
4049 stream_env->acc_stream_state = CSS_STREAM_STOPPED;
4054 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd)
4056 struct atomisp_stream_env *stream_env =
4057 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4058 if (stream_env->acc_stream) {
4059 if (ia_css_stream_destroy(stream_env->acc_stream)
4061 dev_warn(asd->isp->dev,
4062 "destroy acc_stream failed.\n");
4063 stream_env->acc_stream = NULL;
4066 if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) {
4067 if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC])
4069 dev_warn(asd->isp->dev,
4070 "destroy ACC pipe failed.\n");
4071 stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL;
4072 stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false;
4073 ia_css_pipe_config_defaults(
4074 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]);
4075 ia_css_pipe_extra_config_defaults(
4076 &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]);
4078 asd->acc.pipeline = NULL;
4080 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
4085 kfree(asd->acc.acc_stages);
4086 asd->acc.acc_stages = NULL;
4088 atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false);
4091 int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd,
4092 struct ia_css_fw_info *fw,
4095 struct ia_css_pipe_config *pipe_config =
4096 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4097 .pipe_configs[IA_CSS_PIPE_ID_ACC];
4099 if (index >= MAX_ACC_STAGES) {
4100 dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n",
4105 pipe_config->acc_stages[index] = fw;
4106 pipe_config->num_acc_stages = index + 1;
4107 pipe_config->acc_num_execs = 1;
4112 static struct atomisp_sub_device *__get_atomisp_subdev(
4113 struct ia_css_pipe *css_pipe,
4114 struct atomisp_device *isp,
4115 enum atomisp_input_stream_id *stream_id)
4118 struct atomisp_sub_device *asd;
4119 struct atomisp_stream_env *stream_env;
4121 for (i = 0; i < isp->num_of_streams; i++) {
4123 if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED &&
4126 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4127 stream_env = &asd->stream_env[j];
4128 for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
4129 if (stream_env->pipes[k] &&
4130 stream_env->pipes[k] == css_pipe) {
4141 int atomisp_css_isr_thread(struct atomisp_device *isp,
4142 bool *frame_done_found,
4143 bool *css_pipe_done)
4145 enum atomisp_input_stream_id stream_id = 0;
4146 struct atomisp_css_event current_event;
4147 struct atomisp_sub_device *asd;
4148 bool reset_wdt_timer[MAX_STREAM_NUM] = {false};
4151 while (!atomisp_css_dequeue_event(¤t_event)) {
4152 if (current_event.event.type ==
4153 IA_CSS_EVENT_TYPE_FW_ASSERT) {
4155 * Received FW assertion signal,
4156 * trigger WDT to recover
4159 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
4161 current_event.event.fw_assert_module_id,
4162 current_event.event.fw_assert_line_no);
4163 for (i = 0; i < isp->num_of_streams; i++)
4164 atomisp_wdt_stop(&isp->asd[i], 0);
4167 atomisp_wdt(&isp->asd[0].wdt);
4169 queue_work(isp->wdt_work_queue, &isp->wdt_work);
4172 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4173 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
4174 __func__, current_event.event.fw_warning,
4175 current_event.event.exp_id);
4179 asd = __get_atomisp_subdev(current_event.event.pipe,
4182 if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
4184 "event: Timer event.");
4186 dev_warn(isp->dev, "%s:no subdev.event:%d",
4188 current_event.event.type);
4192 atomisp_css_temp_pipe_to_pipe_id(asd, ¤t_event);
4193 switch (current_event.event.type) {
4194 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
4195 dev_dbg(isp->dev, "event: Output frame done");
4196 frame_done_found[asd->index] = true;
4197 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
4198 current_event.pipe, true, stream_id);
4201 reset_wdt_timer[asd->index] = true; /* ISP running */
4204 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
4205 dev_dbg(isp->dev, "event: Second output frame done");
4206 frame_done_found[asd->index] = true;
4207 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
4208 current_event.pipe, true, stream_id);
4211 reset_wdt_timer[asd->index] = true; /* ISP running */
4214 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
4215 dev_dbg(isp->dev, "event: 3A stats frame done");
4216 atomisp_buf_done(asd, 0,
4217 IA_CSS_BUFFER_TYPE_3A_STATISTICS,
4221 case IA_CSS_EVENT_TYPE_METADATA_DONE:
4222 dev_dbg(isp->dev, "event: metadata frame done");
4223 atomisp_buf_done(asd, 0,
4224 IA_CSS_BUFFER_TYPE_METADATA,
4228 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
4229 dev_dbg(isp->dev, "event: VF output frame done");
4230 atomisp_buf_done(asd, 0,
4231 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
4232 current_event.pipe, true, stream_id);
4235 reset_wdt_timer[asd->index] = true; /* ISP running */
4238 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
4239 dev_dbg(isp->dev, "event: second VF output frame done");
4240 atomisp_buf_done(asd, 0,
4241 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
4242 current_event.pipe, true, stream_id);
4244 reset_wdt_timer[asd->index] = true; /* ISP running */
4247 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
4248 dev_dbg(isp->dev, "event: dis stats frame done");
4249 atomisp_buf_done(asd, 0,
4250 IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
4254 case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
4255 dev_dbg(isp->dev, "event: pipeline done");
4256 css_pipe_done[asd->index] = true;
4258 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
4259 dev_dbg(isp->dev, "event: acc stage done");
4260 atomisp_acc_done(asd, current_event.event.fw_handle);
4263 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
4264 current_event.event.type);
4272 /* ISP2400: If there are no buffers queued then delete wdt timer. */
4273 for (i = 0; i < isp->num_of_streams; i++) {
4277 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
4279 if (!atomisp_buffers_queued(asd))
4280 atomisp_wdt_stop(asd, false);
4281 else if (reset_wdt_timer[i])
4282 /* SOF irq should not reset wdt timer. */
4283 atomisp_wdt_refresh(asd,
4284 ATOMISP_WDT_KEEP_CURRENT_DELAY);
4290 bool atomisp_css_valid_sof(struct atomisp_device *isp)
4294 /* Loop for each css stream */
4295 for (i = 0; i < isp->num_of_streams; i++) {
4296 struct atomisp_sub_device *asd = &isp->asd[i];
4297 /* Loop for each css vc stream */
4298 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4299 if (!asd->stream_env[j].stream)
4303 "stream #%d: mode: %d\n", j,
4304 asd->stream_env[j].stream_config.mode);
4305 if (asd->stream_env[j].stream_config.mode ==
4306 IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
4314 int atomisp_css_debug_dump_isp_binary(void)
4316 ia_css_debug_dump_isp_binary();
4320 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
4322 sh_css_dump_sp_raw_copy_linecount(reduced);
4326 static const char * const fw_type_name[] = {
4327 [ia_css_sp_firmware] = "SP",
4328 [ia_css_isp_firmware] = "ISP",
4329 [ia_css_bootloader_firmware] = "BootLoader",
4330 [ia_css_acc_firmware] = "accel",
4333 static const char * const fw_acc_type_name[] = {
4334 [IA_CSS_ACC_NONE] = "Normal",
4335 [IA_CSS_ACC_OUTPUT] = "Accel stage on output",
4336 [IA_CSS_ACC_VIEWFINDER] = "Accel stage on viewfinder",
4337 [IA_CSS_ACC_STANDALONE] = "Stand-alone acceleration",
4340 int atomisp_css_dump_blob_infor(struct atomisp_device *isp)
4342 struct ia_css_blob_descr *bd = sh_css_blob_info;
4343 unsigned int i, nm = sh_css_num_binaries;
4351 * The sh_css_load_firmware function discard the initial
4354 for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) {
4355 switch (bd[i].header.type) {
4356 case ia_css_isp_firmware:
4357 dev_dbg(isp->dev, "Num%2d type %s (%s), binary id is %2d, name is %s\n",
4359 fw_type_name[bd[i].header.type],
4360 fw_acc_type_name[bd[i].header.info.isp.type],
4361 bd[i].header.info.isp.sp.id,
4365 dev_dbg(isp->dev, "Num%2d type %s, name is %s\n",
4366 i + NUM_OF_SPS, fw_type_name[bd[i].header.type],
4374 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
4375 uint32_t isp_config_id)
4377 asd->params.config.isp_config_id = isp_config_id;
4380 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
4381 struct ia_css_frame *output_frame)
4383 asd->params.config.output_frame = output_frame;
4386 int atomisp_get_css_dbgfunc(void)
4391 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
4395 ret = __set_css_print_env(isp, opt);
4402 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
4404 ia_css_en_dz_capt_pipe(
4405 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4409 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
4410 struct ia_css_grid_info *grid_info)
4415 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
4416 return &grid_info->dvs_grid.dvs_grid_info;
4418 return &grid_info->dvs_grid;