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