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 __printf(1, 0) atomisp_css2_dbg_ftrace_print(const char *fmt,
165 ftrace_vprintk(fmt, args);
169 static int __printf(1, 0) atomisp_vprintk(const char *fmt, va_list args)
175 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
177 *data = atomisp_css2_hw_load_32(addr);
180 static int hmm_get_mmu_base_addr(struct device *dev, unsigned int *mmu_base_addr)
182 if (!sh_mmu_mrfld.get_pd_base) {
183 dev_err(dev, "get mmu base address failed.\n");
187 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
188 bo_device.mmu.base_address);
192 static void __dump_pipe_config(struct atomisp_sub_device *asd,
193 struct atomisp_stream_env *stream_env,
194 unsigned int pipe_id)
196 struct atomisp_device *isp = asd->isp;
198 if (stream_env->pipes[pipe_id]) {
199 struct ia_css_pipe_config *p_config;
200 struct ia_css_pipe_extra_config *pe_config;
202 p_config = &stream_env->pipe_configs[pipe_id];
203 pe_config = &stream_env->pipe_extra_configs[pipe_id];
204 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
206 "pipe_config.pipe_mode:%d.\n", p_config->mode);
208 "pipe_config.output_info[0] w=%d, h=%d.\n",
209 p_config->output_info[0].res.width,
210 p_config->output_info[0].res.height);
212 "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
213 p_config->vf_pp_in_res.width,
214 p_config->vf_pp_in_res.height);
216 "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
217 p_config->capt_pp_in_res.width,
218 p_config->capt_pp_in_res.height);
220 "pipe_config.output.padded w=%d.\n",
221 p_config->output_info[0].padded_width);
223 "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
224 p_config->vf_output_info[0].res.width,
225 p_config->vf_output_info[0].res.height);
227 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
228 p_config->bayer_ds_out_res.width,
229 p_config->bayer_ds_out_res.height);
231 "pipe_config.envelope w=%d, h=%d.\n",
232 p_config->dvs_envelope.width,
233 p_config->dvs_envelope.height);
235 "pipe_config.dvs_frame_delay=%d.\n",
236 p_config->dvs_frame_delay);
238 "pipe_config.isp_pipe_version:%d.\n",
239 p_config->isp_pipe_version);
241 "pipe_config.acc_extension=%p.\n",
242 p_config->acc_extension);
244 "pipe_config.acc_stages=%p.\n",
245 p_config->acc_stages);
247 "pipe_config.num_acc_stages=%d.\n",
248 p_config->num_acc_stages);
250 "pipe_config.acc_num_execs=%d.\n",
251 p_config->acc_num_execs);
253 "pipe_config.default_capture_config.capture_mode=%d.\n",
254 p_config->default_capture_config.mode);
256 "pipe_config.enable_dz=%d.\n",
257 p_config->enable_dz);
259 "pipe_config.default_capture_config.enable_xnr=%d.\n",
260 p_config->default_capture_config.enable_xnr);
262 "dumping pipe[%d] extra config:\n", pipe_id);
264 "pipe_extra_config.enable_raw_binning:%d.\n",
265 pe_config->enable_raw_binning);
267 "pipe_extra_config.enable_yuv_ds:%d.\n",
268 pe_config->enable_yuv_ds);
270 "pipe_extra_config.enable_high_speed:%d.\n",
271 pe_config->enable_high_speed);
273 "pipe_extra_config.enable_dvs_6axis:%d.\n",
274 pe_config->enable_dvs_6axis);
276 "pipe_extra_config.enable_reduced_pipe:%d.\n",
277 pe_config->enable_reduced_pipe);
279 "pipe_(extra_)config.enable_dz:%d.\n",
280 p_config->enable_dz);
282 "pipe_extra_config.disable_vf_pp:%d.\n",
283 pe_config->disable_vf_pp);
287 static void __dump_stream_config(struct atomisp_sub_device *asd,
288 struct atomisp_stream_env *stream_env)
290 struct atomisp_device *isp = asd->isp;
291 struct ia_css_stream_config *s_config;
293 bool valid_stream = false;
295 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
296 if (stream_env->pipes[j]) {
297 __dump_pipe_config(asd, stream_env, j);
303 s_config = &stream_env->stream_config;
304 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
306 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
307 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
308 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
309 s_config->source.port.port);
310 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
311 s_config->source.port.num_lanes);
312 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
313 s_config->source.port.timeout);
314 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
315 s_config->source.port.rxcount);
316 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
317 s_config->source.port.compression.type);
319 "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
320 s_config->source.port.compression.
321 compressed_bits_per_pixel);
323 "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
324 s_config->source.port.compression.
325 uncompressed_bits_per_pixel);
326 } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
327 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
328 s_config->source.tpg.id);
329 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
330 s_config->source.tpg.mode);
331 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
332 s_config->source.tpg.x_mask);
333 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
334 s_config->source.tpg.x_delta);
335 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
336 s_config->source.tpg.y_mask);
337 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
338 s_config->source.tpg.y_delta);
339 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
340 s_config->source.tpg.xy_mask);
341 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
342 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
343 s_config->source.prbs.id);
344 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
345 s_config->source.prbs.h_blank);
346 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
347 s_config->source.prbs.v_blank);
348 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
349 s_config->source.prbs.seed);
350 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
351 s_config->source.prbs.seed1);
354 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
355 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
357 s_config->isys_config[j].input_res.width,
358 s_config->isys_config[j].input_res.height);
360 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
362 s_config->isys_config[j].linked_isys_stream_id);
364 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
366 s_config->isys_config[j].format);
368 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
370 s_config->isys_config[j].valid);
373 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
374 s_config->input_config.input_res.width,
375 s_config->input_config.input_res.height);
377 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
378 s_config->input_config.effective_res.width,
379 s_config->input_config.effective_res.height);
381 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
382 s_config->input_config.format);
384 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
385 s_config->input_config.bayer_order);
387 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
388 s_config->pixels_per_clock);
389 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
390 dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
391 s_config->continuous);
392 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
393 s_config->disable_cont_viewfinder);
394 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
395 s_config->channel_id);
396 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
397 s_config->init_num_cont_raw_buf);
398 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
399 s_config->target_num_cont_raw_buf);
400 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
401 s_config->left_padding);
402 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
403 s_config->sensor_binning_factor);
404 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
405 s_config->pixels_per_clock);
406 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
407 s_config->pack_raw_pixels);
408 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
409 s_config->flash_gpio_pin);
410 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
411 s_config->mipi_buffer_config.size_mem_words);
412 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
413 s_config->mipi_buffer_config.contiguous);
414 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
415 s_config->metadata_config.data_type);
416 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
417 s_config->metadata_config.resolution.width,
418 s_config->metadata_config.resolution.height);
421 static int __destroy_stream(struct atomisp_sub_device *asd,
422 struct atomisp_stream_env *stream_env, bool force)
424 struct atomisp_device *isp = asd->isp;
426 unsigned long timeout;
428 if (!stream_env->stream)
432 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
433 if (stream_env->update_pipe[i])
436 if (i == IA_CSS_PIPE_ID_NUM)
440 if (stream_env->stream_state == CSS_STREAM_STARTED
441 && ia_css_stream_stop(stream_env->stream) != 0) {
442 dev_err(isp->dev, "stop stream failed.\n");
446 if (stream_env->stream_state == CSS_STREAM_STARTED) {
447 timeout = jiffies + msecs_to_jiffies(40);
449 if (ia_css_stream_has_stopped(stream_env->stream))
452 if (time_after(jiffies, timeout)) {
453 dev_warn(isp->dev, "stop stream timeout.\n");
457 usleep_range(100, 200);
461 stream_env->stream_state = CSS_STREAM_STOPPED;
463 if (ia_css_stream_destroy(stream_env->stream)) {
464 dev_err(isp->dev, "destroy stream failed.\n");
467 stream_env->stream_state = CSS_STREAM_UNINIT;
468 stream_env->stream = NULL;
473 static int __destroy_streams(struct atomisp_sub_device *asd, bool force)
477 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
478 ret = __destroy_stream(asd, &asd->stream_env[i], force);
482 asd->stream_prepared = false;
486 static int __create_stream(struct atomisp_sub_device *asd,
487 struct atomisp_stream_env *stream_env)
489 int pipe_index = 0, i;
490 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
492 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
493 if (stream_env->pipes[i])
494 multi_pipes[pipe_index++] = stream_env->pipes[i];
499 stream_env->stream_config.target_num_cont_raw_buf =
500 asd->continuous_raw_buffer_size->val;
501 stream_env->stream_config.channel_id = stream_env->ch_id;
502 stream_env->stream_config.ia_css_enable_raw_buffer_locking =
503 asd->enable_raw_buffer_lock->val;
505 __dump_stream_config(asd, stream_env);
506 if (ia_css_stream_create(&stream_env->stream_config,
507 pipe_index, multi_pipes, &stream_env->stream) != 0)
509 if (ia_css_stream_get_info(stream_env->stream,
510 &stream_env->stream_info) != 0) {
511 ia_css_stream_destroy(stream_env->stream);
512 stream_env->stream = NULL;
516 stream_env->stream_state = CSS_STREAM_CREATED;
520 static int __create_streams(struct atomisp_sub_device *asd)
524 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
525 ret = __create_stream(asd, &asd->stream_env[i]);
529 asd->stream_prepared = true;
532 for (i--; i >= 0; i--)
533 __destroy_stream(asd, &asd->stream_env[i], true);
537 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
538 struct atomisp_stream_env *stream_env,
541 struct atomisp_device *isp = asd->isp;
545 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
546 if (!stream_env->pipes[i] ||
547 !(force || stream_env->update_pipe[i]))
549 if (ia_css_pipe_destroy(stream_env->pipes[i])
552 "destroy pipe[%d]failed.cannot recover.\n", i);
555 stream_env->pipes[i] = NULL;
556 stream_env->update_pipe[i] = false;
561 static int __destroy_pipes(struct atomisp_sub_device *asd, bool force)
563 struct atomisp_device *isp = asd->isp;
567 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
568 if (asd->stream_env[i].stream) {
570 "cannot destroy css pipes for stream[%d].\n",
575 ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force);
583 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
585 __destroy_streams(asd, true);
586 __destroy_pipes(asd, true);
589 static void __apply_additional_pipe_config(
590 struct atomisp_sub_device *asd,
591 struct atomisp_stream_env *stream_env,
592 enum ia_css_pipe_id pipe_id)
594 struct atomisp_device *isp = asd->isp;
596 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
598 "wrong pipe_id for additional pipe config.\n");
602 /* apply default pipe config */
603 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
604 stream_env->pipe_configs[pipe_id].enable_dz =
605 asd->disable_dz->val ? false : true;
606 /* apply isp 2.2 specific config for baytrail*/
608 case IA_CSS_PIPE_ID_CAPTURE:
609 /* enable capture pp/dz manually or digital zoom would
611 if (stream_env->pipe_configs[pipe_id].
612 default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW)
613 stream_env->pipe_configs[pipe_id].enable_dz = false;
615 case IA_CSS_PIPE_ID_VIDEO:
616 /* enable reduced pipe to have binary
617 * video_dz_2_min selected*/
618 stream_env->pipe_extra_configs[pipe_id]
619 .enable_reduced_pipe = true;
620 stream_env->pipe_configs[pipe_id]
622 if (ATOMISP_SOC_CAMERA(asd))
623 stream_env->pipe_configs[pipe_id].enable_dz = true;
625 if (asd->params.video_dis_en) {
626 stream_env->pipe_extra_configs[pipe_id]
627 .enable_dvs_6axis = true;
628 stream_env->pipe_configs[pipe_id]
630 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
633 case IA_CSS_PIPE_ID_PREVIEW:
635 case IA_CSS_PIPE_ID_YUVPP:
636 case IA_CSS_PIPE_ID_COPY:
637 if (ATOMISP_SOC_CAMERA(asd))
638 stream_env->pipe_configs[pipe_id].enable_dz = true;
640 stream_env->pipe_configs[pipe_id].enable_dz = false;
642 case IA_CSS_PIPE_ID_ACC:
643 stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC;
644 stream_env->pipe_configs[pipe_id].enable_dz = false;
651 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
652 enum ia_css_pipe_id pipe_id)
657 if (pipe_id == IA_CSS_PIPE_ID_ACC || pipe_id == IA_CSS_PIPE_ID_YUVPP)
661 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
662 if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
666 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
667 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
677 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
680 switch (asd->run_mode->val) {
681 case ATOMISP_RUN_MODE_STILL_CAPTURE:
682 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
686 case ATOMISP_RUN_MODE_PREVIEW:
687 if (!asd->continuous_mode->val) {
688 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
694 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
695 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
696 pipe_id == IA_CSS_PIPE_ID_PREVIEW)
700 case ATOMISP_RUN_MODE_VIDEO:
701 if (!asd->continuous_mode->val) {
702 if (pipe_id == IA_CSS_PIPE_ID_VIDEO ||
703 pipe_id == IA_CSS_PIPE_ID_YUVPP)
709 case ATOMISP_RUN_MODE_SDV:
710 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
711 pipe_id == IA_CSS_PIPE_ID_VIDEO)
720 static int __create_pipe(struct atomisp_sub_device *asd,
721 struct atomisp_stream_env *stream_env,
722 enum ia_css_pipe_id pipe_id)
724 struct atomisp_device *isp = asd->isp;
725 struct ia_css_pipe_extra_config extra_config;
728 if (pipe_id >= IA_CSS_PIPE_ID_NUM)
731 if (pipe_id != IA_CSS_PIPE_ID_ACC &&
732 !stream_env->pipe_configs[pipe_id].output_info[0].res.width)
735 if (pipe_id == IA_CSS_PIPE_ID_ACC &&
736 !stream_env->pipe_configs[pipe_id].acc_extension)
739 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
742 ia_css_pipe_extra_config_defaults(&extra_config);
744 __apply_additional_pipe_config(asd, stream_env, pipe_id);
745 if (!memcmp(&extra_config,
746 &stream_env->pipe_extra_configs[pipe_id],
747 sizeof(extra_config)))
748 ret = ia_css_pipe_create(
749 &stream_env->pipe_configs[pipe_id],
750 &stream_env->pipes[pipe_id]);
752 ret = ia_css_pipe_create_extra(
753 &stream_env->pipe_configs[pipe_id],
754 &stream_env->pipe_extra_configs[pipe_id],
755 &stream_env->pipes[pipe_id]);
757 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
761 static int __create_pipes(struct atomisp_sub_device *asd)
766 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
767 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
768 ret = __create_pipe(asd, &asd->stream_env[i], j);
772 if (j < IA_CSS_PIPE_ID_NUM)
777 for (; i >= 0; i--) {
778 for (j--; j >= 0; j--) {
779 if (asd->stream_env[i].pipes[j]) {
780 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
781 asd->stream_env[i].pipes[j] = NULL;
784 j = IA_CSS_PIPE_ID_NUM;
789 void atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
792 __create_streams(asd);
795 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
798 struct atomisp_device *isp = asd->isp;
800 if (__destroy_streams(asd, true))
801 dev_warn(isp->dev, "destroy stream failed.\n");
803 if (__destroy_pipes(asd, true))
804 dev_warn(isp->dev, "destroy pipe failed.\n");
806 ret = __create_pipes(asd);
808 dev_err(isp->dev, "create pipe failed %d.\n", ret);
812 ret = __create_streams(asd);
814 dev_warn(isp->dev, "create stream failed %d.\n", ret);
815 __destroy_pipes(asd, true);
822 int atomisp_css_init(struct atomisp_device *isp)
824 unsigned int mmu_base_addr;
828 ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
833 err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
834 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
836 dev_err(isp->dev, "css init failed --- bad firmware?\n");
839 ia_css_enable_isys_event_queue(true);
841 isp->css_initialized = true;
842 dev_dbg(isp->dev, "sh_css_init success\n");
847 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
852 isp->css_env.isp_css_env.print_env.debug_print = NULL;
854 isp->css_env.isp_css_env.print_env.debug_print =
855 atomisp_css2_dbg_ftrace_print;
857 isp->css_env.isp_css_env.print_env.debug_print = atomisp_vprintk;
864 int atomisp_css_load_firmware(struct atomisp_device *isp)
869 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
870 isp->css_env.isp_css_fw.bytes = isp->firmware->size;
872 isp->css_env.isp_css_env.hw_access_env.store_8 =
873 atomisp_css2_hw_store_8;
874 isp->css_env.isp_css_env.hw_access_env.store_16 =
875 atomisp_css2_hw_store_16;
876 isp->css_env.isp_css_env.hw_access_env.store_32 =
877 atomisp_css2_hw_store_32;
879 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
880 isp->css_env.isp_css_env.hw_access_env.load_16 =
881 atomisp_css2_hw_load_16;
882 isp->css_env.isp_css_env.hw_access_env.load_32 =
883 atomisp_css2_hw_load_32;
885 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
886 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
888 __set_css_print_env(isp, dbg_func);
890 isp->css_env.isp_css_env.print_env.error_print = atomisp_vprintk;
892 /* load isp fw into ISP memory */
893 err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env,
894 &isp->css_env.isp_css_fw);
896 dev_err(isp->dev, "css load fw failed.\n");
903 void atomisp_css_uninit(struct atomisp_device *isp)
905 struct atomisp_sub_device *asd;
908 for (i = 0; i < isp->num_of_streams; i++) {
910 memset(&asd->params.config, 0, sizeof(asd->params.config));
911 asd->params.css_update_params_needed = false;
914 isp->css_initialized = false;
918 void atomisp_css_suspend(struct atomisp_device *isp)
920 isp->css_initialized = false;
924 int atomisp_css_resume(struct atomisp_device *isp)
926 unsigned int mmu_base_addr;
929 ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
931 dev_err(isp->dev, "get base address error.\n");
935 ret = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
936 mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
938 dev_err(isp->dev, "re-init css failed.\n");
941 ia_css_enable_isys_event_queue(true);
943 isp->css_initialized = true;
947 int atomisp_css_irq_translate(struct atomisp_device *isp,
952 err = ia_css_irq_translate(infos);
955 "%s:failed to translate irq (err = %d,infos = %d)\n",
956 __func__, err, *infos);
963 void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
967 ia_css_isys_rx_get_irq_info(port, infos);
973 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
977 ia_css_isys_rx_clear_irq_info(port, infos);
981 int atomisp_css_irq_enable(struct atomisp_device *isp,
982 enum ia_css_irq_info info, bool enable)
984 dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s (%d).\n",
986 enable ? "enable" : "disable", enable);
987 if (ia_css_irq_enable(info, enable)) {
988 dev_warn(isp->dev, "%s:Invalid irq info: 0x%08x when %s.\n",
990 enable ? "enabling" : "disabling");
997 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
1001 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1002 asd->stream_env[i].stream = NULL;
1003 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
1004 asd->stream_env[i].pipes[j] = NULL;
1005 asd->stream_env[i].update_pipe[j] = false;
1006 ia_css_pipe_config_defaults(
1007 &asd->stream_env[i].pipe_configs[j]);
1008 ia_css_pipe_extra_config_defaults(
1009 &asd->stream_env[i].pipe_extra_configs[j]);
1011 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
1015 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
1016 struct videobuf_vmalloc_memory *vm_mem,
1017 enum atomisp_input_stream_id stream_id,
1018 enum ia_css_buffer_type css_buf_type,
1019 enum ia_css_pipe_id css_pipe_id)
1021 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1022 struct ia_css_buffer css_buf = {0};
1025 css_buf.type = css_buf_type;
1026 css_buf.data.frame = vm_mem->vaddr;
1028 err = ia_css_pipe_enqueue_buffer(
1029 stream_env->pipes[css_pipe_id], &css_buf);
1036 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
1037 struct atomisp_metadata_buf *metadata_buf,
1038 enum atomisp_input_stream_id stream_id,
1039 enum ia_css_pipe_id css_pipe_id)
1041 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1042 struct ia_css_buffer buffer = {0};
1043 struct atomisp_device *isp = asd->isp;
1045 buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
1046 buffer.data.metadata = metadata_buf->metadata;
1047 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
1049 dev_err(isp->dev, "failed to q meta data buffer\n");
1056 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
1057 struct atomisp_s3a_buf *s3a_buf,
1058 enum atomisp_input_stream_id stream_id,
1059 enum ia_css_pipe_id css_pipe_id)
1061 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1062 struct ia_css_buffer buffer = {0};
1063 struct atomisp_device *isp = asd->isp;
1065 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
1066 buffer.data.stats_3a = s3a_buf->s3a_data;
1067 if (ia_css_pipe_enqueue_buffer(
1068 stream_env->pipes[css_pipe_id],
1070 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
1077 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
1078 struct atomisp_dis_buf *dis_buf,
1079 enum atomisp_input_stream_id stream_id,
1080 enum ia_css_pipe_id css_pipe_id)
1082 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1083 struct ia_css_buffer buffer = {0};
1084 struct atomisp_device *isp = asd->isp;
1086 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
1087 buffer.data.stats_dvs = dis_buf->dis_data;
1088 if (ia_css_pipe_enqueue_buffer(
1089 stream_env->pipes[css_pipe_id],
1091 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
1098 int atomisp_css_start(struct atomisp_sub_device *asd,
1099 enum ia_css_pipe_id pipe_id, bool in_reset)
1101 struct atomisp_device *isp = asd->isp;
1102 bool sp_is_started = false;
1106 if (__destroy_streams(asd, true))
1107 dev_warn(isp->dev, "destroy stream failed.\n");
1109 if (__destroy_pipes(asd, true))
1110 dev_warn(isp->dev, "destroy pipe failed.\n");
1112 if (__create_pipes(asd)) {
1113 dev_err(isp->dev, "create pipe error.\n");
1116 if (__create_streams(asd)) {
1117 dev_err(isp->dev, "create stream error.\n");
1121 /* in_reset == true, extension firmwares are reloaded after the recovery */
1122 atomisp_acc_load_extensions(asd);
1126 * For dual steam case, it is possible that:
1127 * 1: for this stream, it is at the stage that:
1128 * - after set_fmt is called
1129 * - before stream on is called
1130 * 2: for the other stream, the stream off is called which css reset
1133 * Thus the stream created in set_fmt get destroyed and need to be
1134 * recreated in the next stream on.
1136 if (!asd->stream_prepared) {
1137 if (__create_pipes(asd)) {
1138 dev_err(isp->dev, "create pipe error.\n");
1141 if (__create_streams(asd)) {
1142 dev_err(isp->dev, "create stream error.\n");
1148 * SP can only be started one time
1149 * if atomisp_subdev_streaming_count() tell there already has some
1150 * subdev at streamming, then SP should already be started previously,
1151 * so need to skip start sp procedure
1153 if (atomisp_streaming_count(isp)) {
1154 dev_dbg(isp->dev, "skip start sp\n");
1156 if (!sh_css_hrt_system_is_idle())
1157 dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1158 if (ia_css_start_sp()) {
1159 dev_err(isp->dev, "start sp error.\n");
1163 sp_is_started = true;
1167 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1168 if (asd->stream_env[i].stream) {
1169 if (ia_css_stream_start(asd->stream_env[i]
1171 dev_err(isp->dev, "stream[%d] start error.\n", i);
1175 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1176 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1184 __destroy_streams(asd, true);
1186 __destroy_pipes(asd, true);
1188 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1192 * SP can not be stop if other streams are in use
1194 if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1200 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1204 * for ISP2401 new input system, this api is under development.
1205 * Calling it would cause kernel panic.
1209 * Check if it is Cherry Trail and also new input system
1211 if (asd->copy_mode) {
1212 dev_warn(asd->isp->dev,
1213 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1218 ia_css_stream_set_isp_config(
1219 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1220 &asd->params.config);
1221 memset(&asd->params.config, 0, sizeof(asd->params.config));
1224 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1225 struct ia_css_pipe *pipe)
1230 atomisp_css_update_isp_params(asd);
1234 dev_dbg(asd->isp->dev,
1235 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1236 __func__, asd->params.config.output_frame,
1237 asd->params.config.isp_config_id, pipe);
1239 ret = ia_css_stream_set_isp_config_on_pipe(
1240 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1241 &asd->params.config, pipe);
1243 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1245 memset(&asd->params.config, 0, sizeof(asd->params.config));
1248 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1249 enum atomisp_input_stream_id stream_id,
1250 enum ia_css_pipe_id pipe_id,
1251 enum ia_css_buffer_type buf_type,
1252 struct atomisp_css_buffer *isp_css_buffer)
1254 if (ia_css_pipe_enqueue_buffer(
1255 asd->stream_env[stream_id].pipes[pipe_id],
1256 &isp_css_buffer->css_buffer)
1263 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1264 enum atomisp_input_stream_id stream_id,
1265 enum ia_css_pipe_id pipe_id,
1266 enum ia_css_buffer_type buf_type,
1267 struct atomisp_css_buffer *isp_css_buffer)
1269 struct atomisp_device *isp = asd->isp;
1272 err = ia_css_pipe_dequeue_buffer(
1273 asd->stream_env[stream_id].pipes[pipe_id],
1274 &isp_css_buffer->css_buffer);
1277 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1284 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd,
1286 struct atomisp_s3a_buf *s3a_buf,
1287 struct atomisp_dis_buf *dis_buf,
1288 struct atomisp_metadata_buf *md_buf)
1290 struct atomisp_device *isp = asd->isp;
1291 struct ia_css_dvs_grid_info *dvs_grid_info =
1292 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1294 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1297 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1298 &asd->params.curr_grid_info.s3a_grid);
1299 if (!s3a_buf->s3a_data) {
1300 dev_err(isp->dev, "3a buf allocation failed.\n");
1304 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1305 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1306 s3a_buf->s3a_data, s3a_ptr);
1309 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1312 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1314 if (!dis_buf->dis_data) {
1315 dev_err(isp->dev, "dvs buf allocation failed.\n");
1317 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1321 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1322 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1323 dis_buf->dis_data, dvs_ptr);
1326 if (asd->stream_env[stream_id].stream_info.
1327 metadata_info.size && md_buf) {
1328 md_buf->metadata = ia_css_metadata_allocate(
1329 &asd->stream_env[stream_id].stream_info.metadata_info);
1330 if (!md_buf->metadata) {
1332 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1334 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1335 dev_err(isp->dev, "metadata buf allocation failed.\n");
1338 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1344 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1346 if (s3a_buf->s3a_data)
1347 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1349 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1350 s3a_buf->s3a_map = NULL;
1351 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1354 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1356 if (dis_buf->dis_data)
1357 hmm_vunmap(dis_buf->dis_data->data_ptr);
1359 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1360 dis_buf->dvs_map = NULL;
1361 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1364 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1366 if (metadata_buf->md_vptr) {
1367 hmm_vunmap(metadata_buf->metadata->address);
1368 metadata_buf->md_vptr = NULL;
1370 ia_css_metadata_free(metadata_buf->metadata);
1373 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1375 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1376 struct atomisp_dis_buf *dis_buf, *_dis_buf;
1377 struct atomisp_metadata_buf *md_buf, *_md_buf;
1378 struct ia_css_dvs_grid_info *dvs_grid_info =
1379 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1382 /* 3A statistics use vmalloc, DIS use kmalloc */
1383 if (dvs_grid_info && dvs_grid_info->enable) {
1384 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1385 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1386 asd->params.css_param.dvs2_coeff = NULL;
1387 asd->params.dvs_stat = NULL;
1388 asd->params.dvs_hor_proj_bytes = 0;
1389 asd->params.dvs_ver_proj_bytes = 0;
1390 asd->params.dvs_hor_coef_bytes = 0;
1391 asd->params.dvs_ver_coef_bytes = 0;
1392 asd->params.dis_proj_data_valid = false;
1393 list_for_each_entry_safe(dis_buf, _dis_buf,
1394 &asd->dis_stats, list) {
1395 atomisp_css_free_dis_buffer(dis_buf);
1396 list_del(&dis_buf->list);
1399 list_for_each_entry_safe(dis_buf, _dis_buf,
1400 &asd->dis_stats_in_css, list) {
1401 atomisp_css_free_dis_buffer(dis_buf);
1402 list_del(&dis_buf->list);
1406 if (asd->params.curr_grid_info.s3a_grid.enable) {
1407 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1408 asd->params.s3a_user_stat = NULL;
1409 asd->params.s3a_output_bytes = 0;
1410 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1411 &asd->s3a_stats, list) {
1412 atomisp_css_free_3a_buffer(s3a_buf);
1413 list_del(&s3a_buf->list);
1416 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1417 &asd->s3a_stats_in_css, list) {
1418 atomisp_css_free_3a_buffer(s3a_buf);
1419 list_del(&s3a_buf->list);
1422 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1423 &asd->s3a_stats_ready, list) {
1424 atomisp_css_free_3a_buffer(s3a_buf);
1425 list_del(&s3a_buf->list);
1430 if (asd->params.css_param.dvs_6axis) {
1431 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1432 asd->params.css_param.dvs_6axis = NULL;
1435 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1436 list_for_each_entry_safe(md_buf, _md_buf,
1437 &asd->metadata[i], list) {
1438 atomisp_css_free_metadata_buffer(md_buf);
1439 list_del(&md_buf->list);
1442 list_for_each_entry_safe(md_buf, _md_buf,
1443 &asd->metadata_in_css[i], list) {
1444 atomisp_css_free_metadata_buffer(md_buf);
1445 list_del(&md_buf->list);
1448 list_for_each_entry_safe(md_buf, _md_buf,
1449 &asd->metadata_ready[i], list) {
1450 atomisp_css_free_metadata_buffer(md_buf);
1451 list_del(&md_buf->list);
1455 asd->params.metadata_width_size = 0;
1456 atomisp_free_metadata_output_buf(asd);
1459 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1460 enum ia_css_pipe_id pipe_id,
1463 struct ia_css_pipe_info p_info;
1464 struct ia_css_grid_info old_info;
1465 struct atomisp_device *isp = asd->isp;
1466 int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
1467 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1468 stream_config.metadata_config.resolution.width;
1470 memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1471 memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1473 if (ia_css_pipe_get_info(
1474 asd->stream_env[stream_index].pipes[pipe_id],
1476 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1480 memcpy(&old_info, &asd->params.curr_grid_info,
1481 sizeof(struct ia_css_grid_info));
1482 memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1483 sizeof(struct ia_css_grid_info));
1485 * Record which css pipe enables s3a_grid.
1486 * Currently would have one css pipe that need it
1488 if (asd->params.curr_grid_info.s3a_grid.enable) {
1489 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM)
1490 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1491 asd->params.s3a_enabled_pipe, pipe_id);
1492 asd->params.s3a_enabled_pipe = pipe_id;
1495 /* If the grid info has not changed and the buffers for 3A and
1496 * DIS statistics buffers are allocated or buffer size would be zero
1497 * then no need to do anything. */
1498 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1499 && asd->params.s3a_user_stat && asd->params.dvs_stat)
1500 || asd->params.curr_grid_info.s3a_grid.width == 0
1501 || asd->params.curr_grid_info.s3a_grid.height == 0)
1502 && asd->params.metadata_width_size == md_width) {
1504 "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1505 !memcmp(&old_info, &asd->params.curr_grid_info,
1507 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1508 asd->params.curr_grid_info.s3a_grid.width,
1509 asd->params.curr_grid_info.s3a_grid.height,
1510 asd->params.metadata_width_size);
1513 asd->params.metadata_width_size = md_width;
1518 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1520 if (!asd->params.curr_grid_info.s3a_grid.width ||
1521 !asd->params.curr_grid_info.s3a_grid.height)
1524 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1525 &asd->params.curr_grid_info.s3a_grid);
1526 if (!asd->params.s3a_user_stat)
1528 /* 3A statistics. These can be big, so we use vmalloc. */
1529 asd->params.s3a_output_bytes =
1530 asd->params.curr_grid_info.s3a_grid.width *
1531 asd->params.curr_grid_info.s3a_grid.height *
1532 sizeof(*asd->params.s3a_user_stat->data);
1537 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1539 struct ia_css_dvs_grid_info *dvs_grid =
1540 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1545 if (!dvs_grid->enable) {
1546 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1550 /* DIS coefficients. */
1551 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1553 if (!asd->params.css_param.dvs2_coeff)
1556 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1557 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1559 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1560 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1562 /* DIS projections. */
1563 asd->params.dis_proj_data_valid = false;
1564 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1565 if (!asd->params.dvs_stat)
1568 asd->params.dvs_hor_proj_bytes =
1569 dvs_grid->aligned_height * dvs_grid->aligned_width *
1570 sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1572 asd->params.dvs_ver_proj_bytes =
1573 dvs_grid->aligned_height * dvs_grid->aligned_width *
1574 sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1579 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1583 /* We allocate the cpu-side buffer used for communication with user
1585 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1586 asd->params.metadata_user[i] = kvmalloc(
1587 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1588 stream_info.metadata_info.size, GFP_KERNEL);
1589 if (!asd->params.metadata_user[i]) {
1591 kvfree(asd->params.metadata_user[i]);
1592 asd->params.metadata_user[i] = NULL;
1601 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1605 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1606 if (asd->params.metadata_user[i]) {
1607 kvfree(asd->params.metadata_user[i]);
1608 asd->params.metadata_user[i] = NULL;
1613 void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd,
1614 struct atomisp_css_buffer *isp_css_buffer,
1615 struct ia_css_isp_dvs_statistics_map *dvs_map)
1617 if (asd->params.dvs_stat) {
1619 ia_css_translate_dvs2_statistics(
1620 asd->params.dvs_stat, dvs_map);
1622 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
1623 isp_css_buffer->css_buffer.data.stats_dvs);
1627 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1628 struct atomisp_css_event *current_event)
1632 * Pipe ID reported in CSS event is not correct for new system's
1636 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1637 ¤t_event->pipe);
1638 if (asd && asd->copy_mode &&
1639 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1640 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1643 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1644 enum atomisp_input_stream_id stream_id,
1645 struct v4l2_mbus_framefmt *ffmt,
1648 struct ia_css_stream_config *s_config =
1649 &asd->stream_env[stream_id].stream_config;
1651 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1654 s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1655 s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1659 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1660 enum atomisp_input_stream_id stream_id,
1661 struct v4l2_mbus_framefmt *ffmt)
1663 struct ia_css_stream_config *s_config =
1664 &asd->stream_env[stream_id].stream_config;
1666 s_config->input_config.input_res.width = ffmt->width;
1667 s_config->input_config.input_res.height = ffmt->height;
1671 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1672 enum atomisp_input_stream_id stream_id,
1673 unsigned int bin_factor)
1675 asd->stream_env[stream_id]
1676 .stream_config.sensor_binning_factor = bin_factor;
1679 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1680 enum atomisp_input_stream_id stream_id,
1681 enum ia_css_bayer_order bayer_order)
1683 struct ia_css_stream_config *s_config =
1684 &asd->stream_env[stream_id].stream_config;
1685 s_config->input_config.bayer_order = bayer_order;
1688 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1689 enum atomisp_input_stream_id stream_id,
1693 struct ia_css_stream_config *s_config =
1694 &asd->stream_env[stream_id].stream_config;
1696 s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1699 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1700 enum atomisp_input_stream_id stream_id,
1704 struct ia_css_stream_config *s_config =
1705 &asd->stream_env[stream_id].stream_config;
1707 s_config->isys_config[isys_stream].valid = valid;
1710 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1711 enum atomisp_input_stream_id stream_id,
1712 enum atomisp_input_format format,
1715 struct ia_css_stream_config *s_config =
1716 &asd->stream_env[stream_id].stream_config;
1718 s_config->isys_config[isys_stream].format = format;
1721 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1722 enum atomisp_input_stream_id stream_id,
1723 enum atomisp_input_format format)
1725 struct ia_css_stream_config *s_config =
1726 &asd->stream_env[stream_id].stream_config;
1728 s_config->input_config.format = format;
1731 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1732 enum atomisp_input_stream_id stream_id,
1733 struct v4l2_mbus_framefmt *ffmt)
1736 struct ia_css_stream_config *s_config =
1737 &asd->stream_env[stream_id].stream_config;
1739 * Set all isys configs to not valid.
1740 * Currently we support only one stream per channel
1742 for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1743 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1744 s_config->isys_config[i].valid = false;
1746 atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1747 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1748 atomisp_css_isys_set_format(asd, stream_id,
1749 s_config->input_config.format,
1750 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1751 atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1752 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1753 atomisp_css_isys_set_valid(asd, stream_id, true,
1754 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1759 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1760 enum atomisp_input_stream_id stream_id,
1761 enum atomisp_input_format input_format)
1763 struct ia_css_stream_config *s_config =
1764 &asd->stream_env[stream_id].stream_config;
1766 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1767 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1769 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1770 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1772 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1773 = IA_CSS_STREAM_ISYS_STREAM_0;
1774 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1775 ATOMISP_INPUT_FORMAT_USER_DEF1;
1776 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1777 ATOMISP_INPUT_FORMAT_USER_DEF2;
1778 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1782 void atomisp_css_isys_two_stream_cfg_update_stream1(
1783 struct atomisp_sub_device *asd,
1784 enum atomisp_input_stream_id stream_id,
1785 enum atomisp_input_format input_format,
1786 unsigned int width, unsigned int height)
1788 struct ia_css_stream_config *s_config =
1789 &asd->stream_env[stream_id].stream_config;
1791 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1793 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1795 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1797 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1800 void atomisp_css_isys_two_stream_cfg_update_stream2(
1801 struct atomisp_sub_device *asd,
1802 enum atomisp_input_stream_id stream_id,
1803 enum atomisp_input_format input_format,
1804 unsigned int width, unsigned int height)
1806 struct ia_css_stream_config *s_config =
1807 &asd->stream_env[stream_id].stream_config;
1809 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1811 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1813 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1814 = IA_CSS_STREAM_ISYS_STREAM_0;
1815 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1817 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1820 int atomisp_css_input_set_effective_resolution(
1821 struct atomisp_sub_device *asd,
1822 enum atomisp_input_stream_id stream_id,
1823 unsigned int width, unsigned int height)
1825 struct ia_css_stream_config *s_config =
1826 &asd->stream_env[stream_id].stream_config;
1827 s_config->input_config.effective_res.width = width;
1828 s_config->input_config.effective_res.height = height;
1832 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1833 unsigned int dvs_w, unsigned int dvs_h)
1835 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1836 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1837 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1838 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1841 void atomisp_css_input_set_two_pixels_per_clock(
1842 struct atomisp_sub_device *asd,
1847 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1848 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1851 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1852 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1853 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1854 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1855 .update_pipe[i] = true;
1858 void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
1861 struct atomisp_stream_env *stream_env =
1862 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1865 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
1866 pipe = IA_CSS_PIPE_ID_VIDEO;
1868 pipe = IA_CSS_PIPE_ID_PREVIEW;
1870 stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable;
1871 stream_env->update_pipe[pipe] = true;
1873 stream_env->pipe_configs[pipe].output_info[0].padded_width =
1874 stream_env->stream_config.input_config.effective_res.width;
1877 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1881 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1882 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1883 .pipe_configs[i].enable_dz = enable;
1886 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1887 enum ia_css_capture_mode mode)
1889 struct atomisp_stream_env *stream_env =
1890 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1892 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1893 .default_capture_config.mode == mode)
1896 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1897 default_capture_config.mode = mode;
1898 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1901 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
1902 enum ia_css_input_mode mode)
1905 struct atomisp_device *isp = asd->isp;
1906 unsigned int size_mem_words;
1908 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
1909 asd->stream_env[i].stream_config.mode = mode;
1911 if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
1912 struct ia_css_stream_config *s_config =
1913 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
1914 s_config->mode = IA_CSS_INPUT_MODE_TPG;
1915 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
1916 s_config->source.tpg.x_mask = (1 << 4) - 1;
1917 s_config->source.tpg.x_delta = -2;
1918 s_config->source.tpg.y_mask = (1 << 4) - 1;
1919 s_config->source.tpg.y_delta = 3;
1920 s_config->source.tpg.xy_mask = (1 << 8) - 1;
1924 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1927 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1929 * TODO: sensor needs to export the embedded_data_size_words
1930 * information to atomisp for each setting.
1931 * Here using a large safe value.
1933 struct ia_css_stream_config *s_config =
1934 &asd->stream_env[i].stream_config;
1936 if (s_config->input_config.input_res.width == 0)
1939 if (ia_css_mipi_frame_calculate_size(
1940 s_config->input_config.input_res.width,
1941 s_config->input_config.input_res.height,
1942 s_config->input_config.format,
1945 &size_mem_words) != 0) {
1947 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
1949 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
1950 dev_warn(asd->isp->dev,
1951 "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n",
1954 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
1955 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
1959 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
1960 unsigned short stream_index, bool enable)
1962 struct atomisp_stream_env *stream_env =
1963 &asd->stream_env[stream_index];
1965 if (stream_env->stream_config.online == !!enable)
1968 stream_env->stream_config.online = !!enable;
1969 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1972 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
1973 unsigned short stream_index, bool enable)
1975 struct atomisp_stream_env *stream_env =
1976 &asd->stream_env[stream_index];
1979 if (stream_env->stream_config.online != !!enable) {
1980 stream_env->stream_config.online = !!enable;
1981 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1982 stream_env->update_pipe[i] = true;
1986 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
1989 struct atomisp_stream_env *stream_env =
1990 &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
1993 if (stream_env->stream_config.online != enable) {
1994 stream_env->stream_config.online = enable;
1995 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1996 stream_env->update_pipe[i] = true;
2000 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
2003 struct atomisp_stream_env *stream_env =
2004 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2008 * To SOC camera, there is only one YUVPP pipe in any case
2009 * including ZSL/SDV/continuous viewfinder, so always set
2010 * stream_config.continuous to 0.
2012 if (ATOMISP_USE_YUVPP(asd)) {
2013 stream_env->stream_config.continuous = 0;
2014 stream_env->stream_config.online = 1;
2018 if (stream_env->stream_config.continuous != !!enable) {
2019 stream_env->stream_config.continuous = !!enable;
2020 stream_env->stream_config.pack_raw_pixels = true;
2021 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2022 stream_env->update_pipe[i] = true;
2026 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
2029 struct atomisp_stream_env *stream_env =
2030 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2033 if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
2034 stream_env->stream_config.disable_cont_viewfinder = !enable;
2035 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2036 stream_env->update_pipe[i] = true;
2040 int atomisp_css_input_configure_port(
2041 struct atomisp_sub_device *asd,
2042 enum mipi_port_id port,
2043 unsigned int num_lanes,
2044 unsigned int timeout,
2045 unsigned int mipi_freq,
2046 enum atomisp_input_format metadata_format,
2047 unsigned int metadata_width,
2048 unsigned int metadata_height)
2051 struct atomisp_stream_env *stream_env;
2053 * Calculate rx_count as follows:
2054 * Input: mipi_freq : CSI-2 bus frequency in Hz
2055 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus
2056 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds
2057 * max = 145e-9 + 10 * UI
2058 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
2059 * rxcount = rxcount0 - 2 : adjust for better results
2060 * The formula below is simplified version of the above with
2061 * 10-bit fixed points for improved accuracy.
2063 const unsigned int rxcount =
2064 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
2066 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2067 stream_env = &asd->stream_env[i];
2068 stream_env->stream_config.source.port.port = port;
2069 stream_env->stream_config.source.port.num_lanes = num_lanes;
2070 stream_env->stream_config.source.port.timeout = timeout;
2072 stream_env->stream_config.source.port.rxcount = rxcount;
2073 stream_env->stream_config.
2074 metadata_config.data_type = metadata_format;
2075 stream_env->stream_config.
2076 metadata_config.resolution.width = metadata_width;
2077 stream_env->stream_config.
2078 metadata_config.resolution.height = metadata_height;
2084 void atomisp_css_stop(struct atomisp_sub_device *asd,
2085 enum ia_css_pipe_id pipe_id, bool in_reset)
2087 struct atomisp_device *isp = asd->isp;
2088 unsigned long irqflags;
2091 /* if is called in atomisp_reset(), force destroy stream */
2092 if (__destroy_streams(asd, true))
2093 dev_err(isp->dev, "destroy stream failed.\n");
2095 /* if is called in atomisp_reset(), force destroy all pipes */
2096 if (__destroy_pipes(asd, true))
2097 dev_err(isp->dev, "destroy pipes failed.\n");
2099 atomisp_init_raw_buffer_bitmap(asd);
2102 * SP can not be stop if other streams are in use
2104 if (atomisp_streaming_count(isp) == 0)
2108 struct atomisp_stream_env *stream_env;
2111 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2112 stream_env = &asd->stream_env[i];
2113 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
2114 ia_css_pipe_config_defaults(
2115 &stream_env->pipe_configs[j]);
2116 ia_css_pipe_extra_config_defaults(
2117 &stream_env->pipe_extra_configs[j]);
2119 ia_css_stream_config_defaults(
2120 &stream_env->stream_config);
2122 memset(&asd->params.config, 0, sizeof(asd->params.config));
2123 asd->params.css_update_params_needed = false;
2126 /* move stats buffers to free queue list */
2127 list_splice_init(&asd->s3a_stats_in_css, &asd->s3a_stats);
2128 list_splice_init(&asd->s3a_stats_ready, &asd->s3a_stats);
2130 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
2131 list_splice_init(&asd->dis_stats_in_css, &asd->dis_stats);
2132 asd->params.dis_proj_data_valid = false;
2133 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
2135 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
2136 list_splice_init(&asd->metadata_in_css[i], &asd->metadata[i]);
2137 list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]);
2140 atomisp_flush_params_queue(&asd->video_out_capture);
2141 atomisp_flush_params_queue(&asd->video_out_vf);
2142 atomisp_flush_params_queue(&asd->video_out_preview);
2143 atomisp_flush_params_queue(&asd->video_out_video_capture);
2144 atomisp_free_css_parameters(&asd->params.css_param);
2145 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
2148 void atomisp_css_continuous_set_num_raw_frames(
2149 struct atomisp_sub_device *asd,
2152 if (asd->enable_raw_buffer_lock->val) {
2153 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2154 .stream_config.init_num_cont_raw_buf =
2155 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
2156 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2157 asd->params.video_dis_en)
2158 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2159 .stream_config.init_num_cont_raw_buf +=
2160 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2162 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2163 .stream_config.init_num_cont_raw_buf =
2164 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
2167 if (asd->params.video_dis_en)
2168 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2169 .stream_config.init_num_cont_raw_buf +=
2170 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2172 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2173 .stream_config.target_num_cont_raw_buf = num_frames;
2176 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2177 struct atomisp_sub_device *asd,
2178 enum ia_css_pipe_id pipe_id)
2180 struct atomisp_device *isp = asd->isp;
2181 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2182 isp->inputs[asd->input_curr].camera);
2185 case IA_CSS_PIPE_ID_COPY:
2186 /* Currently only YUVPP mode supports YUV420_Legacy format.
2187 * Revert this when other pipe modes can support
2188 * YUV420_Legacy format.
2190 if (mipi_info && mipi_info->input_format ==
2191 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2192 return IA_CSS_PIPE_MODE_YUVPP;
2193 return IA_CSS_PIPE_MODE_COPY;
2194 case IA_CSS_PIPE_ID_PREVIEW:
2195 return IA_CSS_PIPE_MODE_PREVIEW;
2196 case IA_CSS_PIPE_ID_CAPTURE:
2197 return IA_CSS_PIPE_MODE_CAPTURE;
2198 case IA_CSS_PIPE_ID_VIDEO:
2199 return IA_CSS_PIPE_MODE_VIDEO;
2200 case IA_CSS_PIPE_ID_ACC:
2201 return IA_CSS_PIPE_MODE_ACC;
2202 case IA_CSS_PIPE_ID_YUVPP:
2203 return IA_CSS_PIPE_MODE_YUVPP;
2206 return IA_CSS_PIPE_MODE_PREVIEW;
2210 static void __configure_output(struct atomisp_sub_device *asd,
2211 unsigned int stream_index,
2212 unsigned int width, unsigned int height,
2213 unsigned int min_width,
2214 enum ia_css_frame_format format,
2215 enum ia_css_pipe_id pipe_id)
2217 struct atomisp_device *isp = asd->isp;
2218 struct atomisp_stream_env *stream_env =
2219 &asd->stream_env[stream_index];
2220 struct ia_css_stream_config *s_config = &stream_env->stream_config;
2222 stream_env->pipe_configs[pipe_id].mode =
2223 __pipe_id_to_pipe_mode(asd, pipe_id);
2224 stream_env->update_pipe[pipe_id] = true;
2226 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2227 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2228 stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2229 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2231 /* isp binary 2.2 specific setting*/
2232 if (width > s_config->input_config.effective_res.width ||
2233 height > s_config->input_config.effective_res.height) {
2234 s_config->input_config.effective_res.width = width;
2235 s_config->input_config.effective_res.height = height;
2238 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2239 pipe_id, width, height, format);
2242 static void __configure_video_preview_output(struct atomisp_sub_device *asd,
2243 unsigned int stream_index,
2244 unsigned int width, unsigned int height,
2245 unsigned int min_width,
2246 enum ia_css_frame_format format,
2247 enum ia_css_pipe_id pipe_id)
2249 struct atomisp_device *isp = asd->isp;
2250 struct atomisp_stream_env *stream_env =
2251 &asd->stream_env[stream_index];
2252 struct ia_css_frame_info *css_output_info;
2253 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2255 stream_env->pipe_configs[pipe_id].mode =
2256 __pipe_id_to_pipe_mode(asd, pipe_id);
2257 stream_env->update_pipe[pipe_id] = true;
2260 * second_output will be as video main output in SDV mode
2261 * with SOC camera. output will be as video main output in
2262 * normal video mode.
2264 if (asd->continuous_mode->val)
2265 css_output_info = &stream_env->pipe_configs[pipe_id].
2266 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2268 css_output_info = &stream_env->pipe_configs[pipe_id].
2269 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2271 css_output_info->res.width = width;
2272 css_output_info->res.height = height;
2273 css_output_info->format = format;
2274 css_output_info->padded_width = min_width;
2276 /* isp binary 2.2 specific setting*/
2277 if (width > stream_config->input_config.effective_res.width ||
2278 height > stream_config->input_config.effective_res.height) {
2279 stream_config->input_config.effective_res.width = width;
2280 stream_config->input_config.effective_res.height = height;
2283 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2284 pipe_id, width, height, format);
2288 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2289 * downscaling input resolution.
2291 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2292 unsigned int width, unsigned int height,
2293 enum ia_css_pipe_id pipe_id)
2295 struct atomisp_device *isp = asd->isp;
2296 struct atomisp_stream_env *stream_env =
2297 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2298 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2299 struct ia_css_pipe_config *pipe_configs =
2300 &stream_env->pipe_configs[pipe_id];
2301 struct ia_css_pipe_extra_config *pipe_extra_configs =
2302 &stream_env->pipe_extra_configs[pipe_id];
2303 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2305 if (width == 0 && height == 0)
2308 if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2309 height * 9 / 10 < pipe_configs->output_info[0].res.height)
2311 /* here just copy the calculation in css */
2312 hor_ds_factor = CEIL_DIV(width >> 1,
2313 pipe_configs->output_info[0].res.width);
2314 ver_ds_factor = CEIL_DIV(height >> 1,
2315 pipe_configs->output_info[0].res.height);
2317 if ((asd->isp->media_dev.hw_revision <
2318 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2319 IS_CHT) && hor_ds_factor != ver_ds_factor) {
2320 dev_warn(asd->isp->dev,
2321 "Cropping for capture due to FW limitation");
2325 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2326 stream_env->update_pipe[pipe_id] = true;
2328 pipe_extra_configs->enable_yuv_ds = true;
2330 pipe_configs->capt_pp_in_res.width =
2331 stream_config->input_config.effective_res.width;
2332 pipe_configs->capt_pp_in_res.height =
2333 stream_config->input_config.effective_res.height;
2335 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2336 pipe_id, width, height);
2340 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2341 * yuv downscaling, which needs addtional configurations.
2343 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2344 unsigned int width, unsigned int height,
2345 enum ia_css_pipe_id pipe_id)
2347 struct atomisp_device *isp = asd->isp;
2348 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2349 struct atomisp_stream_env *stream_env =
2350 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2351 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2352 struct ia_css_pipe_config *pipe_configs =
2353 &stream_env->pipe_configs[pipe_id];
2354 struct ia_css_pipe_extra_config *pipe_extra_configs =
2355 &stream_env->pipe_extra_configs[pipe_id];
2356 struct ia_css_resolution *bayer_ds_out_res =
2357 &pipe_configs->bayer_ds_out_res;
2358 struct ia_css_resolution *vf_pp_in_res =
2359 &pipe_configs->vf_pp_in_res;
2360 struct ia_css_resolution *effective_res =
2361 &stream_config->input_config.effective_res;
2363 static const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2365 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2366 * columns to be shaded. Remove this factor to work around the CSS bug.
2367 * const unsigned int yuv_dec_fct[] = {4, 2};
2369 static const unsigned int yuv_dec_fct[] = { 2 };
2372 if (width == 0 && height == 0)
2375 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2376 stream_env->update_pipe[pipe_id] = true;
2378 out_width = pipe_configs->output_info[0].res.width;
2379 out_height = pipe_configs->output_info[0].res.height;
2382 * The ISP could do bayer downscaling, yuv decimation and yuv
2384 * 1: Bayer Downscaling: between effective resolution and
2386 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2387 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2389 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2390 * Rule for YUV Decimation: support factor 2, 4
2391 * Rule for YUV Downscaling: arbitrary value below 2
2393 * General rule of factor distribution among these stages:
2394 * 1: try to do Bayer downscaling first if not in online mode.
2395 * 2: try to do maximum of 2 for YUV downscaling
2396 * 3: the remainling for YUV decimation
2399 * Do not configure bayer_ds_out_res if:
2400 * online == 1 or continuous == 0 or raw_binning = 0
2402 if (stream_config->online || !stream_config->continuous ||
2403 !pipe_extra_configs->enable_raw_binning) {
2404 bayer_ds_out_res->width = 0;
2405 bayer_ds_out_res->height = 0;
2407 bayer_ds_out_res->width = effective_res->width;
2408 bayer_ds_out_res->height = effective_res->height;
2410 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2411 if (effective_res->width >= out_width *
2412 bds_fct[i].numerator / bds_fct[i].denominator &&
2413 effective_res->height >= out_height *
2414 bds_fct[i].numerator / bds_fct[i].denominator) {
2415 bayer_ds_out_res->width =
2416 effective_res->width *
2417 bds_fct[i].denominator /
2418 bds_fct[i].numerator;
2419 bayer_ds_out_res->height =
2420 effective_res->height *
2421 bds_fct[i].denominator /
2422 bds_fct[i].numerator;
2428 * calculate YUV Decimation, YUV downscaling facor:
2429 * YUV Downscaling factor must not exceed 2.
2430 * YUV Decimation factor could be 2, 4.
2432 /* first decide the yuv_ds input resolution */
2433 if (bayer_ds_out_res->width == 0) {
2434 yuv_ds_in_width = effective_res->width;
2435 yuv_ds_in_height = effective_res->height;
2437 yuv_ds_in_width = bayer_ds_out_res->width;
2438 yuv_ds_in_height = bayer_ds_out_res->height;
2441 vf_pp_in_res->width = yuv_ds_in_width;
2442 vf_pp_in_res->height = yuv_ds_in_height;
2444 /* find out the yuv decimation factor */
2445 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2446 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2447 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2448 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2449 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2454 if (vf_pp_in_res->width == out_width &&
2455 vf_pp_in_res->height == out_height) {
2456 pipe_extra_configs->enable_yuv_ds = false;
2457 vf_pp_in_res->width = 0;
2458 vf_pp_in_res->height = 0;
2460 pipe_extra_configs->enable_yuv_ds = true;
2463 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2464 pipe_id, width, height);
2468 * For CSS2.1, offline video pipe could support bayer decimation, and
2469 * yuv downscaling, which needs addtional configurations.
2471 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2472 unsigned int width, unsigned int height,
2473 enum ia_css_pipe_id pipe_id)
2475 struct atomisp_device *isp = asd->isp;
2476 int out_width, out_height;
2477 struct atomisp_stream_env *stream_env =
2478 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2479 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2480 struct ia_css_pipe_config *pipe_configs =
2481 &stream_env->pipe_configs[pipe_id];
2482 struct ia_css_pipe_extra_config *pipe_extra_configs =
2483 &stream_env->pipe_extra_configs[pipe_id];
2484 struct ia_css_resolution *bayer_ds_out_res =
2485 &pipe_configs->bayer_ds_out_res;
2486 struct ia_css_resolution *effective_res =
2487 &stream_config->input_config.effective_res;
2489 static const struct bayer_ds_factor bds_factors[] = {
2490 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
2494 if (width == 0 && height == 0)
2497 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2498 stream_env->update_pipe[pipe_id] = true;
2500 pipe_extra_configs->enable_yuv_ds = false;
2503 * If DVS is enabled, video binary will take care the dvs envelope
2504 * and usually the bayer_ds_out_res should be larger than 120% of
2505 * destination resolution, the extra 20% will be cropped as DVS
2506 * envelope. But, if the bayer_ds_out_res is less than 120% of the
2507 * destination. The ISP can still work, but DVS quality is not good.
2509 /* taking at least 10% as envelope */
2510 if (asd->params.video_dis_en) {
2511 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2512 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2514 out_width = pipe_configs->output_info[0].res.width;
2515 out_height = pipe_configs->output_info[0].res.height;
2519 * calculate bayer decimate factor:
2520 * 1: only 1.5, 2, 4 and 8 get supported
2521 * 2: Do not configure bayer_ds_out_res if:
2522 * online == 1 or continuous == 0 or raw_binning = 0
2524 if (stream_config->online || !stream_config->continuous) {
2525 bayer_ds_out_res->width = 0;
2526 bayer_ds_out_res->height = 0;
2530 pipe_extra_configs->enable_raw_binning = true;
2531 bayer_ds_out_res->width = effective_res->width;
2532 bayer_ds_out_res->height = effective_res->height;
2534 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2536 if (effective_res->width >= out_width *
2537 bds_factors[i].numerator / bds_factors[i].denominator &&
2538 effective_res->height >= out_height *
2539 bds_factors[i].numerator / bds_factors[i].denominator) {
2540 bayer_ds_out_res->width = effective_res->width *
2541 bds_factors[i].denominator /
2542 bds_factors[i].numerator;
2543 bayer_ds_out_res->height = effective_res->height *
2544 bds_factors[i].denominator /
2545 bds_factors[i].numerator;
2551 * DVS is cropped from BDS output, so we do not really need to set the
2552 * envelope to 20% of output resolution here. always set it to 12x12
2553 * per firmware requirement.
2555 pipe_configs->dvs_envelope.width = 12;
2556 pipe_configs->dvs_envelope.height = 12;
2559 if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2560 stream_config->left_padding = -1;
2562 stream_config->left_padding = 12;
2563 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2564 pipe_id, width, height);
2567 static void __configure_vf_output(struct atomisp_sub_device *asd,
2568 unsigned int width, unsigned int height,
2569 unsigned int min_width,
2570 enum ia_css_frame_format format,
2571 enum ia_css_pipe_id pipe_id)
2573 struct atomisp_device *isp = asd->isp;
2574 struct atomisp_stream_env *stream_env =
2575 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2576 stream_env->pipe_configs[pipe_id].mode =
2577 __pipe_id_to_pipe_mode(asd, pipe_id);
2578 stream_env->update_pipe[pipe_id] = true;
2580 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2581 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2582 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2583 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2586 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2587 pipe_id, width, height, format);
2590 static void __configure_video_vf_output(struct atomisp_sub_device *asd,
2591 unsigned int width, unsigned int height,
2592 unsigned int min_width,
2593 enum ia_css_frame_format format,
2594 enum ia_css_pipe_id pipe_id)
2596 struct atomisp_device *isp = asd->isp;
2597 struct atomisp_stream_env *stream_env =
2598 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2599 struct ia_css_frame_info *css_output_info;
2601 stream_env->pipe_configs[pipe_id].mode =
2602 __pipe_id_to_pipe_mode(asd, pipe_id);
2603 stream_env->update_pipe[pipe_id] = true;
2606 * second_vf_output will be as video viewfinder in SDV mode
2607 * with SOC camera. vf_output will be as video viewfinder in
2608 * normal video mode.
2610 if (asd->continuous_mode->val)
2611 css_output_info = &stream_env->pipe_configs[pipe_id].
2612 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2614 css_output_info = &stream_env->pipe_configs[pipe_id].
2615 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2617 css_output_info->res.width = width;
2618 css_output_info->res.height = height;
2619 css_output_info->format = format;
2620 css_output_info->padded_width = min_width;
2622 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2623 pipe_id, width, height, format);
2626 static int __get_frame_info(struct atomisp_sub_device *asd,
2627 unsigned int stream_index,
2628 struct ia_css_frame_info *info,
2629 enum frame_info_type type,
2630 enum ia_css_pipe_id pipe_id)
2632 struct atomisp_device *isp = asd->isp;
2634 struct ia_css_pipe_info p_info;
2636 /* FIXME! No need to destroy/recreate all streams */
2637 if (__destroy_streams(asd, true))
2638 dev_warn(isp->dev, "destroy stream failed.\n");
2640 if (__destroy_pipes(asd, true))
2641 dev_warn(isp->dev, "destroy pipe failed.\n");
2643 if (__create_pipes(asd)) {
2644 dev_err(isp->dev, "can't create pipes\n");
2648 if (__create_streams(asd)) {
2649 dev_err(isp->dev, "can't create streams\n");
2653 ret = ia_css_pipe_get_info(asd->stream_env[stream_index].pipes[pipe_id],
2656 dev_err(isp->dev, "can't get info from pipe\n");
2661 case ATOMISP_CSS_VF_FRAME:
2662 *info = p_info.vf_output_info[0];
2663 dev_dbg(isp->dev, "getting vf frame info.\n");
2665 case ATOMISP_CSS_SECOND_VF_FRAME:
2666 *info = p_info.vf_output_info[1];
2667 dev_dbg(isp->dev, "getting second vf frame info.\n");
2669 case ATOMISP_CSS_OUTPUT_FRAME:
2670 *info = p_info.output_info[0];
2671 dev_dbg(isp->dev, "getting main frame info.\n");
2673 case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2674 *info = p_info.output_info[1];
2675 dev_dbg(isp->dev, "getting second main frame info.\n");
2678 case ATOMISP_CSS_RAW_FRAME:
2679 *info = p_info.raw_output_info;
2680 dev_dbg(isp->dev, "getting raw frame info.\n");
2683 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2684 info->res.width, info->res.height, p_info.num_invalid_frames);
2689 __destroy_pipes(asd, true);
2693 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2694 uint16_t source_pad)
2696 struct atomisp_device *isp = asd->isp;
2698 * to SOC camera, use yuvpp pipe.
2700 if (ATOMISP_USE_YUVPP(asd))
2701 return IA_CSS_PIPE_ID_YUVPP;
2703 switch (source_pad) {
2704 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2705 if (asd->yuvpp_mode)
2706 return IA_CSS_PIPE_ID_YUVPP;
2708 return IA_CSS_PIPE_ID_COPY;
2709 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2710 || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2711 return IA_CSS_PIPE_ID_VIDEO;
2713 return IA_CSS_PIPE_ID_CAPTURE;
2714 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2716 return IA_CSS_PIPE_ID_COPY;
2718 return IA_CSS_PIPE_ID_CAPTURE;
2719 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2720 if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) {
2721 return IA_CSS_PIPE_ID_CAPTURE;
2724 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2725 if (asd->yuvpp_mode)
2726 return IA_CSS_PIPE_ID_YUVPP;
2728 return IA_CSS_PIPE_ID_COPY;
2729 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2730 return IA_CSS_PIPE_ID_VIDEO;
2732 return IA_CSS_PIPE_ID_PREVIEW;
2735 "invalid source pad:%d, return default preview pipe index.\n",
2737 return IA_CSS_PIPE_ID_PREVIEW;
2740 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2742 struct ia_css_frame_info *frame_info)
2744 struct ia_css_pipe_info info;
2745 int pipe_index = atomisp_get_pipe_index(asd, source_pad);
2747 struct atomisp_device *isp = asd->isp;
2749 if (ATOMISP_SOC_CAMERA(asd)) {
2750 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
2752 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2753 ATOMISP_INPUT_STREAM_VIDEO :
2754 atomisp_source_pad_to_stream_id(asd, source_pad);
2757 if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index]
2758 .pipes[pipe_index], &info)) {
2759 dev_err(isp->dev, "ia_css_pipe_get_info FAILED");
2763 switch (source_pad) {
2764 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2765 *frame_info = info.output_info[0];
2767 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2768 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2770 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2773 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2775 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2776 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
2777 *frame_info = info.output_info[0];
2779 *frame_info = info.vf_output_info[0];
2781 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2782 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2783 (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
2784 pipe_index == IA_CSS_PIPE_ID_YUVPP))
2785 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2787 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2790 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2791 else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2793 info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2796 info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2803 return frame_info ? 0 : -EINVAL;
2806 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2807 unsigned int stream_index,
2808 unsigned int width, unsigned int height,
2809 unsigned int padded_width,
2810 enum ia_css_frame_format format)
2812 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
2813 default_capture_config.mode =
2814 IA_CSS_CAPTURE_MODE_RAW;
2816 __configure_output(asd, stream_index, width, height, padded_width,
2817 format, IA_CSS_PIPE_ID_COPY);
2821 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
2822 unsigned int stream_index,
2823 unsigned int width, unsigned int height,
2824 unsigned int padded_width,
2825 enum ia_css_frame_format format)
2827 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
2828 default_capture_config.mode =
2829 IA_CSS_CAPTURE_MODE_RAW;
2831 __configure_output(asd, stream_index, width, height, padded_width,
2832 format, IA_CSS_PIPE_ID_YUVPP);
2836 int atomisp_css_yuvpp_configure_viewfinder(
2837 struct atomisp_sub_device *asd,
2838 unsigned int stream_index,
2839 unsigned int width, unsigned int height,
2840 unsigned int min_width,
2841 enum ia_css_frame_format format)
2843 struct atomisp_stream_env *stream_env =
2844 &asd->stream_env[stream_index];
2845 enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP;
2847 stream_env->pipe_configs[pipe_id].mode =
2848 __pipe_id_to_pipe_mode(asd, pipe_id);
2849 stream_env->update_pipe[pipe_id] = true;
2851 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2852 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2853 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2854 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2859 int atomisp_css_yuvpp_get_output_frame_info(
2860 struct atomisp_sub_device *asd,
2861 unsigned int stream_index,
2862 struct ia_css_frame_info *info)
2864 return __get_frame_info(asd, stream_index, info,
2865 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
2868 int atomisp_css_yuvpp_get_viewfinder_frame_info(
2869 struct atomisp_sub_device *asd,
2870 unsigned int stream_index,
2871 struct ia_css_frame_info *info)
2873 return __get_frame_info(asd, stream_index, info,
2874 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
2877 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
2878 unsigned int width, unsigned int height,
2879 unsigned int min_width,
2880 enum ia_css_frame_format format)
2883 * to SOC camera, use yuvpp pipe.
2885 if (ATOMISP_USE_YUVPP(asd))
2886 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
2888 min_width, format, IA_CSS_PIPE_ID_YUVPP);
2890 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2891 min_width, format, IA_CSS_PIPE_ID_PREVIEW);
2895 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
2896 unsigned int width, unsigned int height,
2897 unsigned int min_width,
2898 enum ia_css_frame_format format)
2900 enum ia_css_pipe_id pipe_id;
2903 * to SOC camera, use yuvpp pipe.
2905 if (ATOMISP_USE_YUVPP(asd))
2906 pipe_id = IA_CSS_PIPE_ID_YUVPP;
2908 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
2910 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2911 min_width, format, pipe_id);
2915 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
2916 unsigned int width, unsigned int height,
2917 unsigned int min_width,
2918 enum ia_css_frame_format format)
2921 * to SOC camera, use yuvpp pipe.
2923 if (ATOMISP_USE_YUVPP(asd))
2924 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
2926 min_width, format, IA_CSS_PIPE_ID_YUVPP);
2928 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2929 min_width, format, IA_CSS_PIPE_ID_VIDEO);
2933 int atomisp_css_video_configure_viewfinder(
2934 struct atomisp_sub_device *asd,
2935 unsigned int width, unsigned int height,
2936 unsigned int min_width,
2937 enum ia_css_frame_format format)
2940 * to SOC camera, video will use yuvpp pipe.
2942 if (ATOMISP_USE_YUVPP(asd))
2943 __configure_video_vf_output(asd, width, height, min_width, format,
2944 IA_CSS_PIPE_ID_YUVPP);
2946 __configure_vf_output(asd, width, height, min_width, format,
2947 IA_CSS_PIPE_ID_VIDEO);
2951 int atomisp_css_capture_configure_viewfinder(
2952 struct atomisp_sub_device *asd,
2953 unsigned int width, unsigned int height,
2954 unsigned int min_width,
2955 enum ia_css_frame_format format)
2957 enum ia_css_pipe_id pipe_id;
2960 * to SOC camera, video will use yuvpp pipe.
2962 if (ATOMISP_USE_YUVPP(asd))
2963 pipe_id = IA_CSS_PIPE_ID_YUVPP;
2965 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
2967 __configure_vf_output(asd, width, height, min_width, format,
2972 int atomisp_css_video_get_viewfinder_frame_info(
2973 struct atomisp_sub_device *asd,
2974 struct ia_css_frame_info *info)
2976 enum ia_css_pipe_id pipe_id;
2977 enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME;
2979 if (ATOMISP_USE_YUVPP(asd)) {
2980 pipe_id = IA_CSS_PIPE_ID_YUVPP;
2981 if (asd->continuous_mode->val)
2982 frame_type = ATOMISP_CSS_SECOND_VF_FRAME;
2984 pipe_id = IA_CSS_PIPE_ID_VIDEO;
2987 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2988 frame_type, pipe_id);
2991 int atomisp_css_capture_get_viewfinder_frame_info(
2992 struct atomisp_sub_device *asd,
2993 struct ia_css_frame_info *info)
2995 enum ia_css_pipe_id pipe_id;
2997 if (ATOMISP_USE_YUVPP(asd))
2998 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3000 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3002 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3003 ATOMISP_CSS_VF_FRAME, pipe_id);
3006 int atomisp_css_capture_get_output_raw_frame_info(
3007 struct atomisp_sub_device *asd,
3008 struct ia_css_frame_info *info)
3010 if (ATOMISP_USE_YUVPP(asd))
3013 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3014 ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE);
3017 int atomisp_css_copy_get_output_frame_info(
3018 struct atomisp_sub_device *asd,
3019 unsigned int stream_index,
3020 struct ia_css_frame_info *info)
3022 return __get_frame_info(asd, stream_index, info,
3023 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
3026 int atomisp_css_preview_get_output_frame_info(
3027 struct atomisp_sub_device *asd,
3028 struct ia_css_frame_info *info)
3030 enum ia_css_pipe_id pipe_id;
3031 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3033 if (ATOMISP_USE_YUVPP(asd)) {
3034 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3035 if (asd->continuous_mode->val)
3036 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3038 pipe_id = IA_CSS_PIPE_ID_PREVIEW;
3041 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3042 frame_type, pipe_id);
3045 int atomisp_css_capture_get_output_frame_info(
3046 struct atomisp_sub_device *asd,
3047 struct ia_css_frame_info *info)
3049 enum ia_css_pipe_id pipe_id;
3051 if (ATOMISP_USE_YUVPP(asd))
3052 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3054 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3056 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3057 ATOMISP_CSS_OUTPUT_FRAME, pipe_id);
3060 int atomisp_css_video_get_output_frame_info(
3061 struct atomisp_sub_device *asd,
3062 struct ia_css_frame_info *info)
3064 enum ia_css_pipe_id pipe_id;
3065 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3067 if (ATOMISP_USE_YUVPP(asd)) {
3068 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3069 if (asd->continuous_mode->val)
3070 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3072 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3075 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3076 frame_type, pipe_id);
3079 int atomisp_css_preview_configure_pp_input(
3080 struct atomisp_sub_device *asd,
3081 unsigned int width, unsigned int height)
3083 struct atomisp_stream_env *stream_env =
3084 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3085 __configure_preview_pp_input(asd, width, height,
3086 ATOMISP_USE_YUVPP(asd) ?
3087 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW);
3089 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3090 capt_pp_in_res.width)
3091 __configure_capture_pp_input(asd, width, height,
3092 ATOMISP_USE_YUVPP(asd) ?
3093 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3097 int atomisp_css_capture_configure_pp_input(
3098 struct atomisp_sub_device *asd,
3099 unsigned int width, unsigned int height)
3101 __configure_capture_pp_input(asd, width, height,
3102 ATOMISP_USE_YUVPP(asd) ?
3103 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3107 int atomisp_css_video_configure_pp_input(
3108 struct atomisp_sub_device *asd,
3109 unsigned int width, unsigned int height)
3111 struct atomisp_stream_env *stream_env =
3112 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3114 __configure_video_pp_input(asd, width, height,
3115 ATOMISP_USE_YUVPP(asd) ?
3116 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO);
3118 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3119 capt_pp_in_res.width)
3120 __configure_capture_pp_input(asd, width, height,
3121 ATOMISP_USE_YUVPP(asd) ?
3122 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3126 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
3127 int num_captures, unsigned int skip, int offset)
3131 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
3132 __func__, num_captures, skip, offset);
3134 ret = ia_css_stream_capture(
3135 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3136 num_captures, skip, offset);
3143 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
3147 ret = ia_css_stream_capture_frame(
3148 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3150 if (ret == -ENOBUFS) {
3151 /* capture cmd queue is full */
3160 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
3164 ret = ia_css_unlock_raw_frame(
3165 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3167 if (ret == -ENOBUFS)
3175 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
3178 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3179 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
3180 .default_capture_config.enable_xnr = enable;
3181 asd->params.capture_config.enable_xnr = enable;
3182 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3183 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
3188 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
3189 struct ia_css_ctc_table *ctc_table)
3192 u16 *vamem_ptr = ctc_table->data.vamem_1;
3193 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
3196 /* workaround: if ctc_table is all 0, do not apply it */
3197 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
3198 vamem_ptr = ctc_table->data.vamem_2;
3199 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
3202 for (i = 0; i < data_size; i++) {
3203 if (*(vamem_ptr + i)) {
3210 asd->params.config.ctc_table = ctc_table;
3212 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
3215 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
3216 struct ia_css_anr_thres *anr_thres)
3218 asd->params.config.anr_thres = anr_thres;
3221 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
3222 struct ia_css_dvs_6axis_config *dvs_6axis)
3224 asd->params.config.dvs_6axis_config = dvs_6axis;
3227 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
3228 struct atomisp_dis_vector *vector)
3230 if (!asd->params.config.motion_vector)
3231 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
3233 memset(asd->params.config.motion_vector,
3234 0, sizeof(struct ia_css_vector));
3235 asd->params.css_param.motion_vector.x = vector->x;
3236 asd->params.css_param.motion_vector.y = vector->y;
3239 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
3240 struct atomisp_dvs_grid_info *atomgrid)
3242 struct ia_css_dvs_grid_info *cur =
3243 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
3246 dev_err(asd->isp->dev, "dvs grid not available!\n");
3250 if (sizeof(*cur) != sizeof(*atomgrid)) {
3251 dev_err(asd->isp->dev, "dvs grid mis-match!\n");
3256 dev_err(asd->isp->dev, "dvs not enabled!\n");
3260 return memcmp(atomgrid, cur, sizeof(*cur));
3263 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
3264 struct ia_css_dvs2_coefficients *coefs)
3266 asd->params.config.dvs2_coefs = coefs;
3269 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
3270 struct atomisp_dis_coefficients *coefs)
3272 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
3273 /* If the grid info in the argument differs from the current
3274 grid info, we tell the caller to reset the grid size and
3278 if (!coefs->hor_coefs.odd_real ||
3279 !coefs->hor_coefs.odd_imag ||
3280 !coefs->hor_coefs.even_real ||
3281 !coefs->hor_coefs.even_imag ||
3282 !coefs->ver_coefs.odd_real ||
3283 !coefs->ver_coefs.odd_imag ||
3284 !coefs->ver_coefs.even_real ||
3285 !coefs->ver_coefs.even_imag ||
3286 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real ||
3287 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag ||
3288 !asd->params.css_param.dvs2_coeff->hor_coefs.even_real ||
3289 !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag ||
3290 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real ||
3291 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag ||
3292 !asd->params.css_param.dvs2_coeff->ver_coefs.even_real ||
3293 !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag)
3296 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
3297 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
3299 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
3300 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
3302 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
3303 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
3305 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
3306 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
3309 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
3310 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
3312 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
3313 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
3315 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
3316 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
3318 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
3319 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
3322 asd->params.css_param.update_flag.dvs2_coefs =
3323 (struct atomisp_dis_coefficients *)
3324 asd->params.css_param.dvs2_coeff;
3326 /* asd->params.dis_proj_data_valid = false; */
3327 asd->params.css_update_params_needed = true;
3332 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
3335 struct atomisp_device *isp = asd->isp;
3337 if (zoom == asd->params.css_param.dz_config.dx &&
3338 zoom == asd->params.css_param.dz_config.dy) {
3339 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
3343 memset(&asd->params.css_param.dz_config, 0,
3344 sizeof(struct ia_css_dz_config));
3345 asd->params.css_param.dz_config.dx = zoom;
3346 asd->params.css_param.dz_config.dy = zoom;
3348 asd->params.css_param.update_flag.dz_config =
3349 (struct atomisp_dz_config *)&asd->params.css_param.dz_config;
3350 asd->params.css_update_params_needed = true;
3353 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
3354 struct ia_css_formats_config *formats_config)
3356 asd->params.config.formats_config = formats_config;
3359 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
3360 struct atomisp_wb_config *config)
3362 struct ia_css_wb_config wb_config;
3363 struct ia_css_isp_config isp_config;
3364 struct atomisp_device *isp = asd->isp;
3366 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3367 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3371 memset(&wb_config, 0, sizeof(struct ia_css_wb_config));
3372 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3373 isp_config.wb_config = &wb_config;
3374 ia_css_stream_get_isp_config(
3375 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3377 memcpy(config, &wb_config, sizeof(*config));
3382 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
3383 struct atomisp_ob_config *config)
3385 struct ia_css_ob_config ob_config;
3386 struct ia_css_isp_config isp_config;
3387 struct atomisp_device *isp = asd->isp;
3389 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3390 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3394 memset(&ob_config, 0, sizeof(struct ia_css_ob_config));
3395 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3396 isp_config.ob_config = &ob_config;
3397 ia_css_stream_get_isp_config(
3398 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3400 memcpy(config, &ob_config, sizeof(*config));
3405 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
3406 struct atomisp_dp_config *config)
3408 struct ia_css_dp_config dp_config;
3409 struct ia_css_isp_config isp_config;
3410 struct atomisp_device *isp = asd->isp;
3412 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3413 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3417 memset(&dp_config, 0, sizeof(struct ia_css_dp_config));
3418 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3419 isp_config.dp_config = &dp_config;
3420 ia_css_stream_get_isp_config(
3421 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3423 memcpy(config, &dp_config, sizeof(*config));
3428 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3429 struct atomisp_de_config *config)
3431 struct ia_css_de_config de_config;
3432 struct ia_css_isp_config isp_config;
3433 struct atomisp_device *isp = asd->isp;
3435 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3436 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3440 memset(&de_config, 0, sizeof(struct ia_css_de_config));
3441 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3442 isp_config.de_config = &de_config;
3443 ia_css_stream_get_isp_config(
3444 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3446 memcpy(config, &de_config, sizeof(*config));
3451 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3452 struct atomisp_nr_config *config)
3454 struct ia_css_nr_config nr_config;
3455 struct ia_css_isp_config isp_config;
3456 struct atomisp_device *isp = asd->isp;
3458 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3459 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3463 memset(&nr_config, 0, sizeof(struct ia_css_nr_config));
3464 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3466 isp_config.nr_config = &nr_config;
3467 ia_css_stream_get_isp_config(
3468 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3470 memcpy(config, &nr_config, sizeof(*config));
3475 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3476 struct atomisp_ee_config *config)
3478 struct ia_css_ee_config ee_config;
3479 struct ia_css_isp_config isp_config;
3480 struct atomisp_device *isp = asd->isp;
3482 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3483 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3487 memset(&ee_config, 0, sizeof(struct ia_css_ee_config));
3488 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3489 isp_config.ee_config = &ee_config;
3490 ia_css_stream_get_isp_config(
3491 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3493 memcpy(config, &ee_config, sizeof(*config));
3498 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3499 struct atomisp_tnr_config *config)
3501 struct ia_css_tnr_config tnr_config;
3502 struct ia_css_isp_config isp_config;
3503 struct atomisp_device *isp = asd->isp;
3505 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3506 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3510 memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config));
3511 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3512 isp_config.tnr_config = &tnr_config;
3513 ia_css_stream_get_isp_config(
3514 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3516 memcpy(config, &tnr_config, sizeof(*config));
3521 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3522 struct atomisp_ctc_table *config)
3524 struct ia_css_ctc_table *tab;
3525 struct ia_css_isp_config isp_config;
3526 struct atomisp_device *isp = asd->isp;
3528 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3529 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3534 tab = vzalloc(sizeof(struct ia_css_ctc_table));
3538 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3539 isp_config.ctc_table = tab;
3540 ia_css_stream_get_isp_config(
3541 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3543 memcpy(config, tab, sizeof(*tab));
3549 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
3550 struct atomisp_gamma_table *config)
3552 struct ia_css_gamma_table *tab;
3553 struct ia_css_isp_config isp_config;
3554 struct atomisp_device *isp = asd->isp;
3556 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3557 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3562 tab = vzalloc(sizeof(struct ia_css_gamma_table));
3566 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3567 isp_config.gamma_table = tab;
3568 ia_css_stream_get_isp_config(
3569 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3571 memcpy(config, tab, sizeof(*tab));
3577 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
3578 struct atomisp_gc_config *config)
3580 struct ia_css_gc_config gc_config;
3581 struct ia_css_isp_config isp_config;
3582 struct atomisp_device *isp = asd->isp;
3584 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3585 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3589 memset(&gc_config, 0, sizeof(struct ia_css_gc_config));
3590 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3591 isp_config.gc_config = &gc_config;
3592 ia_css_stream_get_isp_config(
3593 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3595 /* Get gamma correction params from current setup */
3596 memcpy(config, &gc_config, sizeof(*config));
3601 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
3602 struct atomisp_3a_config *config)
3604 struct ia_css_3a_config s3a_config;
3605 struct ia_css_isp_config isp_config;
3606 struct atomisp_device *isp = asd->isp;
3608 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3609 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3613 memset(&s3a_config, 0, sizeof(struct ia_css_3a_config));
3614 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3615 isp_config.s3a_config = &s3a_config;
3616 ia_css_stream_get_isp_config(
3617 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3619 /* Get white balance from current setup */
3620 memcpy(config, &s3a_config, sizeof(*config));
3625 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
3626 struct atomisp_formats_config *config)
3628 struct ia_css_formats_config formats_config;
3629 struct ia_css_isp_config isp_config;
3630 struct atomisp_device *isp = asd->isp;
3632 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3633 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3637 memset(&formats_config, 0, sizeof(formats_config));
3638 memset(&isp_config, 0, sizeof(isp_config));
3639 isp_config.formats_config = &formats_config;
3640 ia_css_stream_get_isp_config(
3641 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3643 /* Get narrow gamma from current setup */
3644 memcpy(config, &formats_config, sizeof(*config));
3649 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
3652 struct ia_css_dz_config dz_config; /** Digital Zoom */
3653 struct ia_css_isp_config isp_config;
3654 struct atomisp_device *isp = asd->isp;
3656 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3657 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3661 memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
3662 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3663 isp_config.dz_config = &dz_config;
3664 ia_css_stream_get_isp_config(
3665 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3667 *zoom = dz_config.dx;
3673 * Function to set/get image stablization statistics
3675 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
3676 struct atomisp_dis_statistics *stats)
3678 struct atomisp_device *isp = asd->isp;
3679 struct atomisp_dis_buf *dis_buf;
3680 unsigned long flags;
3682 if (!asd->params.dvs_stat->hor_prod.odd_real ||
3683 !asd->params.dvs_stat->hor_prod.odd_imag ||
3684 !asd->params.dvs_stat->hor_prod.even_real ||
3685 !asd->params.dvs_stat->hor_prod.even_imag ||
3686 !asd->params.dvs_stat->ver_prod.odd_real ||
3687 !asd->params.dvs_stat->ver_prod.odd_imag ||
3688 !asd->params.dvs_stat->ver_prod.even_real ||
3689 !asd->params.dvs_stat->ver_prod.even_imag)
3692 /* isp needs to be streaming to get DIS statistics */
3693 spin_lock_irqsave(&isp->lock, flags);
3694 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) {
3695 spin_unlock_irqrestore(&isp->lock, flags);
3698 spin_unlock_irqrestore(&isp->lock, flags);
3700 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
3701 /* If the grid info in the argument differs from the current
3702 grid info, we tell the caller to reset the grid size and
3706 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3707 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
3708 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3709 dev_err(isp->dev, "dis statistics is not valid.\n");
3713 dis_buf = list_entry(asd->dis_stats.next,
3714 struct atomisp_dis_buf, list);
3715 list_del_init(&dis_buf->list);
3716 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3718 if (dis_buf->dvs_map)
3719 ia_css_translate_dvs2_statistics(
3720 asd->params.dvs_stat, dis_buf->dvs_map);
3722 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
3724 stats->exp_id = dis_buf->dis_data->exp_id;
3726 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3727 list_add_tail(&dis_buf->list, &asd->dis_stats);
3728 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3730 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
3731 asd->params.dvs_stat->ver_prod.odd_real,
3732 asd->params.dvs_ver_proj_bytes))
3734 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
3735 asd->params.dvs_stat->ver_prod.odd_imag,
3736 asd->params.dvs_ver_proj_bytes))
3738 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
3739 asd->params.dvs_stat->ver_prod.even_real,
3740 asd->params.dvs_ver_proj_bytes))
3742 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
3743 asd->params.dvs_stat->ver_prod.even_imag,
3744 asd->params.dvs_ver_proj_bytes))
3746 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
3747 asd->params.dvs_stat->hor_prod.odd_real,
3748 asd->params.dvs_hor_proj_bytes))
3750 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
3751 asd->params.dvs_stat->hor_prod.odd_imag,
3752 asd->params.dvs_hor_proj_bytes))
3754 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
3755 asd->params.dvs_stat->hor_prod.even_real,
3756 asd->params.dvs_hor_proj_bytes))
3758 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
3759 asd->params.dvs_stat->hor_prod.even_imag,
3760 asd->params.dvs_hor_proj_bytes))
3766 struct ia_css_shading_table *atomisp_css_shading_table_alloc(
3767 unsigned int width, unsigned int height)
3769 return ia_css_shading_table_alloc(width, height);
3772 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
3773 struct ia_css_shading_table *table)
3775 asd->params.config.shading_table = table;
3778 void atomisp_css_shading_table_free(struct ia_css_shading_table *table)
3780 ia_css_shading_table_free(table);
3783 struct ia_css_morph_table *atomisp_css_morph_table_allocate(
3784 unsigned int width, unsigned int height)
3786 return ia_css_morph_table_allocate(width, height);
3789 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
3790 struct ia_css_morph_table *table)
3792 asd->params.config.morph_table = table;
3795 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
3796 struct ia_css_morph_table *table)
3798 struct ia_css_isp_config isp_config;
3799 struct atomisp_device *isp = asd->isp;
3801 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3803 "%s called after streamoff, skipping.\n", __func__);
3806 memset(table, 0, sizeof(struct ia_css_morph_table));
3807 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3808 isp_config.morph_table = table;
3809 ia_css_stream_get_isp_config(
3810 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3814 void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
3816 ia_css_morph_table_free(table);
3819 void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp,
3820 unsigned int overlap)
3822 /* CSS 2.0 doesn't support this API. */
3823 dev_dbg(isp->dev, "set cont prev start time is not supported.\n");
3827 void atomisp_css_acc_done(struct atomisp_sub_device *asd)
3829 complete(&asd->acc.acc_done);
3832 int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd)
3835 struct atomisp_device *isp = asd->isp;
3837 /* Unlock the isp mutex taken in IOCTL handler before sleeping! */
3838 rt_mutex_unlock(&isp->mutex);
3839 if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done,
3840 ATOMISP_ISP_TIMEOUT_DURATION) == 0) {
3841 dev_err(isp->dev, "<%s: completion timeout\n", __func__);
3842 ia_css_debug_dump_sp_sw_debug_info();
3843 ia_css_debug_dump_debug_info(__func__);
3846 rt_mutex_lock(&isp->mutex);
3851 /* Set the ACC binary arguments */
3852 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw)
3856 for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) {
3857 if (acc_fw->args[mem].length == 0)
3860 ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers,
3861 IA_CSS_PARAM_CLASS_PARAM, mem,
3862 acc_fw->args[mem].css_ptr,
3863 acc_fw->args[mem].length);
3869 /* Load acc binary extension */
3870 int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd,
3871 struct ia_css_fw_info *fw,
3872 enum ia_css_pipe_id pipe_id,
3875 struct ia_css_fw_info **hd;
3878 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3879 .pipe_configs[pipe_id].acc_extension);
3884 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3885 .update_pipe[pipe_id] = true;
3889 /* Unload acc binary extension */
3890 void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd,
3891 struct ia_css_fw_info *fw,
3892 enum ia_css_pipe_id pipe_id)
3894 struct ia_css_fw_info **hd;
3896 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3897 .pipe_configs[pipe_id].acc_extension);
3898 while (*hd && *hd != fw)
3901 dev_err(asd->isp->dev, "did not find acc fw for removal\n");
3907 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3908 .update_pipe[pipe_id] = true;
3911 int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd)
3913 struct atomisp_device *isp = asd->isp;
3914 struct ia_css_pipe_config *pipe_config;
3915 struct atomisp_stream_env *stream_env =
3916 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3918 if (stream_env->acc_stream) {
3919 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
3920 if (ia_css_stream_stop(stream_env->acc_stream)
3922 dev_err(isp->dev, "stop acc_stream failed.\n");
3927 if (ia_css_stream_destroy(stream_env->acc_stream)
3929 dev_err(isp->dev, "destroy acc_stream failed.\n");
3932 stream_env->acc_stream = NULL;
3935 pipe_config = &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
3936 ia_css_pipe_config_defaults(pipe_config);
3937 asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES *
3938 sizeof(void *), GFP_KERNEL);
3939 if (!asd->acc.acc_stages)
3941 pipe_config->acc_stages = asd->acc.acc_stages;
3942 pipe_config->mode = IA_CSS_PIPE_MODE_ACC;
3943 pipe_config->num_acc_stages = 0;
3946 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe,
3947 * because pipe configuration will soon be changed by
3948 * atomisp_css_load_acc_binary()
3953 int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd)
3955 struct atomisp_device *isp = asd->isp;
3956 struct atomisp_stream_env *stream_env =
3957 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3958 struct ia_css_pipe_config *pipe_config =
3959 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
3961 if (ia_css_pipe_create(pipe_config,
3962 &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != 0) {
3963 dev_err(isp->dev, "%s: ia_css_pipe_create failed\n",
3968 memset(&stream_env->acc_stream_config, 0,
3969 sizeof(struct ia_css_stream_config));
3970 if (ia_css_stream_create(&stream_env->acc_stream_config, 1,
3971 &stream_env->pipes[IA_CSS_PIPE_ID_ACC],
3972 &stream_env->acc_stream) != 0) {
3973 dev_err(isp->dev, "%s: create acc_stream error.\n", __func__);
3976 stream_env->acc_stream_state = CSS_STREAM_CREATED;
3978 init_completion(&asd->acc.acc_done);
3979 asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC];
3981 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
3983 if (ia_css_start_sp()) {
3984 dev_err(isp->dev, "start sp error.\n");
3988 if (ia_css_stream_start(stream_env->acc_stream)
3990 dev_err(isp->dev, "acc_stream start error.\n");
3994 stream_env->acc_stream_state = CSS_STREAM_STARTED;
3998 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd)
4000 struct atomisp_stream_env *stream_env =
4001 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4002 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4003 ia_css_stream_stop(stream_env->acc_stream);
4004 stream_env->acc_stream_state = CSS_STREAM_STOPPED;
4009 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd)
4011 struct atomisp_stream_env *stream_env =
4012 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4013 if (stream_env->acc_stream) {
4014 if (ia_css_stream_destroy(stream_env->acc_stream)
4016 dev_warn(asd->isp->dev,
4017 "destroy acc_stream failed.\n");
4018 stream_env->acc_stream = NULL;
4021 if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) {
4022 if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC])
4024 dev_warn(asd->isp->dev,
4025 "destroy ACC pipe failed.\n");
4026 stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL;
4027 stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false;
4028 ia_css_pipe_config_defaults(
4029 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]);
4030 ia_css_pipe_extra_config_defaults(
4031 &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]);
4033 asd->acc.pipeline = NULL;
4035 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
4040 kfree(asd->acc.acc_stages);
4041 asd->acc.acc_stages = NULL;
4043 atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false);
4046 int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd,
4047 struct ia_css_fw_info *fw,
4050 struct ia_css_pipe_config *pipe_config =
4051 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4052 .pipe_configs[IA_CSS_PIPE_ID_ACC];
4054 if (index >= MAX_ACC_STAGES) {
4055 dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n",
4060 pipe_config->acc_stages[index] = fw;
4061 pipe_config->num_acc_stages = index + 1;
4062 pipe_config->acc_num_execs = 1;
4067 static struct atomisp_sub_device *__get_atomisp_subdev(
4068 struct ia_css_pipe *css_pipe,
4069 struct atomisp_device *isp,
4070 enum atomisp_input_stream_id *stream_id)
4073 struct atomisp_sub_device *asd;
4074 struct atomisp_stream_env *stream_env;
4076 for (i = 0; i < isp->num_of_streams; i++) {
4078 if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED &&
4081 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4082 stream_env = &asd->stream_env[j];
4083 for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
4084 if (stream_env->pipes[k] &&
4085 stream_env->pipes[k] == css_pipe) {
4096 int atomisp_css_isr_thread(struct atomisp_device *isp,
4097 bool *frame_done_found,
4098 bool *css_pipe_done)
4100 enum atomisp_input_stream_id stream_id = 0;
4101 struct atomisp_css_event current_event;
4102 struct atomisp_sub_device *asd;
4103 bool reset_wdt_timer[MAX_STREAM_NUM] = {false};
4106 while (!ia_css_dequeue_psys_event(¤t_event.event)) {
4107 if (current_event.event.type ==
4108 IA_CSS_EVENT_TYPE_FW_ASSERT) {
4110 * Received FW assertion signal,
4111 * trigger WDT to recover
4114 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
4116 current_event.event.fw_assert_module_id,
4117 current_event.event.fw_assert_line_no);
4118 for (i = 0; i < isp->num_of_streams; i++)
4119 atomisp_wdt_stop(&isp->asd[i], 0);
4122 atomisp_wdt(&isp->asd[0].wdt);
4124 queue_work(isp->wdt_work_queue, &isp->wdt_work);
4127 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4128 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
4129 __func__, current_event.event.fw_warning,
4130 current_event.event.exp_id);
4134 asd = __get_atomisp_subdev(current_event.event.pipe,
4137 if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
4139 "event: Timer event.");
4141 dev_warn(isp->dev, "%s:no subdev.event:%d",
4143 current_event.event.type);
4147 atomisp_css_temp_pipe_to_pipe_id(asd, ¤t_event);
4148 switch (current_event.event.type) {
4149 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
4150 dev_dbg(isp->dev, "event: Output frame done");
4151 frame_done_found[asd->index] = true;
4152 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
4153 current_event.pipe, true, stream_id);
4156 reset_wdt_timer[asd->index] = true; /* ISP running */
4159 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
4160 dev_dbg(isp->dev, "event: Second output frame done");
4161 frame_done_found[asd->index] = true;
4162 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
4163 current_event.pipe, true, stream_id);
4166 reset_wdt_timer[asd->index] = true; /* ISP running */
4169 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
4170 dev_dbg(isp->dev, "event: 3A stats frame done");
4171 atomisp_buf_done(asd, 0,
4172 IA_CSS_BUFFER_TYPE_3A_STATISTICS,
4176 case IA_CSS_EVENT_TYPE_METADATA_DONE:
4177 dev_dbg(isp->dev, "event: metadata frame done");
4178 atomisp_buf_done(asd, 0,
4179 IA_CSS_BUFFER_TYPE_METADATA,
4183 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
4184 dev_dbg(isp->dev, "event: VF output frame done");
4185 atomisp_buf_done(asd, 0,
4186 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
4187 current_event.pipe, true, stream_id);
4190 reset_wdt_timer[asd->index] = true; /* ISP running */
4193 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
4194 dev_dbg(isp->dev, "event: second VF output frame done");
4195 atomisp_buf_done(asd, 0,
4196 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
4197 current_event.pipe, true, stream_id);
4199 reset_wdt_timer[asd->index] = true; /* ISP running */
4202 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
4203 dev_dbg(isp->dev, "event: dis stats frame done");
4204 atomisp_buf_done(asd, 0,
4205 IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
4209 case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
4210 dev_dbg(isp->dev, "event: pipeline done");
4211 css_pipe_done[asd->index] = true;
4213 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
4214 dev_dbg(isp->dev, "event: acc stage done");
4215 atomisp_acc_done(asd, current_event.event.fw_handle);
4218 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
4219 current_event.event.type);
4227 /* ISP2400: If there are no buffers queued then delete wdt timer. */
4228 for (i = 0; i < isp->num_of_streams; i++) {
4232 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
4234 if (!atomisp_buffers_queued(asd))
4235 atomisp_wdt_stop(asd, false);
4236 else if (reset_wdt_timer[i])
4237 /* SOF irq should not reset wdt timer. */
4238 atomisp_wdt_refresh(asd,
4239 ATOMISP_WDT_KEEP_CURRENT_DELAY);
4245 bool atomisp_css_valid_sof(struct atomisp_device *isp)
4249 /* Loop for each css stream */
4250 for (i = 0; i < isp->num_of_streams; i++) {
4251 struct atomisp_sub_device *asd = &isp->asd[i];
4252 /* Loop for each css vc stream */
4253 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4254 if (!asd->stream_env[j].stream)
4258 "stream #%d: mode: %d\n", j,
4259 asd->stream_env[j].stream_config.mode);
4260 if (asd->stream_env[j].stream_config.mode ==
4261 IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
4269 int atomisp_css_debug_dump_isp_binary(void)
4271 ia_css_debug_dump_isp_binary();
4275 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
4277 sh_css_dump_sp_raw_copy_linecount(reduced);
4281 static const char * const fw_type_name[] = {
4282 [ia_css_sp_firmware] = "SP",
4283 [ia_css_isp_firmware] = "ISP",
4284 [ia_css_bootloader_firmware] = "BootLoader",
4285 [ia_css_acc_firmware] = "accel",
4288 static const char * const fw_acc_type_name[] = {
4289 [IA_CSS_ACC_NONE] = "Normal",
4290 [IA_CSS_ACC_OUTPUT] = "Accel stage on output",
4291 [IA_CSS_ACC_VIEWFINDER] = "Accel stage on viewfinder",
4292 [IA_CSS_ACC_STANDALONE] = "Stand-alone acceleration",
4295 int atomisp_css_dump_blob_infor(struct atomisp_device *isp)
4297 struct ia_css_blob_descr *bd = sh_css_blob_info;
4298 unsigned int i, nm = sh_css_num_binaries;
4306 * The sh_css_load_firmware function discard the initial
4309 for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) {
4310 switch (bd[i].header.type) {
4311 case ia_css_isp_firmware:
4312 dev_dbg(isp->dev, "Num%2d type %s (%s), binary id is %2d, name is %s\n",
4314 fw_type_name[bd[i].header.type],
4315 fw_acc_type_name[bd[i].header.info.isp.type],
4316 bd[i].header.info.isp.sp.id,
4320 dev_dbg(isp->dev, "Num%2d type %s, name is %s\n",
4321 i + NUM_OF_SPS, fw_type_name[bd[i].header.type],
4329 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
4330 uint32_t isp_config_id)
4332 asd->params.config.isp_config_id = isp_config_id;
4335 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
4336 struct ia_css_frame *output_frame)
4338 asd->params.config.output_frame = output_frame;
4341 int atomisp_get_css_dbgfunc(void)
4346 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
4350 ret = __set_css_print_env(isp, opt);
4357 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
4359 ia_css_en_dz_capt_pipe(
4360 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4364 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
4365 struct ia_css_grid_info *grid_info)
4370 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
4371 return &grid_info->dvs_grid.dvs_grid_info;
4373 return &grid_info->dvs_grid;