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