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