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