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