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