1 /*
2  * Support for Clovertrail PNW Camera Imaging ISP subsystem.
3  *
4  * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License version
8  * 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  *
16  */
17 
18 #include <media/videobuf-vmalloc.h>
19 #include <media/v4l2-dev.h>
20 #include <media/v4l2-event.h>
21 
22 #include "mmu/isp_mmu.h"
23 #include "mmu/sh_mmu_mrfld.h"
24 #include "hmm/hmm_bo.h"
25 #include "hmm/hmm.h"
26 
27 #include "atomisp_compat.h"
28 #include "atomisp_internal.h"
29 #include "atomisp_cmd.h"
30 #include "atomisp-regs.h"
31 #include "atomisp_fops.h"
32 #include "atomisp_ioctl.h"
33 #include "atomisp_acc.h"
34 
35 #include <asm/intel-mid.h>
36 
37 #include "ia_css_debug.h"
38 #include "ia_css_isp_param.h"
39 #include "sh_css_hrt.h"
40 #include "ia_css_isys.h"
41 
42 #include <linux/pm_runtime.h>
43 
44 /* Assume max number of ACC stages */
45 #define MAX_ACC_STAGES	20
46 
47 /* Ideally, this should come from CSS headers */
48 #define NO_LINK -1
49 
50 /*
51  * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
52  * #4684168, if concurrency access happened, system may hard hang.
53  */
54 static DEFINE_SPINLOCK(mmio_lock);
55 
56 enum frame_info_type {
57 	ATOMISP_CSS_VF_FRAME,
58 	ATOMISP_CSS_SECOND_VF_FRAME,
59 	ATOMISP_CSS_OUTPUT_FRAME,
60 	ATOMISP_CSS_SECOND_OUTPUT_FRAME,
61 	ATOMISP_CSS_RAW_FRAME,
62 };
63 
64 struct bayer_ds_factor {
65 	unsigned int numerator;
66 	unsigned int denominator;
67 };
68 
69 void atomisp_css_debug_dump_sp_sw_debug_info(void)
70 {
71 	ia_css_debug_dump_sp_sw_debug_info();
72 }
73 
74 void atomisp_css_debug_dump_debug_info(const char *context)
75 {
76 	ia_css_debug_dump_debug_info(context);
77 }
78 
79 void atomisp_css_debug_set_dtrace_level(const unsigned int trace_level)
80 {
81 	ia_css_debug_set_dtrace_level(trace_level);
82 }
83 
84 unsigned int atomisp_css_debug_get_dtrace_level(void)
85 {
86 	return dbg_level;
87 }
88 
89 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
90 {
91 	unsigned long flags;
92 
93 	spin_lock_irqsave(&mmio_lock, flags);
94 	_hrt_master_port_store_8(addr, data);
95 	spin_unlock_irqrestore(&mmio_lock, flags);
96 }
97 
98 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
99 {
100 	unsigned long flags;
101 
102 	spin_lock_irqsave(&mmio_lock, flags);
103 	_hrt_master_port_store_16(addr, data);
104 	spin_unlock_irqrestore(&mmio_lock, flags);
105 }
106 
107 static void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
108 {
109 	unsigned long flags;
110 
111 	spin_lock_irqsave(&mmio_lock, flags);
112 	_hrt_master_port_store_32(addr, data);
113 	spin_unlock_irqrestore(&mmio_lock, flags);
114 }
115 
116 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
117 {
118 	unsigned long flags;
119 	u8 ret;
120 
121 	spin_lock_irqsave(&mmio_lock, flags);
122 	ret = _hrt_master_port_load_8(addr);
123 	spin_unlock_irqrestore(&mmio_lock, flags);
124 	return ret;
125 }
126 
127 static uint16_t atomisp_css2_hw_load_16(hrt_address addr)
128 {
129 	unsigned long flags;
130 	u16 ret;
131 
132 	spin_lock_irqsave(&mmio_lock, flags);
133 	ret = _hrt_master_port_load_16(addr);
134 	spin_unlock_irqrestore(&mmio_lock, flags);
135 	return ret;
136 }
137 
138 static uint32_t atomisp_css2_hw_load_32(hrt_address addr)
139 {
140 	unsigned long flags;
141 	u32 ret;
142 
143 	spin_lock_irqsave(&mmio_lock, flags);
144 	ret = _hrt_master_port_load_32(addr);
145 	spin_unlock_irqrestore(&mmio_lock, flags);
146 	return ret;
147 }
148 
149 static void atomisp_css2_hw_store(hrt_address addr,
150 				  const void *from, uint32_t n)
151 {
152 	unsigned long flags;
153 	unsigned int i;
154 	unsigned int _to = (unsigned int)addr;
155 	const char *_from = (const char *)from;
156 
157 	spin_lock_irqsave(&mmio_lock, flags);
158 	for (i = 0; i < n; i++, _to++, _from++)
159 		_hrt_master_port_store_8(_to, *_from);
160 	spin_unlock_irqrestore(&mmio_lock, flags);
161 }
162 
163 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
164 {
165 	unsigned long flags;
166 	unsigned int i;
167 	char *_to = (char *)to;
168 	unsigned int _from = (unsigned int)addr;
169 
170 	spin_lock_irqsave(&mmio_lock, flags);
171 	for (i = 0; i < n; i++, _to++, _from++)
172 		*_to = _hrt_master_port_load_8(_from);
173 	spin_unlock_irqrestore(&mmio_lock, flags);
174 }
175 
176 static int atomisp_css2_dbg_print(const char *fmt, va_list args)
177 {
178 	vprintk(fmt, args);
179 	return 0;
180 }
181 
182 static int atomisp_css2_dbg_ftrace_print(const char *fmt, va_list args)
183 {
184 	ftrace_vprintk(fmt, args);
185 	return 0;
186 }
187 
188 static int atomisp_css2_err_print(const char *fmt, va_list args)
189 {
190 	vprintk(fmt, args);
191 	return 0;
192 }
193 
194 void atomisp_store_uint32(hrt_address addr, uint32_t data)
195 {
196 	atomisp_css2_hw_store_32(addr, data);
197 }
198 
199 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
200 {
201 	*data = atomisp_css2_hw_load_32(addr);
202 }
203 
204 static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr)
205 {
206 	if (!sh_mmu_mrfld.get_pd_base) {
207 		dev_err(atomisp_dev, "get mmu base address failed.\n");
208 		return -EINVAL;
209 	}
210 
211 	*mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
212 			 bo_device.mmu.base_address);
213 	return 0;
214 }
215 
216 static void atomisp_isp_parameters_clean_up(
217     struct ia_css_isp_config *config)
218 {
219 	/*
220 	 * Set NULL to configs pointer to avoid they are set into isp again when
221 	 * some configs are changed and need to be updated later.
222 	 */
223 	memset(config, 0, sizeof(*config));
224 }
225 
226 static void __dump_pipe_config(struct atomisp_sub_device *asd,
227 			       struct atomisp_stream_env *stream_env,
228 			       unsigned int pipe_id)
229 {
230 	struct atomisp_device *isp = asd->isp;
231 
232 	if (stream_env->pipes[pipe_id]) {
233 		struct ia_css_pipe_config *p_config;
234 		struct ia_css_pipe_extra_config *pe_config;
235 
236 		p_config = &stream_env->pipe_configs[pipe_id];
237 		pe_config = &stream_env->pipe_extra_configs[pipe_id];
238 		dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
239 		dev_dbg(isp->dev,
240 			"pipe_config.pipe_mode:%d.\n", p_config->mode);
241 		dev_dbg(isp->dev,
242 			"pipe_config.output_info[0] w=%d, h=%d.\n",
243 			p_config->output_info[0].res.width,
244 			p_config->output_info[0].res.height);
245 		dev_dbg(isp->dev,
246 			"pipe_config.vf_pp_in_res w=%d, h=%d.\n",
247 			p_config->vf_pp_in_res.width,
248 			p_config->vf_pp_in_res.height);
249 		dev_dbg(isp->dev,
250 			"pipe_config.capt_pp_in_res w=%d, h=%d.\n",
251 			p_config->capt_pp_in_res.width,
252 			p_config->capt_pp_in_res.height);
253 		dev_dbg(isp->dev,
254 			"pipe_config.output.padded w=%d.\n",
255 			p_config->output_info[0].padded_width);
256 		dev_dbg(isp->dev,
257 			"pipe_config.vf_output_info[0] w=%d, h=%d.\n",
258 			p_config->vf_output_info[0].res.width,
259 			p_config->vf_output_info[0].res.height);
260 		dev_dbg(isp->dev,
261 			"pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
262 			p_config->bayer_ds_out_res.width,
263 			p_config->bayer_ds_out_res.height);
264 		dev_dbg(isp->dev,
265 			"pipe_config.envelope w=%d, h=%d.\n",
266 			p_config->dvs_envelope.width,
267 			p_config->dvs_envelope.height);
268 		dev_dbg(isp->dev,
269 			"pipe_config.dvs_frame_delay=%d.\n",
270 			p_config->dvs_frame_delay);
271 		dev_dbg(isp->dev,
272 			"pipe_config.isp_pipe_version:%d.\n",
273 			p_config->isp_pipe_version);
274 		dev_dbg(isp->dev,
275 			"pipe_config.acc_extension=%p.\n",
276 			p_config->acc_extension);
277 		dev_dbg(isp->dev,
278 			"pipe_config.acc_stages=%p.\n",
279 			p_config->acc_stages);
280 		dev_dbg(isp->dev,
281 			"pipe_config.num_acc_stages=%d.\n",
282 			p_config->num_acc_stages);
283 		dev_dbg(isp->dev,
284 			"pipe_config.acc_num_execs=%d.\n",
285 			p_config->acc_num_execs);
286 		dev_dbg(isp->dev,
287 			"pipe_config.default_capture_config.capture_mode=%d.\n",
288 			p_config->default_capture_config.mode);
289 		dev_dbg(isp->dev,
290 			"pipe_config.enable_dz=%d.\n",
291 			p_config->enable_dz);
292 		dev_dbg(isp->dev,
293 			"pipe_config.default_capture_config.enable_xnr=%d.\n",
294 			p_config->default_capture_config.enable_xnr);
295 		dev_dbg(isp->dev,
296 			"dumping pipe[%d] extra config:\n", pipe_id);
297 		dev_dbg(isp->dev,
298 			"pipe_extra_config.enable_raw_binning:%d.\n",
299 			pe_config->enable_raw_binning);
300 		dev_dbg(isp->dev,
301 			"pipe_extra_config.enable_yuv_ds:%d.\n",
302 			pe_config->enable_yuv_ds);
303 		dev_dbg(isp->dev,
304 			"pipe_extra_config.enable_high_speed:%d.\n",
305 			pe_config->enable_high_speed);
306 		dev_dbg(isp->dev,
307 			"pipe_extra_config.enable_dvs_6axis:%d.\n",
308 			pe_config->enable_dvs_6axis);
309 		dev_dbg(isp->dev,
310 			"pipe_extra_config.enable_reduced_pipe:%d.\n",
311 			pe_config->enable_reduced_pipe);
312 		dev_dbg(isp->dev,
313 			"pipe_(extra_)config.enable_dz:%d.\n",
314 			p_config->enable_dz);
315 		dev_dbg(isp->dev,
316 			"pipe_extra_config.disable_vf_pp:%d.\n",
317 			pe_config->disable_vf_pp);
318 	}
319 }
320 
321 static void __dump_stream_config(struct atomisp_sub_device *asd,
322 				 struct atomisp_stream_env *stream_env)
323 {
324 	struct atomisp_device *isp = asd->isp;
325 	struct ia_css_stream_config *s_config;
326 	int j;
327 	bool valid_stream = false;
328 
329 	for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
330 		if (stream_env->pipes[j]) {
331 			__dump_pipe_config(asd, stream_env, j);
332 			valid_stream = true;
333 		}
334 	}
335 	if (!valid_stream)
336 		return;
337 	s_config = &stream_env->stream_config;
338 	dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
339 
340 	if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
341 	    s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
342 		dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
343 			s_config->source.port.port);
344 		dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
345 			s_config->source.port.num_lanes);
346 		dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
347 			s_config->source.port.timeout);
348 		dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
349 			s_config->source.port.rxcount);
350 		dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
351 			s_config->source.port.compression.type);
352 		dev_dbg(isp->dev,
353 			"stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
354 			s_config->source.port.compression.
355 			compressed_bits_per_pixel);
356 		dev_dbg(isp->dev,
357 			"stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
358 			s_config->source.port.compression.
359 			uncompressed_bits_per_pixel);
360 	} else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
361 		dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
362 			s_config->source.tpg.id);
363 		dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
364 			s_config->source.tpg.mode);
365 		dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
366 			s_config->source.tpg.x_mask);
367 		dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
368 			s_config->source.tpg.x_delta);
369 		dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
370 			s_config->source.tpg.y_mask);
371 		dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
372 			s_config->source.tpg.y_delta);
373 		dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
374 			s_config->source.tpg.xy_mask);
375 	} else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
376 		dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
377 			s_config->source.prbs.id);
378 		dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
379 			s_config->source.prbs.h_blank);
380 		dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
381 			s_config->source.prbs.v_blank);
382 		dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
383 			s_config->source.prbs.seed);
384 		dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
385 			s_config->source.prbs.seed1);
386 	}
387 
388 	for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
389 		dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
390 			j,
391 			s_config->isys_config[j].input_res.width,
392 			s_config->isys_config[j].input_res.height);
393 
394 		dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
395 			j,
396 			s_config->isys_config[j].linked_isys_stream_id);
397 
398 		dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
399 			j,
400 			s_config->isys_config[j].format);
401 
402 		dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
403 			j,
404 			s_config->isys_config[j].valid);
405 	}
406 
407 	dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
408 		s_config->input_config.input_res.width,
409 		s_config->input_config.input_res.height);
410 
411 	dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
412 		s_config->input_config.effective_res.width,
413 		s_config->input_config.effective_res.height);
414 
415 	dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
416 		s_config->input_config.format);
417 
418 	dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
419 		s_config->input_config.bayer_order);
420 
421 	dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
422 		s_config->pixels_per_clock);
423 	dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
424 	dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
425 		s_config->continuous);
426 	dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
427 		s_config->disable_cont_viewfinder);
428 	dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
429 		s_config->channel_id);
430 	dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
431 		s_config->init_num_cont_raw_buf);
432 	dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
433 		s_config->target_num_cont_raw_buf);
434 	dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
435 		s_config->left_padding);
436 	dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
437 		s_config->sensor_binning_factor);
438 	dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
439 		s_config->pixels_per_clock);
440 	dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
441 		s_config->pack_raw_pixels);
442 	dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
443 		s_config->flash_gpio_pin);
444 	dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
445 		s_config->mipi_buffer_config.size_mem_words);
446 	dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
447 		s_config->mipi_buffer_config.contiguous);
448 	dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
449 		s_config->metadata_config.data_type);
450 	dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
451 		s_config->metadata_config.resolution.width,
452 		s_config->metadata_config.resolution.height);
453 }
454 
455 static int __destroy_stream(struct atomisp_sub_device *asd,
456 			    struct atomisp_stream_env *stream_env, bool force)
457 {
458 	struct atomisp_device *isp = asd->isp;
459 	int i;
460 	unsigned long timeout;
461 
462 	if (!stream_env->stream)
463 		return 0;
464 
465 	if (!force) {
466 		for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
467 			if (stream_env->update_pipe[i])
468 				break;
469 
470 		if (i == IA_CSS_PIPE_ID_NUM)
471 			return 0;
472 	}
473 
474 	if (stream_env->stream_state == CSS_STREAM_STARTED
475 	    && ia_css_stream_stop(stream_env->stream) != IA_CSS_SUCCESS) {
476 		dev_err(isp->dev, "stop stream failed.\n");
477 		return -EINVAL;
478 	}
479 
480 	if (stream_env->stream_state == CSS_STREAM_STARTED) {
481 		timeout = jiffies + msecs_to_jiffies(40);
482 		while (1) {
483 			if (ia_css_stream_has_stopped(stream_env->stream))
484 				break;
485 
486 			if (time_after(jiffies, timeout)) {
487 				dev_warn(isp->dev, "stop stream timeout.\n");
488 				break;
489 			}
490 
491 			usleep_range(100, 200);
492 		}
493 	}
494 
495 	stream_env->stream_state = CSS_STREAM_STOPPED;
496 
497 	if (ia_css_stream_destroy(stream_env->stream) != IA_CSS_SUCCESS) {
498 		dev_err(isp->dev, "destroy stream failed.\n");
499 		return -EINVAL;
500 	}
501 	stream_env->stream_state = CSS_STREAM_UNINIT;
502 	stream_env->stream = NULL;
503 
504 	return 0;
505 }
506 
507 static int __destroy_streams(struct atomisp_sub_device *asd, bool force)
508 {
509 	int ret, i;
510 
511 	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
512 		ret = __destroy_stream(asd, &asd->stream_env[i], force);
513 		if (ret)
514 			return ret;
515 	}
516 	asd->stream_prepared = false;
517 	return 0;
518 }
519 
520 static int __create_stream(struct atomisp_sub_device *asd,
521 			   struct atomisp_stream_env *stream_env)
522 {
523 	int pipe_index = 0, i;
524 	struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
525 
526 	for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
527 		if (stream_env->pipes[i])
528 			multi_pipes[pipe_index++] = stream_env->pipes[i];
529 	}
530 	if (pipe_index == 0)
531 		return 0;
532 
533 	stream_env->stream_config.target_num_cont_raw_buf =
534 	    asd->continuous_raw_buffer_size->val;
535 	stream_env->stream_config.channel_id = stream_env->ch_id;
536 	stream_env->stream_config.ia_css_enable_raw_buffer_locking =
537 	    asd->enable_raw_buffer_lock->val;
538 
539 	__dump_stream_config(asd, stream_env);
540 	if (ia_css_stream_create(&stream_env->stream_config,
541 				 pipe_index, multi_pipes, &stream_env->stream) != IA_CSS_SUCCESS)
542 		return -EINVAL;
543 	if (ia_css_stream_get_info(stream_env->stream,
544 				   &stream_env->stream_info) != IA_CSS_SUCCESS) {
545 		ia_css_stream_destroy(stream_env->stream);
546 		stream_env->stream = NULL;
547 		return -EINVAL;
548 	}
549 
550 	stream_env->stream_state = CSS_STREAM_CREATED;
551 	return 0;
552 }
553 
554 static int __create_streams(struct atomisp_sub_device *asd)
555 {
556 	int ret, i;
557 
558 	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
559 		ret = __create_stream(asd, &asd->stream_env[i]);
560 		if (ret)
561 			goto rollback;
562 	}
563 	asd->stream_prepared = true;
564 	return 0;
565 rollback:
566 	for (i--; i >= 0; i--)
567 		__destroy_stream(asd, &asd->stream_env[i], true);
568 	return ret;
569 }
570 
571 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
572 				  struct atomisp_stream_env *stream_env,
573 				  bool force)
574 {
575 	struct atomisp_device *isp = asd->isp;
576 	int ret = 0;
577 	int i;
578 
579 	for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
580 		if (!stream_env->pipes[i] ||
581 		    !(force || stream_env->update_pipe[i]))
582 			continue;
583 		if (ia_css_pipe_destroy(stream_env->pipes[i])
584 		    != IA_CSS_SUCCESS) {
585 			dev_err(isp->dev,
586 				"destroy pipe[%d]failed.cannot recover.\n", i);
587 			ret = -EINVAL;
588 		}
589 		stream_env->pipes[i] = NULL;
590 		stream_env->update_pipe[i] = false;
591 	}
592 	return ret;
593 }
594 
595 static int __destroy_pipes(struct atomisp_sub_device *asd, bool force)
596 {
597 	struct atomisp_device *isp = asd->isp;
598 	int i;
599 	int ret = 0;
600 
601 	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
602 		if (asd->stream_env[i].stream) {
603 			dev_err(isp->dev,
604 				"cannot destroy css pipes for stream[%d].\n",
605 				i);
606 			continue;
607 		}
608 
609 		ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force);
610 		if (ret)
611 			return ret;
612 	}
613 
614 	return 0;
615 }
616 
617 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
618 {
619 	__destroy_streams(asd, true);
620 	__destroy_pipes(asd, true);
621 }
622 
623 static void __apply_additional_pipe_config(
624     struct atomisp_sub_device *asd,
625     struct atomisp_stream_env *stream_env,
626     enum ia_css_pipe_id pipe_id)
627 {
628 	struct atomisp_device *isp = asd->isp;
629 
630 	if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
631 		dev_err(isp->dev,
632 			"wrong pipe_id for additional pipe config.\n");
633 		return;
634 	}
635 
636 	/* apply default pipe config */
637 	stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
638 	stream_env->pipe_configs[pipe_id].enable_dz =
639 	    asd->disable_dz->val ? false : true;
640 	/* apply isp 2.2 specific config for baytrail*/
641 	switch (pipe_id) {
642 	case IA_CSS_PIPE_ID_CAPTURE:
643 		/* enable capture pp/dz manually or digital zoom would
644 		 * fail*/
645 		if (stream_env->pipe_configs[pipe_id].
646 		    default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW)
647 			stream_env->pipe_configs[pipe_id].enable_dz = false;
648 
649 		if (atomisp_hw_is_isp2401) {
650 			/* the isp default to use ISP2.2 and the camera hal will
651 			* control whether use isp2.7 */
652 			if (asd->select_isp_version->val == ATOMISP_CSS_ISP_PIPE_VERSION_2_7)
653 				stream_env->pipe_configs[pipe_id].isp_pipe_version =  SH_CSS_ISP_PIPE_VERSION_2_7;
654 			else
655 				stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_2;
656 		}
657 		break;
658 	case IA_CSS_PIPE_ID_VIDEO:
659 		/* enable reduced pipe to have binary
660 		 * video_dz_2_min selected*/
661 		stream_env->pipe_extra_configs[pipe_id]
662 		.enable_reduced_pipe = true;
663 		stream_env->pipe_configs[pipe_id]
664 		.enable_dz = false;
665 		if (ATOMISP_SOC_CAMERA(asd))
666 			stream_env->pipe_configs[pipe_id].enable_dz = true;
667 
668 		if (asd->params.video_dis_en) {
669 			stream_env->pipe_extra_configs[pipe_id]
670 			.enable_dvs_6axis = true;
671 			stream_env->pipe_configs[pipe_id]
672 			.dvs_frame_delay =
673 			    ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
674 		}
675 		break;
676 	case IA_CSS_PIPE_ID_PREVIEW:
677 		break;
678 	case IA_CSS_PIPE_ID_YUVPP:
679 	case IA_CSS_PIPE_ID_COPY:
680 		if (ATOMISP_SOC_CAMERA(asd))
681 			stream_env->pipe_configs[pipe_id].enable_dz = true;
682 		else
683 			stream_env->pipe_configs[pipe_id].enable_dz = false;
684 		break;
685 	case IA_CSS_PIPE_ID_ACC:
686 		stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC;
687 		stream_env->pipe_configs[pipe_id].enable_dz = false;
688 		break;
689 	default:
690 		break;
691 	}
692 }
693 
694 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
695 	enum ia_css_pipe_id pipe_id)
696 {
697 	if (!asd)
698 		return false;
699 
700 	if (pipe_id == IA_CSS_PIPE_ID_ACC || pipe_id == IA_CSS_PIPE_ID_YUVPP)
701 		return true;
702 
703 	if (asd->vfpp) {
704 		if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
705 			if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
706 				return true;
707 			else
708 				return false;
709 		} else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
710 			if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
711 				return true;
712 			else
713 				return false;
714 		}
715 	}
716 
717 	if (!asd->run_mode)
718 		return false;
719 
720 	if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
721 		return true;
722 
723 	switch (asd->run_mode->val) {
724 	case ATOMISP_RUN_MODE_STILL_CAPTURE:
725 		if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
726 			return true;
727 		else
728 			return false;
729 	case ATOMISP_RUN_MODE_PREVIEW:
730 		if (!asd->continuous_mode->val) {
731 			if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
732 				return true;
733 			else
734 				return false;
735 		}
736 	/* fall through to ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE */
737 	case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
738 		if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
739 		    pipe_id == IA_CSS_PIPE_ID_PREVIEW)
740 			return true;
741 		else
742 			return false;
743 	case ATOMISP_RUN_MODE_VIDEO:
744 		if (!asd->continuous_mode->val) {
745 			if (pipe_id == IA_CSS_PIPE_ID_VIDEO ||
746 			    pipe_id == IA_CSS_PIPE_ID_YUVPP)
747 				return true;
748 			else
749 				return false;
750 		}
751 	/* fall through to ATOMISP_RUN_MODE_SDV */
752 	case ATOMISP_RUN_MODE_SDV:
753 		if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
754 		    pipe_id == IA_CSS_PIPE_ID_VIDEO)
755 			return true;
756 		else
757 			return false;
758 	}
759 
760 	return false;
761 }
762 
763 static int __create_pipe(struct atomisp_sub_device *asd,
764 			 struct atomisp_stream_env *stream_env,
765 			 enum ia_css_pipe_id pipe_id)
766 {
767 	struct atomisp_device *isp = asd->isp;
768 	struct ia_css_pipe_extra_config extra_config;
769 	enum ia_css_err ret;
770 
771 	if (pipe_id >= IA_CSS_PIPE_ID_NUM)
772 		return -EINVAL;
773 
774 	if (pipe_id != IA_CSS_PIPE_ID_ACC &&
775 	    !stream_env->pipe_configs[pipe_id].output_info[0].res.width)
776 		return 0;
777 
778 	if (pipe_id == IA_CSS_PIPE_ID_ACC &&
779 	    !stream_env->pipe_configs[pipe_id].acc_extension)
780 		return 0;
781 
782 	if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
783 		return 0;
784 
785 	ia_css_pipe_extra_config_defaults(&extra_config);
786 
787 	__apply_additional_pipe_config(asd, stream_env, pipe_id);
788 	if (!memcmp(&extra_config,
789 		    &stream_env->pipe_extra_configs[pipe_id],
790 		    sizeof(extra_config)))
791 		ret = ia_css_pipe_create(
792 			  &stream_env->pipe_configs[pipe_id],
793 			  &stream_env->pipes[pipe_id]);
794 	else
795 		ret = ia_css_pipe_create_extra(
796 			  &stream_env->pipe_configs[pipe_id],
797 			  &stream_env->pipe_extra_configs[pipe_id],
798 			  &stream_env->pipes[pipe_id]);
799 	if (ret != IA_CSS_SUCCESS)
800 		dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
801 	return ret;
802 }
803 
804 static int __create_pipes(struct atomisp_sub_device *asd)
805 {
806 	enum ia_css_err ret;
807 	int i, j;
808 
809 	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
810 		for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
811 			ret = __create_pipe(asd, &asd->stream_env[i], j);
812 			if (ret != IA_CSS_SUCCESS)
813 				break;
814 		}
815 		if (j < IA_CSS_PIPE_ID_NUM)
816 			goto pipe_err;
817 	}
818 	return 0;
819 pipe_err:
820 	for (; i >= 0; i--) {
821 		for (j--; j >= 0; j--) {
822 			if (asd->stream_env[i].pipes[j]) {
823 				ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
824 				asd->stream_env[i].pipes[j] = NULL;
825 			}
826 		}
827 		j = IA_CSS_PIPE_ID_NUM;
828 	}
829 	return -EINVAL;
830 }
831 
832 void atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
833 {
834 	__create_pipes(asd);
835 	__create_streams(asd);
836 }
837 
838 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
839 {
840 	int ret;
841 	struct atomisp_device *isp = asd->isp;
842 
843 	if (__destroy_streams(asd, true) != IA_CSS_SUCCESS)
844 		dev_warn(isp->dev, "destroy stream failed.\n");
845 
846 	if (__destroy_pipes(asd, true) != IA_CSS_SUCCESS)
847 		dev_warn(isp->dev, "destroy pipe failed.\n");
848 
849 	ret = __create_pipes(asd);
850 	if (ret != IA_CSS_SUCCESS) {
851 		dev_err(isp->dev, "create pipe failed %d.\n", ret);
852 		return -EIO;
853 	}
854 
855 	ret = __create_streams(asd);
856 	if (ret != IA_CSS_SUCCESS) {
857 		dev_warn(isp->dev, "create stream failed %d.\n", ret);
858 		__destroy_pipes(asd, true);
859 		return -EIO;
860 	}
861 
862 	return 0;
863 }
864 
865 int atomisp_css_init(struct atomisp_device *isp)
866 {
867 	unsigned int mmu_base_addr;
868 	int ret;
869 	enum ia_css_err err;
870 
871 	ret = hmm_get_mmu_base_addr(&mmu_base_addr);
872 	if (ret)
873 		return ret;
874 
875 	/* Init ISP */
876 	err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
877 			  (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
878 	if (err != IA_CSS_SUCCESS) {
879 		dev_err(isp->dev, "css init failed --- bad firmware?\n");
880 		return -EINVAL;
881 	}
882 	ia_css_enable_isys_event_queue(true);
883 
884 	isp->css_initialized = true;
885 	dev_dbg(isp->dev, "sh_css_init success\n");
886 
887 	return 0;
888 }
889 
890 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
891 {
892 	int ret = 0;
893 
894 	if (opt == 0)
895 		isp->css_env.isp_css_env.print_env.debug_print = NULL;
896 	else if (opt == 1)
897 		isp->css_env.isp_css_env.print_env.debug_print =
898 		    atomisp_css2_dbg_ftrace_print;
899 	else if (opt == 2)
900 		isp->css_env.isp_css_env.print_env.debug_print =
901 		    atomisp_css2_dbg_print;
902 	else
903 		ret = -EINVAL;
904 
905 	return ret;
906 }
907 
908 int atomisp_css_check_firmware_version(struct atomisp_device *isp)
909 {
910 	if (!sh_css_check_firmware_version(isp->dev, (void *)isp->firmware->data)) {
911 		return -EINVAL;
912 	}
913 	return 0;
914 }
915 
916 int atomisp_css_load_firmware(struct atomisp_device *isp)
917 {
918 	enum ia_css_err err;
919 
920 	/* set css env */
921 	isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
922 	isp->css_env.isp_css_fw.bytes = isp->firmware->size;
923 
924 	isp->css_env.isp_css_env.hw_access_env.store_8 =
925 	    atomisp_css2_hw_store_8;
926 	isp->css_env.isp_css_env.hw_access_env.store_16 =
927 	    atomisp_css2_hw_store_16;
928 	isp->css_env.isp_css_env.hw_access_env.store_32 =
929 	    atomisp_css2_hw_store_32;
930 
931 	isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
932 	isp->css_env.isp_css_env.hw_access_env.load_16 =
933 	    atomisp_css2_hw_load_16;
934 	isp->css_env.isp_css_env.hw_access_env.load_32 =
935 	    atomisp_css2_hw_load_32;
936 
937 	isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
938 	isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
939 
940 	__set_css_print_env(isp, dbg_func);
941 
942 	isp->css_env.isp_css_env.print_env.error_print = atomisp_css2_err_print;
943 
944 	/* load isp fw into ISP memory */
945 	err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env,
946 				   &isp->css_env.isp_css_fw);
947 	if (err != IA_CSS_SUCCESS) {
948 		dev_err(isp->dev, "css load fw failed.\n");
949 		return -EINVAL;
950 	}
951 
952 	return 0;
953 }
954 
955 void atomisp_css_unload_firmware(struct atomisp_device *isp)
956 {
957 	ia_css_unload_firmware();
958 }
959 
960 void atomisp_css_uninit(struct atomisp_device *isp)
961 {
962 	struct atomisp_sub_device *asd;
963 	unsigned int i;
964 
965 	for (i = 0; i < isp->num_of_streams; i++) {
966 		asd = &isp->asd[i];
967 		atomisp_isp_parameters_clean_up(&asd->params.config);
968 		asd->params.css_update_params_needed = false;
969 	}
970 
971 	isp->css_initialized = false;
972 	ia_css_uninit();
973 }
974 
975 void atomisp_css_suspend(struct atomisp_device *isp)
976 {
977 	isp->css_initialized = false;
978 	ia_css_uninit();
979 }
980 
981 int atomisp_css_resume(struct atomisp_device *isp)
982 {
983 	unsigned int mmu_base_addr;
984 	int ret;
985 
986 	ret = hmm_get_mmu_base_addr(&mmu_base_addr);
987 	if (ret) {
988 		dev_err(isp->dev, "get base address error.\n");
989 		return -EINVAL;
990 	}
991 
992 	ret = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
993 			  mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
994 	if (ret) {
995 		dev_err(isp->dev, "re-init css failed.\n");
996 		return -EINVAL;
997 	}
998 	ia_css_enable_isys_event_queue(true);
999 
1000 	isp->css_initialized = true;
1001 	return 0;
1002 }
1003 
1004 int atomisp_css_irq_translate(struct atomisp_device *isp,
1005 			      unsigned int *infos)
1006 {
1007 	int err;
1008 
1009 	err = ia_css_irq_translate(infos);
1010 	if (err != IA_CSS_SUCCESS) {
1011 		dev_warn(isp->dev,
1012 			 "%s:failed to translate irq (err = %d,infos = %d)\n",
1013 			 __func__, err, *infos);
1014 		return -EINVAL;
1015 	}
1016 
1017 	return 0;
1018 }
1019 
1020 void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
1021 				 unsigned int *infos)
1022 {
1023 #ifndef ISP2401_NEW_INPUT_SYSTEM
1024 	ia_css_isys_rx_get_irq_info(port, infos);
1025 #else
1026 	*infos = 0;
1027 #endif
1028 }
1029 
1030 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
1031 				   unsigned int infos)
1032 {
1033 #ifndef ISP2401_NEW_INPUT_SYSTEM
1034 	ia_css_isys_rx_clear_irq_info(port, infos);
1035 #endif
1036 }
1037 
1038 int atomisp_css_irq_enable(struct atomisp_device *isp,
1039 			   enum ia_css_irq_info info, bool enable)
1040 {
1041 	dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s.\n",
1042 		__func__, info,
1043 		enable ? "enable" : "disable");
1044 	if (ia_css_irq_enable(info, enable) != IA_CSS_SUCCESS) {
1045 		dev_warn(isp->dev, "%s:Invalid irq info.\n", __func__);
1046 		return -EINVAL;
1047 	}
1048 
1049 	return 0;
1050 }
1051 
1052 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
1053 {
1054 	int i, j;
1055 
1056 	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1057 		asd->stream_env[i].stream = NULL;
1058 		for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
1059 			asd->stream_env[i].pipes[j] = NULL;
1060 			asd->stream_env[i].update_pipe[j] = false;
1061 			ia_css_pipe_config_defaults(
1062 			    &asd->stream_env[i].pipe_configs[j]);
1063 			ia_css_pipe_extra_config_defaults(
1064 			    &asd->stream_env[i].pipe_extra_configs[j]);
1065 		}
1066 		ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
1067 	}
1068 }
1069 
1070 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
1071 				  struct videobuf_vmalloc_memory *vm_mem,
1072 				  enum atomisp_input_stream_id stream_id,
1073 				  enum ia_css_buffer_type css_buf_type,
1074 				  enum ia_css_pipe_id css_pipe_id)
1075 {
1076 	struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1077 	struct ia_css_buffer css_buf = {0};
1078 	enum ia_css_err err;
1079 
1080 	css_buf.type = css_buf_type;
1081 	css_buf.data.frame = vm_mem->vaddr;
1082 
1083 	err = ia_css_pipe_enqueue_buffer(
1084 		  stream_env->pipes[css_pipe_id], &css_buf);
1085 	if (err != IA_CSS_SUCCESS)
1086 		return -EINVAL;
1087 
1088 	return 0;
1089 }
1090 
1091 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
1092 				     struct atomisp_metadata_buf *metadata_buf,
1093 				     enum atomisp_input_stream_id stream_id,
1094 				     enum ia_css_pipe_id css_pipe_id)
1095 {
1096 	struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1097 	struct ia_css_buffer buffer = {0};
1098 	struct atomisp_device *isp = asd->isp;
1099 
1100 	buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
1101 	buffer.data.metadata = metadata_buf->metadata;
1102 	if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
1103 				       &buffer)) {
1104 		dev_err(isp->dev, "failed to q meta data buffer\n");
1105 		return -EINVAL;
1106 	}
1107 
1108 	return 0;
1109 }
1110 
1111 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
1112 				struct atomisp_s3a_buf *s3a_buf,
1113 				enum atomisp_input_stream_id stream_id,
1114 				enum ia_css_pipe_id css_pipe_id)
1115 {
1116 	struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1117 	struct ia_css_buffer buffer = {0};
1118 	struct atomisp_device *isp = asd->isp;
1119 
1120 	buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
1121 	buffer.data.stats_3a = s3a_buf->s3a_data;
1122 	if (ia_css_pipe_enqueue_buffer(
1123 		stream_env->pipes[css_pipe_id],
1124 		&buffer)) {
1125 		dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
1126 		return -EINVAL;
1127 	}
1128 
1129 	return 0;
1130 }
1131 
1132 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
1133 				struct atomisp_dis_buf *dis_buf,
1134 				enum atomisp_input_stream_id stream_id,
1135 				enum ia_css_pipe_id css_pipe_id)
1136 {
1137 	struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1138 	struct ia_css_buffer buffer = {0};
1139 	struct atomisp_device *isp = asd->isp;
1140 
1141 	buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
1142 	buffer.data.stats_dvs = dis_buf->dis_data;
1143 	if (ia_css_pipe_enqueue_buffer(
1144 		stream_env->pipes[css_pipe_id],
1145 		&buffer)) {
1146 		dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
1147 		return -EINVAL;
1148 	}
1149 
1150 	return 0;
1151 }
1152 
1153 void atomisp_css_mmu_invalidate_cache(void)
1154 {
1155 	ia_css_mmu_invalidate_cache();
1156 }
1157 
1158 void atomisp_css_mmu_invalidate_tlb(void)
1159 {
1160 	ia_css_mmu_invalidate_cache();
1161 }
1162 
1163 int atomisp_css_start(struct atomisp_sub_device *asd,
1164 		      enum ia_css_pipe_id pipe_id, bool in_reset)
1165 {
1166 	struct atomisp_device *isp = asd->isp;
1167 	bool sp_is_started = false;
1168 	int ret = 0, i = 0;
1169 
1170 	if (in_reset) {
1171 		if (__destroy_streams(asd, true))
1172 			dev_warn(isp->dev, "destroy stream failed.\n");
1173 
1174 		if (__destroy_pipes(asd, true))
1175 			dev_warn(isp->dev, "destroy pipe failed.\n");
1176 
1177 		if (__create_pipes(asd)) {
1178 			dev_err(isp->dev, "create pipe error.\n");
1179 			return -EINVAL;
1180 		}
1181 		if (__create_streams(asd)) {
1182 			dev_err(isp->dev, "create stream error.\n");
1183 			ret = -EINVAL;
1184 			goto stream_err;
1185 		}
1186 		/* in_reset == true, extension firmwares are reloaded after the recovery */
1187 		atomisp_acc_load_extensions(asd);
1188 	}
1189 
1190 	/*
1191 	 * For dual steam case, it is possible that:
1192 	 * 1: for this stream, it is at the stage that:
1193 	 * - after set_fmt is called
1194 	 * - before stream on is called
1195 	 * 2: for the other stream, the stream off is called which css reset
1196 	 * has been done.
1197 	 *
1198 	 * Thus the stream created in set_fmt get destroyed and need to be
1199 	 * recreated in the next stream on.
1200 	 */
1201 	if (asd->stream_prepared == false) {
1202 		if (__create_pipes(asd)) {
1203 			dev_err(isp->dev, "create pipe error.\n");
1204 			return -EINVAL;
1205 		}
1206 		if (__create_streams(asd)) {
1207 			dev_err(isp->dev, "create stream error.\n");
1208 			ret = -EINVAL;
1209 			goto stream_err;
1210 		}
1211 	}
1212 	/*
1213 	 * SP can only be started one time
1214 	 * if atomisp_subdev_streaming_count() tell there already has some
1215 	 * subdev at streamming, then SP should already be started previously,
1216 	 * so need to skip start sp procedure
1217 	 */
1218 	if (atomisp_streaming_count(isp)) {
1219 		dev_dbg(isp->dev, "skip start sp\n");
1220 	} else {
1221 		if (!sh_css_hrt_system_is_idle())
1222 			dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1223 		if (ia_css_start_sp() != IA_CSS_SUCCESS) {
1224 			dev_err(isp->dev, "start sp error.\n");
1225 			ret = -EINVAL;
1226 			goto start_err;
1227 		} else {
1228 			sp_is_started = true;
1229 		}
1230 	}
1231 
1232 	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1233 		if (asd->stream_env[i].stream) {
1234 			if (ia_css_stream_start(asd->stream_env[i]
1235 						.stream) != IA_CSS_SUCCESS) {
1236 				dev_err(isp->dev, "stream[%d] start error.\n", i);
1237 				ret = -EINVAL;
1238 				goto start_err;
1239 			} else {
1240 				asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1241 				dev_dbg(isp->dev, "stream[%d] started.\n", i);
1242 			}
1243 		}
1244 	}
1245 
1246 	return 0;
1247 
1248 start_err:
1249 	__destroy_streams(asd, true);
1250 stream_err:
1251 	__destroy_pipes(asd, true);
1252 
1253 	/* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1254 	 * destroy all pipes
1255 	 */
1256 	/*
1257 	 * SP can not be stop if other streams are in use
1258 	 */
1259 	if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1260 		ia_css_stop_sp();
1261 
1262 	return ret;
1263 }
1264 
1265 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1266 {
1267 	/*
1268 	 * FIXME!
1269 	 * for ISP2401 new input system, this api is under development.
1270 	 * Calling it would cause kernel panic.
1271 	 *
1272 	 * VIED BZ: 1458
1273 	 *
1274 	 * Check if it is Cherry Trail and also new input system
1275 	 */
1276 	if (asd->copy_mode) {
1277 		dev_warn(asd->isp->dev,
1278 			 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1279 			 __func__);
1280 		return;
1281 	}
1282 
1283 	ia_css_stream_set_isp_config(
1284 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1285 	    &asd->params.config);
1286 	atomisp_isp_parameters_clean_up(&asd->params.config);
1287 }
1288 
1289 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1290 	struct ia_css_pipe *pipe)
1291 {
1292 	enum ia_css_err ret;
1293 
1294 	if (!pipe) {
1295 		atomisp_css_update_isp_params(asd);
1296 		return;
1297 	}
1298 
1299 	dev_dbg(asd->isp->dev,
1300 		"%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1301 		__func__, asd->params.config.output_frame,
1302 		asd->params.config.isp_config_id, pipe);
1303 
1304 	ret = ia_css_stream_set_isp_config_on_pipe(
1305 		  asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1306 		  &asd->params.config, pipe);
1307 	if (ret != IA_CSS_SUCCESS)
1308 		dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1309 			 __func__, ret);
1310 	atomisp_isp_parameters_clean_up(&asd->params.config);
1311 }
1312 
1313 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1314 			     enum atomisp_input_stream_id stream_id,
1315 			     enum ia_css_pipe_id pipe_id,
1316 			     enum ia_css_buffer_type buf_type,
1317 			     struct atomisp_css_buffer *isp_css_buffer)
1318 {
1319 	if (ia_css_pipe_enqueue_buffer(
1320 		asd->stream_env[stream_id].pipes[pipe_id],
1321 		&isp_css_buffer->css_buffer)
1322 	    != IA_CSS_SUCCESS)
1323 		return -EINVAL;
1324 
1325 	return 0;
1326 }
1327 
1328 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1329 			       enum atomisp_input_stream_id stream_id,
1330 			       enum ia_css_pipe_id pipe_id,
1331 			       enum ia_css_buffer_type buf_type,
1332 			       struct atomisp_css_buffer *isp_css_buffer)
1333 {
1334 	struct atomisp_device *isp = asd->isp;
1335 	enum ia_css_err err;
1336 
1337 	err = ia_css_pipe_dequeue_buffer(
1338 		  asd->stream_env[stream_id].pipes[pipe_id],
1339 		  &isp_css_buffer->css_buffer);
1340 	if (err != IA_CSS_SUCCESS) {
1341 		dev_err(isp->dev,
1342 			"ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1343 		return -EINVAL;
1344 	}
1345 
1346 	return 0;
1347 }
1348 
1349 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device   *asd,
1350 				      u16 stream_id,
1351 				      struct atomisp_s3a_buf      *s3a_buf,
1352 				      struct atomisp_dis_buf      *dis_buf,
1353 				      struct atomisp_metadata_buf *md_buf)
1354 {
1355 	struct atomisp_device *isp = asd->isp;
1356 	struct ia_css_dvs_grid_info *dvs_grid_info =
1357 	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1358 
1359 	if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1360 		void *s3a_ptr;
1361 
1362 		s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1363 					&asd->params.curr_grid_info.s3a_grid);
1364 		if (!s3a_buf->s3a_data) {
1365 			dev_err(isp->dev, "3a buf allocation failed.\n");
1366 			return -EINVAL;
1367 		}
1368 
1369 		s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1370 		s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1371 				       s3a_buf->s3a_data, s3a_ptr);
1372 	}
1373 
1374 	if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1375 		void *dvs_ptr;
1376 
1377 		dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1378 					dvs_grid_info);
1379 		if (!dis_buf->dis_data) {
1380 			dev_err(isp->dev, "dvs buf allocation failed.\n");
1381 			if (s3a_buf)
1382 				ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1383 			return -EINVAL;
1384 		}
1385 
1386 		dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1387 		dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1388 				       dis_buf->dis_data, dvs_ptr);
1389 	}
1390 
1391 	if (asd->stream_env[stream_id].stream_info.
1392 	    metadata_info.size && md_buf) {
1393 		md_buf->metadata = ia_css_metadata_allocate(
1394 				       &asd->stream_env[stream_id].stream_info.metadata_info);
1395 		if (!md_buf->metadata) {
1396 			if (s3a_buf)
1397 				ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1398 			if (dis_buf)
1399 				ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1400 			dev_err(isp->dev, "metadata buf allocation failed.\n");
1401 			return -EINVAL;
1402 		}
1403 		md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1404 	}
1405 
1406 	return 0;
1407 }
1408 
1409 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1410 {
1411 	if (s3a_buf->s3a_data)
1412 		hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1413 
1414 	ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1415 	s3a_buf->s3a_map = NULL;
1416 	ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1417 }
1418 
1419 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1420 {
1421 	if (dis_buf->dis_data)
1422 		hmm_vunmap(dis_buf->dis_data->data_ptr);
1423 
1424 	ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1425 	dis_buf->dvs_map = NULL;
1426 	ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1427 }
1428 
1429 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1430 {
1431 	if (metadata_buf->md_vptr) {
1432 		hmm_vunmap(metadata_buf->metadata->address);
1433 		metadata_buf->md_vptr = NULL;
1434 	}
1435 	ia_css_metadata_free(metadata_buf->metadata);
1436 }
1437 
1438 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1439 {
1440 	struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1441 	struct atomisp_dis_buf *dis_buf, *_dis_buf;
1442 	struct atomisp_metadata_buf *md_buf, *_md_buf;
1443 	struct ia_css_dvs_grid_info *dvs_grid_info =
1444 	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1445 	unsigned int i;
1446 
1447 	/* 3A statistics use vmalloc, DIS use kmalloc */
1448 	if (dvs_grid_info && dvs_grid_info->enable) {
1449 		ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1450 		ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1451 		asd->params.css_param.dvs2_coeff = NULL;
1452 		asd->params.dvs_stat = NULL;
1453 		asd->params.dvs_hor_proj_bytes = 0;
1454 		asd->params.dvs_ver_proj_bytes = 0;
1455 		asd->params.dvs_hor_coef_bytes = 0;
1456 		asd->params.dvs_ver_coef_bytes = 0;
1457 		asd->params.dis_proj_data_valid = false;
1458 		list_for_each_entry_safe(dis_buf, _dis_buf,
1459 					 &asd->dis_stats, list) {
1460 			atomisp_css_free_dis_buffer(dis_buf);
1461 			list_del(&dis_buf->list);
1462 			kfree(dis_buf);
1463 		}
1464 		list_for_each_entry_safe(dis_buf, _dis_buf,
1465 					 &asd->dis_stats_in_css, list) {
1466 			atomisp_css_free_dis_buffer(dis_buf);
1467 			list_del(&dis_buf->list);
1468 			kfree(dis_buf);
1469 		}
1470 	}
1471 	if (asd->params.curr_grid_info.s3a_grid.enable) {
1472 		ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1473 		asd->params.s3a_user_stat = NULL;
1474 		asd->params.s3a_output_bytes = 0;
1475 		list_for_each_entry_safe(s3a_buf, _s3a_buf,
1476 					 &asd->s3a_stats, list) {
1477 			atomisp_css_free_3a_buffer(s3a_buf);
1478 			list_del(&s3a_buf->list);
1479 			kfree(s3a_buf);
1480 		}
1481 		list_for_each_entry_safe(s3a_buf, _s3a_buf,
1482 					 &asd->s3a_stats_in_css, list) {
1483 			atomisp_css_free_3a_buffer(s3a_buf);
1484 			list_del(&s3a_buf->list);
1485 			kfree(s3a_buf);
1486 		}
1487 		list_for_each_entry_safe(s3a_buf, _s3a_buf,
1488 					 &asd->s3a_stats_ready, list) {
1489 			atomisp_css_free_3a_buffer(s3a_buf);
1490 			list_del(&s3a_buf->list);
1491 			kfree(s3a_buf);
1492 		}
1493 	}
1494 
1495 	if (asd->params.css_param.dvs_6axis) {
1496 		ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1497 		asd->params.css_param.dvs_6axis = NULL;
1498 	}
1499 
1500 	for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1501 		list_for_each_entry_safe(md_buf, _md_buf,
1502 					 &asd->metadata[i], list) {
1503 			atomisp_css_free_metadata_buffer(md_buf);
1504 			list_del(&md_buf->list);
1505 			kfree(md_buf);
1506 		}
1507 		list_for_each_entry_safe(md_buf, _md_buf,
1508 					 &asd->metadata_in_css[i], list) {
1509 			atomisp_css_free_metadata_buffer(md_buf);
1510 			list_del(&md_buf->list);
1511 			kfree(md_buf);
1512 		}
1513 		list_for_each_entry_safe(md_buf, _md_buf,
1514 					 &asd->metadata_ready[i], list) {
1515 			atomisp_css_free_metadata_buffer(md_buf);
1516 			list_del(&md_buf->list);
1517 			kfree(md_buf);
1518 		}
1519 	}
1520 	asd->params.metadata_width_size = 0;
1521 	atomisp_free_metadata_output_buf(asd);
1522 }
1523 
1524 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1525 			      enum ia_css_pipe_id pipe_id,
1526 			      int source_pad)
1527 {
1528 	struct ia_css_pipe_info p_info;
1529 	struct ia_css_grid_info old_info;
1530 	struct atomisp_device *isp = asd->isp;
1531 	int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
1532 	int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1533 		       stream_config.metadata_config.resolution.width;
1534 
1535 	memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1536 	memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1537 
1538 	if (ia_css_pipe_get_info(
1539 		asd->stream_env[stream_index].pipes[pipe_id],
1540 		&p_info) != IA_CSS_SUCCESS) {
1541 		dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1542 		return -EINVAL;
1543 	}
1544 
1545 	memcpy(&old_info, &asd->params.curr_grid_info,
1546 	       sizeof(struct ia_css_grid_info));
1547 	memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1548 	       sizeof(struct ia_css_grid_info));
1549 	/*
1550 	 * Record which css pipe enables s3a_grid.
1551 	 * Currently would have one css pipe that need it
1552 	 */
1553 	if (asd->params.curr_grid_info.s3a_grid.enable) {
1554 		if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM)
1555 			dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1556 				asd->params.s3a_enabled_pipe, pipe_id);
1557 		asd->params.s3a_enabled_pipe = pipe_id;
1558 	}
1559 
1560 	/* If the grid info has not changed and the buffers for 3A and
1561 	 * DIS statistics buffers are allocated or buffer size would be zero
1562 	 * then no need to do anything. */
1563 	if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1564 	      && asd->params.s3a_user_stat && asd->params.dvs_stat)
1565 	     || asd->params.curr_grid_info.s3a_grid.width == 0
1566 	     || asd->params.curr_grid_info.s3a_grid.height == 0)
1567 	    && asd->params.metadata_width_size == md_width) {
1568 		dev_dbg(isp->dev,
1569 			"grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1570 			!memcmp(&old_info, &asd->params.curr_grid_info,
1571 				sizeof(old_info)),
1572 			!!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1573 			asd->params.curr_grid_info.s3a_grid.width,
1574 			asd->params.curr_grid_info.s3a_grid.height,
1575 			asd->params.metadata_width_size);
1576 		return -EINVAL;
1577 	}
1578 	asd->params.metadata_width_size = md_width;
1579 
1580 	return 0;
1581 }
1582 
1583 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1584 {
1585 	if (!asd->params.curr_grid_info.s3a_grid.width ||
1586 	    !asd->params.curr_grid_info.s3a_grid.height)
1587 		return 0;
1588 
1589 	asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1590 					&asd->params.curr_grid_info.s3a_grid);
1591 	if (!asd->params.s3a_user_stat)
1592 		return -ENOMEM;
1593 	/* 3A statistics. These can be big, so we use vmalloc. */
1594 	asd->params.s3a_output_bytes =
1595 	    asd->params.curr_grid_info.s3a_grid.width *
1596 	    asd->params.curr_grid_info.s3a_grid.height *
1597 	    sizeof(*asd->params.s3a_user_stat->data);
1598 
1599 	return 0;
1600 }
1601 
1602 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1603 {
1604 	struct ia_css_dvs_grid_info *dvs_grid =
1605 	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1606 
1607 	if (!dvs_grid)
1608 		return 0;
1609 
1610 	if (!dvs_grid->enable) {
1611 		dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1612 		return 0;
1613 	}
1614 
1615 	/* DIS coefficients. */
1616 	asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1617 					       dvs_grid);
1618 	if (!asd->params.css_param.dvs2_coeff)
1619 		return -ENOMEM;
1620 
1621 	asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1622 					 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1623 
1624 	asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1625 					 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1626 
1627 	/* DIS projections. */
1628 	asd->params.dis_proj_data_valid = false;
1629 	asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1630 	if (!asd->params.dvs_stat)
1631 		return -ENOMEM;
1632 
1633 	asd->params.dvs_hor_proj_bytes =
1634 	    dvs_grid->aligned_height * dvs_grid->aligned_width *
1635 	    sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1636 
1637 	asd->params.dvs_ver_proj_bytes =
1638 	    dvs_grid->aligned_height * dvs_grid->aligned_width *
1639 	    sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1640 
1641 	return 0;
1642 }
1643 
1644 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1645 {
1646 	int i;
1647 
1648 	/* We allocate the cpu-side buffer used for communication with user
1649 	 * space */
1650 	for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1651 		asd->params.metadata_user[i] = kvmalloc(
1652 						   asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1653 						   stream_info.metadata_info.size, GFP_KERNEL);
1654 		if (!asd->params.metadata_user[i]) {
1655 			while (--i >= 0) {
1656 				kvfree(asd->params.metadata_user[i]);
1657 				asd->params.metadata_user[i] = NULL;
1658 			}
1659 			return -ENOMEM;
1660 		}
1661 	}
1662 
1663 	return 0;
1664 }
1665 
1666 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1667 {
1668 	unsigned int i;
1669 
1670 	for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1671 		if (asd->params.metadata_user[i]) {
1672 			kvfree(asd->params.metadata_user[i]);
1673 			asd->params.metadata_user[i] = NULL;
1674 		}
1675 	}
1676 }
1677 
1678 void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd,
1679 				    struct atomisp_css_buffer *isp_css_buffer,
1680 				    struct ia_css_isp_dvs_statistics_map *dvs_map)
1681 {
1682 	if (asd->params.dvs_stat) {
1683 		if (dvs_map)
1684 			ia_css_translate_dvs2_statistics(
1685 			    asd->params.dvs_stat, dvs_map);
1686 		else
1687 			ia_css_get_dvs2_statistics(asd->params.dvs_stat,
1688 						   isp_css_buffer->css_buffer.data.stats_dvs);
1689 	}
1690 }
1691 
1692 int atomisp_css_dequeue_event(struct atomisp_css_event *current_event)
1693 {
1694 	if (ia_css_dequeue_event(&current_event->event) != IA_CSS_SUCCESS)
1695 		return -EINVAL;
1696 
1697 	return 0;
1698 }
1699 
1700 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1701 				      struct atomisp_css_event *current_event)
1702 {
1703 	/*
1704 	 * FIXME!
1705 	 * Pipe ID reported in CSS event is not correct for new system's
1706 	 * copy pipe.
1707 	 * VIED BZ: 1463
1708 	 */
1709 	ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1710 				    &current_event->pipe);
1711 	if (asd && asd->copy_mode &&
1712 	    current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1713 		current_event->pipe = IA_CSS_PIPE_ID_COPY;
1714 }
1715 
1716 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1717 				    enum atomisp_input_stream_id stream_id,
1718 				    struct v4l2_mbus_framefmt *ffmt,
1719 				    int isys_stream)
1720 {
1721 	struct ia_css_stream_config *s_config =
1722 		    &asd->stream_env[stream_id].stream_config;
1723 
1724 	if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1725 		return -EINVAL;
1726 
1727 	s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1728 	s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1729 	return 0;
1730 }
1731 
1732 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1733 				     enum atomisp_input_stream_id stream_id,
1734 				     struct v4l2_mbus_framefmt *ffmt)
1735 {
1736 	struct ia_css_stream_config *s_config =
1737 		    &asd->stream_env[stream_id].stream_config;
1738 
1739 	s_config->input_config.input_res.width = ffmt->width;
1740 	s_config->input_config.input_res.height = ffmt->height;
1741 	return 0;
1742 }
1743 
1744 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1745 	enum atomisp_input_stream_id stream_id,
1746 	unsigned int bin_factor)
1747 {
1748 	asd->stream_env[stream_id]
1749 	.stream_config.sensor_binning_factor = bin_factor;
1750 }
1751 
1752 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1753 				       enum atomisp_input_stream_id stream_id,
1754 				       enum ia_css_bayer_order bayer_order)
1755 {
1756 	struct ia_css_stream_config *s_config =
1757 		    &asd->stream_env[stream_id].stream_config;
1758 	s_config->input_config.bayer_order = bayer_order;
1759 }
1760 
1761 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1762 			       enum atomisp_input_stream_id stream_id,
1763 			       int link,
1764 			       int isys_stream)
1765 {
1766 	struct ia_css_stream_config *s_config =
1767 		    &asd->stream_env[stream_id].stream_config;
1768 
1769 	s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1770 }
1771 
1772 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1773 				enum atomisp_input_stream_id stream_id,
1774 				bool valid,
1775 				int isys_stream)
1776 {
1777 	struct ia_css_stream_config *s_config =
1778 		    &asd->stream_env[stream_id].stream_config;
1779 
1780 	s_config->isys_config[isys_stream].valid = valid;
1781 }
1782 
1783 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1784 				 enum atomisp_input_stream_id stream_id,
1785 				 enum atomisp_input_format format,
1786 				 int isys_stream)
1787 {
1788 	struct ia_css_stream_config *s_config =
1789 		    &asd->stream_env[stream_id].stream_config;
1790 
1791 	s_config->isys_config[isys_stream].format = format;
1792 }
1793 
1794 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1795 				  enum atomisp_input_stream_id stream_id,
1796 				  enum atomisp_input_format format)
1797 {
1798 	struct ia_css_stream_config *s_config =
1799 		    &asd->stream_env[stream_id].stream_config;
1800 
1801 	s_config->input_config.format = format;
1802 }
1803 
1804 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1805 					enum atomisp_input_stream_id stream_id,
1806 					struct v4l2_mbus_framefmt *ffmt)
1807 {
1808 	int i;
1809 	struct ia_css_stream_config *s_config =
1810 		    &asd->stream_env[stream_id].stream_config;
1811 	/*
1812 	 * Set all isys configs to not valid.
1813 	 * Currently we support only one stream per channel
1814 	 */
1815 	for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1816 	     i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1817 		s_config->isys_config[i].valid = false;
1818 
1819 	atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1820 					IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1821 	atomisp_css_isys_set_format(asd, stream_id,
1822 				    s_config->input_config.format,
1823 				    IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1824 	atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1825 				  IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1826 	atomisp_css_isys_set_valid(asd, stream_id, true,
1827 				   IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1828 
1829 	return 0;
1830 }
1831 
1832 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1833 				    enum atomisp_input_stream_id stream_id,
1834 				    enum atomisp_input_format input_format)
1835 {
1836 	struct ia_css_stream_config *s_config =
1837 		    &asd->stream_env[stream_id].stream_config;
1838 
1839 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1840 	    s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1841 
1842 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1843 	    s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1844 
1845 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1846 	    = IA_CSS_STREAM_ISYS_STREAM_0;
1847 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1848 	    ATOMISP_INPUT_FORMAT_USER_DEF1;
1849 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1850 	    ATOMISP_INPUT_FORMAT_USER_DEF2;
1851 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1852 	return 0;
1853 }
1854 
1855 void atomisp_css_isys_two_stream_cfg_update_stream1(
1856     struct atomisp_sub_device *asd,
1857     enum atomisp_input_stream_id stream_id,
1858     enum atomisp_input_format input_format,
1859     unsigned int width, unsigned int height)
1860 {
1861 	struct ia_css_stream_config *s_config =
1862 		    &asd->stream_env[stream_id].stream_config;
1863 
1864 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1865 	    width;
1866 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1867 	    height;
1868 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1869 	    input_format;
1870 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1871 }
1872 
1873 void atomisp_css_isys_two_stream_cfg_update_stream2(
1874     struct atomisp_sub_device *asd,
1875     enum atomisp_input_stream_id stream_id,
1876     enum atomisp_input_format input_format,
1877     unsigned int width, unsigned int height)
1878 {
1879 	struct ia_css_stream_config *s_config =
1880 		    &asd->stream_env[stream_id].stream_config;
1881 
1882 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1883 	    width;
1884 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1885 	    height;
1886 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1887 	    = IA_CSS_STREAM_ISYS_STREAM_0;
1888 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1889 	    input_format;
1890 	s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1891 }
1892 
1893 int atomisp_css_input_set_effective_resolution(
1894     struct atomisp_sub_device *asd,
1895     enum atomisp_input_stream_id stream_id,
1896     unsigned int width, unsigned int height)
1897 {
1898 	struct ia_css_stream_config *s_config =
1899 		    &asd->stream_env[stream_id].stream_config;
1900 	s_config->input_config.effective_res.width = width;
1901 	s_config->input_config.effective_res.height = height;
1902 	return 0;
1903 }
1904 
1905 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1906 					unsigned int dvs_w, unsigned int dvs_h)
1907 {
1908 	asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1909 	.pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1910 	asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1911 	.pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1912 }
1913 
1914 void atomisp_css_input_set_two_pixels_per_clock(
1915     struct atomisp_sub_device *asd,
1916     bool two_ppc)
1917 {
1918 	int i;
1919 
1920 	if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1921 	    .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1922 		return;
1923 
1924 	asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1925 	.stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1926 	for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1927 		asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1928 		.update_pipe[i] = true;
1929 }
1930 
1931 void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
1932 				    bool enable)
1933 {
1934 	struct atomisp_stream_env *stream_env =
1935 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1936 	unsigned int pipe;
1937 
1938 	if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
1939 		pipe = IA_CSS_PIPE_ID_VIDEO;
1940 	else
1941 		pipe = IA_CSS_PIPE_ID_PREVIEW;
1942 
1943 	stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable;
1944 	stream_env->update_pipe[pipe] = true;
1945 	if (enable)
1946 		stream_env->pipe_configs[pipe].output_info[0].padded_width =
1947 		    stream_env->stream_config.input_config.effective_res.width;
1948 }
1949 
1950 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1951 {
1952 	int i;
1953 
1954 	for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1955 		asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1956 		.pipe_configs[i].enable_dz = enable;
1957 }
1958 
1959 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1960 				  enum ia_css_capture_mode mode)
1961 {
1962 	struct atomisp_stream_env *stream_env =
1963 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1964 
1965 	if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1966 	    .default_capture_config.mode == mode)
1967 		return;
1968 
1969 	stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1970 	default_capture_config.mode = mode;
1971 	stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1972 }
1973 
1974 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
1975 				enum ia_css_input_mode mode)
1976 {
1977 	int i;
1978 	struct atomisp_device *isp = asd->isp;
1979 	unsigned int size_mem_words;
1980 
1981 	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
1982 		asd->stream_env[i].stream_config.mode = mode;
1983 
1984 	if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
1985 		struct ia_css_stream_config *s_config =
1986 			    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
1987 		s_config->mode = IA_CSS_INPUT_MODE_TPG;
1988 		s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
1989 		s_config->source.tpg.x_mask = (1 << 4) - 1;
1990 		s_config->source.tpg.x_delta = -2;
1991 		s_config->source.tpg.y_mask = (1 << 4) - 1;
1992 		s_config->source.tpg.y_delta = 3;
1993 		s_config->source.tpg.xy_mask = (1 << 8) - 1;
1994 		return;
1995 	}
1996 
1997 	if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1998 		return;
1999 
2000 	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2001 		/*
2002 		 * TODO: sensor needs to export the embedded_data_size_words
2003 		 * information to atomisp for each setting.
2004 		 * Here using a large safe value.
2005 		 */
2006 		struct ia_css_stream_config *s_config =
2007 			    &asd->stream_env[i].stream_config;
2008 
2009 		if (s_config->input_config.input_res.width == 0)
2010 			continue;
2011 
2012 		if (ia_css_mipi_frame_calculate_size(
2013 			s_config->input_config.input_res.width,
2014 			s_config->input_config.input_res.height,
2015 			s_config->input_config.format,
2016 			true,
2017 			0x13000,
2018 			&size_mem_words) != IA_CSS_SUCCESS) {
2019 			if (intel_mid_identify_cpu() ==
2020 			    INTEL_MID_CPU_CHIP_TANGIER)
2021 				size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
2022 			else
2023 				size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
2024 			dev_warn(asd->isp->dev,
2025 				 "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n",
2026 				 size_mem_words);
2027 		}
2028 		s_config->mipi_buffer_config.size_mem_words = size_mem_words;
2029 		s_config->mipi_buffer_config.nof_mipi_buffers = 2;
2030 	}
2031 }
2032 
2033 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
2034 				       unsigned short stream_index, bool enable)
2035 {
2036 	struct atomisp_stream_env *stream_env =
2037 		    &asd->stream_env[stream_index];
2038 
2039 	if (stream_env->stream_config.online == !!enable)
2040 		return;
2041 
2042 	stream_env->stream_config.online = !!enable;
2043 	stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
2044 }
2045 
2046 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
2047 				       unsigned short stream_index, bool enable)
2048 {
2049 	struct atomisp_stream_env *stream_env =
2050 		    &asd->stream_env[stream_index];
2051 	int i;
2052 
2053 	if (stream_env->stream_config.online != !!enable) {
2054 		stream_env->stream_config.online = !!enable;
2055 		for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2056 			stream_env->update_pipe[i] = true;
2057 	}
2058 }
2059 
2060 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
2061 				     bool enable)
2062 {
2063 	struct atomisp_stream_env *stream_env =
2064 		    &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
2065 	int i;
2066 
2067 	if (stream_env->stream_config.online != enable) {
2068 		stream_env->stream_config.online = enable;
2069 		for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2070 			stream_env->update_pipe[i] = true;
2071 	}
2072 }
2073 
2074 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
2075 				   bool enable)
2076 {
2077 	struct atomisp_stream_env *stream_env =
2078 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2079 	int i;
2080 
2081 	/*
2082 	 * To SOC camera, there is only one YUVPP pipe in any case
2083 	 * including ZSL/SDV/continuous viewfinder, so always set
2084 	 * stream_config.continuous to 0.
2085 	 */
2086 	if (ATOMISP_USE_YUVPP(asd)) {
2087 		stream_env->stream_config.continuous = 0;
2088 		stream_env->stream_config.online = 1;
2089 		return;
2090 	}
2091 
2092 	if (stream_env->stream_config.continuous != !!enable) {
2093 		stream_env->stream_config.continuous = !!enable;
2094 		stream_env->stream_config.pack_raw_pixels = true;
2095 		for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2096 			stream_env->update_pipe[i] = true;
2097 	}
2098 }
2099 
2100 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
2101 			    bool enable)
2102 {
2103 	struct atomisp_stream_env *stream_env =
2104 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2105 	int i;
2106 
2107 	if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
2108 		stream_env->stream_config.disable_cont_viewfinder = !enable;
2109 		for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2110 			stream_env->update_pipe[i] = true;
2111 	}
2112 }
2113 
2114 int atomisp_css_input_configure_port(
2115     struct atomisp_sub_device *asd,
2116     enum mipi_port_id port,
2117     unsigned int num_lanes,
2118     unsigned int timeout,
2119     unsigned int mipi_freq,
2120     enum atomisp_input_format metadata_format,
2121     unsigned int metadata_width,
2122     unsigned int metadata_height)
2123 {
2124 	int i;
2125 	struct atomisp_stream_env *stream_env;
2126 	/*
2127 	 * Calculate rx_count as follows:
2128 	 * Input: mipi_freq                 : CSI-2 bus frequency in Hz
2129 	 * UI = 1 / (2 * mipi_freq)         : period of one bit on the bus
2130 	 * min = 85e-9 + 6 * UI             : Limits for rx_count in seconds
2131 	 * max = 145e-9 + 10 * UI
2132 	 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
2133 	 * rxcount = rxcount0 - 2           : adjust for better results
2134 	 * The formula below is simplified version of the above with
2135 	 * 10-bit fixed points for improved accuracy.
2136 	 */
2137 	const unsigned int rxcount =
2138 	    min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
2139 
2140 	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2141 		stream_env = &asd->stream_env[i];
2142 		stream_env->stream_config.source.port.port = port;
2143 		stream_env->stream_config.source.port.num_lanes = num_lanes;
2144 		stream_env->stream_config.source.port.timeout = timeout;
2145 		if (mipi_freq)
2146 			stream_env->stream_config.source.port.rxcount = rxcount;
2147 		stream_env->stream_config.
2148 		metadata_config.data_type = metadata_format;
2149 		stream_env->stream_config.
2150 		metadata_config.resolution.width = metadata_width;
2151 		stream_env->stream_config.
2152 		metadata_config.resolution.height = metadata_height;
2153 	}
2154 
2155 	return 0;
2156 }
2157 
2158 int atomisp_css_frame_allocate(struct ia_css_frame **frame,
2159 			       unsigned int width, unsigned int height,
2160 			       enum ia_css_frame_format format,
2161 			       unsigned int padded_width,
2162 			       unsigned int raw_bit_depth)
2163 {
2164 	if (ia_css_frame_allocate(frame, width, height, format,
2165 				  padded_width, raw_bit_depth) != IA_CSS_SUCCESS)
2166 		return -ENOMEM;
2167 
2168 	return 0;
2169 }
2170 
2171 int atomisp_css_frame_allocate_from_info(struct ia_css_frame **frame,
2172 	const struct ia_css_frame_info *info)
2173 {
2174 	if (ia_css_frame_allocate_from_info(frame, info) != IA_CSS_SUCCESS)
2175 		return -ENOMEM;
2176 
2177 	return 0;
2178 }
2179 
2180 void atomisp_css_frame_free(struct ia_css_frame *frame)
2181 {
2182 	ia_css_frame_free(frame);
2183 }
2184 
2185 int atomisp_css_frame_map(struct ia_css_frame **frame,
2186 			  const struct ia_css_frame_info *info,
2187 			  const void __user *data, uint16_t attribute,
2188 			  unsigned int pgnr)
2189 {
2190 	if (ia_css_frame_map(frame, info, data, attribute, pgnr)
2191 	    != IA_CSS_SUCCESS)
2192 		return -ENOMEM;
2193 
2194 	return 0;
2195 }
2196 
2197 int atomisp_css_set_black_frame(struct atomisp_sub_device *asd,
2198 				const struct ia_css_frame *raw_black_frame)
2199 {
2200 	if (sh_css_set_black_frame(
2201 		asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2202 		raw_black_frame) != IA_CSS_SUCCESS)
2203 		return -ENOMEM;
2204 
2205 	return 0;
2206 }
2207 
2208 int atomisp_css_allocate_continuous_frames(bool init_time,
2209 	struct atomisp_sub_device *asd)
2210 {
2211 	if (ia_css_alloc_continuous_frame_remain(
2212 		asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream)
2213 	    != IA_CSS_SUCCESS)
2214 		return -EINVAL;
2215 	return 0;
2216 }
2217 
2218 void atomisp_css_update_continuous_frames(struct atomisp_sub_device *asd)
2219 {
2220 	ia_css_update_continuous_frames(
2221 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream);
2222 }
2223 
2224 int atomisp_css_stop(struct atomisp_sub_device *asd,
2225 		     enum ia_css_pipe_id pipe_id, bool in_reset)
2226 {
2227 	struct atomisp_device *isp = asd->isp;
2228 	struct atomisp_s3a_buf *s3a_buf;
2229 	struct atomisp_dis_buf *dis_buf;
2230 	struct atomisp_metadata_buf *md_buf;
2231 	unsigned long irqflags;
2232 	unsigned int i;
2233 
2234 	/* if is called in atomisp_reset(), force destroy stream */
2235 	if (__destroy_streams(asd, true))
2236 		dev_err(isp->dev, "destroy stream failed.\n");
2237 
2238 	/* if is called in atomisp_reset(), force destroy all pipes */
2239 	if (__destroy_pipes(asd, true))
2240 		dev_err(isp->dev, "destroy pipes failed.\n");
2241 
2242 	atomisp_init_raw_buffer_bitmap(asd);
2243 
2244 	/*
2245 	 * SP can not be stop if other streams are in use
2246 	 */
2247 	if (atomisp_streaming_count(isp) == 0)
2248 		ia_css_stop_sp();
2249 
2250 	if (!in_reset) {
2251 		struct atomisp_stream_env *stream_env;
2252 		int i, j;
2253 
2254 		for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2255 			stream_env = &asd->stream_env[i];
2256 			for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
2257 				ia_css_pipe_config_defaults(
2258 				    &stream_env->pipe_configs[j]);
2259 				ia_css_pipe_extra_config_defaults(
2260 				    &stream_env->pipe_extra_configs[j]);
2261 			}
2262 			ia_css_stream_config_defaults(
2263 			    &stream_env->stream_config);
2264 		}
2265 		atomisp_isp_parameters_clean_up(&asd->params.config);
2266 		asd->params.css_update_params_needed = false;
2267 	}
2268 
2269 	/* move stats buffers to free queue list */
2270 	while (!list_empty(&asd->s3a_stats_in_css)) {
2271 		s3a_buf = list_entry(asd->s3a_stats_in_css.next,
2272 				     struct atomisp_s3a_buf, list);
2273 		list_del(&s3a_buf->list);
2274 		list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2275 	}
2276 	while (!list_empty(&asd->s3a_stats_ready)) {
2277 		s3a_buf = list_entry(asd->s3a_stats_ready.next,
2278 				     struct atomisp_s3a_buf, list);
2279 		list_del(&s3a_buf->list);
2280 		list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2281 	}
2282 
2283 	spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
2284 	while (!list_empty(&asd->dis_stats_in_css)) {
2285 		dis_buf = list_entry(asd->dis_stats_in_css.next,
2286 				     struct atomisp_dis_buf, list);
2287 		list_del(&dis_buf->list);
2288 		list_add_tail(&dis_buf->list, &asd->dis_stats);
2289 	}
2290 	asd->params.dis_proj_data_valid = false;
2291 	spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
2292 
2293 	for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
2294 		while (!list_empty(&asd->metadata_in_css[i])) {
2295 			md_buf = list_entry(asd->metadata_in_css[i].next,
2296 					    struct atomisp_metadata_buf, list);
2297 			list_del(&md_buf->list);
2298 			list_add_tail(&md_buf->list, &asd->metadata[i]);
2299 		}
2300 		while (!list_empty(&asd->metadata_ready[i])) {
2301 			md_buf = list_entry(asd->metadata_ready[i].next,
2302 					    struct atomisp_metadata_buf, list);
2303 			list_del(&md_buf->list);
2304 			list_add_tail(&md_buf->list, &asd->metadata[i]);
2305 		}
2306 	}
2307 
2308 	atomisp_flush_params_queue(&asd->video_out_capture);
2309 	atomisp_flush_params_queue(&asd->video_out_vf);
2310 	atomisp_flush_params_queue(&asd->video_out_preview);
2311 	atomisp_flush_params_queue(&asd->video_out_video_capture);
2312 	atomisp_free_css_parameters(&asd->params.css_param);
2313 	memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
2314 	return 0;
2315 }
2316 
2317 int atomisp_css_continuous_set_num_raw_frames(
2318     struct atomisp_sub_device *asd,
2319     int num_frames)
2320 {
2321 	if (asd->enable_raw_buffer_lock->val) {
2322 		asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2323 		.stream_config.init_num_cont_raw_buf =
2324 		    ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
2325 		if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2326 		    asd->params.video_dis_en)
2327 			asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2328 			.stream_config.init_num_cont_raw_buf +=
2329 			    ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2330 	} else {
2331 		asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2332 		.stream_config.init_num_cont_raw_buf =
2333 		    ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
2334 	}
2335 
2336 	if (asd->params.video_dis_en)
2337 		asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2338 		.stream_config.init_num_cont_raw_buf +=
2339 		    ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2340 
2341 	asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2342 	.stream_config.target_num_cont_raw_buf = num_frames;
2343 	return 0;
2344 }
2345 
2346 void atomisp_css_disable_vf_pp(struct atomisp_sub_device *asd,
2347 			       bool disable)
2348 {
2349 	int i;
2350 
2351 	for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2352 		asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2353 		.pipe_extra_configs[i].disable_vf_pp = !!disable;
2354 }
2355 
2356 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2357     struct atomisp_sub_device *asd,
2358     enum ia_css_pipe_id pipe_id)
2359 {
2360 	struct atomisp_device *isp = asd->isp;
2361 	struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2362 		isp->inputs[asd->input_curr].camera);
2363 
2364 	switch (pipe_id) {
2365 	case IA_CSS_PIPE_ID_COPY:
2366 		/* Currently only YUVPP mode supports YUV420_Legacy format.
2367 		 * Revert this when other pipe modes can support
2368 		 * YUV420_Legacy format.
2369 		 */
2370 		if (mipi_info && mipi_info->input_format ==
2371 		    ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2372 			return IA_CSS_PIPE_MODE_YUVPP;
2373 		return IA_CSS_PIPE_MODE_COPY;
2374 	case IA_CSS_PIPE_ID_PREVIEW:
2375 		return IA_CSS_PIPE_MODE_PREVIEW;
2376 	case IA_CSS_PIPE_ID_CAPTURE:
2377 		return IA_CSS_PIPE_MODE_CAPTURE;
2378 	case IA_CSS_PIPE_ID_VIDEO:
2379 		return IA_CSS_PIPE_MODE_VIDEO;
2380 	case IA_CSS_PIPE_ID_ACC:
2381 		return IA_CSS_PIPE_MODE_ACC;
2382 	case IA_CSS_PIPE_ID_YUVPP:
2383 		return IA_CSS_PIPE_MODE_YUVPP;
2384 	default:
2385 		WARN_ON(1);
2386 		return IA_CSS_PIPE_MODE_PREVIEW;
2387 	}
2388 }
2389 
2390 static void __configure_output(struct atomisp_sub_device *asd,
2391 			       unsigned int stream_index,
2392 			       unsigned int width, unsigned int height,
2393 			       unsigned int min_width,
2394 			       enum ia_css_frame_format format,
2395 			       enum ia_css_pipe_id pipe_id)
2396 {
2397 	struct atomisp_device *isp = asd->isp;
2398 	struct atomisp_stream_env *stream_env =
2399 		    &asd->stream_env[stream_index];
2400 	struct ia_css_stream_config *s_config = &stream_env->stream_config;
2401 
2402 	stream_env->pipe_configs[pipe_id].mode =
2403 	    __pipe_id_to_pipe_mode(asd, pipe_id);
2404 	stream_env->update_pipe[pipe_id] = true;
2405 
2406 	stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2407 	stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2408 	stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2409 	stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2410 
2411 	/* isp binary 2.2 specific setting*/
2412 	if (width > s_config->input_config.effective_res.width ||
2413 	    height > s_config->input_config.effective_res.height) {
2414 		s_config->input_config.effective_res.width = width;
2415 		s_config->input_config.effective_res.height = height;
2416 	}
2417 
2418 	dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2419 		pipe_id, width, height, format);
2420 }
2421 
2422 static void __configure_video_preview_output(struct atomisp_sub_device *asd,
2423 	unsigned int stream_index,
2424 	unsigned int width, unsigned int height,
2425 	unsigned int min_width,
2426 	enum ia_css_frame_format format,
2427 	enum ia_css_pipe_id pipe_id)
2428 {
2429 	struct atomisp_device *isp = asd->isp;
2430 	struct atomisp_stream_env *stream_env =
2431 		    &asd->stream_env[stream_index];
2432 	struct ia_css_frame_info *css_output_info;
2433 	struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2434 
2435 	stream_env->pipe_configs[pipe_id].mode =
2436 	    __pipe_id_to_pipe_mode(asd, pipe_id);
2437 	stream_env->update_pipe[pipe_id] = true;
2438 
2439 	/*
2440 	 * second_output will be as video main output in SDV mode
2441 	 * with SOC camera. output will be as video main output in
2442 	 * normal video mode.
2443 	 */
2444 	if (asd->continuous_mode->val)
2445 		css_output_info = &stream_env->pipe_configs[pipe_id].
2446 				  output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2447 	else
2448 		css_output_info = &stream_env->pipe_configs[pipe_id].
2449 				  output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2450 
2451 	css_output_info->res.width = width;
2452 	css_output_info->res.height = height;
2453 	css_output_info->format = format;
2454 	css_output_info->padded_width = min_width;
2455 
2456 	/* isp binary 2.2 specific setting*/
2457 	if (width > stream_config->input_config.effective_res.width ||
2458 	    height > stream_config->input_config.effective_res.height) {
2459 		stream_config->input_config.effective_res.width = width;
2460 		stream_config->input_config.effective_res.height = height;
2461 	}
2462 
2463 	dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2464 		pipe_id, width, height, format);
2465 }
2466 
2467 /*
2468  * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2469  * downscaling input resolution.
2470  */
2471 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2472 	unsigned int width, unsigned int height,
2473 	enum ia_css_pipe_id pipe_id)
2474 {
2475 	struct atomisp_device *isp = asd->isp;
2476 	struct atomisp_stream_env *stream_env =
2477 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2478 	struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2479 	struct ia_css_pipe_config *pipe_configs =
2480 		    &stream_env->pipe_configs[pipe_id];
2481 	struct ia_css_pipe_extra_config *pipe_extra_configs =
2482 		    &stream_env->pipe_extra_configs[pipe_id];
2483 	unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2484 
2485 	if (width == 0 && height == 0)
2486 		return;
2487 
2488 	if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2489 	    height * 9 / 10 < pipe_configs->output_info[0].res.height)
2490 		return;
2491 	/* here just copy the calculation in css */
2492 	hor_ds_factor = CEIL_DIV(width >> 1,
2493 				 pipe_configs->output_info[0].res.width);
2494 	ver_ds_factor = CEIL_DIV(height >> 1,
2495 				 pipe_configs->output_info[0].res.height);
2496 
2497 	if ((asd->isp->media_dev.hw_revision <
2498 	     (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2499 	     IS_CHT) && hor_ds_factor != ver_ds_factor) {
2500 		dev_warn(asd->isp->dev,
2501 			 "Cropping for capture due to FW limitation");
2502 		return;
2503 	}
2504 
2505 	pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2506 	stream_env->update_pipe[pipe_id] = true;
2507 
2508 	pipe_extra_configs->enable_yuv_ds = true;
2509 
2510 	pipe_configs->capt_pp_in_res.width =
2511 	    stream_config->input_config.effective_res.width;
2512 	pipe_configs->capt_pp_in_res.height =
2513 	    stream_config->input_config.effective_res.height;
2514 
2515 	dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2516 		pipe_id, width, height);
2517 }
2518 
2519 /*
2520  * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2521  * yuv downscaling, which needs addtional configurations.
2522  */
2523 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2524 	unsigned int width, unsigned int height,
2525 	enum ia_css_pipe_id pipe_id)
2526 {
2527 	struct atomisp_device *isp = asd->isp;
2528 	int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2529 	struct atomisp_stream_env *stream_env =
2530 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2531 	struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2532 	struct ia_css_pipe_config *pipe_configs =
2533 		    &stream_env->pipe_configs[pipe_id];
2534 	struct ia_css_pipe_extra_config *pipe_extra_configs =
2535 		    &stream_env->pipe_extra_configs[pipe_id];
2536 	struct ia_css_resolution *bayer_ds_out_res =
2537 		    &pipe_configs->bayer_ds_out_res;
2538 	struct ia_css_resolution *vf_pp_in_res =
2539 		    &pipe_configs->vf_pp_in_res;
2540 	struct ia_css_resolution  *effective_res =
2541 		    &stream_config->input_config.effective_res;
2542 
2543 	const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2544 	/*
2545 	 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2546 	 * columns to be shaded. Remove this factor to work around the CSS bug.
2547 	 * const unsigned int yuv_dec_fct[] = {4, 2};
2548 	 */
2549 	const unsigned int yuv_dec_fct[] = { 2 };
2550 	unsigned int i;
2551 
2552 	if (width == 0 && height == 0)
2553 		return;
2554 
2555 	pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2556 	stream_env->update_pipe[pipe_id] = true;
2557 
2558 	out_width = pipe_configs->output_info[0].res.width;
2559 	out_height = pipe_configs->output_info[0].res.height;
2560 
2561 	/*
2562 	 * The ISP could do bayer downscaling, yuv decimation and yuv
2563 	 * downscaling:
2564 	 * 1: Bayer Downscaling: between effective resolution and
2565 	 * bayer_ds_res_out;
2566 	 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2567 	 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2568 	 *
2569 	 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2570 	 * Rule for YUV Decimation: support factor 2, 4
2571 	 * Rule for YUV Downscaling: arbitrary value below 2
2572 	 *
2573 	 * General rule of factor distribution among these stages:
2574 	 * 1: try to do Bayer downscaling first if not in online mode.
2575 	 * 2: try to do maximum of 2 for YUV downscaling
2576 	 * 3: the remainling for YUV decimation
2577 	 *
2578 	 * Note:
2579 	 * Do not configure bayer_ds_out_res if:
2580 	 * online == 1 or continuous == 0 or raw_binning = 0
2581 	 */
2582 	if (stream_config->online || !stream_config->continuous ||
2583 	    !pipe_extra_configs->enable_raw_binning) {
2584 		bayer_ds_out_res->width = 0;
2585 		bayer_ds_out_res->height = 0;
2586 	} else {
2587 		bayer_ds_out_res->width = effective_res->width;
2588 		bayer_ds_out_res->height = effective_res->height;
2589 
2590 		for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2591 			if (effective_res->width >= out_width *
2592 			    bds_fct[i].numerator / bds_fct[i].denominator &&
2593 			    effective_res->height >= out_height *
2594 			    bds_fct[i].numerator / bds_fct[i].denominator) {
2595 				bayer_ds_out_res->width =
2596 				    effective_res->width *
2597 				    bds_fct[i].denominator /
2598 				    bds_fct[i].numerator;
2599 				bayer_ds_out_res->height =
2600 				    effective_res->height *
2601 				    bds_fct[i].denominator /
2602 				    bds_fct[i].numerator;
2603 				break;
2604 			}
2605 		}
2606 	}
2607 	/*
2608 	 * calculate YUV Decimation, YUV downscaling facor:
2609 	 * YUV Downscaling factor must not exceed 2.
2610 	 * YUV Decimation factor could be 2, 4.
2611 	 */
2612 	/* first decide the yuv_ds input resolution */
2613 	if (bayer_ds_out_res->width == 0) {
2614 		yuv_ds_in_width = effective_res->width;
2615 		yuv_ds_in_height = effective_res->height;
2616 	} else {
2617 		yuv_ds_in_width = bayer_ds_out_res->width;
2618 		yuv_ds_in_height = bayer_ds_out_res->height;
2619 	}
2620 
2621 	vf_pp_in_res->width = yuv_ds_in_width;
2622 	vf_pp_in_res->height = yuv_ds_in_height;
2623 
2624 	/* find out the yuv decimation factor */
2625 	for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2626 		if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2627 		    yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2628 			vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2629 			vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2630 			break;
2631 		}
2632 	}
2633 
2634 	if (vf_pp_in_res->width == out_width &&
2635 	    vf_pp_in_res->height == out_height) {
2636 		pipe_extra_configs->enable_yuv_ds = false;
2637 		vf_pp_in_res->width = 0;
2638 		vf_pp_in_res->height = 0;
2639 	} else {
2640 		pipe_extra_configs->enable_yuv_ds = true;
2641 	}
2642 
2643 	dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2644 		pipe_id, width, height);
2645 }
2646 
2647 /*
2648  * For CSS2.1, offline video pipe could support bayer decimation, and
2649  * yuv downscaling, which needs addtional configurations.
2650  */
2651 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2652 				       unsigned int width, unsigned int height,
2653 				       enum ia_css_pipe_id pipe_id)
2654 {
2655 	struct atomisp_device *isp = asd->isp;
2656 	int out_width, out_height;
2657 	struct atomisp_stream_env *stream_env =
2658 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2659 	struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2660 	struct ia_css_pipe_config *pipe_configs =
2661 		    &stream_env->pipe_configs[pipe_id];
2662 	struct ia_css_pipe_extra_config *pipe_extra_configs =
2663 		    &stream_env->pipe_extra_configs[pipe_id];
2664 	struct ia_css_resolution *bayer_ds_out_res =
2665 		    &pipe_configs->bayer_ds_out_res;
2666 	struct ia_css_resolution  *effective_res =
2667 		    &stream_config->input_config.effective_res;
2668 
2669 	const struct bayer_ds_factor bds_factors[] = {
2670 		{8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
2671 	};
2672 	unsigned int i;
2673 
2674 	if (width == 0 && height == 0)
2675 		return;
2676 
2677 	pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2678 	stream_env->update_pipe[pipe_id] = true;
2679 
2680 	pipe_extra_configs->enable_yuv_ds = false;
2681 
2682 	/*
2683 	 * If DVS is enabled,  video binary will take care the dvs envelope
2684 	 * and usually the bayer_ds_out_res should be larger than 120% of
2685 	 * destination resolution, the extra 20% will be cropped as DVS
2686 	 * envelope. But,  if the bayer_ds_out_res is less than 120% of the
2687 	 * destination. The ISP can still work,  but DVS quality is not good.
2688 	 */
2689 	/* taking at least 10% as envelope */
2690 	if (asd->params.video_dis_en) {
2691 		out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2692 		out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2693 	} else {
2694 		out_width = pipe_configs->output_info[0].res.width;
2695 		out_height = pipe_configs->output_info[0].res.height;
2696 	}
2697 
2698 	/*
2699 	 * calculate bayer decimate factor:
2700 	 * 1: only 1.5, 2, 4 and 8 get supported
2701 	 * 2: Do not configure bayer_ds_out_res if:
2702 	 *    online == 1 or continuous == 0 or raw_binning = 0
2703 	 */
2704 	if (stream_config->online || !stream_config->continuous) {
2705 		bayer_ds_out_res->width = 0;
2706 		bayer_ds_out_res->height = 0;
2707 		goto done;
2708 	}
2709 
2710 	pipe_extra_configs->enable_raw_binning = true;
2711 	bayer_ds_out_res->width = effective_res->width;
2712 	bayer_ds_out_res->height = effective_res->height;
2713 
2714 	for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2715 	     i++) {
2716 		if (effective_res->width >= out_width *
2717 		    bds_factors[i].numerator / bds_factors[i].denominator &&
2718 		    effective_res->height >= out_height *
2719 		    bds_factors[i].numerator / bds_factors[i].denominator) {
2720 			bayer_ds_out_res->width = effective_res->width *
2721 						  bds_factors[i].denominator /
2722 						  bds_factors[i].numerator;
2723 			bayer_ds_out_res->height = effective_res->height *
2724 						   bds_factors[i].denominator /
2725 						   bds_factors[i].numerator;
2726 			break;
2727 		}
2728 	}
2729 
2730 	/*
2731 	 * DVS is cropped from BDS output, so we do not really need to set the
2732 	 * envelope to 20% of output resolution here. always set it to 12x12
2733 	 * per firmware requirement.
2734 	 */
2735 	pipe_configs->dvs_envelope.width = 12;
2736 	pipe_configs->dvs_envelope.height = 12;
2737 
2738 done:
2739 	if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2740 		stream_config->left_padding = -1;
2741 	else
2742 		stream_config->left_padding = 12;
2743 	dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2744 		pipe_id, width, height);
2745 }
2746 
2747 static void __configure_vf_output(struct atomisp_sub_device *asd,
2748 				  unsigned int width, unsigned int height,
2749 				  unsigned int min_width,
2750 				  enum ia_css_frame_format format,
2751 				  enum ia_css_pipe_id pipe_id)
2752 {
2753 	struct atomisp_device *isp = asd->isp;
2754 	struct atomisp_stream_env *stream_env =
2755 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2756 	stream_env->pipe_configs[pipe_id].mode =
2757 	    __pipe_id_to_pipe_mode(asd, pipe_id);
2758 	stream_env->update_pipe[pipe_id] = true;
2759 
2760 	stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2761 	stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2762 	stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2763 	stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2764 	    min_width;
2765 	dev_dbg(isp->dev,
2766 		"configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2767 		pipe_id, width, height, format);
2768 }
2769 
2770 static void __configure_video_vf_output(struct atomisp_sub_device *asd,
2771 					unsigned int width, unsigned int height,
2772 					unsigned int min_width,
2773 					enum ia_css_frame_format format,
2774 					enum ia_css_pipe_id pipe_id)
2775 {
2776 	struct atomisp_device *isp = asd->isp;
2777 	struct atomisp_stream_env *stream_env =
2778 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2779 	struct ia_css_frame_info *css_output_info;
2780 
2781 	stream_env->pipe_configs[pipe_id].mode =
2782 	    __pipe_id_to_pipe_mode(asd, pipe_id);
2783 	stream_env->update_pipe[pipe_id] = true;
2784 
2785 	/*
2786 	 * second_vf_output will be as video viewfinder in SDV mode
2787 	 * with SOC camera. vf_output will be as video viewfinder in
2788 	 * normal video mode.
2789 	 */
2790 	if (asd->continuous_mode->val)
2791 		css_output_info = &stream_env->pipe_configs[pipe_id].
2792 				  vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2793 	else
2794 		css_output_info = &stream_env->pipe_configs[pipe_id].
2795 				  vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2796 
2797 	css_output_info->res.width = width;
2798 	css_output_info->res.height = height;
2799 	css_output_info->format = format;
2800 	css_output_info->padded_width = min_width;
2801 	dev_dbg(isp->dev,
2802 		"configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2803 		pipe_id, width, height, format);
2804 }
2805 
2806 static int __get_frame_info(struct atomisp_sub_device *asd,
2807 			    unsigned int stream_index,
2808 			    struct ia_css_frame_info *info,
2809 			    enum frame_info_type type,
2810 			    enum ia_css_pipe_id pipe_id)
2811 {
2812 	struct atomisp_device *isp = asd->isp;
2813 	enum ia_css_err ret;
2814 	struct ia_css_pipe_info p_info;
2815 
2816 	/* FIXME! No need to destroy/recreate all streams */
2817 	if (__destroy_streams(asd, true))
2818 		dev_warn(isp->dev, "destroy stream failed.\n");
2819 
2820 	if (__destroy_pipes(asd, true))
2821 		dev_warn(isp->dev, "destroy pipe failed.\n");
2822 
2823 	if (__create_pipes(asd))
2824 		return -EINVAL;
2825 
2826 	if (__create_streams(asd))
2827 		goto stream_err;
2828 
2829 	ret = ia_css_pipe_get_info(
2830 		  asd->stream_env[stream_index]
2831 		  .pipes[pipe_id], &p_info);
2832 	if (ret == IA_CSS_SUCCESS) {
2833 		switch (type) {
2834 		case ATOMISP_CSS_VF_FRAME:
2835 			*info = p_info.vf_output_info[0];
2836 			dev_dbg(isp->dev, "getting vf frame info.\n");
2837 			break;
2838 		case ATOMISP_CSS_SECOND_VF_FRAME:
2839 			*info = p_info.vf_output_info[1];
2840 			dev_dbg(isp->dev, "getting second vf frame info.\n");
2841 			break;
2842 		case ATOMISP_CSS_OUTPUT_FRAME:
2843 			*info = p_info.output_info[0];
2844 			dev_dbg(isp->dev, "getting main frame info.\n");
2845 			break;
2846 		case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2847 			*info = p_info.output_info[1];
2848 			dev_dbg(isp->dev, "getting second main frame info.\n");
2849 			break;
2850 		case ATOMISP_CSS_RAW_FRAME:
2851 			*info = p_info.raw_output_info;
2852 			dev_dbg(isp->dev, "getting raw frame info.\n");
2853 		}
2854 		dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2855 			info->res.width, info->res.height, p_info.num_invalid_frames);
2856 		return 0;
2857 	}
2858 
2859 stream_err:
2860 	__destroy_pipes(asd, true);
2861 	return -EINVAL;
2862 }
2863 
2864 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2865 	uint16_t source_pad)
2866 {
2867 	struct atomisp_device *isp = asd->isp;
2868 	/*
2869 	 * to SOC camera, use yuvpp pipe.
2870 	 */
2871 	if (ATOMISP_USE_YUVPP(asd))
2872 		return IA_CSS_PIPE_ID_YUVPP;
2873 
2874 	switch (source_pad) {
2875 	case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2876 		if (asd->yuvpp_mode)
2877 			return IA_CSS_PIPE_ID_YUVPP;
2878 		if (asd->copy_mode)
2879 			return IA_CSS_PIPE_ID_COPY;
2880 		if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2881 		    || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2882 			return IA_CSS_PIPE_ID_VIDEO;
2883 		else
2884 			return IA_CSS_PIPE_ID_CAPTURE;
2885 	case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2886 		if (asd->copy_mode)
2887 			return IA_CSS_PIPE_ID_COPY;
2888 		return IA_CSS_PIPE_ID_CAPTURE;
2889 	case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2890 		if (!atomisp_is_mbuscode_raw(
2891 			asd->fmt[asd->capture_pad].fmt.code))
2892 			return IA_CSS_PIPE_ID_CAPTURE;
2893 	case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2894 		if (asd->yuvpp_mode)
2895 			return IA_CSS_PIPE_ID_YUVPP;
2896 		if (asd->copy_mode)
2897 			return IA_CSS_PIPE_ID_COPY;
2898 		if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2899 			return IA_CSS_PIPE_ID_VIDEO;
2900 		else
2901 			return IA_CSS_PIPE_ID_PREVIEW;
2902 	}
2903 	dev_warn(isp->dev,
2904 		 "invalid source pad:%d, return default preview pipe index.\n",
2905 		 source_pad);
2906 	return IA_CSS_PIPE_ID_PREVIEW;
2907 }
2908 
2909 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2910 			       u16 source_pad,
2911 			       struct ia_css_frame_info *frame_info)
2912 {
2913 	struct ia_css_pipe_info info;
2914 	int pipe_index = atomisp_get_pipe_index(asd, source_pad);
2915 	int stream_index;
2916 	struct atomisp_device *isp = asd->isp;
2917 
2918 	if (ATOMISP_SOC_CAMERA(asd))
2919 		stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
2920 	else {
2921 		stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2922 			       ATOMISP_INPUT_STREAM_VIDEO :
2923 			       atomisp_source_pad_to_stream_id(asd, source_pad);
2924 	}
2925 
2926 	if (IA_CSS_SUCCESS != ia_css_pipe_get_info(asd->stream_env[stream_index]
2927 		.pipes[pipe_index], &info)) {
2928 		dev_err(isp->dev, "ia_css_pipe_get_info FAILED");
2929 		return -EINVAL;
2930 	}
2931 
2932 	switch (source_pad) {
2933 	case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2934 		*frame_info = info.output_info[0];
2935 		break;
2936 	case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2937 		if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2938 			*frame_info = info.
2939 				      output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2940 		else
2941 			*frame_info = info.
2942 				      output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2943 		break;
2944 	case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2945 		if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
2946 			*frame_info = info.output_info[0];
2947 		else
2948 			*frame_info = info.vf_output_info[0];
2949 		break;
2950 	case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2951 		if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2952 		    (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
2953 		     pipe_index == IA_CSS_PIPE_ID_YUVPP))
2954 			if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2955 				*frame_info = info.
2956 					      vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2957 			else
2958 				*frame_info = info.
2959 					      vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2960 		else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2961 			*frame_info =
2962 			    info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2963 		else
2964 			*frame_info =
2965 			    info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2966 
2967 		break;
2968 	default:
2969 		frame_info = NULL;
2970 		break;
2971 	}
2972 	return frame_info ? 0 : -EINVAL;
2973 }
2974 
2975 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2976 				      unsigned int stream_index,
2977 				      unsigned int width, unsigned int height,
2978 				      unsigned int padded_width,
2979 				      enum ia_css_frame_format format)
2980 {
2981 	asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
2982 	default_capture_config.mode =
2983 	    IA_CSS_CAPTURE_MODE_RAW;
2984 
2985 	__configure_output(asd, stream_index, width, height, padded_width,
2986 			   format, IA_CSS_PIPE_ID_COPY);
2987 	return 0;
2988 }
2989 
2990 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
2991 				       unsigned int stream_index,
2992 				       unsigned int width, unsigned int height,
2993 				       unsigned int padded_width,
2994 				       enum ia_css_frame_format format)
2995 {
2996 	asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
2997 	default_capture_config.mode =
2998 	    IA_CSS_CAPTURE_MODE_RAW;
2999 
3000 	__configure_output(asd, stream_index, width, height, padded_width,
3001 			   format, IA_CSS_PIPE_ID_YUVPP);
3002 	return 0;
3003 }
3004 
3005 int atomisp_css_yuvpp_configure_viewfinder(
3006     struct atomisp_sub_device *asd,
3007     unsigned int stream_index,
3008     unsigned int width, unsigned int height,
3009     unsigned int min_width,
3010     enum ia_css_frame_format format)
3011 {
3012 	struct atomisp_stream_env *stream_env =
3013 		    &asd->stream_env[stream_index];
3014 	enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP;
3015 
3016 	stream_env->pipe_configs[pipe_id].mode =
3017 	    __pipe_id_to_pipe_mode(asd, pipe_id);
3018 	stream_env->update_pipe[pipe_id] = true;
3019 
3020 	stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
3021 	stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
3022 	stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
3023 	stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
3024 	    min_width;
3025 	return 0;
3026 }
3027 
3028 int atomisp_css_yuvpp_get_output_frame_info(
3029     struct atomisp_sub_device *asd,
3030     unsigned int stream_index,
3031     struct ia_css_frame_info *info)
3032 {
3033 	return __get_frame_info(asd, stream_index, info,
3034 				ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
3035 }
3036 
3037 int atomisp_css_yuvpp_get_viewfinder_frame_info(
3038     struct atomisp_sub_device *asd,
3039     unsigned int stream_index,
3040     struct ia_css_frame_info *info)
3041 {
3042 	return __get_frame_info(asd, stream_index, info,
3043 				ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
3044 }
3045 
3046 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
3047 	unsigned int width, unsigned int height,
3048 	unsigned int min_width,
3049 	enum ia_css_frame_format format)
3050 {
3051 	/*
3052 	 * to SOC camera, use yuvpp pipe.
3053 	 */
3054 	if (ATOMISP_USE_YUVPP(asd))
3055 		__configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
3056 						 height,
3057 						 min_width, format, IA_CSS_PIPE_ID_YUVPP);
3058 	else
3059 		__configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3060 				   min_width, format, IA_CSS_PIPE_ID_PREVIEW);
3061 	return 0;
3062 }
3063 
3064 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
3065 	unsigned int width, unsigned int height,
3066 	unsigned int min_width,
3067 	enum ia_css_frame_format format)
3068 {
3069 	enum ia_css_pipe_id pipe_id;
3070 
3071 	/*
3072 	 * to SOC camera, use yuvpp pipe.
3073 	 */
3074 	if (ATOMISP_USE_YUVPP(asd))
3075 		pipe_id = IA_CSS_PIPE_ID_YUVPP;
3076 	else
3077 		pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3078 
3079 	__configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3080 			   min_width, format, pipe_id);
3081 	return 0;
3082 }
3083 
3084 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
3085 				       unsigned int width, unsigned int height,
3086 				       unsigned int min_width,
3087 				       enum ia_css_frame_format format)
3088 {
3089 	/*
3090 	 * to SOC camera, use yuvpp pipe.
3091 	 */
3092 	if (ATOMISP_USE_YUVPP(asd))
3093 		__configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
3094 						 height,
3095 						 min_width, format, IA_CSS_PIPE_ID_YUVPP);
3096 	else
3097 		__configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3098 				   min_width, format, IA_CSS_PIPE_ID_VIDEO);
3099 	return 0;
3100 }
3101 
3102 int atomisp_css_video_configure_viewfinder(
3103     struct atomisp_sub_device *asd,
3104     unsigned int width, unsigned int height,
3105     unsigned int min_width,
3106     enum ia_css_frame_format format)
3107 {
3108 	/*
3109 	 * to SOC camera, video will use yuvpp pipe.
3110 	 */
3111 	if (ATOMISP_USE_YUVPP(asd))
3112 		__configure_video_vf_output(asd, width, height, min_width, format,
3113 					    IA_CSS_PIPE_ID_YUVPP);
3114 	else
3115 		__configure_vf_output(asd, width, height, min_width, format,
3116 				      IA_CSS_PIPE_ID_VIDEO);
3117 	return 0;
3118 }
3119 
3120 int atomisp_css_capture_configure_viewfinder(
3121     struct atomisp_sub_device *asd,
3122     unsigned int width, unsigned int height,
3123     unsigned int min_width,
3124     enum ia_css_frame_format format)
3125 {
3126 	enum ia_css_pipe_id pipe_id;
3127 
3128 	/*
3129 	 * to SOC camera, video will use yuvpp pipe.
3130 	 */
3131 	if (ATOMISP_USE_YUVPP(asd))
3132 		pipe_id = IA_CSS_PIPE_ID_YUVPP;
3133 	else
3134 		pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3135 
3136 	__configure_vf_output(asd, width, height, min_width, format,
3137 			      pipe_id);
3138 	return 0;
3139 }
3140 
3141 int atomisp_css_video_get_viewfinder_frame_info(
3142     struct atomisp_sub_device *asd,
3143     struct ia_css_frame_info *info)
3144 {
3145 	enum ia_css_pipe_id pipe_id;
3146 	enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME;
3147 
3148 	if (ATOMISP_USE_YUVPP(asd)) {
3149 		pipe_id = IA_CSS_PIPE_ID_YUVPP;
3150 		if (asd->continuous_mode->val)
3151 			frame_type = ATOMISP_CSS_SECOND_VF_FRAME;
3152 	} else {
3153 		pipe_id = IA_CSS_PIPE_ID_VIDEO;
3154 	}
3155 
3156 	return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3157 				frame_type, pipe_id);
3158 }
3159 
3160 int atomisp_css_capture_get_viewfinder_frame_info(
3161     struct atomisp_sub_device *asd,
3162     struct ia_css_frame_info *info)
3163 {
3164 	enum ia_css_pipe_id pipe_id;
3165 
3166 	if (ATOMISP_USE_YUVPP(asd))
3167 		pipe_id = IA_CSS_PIPE_ID_YUVPP;
3168 	else
3169 		pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3170 
3171 	return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3172 				ATOMISP_CSS_VF_FRAME, pipe_id);
3173 }
3174 
3175 int atomisp_css_capture_get_output_raw_frame_info(
3176     struct atomisp_sub_device *asd,
3177     struct ia_css_frame_info *info)
3178 {
3179 	if (ATOMISP_USE_YUVPP(asd))
3180 		return 0;
3181 
3182 	return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3183 				ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE);
3184 }
3185 
3186 int atomisp_css_copy_get_output_frame_info(
3187     struct atomisp_sub_device *asd,
3188     unsigned int stream_index,
3189     struct ia_css_frame_info *info)
3190 {
3191 	return __get_frame_info(asd, stream_index, info,
3192 				ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
3193 }
3194 
3195 int atomisp_css_preview_get_output_frame_info(
3196     struct atomisp_sub_device *asd,
3197     struct ia_css_frame_info *info)
3198 {
3199 	enum ia_css_pipe_id pipe_id;
3200 	enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3201 
3202 	if (ATOMISP_USE_YUVPP(asd)) {
3203 		pipe_id = IA_CSS_PIPE_ID_YUVPP;
3204 		if (asd->continuous_mode->val)
3205 			frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3206 	} else {
3207 		pipe_id = IA_CSS_PIPE_ID_PREVIEW;
3208 	}
3209 
3210 	return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3211 				frame_type, pipe_id);
3212 }
3213 
3214 int atomisp_css_capture_get_output_frame_info(
3215     struct atomisp_sub_device *asd,
3216     struct ia_css_frame_info *info)
3217 {
3218 	enum ia_css_pipe_id pipe_id;
3219 
3220 	if (ATOMISP_USE_YUVPP(asd))
3221 		pipe_id = IA_CSS_PIPE_ID_YUVPP;
3222 	else
3223 		pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3224 
3225 	return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3226 				ATOMISP_CSS_OUTPUT_FRAME, pipe_id);
3227 }
3228 
3229 int atomisp_css_video_get_output_frame_info(
3230     struct atomisp_sub_device *asd,
3231     struct ia_css_frame_info *info)
3232 {
3233 	enum ia_css_pipe_id pipe_id;
3234 	enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3235 
3236 	if (ATOMISP_USE_YUVPP(asd)) {
3237 		pipe_id = IA_CSS_PIPE_ID_YUVPP;
3238 		if (asd->continuous_mode->val)
3239 			frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3240 	} else {
3241 		pipe_id = IA_CSS_PIPE_ID_VIDEO;
3242 	}
3243 
3244 	return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3245 				frame_type, pipe_id);
3246 }
3247 
3248 int atomisp_css_preview_configure_pp_input(
3249     struct atomisp_sub_device *asd,
3250     unsigned int width, unsigned int height)
3251 {
3252 	struct atomisp_stream_env *stream_env =
3253 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3254 	__configure_preview_pp_input(asd, width, height,
3255 				     ATOMISP_USE_YUVPP(asd) ?
3256 				     IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW);
3257 
3258 	if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3259 	    capt_pp_in_res.width)
3260 		__configure_capture_pp_input(asd, width, height,
3261 					     ATOMISP_USE_YUVPP(asd) ?
3262 					     IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3263 	return 0;
3264 }
3265 
3266 int atomisp_css_capture_configure_pp_input(
3267     struct atomisp_sub_device *asd,
3268     unsigned int width, unsigned int height)
3269 {
3270 	__configure_capture_pp_input(asd, width, height,
3271 				     ATOMISP_USE_YUVPP(asd) ?
3272 				     IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3273 	return 0;
3274 }
3275 
3276 int atomisp_css_video_configure_pp_input(
3277     struct atomisp_sub_device *asd,
3278     unsigned int width, unsigned int height)
3279 {
3280 	struct atomisp_stream_env *stream_env =
3281 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3282 
3283 	__configure_video_pp_input(asd, width, height,
3284 				   ATOMISP_USE_YUVPP(asd) ?
3285 				   IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO);
3286 
3287 	if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3288 	    capt_pp_in_res.width)
3289 		__configure_capture_pp_input(asd, width, height,
3290 					     ATOMISP_USE_YUVPP(asd) ?
3291 					     IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3292 	return 0;
3293 }
3294 
3295 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
3296 	int num_captures, unsigned int skip, int offset)
3297 {
3298 	enum ia_css_err ret;
3299 
3300 	dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
3301 		__func__, num_captures, skip, offset);
3302 
3303 	ret = ia_css_stream_capture(
3304 		  asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3305 		  num_captures, skip, offset);
3306 	if (ret != IA_CSS_SUCCESS)
3307 		return -EINVAL;
3308 
3309 	return 0;
3310 }
3311 
3312 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
3313 {
3314 	enum ia_css_err ret;
3315 
3316 	ret = ia_css_stream_capture_frame(
3317 		  asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3318 		  exp_id);
3319 	if (ret == IA_CSS_ERR_QUEUE_IS_FULL) {
3320 		/* capture cmd queue is full */
3321 		return -EBUSY;
3322 	} else if (ret != IA_CSS_SUCCESS) {
3323 		return -EIO;
3324 	}
3325 
3326 	return 0;
3327 }
3328 
3329 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
3330 {
3331 	enum ia_css_err ret;
3332 
3333 	ret = ia_css_unlock_raw_frame(
3334 		  asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3335 		  exp_id);
3336 	if (ret == IA_CSS_ERR_QUEUE_IS_FULL)
3337 		return -EAGAIN;
3338 	else if (ret != IA_CSS_SUCCESS)
3339 		return -EIO;
3340 
3341 	return 0;
3342 }
3343 
3344 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
3345 				   bool enable)
3346 {
3347 	asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3348 	.pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
3349 	.default_capture_config.enable_xnr = enable;
3350 	asd->params.capture_config.enable_xnr = enable;
3351 	asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3352 	.update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
3353 
3354 	return 0;
3355 }
3356 
3357 void atomisp_css_send_input_frame(struct atomisp_sub_device *asd,
3358 				  unsigned short *data, unsigned int width,
3359 				  unsigned int height)
3360 {
3361 	ia_css_stream_send_input_frame(
3362 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3363 	    data, width, height);
3364 }
3365 
3366 bool atomisp_css_isp_has_started(void)
3367 {
3368 	return ia_css_isp_has_started();
3369 }
3370 
3371 void atomisp_css_request_flash(struct atomisp_sub_device *asd)
3372 {
3373 	ia_css_stream_request_flash(
3374 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream);
3375 }
3376 
3377 void atomisp_css_set_wb_config(struct atomisp_sub_device *asd,
3378 			       struct ia_css_wb_config *wb_config)
3379 {
3380 	asd->params.config.wb_config = wb_config;
3381 }
3382 
3383 void atomisp_css_set_ob_config(struct atomisp_sub_device *asd,
3384 			       struct ia_css_ob_config *ob_config)
3385 {
3386 	asd->params.config.ob_config = ob_config;
3387 }
3388 
3389 void atomisp_css_set_dp_config(struct atomisp_sub_device *asd,
3390 			       struct ia_css_dp_config *dp_config)
3391 {
3392 	asd->params.config.dp_config = dp_config;
3393 }
3394 
3395 void atomisp_css_set_de_config(struct atomisp_sub_device *asd,
3396 			       struct ia_css_de_config *de_config)
3397 {
3398 	asd->params.config.de_config = de_config;
3399 }
3400 
3401 void atomisp_css_set_dz_config(struct atomisp_sub_device *asd,
3402 			       struct ia_css_dz_config *dz_config)
3403 {
3404 	asd->params.config.dz_config = dz_config;
3405 }
3406 
3407 void atomisp_css_set_default_de_config(struct atomisp_sub_device *asd)
3408 {
3409 	asd->params.config.de_config = NULL;
3410 }
3411 
3412 void atomisp_css_set_ce_config(struct atomisp_sub_device *asd,
3413 			       struct ia_css_ce_config *ce_config)
3414 {
3415 	asd->params.config.ce_config = ce_config;
3416 }
3417 
3418 void atomisp_css_set_nr_config(struct atomisp_sub_device *asd,
3419 			       struct ia_css_nr_config *nr_config)
3420 {
3421 	asd->params.config.nr_config = nr_config;
3422 }
3423 
3424 void atomisp_css_set_ee_config(struct atomisp_sub_device *asd,
3425 			       struct ia_css_ee_config *ee_config)
3426 {
3427 	asd->params.config.ee_config = ee_config;
3428 }
3429 
3430 void atomisp_css_set_tnr_config(struct atomisp_sub_device *asd,
3431 				struct ia_css_tnr_config *tnr_config)
3432 {
3433 	asd->params.config.tnr_config = tnr_config;
3434 }
3435 
3436 void atomisp_css_set_cc_config(struct atomisp_sub_device *asd,
3437 			       struct ia_css_cc_config *cc_config)
3438 {
3439 	asd->params.config.cc_config = cc_config;
3440 }
3441 
3442 void atomisp_css_set_macc_table(struct atomisp_sub_device *asd,
3443 				struct ia_css_macc_table *macc_table)
3444 {
3445 	asd->params.config.macc_table = macc_table;
3446 }
3447 
3448 void atomisp_css_set_macc_config(struct atomisp_sub_device *asd,
3449 				 struct ia_css_macc_config *macc_config)
3450 {
3451 	asd->params.config.macc_config = macc_config;
3452 }
3453 
3454 void atomisp_css_set_ecd_config(struct atomisp_sub_device *asd,
3455 				struct ia_css_ecd_config *ecd_config)
3456 {
3457 	asd->params.config.ecd_config = ecd_config;
3458 }
3459 
3460 void atomisp_css_set_ynr_config(struct atomisp_sub_device *asd,
3461 				struct ia_css_ynr_config *ynr_config)
3462 {
3463 	asd->params.config.ynr_config = ynr_config;
3464 }
3465 
3466 void atomisp_css_set_fc_config(struct atomisp_sub_device *asd,
3467 			       struct ia_css_fc_config *fc_config)
3468 {
3469 	asd->params.config.fc_config = fc_config;
3470 }
3471 
3472 void atomisp_css_set_ctc_config(struct atomisp_sub_device *asd,
3473 				struct ia_css_ctc_config *ctc_config)
3474 {
3475 	asd->params.config.ctc_config = ctc_config;
3476 }
3477 
3478 void atomisp_css_set_cnr_config(struct atomisp_sub_device *asd,
3479 				struct ia_css_cnr_config *cnr_config)
3480 {
3481 	asd->params.config.cnr_config = cnr_config;
3482 }
3483 
3484 void atomisp_css_set_aa_config(struct atomisp_sub_device *asd,
3485 			       struct ia_css_aa_config *aa_config)
3486 {
3487 	asd->params.config.aa_config = aa_config;
3488 }
3489 
3490 void atomisp_css_set_baa_config(struct atomisp_sub_device *asd,
3491 				struct ia_css_aa_config *baa_config)
3492 {
3493 	asd->params.config.baa_config = baa_config;
3494 }
3495 
3496 void atomisp_css_set_anr_config(struct atomisp_sub_device *asd,
3497 				struct ia_css_anr_config *anr_config)
3498 {
3499 	asd->params.config.anr_config = anr_config;
3500 }
3501 
3502 void atomisp_css_set_xnr_config(struct atomisp_sub_device *asd,
3503 				struct ia_css_xnr_config *xnr_config)
3504 {
3505 	asd->params.config.xnr_config = xnr_config;
3506 }
3507 
3508 void atomisp_css_set_yuv2rgb_cc_config(struct atomisp_sub_device *asd,
3509 				       struct ia_css_cc_config *yuv2rgb_cc_config)
3510 {
3511 	asd->params.config.yuv2rgb_cc_config = yuv2rgb_cc_config;
3512 }
3513 
3514 void atomisp_css_set_rgb2yuv_cc_config(struct atomisp_sub_device *asd,
3515 				       struct ia_css_cc_config *rgb2yuv_cc_config)
3516 {
3517 	asd->params.config.rgb2yuv_cc_config = rgb2yuv_cc_config;
3518 }
3519 
3520 void atomisp_css_set_xnr_table(struct atomisp_sub_device *asd,
3521 			       struct ia_css_xnr_table *xnr_table)
3522 {
3523 	asd->params.config.xnr_table = xnr_table;
3524 }
3525 
3526 void atomisp_css_set_r_gamma_table(struct atomisp_sub_device *asd,
3527 				   struct ia_css_rgb_gamma_table *r_gamma_table)
3528 {
3529 	asd->params.config.r_gamma_table = r_gamma_table;
3530 }
3531 
3532 void atomisp_css_set_g_gamma_table(struct atomisp_sub_device *asd,
3533 				   struct ia_css_rgb_gamma_table *g_gamma_table)
3534 {
3535 	asd->params.config.g_gamma_table = g_gamma_table;
3536 }
3537 
3538 void atomisp_css_set_b_gamma_table(struct atomisp_sub_device *asd,
3539 				   struct ia_css_rgb_gamma_table *b_gamma_table)
3540 {
3541 	asd->params.config.b_gamma_table = b_gamma_table;
3542 }
3543 
3544 void atomisp_css_set_gamma_table(struct atomisp_sub_device *asd,
3545 				 struct ia_css_gamma_table *gamma_table)
3546 {
3547 	asd->params.config.gamma_table = gamma_table;
3548 }
3549 
3550 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
3551 			       struct ia_css_ctc_table *ctc_table)
3552 {
3553 	int i;
3554 	u16 *vamem_ptr = ctc_table->data.vamem_1;
3555 	int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
3556 	bool valid = false;
3557 
3558 	/* workaround: if ctc_table is all 0, do not apply it */
3559 	if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
3560 		vamem_ptr = ctc_table->data.vamem_2;
3561 		data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
3562 	}
3563 
3564 	for (i = 0; i < data_size; i++) {
3565 		if (*(vamem_ptr + i)) {
3566 			valid = true;
3567 			break;
3568 		}
3569 	}
3570 
3571 	if (valid)
3572 		asd->params.config.ctc_table = ctc_table;
3573 	else
3574 		dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
3575 }
3576 
3577 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
3578 			       struct ia_css_anr_thres *anr_thres)
3579 {
3580 	asd->params.config.anr_thres = anr_thres;
3581 }
3582 
3583 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
3584 			       struct ia_css_dvs_6axis_config *dvs_6axis)
3585 {
3586 	asd->params.config.dvs_6axis_config = dvs_6axis;
3587 }
3588 
3589 void atomisp_css_set_gc_config(struct atomisp_sub_device *asd,
3590 			       struct ia_css_gc_config *gc_config)
3591 {
3592 	asd->params.config.gc_config = gc_config;
3593 }
3594 
3595 void atomisp_css_set_3a_config(struct atomisp_sub_device *asd,
3596 			       struct ia_css_3a_config *s3a_config)
3597 {
3598 	asd->params.config.s3a_config = s3a_config;
3599 }
3600 
3601 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
3602 				      struct atomisp_dis_vector *vector)
3603 {
3604 	if (!asd->params.config.motion_vector)
3605 		asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
3606 
3607 	memset(asd->params.config.motion_vector,
3608 	       0, sizeof(struct ia_css_vector));
3609 	asd->params.css_param.motion_vector.x = vector->x;
3610 	asd->params.css_param.motion_vector.y = vector->y;
3611 }
3612 
3613 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
3614 				    struct atomisp_dvs_grid_info *atomgrid)
3615 {
3616 	struct ia_css_dvs_grid_info *cur =
3617 	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
3618 
3619 	if (!cur) {
3620 		dev_err(asd->isp->dev, "dvs grid not available!\n");
3621 		return -EINVAL;
3622 	}
3623 
3624 	if (sizeof(*cur) != sizeof(*atomgrid)) {
3625 		dev_err(asd->isp->dev, "dvs grid mis-match!\n");
3626 		return -EINVAL;
3627 	}
3628 
3629 	if (!cur->enable) {
3630 		dev_err(asd->isp->dev, "dvs not enabled!\n");
3631 		return -EINVAL;
3632 	}
3633 
3634 	return memcmp(atomgrid, cur, sizeof(*cur));
3635 }
3636 
3637 void  atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
3638 				 struct ia_css_dvs2_coefficients *coefs)
3639 {
3640 	asd->params.config.dvs2_coefs = coefs;
3641 }
3642 
3643 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
3644 			      struct atomisp_dis_coefficients *coefs)
3645 {
3646 	if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
3647 		/* If the grid info in the argument differs from the current
3648 		   grid info, we tell the caller to reset the grid size and
3649 		   try again. */
3650 		return -EAGAIN;
3651 
3652 	if (!coefs->hor_coefs.odd_real ||
3653 	    !coefs->hor_coefs.odd_imag ||
3654 	    !coefs->hor_coefs.even_real ||
3655 	    !coefs->hor_coefs.even_imag ||
3656 	    !coefs->ver_coefs.odd_real ||
3657 	    !coefs->ver_coefs.odd_imag ||
3658 	    !coefs->ver_coefs.even_real ||
3659 	    !coefs->ver_coefs.even_imag ||
3660 	    !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real ||
3661 	    !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag ||
3662 	    !asd->params.css_param.dvs2_coeff->hor_coefs.even_real ||
3663 	    !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag ||
3664 	    !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real ||
3665 	    !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag ||
3666 	    !asd->params.css_param.dvs2_coeff->ver_coefs.even_real ||
3667 	    !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag)
3668 		return -EINVAL;
3669 
3670 	if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
3671 			   coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
3672 		return -EFAULT;
3673 	if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
3674 			   coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
3675 		return -EFAULT;
3676 	if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
3677 			   coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
3678 		return -EFAULT;
3679 	if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
3680 			   coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
3681 		return -EFAULT;
3682 
3683 	if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
3684 			   coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
3685 		return -EFAULT;
3686 	if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
3687 			   coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
3688 		return -EFAULT;
3689 	if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
3690 			   coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
3691 		return -EFAULT;
3692 	if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
3693 			   coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
3694 		return -EFAULT;
3695 
3696 	asd->params.css_param.update_flag.dvs2_coefs =
3697 	    (struct atomisp_dvs2_coefficients *)
3698 	    asd->params.css_param.dvs2_coeff;
3699 	/* FIXME! */
3700 	/*	asd->params.dis_proj_data_valid = false; */
3701 	asd->params.css_update_params_needed = true;
3702 
3703 	return 0;
3704 }
3705 
3706 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
3707 				 unsigned int zoom)
3708 {
3709 	struct atomisp_device *isp = asd->isp;
3710 
3711 	if (zoom == asd->params.css_param.dz_config.dx &&
3712 	    zoom == asd->params.css_param.dz_config.dy) {
3713 		dev_dbg(isp->dev, "same zoom scale. skipped.\n");
3714 		return;
3715 	}
3716 
3717 	memset(&asd->params.css_param.dz_config, 0,
3718 	       sizeof(struct ia_css_dz_config));
3719 	asd->params.css_param.dz_config.dx = zoom;
3720 	asd->params.css_param.dz_config.dy = zoom;
3721 
3722 	asd->params.css_param.update_flag.dz_config =
3723 	    (struct atomisp_dz_config *)&asd->params.css_param.dz_config;
3724 	asd->params.css_update_params_needed = true;
3725 }
3726 
3727 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
3728 				    struct ia_css_formats_config *formats_config)
3729 {
3730 	asd->params.config.formats_config = formats_config;
3731 }
3732 
3733 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
3734 			      struct atomisp_wb_config *config)
3735 {
3736 	struct ia_css_wb_config wb_config;
3737 	struct ia_css_isp_config isp_config;
3738 	struct atomisp_device *isp = asd->isp;
3739 
3740 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3741 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3742 			__func__);
3743 		return -EINVAL;
3744 	}
3745 	memset(&wb_config, 0, sizeof(struct ia_css_wb_config));
3746 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3747 	isp_config.wb_config = &wb_config;
3748 	ia_css_stream_get_isp_config(
3749 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3750 	    &isp_config);
3751 	memcpy(config, &wb_config, sizeof(*config));
3752 
3753 	return 0;
3754 }
3755 
3756 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
3757 			      struct atomisp_ob_config *config)
3758 {
3759 	struct ia_css_ob_config ob_config;
3760 	struct ia_css_isp_config isp_config;
3761 	struct atomisp_device *isp = asd->isp;
3762 
3763 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3764 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3765 			__func__);
3766 		return -EINVAL;
3767 	}
3768 	memset(&ob_config, 0, sizeof(struct ia_css_ob_config));
3769 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3770 	isp_config.ob_config = &ob_config;
3771 	ia_css_stream_get_isp_config(
3772 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3773 	    &isp_config);
3774 	memcpy(config, &ob_config, sizeof(*config));
3775 
3776 	return 0;
3777 }
3778 
3779 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
3780 			      struct atomisp_dp_config *config)
3781 {
3782 	struct ia_css_dp_config dp_config;
3783 	struct ia_css_isp_config isp_config;
3784 	struct atomisp_device *isp = asd->isp;
3785 
3786 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3787 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3788 			__func__);
3789 		return -EINVAL;
3790 	}
3791 	memset(&dp_config, 0, sizeof(struct ia_css_dp_config));
3792 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3793 	isp_config.dp_config = &dp_config;
3794 	ia_css_stream_get_isp_config(
3795 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3796 	    &isp_config);
3797 	memcpy(config, &dp_config, sizeof(*config));
3798 
3799 	return 0;
3800 }
3801 
3802 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3803 			      struct atomisp_de_config *config)
3804 {
3805 	struct ia_css_de_config de_config;
3806 	struct ia_css_isp_config isp_config;
3807 	struct atomisp_device *isp = asd->isp;
3808 
3809 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3810 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3811 			__func__);
3812 		return -EINVAL;
3813 	}
3814 	memset(&de_config, 0, sizeof(struct ia_css_de_config));
3815 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3816 	isp_config.de_config = &de_config;
3817 	ia_css_stream_get_isp_config(
3818 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3819 	    &isp_config);
3820 	memcpy(config, &de_config, sizeof(*config));
3821 
3822 	return 0;
3823 }
3824 
3825 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3826 			      struct atomisp_nr_config *config)
3827 {
3828 	struct ia_css_nr_config nr_config;
3829 	struct ia_css_isp_config isp_config;
3830 	struct atomisp_device *isp = asd->isp;
3831 
3832 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3833 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3834 			__func__);
3835 		return -EINVAL;
3836 	}
3837 	memset(&nr_config, 0, sizeof(struct ia_css_nr_config));
3838 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3839 
3840 	isp_config.nr_config = &nr_config;
3841 	ia_css_stream_get_isp_config(
3842 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3843 	    &isp_config);
3844 	memcpy(config, &nr_config, sizeof(*config));
3845 
3846 	return 0;
3847 }
3848 
3849 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3850 			      struct atomisp_ee_config *config)
3851 {
3852 	struct ia_css_ee_config ee_config;
3853 	struct ia_css_isp_config isp_config;
3854 	struct atomisp_device *isp = asd->isp;
3855 
3856 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3857 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3858 			__func__);
3859 		return -EINVAL;
3860 	}
3861 	memset(&ee_config, 0, sizeof(struct ia_css_ee_config));
3862 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3863 	isp_config.ee_config = &ee_config;
3864 	ia_css_stream_get_isp_config(
3865 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3866 	    &isp_config);
3867 	memcpy(config, &ee_config, sizeof(*config));
3868 
3869 	return 0;
3870 }
3871 
3872 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3873 			       struct atomisp_tnr_config *config)
3874 {
3875 	struct ia_css_tnr_config tnr_config;
3876 	struct ia_css_isp_config isp_config;
3877 	struct atomisp_device *isp = asd->isp;
3878 
3879 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3880 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3881 			__func__);
3882 		return -EINVAL;
3883 	}
3884 	memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config));
3885 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3886 	isp_config.tnr_config = &tnr_config;
3887 	ia_css_stream_get_isp_config(
3888 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3889 	    &isp_config);
3890 	memcpy(config, &tnr_config, sizeof(*config));
3891 
3892 	return 0;
3893 }
3894 
3895 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3896 			      struct atomisp_ctc_table *config)
3897 {
3898 	struct ia_css_ctc_table *tab;
3899 	struct ia_css_isp_config isp_config;
3900 	struct atomisp_device *isp = asd->isp;
3901 
3902 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3903 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3904 			__func__);
3905 		return -EINVAL;
3906 	}
3907 
3908 	tab = vzalloc(sizeof(struct ia_css_ctc_table));
3909 	if (!tab)
3910 		return -ENOMEM;
3911 
3912 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3913 	isp_config.ctc_table = tab;
3914 	ia_css_stream_get_isp_config(
3915 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3916 	    &isp_config);
3917 	memcpy(config, tab, sizeof(*tab));
3918 	vfree(tab);
3919 
3920 	return 0;
3921 }
3922 
3923 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
3924 				struct atomisp_gamma_table *config)
3925 {
3926 	struct ia_css_gamma_table *tab;
3927 	struct ia_css_isp_config isp_config;
3928 	struct atomisp_device *isp = asd->isp;
3929 
3930 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3931 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3932 			__func__);
3933 		return -EINVAL;
3934 	}
3935 
3936 	tab = vzalloc(sizeof(struct ia_css_gamma_table));
3937 	if (!tab)
3938 		return -ENOMEM;
3939 
3940 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3941 	isp_config.gamma_table = tab;
3942 	ia_css_stream_get_isp_config(
3943 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3944 	    &isp_config);
3945 	memcpy(config, tab, sizeof(*tab));
3946 	vfree(tab);
3947 
3948 	return 0;
3949 }
3950 
3951 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
3952 			      struct atomisp_gc_config *config)
3953 {
3954 	struct ia_css_gc_config gc_config;
3955 	struct ia_css_isp_config isp_config;
3956 	struct atomisp_device *isp = asd->isp;
3957 
3958 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3959 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3960 			__func__);
3961 		return -EINVAL;
3962 	}
3963 	memset(&gc_config, 0, sizeof(struct ia_css_gc_config));
3964 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3965 	isp_config.gc_config = &gc_config;
3966 	ia_css_stream_get_isp_config(
3967 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3968 	    &isp_config);
3969 	/* Get gamma correction params from current setup */
3970 	memcpy(config, &gc_config, sizeof(*config));
3971 
3972 	return 0;
3973 }
3974 
3975 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
3976 			      struct atomisp_3a_config *config)
3977 {
3978 	struct ia_css_3a_config s3a_config;
3979 	struct ia_css_isp_config isp_config;
3980 	struct atomisp_device *isp = asd->isp;
3981 
3982 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3983 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3984 			__func__);
3985 		return -EINVAL;
3986 	}
3987 	memset(&s3a_config, 0, sizeof(struct ia_css_3a_config));
3988 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3989 	isp_config.s3a_config = &s3a_config;
3990 	ia_css_stream_get_isp_config(
3991 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3992 	    &isp_config);
3993 	/* Get white balance from current setup */
3994 	memcpy(config, &s3a_config, sizeof(*config));
3995 
3996 	return 0;
3997 }
3998 
3999 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
4000 				   struct atomisp_formats_config *config)
4001 {
4002 	struct ia_css_formats_config formats_config;
4003 	struct ia_css_isp_config isp_config;
4004 	struct atomisp_device *isp = asd->isp;
4005 
4006 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4007 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4008 			__func__);
4009 		return -EINVAL;
4010 	}
4011 	memset(&formats_config, 0, sizeof(formats_config));
4012 	memset(&isp_config, 0, sizeof(isp_config));
4013 	isp_config.formats_config = &formats_config;
4014 	ia_css_stream_get_isp_config(
4015 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4016 	    &isp_config);
4017 	/* Get narrow gamma from current setup */
4018 	memcpy(config, &formats_config, sizeof(*config));
4019 
4020 	return 0;
4021 }
4022 
4023 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
4024 				unsigned int *zoom)
4025 {
4026 	struct ia_css_dz_config dz_config;  /** Digital Zoom */
4027 	struct ia_css_isp_config isp_config;
4028 	struct atomisp_device *isp = asd->isp;
4029 
4030 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4031 		dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4032 			__func__);
4033 		return -EINVAL;
4034 	}
4035 	memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
4036 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4037 	isp_config.dz_config = &dz_config;
4038 	ia_css_stream_get_isp_config(
4039 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4040 	    &isp_config);
4041 	*zoom = dz_config.dx;
4042 
4043 	return 0;
4044 }
4045 
4046 /*
4047  * Function to set/get image stablization statistics
4048  */
4049 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
4050 			     struct atomisp_dis_statistics *stats)
4051 {
4052 	struct atomisp_device *isp = asd->isp;
4053 	struct atomisp_dis_buf *dis_buf;
4054 	unsigned long flags;
4055 
4056 	if (!asd->params.dvs_stat->hor_prod.odd_real ||
4057 	    !asd->params.dvs_stat->hor_prod.odd_imag ||
4058 	    !asd->params.dvs_stat->hor_prod.even_real ||
4059 	    !asd->params.dvs_stat->hor_prod.even_imag ||
4060 	    !asd->params.dvs_stat->ver_prod.odd_real ||
4061 	    !asd->params.dvs_stat->ver_prod.odd_imag ||
4062 	    !asd->params.dvs_stat->ver_prod.even_real ||
4063 	    !asd->params.dvs_stat->ver_prod.even_imag)
4064 		return -EINVAL;
4065 
4066 	/* isp needs to be streaming to get DIS statistics */
4067 	spin_lock_irqsave(&isp->lock, flags);
4068 	if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) {
4069 		spin_unlock_irqrestore(&isp->lock, flags);
4070 		return -EINVAL;
4071 	}
4072 	spin_unlock_irqrestore(&isp->lock, flags);
4073 
4074 	if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
4075 		/* If the grid info in the argument differs from the current
4076 		   grid info, we tell the caller to reset the grid size and
4077 		   try again. */
4078 		return -EAGAIN;
4079 
4080 	spin_lock_irqsave(&asd->dis_stats_lock, flags);
4081 	if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
4082 		spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4083 		dev_err(isp->dev, "dis statistics is not valid.\n");
4084 		return -EAGAIN;
4085 	}
4086 
4087 	dis_buf = list_entry(asd->dis_stats.next,
4088 			     struct atomisp_dis_buf, list);
4089 	list_del_init(&dis_buf->list);
4090 	spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4091 
4092 	if (dis_buf->dvs_map)
4093 		ia_css_translate_dvs2_statistics(
4094 		    asd->params.dvs_stat, dis_buf->dvs_map);
4095 	else
4096 		ia_css_get_dvs2_statistics(asd->params.dvs_stat,
4097 					   dis_buf->dis_data);
4098 	stats->exp_id = dis_buf->dis_data->exp_id;
4099 
4100 	spin_lock_irqsave(&asd->dis_stats_lock, flags);
4101 	list_add_tail(&dis_buf->list, &asd->dis_stats);
4102 	spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4103 
4104 	if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
4105 			 asd->params.dvs_stat->ver_prod.odd_real,
4106 			 asd->params.dvs_ver_proj_bytes))
4107 		return -EFAULT;
4108 	if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
4109 			 asd->params.dvs_stat->ver_prod.odd_imag,
4110 			 asd->params.dvs_ver_proj_bytes))
4111 		return -EFAULT;
4112 	if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
4113 			 asd->params.dvs_stat->ver_prod.even_real,
4114 			 asd->params.dvs_ver_proj_bytes))
4115 		return -EFAULT;
4116 	if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
4117 			 asd->params.dvs_stat->ver_prod.even_imag,
4118 			 asd->params.dvs_ver_proj_bytes))
4119 		return -EFAULT;
4120 	if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
4121 			 asd->params.dvs_stat->hor_prod.odd_real,
4122 			 asd->params.dvs_hor_proj_bytes))
4123 		return -EFAULT;
4124 	if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
4125 			 asd->params.dvs_stat->hor_prod.odd_imag,
4126 			 asd->params.dvs_hor_proj_bytes))
4127 		return -EFAULT;
4128 	if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
4129 			 asd->params.dvs_stat->hor_prod.even_real,
4130 			 asd->params.dvs_hor_proj_bytes))
4131 		return -EFAULT;
4132 	if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
4133 			 asd->params.dvs_stat->hor_prod.even_imag,
4134 			 asd->params.dvs_hor_proj_bytes))
4135 		return -EFAULT;
4136 
4137 	return 0;
4138 }
4139 
4140 struct ia_css_shading_table *atomisp_css_shading_table_alloc(
4141     unsigned int width, unsigned int height)
4142 {
4143 	return ia_css_shading_table_alloc(width, height);
4144 }
4145 
4146 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
4147 				   struct ia_css_shading_table *table)
4148 {
4149 	asd->params.config.shading_table = table;
4150 }
4151 
4152 void atomisp_css_shading_table_free(struct ia_css_shading_table *table)
4153 {
4154 	ia_css_shading_table_free(table);
4155 }
4156 
4157 struct ia_css_morph_table *atomisp_css_morph_table_allocate(
4158     unsigned int width, unsigned int height)
4159 {
4160 	return ia_css_morph_table_allocate(width, height);
4161 }
4162 
4163 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
4164 				 struct ia_css_morph_table *table)
4165 {
4166 	asd->params.config.morph_table = table;
4167 }
4168 
4169 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
4170 				 struct ia_css_morph_table *table)
4171 {
4172 	struct ia_css_isp_config isp_config;
4173 	struct atomisp_device *isp = asd->isp;
4174 
4175 	if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4176 		dev_err(isp->dev,
4177 			"%s called after streamoff, skipping.\n", __func__);
4178 		return;
4179 	}
4180 	memset(table, 0, sizeof(struct ia_css_morph_table));
4181 	memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4182 	isp_config.morph_table = table;
4183 	ia_css_stream_get_isp_config(
4184 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4185 	    &isp_config);
4186 }
4187 
4188 void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
4189 {
4190 	ia_css_morph_table_free(table);
4191 }
4192 
4193 void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp,
4194 	unsigned int overlap)
4195 {
4196 	/* CSS 2.0 doesn't support this API. */
4197 	dev_dbg(isp->dev, "set cont prev start time is not supported.\n");
4198 	return;
4199 }
4200 
4201 void atomisp_css_acc_done(struct atomisp_sub_device *asd)
4202 {
4203 	complete(&asd->acc.acc_done);
4204 }
4205 
4206 int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd)
4207 {
4208 	int ret = 0;
4209 	struct atomisp_device *isp = asd->isp;
4210 
4211 	/* Unlock the isp mutex taken in IOCTL handler before sleeping! */
4212 	rt_mutex_unlock(&isp->mutex);
4213 	if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done,
4214 		ATOMISP_ISP_TIMEOUT_DURATION) == 0) {
4215 		dev_err(isp->dev, "<%s: completion timeout\n", __func__);
4216 		atomisp_css_debug_dump_sp_sw_debug_info();
4217 		atomisp_css_debug_dump_debug_info(__func__);
4218 		ret = -EIO;
4219 	}
4220 	rt_mutex_lock(&isp->mutex);
4221 
4222 	return ret;
4223 }
4224 
4225 /* Set the ACC binary arguments */
4226 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw)
4227 {
4228 	unsigned int mem;
4229 
4230 	for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) {
4231 		if (acc_fw->args[mem].length == 0)
4232 			continue;
4233 
4234 		ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers,
4235 						  IA_CSS_PARAM_CLASS_PARAM, mem,
4236 						  acc_fw->args[mem].css_ptr,
4237 						  acc_fw->args[mem].length);
4238 	}
4239 
4240 	return 0;
4241 }
4242 
4243 /* Load acc binary extension */
4244 int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd,
4245 				   struct ia_css_fw_info *fw,
4246 				   enum ia_css_pipe_id pipe_id,
4247 				   unsigned int type)
4248 {
4249 	struct ia_css_fw_info **hd;
4250 
4251 	fw->next = NULL;
4252 	hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4253 	       .pipe_configs[pipe_id].acc_extension);
4254 	while (*hd)
4255 		hd = &(*hd)->next;
4256 	*hd = fw;
4257 
4258 	asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4259 	.update_pipe[pipe_id] = true;
4260 	return 0;
4261 }
4262 
4263 /* Unload acc binary extension */
4264 void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd,
4265 				      struct ia_css_fw_info *fw,
4266 				      enum ia_css_pipe_id pipe_id)
4267 {
4268 	struct ia_css_fw_info **hd;
4269 
4270 	hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4271 	       .pipe_configs[pipe_id].acc_extension);
4272 	while (*hd && *hd != fw)
4273 		hd = &(*hd)->next;
4274 	if (!*hd) {
4275 		dev_err(asd->isp->dev, "did not find acc fw for removal\n");
4276 		return;
4277 	}
4278 	*hd = fw->next;
4279 	fw->next = NULL;
4280 
4281 	asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4282 	.update_pipe[pipe_id] = true;
4283 }
4284 
4285 int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd)
4286 {
4287 	struct atomisp_device *isp = asd->isp;
4288 	struct ia_css_pipe_config *pipe_config;
4289 	struct atomisp_stream_env *stream_env =
4290 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4291 
4292 	if (stream_env->acc_stream) {
4293 		if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4294 			if (ia_css_stream_stop(stream_env->acc_stream)
4295 			    != IA_CSS_SUCCESS) {
4296 				dev_err(isp->dev, "stop acc_stream failed.\n");
4297 				return -EBUSY;
4298 			}
4299 		}
4300 
4301 		if (ia_css_stream_destroy(stream_env->acc_stream)
4302 		    != IA_CSS_SUCCESS) {
4303 			dev_err(isp->dev, "destroy acc_stream failed.\n");
4304 			return -EBUSY;
4305 		}
4306 		stream_env->acc_stream = NULL;
4307 	}
4308 
4309 	pipe_config = &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
4310 	ia_css_pipe_config_defaults(pipe_config);
4311 	asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES *
4312 				      sizeof(void *), GFP_KERNEL);
4313 	if (!asd->acc.acc_stages)
4314 		return -ENOMEM;
4315 	pipe_config->acc_stages = asd->acc.acc_stages;
4316 	pipe_config->mode = IA_CSS_PIPE_MODE_ACC;
4317 	pipe_config->num_acc_stages = 0;
4318 
4319 	/*
4320 	 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe,
4321 	 * because pipe configuration will soon be changed by
4322 	 * atomisp_css_load_acc_binary()
4323 	 */
4324 	return 0;
4325 }
4326 
4327 int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd)
4328 {
4329 	struct atomisp_device *isp = asd->isp;
4330 	struct atomisp_stream_env *stream_env =
4331 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4332 	struct ia_css_pipe_config *pipe_config =
4333 		    &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
4334 
4335 	if (ia_css_pipe_create(pipe_config,
4336 			       &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != IA_CSS_SUCCESS) {
4337 		dev_err(isp->dev, "%s: ia_css_pipe_create failed\n",
4338 			__func__);
4339 		return -EBADE;
4340 	}
4341 
4342 	memset(&stream_env->acc_stream_config, 0,
4343 	       sizeof(struct ia_css_stream_config));
4344 	if (ia_css_stream_create(&stream_env->acc_stream_config, 1,
4345 				 &stream_env->pipes[IA_CSS_PIPE_ID_ACC],
4346 				 &stream_env->acc_stream) != IA_CSS_SUCCESS) {
4347 		dev_err(isp->dev, "%s: create acc_stream error.\n", __func__);
4348 		return -EINVAL;
4349 	}
4350 	stream_env->acc_stream_state = CSS_STREAM_CREATED;
4351 
4352 	init_completion(&asd->acc.acc_done);
4353 	asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC];
4354 
4355 	atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
4356 
4357 	if (ia_css_start_sp() != IA_CSS_SUCCESS) {
4358 		dev_err(isp->dev, "start sp error.\n");
4359 		return -EIO;
4360 	}
4361 
4362 	if (ia_css_stream_start(stream_env->acc_stream)
4363 	    != IA_CSS_SUCCESS) {
4364 		dev_err(isp->dev, "acc_stream start error.\n");
4365 		return -EIO;
4366 	}
4367 
4368 	stream_env->acc_stream_state = CSS_STREAM_STARTED;
4369 	return 0;
4370 }
4371 
4372 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd)
4373 {
4374 	struct atomisp_stream_env *stream_env =
4375 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4376 	if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4377 		ia_css_stream_stop(stream_env->acc_stream);
4378 		stream_env->acc_stream_state = CSS_STREAM_STOPPED;
4379 	}
4380 	return 0;
4381 }
4382 
4383 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd)
4384 {
4385 	struct atomisp_stream_env *stream_env =
4386 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4387 	if (stream_env->acc_stream) {
4388 		if (ia_css_stream_destroy(stream_env->acc_stream)
4389 		    != IA_CSS_SUCCESS)
4390 			dev_warn(asd->isp->dev,
4391 				 "destroy acc_stream failed.\n");
4392 		stream_env->acc_stream = NULL;
4393 	}
4394 
4395 	if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) {
4396 		if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC])
4397 		    != IA_CSS_SUCCESS)
4398 			dev_warn(asd->isp->dev,
4399 				 "destroy ACC pipe failed.\n");
4400 		stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL;
4401 		stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false;
4402 		ia_css_pipe_config_defaults(
4403 		    &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]);
4404 		ia_css_pipe_extra_config_defaults(
4405 		    &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]);
4406 	}
4407 	asd->acc.pipeline = NULL;
4408 
4409 	/* css 2.0 API limitation: ia_css_stop_sp() could be only called after
4410 	 * destroy all pipes
4411 	 */
4412 	ia_css_stop_sp();
4413 
4414 	kfree(asd->acc.acc_stages);
4415 	asd->acc.acc_stages = NULL;
4416 
4417 	atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false);
4418 }
4419 
4420 int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd,
4421 				struct ia_css_fw_info *fw,
4422 				unsigned int index)
4423 {
4424 	struct ia_css_pipe_config *pipe_config =
4425 		    &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4426 		    .pipe_configs[IA_CSS_PIPE_ID_ACC];
4427 
4428 	if (index >= MAX_ACC_STAGES) {
4429 		dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n",
4430 			__func__, index);
4431 		return -ENOMEM;
4432 	}
4433 
4434 	pipe_config->acc_stages[index] = fw;
4435 	pipe_config->num_acc_stages = index + 1;
4436 	pipe_config->acc_num_execs = 1;
4437 
4438 	return 0;
4439 }
4440 
4441 static struct atomisp_sub_device *__get_atomisp_subdev(
4442     struct ia_css_pipe *css_pipe,
4443     struct atomisp_device *isp,
4444     enum atomisp_input_stream_id *stream_id)
4445 {
4446 	int i, j, k;
4447 	struct atomisp_sub_device *asd;
4448 	struct atomisp_stream_env *stream_env;
4449 
4450 	for (i = 0; i < isp->num_of_streams; i++) {
4451 		asd = &isp->asd[i];
4452 		if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED &&
4453 		    !asd->acc.pipeline)
4454 			continue;
4455 		for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4456 			stream_env = &asd->stream_env[j];
4457 			for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
4458 				if (stream_env->pipes[k] &&
4459 				    stream_env->pipes[k] == css_pipe) {
4460 					*stream_id = j;
4461 					return asd;
4462 				}
4463 			}
4464 		}
4465 	}
4466 
4467 	return NULL;
4468 }
4469 
4470 int atomisp_css_isr_thread(struct atomisp_device *isp,
4471 			   bool *frame_done_found,
4472 			   bool *css_pipe_done)
4473 {
4474 	enum atomisp_input_stream_id stream_id = 0;
4475 	struct atomisp_css_event current_event;
4476 	struct atomisp_sub_device *asd;
4477 	bool reset_wdt_timer[MAX_STREAM_NUM] = {false};
4478 	int i;
4479 
4480 	while (!atomisp_css_dequeue_event(&current_event)) {
4481 		if (current_event.event.type ==
4482 		    IA_CSS_EVENT_TYPE_FW_ASSERT) {
4483 			/*
4484 			 * Received FW assertion signal,
4485 			 * trigger WDT to recover
4486 			 */
4487 			dev_err(isp->dev,
4488 				"%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
4489 				__func__,
4490 				current_event.event.fw_assert_module_id,
4491 				current_event.event.fw_assert_line_no);
4492 			for (i = 0; i < isp->num_of_streams; i++)
4493 				atomisp_wdt_stop(&isp->asd[i], 0);
4494 
4495 			if (!atomisp_hw_is_isp2401)
4496 				atomisp_wdt(&isp->asd[0].wdt);
4497 			else
4498 				queue_work(isp->wdt_work_queue, &isp->wdt_work);
4499 
4500 			return -EINVAL;
4501 		} else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4502 			dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
4503 				 __func__, current_event.event.fw_warning,
4504 				 current_event.event.exp_id);
4505 			continue;
4506 		}
4507 
4508 		asd = __get_atomisp_subdev(current_event.event.pipe,
4509 					   isp, &stream_id);
4510 		if (!asd) {
4511 			if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
4512 				dev_dbg(isp->dev,
4513 					"event: Timer event.");
4514 			else
4515 				dev_warn(isp->dev, "%s:no subdev.event:%d",
4516 					 __func__,
4517 					 current_event.event.type);
4518 			continue;
4519 		}
4520 
4521 		atomisp_css_temp_pipe_to_pipe_id(asd, &current_event);
4522 		switch (current_event.event.type) {
4523 		case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
4524 			frame_done_found[asd->index] = true;
4525 			atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
4526 					 current_event.pipe, true, stream_id);
4527 
4528 			if (!atomisp_hw_is_isp2401)
4529 				reset_wdt_timer[asd->index] = true; /* ISP running */
4530 
4531 			break;
4532 		case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
4533 			frame_done_found[asd->index] = true;
4534 			atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
4535 					 current_event.pipe, true, stream_id);
4536 
4537 			if (!atomisp_hw_is_isp2401)
4538 				reset_wdt_timer[asd->index] = true; /* ISP running */
4539 
4540 			break;
4541 		case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
4542 			atomisp_buf_done(asd, 0,
4543 					 IA_CSS_BUFFER_TYPE_3A_STATISTICS,
4544 					 current_event.pipe,
4545 					 false, stream_id);
4546 			break;
4547 		case IA_CSS_EVENT_TYPE_METADATA_DONE:
4548 			atomisp_buf_done(asd, 0,
4549 					 IA_CSS_BUFFER_TYPE_METADATA,
4550 					 current_event.pipe,
4551 					 false, stream_id);
4552 			break;
4553 		case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
4554 			atomisp_buf_done(asd, 0,
4555 					 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
4556 					 current_event.pipe, true, stream_id);
4557 
4558 			if (!atomisp_hw_is_isp2401)
4559 				reset_wdt_timer[asd->index] = true; /* ISP running */
4560 
4561 			break;
4562 		case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
4563 			atomisp_buf_done(asd, 0,
4564 					 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
4565 					 current_event.pipe, true, stream_id);
4566 			if (!atomisp_hw_is_isp2401)
4567 				reset_wdt_timer[asd->index] = true; /* ISP running */
4568 
4569 			break;
4570 		case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
4571 			atomisp_buf_done(asd, 0,
4572 					 IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
4573 					 current_event.pipe,
4574 					 false, stream_id);
4575 			break;
4576 		case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
4577 			css_pipe_done[asd->index] = true;
4578 			break;
4579 		case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
4580 			atomisp_acc_done(asd, current_event.event.fw_handle);
4581 			break;
4582 		default:
4583 			dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
4584 				current_event.event.type);
4585 			break;
4586 		}
4587 	}
4588 
4589 	if (atomisp_hw_is_isp2401)
4590 		return 0;
4591 
4592 	/* ISP2400: If there are no buffers queued then delete wdt timer. */
4593 	for (i = 0; i < isp->num_of_streams; i++) {
4594 		asd = &isp->asd[i];
4595 		if (!asd)
4596 			continue;
4597 		if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
4598 			continue;
4599 		if (!atomisp_buffers_queued(asd))
4600 			atomisp_wdt_stop(asd, false);
4601 		else if (reset_wdt_timer[i])
4602 			/* SOF irq should not reset wdt timer. */
4603 			atomisp_wdt_refresh(asd,
4604 					    ATOMISP_WDT_KEEP_CURRENT_DELAY);
4605 	}
4606 
4607 	return 0;
4608 }
4609 
4610 bool atomisp_css_valid_sof(struct atomisp_device *isp)
4611 {
4612 	unsigned int i, j;
4613 
4614 	/* Loop for each css stream */
4615 	for (i = 0; i < isp->num_of_streams; i++) {
4616 		struct atomisp_sub_device *asd = &isp->asd[i];
4617 		/* Loop for each css vc stream */
4618 		for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4619 			if (asd->stream_env[j].stream &&
4620 			    asd->stream_env[j].stream_config.mode ==
4621 			    IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
4622 				return false;
4623 		}
4624 	}
4625 
4626 	return true;
4627 }
4628 
4629 int atomisp_css_debug_dump_isp_binary(void)
4630 {
4631 	ia_css_debug_dump_isp_binary();
4632 	return 0;
4633 }
4634 
4635 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
4636 {
4637 	sh_css_dump_sp_raw_copy_linecount(reduced);
4638 	return 0;
4639 }
4640 
4641 int atomisp_css_dump_blob_infor(void)
4642 {
4643 	struct ia_css_blob_descr *bd = sh_css_blob_info;
4644 	unsigned int i, nm = sh_css_num_binaries;
4645 
4646 	if (nm == 0)
4647 		return -EPERM;
4648 	if (!bd)
4649 		return -EPERM;
4650 
4651 	for (i = 1; i < sh_css_num_binaries; i++)
4652 		dev_dbg(atomisp_dev, "Num%d binary id is %d, name is %s\n", i,
4653 			bd[i - 1].header.info.isp.sp.id, bd[i - 1].name);
4654 
4655 	return 0;
4656 }
4657 
4658 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
4659 				   uint32_t isp_config_id)
4660 {
4661 	asd->params.config.isp_config_id = isp_config_id;
4662 }
4663 
4664 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
4665 	struct ia_css_frame *output_frame)
4666 {
4667 	asd->params.config.output_frame = output_frame;
4668 }
4669 
4670 int atomisp_get_css_dbgfunc(void)
4671 {
4672 	return dbg_func;
4673 }
4674 
4675 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
4676 {
4677 	int ret;
4678 
4679 	ret = __set_css_print_env(isp, opt);
4680 	if (ret == 0)
4681 		dbg_func = opt;
4682 
4683 	return ret;
4684 }
4685 
4686 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
4687 {
4688 	ia_css_en_dz_capt_pipe(
4689 	    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4690 	    enable);
4691 }
4692 
4693 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
4694     struct ia_css_grid_info *grid_info)
4695 {
4696 	if (!grid_info)
4697 		return NULL;
4698 
4699 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
4700 	return &grid_info->dvs_grid.dvs_grid_info;
4701 #else
4702 	return &grid_info->dvs_grid;
4703 #endif
4704 }
4705