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