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