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"
35 #include "ia_css_debug.h"
36 #include "ia_css_isp_param.h"
37 #include "sh_css_hrt.h"
38 #include "ia_css_isys.h"
41 #include <linux/pm_runtime.h>
43 /* Assume max number of ACC stages */
44 #define MAX_ACC_STAGES 20
46 /* Ideally, this should come from CSS headers */
50 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
51 * #4684168, if concurrency access happened, system may hard hang.
53 static DEFINE_SPINLOCK(mmio_lock);
55 enum frame_info_type {
57 ATOMISP_CSS_SECOND_VF_FRAME,
58 ATOMISP_CSS_OUTPUT_FRAME,
59 ATOMISP_CSS_SECOND_OUTPUT_FRAME,
60 ATOMISP_CSS_RAW_FRAME,
63 struct bayer_ds_factor {
64 unsigned int numerator;
65 unsigned int denominator;
68 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
70 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
73 spin_lock_irqsave(&mmio_lock, flags);
74 writeb(data, isp->base + (addr & 0x003FFFFF));
75 spin_unlock_irqrestore(&mmio_lock, flags);
78 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
80 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
83 spin_lock_irqsave(&mmio_lock, flags);
84 writew(data, isp->base + (addr & 0x003FFFFF));
85 spin_unlock_irqrestore(&mmio_lock, flags);
88 void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
90 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
93 spin_lock_irqsave(&mmio_lock, flags);
94 writel(data, isp->base + (addr & 0x003FFFFF));
95 spin_unlock_irqrestore(&mmio_lock, flags);
98 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
100 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
104 spin_lock_irqsave(&mmio_lock, flags);
105 ret = readb(isp->base + (addr & 0x003FFFFF));
106 spin_unlock_irqrestore(&mmio_lock, flags);
110 static uint16_t atomisp_css2_hw_load_16(hrt_address addr)
112 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
116 spin_lock_irqsave(&mmio_lock, flags);
117 ret = readw(isp->base + (addr & 0x003FFFFF));
118 spin_unlock_irqrestore(&mmio_lock, flags);
122 static uint32_t atomisp_css2_hw_load_32(hrt_address addr)
124 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
128 spin_lock_irqsave(&mmio_lock, flags);
129 ret = readl(isp->base + (addr & 0x003FFFFF));
130 spin_unlock_irqrestore(&mmio_lock, flags);
134 static void atomisp_css2_hw_store(hrt_address addr, const void *from, uint32_t n)
136 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
141 spin_lock_irqsave(&mmio_lock, flags);
142 for (i = 0; i < n; i++, from++)
143 writeb(*(s8 *)from, isp->base + addr + i);
145 spin_unlock_irqrestore(&mmio_lock, flags);
148 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
150 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
155 spin_lock_irqsave(&mmio_lock, flags);
156 for (i = 0; i < n; i++, to++)
157 *(s8 *)to = readb(isp->base + addr + i);
158 spin_unlock_irqrestore(&mmio_lock, flags);
161 static int __printf(1, 0) atomisp_vprintk(const char *fmt, va_list args)
167 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
169 *data = atomisp_css2_hw_load_32(addr);
172 static int hmm_get_mmu_base_addr(struct device *dev, unsigned int *mmu_base_addr)
174 if (!sh_mmu_mrfld.get_pd_base) {
175 dev_err(dev, "get mmu base address failed.\n");
179 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
180 bo_device.mmu.base_address);
184 static void __dump_pipe_config(struct atomisp_sub_device *asd,
185 struct atomisp_stream_env *stream_env,
186 unsigned int pipe_id)
188 struct atomisp_device *isp = asd->isp;
190 if (stream_env->pipes[pipe_id]) {
191 struct ia_css_pipe_config *p_config;
192 struct ia_css_pipe_extra_config *pe_config;
194 p_config = &stream_env->pipe_configs[pipe_id];
195 pe_config = &stream_env->pipe_extra_configs[pipe_id];
196 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
198 "pipe_config.pipe_mode:%d.\n", p_config->mode);
200 "pipe_config.output_info[0] w=%d, h=%d.\n",
201 p_config->output_info[0].res.width,
202 p_config->output_info[0].res.height);
204 "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
205 p_config->vf_pp_in_res.width,
206 p_config->vf_pp_in_res.height);
208 "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
209 p_config->capt_pp_in_res.width,
210 p_config->capt_pp_in_res.height);
212 "pipe_config.output.padded w=%d.\n",
213 p_config->output_info[0].padded_width);
215 "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
216 p_config->vf_output_info[0].res.width,
217 p_config->vf_output_info[0].res.height);
219 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
220 p_config->bayer_ds_out_res.width,
221 p_config->bayer_ds_out_res.height);
223 "pipe_config.envelope w=%d, h=%d.\n",
224 p_config->dvs_envelope.width,
225 p_config->dvs_envelope.height);
227 "pipe_config.dvs_frame_delay=%d.\n",
228 p_config->dvs_frame_delay);
230 "pipe_config.isp_pipe_version:%d.\n",
231 p_config->isp_pipe_version);
233 "pipe_config.default_capture_config.capture_mode=%d.\n",
234 p_config->default_capture_config.mode);
236 "pipe_config.enable_dz=%d.\n",
237 p_config->enable_dz);
239 "pipe_config.default_capture_config.enable_xnr=%d.\n",
240 p_config->default_capture_config.enable_xnr);
242 "dumping pipe[%d] extra config:\n", pipe_id);
244 "pipe_extra_config.enable_raw_binning:%d.\n",
245 pe_config->enable_raw_binning);
247 "pipe_extra_config.enable_yuv_ds:%d.\n",
248 pe_config->enable_yuv_ds);
250 "pipe_extra_config.enable_high_speed:%d.\n",
251 pe_config->enable_high_speed);
253 "pipe_extra_config.enable_dvs_6axis:%d.\n",
254 pe_config->enable_dvs_6axis);
256 "pipe_extra_config.enable_reduced_pipe:%d.\n",
257 pe_config->enable_reduced_pipe);
259 "pipe_(extra_)config.enable_dz:%d.\n",
260 p_config->enable_dz);
262 "pipe_extra_config.disable_vf_pp:%d.\n",
263 pe_config->disable_vf_pp);
267 static void __dump_stream_config(struct atomisp_sub_device *asd,
268 struct atomisp_stream_env *stream_env)
270 struct atomisp_device *isp = asd->isp;
271 struct ia_css_stream_config *s_config;
273 bool valid_stream = false;
275 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
276 if (stream_env->pipes[j]) {
277 __dump_pipe_config(asd, stream_env, j);
283 s_config = &stream_env->stream_config;
284 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
286 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
287 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
288 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
289 s_config->source.port.port);
290 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
291 s_config->source.port.num_lanes);
292 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
293 s_config->source.port.timeout);
294 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
295 s_config->source.port.rxcount);
296 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
297 s_config->source.port.compression.type);
299 "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
300 s_config->source.port.compression.
301 compressed_bits_per_pixel);
303 "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
304 s_config->source.port.compression.
305 uncompressed_bits_per_pixel);
306 } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
307 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
308 s_config->source.tpg.id);
309 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
310 s_config->source.tpg.mode);
311 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
312 s_config->source.tpg.x_mask);
313 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
314 s_config->source.tpg.x_delta);
315 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
316 s_config->source.tpg.y_mask);
317 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
318 s_config->source.tpg.y_delta);
319 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
320 s_config->source.tpg.xy_mask);
321 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
322 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
323 s_config->source.prbs.id);
324 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
325 s_config->source.prbs.h_blank);
326 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
327 s_config->source.prbs.v_blank);
328 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
329 s_config->source.prbs.seed);
330 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
331 s_config->source.prbs.seed1);
334 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
335 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
337 s_config->isys_config[j].input_res.width,
338 s_config->isys_config[j].input_res.height);
340 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
342 s_config->isys_config[j].linked_isys_stream_id);
344 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
346 s_config->isys_config[j].format);
348 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
350 s_config->isys_config[j].valid);
353 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
354 s_config->input_config.input_res.width,
355 s_config->input_config.input_res.height);
357 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
358 s_config->input_config.effective_res.width,
359 s_config->input_config.effective_res.height);
361 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
362 s_config->input_config.format);
364 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
365 s_config->input_config.bayer_order);
367 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
368 s_config->pixels_per_clock);
369 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
370 dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
371 s_config->continuous);
372 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
373 s_config->disable_cont_viewfinder);
374 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
375 s_config->channel_id);
376 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
377 s_config->init_num_cont_raw_buf);
378 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
379 s_config->target_num_cont_raw_buf);
380 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
381 s_config->left_padding);
382 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
383 s_config->sensor_binning_factor);
384 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
385 s_config->pixels_per_clock);
386 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
387 s_config->pack_raw_pixels);
388 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
389 s_config->flash_gpio_pin);
390 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
391 s_config->mipi_buffer_config.size_mem_words);
392 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
393 s_config->mipi_buffer_config.contiguous);
394 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
395 s_config->metadata_config.data_type);
396 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
397 s_config->metadata_config.resolution.width,
398 s_config->metadata_config.resolution.height);
401 static int __destroy_stream(struct atomisp_sub_device *asd,
402 struct atomisp_stream_env *stream_env)
404 struct atomisp_device *isp = asd->isp;
405 unsigned long timeout;
407 if (!stream_env->stream)
410 if (stream_env->stream_state == CSS_STREAM_STARTED
411 && ia_css_stream_stop(stream_env->stream) != 0) {
412 dev_err(isp->dev, "stop stream failed.\n");
416 if (stream_env->stream_state == CSS_STREAM_STARTED) {
417 timeout = jiffies + msecs_to_jiffies(40);
419 if (ia_css_stream_has_stopped(stream_env->stream))
422 if (time_after(jiffies, timeout)) {
423 dev_warn(isp->dev, "stop stream timeout.\n");
427 usleep_range(100, 200);
431 stream_env->stream_state = CSS_STREAM_STOPPED;
433 if (ia_css_stream_destroy(stream_env->stream)) {
434 dev_err(isp->dev, "destroy stream failed.\n");
437 stream_env->stream_state = CSS_STREAM_UNINIT;
438 stream_env->stream = NULL;
443 static int __destroy_streams(struct atomisp_sub_device *asd)
447 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
448 ret = __destroy_stream(asd, &asd->stream_env[i]);
452 asd->stream_prepared = false;
456 static int __create_stream(struct atomisp_sub_device *asd,
457 struct atomisp_stream_env *stream_env)
459 int pipe_index = 0, i;
460 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
462 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
463 if (stream_env->pipes[i])
464 multi_pipes[pipe_index++] = stream_env->pipes[i];
469 stream_env->stream_config.target_num_cont_raw_buf =
470 asd->continuous_raw_buffer_size->val;
471 stream_env->stream_config.channel_id = stream_env->ch_id;
472 stream_env->stream_config.ia_css_enable_raw_buffer_locking =
473 asd->enable_raw_buffer_lock->val;
475 __dump_stream_config(asd, stream_env);
476 if (ia_css_stream_create(&stream_env->stream_config,
477 pipe_index, multi_pipes, &stream_env->stream) != 0)
479 if (ia_css_stream_get_info(stream_env->stream,
480 &stream_env->stream_info) != 0) {
481 ia_css_stream_destroy(stream_env->stream);
482 stream_env->stream = NULL;
486 stream_env->stream_state = CSS_STREAM_CREATED;
490 static int __create_streams(struct atomisp_sub_device *asd)
494 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
495 ret = __create_stream(asd, &asd->stream_env[i]);
499 asd->stream_prepared = true;
502 for (i--; i >= 0; i--)
503 __destroy_stream(asd, &asd->stream_env[i]);
507 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
508 struct atomisp_stream_env *stream_env)
510 struct atomisp_device *isp = asd->isp;
514 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
515 if (!stream_env->pipes[i])
517 if (ia_css_pipe_destroy(stream_env->pipes[i])
520 "destroy pipe[%d]failed.cannot recover.\n", i);
523 stream_env->pipes[i] = NULL;
524 stream_env->update_pipe[i] = false;
529 static int __destroy_pipes(struct atomisp_sub_device *asd)
531 struct atomisp_device *isp = asd->isp;
535 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
536 if (asd->stream_env[i].stream) {
538 "cannot destroy css pipes for stream[%d].\n",
543 ret = __destroy_stream_pipes(asd, &asd->stream_env[i]);
551 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
553 if (__destroy_streams(asd))
554 dev_warn(asd->isp->dev, "destroy stream failed.\n");
556 if (__destroy_pipes(asd))
557 dev_warn(asd->isp->dev, "destroy pipe failed.\n");
560 static void __apply_additional_pipe_config(
561 struct atomisp_sub_device *asd,
562 struct atomisp_stream_env *stream_env,
563 enum ia_css_pipe_id pipe_id)
565 struct atomisp_device *isp = asd->isp;
567 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
569 "wrong pipe_id for additional pipe config.\n");
573 /* apply default pipe config */
574 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
575 stream_env->pipe_configs[pipe_id].enable_dz =
576 asd->disable_dz->val ? false : true;
577 /* apply isp 2.2 specific config for baytrail*/
579 case IA_CSS_PIPE_ID_CAPTURE:
580 /* enable capture pp/dz manually or digital zoom would
582 if (stream_env->pipe_configs[pipe_id].
583 default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW)
584 stream_env->pipe_configs[pipe_id].enable_dz = false;
586 case IA_CSS_PIPE_ID_VIDEO:
587 /* enable reduced pipe to have binary
588 * video_dz_2_min selected*/
589 stream_env->pipe_extra_configs[pipe_id]
590 .enable_reduced_pipe = true;
591 stream_env->pipe_configs[pipe_id]
594 if (asd->params.video_dis_en) {
595 stream_env->pipe_extra_configs[pipe_id]
596 .enable_dvs_6axis = true;
597 stream_env->pipe_configs[pipe_id]
599 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
602 case IA_CSS_PIPE_ID_PREVIEW:
604 case IA_CSS_PIPE_ID_YUVPP:
605 case IA_CSS_PIPE_ID_COPY:
606 stream_env->pipe_configs[pipe_id].enable_dz = false;
613 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
614 enum ia_css_pipe_id pipe_id)
619 if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
623 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
624 if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
628 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
629 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
639 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
642 switch (asd->run_mode->val) {
643 case ATOMISP_RUN_MODE_STILL_CAPTURE:
644 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
648 case ATOMISP_RUN_MODE_PREVIEW:
649 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
653 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
654 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
655 pipe_id == IA_CSS_PIPE_ID_PREVIEW)
659 case ATOMISP_RUN_MODE_VIDEO:
660 if (pipe_id == IA_CSS_PIPE_ID_VIDEO || pipe_id == IA_CSS_PIPE_ID_YUVPP)
664 case ATOMISP_RUN_MODE_SDV:
665 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
666 pipe_id == IA_CSS_PIPE_ID_VIDEO)
675 static int __create_pipe(struct atomisp_sub_device *asd,
676 struct atomisp_stream_env *stream_env,
677 enum ia_css_pipe_id pipe_id)
679 struct atomisp_device *isp = asd->isp;
680 struct ia_css_pipe_extra_config extra_config;
683 if (pipe_id >= IA_CSS_PIPE_ID_NUM)
686 if (!stream_env->pipe_configs[pipe_id].output_info[0].res.width)
689 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
692 ia_css_pipe_extra_config_defaults(&extra_config);
694 __apply_additional_pipe_config(asd, stream_env, pipe_id);
695 if (!memcmp(&extra_config,
696 &stream_env->pipe_extra_configs[pipe_id],
697 sizeof(extra_config)))
698 ret = ia_css_pipe_create(
699 &stream_env->pipe_configs[pipe_id],
700 &stream_env->pipes[pipe_id]);
702 ret = ia_css_pipe_create_extra(
703 &stream_env->pipe_configs[pipe_id],
704 &stream_env->pipe_extra_configs[pipe_id],
705 &stream_env->pipes[pipe_id]);
707 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
711 static int __create_pipes(struct atomisp_sub_device *asd)
716 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
717 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
718 ret = __create_pipe(asd, &asd->stream_env[i], j);
722 if (j < IA_CSS_PIPE_ID_NUM)
727 for (; i >= 0; i--) {
728 for (j--; j >= 0; j--) {
729 if (asd->stream_env[i].pipes[j]) {
730 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
731 asd->stream_env[i].pipes[j] = NULL;
734 j = IA_CSS_PIPE_ID_NUM;
739 int atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
743 ret = __create_pipes(asd);
745 dev_err(asd->isp->dev, "create pipe failed %d.\n", ret);
749 ret = __create_streams(asd);
751 dev_warn(asd->isp->dev, "create stream failed %d.\n", ret);
752 __destroy_pipes(asd);
759 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
761 atomisp_destroy_pipes_stream_force(asd);
762 return atomisp_create_pipes_stream(asd);
765 int atomisp_css_init(struct atomisp_device *isp)
767 unsigned int mmu_base_addr;
771 ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
776 err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
777 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
779 dev_err(isp->dev, "css init failed --- bad firmware?\n");
782 ia_css_enable_isys_event_queue(true);
784 isp->css_initialized = true;
785 dev_dbg(isp->dev, "sh_css_init success\n");
790 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
795 isp->css_env.isp_css_env.print_env.debug_print = NULL;
797 isp->css_env.isp_css_env.print_env.debug_print = atomisp_vprintk;
804 int atomisp_css_load_firmware(struct atomisp_device *isp)
809 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
810 isp->css_env.isp_css_fw.bytes = isp->firmware->size;
812 isp->css_env.isp_css_env.hw_access_env.store_8 =
813 atomisp_css2_hw_store_8;
814 isp->css_env.isp_css_env.hw_access_env.store_16 =
815 atomisp_css2_hw_store_16;
816 isp->css_env.isp_css_env.hw_access_env.store_32 =
817 atomisp_css2_hw_store_32;
819 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
820 isp->css_env.isp_css_env.hw_access_env.load_16 =
821 atomisp_css2_hw_load_16;
822 isp->css_env.isp_css_env.hw_access_env.load_32 =
823 atomisp_css2_hw_load_32;
825 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
826 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
828 __set_css_print_env(isp, dbg_func);
830 isp->css_env.isp_css_env.print_env.error_print = atomisp_vprintk;
832 /* load isp fw into ISP memory */
833 err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env,
834 &isp->css_env.isp_css_fw);
836 dev_err(isp->dev, "css load fw failed.\n");
843 void atomisp_css_uninit(struct atomisp_device *isp)
845 isp->css_initialized = false;
849 int atomisp_css_irq_translate(struct atomisp_device *isp,
854 err = ia_css_irq_translate(infos);
857 "%s:failed to translate irq (err = %d,infos = %d)\n",
858 __func__, err, *infos);
865 void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
869 ia_css_isys_rx_get_irq_info(port, infos);
875 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
879 ia_css_isys_rx_clear_irq_info(port, infos);
883 int atomisp_css_irq_enable(struct atomisp_device *isp,
884 enum ia_css_irq_info info, bool enable)
886 dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s (%d).\n",
888 enable ? "enable" : "disable", enable);
889 if (ia_css_irq_enable(info, enable)) {
890 dev_warn(isp->dev, "%s:Invalid irq info: 0x%08x when %s.\n",
892 enable ? "enabling" : "disabling");
899 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
903 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
904 asd->stream_env[i].stream = NULL;
905 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
906 asd->stream_env[i].pipes[j] = NULL;
907 asd->stream_env[i].update_pipe[j] = false;
908 ia_css_pipe_config_defaults(
909 &asd->stream_env[i].pipe_configs[j]);
910 ia_css_pipe_extra_config_defaults(
911 &asd->stream_env[i].pipe_extra_configs[j]);
913 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
917 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
918 struct ia_css_frame *frame,
919 enum atomisp_input_stream_id stream_id,
920 enum ia_css_buffer_type css_buf_type,
921 enum ia_css_pipe_id css_pipe_id)
923 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
924 struct ia_css_buffer css_buf = {0};
927 css_buf.type = css_buf_type;
928 css_buf.data.frame = frame;
930 err = ia_css_pipe_enqueue_buffer(
931 stream_env->pipes[css_pipe_id], &css_buf);
938 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
939 struct atomisp_metadata_buf *metadata_buf,
940 enum atomisp_input_stream_id stream_id,
941 enum ia_css_pipe_id css_pipe_id)
943 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
944 struct ia_css_buffer buffer = {0};
945 struct atomisp_device *isp = asd->isp;
947 buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
948 buffer.data.metadata = metadata_buf->metadata;
949 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
951 dev_err(isp->dev, "failed to q meta data buffer\n");
958 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
959 struct atomisp_s3a_buf *s3a_buf,
960 enum atomisp_input_stream_id stream_id,
961 enum ia_css_pipe_id css_pipe_id)
963 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
964 struct ia_css_buffer buffer = {0};
965 struct atomisp_device *isp = asd->isp;
967 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
968 buffer.data.stats_3a = s3a_buf->s3a_data;
969 if (ia_css_pipe_enqueue_buffer(
970 stream_env->pipes[css_pipe_id],
972 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
979 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
980 struct atomisp_dis_buf *dis_buf,
981 enum atomisp_input_stream_id stream_id,
982 enum ia_css_pipe_id css_pipe_id)
984 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
985 struct ia_css_buffer buffer = {0};
986 struct atomisp_device *isp = asd->isp;
988 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
989 buffer.data.stats_dvs = dis_buf->dis_data;
990 if (ia_css_pipe_enqueue_buffer(
991 stream_env->pipes[css_pipe_id],
993 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
1000 int atomisp_css_start(struct atomisp_sub_device *asd,
1001 enum ia_css_pipe_id pipe_id, bool in_reset)
1003 struct atomisp_device *isp = asd->isp;
1004 bool sp_is_started = false;
1008 ret = atomisp_css_update_stream(asd);
1012 /* Invalidate caches. FIXME: should flush only necessary buffers */
1017 * For dual steam case, it is possible that:
1018 * 1: for this stream, it is at the stage that:
1019 * - after set_fmt is called
1020 * - before stream on is called
1021 * 2: for the other stream, the stream off is called which css reset
1024 * Thus the stream created in set_fmt get destroyed and need to be
1025 * recreated in the next stream on.
1027 if (!asd->stream_prepared) {
1028 ret = atomisp_create_pipes_stream(asd);
1033 * SP can only be started one time
1034 * if atomisp_subdev_streaming_count() tell there already has some
1035 * subdev at streamming, then SP should already be started previously,
1036 * so need to skip start sp procedure
1038 if (atomisp_streaming_count(isp)) {
1039 dev_dbg(isp->dev, "skip start sp\n");
1041 if (!sh_css_hrt_system_is_idle())
1042 dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1043 if (ia_css_start_sp()) {
1044 dev_err(isp->dev, "start sp error.\n");
1048 sp_is_started = true;
1052 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1053 if (asd->stream_env[i].stream) {
1054 if (ia_css_stream_start(asd->stream_env[i]
1056 dev_err(isp->dev, "stream[%d] start error.\n", i);
1060 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1061 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1069 atomisp_destroy_pipes_stream_force(asd);
1071 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1075 * SP can not be stop if other streams are in use
1077 if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1083 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1087 * for ISP2401 new input system, this api is under development.
1088 * Calling it would cause kernel panic.
1092 * Check if it is Cherry Trail and also new input system
1094 if (asd->copy_mode) {
1095 dev_warn(asd->isp->dev,
1096 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1101 ia_css_stream_set_isp_config(
1102 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1103 &asd->params.config);
1104 memset(&asd->params.config, 0, sizeof(asd->params.config));
1107 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1108 struct ia_css_pipe *pipe)
1113 atomisp_css_update_isp_params(asd);
1117 dev_dbg(asd->isp->dev,
1118 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1119 __func__, asd->params.config.output_frame,
1120 asd->params.config.isp_config_id, pipe);
1122 ret = ia_css_stream_set_isp_config_on_pipe(
1123 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1124 &asd->params.config, pipe);
1126 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1128 memset(&asd->params.config, 0, sizeof(asd->params.config));
1131 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1132 enum atomisp_input_stream_id stream_id,
1133 enum ia_css_pipe_id pipe_id,
1134 enum ia_css_buffer_type buf_type,
1135 struct atomisp_css_buffer *isp_css_buffer)
1137 if (ia_css_pipe_enqueue_buffer(
1138 asd->stream_env[stream_id].pipes[pipe_id],
1139 &isp_css_buffer->css_buffer)
1146 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1147 enum atomisp_input_stream_id stream_id,
1148 enum ia_css_pipe_id pipe_id,
1149 enum ia_css_buffer_type buf_type,
1150 struct atomisp_css_buffer *isp_css_buffer)
1152 struct atomisp_device *isp = asd->isp;
1155 err = ia_css_pipe_dequeue_buffer(
1156 asd->stream_env[stream_id].pipes[pipe_id],
1157 &isp_css_buffer->css_buffer);
1160 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1167 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd,
1169 struct atomisp_s3a_buf *s3a_buf,
1170 struct atomisp_dis_buf *dis_buf,
1171 struct atomisp_metadata_buf *md_buf)
1173 struct atomisp_device *isp = asd->isp;
1174 struct ia_css_dvs_grid_info *dvs_grid_info =
1175 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1177 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1180 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1181 &asd->params.curr_grid_info.s3a_grid);
1182 if (!s3a_buf->s3a_data) {
1183 dev_err(isp->dev, "3a buf allocation failed.\n");
1187 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1188 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1189 s3a_buf->s3a_data, s3a_ptr);
1192 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1195 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1197 if (!dis_buf->dis_data) {
1198 dev_err(isp->dev, "dvs buf allocation failed.\n");
1200 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1204 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1205 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1206 dis_buf->dis_data, dvs_ptr);
1209 if (asd->stream_env[stream_id].stream_info.
1210 metadata_info.size && md_buf) {
1211 md_buf->metadata = ia_css_metadata_allocate(
1212 &asd->stream_env[stream_id].stream_info.metadata_info);
1213 if (!md_buf->metadata) {
1215 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1217 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1218 dev_err(isp->dev, "metadata buf allocation failed.\n");
1221 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1227 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1229 if (s3a_buf->s3a_data)
1230 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1232 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1233 s3a_buf->s3a_map = NULL;
1234 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1237 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1239 if (dis_buf->dis_data)
1240 hmm_vunmap(dis_buf->dis_data->data_ptr);
1242 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1243 dis_buf->dvs_map = NULL;
1244 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1247 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1249 if (metadata_buf->md_vptr) {
1250 hmm_vunmap(metadata_buf->metadata->address);
1251 metadata_buf->md_vptr = NULL;
1253 ia_css_metadata_free(metadata_buf->metadata);
1256 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1258 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1259 struct atomisp_dis_buf *dis_buf, *_dis_buf;
1260 struct atomisp_metadata_buf *md_buf, *_md_buf;
1261 struct ia_css_dvs_grid_info *dvs_grid_info =
1262 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1265 /* 3A statistics use vmalloc, DIS use kmalloc */
1266 if (dvs_grid_info && dvs_grid_info->enable) {
1267 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1268 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1269 asd->params.css_param.dvs2_coeff = NULL;
1270 asd->params.dvs_stat = NULL;
1271 asd->params.dvs_hor_proj_bytes = 0;
1272 asd->params.dvs_ver_proj_bytes = 0;
1273 asd->params.dvs_hor_coef_bytes = 0;
1274 asd->params.dvs_ver_coef_bytes = 0;
1275 asd->params.dis_proj_data_valid = false;
1276 list_for_each_entry_safe(dis_buf, _dis_buf,
1277 &asd->dis_stats, list) {
1278 atomisp_css_free_dis_buffer(dis_buf);
1279 list_del(&dis_buf->list);
1282 list_for_each_entry_safe(dis_buf, _dis_buf,
1283 &asd->dis_stats_in_css, list) {
1284 atomisp_css_free_dis_buffer(dis_buf);
1285 list_del(&dis_buf->list);
1289 if (asd->params.curr_grid_info.s3a_grid.enable) {
1290 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1291 asd->params.s3a_user_stat = NULL;
1292 asd->params.s3a_output_bytes = 0;
1293 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1294 &asd->s3a_stats, list) {
1295 atomisp_css_free_3a_buffer(s3a_buf);
1296 list_del(&s3a_buf->list);
1299 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1300 &asd->s3a_stats_in_css, list) {
1301 atomisp_css_free_3a_buffer(s3a_buf);
1302 list_del(&s3a_buf->list);
1305 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1306 &asd->s3a_stats_ready, list) {
1307 atomisp_css_free_3a_buffer(s3a_buf);
1308 list_del(&s3a_buf->list);
1313 if (asd->params.css_param.dvs_6axis) {
1314 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1315 asd->params.css_param.dvs_6axis = NULL;
1318 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1319 list_for_each_entry_safe(md_buf, _md_buf,
1320 &asd->metadata[i], list) {
1321 atomisp_css_free_metadata_buffer(md_buf);
1322 list_del(&md_buf->list);
1325 list_for_each_entry_safe(md_buf, _md_buf,
1326 &asd->metadata_in_css[i], list) {
1327 atomisp_css_free_metadata_buffer(md_buf);
1328 list_del(&md_buf->list);
1331 list_for_each_entry_safe(md_buf, _md_buf,
1332 &asd->metadata_ready[i], list) {
1333 atomisp_css_free_metadata_buffer(md_buf);
1334 list_del(&md_buf->list);
1338 asd->params.metadata_width_size = 0;
1339 atomisp_free_metadata_output_buf(asd);
1342 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1343 enum ia_css_pipe_id pipe_id,
1346 struct ia_css_pipe_info p_info;
1347 struct ia_css_grid_info old_info;
1348 struct atomisp_device *isp = asd->isp;
1349 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1350 stream_config.metadata_config.resolution.width;
1352 memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1353 memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1355 if (ia_css_pipe_get_info(
1356 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipes[pipe_id],
1358 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1362 memcpy(&old_info, &asd->params.curr_grid_info,
1363 sizeof(struct ia_css_grid_info));
1364 memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1365 sizeof(struct ia_css_grid_info));
1367 * Record which css pipe enables s3a_grid.
1368 * Currently would have one css pipe that need it
1370 if (asd->params.curr_grid_info.s3a_grid.enable) {
1371 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM)
1372 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1373 asd->params.s3a_enabled_pipe, pipe_id);
1374 asd->params.s3a_enabled_pipe = pipe_id;
1377 /* If the grid info has not changed and the buffers for 3A and
1378 * DIS statistics buffers are allocated or buffer size would be zero
1379 * then no need to do anything. */
1380 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1381 && asd->params.s3a_user_stat && asd->params.dvs_stat)
1382 || asd->params.curr_grid_info.s3a_grid.width == 0
1383 || asd->params.curr_grid_info.s3a_grid.height == 0)
1384 && asd->params.metadata_width_size == md_width) {
1386 "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1387 !memcmp(&old_info, &asd->params.curr_grid_info,
1389 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1390 asd->params.curr_grid_info.s3a_grid.width,
1391 asd->params.curr_grid_info.s3a_grid.height,
1392 asd->params.metadata_width_size);
1395 asd->params.metadata_width_size = md_width;
1400 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1402 if (!asd->params.curr_grid_info.s3a_grid.width ||
1403 !asd->params.curr_grid_info.s3a_grid.height)
1406 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1407 &asd->params.curr_grid_info.s3a_grid);
1408 if (!asd->params.s3a_user_stat)
1410 /* 3A statistics. These can be big, so we use vmalloc. */
1411 asd->params.s3a_output_bytes =
1412 asd->params.curr_grid_info.s3a_grid.width *
1413 asd->params.curr_grid_info.s3a_grid.height *
1414 sizeof(*asd->params.s3a_user_stat->data);
1419 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1421 struct ia_css_dvs_grid_info *dvs_grid =
1422 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1427 if (!dvs_grid->enable) {
1428 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1432 /* DIS coefficients. */
1433 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1435 if (!asd->params.css_param.dvs2_coeff)
1438 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1439 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1441 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1442 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1444 /* DIS projections. */
1445 asd->params.dis_proj_data_valid = false;
1446 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1447 if (!asd->params.dvs_stat)
1450 asd->params.dvs_hor_proj_bytes =
1451 dvs_grid->aligned_height * dvs_grid->aligned_width *
1452 sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1454 asd->params.dvs_ver_proj_bytes =
1455 dvs_grid->aligned_height * dvs_grid->aligned_width *
1456 sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1461 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1465 /* We allocate the cpu-side buffer used for communication with user
1467 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1468 asd->params.metadata_user[i] = kvmalloc(
1469 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1470 stream_info.metadata_info.size, GFP_KERNEL);
1471 if (!asd->params.metadata_user[i]) {
1473 kvfree(asd->params.metadata_user[i]);
1474 asd->params.metadata_user[i] = NULL;
1483 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1487 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1488 if (asd->params.metadata_user[i]) {
1489 kvfree(asd->params.metadata_user[i]);
1490 asd->params.metadata_user[i] = NULL;
1495 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1496 struct atomisp_css_event *current_event)
1500 * Pipe ID reported in CSS event is not correct for new system's
1504 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1505 ¤t_event->pipe);
1506 if (asd && asd->copy_mode &&
1507 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1508 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1511 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1512 enum atomisp_input_stream_id stream_id,
1513 struct v4l2_mbus_framefmt *ffmt,
1516 struct ia_css_stream_config *s_config =
1517 &asd->stream_env[stream_id].stream_config;
1519 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1522 s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1523 s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1527 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1528 enum atomisp_input_stream_id stream_id,
1529 struct v4l2_mbus_framefmt *ffmt)
1531 struct ia_css_stream_config *s_config =
1532 &asd->stream_env[stream_id].stream_config;
1534 s_config->input_config.input_res.width = ffmt->width;
1535 s_config->input_config.input_res.height = ffmt->height;
1539 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1540 enum atomisp_input_stream_id stream_id,
1541 unsigned int bin_factor)
1543 asd->stream_env[stream_id]
1544 .stream_config.sensor_binning_factor = bin_factor;
1547 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1548 enum atomisp_input_stream_id stream_id,
1549 enum ia_css_bayer_order bayer_order)
1551 struct ia_css_stream_config *s_config =
1552 &asd->stream_env[stream_id].stream_config;
1553 s_config->input_config.bayer_order = bayer_order;
1556 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1557 enum atomisp_input_stream_id stream_id,
1561 struct ia_css_stream_config *s_config =
1562 &asd->stream_env[stream_id].stream_config;
1564 s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1567 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1568 enum atomisp_input_stream_id stream_id,
1572 struct ia_css_stream_config *s_config =
1573 &asd->stream_env[stream_id].stream_config;
1575 s_config->isys_config[isys_stream].valid = valid;
1578 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1579 enum atomisp_input_stream_id stream_id,
1580 enum atomisp_input_format format,
1583 struct ia_css_stream_config *s_config =
1584 &asd->stream_env[stream_id].stream_config;
1586 s_config->isys_config[isys_stream].format = format;
1589 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1590 enum atomisp_input_stream_id stream_id,
1591 enum atomisp_input_format format)
1593 struct ia_css_stream_config *s_config =
1594 &asd->stream_env[stream_id].stream_config;
1596 s_config->input_config.format = format;
1599 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1600 enum atomisp_input_stream_id stream_id,
1601 struct v4l2_mbus_framefmt *ffmt)
1604 struct ia_css_stream_config *s_config =
1605 &asd->stream_env[stream_id].stream_config;
1607 * Set all isys configs to not valid.
1608 * Currently we support only one stream per channel
1610 for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1611 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1612 s_config->isys_config[i].valid = false;
1614 atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1615 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1616 atomisp_css_isys_set_format(asd, stream_id,
1617 s_config->input_config.format,
1618 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1619 atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1620 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1621 atomisp_css_isys_set_valid(asd, stream_id, true,
1622 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1627 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1628 enum atomisp_input_stream_id stream_id,
1629 enum atomisp_input_format input_format)
1631 struct ia_css_stream_config *s_config =
1632 &asd->stream_env[stream_id].stream_config;
1634 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1635 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1637 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1638 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1640 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1641 = IA_CSS_STREAM_ISYS_STREAM_0;
1642 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1643 ATOMISP_INPUT_FORMAT_USER_DEF1;
1644 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1645 ATOMISP_INPUT_FORMAT_USER_DEF2;
1646 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1650 void atomisp_css_isys_two_stream_cfg_update_stream1(
1651 struct atomisp_sub_device *asd,
1652 enum atomisp_input_stream_id stream_id,
1653 enum atomisp_input_format input_format,
1654 unsigned int width, unsigned int height)
1656 struct ia_css_stream_config *s_config =
1657 &asd->stream_env[stream_id].stream_config;
1659 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1661 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1663 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1665 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1668 void atomisp_css_isys_two_stream_cfg_update_stream2(
1669 struct atomisp_sub_device *asd,
1670 enum atomisp_input_stream_id stream_id,
1671 enum atomisp_input_format input_format,
1672 unsigned int width, unsigned int height)
1674 struct ia_css_stream_config *s_config =
1675 &asd->stream_env[stream_id].stream_config;
1677 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1679 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1681 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1682 = IA_CSS_STREAM_ISYS_STREAM_0;
1683 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1685 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1688 int atomisp_css_input_set_effective_resolution(
1689 struct atomisp_sub_device *asd,
1690 enum atomisp_input_stream_id stream_id,
1691 unsigned int width, unsigned int height)
1693 struct ia_css_stream_config *s_config =
1694 &asd->stream_env[stream_id].stream_config;
1695 s_config->input_config.effective_res.width = width;
1696 s_config->input_config.effective_res.height = height;
1700 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1701 unsigned int dvs_w, unsigned int dvs_h)
1703 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1704 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1705 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1706 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1709 void atomisp_css_input_set_two_pixels_per_clock(
1710 struct atomisp_sub_device *asd,
1715 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1716 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1719 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1720 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1721 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1722 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1723 .update_pipe[i] = true;
1726 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1730 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1731 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1732 .pipe_configs[i].enable_dz = enable;
1735 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1736 enum ia_css_capture_mode mode)
1738 struct atomisp_stream_env *stream_env =
1739 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1741 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1742 .default_capture_config.mode == mode)
1745 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1746 default_capture_config.mode = mode;
1747 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1750 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
1751 enum ia_css_input_mode mode)
1754 struct atomisp_device *isp = asd->isp;
1755 unsigned int size_mem_words;
1757 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
1758 asd->stream_env[i].stream_config.mode = mode;
1760 if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
1761 struct ia_css_stream_config *s_config =
1762 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
1763 s_config->mode = IA_CSS_INPUT_MODE_TPG;
1764 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
1765 s_config->source.tpg.x_mask = (1 << 4) - 1;
1766 s_config->source.tpg.x_delta = -2;
1767 s_config->source.tpg.y_mask = (1 << 4) - 1;
1768 s_config->source.tpg.y_delta = 3;
1769 s_config->source.tpg.xy_mask = (1 << 8) - 1;
1773 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1776 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1778 * TODO: sensor needs to export the embedded_data_size_words
1779 * information to atomisp for each setting.
1780 * Here using a large safe value.
1782 struct ia_css_stream_config *s_config =
1783 &asd->stream_env[i].stream_config;
1785 if (s_config->input_config.input_res.width == 0)
1788 if (ia_css_mipi_frame_calculate_size(
1789 s_config->input_config.input_res.width,
1790 s_config->input_config.input_res.height,
1791 s_config->input_config.format,
1794 &size_mem_words) != 0) {
1796 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
1798 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
1799 dev_warn(asd->isp->dev,
1800 "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n",
1803 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
1804 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
1808 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
1809 unsigned short stream_index, bool enable)
1811 struct atomisp_stream_env *stream_env =
1812 &asd->stream_env[stream_index];
1814 if (stream_env->stream_config.online == !!enable)
1817 stream_env->stream_config.online = !!enable;
1818 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1821 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
1822 unsigned short stream_index, bool enable)
1824 struct atomisp_stream_env *stream_env =
1825 &asd->stream_env[stream_index];
1828 if (stream_env->stream_config.online != !!enable) {
1829 stream_env->stream_config.online = !!enable;
1830 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1831 stream_env->update_pipe[i] = true;
1835 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
1838 struct atomisp_stream_env *stream_env =
1839 &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
1842 if (stream_env->stream_config.online != enable) {
1843 stream_env->stream_config.online = enable;
1844 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1845 stream_env->update_pipe[i] = true;
1849 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
1852 struct atomisp_stream_env *stream_env =
1853 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1856 if (stream_env->stream_config.continuous != !!enable) {
1857 stream_env->stream_config.continuous = !!enable;
1858 stream_env->stream_config.pack_raw_pixels = true;
1859 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1860 stream_env->update_pipe[i] = true;
1864 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
1867 struct atomisp_stream_env *stream_env =
1868 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1871 if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
1872 stream_env->stream_config.disable_cont_viewfinder = !enable;
1873 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1874 stream_env->update_pipe[i] = true;
1878 int atomisp_css_input_configure_port(
1879 struct atomisp_sub_device *asd,
1880 enum mipi_port_id port,
1881 unsigned int num_lanes,
1882 unsigned int timeout,
1883 unsigned int mipi_freq,
1884 enum atomisp_input_format metadata_format,
1885 unsigned int metadata_width,
1886 unsigned int metadata_height)
1889 struct atomisp_stream_env *stream_env;
1891 * Calculate rx_count as follows:
1892 * Input: mipi_freq : CSI-2 bus frequency in Hz
1893 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus
1894 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds
1895 * max = 145e-9 + 10 * UI
1896 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
1897 * rxcount = rxcount0 - 2 : adjust for better results
1898 * The formula below is simplified version of the above with
1899 * 10-bit fixed points for improved accuracy.
1901 const unsigned int rxcount =
1902 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
1904 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1905 stream_env = &asd->stream_env[i];
1906 stream_env->stream_config.source.port.port = port;
1907 stream_env->stream_config.source.port.num_lanes = num_lanes;
1908 stream_env->stream_config.source.port.timeout = timeout;
1910 stream_env->stream_config.source.port.rxcount = rxcount;
1911 stream_env->stream_config.
1912 metadata_config.data_type = metadata_format;
1913 stream_env->stream_config.
1914 metadata_config.resolution.width = metadata_width;
1915 stream_env->stream_config.
1916 metadata_config.resolution.height = metadata_height;
1922 void atomisp_css_stop(struct atomisp_sub_device *asd,
1923 enum ia_css_pipe_id pipe_id, bool in_reset)
1925 struct atomisp_device *isp = asd->isp;
1926 unsigned long irqflags;
1929 /* if is called in atomisp_reset(), force destroy streams and pipes */
1930 atomisp_destroy_pipes_stream_force(asd);
1932 atomisp_init_raw_buffer_bitmap(asd);
1935 * SP can not be stop if other streams are in use
1937 if (atomisp_streaming_count(isp) == 0)
1941 struct atomisp_stream_env *stream_env;
1944 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1945 stream_env = &asd->stream_env[i];
1946 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
1947 ia_css_pipe_config_defaults(
1948 &stream_env->pipe_configs[j]);
1949 ia_css_pipe_extra_config_defaults(
1950 &stream_env->pipe_extra_configs[j]);
1952 ia_css_stream_config_defaults(
1953 &stream_env->stream_config);
1955 memset(&asd->params.config, 0, sizeof(asd->params.config));
1956 asd->params.css_update_params_needed = false;
1959 /* move stats buffers to free queue list */
1960 list_splice_init(&asd->s3a_stats_in_css, &asd->s3a_stats);
1961 list_splice_init(&asd->s3a_stats_ready, &asd->s3a_stats);
1963 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
1964 list_splice_init(&asd->dis_stats_in_css, &asd->dis_stats);
1965 asd->params.dis_proj_data_valid = false;
1966 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
1968 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1969 list_splice_init(&asd->metadata_in_css[i], &asd->metadata[i]);
1970 list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]);
1973 atomisp_flush_params_queue(&asd->video_out_capture);
1974 atomisp_flush_params_queue(&asd->video_out_vf);
1975 atomisp_flush_params_queue(&asd->video_out_preview);
1976 atomisp_flush_params_queue(&asd->video_out_video_capture);
1977 atomisp_free_css_parameters(&asd->params.css_param);
1978 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
1981 void atomisp_css_continuous_set_num_raw_frames(
1982 struct atomisp_sub_device *asd,
1985 if (asd->enable_raw_buffer_lock->val) {
1986 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1987 .stream_config.init_num_cont_raw_buf =
1988 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
1989 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
1990 asd->params.video_dis_en)
1991 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1992 .stream_config.init_num_cont_raw_buf +=
1993 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
1995 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1996 .stream_config.init_num_cont_raw_buf =
1997 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
2000 if (asd->params.video_dis_en)
2001 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2002 .stream_config.init_num_cont_raw_buf +=
2003 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2005 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2006 .stream_config.target_num_cont_raw_buf = num_frames;
2009 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2010 struct atomisp_sub_device *asd,
2011 enum ia_css_pipe_id pipe_id)
2013 struct atomisp_device *isp = asd->isp;
2014 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2015 isp->inputs[asd->input_curr].camera);
2018 case IA_CSS_PIPE_ID_COPY:
2019 /* Currently only YUVPP mode supports YUV420_Legacy format.
2020 * Revert this when other pipe modes can support
2021 * YUV420_Legacy format.
2023 if (mipi_info && mipi_info->input_format ==
2024 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2025 return IA_CSS_PIPE_MODE_YUVPP;
2026 return IA_CSS_PIPE_MODE_COPY;
2027 case IA_CSS_PIPE_ID_PREVIEW:
2028 return IA_CSS_PIPE_MODE_PREVIEW;
2029 case IA_CSS_PIPE_ID_CAPTURE:
2030 return IA_CSS_PIPE_MODE_CAPTURE;
2031 case IA_CSS_PIPE_ID_VIDEO:
2032 return IA_CSS_PIPE_MODE_VIDEO;
2033 case IA_CSS_PIPE_ID_YUVPP:
2034 return IA_CSS_PIPE_MODE_YUVPP;
2037 return IA_CSS_PIPE_MODE_PREVIEW;
2041 static void __configure_output(struct atomisp_sub_device *asd,
2042 unsigned int stream_index,
2043 unsigned int width, unsigned int height,
2044 unsigned int min_width,
2045 enum ia_css_frame_format format,
2046 enum ia_css_pipe_id pipe_id)
2048 struct atomisp_device *isp = asd->isp;
2049 struct atomisp_stream_env *stream_env =
2050 &asd->stream_env[stream_index];
2051 struct ia_css_stream_config *s_config = &stream_env->stream_config;
2053 stream_env->pipe_configs[pipe_id].mode =
2054 __pipe_id_to_pipe_mode(asd, pipe_id);
2055 stream_env->update_pipe[pipe_id] = true;
2057 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2058 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2059 stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2060 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2062 /* isp binary 2.2 specific setting*/
2063 if (width > s_config->input_config.effective_res.width ||
2064 height > s_config->input_config.effective_res.height) {
2065 s_config->input_config.effective_res.width = width;
2066 s_config->input_config.effective_res.height = height;
2069 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2070 pipe_id, width, height, format);
2074 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2075 * downscaling input resolution.
2077 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2078 unsigned int width, unsigned int height,
2079 enum ia_css_pipe_id pipe_id)
2081 struct atomisp_device *isp = asd->isp;
2082 struct atomisp_stream_env *stream_env =
2083 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2084 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2085 struct ia_css_pipe_config *pipe_configs =
2086 &stream_env->pipe_configs[pipe_id];
2087 struct ia_css_pipe_extra_config *pipe_extra_configs =
2088 &stream_env->pipe_extra_configs[pipe_id];
2089 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2091 if (width == 0 && height == 0)
2094 if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2095 height * 9 / 10 < pipe_configs->output_info[0].res.height)
2097 /* here just copy the calculation in css */
2098 hor_ds_factor = CEIL_DIV(width >> 1,
2099 pipe_configs->output_info[0].res.width);
2100 ver_ds_factor = CEIL_DIV(height >> 1,
2101 pipe_configs->output_info[0].res.height);
2103 if ((asd->isp->media_dev.hw_revision <
2104 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2105 IS_CHT) && hor_ds_factor != ver_ds_factor) {
2106 dev_warn(asd->isp->dev,
2107 "Cropping for capture due to FW limitation");
2111 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2112 stream_env->update_pipe[pipe_id] = true;
2114 pipe_extra_configs->enable_yuv_ds = true;
2116 pipe_configs->capt_pp_in_res.width =
2117 stream_config->input_config.effective_res.width;
2118 pipe_configs->capt_pp_in_res.height =
2119 stream_config->input_config.effective_res.height;
2121 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2122 pipe_id, width, height);
2126 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2127 * yuv downscaling, which needs addtional configurations.
2129 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2130 unsigned int width, unsigned int height,
2131 enum ia_css_pipe_id pipe_id)
2133 struct atomisp_device *isp = asd->isp;
2134 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2135 struct atomisp_stream_env *stream_env =
2136 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2137 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2138 struct ia_css_pipe_config *pipe_configs =
2139 &stream_env->pipe_configs[pipe_id];
2140 struct ia_css_pipe_extra_config *pipe_extra_configs =
2141 &stream_env->pipe_extra_configs[pipe_id];
2142 struct ia_css_resolution *bayer_ds_out_res =
2143 &pipe_configs->bayer_ds_out_res;
2144 struct ia_css_resolution *vf_pp_in_res =
2145 &pipe_configs->vf_pp_in_res;
2146 struct ia_css_resolution *effective_res =
2147 &stream_config->input_config.effective_res;
2149 static const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2151 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2152 * columns to be shaded. Remove this factor to work around the CSS bug.
2153 * const unsigned int yuv_dec_fct[] = {4, 2};
2155 static const unsigned int yuv_dec_fct[] = { 2 };
2158 if (width == 0 && height == 0)
2161 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2162 stream_env->update_pipe[pipe_id] = true;
2164 out_width = pipe_configs->output_info[0].res.width;
2165 out_height = pipe_configs->output_info[0].res.height;
2168 * The ISP could do bayer downscaling, yuv decimation and yuv
2170 * 1: Bayer Downscaling: between effective resolution and
2172 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2173 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2175 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2176 * Rule for YUV Decimation: support factor 2, 4
2177 * Rule for YUV Downscaling: arbitrary value below 2
2179 * General rule of factor distribution among these stages:
2180 * 1: try to do Bayer downscaling first if not in online mode.
2181 * 2: try to do maximum of 2 for YUV downscaling
2182 * 3: the remainling for YUV decimation
2185 * Do not configure bayer_ds_out_res if:
2186 * online == 1 or continuous == 0 or raw_binning = 0
2188 if (stream_config->online || !stream_config->continuous ||
2189 !pipe_extra_configs->enable_raw_binning) {
2190 bayer_ds_out_res->width = 0;
2191 bayer_ds_out_res->height = 0;
2193 bayer_ds_out_res->width = effective_res->width;
2194 bayer_ds_out_res->height = effective_res->height;
2196 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2197 if (effective_res->width >= out_width *
2198 bds_fct[i].numerator / bds_fct[i].denominator &&
2199 effective_res->height >= out_height *
2200 bds_fct[i].numerator / bds_fct[i].denominator) {
2201 bayer_ds_out_res->width =
2202 effective_res->width *
2203 bds_fct[i].denominator /
2204 bds_fct[i].numerator;
2205 bayer_ds_out_res->height =
2206 effective_res->height *
2207 bds_fct[i].denominator /
2208 bds_fct[i].numerator;
2214 * calculate YUV Decimation, YUV downscaling facor:
2215 * YUV Downscaling factor must not exceed 2.
2216 * YUV Decimation factor could be 2, 4.
2218 /* first decide the yuv_ds input resolution */
2219 if (bayer_ds_out_res->width == 0) {
2220 yuv_ds_in_width = effective_res->width;
2221 yuv_ds_in_height = effective_res->height;
2223 yuv_ds_in_width = bayer_ds_out_res->width;
2224 yuv_ds_in_height = bayer_ds_out_res->height;
2227 vf_pp_in_res->width = yuv_ds_in_width;
2228 vf_pp_in_res->height = yuv_ds_in_height;
2230 /* find out the yuv decimation factor */
2231 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2232 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2233 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2234 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2235 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2240 if (vf_pp_in_res->width == out_width &&
2241 vf_pp_in_res->height == out_height) {
2242 pipe_extra_configs->enable_yuv_ds = false;
2243 vf_pp_in_res->width = 0;
2244 vf_pp_in_res->height = 0;
2246 pipe_extra_configs->enable_yuv_ds = true;
2249 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2250 pipe_id, width, height);
2254 * For CSS2.1, offline video pipe could support bayer decimation, and
2255 * yuv downscaling, which needs addtional configurations.
2257 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2258 unsigned int width, unsigned int height,
2259 enum ia_css_pipe_id pipe_id)
2261 struct atomisp_device *isp = asd->isp;
2262 int out_width, out_height;
2263 struct atomisp_stream_env *stream_env =
2264 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2265 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2266 struct ia_css_pipe_config *pipe_configs =
2267 &stream_env->pipe_configs[pipe_id];
2268 struct ia_css_pipe_extra_config *pipe_extra_configs =
2269 &stream_env->pipe_extra_configs[pipe_id];
2270 struct ia_css_resolution *bayer_ds_out_res =
2271 &pipe_configs->bayer_ds_out_res;
2272 struct ia_css_resolution *effective_res =
2273 &stream_config->input_config.effective_res;
2275 static const struct bayer_ds_factor bds_factors[] = {
2276 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
2280 if (width == 0 && height == 0)
2283 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2284 stream_env->update_pipe[pipe_id] = true;
2286 pipe_extra_configs->enable_yuv_ds = false;
2289 * If DVS is enabled, video binary will take care the dvs envelope
2290 * and usually the bayer_ds_out_res should be larger than 120% of
2291 * destination resolution, the extra 20% will be cropped as DVS
2292 * envelope. But, if the bayer_ds_out_res is less than 120% of the
2293 * destination. The ISP can still work, but DVS quality is not good.
2295 /* taking at least 10% as envelope */
2296 if (asd->params.video_dis_en) {
2297 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2298 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2300 out_width = pipe_configs->output_info[0].res.width;
2301 out_height = pipe_configs->output_info[0].res.height;
2305 * calculate bayer decimate factor:
2306 * 1: only 1.5, 2, 4 and 8 get supported
2307 * 2: Do not configure bayer_ds_out_res if:
2308 * online == 1 or continuous == 0 or raw_binning = 0
2310 if (stream_config->online || !stream_config->continuous) {
2311 bayer_ds_out_res->width = 0;
2312 bayer_ds_out_res->height = 0;
2316 pipe_extra_configs->enable_raw_binning = true;
2317 bayer_ds_out_res->width = effective_res->width;
2318 bayer_ds_out_res->height = effective_res->height;
2320 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2322 if (effective_res->width >= out_width *
2323 bds_factors[i].numerator / bds_factors[i].denominator &&
2324 effective_res->height >= out_height *
2325 bds_factors[i].numerator / bds_factors[i].denominator) {
2326 bayer_ds_out_res->width = effective_res->width *
2327 bds_factors[i].denominator /
2328 bds_factors[i].numerator;
2329 bayer_ds_out_res->height = effective_res->height *
2330 bds_factors[i].denominator /
2331 bds_factors[i].numerator;
2337 * DVS is cropped from BDS output, so we do not really need to set the
2338 * envelope to 20% of output resolution here. always set it to 12x12
2339 * per firmware requirement.
2341 pipe_configs->dvs_envelope.width = 12;
2342 pipe_configs->dvs_envelope.height = 12;
2345 if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2346 stream_config->left_padding = -1;
2348 stream_config->left_padding = 12;
2349 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2350 pipe_id, width, height);
2353 static void __configure_vf_output(struct atomisp_sub_device *asd,
2354 unsigned int width, unsigned int height,
2355 unsigned int min_width,
2356 enum ia_css_frame_format format,
2357 enum ia_css_pipe_id pipe_id)
2359 struct atomisp_device *isp = asd->isp;
2360 struct atomisp_stream_env *stream_env =
2361 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2362 stream_env->pipe_configs[pipe_id].mode =
2363 __pipe_id_to_pipe_mode(asd, pipe_id);
2364 stream_env->update_pipe[pipe_id] = true;
2366 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2367 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2368 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2369 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2372 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2373 pipe_id, width, height, format);
2376 static int __get_frame_info(struct atomisp_sub_device *asd,
2377 unsigned int stream_index,
2378 struct ia_css_frame_info *info,
2379 enum frame_info_type type,
2380 enum ia_css_pipe_id pipe_id)
2382 struct atomisp_device *isp = asd->isp;
2384 struct ia_css_pipe_info p_info;
2386 /* FIXME! No need to destroy/recreate all streams */
2387 ret = atomisp_css_update_stream(asd);
2391 ret = ia_css_pipe_get_info(asd->stream_env[stream_index].pipes[pipe_id],
2394 dev_err(isp->dev, "can't get info from pipe\n");
2399 case ATOMISP_CSS_VF_FRAME:
2400 *info = p_info.vf_output_info[0];
2401 dev_dbg(isp->dev, "getting vf frame info.\n");
2403 case ATOMISP_CSS_SECOND_VF_FRAME:
2404 *info = p_info.vf_output_info[1];
2405 dev_dbg(isp->dev, "getting second vf frame info.\n");
2407 case ATOMISP_CSS_OUTPUT_FRAME:
2408 *info = p_info.output_info[0];
2409 dev_dbg(isp->dev, "getting main frame info.\n");
2411 case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2412 *info = p_info.output_info[1];
2413 dev_dbg(isp->dev, "getting second main frame info.\n");
2416 case ATOMISP_CSS_RAW_FRAME:
2417 *info = p_info.raw_output_info;
2418 dev_dbg(isp->dev, "getting raw frame info.\n");
2421 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2422 info->res.width, info->res.height, p_info.num_invalid_frames);
2427 atomisp_destroy_pipes_stream_force(asd);
2431 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2432 uint16_t source_pad)
2434 struct atomisp_device *isp = asd->isp;
2436 switch (source_pad) {
2437 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2439 return IA_CSS_PIPE_ID_COPY;
2440 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2441 || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2442 return IA_CSS_PIPE_ID_VIDEO;
2444 return IA_CSS_PIPE_ID_CAPTURE;
2445 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2447 return IA_CSS_PIPE_ID_COPY;
2449 return IA_CSS_PIPE_ID_CAPTURE;
2450 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2451 if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) {
2452 return IA_CSS_PIPE_ID_CAPTURE;
2455 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2457 return IA_CSS_PIPE_ID_COPY;
2458 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2459 return IA_CSS_PIPE_ID_VIDEO;
2461 return IA_CSS_PIPE_ID_PREVIEW;
2464 "invalid source pad:%d, return default preview pipe index.\n",
2466 return IA_CSS_PIPE_ID_PREVIEW;
2469 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2471 struct ia_css_frame_info *frame_info)
2473 struct ia_css_pipe_info info;
2474 int pipe_index = atomisp_get_pipe_index(asd, source_pad);
2476 struct atomisp_device *isp = asd->isp;
2478 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2479 ATOMISP_INPUT_STREAM_VIDEO :
2480 ATOMISP_INPUT_STREAM_GENERAL;
2482 if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index]
2483 .pipes[pipe_index], &info)) {
2484 dev_dbg(isp->dev, "ia_css_pipe_get_info FAILED");
2488 switch (source_pad) {
2489 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2490 *frame_info = info.output_info[0];
2492 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2493 *frame_info = info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2495 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2496 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
2497 *frame_info = info.output_info[0];
2499 *frame_info = info.vf_output_info[0];
2501 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2502 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2503 (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
2504 pipe_index == IA_CSS_PIPE_ID_YUVPP))
2505 *frame_info = info.vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2508 info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2515 return frame_info ? 0 : -EINVAL;
2518 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2519 unsigned int stream_index,
2520 unsigned int width, unsigned int height,
2521 unsigned int padded_width,
2522 enum ia_css_frame_format format)
2524 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
2525 default_capture_config.mode =
2526 IA_CSS_CAPTURE_MODE_RAW;
2528 __configure_output(asd, stream_index, width, height, padded_width,
2529 format, IA_CSS_PIPE_ID_COPY);
2533 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
2534 unsigned int stream_index,
2535 unsigned int width, unsigned int height,
2536 unsigned int padded_width,
2537 enum ia_css_frame_format format)
2539 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
2540 default_capture_config.mode =
2541 IA_CSS_CAPTURE_MODE_RAW;
2543 __configure_output(asd, stream_index, width, height, padded_width,
2544 format, IA_CSS_PIPE_ID_YUVPP);
2548 int atomisp_css_yuvpp_get_output_frame_info(
2549 struct atomisp_sub_device *asd,
2550 unsigned int stream_index,
2551 struct ia_css_frame_info *info)
2553 return __get_frame_info(asd, stream_index, info,
2554 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
2557 int atomisp_css_yuvpp_get_viewfinder_frame_info(
2558 struct atomisp_sub_device *asd,
2559 unsigned int stream_index,
2560 struct ia_css_frame_info *info)
2562 return __get_frame_info(asd, stream_index, info,
2563 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
2566 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
2567 unsigned int width, unsigned int height,
2568 unsigned int min_width,
2569 enum ia_css_frame_format format)
2571 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2572 min_width, format, IA_CSS_PIPE_ID_PREVIEW);
2576 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
2577 unsigned int width, unsigned int height,
2578 unsigned int min_width,
2579 enum ia_css_frame_format format)
2581 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2582 min_width, format, IA_CSS_PIPE_ID_CAPTURE);
2586 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
2587 unsigned int width, unsigned int height,
2588 unsigned int min_width,
2589 enum ia_css_frame_format format)
2591 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2592 min_width, format, IA_CSS_PIPE_ID_VIDEO);
2596 int atomisp_css_video_configure_viewfinder(
2597 struct atomisp_sub_device *asd,
2598 unsigned int width, unsigned int height,
2599 unsigned int min_width,
2600 enum ia_css_frame_format format)
2602 __configure_vf_output(asd, width, height, min_width, format,
2603 IA_CSS_PIPE_ID_VIDEO);
2607 int atomisp_css_capture_configure_viewfinder(
2608 struct atomisp_sub_device *asd,
2609 unsigned int width, unsigned int height,
2610 unsigned int min_width,
2611 enum ia_css_frame_format format)
2613 __configure_vf_output(asd, width, height, min_width, format, IA_CSS_PIPE_ID_CAPTURE);
2617 int atomisp_css_video_get_viewfinder_frame_info(
2618 struct atomisp_sub_device *asd,
2619 struct ia_css_frame_info *info)
2621 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2622 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_VIDEO);
2625 int atomisp_css_capture_get_viewfinder_frame_info(
2626 struct atomisp_sub_device *asd,
2627 struct ia_css_frame_info *info)
2629 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2630 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_CAPTURE);
2633 int atomisp_css_copy_get_output_frame_info(
2634 struct atomisp_sub_device *asd,
2635 unsigned int stream_index,
2636 struct ia_css_frame_info *info)
2638 return __get_frame_info(asd, stream_index, info,
2639 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
2642 int atomisp_css_preview_get_output_frame_info(
2643 struct atomisp_sub_device *asd,
2644 struct ia_css_frame_info *info)
2646 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2647 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_PREVIEW);
2650 int atomisp_css_capture_get_output_frame_info(
2651 struct atomisp_sub_device *asd,
2652 struct ia_css_frame_info *info)
2654 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2655 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_CAPTURE);
2658 int atomisp_css_video_get_output_frame_info(
2659 struct atomisp_sub_device *asd,
2660 struct ia_css_frame_info *info)
2662 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2663 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_VIDEO);
2666 int atomisp_css_preview_configure_pp_input(
2667 struct atomisp_sub_device *asd,
2668 unsigned int width, unsigned int height)
2670 struct atomisp_stream_env *stream_env =
2671 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2672 __configure_preview_pp_input(asd, width, height, IA_CSS_PIPE_ID_PREVIEW);
2674 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
2675 capt_pp_in_res.width)
2676 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
2681 int atomisp_css_capture_configure_pp_input(
2682 struct atomisp_sub_device *asd,
2683 unsigned int width, unsigned int height)
2685 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
2689 int atomisp_css_video_configure_pp_input(
2690 struct atomisp_sub_device *asd,
2691 unsigned int width, unsigned int height)
2693 struct atomisp_stream_env *stream_env =
2694 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2696 __configure_video_pp_input(asd, width, height, IA_CSS_PIPE_ID_VIDEO);
2698 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
2699 capt_pp_in_res.width)
2700 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
2705 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
2706 int num_captures, unsigned int skip, int offset)
2710 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
2711 __func__, num_captures, skip, offset);
2713 ret = ia_css_stream_capture(
2714 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2715 num_captures, skip, offset);
2722 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
2726 ret = ia_css_stream_capture_frame(
2727 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2729 if (ret == -ENOBUFS) {
2730 /* capture cmd queue is full */
2739 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
2743 ret = ia_css_unlock_raw_frame(
2744 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2746 if (ret == -ENOBUFS)
2754 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
2757 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2758 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
2759 .default_capture_config.enable_xnr = enable;
2760 asd->params.capture_config.enable_xnr = enable;
2761 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2762 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
2767 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
2768 struct ia_css_ctc_table *ctc_table)
2771 u16 *vamem_ptr = ctc_table->data.vamem_1;
2772 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
2775 /* workaround: if ctc_table is all 0, do not apply it */
2776 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
2777 vamem_ptr = ctc_table->data.vamem_2;
2778 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
2781 for (i = 0; i < data_size; i++) {
2782 if (*(vamem_ptr + i)) {
2789 asd->params.config.ctc_table = ctc_table;
2791 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
2794 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
2795 struct ia_css_anr_thres *anr_thres)
2797 asd->params.config.anr_thres = anr_thres;
2800 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
2801 struct ia_css_dvs_6axis_config *dvs_6axis)
2803 asd->params.config.dvs_6axis_config = dvs_6axis;
2806 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
2807 struct atomisp_dis_vector *vector)
2809 if (!asd->params.config.motion_vector)
2810 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
2812 memset(asd->params.config.motion_vector,
2813 0, sizeof(struct ia_css_vector));
2814 asd->params.css_param.motion_vector.x = vector->x;
2815 asd->params.css_param.motion_vector.y = vector->y;
2818 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
2819 struct atomisp_dvs_grid_info *atomgrid)
2821 struct ia_css_dvs_grid_info *cur =
2822 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
2825 dev_err(asd->isp->dev, "dvs grid not available!\n");
2829 if (sizeof(*cur) != sizeof(*atomgrid)) {
2830 dev_err(asd->isp->dev, "dvs grid mismatch!\n");
2835 dev_err(asd->isp->dev, "dvs not enabled!\n");
2839 return memcmp(atomgrid, cur, sizeof(*cur));
2842 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
2843 struct ia_css_dvs2_coefficients *coefs)
2845 asd->params.config.dvs2_coefs = coefs;
2848 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
2849 struct atomisp_dis_coefficients *coefs)
2851 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
2852 /* If the grid info in the argument differs from the current
2853 grid info, we tell the caller to reset the grid size and
2857 if (!coefs->hor_coefs.odd_real ||
2858 !coefs->hor_coefs.odd_imag ||
2859 !coefs->hor_coefs.even_real ||
2860 !coefs->hor_coefs.even_imag ||
2861 !coefs->ver_coefs.odd_real ||
2862 !coefs->ver_coefs.odd_imag ||
2863 !coefs->ver_coefs.even_real ||
2864 !coefs->ver_coefs.even_imag ||
2865 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real ||
2866 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag ||
2867 !asd->params.css_param.dvs2_coeff->hor_coefs.even_real ||
2868 !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag ||
2869 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real ||
2870 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag ||
2871 !asd->params.css_param.dvs2_coeff->ver_coefs.even_real ||
2872 !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag)
2875 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
2876 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
2878 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
2879 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
2881 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
2882 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
2884 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
2885 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
2888 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
2889 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
2891 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
2892 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
2894 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
2895 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
2897 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
2898 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
2901 asd->params.css_param.update_flag.dvs2_coefs =
2902 (struct atomisp_dis_coefficients *)
2903 asd->params.css_param.dvs2_coeff;
2905 /* asd->params.dis_proj_data_valid = false; */
2906 asd->params.css_update_params_needed = true;
2911 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
2914 struct atomisp_device *isp = asd->isp;
2916 if (zoom == asd->params.css_param.dz_config.dx &&
2917 zoom == asd->params.css_param.dz_config.dy) {
2918 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
2922 memset(&asd->params.css_param.dz_config, 0,
2923 sizeof(struct ia_css_dz_config));
2924 asd->params.css_param.dz_config.dx = zoom;
2925 asd->params.css_param.dz_config.dy = zoom;
2927 asd->params.css_param.update_flag.dz_config =
2928 (struct atomisp_dz_config *)&asd->params.css_param.dz_config;
2929 asd->params.css_update_params_needed = true;
2932 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
2933 struct ia_css_formats_config *formats_config)
2935 asd->params.config.formats_config = formats_config;
2938 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
2939 struct atomisp_wb_config *config)
2941 struct ia_css_wb_config wb_config;
2942 struct ia_css_isp_config isp_config;
2943 struct atomisp_device *isp = asd->isp;
2945 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2946 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2950 memset(&wb_config, 0, sizeof(struct ia_css_wb_config));
2951 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2952 isp_config.wb_config = &wb_config;
2953 ia_css_stream_get_isp_config(
2954 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2956 memcpy(config, &wb_config, sizeof(*config));
2961 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
2962 struct atomisp_ob_config *config)
2964 struct ia_css_ob_config ob_config;
2965 struct ia_css_isp_config isp_config;
2966 struct atomisp_device *isp = asd->isp;
2968 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2969 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2973 memset(&ob_config, 0, sizeof(struct ia_css_ob_config));
2974 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2975 isp_config.ob_config = &ob_config;
2976 ia_css_stream_get_isp_config(
2977 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2979 memcpy(config, &ob_config, sizeof(*config));
2984 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
2985 struct atomisp_dp_config *config)
2987 struct ia_css_dp_config dp_config;
2988 struct ia_css_isp_config isp_config;
2989 struct atomisp_device *isp = asd->isp;
2991 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2992 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2996 memset(&dp_config, 0, sizeof(struct ia_css_dp_config));
2997 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2998 isp_config.dp_config = &dp_config;
2999 ia_css_stream_get_isp_config(
3000 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3002 memcpy(config, &dp_config, sizeof(*config));
3007 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3008 struct atomisp_de_config *config)
3010 struct ia_css_de_config de_config;
3011 struct ia_css_isp_config isp_config;
3012 struct atomisp_device *isp = asd->isp;
3014 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3015 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3019 memset(&de_config, 0, sizeof(struct ia_css_de_config));
3020 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3021 isp_config.de_config = &de_config;
3022 ia_css_stream_get_isp_config(
3023 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3025 memcpy(config, &de_config, sizeof(*config));
3030 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3031 struct atomisp_nr_config *config)
3033 struct ia_css_nr_config nr_config;
3034 struct ia_css_isp_config isp_config;
3035 struct atomisp_device *isp = asd->isp;
3037 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3038 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3042 memset(&nr_config, 0, sizeof(struct ia_css_nr_config));
3043 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3045 isp_config.nr_config = &nr_config;
3046 ia_css_stream_get_isp_config(
3047 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3049 memcpy(config, &nr_config, sizeof(*config));
3054 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3055 struct atomisp_ee_config *config)
3057 struct ia_css_ee_config ee_config;
3058 struct ia_css_isp_config isp_config;
3059 struct atomisp_device *isp = asd->isp;
3061 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3062 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3066 memset(&ee_config, 0, sizeof(struct ia_css_ee_config));
3067 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3068 isp_config.ee_config = &ee_config;
3069 ia_css_stream_get_isp_config(
3070 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3072 memcpy(config, &ee_config, sizeof(*config));
3077 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3078 struct atomisp_tnr_config *config)
3080 struct ia_css_tnr_config tnr_config;
3081 struct ia_css_isp_config isp_config;
3082 struct atomisp_device *isp = asd->isp;
3084 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3085 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3089 memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config));
3090 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3091 isp_config.tnr_config = &tnr_config;
3092 ia_css_stream_get_isp_config(
3093 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3095 memcpy(config, &tnr_config, sizeof(*config));
3100 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3101 struct atomisp_ctc_table *config)
3103 struct ia_css_ctc_table *tab;
3104 struct ia_css_isp_config isp_config;
3105 struct atomisp_device *isp = asd->isp;
3107 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3108 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3113 tab = vzalloc(sizeof(struct ia_css_ctc_table));
3117 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3118 isp_config.ctc_table = tab;
3119 ia_css_stream_get_isp_config(
3120 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3122 memcpy(config, tab, sizeof(*tab));
3128 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
3129 struct atomisp_gamma_table *config)
3131 struct ia_css_gamma_table *tab;
3132 struct ia_css_isp_config isp_config;
3133 struct atomisp_device *isp = asd->isp;
3135 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3136 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3141 tab = vzalloc(sizeof(struct ia_css_gamma_table));
3145 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3146 isp_config.gamma_table = tab;
3147 ia_css_stream_get_isp_config(
3148 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3150 memcpy(config, tab, sizeof(*tab));
3156 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
3157 struct atomisp_gc_config *config)
3159 struct ia_css_gc_config gc_config;
3160 struct ia_css_isp_config isp_config;
3161 struct atomisp_device *isp = asd->isp;
3163 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3164 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3168 memset(&gc_config, 0, sizeof(struct ia_css_gc_config));
3169 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3170 isp_config.gc_config = &gc_config;
3171 ia_css_stream_get_isp_config(
3172 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3174 /* Get gamma correction params from current setup */
3175 memcpy(config, &gc_config, sizeof(*config));
3180 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
3181 struct atomisp_3a_config *config)
3183 struct ia_css_3a_config s3a_config;
3184 struct ia_css_isp_config isp_config;
3185 struct atomisp_device *isp = asd->isp;
3187 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3188 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3192 memset(&s3a_config, 0, sizeof(struct ia_css_3a_config));
3193 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3194 isp_config.s3a_config = &s3a_config;
3195 ia_css_stream_get_isp_config(
3196 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3198 /* Get white balance from current setup */
3199 memcpy(config, &s3a_config, sizeof(*config));
3204 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
3205 struct atomisp_formats_config *config)
3207 struct ia_css_formats_config formats_config;
3208 struct ia_css_isp_config isp_config;
3209 struct atomisp_device *isp = asd->isp;
3211 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3212 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3216 memset(&formats_config, 0, sizeof(formats_config));
3217 memset(&isp_config, 0, sizeof(isp_config));
3218 isp_config.formats_config = &formats_config;
3219 ia_css_stream_get_isp_config(
3220 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3222 /* Get narrow gamma from current setup */
3223 memcpy(config, &formats_config, sizeof(*config));
3228 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
3231 struct ia_css_dz_config dz_config; /** Digital Zoom */
3232 struct ia_css_isp_config isp_config;
3233 struct atomisp_device *isp = asd->isp;
3235 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3236 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3240 memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
3241 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3242 isp_config.dz_config = &dz_config;
3243 ia_css_stream_get_isp_config(
3244 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3246 *zoom = dz_config.dx;
3252 * Function to set/get image stablization statistics
3254 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
3255 struct atomisp_dis_statistics *stats)
3257 struct atomisp_device *isp = asd->isp;
3258 struct atomisp_dis_buf *dis_buf;
3259 unsigned long flags;
3261 lockdep_assert_held(&isp->mutex);
3263 if (!asd->params.dvs_stat->hor_prod.odd_real ||
3264 !asd->params.dvs_stat->hor_prod.odd_imag ||
3265 !asd->params.dvs_stat->hor_prod.even_real ||
3266 !asd->params.dvs_stat->hor_prod.even_imag ||
3267 !asd->params.dvs_stat->ver_prod.odd_real ||
3268 !asd->params.dvs_stat->ver_prod.odd_imag ||
3269 !asd->params.dvs_stat->ver_prod.even_real ||
3270 !asd->params.dvs_stat->ver_prod.even_imag)
3273 /* isp needs to be streaming to get DIS statistics */
3274 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
3277 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
3278 /* If the grid info in the argument differs from the current
3279 grid info, we tell the caller to reset the grid size and
3283 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3284 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
3285 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3286 dev_err(isp->dev, "dis statistics is not valid.\n");
3290 dis_buf = list_entry(asd->dis_stats.next,
3291 struct atomisp_dis_buf, list);
3292 list_del_init(&dis_buf->list);
3293 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3295 if (dis_buf->dvs_map)
3296 ia_css_translate_dvs2_statistics(
3297 asd->params.dvs_stat, dis_buf->dvs_map);
3299 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
3301 stats->exp_id = dis_buf->dis_data->exp_id;
3303 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3304 list_add_tail(&dis_buf->list, &asd->dis_stats);
3305 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3307 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
3308 asd->params.dvs_stat->ver_prod.odd_real,
3309 asd->params.dvs_ver_proj_bytes))
3311 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
3312 asd->params.dvs_stat->ver_prod.odd_imag,
3313 asd->params.dvs_ver_proj_bytes))
3315 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
3316 asd->params.dvs_stat->ver_prod.even_real,
3317 asd->params.dvs_ver_proj_bytes))
3319 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
3320 asd->params.dvs_stat->ver_prod.even_imag,
3321 asd->params.dvs_ver_proj_bytes))
3323 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
3324 asd->params.dvs_stat->hor_prod.odd_real,
3325 asd->params.dvs_hor_proj_bytes))
3327 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
3328 asd->params.dvs_stat->hor_prod.odd_imag,
3329 asd->params.dvs_hor_proj_bytes))
3331 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
3332 asd->params.dvs_stat->hor_prod.even_real,
3333 asd->params.dvs_hor_proj_bytes))
3335 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
3336 asd->params.dvs_stat->hor_prod.even_imag,
3337 asd->params.dvs_hor_proj_bytes))
3343 struct ia_css_shading_table *atomisp_css_shading_table_alloc(
3344 unsigned int width, unsigned int height)
3346 return ia_css_shading_table_alloc(width, height);
3349 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
3350 struct ia_css_shading_table *table)
3352 asd->params.config.shading_table = table;
3355 void atomisp_css_shading_table_free(struct ia_css_shading_table *table)
3357 ia_css_shading_table_free(table);
3360 struct ia_css_morph_table *atomisp_css_morph_table_allocate(
3361 unsigned int width, unsigned int height)
3363 return ia_css_morph_table_allocate(width, height);
3366 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
3367 struct ia_css_morph_table *table)
3369 asd->params.config.morph_table = table;
3372 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
3373 struct ia_css_morph_table *table)
3375 struct ia_css_isp_config isp_config;
3376 struct atomisp_device *isp = asd->isp;
3378 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3380 "%s called after streamoff, skipping.\n", __func__);
3383 memset(table, 0, sizeof(struct ia_css_morph_table));
3384 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3385 isp_config.morph_table = table;
3386 ia_css_stream_get_isp_config(
3387 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3391 void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
3393 ia_css_morph_table_free(table);
3396 static bool atomisp_css_isr_get_stream_id(struct ia_css_pipe *css_pipe,
3397 struct atomisp_device *isp,
3398 enum atomisp_input_stream_id *stream_id)
3400 struct atomisp_stream_env *stream_env;
3403 if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_DISABLED)
3406 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
3407 stream_env = &isp->asd.stream_env[i];
3408 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
3409 if (stream_env->pipes[j] && stream_env->pipes[j] == css_pipe) {
3419 int atomisp_css_isr_thread(struct atomisp_device *isp)
3421 enum atomisp_input_stream_id stream_id = 0;
3422 struct atomisp_css_event current_event;
3424 lockdep_assert_held(&isp->mutex);
3426 while (!ia_css_dequeue_psys_event(¤t_event.event)) {
3427 if (current_event.event.type ==
3428 IA_CSS_EVENT_TYPE_FW_ASSERT) {
3430 * Received FW assertion signal,
3431 * trigger WDT to recover
3434 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
3436 current_event.event.fw_assert_module_id,
3437 current_event.event.fw_assert_line_no);
3439 queue_work(system_long_wq, &isp->assert_recovery_work);
3441 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
3442 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
3443 __func__, current_event.event.fw_warning,
3444 current_event.event.exp_id);
3448 if (!atomisp_css_isr_get_stream_id(current_event.event.pipe, isp, &stream_id)) {
3449 if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
3451 "event: Timer event.");
3453 dev_warn(isp->dev, "%s:no subdev.event:%d",
3455 current_event.event.type);
3459 atomisp_css_temp_pipe_to_pipe_id(&isp->asd, ¤t_event);
3460 switch (current_event.event.type) {
3461 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
3462 dev_dbg(isp->dev, "event: Output frame done");
3463 atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
3464 current_event.pipe, true, stream_id);
3466 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
3467 dev_dbg(isp->dev, "event: Second output frame done");
3468 atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
3469 current_event.pipe, true, stream_id);
3471 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
3472 dev_dbg(isp->dev, "event: 3A stats frame done");
3473 atomisp_buf_done(&isp->asd, 0,
3474 IA_CSS_BUFFER_TYPE_3A_STATISTICS,
3478 case IA_CSS_EVENT_TYPE_METADATA_DONE:
3479 dev_dbg(isp->dev, "event: metadata frame done");
3480 atomisp_buf_done(&isp->asd, 0,
3481 IA_CSS_BUFFER_TYPE_METADATA,
3485 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
3486 dev_dbg(isp->dev, "event: VF output frame done");
3487 atomisp_buf_done(&isp->asd, 0,
3488 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
3489 current_event.pipe, true, stream_id);
3491 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
3492 dev_dbg(isp->dev, "event: second VF output frame done");
3493 atomisp_buf_done(&isp->asd, 0,
3494 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
3495 current_event.pipe, true, stream_id);
3497 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
3498 dev_dbg(isp->dev, "event: dis stats frame done");
3499 atomisp_buf_done(&isp->asd, 0,
3500 IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
3504 case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
3505 dev_dbg(isp->dev, "event: pipeline done");
3507 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
3508 dev_warn(isp->dev, "unexpected event: acc stage done");
3511 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
3512 current_event.event.type);
3520 bool atomisp_css_valid_sof(struct atomisp_device *isp)
3524 /* Loop for each css vc stream */
3525 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
3526 if (!isp->asd.stream_env[i].stream)
3529 dev_dbg(isp->dev, "stream #%d: mode: %d\n",
3530 i, isp->asd.stream_env[i].stream_config.mode);
3531 if (isp->asd.stream_env[i].stream_config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
3538 int atomisp_css_debug_dump_isp_binary(void)
3540 ia_css_debug_dump_isp_binary();
3544 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
3546 sh_css_dump_sp_raw_copy_linecount(reduced);
3550 static const char * const fw_type_name[] = {
3551 [ia_css_sp_firmware] = "SP",
3552 [ia_css_isp_firmware] = "ISP",
3553 [ia_css_bootloader_firmware] = "BootLoader",
3554 [ia_css_acc_firmware] = "accel",
3557 static const char * const fw_acc_type_name[] = {
3558 [IA_CSS_ACC_NONE] = "Normal",
3559 [IA_CSS_ACC_OUTPUT] = "Accel stage on output",
3560 [IA_CSS_ACC_VIEWFINDER] = "Accel stage on viewfinder",
3561 [IA_CSS_ACC_STANDALONE] = "Stand-alone acceleration",
3564 int atomisp_css_dump_blob_infor(struct atomisp_device *isp)
3566 struct ia_css_blob_descr *bd = sh_css_blob_info;
3567 unsigned int i, nm = sh_css_num_binaries;
3575 * The sh_css_load_firmware function discard the initial
3578 for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) {
3579 switch (bd[i].header.type) {
3580 case ia_css_isp_firmware:
3581 dev_dbg(isp->dev, "Num%2d type %s (%s), binary id is %2d, name is %s\n",
3583 fw_type_name[bd[i].header.type],
3584 fw_acc_type_name[bd[i].header.info.isp.type],
3585 bd[i].header.info.isp.sp.id,
3589 dev_dbg(isp->dev, "Num%2d type %s, name is %s\n",
3590 i + NUM_OF_SPS, fw_type_name[bd[i].header.type],
3598 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
3599 uint32_t isp_config_id)
3601 asd->params.config.isp_config_id = isp_config_id;
3604 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
3605 struct ia_css_frame *output_frame)
3607 asd->params.config.output_frame = output_frame;
3610 int atomisp_get_css_dbgfunc(void)
3615 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
3619 ret = __set_css_print_env(isp, opt);
3626 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
3628 ia_css_en_dz_capt_pipe(
3629 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3633 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
3634 struct ia_css_grid_info *grid_info)
3639 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
3640 return &grid_info->dvs_grid.dvs_grid_info;
3642 return &grid_info->dvs_grid;