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