]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/staging/media/atomisp/pci/atomisp2/atomisp_compat_css20.c
staging/atomisp: Add support for the Intel IPU v2
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / media / atomisp / pci / atomisp2 / atomisp_compat_css20.c
1 /*
2 * Support for Clovertrail PNW Camera Imaging ISP subsystem.
3 *
4 * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
19 *
20 */
21
22 #include <media/videobuf-vmalloc.h>
23 #include <media/v4l2-dev.h>
24 #include <media/v4l2-event.h>
25
26 #include "mmu/isp_mmu.h"
27 #include "mmu/sh_mmu_mrfld.h"
28 #include "hmm/hmm_bo.h"
29 #include "hmm/hmm.h"
30
31 #include "atomisp_compat.h"
32 #include "atomisp_internal.h"
33 #include "atomisp_cmd.h"
34 #include "atomisp-regs.h"
35 #include "atomisp_fops.h"
36 #include "atomisp_ioctl.h"
37 #include "atomisp_acc.h"
38
39 #include "hrt/hive_isp_css_mm_hrt.h"
40
41 #include <asm/intel-mid.h>
42
43 #include "ia_css_debug.h"
44 #include "ia_css_isp_param.h"
45 #include "sh_css_hrt.h"
46 #include "ia_css_isys.h"
47
48 #include <linux/pm_runtime.h>
49
50 /* Assume max number of ACC stages */
51 #define MAX_ACC_STAGES 20
52
53 /* Ideally, this should come from CSS headers */
54 #define NO_LINK -1
55
56 /*
57 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
58 * #4684168, if concurrency access happened, system may hard hang.
59 */
60 static DEFINE_SPINLOCK(mmio_lock);
61
62 enum frame_info_type {
63 ATOMISP_CSS_VF_FRAME,
64 ATOMISP_CSS_SECOND_VF_FRAME,
65 ATOMISP_CSS_OUTPUT_FRAME,
66 ATOMISP_CSS_SECOND_OUTPUT_FRAME,
67 ATOMISP_CSS_RAW_FRAME,
68 };
69
70 struct bayer_ds_factor {
71 unsigned int numerator;
72 unsigned int denominator;
73 };
74
75 void atomisp_css_debug_dump_sp_sw_debug_info(void)
76 {
77 ia_css_debug_dump_sp_sw_debug_info();
78 }
79
80 void atomisp_css_debug_dump_debug_info(const char *context)
81 {
82 ia_css_debug_dump_debug_info(context);
83 }
84
85 void atomisp_css_debug_set_dtrace_level(const unsigned int trace_level)
86 {
87 ia_css_debug_set_dtrace_level(trace_level);
88 }
89
90 unsigned int atomisp_css_debug_get_dtrace_level(void)
91 {
92 return ia_css_debug_trace_level;
93 }
94
95 static ia_css_ptr atomisp_css2_mm_alloc(size_t bytes, uint32_t attr)
96 {
97 if (attr & IA_CSS_MEM_ATTR_ZEROED) {
98 if (attr & IA_CSS_MEM_ATTR_CACHED) {
99 if (attr & IA_CSS_MEM_ATTR_CONTIGUOUS)
100 return (ia_css_ptr) hrt_isp_css_mm_calloc_contiguous(bytes);
101 else
102 return (ia_css_ptr) hrt_isp_css_mm_calloc_cached(bytes);
103 } else {
104 if (attr & IA_CSS_MEM_ATTR_CONTIGUOUS)
105 return (ia_css_ptr) hrt_isp_css_mm_calloc_contiguous(bytes);
106 else
107 return (ia_css_ptr) hrt_isp_css_mm_calloc(bytes);
108 }
109 } else {
110 if (attr & IA_CSS_MEM_ATTR_CACHED) {
111 if (attr & IA_CSS_MEM_ATTR_CONTIGUOUS)
112 return (ia_css_ptr) hrt_isp_css_mm_alloc_contiguous(bytes);
113 else
114 return (ia_css_ptr) hrt_isp_css_mm_alloc_cached(bytes);
115 } else {
116 if (attr & IA_CSS_MEM_ATTR_CONTIGUOUS)
117 return (ia_css_ptr) hrt_isp_css_mm_alloc_contiguous(bytes);
118 else
119 return (ia_css_ptr) hrt_isp_css_mm_alloc(bytes);
120 }
121 }
122 }
123
124 static void atomisp_css2_mm_free(ia_css_ptr ptr)
125 {
126 hrt_isp_css_mm_free(ptr);
127 }
128
129 static int atomisp_css2_mm_load(ia_css_ptr ptr, void *data, size_t bytes)
130 {
131 return hrt_isp_css_mm_load(ptr, data, bytes);
132 }
133
134 static int atomisp_css2_mm_store(ia_css_ptr ptr, const void *data, size_t bytes)
135 {
136 return hrt_isp_css_mm_store(ptr, data, bytes);
137 }
138
139 static int atomisp_css2_mm_set(ia_css_ptr ptr, int c, size_t bytes)
140 {
141 return hrt_isp_css_mm_set(ptr, c, bytes);
142 }
143
144 static ia_css_ptr atomisp_css2_mm_mmap(const void *ptr, const size_t size,
145 uint16_t attribute, void *context)
146 {
147 struct hrt_userbuffer_attr *userbuffer_attr = context;
148 return hrt_isp_css_mm_alloc_user_ptr(
149 size, (void *)ptr, userbuffer_attr->pgnr,
150 userbuffer_attr->type,
151 attribute & HRT_BUF_FLAG_CACHED);
152 }
153
154 void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
155 {
156 unsigned long flags;
157
158 spin_lock_irqsave(&mmio_lock, flags);
159 _hrt_master_port_store_8(addr, data);
160 spin_unlock_irqrestore(&mmio_lock, flags);
161 }
162
163 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
164 {
165 unsigned long flags;
166
167 spin_lock_irqsave(&mmio_lock, flags);
168 _hrt_master_port_store_16(addr, data);
169 spin_unlock_irqrestore(&mmio_lock, flags);
170 }
171
172 static void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
173 {
174 unsigned long flags;
175
176 spin_lock_irqsave(&mmio_lock, flags);
177 _hrt_master_port_store_32(addr, data);
178 spin_unlock_irqrestore(&mmio_lock, flags);
179 }
180
181 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
182 {
183 unsigned long flags;
184 uint8_t ret;
185
186 spin_lock_irqsave(&mmio_lock, flags);
187 ret = _hrt_master_port_load_8(addr);
188 spin_unlock_irqrestore(&mmio_lock, flags);
189 return ret;
190 }
191
192 uint16_t atomisp_css2_hw_load_16(hrt_address addr)
193 {
194 unsigned long flags;
195 uint16_t ret;
196
197 spin_lock_irqsave(&mmio_lock, flags);
198 ret = _hrt_master_port_load_16(addr);
199 spin_unlock_irqrestore(&mmio_lock, flags);
200 return ret;
201 }
202 uint32_t atomisp_css2_hw_load_32(hrt_address addr)
203 {
204 unsigned long flags;
205 uint32_t ret;
206
207 spin_lock_irqsave(&mmio_lock, flags);
208 ret = _hrt_master_port_load_32(addr);
209 spin_unlock_irqrestore(&mmio_lock, flags);
210 return ret;
211 }
212
213 static void atomisp_css2_hw_store(hrt_address addr,
214 const void *from, uint32_t n)
215 {
216 unsigned long flags;
217 unsigned i;
218 unsigned int _to = (unsigned int)addr;
219 const char *_from = (const char *)from;
220
221 spin_lock_irqsave(&mmio_lock, flags);
222 for (i = 0; i < n; i++, _to++, _from++)
223 _hrt_master_port_store_8(_to , *_from);
224 spin_unlock_irqrestore(&mmio_lock, flags);
225 }
226
227 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
228 {
229 unsigned long flags;
230 unsigned i;
231 char *_to = (char *)to;
232 unsigned int _from = (unsigned int)addr;
233
234 spin_lock_irqsave(&mmio_lock, flags);
235 for (i = 0; i < n; i++, _to++, _from++)
236 *_to = _hrt_master_port_load_8(_from);
237 spin_unlock_irqrestore(&mmio_lock, flags);
238 }
239
240 static int atomisp_css2_dbg_print(const char *fmt, va_list args)
241 {
242 vprintk(fmt, args);
243 return 0;
244 }
245
246 static int atomisp_css2_dbg_ftrace_print(const char *fmt, va_list args)
247 {
248 ftrace_vprintk(fmt, args);
249 return 0;
250 }
251
252 static int atomisp_css2_err_print(const char *fmt, va_list args)
253 {
254 vprintk(fmt, args);
255 return 0;
256 }
257
258 void atomisp_store_uint32(hrt_address addr, uint32_t data)
259 {
260 atomisp_css2_hw_store_32(addr, data);
261 }
262
263 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
264 {
265 *data = atomisp_css2_hw_load_32(addr);
266 }
267 static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr)
268 {
269 if (sh_mmu_mrfld.get_pd_base == NULL) {
270 dev_err(atomisp_dev, "get mmu base address failed.\n");
271 return -EINVAL;
272 }
273
274 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
275 bo_device.mmu.base_address);
276 return 0;
277 }
278
279 static void atomisp_isp_parameters_clean_up(
280 struct atomisp_css_isp_config *config)
281 {
282 /*
283 * Set NULL to configs pointer to avoid they are set into isp again when
284 * some configs are changed and need to be updated later.
285 */
286 memset(config, 0, sizeof(*config));
287 }
288
289 static void __dump_pipe_config(struct atomisp_sub_device *asd,
290 struct atomisp_stream_env *stream_env,
291 unsigned int pipe_id)
292 {
293 struct atomisp_device *isp = asd->isp;
294 if (stream_env->pipes[pipe_id]) {
295 struct ia_css_pipe_config *p_config;
296 struct ia_css_pipe_extra_config *pe_config;
297 p_config = &stream_env->pipe_configs[pipe_id];
298 pe_config = &stream_env->pipe_extra_configs[pipe_id];
299 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
300 dev_dbg(isp->dev,
301 "pipe_config.pipe_mode:%d.\n", p_config->mode);
302 dev_dbg(isp->dev,
303 "pipe_config.output_info[0] w=%d, h=%d.\n",
304 p_config->output_info[0].res.width,
305 p_config->output_info[0].res.height);
306 dev_dbg(isp->dev,
307 "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
308 p_config->vf_pp_in_res.width,
309 p_config->vf_pp_in_res.height);
310 dev_dbg(isp->dev,
311 "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
312 p_config->capt_pp_in_res.width,
313 p_config->capt_pp_in_res.height);
314 dev_dbg(isp->dev,
315 "pipe_config.output.padded w=%d.\n",
316 p_config->output_info[0].padded_width);
317 dev_dbg(isp->dev,
318 "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
319 p_config->vf_output_info[0].res.width,
320 p_config->vf_output_info[0].res.height);
321 dev_dbg(isp->dev,
322 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
323 p_config->bayer_ds_out_res.width,
324 p_config->bayer_ds_out_res.height);
325 dev_dbg(isp->dev,
326 "pipe_config.envelope w=%d, h=%d.\n",
327 p_config->dvs_envelope.width,
328 p_config->dvs_envelope.height);
329 dev_dbg(isp->dev,
330 "pipe_config.dvs_frame_delay=%d.\n",
331 p_config->dvs_frame_delay);
332 dev_dbg(isp->dev,
333 "pipe_config.isp_pipe_version:%d.\n",
334 p_config->isp_pipe_version);
335 dev_dbg(isp->dev,
336 "pipe_config.acc_extension=%p.\n",
337 p_config->acc_extension);
338 dev_dbg(isp->dev,
339 "pipe_config.acc_stages=%p.\n",
340 p_config->acc_stages);
341 dev_dbg(isp->dev,
342 "pipe_config.num_acc_stages=%d.\n",
343 p_config->num_acc_stages);
344 dev_dbg(isp->dev,
345 "pipe_config.acc_num_execs=%d.\n",
346 p_config->acc_num_execs);
347 dev_dbg(isp->dev,
348 "pipe_config.default_capture_config.capture_mode=%d.\n",
349 p_config->default_capture_config.mode);
350 dev_dbg(isp->dev,
351 "pipe_config.enable_dz=%d.\n",
352 p_config->enable_dz);
353 dev_dbg(isp->dev,
354 "pipe_config.default_capture_config.enable_xnr=%d.\n",
355 p_config->default_capture_config.enable_xnr);
356 dev_dbg(isp->dev,
357 "dumping pipe[%d] extra config:\n", pipe_id);
358 dev_dbg(isp->dev,
359 "pipe_extra_config.enable_raw_binning:%d.\n",
360 pe_config->enable_raw_binning);
361 dev_dbg(isp->dev,
362 "pipe_extra_config.enable_yuv_ds:%d.\n",
363 pe_config->enable_yuv_ds);
364 dev_dbg(isp->dev,
365 "pipe_extra_config.enable_high_speed:%d.\n",
366 pe_config->enable_high_speed);
367 dev_dbg(isp->dev,
368 "pipe_extra_config.enable_dvs_6axis:%d.\n",
369 pe_config->enable_dvs_6axis);
370 dev_dbg(isp->dev,
371 "pipe_extra_config.enable_reduced_pipe:%d.\n",
372 pe_config->enable_reduced_pipe);
373 dev_dbg(isp->dev,
374 "pipe_(extra_)config.enable_dz:%d.\n",
375 p_config->enable_dz);
376 dev_dbg(isp->dev,
377 "pipe_extra_config.disable_vf_pp:%d.\n",
378 pe_config->disable_vf_pp);
379 }
380 }
381
382 static void __dump_stream_config(struct atomisp_sub_device *asd,
383 struct atomisp_stream_env *stream_env)
384 {
385 struct atomisp_device *isp = asd->isp;
386 struct ia_css_stream_config *s_config;
387 int j;
388 bool valid_stream = false;
389
390 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
391 if (stream_env->pipes[j]) {
392 __dump_pipe_config(asd, stream_env, j);
393 valid_stream = true;
394 }
395 }
396 if (!valid_stream)
397 return;
398 s_config = &stream_env->stream_config;
399 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
400
401 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
402 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
403 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
404 s_config->source.port.port);
405 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
406 s_config->source.port.num_lanes);
407 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
408 s_config->source.port.timeout);
409 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
410 s_config->source.port.rxcount);
411 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
412 s_config->source.port.compression.type);
413 dev_dbg(isp->dev, "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
414 s_config->source.port.compression.
415 compressed_bits_per_pixel);
416 dev_dbg(isp->dev, "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
417 s_config->source.port.compression.
418 uncompressed_bits_per_pixel);
419 } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
420 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
421 s_config->source.tpg.id);
422 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
423 s_config->source.tpg.mode);
424 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
425 s_config->source.tpg.x_mask);
426 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
427 s_config->source.tpg.x_delta);
428 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
429 s_config->source.tpg.y_mask);
430 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
431 s_config->source.tpg.y_delta);
432 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
433 s_config->source.tpg.xy_mask);
434 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
435 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
436 s_config->source.prbs.id);
437 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
438 s_config->source.prbs.h_blank);
439 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
440 s_config->source.prbs.v_blank);
441 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
442 s_config->source.prbs.seed);
443 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
444 s_config->source.prbs.seed1);
445 }
446
447 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
448 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
449 j,
450 s_config->isys_config[j].input_res.width,
451 s_config->isys_config[j].input_res.height);
452
453 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
454 j,
455 s_config->isys_config[j].linked_isys_stream_id);
456
457 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
458 j,
459 s_config->isys_config[j].format);
460
461 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
462 j,
463 s_config->isys_config[j].valid);
464 }
465
466 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
467 s_config->input_config.input_res.width,
468 s_config->input_config.input_res.height);
469
470 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
471 s_config->input_config.effective_res.width,
472 s_config->input_config.effective_res.height);
473
474 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
475 s_config->input_config.format);
476
477 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
478 s_config->input_config.bayer_order);
479
480 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
481 s_config->pixels_per_clock);
482 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
483 dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
484 s_config->continuous);
485 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
486 s_config->disable_cont_viewfinder);
487 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
488 s_config->channel_id);
489 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
490 s_config->init_num_cont_raw_buf);
491 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
492 s_config->target_num_cont_raw_buf);
493 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
494 s_config->left_padding);
495 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
496 s_config->sensor_binning_factor);
497 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
498 s_config->pixels_per_clock);
499 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
500 s_config->pack_raw_pixels);
501 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
502 s_config->flash_gpio_pin);
503 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
504 s_config->mipi_buffer_config.size_mem_words);
505 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
506 s_config->mipi_buffer_config.contiguous);
507 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
508 s_config->metadata_config.data_type);
509 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
510 s_config->metadata_config.resolution.width,
511 s_config->metadata_config.resolution.height);
512 }
513
514 static int __destroy_stream(struct atomisp_sub_device *asd,
515 struct atomisp_stream_env *stream_env, bool force)
516 {
517 struct atomisp_device *isp = asd->isp;
518 int i;
519 unsigned long timeout;
520
521 if (!stream_env->stream)
522 return 0;
523
524 if (!force) {
525 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
526 if (stream_env->update_pipe[i])
527 break;
528
529 if (i == IA_CSS_PIPE_ID_NUM)
530 return 0;
531 }
532
533 if (stream_env->stream_state == CSS_STREAM_STARTED
534 && ia_css_stream_stop(stream_env->stream) != IA_CSS_SUCCESS) {
535 dev_err(isp->dev, "stop stream failed.\n");
536 return -EINVAL;
537 }
538
539 if (stream_env->stream_state == CSS_STREAM_STARTED) {
540 timeout = jiffies + msecs_to_jiffies(40);
541 while (1) {
542 if (ia_css_stream_has_stopped(stream_env->stream))
543 break;
544
545 if (time_after(jiffies, timeout)) {
546 dev_warn(isp->dev, "stop stream timeout.\n");
547 break;
548 }
549
550 usleep_range(100, 200);
551 };
552 }
553
554 stream_env->stream_state = CSS_STREAM_STOPPED;
555
556 if (ia_css_stream_destroy(stream_env->stream) != IA_CSS_SUCCESS) {
557 dev_err(isp->dev, "destroy stream failed.\n");
558 return -EINVAL;
559 }
560 stream_env->stream_state = CSS_STREAM_UNINIT;
561 stream_env->stream = NULL;
562
563 return 0;
564 }
565
566 static int __destroy_streams(struct atomisp_sub_device *asd, bool force)
567 {
568 int ret, i;
569 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
570 ret = __destroy_stream(asd, &asd->stream_env[i], force);
571 if (ret)
572 return ret;
573 }
574 asd->stream_prepared = false;
575 return 0;
576 }
577 static int __create_stream(struct atomisp_sub_device *asd,
578 struct atomisp_stream_env *stream_env)
579 {
580 int pipe_index = 0, i;
581 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
582
583 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
584 if (stream_env->pipes[i])
585 multi_pipes[pipe_index++] = stream_env->pipes[i];
586 }
587 if (pipe_index == 0)
588 return 0;
589
590 stream_env->stream_config.target_num_cont_raw_buf =
591 asd->continuous_raw_buffer_size->val;
592 stream_env->stream_config.channel_id = stream_env->ch_id;
593 stream_env->stream_config.ia_css_enable_raw_buffer_locking =
594 asd->enable_raw_buffer_lock->val;
595
596 __dump_stream_config(asd, stream_env);
597 if (ia_css_stream_create(&stream_env->stream_config,
598 pipe_index, multi_pipes, &stream_env->stream) != IA_CSS_SUCCESS)
599 return -EINVAL;
600 if (ia_css_stream_get_info(stream_env->stream,
601 &stream_env->stream_info) != IA_CSS_SUCCESS) {
602 ia_css_stream_destroy(stream_env->stream);
603 stream_env->stream = NULL;
604 return -EINVAL;
605 }
606
607 stream_env->stream_state = CSS_STREAM_CREATED;
608 return 0;
609 }
610
611 static int __create_streams(struct atomisp_sub_device *asd)
612 {
613 int ret, i;
614
615 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
616 ret = __create_stream(asd, &asd->stream_env[i]);
617 if (ret)
618 goto rollback;
619 }
620 asd->stream_prepared = true;
621 return 0;
622 rollback:
623 for (i--; i >= 0; i--)
624 __destroy_stream(asd, &asd->stream_env[i], true);
625 return ret;
626 }
627
628 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
629 struct atomisp_stream_env *stream_env,
630 bool force)
631 {
632 struct atomisp_device *isp = asd->isp;
633 int ret = 0;
634 int i;
635 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
636 if (!stream_env->pipes[i] ||
637 !(force || stream_env->update_pipe[i]))
638 continue;
639 if (ia_css_pipe_destroy(stream_env->pipes[i])
640 != IA_CSS_SUCCESS) {
641 dev_err(isp->dev,
642 "destroy pipe[%d]failed.cannot recover.\n", i);
643 ret = -EINVAL;
644 }
645 stream_env->pipes[i] = NULL;
646 stream_env->update_pipe[i] = false;
647 }
648 return ret;
649 }
650
651 static int __destroy_pipes(struct atomisp_sub_device *asd, bool force)
652 {
653 struct atomisp_device *isp = asd->isp;
654 int i;
655 int ret = 0;
656
657 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
658 if (asd->stream_env[i].stream) {
659
660 dev_err(isp->dev,
661 "cannot destroy css pipes for stream[%d].\n",
662 i);
663 continue;
664 }
665
666 ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force);
667 if (ret)
668 return ret;
669 }
670
671 return 0;
672 }
673
674 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
675 {
676 __destroy_streams(asd, true);
677 __destroy_pipes(asd, true);
678 }
679
680 static void __apply_additional_pipe_config(
681 struct atomisp_sub_device *asd,
682 struct atomisp_stream_env *stream_env,
683 enum ia_css_pipe_id pipe_id)
684 {
685 struct atomisp_device *isp = asd->isp;
686
687 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
688 dev_err(isp->dev,
689 "wrong pipe_id for additional pipe config.\n");
690 return;
691 }
692
693 /* apply default pipe config */
694 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
695 stream_env->pipe_configs[pipe_id].enable_dz =
696 asd->disable_dz->val ? false : true;
697 /* apply isp 2.2 specific config for baytrail*/
698 switch (pipe_id) {
699 case IA_CSS_PIPE_ID_CAPTURE:
700 /* enable capture pp/dz manually or digital zoom would
701 * fail*/
702 if (stream_env->pipe_configs[pipe_id].
703 default_capture_config.mode == CSS_CAPTURE_MODE_RAW)
704 stream_env->pipe_configs[pipe_id].enable_dz = false;
705 #ifdef ISP2401
706
707 /* the isp default to use ISP2.2 and the camera hal will
708 * control whether use isp2.7 */
709 if (asd->select_isp_version->val ==
710 ATOMISP_CSS_ISP_PIPE_VERSION_2_7)
711 stream_env->pipe_configs[pipe_id].isp_pipe_version =
712 SH_CSS_ISP_PIPE_VERSION_2_7;
713 else
714 stream_env->pipe_configs[pipe_id].isp_pipe_version =
715 SH_CSS_ISP_PIPE_VERSION_2_2;
716 #endif
717 break;
718 case IA_CSS_PIPE_ID_VIDEO:
719 /* enable reduced pipe to have binary
720 * video_dz_2_min selected*/
721 stream_env->pipe_extra_configs[pipe_id]
722 .enable_reduced_pipe = true;
723 stream_env->pipe_configs[pipe_id]
724 .enable_dz = false;
725 if (ATOMISP_SOC_CAMERA(asd))
726 stream_env->pipe_configs[pipe_id].enable_dz = true;
727
728 if (asd->params.video_dis_en) {
729 stream_env->pipe_extra_configs[pipe_id]
730 .enable_dvs_6axis = true;
731 stream_env->pipe_configs[pipe_id]
732 .dvs_frame_delay =
733 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
734 }
735 break;
736 case IA_CSS_PIPE_ID_PREVIEW:
737 break;
738 case IA_CSS_PIPE_ID_YUVPP:
739 case IA_CSS_PIPE_ID_COPY:
740 if (ATOMISP_SOC_CAMERA(asd))
741 stream_env->pipe_configs[pipe_id].enable_dz = true;
742 else
743 stream_env->pipe_configs[pipe_id].enable_dz = false;
744 break;
745 case IA_CSS_PIPE_ID_ACC:
746 stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC;
747 stream_env->pipe_configs[pipe_id].enable_dz = false;
748 break;
749 default:
750 break;
751 }
752 }
753
754 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
755 enum ia_css_pipe_id pipe_id)
756 {
757 if (!asd)
758 return false;
759
760 if (pipe_id == CSS_PIPE_ID_ACC || pipe_id == CSS_PIPE_ID_YUVPP)
761 return true;
762
763 if (asd->vfpp) {
764 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
765 if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
766 return true;
767 else
768 return false;
769 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
770 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
771 return true;
772 else
773 return false;
774 }
775 }
776
777 if (!asd->run_mode)
778 return false;
779
780 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
781 return true;
782
783 switch (asd->run_mode->val) {
784 case ATOMISP_RUN_MODE_STILL_CAPTURE:
785 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
786 return true;
787 else
788 return false;
789 case ATOMISP_RUN_MODE_PREVIEW:
790 if (!asd->continuous_mode->val) {
791 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
792 return true;
793 else
794 return false;
795 }
796 /* fall through to ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE */
797 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
798 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
799 pipe_id == IA_CSS_PIPE_ID_PREVIEW)
800 return true;
801 else
802 return false;
803 case ATOMISP_RUN_MODE_VIDEO:
804 if (!asd->continuous_mode->val) {
805 if (pipe_id == IA_CSS_PIPE_ID_VIDEO ||
806 pipe_id == IA_CSS_PIPE_ID_YUVPP)
807 return true;
808 else
809 return false;
810 }
811 /* fall through to ATOMISP_RUN_MODE_SDV */
812 case ATOMISP_RUN_MODE_SDV:
813 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
814 pipe_id == IA_CSS_PIPE_ID_VIDEO)
815 return true;
816 else
817 return false;
818 }
819
820 return false;
821 }
822
823 static int __create_pipe(struct atomisp_sub_device *asd,
824 struct atomisp_stream_env *stream_env,
825 enum ia_css_pipe_id pipe_id)
826 {
827 struct atomisp_device *isp = asd->isp;
828 struct ia_css_pipe_extra_config extra_config;
829 enum ia_css_err ret;
830
831 if (pipe_id >= IA_CSS_PIPE_ID_NUM)
832 return -EINVAL;
833
834 if (pipe_id != CSS_PIPE_ID_ACC &&
835 !stream_env->pipe_configs[pipe_id].output_info[0].res.width)
836 return 0;
837
838 if (pipe_id == CSS_PIPE_ID_ACC &&
839 !stream_env->pipe_configs[pipe_id].acc_extension)
840 return 0;
841
842 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
843 return 0;
844
845 ia_css_pipe_extra_config_defaults(&extra_config);
846
847 __apply_additional_pipe_config(asd, stream_env, pipe_id);
848 if (!memcmp(&extra_config,
849 &stream_env->pipe_extra_configs[pipe_id],
850 sizeof(extra_config)))
851 ret = ia_css_pipe_create(
852 &stream_env->pipe_configs[pipe_id],
853 &stream_env->pipes[pipe_id]);
854 else
855 ret = ia_css_pipe_create_extra(
856 &stream_env->pipe_configs[pipe_id],
857 &stream_env->pipe_extra_configs[pipe_id],
858 &stream_env->pipes[pipe_id]);
859 if (ret != IA_CSS_SUCCESS)
860 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
861 return ret;
862 }
863
864 static int __create_pipes(struct atomisp_sub_device *asd)
865 {
866 enum ia_css_err ret;
867 int i, j;
868
869 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
870 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
871 ret = __create_pipe(asd, &asd->stream_env[i], j);
872 if (ret != IA_CSS_SUCCESS)
873 break;
874 }
875 if (j < IA_CSS_PIPE_ID_NUM)
876 goto pipe_err;
877 }
878 return 0;
879 pipe_err:
880 for (; i >= 0; i--) {
881 for (j--; j >= 0; j--) {
882 if (asd->stream_env[i].pipes[j]) {
883 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
884 asd->stream_env[i].pipes[j] = NULL;
885 }
886 }
887 j = IA_CSS_PIPE_ID_NUM;
888 }
889 return -EINVAL;
890 }
891
892 void atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
893 {
894 __create_pipes(asd);
895 __create_streams(asd);
896 }
897
898 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
899 {
900 int ret;
901 struct atomisp_device *isp = asd->isp;
902
903 if (__destroy_streams(asd, true) != IA_CSS_SUCCESS)
904 dev_warn(isp->dev, "destroy stream failed.\n");
905
906 if (__destroy_pipes(asd, true) != IA_CSS_SUCCESS)
907 dev_warn(isp->dev, "destroy pipe failed.\n");
908
909 ret = __create_pipes(asd);
910 if (ret != IA_CSS_SUCCESS) {
911 dev_err(isp->dev, "create pipe failed %d.\n", ret);
912 return -EIO;
913 }
914
915 ret = __create_streams(asd);
916 if (ret != IA_CSS_SUCCESS) {
917 dev_warn(isp->dev, "create stream failed %d.\n", ret);
918 __destroy_pipes(asd, true);
919 return -EIO;
920 }
921
922 return 0;
923 }
924
925 int atomisp_css_init(struct atomisp_device *isp)
926 {
927 unsigned int mmu_base_addr;
928 int ret;
929 enum ia_css_err err;
930
931 ret = hmm_get_mmu_base_addr(&mmu_base_addr);
932 if (ret)
933 return ret;
934
935 /* Init ISP */
936 err = ia_css_init(&isp->css_env.isp_css_env, NULL,
937 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
938 if (err != IA_CSS_SUCCESS) {
939 dev_err(isp->dev, "css init failed --- bad firmware?\n");
940 return -EINVAL;
941 }
942 ia_css_enable_isys_event_queue(true);
943
944 isp->css_initialized = true;
945 dev_dbg(isp->dev, "sh_css_init success\n");
946
947 return 0;
948 }
949
950 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
951 {
952 int ret = 0;
953
954 if (0 == opt)
955 isp->css_env.isp_css_env.print_env.debug_print = NULL;
956 else if (1 == opt)
957 isp->css_env.isp_css_env.print_env.debug_print =
958 atomisp_css2_dbg_ftrace_print;
959 else if (2 == opt)
960 isp->css_env.isp_css_env.print_env.debug_print =
961 atomisp_css2_dbg_print;
962 else
963 ret = -EINVAL;
964
965 return ret;
966 }
967
968 int atomisp_css_check_firmware_version(struct atomisp_device *isp)
969 {
970 if (!sh_css_check_firmware_version((void *)isp->firmware->data)) {
971 dev_err(isp->dev, "Fw version check failed.\n");
972 return -EINVAL;
973 }
974 return 0;
975 }
976
977 int atomisp_css_load_firmware(struct atomisp_device *isp)
978 {
979 enum ia_css_err err;
980
981 /* set css env */
982 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
983 isp->css_env.isp_css_fw.bytes = isp->firmware->size;
984
985 isp->css_env.isp_css_env.cpu_mem_env.alloc = atomisp_kernel_zalloc;
986 isp->css_env.isp_css_env.cpu_mem_env.free = atomisp_kernel_free;
987
988 isp->css_env.isp_css_env.css_mem_env.alloc = atomisp_css2_mm_alloc;
989 isp->css_env.isp_css_env.css_mem_env.free = atomisp_css2_mm_free;
990 isp->css_env.isp_css_env.css_mem_env.load = atomisp_css2_mm_load;
991 isp->css_env.isp_css_env.css_mem_env.store = atomisp_css2_mm_store;
992 isp->css_env.isp_css_env.css_mem_env.set = atomisp_css2_mm_set;
993 isp->css_env.isp_css_env.css_mem_env.mmap = atomisp_css2_mm_mmap;
994
995 isp->css_env.isp_css_env.hw_access_env.store_8 =
996 atomisp_css2_hw_store_8;
997 isp->css_env.isp_css_env.hw_access_env.store_16 =
998 atomisp_css2_hw_store_16;
999 isp->css_env.isp_css_env.hw_access_env.store_32 =
1000 atomisp_css2_hw_store_32;
1001
1002 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
1003 isp->css_env.isp_css_env.hw_access_env.load_16 =
1004 atomisp_css2_hw_load_16;
1005 isp->css_env.isp_css_env.hw_access_env.load_32 =
1006 atomisp_css2_hw_load_32;
1007
1008 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
1009 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
1010
1011 __set_css_print_env(isp, dbg_func);
1012
1013 isp->css_env.isp_css_env.print_env.error_print = atomisp_css2_err_print;
1014
1015 /* load isp fw into ISP memory */
1016 err = ia_css_load_firmware(&isp->css_env.isp_css_env,
1017 &isp->css_env.isp_css_fw);
1018 if (err != IA_CSS_SUCCESS) {
1019 dev_err(isp->dev, "css load fw failed.\n");
1020 return -EINVAL;
1021 }
1022
1023 return 0;
1024 }
1025
1026 void atomisp_css_unload_firmware(struct atomisp_device *isp)
1027 {
1028 ia_css_unload_firmware();
1029 }
1030
1031 void atomisp_css_uninit(struct atomisp_device *isp)
1032 {
1033 struct atomisp_sub_device *asd;
1034 unsigned int i;
1035
1036 for (i = 0; i < isp->num_of_streams; i++) {
1037 asd = &isp->asd[i];
1038 atomisp_isp_parameters_clean_up(&asd->params.config);
1039 asd->params.css_update_params_needed = false;
1040 }
1041
1042 isp->css_initialized = false;
1043 ia_css_uninit();
1044 }
1045
1046 void atomisp_css_suspend(struct atomisp_device *isp)
1047 {
1048 isp->css_initialized = false;
1049 ia_css_uninit();
1050 }
1051
1052 int atomisp_css_resume(struct atomisp_device *isp)
1053 {
1054 unsigned int mmu_base_addr;
1055 int ret;
1056
1057 ret = hmm_get_mmu_base_addr(&mmu_base_addr);
1058 if (ret) {
1059 dev_err(isp->dev, "get base address error.\n");
1060 return -EINVAL;
1061 }
1062
1063 ret = ia_css_init(&isp->css_env.isp_css_env, NULL,
1064 mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
1065 if (ret) {
1066 dev_err(isp->dev, "re-init css failed.\n");
1067 return -EINVAL;
1068 }
1069 ia_css_enable_isys_event_queue(true);
1070
1071 isp->css_initialized = true;
1072 return 0;
1073 }
1074
1075 int atomisp_css_irq_translate(struct atomisp_device *isp,
1076 unsigned int *infos)
1077 {
1078 int err;
1079
1080 err = ia_css_irq_translate(infos);
1081 if (err != IA_CSS_SUCCESS) {
1082 dev_warn(isp->dev,
1083 "%s:failed to translate irq (err = %d,infos = %d)\n",
1084 __func__, err, *infos);
1085 return -EINVAL;
1086 }
1087
1088 return 0;
1089 }
1090
1091 void atomisp_css_rx_get_irq_info(enum ia_css_csi2_port port,
1092 unsigned int *infos)
1093 {
1094 #ifndef ISP2401_NEW_INPUT_SYSTEM
1095 ia_css_isys_rx_get_irq_info(port, infos);
1096 #else
1097 *infos = 0;
1098 #endif
1099 }
1100
1101 void atomisp_css_rx_clear_irq_info(enum ia_css_csi2_port port,
1102 unsigned int infos)
1103 {
1104 #ifndef ISP2401_NEW_INPUT_SYSTEM
1105 ia_css_isys_rx_clear_irq_info(port, infos);
1106 #endif
1107 }
1108
1109 int atomisp_css_irq_enable(struct atomisp_device *isp,
1110 enum atomisp_css_irq_info info, bool enable)
1111 {
1112 if (ia_css_irq_enable(info, enable) != IA_CSS_SUCCESS) {
1113 dev_warn(isp->dev, "%s:Invalid irq info.\n", __func__);
1114 return -EINVAL;
1115 }
1116
1117 return 0;
1118 }
1119
1120 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
1121 {
1122 int i, j;
1123 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1124 asd->stream_env[i].stream = NULL;
1125 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
1126 asd->stream_env[i].pipes[j] = NULL;
1127 asd->stream_env[i].update_pipe[j] = false;
1128 ia_css_pipe_config_defaults(
1129 &asd->stream_env[i].pipe_configs[j]);
1130 ia_css_pipe_extra_config_defaults(
1131 &asd->stream_env[i].pipe_extra_configs[j]);
1132 }
1133 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
1134 }
1135 }
1136
1137 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
1138 struct videobuf_vmalloc_memory *vm_mem,
1139 enum atomisp_input_stream_id stream_id,
1140 enum atomisp_css_buffer_type css_buf_type,
1141 enum atomisp_css_pipe_id css_pipe_id)
1142 {
1143 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1144 struct ia_css_buffer css_buf = {0};
1145 enum ia_css_err err;
1146
1147 css_buf.type = css_buf_type;
1148 css_buf.data.frame = vm_mem->vaddr;
1149
1150 err = ia_css_pipe_enqueue_buffer(
1151 stream_env->pipes[css_pipe_id], &css_buf);
1152 if (err != IA_CSS_SUCCESS)
1153 return -EINVAL;
1154
1155 return 0;
1156 }
1157
1158 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
1159 struct atomisp_metadata_buf *metadata_buf,
1160 enum atomisp_input_stream_id stream_id,
1161 enum atomisp_css_pipe_id css_pipe_id)
1162 {
1163 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1164 struct ia_css_buffer buffer = {0};
1165 struct atomisp_device *isp = asd->isp;
1166
1167 buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
1168 buffer.data.metadata = metadata_buf->metadata;
1169 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
1170 &buffer)) {
1171 dev_err(isp->dev, "failed to q meta data buffer\n");
1172 return -EINVAL;
1173 }
1174
1175 return 0;
1176 }
1177
1178 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
1179 struct atomisp_s3a_buf *s3a_buf,
1180 enum atomisp_input_stream_id stream_id,
1181 enum atomisp_css_pipe_id css_pipe_id)
1182 {
1183 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1184 struct ia_css_buffer buffer = {0};
1185 struct atomisp_device *isp = asd->isp;
1186
1187 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
1188 buffer.data.stats_3a = s3a_buf->s3a_data;
1189 if (ia_css_pipe_enqueue_buffer(
1190 stream_env->pipes[css_pipe_id],
1191 &buffer)) {
1192 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
1193 return -EINVAL;
1194 }
1195
1196 return 0;
1197 }
1198
1199 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
1200 struct atomisp_dis_buf *dis_buf,
1201 enum atomisp_input_stream_id stream_id,
1202 enum atomisp_css_pipe_id css_pipe_id)
1203 {
1204 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1205 struct ia_css_buffer buffer = {0};
1206 struct atomisp_device *isp = asd->isp;
1207
1208 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
1209 buffer.data.stats_dvs = dis_buf->dis_data;
1210 if (ia_css_pipe_enqueue_buffer(
1211 stream_env->pipes[css_pipe_id],
1212 &buffer)) {
1213 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
1214 return -EINVAL;
1215 }
1216
1217 return 0;
1218 }
1219
1220 void atomisp_css_mmu_invalidate_cache(void)
1221 {
1222 ia_css_mmu_invalidate_cache();
1223 }
1224
1225 void atomisp_css_mmu_invalidate_tlb(void)
1226 {
1227 ia_css_mmu_invalidate_cache();
1228 }
1229
1230 void atomisp_css_mmu_set_page_table_base_index(unsigned long base_index)
1231 {
1232 }
1233
1234 /*
1235 * Check whether currently running MIPI buffer size fulfill
1236 * the requirement of the stream to be run
1237 */
1238 bool __need_realloc_mipi_buffer(struct atomisp_device *isp)
1239 {
1240 unsigned int i;
1241
1242 for (i = 0; i < isp->num_of_streams; i++) {
1243 struct atomisp_sub_device *asd = &isp->asd[i];
1244
1245 if (asd->streaming !=
1246 ATOMISP_DEVICE_STREAMING_ENABLED)
1247 continue;
1248 if (asd->mipi_frame_size < isp->mipi_frame_size)
1249 return true;
1250 }
1251
1252 return false;
1253 }
1254
1255 int atomisp_css_start(struct atomisp_sub_device *asd,
1256 enum atomisp_css_pipe_id pipe_id, bool in_reset)
1257 {
1258 struct atomisp_device *isp = asd->isp;
1259 bool sp_is_started = false;
1260 int ret = 0, i = 0;
1261 if (in_reset) {
1262 if (__destroy_streams(asd, true))
1263 dev_warn(isp->dev, "destroy stream failed.\n");
1264
1265 if (__destroy_pipes(asd, true))
1266 dev_warn(isp->dev, "destroy pipe failed.\n");
1267
1268 if (__create_pipes(asd)) {
1269 dev_err(isp->dev, "create pipe error.\n");
1270 return -EINVAL;
1271 }
1272 if (__create_streams(asd)) {
1273 dev_err(isp->dev, "create stream error.\n");
1274 ret = -EINVAL;
1275 goto stream_err;
1276 }
1277 /* in_reset == true, extension firmwares are reloaded after the recovery */
1278 atomisp_acc_load_extensions(asd);
1279 }
1280
1281 /*
1282 * For dual steam case, it is possible that:
1283 * 1: for this stream, it is at the stage that:
1284 * - after set_fmt is called
1285 * - before stream on is called
1286 * 2: for the other stream, the stream off is called which css reset
1287 * has been done.
1288 *
1289 * Thus the stream created in set_fmt get destroyed and need to be
1290 * recreated in the next stream on.
1291 */
1292 if (asd->stream_prepared == false) {
1293 if (__create_pipes(asd)) {
1294 dev_err(isp->dev, "create pipe error.\n");
1295 return -EINVAL;
1296 }
1297 if (__create_streams(asd)) {
1298 dev_err(isp->dev, "create stream error.\n");
1299 ret = -EINVAL;
1300 goto stream_err;
1301 }
1302 }
1303 /*
1304 * SP can only be started one time
1305 * if atomisp_subdev_streaming_count() tell there already has some
1306 * subdev at streamming, then SP should already be started previously,
1307 * so need to skip start sp procedure
1308 */
1309 if (atomisp_streaming_count(isp)) {
1310 dev_dbg(isp->dev, "skip start sp\n");
1311 } else {
1312 if (!sh_css_hrt_system_is_idle())
1313 dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1314 if (ia_css_start_sp() != IA_CSS_SUCCESS) {
1315 dev_err(isp->dev, "start sp error.\n");
1316 ret = -EINVAL;
1317 goto start_err;
1318 } else {
1319 sp_is_started = true;
1320 }
1321 }
1322
1323 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1324 if (asd->stream_env[i].stream) {
1325 if (ia_css_stream_start(asd->stream_env[i]
1326 .stream) != IA_CSS_SUCCESS) {
1327 dev_err(isp->dev, "stream[%d] start error.\n", i);
1328 ret = -EINVAL;
1329 goto start_err;
1330 } else {
1331 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1332 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1333 }
1334 }
1335 }
1336
1337 return 0;
1338
1339 start_err:
1340 __destroy_streams(asd, true);
1341 stream_err:
1342 __destroy_pipes(asd, true);
1343
1344 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1345 * destroy all pipes
1346 */
1347 /*
1348 * SP can not be stop if other streams are in use
1349 */
1350 if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1351 ia_css_stop_sp();
1352
1353 return ret;
1354 }
1355
1356 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1357 {
1358 /*
1359 * FIXME!
1360 * for ISP2401 new input system, this api is under development.
1361 * Calling it would cause kernel panic.
1362 *
1363 * VIED BZ: 1458
1364 *
1365 * Check if it is Cherry Trail and also new input system
1366 */
1367 if (asd->copy_mode) {
1368 dev_warn(asd->isp->dev,
1369 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1370 __func__);
1371 return;
1372 }
1373
1374 ia_css_stream_set_isp_config(
1375 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1376 &asd->params.config);
1377 atomisp_isp_parameters_clean_up(&asd->params.config);
1378 }
1379
1380
1381 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1382 struct ia_css_pipe *pipe)
1383 {
1384 enum ia_css_err ret;
1385
1386 if (!pipe) {
1387 atomisp_css_update_isp_params(asd);
1388 return;
1389 }
1390
1391 dev_dbg(asd->isp->dev, "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1392 __func__, asd->params.config.output_frame,
1393 asd->params.config.isp_config_id, pipe);
1394
1395 ret = ia_css_stream_set_isp_config_on_pipe(
1396 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1397 &asd->params.config, pipe);
1398 if (ret != IA_CSS_SUCCESS)
1399 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1400 __func__, ret);
1401 atomisp_isp_parameters_clean_up(&asd->params.config);
1402 }
1403
1404 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1405 enum atomisp_input_stream_id stream_id,
1406 enum atomisp_css_pipe_id pipe_id,
1407 enum atomisp_css_buffer_type buf_type,
1408 struct atomisp_css_buffer *isp_css_buffer)
1409 {
1410 if (ia_css_pipe_enqueue_buffer(
1411 asd->stream_env[stream_id].pipes[pipe_id],
1412 &isp_css_buffer->css_buffer)
1413 != IA_CSS_SUCCESS)
1414 return -EINVAL;
1415
1416 return 0;
1417 }
1418
1419 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1420 enum atomisp_input_stream_id stream_id,
1421 enum atomisp_css_pipe_id pipe_id,
1422 enum atomisp_css_buffer_type buf_type,
1423 struct atomisp_css_buffer *isp_css_buffer)
1424 {
1425 struct atomisp_device *isp = asd->isp;
1426 enum ia_css_err err;
1427
1428 err = ia_css_pipe_dequeue_buffer(
1429 asd->stream_env[stream_id].pipes[pipe_id],
1430 &isp_css_buffer->css_buffer);
1431 if (err != IA_CSS_SUCCESS) {
1432 dev_err(isp->dev,
1433 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1434 return -EINVAL;
1435 }
1436
1437 return 0;
1438 }
1439
1440 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd,
1441 uint16_t stream_id,
1442 struct atomisp_s3a_buf *s3a_buf,
1443 struct atomisp_dis_buf *dis_buf,
1444 struct atomisp_metadata_buf *md_buf)
1445 {
1446 struct atomisp_device *isp = asd->isp;
1447 struct atomisp_css_dvs_grid_info *dvs_grid_info =
1448 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1449
1450 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1451 void *s3a_ptr;
1452
1453 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1454 &asd->params.curr_grid_info.s3a_grid);
1455 if (!s3a_buf->s3a_data) {
1456 dev_err(isp->dev, "3a buf allocation failed.\n");
1457 return -EINVAL;
1458 }
1459
1460 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1461 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1462 s3a_buf->s3a_data, s3a_ptr);
1463 }
1464
1465 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1466 void *dvs_ptr;
1467
1468 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1469 dvs_grid_info);
1470 if (!dis_buf->dis_data) {
1471 dev_err(isp->dev, "dvs buf allocation failed.\n");
1472 if (s3a_buf)
1473 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1474 return -EINVAL;
1475 }
1476
1477 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1478 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1479 dis_buf->dis_data, dvs_ptr);
1480 }
1481
1482 if (asd->stream_env[stream_id].stream_info.
1483 metadata_info.size && md_buf) {
1484 md_buf->metadata = ia_css_metadata_allocate(
1485 &asd->stream_env[stream_id].stream_info.metadata_info);
1486 if (!md_buf->metadata) {
1487 if (s3a_buf)
1488 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1489 if (dis_buf)
1490 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1491 dev_err(isp->dev, "metadata buf allocation failed.\n");
1492 return -EINVAL;
1493 }
1494 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1495 }
1496
1497 return 0;
1498 }
1499
1500 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1501 {
1502 if (s3a_buf->s3a_data)
1503 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1504
1505 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1506 s3a_buf->s3a_map = NULL;
1507 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1508 }
1509
1510 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1511 {
1512 if (dis_buf->dis_data)
1513 hmm_vunmap(dis_buf->dis_data->data_ptr);
1514
1515 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1516 dis_buf->dvs_map = NULL;
1517 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1518 }
1519
1520 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1521 {
1522 if (metadata_buf->md_vptr) {
1523 hmm_vunmap(metadata_buf->metadata->address);
1524 metadata_buf->md_vptr = NULL;
1525 }
1526 ia_css_metadata_free(metadata_buf->metadata);
1527 }
1528
1529 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1530 {
1531 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1532 struct atomisp_dis_buf *dis_buf, *_dis_buf;
1533 struct atomisp_metadata_buf *md_buf, *_md_buf;
1534 struct atomisp_css_dvs_grid_info *dvs_grid_info =
1535 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1536 unsigned int i;
1537
1538 /* 3A statistics use vmalloc, DIS use kmalloc */
1539 if (dvs_grid_info && dvs_grid_info->enable) {
1540 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1541 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1542 asd->params.css_param.dvs2_coeff = NULL;
1543 asd->params.dvs_stat = NULL;
1544 asd->params.dvs_hor_proj_bytes = 0;
1545 asd->params.dvs_ver_proj_bytes = 0;
1546 asd->params.dvs_hor_coef_bytes = 0;
1547 asd->params.dvs_ver_coef_bytes = 0;
1548 asd->params.dis_proj_data_valid = false;
1549 list_for_each_entry_safe(dis_buf, _dis_buf,
1550 &asd->dis_stats, list) {
1551 atomisp_css_free_dis_buffer(dis_buf);
1552 list_del(&dis_buf->list);
1553 kfree(dis_buf);
1554 }
1555 list_for_each_entry_safe(dis_buf, _dis_buf,
1556 &asd->dis_stats_in_css, list) {
1557 atomisp_css_free_dis_buffer(dis_buf);
1558 list_del(&dis_buf->list);
1559 kfree(dis_buf);
1560 }
1561 }
1562 if (asd->params.curr_grid_info.s3a_grid.enable) {
1563 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1564 asd->params.s3a_user_stat = NULL;
1565 asd->params.s3a_output_bytes = 0;
1566 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1567 &asd->s3a_stats, list) {
1568 atomisp_css_free_3a_buffer(s3a_buf);
1569 list_del(&s3a_buf->list);
1570 kfree(s3a_buf);
1571 }
1572 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1573 &asd->s3a_stats_in_css, list) {
1574 atomisp_css_free_3a_buffer(s3a_buf);
1575 list_del(&s3a_buf->list);
1576 kfree(s3a_buf);
1577 }
1578 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1579 &asd->s3a_stats_ready, list) {
1580 atomisp_css_free_3a_buffer(s3a_buf);
1581 list_del(&s3a_buf->list);
1582 kfree(s3a_buf);
1583 }
1584 }
1585
1586 if (asd->params.css_param.dvs_6axis) {
1587 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1588 asd->params.css_param.dvs_6axis = NULL;
1589 }
1590
1591 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1592 list_for_each_entry_safe(md_buf, _md_buf,
1593 &asd->metadata[i], list) {
1594 atomisp_css_free_metadata_buffer(md_buf);
1595 list_del(&md_buf->list);
1596 kfree(md_buf);
1597 }
1598 list_for_each_entry_safe(md_buf, _md_buf,
1599 &asd->metadata_in_css[i], list) {
1600 atomisp_css_free_metadata_buffer(md_buf);
1601 list_del(&md_buf->list);
1602 kfree(md_buf);
1603 }
1604 list_for_each_entry_safe(md_buf, _md_buf,
1605 &asd->metadata_ready[i], list) {
1606 atomisp_css_free_metadata_buffer(md_buf);
1607 list_del(&md_buf->list);
1608 kfree(md_buf);
1609 }
1610 }
1611 asd->params.metadata_width_size = 0;
1612 atomisp_free_metadata_output_buf(asd);
1613 }
1614
1615 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1616 enum atomisp_css_pipe_id pipe_id,
1617 int source_pad)
1618 {
1619 struct ia_css_pipe_info p_info;
1620 struct ia_css_grid_info old_info;
1621 struct atomisp_device *isp = asd->isp;
1622 int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
1623 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1624 stream_config.metadata_config.resolution.width;
1625
1626 memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1627 memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1628
1629 if (ia_css_pipe_get_info(
1630 asd->stream_env[stream_index].pipes[pipe_id],
1631 &p_info) != IA_CSS_SUCCESS) {
1632 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1633 return -EINVAL;
1634 }
1635
1636 memcpy(&old_info, &asd->params.curr_grid_info,
1637 sizeof(struct ia_css_grid_info));
1638 memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1639 sizeof(struct ia_css_grid_info));
1640 /*
1641 * Record which css pipe enables s3a_grid.
1642 * Currently would have one css pipe that need it
1643 */
1644 if (asd->params.curr_grid_info.s3a_grid.enable) {
1645 if (asd->params.s3a_enabled_pipe != CSS_PIPE_ID_NUM)
1646 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1647 asd->params.s3a_enabled_pipe, pipe_id);
1648 asd->params.s3a_enabled_pipe = pipe_id;
1649 }
1650
1651 /* If the grid info has not changed and the buffers for 3A and
1652 * DIS statistics buffers are allocated or buffer size would be zero
1653 * then no need to do anything. */
1654 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1655 && asd->params.s3a_user_stat && asd->params.dvs_stat)
1656 || asd->params.curr_grid_info.s3a_grid.width == 0
1657 || asd->params.curr_grid_info.s3a_grid.height == 0)
1658 && asd->params.metadata_width_size == md_width) {
1659 dev_dbg(isp->dev,
1660 "grid info change escape. memcmp=%d, s3a_user_stat=%d,"
1661 "dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1662 !memcmp(&old_info, &asd->params.curr_grid_info,
1663 sizeof(old_info)),
1664 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1665 asd->params.curr_grid_info.s3a_grid.width,
1666 asd->params.curr_grid_info.s3a_grid.height,
1667 asd->params.metadata_width_size);
1668 return -EINVAL;
1669 }
1670 asd->params.metadata_width_size = md_width;
1671
1672 return 0;
1673 }
1674
1675 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1676 {
1677 if (!asd->params.curr_grid_info.s3a_grid.width ||
1678 !asd->params.curr_grid_info.s3a_grid.height)
1679 return 0;
1680
1681 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1682 &asd->params.curr_grid_info.s3a_grid);
1683 if (!asd->params.s3a_user_stat)
1684 return -ENOMEM;
1685 /* 3A statistics. These can be big, so we use vmalloc. */
1686 asd->params.s3a_output_bytes =
1687 asd->params.curr_grid_info.s3a_grid.width *
1688 asd->params.curr_grid_info.s3a_grid.height *
1689 sizeof(*asd->params.s3a_user_stat->data);
1690
1691 return 0;
1692 }
1693
1694 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1695 {
1696 struct atomisp_css_dvs_grid_info *dvs_grid =
1697 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1698
1699 if (!dvs_grid)
1700 return 0;
1701
1702 if (!dvs_grid->enable) {
1703 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1704 return 0;
1705 }
1706
1707 /* DIS coefficients. */
1708 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1709 dvs_grid);
1710 if (!asd->params.css_param.dvs2_coeff)
1711 return -ENOMEM;
1712
1713 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1714 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1715
1716 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1717 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1718
1719 /* DIS projections. */
1720 asd->params.dis_proj_data_valid = false;
1721 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1722 if (!asd->params.dvs_stat)
1723 return -ENOMEM;
1724
1725 asd->params.dvs_hor_proj_bytes =
1726 dvs_grid->aligned_height * dvs_grid->aligned_width *
1727 sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1728
1729 asd->params.dvs_ver_proj_bytes =
1730 dvs_grid->aligned_height * dvs_grid->aligned_width *
1731 sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1732
1733 return 0;
1734 }
1735
1736 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1737 {
1738 #ifndef ISP2401
1739 int i; /* Coverity CID 298003 - index var must be signed */
1740 #else
1741 int i;
1742 #endif
1743
1744 /* We allocate the cpu-side buffer used for communication with user
1745 * space */
1746 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1747 asd->params.metadata_user[i] = atomisp_kernel_malloc(
1748 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1749 stream_info.metadata_info.size);
1750 if (!asd->params.metadata_user[i]) {
1751 while (--i >= 0) {
1752 atomisp_kernel_free(asd->params.metadata_user[i]);
1753 asd->params.metadata_user[i] = NULL;
1754 }
1755 return -ENOMEM;
1756 }
1757 }
1758
1759 return 0;
1760 }
1761
1762 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1763 {
1764 unsigned int i;
1765
1766 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1767 if (asd->params.metadata_user[i]) {
1768 atomisp_kernel_free(asd->params.metadata_user[i]);
1769 asd->params.metadata_user[i] = NULL;
1770 }
1771 }
1772 }
1773
1774 void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd,
1775 struct atomisp_css_buffer *isp_css_buffer,
1776 struct ia_css_isp_dvs_statistics_map *dvs_map)
1777 {
1778 if (asd->params.dvs_stat) {
1779 if (dvs_map)
1780 ia_css_translate_dvs2_statistics(
1781 asd->params.dvs_stat, dvs_map);
1782 else
1783 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
1784 isp_css_buffer->css_buffer.data.stats_dvs);
1785
1786 }
1787 }
1788
1789 int atomisp_css_dequeue_event(struct atomisp_css_event *current_event)
1790 {
1791 if (ia_css_dequeue_event(&current_event->event) != IA_CSS_SUCCESS)
1792 return -EINVAL;
1793
1794 return 0;
1795 }
1796
1797 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1798 struct atomisp_css_event *current_event)
1799 {
1800 /*
1801 * FIXME!
1802 * Pipe ID reported in CSS event is not correct for new system's
1803 * copy pipe.
1804 * VIED BZ: 1463
1805 */
1806 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1807 &current_event->pipe);
1808 if (asd && asd->copy_mode &&
1809 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1810 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1811 }
1812
1813 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1814 enum atomisp_input_stream_id stream_id,
1815 struct v4l2_mbus_framefmt *ffmt,
1816 int isys_stream)
1817 {
1818 struct ia_css_stream_config *s_config =
1819 &asd->stream_env[stream_id].stream_config;
1820
1821 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1822 return -EINVAL;
1823
1824 s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1825 s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1826 return 0;
1827 }
1828
1829 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1830 enum atomisp_input_stream_id stream_id,
1831 struct v4l2_mbus_framefmt *ffmt)
1832 {
1833 struct ia_css_stream_config *s_config =
1834 &asd->stream_env[stream_id].stream_config;
1835
1836 s_config->input_config.input_res.width = ffmt->width;
1837 s_config->input_config.input_res.height = ffmt->height;
1838 return 0;
1839 }
1840
1841 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1842 enum atomisp_input_stream_id stream_id,
1843 unsigned int bin_factor)
1844 {
1845 asd->stream_env[stream_id]
1846 .stream_config.sensor_binning_factor = bin_factor;
1847 }
1848
1849 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1850 enum atomisp_input_stream_id stream_id,
1851 enum atomisp_css_bayer_order bayer_order)
1852 {
1853 struct ia_css_stream_config *s_config =
1854 &asd->stream_env[stream_id].stream_config;
1855 s_config->input_config.bayer_order = bayer_order;
1856 }
1857
1858 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1859 enum atomisp_input_stream_id stream_id,
1860 int link,
1861 int isys_stream)
1862 {
1863 struct ia_css_stream_config *s_config =
1864 &asd->stream_env[stream_id].stream_config;
1865
1866 s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1867 }
1868
1869 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1870 enum atomisp_input_stream_id stream_id,
1871 bool valid,
1872 int isys_stream)
1873 {
1874 struct ia_css_stream_config *s_config =
1875 &asd->stream_env[stream_id].stream_config;
1876
1877 s_config->isys_config[isys_stream].valid = valid;
1878 }
1879
1880 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1881 enum atomisp_input_stream_id stream_id,
1882 enum atomisp_css_stream_format format,
1883 int isys_stream)
1884 {
1885
1886 struct ia_css_stream_config *s_config =
1887 &asd->stream_env[stream_id].stream_config;
1888
1889 s_config->isys_config[isys_stream].format = format;
1890 }
1891
1892 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1893 enum atomisp_input_stream_id stream_id,
1894 enum atomisp_css_stream_format format)
1895 {
1896
1897 struct ia_css_stream_config *s_config =
1898 &asd->stream_env[stream_id].stream_config;
1899
1900 s_config->input_config.format = format;
1901 }
1902
1903 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1904 enum atomisp_input_stream_id stream_id,
1905 struct v4l2_mbus_framefmt *ffmt)
1906 {
1907 int i;
1908 struct ia_css_stream_config *s_config =
1909 &asd->stream_env[stream_id].stream_config;
1910 /*
1911 * Set all isys configs to not valid.
1912 * Currently we support only one stream per channel
1913 */
1914 for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1915 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1916 s_config->isys_config[i].valid = false;
1917
1918 atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1919 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1920 atomisp_css_isys_set_format(asd, stream_id,
1921 s_config->input_config.format,
1922 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1923 atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1924 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1925 atomisp_css_isys_set_valid(asd, stream_id, true,
1926 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1927
1928 return 0;
1929 }
1930
1931 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1932 enum atomisp_input_stream_id stream_id,
1933 enum atomisp_css_stream_format input_format)
1934 {
1935 struct ia_css_stream_config *s_config =
1936 &asd->stream_env[stream_id].stream_config;
1937
1938 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1939 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1940
1941 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1942 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1943
1944 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1945 = IA_CSS_STREAM_ISYS_STREAM_0;
1946 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1947 IA_CSS_STREAM_FORMAT_USER_DEF1;
1948 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1949 IA_CSS_STREAM_FORMAT_USER_DEF2;
1950 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1951 return 0;
1952 }
1953
1954 void atomisp_css_isys_two_stream_cfg_update_stream1(
1955 struct atomisp_sub_device *asd,
1956 enum atomisp_input_stream_id stream_id,
1957 enum atomisp_css_stream_format input_format,
1958 unsigned int width, unsigned int height)
1959 {
1960 struct ia_css_stream_config *s_config =
1961 &asd->stream_env[stream_id].stream_config;
1962
1963 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1964 width;
1965 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1966 height;
1967 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1968 input_format;
1969 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1970 }
1971
1972 void atomisp_css_isys_two_stream_cfg_update_stream2(
1973 struct atomisp_sub_device *asd,
1974 enum atomisp_input_stream_id stream_id,
1975 enum atomisp_css_stream_format input_format,
1976 unsigned int width, unsigned int height)
1977 {
1978 struct ia_css_stream_config *s_config =
1979 &asd->stream_env[stream_id].stream_config;
1980
1981 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1982 width;
1983 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1984 height;
1985 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1986 = IA_CSS_STREAM_ISYS_STREAM_0;
1987 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1988 input_format;
1989 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1990 }
1991
1992 int atomisp_css_input_set_effective_resolution(
1993 struct atomisp_sub_device *asd,
1994 enum atomisp_input_stream_id stream_id,
1995 unsigned int width, unsigned int height)
1996 {
1997 struct ia_css_stream_config *s_config =
1998 &asd->stream_env[stream_id].stream_config;
1999 s_config->input_config.effective_res.width = width;
2000 s_config->input_config.effective_res.height = height;
2001 return 0;
2002 }
2003
2004 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
2005 unsigned int dvs_w, unsigned int dvs_h)
2006 {
2007 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2008 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
2009 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2010 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
2011 }
2012
2013 void atomisp_css_input_set_two_pixels_per_clock(
2014 struct atomisp_sub_device *asd,
2015 bool two_ppc)
2016 {
2017 int i;
2018
2019 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2020 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
2021 return;
2022
2023 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2024 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
2025 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2026 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2027 .update_pipe[i] = true;
2028 }
2029
2030 void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
2031 bool enable)
2032 {
2033 struct atomisp_stream_env *stream_env =
2034 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2035 unsigned int pipe;
2036
2037 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2038 pipe = IA_CSS_PIPE_ID_VIDEO;
2039 else
2040 pipe = IA_CSS_PIPE_ID_PREVIEW;
2041
2042 stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable;
2043 stream_env->update_pipe[pipe] = true;
2044 if (enable)
2045 stream_env->pipe_configs[pipe].output_info[0].padded_width =
2046 stream_env->stream_config.input_config.effective_res.width;
2047 }
2048
2049 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
2050 {
2051 int i;
2052 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2053 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2054 .pipe_configs[i].enable_dz = enable;
2055 }
2056
2057 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
2058 enum atomisp_css_capture_mode mode)
2059 {
2060 struct atomisp_stream_env *stream_env =
2061 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2062
2063 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
2064 .default_capture_config.mode == mode)
2065 return;
2066
2067 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
2068 default_capture_config.mode = mode;
2069 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
2070 }
2071
2072 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
2073 enum atomisp_css_input_mode mode)
2074 {
2075 int i;
2076 struct atomisp_device *isp = asd->isp;
2077 unsigned int size_mem_words;
2078 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
2079 asd->stream_env[i].stream_config.mode = mode;
2080
2081 if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
2082 struct ia_css_stream_config *s_config =
2083 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
2084 s_config->mode = IA_CSS_INPUT_MODE_TPG;
2085 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
2086 s_config->source.tpg.x_mask = (1 << 4) - 1;
2087 s_config->source.tpg.x_delta = -2;
2088 s_config->source.tpg.y_mask = (1 << 4) - 1;
2089 s_config->source.tpg.y_delta = 3;
2090 s_config->source.tpg.xy_mask = (1 << 8) - 1;
2091 return;
2092 }
2093
2094 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
2095 return;
2096
2097 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2098 /*
2099 * TODO: sensor needs to export the embedded_data_size_words
2100 * information to atomisp for each setting.
2101 * Here using a large safe value.
2102 */
2103 struct ia_css_stream_config *s_config =
2104 &asd->stream_env[i].stream_config;
2105
2106 if (s_config->input_config.input_res.width == 0)
2107 continue;
2108
2109 if (ia_css_mipi_frame_calculate_size(
2110 s_config->input_config.input_res.width,
2111 s_config->input_config.input_res.height,
2112 s_config->input_config.format,
2113 true,
2114 0x13000,
2115 &size_mem_words) != IA_CSS_SUCCESS) {
2116 if (intel_mid_identify_cpu() ==
2117 INTEL_MID_CPU_CHIP_TANGIER)
2118 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
2119 else
2120 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
2121 dev_warn(asd->isp->dev,
2122 "ia_css_mipi_frame_calculate_size failed,"
2123 "applying pre-defined MIPI buffer size %u.\n",
2124 size_mem_words);
2125 }
2126 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
2127 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
2128 }
2129 }
2130
2131 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
2132 unsigned short stream_index, bool enable)
2133 {
2134 struct atomisp_stream_env *stream_env =
2135 &asd->stream_env[stream_index];
2136
2137 if (stream_env->stream_config.online == !!enable)
2138 return;
2139
2140 stream_env->stream_config.online = !!enable;
2141 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
2142 }
2143
2144 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
2145 unsigned short stream_index, bool enable)
2146 {
2147 struct atomisp_stream_env *stream_env =
2148 &asd->stream_env[stream_index];
2149 int i;
2150
2151 if (stream_env->stream_config.online != !!enable) {
2152 stream_env->stream_config.online = !!enable;
2153 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2154 stream_env->update_pipe[i] = true;
2155 }
2156 }
2157
2158 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
2159 bool enable)
2160 {
2161 struct atomisp_stream_env *stream_env =
2162 &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
2163 int i;
2164
2165 if (stream_env->stream_config.online != enable) {
2166 stream_env->stream_config.online = enable;
2167 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2168 stream_env->update_pipe[i] = true;
2169 }
2170 }
2171
2172 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
2173 bool enable)
2174 {
2175 struct atomisp_stream_env *stream_env =
2176 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2177 int i;
2178
2179 /*
2180 * To SOC camera, there is only one YUVPP pipe in any case
2181 * including ZSL/SDV/continuous viewfinder, so always set
2182 * stream_config.continuous to 0.
2183 */
2184 if (ATOMISP_USE_YUVPP(asd)) {
2185 stream_env->stream_config.continuous = 0;
2186 stream_env->stream_config.online = 1;
2187 return;
2188 }
2189
2190 if (stream_env->stream_config.continuous != !!enable) {
2191 stream_env->stream_config.continuous = !!enable;
2192 stream_env->stream_config.pack_raw_pixels = true;
2193 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2194 stream_env->update_pipe[i] = true;
2195 }
2196 }
2197
2198 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
2199 bool enable)
2200 {
2201 struct atomisp_stream_env *stream_env =
2202 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2203 int i;
2204
2205 if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
2206 stream_env->stream_config.disable_cont_viewfinder = !enable;
2207 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2208 stream_env->update_pipe[i] = true;
2209 }
2210 }
2211
2212 int atomisp_css_input_configure_port(
2213 struct atomisp_sub_device *asd,
2214 mipi_port_ID_t port,
2215 unsigned int num_lanes,
2216 unsigned int timeout,
2217 unsigned int mipi_freq,
2218 enum atomisp_css_stream_format metadata_format,
2219 unsigned int metadata_width,
2220 unsigned int metadata_height)
2221 {
2222 int i;
2223 struct atomisp_stream_env *stream_env;
2224 /*
2225 * Calculate rx_count as follows:
2226 * Input: mipi_freq : CSI-2 bus frequency in Hz
2227 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus
2228 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds
2229 * max = 145e-9 + 10 * UI
2230 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
2231 * rxcount = rxcount0 - 2 : adjust for better results
2232 * The formula below is simplified version of the above with
2233 * 10-bit fixed points for improved accuracy.
2234 */
2235 const unsigned int rxcount =
2236 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
2237
2238 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2239 stream_env = &asd->stream_env[i];
2240 stream_env->stream_config.source.port.port = port;
2241 stream_env->stream_config.source.port.num_lanes = num_lanes;
2242 stream_env->stream_config.source.port.timeout = timeout;
2243 if (mipi_freq)
2244 stream_env->stream_config.source.port.rxcount = rxcount;
2245 stream_env->stream_config.
2246 metadata_config.data_type = metadata_format;
2247 stream_env->stream_config.
2248 metadata_config.resolution.width = metadata_width;
2249 stream_env->stream_config.
2250 metadata_config.resolution.height = metadata_height;
2251 }
2252
2253 return 0;
2254 }
2255
2256 int atomisp_css_frame_allocate(struct atomisp_css_frame **frame,
2257 unsigned int width, unsigned int height,
2258 enum atomisp_css_frame_format format,
2259 unsigned int padded_width,
2260 unsigned int raw_bit_depth)
2261 {
2262 if (ia_css_frame_allocate(frame, width, height, format,
2263 padded_width, raw_bit_depth) != IA_CSS_SUCCESS)
2264 return -ENOMEM;
2265
2266 return 0;
2267 }
2268
2269 int atomisp_css_frame_allocate_from_info(struct atomisp_css_frame **frame,
2270 const struct atomisp_css_frame_info *info)
2271 {
2272 if (ia_css_frame_allocate_from_info(frame, info) != IA_CSS_SUCCESS)
2273 return -ENOMEM;
2274
2275 return 0;
2276 }
2277
2278 void atomisp_css_frame_free(struct atomisp_css_frame *frame)
2279 {
2280 ia_css_frame_free(frame);
2281 }
2282
2283 int atomisp_css_frame_map(struct atomisp_css_frame **frame,
2284 const struct atomisp_css_frame_info *info,
2285 const void *data, uint16_t attribute,
2286 void *context)
2287 {
2288 if (ia_css_frame_map(frame, info, data, attribute, context)
2289 != IA_CSS_SUCCESS)
2290 return -ENOMEM;
2291
2292 return 0;
2293 }
2294
2295 int atomisp_css_set_black_frame(struct atomisp_sub_device *asd,
2296 const struct atomisp_css_frame *raw_black_frame)
2297 {
2298 if (sh_css_set_black_frame(
2299 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2300 raw_black_frame) != IA_CSS_SUCCESS)
2301 return -ENOMEM;
2302
2303 return 0;
2304 }
2305
2306 int atomisp_css_allocate_continuous_frames(bool init_time,
2307 struct atomisp_sub_device *asd)
2308 {
2309 if (ia_css_alloc_continuous_frame_remain(
2310 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream)
2311 != IA_CSS_SUCCESS)
2312 return -EINVAL;
2313 return 0;
2314 }
2315
2316 void atomisp_css_update_continuous_frames(struct atomisp_sub_device *asd)
2317 {
2318 ia_css_update_continuous_frames(
2319 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream);
2320 }
2321
2322 int atomisp_css_stop(struct atomisp_sub_device *asd,
2323 enum atomisp_css_pipe_id pipe_id, bool in_reset)
2324 {
2325 struct atomisp_device *isp = asd->isp;
2326 struct atomisp_s3a_buf *s3a_buf;
2327 struct atomisp_dis_buf *dis_buf;
2328 struct atomisp_metadata_buf *md_buf;
2329 unsigned long irqflags;
2330 unsigned int i;
2331
2332 /* if is called in atomisp_reset(), force destroy stream */
2333 if (__destroy_streams(asd, true))
2334 dev_err(isp->dev, "destroy stream failed.\n");
2335
2336 /* if is called in atomisp_reset(), force destroy all pipes */
2337 if (__destroy_pipes(asd, true))
2338 dev_err(isp->dev, "destroy pipes failed.\n");
2339
2340 atomisp_init_raw_buffer_bitmap(asd);
2341
2342 /*
2343 * SP can not be stop if other streams are in use
2344 */
2345 if (atomisp_streaming_count(isp) == 0)
2346 ia_css_stop_sp();
2347
2348 if (!in_reset) {
2349 struct atomisp_stream_env *stream_env;
2350 int i, j;
2351 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2352 stream_env = &asd->stream_env[i];
2353 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
2354 ia_css_pipe_config_defaults(
2355 &stream_env->pipe_configs[j]);
2356 ia_css_pipe_extra_config_defaults(
2357 &stream_env->pipe_extra_configs[j]);
2358 }
2359 ia_css_stream_config_defaults(
2360 &stream_env->stream_config);
2361 }
2362 atomisp_isp_parameters_clean_up(&asd->params.config);
2363 asd->params.css_update_params_needed = false;
2364 }
2365
2366 /* move stats buffers to free queue list */
2367 while (!list_empty(&asd->s3a_stats_in_css)) {
2368 s3a_buf = list_entry(asd->s3a_stats_in_css.next,
2369 struct atomisp_s3a_buf, list);
2370 list_del(&s3a_buf->list);
2371 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2372 }
2373 while (!list_empty(&asd->s3a_stats_ready)) {
2374 s3a_buf = list_entry(asd->s3a_stats_ready.next,
2375 struct atomisp_s3a_buf, list);
2376 list_del(&s3a_buf->list);
2377 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2378 }
2379
2380 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
2381 while (!list_empty(&asd->dis_stats_in_css)) {
2382 dis_buf = list_entry(asd->dis_stats_in_css.next,
2383 struct atomisp_dis_buf, list);
2384 list_del(&dis_buf->list);
2385 list_add_tail(&dis_buf->list, &asd->dis_stats);
2386 }
2387 asd->params.dis_proj_data_valid = false;
2388 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
2389
2390 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
2391 while (!list_empty(&asd->metadata_in_css[i])) {
2392 md_buf = list_entry(asd->metadata_in_css[i].next,
2393 struct atomisp_metadata_buf, list);
2394 list_del(&md_buf->list);
2395 list_add_tail(&md_buf->list, &asd->metadata[i]);
2396 }
2397 while (!list_empty(&asd->metadata_ready[i])) {
2398 md_buf = list_entry(asd->metadata_ready[i].next,
2399 struct atomisp_metadata_buf, list);
2400 list_del(&md_buf->list);
2401 list_add_tail(&md_buf->list, &asd->metadata[i]);
2402 }
2403 }
2404
2405 atomisp_flush_params_queue(&asd->video_out_capture);
2406 atomisp_flush_params_queue(&asd->video_out_vf);
2407 atomisp_flush_params_queue(&asd->video_out_preview);
2408 atomisp_flush_params_queue(&asd->video_out_video_capture);
2409 atomisp_free_css_parameters(&asd->params.css_param);
2410 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
2411 return 0;
2412 }
2413
2414 int atomisp_css_continuous_set_num_raw_frames(
2415 struct atomisp_sub_device *asd,
2416 int num_frames)
2417 {
2418 if (asd->enable_raw_buffer_lock->val) {
2419 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2420 .stream_config.init_num_cont_raw_buf =
2421 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
2422 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2423 asd->params.video_dis_en)
2424 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2425 .stream_config.init_num_cont_raw_buf +=
2426 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2427 } else {
2428 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2429 .stream_config.init_num_cont_raw_buf =
2430 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
2431 }
2432
2433 if (asd->params.video_dis_en)
2434 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2435 .stream_config.init_num_cont_raw_buf +=
2436 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2437
2438 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2439 .stream_config.target_num_cont_raw_buf = num_frames;
2440 return 0;
2441 }
2442
2443 void atomisp_css_disable_vf_pp(struct atomisp_sub_device *asd,
2444 bool disable)
2445 {
2446 int i;
2447
2448 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2449 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2450 .pipe_extra_configs[i].disable_vf_pp = !!disable;
2451 }
2452
2453 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2454 struct atomisp_sub_device *asd,
2455 enum ia_css_pipe_id pipe_id)
2456 {
2457 struct atomisp_device *isp = asd->isp;
2458 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2459 isp->inputs[asd->input_curr].camera);
2460
2461 switch (pipe_id) {
2462 case IA_CSS_PIPE_ID_COPY:
2463 /* Currently only YUVPP mode supports YUV420_Legacy format.
2464 * Revert this when other pipe modes can support
2465 * YUV420_Legacy format.
2466 */
2467 if (mipi_info && mipi_info->input_format ==
2468 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2469 return IA_CSS_PIPE_MODE_YUVPP;
2470 return IA_CSS_PIPE_MODE_COPY;
2471 case IA_CSS_PIPE_ID_PREVIEW:
2472 return IA_CSS_PIPE_MODE_PREVIEW;
2473 case IA_CSS_PIPE_ID_CAPTURE:
2474 return IA_CSS_PIPE_MODE_CAPTURE;
2475 case IA_CSS_PIPE_ID_VIDEO:
2476 return IA_CSS_PIPE_MODE_VIDEO;
2477 case IA_CSS_PIPE_ID_ACC:
2478 return IA_CSS_PIPE_MODE_ACC;
2479 case IA_CSS_PIPE_ID_YUVPP:
2480 return IA_CSS_PIPE_MODE_YUVPP;
2481 default:
2482 WARN_ON(1);
2483 return IA_CSS_PIPE_MODE_PREVIEW;
2484 }
2485
2486 }
2487
2488 static void __configure_output(struct atomisp_sub_device *asd,
2489 unsigned int stream_index,
2490 unsigned int width, unsigned int height,
2491 unsigned int min_width,
2492 enum ia_css_frame_format format,
2493 enum ia_css_pipe_id pipe_id)
2494 {
2495 struct atomisp_device *isp = asd->isp;
2496 struct atomisp_stream_env *stream_env =
2497 &asd->stream_env[stream_index];
2498 struct ia_css_stream_config *s_config = &stream_env->stream_config;
2499
2500 stream_env->pipe_configs[pipe_id].mode =
2501 __pipe_id_to_pipe_mode(asd, pipe_id);
2502 stream_env->update_pipe[pipe_id] = true;
2503
2504 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2505 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2506 stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2507 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2508
2509 /* isp binary 2.2 specific setting*/
2510 if (width > s_config->input_config.effective_res.width ||
2511 height > s_config->input_config.effective_res.height) {
2512 s_config->input_config.effective_res.width = width;
2513 s_config->input_config.effective_res.height = height;
2514 }
2515
2516 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2517 pipe_id, width, height, format);
2518 }
2519
2520 static void __configure_video_preview_output(struct atomisp_sub_device *asd,
2521 unsigned int stream_index,
2522 unsigned int width, unsigned int height,
2523 unsigned int min_width,
2524 enum ia_css_frame_format format,
2525 enum ia_css_pipe_id pipe_id)
2526 {
2527 struct atomisp_device *isp = asd->isp;
2528 struct atomisp_stream_env *stream_env =
2529 &asd->stream_env[stream_index];
2530 struct ia_css_frame_info *css_output_info;
2531 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2532
2533 stream_env->pipe_configs[pipe_id].mode =
2534 __pipe_id_to_pipe_mode(asd, pipe_id);
2535 stream_env->update_pipe[pipe_id] = true;
2536
2537 /*
2538 * second_output will be as video main output in SDV mode
2539 * with SOC camera. output will be as video main output in
2540 * normal video mode.
2541 */
2542 if (asd->continuous_mode->val)
2543 css_output_info = &stream_env->pipe_configs[pipe_id].
2544 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2545 else
2546 css_output_info = &stream_env->pipe_configs[pipe_id].
2547 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2548
2549 css_output_info->res.width = width;
2550 css_output_info->res.height = height;
2551 css_output_info->format = format;
2552 css_output_info->padded_width = min_width;
2553
2554 /* isp binary 2.2 specific setting*/
2555 if (width > stream_config->input_config.effective_res.width ||
2556 height > stream_config->input_config.effective_res.height) {
2557 stream_config->input_config.effective_res.width = width;
2558 stream_config->input_config.effective_res.height = height;
2559 }
2560
2561 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2562 pipe_id, width, height, format);
2563 }
2564
2565 /*
2566 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2567 * downscaling input resolution.
2568 */
2569 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2570 unsigned int width, unsigned int height,
2571 enum ia_css_pipe_id pipe_id)
2572 {
2573 struct atomisp_device *isp = asd->isp;
2574 struct atomisp_stream_env *stream_env =
2575 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2576 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2577 struct ia_css_pipe_config *pipe_configs =
2578 &stream_env->pipe_configs[pipe_id];
2579 struct ia_css_pipe_extra_config *pipe_extra_configs =
2580 &stream_env->pipe_extra_configs[pipe_id];
2581 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2582 #define CEIL_DIV(a, b) ((b) ? ((a) + (b) - 1) / (b) : 0)
2583
2584 if (width == 0 && height == 0)
2585 return;
2586
2587 if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2588 height * 9 / 10 < pipe_configs->output_info[0].res.height)
2589 return;
2590 /* here just copy the calculation in css */
2591 hor_ds_factor = CEIL_DIV(width >> 1,
2592 pipe_configs->output_info[0].res.width);
2593 ver_ds_factor = CEIL_DIV(height >> 1,
2594 pipe_configs->output_info[0].res.height);
2595
2596 if ((asd->isp->media_dev.hw_revision <
2597 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2598 IS_CHT) && hor_ds_factor != ver_ds_factor) {
2599 dev_warn(asd->isp->dev,
2600 "Cropping for capture due to FW limitation");
2601 return;
2602 }
2603
2604 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2605 stream_env->update_pipe[pipe_id] = true;
2606
2607 pipe_extra_configs->enable_yuv_ds = true;
2608
2609 pipe_configs->capt_pp_in_res.width =
2610 stream_config->input_config.effective_res.width;
2611 pipe_configs->capt_pp_in_res.height =
2612 stream_config->input_config.effective_res.height;
2613
2614 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2615 pipe_id, width, height);
2616 }
2617
2618 /*
2619 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2620 * yuv downscaling, which needs addtional configurations.
2621 */
2622 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2623 unsigned int width, unsigned int height,
2624 enum ia_css_pipe_id pipe_id)
2625 {
2626 struct atomisp_device *isp = asd->isp;
2627 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2628 struct atomisp_stream_env *stream_env =
2629 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2630 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2631 struct ia_css_pipe_config *pipe_configs =
2632 &stream_env->pipe_configs[pipe_id];
2633 struct ia_css_pipe_extra_config *pipe_extra_configs =
2634 &stream_env->pipe_extra_configs[pipe_id];
2635 struct ia_css_resolution *bayer_ds_out_res =
2636 &pipe_configs->bayer_ds_out_res;
2637 struct ia_css_resolution *vf_pp_in_res =
2638 &pipe_configs->vf_pp_in_res;
2639 struct ia_css_resolution *effective_res =
2640 &stream_config->input_config.effective_res;
2641
2642 const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2643 /*
2644 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2645 * columns to be shaded. Remove this factor to work around the CSS bug.
2646 * const unsigned int yuv_dec_fct[] = {4, 2};
2647 */
2648 const unsigned int yuv_dec_fct[] = { 2 };
2649 unsigned int i;
2650
2651 if (width == 0 && height == 0)
2652 return;
2653
2654 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2655 stream_env->update_pipe[pipe_id] = true;
2656
2657 out_width = pipe_configs->output_info[0].res.width;
2658 out_height = pipe_configs->output_info[0].res.height;
2659
2660 /*
2661 * The ISP could do bayer downscaling, yuv decimation and yuv
2662 * downscaling:
2663 * 1: Bayer Downscaling: between effective resolution and
2664 * bayer_ds_res_out;
2665 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2666 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2667 *
2668 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2669 * Rule for YUV Decimation: support factor 2, 4
2670 * Rule for YUV Downscaling: arbitary value below 2
2671 *
2672 * General rule of factor distribution among these stages:
2673 * 1: try to do Bayer downscaling first if not in online mode.
2674 * 2: try to do maximum of 2 for YUV downscaling
2675 * 3: the remainling for YUV decimation
2676 *
2677 * Note:
2678 * Do not configure bayer_ds_out_res if:
2679 * online == 1 or continuous == 0 or raw_binning = 0
2680 */
2681 if (stream_config->online || !stream_config->continuous ||
2682 !pipe_extra_configs->enable_raw_binning) {
2683 bayer_ds_out_res->width = 0;
2684 bayer_ds_out_res->height = 0;
2685 } else {
2686 bayer_ds_out_res->width = effective_res->width;
2687 bayer_ds_out_res->height = effective_res->height;
2688
2689 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2690 if (effective_res->width >= out_width *
2691 bds_fct[i].numerator / bds_fct[i].denominator &&
2692 effective_res->height >= out_height *
2693 bds_fct[i].numerator / bds_fct[i].denominator) {
2694 bayer_ds_out_res->width =
2695 effective_res->width *
2696 bds_fct[i].denominator /
2697 bds_fct[i].numerator;
2698 bayer_ds_out_res->height =
2699 effective_res->height *
2700 bds_fct[i].denominator /
2701 bds_fct[i].numerator;
2702 break;
2703 }
2704 }
2705 }
2706 /*
2707 * calculate YUV Decimation, YUV downscaling facor:
2708 * YUV Downscaling factor must not exceed 2.
2709 * YUV Decimation factor could be 2, 4.
2710 */
2711 /* first decide the yuv_ds input resolution */
2712 if (bayer_ds_out_res->width == 0) {
2713 yuv_ds_in_width = effective_res->width;
2714 yuv_ds_in_height = effective_res->height;
2715 } else {
2716 yuv_ds_in_width = bayer_ds_out_res->width;
2717 yuv_ds_in_height = bayer_ds_out_res->height;
2718 }
2719
2720 vf_pp_in_res->width = yuv_ds_in_width;
2721 vf_pp_in_res->height = yuv_ds_in_height;
2722
2723 /* find out the yuv decimation factor */
2724 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2725 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2726 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2727 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2728 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2729 break;
2730 }
2731 }
2732
2733 if (vf_pp_in_res->width == out_width &&
2734 vf_pp_in_res->height == out_height) {
2735 pipe_extra_configs->enable_yuv_ds = false;
2736 vf_pp_in_res->width = 0;
2737 vf_pp_in_res->height = 0;
2738 } else {
2739 pipe_extra_configs->enable_yuv_ds = true;
2740 }
2741
2742 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2743 pipe_id, width, height);
2744 }
2745
2746 /*
2747 * For CSS2.1, offline video pipe could support bayer decimation, and
2748 * yuv downscaling, which needs addtional configurations.
2749 */
2750 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2751 unsigned int width, unsigned int height,
2752 enum ia_css_pipe_id pipe_id)
2753 {
2754 struct atomisp_device *isp = asd->isp;
2755 int out_width, out_height;
2756 struct atomisp_stream_env *stream_env =
2757 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2758 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2759 struct ia_css_pipe_config *pipe_configs =
2760 &stream_env->pipe_configs[pipe_id];
2761 struct ia_css_pipe_extra_config *pipe_extra_configs =
2762 &stream_env->pipe_extra_configs[pipe_id];
2763 struct ia_css_resolution *bayer_ds_out_res =
2764 &pipe_configs->bayer_ds_out_res;
2765 struct ia_css_resolution *effective_res =
2766 &stream_config->input_config.effective_res;
2767
2768 const struct bayer_ds_factor bds_factors[] = {
2769 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2} };
2770 unsigned int i;
2771
2772 if (width == 0 && height == 0)
2773 return;
2774
2775 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2776 stream_env->update_pipe[pipe_id] = true;
2777
2778 pipe_extra_configs->enable_yuv_ds = false;
2779
2780 /*
2781 * If DVS is enabled, video binary will take care the dvs envelope
2782 * and usually the bayer_ds_out_res should be larger than 120% of
2783 * destination resolution, the extra 20% will be cropped as DVS
2784 * envelope. But, if the bayer_ds_out_res is less than 120% of the
2785 * destination. The ISP can still work, but DVS quality is not good.
2786 */
2787 /* taking at least 10% as envelope */
2788 if (asd->params.video_dis_en) {
2789 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2790 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2791 } else {
2792 out_width = pipe_configs->output_info[0].res.width;
2793 out_height = pipe_configs->output_info[0].res.height;
2794 }
2795
2796 /*
2797 * calculate bayer decimate factor:
2798 * 1: only 1.5, 2, 4 and 8 get supported
2799 * 2: Do not configure bayer_ds_out_res if:
2800 * online == 1 or continuous == 0 or raw_binning = 0
2801 */
2802 if (stream_config->online || !stream_config->continuous) {
2803 bayer_ds_out_res->width = 0;
2804 bayer_ds_out_res->height = 0;
2805 goto done;
2806 }
2807
2808 pipe_extra_configs->enable_raw_binning = true;
2809 bayer_ds_out_res->width = effective_res->width;
2810 bayer_ds_out_res->height = effective_res->height;
2811
2812 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2813 i++) {
2814 if (effective_res->width >= out_width *
2815 bds_factors[i].numerator / bds_factors[i].denominator &&
2816 effective_res->height >= out_height *
2817 bds_factors[i].numerator / bds_factors[i].denominator) {
2818 bayer_ds_out_res->width = effective_res->width *
2819 bds_factors[i].denominator /
2820 bds_factors[i].numerator;
2821 bayer_ds_out_res->height = effective_res->height *
2822 bds_factors[i].denominator /
2823 bds_factors[i].numerator;
2824 break;
2825 }
2826 }
2827
2828 /*
2829 * DVS is cropped from BDS output, so we do not really need to set the
2830 * envelope to 20% of output resolution here. always set it to 12x12
2831 * per firmware requirement.
2832 */
2833 pipe_configs->dvs_envelope.width = 12;
2834 pipe_configs->dvs_envelope.height = 12;
2835
2836 done:
2837 if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2838 stream_config->left_padding = -1;
2839 else
2840 stream_config->left_padding = 12;
2841 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2842 pipe_id, width, height);
2843 }
2844
2845 static void __configure_vf_output(struct atomisp_sub_device *asd,
2846 unsigned int width, unsigned int height,
2847 unsigned int min_width,
2848 enum atomisp_css_frame_format format,
2849 enum ia_css_pipe_id pipe_id)
2850 {
2851 struct atomisp_device *isp = asd->isp;
2852 struct atomisp_stream_env *stream_env =
2853 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2854 stream_env->pipe_configs[pipe_id].mode =
2855 __pipe_id_to_pipe_mode(asd, pipe_id);
2856 stream_env->update_pipe[pipe_id] = true;
2857
2858 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2859 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2860 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2861 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2862 min_width;
2863 dev_dbg(isp->dev,
2864 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2865 pipe_id, width, height, format);
2866 }
2867
2868 static void __configure_video_vf_output(struct atomisp_sub_device *asd,
2869 unsigned int width, unsigned int height,
2870 unsigned int min_width,
2871 enum atomisp_css_frame_format format,
2872 enum ia_css_pipe_id pipe_id)
2873 {
2874 struct atomisp_device *isp = asd->isp;
2875 struct atomisp_stream_env *stream_env =
2876 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2877 struct ia_css_frame_info *css_output_info;
2878 stream_env->pipe_configs[pipe_id].mode =
2879 __pipe_id_to_pipe_mode(asd, pipe_id);
2880 stream_env->update_pipe[pipe_id] = true;
2881
2882 /*
2883 * second_vf_output will be as video viewfinder in SDV mode
2884 * with SOC camera. vf_output will be as video viewfinder in
2885 * normal video mode.
2886 */
2887 if (asd->continuous_mode->val)
2888 css_output_info = &stream_env->pipe_configs[pipe_id].
2889 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2890 else
2891 css_output_info = &stream_env->pipe_configs[pipe_id].
2892 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2893
2894 css_output_info->res.width = width;
2895 css_output_info->res.height = height;
2896 css_output_info->format = format;
2897 css_output_info->padded_width = min_width;
2898 dev_dbg(isp->dev,
2899 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2900 pipe_id, width, height, format);
2901 }
2902
2903 static int __get_frame_info(struct atomisp_sub_device *asd,
2904 unsigned int stream_index,
2905 struct atomisp_css_frame_info *info,
2906 enum frame_info_type type,
2907 enum ia_css_pipe_id pipe_id)
2908 {
2909 struct atomisp_device *isp = asd->isp;
2910 enum ia_css_err ret;
2911 struct ia_css_pipe_info p_info;
2912
2913 /* FIXME! No need to destroy/recreate all streams */
2914 if (__destroy_streams(asd, true))
2915 dev_warn(isp->dev, "destroy stream failed.\n");
2916
2917 if (__destroy_pipes(asd, true))
2918 dev_warn(isp->dev, "destroy pipe failed.\n");
2919
2920 if (__create_pipes(asd))
2921 return -EINVAL;
2922
2923 if (__create_streams(asd))
2924 goto stream_err;
2925
2926 ret = ia_css_pipe_get_info(
2927 asd->stream_env[stream_index]
2928 .pipes[pipe_id], &p_info);
2929 if (ret == IA_CSS_SUCCESS) {
2930 switch (type) {
2931 case ATOMISP_CSS_VF_FRAME:
2932 *info = p_info.vf_output_info[0];
2933 dev_dbg(isp->dev, "getting vf frame info.\n");
2934 break;
2935 case ATOMISP_CSS_SECOND_VF_FRAME:
2936 *info = p_info.vf_output_info[1];
2937 dev_dbg(isp->dev, "getting second vf frame info.\n");
2938 break;
2939 case ATOMISP_CSS_OUTPUT_FRAME:
2940 *info = p_info.output_info[0];
2941 dev_dbg(isp->dev, "getting main frame info.\n");
2942 break;
2943 case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2944 *info = p_info.output_info[1];
2945 dev_dbg(isp->dev, "getting second main frame info.\n");
2946 break;
2947 case ATOMISP_CSS_RAW_FRAME:
2948 *info = p_info.raw_output_info;
2949 dev_dbg(isp->dev, "getting raw frame info.\n");
2950 }
2951 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2952 info->res.width, info->res.height, p_info.num_invalid_frames);
2953 return 0;
2954 }
2955
2956 stream_err:
2957 __destroy_pipes(asd, true);
2958 return -EINVAL;
2959 }
2960
2961 unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2962 uint16_t source_pad)
2963 {
2964 struct atomisp_device *isp = asd->isp;
2965 /*
2966 * to SOC camera, use yuvpp pipe.
2967 */
2968 if (ATOMISP_USE_YUVPP(asd))
2969 return IA_CSS_PIPE_ID_YUVPP;
2970
2971 switch (source_pad) {
2972 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2973 if (asd->yuvpp_mode)
2974 return IA_CSS_PIPE_ID_YUVPP;
2975 if (asd->copy_mode)
2976 return IA_CSS_PIPE_ID_COPY;
2977 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2978 || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2979 return IA_CSS_PIPE_ID_VIDEO;
2980 else
2981 return IA_CSS_PIPE_ID_CAPTURE;
2982 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2983 if (asd->copy_mode)
2984 return IA_CSS_PIPE_ID_COPY;
2985 return IA_CSS_PIPE_ID_CAPTURE;
2986 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2987 if (!atomisp_is_mbuscode_raw(
2988 asd->fmt[asd->capture_pad].fmt.code))
2989 return IA_CSS_PIPE_ID_CAPTURE;
2990 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2991 if (asd->yuvpp_mode)
2992 return IA_CSS_PIPE_ID_YUVPP;
2993 if (asd->copy_mode)
2994 return IA_CSS_PIPE_ID_COPY;
2995 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2996 return IA_CSS_PIPE_ID_VIDEO;
2997 else
2998 return IA_CSS_PIPE_ID_PREVIEW;
2999 }
3000 dev_warn(isp->dev,
3001 "invalid source pad:%d, return default preview pipe index.\n",
3002 source_pad);
3003 return IA_CSS_PIPE_ID_PREVIEW;
3004 }
3005
3006 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
3007 uint16_t source_pad,
3008 struct atomisp_css_frame_info *frame_info)
3009 {
3010 struct ia_css_pipe_info info;
3011 int pipe_index = atomisp_get_pipe_index(asd, source_pad);
3012 int stream_index;
3013 struct atomisp_device *isp = asd->isp;
3014
3015 if (ATOMISP_SOC_CAMERA(asd))
3016 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
3017 else {
3018 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
3019 ATOMISP_INPUT_STREAM_VIDEO :
3020 atomisp_source_pad_to_stream_id(asd, source_pad);
3021 }
3022
3023 if (IA_CSS_SUCCESS != ia_css_pipe_get_info(asd->stream_env[stream_index]
3024 .pipes[pipe_index], &info)) {
3025 dev_err(isp->dev, "ia_css_pipe_get_info FAILED");
3026 return -EINVAL;
3027 }
3028
3029 switch (source_pad) {
3030 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
3031 *frame_info = info.output_info[0];
3032 break;
3033 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
3034 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
3035 *frame_info = info.
3036 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
3037 else
3038 *frame_info = info.
3039 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
3040 break;
3041 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
3042 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
3043 *frame_info = info.output_info[0];
3044 else
3045 *frame_info = info.vf_output_info[0];
3046 break;
3047 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
3048 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
3049 (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
3050 pipe_index == IA_CSS_PIPE_ID_YUVPP))
3051 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
3052 *frame_info = info.
3053 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
3054 else
3055 *frame_info = info.
3056 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
3057 else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
3058 *frame_info =
3059 info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
3060 else
3061 *frame_info =
3062 info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
3063
3064 break;
3065 default:
3066 frame_info = NULL;
3067 break;
3068 }
3069 return frame_info ? 0 : -EINVAL;
3070 }
3071
3072 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
3073 unsigned int stream_index,
3074 unsigned int width, unsigned int height,
3075 unsigned int padded_width,
3076 enum atomisp_css_frame_format format)
3077 {
3078 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
3079 default_capture_config.mode =
3080 CSS_CAPTURE_MODE_RAW;
3081
3082 __configure_output(asd, stream_index, width, height, padded_width,
3083 format, IA_CSS_PIPE_ID_COPY);
3084 return 0;
3085 }
3086
3087 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
3088 unsigned int stream_index,
3089 unsigned int width, unsigned int height,
3090 unsigned int padded_width,
3091 enum atomisp_css_frame_format format)
3092 {
3093 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
3094 default_capture_config.mode =
3095 CSS_CAPTURE_MODE_RAW;
3096
3097 __configure_output(asd, stream_index, width, height, padded_width,
3098 format, IA_CSS_PIPE_ID_YUVPP);
3099 return 0;
3100 }
3101
3102 int atomisp_css_yuvpp_configure_viewfinder(
3103 struct atomisp_sub_device *asd,
3104 unsigned int stream_index,
3105 unsigned int width, unsigned int height,
3106 unsigned int min_width,
3107 enum atomisp_css_frame_format format)
3108 {
3109 struct atomisp_stream_env *stream_env =
3110 &asd->stream_env[stream_index];
3111 enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP;
3112
3113 stream_env->pipe_configs[pipe_id].mode =
3114 __pipe_id_to_pipe_mode(asd, pipe_id);
3115 stream_env->update_pipe[pipe_id] = true;
3116
3117 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
3118 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
3119 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
3120 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
3121 min_width;
3122 return 0;
3123 }
3124
3125 int atomisp_css_yuvpp_get_output_frame_info(
3126 struct atomisp_sub_device *asd,
3127 unsigned int stream_index,
3128 struct atomisp_css_frame_info *info)
3129 {
3130 return __get_frame_info(asd, stream_index, info,
3131 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
3132 }
3133
3134 int atomisp_css_yuvpp_get_viewfinder_frame_info(
3135 struct atomisp_sub_device *asd,
3136 unsigned int stream_index,
3137 struct atomisp_css_frame_info *info)
3138 {
3139 return __get_frame_info(asd, stream_index, info,
3140 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
3141 }
3142
3143 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
3144 unsigned int width, unsigned int height,
3145 unsigned int min_width,
3146 enum atomisp_css_frame_format format)
3147 {
3148 /*
3149 * to SOC camera, use yuvpp pipe.
3150 */
3151 if (ATOMISP_USE_YUVPP(asd))
3152 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3153 min_width, format, IA_CSS_PIPE_ID_YUVPP);
3154 else
3155 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3156 min_width, format, IA_CSS_PIPE_ID_PREVIEW);
3157 return 0;
3158 }
3159
3160 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
3161 unsigned int width, unsigned int height,
3162 unsigned int min_width,
3163 enum atomisp_css_frame_format format)
3164 {
3165 enum ia_css_pipe_id pipe_id;
3166
3167 /*
3168 * to SOC camera, use yuvpp pipe.
3169 */
3170 if (ATOMISP_USE_YUVPP(asd))
3171 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3172 else
3173 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3174
3175 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3176 min_width, format, pipe_id);
3177 return 0;
3178 }
3179
3180 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
3181 unsigned int width, unsigned int height,
3182 unsigned int min_width,
3183 enum atomisp_css_frame_format format)
3184 {
3185 /*
3186 * to SOC camera, use yuvpp pipe.
3187 */
3188 if (ATOMISP_USE_YUVPP(asd))
3189 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3190 min_width, format, IA_CSS_PIPE_ID_YUVPP);
3191 else
3192 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
3193 min_width, format, IA_CSS_PIPE_ID_VIDEO);
3194 return 0;
3195 }
3196
3197 int atomisp_css_video_configure_viewfinder(
3198 struct atomisp_sub_device *asd,
3199 unsigned int width, unsigned int height,
3200 unsigned int min_width,
3201 enum atomisp_css_frame_format format)
3202 {
3203 /*
3204 * to SOC camera, video will use yuvpp pipe.
3205 */
3206 if (ATOMISP_USE_YUVPP(asd))
3207 __configure_video_vf_output(asd, width, height, min_width, format,
3208 IA_CSS_PIPE_ID_YUVPP);
3209 else
3210 __configure_vf_output(asd, width, height, min_width, format,
3211 IA_CSS_PIPE_ID_VIDEO);
3212 return 0;
3213 }
3214
3215 int atomisp_css_capture_configure_viewfinder(
3216 struct atomisp_sub_device *asd,
3217 unsigned int width, unsigned int height,
3218 unsigned int min_width,
3219 enum atomisp_css_frame_format format)
3220 {
3221 enum ia_css_pipe_id pipe_id;
3222
3223 /*
3224 * to SOC camera, video will use yuvpp pipe.
3225 */
3226 if (ATOMISP_USE_YUVPP(asd))
3227 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3228 else
3229 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3230
3231 __configure_vf_output(asd, width, height, min_width, format,
3232 pipe_id);
3233 return 0;
3234 }
3235
3236 int atomisp_css_video_get_viewfinder_frame_info(
3237 struct atomisp_sub_device *asd,
3238 struct atomisp_css_frame_info *info)
3239 {
3240 enum ia_css_pipe_id pipe_id;
3241 enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME;
3242
3243 if (ATOMISP_USE_YUVPP(asd)) {
3244 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3245 if (asd->continuous_mode->val)
3246 frame_type = ATOMISP_CSS_SECOND_VF_FRAME;
3247 } else {
3248 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3249 }
3250
3251 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3252 frame_type, pipe_id);
3253 }
3254
3255 int atomisp_css_capture_get_viewfinder_frame_info(
3256 struct atomisp_sub_device *asd,
3257 struct atomisp_css_frame_info *info)
3258 {
3259 enum ia_css_pipe_id pipe_id;
3260
3261 if (ATOMISP_USE_YUVPP(asd))
3262 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3263 else
3264 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3265
3266 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3267 ATOMISP_CSS_VF_FRAME, pipe_id);
3268 }
3269
3270 int atomisp_css_capture_get_output_raw_frame_info(
3271 struct atomisp_sub_device *asd,
3272 struct atomisp_css_frame_info *info)
3273 {
3274 if (ATOMISP_USE_YUVPP(asd))
3275 return 0;
3276
3277 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3278 ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE);
3279 }
3280
3281 int atomisp_css_copy_get_output_frame_info(
3282 struct atomisp_sub_device *asd,
3283 unsigned int stream_index,
3284 struct atomisp_css_frame_info *info)
3285 {
3286 return __get_frame_info(asd, stream_index, info,
3287 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
3288 }
3289
3290 int atomisp_css_preview_get_output_frame_info(
3291 struct atomisp_sub_device *asd,
3292 struct atomisp_css_frame_info *info)
3293 {
3294 enum ia_css_pipe_id pipe_id;
3295 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3296
3297 if (ATOMISP_USE_YUVPP(asd)) {
3298 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3299 if (asd->continuous_mode->val)
3300 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3301 } else {
3302 pipe_id = IA_CSS_PIPE_ID_PREVIEW;
3303 }
3304
3305 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3306 frame_type, pipe_id);
3307 }
3308
3309 int atomisp_css_capture_get_output_frame_info(
3310 struct atomisp_sub_device *asd,
3311 struct atomisp_css_frame_info *info)
3312 {
3313 enum ia_css_pipe_id pipe_id;
3314
3315 if (ATOMISP_USE_YUVPP(asd))
3316 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3317 else
3318 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3319
3320 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3321 ATOMISP_CSS_OUTPUT_FRAME, pipe_id);
3322 }
3323
3324 int atomisp_css_video_get_output_frame_info(
3325 struct atomisp_sub_device *asd,
3326 struct atomisp_css_frame_info *info)
3327 {
3328 enum ia_css_pipe_id pipe_id;
3329 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3330
3331 if (ATOMISP_USE_YUVPP(asd)) {
3332 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3333 if (asd->continuous_mode->val)
3334 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3335 } else {
3336 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3337 }
3338
3339 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3340 frame_type, pipe_id);
3341 }
3342
3343 int atomisp_css_preview_configure_pp_input(
3344 struct atomisp_sub_device *asd,
3345 unsigned int width, unsigned int height)
3346 {
3347 struct atomisp_stream_env *stream_env =
3348 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3349 __configure_preview_pp_input(asd, width, height,
3350 ATOMISP_USE_YUVPP(asd) ?
3351 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW);
3352
3353 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3354 capt_pp_in_res.width)
3355 __configure_capture_pp_input(asd, width, height,
3356 ATOMISP_USE_YUVPP(asd) ?
3357 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3358 return 0;
3359 }
3360
3361 int atomisp_css_capture_configure_pp_input(
3362 struct atomisp_sub_device *asd,
3363 unsigned int width, unsigned int height)
3364 {
3365 __configure_capture_pp_input(asd, width, height,
3366 ATOMISP_USE_YUVPP(asd) ?
3367 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3368 return 0;
3369 }
3370
3371 int atomisp_css_video_configure_pp_input(
3372 struct atomisp_sub_device *asd,
3373 unsigned int width, unsigned int height)
3374 {
3375 struct atomisp_stream_env *stream_env =
3376 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3377
3378 __configure_video_pp_input(asd, width, height,
3379 ATOMISP_USE_YUVPP(asd) ?
3380 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO);
3381
3382 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3383 capt_pp_in_res.width)
3384 __configure_capture_pp_input(asd, width, height,
3385 ATOMISP_USE_YUVPP(asd) ?
3386 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3387 return 0;
3388 }
3389
3390 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
3391 int num_captures, unsigned int skip, int offset)
3392 {
3393 enum ia_css_err ret;
3394
3395 #ifdef ISP2401
3396 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
3397 __func__, num_captures, skip, offset);
3398 #endif
3399 ret = ia_css_stream_capture(
3400 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3401 num_captures, skip, offset);
3402 if (ret != IA_CSS_SUCCESS)
3403 return -EINVAL;
3404
3405 return 0;
3406 }
3407
3408 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
3409 {
3410 enum ia_css_err ret;
3411
3412 ret = ia_css_stream_capture_frame(
3413 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3414 exp_id);
3415 if (ret == IA_CSS_ERR_QUEUE_IS_FULL) {
3416 /* capture cmd queue is full */
3417 return -EBUSY;
3418 } else if (ret != IA_CSS_SUCCESS) {
3419 return -EIO;
3420 }
3421
3422 return 0;
3423 }
3424
3425 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
3426 {
3427 enum ia_css_err ret;
3428
3429 ret = ia_css_unlock_raw_frame(
3430 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3431 exp_id);
3432 if (ret == IA_CSS_ERR_QUEUE_IS_FULL)
3433 return -EAGAIN;
3434 else if (ret != IA_CSS_SUCCESS)
3435 return -EIO;
3436
3437 return 0;
3438 }
3439
3440 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
3441 bool enable)
3442 {
3443 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3444 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
3445 .default_capture_config.enable_xnr = enable;
3446 asd->params.capture_config.enable_xnr = enable;
3447 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3448 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
3449
3450 return 0;
3451 }
3452
3453 void atomisp_css_send_input_frame(struct atomisp_sub_device *asd,
3454 unsigned short *data, unsigned int width,
3455 unsigned int height)
3456 {
3457 ia_css_stream_send_input_frame(
3458 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3459 data, width, height);
3460 }
3461
3462 bool atomisp_css_isp_has_started(void)
3463 {
3464 return ia_css_isp_has_started();
3465 }
3466
3467 void atomisp_css_request_flash(struct atomisp_sub_device *asd)
3468 {
3469 ia_css_stream_request_flash(
3470 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream);
3471 }
3472
3473 void atomisp_css_set_wb_config(struct atomisp_sub_device *asd,
3474 struct atomisp_css_wb_config *wb_config)
3475 {
3476 asd->params.config.wb_config = wb_config;
3477 }
3478
3479 void atomisp_css_set_ob_config(struct atomisp_sub_device *asd,
3480 struct atomisp_css_ob_config *ob_config)
3481 {
3482 asd->params.config.ob_config = ob_config;
3483 }
3484
3485 void atomisp_css_set_dp_config(struct atomisp_sub_device *asd,
3486 struct atomisp_css_dp_config *dp_config)
3487 {
3488 asd->params.config.dp_config = dp_config;
3489 }
3490
3491 void atomisp_css_set_de_config(struct atomisp_sub_device *asd,
3492 struct atomisp_css_de_config *de_config)
3493 {
3494 asd->params.config.de_config = de_config;
3495 }
3496
3497 void atomisp_css_set_dz_config(struct atomisp_sub_device *asd,
3498 struct atomisp_css_dz_config *dz_config)
3499 {
3500 asd->params.config.dz_config = dz_config;
3501 }
3502
3503 void atomisp_css_set_default_de_config(struct atomisp_sub_device *asd)
3504 {
3505 asd->params.config.de_config = NULL;
3506 }
3507
3508 void atomisp_css_set_ce_config(struct atomisp_sub_device *asd,
3509 struct atomisp_css_ce_config *ce_config)
3510 {
3511 asd->params.config.ce_config = ce_config;
3512 }
3513
3514 void atomisp_css_set_nr_config(struct atomisp_sub_device *asd,
3515 struct atomisp_css_nr_config *nr_config)
3516 {
3517 asd->params.config.nr_config = nr_config;
3518 }
3519
3520 void atomisp_css_set_ee_config(struct atomisp_sub_device *asd,
3521 struct atomisp_css_ee_config *ee_config)
3522 {
3523 asd->params.config.ee_config = ee_config;
3524 }
3525
3526 void atomisp_css_set_tnr_config(struct atomisp_sub_device *asd,
3527 struct atomisp_css_tnr_config *tnr_config)
3528 {
3529 asd->params.config.tnr_config = tnr_config;
3530 }
3531
3532 void atomisp_css_set_cc_config(struct atomisp_sub_device *asd,
3533 struct atomisp_css_cc_config *cc_config)
3534 {
3535 asd->params.config.cc_config = cc_config;
3536 }
3537
3538 void atomisp_css_set_macc_table(struct atomisp_sub_device *asd,
3539 struct atomisp_css_macc_table *macc_table)
3540 {
3541 asd->params.config.macc_table = macc_table;
3542 }
3543
3544 void atomisp_css_set_macc_config(struct atomisp_sub_device *asd,
3545 struct atomisp_css_macc_config *macc_config)
3546 {
3547 asd->params.config.macc_config = macc_config;
3548 }
3549
3550 void atomisp_css_set_ecd_config(struct atomisp_sub_device *asd,
3551 struct atomisp_css_ecd_config *ecd_config)
3552 {
3553 asd->params.config.ecd_config = ecd_config;
3554 }
3555
3556 void atomisp_css_set_ynr_config(struct atomisp_sub_device *asd,
3557 struct atomisp_css_ynr_config *ynr_config)
3558 {
3559 asd->params.config.ynr_config = ynr_config;
3560 }
3561
3562 void atomisp_css_set_fc_config(struct atomisp_sub_device *asd,
3563 struct atomisp_css_fc_config *fc_config)
3564 {
3565 asd->params.config.fc_config = fc_config;
3566 }
3567
3568 void atomisp_css_set_ctc_config(struct atomisp_sub_device *asd,
3569 struct atomisp_css_ctc_config *ctc_config)
3570 {
3571 asd->params.config.ctc_config = ctc_config;
3572 }
3573
3574 void atomisp_css_set_cnr_config(struct atomisp_sub_device *asd,
3575 struct atomisp_css_cnr_config *cnr_config)
3576 {
3577 asd->params.config.cnr_config = cnr_config;
3578 }
3579
3580 void atomisp_css_set_aa_config(struct atomisp_sub_device *asd,
3581 struct atomisp_css_aa_config *aa_config)
3582 {
3583 asd->params.config.aa_config = aa_config;
3584 }
3585
3586 void atomisp_css_set_baa_config(struct atomisp_sub_device *asd,
3587 struct atomisp_css_baa_config *baa_config)
3588 {
3589 asd->params.config.baa_config = baa_config;
3590 }
3591
3592 void atomisp_css_set_anr_config(struct atomisp_sub_device *asd,
3593 struct atomisp_css_anr_config *anr_config)
3594 {
3595 asd->params.config.anr_config = anr_config;
3596 }
3597
3598 void atomisp_css_set_xnr_config(struct atomisp_sub_device *asd,
3599 struct atomisp_css_xnr_config *xnr_config)
3600 {
3601 asd->params.config.xnr_config = xnr_config;
3602 }
3603
3604 void atomisp_css_set_yuv2rgb_cc_config(struct atomisp_sub_device *asd,
3605 struct atomisp_css_cc_config *yuv2rgb_cc_config)
3606 {
3607 asd->params.config.yuv2rgb_cc_config = yuv2rgb_cc_config;
3608 }
3609
3610 void atomisp_css_set_rgb2yuv_cc_config(struct atomisp_sub_device *asd,
3611 struct atomisp_css_cc_config *rgb2yuv_cc_config)
3612 {
3613 asd->params.config.rgb2yuv_cc_config = rgb2yuv_cc_config;
3614 }
3615
3616 void atomisp_css_set_xnr_table(struct atomisp_sub_device *asd,
3617 struct atomisp_css_xnr_table *xnr_table)
3618 {
3619 asd->params.config.xnr_table = xnr_table;
3620 }
3621
3622 void atomisp_css_set_r_gamma_table(struct atomisp_sub_device *asd,
3623 struct atomisp_css_rgb_gamma_table *r_gamma_table)
3624 {
3625 asd->params.config.r_gamma_table = r_gamma_table;
3626 }
3627
3628 void atomisp_css_set_g_gamma_table(struct atomisp_sub_device *asd,
3629 struct atomisp_css_rgb_gamma_table *g_gamma_table)
3630 {
3631 asd->params.config.g_gamma_table = g_gamma_table;
3632 }
3633
3634 void atomisp_css_set_b_gamma_table(struct atomisp_sub_device *asd,
3635 struct atomisp_css_rgb_gamma_table *b_gamma_table)
3636 {
3637 asd->params.config.b_gamma_table = b_gamma_table;
3638 }
3639
3640 void atomisp_css_set_gamma_table(struct atomisp_sub_device *asd,
3641 struct atomisp_css_gamma_table *gamma_table)
3642 {
3643 asd->params.config.gamma_table = gamma_table;
3644 }
3645
3646 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
3647 struct atomisp_css_ctc_table *ctc_table)
3648 {
3649 int i;
3650 uint16_t *vamem_ptr = ctc_table->data.vamem_1;
3651 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
3652 bool valid = false;
3653
3654 /* workaround: if ctc_table is all 0, do not apply it */
3655 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
3656 vamem_ptr = ctc_table->data.vamem_2;
3657 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
3658 }
3659
3660 for (i = 0; i < data_size; i++) {
3661 if (*(vamem_ptr + i)) {
3662 valid = true;
3663 break;
3664 }
3665 }
3666
3667 if (valid)
3668 asd->params.config.ctc_table = ctc_table;
3669 else
3670 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
3671 }
3672
3673 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
3674 struct atomisp_css_anr_thres *anr_thres)
3675 {
3676 asd->params.config.anr_thres = anr_thres;
3677 }
3678
3679 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
3680 struct atomisp_css_dvs_6axis *dvs_6axis)
3681 {
3682 asd->params.config.dvs_6axis_config = dvs_6axis;
3683 }
3684
3685 void atomisp_css_set_gc_config(struct atomisp_sub_device *asd,
3686 struct atomisp_css_gc_config *gc_config)
3687 {
3688 asd->params.config.gc_config = gc_config;
3689 }
3690
3691 void atomisp_css_set_3a_config(struct atomisp_sub_device *asd,
3692 struct atomisp_css_3a_config *s3a_config)
3693 {
3694 asd->params.config.s3a_config = s3a_config;
3695 }
3696
3697 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
3698 struct atomisp_dis_vector *vector)
3699 {
3700 if (!asd->params.config.motion_vector)
3701 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
3702
3703 memset(asd->params.config.motion_vector,
3704 0, sizeof(struct ia_css_vector));
3705 asd->params.css_param.motion_vector.x = vector->x;
3706 asd->params.css_param.motion_vector.y = vector->y;
3707 }
3708
3709 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
3710 struct atomisp_dvs_grid_info *atomgrid)
3711 {
3712 struct atomisp_css_dvs_grid_info *cur =
3713 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
3714
3715 if (!cur) {
3716 dev_err(asd->isp->dev, "dvs grid not available!\n");
3717 return -EINVAL;
3718 }
3719
3720 if (sizeof(*cur) != sizeof(*atomgrid)) {
3721 dev_err(asd->isp->dev, "dvs grid mis-match!\n");
3722 return -EINVAL;
3723 }
3724
3725 if (!cur->enable) {
3726 dev_err(asd->isp->dev, "dvs not enabled!\n");
3727 return -EINVAL;
3728 }
3729
3730 return memcmp(atomgrid, cur, sizeof(*cur));
3731 }
3732
3733 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
3734 struct ia_css_dvs2_coefficients *coefs)
3735 {
3736 asd->params.config.dvs2_coefs = coefs;
3737 }
3738
3739 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
3740 struct atomisp_dis_coefficients *coefs)
3741 {
3742 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
3743 /* If the grid info in the argument differs from the current
3744 grid info, we tell the caller to reset the grid size and
3745 try again. */
3746 return -EAGAIN;
3747
3748 if (coefs->hor_coefs.odd_real == NULL ||
3749 coefs->hor_coefs.odd_imag == NULL ||
3750 coefs->hor_coefs.even_real == NULL ||
3751 coefs->hor_coefs.even_imag == NULL ||
3752 coefs->ver_coefs.odd_real == NULL ||
3753 coefs->ver_coefs.odd_imag == NULL ||
3754 coefs->ver_coefs.even_real == NULL ||
3755 coefs->ver_coefs.even_imag == NULL ||
3756 asd->params.css_param.dvs2_coeff->hor_coefs.odd_real == NULL ||
3757 asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag == NULL ||
3758 asd->params.css_param.dvs2_coeff->hor_coefs.even_real == NULL ||
3759 asd->params.css_param.dvs2_coeff->hor_coefs.even_imag == NULL ||
3760 asd->params.css_param.dvs2_coeff->ver_coefs.odd_real == NULL ||
3761 asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag == NULL ||
3762 asd->params.css_param.dvs2_coeff->ver_coefs.even_real == NULL ||
3763 asd->params.css_param.dvs2_coeff->ver_coefs.even_imag == NULL)
3764 return -EINVAL;
3765
3766 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
3767 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
3768 return -EFAULT;
3769 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
3770 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
3771 return -EFAULT;
3772 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
3773 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
3774 return -EFAULT;
3775 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
3776 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
3777 return -EFAULT;
3778
3779 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
3780 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
3781 return -EFAULT;
3782 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
3783 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
3784 return -EFAULT;
3785 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
3786 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
3787 return -EFAULT;
3788 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
3789 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
3790 return -EFAULT;
3791
3792 asd->params.css_param.update_flag.dvs2_coefs =
3793 (struct atomisp_dvs2_coefficients *)
3794 asd->params.css_param.dvs2_coeff;
3795 /* FIXME! */
3796 /* asd->params.dis_proj_data_valid = false; */
3797 asd->params.css_update_params_needed = true;
3798
3799 return 0;
3800 }
3801
3802 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
3803 unsigned int zoom)
3804 {
3805 struct atomisp_device *isp = asd->isp;
3806
3807 if (zoom == asd->params.css_param.dz_config.dx &&
3808 zoom == asd->params.css_param.dz_config.dy) {
3809 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
3810 return;
3811 }
3812
3813 memset(&asd->params.css_param.dz_config, 0,
3814 sizeof(struct ia_css_dz_config));
3815 asd->params.css_param.dz_config.dx = zoom;
3816 asd->params.css_param.dz_config.dy = zoom;
3817
3818 asd->params.css_param.update_flag.dz_config =
3819 (struct atomisp_dz_config *) &asd->params.css_param.dz_config;
3820 asd->params.css_update_params_needed = true;
3821 }
3822
3823 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
3824 struct atomisp_css_formats_config *formats_config)
3825 {
3826 asd->params.config.formats_config = formats_config;
3827 }
3828
3829 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
3830 struct atomisp_wb_config *config)
3831 {
3832 struct atomisp_css_wb_config wb_config;
3833 struct ia_css_isp_config isp_config;
3834 struct atomisp_device *isp = asd->isp;
3835
3836 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3837 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3838 __func__);
3839 return -EINVAL;
3840 }
3841 memset(&wb_config, 0, sizeof(struct atomisp_css_wb_config));
3842 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3843 isp_config.wb_config = &wb_config;
3844 ia_css_stream_get_isp_config(
3845 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3846 &isp_config);
3847 memcpy(config, &wb_config, sizeof(*config));
3848
3849 return 0;
3850 }
3851
3852 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
3853 struct atomisp_ob_config *config)
3854 {
3855 struct atomisp_css_ob_config ob_config;
3856 struct ia_css_isp_config isp_config;
3857 struct atomisp_device *isp = asd->isp;
3858
3859 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3860 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3861 __func__);
3862 return -EINVAL;
3863 }
3864 memset(&ob_config, 0, sizeof(struct atomisp_css_ob_config));
3865 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3866 isp_config.ob_config = &ob_config;
3867 ia_css_stream_get_isp_config(
3868 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3869 &isp_config);
3870 memcpy(config, &ob_config, sizeof(*config));
3871
3872 return 0;
3873 }
3874
3875 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
3876 struct atomisp_dp_config *config)
3877 {
3878 struct atomisp_css_dp_config dp_config;
3879 struct ia_css_isp_config isp_config;
3880 struct atomisp_device *isp = asd->isp;
3881
3882 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3883 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3884 __func__);
3885 return -EINVAL;
3886 }
3887 memset(&dp_config, 0, sizeof(struct atomisp_css_dp_config));
3888 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3889 isp_config.dp_config = &dp_config;
3890 ia_css_stream_get_isp_config(
3891 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3892 &isp_config);
3893 memcpy(config, &dp_config, sizeof(*config));
3894
3895 return 0;
3896 }
3897
3898 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3899 struct atomisp_de_config *config)
3900 {
3901 struct atomisp_css_de_config de_config;
3902 struct ia_css_isp_config isp_config;
3903 struct atomisp_device *isp = asd->isp;
3904
3905 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3906 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3907 __func__);
3908 return -EINVAL;
3909 }
3910 memset(&de_config, 0, sizeof(struct atomisp_css_de_config));
3911 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3912 isp_config.de_config = &de_config;
3913 ia_css_stream_get_isp_config(
3914 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3915 &isp_config);
3916 memcpy(config, &de_config, sizeof(*config));
3917
3918 return 0;
3919 }
3920
3921 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3922 struct atomisp_nr_config *config)
3923 {
3924 struct atomisp_css_nr_config nr_config;
3925 struct ia_css_isp_config isp_config;
3926 struct atomisp_device *isp = asd->isp;
3927
3928 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3929 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3930 __func__);
3931 return -EINVAL;
3932 }
3933 memset(&nr_config, 0, sizeof(struct atomisp_css_nr_config));
3934 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3935
3936 isp_config.nr_config = &nr_config;
3937 ia_css_stream_get_isp_config(
3938 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3939 &isp_config);
3940 memcpy(config, &nr_config, sizeof(*config));
3941
3942 return 0;
3943 }
3944
3945 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3946 struct atomisp_ee_config *config)
3947 {
3948 struct atomisp_css_ee_config ee_config;
3949 struct ia_css_isp_config isp_config;
3950 struct atomisp_device *isp = asd->isp;
3951
3952 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3953 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3954 __func__);
3955 return -EINVAL;
3956 }
3957 memset(&ee_config, 0, sizeof(struct atomisp_css_ee_config));
3958 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3959 isp_config.ee_config = &ee_config;
3960 ia_css_stream_get_isp_config(
3961 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3962 &isp_config);
3963 memcpy(config, &ee_config, sizeof(*config));
3964
3965 return 0;
3966 }
3967
3968 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3969 struct atomisp_tnr_config *config)
3970 {
3971 struct atomisp_css_tnr_config tnr_config;
3972 struct ia_css_isp_config isp_config;
3973 struct atomisp_device *isp = asd->isp;
3974
3975 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3976 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3977 __func__);
3978 return -EINVAL;
3979 }
3980 memset(&tnr_config, 0, sizeof(struct atomisp_css_tnr_config));
3981 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3982 isp_config.tnr_config = &tnr_config;
3983 ia_css_stream_get_isp_config(
3984 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3985 &isp_config);
3986 memcpy(config, &tnr_config, sizeof(*config));
3987
3988 return 0;
3989 }
3990
3991 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3992 struct atomisp_ctc_table *config)
3993 {
3994 struct atomisp_css_ctc_table *tab;
3995 struct ia_css_isp_config isp_config;
3996 struct atomisp_device *isp = asd->isp;
3997
3998 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3999 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4000 __func__);
4001 return -EINVAL;
4002 }
4003
4004 tab = vzalloc(sizeof(struct atomisp_css_ctc_table));
4005 if (!tab)
4006 return -ENOMEM;
4007
4008 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4009 isp_config.ctc_table = tab;
4010 ia_css_stream_get_isp_config(
4011 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4012 &isp_config);
4013 memcpy(config, tab, sizeof(*tab));
4014 vfree(tab);
4015
4016 return 0;
4017 }
4018
4019 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
4020 struct atomisp_gamma_table *config)
4021 {
4022 struct atomisp_css_gamma_table *tab;
4023 struct ia_css_isp_config isp_config;
4024 struct atomisp_device *isp = asd->isp;
4025
4026 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4027 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4028 __func__);
4029 return -EINVAL;
4030 }
4031
4032 tab = vzalloc(sizeof(struct atomisp_css_gamma_table));
4033 if (!tab)
4034 return -ENOMEM;
4035
4036 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4037 isp_config.gamma_table = tab;
4038 ia_css_stream_get_isp_config(
4039 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4040 &isp_config);
4041 memcpy(config, tab, sizeof(*tab));
4042 vfree(tab);
4043
4044 return 0;
4045 }
4046
4047 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
4048 struct atomisp_gc_config *config)
4049 {
4050 struct atomisp_css_gc_config gc_config;
4051 struct ia_css_isp_config isp_config;
4052 struct atomisp_device *isp = asd->isp;
4053
4054 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4055 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4056 __func__);
4057 return -EINVAL;
4058 }
4059 memset(&gc_config, 0, sizeof(struct atomisp_css_gc_config));
4060 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4061 isp_config.gc_config = &gc_config;
4062 ia_css_stream_get_isp_config(
4063 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4064 &isp_config);
4065 /* Get gamma correction params from current setup */
4066 memcpy(config, &gc_config, sizeof(*config));
4067
4068 return 0;
4069 }
4070
4071 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
4072 struct atomisp_3a_config *config)
4073 {
4074 struct atomisp_css_3a_config s3a_config;
4075 struct ia_css_isp_config isp_config;
4076 struct atomisp_device *isp = asd->isp;
4077
4078 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4079 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4080 __func__);
4081 return -EINVAL;
4082 }
4083 memset(&s3a_config, 0, sizeof(struct atomisp_css_3a_config));
4084 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4085 isp_config.s3a_config = &s3a_config;
4086 ia_css_stream_get_isp_config(
4087 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4088 &isp_config);
4089 /* Get white balance from current setup */
4090 memcpy(config, &s3a_config, sizeof(*config));
4091
4092 return 0;
4093 }
4094
4095 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
4096 struct atomisp_formats_config *config)
4097 {
4098 struct atomisp_css_formats_config formats_config;
4099 struct ia_css_isp_config isp_config;
4100 struct atomisp_device *isp = asd->isp;
4101
4102 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4103 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4104 __func__);
4105 return -EINVAL;
4106 }
4107 memset(&formats_config, 0, sizeof(formats_config));
4108 memset(&isp_config, 0, sizeof(isp_config));
4109 isp_config.formats_config = &formats_config;
4110 ia_css_stream_get_isp_config(
4111 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4112 &isp_config);
4113 /* Get narrow gamma from current setup */
4114 memcpy(config, &formats_config, sizeof(*config));
4115
4116 return 0;
4117 }
4118
4119 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
4120 unsigned int *zoom)
4121 {
4122 struct ia_css_dz_config dz_config; /**< Digital Zoom */
4123 struct ia_css_isp_config isp_config;
4124 struct atomisp_device *isp = asd->isp;
4125
4126 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4127 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
4128 __func__);
4129 return -EINVAL;
4130 }
4131 memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
4132 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4133 isp_config.dz_config = &dz_config;
4134 ia_css_stream_get_isp_config(
4135 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4136 &isp_config);
4137 *zoom = dz_config.dx;
4138
4139 return 0;
4140 }
4141
4142
4143 /*
4144 * Function to set/get image stablization statistics
4145 */
4146 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
4147 struct atomisp_dis_statistics *stats)
4148 {
4149 struct atomisp_device *isp = asd->isp;
4150 struct atomisp_dis_buf *dis_buf;
4151 unsigned long flags;
4152
4153 if (asd->params.dvs_stat->hor_prod.odd_real == NULL ||
4154 asd->params.dvs_stat->hor_prod.odd_imag == NULL ||
4155 asd->params.dvs_stat->hor_prod.even_real == NULL ||
4156 asd->params.dvs_stat->hor_prod.even_imag == NULL ||
4157 asd->params.dvs_stat->ver_prod.odd_real == NULL ||
4158 asd->params.dvs_stat->ver_prod.odd_imag == NULL ||
4159 asd->params.dvs_stat->ver_prod.even_real == NULL ||
4160 asd->params.dvs_stat->ver_prod.even_imag == NULL)
4161 return -EINVAL;
4162
4163 /* isp needs to be streaming to get DIS statistics */
4164 spin_lock_irqsave(&isp->lock, flags);
4165 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) {
4166 spin_unlock_irqrestore(&isp->lock, flags);
4167 return -EINVAL;
4168 }
4169 spin_unlock_irqrestore(&isp->lock, flags);
4170
4171 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
4172 /* If the grid info in the argument differs from the current
4173 grid info, we tell the caller to reset the grid size and
4174 try again. */
4175 return -EAGAIN;
4176
4177 spin_lock_irqsave(&asd->dis_stats_lock, flags);
4178 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
4179 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4180 dev_err(isp->dev, "dis statistics is not valid.\n");
4181 return -EAGAIN;
4182 }
4183
4184 dis_buf = list_entry(asd->dis_stats.next,
4185 struct atomisp_dis_buf, list);
4186 list_del_init(&dis_buf->list);
4187 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4188
4189 if (dis_buf->dvs_map)
4190 ia_css_translate_dvs2_statistics(
4191 asd->params.dvs_stat, dis_buf->dvs_map);
4192 else
4193 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
4194 dis_buf->dis_data);
4195 stats->exp_id = dis_buf->dis_data->exp_id;
4196
4197 spin_lock_irqsave(&asd->dis_stats_lock, flags);
4198 list_add_tail(&dis_buf->list, &asd->dis_stats);
4199 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
4200
4201 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
4202 asd->params.dvs_stat->ver_prod.odd_real,
4203 asd->params.dvs_ver_proj_bytes))
4204 return -EFAULT;
4205 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
4206 asd->params.dvs_stat->ver_prod.odd_imag,
4207 asd->params.dvs_ver_proj_bytes))
4208 return -EFAULT;
4209 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
4210 asd->params.dvs_stat->ver_prod.even_real,
4211 asd->params.dvs_ver_proj_bytes))
4212 return -EFAULT;
4213 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
4214 asd->params.dvs_stat->ver_prod.even_imag,
4215 asd->params.dvs_ver_proj_bytes))
4216 return -EFAULT;
4217 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
4218 asd->params.dvs_stat->hor_prod.odd_real,
4219 asd->params.dvs_hor_proj_bytes))
4220 return -EFAULT;
4221 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
4222 asd->params.dvs_stat->hor_prod.odd_imag,
4223 asd->params.dvs_hor_proj_bytes))
4224 return -EFAULT;
4225 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
4226 asd->params.dvs_stat->hor_prod.even_real,
4227 asd->params.dvs_hor_proj_bytes))
4228 return -EFAULT;
4229 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
4230 asd->params.dvs_stat->hor_prod.even_imag,
4231 asd->params.dvs_hor_proj_bytes))
4232 return -EFAULT;
4233
4234 return 0;
4235 }
4236
4237 struct atomisp_css_shading_table *atomisp_css_shading_table_alloc(
4238 unsigned int width, unsigned int height)
4239 {
4240 return ia_css_shading_table_alloc(width, height);
4241 }
4242
4243 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
4244 struct atomisp_css_shading_table *table)
4245 {
4246 asd->params.config.shading_table = table;
4247 }
4248
4249 void atomisp_css_shading_table_free(struct atomisp_css_shading_table *table)
4250 {
4251 ia_css_shading_table_free(table);
4252 }
4253
4254 struct atomisp_css_morph_table *atomisp_css_morph_table_allocate(
4255 unsigned int width, unsigned int height)
4256 {
4257 return ia_css_morph_table_allocate(width, height);
4258 }
4259
4260 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
4261 struct atomisp_css_morph_table *table)
4262 {
4263 asd->params.config.morph_table = table;
4264 }
4265
4266 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
4267 struct atomisp_css_morph_table *table)
4268 {
4269 struct ia_css_isp_config isp_config;
4270 struct atomisp_device *isp = asd->isp;
4271
4272 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
4273 dev_err(isp->dev,
4274 "%s called after streamoff, skipping.\n", __func__);
4275 return;
4276 }
4277 memset(table, 0, sizeof(struct atomisp_css_morph_table));
4278 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
4279 isp_config.morph_table = table;
4280 ia_css_stream_get_isp_config(
4281 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4282 &isp_config);
4283 }
4284
4285 void atomisp_css_morph_table_free(struct atomisp_css_morph_table *table)
4286 {
4287 ia_css_morph_table_free(table);
4288 }
4289
4290 void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp,
4291 unsigned int overlap)
4292 {
4293 /* CSS 2.0 doesn't support this API. */
4294 dev_dbg(isp->dev, "set cont prev start time is not supported.\n");
4295 return;
4296 }
4297
4298 void atomisp_css_acc_done(struct atomisp_sub_device *asd)
4299 {
4300 complete(&asd->acc.acc_done);
4301 }
4302
4303 int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd)
4304 {
4305 int ret = 0;
4306 struct atomisp_device *isp = asd->isp;
4307
4308 /* Unlock the isp mutex taken in IOCTL handler before sleeping! */
4309 rt_mutex_unlock(&isp->mutex);
4310 if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done,
4311 ATOMISP_ISP_TIMEOUT_DURATION) == 0) {
4312 dev_err(isp->dev, "<%s: completion timeout\n", __func__);
4313 atomisp_css_debug_dump_sp_sw_debug_info();
4314 atomisp_css_debug_dump_debug_info(__func__);
4315 ret = -EIO;
4316 }
4317 rt_mutex_lock(&isp->mutex);
4318
4319 return ret;
4320 }
4321
4322 /* Set the ACC binary arguments */
4323 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw)
4324 {
4325 unsigned int mem;
4326
4327 for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) {
4328 if (acc_fw->args[mem].length == 0)
4329 continue;
4330
4331 ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers,
4332 IA_CSS_PARAM_CLASS_PARAM, mem,
4333 acc_fw->args[mem].css_ptr,
4334 acc_fw->args[mem].length);
4335 }
4336
4337 return 0;
4338 }
4339
4340 /* Load acc binary extension */
4341 int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd,
4342 struct atomisp_css_fw_info *fw,
4343 enum atomisp_css_pipe_id pipe_id,
4344 unsigned int type)
4345 {
4346 struct atomisp_css_fw_info **hd;
4347
4348 fw->next = NULL;
4349 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4350 .pipe_configs[pipe_id].acc_extension);
4351 while (*hd)
4352 hd = &(*hd)->next;
4353 *hd = fw;
4354
4355 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4356 .update_pipe[pipe_id] = true;
4357 return 0;
4358 }
4359
4360 /* Unload acc binary extension */
4361 void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd,
4362 struct atomisp_css_fw_info *fw,
4363 enum atomisp_css_pipe_id pipe_id)
4364 {
4365 struct atomisp_css_fw_info **hd;
4366
4367 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4368 .pipe_configs[pipe_id].acc_extension);
4369 while (*hd && *hd != fw)
4370 hd = &(*hd)->next;
4371 if (!*hd) {
4372 dev_err(asd->isp->dev, "did not find acc fw for removal\n");
4373 return;
4374 }
4375 *hd = fw->next;
4376 fw->next = NULL;
4377
4378 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4379 .update_pipe[pipe_id] = true;
4380 }
4381
4382 int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd)
4383 {
4384 struct atomisp_device *isp = asd->isp;
4385 struct ia_css_pipe_config *pipe_config;
4386 struct atomisp_stream_env *stream_env =
4387 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4388
4389 if (stream_env->acc_stream) {
4390 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4391 if (ia_css_stream_stop(stream_env->acc_stream)
4392 != IA_CSS_SUCCESS) {
4393 dev_err(isp->dev, "stop acc_stream failed.\n");
4394 return -EBUSY;
4395 }
4396 }
4397
4398 if (ia_css_stream_destroy(stream_env->acc_stream)
4399 != IA_CSS_SUCCESS) {
4400 dev_err(isp->dev, "destroy acc_stream failed.\n");
4401 return -EBUSY;
4402 }
4403 stream_env->acc_stream = NULL;
4404 }
4405
4406 pipe_config = &stream_env->pipe_configs[CSS_PIPE_ID_ACC];
4407 ia_css_pipe_config_defaults(pipe_config);
4408 asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES *
4409 sizeof(void *), GFP_KERNEL);
4410 if (!asd->acc.acc_stages)
4411 return -ENOMEM;
4412 pipe_config->acc_stages = asd->acc.acc_stages;
4413 pipe_config->mode = IA_CSS_PIPE_MODE_ACC;
4414 pipe_config->num_acc_stages = 0;
4415
4416 /*
4417 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe,
4418 * because pipe configuration will soon be changed by
4419 * atomisp_css_load_acc_binary()
4420 */
4421 return 0;
4422 }
4423
4424 int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd)
4425 {
4426 struct atomisp_device *isp = asd->isp;
4427 struct atomisp_stream_env *stream_env =
4428 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4429 struct ia_css_pipe_config *pipe_config =
4430 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
4431
4432 if (ia_css_pipe_create(pipe_config,
4433 &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != IA_CSS_SUCCESS) {
4434 dev_err(isp->dev, "%s: ia_css_pipe_create failed\n",
4435 __func__);
4436 return -EBADE;
4437 }
4438
4439 memset(&stream_env->acc_stream_config, 0,
4440 sizeof(struct ia_css_stream_config));
4441 if (ia_css_stream_create(&stream_env->acc_stream_config, 1,
4442 &stream_env->pipes[IA_CSS_PIPE_ID_ACC],
4443 &stream_env->acc_stream) != IA_CSS_SUCCESS) {
4444 dev_err(isp->dev, "%s: create acc_stream error.\n", __func__);
4445 return -EINVAL;
4446 }
4447 stream_env->acc_stream_state = CSS_STREAM_CREATED;
4448
4449 init_completion(&asd->acc.acc_done);
4450 asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC];
4451
4452 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
4453
4454 if (ia_css_start_sp() != IA_CSS_SUCCESS) {
4455 dev_err(isp->dev, "start sp error.\n");
4456 return -EIO;
4457 }
4458
4459 if (ia_css_stream_start(stream_env->acc_stream)
4460 != IA_CSS_SUCCESS) {
4461 dev_err(isp->dev, "acc_stream start error.\n");
4462 return -EIO;
4463 }
4464
4465 stream_env->acc_stream_state = CSS_STREAM_STARTED;
4466 return 0;
4467 }
4468
4469 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd)
4470 {
4471 struct atomisp_stream_env *stream_env =
4472 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4473 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4474 ia_css_stream_stop(stream_env->acc_stream);
4475 stream_env->acc_stream_state = CSS_STREAM_STOPPED;
4476 }
4477 return 0;
4478 }
4479
4480 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd)
4481 {
4482 struct atomisp_stream_env *stream_env =
4483 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4484 if (stream_env->acc_stream) {
4485 if (ia_css_stream_destroy(stream_env->acc_stream)
4486 != IA_CSS_SUCCESS)
4487 dev_warn(asd->isp->dev,
4488 "destroy acc_stream failed.\n");
4489 stream_env->acc_stream = NULL;
4490 }
4491
4492 if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) {
4493 if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC])
4494 != IA_CSS_SUCCESS)
4495 dev_warn(asd->isp->dev,
4496 "destroy ACC pipe failed.\n");
4497 stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL;
4498 stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false;
4499 ia_css_pipe_config_defaults(
4500 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]);
4501 ia_css_pipe_extra_config_defaults(
4502 &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]);
4503 }
4504 asd->acc.pipeline = NULL;
4505
4506 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
4507 * destroy all pipes
4508 */
4509 ia_css_stop_sp();
4510
4511 kfree(asd->acc.acc_stages);
4512 asd->acc.acc_stages = NULL;
4513
4514 atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false);
4515 }
4516
4517 int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd,
4518 struct atomisp_css_fw_info *fw,
4519 unsigned int index)
4520 {
4521 struct ia_css_pipe_config *pipe_config =
4522 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4523 .pipe_configs[IA_CSS_PIPE_ID_ACC];
4524
4525 if (index >= MAX_ACC_STAGES) {
4526 dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n",
4527 __func__, index);
4528 return -ENOMEM;
4529 }
4530
4531 pipe_config->acc_stages[index] = fw;
4532 pipe_config->num_acc_stages = index + 1;
4533 pipe_config->acc_num_execs = 1;
4534
4535 return 0;
4536 }
4537
4538 static struct atomisp_sub_device *__get_atomisp_subdev(
4539 struct ia_css_pipe *css_pipe,
4540 struct atomisp_device *isp,
4541 enum atomisp_input_stream_id *stream_id) {
4542 int i, j, k;
4543 struct atomisp_sub_device *asd;
4544 struct atomisp_stream_env *stream_env;
4545
4546 for (i = 0; i < isp->num_of_streams; i++) {
4547 asd = &isp->asd[i];
4548 if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED &&
4549 !asd->acc.pipeline)
4550 continue;
4551 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4552 stream_env = &asd->stream_env[j];
4553 for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
4554 if (stream_env->pipes[k] &&
4555 stream_env->pipes[k] == css_pipe) {
4556 *stream_id = j;
4557 return asd;
4558 }
4559 }
4560 }
4561 }
4562
4563 return NULL;
4564 }
4565
4566 int atomisp_css_isr_thread(struct atomisp_device *isp,
4567 bool *frame_done_found,
4568 bool *css_pipe_done)
4569 {
4570 enum atomisp_input_stream_id stream_id = 0;
4571 struct atomisp_css_event current_event;
4572 struct atomisp_sub_device *asd = &isp->asd[0];
4573 #ifndef ISP2401
4574 bool reset_wdt_timer[MAX_STREAM_NUM] = {false};
4575 #endif
4576 int i;
4577
4578 while (!atomisp_css_dequeue_event(&current_event)) {
4579 if (current_event.event.type ==
4580 IA_CSS_EVENT_TYPE_FW_ASSERT) {
4581 /*
4582 * Received FW assertion signal,
4583 * trigger WDT to recover
4584 */
4585 dev_err(isp->dev, "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
4586 __func__,
4587 current_event.event.fw_assert_module_id,
4588 current_event.event.fw_assert_line_no);
4589 for (i = 0; i < isp->num_of_streams; i++)
4590 atomisp_wdt_stop(&isp->asd[i], 0);
4591 #ifndef ISP2401
4592 atomisp_wdt((unsigned long)isp);
4593 #else
4594 queue_work(isp->wdt_work_queue, &isp->wdt_work);
4595 #endif
4596 return -EINVAL;
4597 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4598 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
4599 __func__, current_event.event.fw_warning,
4600 current_event.event.exp_id);
4601 continue;
4602 }
4603
4604 asd = __get_atomisp_subdev(current_event.event.pipe,
4605 isp, &stream_id);
4606 if (!asd) {
4607 if (current_event.event.type == CSS_EVENT_TIMER)
4608 dev_dbg(isp->dev,
4609 "event: Timer event.");
4610 else
4611 dev_warn(isp->dev, "%s:no subdev.event:%d",
4612 __func__,
4613 current_event.event.type);
4614 continue;
4615 }
4616
4617 atomisp_css_temp_pipe_to_pipe_id(asd, &current_event);
4618 switch (current_event.event.type) {
4619 case CSS_EVENT_OUTPUT_FRAME_DONE:
4620 frame_done_found[asd->index] = true;
4621 atomisp_buf_done(asd, 0, CSS_BUFFER_TYPE_OUTPUT_FRAME,
4622 current_event.pipe, true, stream_id);
4623 #ifndef ISP2401
4624 reset_wdt_timer[asd->index] = true; /* ISP running */
4625 #endif
4626 break;
4627 case CSS_EVENT_SEC_OUTPUT_FRAME_DONE:
4628 frame_done_found[asd->index] = true;
4629 atomisp_buf_done(asd, 0, CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
4630 current_event.pipe, true, stream_id);
4631 #ifndef ISP2401
4632 reset_wdt_timer[asd->index] = true; /* ISP running */
4633 #endif
4634 break;
4635 case CSS_EVENT_3A_STATISTICS_DONE:
4636 atomisp_buf_done(asd, 0,
4637 CSS_BUFFER_TYPE_3A_STATISTICS,
4638 current_event.pipe,
4639 false, stream_id);
4640 break;
4641 case CSS_EVENT_METADATA_DONE:
4642 atomisp_buf_done(asd, 0,
4643 CSS_BUFFER_TYPE_METADATA,
4644 current_event.pipe,
4645 false, stream_id);
4646 break;
4647 case CSS_EVENT_VF_OUTPUT_FRAME_DONE:
4648 atomisp_buf_done(asd, 0,
4649 CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
4650 current_event.pipe, true, stream_id);
4651 #ifndef ISP2401
4652 reset_wdt_timer[asd->index] = true; /* ISP running */
4653 #endif
4654 break;
4655 case CSS_EVENT_SEC_VF_OUTPUT_FRAME_DONE:
4656 atomisp_buf_done(asd, 0,
4657 CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
4658 current_event.pipe, true, stream_id);
4659 #ifndef ISP2401
4660 reset_wdt_timer[asd->index] = true; /* ISP running */
4661 #endif
4662 break;
4663 case CSS_EVENT_DIS_STATISTICS_DONE:
4664 atomisp_buf_done(asd, 0,
4665 CSS_BUFFER_TYPE_DIS_STATISTICS,
4666 current_event.pipe,
4667 false, stream_id);
4668 break;
4669 case CSS_EVENT_PIPELINE_DONE:
4670 css_pipe_done[asd->index] = true;
4671 break;
4672 case CSS_EVENT_ACC_STAGE_COMPLETE:
4673 atomisp_acc_done(asd, current_event.event.fw_handle);
4674 break;
4675 default:
4676 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
4677 current_event.event.type);
4678 break;
4679 }
4680 }
4681 #ifndef ISP2401
4682 /* If there are no buffers queued then
4683 * delete wdt timer. */
4684 for (i = 0; i < isp->num_of_streams; i++) {
4685 asd = &isp->asd[i];
4686 if (!asd)
4687 continue;
4688 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
4689 continue;
4690 if (!atomisp_buffers_queued(asd))
4691 atomisp_wdt_stop(asd, false);
4692 else if (reset_wdt_timer[i])
4693 /* SOF irq should not reset wdt timer. */
4694 atomisp_wdt_refresh(asd,
4695 ATOMISP_WDT_KEEP_CURRENT_DELAY);
4696 }
4697 #endif
4698
4699 return 0;
4700 }
4701
4702 void atomisp_set_stop_timeout(unsigned int timeout)
4703 {
4704 return;
4705 }
4706
4707 bool atomisp_css_valid_sof(struct atomisp_device *isp)
4708 {
4709 unsigned int i, j;
4710
4711 /* Loop for each css stream */
4712 for (i = 0; i < isp->num_of_streams; i++) {
4713 struct atomisp_sub_device *asd = &isp->asd[i];
4714 /* Loop for each css vc stream */
4715 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4716 if (asd->stream_env[j].stream &&
4717 asd->stream_env[j].stream_config.mode ==
4718 IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
4719 return false;
4720 }
4721 }
4722
4723 return true;
4724 }
4725
4726 int atomisp_css_debug_dump_isp_binary(void)
4727 {
4728 ia_css_debug_dump_isp_binary();
4729 return 0;
4730 }
4731
4732 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
4733 {
4734 sh_css_dump_sp_raw_copy_linecount(reduced);
4735 return 0;
4736 }
4737
4738 int atomisp_css_dump_blob_infor(void)
4739 {
4740 struct ia_css_blob_descr *bd = sh_css_blob_info;
4741 unsigned i, nm = sh_css_num_binaries;
4742
4743 if (nm == 0)
4744 return -EPERM;
4745 if (bd == NULL)
4746 return -EPERM;
4747
4748 for (i = 1; i < sh_css_num_binaries; i++)
4749 dev_dbg(atomisp_dev, "Num%d binary id is %d, name is %s\n", i,
4750 bd[i-1].header.info.isp.sp.id, bd[i-1].name);
4751
4752 return 0;
4753 }
4754
4755 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
4756 uint32_t isp_config_id)
4757 {
4758 asd->params.config.isp_config_id = isp_config_id;
4759 }
4760
4761 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
4762 struct atomisp_css_frame *output_frame)
4763 {
4764 asd->params.config.output_frame = output_frame;
4765 }
4766
4767 int atomisp_get_css_dbgfunc(void)
4768 {
4769 return dbg_func;
4770 }
4771
4772 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
4773 {
4774 int ret;
4775
4776 ret = __set_css_print_env(isp, opt);
4777 if (0 == ret)
4778 dbg_func = opt;
4779
4780 return ret;
4781 }
4782 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
4783 {
4784 ia_css_en_dz_capt_pipe(
4785 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4786 enable);
4787 }
4788
4789 struct atomisp_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
4790 struct atomisp_css_grid_info *grid_info)
4791 {
4792 if (!grid_info)
4793 return NULL;
4794
4795 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
4796 return &grid_info->dvs_grid.dvs_grid_info;
4797 #else
4798 return &grid_info->dvs_grid;
4799 #endif
4800 }