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