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