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