1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2015, Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15
16 /*! \file */
17 #include <linux/mm.h>
18 #include <linux/slab.h>
19 #include <linux/vmalloc.h>
20
21 #include "hmm.h"
22
23 #include "atomisp_internal.h"
24
25 #include "ia_css.h"
26 #include "sh_css_hrt.h" /* only for file 2 MIPI */
27 #include "ia_css_buffer.h"
28 #include "ia_css_binary.h"
29 #include "sh_css_internal.h"
30 #include "sh_css_mipi.h"
31 #include "sh_css_sp.h" /* sh_css_sp_group */
32 #include "ia_css_isys.h"
33 #include "ia_css_frame.h"
34 #include "sh_css_defs.h"
35 #include "sh_css_firmware.h"
36 #include "sh_css_params.h"
37 #include "sh_css_params_internal.h"
38 #include "sh_css_param_shading.h"
39 #include "ia_css_refcount.h"
40 #include "ia_css_rmgr.h"
41 #include "ia_css_debug.h"
42 #include "ia_css_debug_pipe.h"
43 #include "ia_css_device_access.h"
44 #include "device_access.h"
45 #include "sh_css_legacy.h"
46 #include "ia_css_pipeline.h"
47 #include "ia_css_stream.h"
48 #include "sh_css_stream_format.h"
49 #include "ia_css_pipe.h"
50 #include "ia_css_util.h"
51 #include "ia_css_pipe_util.h"
52 #include "ia_css_pipe_binarydesc.h"
53 #include "ia_css_pipe_stagedesc.h"
54
55 #include "tag.h"
56 #include "assert_support.h"
57 #include "math_support.h"
58 #include "sw_event_global.h" /* Event IDs.*/
59 #include "ia_css_ifmtr.h"
60 #include "input_system.h"
61 #include "mmu_device.h" /* mmu_set_page_table_base_index(), ... */
62 #include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */
63 #include "gdc_device.h" /* HRT_GDC_N */
64 #include "dma.h" /* dma_set_max_burst_size() */
65 #include "irq.h" /* virq */
66 #include "sp.h" /* cnd_sp_irq_enable() */
67 #include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */
68 #include "gp_device.h" /* gp_device_reg_store() */
69 #define __INLINE_GPIO__
70 #include "gpio.h"
71 #include "timed_ctrl.h"
72 #include "ia_css_inputfifo.h"
73 #define WITH_PC_MONITORING 0
74
75 #define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0
76
77
78 #include "ia_css_spctrl.h"
79 #include "ia_css_version_data.h"
80 #include "sh_css_struct.h"
81 #include "ia_css_bufq.h"
82 #include "ia_css_timer.h" /* clock_value_t */
83
84 #include "isp/modes/interface/input_buf.isp.h"
85
86 /* Name of the sp program: should not be built-in */
87 #define SP_PROG_NAME "sp"
88 /* Size of Refcount List */
89 #define REFCOUNT_SIZE 1000
90
91 /*
92 * for JPEG, we don't know the length of the image upfront,
93 * but since we support sensor up to 16MP, we take this as
94 * upper limit.
95 */
96 #define JPEG_BYTES (16 * 1024 * 1024)
97
98 struct sh_css my_css;
99
100 int __printf(1, 0) (*sh_css_printf)(const char *fmt, va_list args) = NULL;
101
102 /*
103 * modes of work: stream_create and stream_destroy will update the save/restore
104 * data only when in working mode, not suspend/resume
105 */
106 enum ia_sh_css_modes {
107 sh_css_mode_none = 0,
108 sh_css_mode_working,
109 sh_css_mode_suspend,
110 sh_css_mode_resume
111 };
112
113 /**
114 * struct sh_css_stream_seed - a stream seed, to save and restore the
115 * stream data.
116 *
117 * @orig_stream: pointer to restore the original handle
118 * @stream: handle, used as ID too.
119 * @stream_config: stream config struct
120 * @num_pipes: number of pipes
121 * @pipes: pipe handles
122 * @orig_pipes: pointer to restore original handle
123 * @pipe_config: pipe config structs
124 *
125 * the stream seed contains all the data required to "grow" the seed again
126 * after it was closed.
127 */
128 struct sh_css_stream_seed {
129 struct ia_css_stream **orig_stream;
130 struct ia_css_stream *stream;
131 struct ia_css_stream_config stream_config;
132 int num_pipes;
133 struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM];
134 struct ia_css_pipe **orig_pipes[IA_CSS_PIPE_ID_NUM];
135 struct ia_css_pipe_config pipe_config[IA_CSS_PIPE_ID_NUM];
136 };
137
138 #define MAX_ACTIVE_STREAMS 5
139 /*
140 * A global struct for save/restore to hold all the data that should
141 * sustain power-down: MMU base, IRQ type, env for routines, binary loaded FW
142 * and the stream seeds.
143 */
144 struct sh_css_save {
145 enum ia_sh_css_modes mode;
146 u32 mmu_base; /* the last mmu_base */
147 enum ia_css_irq_type irq_type;
148 struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS];
149 struct ia_css_fw *loaded_fw; /* fw struct previously loaded */
150 struct ia_css_env driver_env; /* driver-supplied env copy */
151 };
152
153 static bool my_css_save_initialized; /* if my_css_save was initialized */
154 static struct sh_css_save my_css_save;
155
156 /*
157 * pqiao NOTICE: this is for css internal buffer recycling when stopping
158 * pipeline,
159 * this array is temporary and will be replaced by resource manager
160 */
161
162 /* Taking the biggest Size for number of Elements */
163 #define MAX_HMM_BUFFER_NUM \
164 (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2))
165
166 struct sh_css_hmm_buffer_record {
167 bool in_use;
168 enum ia_css_buffer_type type;
169 struct ia_css_rmgr_vbuf_handle *h_vbuf;
170 hrt_address kernel_ptr;
171 };
172
173 static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM];
174
175 #define GPIO_FLASH_PIN_MASK BIT(HIVE_GPIO_STROBE_TRIGGER_PIN)
176
177 /*
178 * Local prototypes
179 */
180
181 static int
182 allocate_delay_frames(struct ia_css_pipe *pipe);
183
184 static int
185 sh_css_pipe_start(struct ia_css_stream *stream);
186
187 /*
188 * @brief Check if all "ia_css_pipe" instances in the target
189 * "ia_css_stream" instance have stopped.
190 *
191 * @param[in] stream Point to the target "ia_css_stream" instance.
192 *
193 * @return
194 * - true, if all "ia_css_pipe" instances in the target "ia_css_stream"
195 * instance have ben stopped.
196 * - false, otherwise.
197 */
198
199 /* ISP 2401 */
200 static int
201 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
202 enum ia_css_frame_format format);
203
204 /* ISP 2401 */
205 static void
206 ia_css_reset_defaults(struct sh_css *css);
207
208 static void
209 sh_css_init_host_sp_control_vars(void);
210
211 static int
212 set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version);
213
214 static bool
215 need_capture_pp(const struct ia_css_pipe *pipe);
216
217 static bool
218 need_yuv_scaler_stage(const struct ia_css_pipe *pipe);
219
220 static int ia_css_pipe_create_cas_scaler_desc_single_output(
221 struct ia_css_frame_info *cas_scaler_in_info,
222 struct ia_css_frame_info *cas_scaler_out_info,
223 struct ia_css_frame_info *cas_scaler_vf_info,
224 struct ia_css_cas_binary_descr *descr);
225
226 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
227 *descr);
228
229 static bool
230 need_downscaling(const struct ia_css_resolution in_res,
231 const struct ia_css_resolution out_res);
232
233 static bool need_capt_ldc(const struct ia_css_pipe *pipe);
234
235 static int
236 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe);
237
238 static
239 int sh_css_pipe_get_viewfinder_frame_info(
240 struct ia_css_pipe *pipe,
241 struct ia_css_frame_info *info,
242 unsigned int idx);
243
244 static int
245 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
246 struct ia_css_frame_info *info,
247 unsigned int idx);
248
249 static int
250 capture_start(struct ia_css_pipe *pipe);
251
252 static int
253 video_start(struct ia_css_pipe *pipe);
254
255 static int
256 preview_start(struct ia_css_pipe *pipe);
257
258 static int
259 yuvpp_start(struct ia_css_pipe *pipe);
260
261 static bool copy_on_sp(struct ia_css_pipe *pipe);
262
263 static int
264 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
265 struct ia_css_frame *vf_frame, unsigned int idx);
266
267 static int
268 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
269 struct ia_css_frame *frame, enum ia_css_frame_format format);
270
271 static int
272 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
273 struct ia_css_frame *out_frame, unsigned int idx);
274
275 static int
276 alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time);
277
278 static void
279 pipe_global_init(void);
280
281 static int
282 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
283 unsigned int *pipe_number);
284
285 static void
286 pipe_release_pipe_num(unsigned int pipe_num);
287
288 static int
289 create_host_pipeline_structure(struct ia_css_stream *stream);
290
291 static int
292 create_host_pipeline(struct ia_css_stream *stream);
293
294 static int
295 create_host_preview_pipeline(struct ia_css_pipe *pipe);
296
297 static int
298 create_host_video_pipeline(struct ia_css_pipe *pipe);
299
300 static int
301 create_host_copy_pipeline(struct ia_css_pipe *pipe,
302 unsigned int max_input_width,
303 struct ia_css_frame *out_frame);
304
305 static int
306 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe);
307
308 static int
309 create_host_capture_pipeline(struct ia_css_pipe *pipe);
310
311 static int
312 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe);
313
314 static unsigned int
315 sh_css_get_sw_interrupt_value(unsigned int irq);
316
317 static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary(
318 const struct ia_css_pipe *pipe);
319
320 static struct ia_css_binary *
321 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe);
322
323 static struct ia_css_binary *
324 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe);
325
326 static void
327 sh_css_hmm_buffer_record_init(void);
328
329 static void
330 sh_css_hmm_buffer_record_uninit(void);
331
332 static void
333 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record);
334
335 static struct sh_css_hmm_buffer_record
336 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
337 enum ia_css_buffer_type type,
338 hrt_address kernel_ptr);
339
340 static struct sh_css_hmm_buffer_record
341 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
342 enum ia_css_buffer_type type);
343
344 static unsigned int get_crop_lines_for_bayer_order(const struct
345 ia_css_stream_config *config);
346 static unsigned int get_crop_columns_for_bayer_order(const struct
347 ia_css_stream_config *config);
348 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
349 unsigned int *extra_row, unsigned int *extra_column);
350
351 static void
sh_css_pipe_free_shading_table(struct ia_css_pipe * pipe)352 sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe)
353 {
354 if (!pipe) {
355 IA_CSS_ERROR("NULL input parameter");
356 return;
357 }
358
359 if (pipe->shading_table)
360 ia_css_shading_table_free(pipe->shading_table);
361 pipe->shading_table = NULL;
362 }
363
364 static enum ia_css_frame_format yuv420_copy_formats[] = {
365 IA_CSS_FRAME_FORMAT_NV12,
366 IA_CSS_FRAME_FORMAT_NV21,
367 IA_CSS_FRAME_FORMAT_YV12,
368 IA_CSS_FRAME_FORMAT_YUV420,
369 IA_CSS_FRAME_FORMAT_YUV420_16,
370 IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8,
371 IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
372 };
373
374 static enum ia_css_frame_format yuv422_copy_formats[] = {
375 IA_CSS_FRAME_FORMAT_NV12,
376 IA_CSS_FRAME_FORMAT_NV16,
377 IA_CSS_FRAME_FORMAT_NV21,
378 IA_CSS_FRAME_FORMAT_NV61,
379 IA_CSS_FRAME_FORMAT_YV12,
380 IA_CSS_FRAME_FORMAT_YV16,
381 IA_CSS_FRAME_FORMAT_YUV420,
382 IA_CSS_FRAME_FORMAT_YUV420_16,
383 IA_CSS_FRAME_FORMAT_YUV422,
384 IA_CSS_FRAME_FORMAT_YUV422_16,
385 IA_CSS_FRAME_FORMAT_UYVY,
386 IA_CSS_FRAME_FORMAT_YUYV
387 };
388
389 /*
390 * Verify whether the selected output format is can be produced
391 * by the copy binary given the stream format.
392 */
393 static int
verify_copy_out_frame_format(struct ia_css_pipe * pipe)394 verify_copy_out_frame_format(struct ia_css_pipe *pipe)
395 {
396 enum ia_css_frame_format out_fmt = pipe->output_info[0].format;
397 unsigned int i, found = 0;
398
399 assert(pipe);
400 assert(pipe->stream);
401
402 switch (pipe->stream->config.input_config.format) {
403 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
404 case ATOMISP_INPUT_FORMAT_YUV420_8:
405 for (i = 0; i < ARRAY_SIZE(yuv420_copy_formats) && !found; i++)
406 found = (out_fmt == yuv420_copy_formats[i]);
407 break;
408 case ATOMISP_INPUT_FORMAT_YUV420_10:
409 case ATOMISP_INPUT_FORMAT_YUV420_16:
410 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
411 break;
412 case ATOMISP_INPUT_FORMAT_YUV422_8:
413 for (i = 0; i < ARRAY_SIZE(yuv422_copy_formats) && !found; i++)
414 found = (out_fmt == yuv422_copy_formats[i]);
415 break;
416 case ATOMISP_INPUT_FORMAT_YUV422_10:
417 case ATOMISP_INPUT_FORMAT_YUV422_16:
418 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 ||
419 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
420 break;
421 case ATOMISP_INPUT_FORMAT_RGB_444:
422 case ATOMISP_INPUT_FORMAT_RGB_555:
423 case ATOMISP_INPUT_FORMAT_RGB_565:
424 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
425 out_fmt == IA_CSS_FRAME_FORMAT_RGB565);
426 break;
427 case ATOMISP_INPUT_FORMAT_RGB_666:
428 case ATOMISP_INPUT_FORMAT_RGB_888:
429 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
430 out_fmt == IA_CSS_FRAME_FORMAT_YUV420);
431 break;
432 case ATOMISP_INPUT_FORMAT_RAW_6:
433 case ATOMISP_INPUT_FORMAT_RAW_7:
434 case ATOMISP_INPUT_FORMAT_RAW_8:
435 case ATOMISP_INPUT_FORMAT_RAW_10:
436 case ATOMISP_INPUT_FORMAT_RAW_12:
437 case ATOMISP_INPUT_FORMAT_RAW_14:
438 case ATOMISP_INPUT_FORMAT_RAW_16:
439 found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) ||
440 (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED);
441 break;
442 case ATOMISP_INPUT_FORMAT_BINARY_8:
443 found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8);
444 break;
445 default:
446 break;
447 }
448 if (!found)
449 return -EINVAL;
450 return 0;
451 }
452
453 unsigned int
ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream * stream)454 ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream)
455 {
456 int bpp = 0;
457
458 if (stream)
459 bpp = ia_css_util_input_format_bpp(stream->config.input_config.format,
460 stream->config.pixels_per_clock == 2);
461
462 return bpp;
463 }
464
465 static int
sh_css_config_input_network_2400(struct ia_css_stream * stream)466 sh_css_config_input_network_2400(struct ia_css_stream *stream)
467 {
468 unsigned int fmt_type;
469 struct ia_css_pipe *pipe = stream->last_pipe;
470 struct ia_css_binary *binary = NULL;
471 int err = 0;
472
473 assert(stream);
474 assert(pipe);
475
476 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
477 "sh_css_config_input_network() enter:\n");
478
479 if (pipe->pipeline.stages)
480 binary = pipe->pipeline.stages->binary;
481
482 err = ia_css_isys_convert_stream_format_to_mipi_format(
483 stream->config.input_config.format,
484 stream->csi_rx_config.comp,
485 &fmt_type);
486 if (err)
487 return err;
488 sh_css_sp_program_input_circuit(fmt_type,
489 stream->config.channel_id,
490 stream->config.mode);
491
492 if ((binary && (binary->online || stream->config.continuous)) ||
493 pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
494 err = ia_css_ifmtr_configure(&stream->config,
495 binary);
496 if (err)
497 return err;
498 }
499
500 if (stream->config.mode == IA_CSS_INPUT_MODE_PRBS) {
501 unsigned int width, height, vblank_cycles;
502 const unsigned int hblank_cycles = 100;
503 const unsigned int vblank_lines = 6;
504
505 width = (stream->config.input_config.input_res.width) /
506 (1 + (stream->config.pixels_per_clock == 2));
507 height = stream->config.input_config.input_res.height;
508 vblank_cycles = vblank_lines * (width + hblank_cycles);
509 sh_css_sp_configure_sync_gen(width, height, hblank_cycles, vblank_cycles);
510 }
511 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
512 "sh_css_config_input_network() leave:\n");
513 return 0;
514 }
515
csi2_protocol_calculate_max_subpixels_per_line(enum atomisp_input_format format,unsigned int pixels_per_line)516 static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
517 enum atomisp_input_format format,
518 unsigned int pixels_per_line)
519 {
520 unsigned int rval;
521
522 switch (format) {
523 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
524 /*
525 * The frame format layout is shown below.
526 *
527 * Line 0: UYY0 UYY0 ... UYY0
528 * Line 1: VYY0 VYY0 ... VYY0
529 * Line 2: UYY0 UYY0 ... UYY0
530 * Line 3: VYY0 VYY0 ... VYY0
531 * ...
532 * Line (n-2): UYY0 UYY0 ... UYY0
533 * Line (n-1): VYY0 VYY0 ... VYY0
534 *
535 * In this frame format, the even-line is
536 * as wide as the odd-line.
537 * The 0 is introduced by the input system
538 * (mipi backend).
539 */
540 rval = pixels_per_line * 2;
541 break;
542 case ATOMISP_INPUT_FORMAT_YUV420_8:
543 case ATOMISP_INPUT_FORMAT_YUV420_10:
544 case ATOMISP_INPUT_FORMAT_YUV420_16:
545 /*
546 * The frame format layout is shown below.
547 *
548 * Line 0: YYYY YYYY ... YYYY
549 * Line 1: UYVY UYVY ... UYVY UYVY
550 * Line 2: YYYY YYYY ... YYYY
551 * Line 3: UYVY UYVY ... UYVY UYVY
552 * ...
553 * Line (n-2): YYYY YYYY ... YYYY
554 * Line (n-1): UYVY UYVY ... UYVY UYVY
555 *
556 * In this frame format, the odd-line is twice
557 * wider than the even-line.
558 */
559 rval = pixels_per_line * 2;
560 break;
561 case ATOMISP_INPUT_FORMAT_YUV422_8:
562 case ATOMISP_INPUT_FORMAT_YUV422_10:
563 case ATOMISP_INPUT_FORMAT_YUV422_16:
564 /*
565 * The frame format layout is shown below.
566 *
567 * Line 0: UYVY UYVY ... UYVY
568 * Line 1: UYVY UYVY ... UYVY
569 * Line 2: UYVY UYVY ... UYVY
570 * Line 3: UYVY UYVY ... UYVY
571 * ...
572 * Line (n-2): UYVY UYVY ... UYVY
573 * Line (n-1): UYVY UYVY ... UYVY
574 *
575 * In this frame format, the even-line is
576 * as wide as the odd-line.
577 */
578 rval = pixels_per_line * 2;
579 break;
580 case ATOMISP_INPUT_FORMAT_RGB_444:
581 case ATOMISP_INPUT_FORMAT_RGB_555:
582 case ATOMISP_INPUT_FORMAT_RGB_565:
583 case ATOMISP_INPUT_FORMAT_RGB_666:
584 case ATOMISP_INPUT_FORMAT_RGB_888:
585 /*
586 * The frame format layout is shown below.
587 *
588 * Line 0: ABGR ABGR ... ABGR
589 * Line 1: ABGR ABGR ... ABGR
590 * Line 2: ABGR ABGR ... ABGR
591 * Line 3: ABGR ABGR ... ABGR
592 * ...
593 * Line (n-2): ABGR ABGR ... ABGR
594 * Line (n-1): ABGR ABGR ... ABGR
595 *
596 * In this frame format, the even-line is
597 * as wide as the odd-line.
598 */
599 rval = pixels_per_line * 4;
600 break;
601 case ATOMISP_INPUT_FORMAT_RAW_6:
602 case ATOMISP_INPUT_FORMAT_RAW_7:
603 case ATOMISP_INPUT_FORMAT_RAW_8:
604 case ATOMISP_INPUT_FORMAT_RAW_10:
605 case ATOMISP_INPUT_FORMAT_RAW_12:
606 case ATOMISP_INPUT_FORMAT_RAW_14:
607 case ATOMISP_INPUT_FORMAT_RAW_16:
608 case ATOMISP_INPUT_FORMAT_BINARY_8:
609 case ATOMISP_INPUT_FORMAT_USER_DEF1:
610 case ATOMISP_INPUT_FORMAT_USER_DEF2:
611 case ATOMISP_INPUT_FORMAT_USER_DEF3:
612 case ATOMISP_INPUT_FORMAT_USER_DEF4:
613 case ATOMISP_INPUT_FORMAT_USER_DEF5:
614 case ATOMISP_INPUT_FORMAT_USER_DEF6:
615 case ATOMISP_INPUT_FORMAT_USER_DEF7:
616 case ATOMISP_INPUT_FORMAT_USER_DEF8:
617 /*
618 * The frame format layout is shown below.
619 *
620 * Line 0: Pixel ... Pixel
621 * Line 1: Pixel ... Pixel
622 * Line 2: Pixel ... Pixel
623 * Line 3: Pixel ... Pixel
624 * ...
625 * Line (n-2): Pixel ... Pixel
626 * Line (n-1): Pixel ... Pixel
627 *
628 * In this frame format, the even-line is
629 * as wide as the odd-line.
630 */
631 rval = pixels_per_line;
632 break;
633 default:
634 rval = 0;
635 break;
636 }
637
638 return rval;
639 }
640
sh_css_translate_stream_cfg_to_input_system_input_port_id(struct ia_css_stream_config * stream_cfg,ia_css_isys_descr_t * isys_stream_descr)641 static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
642 struct ia_css_stream_config *stream_cfg,
643 ia_css_isys_descr_t *isys_stream_descr)
644 {
645 bool rc;
646
647 rc = true;
648 switch (stream_cfg->mode) {
649 case IA_CSS_INPUT_MODE_PRBS:
650
651 if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0)
652 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
653 else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1)
654 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
655 else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2)
656 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
657
658 break;
659 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
660
661 if (stream_cfg->source.port.port == MIPI_PORT0_ID)
662 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
663 else if (stream_cfg->source.port.port == MIPI_PORT1_ID)
664 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
665 else if (stream_cfg->source.port.port == MIPI_PORT2_ID)
666 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
667
668 break;
669 default:
670 rc = false;
671 break;
672 }
673
674 return rc;
675 }
676
sh_css_translate_stream_cfg_to_input_system_input_port_type(struct ia_css_stream_config * stream_cfg,ia_css_isys_descr_t * isys_stream_descr)677 static bool sh_css_translate_stream_cfg_to_input_system_input_port_type(
678 struct ia_css_stream_config *stream_cfg,
679 ia_css_isys_descr_t *isys_stream_descr)
680 {
681 bool rc;
682
683 rc = true;
684 switch (stream_cfg->mode) {
685 case IA_CSS_INPUT_MODE_PRBS:
686
687 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS;
688
689 break;
690 case IA_CSS_INPUT_MODE_SENSOR:
691 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
692
693 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR;
694 break;
695
696 default:
697 rc = false;
698 break;
699 }
700
701 return rc;
702 }
703
sh_css_translate_stream_cfg_to_input_system_input_port_attr(struct ia_css_stream_config * stream_cfg,ia_css_isys_descr_t * isys_stream_descr,int isys_stream_idx)704 static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
705 struct ia_css_stream_config *stream_cfg,
706 ia_css_isys_descr_t *isys_stream_descr,
707 int isys_stream_idx)
708 {
709 bool rc;
710
711 rc = true;
712 switch (stream_cfg->mode) {
713 case IA_CSS_INPUT_MODE_PRBS:
714
715 isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed;
716 isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1;
717
718 /*
719 * TODO
720 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config".
721 */
722 isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100;
723 isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100;
724 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock =
725 stream_cfg->pixels_per_clock;
726 isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0);
727 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_line =
728 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
729 isys_stream_descr->prbs_port_attr.sync_gen_cfg.lines_per_frame =
730 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
731
732 break;
733 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: {
734 int err;
735 unsigned int fmt_type;
736
737 err = ia_css_isys_convert_stream_format_to_mipi_format(
738 stream_cfg->isys_config[isys_stream_idx].format,
739 MIPI_PREDICTOR_NONE,
740 &fmt_type);
741 if (err)
742 rc = false;
743
744 isys_stream_descr->csi_port_attr.active_lanes =
745 stream_cfg->source.port.num_lanes;
746 isys_stream_descr->csi_port_attr.fmt_type = fmt_type;
747 isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id;
748
749 if (IS_ISP2401)
750 isys_stream_descr->online = stream_cfg->online;
751
752 err |= ia_css_isys_convert_compressed_format(
753 &stream_cfg->source.port.compression,
754 isys_stream_descr);
755 if (err)
756 rc = false;
757
758 /* metadata */
759 isys_stream_descr->metadata.enable = false;
760 if (stream_cfg->metadata_config.resolution.height > 0) {
761 err = ia_css_isys_convert_stream_format_to_mipi_format(
762 stream_cfg->metadata_config.data_type,
763 MIPI_PREDICTOR_NONE,
764 &fmt_type);
765 if (err)
766 rc = false;
767 isys_stream_descr->metadata.fmt_type = fmt_type;
768 isys_stream_descr->metadata.bits_per_pixel =
769 ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true);
770 isys_stream_descr->metadata.pixels_per_line =
771 stream_cfg->metadata_config.resolution.width;
772 isys_stream_descr->metadata.lines_per_frame =
773 stream_cfg->metadata_config.resolution.height;
774
775 /*
776 * For new input system, number of str2mmio requests must be even.
777 * So we round up number of metadata lines to be even.
778 */
779 if (IS_ISP2401 && isys_stream_descr->metadata.lines_per_frame > 0)
780 isys_stream_descr->metadata.lines_per_frame +=
781 (isys_stream_descr->metadata.lines_per_frame & 1);
782
783 isys_stream_descr->metadata.align_req_in_bytes =
784 ia_css_csi2_calculate_input_system_alignment(
785 stream_cfg->metadata_config.data_type);
786 isys_stream_descr->metadata.enable = true;
787 }
788
789 break;
790 }
791 default:
792 rc = false;
793 break;
794 }
795
796 return rc;
797 }
798
sh_css_translate_stream_cfg_to_input_system_input_port_resolution(struct ia_css_stream_config * stream_cfg,ia_css_isys_descr_t * isys_stream_descr,int isys_stream_idx)799 static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
800 struct ia_css_stream_config *stream_cfg,
801 ia_css_isys_descr_t *isys_stream_descr,
802 int isys_stream_idx)
803 {
804 unsigned int bits_per_subpixel;
805 unsigned int max_subpixels_per_line;
806 unsigned int lines_per_frame;
807 unsigned int align_req_in_bytes;
808 enum atomisp_input_format fmt_type;
809
810 fmt_type = stream_cfg->isys_config[isys_stream_idx].format;
811 if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR ||
812 stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) &&
813 stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
814 if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
815 UNCOMPRESSED_BITS_PER_PIXEL_10)
816 fmt_type = ATOMISP_INPUT_FORMAT_RAW_10;
817 else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
818 UNCOMPRESSED_BITS_PER_PIXEL_12)
819 fmt_type = ATOMISP_INPUT_FORMAT_RAW_12;
820 else
821 return false;
822 }
823
824 bits_per_subpixel =
825 sh_css_stream_format_2_bits_per_subpixel(fmt_type);
826 if (bits_per_subpixel == 0)
827 return false;
828
829 max_subpixels_per_line =
830 csi2_protocol_calculate_max_subpixels_per_line(fmt_type,
831 stream_cfg->isys_config[isys_stream_idx].input_res.width);
832 if (max_subpixels_per_line == 0)
833 return false;
834
835 lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height;
836 if (lines_per_frame == 0)
837 return false;
838
839 align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type);
840
841 /* HW needs subpixel info for their settings */
842 isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel;
843 isys_stream_descr->input_port_resolution.pixels_per_line =
844 max_subpixels_per_line;
845 isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame;
846 isys_stream_descr->input_port_resolution.align_req_in_bytes =
847 align_req_in_bytes;
848
849 return true;
850 }
851
sh_css_translate_stream_cfg_to_isys_stream_descr(struct ia_css_stream_config * stream_cfg,bool early_polling,ia_css_isys_descr_t * isys_stream_descr,int isys_stream_idx)852 static bool sh_css_translate_stream_cfg_to_isys_stream_descr(
853 struct ia_css_stream_config *stream_cfg,
854 bool early_polling,
855 ia_css_isys_descr_t *isys_stream_descr,
856 int isys_stream_idx)
857 {
858 bool rc;
859
860 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
861 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n");
862 rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg,
863 isys_stream_descr);
864 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg,
865 isys_stream_descr);
866 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg,
867 isys_stream_descr, isys_stream_idx);
868 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
869 stream_cfg, isys_stream_descr, isys_stream_idx);
870
871 isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels;
872 isys_stream_descr->linked_isys_stream_id = (int8_t)
873 stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id;
874
875 if (IS_ISP2401)
876 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
877 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n");
878
879 return rc;
880 }
881
sh_css_translate_binary_info_to_input_system_output_port_attr(struct ia_css_binary * binary,ia_css_isys_descr_t * isys_stream_descr)882 static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
883 struct ia_css_binary *binary,
884 ia_css_isys_descr_t *isys_stream_descr)
885 {
886 if (!binary)
887 return false;
888
889 isys_stream_descr->output_port_attr.left_padding = binary->left_padding;
890 isys_stream_descr->output_port_attr.max_isp_input_width =
891 binary->info->sp.input.max_width;
892
893 return true;
894 }
895
896 static int
sh_css_config_input_network_2401(struct ia_css_stream * stream)897 sh_css_config_input_network_2401(struct ia_css_stream *stream)
898 {
899 bool rc;
900 ia_css_isys_descr_t isys_stream_descr;
901 unsigned int sp_thread_id;
902 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
903 struct ia_css_pipe *pipe = NULL;
904 struct ia_css_binary *binary = NULL;
905 int i;
906 u32 isys_stream_id;
907 bool early_polling = false;
908
909 assert(stream);
910 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
911 "sh_css_config_input_network() enter 0x%p:\n", stream);
912
913 if (stream->config.continuous) {
914 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE)
915 pipe = stream->last_pipe;
916 else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP)
917 pipe = stream->last_pipe;
918 else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
919 pipe = stream->last_pipe->pipe_settings.preview.copy_pipe;
920 else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO)
921 pipe = stream->last_pipe->pipe_settings.video.copy_pipe;
922 } else {
923 pipe = stream->last_pipe;
924 }
925
926 if (!pipe)
927 return -EINVAL;
928
929 if (pipe->pipeline.stages)
930 if (pipe->pipeline.stages->binary)
931 binary = pipe->pipeline.stages->binary;
932
933 if (binary) {
934 /*
935 * this was being done in ifmtr in 2400.
936 * online and cont bypass the init_in_frameinfo_memory_defaults
937 * so need to do it here
938 */
939 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
940 }
941
942 /* get the SP thread id */
943 rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id);
944 if (!rc)
945 return -EINVAL;
946 /* get the target input terminal */
947 sp_pipeline_input_terminal = &sh_css_sp_group.pipe_io[sp_thread_id].input;
948
949 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
950 /* initialization */
951 memset((void *)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t));
952 sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0;
953 sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0;
954
955 if (!stream->config.isys_config[i].valid)
956 continue;
957
958 /* translate the stream configuration to the Input System (2401) configuration */
959 rc = sh_css_translate_stream_cfg_to_isys_stream_descr(
960 &stream->config,
961 early_polling,
962 &(isys_stream_descr), i);
963
964 if (stream->config.online) {
965 rc &= sh_css_translate_binary_info_to_input_system_output_port_attr(
966 binary,
967 &(isys_stream_descr));
968 }
969
970 if (!rc)
971 return -EINVAL;
972
973 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i);
974
975 /* create the virtual Input System (2401) */
976 rc = ia_css_isys_stream_create(
977 &(isys_stream_descr),
978 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
979 isys_stream_id);
980 if (!rc)
981 return -EINVAL;
982
983 /* calculate the configuration of the virtual Input System (2401) */
984 rc = ia_css_isys_stream_calculate_cfg(
985 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
986 &(isys_stream_descr),
987 &sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]);
988 if (!rc) {
989 ia_css_isys_stream_destroy(
990 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]);
991 return -EINVAL;
992 }
993 }
994
995 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
996 "sh_css_config_input_network() leave:\n");
997
998 return 0;
999 }
1000
stream_get_last_pipe(struct ia_css_stream * stream)1001 static inline struct ia_css_pipe *stream_get_last_pipe(
1002 struct ia_css_stream *stream)
1003 {
1004 struct ia_css_pipe *last_pipe = NULL;
1005
1006 if (stream)
1007 last_pipe = stream->last_pipe;
1008
1009 return last_pipe;
1010 }
1011
stream_get_copy_pipe(struct ia_css_stream * stream)1012 static inline struct ia_css_pipe *stream_get_copy_pipe(
1013 struct ia_css_stream *stream)
1014 {
1015 struct ia_css_pipe *copy_pipe = NULL;
1016 struct ia_css_pipe *last_pipe = NULL;
1017 enum ia_css_pipe_id pipe_id;
1018
1019 last_pipe = stream_get_last_pipe(stream);
1020
1021 if ((stream) &&
1022 (last_pipe) &&
1023 (stream->config.continuous)) {
1024 pipe_id = last_pipe->mode;
1025 switch (pipe_id) {
1026 case IA_CSS_PIPE_ID_PREVIEW:
1027 copy_pipe = last_pipe->pipe_settings.preview.copy_pipe;
1028 break;
1029 case IA_CSS_PIPE_ID_VIDEO:
1030 copy_pipe = last_pipe->pipe_settings.video.copy_pipe;
1031 break;
1032 default:
1033 copy_pipe = NULL;
1034 break;
1035 }
1036 }
1037
1038 return copy_pipe;
1039 }
1040
stream_get_target_pipe(struct ia_css_stream * stream)1041 static inline struct ia_css_pipe *stream_get_target_pipe(
1042 struct ia_css_stream *stream)
1043 {
1044 struct ia_css_pipe *target_pipe;
1045
1046 /* get the pipe that consumes the stream */
1047 if (stream->config.continuous)
1048 target_pipe = stream_get_copy_pipe(stream);
1049 else
1050 target_pipe = stream_get_last_pipe(stream);
1051
1052 return target_pipe;
1053 }
1054
stream_csi_rx_helper(struct ia_css_stream * stream,int (* func)(enum mipi_port_id,uint32_t))1055 static int stream_csi_rx_helper(
1056 struct ia_css_stream *stream,
1057 int (*func)(enum mipi_port_id, uint32_t))
1058 {
1059 int retval = -EINVAL;
1060 u32 sp_thread_id, stream_id;
1061 bool rc;
1062 struct ia_css_pipe *target_pipe = NULL;
1063
1064 if ((!stream) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
1065 goto exit;
1066
1067 target_pipe = stream_get_target_pipe(stream);
1068
1069 if (!target_pipe)
1070 goto exit;
1071
1072 rc = ia_css_pipeline_get_sp_thread_id(
1073 ia_css_pipe_get_pipe_num(target_pipe),
1074 &sp_thread_id);
1075
1076 if (!rc)
1077 goto exit;
1078
1079 /* (un)register all valid "virtual isys streams" within the ia_css_stream */
1080 stream_id = 0;
1081 do {
1082 if (stream->config.isys_config[stream_id].valid) {
1083 u32 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id);
1084
1085 retval = func(stream->config.source.port.port, isys_stream_id);
1086 }
1087 stream_id++;
1088 } while ((retval == 0) &&
1089 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH));
1090
1091 exit:
1092 return retval;
1093 }
1094
stream_register_with_csi_rx(struct ia_css_stream * stream)1095 static inline int stream_register_with_csi_rx(
1096 struct ia_css_stream *stream)
1097 {
1098 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream);
1099 }
1100
stream_unregister_with_csi_rx(struct ia_css_stream * stream)1101 static inline int stream_unregister_with_csi_rx(
1102 struct ia_css_stream *stream)
1103 {
1104 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream);
1105 }
1106
1107
1108 static void
start_binary(struct ia_css_pipe * pipe,struct ia_css_binary * binary)1109 start_binary(struct ia_css_pipe *pipe,
1110 struct ia_css_binary *binary)
1111 {
1112 assert(pipe);
1113 /* Acceleration uses firmware, the binary thus can be NULL */
1114
1115 if (binary)
1116 sh_css_metrics_start_binary(&binary->metrics);
1117
1118 if (!IS_ISP2401 && pipe->stream->reconfigure_css_rx) {
1119 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1120 pipe->stream->config.mode);
1121 pipe->stream->reconfigure_css_rx = false;
1122 }
1123 }
1124
1125 /* start the copy function on the SP */
1126 static int
start_copy_on_sp(struct ia_css_pipe * pipe,struct ia_css_frame * out_frame)1127 start_copy_on_sp(struct ia_css_pipe *pipe,
1128 struct ia_css_frame *out_frame)
1129 {
1130 (void)out_frame;
1131
1132 if ((!pipe) || (!pipe->stream))
1133 return -EINVAL;
1134
1135 if (!IS_ISP2401 && pipe->stream->reconfigure_css_rx)
1136 ia_css_isys_rx_disable();
1137
1138 if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8)
1139 return -EINVAL;
1140 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
1141
1142 if (!IS_ISP2401 && pipe->stream->reconfigure_css_rx) {
1143 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1144 pipe->stream->config.mode);
1145 pipe->stream->reconfigure_css_rx = false;
1146 }
1147
1148 return 0;
1149 }
1150
sh_css_binary_args_reset(struct sh_css_binary_args * args)1151 void sh_css_binary_args_reset(struct sh_css_binary_args *args)
1152 {
1153 unsigned int i;
1154
1155 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++)
1156 args->tnr_frames[i] = NULL;
1157 for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++)
1158 args->delay_frames[i] = NULL;
1159 args->in_frame = NULL;
1160 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1161 args->out_frame[i] = NULL;
1162 args->out_vf_frame = NULL;
1163 args->copy_vf = false;
1164 args->copy_output = true;
1165 args->vf_downscale_log2 = 0;
1166 }
1167
start_pipe(struct ia_css_pipe * me,enum sh_css_pipe_config_override copy_ovrd,enum ia_css_input_mode input_mode)1168 static void start_pipe(
1169 struct ia_css_pipe *me,
1170 enum sh_css_pipe_config_override copy_ovrd,
1171 enum ia_css_input_mode input_mode)
1172 {
1173 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d",
1174 me, copy_ovrd, input_mode);
1175
1176 assert(me); /* all callers are in this file and call with non null argument */
1177
1178 sh_css_sp_init_pipeline(&me->pipeline,
1179 me->mode,
1180 (uint8_t)ia_css_pipe_get_pipe_num(me),
1181 me->config.default_capture_config.enable_xnr != 0,
1182 me->stream->config.pixels_per_clock == 2,
1183 me->stream->config.continuous,
1184 false,
1185 me->required_bds_factor,
1186 copy_ovrd,
1187 input_mode,
1188 &me->stream->config.metadata_config,
1189 &me->stream->info.metadata_info
1190 , (input_mode == IA_CSS_INPUT_MODE_MEMORY) ?
1191 (enum mipi_port_id)0 :
1192 me->stream->config.source.port.port);
1193
1194 if (me->config.mode != IA_CSS_PIPE_MODE_COPY) {
1195 struct ia_css_pipeline_stage *stage;
1196
1197 stage = me->pipeline.stages;
1198 if (stage) {
1199 me->pipeline.current_stage = stage;
1200 start_binary(me, stage->binary);
1201 }
1202 }
1203 IA_CSS_LEAVE_PRIVATE("void");
1204 }
1205
1206 void
sh_css_invalidate_shading_tables(struct ia_css_stream * stream)1207 sh_css_invalidate_shading_tables(struct ia_css_stream *stream)
1208 {
1209 int i;
1210
1211 assert(stream);
1212
1213 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1214 "sh_css_invalidate_shading_tables() enter:\n");
1215
1216 for (i = 0; i < stream->num_pipes; i++) {
1217 assert(stream->pipes[i]);
1218 sh_css_pipe_free_shading_table(stream->pipes[i]);
1219 }
1220
1221 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1222 "sh_css_invalidate_shading_tables() leave: return_void\n");
1223 }
1224
1225 static void
enable_interrupts(enum ia_css_irq_type irq_type)1226 enable_interrupts(enum ia_css_irq_type irq_type)
1227 {
1228 enum mipi_port_id port;
1229 bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE;
1230
1231 IA_CSS_ENTER_PRIVATE("");
1232 /* Enable IRQ on the SP which signals that SP goes to idle
1233 * (aka ready state) */
1234 cnd_sp_irq_enable(SP0_ID, true);
1235 /* Set the IRQ device 0 to either level or pulse */
1236 irq_enable_pulse(IRQ0_ID, enable_pulse);
1237
1238 cnd_virq_enable_channel(virq_sp, true);
1239
1240 /* Enable SW interrupt 0, this is used to signal ISYS events */
1241 cnd_virq_enable_channel(
1242 (enum virq_id)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET),
1243 true);
1244 /* Enable SW interrupt 1, this is used to signal PSYS events */
1245 cnd_virq_enable_channel(
1246 (enum virq_id)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET),
1247 true);
1248
1249 if (!IS_ISP2401) {
1250 for (port = 0; port < N_MIPI_PORT_ID; port++)
1251 ia_css_isys_rx_enable_all_interrupts(port);
1252 }
1253
1254 IA_CSS_LEAVE_PRIVATE("");
1255 }
1256
sh_css_setup_spctrl_config(const struct ia_css_fw_info * fw,const char * program,ia_css_spctrl_cfg * spctrl_cfg)1257 static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw,
1258 const char *program,
1259 ia_css_spctrl_cfg *spctrl_cfg)
1260 {
1261 if ((!fw) || (!spctrl_cfg))
1262 return false;
1263 spctrl_cfg->sp_entry = 0;
1264 spctrl_cfg->program_name = (char *)(program);
1265
1266 spctrl_cfg->ddr_data_offset = fw->blob.data_source;
1267 spctrl_cfg->dmem_data_addr = fw->blob.data_target;
1268 spctrl_cfg->dmem_bss_addr = fw->blob.bss_target;
1269 spctrl_cfg->data_size = fw->blob.data_size;
1270 spctrl_cfg->bss_size = fw->blob.bss_size;
1271
1272 spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data;
1273 spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state;
1274
1275 spctrl_cfg->code_size = fw->blob.size;
1276 spctrl_cfg->code = fw->blob.code;
1277 spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */
1278
1279 return true;
1280 }
1281
1282 void
ia_css_unload_firmware(void)1283 ia_css_unload_firmware(void)
1284 {
1285 if (sh_css_num_binaries) {
1286 /* we have already loaded before so get rid of the old stuff */
1287 ia_css_binary_uninit();
1288 sh_css_unload_firmware();
1289 }
1290 }
1291
1292 static void
ia_css_reset_defaults(struct sh_css * css)1293 ia_css_reset_defaults(struct sh_css *css)
1294 {
1295 struct sh_css default_css;
1296
1297 /* Reset everything to zero */
1298 memset(&default_css, 0, sizeof(default_css));
1299
1300 /* Initialize the non zero values */
1301 default_css.check_system_idle = true;
1302 default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES;
1303
1304 /*
1305 * All should be 0: but memset does it already.
1306 * default_css.num_mipi_frames[N_CSI_PORTS] = 0;
1307 */
1308
1309 default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE;
1310
1311 /* Set the defaults to the output */
1312 *css = default_css;
1313 }
1314
1315 int
ia_css_load_firmware(struct device * dev,const struct ia_css_env * env,const struct ia_css_fw * fw)1316 ia_css_load_firmware(struct device *dev, const struct ia_css_env *env,
1317 const struct ia_css_fw *fw)
1318 {
1319 int err;
1320
1321 if (!env)
1322 return -EINVAL;
1323 if (!fw)
1324 return -EINVAL;
1325
1326 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n");
1327
1328 /* make sure we initialize my_css */
1329 if (my_css.flush != env->cpu_mem_env.flush) {
1330 ia_css_reset_defaults(&my_css);
1331 my_css.flush = env->cpu_mem_env.flush;
1332 }
1333
1334 err = sh_css_load_firmware(dev, fw->data, fw->bytes);
1335 if (!err)
1336 err = ia_css_binary_init_infos();
1337
1338 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave\n");
1339 return err;
1340 }
1341
1342 int
ia_css_init(struct device * dev,const struct ia_css_env * env,u32 mmu_l1_base,enum ia_css_irq_type irq_type)1343 ia_css_init(struct device *dev, const struct ia_css_env *env,
1344 u32 mmu_l1_base, enum ia_css_irq_type irq_type)
1345 {
1346 int err;
1347 ia_css_spctrl_cfg spctrl_cfg;
1348
1349 void (*flush_func)(struct ia_css_acc_fw *fw);
1350 hrt_data select, enable;
1351
1352 /*
1353 * The C99 standard does not specify the exact object representation of structs;
1354 * the representation is compiler dependent.
1355 *
1356 * The structs that are communicated between host and SP/ISP should have the
1357 * exact same object representation. The compiler that is used to compile the
1358 * firmware is hivecc.
1359 *
1360 * To check if a different compiler, used to compile a host application, uses
1361 * another object representation, macros are defined specifying the size of
1362 * the structs as expected by the firmware.
1363 *
1364 * A host application shall verify that a sizeof( ) of the struct is equal to
1365 * the SIZE_OF_XXX macro of the corresponding struct. If they are not
1366 * equal, functionality will break.
1367 */
1368
1369 /* Check struct sh_css_ddr_address_map */
1370 COMPILATION_ERROR_IF(sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT);
1371 /* Check struct host_sp_queues */
1372 COMPILATION_ERROR_IF(sizeof(struct host_sp_queues) != SIZE_OF_HOST_SP_QUEUES_STRUCT);
1373 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_desc_s) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT);
1374 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_elem_s) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT);
1375
1376 /* Check struct host_sp_communication */
1377 COMPILATION_ERROR_IF(sizeof(struct host_sp_communication) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT);
1378 COMPILATION_ERROR_IF(sizeof(struct sh_css_event_irq_mask) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT);
1379
1380 /* Check struct sh_css_hmm_buffer */
1381 COMPILATION_ERROR_IF(sizeof(struct sh_css_hmm_buffer) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT);
1382 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_3a_statistics) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT);
1383 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_dvs_statistics) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT);
1384 COMPILATION_ERROR_IF(sizeof(struct ia_css_metadata) != SIZE_OF_IA_CSS_METADATA_STRUCT);
1385
1386 /* Check struct ia_css_init_dmem_cfg */
1387 COMPILATION_ERROR_IF(sizeof(struct ia_css_sp_init_dmem_cfg) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT);
1388
1389 if (!env)
1390 return -EINVAL;
1391
1392 sh_css_printf = env->print_env.debug_print;
1393
1394 IA_CSS_ENTER("void");
1395
1396 flush_func = env->cpu_mem_env.flush;
1397
1398 pipe_global_init();
1399 ia_css_pipeline_init();
1400 ia_css_queue_map_init();
1401
1402 ia_css_device_access_init(&env->hw_access_env);
1403
1404 select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select)
1405 & (~GPIO_FLASH_PIN_MASK);
1406 enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e)
1407 | GPIO_FLASH_PIN_MASK;
1408 sh_css_mmu_set_page_table_base_index(mmu_l1_base);
1409
1410 my_css_save.mmu_base = mmu_l1_base;
1411
1412 ia_css_reset_defaults(&my_css);
1413
1414 my_css_save.driver_env = *env;
1415 my_css.flush = flush_func;
1416
1417 err = ia_css_rmgr_init();
1418 if (err) {
1419 IA_CSS_LEAVE_ERR(err);
1420 return err;
1421 }
1422
1423 IA_CSS_LOG("init: %d", my_css_save_initialized);
1424
1425 if (!my_css_save_initialized) {
1426 my_css_save_initialized = true;
1427 my_css_save.mode = sh_css_mode_working;
1428 memset(my_css_save.stream_seeds, 0,
1429 sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS);
1430 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode);
1431 }
1432
1433 mipi_init();
1434
1435 /*
1436 * In case this has been programmed already, update internal
1437 * data structure ...
1438 * DEPRECATED
1439 */
1440 if (!IS_ISP2401)
1441 my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
1442
1443 my_css.irq_type = irq_type;
1444
1445 my_css_save.irq_type = irq_type;
1446
1447 enable_interrupts(my_css.irq_type);
1448
1449 /* configure GPIO to output mode */
1450 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select);
1451 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable);
1452 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0);
1453
1454 err = ia_css_refcount_init(REFCOUNT_SIZE);
1455 if (err) {
1456 IA_CSS_LEAVE_ERR(err);
1457 return err;
1458 }
1459 err = sh_css_params_init();
1460 if (err) {
1461 IA_CSS_LEAVE_ERR(err);
1462 return err;
1463 }
1464
1465 if (!sh_css_setup_spctrl_config(&sh_css_sp_fw, SP_PROG_NAME, &spctrl_cfg))
1466 return -EINVAL;
1467
1468 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
1469 if (err) {
1470 IA_CSS_LEAVE_ERR(err);
1471 return err;
1472 }
1473
1474 if (!sh_css_hrt_system_is_idle()) {
1475 IA_CSS_LEAVE_ERR(-EBUSY);
1476 return -EBUSY;
1477 }
1478 /*
1479 * can be called here, queuing works, but:
1480 * - when sp is started later, it will wipe queued items
1481 * so for now we leave it for later and make sure
1482 * updates are not called to frequently.
1483 * sh_css_init_buffer_queues();
1484 */
1485
1486 if (IS_ISP2401)
1487 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
1488
1489 if (!IS_ISP2401)
1490 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1491 ISP2400_DMA_MAX_BURST_LENGTH);
1492 else
1493 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1494 ISP2401_DMA_MAX_BURST_LENGTH);
1495
1496 if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
1497 err = -EINVAL;
1498
1499 sh_css_params_map_and_store_default_gdc_lut();
1500
1501 IA_CSS_LEAVE_ERR(err);
1502 return err;
1503 }
1504
1505 int
ia_css_enable_isys_event_queue(bool enable)1506 ia_css_enable_isys_event_queue(bool enable)
1507 {
1508 if (sh_css_sp_is_running())
1509 return -EBUSY;
1510 sh_css_sp_enable_isys_event_queue(enable);
1511 return 0;
1512 }
1513
1514 /*
1515 * Mapping sp threads. Currently, this is done when a stream is created and
1516 * pipelines are ready to be converted to sp pipelines. Be careful if you are
1517 * doing it from stream_create since we could run out of sp threads due to
1518 * allocation on inactive pipelines.
1519 */
1520 static int
map_sp_threads(struct ia_css_stream * stream,bool map)1521 map_sp_threads(struct ia_css_stream *stream, bool map)
1522 {
1523 struct ia_css_pipe *main_pipe = NULL;
1524 struct ia_css_pipe *copy_pipe = NULL;
1525 struct ia_css_pipe *capture_pipe = NULL;
1526 int err = 0;
1527 enum ia_css_pipe_id pipe_id;
1528
1529 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1530 stream, map ? "true" : "false");
1531
1532 if (!stream) {
1533 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1534 return -EINVAL;
1535 }
1536
1537 main_pipe = stream->last_pipe;
1538 pipe_id = main_pipe->mode;
1539
1540 ia_css_pipeline_map(main_pipe->pipe_num, map);
1541
1542 switch (pipe_id) {
1543 case IA_CSS_PIPE_ID_PREVIEW:
1544 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1545 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1546 break;
1547
1548 case IA_CSS_PIPE_ID_VIDEO:
1549 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1550 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1551 break;
1552
1553 case IA_CSS_PIPE_ID_CAPTURE:
1554 default:
1555 break;
1556 }
1557
1558 if (capture_pipe)
1559 ia_css_pipeline_map(capture_pipe->pipe_num, map);
1560
1561 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
1562 if (copy_pipe)
1563 ia_css_pipeline_map(copy_pipe->pipe_num, map);
1564
1565 /* DH regular multi pipe - not continuous mode: map the next pipes too */
1566 if (!stream->config.continuous) {
1567 int i;
1568
1569 for (i = 1; i < stream->num_pipes; i++)
1570 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map);
1571 }
1572
1573 IA_CSS_LEAVE_ERR_PRIVATE(err);
1574 return err;
1575 }
1576
1577 /*
1578 * creates a host pipeline skeleton for all pipes in a stream. Called during
1579 * stream_create.
1580 */
1581 static int
create_host_pipeline_structure(struct ia_css_stream * stream)1582 create_host_pipeline_structure(struct ia_css_stream *stream)
1583 {
1584 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
1585 enum ia_css_pipe_id pipe_id;
1586 struct ia_css_pipe *main_pipe = NULL;
1587 int err = 0;
1588 unsigned int copy_pipe_delay = 0,
1589 capture_pipe_delay = 0;
1590
1591 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
1592
1593 if (!stream) {
1594 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1595 return -EINVAL;
1596 }
1597
1598 main_pipe = stream->last_pipe;
1599 if (!main_pipe) {
1600 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1601 return -EINVAL;
1602 }
1603
1604 pipe_id = main_pipe->mode;
1605
1606 switch (pipe_id) {
1607 case IA_CSS_PIPE_ID_PREVIEW:
1608 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1609 copy_pipe_delay = main_pipe->dvs_frame_delay;
1610 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1611 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
1612 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1613 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
1614 break;
1615
1616 case IA_CSS_PIPE_ID_VIDEO:
1617 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1618 copy_pipe_delay = main_pipe->dvs_frame_delay;
1619 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1620 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
1621 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1622 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
1623 break;
1624
1625 case IA_CSS_PIPE_ID_CAPTURE:
1626 capture_pipe = main_pipe;
1627 capture_pipe_delay = main_pipe->dvs_frame_delay;
1628 break;
1629
1630 case IA_CSS_PIPE_ID_YUVPP:
1631 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1632 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
1633 break;
1634
1635 default:
1636 err = -EINVAL;
1637 }
1638
1639 if (!(err) && copy_pipe)
1640 err = ia_css_pipeline_create(©_pipe->pipeline,
1641 copy_pipe->mode,
1642 copy_pipe->pipe_num,
1643 copy_pipe_delay);
1644
1645 if (!(err) && capture_pipe)
1646 err = ia_css_pipeline_create(&capture_pipe->pipeline,
1647 capture_pipe->mode,
1648 capture_pipe->pipe_num,
1649 capture_pipe_delay);
1650
1651 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
1652 if (!stream->config.continuous) {
1653 int i;
1654
1655 for (i = 1; i < stream->num_pipes && 0 == err; i++) {
1656 main_pipe = stream->pipes[i];
1657 err = ia_css_pipeline_create(&main_pipe->pipeline,
1658 main_pipe->mode,
1659 main_pipe->pipe_num,
1660 main_pipe->dvs_frame_delay);
1661 }
1662 }
1663
1664 IA_CSS_LEAVE_ERR_PRIVATE(err);
1665 return err;
1666 }
1667
1668 /*
1669 * creates a host pipeline for all pipes in a stream. Called during
1670 * stream_start.
1671 */
1672 static int
create_host_pipeline(struct ia_css_stream * stream)1673 create_host_pipeline(struct ia_css_stream *stream)
1674 {
1675 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
1676 enum ia_css_pipe_id pipe_id;
1677 struct ia_css_pipe *main_pipe = NULL;
1678 int err = 0;
1679 unsigned int max_input_width = 0;
1680
1681 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
1682 if (!stream) {
1683 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1684 return -EINVAL;
1685 }
1686
1687 main_pipe = stream->last_pipe;
1688 pipe_id = main_pipe->mode;
1689
1690 /*
1691 * No continuous frame allocation for capture pipe. It uses the
1692 * "main" pipe's frames.
1693 */
1694 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
1695 (pipe_id == IA_CSS_PIPE_ID_VIDEO)) {
1696 /*
1697 * About
1698 * pipe_id == IA_CSS_PIPE_ID_PREVIEW &&
1699 * stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
1700 *
1701 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is
1702 * too strong. E.g. in SkyCam (with memory based input frames)
1703 * there is no continuous mode and thus no need for allocated
1704 * continuous frames.
1705 * This is not only for SkyCam but for all preview cases that
1706 * use DDR based input frames. For this reason the
1707 * stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed
1708 * added.
1709 */
1710 if (stream->config.continuous ||
1711 (pipe_id == IA_CSS_PIPE_ID_PREVIEW &&
1712 stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) {
1713 err = alloc_continuous_frames(main_pipe, true);
1714 if (err)
1715 goto ERR;
1716 }
1717 }
1718
1719 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
1720 if (!IS_ISP2401 || main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
1721 err = allocate_mipi_frames(main_pipe, &stream->info);
1722 if (err)
1723 goto ERR;
1724 }
1725
1726 switch (pipe_id) {
1727 case IA_CSS_PIPE_ID_PREVIEW:
1728 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1729 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1730 max_input_width =
1731 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width;
1732
1733 err = create_host_preview_pipeline(main_pipe);
1734 if (err)
1735 goto ERR;
1736
1737 break;
1738
1739 case IA_CSS_PIPE_ID_VIDEO:
1740 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1741 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1742 max_input_width =
1743 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width;
1744
1745 err = create_host_video_pipeline(main_pipe);
1746 if (err)
1747 goto ERR;
1748
1749 break;
1750
1751 case IA_CSS_PIPE_ID_CAPTURE:
1752 capture_pipe = main_pipe;
1753
1754 break;
1755
1756 case IA_CSS_PIPE_ID_YUVPP:
1757 err = create_host_yuvpp_pipeline(main_pipe);
1758 if (err)
1759 goto ERR;
1760
1761 break;
1762
1763 default:
1764 err = -EINVAL;
1765 }
1766 if (err)
1767 goto ERR;
1768
1769 if (copy_pipe) {
1770 err = create_host_copy_pipeline(copy_pipe, max_input_width,
1771 main_pipe->continuous_frames[0]);
1772 if (err)
1773 goto ERR;
1774 }
1775
1776 if (capture_pipe) {
1777 err = create_host_capture_pipeline(capture_pipe);
1778 if (err)
1779 goto ERR;
1780 }
1781
1782 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
1783 if (!stream->config.continuous) {
1784 int i;
1785
1786 for (i = 1; i < stream->num_pipes && 0 == err; i++) {
1787 switch (stream->pipes[i]->mode) {
1788 case IA_CSS_PIPE_ID_PREVIEW:
1789 err = create_host_preview_pipeline(stream->pipes[i]);
1790 break;
1791 case IA_CSS_PIPE_ID_VIDEO:
1792 err = create_host_video_pipeline(stream->pipes[i]);
1793 break;
1794 case IA_CSS_PIPE_ID_CAPTURE:
1795 err = create_host_capture_pipeline(stream->pipes[i]);
1796 break;
1797 case IA_CSS_PIPE_ID_YUVPP:
1798 err = create_host_yuvpp_pipeline(stream->pipes[i]);
1799 break;
1800 default:
1801 err = -EINVAL;
1802 }
1803 if (err)
1804 goto ERR;
1805 }
1806 }
1807
1808 ERR:
1809 IA_CSS_LEAVE_ERR_PRIVATE(err);
1810 return err;
1811 }
1812
1813 static const struct ia_css_pipe default_pipe = IA_CSS_DEFAULT_PIPE;
1814 static const struct ia_css_preview_settings preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS;
1815 static const struct ia_css_capture_settings capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS;
1816 static const struct ia_css_video_settings video = IA_CSS_DEFAULT_VIDEO_SETTINGS;
1817 static const struct ia_css_yuvpp_settings yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
1818
1819 static int
init_pipe_defaults(enum ia_css_pipe_mode mode,struct ia_css_pipe * pipe,bool copy_pipe)1820 init_pipe_defaults(enum ia_css_pipe_mode mode,
1821 struct ia_css_pipe *pipe,
1822 bool copy_pipe)
1823 {
1824 if (!pipe) {
1825 IA_CSS_ERROR("NULL pipe parameter");
1826 return -EINVAL;
1827 }
1828
1829 /* Initialize pipe to pre-defined defaults */
1830 memcpy(pipe, &default_pipe, sizeof(default_pipe));
1831
1832 /* TODO: JB should not be needed, but temporary backward reference */
1833 switch (mode) {
1834 case IA_CSS_PIPE_MODE_PREVIEW:
1835 pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
1836 memcpy(&pipe->pipe_settings.preview, &preview, sizeof(preview));
1837 break;
1838 case IA_CSS_PIPE_MODE_CAPTURE:
1839 if (copy_pipe)
1840 pipe->mode = IA_CSS_PIPE_ID_COPY;
1841 else
1842 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
1843
1844 memcpy(&pipe->pipe_settings.capture, &capture, sizeof(capture));
1845 break;
1846 case IA_CSS_PIPE_MODE_VIDEO:
1847 pipe->mode = IA_CSS_PIPE_ID_VIDEO;
1848 memcpy(&pipe->pipe_settings.video, &video, sizeof(video));
1849 break;
1850 case IA_CSS_PIPE_MODE_COPY:
1851 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
1852 break;
1853 case IA_CSS_PIPE_MODE_YUVPP:
1854 pipe->mode = IA_CSS_PIPE_ID_YUVPP;
1855 memcpy(&pipe->pipe_settings.yuvpp, &yuvpp, sizeof(yuvpp));
1856 break;
1857 default:
1858 return -EINVAL;
1859 }
1860
1861 return 0;
1862 }
1863
1864 static void
pipe_global_init(void)1865 pipe_global_init(void)
1866 {
1867 u8 i;
1868
1869 my_css.pipe_counter = 0;
1870 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
1871 my_css.all_pipes[i] = NULL;
1872 }
1873
1874 static int
pipe_generate_pipe_num(const struct ia_css_pipe * pipe,unsigned int * pipe_number)1875 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
1876 unsigned int *pipe_number)
1877 {
1878 const u8 INVALID_PIPE_NUM = (uint8_t)~(0);
1879 u8 pipe_num = INVALID_PIPE_NUM;
1880 u8 i;
1881
1882 if (!pipe) {
1883 IA_CSS_ERROR("NULL pipe parameter");
1884 return -EINVAL;
1885 }
1886
1887 /* Assign a new pipe_num .... search for empty place */
1888 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
1889 if (!my_css.all_pipes[i]) {
1890 /* position is reserved */
1891 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
1892 pipe_num = i;
1893 break;
1894 }
1895 }
1896 if (pipe_num == INVALID_PIPE_NUM) {
1897 /* Max number of pipes already allocated */
1898 IA_CSS_ERROR("Max number of pipes already created");
1899 return -ENOSPC;
1900 }
1901
1902 my_css.pipe_counter++;
1903
1904 IA_CSS_LOG("pipe_num (%d)", pipe_num);
1905
1906 *pipe_number = pipe_num;
1907 return 0;
1908 }
1909
1910 static void
pipe_release_pipe_num(unsigned int pipe_num)1911 pipe_release_pipe_num(unsigned int pipe_num)
1912 {
1913 my_css.all_pipes[pipe_num] = NULL;
1914 my_css.pipe_counter--;
1915 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1916 "pipe_release_pipe_num (%d)\n", pipe_num);
1917 }
1918
1919 static int
create_pipe(enum ia_css_pipe_mode mode,struct ia_css_pipe ** pipe,bool copy_pipe)1920 create_pipe(enum ia_css_pipe_mode mode,
1921 struct ia_css_pipe **pipe,
1922 bool copy_pipe)
1923 {
1924 int err = 0;
1925 struct ia_css_pipe *me;
1926
1927 if (!pipe) {
1928 IA_CSS_ERROR("NULL pipe parameter");
1929 return -EINVAL;
1930 }
1931
1932 me = kmalloc(sizeof(*me), GFP_KERNEL);
1933 if (!me)
1934 return -ENOMEM;
1935
1936 err = init_pipe_defaults(mode, me, copy_pipe);
1937 if (err) {
1938 kfree(me);
1939 return err;
1940 }
1941
1942 err = pipe_generate_pipe_num(me, &me->pipe_num);
1943 if (err) {
1944 kfree(me);
1945 return err;
1946 }
1947
1948 *pipe = me;
1949 return 0;
1950 }
1951
1952 struct ia_css_pipe *
find_pipe_by_num(uint32_t pipe_num)1953 find_pipe_by_num(uint32_t pipe_num)
1954 {
1955 unsigned int i;
1956
1957 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
1958 if (my_css.all_pipes[i] &&
1959 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) {
1960 return my_css.all_pipes[i];
1961 }
1962 }
1963 return NULL;
1964 }
1965
1966 int
ia_css_pipe_destroy(struct ia_css_pipe * pipe)1967 ia_css_pipe_destroy(struct ia_css_pipe *pipe)
1968 {
1969 int err = 0;
1970
1971 IA_CSS_ENTER("pipe = %p", pipe);
1972
1973 if (!pipe) {
1974 IA_CSS_LEAVE_ERR(-EINVAL);
1975 return -EINVAL;
1976 }
1977
1978 if (pipe->stream) {
1979 IA_CSS_LOG("ia_css_stream_destroy not called!");
1980 IA_CSS_LEAVE_ERR(-EINVAL);
1981 return -EINVAL;
1982 }
1983
1984 switch (pipe->config.mode) {
1985 case IA_CSS_PIPE_MODE_PREVIEW:
1986 /*
1987 * need to take into account that this function is also called
1988 * on the internal copy pipe
1989 */
1990 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
1991 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
1992 pipe->continuous_frames);
1993 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
1994 pipe->cont_md_buffers);
1995 if (pipe->pipe_settings.preview.copy_pipe) {
1996 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe);
1997 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1998 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
1999 err);
2000 }
2001 }
2002 break;
2003 case IA_CSS_PIPE_MODE_VIDEO:
2004 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
2005 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2006 pipe->continuous_frames);
2007 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2008 pipe->cont_md_buffers);
2009 if (pipe->pipe_settings.video.copy_pipe) {
2010 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe);
2011 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2012 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2013 err);
2014 }
2015 }
2016 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES,
2017 pipe->pipe_settings.video.tnr_frames);
2018 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2019 pipe->pipe_settings.video.delay_frames);
2020 break;
2021 case IA_CSS_PIPE_MODE_CAPTURE:
2022 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2023 pipe->pipe_settings.capture.delay_frames);
2024 break;
2025 case IA_CSS_PIPE_MODE_COPY:
2026 break;
2027 case IA_CSS_PIPE_MODE_YUVPP:
2028 break;
2029 }
2030
2031 if (pipe->scaler_pp_lut != mmgr_NULL) {
2032 hmm_free(pipe->scaler_pp_lut);
2033 pipe->scaler_pp_lut = mmgr_NULL;
2034 }
2035
2036 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL;
2037 sh_css_pipe_free_shading_table(pipe);
2038
2039 ia_css_pipeline_destroy(&pipe->pipeline);
2040 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe));
2041
2042 kfree(pipe);
2043 IA_CSS_LEAVE("err = %d", err);
2044 return err;
2045 }
2046
2047 void
ia_css_uninit(void)2048 ia_css_uninit(void)
2049 {
2050 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n");
2051
2052 sh_css_params_free_default_gdc_lut();
2053
2054 /* TODO: JB: implement decent check and handling of freeing mipi frames */
2055 if (!mipi_is_free())
2056 dev_warn(atomisp_dev, "mipi frames are not freed.\n");
2057
2058 /* cleanup generic data */
2059 sh_css_params_uninit();
2060 ia_css_refcount_uninit();
2061
2062 ia_css_rmgr_uninit();
2063
2064 if (!IS_ISP2401) {
2065 /* needed for reprogramming the inputformatter after power cycle of css */
2066 ifmtr_set_if_blocking_mode_reset = true;
2067 }
2068
2069 ia_css_spctrl_unload_fw(SP0_ID);
2070 sh_css_sp_set_sp_running(false);
2071 /* check and free any remaining mipi frames */
2072 free_mipi_frames(NULL);
2073
2074 sh_css_sp_reset_global_vars();
2075
2076 ia_css_isys_uninit();
2077
2078 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n");
2079 }
2080
ia_css_irq_translate(unsigned int * irq_infos)2081 int ia_css_irq_translate(
2082 unsigned int *irq_infos)
2083 {
2084 enum virq_id irq;
2085 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
2086 unsigned int infos = 0;
2087
2088 /* irq_infos can be NULL, but that would make the function useless */
2089 /* assert(irq_infos != NULL); */
2090 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2091 "ia_css_irq_translate() enter: irq_infos=%p\n", irq_infos);
2092
2093 while (status == hrt_isp_css_irq_status_more_irqs) {
2094 status = virq_get_channel_id(&irq);
2095 if (status == hrt_isp_css_irq_status_error)
2096 return -EINVAL;
2097
2098
2099 switch (irq) {
2100 case virq_sp:
2101 /*
2102 * When SP goes to idle, info is available in the
2103 * event queue.
2104 */
2105 infos |= IA_CSS_IRQ_INFO_EVENTS_READY;
2106 break;
2107 case virq_isp:
2108 break;
2109 case virq_isys_sof:
2110 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
2111 break;
2112 case virq_isys_eof:
2113 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
2114 break;
2115 case virq_isys_csi:
2116 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
2117 break;
2118 case virq_ifmt0_id:
2119 if (!IS_ISP2401)
2120 infos |= IA_CSS_IRQ_INFO_IF_ERROR;
2121 break;
2122 case virq_dma:
2123 infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
2124 break;
2125 case virq_sw_pin_0:
2126 infos |= sh_css_get_sw_interrupt_value(0);
2127 break;
2128 case virq_sw_pin_1:
2129 infos |= sh_css_get_sw_interrupt_value(1);
2130 /* pqiao TODO: also assumption here */
2131 break;
2132 default:
2133 break;
2134 }
2135 }
2136
2137 if (irq_infos)
2138 *irq_infos = infos;
2139
2140 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2141 "ia_css_irq_translate() leave: irq_infos=%u\n",
2142 infos);
2143
2144 return 0;
2145 }
2146
ia_css_irq_enable(enum ia_css_irq_info info,bool enable)2147 int ia_css_irq_enable(
2148 enum ia_css_irq_info info,
2149 bool enable)
2150 {
2151 enum virq_id irq = N_virq_id;
2152
2153 IA_CSS_ENTER("info=%d, enable=%d", info, enable);
2154
2155 switch (info) {
2156 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2157 if (IS_ISP2401)
2158 /* Just ignore those unused IRQs without printing errors */
2159 return 0;
2160
2161 irq = virq_isys_sof;
2162 break;
2163 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2164 if (IS_ISP2401)
2165 /* Just ignore those unused IRQs without printing errors */
2166 return 0;
2167
2168 irq = virq_isys_eof;
2169 break;
2170 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2171 if (IS_ISP2401)
2172 /* Just ignore those unused IRQs without printing errors */
2173 return 0;
2174
2175 irq = virq_isys_csi;
2176 break;
2177 case IA_CSS_IRQ_INFO_IF_ERROR:
2178 if (IS_ISP2401)
2179 /* Just ignore those unused IRQs without printing errors */
2180 return 0;
2181
2182 irq = virq_ifmt0_id;
2183 break;
2184 case IA_CSS_IRQ_INFO_DMA_ERROR:
2185 irq = virq_dma;
2186 break;
2187 case IA_CSS_IRQ_INFO_SW_0:
2188 irq = virq_sw_pin_0;
2189 break;
2190 case IA_CSS_IRQ_INFO_SW_1:
2191 irq = virq_sw_pin_1;
2192 break;
2193 default:
2194 IA_CSS_LEAVE_ERR(-EINVAL);
2195 return -EINVAL;
2196 }
2197
2198 cnd_virq_enable_channel(irq, enable);
2199
2200 IA_CSS_LEAVE_ERR(0);
2201 return 0;
2202 }
2203
2204
2205 static unsigned int
sh_css_get_sw_interrupt_value(unsigned int irq)2206 sh_css_get_sw_interrupt_value(unsigned int irq)
2207 {
2208 unsigned int irq_value;
2209
2210 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2211 "sh_css_get_sw_interrupt_value() enter: irq=%d\n", irq);
2212 irq_value = sh_css_sp_get_sw_interrupt_value(irq);
2213 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2214 "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n", irq_value);
2215 return irq_value;
2216 }
2217
2218 /*
2219 * configure and load the copy binary, the next binary is used to
2220 * determine whether the copy binary needs to do left padding.
2221 */
load_copy_binary(struct ia_css_pipe * pipe,struct ia_css_binary * copy_binary,struct ia_css_binary * next_binary)2222 static int load_copy_binary(
2223 struct ia_css_pipe *pipe,
2224 struct ia_css_binary *copy_binary,
2225 struct ia_css_binary *next_binary)
2226 {
2227 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info;
2228 unsigned int left_padding;
2229 int err;
2230 struct ia_css_binary_descr copy_descr;
2231
2232 /* next_binary can be NULL */
2233 assert(pipe);
2234 assert(copy_binary);
2235 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2236 "load_copy_binary() enter:\n");
2237
2238 if (next_binary) {
2239 copy_out_info = next_binary->in_frame_info;
2240 left_padding = next_binary->left_padding;
2241 } else {
2242 copy_out_info = pipe->output_info[0];
2243 copy_vf_info = pipe->vf_output_info[0];
2244 ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
2245 left_padding = 0;
2246 }
2247
2248 ia_css_pipe_get_copy_binarydesc(pipe, ©_descr,
2249 ©_in_info, ©_out_info,
2250 (next_binary) ? NULL : NULL/*TODO: ©_vf_info*/);
2251 err = ia_css_binary_find(©_descr, copy_binary);
2252 if (err)
2253 return err;
2254 copy_binary->left_padding = left_padding;
2255 return 0;
2256 }
2257
2258 static int
alloc_continuous_frames(struct ia_css_pipe * pipe,bool init_time)2259 alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time)
2260 {
2261 int err = 0;
2262 struct ia_css_frame_info ref_info;
2263 enum ia_css_pipe_id pipe_id;
2264 bool continuous;
2265 unsigned int i, idx;
2266 unsigned int num_frames;
2267
2268 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
2269
2270 if ((!pipe) || (!pipe->stream)) {
2271 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2272 return -EINVAL;
2273 }
2274
2275 pipe_id = pipe->mode;
2276 continuous = pipe->stream->config.continuous;
2277
2278 if (continuous) {
2279 if (init_time) {
2280 num_frames = pipe->stream->config.init_num_cont_raw_buf;
2281 pipe->stream->continuous_pipe = pipe;
2282 } else {
2283 num_frames = pipe->stream->config.target_num_cont_raw_buf;
2284 }
2285 } else {
2286 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
2287 }
2288
2289 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2290 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
2291 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2292 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
2293 } else {
2294 /* should not happen */
2295 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2296 return -EINVAL;
2297 }
2298
2299 if (IS_ISP2401) {
2300 /* For CSI2+, the continuous frame will hold the full input frame */
2301 ref_info.res.width = pipe->stream->config.input_config.input_res.width;
2302 ref_info.res.height = pipe->stream->config.input_config.input_res.height;
2303
2304 /* Ensure padded width is aligned for 2401 */
2305 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
2306 }
2307
2308 if (pipe->stream->config.pack_raw_pixels) {
2309 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2310 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2311 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
2312 } else
2313 {
2314 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2315 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2316 ref_info.format = IA_CSS_FRAME_FORMAT_RAW;
2317 }
2318
2319 /* Write format back to binary */
2320 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2321 pipe->pipe_settings.preview.preview_binary.in_frame_info.format =
2322 ref_info.format;
2323 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2324 pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format;
2325 } else {
2326 /* should not happen */
2327 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2328 return -EINVAL;
2329 }
2330
2331 if (init_time)
2332 idx = 0;
2333 else
2334 idx = pipe->stream->config.init_num_cont_raw_buf;
2335
2336 for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) {
2337 /* free previous frame */
2338 if (pipe->continuous_frames[i]) {
2339 ia_css_frame_free(pipe->continuous_frames[i]);
2340 pipe->continuous_frames[i] = NULL;
2341 }
2342 /* free previous metadata buffer */
2343 ia_css_metadata_free(pipe->cont_md_buffers[i]);
2344 pipe->cont_md_buffers[i] = NULL;
2345
2346 /* check if new frame needed */
2347 if (i < num_frames) {
2348 /* allocate new frame */
2349 err = ia_css_frame_allocate_from_info(
2350 &pipe->continuous_frames[i],
2351 &ref_info);
2352 if (err) {
2353 IA_CSS_LEAVE_ERR_PRIVATE(err);
2354 return err;
2355 }
2356 /* allocate metadata buffer */
2357 pipe->cont_md_buffers[i] = ia_css_metadata_allocate(
2358 &pipe->stream->info.metadata_info);
2359 }
2360 }
2361 IA_CSS_LEAVE_ERR_PRIVATE(0);
2362 return 0;
2363 }
2364
2365 int
ia_css_alloc_continuous_frame_remain(struct ia_css_stream * stream)2366 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream)
2367 {
2368 if (!stream)
2369 return -EINVAL;
2370 return alloc_continuous_frames(stream->continuous_pipe, false);
2371 }
2372
2373 static int
load_preview_binaries(struct ia_css_pipe * pipe)2374 load_preview_binaries(struct ia_css_pipe *pipe)
2375 {
2376 struct ia_css_frame_info prev_in_info,
2377 prev_bds_out_info,
2378 prev_out_info,
2379 prev_vf_info;
2380 struct ia_css_binary_descr preview_descr;
2381 bool online;
2382 int err = 0;
2383 bool need_vf_pp = false;
2384 bool need_isp_copy_binary = false;
2385 bool sensor = false;
2386 bool continuous;
2387
2388 /* preview only have 1 output pin now */
2389 struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
2390 struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview;
2391
2392 IA_CSS_ENTER_PRIVATE("");
2393 assert(pipe);
2394 assert(pipe->stream);
2395 assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
2396
2397 online = pipe->stream->config.online;
2398
2399 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
2400 continuous = pipe->stream->config.continuous;
2401
2402 if (mycs->preview_binary.info)
2403 return 0;
2404
2405 err = ia_css_util_check_input(&pipe->stream->config, false, false);
2406 if (err)
2407 return err;
2408 err = ia_css_frame_check_info(pipe_out_info);
2409 if (err)
2410 return err;
2411
2412 /*
2413 * Note: the current selection of vf_pp binary and
2414 * parameterization of the preview binary contains a few pieces
2415 * of hardcoded knowledge. This needs to be cleaned up such that
2416 * the binary selection becomes more generic.
2417 * The vf_pp binary is needed if one or more of the following features
2418 * are required:
2419 * 1. YUV downscaling.
2420 * 2. Digital zoom.
2421 * 3. An output format that is not supported by the preview binary.
2422 * In practice this means something other than yuv_line or nv12.
2423 * The decision if the vf_pp binary is needed for YUV downscaling is
2424 * made after the preview binary selection, since some preview binaries
2425 * can perform the requested YUV downscaling.
2426 */
2427 need_vf_pp = pipe->config.enable_dz;
2428 need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE &&
2429 !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 ||
2430 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 ||
2431 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY);
2432
2433 /* Preview step 1 */
2434 if (pipe->vf_yuv_ds_input_info.res.width)
2435 prev_vf_info = pipe->vf_yuv_ds_input_info;
2436 else
2437 prev_vf_info = *pipe_out_info;
2438 /*
2439 * If vf_pp is needed, then preview must output yuv_line.
2440 * The exception is when vf_pp is manually disabled, that is only
2441 * used in combination with a pipeline extension that requires
2442 * yuv_line as input.
2443 */
2444 if (need_vf_pp)
2445 ia_css_frame_info_set_format(&prev_vf_info,
2446 IA_CSS_FRAME_FORMAT_YUV_LINE);
2447
2448 err = ia_css_pipe_get_preview_binarydesc(
2449 pipe,
2450 &preview_descr,
2451 &prev_in_info,
2452 &prev_bds_out_info,
2453 &prev_out_info,
2454 &prev_vf_info);
2455 if (err)
2456 return err;
2457 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary);
2458 if (err)
2459 return err;
2460
2461 /* The vf_pp binary is needed when (further) YUV downscaling is required */
2462 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width;
2463 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height;
2464
2465 /*
2466 * When vf_pp is needed, then the output format of the selected
2467 * preview binary must be yuv_line. If this is not the case,
2468 * then the preview binary selection is done again.
2469 */
2470 if (need_vf_pp &&
2471 (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) {
2472 /* Preview step 2 */
2473 if (pipe->vf_yuv_ds_input_info.res.width)
2474 prev_vf_info = pipe->vf_yuv_ds_input_info;
2475 else
2476 prev_vf_info = *pipe_out_info;
2477
2478 ia_css_frame_info_set_format(&prev_vf_info,
2479 IA_CSS_FRAME_FORMAT_YUV_LINE);
2480
2481 err = ia_css_pipe_get_preview_binarydesc(
2482 pipe,
2483 &preview_descr,
2484 &prev_in_info,
2485 &prev_bds_out_info,
2486 &prev_out_info,
2487 &prev_vf_info);
2488 if (err)
2489 return err;
2490 err = ia_css_binary_find(&preview_descr,
2491 &mycs->preview_binary);
2492 if (err)
2493 return err;
2494 }
2495
2496 if (need_vf_pp) {
2497 struct ia_css_binary_descr vf_pp_descr;
2498
2499 /* Viewfinder post-processing */
2500 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
2501 &mycs->preview_binary.out_frame_info[0],
2502 pipe_out_info);
2503 err = ia_css_binary_find(&vf_pp_descr,
2504 &mycs->vf_pp_binary);
2505 if (err)
2506 return err;
2507 }
2508
2509 if (IS_ISP2401) {
2510 /*
2511 * When the input system is 2401, only the Direct Sensor Mode
2512 * Offline Preview uses the ISP copy binary.
2513 */
2514 need_isp_copy_binary = !online && sensor;
2515 } else {
2516 /*
2517 * About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
2518 * This is typical the case with SkyCam (which has no input system) but it also
2519 * applies to all cases where the driver chooses for memory based input frames.
2520 * In these cases, a copy binary (which typical copies sensor data to DDR) does
2521 * not have much use.
2522 */
2523 need_isp_copy_binary = !online && !continuous;
2524 }
2525
2526 /* Copy */
2527 if (need_isp_copy_binary) {
2528 err = load_copy_binary(pipe,
2529 &mycs->copy_binary,
2530 &mycs->preview_binary);
2531 if (err)
2532 return err;
2533 }
2534
2535 if (pipe->shading_table) {
2536 ia_css_shading_table_free(pipe->shading_table);
2537 pipe->shading_table = NULL;
2538 }
2539
2540 return 0;
2541 }
2542
2543 static void
ia_css_binary_unload(struct ia_css_binary * binary)2544 ia_css_binary_unload(struct ia_css_binary *binary)
2545 {
2546 ia_css_binary_destroy_isp_parameters(binary);
2547 }
2548
2549 static int
unload_preview_binaries(struct ia_css_pipe * pipe)2550 unload_preview_binaries(struct ia_css_pipe *pipe)
2551 {
2552 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
2553
2554 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
2555 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2556 return -EINVAL;
2557 }
2558 ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary);
2559 ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary);
2560 ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary);
2561
2562 IA_CSS_LEAVE_ERR_PRIVATE(0);
2563 return 0;
2564 }
2565
last_output_firmware(const struct ia_css_fw_info * fw)2566 static const struct ia_css_fw_info *last_output_firmware(
2567 const struct ia_css_fw_info *fw)
2568 {
2569 const struct ia_css_fw_info *last_fw = NULL;
2570 /* fw can be NULL */
2571 IA_CSS_ENTER_LEAVE_PRIVATE("");
2572
2573 for (; fw; fw = fw->next) {
2574 const struct ia_css_fw_info *info = fw;
2575
2576 if (info->info.isp.sp.enable.output)
2577 last_fw = fw;
2578 }
2579 return last_fw;
2580 }
2581
add_firmwares(struct ia_css_pipeline * me,struct ia_css_binary * binary,const struct ia_css_fw_info * fw,const struct ia_css_fw_info * last_fw,unsigned int binary_mode,struct ia_css_frame * in_frame,struct ia_css_frame * out_frame,struct ia_css_frame * vf_frame,struct ia_css_pipeline_stage ** my_stage,struct ia_css_pipeline_stage ** vf_stage)2582 static int add_firmwares(
2583 struct ia_css_pipeline *me,
2584 struct ia_css_binary *binary,
2585 const struct ia_css_fw_info *fw,
2586 const struct ia_css_fw_info *last_fw,
2587 unsigned int binary_mode,
2588 struct ia_css_frame *in_frame,
2589 struct ia_css_frame *out_frame,
2590 struct ia_css_frame *vf_frame,
2591 struct ia_css_pipeline_stage **my_stage,
2592 struct ia_css_pipeline_stage **vf_stage)
2593 {
2594 int err = 0;
2595 struct ia_css_pipeline_stage *extra_stage = NULL;
2596 struct ia_css_pipeline_stage_desc stage_desc;
2597
2598 /* all args can be NULL ??? */
2599 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2600 "add_firmwares() enter:\n");
2601
2602 for (; fw; fw = fw->next) {
2603 struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
2604 struct ia_css_frame *in = NULL;
2605 struct ia_css_frame *vf = NULL;
2606
2607 if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0))
2608 out[0] = out_frame;
2609
2610 if (fw->info.isp.sp.enable.in_frame != 0)
2611 in = in_frame;
2612
2613 if (fw->info.isp.sp.enable.out_frame != 0)
2614 vf = vf_frame;
2615
2616 ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
2617 out, in, vf, fw, binary_mode);
2618 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
2619 &extra_stage);
2620 if (err)
2621 return err;
2622 if (fw->info.isp.sp.enable.output != 0)
2623 in_frame = extra_stage->args.out_frame[0];
2624 if (my_stage && !*my_stage && extra_stage)
2625 *my_stage = extra_stage;
2626 if (vf_stage && !*vf_stage && extra_stage &&
2627 fw->info.isp.sp.enable.vf_veceven)
2628 *vf_stage = extra_stage;
2629 }
2630 return err;
2631 }
2632
add_vf_pp_stage(struct ia_css_pipe * pipe,struct ia_css_frame * in_frame,struct ia_css_frame * out_frame,struct ia_css_binary * vf_pp_binary,struct ia_css_pipeline_stage ** vf_pp_stage)2633 static int add_vf_pp_stage(
2634 struct ia_css_pipe *pipe,
2635 struct ia_css_frame *in_frame,
2636 struct ia_css_frame *out_frame,
2637 struct ia_css_binary *vf_pp_binary,
2638 struct ia_css_pipeline_stage **vf_pp_stage)
2639 {
2640 struct ia_css_pipeline *me = NULL;
2641 const struct ia_css_fw_info *last_fw = NULL;
2642 int err = 0;
2643 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
2644 struct ia_css_pipeline_stage_desc stage_desc;
2645
2646 /* out_frame can be NULL ??? */
2647
2648 if (!pipe)
2649 return -EINVAL;
2650 if (!in_frame)
2651 return -EINVAL;
2652 if (!vf_pp_binary)
2653 return -EINVAL;
2654 if (!vf_pp_stage)
2655 return -EINVAL;
2656
2657 ia_css_pipe_util_create_output_frames(out_frames);
2658 me = &pipe->pipeline;
2659
2660 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2661 "add_vf_pp_stage() enter:\n");
2662
2663 *vf_pp_stage = NULL;
2664
2665 last_fw = last_output_firmware(pipe->vf_stage);
2666 if (!pipe->extra_config.disable_vf_pp) {
2667 if (last_fw) {
2668 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
2669 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
2670 out_frames, in_frame, NULL);
2671 } else {
2672 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
2673 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
2674 out_frames, in_frame, NULL);
2675 }
2676 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage);
2677 if (err)
2678 return err;
2679 in_frame = (*vf_pp_stage)->args.out_frame[0];
2680 }
2681 err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw,
2682 IA_CSS_BINARY_MODE_VF_PP,
2683 in_frame, out_frame, NULL,
2684 vf_pp_stage, NULL);
2685 return err;
2686 }
2687
add_yuv_scaler_stage(struct ia_css_pipe * pipe,struct ia_css_pipeline * me,struct ia_css_frame * in_frame,struct ia_css_frame * out_frame,struct ia_css_frame * internal_out_frame,struct ia_css_binary * yuv_scaler_binary,struct ia_css_pipeline_stage ** pre_vf_pp_stage)2688 static int add_yuv_scaler_stage(
2689 struct ia_css_pipe *pipe,
2690 struct ia_css_pipeline *me,
2691 struct ia_css_frame *in_frame,
2692 struct ia_css_frame *out_frame,
2693 struct ia_css_frame *internal_out_frame,
2694 struct ia_css_binary *yuv_scaler_binary,
2695 struct ia_css_pipeline_stage **pre_vf_pp_stage)
2696 {
2697 const struct ia_css_fw_info *last_fw;
2698 int err = 0;
2699 struct ia_css_frame *vf_frame = NULL;
2700 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
2701 struct ia_css_pipeline_stage_desc stage_desc;
2702
2703 /* out_frame can be NULL ??? */
2704 assert(in_frame);
2705 assert(pipe);
2706 assert(me);
2707 assert(yuv_scaler_binary);
2708 assert(pre_vf_pp_stage);
2709 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2710 "add_yuv_scaler_stage() enter:\n");
2711
2712 *pre_vf_pp_stage = NULL;
2713 ia_css_pipe_util_create_output_frames(out_frames);
2714
2715 last_fw = last_output_firmware(pipe->output_stage);
2716
2717 if (last_fw) {
2718 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
2719 ia_css_pipe_get_generic_stage_desc(&stage_desc,
2720 yuv_scaler_binary, out_frames, in_frame, vf_frame);
2721 } else {
2722 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
2723 ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame);
2724 ia_css_pipe_get_generic_stage_desc(&stage_desc,
2725 yuv_scaler_binary, out_frames, in_frame, vf_frame);
2726 }
2727 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
2728 pre_vf_pp_stage);
2729 if (err)
2730 return err;
2731 in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
2732
2733 err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw,
2734 IA_CSS_BINARY_MODE_CAPTURE_PP,
2735 in_frame, out_frame, vf_frame,
2736 NULL, pre_vf_pp_stage);
2737 /* If a firmware produce vf_pp output, we set that as vf_pp input */
2738 (*pre_vf_pp_stage)->args.vf_downscale_log2 =
2739 yuv_scaler_binary->vf_downscale_log2;
2740
2741 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2742 "add_yuv_scaler_stage() leave:\n");
2743 return err;
2744 }
2745
add_capture_pp_stage(struct ia_css_pipe * pipe,struct ia_css_pipeline * me,struct ia_css_frame * in_frame,struct ia_css_frame * out_frame,struct ia_css_binary * capture_pp_binary,struct ia_css_pipeline_stage ** capture_pp_stage)2746 static int add_capture_pp_stage(
2747 struct ia_css_pipe *pipe,
2748 struct ia_css_pipeline *me,
2749 struct ia_css_frame *in_frame,
2750 struct ia_css_frame *out_frame,
2751 struct ia_css_binary *capture_pp_binary,
2752 struct ia_css_pipeline_stage **capture_pp_stage)
2753 {
2754 const struct ia_css_fw_info *last_fw = NULL;
2755 int err = 0;
2756 struct ia_css_frame *vf_frame = NULL;
2757 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
2758 struct ia_css_pipeline_stage_desc stage_desc;
2759
2760 /* out_frame can be NULL ??? */
2761 assert(in_frame);
2762 assert(pipe);
2763 assert(me);
2764 assert(capture_pp_binary);
2765 assert(capture_pp_stage);
2766 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2767 "add_capture_pp_stage() enter:\n");
2768
2769 *capture_pp_stage = NULL;
2770 ia_css_pipe_util_create_output_frames(out_frames);
2771
2772 last_fw = last_output_firmware(pipe->output_stage);
2773 err = ia_css_frame_allocate_from_info(&vf_frame,
2774 &capture_pp_binary->vf_frame_info);
2775 if (err)
2776 return err;
2777 if (last_fw) {
2778 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
2779 ia_css_pipe_get_generic_stage_desc(&stage_desc,
2780 capture_pp_binary, out_frames, NULL, vf_frame);
2781 } else {
2782 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
2783 ia_css_pipe_get_generic_stage_desc(&stage_desc,
2784 capture_pp_binary, out_frames, NULL, vf_frame);
2785 }
2786 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
2787 capture_pp_stage);
2788 if (err)
2789 return err;
2790 err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
2791 IA_CSS_BINARY_MODE_CAPTURE_PP,
2792 in_frame, out_frame, vf_frame,
2793 NULL, capture_pp_stage);
2794 /* If a firmware produce vf_pp output, we set that as vf_pp input */
2795 if (*capture_pp_stage) {
2796 (*capture_pp_stage)->args.vf_downscale_log2 =
2797 capture_pp_binary->vf_downscale_log2;
2798 }
2799 return err;
2800 }
2801
sh_css_setup_queues(void)2802 static void sh_css_setup_queues(void)
2803 {
2804 const struct ia_css_fw_info *fw;
2805 unsigned int HIVE_ADDR_host_sp_queues_initialized;
2806
2807 sh_css_hmm_buffer_record_init();
2808
2809 sh_css_event_init_irq_mask();
2810
2811 fw = &sh_css_sp_fw;
2812 HIVE_ADDR_host_sp_queues_initialized =
2813 fw->info.sp.host_sp_queues_initialized;
2814
2815 ia_css_bufq_init();
2816
2817 /* set "host_sp_queues_initialized" to "true" */
2818 sp_dmem_store_uint32(SP0_ID,
2819 (unsigned int)sp_address_of(host_sp_queues_initialized),
2820 (uint32_t)(1));
2821 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n");
2822 }
2823
2824 static int
init_vf_frameinfo_defaults(struct ia_css_pipe * pipe,struct ia_css_frame * vf_frame,unsigned int idx)2825 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
2826 struct ia_css_frame *vf_frame, unsigned int idx)
2827 {
2828 int err = 0;
2829 unsigned int thread_id;
2830 enum sh_css_queue_id queue_id;
2831
2832 assert(vf_frame);
2833
2834 sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->frame_info, idx);
2835 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
2836 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id);
2837 vf_frame->dynamic_queue_id = queue_id;
2838 vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx;
2839
2840 err = ia_css_frame_init_planes(vf_frame);
2841 return err;
2842 }
2843
2844 static unsigned int
get_crop_lines_for_bayer_order(const struct ia_css_stream_config * config)2845 get_crop_lines_for_bayer_order(const struct ia_css_stream_config *config)
2846 {
2847 assert(config);
2848 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR) ||
2849 (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
2850 return 1;
2851
2852 return 0;
2853 }
2854
2855 static unsigned int
get_crop_columns_for_bayer_order(const struct ia_css_stream_config * config)2856 get_crop_columns_for_bayer_order(const struct ia_css_stream_config *config)
2857 {
2858 assert(config);
2859 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB) ||
2860 (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
2861 return 1;
2862
2863 return 0;
2864 }
2865
2866 /*
2867 * This function is to get the sum of all extra pixels in addition to the effective
2868 * input, it includes dvs envelop and filter run-in
2869 */
get_pipe_extra_pixel(struct ia_css_pipe * pipe,unsigned int * extra_row,unsigned int * extra_column)2870 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
2871 unsigned int *extra_row, unsigned int *extra_column)
2872 {
2873 enum ia_css_pipe_id pipe_id = pipe->mode;
2874 unsigned int left_cropping = 0, top_cropping = 0;
2875 unsigned int i;
2876 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
2877
2878 /*
2879 * The dvs envelope info may not be correctly sent down via pipe config
2880 * The check is made and the correct value is populated in the binary info
2881 * Use this value when computing crop, else excess lines may get trimmed
2882 */
2883 switch (pipe_id) {
2884 case IA_CSS_PIPE_ID_PREVIEW:
2885 if (pipe->pipe_settings.preview.preview_binary.info) {
2886 left_cropping =
2887 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
2888 top_cropping =
2889 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
2890 }
2891 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
2892 break;
2893 case IA_CSS_PIPE_ID_VIDEO:
2894 if (pipe->pipe_settings.video.video_binary.info) {
2895 left_cropping =
2896 pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
2897 top_cropping =
2898 pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
2899 }
2900 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
2901 break;
2902 case IA_CSS_PIPE_ID_CAPTURE:
2903 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
2904 if (pipe->pipe_settings.capture.primary_binary[i].info) {
2905 left_cropping +=
2906 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
2907 top_cropping +=
2908 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
2909 }
2910 dvs_env.width +=
2911 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
2912 dvs_env.height +=
2913 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
2914 }
2915 break;
2916 default:
2917 break;
2918 }
2919
2920 *extra_row = top_cropping + dvs_env.height;
2921 *extra_column = left_cropping + dvs_env.width;
2922 }
2923
2924 void
ia_css_get_crop_offsets(struct ia_css_pipe * pipe,struct ia_css_frame_info * in_frame)2925 ia_css_get_crop_offsets(
2926 struct ia_css_pipe *pipe,
2927 struct ia_css_frame_info *in_frame)
2928 {
2929 unsigned int row = 0;
2930 unsigned int column = 0;
2931 struct ia_css_resolution *input_res;
2932 struct ia_css_resolution *effective_res;
2933 unsigned int extra_row = 0, extra_col = 0;
2934 unsigned int min_reqd_height, min_reqd_width;
2935
2936 assert(pipe);
2937 assert(pipe->stream);
2938 assert(in_frame);
2939
2940 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
2941 pipe, pipe->config.input_effective_res.width,
2942 pipe->config.input_effective_res.height);
2943
2944 input_res = &pipe->stream->config.input_config.input_res;
2945
2946 if (IS_ISP2401)
2947 effective_res = &pipe->config.input_effective_res;
2948 else
2949 effective_res = &pipe->stream->config.input_config.effective_res;
2950
2951 get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
2952
2953 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
2954
2955 min_reqd_height = effective_res->height + extra_row;
2956 min_reqd_width = effective_res->width + extra_col;
2957
2958 if (input_res->height > min_reqd_height) {
2959 row = (input_res->height - min_reqd_height) / 2;
2960 row &= ~0x1;
2961 }
2962 if (input_res->width > min_reqd_width) {
2963 column = (input_res->width - min_reqd_width) / 2;
2964 column &= ~0x1;
2965 }
2966
2967 /*
2968 * TODO:
2969 * 1. Require the special support for RAW10 packed mode.
2970 * 2. Require the special support for the online use cases.
2971 */
2972
2973 /*
2974 * ISP expects GRBG bayer order, we skip one line and/or one row
2975 * to correct in case the input bayer order is different.
2976 */
2977 column += get_crop_columns_for_bayer_order(&pipe->stream->config);
2978 row += get_crop_lines_for_bayer_order(&pipe->stream->config);
2979
2980 in_frame->crop_info.start_column = column;
2981 in_frame->crop_info.start_line = row;
2982
2983 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
2984
2985 return;
2986 }
2987
2988 static int
init_in_frameinfo_memory_defaults(struct ia_css_pipe * pipe,struct ia_css_frame * frame,enum ia_css_frame_format format)2989 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
2990 struct ia_css_frame *frame, enum ia_css_frame_format format)
2991 {
2992 struct ia_css_frame *in_frame;
2993 int err = 0;
2994 unsigned int thread_id;
2995 enum sh_css_queue_id queue_id;
2996
2997 assert(frame);
2998 in_frame = frame;
2999
3000 in_frame->frame_info.format = format;
3001
3002 if (IS_ISP2401 && format == IA_CSS_FRAME_FORMAT_RAW) {
3003 in_frame->frame_info.format = (pipe->stream->config.pack_raw_pixels) ?
3004 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3005 }
3006
3007 in_frame->frame_info.res.width = pipe->stream->config.input_config.input_res.width;
3008 in_frame->frame_info.res.height = pipe->stream->config.input_config.input_res.height;
3009 in_frame->frame_info.raw_bit_depth = ia_css_pipe_util_pipe_input_format_bpp(pipe);
3010 ia_css_frame_info_set_width(&in_frame->frame_info,
3011 pipe->stream->config.input_config.input_res.width, 0);
3012 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3013 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3014 in_frame->dynamic_queue_id = queue_id;
3015 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3016
3017 if (IS_ISP2401)
3018 ia_css_get_crop_offsets(pipe, &in_frame->frame_info);
3019
3020 err = ia_css_frame_init_planes(in_frame);
3021
3022 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "%s() bayer_order = %d\n",
3023 __func__, in_frame->frame_info.raw_bayer_order);
3024
3025 return err;
3026 }
3027
3028 static int
init_out_frameinfo_defaults(struct ia_css_pipe * pipe,struct ia_css_frame * out_frame,unsigned int idx)3029 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3030 struct ia_css_frame *out_frame, unsigned int idx)
3031 {
3032 int err = 0;
3033 unsigned int thread_id;
3034 enum sh_css_queue_id queue_id;
3035
3036 assert(out_frame);
3037
3038 sh_css_pipe_get_output_frame_info(pipe, &out_frame->frame_info, idx);
3039 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3040 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3041 out_frame->dynamic_queue_id = queue_id;
3042 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3043 err = ia_css_frame_init_planes(out_frame);
3044
3045 return err;
3046 }
3047
3048 /* Create stages for video pipe */
create_host_video_pipeline(struct ia_css_pipe * pipe)3049 static int create_host_video_pipeline(struct ia_css_pipe *pipe)
3050 {
3051 struct ia_css_pipeline_stage_desc stage_desc;
3052 struct ia_css_binary *copy_binary, *video_binary,
3053 *yuv_scaler_binary, *vf_pp_binary;
3054 struct ia_css_pipeline_stage *copy_stage = NULL;
3055 struct ia_css_pipeline_stage *video_stage = NULL;
3056 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
3057 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3058 struct ia_css_pipeline *me;
3059 struct ia_css_frame *in_frame = NULL;
3060 struct ia_css_frame *out_frame;
3061 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3062 struct ia_css_frame *vf_frame = NULL;
3063 int err = 0;
3064 bool need_copy = false;
3065 bool need_vf_pp = false;
3066 bool need_yuv_pp = false;
3067 bool need_in_frameinfo_memory = false;
3068
3069 unsigned int i, num_yuv_scaler;
3070 bool *is_output_stage = NULL;
3071
3072 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3073 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3074 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3075 return -EINVAL;
3076 }
3077 ia_css_pipe_util_create_output_frames(out_frames);
3078 out_frame = &pipe->out_frame_struct;
3079
3080 /* pipeline already created as part of create_host_pipeline_structure */
3081 me = &pipe->pipeline;
3082 ia_css_pipeline_clean(me);
3083
3084 me->dvs_frame_delay = pipe->dvs_frame_delay;
3085
3086 if (IS_ISP2401) {
3087 /*
3088 * When the input system is 2401, always enable 'in_frameinfo_memory'
3089 * except for the following: online or continuous
3090 */
3091 need_in_frameinfo_memory = !(pipe->stream->config.online ||
3092 pipe->stream->config.continuous);
3093 } else {
3094 /* Construct in_frame info (only in case we have dynamic input */
3095 need_in_frameinfo_memory = pipe->stream->config.mode ==
3096 IA_CSS_INPUT_MODE_MEMORY;
3097 }
3098
3099 /* Construct in_frame info (only in case we have dynamic input */
3100 if (need_in_frameinfo_memory) {
3101 in_frame = &pipe->in_frame_struct;
3102 err = init_in_frameinfo_memory_defaults(pipe, in_frame,
3103 IA_CSS_FRAME_FORMAT_RAW);
3104 if (err)
3105 goto ERR;
3106 }
3107
3108 out_frame->data = 0;
3109 err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3110 if (err)
3111 goto ERR;
3112
3113 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3114 vf_frame = &pipe->vf_frame_struct;
3115 vf_frame->data = 0;
3116 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3117 if (err)
3118 goto ERR;
3119 }
3120
3121 copy_binary = &pipe->pipe_settings.video.copy_binary;
3122 video_binary = &pipe->pipe_settings.video.video_binary;
3123 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3124
3125 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3126 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler;
3127 is_output_stage = pipe->pipe_settings.video.is_output_stage;
3128
3129 need_copy = (copy_binary && copy_binary->info);
3130 need_vf_pp = (vf_pp_binary && vf_pp_binary->info);
3131 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
3132
3133 if (need_copy) {
3134 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3135 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3136 out_frames, NULL, NULL);
3137 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3138 ©_stage);
3139 if (err)
3140 goto ERR;
3141 in_frame = me->stages->args.out_frame[0];
3142 } else if (pipe->stream->config.continuous) {
3143 if (IS_ISP2401)
3144 /*
3145 * When continuous is enabled, configure in_frame with the
3146 * last pipe, which is the copy pipe.
3147 */
3148 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3149 else
3150 in_frame = pipe->continuous_frames[0];
3151 }
3152
3153 ia_css_pipe_util_set_output_frames(out_frames, 0,
3154 need_yuv_pp ? NULL : out_frame);
3155
3156 /*
3157 * when the video binary supports a second output pin,
3158 * it can directly produce the vf_frame.
3159 */
3160 if (need_vf_pp) {
3161 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3162 out_frames, in_frame, NULL);
3163 } else {
3164 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3165 out_frames, in_frame, vf_frame);
3166 }
3167 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3168 &video_stage);
3169 if (err)
3170 goto ERR;
3171
3172 /* If we use copy iso video, the input must be yuv iso raw */
3173 if (video_stage) {
3174 video_stage->args.copy_vf =
3175 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3176 video_stage->args.copy_output = video_stage->args.copy_vf;
3177 }
3178
3179 /* when the video binary supports only 1 output pin, vf_pp is needed to
3180 produce the vf_frame.*/
3181 if (need_vf_pp && video_stage) {
3182 in_frame = video_stage->args.out_vf_frame;
3183 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3184 &vf_pp_stage);
3185 if (err)
3186 goto ERR;
3187 }
3188 if (video_stage) {
3189 int frm;
3190
3191 for (frm = 0; frm < NUM_VIDEO_TNR_FRAMES; frm++) {
3192 video_stage->args.tnr_frames[frm] =
3193 pipe->pipe_settings.video.tnr_frames[frm];
3194 }
3195 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3196 video_stage->args.delay_frames[frm] =
3197 pipe->pipe_settings.video.delay_frames[frm];
3198 }
3199 }
3200
3201 if (need_yuv_pp && video_stage) {
3202 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3203 struct ia_css_frame *tmp_out_frame = NULL;
3204
3205 for (i = 0; i < num_yuv_scaler; i++) {
3206 tmp_out_frame = is_output_stage[i] ? out_frame : NULL;
3207
3208 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
3209 tmp_out_frame, NULL,
3210 &yuv_scaler_binary[i],
3211 &yuv_scaler_stage);
3212
3213 if (err) {
3214 IA_CSS_LEAVE_ERR_PRIVATE(err);
3215 return err;
3216 }
3217 /* we use output port 1 as internal output port */
3218 if (yuv_scaler_stage)
3219 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3220 }
3221 }
3222
3223 pipe->pipeline.acquire_isp_each_stage = false;
3224 ia_css_pipeline_finalize_stages(&pipe->pipeline,
3225 pipe->stream->config.continuous);
3226
3227 ERR:
3228 IA_CSS_LEAVE_ERR_PRIVATE(err);
3229 return err;
3230 }
3231
3232 /* Create stages for preview */
3233 static int
create_host_preview_pipeline(struct ia_css_pipe * pipe)3234 create_host_preview_pipeline(struct ia_css_pipe *pipe)
3235 {
3236 struct ia_css_pipeline_stage *copy_stage = NULL;
3237 struct ia_css_pipeline_stage *preview_stage = NULL;
3238 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3239 struct ia_css_pipeline_stage_desc stage_desc;
3240 struct ia_css_pipeline *me = NULL;
3241 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3242 struct ia_css_frame *in_frame = NULL;
3243 int err = 0;
3244 struct ia_css_frame *out_frame;
3245 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3246 bool need_in_frameinfo_memory = false;
3247 bool sensor = false;
3248 bool buffered_sensor = false;
3249 bool online = false;
3250 bool continuous = false;
3251
3252 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3253 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3254 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3255 return -EINVAL;
3256 }
3257
3258 ia_css_pipe_util_create_output_frames(out_frames);
3259 /* pipeline already created as part of create_host_pipeline_structure */
3260 me = &pipe->pipeline;
3261 ia_css_pipeline_clean(me);
3262
3263 if (IS_ISP2401) {
3264 /*
3265 * When the input system is 2401, always enable 'in_frameinfo_memory'
3266 * except for the following:
3267 * - Direct Sensor Mode Online Preview
3268 * - Buffered Sensor Mode Online Preview
3269 * - Direct Sensor Mode Continuous Preview
3270 * - Buffered Sensor Mode Continuous Preview
3271 */
3272 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3273 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3274 online = pipe->stream->config.online;
3275 continuous = pipe->stream->config.continuous;
3276 need_in_frameinfo_memory =
3277 !((sensor && (online || continuous)) || (buffered_sensor &&
3278 (online || continuous)));
3279 } else {
3280 /* Construct in_frame info (only in case we have dynamic input */
3281 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3282 }
3283 if (need_in_frameinfo_memory) {
3284 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
3285 IA_CSS_FRAME_FORMAT_RAW);
3286 if (err)
3287 goto ERR;
3288
3289 in_frame = &me->in_frame;
3290 } else {
3291 in_frame = NULL;
3292 }
3293 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3294 if (err)
3295 goto ERR;
3296 out_frame = &me->out_frame[0];
3297
3298 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3299 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3300 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3301 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3302
3303 if (pipe->pipe_settings.preview.copy_binary.info) {
3304 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3305 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3306 out_frames, NULL, NULL);
3307 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3308 ©_stage);
3309 if (err)
3310 goto ERR;
3311 in_frame = me->stages->args.out_frame[0];
3312 } else if (pipe->stream->config.continuous) {
3313 if (IS_ISP2401) {
3314 /*
3315 * When continuous is enabled, configure in_frame with the
3316 * last pipe, which is the copy pipe.
3317 */
3318 if (continuous || !online)
3319 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3320 } else {
3321 in_frame = pipe->continuous_frames[0];
3322 }
3323 }
3324
3325 if (vf_pp_binary) {
3326 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3327 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3328 out_frames, in_frame, NULL);
3329 } else {
3330 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3331 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3332 out_frames, in_frame, NULL);
3333 }
3334 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3335 &preview_stage);
3336 if (err)
3337 goto ERR;
3338 /* If we use copy iso preview, the input must be yuv iso raw */
3339 preview_stage->args.copy_vf =
3340 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3341 preview_stage->args.copy_output = !preview_stage->args.copy_vf;
3342 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) {
3343 /* in case of copy, use the vf frame as output frame */
3344 preview_stage->args.out_vf_frame =
3345 preview_stage->args.out_frame[0];
3346 }
3347 if (vf_pp_binary) {
3348 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
3349 in_frame = preview_stage->args.out_vf_frame;
3350 else
3351 in_frame = preview_stage->args.out_frame[0];
3352 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
3353 &vf_pp_stage);
3354 if (err)
3355 goto ERR;
3356 }
3357
3358 pipe->pipeline.acquire_isp_each_stage = false;
3359 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3360
3361 ERR:
3362 IA_CSS_LEAVE_ERR_PRIVATE(err);
3363 return err;
3364 }
3365
send_raw_frames(struct ia_css_pipe * pipe)3366 static void send_raw_frames(struct ia_css_pipe *pipe)
3367 {
3368 if (pipe->stream->config.continuous) {
3369 unsigned int i;
3370
3371 sh_css_update_host2sp_cont_num_raw_frames
3372 (pipe->stream->config.init_num_cont_raw_buf, true);
3373 sh_css_update_host2sp_cont_num_raw_frames
3374 (pipe->stream->config.target_num_cont_raw_buf, false);
3375
3376 /* Hand-over all the SP-internal buffers */
3377 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
3378 sh_css_update_host2sp_offline_frame(i,
3379 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
3380 }
3381 }
3382
3383 return;
3384 }
3385
3386 static int
preview_start(struct ia_css_pipe * pipe)3387 preview_start(struct ia_css_pipe *pipe)
3388 {
3389 int err = 0;
3390 struct ia_css_pipe *copy_pipe, *capture_pipe;
3391 enum sh_css_pipe_config_override copy_ovrd;
3392 enum ia_css_input_mode preview_pipe_input_mode;
3393 unsigned int thread_id;
3394
3395 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3396 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3397 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3398 return -EINVAL;
3399 }
3400
3401 preview_pipe_input_mode = pipe->stream->config.mode;
3402
3403 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
3404 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
3405
3406 sh_css_metrics_start_frame();
3407
3408 /* multi stream video needs mipi buffers */
3409 err = send_mipi_frames(pipe);
3410 if (err) {
3411 IA_CSS_LEAVE_ERR_PRIVATE(err);
3412 return err;
3413 }
3414 send_raw_frames(pipe);
3415
3416 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3417 copy_ovrd = 1 << thread_id;
3418
3419 if (pipe->stream->cont_capt) {
3420 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
3421 &thread_id);
3422 copy_ovrd |= 1 << thread_id;
3423 }
3424
3425 /* Construct and load the copy pipe */
3426 if (pipe->stream->config.continuous) {
3427 sh_css_sp_init_pipeline(©_pipe->pipeline,
3428 IA_CSS_PIPE_ID_COPY,
3429 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
3430 false,
3431 pipe->stream->config.pixels_per_clock == 2, false,
3432 false, pipe->required_bds_factor,
3433 copy_ovrd,
3434 pipe->stream->config.mode,
3435 &pipe->stream->config.metadata_config,
3436 &pipe->stream->info.metadata_info,
3437 pipe->stream->config.source.port.port);
3438
3439 /*
3440 * make the preview pipe start with mem mode input, copy handles
3441 * the actual mode
3442 */
3443 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
3444 }
3445
3446 /* Construct and load the capture pipe */
3447 if (pipe->stream->cont_capt) {
3448 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
3449 IA_CSS_PIPE_ID_CAPTURE,
3450 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
3451 capture_pipe->config.default_capture_config.enable_xnr != 0,
3452 capture_pipe->stream->config.pixels_per_clock == 2,
3453 true, /* continuous */
3454 false, /* offline */
3455 capture_pipe->required_bds_factor,
3456 0,
3457 IA_CSS_INPUT_MODE_MEMORY,
3458 &pipe->stream->config.metadata_config,
3459 &pipe->stream->info.metadata_info,
3460 (enum mipi_port_id)0);
3461 }
3462
3463 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
3464
3465 IA_CSS_LEAVE_ERR_PRIVATE(err);
3466 return err;
3467 }
3468
3469 int
ia_css_pipe_enqueue_buffer(struct ia_css_pipe * pipe,const struct ia_css_buffer * buffer)3470 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
3471 const struct ia_css_buffer *buffer)
3472 {
3473 int return_err = 0;
3474 unsigned int thread_id;
3475 enum sh_css_queue_id queue_id;
3476 struct ia_css_pipeline *pipeline;
3477 struct ia_css_pipeline_stage *stage;
3478 struct ia_css_rmgr_vbuf_handle p_vbuf;
3479 struct ia_css_rmgr_vbuf_handle *h_vbuf;
3480 struct sh_css_hmm_buffer ddr_buffer;
3481 enum ia_css_buffer_type buf_type;
3482 enum ia_css_pipe_id pipe_id;
3483 bool ret_err;
3484
3485 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
3486
3487 if ((!pipe) || (!buffer)) {
3488 IA_CSS_LEAVE_ERR(-EINVAL);
3489 return -EINVAL;
3490 }
3491
3492 buf_type = buffer->type;
3493
3494 pipe_id = pipe->mode;
3495
3496 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
3497
3498 assert(pipe_id < IA_CSS_PIPE_ID_NUM);
3499 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
3500 if (buf_type == IA_CSS_BUFFER_TYPE_INVALID ||
3501 buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE ||
3502 pipe_id >= IA_CSS_PIPE_ID_NUM) {
3503 IA_CSS_LEAVE_ERR(-EINVAL);
3504 return -EINVAL;
3505 }
3506
3507 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3508 if (!ret_err) {
3509 IA_CSS_LEAVE_ERR(-EINVAL);
3510 return -EINVAL;
3511 }
3512
3513 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
3514 if (!ret_err) {
3515 IA_CSS_LEAVE_ERR(-EINVAL);
3516 return -EINVAL;
3517 }
3518
3519 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
3520 IA_CSS_LEAVE_ERR(-EINVAL);
3521 return -EINVAL;
3522 }
3523
3524 if (!sh_css_sp_is_running()) {
3525 IA_CSS_LOG("SP is not running!");
3526 IA_CSS_LEAVE_ERR(-EBUSY);
3527 /* SP is not running. The queues are not valid */
3528 return -EBUSY;
3529 }
3530
3531 pipeline = &pipe->pipeline;
3532
3533 assert(pipeline || pipe_id == IA_CSS_PIPE_ID_COPY);
3534
3535 assert(sizeof(void *) <= sizeof(ddr_buffer.kernel_ptr));
3536 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
3537 ddr_buffer.cookie_ptr = buffer->driver_cookie;
3538 ddr_buffer.timing_data = buffer->timing_data;
3539
3540 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) {
3541 if (!buffer->data.stats_3a) {
3542 IA_CSS_LEAVE_ERR(-EINVAL);
3543 return -EINVAL;
3544 }
3545 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
3546 ddr_buffer.payload.s3a = *buffer->data.stats_3a;
3547 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) {
3548 if (!buffer->data.stats_dvs) {
3549 IA_CSS_LEAVE_ERR(-EINVAL);
3550 return -EINVAL;
3551 }
3552 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
3553 ddr_buffer.payload.dis = *buffer->data.stats_dvs;
3554 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
3555 if (!buffer->data.metadata) {
3556 IA_CSS_LEAVE_ERR(-EINVAL);
3557 return -EINVAL;
3558 }
3559 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
3560 ddr_buffer.payload.metadata = *buffer->data.metadata;
3561 } else if (buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME ||
3562 buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
3563 buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME ||
3564 buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME ||
3565 buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME) {
3566 if (!buffer->data.frame) {
3567 IA_CSS_LEAVE_ERR(-EINVAL);
3568 return -EINVAL;
3569 }
3570 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame);
3571 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
3572 ddr_buffer.payload.frame.flashed = 0;
3573
3574 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
3575 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
3576 buf_type, buffer->data.frame->data);
3577
3578 }
3579
3580 /* start of test for using rmgr for acq/rel memory */
3581 p_vbuf.vptr = 0;
3582 p_vbuf.count = 0;
3583 p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
3584 h_vbuf = &p_vbuf;
3585 /* TODO: change next to correct pool for optimization */
3586 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
3587
3588 if ((!h_vbuf) || (h_vbuf->vptr == 0x0)) {
3589 IA_CSS_LEAVE_ERR(-EINVAL);
3590 return -EINVAL;
3591 }
3592
3593 hmm_store(h_vbuf->vptr,
3594 (void *)(&ddr_buffer),
3595 sizeof(struct sh_css_hmm_buffer));
3596 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS ||
3597 buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS ||
3598 buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS) {
3599 if (!pipeline) {
3600 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
3601 IA_CSS_LOG("pipeline is empty!");
3602 IA_CSS_LEAVE_ERR(-EINVAL);
3603 return -EINVAL;
3604 }
3605
3606 for (stage = pipeline->stages; stage; stage = stage->next) {
3607 /*
3608 * The SP will read the params after it got
3609 * empty 3a and dis
3610 */
3611 if (stage->binary && stage->binary->info &&
3612 (stage->binary->info->sp.enable.s3a ||
3613 stage->binary->info->sp.enable.dis)) {
3614 /* there is a stage that needs it */
3615 return_err = ia_css_bufq_enqueue_buffer(thread_id,
3616 queue_id,
3617 (uint32_t)h_vbuf->vptr);
3618 }
3619 }
3620 } else if (buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME ||
3621 buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
3622 buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME ||
3623 buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME ||
3624 buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME ||
3625 buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
3626 return_err = ia_css_bufq_enqueue_buffer(thread_id,
3627 queue_id,
3628 (uint32_t)h_vbuf->vptr);
3629 if (!return_err &&
3630 buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
3631 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
3632 ddr_buffer.payload.frame.frame_data,
3633 queue_id, thread_id);
3634 }
3635 }
3636
3637 if (!return_err) {
3638 if (sh_css_hmm_buffer_record_acquire(
3639 h_vbuf, buf_type,
3640 HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
3641 IA_CSS_LOG("send vbuf=%p", h_vbuf);
3642 } else {
3643 return_err = -EINVAL;
3644 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
3645 }
3646 }
3647
3648 /*
3649 * Tell the SP which queues are not empty,
3650 * by sending the software event.
3651 */
3652 if (!return_err) {
3653 if (!sh_css_sp_is_running()) {
3654 /* SP is not running. The queues are not valid */
3655 IA_CSS_LOG("SP is not running!");
3656 IA_CSS_LEAVE_ERR(-EBUSY);
3657 return -EBUSY;
3658 }
3659 return_err = ia_css_bufq_enqueue_psys_event(
3660 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
3661 (uint8_t)thread_id,
3662 queue_id,
3663 0);
3664 } else {
3665 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
3666 IA_CSS_ERROR("buffer not enqueued");
3667 }
3668
3669 IA_CSS_LEAVE("return value = %d", return_err);
3670
3671 return return_err;
3672 }
3673
3674 /*
3675 * TODO: Free up the hmm memory space.
3676 */
3677 int
ia_css_pipe_dequeue_buffer(struct ia_css_pipe * pipe,struct ia_css_buffer * buffer)3678 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
3679 struct ia_css_buffer *buffer)
3680 {
3681 int return_err;
3682 enum sh_css_queue_id queue_id;
3683 ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0;
3684 struct sh_css_hmm_buffer ddr_buffer;
3685 enum ia_css_buffer_type buf_type;
3686 enum ia_css_pipe_id pipe_id;
3687 unsigned int thread_id;
3688 hrt_address kernel_ptr = 0;
3689 bool ret_err;
3690
3691 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
3692
3693 if ((!pipe) || (!buffer)) {
3694 IA_CSS_LEAVE_ERR(-EINVAL);
3695 return -EINVAL;
3696 }
3697
3698 pipe_id = pipe->mode;
3699
3700 buf_type = buffer->type;
3701
3702 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
3703
3704 ddr_buffer.kernel_ptr = 0;
3705
3706 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3707 if (!ret_err) {
3708 IA_CSS_LEAVE_ERR(-EINVAL);
3709 return -EINVAL;
3710 }
3711
3712 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
3713 if (!ret_err) {
3714 IA_CSS_LEAVE_ERR(-EINVAL);
3715 return -EINVAL;
3716 }
3717
3718 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
3719 IA_CSS_LEAVE_ERR(-EINVAL);
3720 return -EINVAL;
3721 }
3722
3723 if (!sh_css_sp_is_running()) {
3724 IA_CSS_LOG("SP is not running!");
3725 IA_CSS_LEAVE_ERR(-EBUSY);
3726 /* SP is not running. The queues are not valid */
3727 return -EBUSY;
3728 }
3729
3730 return_err = ia_css_bufq_dequeue_buffer(queue_id,
3731 (uint32_t *)&ddr_buffer_addr);
3732
3733 if (!return_err) {
3734 struct ia_css_frame *frame;
3735 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
3736
3737 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
3738
3739 /* Validate the ddr_buffer_addr and buf_type */
3740 hmm_buffer_record = sh_css_hmm_buffer_record_validate(
3741 ddr_buffer_addr, buf_type);
3742 if (hmm_buffer_record) {
3743 /*
3744 * valid hmm_buffer_record found. Save the kernel_ptr
3745 * for validation after performing hmm_load. The
3746 * vbuf handle and buffer_record can be released.
3747 */
3748 kernel_ptr = hmm_buffer_record->kernel_ptr;
3749 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
3750 sh_css_hmm_buffer_record_reset(hmm_buffer_record);
3751 } else {
3752 IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)",
3753 ddr_buffer_addr, buf_type);
3754 IA_CSS_LEAVE_ERR(-EINVAL);
3755 return -EINVAL;
3756 }
3757
3758 hmm_load(ddr_buffer_addr,
3759 &ddr_buffer,
3760 sizeof(struct sh_css_hmm_buffer));
3761
3762 /*
3763 * if the kernel_ptr is 0 or an invalid, return an error.
3764 * do not access the buffer via the kernal_ptr.
3765 */
3766 if ((ddr_buffer.kernel_ptr == 0) ||
3767 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
3768 IA_CSS_ERROR("kernel_ptr invalid");
3769 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
3770 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
3771 IA_CSS_ERROR("buf_type: %d\n", buf_type);
3772 IA_CSS_LEAVE_ERR(-EINVAL);
3773 return -EINVAL;
3774 }
3775
3776 if (ddr_buffer.kernel_ptr != 0) {
3777 /*
3778 * buffer->exp_id : all instances to be removed later
3779 * once the driver change is completed. See patch #5758
3780 * for reference
3781 */
3782 buffer->exp_id = 0;
3783 buffer->driver_cookie = ddr_buffer.cookie_ptr;
3784 buffer->timing_data = ddr_buffer.timing_data;
3785
3786 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
3787 buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) {
3788 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
3789 }
3790
3791 switch (buf_type) {
3792 case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
3793 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
3794 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
3795 if (pipe && pipe->stop_requested) {
3796 if (!IS_ISP2401) {
3797 /*
3798 * free mipi frames only for old input
3799 * system for 2401 it is done in
3800 * ia_css_stream_destroy call
3801 */
3802 return_err = free_mipi_frames(pipe);
3803 if (return_err) {
3804 IA_CSS_LOG("free_mipi_frames() failed");
3805 IA_CSS_LEAVE_ERR(return_err);
3806 return return_err;
3807 }
3808 }
3809 pipe->stop_requested = false;
3810 }
3811 fallthrough;
3812 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
3813 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
3814 frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
3815 buffer->data.frame = frame;
3816 buffer->exp_id = ddr_buffer.payload.frame.exp_id;
3817 frame->exp_id = ddr_buffer.payload.frame.exp_id;
3818 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
3819 frame->valid = pipe->num_invalid_frames == 0;
3820 if (!frame->valid)
3821 pipe->num_invalid_frames--;
3822
3823 if (frame->frame_info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
3824 if (IS_ISP2401)
3825 frame->planes.binary.size = frame->data_bytes;
3826 else
3827 frame->planes.binary.size =
3828 sh_css_sp_get_binary_copy_size();
3829 }
3830 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
3831 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
3832 frame->data, frame->isp_config_id, thread_id);
3833 }
3834
3835 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
3836 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
3837 buf_type, buffer->data.frame->data);
3838
3839 break;
3840 case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
3841 buffer->data.stats_3a =
3842 (struct ia_css_isp_3a_statistics *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
3843 buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
3844 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
3845 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
3846 break;
3847 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
3848 buffer->data.stats_dvs =
3849 (struct ia_css_isp_dvs_statistics *)
3850 HOST_ADDRESS(ddr_buffer.kernel_ptr);
3851 buffer->exp_id = ddr_buffer.payload.dis.exp_id;
3852 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
3853 break;
3854 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
3855 break;
3856 case IA_CSS_BUFFER_TYPE_METADATA:
3857 buffer->data.metadata =
3858 (struct ia_css_metadata *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
3859 buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
3860 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
3861 break;
3862 default:
3863 return_err = -EINVAL;
3864 break;
3865 }
3866 }
3867 }
3868
3869 /*
3870 * Tell the SP which queues are not full,
3871 * by sending the software event.
3872 */
3873 if (!return_err) {
3874 if (!sh_css_sp_is_running()) {
3875 IA_CSS_LOG("SP is not running!");
3876 IA_CSS_LEAVE_ERR(-EBUSY);
3877 /* SP is not running. The queues are not valid */
3878 return -EBUSY;
3879 }
3880 ia_css_bufq_enqueue_psys_event(
3881 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
3882 0,
3883 queue_id,
3884 0);
3885 }
3886 IA_CSS_LEAVE("buffer=%p", buffer);
3887
3888 return return_err;
3889 }
3890
3891 /*
3892 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
3893 * TODO: modify and move it if possible.
3894 *
3895 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
3896 * 1) "enum ia_css_event_type" (ia_css_event_public.h)
3897 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h)
3898 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c)
3899 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
3900 */
3901 static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
3902 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /* Output frame ready. */
3903 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /* Second output frame ready. */
3904 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /* Viewfinder Output frame ready. */
3905 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /* Second viewfinder Output frame ready. */
3906 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /* Indication that 3A statistics are available. */
3907 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /* Indication that DIS statistics are available. */
3908 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /* Pipeline Done event, sent after last pipeline stage. */
3909 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /* Frame tagged. */
3910 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /* Input frame ready. */
3911 IA_CSS_EVENT_TYPE_METADATA_DONE, /* Metadata ready. */
3912 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /* Indication that LACE statistics are available. */
3913 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /* Extension stage executed. */
3914 IA_CSS_EVENT_TYPE_TIMER, /* Timing measurement data. */
3915 IA_CSS_EVENT_TYPE_PORT_EOF, /* End Of Frame event, sent when in buffered sensor mode. */
3916 IA_CSS_EVENT_TYPE_FW_WARNING, /* Performance warning encountered by FW */
3917 IA_CSS_EVENT_TYPE_FW_ASSERT, /* Assertion hit by FW */
3918 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
3919 };
3920
3921 int
ia_css_dequeue_psys_event(struct ia_css_event * event)3922 ia_css_dequeue_psys_event(struct ia_css_event *event)
3923 {
3924 enum ia_css_pipe_id pipe_id = 0;
3925 u8 payload[4] = {0, 0, 0, 0};
3926 int ret_err;
3927
3928 /*
3929 * TODO:
3930 * a) use generic decoding function , same as the one used by sp.
3931 * b) group decode and dequeue into eventQueue module
3932 *
3933 * We skip the IA_CSS_ENTER logging call
3934 * to avoid flooding the logs when the host application
3935 * uses polling.
3936 */
3937 if (!event)
3938 return -EINVAL;
3939
3940 /* SP is not running. The queues are not valid */
3941 if (!sh_css_sp_is_running())
3942 return -EBUSY;
3943
3944 /* dequeue the event (if any) from the psys event queue */
3945 ret_err = ia_css_bufq_dequeue_psys_event(payload);
3946 if (ret_err)
3947 return ret_err;
3948
3949 IA_CSS_LOG("event dequeued from psys event queue");
3950
3951 /* Tell the SP that we dequeued an event from the event queue. */
3952 ia_css_bufq_enqueue_psys_event(
3953 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
3954
3955 /*
3956 * Events are decoded into 4 bytes of payload, the first byte
3957 * contains the sp event type. This is converted to a host enum.
3958 * TODO: can this enum conversion be eliminated
3959 */
3960 event->type = convert_event_sp_to_host_domain[payload[0]];
3961 /* Some sane default values since not all events use all fields. */
3962 event->pipe = NULL;
3963 event->port = MIPI_PORT0_ID;
3964 event->exp_id = 0;
3965 event->fw_warning = IA_CSS_FW_WARNING_NONE;
3966 event->fw_handle = 0;
3967 event->timer_data = 0;
3968 event->timer_code = 0;
3969 event->timer_subcode = 0;
3970
3971 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
3972 /*
3973 * timer event ??? get the 2nd event and decode the data
3974 * into the event struct
3975 */
3976 u32 tmp_data;
3977 /* 1st event: LSB 16-bit timer data and code */
3978 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
3979 event->timer_code = payload[2];
3980 payload[0] = payload[1] = payload[2] = payload[3] = 0;
3981 ret_err = ia_css_bufq_dequeue_psys_event(payload);
3982 if (ret_err) {
3983 /* no 2nd event ??? an error */
3984 /*
3985 * Putting IA_CSS_ERROR is resulting in failures in
3986 * Merrifield smoke testing
3987 */
3988 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
3989 return ret_err;
3990 }
3991 ia_css_bufq_enqueue_psys_event(
3992 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
3993 event->type = convert_event_sp_to_host_domain[payload[0]];
3994 /* It's a timer */
3995 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
3996 /* 2nd event data: MSB 16-bit timer and subcode */
3997 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
3998 event->timer_data |= (tmp_data << 16);
3999 event->timer_subcode = payload[2];
4000 } else {
4001 /*
4002 * It's a non timer event. So clear first half of the
4003 * timer event data.
4004 * If the second part of the TIMER event is not
4005 * received, we discard the first half of the timer
4006 * data and process the non timer event without
4007 * affecting the flow. So the non timer event falls
4008 * through the code.
4009 */
4010 event->timer_data = 0;
4011 event->timer_code = 0;
4012 event->timer_subcode = 0;
4013 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4014 }
4015 }
4016 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) {
4017 event->port = (enum mipi_port_id)payload[1];
4018 event->exp_id = payload[3];
4019 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4020 event->fw_warning = (enum ia_css_fw_warning)payload[1];
4021 /* exp_id is only available in these warning types */
4022 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
4023 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
4024 event->exp_id = payload[3];
4025 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) {
4026 event->fw_assert_module_id = payload[1]; /* module */
4027 event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4028 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4029 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) {
4030 /*
4031 * pipe related events.
4032 * payload[1] contains the pipe_num,
4033 * payload[2] contains the pipe_id. These are different.
4034 */
4035 event->pipe = find_pipe_by_num(payload[1]);
4036 pipe_id = (enum ia_css_pipe_id)payload[2];
4037 /* Check to see if pipe still exists */
4038 if (!event->pipe)
4039 return -EBUSY;
4040
4041 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4042 /* find the capture pipe that goes with this */
4043 int i, n;
4044
4045 n = event->pipe->stream->num_pipes;
4046 for (i = 0; i < n; i++) {
4047 struct ia_css_pipe *p =
4048 event->pipe->stream->pipes[i];
4049 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4050 event->pipe = p;
4051 break;
4052 }
4053 }
4054 event->exp_id = payload[3];
4055 }
4056 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4057 /* payload[3] contains the acc fw handle. */
4058 u32 stage_num = (uint32_t)payload[3];
4059
4060 ret_err = ia_css_pipeline_get_fw_from_stage(
4061 &event->pipe->pipeline,
4062 stage_num,
4063 &event->fw_handle);
4064 if (ret_err) {
4065 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4066 stage_num);
4067 return ret_err;
4068 }
4069 }
4070 }
4071
4072 if (event->pipe)
4073 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4074 else
4075 IA_CSS_LEAVE("event_id=%d", event->type);
4076
4077 return 0;
4078 }
4079
4080 int
ia_css_dequeue_isys_event(struct ia_css_event * event)4081 ia_css_dequeue_isys_event(struct ia_css_event *event)
4082 {
4083 u8 payload[4] = {0, 0, 0, 0};
4084 int err = 0;
4085
4086 /*
4087 * We skip the IA_CSS_ENTER logging call
4088 * to avoid flooding the logs when the host application
4089 * uses polling.
4090 */
4091 if (!event)
4092 return -EINVAL;
4093
4094 /* SP is not running. The queues are not valid */
4095 if (!sh_css_sp_is_running())
4096 return -EBUSY;
4097
4098 err = ia_css_bufq_dequeue_isys_event(payload);
4099 if (err)
4100 return err;
4101
4102 IA_CSS_LOG("event dequeued from isys event queue");
4103
4104 /* Update SP state to indicate that element was dequeued. */
4105 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4106
4107 /* Fill return struct with appropriate info */
4108 event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4109 /* EOF events are associated with a CSI port, not with a pipe */
4110 event->pipe = NULL;
4111 event->port = payload[1];
4112 event->exp_id = payload[3];
4113
4114 IA_CSS_LEAVE_ERR(err);
4115 return err;
4116 }
4117
4118 static int
sh_css_pipe_start(struct ia_css_stream * stream)4119 sh_css_pipe_start(struct ia_css_stream *stream)
4120 {
4121 int err = 0;
4122
4123 struct ia_css_pipe *pipe;
4124 enum ia_css_pipe_id pipe_id;
4125 unsigned int thread_id;
4126
4127 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4128
4129 if (!stream) {
4130 IA_CSS_LEAVE_ERR(-EINVAL);
4131 return -EINVAL;
4132 }
4133 pipe = stream->last_pipe;
4134 if (!pipe) {
4135 IA_CSS_LEAVE_ERR(-EINVAL);
4136 return -EINVAL;
4137 }
4138
4139 pipe_id = pipe->mode;
4140
4141 if (stream->started) {
4142 IA_CSS_WARNING("Cannot start stream that is already started");
4143 IA_CSS_LEAVE_ERR(err);
4144 return err;
4145 }
4146
4147 pipe->stop_requested = false;
4148
4149 switch (pipe_id) {
4150 case IA_CSS_PIPE_ID_PREVIEW:
4151 err = preview_start(pipe);
4152 break;
4153 case IA_CSS_PIPE_ID_VIDEO:
4154 err = video_start(pipe);
4155 break;
4156 case IA_CSS_PIPE_ID_CAPTURE:
4157 err = capture_start(pipe);
4158 break;
4159 case IA_CSS_PIPE_ID_YUVPP:
4160 err = yuvpp_start(pipe);
4161 break;
4162 default:
4163 err = -EINVAL;
4164 }
4165 /* DH regular multi pipe - not continuous mode: start the next pipes too */
4166 if (!stream->config.continuous) {
4167 int i;
4168
4169 for (i = 1; i < stream->num_pipes && 0 == err ; i++) {
4170 switch (stream->pipes[i]->mode) {
4171 case IA_CSS_PIPE_ID_PREVIEW:
4172 stream->pipes[i]->stop_requested = false;
4173 err = preview_start(stream->pipes[i]);
4174 break;
4175 case IA_CSS_PIPE_ID_VIDEO:
4176 stream->pipes[i]->stop_requested = false;
4177 err = video_start(stream->pipes[i]);
4178 break;
4179 case IA_CSS_PIPE_ID_CAPTURE:
4180 stream->pipes[i]->stop_requested = false;
4181 err = capture_start(stream->pipes[i]);
4182 break;
4183 case IA_CSS_PIPE_ID_YUVPP:
4184 stream->pipes[i]->stop_requested = false;
4185 err = yuvpp_start(stream->pipes[i]);
4186 break;
4187 default:
4188 err = -EINVAL;
4189 }
4190 }
4191 }
4192 if (err) {
4193 IA_CSS_LEAVE_ERR_PRIVATE(err);
4194 return err;
4195 }
4196
4197 /*
4198 * Force ISP parameter calculation after a mode change
4199 * Acceleration API examples pass NULL for stream but they
4200 * don't use ISP parameters anyway. So this should be okay.
4201 * The SP binary (jpeg) copy does not use any parameters.
4202 */
4203 if (!copy_on_sp(pipe)) {
4204 sh_css_invalidate_params(stream);
4205 err = sh_css_param_update_isp_params(pipe,
4206 stream->isp_params_configs, true, NULL);
4207 if (err) {
4208 IA_CSS_LEAVE_ERR_PRIVATE(err);
4209 return err;
4210 }
4211 }
4212
4213 ia_css_debug_pipe_graph_dump_epilogue();
4214
4215 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4216
4217 if (!sh_css_sp_is_running()) {
4218 IA_CSS_LEAVE_ERR_PRIVATE(-EBUSY);
4219 /* SP is not running. The queues are not valid */
4220 return -EBUSY;
4221 }
4222 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
4223 (uint8_t)thread_id, 0, 0);
4224
4225 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
4226 if (!stream->config.continuous) {
4227 int i;
4228
4229 for (i = 1; i < stream->num_pipes; i++) {
4230 ia_css_pipeline_get_sp_thread_id(
4231 ia_css_pipe_get_pipe_num(stream->pipes[i]),
4232 &thread_id);
4233 ia_css_bufq_enqueue_psys_event(
4234 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4235 (uint8_t)thread_id, 0, 0);
4236 }
4237 }
4238
4239 /* in case of continuous capture mode, we also start capture thread and copy thread*/
4240 if (pipe->stream->config.continuous) {
4241 struct ia_css_pipe *copy_pipe = NULL;
4242
4243 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4244 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4245 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4246 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4247
4248 if (!copy_pipe) {
4249 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4250 return -EINVAL;
4251 }
4252 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe),
4253 &thread_id);
4254 /* by the time we reach here q is initialized and handle is available.*/
4255 ia_css_bufq_enqueue_psys_event(
4256 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4257 (uint8_t)thread_id, 0, 0);
4258 }
4259 if (pipe->stream->cont_capt) {
4260 struct ia_css_pipe *capture_pipe = NULL;
4261
4262 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4263 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4264 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4265 capture_pipe = pipe->pipe_settings.video.capture_pipe;
4266
4267 if (!capture_pipe) {
4268 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4269 return -EINVAL;
4270 }
4271 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
4272 &thread_id);
4273 /* by the time we reach here q is initialized and handle is available.*/
4274 ia_css_bufq_enqueue_psys_event(
4275 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4276 (uint8_t)thread_id, 0, 0);
4277 }
4278
4279 stream->started = true;
4280
4281 IA_CSS_LEAVE_ERR_PRIVATE(err);
4282 return err;
4283 }
4284
4285 /* ISP2400 */
4286 void
sh_css_enable_cont_capt(bool enable,bool stop_copy_preview)4287 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
4288 {
4289 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4290 "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
4291 //my_css.cont_capt = enable;
4292 my_css.stop_copy_preview = stop_copy_preview;
4293 }
4294
4295 bool
sh_css_continuous_is_enabled(uint8_t pipe_num)4296 sh_css_continuous_is_enabled(uint8_t pipe_num)
4297 {
4298 struct ia_css_pipe *pipe;
4299 bool continuous;
4300
4301 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4302 "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
4303
4304 pipe = find_pipe_by_num(pipe_num);
4305 continuous = pipe && pipe->stream->config.continuous;
4306 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4307 "sh_css_continuous_is_enabled() leave: enable=%d\n",
4308 continuous);
4309 return continuous;
4310 }
4311
4312 /* ISP2400 */
4313 int
ia_css_stream_get_max_buffer_depth(struct ia_css_stream * stream,int * buffer_depth)4314 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream,
4315 int *buffer_depth)
4316 {
4317 if (!buffer_depth)
4318 return -EINVAL;
4319 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
4320 (void)stream;
4321 *buffer_depth = NUM_CONTINUOUS_FRAMES;
4322 return 0;
4323 }
4324
4325 int
ia_css_stream_set_buffer_depth(struct ia_css_stream * stream,int buffer_depth)4326 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
4327 {
4328 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth);
4329 (void)stream;
4330 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
4331 return -EINVAL;
4332 /* ok, value allowed */
4333 stream->config.target_num_cont_raw_buf = buffer_depth;
4334 /* TODO: check what to regarding initialization */
4335 return 0;
4336 }
4337
4338 /* ISP2401 */
4339 int
ia_css_stream_get_buffer_depth(struct ia_css_stream * stream,int * buffer_depth)4340 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream,
4341 int *buffer_depth)
4342 {
4343 if (!buffer_depth)
4344 return -EINVAL;
4345 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
4346 (void)stream;
4347 *buffer_depth = stream->config.target_num_cont_raw_buf;
4348 return 0;
4349 }
4350
4351 unsigned int
sh_css_get_mipi_sizes_for_check(const unsigned int port,const unsigned int idx)4352 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
4353 {
4354 OP___assert(port < N_CSI_PORTS);
4355 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
4356 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
4357 "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
4358 port, idx, my_css.mipi_sizes_for_check[port][idx]);
4359 return my_css.mipi_sizes_for_check[port][idx];
4360 }
4361
sh_css_pipe_configure_output(struct ia_css_pipe * pipe,unsigned int width,unsigned int height,unsigned int padded_width,enum ia_css_frame_format format,unsigned int idx)4362 static int sh_css_pipe_configure_output(
4363 struct ia_css_pipe *pipe,
4364 unsigned int width,
4365 unsigned int height,
4366 unsigned int padded_width,
4367 enum ia_css_frame_format format,
4368 unsigned int idx)
4369 {
4370 int err = 0;
4371
4372 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, padded width = %d, format = %d, idx = %d",
4373 pipe, width, height, padded_width, format, idx);
4374 if (!pipe) {
4375 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4376 return -EINVAL;
4377 }
4378
4379 err = ia_css_util_check_res(width, height);
4380 if (err) {
4381 IA_CSS_LEAVE_ERR_PRIVATE(err);
4382 return err;
4383 }
4384 if (pipe->output_info[idx].res.width != width ||
4385 pipe->output_info[idx].res.height != height ||
4386 pipe->output_info[idx].format != format) {
4387 ia_css_frame_info_init(
4388 &pipe->output_info[idx],
4389 width,
4390 height,
4391 format,
4392 padded_width);
4393 }
4394 IA_CSS_LEAVE_ERR_PRIVATE(0);
4395 return 0;
4396 }
4397
4398 static int
sh_css_pipe_get_shading_info(struct ia_css_pipe * pipe,struct ia_css_shading_info * shading_info,struct ia_css_pipe_config * pipe_config)4399 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
4400 struct ia_css_shading_info *shading_info,
4401 struct ia_css_pipe_config *pipe_config)
4402 {
4403 int err = 0;
4404 struct ia_css_binary *binary = NULL;
4405
4406 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
4407 "sh_css_pipe_get_shading_info() enter:\n");
4408
4409 binary = ia_css_pipe_get_shading_correction_binary(pipe);
4410
4411 if (binary) {
4412 err = ia_css_binary_get_shading_info(binary,
4413 IA_CSS_SHADING_CORRECTION_TYPE_1,
4414 pipe->required_bds_factor,
4415 (const struct ia_css_stream_config *)&pipe->stream->config,
4416 shading_info, pipe_config);
4417
4418 /*
4419 * Other function calls can be added here when other shading
4420 * correction types will be added in the future.
4421 */
4422 } else {
4423 /*
4424 * When the pipe does not have a binary which has the shading
4425 * correction, this function does not need to fill the shading
4426 * information. It is not a error case, and then
4427 * this function should return 0.
4428 */
4429 memset(shading_info, 0, sizeof(*shading_info));
4430 }
4431 return err;
4432 }
4433
4434 static int
sh_css_pipe_get_grid_info(struct ia_css_pipe * pipe,struct ia_css_grid_info * info)4435 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
4436 struct ia_css_grid_info *info)
4437 {
4438 int err = 0;
4439 struct ia_css_binary *binary = NULL;
4440
4441 assert(pipe);
4442 assert(info);
4443
4444 IA_CSS_ENTER_PRIVATE("");
4445
4446 binary = ia_css_pipe_get_s3a_binary(pipe);
4447
4448 if (binary) {
4449 err = ia_css_binary_3a_grid_info(binary, info, pipe);
4450 if (err)
4451 goto err;
4452 } else {
4453 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
4454 }
4455
4456 binary = ia_css_pipe_get_sdis_binary(pipe);
4457
4458 if (binary) {
4459 ia_css_binary_dvs_grid_info(binary, info, pipe);
4460 ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
4461 } else {
4462 memset(&info->dvs_grid, 0, sizeof(info->dvs_grid));
4463 memset(&info->dvs_grid.dvs_stat_grid_info, 0,
4464 sizeof(info->dvs_grid.dvs_stat_grid_info));
4465 }
4466
4467 if (binary) {
4468 /* copy pipe does not have ISP binary*/
4469 info->isp_in_width = binary->internal_frame_info.res.width;
4470 info->isp_in_height = binary->internal_frame_info.res.height;
4471 }
4472
4473 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
4474
4475 err:
4476 IA_CSS_LEAVE_ERR_PRIVATE(err);
4477 return err;
4478 }
4479
4480 /* ISP2401 */
4481 /*
4482 * @brief Check if a format is supported by the pipe.
4483 *
4484 */
4485 static int
ia_css_pipe_check_format(struct ia_css_pipe * pipe,enum ia_css_frame_format format)4486 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
4487 enum ia_css_frame_format format)
4488 {
4489 const enum ia_css_frame_format *supported_formats;
4490 int number_of_formats;
4491 int found = 0;
4492 int i;
4493
4494 IA_CSS_ENTER_PRIVATE("");
4495
4496 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) {
4497 IA_CSS_ERROR("Pipe or binary info is not set");
4498 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4499 return -EINVAL;
4500 }
4501
4502 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
4503 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format);
4504
4505 for (i = 0; i < number_of_formats && !found; i++) {
4506 if (supported_formats[i] == format) {
4507 found = 1;
4508 break;
4509 }
4510 }
4511 if (!found) {
4512 IA_CSS_ERROR("Requested format is not supported by binary");
4513 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4514 return -EINVAL;
4515 }
4516 IA_CSS_LEAVE_ERR_PRIVATE(0);
4517 return 0;
4518 }
4519
load_video_binaries(struct ia_css_pipe * pipe)4520 static int load_video_binaries(struct ia_css_pipe *pipe)
4521 {
4522 struct ia_css_frame_info video_in_info, tnr_info,
4523 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
4524 bool online;
4525 int err = 0;
4526 bool continuous = pipe->stream->config.continuous;
4527 unsigned int i;
4528 unsigned int num_output_pins;
4529 struct ia_css_frame_info video_bin_out_info;
4530 bool need_scaler = false;
4531 bool vf_res_different_than_output = false;
4532 bool need_vf_pp = false;
4533 int vf_ds_log2;
4534 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video;
4535
4536 IA_CSS_ENTER_PRIVATE("");
4537 assert(pipe);
4538 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
4539 /*
4540 * we only test the video_binary because offline video doesn't need a
4541 * vf_pp binary and online does not (always use) the copy_binary.
4542 * All are always reset at the same time anyway.
4543 */
4544 if (mycs->video_binary.info)
4545 return 0;
4546
4547 online = pipe->stream->config.online;
4548 pipe_out_info = &pipe->output_info[0];
4549 pipe_vf_out_info = &pipe->vf_output_info[0];
4550
4551 assert(pipe_out_info);
4552
4553 /*
4554 * There is no explicit input format requirement for raw or yuv
4555 * What matters is that there is a binary that supports the stream format.
4556 * This is checked in the binary_find(), so no need to check it here
4557 */
4558 err = ia_css_util_check_input(&pipe->stream->config, false, false);
4559 if (err)
4560 return err;
4561 /* cannot have online video and input_mode memory */
4562 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
4563 return -EINVAL;
4564 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
4565 err = ia_css_util_check_vf_out_info(pipe_out_info,
4566 pipe_vf_out_info);
4567 if (err)
4568 return err;
4569 } else {
4570 err = ia_css_frame_check_info(pipe_out_info);
4571 if (err)
4572 return err;
4573 }
4574
4575 if (pipe->out_yuv_ds_input_info.res.width)
4576 video_bin_out_info = pipe->out_yuv_ds_input_info;
4577 else
4578 video_bin_out_info = *pipe_out_info;
4579
4580 /* Video */
4581 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
4582 video_vf_info = pipe_vf_out_info;
4583 vf_res_different_than_output = (video_vf_info->res.width !=
4584 video_bin_out_info.res.width) ||
4585 (video_vf_info->res.height != video_bin_out_info.res.height);
4586 } else {
4587 video_vf_info = NULL;
4588 }
4589
4590 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
4591
4592 /* we build up the pipeline starting at the end */
4593 /* YUV post-processing if needed */
4594 if (need_scaler) {
4595 struct ia_css_cas_binary_descr cas_scaler_descr = { };
4596
4597 /* NV12 is the common format that is supported by both */
4598 /* yuv_scaler and the video_xx_isp2_min binaries. */
4599 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
4600
4601 err = ia_css_pipe_create_cas_scaler_desc_single_output(
4602 &video_bin_out_info,
4603 pipe_out_info,
4604 NULL,
4605 &cas_scaler_descr);
4606 if (err)
4607 return err;
4608 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
4609 mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage,
4610 sizeof(struct ia_css_binary),
4611 GFP_KERNEL);
4612 if (!mycs->yuv_scaler_binary) {
4613 mycs->num_yuv_scaler = 0;
4614 err = -ENOMEM;
4615 return err;
4616 }
4617 mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage,
4618 sizeof(bool), GFP_KERNEL);
4619 if (!mycs->is_output_stage) {
4620 err = -ENOMEM;
4621 return err;
4622 }
4623 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
4624 struct ia_css_binary_descr yuv_scaler_descr;
4625
4626 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
4627 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
4628 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
4629 &cas_scaler_descr.out_info[i],
4630 &cas_scaler_descr.internal_out_info[i],
4631 &cas_scaler_descr.vf_info[i]);
4632 err = ia_css_binary_find(&yuv_scaler_descr,
4633 &mycs->yuv_scaler_binary[i]);
4634 if (err) {
4635 kfree(mycs->is_output_stage);
4636 mycs->is_output_stage = NULL;
4637 return err;
4638 }
4639 }
4640 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
4641 }
4642
4643 {
4644 struct ia_css_binary_descr video_descr;
4645 enum ia_css_frame_format vf_info_format;
4646
4647 err = ia_css_pipe_get_video_binarydesc(pipe,
4648 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info,
4649 video_vf_info,
4650 pipe->stream->config.left_padding);
4651 if (err)
4652 return err;
4653
4654 /*
4655 * In the case where video_vf_info is not NULL, this allows
4656 * us to find a potential video library with desired vf format.
4657 * If success, no vf_pp binary is needed.
4658 * If failed, we will look up video binary with YUV_LINE vf format
4659 */
4660 err = ia_css_binary_find(&video_descr,
4661 &mycs->video_binary);
4662
4663 if (err) {
4664 /* This will do another video binary lookup later for YUV_LINE format*/
4665 if (video_vf_info)
4666 need_vf_pp = true;
4667 else
4668 return err;
4669 } else if (video_vf_info) {
4670 /*
4671 * The first video binary lookup is successful, but we
4672 * may still need vf_pp binary based on additional check
4673 */
4674 num_output_pins = mycs->video_binary.info->num_output_pins;
4675 vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
4676
4677 /*
4678 * If the binary has dual output pins, we need vf_pp
4679 * if the resolution is different.
4680 */
4681 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
4682
4683 /*
4684 * If the binary has single output pin, we need vf_pp
4685 * if additional scaling is needed for vf
4686 */
4687 need_vf_pp |= ((num_output_pins == 1) &&
4688 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
4689 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
4690 }
4691
4692 if (need_vf_pp) {
4693 /* save the current vf_info format for restoration later */
4694 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4695 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
4696
4697 vf_info_format = video_vf_info->format;
4698
4699 if (!pipe->config.enable_vfpp_bci)
4700 ia_css_frame_info_set_format(video_vf_info,
4701 IA_CSS_FRAME_FORMAT_YUV_LINE);
4702
4703 ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
4704
4705 err = ia_css_binary_find(&video_descr,
4706 &mycs->video_binary);
4707
4708 /* restore original vf_info format */
4709 ia_css_frame_info_set_format(video_vf_info,
4710 vf_info_format);
4711 if (err)
4712 return err;
4713 }
4714 }
4715
4716 /*
4717 * If a video binary does not use a ref_frame, we set the frame delay
4718 * to 0. This is the case for the 1-stage low-power video binary.
4719 */
4720 if (!mycs->video_binary.info->sp.enable.ref_frame)
4721 pipe->dvs_frame_delay = 0;
4722
4723 /*
4724 * The delay latency determines the number of invalid frames after
4725 * a stream is started.
4726 */
4727 pipe->num_invalid_frames = pipe->dvs_frame_delay;
4728 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
4729
4730 /*
4731 * Viewfinder frames also decrement num_invalid_frames. If the pipe
4732 * outputs a viewfinder output, then we need double the number of
4733 * invalid frames
4734 */
4735 if (video_vf_info)
4736 pipe->num_invalid_frames *= 2;
4737
4738 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4739 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
4740 pipe->num_invalid_frames, pipe->dvs_frame_delay);
4741
4742 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
4743 if (!IS_ISP2401) {
4744 /* Copy */
4745 if (!online && !continuous) {
4746 /*
4747 * TODO: what exactly needs doing, prepend the copy binary to
4748 * video base this only on !online?
4749 */
4750 err = load_copy_binary(pipe,
4751 &mycs->copy_binary,
4752 &mycs->video_binary);
4753 if (err)
4754 return err;
4755 }
4756 }
4757
4758 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
4759 struct ia_css_binary_descr vf_pp_descr;
4760
4761 if (mycs->video_binary.vf_frame_info.format
4762 == IA_CSS_FRAME_FORMAT_YUV_LINE) {
4763 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
4764 &mycs->video_binary.vf_frame_info,
4765 pipe_vf_out_info);
4766 } else {
4767 /*
4768 * output from main binary is not yuv line. currently
4769 * this is possible only when bci is enabled on vfpp
4770 * output
4771 */
4772 assert(pipe->config.enable_vfpp_bci);
4773 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
4774 &mycs->video_binary.vf_frame_info,
4775 pipe_vf_out_info, NULL, NULL);
4776 }
4777
4778 err = ia_css_binary_find(&vf_pp_descr,
4779 &mycs->vf_pp_binary);
4780 if (err)
4781 return err;
4782 }
4783
4784 err = allocate_delay_frames(pipe);
4785
4786 if (err)
4787 return err;
4788
4789 if (mycs->video_binary.info->sp.enable.block_output) {
4790 tnr_info = mycs->video_binary.out_frame_info[0];
4791
4792 /* Make tnr reference buffers output block height align */
4793 tnr_info.res.height = CEIL_MUL(tnr_info.res.height,
4794 mycs->video_binary.info->sp.block.output_block_height);
4795 } else {
4796 tnr_info = mycs->video_binary.internal_frame_info;
4797 }
4798 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE;
4799 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH;
4800
4801 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) {
4802 if (mycs->tnr_frames[i]) {
4803 ia_css_frame_free(mycs->tnr_frames[i]);
4804 mycs->tnr_frames[i] = NULL;
4805 }
4806 err = ia_css_frame_allocate_from_info(
4807 &mycs->tnr_frames[i],
4808 &tnr_info);
4809 if (err)
4810 return err;
4811 }
4812 IA_CSS_LEAVE_PRIVATE("");
4813 return 0;
4814 }
4815
4816 static int
unload_video_binaries(struct ia_css_pipe * pipe)4817 unload_video_binaries(struct ia_css_pipe *pipe)
4818 {
4819 unsigned int i;
4820
4821 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
4822
4823 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
4824 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4825 return -EINVAL;
4826 }
4827 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary);
4828 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary);
4829 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
4830
4831 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++)
4832 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]);
4833
4834 kfree(pipe->pipe_settings.video.is_output_stage);
4835 pipe->pipe_settings.video.is_output_stage = NULL;
4836 kfree(pipe->pipe_settings.video.yuv_scaler_binary);
4837 pipe->pipe_settings.video.yuv_scaler_binary = NULL;
4838
4839 IA_CSS_LEAVE_ERR_PRIVATE(0);
4840 return 0;
4841 }
4842
video_start(struct ia_css_pipe * pipe)4843 static int video_start(struct ia_css_pipe *pipe)
4844 {
4845 int err = 0;
4846 struct ia_css_pipe *copy_pipe, *capture_pipe;
4847 enum sh_css_pipe_config_override copy_ovrd;
4848 enum ia_css_input_mode video_pipe_input_mode;
4849 unsigned int thread_id;
4850
4851 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
4852 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
4853 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4854 return -EINVAL;
4855 }
4856
4857 video_pipe_input_mode = pipe->stream->config.mode;
4858
4859 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4860 capture_pipe = pipe->pipe_settings.video.capture_pipe;
4861
4862 sh_css_metrics_start_frame();
4863
4864 /* multi stream video needs mipi buffers */
4865
4866 err = send_mipi_frames(pipe);
4867 if (err)
4868 return err;
4869
4870 send_raw_frames(pipe);
4871
4872 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4873 copy_ovrd = 1 << thread_id;
4874
4875 if (pipe->stream->cont_capt) {
4876 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
4877 &thread_id);
4878 copy_ovrd |= 1 << thread_id;
4879 }
4880
4881 /* Construct and load the copy pipe */
4882 if (pipe->stream->config.continuous) {
4883 sh_css_sp_init_pipeline(©_pipe->pipeline,
4884 IA_CSS_PIPE_ID_COPY,
4885 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
4886 false,
4887 pipe->stream->config.pixels_per_clock == 2, false,
4888 false, pipe->required_bds_factor,
4889 copy_ovrd,
4890 pipe->stream->config.mode,
4891 &pipe->stream->config.metadata_config,
4892 &pipe->stream->info.metadata_info,
4893 pipe->stream->config.source.port.port);
4894
4895 /*
4896 * make the video pipe start with mem mode input, copy handles
4897 * the actual mode
4898 */
4899 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
4900 }
4901
4902 /* Construct and load the capture pipe */
4903 if (pipe->stream->cont_capt) {
4904 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
4905 IA_CSS_PIPE_ID_CAPTURE,
4906 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
4907 capture_pipe->config.default_capture_config.enable_xnr != 0,
4908 capture_pipe->stream->config.pixels_per_clock == 2,
4909 true, /* continuous */
4910 false, /* offline */
4911 capture_pipe->required_bds_factor,
4912 0,
4913 IA_CSS_INPUT_MODE_MEMORY,
4914 &pipe->stream->config.metadata_config,
4915 &pipe->stream->info.metadata_info,
4916 (enum mipi_port_id)0);
4917 }
4918
4919 start_pipe(pipe, copy_ovrd, video_pipe_input_mode);
4920
4921 IA_CSS_LEAVE_ERR_PRIVATE(err);
4922 return err;
4923 }
4924
4925 static
sh_css_pipe_get_viewfinder_frame_info(struct ia_css_pipe * pipe,struct ia_css_frame_info * info,unsigned int idx)4926 int sh_css_pipe_get_viewfinder_frame_info(
4927 struct ia_css_pipe *pipe,
4928 struct ia_css_frame_info *info,
4929 unsigned int idx)
4930 {
4931 assert(pipe);
4932 assert(info);
4933
4934 /* We could print the pointer as input arg, and the values as output */
4935 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
4936 "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
4937
4938 if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE &&
4939 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
4940 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER))
4941 return -EINVAL;
4942 /* offline video does not generate viewfinder output */
4943 *info = pipe->vf_output_info[idx];
4944
4945 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
4946 "sh_css_pipe_get_viewfinder_frame_info() leave: \
4947 info.res.width=%d, info.res.height=%d, \
4948 info.padded_width=%d, info.format=%d, \
4949 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
4950 info->res.width, info->res.height,
4951 info->padded_width, info->format,
4952 info->raw_bit_depth, info->raw_bayer_order);
4953
4954 return 0;
4955 }
4956
4957 static int
sh_css_pipe_configure_viewfinder(struct ia_css_pipe * pipe,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format,unsigned int idx)4958 sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
4959 unsigned int height, unsigned int min_width,
4960 enum ia_css_frame_format format,
4961 unsigned int idx)
4962 {
4963 int err = 0;
4964
4965 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
4966 pipe, width, height, min_width, format, idx);
4967
4968 if (!pipe) {
4969 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4970 return -EINVAL;
4971 }
4972
4973 err = ia_css_util_check_res(width, height);
4974 if (err) {
4975 IA_CSS_LEAVE_ERR_PRIVATE(err);
4976 return err;
4977 }
4978 if (pipe->vf_output_info[idx].res.width != width ||
4979 pipe->vf_output_info[idx].res.height != height ||
4980 pipe->vf_output_info[idx].format != format)
4981 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
4982 format, min_width);
4983
4984 IA_CSS_LEAVE_ERR_PRIVATE(0);
4985 return 0;
4986 }
4987
load_copy_binaries(struct ia_css_pipe * pipe)4988 static int load_copy_binaries(struct ia_css_pipe *pipe)
4989 {
4990 int err = 0;
4991
4992 assert(pipe);
4993 IA_CSS_ENTER_PRIVATE("");
4994
4995 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
4996 pipe->mode == IA_CSS_PIPE_ID_COPY);
4997 if (pipe->pipe_settings.capture.copy_binary.info)
4998 return 0;
4999
5000 err = ia_css_frame_check_info(&pipe->output_info[0]);
5001 if (err)
5002 goto ERR;
5003
5004 err = verify_copy_out_frame_format(pipe);
5005 if (err)
5006 goto ERR;
5007
5008 err = load_copy_binary(pipe,
5009 &pipe->pipe_settings.capture.copy_binary,
5010 NULL);
5011
5012 ERR:
5013 IA_CSS_LEAVE_ERR_PRIVATE(err);
5014 return err;
5015 }
5016
need_capture_pp(const struct ia_css_pipe * pipe)5017 static bool need_capture_pp(
5018 const struct ia_css_pipe *pipe)
5019 {
5020 const struct ia_css_frame_info *out_info = &pipe->output_info[0];
5021
5022 IA_CSS_ENTER_LEAVE_PRIVATE("");
5023 assert(pipe);
5024 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
5025
5026 /* determine whether we need to use the capture_pp binary.
5027 * This is needed for:
5028 * 1. XNR or
5029 * 2. Digital Zoom or
5030 * 3. YUV downscaling
5031 */
5032 if (pipe->out_yuv_ds_input_info.res.width &&
5033 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) ||
5034 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height)))
5035 return true;
5036
5037 if (pipe->config.default_capture_config.enable_xnr != 0)
5038 return true;
5039
5040 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) ||
5041 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) ||
5042 pipe->config.enable_dz)
5043 return true;
5044
5045 return false;
5046 }
5047
need_capt_ldc(const struct ia_css_pipe * pipe)5048 static bool need_capt_ldc(
5049 const struct ia_css_pipe *pipe)
5050 {
5051 IA_CSS_ENTER_LEAVE_PRIVATE("");
5052 assert(pipe);
5053 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
5054 return (pipe->extra_config.enable_dvs_6axis) ? true : false;
5055 }
5056
set_num_primary_stages(unsigned int * num,enum ia_css_pipe_version version)5057 static int set_num_primary_stages(unsigned int *num,
5058 enum ia_css_pipe_version version)
5059 {
5060 int err = 0;
5061
5062 if (!num)
5063 return -EINVAL;
5064
5065 switch (version) {
5066 case IA_CSS_PIPE_VERSION_2_6_1:
5067 *num = NUM_PRIMARY_HQ_STAGES;
5068 break;
5069 case IA_CSS_PIPE_VERSION_2_2:
5070 case IA_CSS_PIPE_VERSION_1:
5071 *num = NUM_PRIMARY_STAGES;
5072 break;
5073 default:
5074 err = -EINVAL;
5075 break;
5076 }
5077
5078 return err;
5079 }
5080
load_primary_binaries(struct ia_css_pipe * pipe)5081 static int load_primary_binaries(
5082 struct ia_css_pipe *pipe)
5083 {
5084 bool online = false;
5085 bool need_pp = false;
5086 bool need_isp_copy_binary = false;
5087 bool need_ldc = false;
5088 bool sensor = false;
5089 bool memory, continuous;
5090 struct ia_css_frame_info prim_in_info,
5091 prim_out_info,
5092 capt_pp_out_info, vf_info,
5093 *vf_pp_in_info, *pipe_out_info,
5094 *pipe_vf_out_info, *capt_pp_in_info,
5095 capt_ldc_out_info;
5096 int err = 0;
5097 struct ia_css_capture_settings *mycs;
5098 unsigned int i;
5099 bool need_extra_yuv_scaler = false;
5100 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES];
5101
5102 IA_CSS_ENTER_PRIVATE("");
5103 assert(pipe);
5104 assert(pipe->stream);
5105 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5106 pipe->mode == IA_CSS_PIPE_ID_COPY);
5107
5108 online = pipe->stream->config.online;
5109 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
5110 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
5111 continuous = pipe->stream->config.continuous;
5112
5113 mycs = &pipe->pipe_settings.capture;
5114 pipe_out_info = &pipe->output_info[0];
5115 pipe_vf_out_info = &pipe->vf_output_info[0];
5116
5117 if (mycs->primary_binary[0].info)
5118 return 0;
5119
5120 err = set_num_primary_stages(&mycs->num_primary_stage,
5121 pipe->config.isp_pipe_version);
5122 if (err) {
5123 IA_CSS_LEAVE_ERR_PRIVATE(err);
5124 return err;
5125 }
5126
5127 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5128 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info);
5129 if (err) {
5130 IA_CSS_LEAVE_ERR_PRIVATE(err);
5131 return err;
5132 }
5133 } else {
5134 err = ia_css_frame_check_info(pipe_out_info);
5135 if (err) {
5136 IA_CSS_LEAVE_ERR_PRIVATE(err);
5137 return err;
5138 }
5139 }
5140 need_pp = need_capture_pp(pipe);
5141
5142 /*
5143 * we use the vf output info to get the primary/capture_pp binary
5144 * configured for vf_veceven. It will select the closest downscaling
5145 * factor.
5146 */
5147 vf_info = *pipe_vf_out_info;
5148
5149 /*
5150 * WARNING: The #if def flag has been added below as a
5151 * temporary solution to solve the problem of enabling the
5152 * view finder in a single binary in a capture flow. The
5153 * vf-pp stage has been removed for Skycam in the solution
5154 * provided. The vf-pp stage should be re-introduced when
5155 * required. This should not be considered as a clean solution.
5156 * Proper investigation should be done to come up with the clean
5157 * solution.
5158 */
5159 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
5160
5161 /*
5162 * TODO: All this yuv_scaler and capturepp calculation logic
5163 * can be shared later. Capture_pp is also a yuv_scale binary
5164 * with extra XNR funcionality. Therefore, it can be made as the
5165 * first step of the cascade.
5166 */
5167 capt_pp_out_info = pipe->out_yuv_ds_input_info;
5168 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420;
5169 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP;
5170 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP;
5171 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0);
5172
5173 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res,
5174 pipe_out_info->res);
5175
5176 if (need_extra_yuv_scaler) {
5177 struct ia_css_cas_binary_descr cas_scaler_descr = { };
5178
5179 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5180 &capt_pp_out_info,
5181 pipe_out_info,
5182 NULL,
5183 &cas_scaler_descr);
5184 if (err) {
5185 IA_CSS_LEAVE_ERR_PRIVATE(err);
5186 return err;
5187 }
5188 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5189 mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage,
5190 sizeof(struct ia_css_binary),
5191 GFP_KERNEL);
5192 if (!mycs->yuv_scaler_binary) {
5193 err = -ENOMEM;
5194 IA_CSS_LEAVE_ERR_PRIVATE(err);
5195 return err;
5196 }
5197 mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage,
5198 sizeof(bool), GFP_KERNEL);
5199 if (!mycs->is_output_stage) {
5200 err = -ENOMEM;
5201 IA_CSS_LEAVE_ERR_PRIVATE(err);
5202 return err;
5203 }
5204 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5205 struct ia_css_binary_descr yuv_scaler_descr;
5206
5207 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5208 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5209 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5210 &cas_scaler_descr.out_info[i],
5211 &cas_scaler_descr.internal_out_info[i],
5212 &cas_scaler_descr.vf_info[i]);
5213 err = ia_css_binary_find(&yuv_scaler_descr,
5214 &mycs->yuv_scaler_binary[i]);
5215 if (err) {
5216 IA_CSS_LEAVE_ERR_PRIVATE(err);
5217 return err;
5218 }
5219 }
5220 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5221
5222 } else {
5223 capt_pp_out_info = pipe->output_info[0];
5224 }
5225
5226 /* TODO Do we disable ldc for skycam */
5227 need_ldc = need_capt_ldc(pipe);
5228
5229 /* we build up the pipeline starting at the end */
5230 /* Capture post-processing */
5231 if (need_pp) {
5232 struct ia_css_binary_descr capture_pp_descr;
5233
5234 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info;
5235
5236 ia_css_pipe_get_capturepp_binarydesc(pipe,
5237 &capture_pp_descr,
5238 capt_pp_in_info,
5239 &capt_pp_out_info,
5240 &vf_info);
5241
5242 err = ia_css_binary_find(&capture_pp_descr,
5243 &mycs->capture_pp_binary);
5244 if (err) {
5245 IA_CSS_LEAVE_ERR_PRIVATE(err);
5246 return err;
5247 }
5248
5249 if (need_ldc) {
5250 struct ia_css_binary_descr capt_ldc_descr;
5251
5252 ia_css_pipe_get_ldc_binarydesc(pipe,
5253 &capt_ldc_descr,
5254 &prim_out_info,
5255 &capt_ldc_out_info);
5256
5257 err = ia_css_binary_find(&capt_ldc_descr,
5258 &mycs->capture_ldc_binary);
5259 if (err) {
5260 IA_CSS_LEAVE_ERR_PRIVATE(err);
5261 return err;
5262 }
5263 }
5264 } else {
5265 prim_out_info = *pipe_out_info;
5266 }
5267
5268 /* Primary */
5269 for (i = 0; i < mycs->num_primary_stage; i++) {
5270 struct ia_css_frame_info *local_vf_info = NULL;
5271
5272 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] &&
5273 (i == mycs->num_primary_stage - 1))
5274 local_vf_info = &vf_info;
5275 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i],
5276 &prim_in_info, &prim_out_info,
5277 local_vf_info, i);
5278 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
5279 if (err) {
5280 IA_CSS_LEAVE_ERR_PRIVATE(err);
5281 return err;
5282 }
5283 }
5284
5285 /* Viewfinder post-processing */
5286 if (need_pp)
5287 vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info;
5288 else
5289 vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info;
5290
5291 /*
5292 * WARNING: The #if def flag has been added below as a
5293 * temporary solution to solve the problem of enabling the
5294 * view finder in a single binary in a capture flow. The
5295 * vf-pp stage has been removed for Skycam in the solution
5296 * provided. The vf-pp stage should be re-introduced when
5297 * required. Thisshould not be considered as a clean solution.
5298 * Proper * investigation should be done to come up with the clean
5299 * solution.
5300 */
5301 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5302 struct ia_css_binary_descr vf_pp_descr;
5303
5304 ia_css_pipe_get_vfpp_binarydesc(pipe,
5305 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
5306 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary);
5307 if (err) {
5308 IA_CSS_LEAVE_ERR_PRIVATE(err);
5309 return err;
5310 }
5311 }
5312 err = allocate_delay_frames(pipe);
5313
5314 if (err)
5315 return err;
5316
5317 if (IS_ISP2401)
5318 /*
5319 * When the input system is 2401, only the Direct Sensor Mode
5320 * Offline Capture uses the ISP copy binary.
5321 */
5322 need_isp_copy_binary = !online && sensor;
5323 else
5324 need_isp_copy_binary = !online && !continuous && !memory;
5325
5326 /* ISP Copy */
5327 if (need_isp_copy_binary) {
5328 err = load_copy_binary(pipe,
5329 &mycs->copy_binary,
5330 &mycs->primary_binary[0]);
5331 if (err) {
5332 IA_CSS_LEAVE_ERR_PRIVATE(err);
5333 return err;
5334 }
5335 }
5336
5337 return 0;
5338 }
5339
5340 static int
allocate_delay_frames(struct ia_css_pipe * pipe)5341 allocate_delay_frames(struct ia_css_pipe *pipe)
5342 {
5343 unsigned int num_delay_frames = 0, i = 0;
5344 unsigned int dvs_frame_delay = 0;
5345 struct ia_css_frame_info ref_info;
5346 int err = 0;
5347 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO;
5348 struct ia_css_frame **delay_frames = NULL;
5349
5350 IA_CSS_ENTER_PRIVATE("");
5351
5352 if (!pipe) {
5353 IA_CSS_ERROR("Invalid args - pipe %p", pipe);
5354 return -EINVAL;
5355 }
5356
5357 mode = pipe->mode;
5358 dvs_frame_delay = pipe->dvs_frame_delay;
5359
5360 if (dvs_frame_delay > 0)
5361 num_delay_frames = dvs_frame_delay + 1;
5362
5363 switch (mode) {
5364 case IA_CSS_PIPE_ID_CAPTURE: {
5365 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
5366 (void)mycs_capture;
5367 return err;
5368 }
5369 break;
5370 case IA_CSS_PIPE_ID_VIDEO: {
5371 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video;
5372
5373 ref_info = mycs_video->video_binary.internal_frame_info;
5374
5375 /*
5376 * The ref frame expects
5377 * 1. Y plane
5378 * 2. UV plane with line interleaving, like below
5379 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
5380 *
5381 * This format is not YUV420(which has Y, U and V planes).
5382 * Its closer to NV12, except that the UV plane has UV
5383 * interleaving, like UVUVUVUVUVUVUVUVU...
5384 *
5385 * TODO: make this ref_frame format as a separate frame format
5386 */
5387 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
5388 delay_frames = mycs_video->delay_frames;
5389 }
5390 break;
5391 case IA_CSS_PIPE_ID_PREVIEW: {
5392 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview;
5393
5394 ref_info = mycs_preview->preview_binary.internal_frame_info;
5395
5396 /*
5397 * The ref frame expects
5398 * 1. Y plane
5399 * 2. UV plane with line interleaving, like below
5400 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
5401 *
5402 * This format is not YUV420(which has Y, U and V planes).
5403 * Its closer to NV12, except that the UV plane has UV
5404 * interleaving, like UVUVUVUVUVUVUVUVU...
5405 *
5406 * TODO: make this ref_frame format as a separate frame format
5407 */
5408 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
5409 delay_frames = mycs_preview->delay_frames;
5410 }
5411 break;
5412 default:
5413 return -EINVAL;
5414 }
5415
5416 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
5417
5418 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
5419 for (i = 0; i < num_delay_frames; i++) {
5420 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info);
5421 if (err)
5422 return err;
5423 }
5424 IA_CSS_LEAVE_PRIVATE("");
5425 return 0;
5426 }
5427
load_advanced_binaries(struct ia_css_pipe * pipe)5428 static int load_advanced_binaries(struct ia_css_pipe *pipe)
5429 {
5430 struct ia_css_frame_info pre_in_info, gdc_in_info,
5431 post_in_info, post_out_info,
5432 vf_info, *vf_pp_in_info, *pipe_out_info,
5433 *pipe_vf_out_info;
5434 bool need_pp;
5435 bool need_isp_copy = true;
5436 int err = 0;
5437
5438 IA_CSS_ENTER_PRIVATE("");
5439
5440 assert(pipe);
5441 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5442 pipe->mode == IA_CSS_PIPE_ID_COPY);
5443 if (pipe->pipe_settings.capture.pre_isp_binary.info)
5444 return 0;
5445 pipe_out_info = &pipe->output_info[0];
5446 pipe_vf_out_info = &pipe->vf_output_info[0];
5447
5448 vf_info = *pipe_vf_out_info;
5449 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info);
5450 if (err)
5451 return err;
5452 need_pp = need_capture_pp(pipe);
5453
5454 ia_css_frame_info_set_format(&vf_info,
5455 IA_CSS_FRAME_FORMAT_YUV_LINE);
5456
5457 /* we build up the pipeline starting at the end */
5458 /* Capture post-processing */
5459 if (need_pp) {
5460 struct ia_css_binary_descr capture_pp_descr;
5461
5462 ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr,
5463 &post_out_info,
5464 pipe_out_info, &vf_info);
5465 err = ia_css_binary_find(&capture_pp_descr,
5466 &pipe->pipe_settings.capture.capture_pp_binary);
5467 if (err)
5468 return err;
5469 } else {
5470 post_out_info = *pipe_out_info;
5471 }
5472
5473 /* Post-gdc */
5474 {
5475 struct ia_css_binary_descr post_gdc_descr;
5476
5477 ia_css_pipe_get_post_gdc_binarydesc(pipe, &post_gdc_descr,
5478 &post_in_info,
5479 &post_out_info, &vf_info);
5480 err = ia_css_binary_find(&post_gdc_descr,
5481 &pipe->pipe_settings.capture.post_isp_binary);
5482 if (err)
5483 return err;
5484 }
5485
5486 /* Gdc */
5487 {
5488 struct ia_css_binary_descr gdc_descr;
5489
5490 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
5491 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
5492 err = ia_css_binary_find(&gdc_descr,
5493 &pipe->pipe_settings.capture.anr_gdc_binary);
5494 if (err)
5495 return err;
5496 }
5497 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
5498 pipe->pipe_settings.capture.post_isp_binary.left_padding;
5499
5500 /* Pre-gdc */
5501 {
5502 struct ia_css_binary_descr pre_gdc_descr;
5503
5504 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
5505 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
5506 err = ia_css_binary_find(&pre_gdc_descr,
5507 &pipe->pipe_settings.capture.pre_isp_binary);
5508 if (err)
5509 return err;
5510 }
5511 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
5512 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
5513
5514 /* Viewfinder post-processing */
5515 if (need_pp) {
5516 vf_pp_in_info =
5517 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
5518 } else {
5519 vf_pp_in_info =
5520 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
5521 }
5522
5523 {
5524 struct ia_css_binary_descr vf_pp_descr;
5525
5526 ia_css_pipe_get_vfpp_binarydesc(pipe,
5527 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
5528 err = ia_css_binary_find(&vf_pp_descr,
5529 &pipe->pipe_settings.capture.vf_pp_binary);
5530 if (err)
5531 return err;
5532 }
5533
5534 /* Copy */
5535 if (IS_ISP2401)
5536 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
5537 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
5538
5539 if (need_isp_copy)
5540 load_copy_binary(pipe,
5541 &pipe->pipe_settings.capture.copy_binary,
5542 &pipe->pipe_settings.capture.pre_isp_binary);
5543
5544 return err;
5545 }
5546
load_bayer_isp_binaries(struct ia_css_pipe * pipe)5547 static int load_bayer_isp_binaries(struct ia_css_pipe *pipe)
5548 {
5549 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
5550 int err = 0;
5551 struct ia_css_binary_descr pre_de_descr;
5552
5553 IA_CSS_ENTER_PRIVATE("");
5554 assert(pipe);
5555 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5556 pipe->mode == IA_CSS_PIPE_ID_COPY);
5557 pipe_out_info = &pipe->output_info[0];
5558
5559 if (pipe->pipe_settings.capture.pre_isp_binary.info)
5560 return 0;
5561
5562 err = ia_css_frame_check_info(pipe_out_info);
5563 if (err)
5564 return err;
5565
5566 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
5567 &pre_isp_in_info,
5568 pipe_out_info);
5569
5570 err = ia_css_binary_find(&pre_de_descr,
5571 &pipe->pipe_settings.capture.pre_isp_binary);
5572
5573 return err;
5574 }
5575
load_low_light_binaries(struct ia_css_pipe * pipe)5576 static int load_low_light_binaries(struct ia_css_pipe *pipe)
5577 {
5578 struct ia_css_frame_info pre_in_info, anr_in_info,
5579 post_in_info, post_out_info,
5580 vf_info, *pipe_vf_out_info, *pipe_out_info,
5581 *vf_pp_in_info;
5582 bool need_pp;
5583 bool need_isp_copy = true;
5584 int err = 0;
5585
5586 IA_CSS_ENTER_PRIVATE("");
5587 assert(pipe);
5588 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5589 pipe->mode == IA_CSS_PIPE_ID_COPY);
5590
5591 if (pipe->pipe_settings.capture.pre_isp_binary.info)
5592 return 0;
5593 pipe_vf_out_info = &pipe->vf_output_info[0];
5594 pipe_out_info = &pipe->output_info[0];
5595
5596 vf_info = *pipe_vf_out_info;
5597 err = ia_css_util_check_vf_out_info(pipe_out_info,
5598 &vf_info);
5599 if (err)
5600 return err;
5601 need_pp = need_capture_pp(pipe);
5602
5603 ia_css_frame_info_set_format(&vf_info,
5604 IA_CSS_FRAME_FORMAT_YUV_LINE);
5605
5606 /* we build up the pipeline starting at the end */
5607 /* Capture post-processing */
5608 if (need_pp) {
5609 struct ia_css_binary_descr capture_pp_descr;
5610
5611 ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr,
5612 &post_out_info,
5613 pipe_out_info, &vf_info);
5614 err = ia_css_binary_find(&capture_pp_descr,
5615 &pipe->pipe_settings.capture.capture_pp_binary);
5616 if (err)
5617 return err;
5618 } else {
5619 post_out_info = *pipe_out_info;
5620 }
5621
5622 /* Post-anr */
5623 {
5624 struct ia_css_binary_descr post_anr_descr;
5625
5626 ia_css_pipe_get_post_anr_binarydesc(pipe,
5627 &post_anr_descr, &post_in_info, &post_out_info, &vf_info);
5628 err = ia_css_binary_find(&post_anr_descr,
5629 &pipe->pipe_settings.capture.post_isp_binary);
5630 if (err)
5631 return err;
5632 }
5633
5634 /* Anr */
5635 {
5636 struct ia_css_binary_descr anr_descr;
5637
5638 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
5639 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
5640 err = ia_css_binary_find(&anr_descr,
5641 &pipe->pipe_settings.capture.anr_gdc_binary);
5642 if (err)
5643 return err;
5644 }
5645 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
5646 pipe->pipe_settings.capture.post_isp_binary.left_padding;
5647
5648 /* Pre-anr */
5649 {
5650 struct ia_css_binary_descr pre_anr_descr;
5651
5652 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
5653 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
5654 err = ia_css_binary_find(&pre_anr_descr,
5655 &pipe->pipe_settings.capture.pre_isp_binary);
5656 if (err)
5657 return err;
5658 }
5659 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
5660 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
5661
5662 /* Viewfinder post-processing */
5663 if (need_pp) {
5664 vf_pp_in_info =
5665 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
5666 } else {
5667 vf_pp_in_info =
5668 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
5669 }
5670
5671 {
5672 struct ia_css_binary_descr vf_pp_descr;
5673
5674 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5675 vf_pp_in_info, pipe_vf_out_info);
5676 err = ia_css_binary_find(&vf_pp_descr,
5677 &pipe->pipe_settings.capture.vf_pp_binary);
5678 if (err)
5679 return err;
5680 }
5681
5682 /* Copy */
5683 if (IS_ISP2401)
5684 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
5685 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
5686
5687 if (need_isp_copy)
5688 err = load_copy_binary(pipe,
5689 &pipe->pipe_settings.capture.copy_binary,
5690 &pipe->pipe_settings.capture.pre_isp_binary);
5691
5692 return err;
5693 }
5694
copy_on_sp(struct ia_css_pipe * pipe)5695 static bool copy_on_sp(struct ia_css_pipe *pipe)
5696 {
5697 bool rval;
5698
5699 assert(pipe);
5700 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n");
5701
5702 rval = true;
5703
5704 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
5705
5706 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
5707
5708 rval &= ((pipe->stream->config.input_config.format ==
5709 ATOMISP_INPUT_FORMAT_BINARY_8) ||
5710 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
5711
5712 return rval;
5713 }
5714
load_capture_binaries(struct ia_css_pipe * pipe)5715 static int load_capture_binaries(struct ia_css_pipe *pipe)
5716 {
5717 int err = 0;
5718 bool must_be_raw;
5719
5720 IA_CSS_ENTER_PRIVATE("");
5721 assert(pipe);
5722 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5723 pipe->mode == IA_CSS_PIPE_ID_COPY);
5724
5725 if (pipe->pipe_settings.capture.primary_binary[0].info) {
5726 IA_CSS_LEAVE_ERR_PRIVATE(0);
5727 return 0;
5728 }
5729
5730 /* in primary, advanced,low light or bayer,
5731 the input format must be raw */
5732 must_be_raw =
5733 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
5734 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ||
5735 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT;
5736 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false);
5737 if (err) {
5738 IA_CSS_LEAVE_ERR_PRIVATE(err);
5739 return err;
5740 }
5741 if (copy_on_sp(pipe) &&
5742 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
5743 ia_css_frame_info_init(
5744 &pipe->output_info[0],
5745 JPEG_BYTES,
5746 1,
5747 IA_CSS_FRAME_FORMAT_BINARY_8,
5748 0);
5749 IA_CSS_LEAVE_ERR_PRIVATE(0);
5750 return 0;
5751 }
5752
5753 switch (pipe->config.default_capture_config.mode) {
5754 case IA_CSS_CAPTURE_MODE_RAW:
5755 err = load_copy_binaries(pipe);
5756 if (!err && IS_ISP2401)
5757 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
5758
5759 break;
5760 case IA_CSS_CAPTURE_MODE_BAYER:
5761 err = load_bayer_isp_binaries(pipe);
5762 break;
5763 case IA_CSS_CAPTURE_MODE_PRIMARY:
5764 err = load_primary_binaries(pipe);
5765 break;
5766 case IA_CSS_CAPTURE_MODE_ADVANCED:
5767 err = load_advanced_binaries(pipe);
5768 break;
5769 case IA_CSS_CAPTURE_MODE_LOW_LIGHT:
5770 err = load_low_light_binaries(pipe);
5771 break;
5772 }
5773 if (err) {
5774 IA_CSS_LEAVE_ERR_PRIVATE(err);
5775 return err;
5776 }
5777
5778 IA_CSS_LEAVE_ERR_PRIVATE(err);
5779 return err;
5780 }
5781
5782 static int
unload_capture_binaries(struct ia_css_pipe * pipe)5783 unload_capture_binaries(struct ia_css_pipe *pipe)
5784 {
5785 unsigned int i;
5786
5787 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5788
5789 if (!pipe || (pipe->mode != IA_CSS_PIPE_ID_CAPTURE &&
5790 pipe->mode != IA_CSS_PIPE_ID_COPY)) {
5791 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5792 return -EINVAL;
5793 }
5794 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary);
5795 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++)
5796 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]);
5797 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary);
5798 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary);
5799 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary);
5800 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary);
5801 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary);
5802 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary);
5803
5804 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++)
5805 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]);
5806
5807 kfree(pipe->pipe_settings.capture.is_output_stage);
5808 pipe->pipe_settings.capture.is_output_stage = NULL;
5809 kfree(pipe->pipe_settings.capture.yuv_scaler_binary);
5810 pipe->pipe_settings.capture.yuv_scaler_binary = NULL;
5811
5812 IA_CSS_LEAVE_ERR_PRIVATE(0);
5813 return 0;
5814 }
5815
5816 static bool
need_downscaling(const struct ia_css_resolution in_res,const struct ia_css_resolution out_res)5817 need_downscaling(const struct ia_css_resolution in_res,
5818 const struct ia_css_resolution out_res)
5819 {
5820 if (in_res.width > out_res.width || in_res.height > out_res.height)
5821 return true;
5822
5823 return false;
5824 }
5825
5826 static bool
need_yuv_scaler_stage(const struct ia_css_pipe * pipe)5827 need_yuv_scaler_stage(const struct ia_css_pipe *pipe)
5828 {
5829 unsigned int i;
5830 struct ia_css_resolution in_res, out_res;
5831
5832 bool need_format_conversion = false;
5833
5834 IA_CSS_ENTER_PRIVATE("");
5835 assert(pipe);
5836 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
5837
5838 /* TODO: make generic function */
5839 need_format_conversion =
5840 ((pipe->stream->config.input_config.format ==
5841 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) &&
5842 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
5843
5844 in_res = pipe->config.input_effective_res;
5845
5846 if (pipe->config.enable_dz)
5847 return true;
5848
5849 if ((pipe->output_info[0].res.width != 0) && need_format_conversion)
5850 return true;
5851
5852 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
5853 out_res = pipe->output_info[i].res;
5854
5855 /* A non-zero width means it is a valid output port */
5856 if ((out_res.width != 0) && need_downscaling(in_res, out_res))
5857 return true;
5858 }
5859
5860 return false;
5861 }
5862
5863 /*
5864 * TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc
5865 * which has some hard-coded knowledge which prevents reuse of the function.
5866 * Later, merge this with ia_css_pipe_create_cas_scaler_desc
5867 */
ia_css_pipe_create_cas_scaler_desc_single_output(struct ia_css_frame_info * cas_scaler_in_info,struct ia_css_frame_info * cas_scaler_out_info,struct ia_css_frame_info * cas_scaler_vf_info,struct ia_css_cas_binary_descr * descr)5868 static int ia_css_pipe_create_cas_scaler_desc_single_output(
5869 struct ia_css_frame_info *cas_scaler_in_info,
5870 struct ia_css_frame_info *cas_scaler_out_info,
5871 struct ia_css_frame_info *cas_scaler_vf_info,
5872 struct ia_css_cas_binary_descr *descr)
5873 {
5874 unsigned int i;
5875 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
5876 int err = 0;
5877 struct ia_css_frame_info tmp_in_info;
5878
5879 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
5880
5881 assert(cas_scaler_in_info);
5882 assert(cas_scaler_out_info);
5883
5884 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5885 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
5886
5887 /* We assume that this function is used only for single output port case. */
5888 descr->num_output_stage = 1;
5889
5890 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width,
5891 cas_scaler_out_info->res.width);
5892 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height,
5893 cas_scaler_out_info->res.height);
5894 /* use the same horizontal and vertical downscaling factor for simplicity */
5895 assert(hor_ds_factor == ver_ds_factor);
5896
5897 i = 1;
5898 while (i < hor_ds_factor) {
5899 descr->num_stage++;
5900 i *= max_scale_factor_per_stage;
5901 }
5902
5903 descr->in_info = kmalloc(descr->num_stage *
5904 sizeof(struct ia_css_frame_info),
5905 GFP_KERNEL);
5906 if (!descr->in_info) {
5907 err = -ENOMEM;
5908 goto ERR;
5909 }
5910 descr->internal_out_info = kmalloc(descr->num_stage *
5911 sizeof(struct ia_css_frame_info),
5912 GFP_KERNEL);
5913 if (!descr->internal_out_info) {
5914 err = -ENOMEM;
5915 goto ERR;
5916 }
5917 descr->out_info = kmalloc(descr->num_stage *
5918 sizeof(struct ia_css_frame_info),
5919 GFP_KERNEL);
5920 if (!descr->out_info) {
5921 err = -ENOMEM;
5922 goto ERR;
5923 }
5924 descr->vf_info = kmalloc(descr->num_stage *
5925 sizeof(struct ia_css_frame_info),
5926 GFP_KERNEL);
5927 if (!descr->vf_info) {
5928 err = -ENOMEM;
5929 goto ERR;
5930 }
5931 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool),
5932 GFP_KERNEL);
5933 if (!descr->is_output_stage) {
5934 err = -ENOMEM;
5935 goto ERR;
5936 }
5937
5938 tmp_in_info = *cas_scaler_in_info;
5939 for (i = 0; i < descr->num_stage; i++) {
5940 descr->in_info[i] = tmp_in_info;
5941 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
5942 cas_scaler_out_info->res.width) {
5943 descr->is_output_stage[i] = true;
5944 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
5945 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width;
5946 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height;
5947 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width;
5948 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
5949 } else {
5950 assert(i == (descr->num_stage - 1));
5951 descr->internal_out_info[i].res.width = 0;
5952 descr->internal_out_info[i].res.height = 0;
5953 }
5954 descr->out_info[i].res.width = cas_scaler_out_info->res.width;
5955 descr->out_info[i].res.height = cas_scaler_out_info->res.height;
5956 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width;
5957 descr->out_info[i].format = cas_scaler_out_info->format;
5958 if (cas_scaler_vf_info) {
5959 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width;
5960 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height;
5961 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width;
5962 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
5963 } else {
5964 descr->vf_info[i].res.width = 0;
5965 descr->vf_info[i].res.height = 0;
5966 descr->vf_info[i].padded_width = 0;
5967 }
5968 } else {
5969 descr->is_output_stage[i] = false;
5970 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
5971 max_scale_factor_per_stage;
5972 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
5973 max_scale_factor_per_stage;
5974 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
5975 ia_css_frame_info_init(&descr->internal_out_info[i],
5976 tmp_in_info.res.width / max_scale_factor_per_stage,
5977 tmp_in_info.res.height / max_scale_factor_per_stage,
5978 IA_CSS_FRAME_FORMAT_YUV420, 0);
5979 descr->out_info[i].res.width = 0;
5980 descr->out_info[i].res.height = 0;
5981 descr->vf_info[i].res.width = 0;
5982 descr->vf_info[i].res.height = 0;
5983 }
5984 tmp_in_info = descr->internal_out_info[i];
5985 }
5986 ERR:
5987 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5988 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
5989 err);
5990 return err;
5991 }
5992
5993 /* FIXME: merge most of this and single output version */
5994 static int
ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe * pipe,struct ia_css_cas_binary_descr * descr)5995 ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe *pipe,
5996 struct ia_css_cas_binary_descr *descr)
5997 {
5998 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
5999 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6000 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6001 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6002 unsigned int i, j;
6003 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6004 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6005 scale_factor = 0;
6006 unsigned int num_stages = 0;
6007 int err = 0;
6008
6009 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6010
6011 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6012 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6013
6014 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6015 out_info[i] = NULL;
6016 vf_out_info[i] = NULL;
6017 hor_scale_factor[i] = 0;
6018 ver_scale_factor[i] = 0;
6019 }
6020
6021 in_info.res = pipe->config.input_effective_res;
6022 in_info.padded_width = in_info.res.width;
6023 descr->num_output_stage = 0;
6024 /* Find out how much scaling we need for each output */
6025 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6026 if (pipe->output_info[i].res.width != 0) {
6027 out_info[i] = &pipe->output_info[i];
6028 if (pipe->vf_output_info[i].res.width != 0)
6029 vf_out_info[i] = &pipe->vf_output_info[i];
6030 descr->num_output_stage += 1;
6031 }
6032
6033 if (out_info[i]) {
6034 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width);
6035 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height);
6036 /* use the same horizontal and vertical scaling factor for simplicity */
6037 assert(hor_scale_factor[i] == ver_scale_factor[i]);
6038 scale_factor = 1;
6039 do {
6040 num_stages++;
6041 scale_factor *= max_scale_factor_per_stage;
6042 } while (scale_factor < hor_scale_factor[i]);
6043
6044 in_info.res = out_info[i]->res;
6045 }
6046 }
6047
6048 if (need_yuv_scaler_stage(pipe) && (num_stages == 0))
6049 num_stages = 1;
6050
6051 descr->num_stage = num_stages;
6052
6053 descr->in_info = kmalloc_array(descr->num_stage,
6054 sizeof(struct ia_css_frame_info),
6055 GFP_KERNEL);
6056 if (!descr->in_info) {
6057 err = -ENOMEM;
6058 goto ERR;
6059 }
6060 descr->internal_out_info = kmalloc(descr->num_stage *
6061 sizeof(struct ia_css_frame_info),
6062 GFP_KERNEL);
6063 if (!descr->internal_out_info) {
6064 err = -ENOMEM;
6065 goto ERR;
6066 }
6067 descr->out_info = kmalloc(descr->num_stage *
6068 sizeof(struct ia_css_frame_info),
6069 GFP_KERNEL);
6070 if (!descr->out_info) {
6071 err = -ENOMEM;
6072 goto ERR;
6073 }
6074 descr->vf_info = kmalloc(descr->num_stage *
6075 sizeof(struct ia_css_frame_info),
6076 GFP_KERNEL);
6077 if (!descr->vf_info) {
6078 err = -ENOMEM;
6079 goto ERR;
6080 }
6081 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool),
6082 GFP_KERNEL);
6083 if (!descr->is_output_stage) {
6084 err = -ENOMEM;
6085 goto ERR;
6086 }
6087
6088 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6089 if (out_info[i]) {
6090 if (i > 0) {
6091 assert((out_info[i - 1]->res.width >= out_info[i]->res.width) &&
6092 (out_info[i - 1]->res.height >= out_info[i]->res.height));
6093 }
6094 }
6095 }
6096
6097 tmp_in_info.res = pipe->config.input_effective_res;
6098 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420;
6099 for (i = 0, j = 0; i < descr->num_stage; i++) {
6100 assert(j < 2);
6101 assert(out_info[j]);
6102
6103 descr->in_info[i] = tmp_in_info;
6104 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
6105 out_info[j]->res.width) {
6106 descr->is_output_stage[i] = true;
6107 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
6108 descr->internal_out_info[i].res.width = out_info[j]->res.width;
6109 descr->internal_out_info[i].res.height = out_info[j]->res.height;
6110 descr->internal_out_info[i].padded_width = out_info[j]->padded_width;
6111 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6112 } else {
6113 assert(i == (descr->num_stage - 1));
6114 descr->internal_out_info[i].res.width = 0;
6115 descr->internal_out_info[i].res.height = 0;
6116 }
6117 descr->out_info[i].res.width = out_info[j]->res.width;
6118 descr->out_info[i].res.height = out_info[j]->res.height;
6119 descr->out_info[i].padded_width = out_info[j]->padded_width;
6120 descr->out_info[i].format = out_info[j]->format;
6121 if (vf_out_info[j]) {
6122 descr->vf_info[i].res.width = vf_out_info[j]->res.width;
6123 descr->vf_info[i].res.height = vf_out_info[j]->res.height;
6124 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width;
6125 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
6126 } else {
6127 descr->vf_info[i].res.width = 0;
6128 descr->vf_info[i].res.height = 0;
6129 descr->vf_info[i].padded_width = 0;
6130 }
6131 j++;
6132 } else {
6133 descr->is_output_stage[i] = false;
6134 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
6135 max_scale_factor_per_stage;
6136 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
6137 max_scale_factor_per_stage;
6138 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6139 ia_css_frame_info_init(&descr->internal_out_info[i],
6140 tmp_in_info.res.width / max_scale_factor_per_stage,
6141 tmp_in_info.res.height / max_scale_factor_per_stage,
6142 IA_CSS_FRAME_FORMAT_YUV420, 0);
6143 descr->out_info[i].res.width = 0;
6144 descr->out_info[i].res.height = 0;
6145 descr->vf_info[i].res.width = 0;
6146 descr->vf_info[i].res.height = 0;
6147 }
6148 tmp_in_info = descr->internal_out_info[i];
6149 }
6150 ERR:
6151 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6152 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
6153 err);
6154 return err;
6155 }
6156
ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr * descr)6157 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
6158 *descr)
6159 {
6160 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6161 "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
6162 kfree(descr->in_info);
6163 descr->in_info = NULL;
6164 kfree(descr->internal_out_info);
6165 descr->internal_out_info = NULL;
6166 kfree(descr->out_info);
6167 descr->out_info = NULL;
6168 kfree(descr->vf_info);
6169 descr->vf_info = NULL;
6170 kfree(descr->is_output_stage);
6171 descr->is_output_stage = NULL;
6172 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6173 "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
6174 }
6175
6176 static int
load_yuvpp_binaries(struct ia_css_pipe * pipe)6177 load_yuvpp_binaries(struct ia_css_pipe *pipe)
6178 {
6179 int err = 0;
6180 bool need_scaler = false;
6181 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6182 struct ia_css_yuvpp_settings *mycs;
6183 struct ia_css_binary *next_binary;
6184 struct ia_css_cas_binary_descr cas_scaler_descr = { };
6185 unsigned int i, j;
6186 bool need_isp_copy_binary = false;
6187
6188 IA_CSS_ENTER_PRIVATE("");
6189 assert(pipe);
6190 assert(pipe->stream);
6191 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6192
6193 if (pipe->pipe_settings.yuvpp.copy_binary.info)
6194 goto ERR;
6195
6196 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */
6197 err = ia_css_util_check_input(&pipe->stream->config, false, false);
6198 if (err)
6199 goto ERR;
6200
6201 mycs = &pipe->pipe_settings.yuvpp;
6202
6203 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6204 if (pipe->vf_output_info[i].res.width != 0) {
6205 err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
6206 &pipe->vf_output_info[i]);
6207 if (err)
6208 goto ERR;
6209 }
6210 vf_pp_in_info[i] = NULL;
6211 }
6212
6213 need_scaler = need_yuv_scaler_stage(pipe);
6214
6215 /* we build up the pipeline starting at the end */
6216 /* Capture post-processing */
6217 if (need_scaler) {
6218 struct ia_css_binary_descr yuv_scaler_descr;
6219
6220 err = ia_css_pipe_create_cas_scaler_desc(pipe,
6221 &cas_scaler_descr);
6222 if (err)
6223 goto ERR;
6224 mycs->num_output = cas_scaler_descr.num_output_stage;
6225 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
6226 mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage,
6227 sizeof(struct ia_css_binary),
6228 GFP_KERNEL);
6229 if (!mycs->yuv_scaler_binary) {
6230 err = -ENOMEM;
6231 goto ERR;
6232 }
6233 mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage,
6234 sizeof(bool), GFP_KERNEL);
6235 if (!mycs->is_output_stage) {
6236 err = -ENOMEM;
6237 goto ERR;
6238 }
6239 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
6240 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
6241 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
6242 &yuv_scaler_descr,
6243 &cas_scaler_descr.in_info[i],
6244 &cas_scaler_descr.out_info[i],
6245 &cas_scaler_descr.internal_out_info[i],
6246 &cas_scaler_descr.vf_info[i]);
6247 err = ia_css_binary_find(&yuv_scaler_descr,
6248 &mycs->yuv_scaler_binary[i]);
6249 if (err)
6250 goto ERR;
6251 }
6252 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6253 } else {
6254 mycs->num_output = 1;
6255 }
6256
6257 if (need_scaler)
6258 next_binary = &mycs->yuv_scaler_binary[0];
6259 else
6260 next_binary = NULL;
6261
6262 /*
6263 * NOTES
6264 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
6265 * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"?
6266 *
6267 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
6268 * binary". However, the "yuv_scale_binary" does NOT support the input-frame
6269 * format as "IA_CSS_STREAM _FORMAT_YUV422_8".
6270 *
6271 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv
6272 * _scale_binary". It would translate the input-frame to the frame formats that
6273 * are supported by the "yuv_scale_binary".
6274 *
6275 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_
6276 * pp_defs.h" for the list of input-frame formats that are supported by the
6277 * "yuv_scale_binary".
6278 */
6279 if (IS_ISP2401)
6280 need_isp_copy_binary =
6281 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
6282 else
6283 need_isp_copy_binary = true;
6284
6285 if (need_isp_copy_binary) {
6286 err = load_copy_binary(pipe,
6287 &mycs->copy_binary,
6288 next_binary);
6289
6290 if (err)
6291 goto ERR;
6292
6293 /*
6294 * NOTES
6295 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified?
6296 *
6297 * In some use cases, the first stage in the "yuvpp" pipe is the
6298 * "isp_copy_binary". The "isp_copy_binary" is designed to process
6299 * the input from either the system DDR or from the IPU internal VMEM.
6300 * So it provides the flag "online" to specify where its input is from,
6301 * i.e.:
6302 *
6303 * (1) "online <= true", the input is from the IPU internal VMEM.
6304 * (2) "online <= false", the input is from the system DDR.
6305 *
6306 * In other use cases, the first stage in the "yuvpp" pipe is the
6307 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the
6308 * input ONLY from the system DDR. So it does not provide the flag "online"
6309 * to specify where its input is from.
6310 */
6311 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6312 }
6313
6314 /* Viewfinder post-processing */
6315 if (need_scaler) {
6316 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
6317 if (mycs->is_output_stage[i]) {
6318 assert(j < 2);
6319 vf_pp_in_info[j] =
6320 &mycs->yuv_scaler_binary[i].vf_frame_info;
6321 j++;
6322 }
6323 }
6324 mycs->num_vf_pp = j;
6325 } else {
6326 vf_pp_in_info[0] =
6327 &mycs->copy_binary.vf_frame_info;
6328 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
6329 vf_pp_in_info[i] = NULL;
6330
6331 mycs->num_vf_pp = 1;
6332 }
6333 mycs->vf_pp_binary = kcalloc(mycs->num_vf_pp,
6334 sizeof(struct ia_css_binary),
6335 GFP_KERNEL);
6336 if (!mycs->vf_pp_binary) {
6337 err = -ENOMEM;
6338 goto ERR;
6339 }
6340
6341 {
6342 struct ia_css_binary_descr vf_pp_descr;
6343
6344 for (i = 0; i < mycs->num_vf_pp; i++) {
6345 if (pipe->vf_output_info[i].res.width != 0) {
6346 ia_css_pipe_get_vfpp_binarydesc(pipe,
6347 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
6348 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]);
6349 if (err)
6350 goto ERR;
6351 }
6352 }
6353 }
6354
6355 if (err)
6356 goto ERR;
6357
6358 ERR:
6359 if (need_scaler)
6360 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6361
6362 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
6363 err);
6364 return err;
6365 }
6366
6367 static int
unload_yuvpp_binaries(struct ia_css_pipe * pipe)6368 unload_yuvpp_binaries(struct ia_css_pipe *pipe)
6369 {
6370 unsigned int i;
6371
6372 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6373
6374 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
6375 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6376 return -EINVAL;
6377 }
6378 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
6379 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++)
6380 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
6381
6382 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++)
6383 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
6384
6385 kfree(pipe->pipe_settings.yuvpp.is_output_stage);
6386 pipe->pipe_settings.yuvpp.is_output_stage = NULL;
6387 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
6388 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL;
6389 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary);
6390 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL;
6391
6392 IA_CSS_LEAVE_ERR_PRIVATE(0);
6393 return 0;
6394 }
6395
yuvpp_start(struct ia_css_pipe * pipe)6396 static int yuvpp_start(struct ia_css_pipe *pipe)
6397 {
6398 int err = 0;
6399 enum sh_css_pipe_config_override copy_ovrd;
6400 enum ia_css_input_mode yuvpp_pipe_input_mode;
6401 unsigned int thread_id;
6402
6403 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6404 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
6405 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6406 return -EINVAL;
6407 }
6408
6409 yuvpp_pipe_input_mode = pipe->stream->config.mode;
6410
6411 sh_css_metrics_start_frame();
6412
6413 /* multi stream video needs mipi buffers */
6414
6415 err = send_mipi_frames(pipe);
6416 if (err) {
6417 IA_CSS_LEAVE_ERR_PRIVATE(err);
6418 return err;
6419 }
6420
6421 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
6422 copy_ovrd = 1 << thread_id;
6423
6424 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode);
6425
6426 IA_CSS_LEAVE_ERR_PRIVATE(err);
6427 return err;
6428 }
6429
6430 static int
sh_css_pipe_unload_binaries(struct ia_css_pipe * pipe)6431 sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe)
6432 {
6433 int err = 0;
6434
6435 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6436
6437 if (!pipe) {
6438 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6439 return -EINVAL;
6440 }
6441 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
6442 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
6443 IA_CSS_LEAVE_ERR_PRIVATE(0);
6444 return 0;
6445 }
6446
6447 switch (pipe->mode) {
6448 case IA_CSS_PIPE_ID_PREVIEW:
6449 err = unload_preview_binaries(pipe);
6450 break;
6451 case IA_CSS_PIPE_ID_VIDEO:
6452 err = unload_video_binaries(pipe);
6453 break;
6454 case IA_CSS_PIPE_ID_CAPTURE:
6455 err = unload_capture_binaries(pipe);
6456 break;
6457 case IA_CSS_PIPE_ID_YUVPP:
6458 err = unload_yuvpp_binaries(pipe);
6459 break;
6460 default:
6461 break;
6462 }
6463 IA_CSS_LEAVE_ERR_PRIVATE(err);
6464 return err;
6465 }
6466
6467 static int
sh_css_pipe_load_binaries(struct ia_css_pipe * pipe)6468 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe)
6469 {
6470 int err = 0;
6471
6472 assert(pipe);
6473 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n");
6474
6475 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
6476 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
6477 return err;
6478
6479 switch (pipe->mode) {
6480 case IA_CSS_PIPE_ID_PREVIEW:
6481 err = load_preview_binaries(pipe);
6482 break;
6483 case IA_CSS_PIPE_ID_VIDEO:
6484 err = load_video_binaries(pipe);
6485 break;
6486 case IA_CSS_PIPE_ID_CAPTURE:
6487 err = load_capture_binaries(pipe);
6488 break;
6489 case IA_CSS_PIPE_ID_YUVPP:
6490 err = load_yuvpp_binaries(pipe);
6491 break;
6492 default:
6493 err = -EINVAL;
6494 break;
6495 }
6496 if (err) {
6497 if (sh_css_pipe_unload_binaries(pipe)) {
6498 /*
6499 * currently css does not support multiple error
6500 * returns in a single function, using -EINVAL in
6501 * this case
6502 */
6503 err = -EINVAL;
6504 }
6505 }
6506 return err;
6507 }
6508
6509 static int
create_host_yuvpp_pipeline(struct ia_css_pipe * pipe)6510 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
6511 {
6512 struct ia_css_pipeline *me;
6513 int err = 0;
6514 struct ia_css_pipeline_stage *vf_pp_stage = NULL,
6515 *copy_stage = NULL,
6516 *yuv_scaler_stage = NULL;
6517 struct ia_css_binary *copy_binary,
6518 *vf_pp_binary,
6519 *yuv_scaler_binary;
6520 bool need_scaler = false;
6521 unsigned int num_stage, num_output_stage;
6522 unsigned int i, j;
6523
6524 struct ia_css_frame *in_frame = NULL;
6525 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6526 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
6527 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6528 struct ia_css_pipeline_stage_desc stage_desc;
6529 bool need_in_frameinfo_memory = false;
6530 bool sensor = false;
6531 bool buffered_sensor = false;
6532 bool online = false;
6533 bool continuous = false;
6534
6535 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6536 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
6537 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6538 return -EINVAL;
6539 }
6540 me = &pipe->pipeline;
6541 ia_css_pipeline_clean(me);
6542 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6543 out_frame[i] = NULL;
6544 vf_frame[i] = NULL;
6545 }
6546 ia_css_pipe_util_create_output_frames(bin_out_frame);
6547 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler;
6548 num_output_stage = pipe->pipe_settings.yuvpp.num_output;
6549
6550 if (IS_ISP2401) {
6551 /*
6552 * When the input system is 2401, always enable 'in_frameinfo_memory'
6553 * except for the following:
6554 * - Direct Sensor Mode Online Capture
6555 * - Direct Sensor Mode Continuous Capture
6556 * - Buffered Sensor Mode Continuous Capture
6557 */
6558 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6559 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
6560 online = pipe->stream->config.online;
6561 continuous = pipe->stream->config.continuous;
6562 need_in_frameinfo_memory =
6563 !((sensor && (online || continuous)) || (buffered_sensor && continuous));
6564 } else {
6565 /* Construct in_frame info (only in case we have dynamic input */
6566 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
6567 }
6568 /*
6569 * the input frame can come from:
6570 *
6571 * a) memory: connect yuvscaler to me->in_frame
6572 * b) sensor, via copy binary: connect yuvscaler to copy binary later
6573 * on
6574 */
6575 if (need_in_frameinfo_memory) {
6576 /* TODO: improve for different input formats. */
6577
6578 /*
6579 * "pipe->stream->config.input_config.format" represents the sensor output
6580 * frame format, e.g. YUV422 8-bit.
6581 *
6582 * "in_frame_format" represents the imaging pipe's input frame format, e.g.
6583 * Bayer-Quad RAW.
6584 */
6585 int in_frame_format;
6586
6587 if (pipe->stream->config.input_config.format ==
6588 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
6589 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
6590 } else if (pipe->stream->config.input_config.format ==
6591 ATOMISP_INPUT_FORMAT_YUV422_8) {
6592 /*
6593 * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8",
6594 * the "isp_copy_var" binary is selected as the first stage in the yuvpp
6595 * pipe.
6596 *
6597 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from
6598 * the frame buffer (at DDR) to the frame-line buffer (at VMEM).
6599 *
6600 * By now, the "isp_copy_var" binary does NOT provide a separated
6601 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores
6602 * the YUV422-8 pixels in the frame-line buffer which is designed to
6603 * store the Bayer-Quad RAW pixels.
6604 *
6605 * To direct the "isp_copy_var" binary reading from the RAW frame-line
6606 * buffer, its input frame format must be specified as "IA_CSS_FRAME_
6607 * FORMAT_RAW".
6608 */
6609 in_frame_format = IA_CSS_FRAME_FORMAT_RAW;
6610 } else {
6611 in_frame_format = IA_CSS_FRAME_FORMAT_NV12;
6612 }
6613
6614 err = init_in_frameinfo_memory_defaults(pipe,
6615 &me->in_frame,
6616 in_frame_format);
6617
6618 if (err) {
6619 IA_CSS_LEAVE_ERR_PRIVATE(err);
6620 return err;
6621 }
6622
6623 in_frame = &me->in_frame;
6624 } else {
6625 in_frame = NULL;
6626 }
6627
6628 for (i = 0; i < num_output_stage; i++) {
6629 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
6630 if (pipe->output_info[i].res.width != 0) {
6631 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
6632 if (err) {
6633 IA_CSS_LEAVE_ERR_PRIVATE(err);
6634 return err;
6635 }
6636 out_frame[i] = &me->out_frame[i];
6637 }
6638
6639 /* Construct vf_frame info (only in case we have VF) */
6640 if (pipe->vf_output_info[i].res.width != 0) {
6641 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i);
6642 if (err) {
6643 IA_CSS_LEAVE_ERR_PRIVATE(err);
6644 return err;
6645 }
6646 vf_frame[i] = &me->vf_frame[i];
6647 }
6648 }
6649
6650 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
6651 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary;
6652 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
6653 need_scaler = need_yuv_scaler_stage(pipe);
6654
6655 if (pipe->pipe_settings.yuvpp.copy_binary.info) {
6656 struct ia_css_frame *in_frame_local = NULL;
6657
6658 if (IS_ISP2401 && !online) {
6659 /* After isp copy is enabled in_frame needs to be passed. */
6660 in_frame_local = in_frame;
6661 }
6662
6663 if (need_scaler) {
6664 ia_css_pipe_util_set_output_frames(bin_out_frame,
6665 0, NULL);
6666 ia_css_pipe_get_generic_stage_desc(&stage_desc,
6667 copy_binary,
6668 bin_out_frame,
6669 in_frame_local,
6670 NULL);
6671 } else {
6672 ia_css_pipe_util_set_output_frames(bin_out_frame,
6673 0, out_frame[0]);
6674 ia_css_pipe_get_generic_stage_desc(&stage_desc,
6675 copy_binary,
6676 bin_out_frame,
6677 in_frame_local,
6678 NULL);
6679 }
6680
6681 err = ia_css_pipeline_create_and_add_stage(me,
6682 &stage_desc,
6683 ©_stage);
6684
6685 if (err) {
6686 IA_CSS_LEAVE_ERR_PRIVATE(err);
6687 return err;
6688 }
6689
6690 if (copy_stage) {
6691 /* if we use yuv scaler binary, vf output should be from there */
6692 copy_stage->args.copy_vf = !need_scaler;
6693 /* for yuvpp pipe, it should always be enabled */
6694 copy_stage->args.copy_output = true;
6695 /* connect output of copy binary to input of yuv scaler */
6696 in_frame = copy_stage->args.out_frame[0];
6697 }
6698 }
6699
6700 if (need_scaler) {
6701 struct ia_css_frame *tmp_out_frame = NULL;
6702 struct ia_css_frame *tmp_vf_frame = NULL;
6703 struct ia_css_frame *tmp_in_frame = in_frame;
6704
6705 for (i = 0, j = 0; i < num_stage; i++) {
6706 assert(j < num_output_stage);
6707 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
6708 tmp_out_frame = out_frame[j];
6709 tmp_vf_frame = vf_frame[j];
6710 } else {
6711 tmp_out_frame = NULL;
6712 tmp_vf_frame = NULL;
6713 }
6714
6715 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
6716 tmp_out_frame,
6717 NULL,
6718 &yuv_scaler_binary[i],
6719 &yuv_scaler_stage);
6720
6721 if (err) {
6722 IA_CSS_LEAVE_ERR_PRIVATE(err);
6723 return err;
6724 }
6725 /* we use output port 1 as internal output port */
6726 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
6727 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
6728 if (tmp_vf_frame && (tmp_vf_frame->frame_info.res.width != 0)) {
6729 in_frame = yuv_scaler_stage->args.out_vf_frame;
6730 err = add_vf_pp_stage(pipe, in_frame,
6731 tmp_vf_frame,
6732 &vf_pp_binary[j],
6733 &vf_pp_stage);
6734
6735 if (err) {
6736 IA_CSS_LEAVE_ERR_PRIVATE(err);
6737 return err;
6738 }
6739 }
6740 j++;
6741 }
6742 }
6743 } else if (copy_stage) {
6744 if (vf_frame[0] && vf_frame[0]->frame_info.res.width != 0) {
6745 in_frame = copy_stage->args.out_vf_frame;
6746 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0],
6747 &vf_pp_binary[0], &vf_pp_stage);
6748 }
6749 if (err) {
6750 IA_CSS_LEAVE_ERR_PRIVATE(err);
6751 return err;
6752 }
6753 }
6754
6755 ia_css_pipeline_finalize_stages(&pipe->pipeline,
6756 pipe->stream->config.continuous);
6757
6758 IA_CSS_LEAVE_ERR_PRIVATE(0);
6759
6760 return 0;
6761 }
6762
6763 static int
create_host_copy_pipeline(struct ia_css_pipe * pipe,unsigned int max_input_width,struct ia_css_frame * out_frame)6764 create_host_copy_pipeline(struct ia_css_pipe *pipe,
6765 unsigned int max_input_width,
6766 struct ia_css_frame *out_frame)
6767 {
6768 struct ia_css_pipeline *me;
6769 int err = 0;
6770 struct ia_css_pipeline_stage_desc stage_desc;
6771
6772 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6773 "create_host_copy_pipeline() enter:\n");
6774
6775 /* pipeline already created as part of create_host_pipeline_structure */
6776 me = &pipe->pipeline;
6777 ia_css_pipeline_clean(me);
6778
6779 /* Construct out_frame info */
6780 if (copy_on_sp(pipe) &&
6781 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
6782 ia_css_frame_info_init(&out_frame->frame_info, JPEG_BYTES, 1,
6783 IA_CSS_FRAME_FORMAT_BINARY_8, 0);
6784 } else if (out_frame->frame_info.format == IA_CSS_FRAME_FORMAT_RAW) {
6785 out_frame->frame_info.raw_bit_depth =
6786 ia_css_pipe_util_pipe_input_format_bpp(pipe);
6787 }
6788
6789 me->num_stages = 1;
6790 me->pipe_id = IA_CSS_PIPE_ID_COPY;
6791 pipe->mode = IA_CSS_PIPE_ID_COPY;
6792
6793 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
6794 IA_CSS_PIPELINE_RAW_COPY,
6795 max_input_width);
6796 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, NULL);
6797
6798 ia_css_pipeline_finalize_stages(&pipe->pipeline,
6799 pipe->stream->config.continuous);
6800
6801 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6802 "create_host_copy_pipeline() leave:\n");
6803
6804 return err;
6805 }
6806
6807 static int
create_host_isyscopy_capture_pipeline(struct ia_css_pipe * pipe)6808 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe)
6809 {
6810 struct ia_css_pipeline *me = &pipe->pipeline;
6811 int err = 0;
6812 struct ia_css_pipeline_stage_desc stage_desc;
6813 struct ia_css_frame *out_frame = &me->out_frame[0];
6814 struct ia_css_pipeline_stage *out_stage = NULL;
6815 unsigned int thread_id;
6816 enum sh_css_queue_id queue_id;
6817 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS;
6818
6819 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6820 "create_host_isyscopy_capture_pipeline() enter:\n");
6821 ia_css_pipeline_clean(me);
6822
6823 /* Construct out_frame info */
6824 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->frame_info, 0);
6825 if (err)
6826 return err;
6827 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
6828 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id);
6829 out_frame->dynamic_queue_id = queue_id;
6830 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
6831
6832 me->num_stages = 1;
6833 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
6834 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
6835 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
6836 IA_CSS_PIPELINE_ISYS_COPY,
6837 max_input_width);
6838 err = ia_css_pipeline_create_and_add_stage(me,
6839 &stage_desc, &out_stage);
6840 if (err)
6841 return err;
6842
6843 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous);
6844
6845 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6846 "create_host_isyscopy_capture_pipeline() leave:\n");
6847
6848 return err;
6849 }
6850
6851 static int
create_host_regular_capture_pipeline(struct ia_css_pipe * pipe)6852 create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
6853 {
6854 struct ia_css_pipeline *me;
6855 int err = 0;
6856 enum ia_css_capture_mode mode;
6857 struct ia_css_pipeline_stage *current_stage = NULL;
6858 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
6859 struct ia_css_binary *copy_binary,
6860 *primary_binary[MAX_NUM_PRIMARY_STAGES],
6861 *vf_pp_binary,
6862 *pre_isp_binary,
6863 *anr_gdc_binary,
6864 *post_isp_binary,
6865 *yuv_scaler_binary,
6866 *capture_pp_binary,
6867 *capture_ldc_binary;
6868 bool need_pp = false;
6869 bool raw;
6870
6871 struct ia_css_frame *in_frame;
6872 struct ia_css_frame *out_frame;
6873 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
6874 struct ia_css_frame *vf_frame;
6875 struct ia_css_pipeline_stage_desc stage_desc;
6876 bool need_in_frameinfo_memory = false;
6877 bool sensor = false;
6878 bool buffered_sensor = false;
6879 bool online = false;
6880 bool continuous = false;
6881 unsigned int i, num_yuv_scaler, num_primary_stage;
6882 bool need_yuv_pp = false;
6883 bool *is_output_stage = NULL;
6884 bool need_ldc = false;
6885
6886 IA_CSS_ENTER_PRIVATE("");
6887 assert(pipe);
6888 assert(pipe->stream);
6889 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6890 pipe->mode == IA_CSS_PIPE_ID_COPY);
6891
6892 me = &pipe->pipeline;
6893 mode = pipe->config.default_capture_config.mode;
6894 raw = (mode == IA_CSS_CAPTURE_MODE_RAW);
6895 ia_css_pipeline_clean(me);
6896 ia_css_pipe_util_create_output_frames(out_frames);
6897
6898 if (IS_ISP2401) {
6899 /*
6900 * When the input system is 2401, always enable 'in_frameinfo_memory'
6901 * except for the following:
6902 * - Direct Sensor Mode Online Capture
6903 * - Direct Sensor Mode Online Capture
6904 * - Direct Sensor Mode Continuous Capture
6905 * - Buffered Sensor Mode Continuous Capture
6906 */
6907 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
6908 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
6909 online = pipe->stream->config.online;
6910 continuous = pipe->stream->config.continuous;
6911 need_in_frameinfo_memory =
6912 !((sensor && (online || continuous)) || (buffered_sensor &&
6913 (online || continuous)));
6914 } else {
6915 /* Construct in_frame info (only in case we have dynamic input */
6916 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
6917 }
6918
6919 if (need_in_frameinfo_memory) {
6920 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
6921 IA_CSS_FRAME_FORMAT_RAW);
6922 if (err) {
6923 IA_CSS_LEAVE_ERR_PRIVATE(err);
6924 return err;
6925 }
6926
6927 in_frame = &me->in_frame;
6928 } else {
6929 in_frame = NULL;
6930 }
6931
6932 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
6933 if (err) {
6934 IA_CSS_LEAVE_ERR_PRIVATE(err);
6935 return err;
6936 }
6937 out_frame = &me->out_frame[0];
6938
6939 /* Construct vf_frame info (only in case we have VF) */
6940 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6941 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
6942 /* These modes don't support viewfinder output */
6943 vf_frame = NULL;
6944 } else {
6945 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
6946 vf_frame = &me->vf_frame[0];
6947 }
6948 } else {
6949 vf_frame = NULL;
6950 }
6951
6952 copy_binary = &pipe->pipe_settings.capture.copy_binary;
6953 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
6954 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) {
6955 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6956 return -EINVAL;
6957 }
6958
6959 for (i = 0; i < num_primary_stage; i++)
6960 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
6961
6962 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary;
6963 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary;
6964 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary;
6965 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary;
6966 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary;
6967 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary;
6968 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler;
6969 is_output_stage = pipe->pipe_settings.capture.is_output_stage;
6970 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary;
6971
6972 need_pp = (need_capture_pp(pipe) || pipe->output_stage) &&
6973 mode != IA_CSS_CAPTURE_MODE_RAW &&
6974 mode != IA_CSS_CAPTURE_MODE_BAYER;
6975 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
6976 need_ldc = (capture_ldc_binary && capture_ldc_binary->info);
6977
6978 if (pipe->pipe_settings.capture.copy_binary.info) {
6979 if (raw) {
6980 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
6981 if (IS_ISP2401) {
6982 if (!continuous) {
6983 ia_css_pipe_get_generic_stage_desc(&stage_desc,
6984 copy_binary,
6985 out_frames,
6986 in_frame,
6987 NULL);
6988 } else {
6989 in_frame = pipe->stream->last_pipe->continuous_frames[0];
6990 ia_css_pipe_get_generic_stage_desc(&stage_desc,
6991 copy_binary,
6992 out_frames,
6993 in_frame,
6994 NULL);
6995 }
6996 } else {
6997 ia_css_pipe_get_generic_stage_desc(&stage_desc,
6998 copy_binary,
6999 out_frames,
7000 NULL, NULL);
7001 }
7002 } else {
7003 ia_css_pipe_util_set_output_frames(out_frames, 0,
7004 in_frame);
7005 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7006 copy_binary,
7007 out_frames,
7008 NULL, NULL);
7009 }
7010
7011 err = ia_css_pipeline_create_and_add_stage(me,
7012 &stage_desc,
7013 ¤t_stage);
7014 if (err) {
7015 IA_CSS_LEAVE_ERR_PRIVATE(err);
7016 return err;
7017 }
7018 } else if (pipe->stream->config.continuous) {
7019 in_frame = pipe->stream->last_pipe->continuous_frames[0];
7020 }
7021
7022 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
7023 struct ia_css_frame *local_in_frame = NULL;
7024 struct ia_css_frame *local_out_frame = NULL;
7025
7026 for (i = 0; i < num_primary_stage; i++) {
7027 if (i == 0)
7028 local_in_frame = in_frame;
7029 else
7030 local_in_frame = NULL;
7031 if (!need_pp && (i == num_primary_stage - 1) && (!IS_ISP2401 || !need_ldc))
7032 local_out_frame = out_frame;
7033 else
7034 local_out_frame = NULL;
7035 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame);
7036 /*
7037 * WARNING: The #if def flag has been added below as a
7038 * temporary solution to solve the problem of enabling the
7039 * view finder in a single binary in a capture flow. The
7040 * vf-pp stage has been removed from Skycam in the solution
7041 * provided. The vf-pp stage should be re-introduced when
7042 * required. This * should not be considered as a clean solution.
7043 * Proper investigation should be done to come up with the clean
7044 * solution.
7045 */
7046 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7047 primary_binary[i],
7048 out_frames,
7049 local_in_frame,
7050 NULL);
7051 err = ia_css_pipeline_create_and_add_stage(me,
7052 &stage_desc,
7053 ¤t_stage);
7054 if (err) {
7055 IA_CSS_LEAVE_ERR_PRIVATE(err);
7056 return err;
7057 }
7058 }
7059 /* If we use copy iso primary, the input must be yuv iso raw */
7060 current_stage->args.copy_vf =
7061 primary_binary[0]->info->sp.pipeline.mode ==
7062 IA_CSS_BINARY_MODE_COPY;
7063 current_stage->args.copy_output = current_stage->args.copy_vf;
7064 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
7065 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
7066 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7067 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
7068 out_frames, in_frame, NULL);
7069 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7070 NULL);
7071 if (err) {
7072 IA_CSS_LEAVE_ERR_PRIVATE(err);
7073 return err;
7074 }
7075 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7076 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
7077 out_frames, NULL, NULL);
7078 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7079 NULL);
7080 if (err) {
7081 IA_CSS_LEAVE_ERR_PRIVATE(err);
7082 return err;
7083 }
7084
7085 if (need_pp) {
7086 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7087 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7088 post_isp_binary,
7089 out_frames,
7090 NULL, NULL);
7091 } else {
7092 ia_css_pipe_util_set_output_frames(out_frames, 0,
7093 out_frame);
7094 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7095 post_isp_binary,
7096 out_frames,
7097 NULL, NULL);
7098 }
7099
7100 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7101 ¤t_stage);
7102 if (err) {
7103 IA_CSS_LEAVE_ERR_PRIVATE(err);
7104 return err;
7105 }
7106 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) {
7107 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
7108 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
7109 out_frames, in_frame, NULL);
7110 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7111 NULL);
7112 if (err) {
7113 IA_CSS_LEAVE_ERR_PRIVATE(err);
7114 return err;
7115 }
7116 }
7117
7118 if (need_pp && current_stage) {
7119 struct ia_css_frame *local_in_frame = NULL;
7120
7121 local_in_frame = current_stage->args.out_frame[0];
7122
7123 if (need_ldc) {
7124 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7125 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7126 capture_ldc_binary,
7127 out_frames,
7128 local_in_frame,
7129 NULL);
7130 err = ia_css_pipeline_create_and_add_stage(me,
7131 &stage_desc,
7132 ¤t_stage);
7133 local_in_frame = current_stage->args.out_frame[0];
7134 }
7135 err = add_capture_pp_stage(pipe, me, local_in_frame,
7136 need_yuv_pp ? NULL : out_frame,
7137 capture_pp_binary,
7138 ¤t_stage);
7139 if (err) {
7140 IA_CSS_LEAVE_ERR_PRIVATE(err);
7141 return err;
7142 }
7143 }
7144
7145 if (need_yuv_pp && current_stage) {
7146 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
7147 struct ia_css_frame *tmp_out_frame = NULL;
7148
7149 for (i = 0; i < num_yuv_scaler; i++) {
7150 if (is_output_stage[i])
7151 tmp_out_frame = out_frame;
7152 else
7153 tmp_out_frame = NULL;
7154
7155 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
7156 tmp_out_frame, NULL,
7157 &yuv_scaler_binary[i],
7158 &yuv_scaler_stage);
7159 if (err) {
7160 IA_CSS_LEAVE_ERR_PRIVATE(err);
7161 return err;
7162 }
7163 /* we use output port 1 as internal output port */
7164 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7165 }
7166 }
7167
7168 /*
7169 * WARNING: The #if def flag has been added below as a
7170 * temporary solution to solve the problem of enabling the
7171 * view finder in a single binary in a capture flow. The vf-pp
7172 * stage has been removed from Skycam in the solution provided.
7173 * The vf-pp stage should be re-introduced when required. This
7174 * should not be considered as a clean solution. Proper
7175 * investigation should be done to come up with the clean solution.
7176 */
7177 if (mode != IA_CSS_CAPTURE_MODE_RAW &&
7178 mode != IA_CSS_CAPTURE_MODE_BAYER &&
7179 current_stage && vf_frame) {
7180 in_frame = current_stage->args.out_vf_frame;
7181 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
7182 ¤t_stage);
7183 if (err) {
7184 IA_CSS_LEAVE_ERR_PRIVATE(err);
7185 return err;
7186 }
7187 }
7188 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7189
7190 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7191 "create_host_regular_capture_pipeline() leave:\n");
7192
7193 return 0;
7194 }
7195
7196 static int
create_host_capture_pipeline(struct ia_css_pipe * pipe)7197 create_host_capture_pipeline(struct ia_css_pipe *pipe)
7198 {
7199 int err = 0;
7200
7201 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7202
7203 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7204 err = create_host_isyscopy_capture_pipeline(pipe);
7205 else
7206 err = create_host_regular_capture_pipeline(pipe);
7207 if (err) {
7208 IA_CSS_LEAVE_ERR_PRIVATE(err);
7209 return err;
7210 }
7211
7212 IA_CSS_LEAVE_ERR_PRIVATE(err);
7213
7214 return err;
7215 }
7216
capture_start(struct ia_css_pipe * pipe)7217 static int capture_start(struct ia_css_pipe *pipe)
7218 {
7219 struct ia_css_pipeline *me;
7220 unsigned int thread_id;
7221
7222 int err = 0;
7223 enum sh_css_pipe_config_override copy_ovrd;
7224
7225 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7226 if (!pipe) {
7227 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7228 return -EINVAL;
7229 }
7230
7231 me = &pipe->pipeline;
7232
7233 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
7234 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) &&
7235 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
7236 if (copy_on_sp(pipe)) {
7237 err = start_copy_on_sp(pipe, &me->out_frame[0]);
7238 IA_CSS_LEAVE_ERR_PRIVATE(err);
7239 return err;
7240 }
7241 }
7242 /* old isys: need to send_mipi_frames() in all pipe modes */
7243 if (!IS_ISP2401 || pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
7244 err = send_mipi_frames(pipe);
7245 if (err) {
7246 IA_CSS_LEAVE_ERR_PRIVATE(err);
7247 return err;
7248 }
7249 }
7250
7251 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7252 copy_ovrd = 1 << thread_id;
7253
7254 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode);
7255
7256 /*
7257 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured,
7258 * which is currently done in start_binary(); but COPY pipe contains no binary,
7259 * and does not call start_binary(); so we need to configure the rx here.
7260 */
7261 if (!IS_ISP2401 &&
7262 pipe->config.mode == IA_CSS_PIPE_MODE_COPY &&
7263 pipe->stream->reconfigure_css_rx) {
7264 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
7265 pipe->stream->config.mode);
7266 pipe->stream->reconfigure_css_rx = false;
7267 }
7268
7269 IA_CSS_LEAVE_ERR_PRIVATE(err);
7270 return err;
7271 }
7272
7273 static int
sh_css_pipe_get_output_frame_info(struct ia_css_pipe * pipe,struct ia_css_frame_info * info,unsigned int idx)7274 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
7275 struct ia_css_frame_info *info,
7276 unsigned int idx)
7277 {
7278 assert(pipe);
7279 assert(info);
7280
7281 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7282 "sh_css_pipe_get_output_frame_info() enter:\n");
7283
7284 *info = pipe->output_info[idx];
7285 if (copy_on_sp(pipe) &&
7286 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
7287 ia_css_frame_info_init(
7288 info,
7289 JPEG_BYTES,
7290 1,
7291 IA_CSS_FRAME_FORMAT_BINARY_8,
7292 0);
7293 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
7294 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) {
7295 info->raw_bit_depth =
7296 ia_css_pipe_util_pipe_input_format_bpp(pipe);
7297 }
7298
7299 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7300 "sh_css_pipe_get_output_frame_info() leave:\n");
7301 return 0;
7302 }
7303
7304 void
ia_css_stream_send_input_frame(const struct ia_css_stream * stream,const unsigned short * data,unsigned int width,unsigned int height)7305 ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
7306 const unsigned short *data,
7307 unsigned int width,
7308 unsigned int height)
7309 {
7310 assert(stream);
7311
7312 ia_css_inputfifo_send_input_frame(
7313 data, width, height,
7314 stream->config.channel_id,
7315 stream->config.input_config.format,
7316 stream->config.pixels_per_clock == 2);
7317 }
7318
7319 void
ia_css_stream_start_input_frame(const struct ia_css_stream * stream)7320 ia_css_stream_start_input_frame(const struct ia_css_stream *stream)
7321 {
7322 assert(stream);
7323
7324 ia_css_inputfifo_start_frame(
7325 stream->config.channel_id,
7326 stream->config.input_config.format,
7327 stream->config.pixels_per_clock == 2);
7328 }
7329
7330 void
ia_css_stream_send_input_line(const struct ia_css_stream * stream,const unsigned short * data,unsigned int width,const unsigned short * data2,unsigned int width2)7331 ia_css_stream_send_input_line(const struct ia_css_stream *stream,
7332 const unsigned short *data,
7333 unsigned int width,
7334 const unsigned short *data2,
7335 unsigned int width2)
7336 {
7337 assert(stream);
7338
7339 ia_css_inputfifo_send_line(stream->config.channel_id,
7340 data, width, data2, width2);
7341 }
7342
7343 void
ia_css_stream_send_input_embedded_line(const struct ia_css_stream * stream,enum atomisp_input_format format,const unsigned short * data,unsigned int width)7344 ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
7345 enum atomisp_input_format format,
7346 const unsigned short *data,
7347 unsigned int width)
7348 {
7349 assert(stream);
7350 if (!data || width == 0)
7351 return;
7352 ia_css_inputfifo_send_embedded_line(stream->config.channel_id,
7353 format, data, width);
7354 }
7355
7356 void
ia_css_stream_end_input_frame(const struct ia_css_stream * stream)7357 ia_css_stream_end_input_frame(const struct ia_css_stream *stream)
7358 {
7359 assert(stream);
7360
7361 ia_css_inputfifo_end_frame(stream->config.channel_id);
7362 }
7363
7364 bool
ia_css_pipeline_uses_params(struct ia_css_pipeline * me)7365 ia_css_pipeline_uses_params(struct ia_css_pipeline *me)
7366 {
7367 struct ia_css_pipeline_stage *stage;
7368
7369 assert(me);
7370
7371 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7372 "ia_css_pipeline_uses_params() enter: me=%p\n", me);
7373
7374 for (stage = me->stages; stage; stage = stage->next)
7375 if (stage->binary_info && stage->binary_info->enable.params) {
7376 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7377 "ia_css_pipeline_uses_params() leave: return_bool=true\n");
7378 return true;
7379 }
7380 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7381 "ia_css_pipeline_uses_params() leave: return_bool=false\n");
7382 return false;
7383 }
7384
7385 /*
7386 * @brief Tag a specific frame in continuous capture.
7387 * Refer to "sh_css_internal.h" for details.
7388 */
ia_css_stream_capture_frame(struct ia_css_stream * stream,unsigned int exp_id)7389 int ia_css_stream_capture_frame(struct ia_css_stream *stream,
7390 unsigned int exp_id)
7391 {
7392 struct sh_css_tag_descr tag_descr;
7393 u32 encoded_tag_descr;
7394 int err;
7395
7396 assert(stream);
7397 IA_CSS_ENTER("exp_id=%d", exp_id);
7398
7399 /* Only continuous streams have a tagger */
7400 if (exp_id == 0 || !stream->config.continuous) {
7401 IA_CSS_LEAVE_ERR(-EINVAL);
7402 return -EINVAL;
7403 }
7404
7405 if (!sh_css_sp_is_running()) {
7406 /* SP is not running. The queues are not valid */
7407 IA_CSS_LEAVE_ERR(-EBUSY);
7408 return -EBUSY;
7409 }
7410
7411 /* Create the tag descriptor from the parameters */
7412 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr);
7413 /* Encode the tag descriptor into a 32-bit value */
7414 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
7415 /*
7416 * Enqueue the encoded tag to the host2sp queue.
7417 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
7418 * on both host and the SP side.
7419 * It is mainly because it is enough to have only one tag_cmd queue
7420 */
7421 err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr);
7422
7423 IA_CSS_LEAVE_ERR(err);
7424 return err;
7425 }
7426
7427 /*
7428 * @brief Configure the continuous capture.
7429 * Refer to "sh_css_internal.h" for details.
7430 */
ia_css_stream_capture(struct ia_css_stream * stream,int num_captures,unsigned int skip,int offset)7431 int ia_css_stream_capture(struct ia_css_stream *stream, int num_captures,
7432 unsigned int skip, int offset)
7433 {
7434 struct sh_css_tag_descr tag_descr;
7435 unsigned int encoded_tag_descr;
7436 int return_err;
7437
7438 if (!stream)
7439 return -EINVAL;
7440
7441 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7442 "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n",
7443 num_captures, skip, offset);
7444
7445 /* Check if the tag descriptor is valid */
7446 if (num_captures < SH_CSS_MINIMUM_TAG_ID) {
7447 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7448 "ia_css_stream_capture() leave: return_err=%d\n",
7449 -EINVAL);
7450 return -EINVAL;
7451 }
7452
7453 /* Create the tag descriptor from the parameters */
7454 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr);
7455
7456 /* Encode the tag descriptor into a 32-bit value */
7457 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
7458
7459 if (!sh_css_sp_is_running()) {
7460 /* SP is not running. The queues are not valid */
7461 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7462 "ia_css_stream_capture() leaving:queues unavailable\n");
7463 return -EBUSY;
7464 }
7465
7466 /*
7467 * Enqueue the encoded tag to the host2sp queue.
7468 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
7469 * on both host and the SP side.
7470 * It is mainly because it is enough to have only one tag_cmd queue
7471 */
7472 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr);
7473
7474 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7475 "ia_css_stream_capture() leave: return_err=%d\n",
7476 return_err);
7477
7478 return return_err;
7479 }
7480
7481 static void
sh_css_init_host_sp_control_vars(void)7482 sh_css_init_host_sp_control_vars(void)
7483 {
7484 const struct ia_css_fw_info *fw;
7485 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
7486
7487 unsigned int HIVE_ADDR_host_sp_queues_initialized;
7488 unsigned int HIVE_ADDR_sp_sleep_mode;
7489 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
7490 unsigned int HIVE_ADDR_sp_stop_copy_preview;
7491 unsigned int HIVE_ADDR_host_sp_com;
7492 unsigned int o = offsetof(struct host_sp_communication, host2sp_command)
7493 / sizeof(int);
7494
7495 unsigned int i;
7496
7497 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7498 "sh_css_init_host_sp_control_vars() enter: void\n");
7499
7500 fw = &sh_css_sp_fw;
7501 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
7502
7503 HIVE_ADDR_host_sp_queues_initialized =
7504 fw->info.sp.host_sp_queues_initialized;
7505 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode;
7506 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb;
7507 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview;
7508 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
7509
7510 sp_dmem_store_uint32(SP0_ID,
7511 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
7512 (uint32_t)(0));
7513
7514 sp_dmem_store_uint32(SP0_ID,
7515 (unsigned int)sp_address_of(host_sp_queues_initialized),
7516 (uint32_t)(0));
7517 sp_dmem_store_uint32(SP0_ID,
7518 (unsigned int)sp_address_of(sp_sleep_mode),
7519 (uint32_t)(0));
7520 sp_dmem_store_uint32(SP0_ID,
7521 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
7522 (uint32_t)(false));
7523 sp_dmem_store_uint32(SP0_ID,
7524 (unsigned int)sp_address_of(sp_stop_copy_preview),
7525 my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0));
7526 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
7527
7528 for (i = 0; i < N_CSI_PORTS; i++) {
7529 sh_css_update_host2sp_num_mipi_frames
7530 (my_css.num_mipi_frames[i]);
7531 }
7532
7533 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7534 "sh_css_init_host_sp_control_vars() leave: return_void\n");
7535 }
7536
7537 /*
7538 * create the internal structures and fill in the configuration data
7539 */
7540
7541 static const struct
7542 ia_css_pipe_config ia_css_pipe_default_config = DEFAULT_PIPE_CONFIG;
7543
ia_css_pipe_config_defaults(struct ia_css_pipe_config * pipe_config)7544 void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config)
7545 {
7546 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n");
7547 memcpy(pipe_config, &ia_css_pipe_default_config, sizeof(*pipe_config));
7548 }
7549
7550 void
ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config * extra_config)7551 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config *extra_config)
7552 {
7553 if (!extra_config) {
7554 IA_CSS_ERROR("NULL input parameter");
7555 return;
7556 }
7557
7558 extra_config->enable_raw_binning = false;
7559 extra_config->enable_yuv_ds = false;
7560 extra_config->enable_high_speed = false;
7561 extra_config->enable_dvs_6axis = false;
7562 extra_config->enable_reduced_pipe = false;
7563 extra_config->disable_vf_pp = false;
7564 extra_config->enable_fractional_ds = false;
7565 }
7566
ia_css_stream_config_defaults(struct ia_css_stream_config * stream_config)7567 void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config)
7568 {
7569 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n");
7570 assert(stream_config);
7571 memset(stream_config, 0, sizeof(*stream_config));
7572 stream_config->online = true;
7573 stream_config->left_padding = -1;
7574 stream_config->pixels_per_clock = 1;
7575 /*
7576 * temporary default value for backwards compatibility.
7577 * This field used to be hardcoded within CSS but this has now
7578 * been moved to the stream_config struct.
7579 */
7580 stream_config->source.port.rxcount = 0x04040404;
7581 }
7582
ia_css_pipe_create(const struct ia_css_pipe_config * config,struct ia_css_pipe ** pipe)7583 int ia_css_pipe_create(const struct ia_css_pipe_config *config,
7584 struct ia_css_pipe **pipe)
7585 {
7586 int err = 0;
7587
7588 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe);
7589
7590 if (!config || !pipe) {
7591 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7592 return -EINVAL;
7593 }
7594
7595 err = ia_css_pipe_create_extra(config, NULL, pipe);
7596
7597 if (err == 0)
7598 IA_CSS_LOG("pipe created successfully = %p", *pipe);
7599
7600 IA_CSS_LEAVE_ERR_PRIVATE(err);
7601
7602 return err;
7603 }
7604
7605 int
ia_css_pipe_create_extra(const struct ia_css_pipe_config * config,const struct ia_css_pipe_extra_config * extra_config,struct ia_css_pipe ** pipe)7606 ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
7607 const struct ia_css_pipe_extra_config *extra_config,
7608 struct ia_css_pipe **pipe)
7609 {
7610 int err = -EINVAL;
7611 struct ia_css_pipe *internal_pipe = NULL;
7612 unsigned int i;
7613
7614 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
7615
7616 /* do not allow to create more than the maximum limit */
7617 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) {
7618 IA_CSS_LEAVE_ERR_PRIVATE(-ENOSPC);
7619 return -EINVAL;
7620 }
7621
7622 if ((!pipe) || (!config)) {
7623 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7624 return -EINVAL;
7625 }
7626
7627 ia_css_debug_dump_pipe_config(config);
7628 ia_css_debug_dump_pipe_extra_config(extra_config);
7629
7630 err = create_pipe(config->mode, &internal_pipe, false);
7631 if (err) {
7632 IA_CSS_LEAVE_ERR_PRIVATE(err);
7633 return err;
7634 }
7635
7636 /* now we have a pipe structure to fill */
7637 internal_pipe->config = *config;
7638 if (extra_config)
7639 internal_pipe->extra_config = *extra_config;
7640 else
7641 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
7642
7643 /*
7644 * Use config value when dvs_frame_delay setting equal to 2,
7645 * otherwise always 1 by default
7646 */
7647 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2)
7648 internal_pipe->dvs_frame_delay = 2;
7649 else
7650 internal_pipe->dvs_frame_delay = 1;
7651
7652 /*
7653 * we still keep enable_raw_binning for backward compatibility,
7654 * for any new fractional bayer downscaling, we should use
7655 * bayer_ds_out_res. if both are specified, bayer_ds_out_res will
7656 * take precedence.if none is specified, we set bayer_ds_out_res
7657 * equal to IF output resolution(IF may do cropping on sensor output)
7658 * or use default decimation factor 1.
7659 */
7660
7661 /* YUV downscaling */
7662 if ((internal_pipe->config.vf_pp_in_res.width ||
7663 internal_pipe->config.capt_pp_in_res.width)) {
7664 enum ia_css_frame_format format;
7665
7666 if (internal_pipe->config.vf_pp_in_res.width) {
7667 format = IA_CSS_FRAME_FORMAT_YUV_LINE;
7668 ia_css_frame_info_init(
7669 &internal_pipe->vf_yuv_ds_input_info,
7670 internal_pipe->config.vf_pp_in_res.width,
7671 internal_pipe->config.vf_pp_in_res.height,
7672 format, 0);
7673 }
7674 if (internal_pipe->config.capt_pp_in_res.width) {
7675 format = IA_CSS_FRAME_FORMAT_YUV420;
7676 ia_css_frame_info_init(
7677 &internal_pipe->out_yuv_ds_input_info,
7678 internal_pipe->config.capt_pp_in_res.width,
7679 internal_pipe->config.capt_pp_in_res.height,
7680 format, 0);
7681 }
7682 }
7683 if (internal_pipe->config.vf_pp_in_res.width &&
7684 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
7685 ia_css_frame_info_init(
7686 &internal_pipe->vf_yuv_ds_input_info,
7687 internal_pipe->config.vf_pp_in_res.width,
7688 internal_pipe->config.vf_pp_in_res.height,
7689 IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
7690 }
7691 /* handle bayer downscaling output info */
7692 if (internal_pipe->config.bayer_ds_out_res.width) {
7693 ia_css_frame_info_init(
7694 &internal_pipe->bds_output_info,
7695 internal_pipe->config.bayer_ds_out_res.width,
7696 internal_pipe->config.bayer_ds_out_res.height,
7697 IA_CSS_FRAME_FORMAT_RAW, 0);
7698 }
7699
7700 /* handle output info, assume always needed */
7701 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7702 if (internal_pipe->config.output_info[i].res.width) {
7703 err = sh_css_pipe_configure_output(
7704 internal_pipe,
7705 internal_pipe->config.output_info[i].res.width,
7706 internal_pipe->config.output_info[i].res.height,
7707 internal_pipe->config.output_info[i].padded_width,
7708 internal_pipe->config.output_info[i].format,
7709 i);
7710 if (err) {
7711 IA_CSS_LEAVE_ERR_PRIVATE(err);
7712 kvfree(internal_pipe);
7713 internal_pipe = NULL;
7714 return err;
7715 }
7716 }
7717
7718 /* handle vf output info, when configured */
7719 internal_pipe->enable_viewfinder[i] =
7720 (internal_pipe->config.vf_output_info[i].res.width != 0);
7721 if (internal_pipe->config.vf_output_info[i].res.width) {
7722 err = sh_css_pipe_configure_viewfinder(
7723 internal_pipe,
7724 internal_pipe->config.vf_output_info[i].res.width,
7725 internal_pipe->config.vf_output_info[i].res.height,
7726 internal_pipe->config.vf_output_info[i].padded_width,
7727 internal_pipe->config.vf_output_info[i].format,
7728 i);
7729 if (err) {
7730 IA_CSS_LEAVE_ERR_PRIVATE(err);
7731 kvfree(internal_pipe);
7732 internal_pipe = NULL;
7733 return err;
7734 }
7735 }
7736 }
7737 /* set all info to zeroes first */
7738 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info));
7739
7740 /* all went well, return the pipe */
7741 *pipe = internal_pipe;
7742 IA_CSS_LEAVE_ERR_PRIVATE(0);
7743 return 0;
7744 }
7745
7746 int
ia_css_pipe_get_info(const struct ia_css_pipe * pipe,struct ia_css_pipe_info * pipe_info)7747 ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
7748 struct ia_css_pipe_info *pipe_info)
7749 {
7750 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7751 "ia_css_pipe_get_info()\n");
7752 if (!pipe_info) {
7753 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
7754 "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
7755 return -EINVAL;
7756 }
7757 if (!pipe || !pipe->stream) {
7758 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
7759 "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n");
7760 return -EINVAL;
7761 }
7762 /* we succeeded return the info */
7763 *pipe_info = pipe->info;
7764 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n");
7765 return 0;
7766 }
7767
ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info * pipe_info)7768 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info)
7769 {
7770 unsigned int i;
7771
7772 if (pipe_info) {
7773 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) {
7774 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable)
7775 return true;
7776 }
7777 }
7778
7779 return false;
7780 }
7781
7782 int
ia_css_pipe_override_frame_format(struct ia_css_pipe * pipe,int pin_index,enum ia_css_frame_format new_format)7783 ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
7784 int pin_index,
7785 enum ia_css_frame_format new_format)
7786 {
7787 int err = 0;
7788
7789 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
7790
7791 if (!pipe) {
7792 IA_CSS_ERROR("pipe is not set");
7793 err = -EINVAL;
7794 IA_CSS_LEAVE_ERR_PRIVATE(err);
7795 return err;
7796 }
7797 if (0 != pin_index && 1 != pin_index) {
7798 IA_CSS_ERROR("pin index is not valid");
7799 err = -EINVAL;
7800 IA_CSS_LEAVE_ERR_PRIVATE(err);
7801 return err;
7802 }
7803 if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY) {
7804 IA_CSS_ERROR("new format is not valid");
7805 err = -EINVAL;
7806 IA_CSS_LEAVE_ERR_PRIVATE(err);
7807 return err;
7808 } else {
7809 err = ia_css_pipe_check_format(pipe, new_format);
7810 if (!err) {
7811 if (pin_index == 0)
7812 pipe->output_info[0].format = new_format;
7813 else
7814 pipe->vf_output_info[0].format = new_format;
7815 }
7816 }
7817 IA_CSS_LEAVE_ERR_PRIVATE(err);
7818 return err;
7819 }
7820
7821 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
7822 static int
ia_css_stream_configure_rx(struct ia_css_stream * stream)7823 ia_css_stream_configure_rx(struct ia_css_stream *stream)
7824 {
7825 struct ia_css_input_port *config;
7826
7827 assert(stream);
7828
7829 config = &stream->config.source.port;
7830 /* AM: this code is not reliable, especially for 2400 */
7831 if (config->num_lanes == 1)
7832 stream->csi_rx_config.mode = MONO_1L_1L_0L;
7833 else if (config->num_lanes == 2)
7834 stream->csi_rx_config.mode = MONO_2L_1L_0L;
7835 else if (config->num_lanes == 3)
7836 stream->csi_rx_config.mode = MONO_3L_1L_0L;
7837 else if (config->num_lanes == 4)
7838 stream->csi_rx_config.mode = MONO_4L_1L_0L;
7839 else if (config->num_lanes != 0)
7840 return -EINVAL;
7841
7842 if (config->port > MIPI_PORT2_ID)
7843 return -EINVAL;
7844 stream->csi_rx_config.port =
7845 ia_css_isys_port_to_mipi_port(config->port);
7846 stream->csi_rx_config.timeout = config->timeout;
7847 stream->csi_rx_config.initcount = 0;
7848 stream->csi_rx_config.synccount = 0x28282828;
7849 stream->csi_rx_config.rxcount = config->rxcount;
7850 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
7851 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
7852 else
7853 /*
7854 * not implemented yet, requires extension of the rx_cfg_t
7855 * struct
7856 */
7857 return -EINVAL;
7858
7859 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
7860 stream->reconfigure_css_rx = true;
7861 return 0;
7862 }
7863
7864 static struct ia_css_pipe *
find_pipe(struct ia_css_pipe * pipes[],unsigned int num_pipes,enum ia_css_pipe_mode mode,bool copy_pipe)7865 find_pipe(struct ia_css_pipe *pipes[], unsigned int num_pipes,
7866 enum ia_css_pipe_mode mode, bool copy_pipe)
7867 {
7868 unsigned int i;
7869
7870 assert(pipes);
7871 for (i = 0; i < num_pipes; i++) {
7872 assert(pipes[i]);
7873 if (pipes[i]->config.mode != mode)
7874 continue;
7875 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY)
7876 continue;
7877 return pipes[i];
7878 }
7879 return NULL;
7880 }
7881
7882 static int
metadata_info_init(const struct ia_css_metadata_config * mdc,struct ia_css_metadata_info * md)7883 metadata_info_init(const struct ia_css_metadata_config *mdc,
7884 struct ia_css_metadata_info *md)
7885 {
7886 /* Either both width and height should be set or neither */
7887 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
7888 return -EINVAL;
7889
7890 md->resolution = mdc->resolution;
7891 /*
7892 * We round up the stride to a multiple of the width
7893 * of the port going to DDR, this is a HW requirements (DMA).
7894 */
7895 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES);
7896 md->size = mdc->resolution.height * md->stride;
7897 return 0;
7898 }
7899
7900 int
ia_css_stream_create(const struct ia_css_stream_config * stream_config,int num_pipes,struct ia_css_pipe * pipes[],struct ia_css_stream ** stream)7901 ia_css_stream_create(const struct ia_css_stream_config *stream_config,
7902 int num_pipes,
7903 struct ia_css_pipe *pipes[],
7904 struct ia_css_stream **stream)
7905 {
7906 struct ia_css_pipe *curr_pipe;
7907 struct ia_css_stream *curr_stream = NULL;
7908 bool spcopyonly;
7909 bool sensor_binning_changed;
7910 int i, j;
7911 int err = -EINVAL;
7912 struct ia_css_metadata_info md_info;
7913 struct ia_css_resolution effective_res;
7914
7915 IA_CSS_ENTER("num_pipes=%d", num_pipes);
7916 ia_css_debug_dump_stream_config(stream_config, num_pipes);
7917
7918 /* some checks */
7919 if (num_pipes == 0 ||
7920 !stream ||
7921 !pipes) {
7922 err = -EINVAL;
7923 IA_CSS_LEAVE_ERR(err);
7924 return err;
7925 }
7926
7927 if (!IS_ISP2401) {
7928 /* We don't support metadata for JPEG stream, since they both use str2mem */
7929 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
7930 stream_config->metadata_config.resolution.height > 0) {
7931 err = -EINVAL;
7932 IA_CSS_LEAVE_ERR(err);
7933 return err;
7934 }
7935 } else {
7936 if (stream_config->online && stream_config->pack_raw_pixels) {
7937 IA_CSS_LOG("online and pack raw is invalid on input system 2401");
7938 err = -EINVAL;
7939 IA_CSS_LEAVE_ERR(err);
7940 return err;
7941 }
7942 }
7943
7944 ia_css_debug_pipe_graph_dump_stream_config(stream_config);
7945
7946 /* check if mipi size specified */
7947 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
7948 if (!IS_ISP2401 || !stream_config->online)
7949 {
7950 unsigned int port = (unsigned int)stream_config->source.port.port;
7951
7952 if (port >= N_MIPI_PORT_ID) {
7953 err = -EINVAL;
7954 IA_CSS_LEAVE_ERR(err);
7955 return err;
7956 }
7957
7958 if (my_css.size_mem_words != 0) {
7959 my_css.mipi_frame_size[port] = my_css.size_mem_words;
7960 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) {
7961 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words;
7962 } else {
7963 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7964 "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
7965 assert(stream_config->mipi_buffer_config.size_mem_words != 0);
7966 err = -EINVAL;
7967 IA_CSS_LEAVE_ERR(err);
7968 return err;
7969 }
7970
7971 if (my_css.size_mem_words != 0) {
7972 my_css.num_mipi_frames[port] =
7973 2; /* Temp change: Default for backwards compatibility. */
7974 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) {
7975 my_css.num_mipi_frames[port] =
7976 stream_config->mipi_buffer_config.nof_mipi_buffers;
7977 } else {
7978 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7979 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
7980 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0);
7981 err = -EINVAL;
7982 IA_CSS_LEAVE_ERR(err);
7983 return err;
7984 }
7985 }
7986
7987 /* Currently we only supported metadata up to a certain size. */
7988 err = metadata_info_init(&stream_config->metadata_config, &md_info);
7989 if (err) {
7990 IA_CSS_LEAVE_ERR(err);
7991 return err;
7992 }
7993
7994 /* allocate the stream instance */
7995 curr_stream = kzalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
7996 if (!curr_stream) {
7997 err = -ENOMEM;
7998 IA_CSS_LEAVE_ERR(err);
7999 return err;
8000 }
8001 /* default all to 0 */
8002 curr_stream->info.metadata_info = md_info;
8003
8004 /* allocate pipes */
8005 curr_stream->num_pipes = num_pipes;
8006 curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL);
8007 if (!curr_stream->pipes) {
8008 curr_stream->num_pipes = 0;
8009 kfree(curr_stream);
8010 curr_stream = NULL;
8011 err = -ENOMEM;
8012 IA_CSS_LEAVE_ERR(err);
8013 return err;
8014 }
8015 /* store pipes */
8016 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY);
8017 for (i = 0; i < num_pipes; i++)
8018 curr_stream->pipes[i] = pipes[i];
8019 curr_stream->last_pipe = curr_stream->pipes[0];
8020 /* take over stream config */
8021 curr_stream->config = *stream_config;
8022
8023 if (IS_ISP2401) {
8024 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
8025 stream_config->online)
8026 curr_stream->config.online = false;
8027
8028 if (curr_stream->config.online) {
8029 curr_stream->config.source.port.num_lanes =
8030 stream_config->source.port.num_lanes;
8031 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
8032 }
8033 }
8034 /* in case driver doesn't configure init number of raw buffers, configure it here */
8035 if (curr_stream->config.target_num_cont_raw_buf == 0)
8036 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
8037 if (curr_stream->config.init_num_cont_raw_buf == 0)
8038 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf;
8039
8040 /* Enable locking & unlocking of buffers in RAW buffer pool */
8041 if (curr_stream->config.ia_css_enable_raw_buffer_locking)
8042 sh_css_sp_configure_enable_raw_pool_locking(
8043 curr_stream->config.lock_all);
8044
8045 /* copy mode specific stuff */
8046 switch (curr_stream->config.mode) {
8047 case IA_CSS_INPUT_MODE_SENSOR:
8048 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
8049 if (!IS_ISP2401)
8050 ia_css_stream_configure_rx(curr_stream);
8051 break;
8052 case IA_CSS_INPUT_MODE_PRBS:
8053 if (!IS_ISP2401) {
8054 IA_CSS_LOG("mode prbs");
8055 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed);
8056 }
8057 break;
8058 case IA_CSS_INPUT_MODE_MEMORY:
8059 IA_CSS_LOG("mode memory");
8060 curr_stream->reconfigure_css_rx = false;
8061 break;
8062 default:
8063 IA_CSS_LOG("mode sensor/default");
8064 }
8065
8066 for (i = 0; i < num_pipes; i++) {
8067 struct ia_css_resolution effective_res;
8068
8069 curr_pipe = pipes[i];
8070 /* set current stream */
8071 curr_pipe->stream = curr_stream;
8072 /* take over effective info */
8073
8074 effective_res = curr_pipe->config.input_effective_res;
8075 if (effective_res.height == 0 || effective_res.width == 0) {
8076 effective_res = curr_pipe->stream->config.input_config.effective_res;
8077
8078 curr_pipe->config.input_effective_res = effective_res;
8079 }
8080 IA_CSS_LOG("effective_res=%dx%d",
8081 effective_res.width,
8082 effective_res.height);
8083 }
8084
8085 err = ia_css_stream_isp_parameters_init(curr_stream);
8086 if (err)
8087 goto ERR;
8088 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
8089
8090 /* sensor binning */
8091 if (!spcopyonly) {
8092 sensor_binning_changed =
8093 sh_css_params_set_binning_factor(curr_stream,
8094 curr_stream->config.sensor_binning_factor);
8095 } else {
8096 sensor_binning_changed = false;
8097 }
8098
8099 IA_CSS_LOG("sensor_binning=%d, changed=%d",
8100 curr_stream->config.sensor_binning_factor, sensor_binning_changed);
8101 /* loop over pipes */
8102 IA_CSS_LOG("num_pipes=%d", num_pipes);
8103 curr_stream->cont_capt = false;
8104 /* Temporary hack: we give the preview pipe a reference to the capture
8105 * pipe in continuous capture mode. */
8106 if (curr_stream->config.continuous) {
8107 /* Search for the preview pipe and create the copy pipe */
8108 struct ia_css_pipe *preview_pipe;
8109 struct ia_css_pipe *video_pipe;
8110 struct ia_css_pipe *capture_pipe = NULL;
8111 struct ia_css_pipe *copy_pipe = NULL;
8112
8113 if (num_pipes >= 2) {
8114 curr_stream->cont_capt = true;
8115 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder;
8116 curr_stream->stop_copy_preview = my_css.stop_copy_preview;
8117 }
8118
8119 /* Create copy pipe here, since it may not be exposed to the driver */
8120 preview_pipe = find_pipe(pipes, num_pipes,
8121 IA_CSS_PIPE_MODE_PREVIEW, false);
8122 video_pipe = find_pipe(pipes, num_pipes,
8123 IA_CSS_PIPE_MODE_VIDEO, false);
8124
8125 if (curr_stream->cont_capt) {
8126 capture_pipe = find_pipe(pipes, num_pipes,
8127 IA_CSS_PIPE_MODE_CAPTURE,
8128 false);
8129 if (!capture_pipe) {
8130 err = -EINVAL;
8131 goto ERR;
8132 }
8133 }
8134 /* We do not support preview and video pipe at the same time */
8135 if (preview_pipe && video_pipe) {
8136 err = -EINVAL;
8137 goto ERR;
8138 }
8139
8140 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) {
8141 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
8142 if (err)
8143 goto ERR;
8144 ia_css_pipe_config_defaults(©_pipe->config);
8145 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
8146 copy_pipe->stream = curr_stream;
8147 }
8148 if (preview_pipe && curr_stream->cont_capt)
8149 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
8150
8151 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
8152 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
8153 if (err)
8154 goto ERR;
8155 ia_css_pipe_config_defaults(©_pipe->config);
8156 video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
8157 copy_pipe->stream = curr_stream;
8158 }
8159 if (video_pipe && curr_stream->cont_capt)
8160 video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
8161 }
8162 for (i = 0; i < num_pipes; i++) {
8163 curr_pipe = pipes[i];
8164 /* set current stream */
8165 curr_pipe->stream = curr_stream;
8166
8167 /* take over effective info */
8168
8169 effective_res = curr_pipe->config.input_effective_res;
8170 err = ia_css_util_check_res(
8171 effective_res.width,
8172 effective_res.height);
8173 if (err)
8174 goto ERR;
8175
8176 /* sensor binning per pipe */
8177 if (sensor_binning_changed)
8178 sh_css_pipe_free_shading_table(curr_pipe);
8179 }
8180
8181 /* now pipes have been configured, info should be available */
8182 for (i = 0; i < num_pipes; i++) {
8183 struct ia_css_pipe_info *pipe_info = NULL;
8184
8185 curr_pipe = pipes[i];
8186
8187 err = sh_css_pipe_load_binaries(curr_pipe);
8188 if (err)
8189 goto ERR;
8190
8191 /* handle each pipe */
8192 pipe_info = &curr_pipe->info;
8193 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
8194 err = sh_css_pipe_get_output_frame_info(curr_pipe,
8195 &pipe_info->output_info[j], j);
8196 if (err)
8197 goto ERR;
8198 }
8199
8200 if (!spcopyonly) {
8201 if (!IS_ISP2401)
8202 err = sh_css_pipe_get_shading_info(curr_pipe,
8203 &pipe_info->shading_info,
8204 NULL);
8205 else
8206 err = sh_css_pipe_get_shading_info(curr_pipe,
8207 &pipe_info->shading_info,
8208 &curr_pipe->config);
8209
8210 if (err)
8211 goto ERR;
8212 err = sh_css_pipe_get_grid_info(curr_pipe,
8213 &pipe_info->grid_info);
8214 if (err)
8215 goto ERR;
8216 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
8217 sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
8218 &pipe_info->vf_output_info[j],
8219 j);
8220 if (err)
8221 goto ERR;
8222 }
8223 }
8224
8225 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe;
8226 }
8227
8228 curr_stream->started = false;
8229
8230 /* Map SP threads before doing anything. */
8231 err = map_sp_threads(curr_stream, true);
8232 if (err) {
8233 IA_CSS_LOG("map_sp_threads: return_err=%d", err);
8234 goto ERR;
8235 }
8236
8237 for (i = 0; i < num_pipes; i++) {
8238 curr_pipe = pipes[i];
8239 ia_css_pipe_map_queue(curr_pipe, true);
8240 }
8241
8242 /* Create host side pipeline objects without stages */
8243 err = create_host_pipeline_structure(curr_stream);
8244 if (err) {
8245 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
8246 goto ERR;
8247 }
8248
8249 /* assign curr_stream */
8250 *stream = curr_stream;
8251
8252 ERR:
8253 if (!err) {
8254 /* working mode: enter into the seed list */
8255 if (my_css_save.mode == sh_css_mode_working) {
8256 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
8257 if (!my_css_save.stream_seeds[i].stream) {
8258 IA_CSS_LOG("entered stream into loc=%d", i);
8259 my_css_save.stream_seeds[i].orig_stream = stream;
8260 my_css_save.stream_seeds[i].stream = curr_stream;
8261 my_css_save.stream_seeds[i].num_pipes = num_pipes;
8262 my_css_save.stream_seeds[i].stream_config = *stream_config;
8263 for (j = 0; j < num_pipes; j++) {
8264 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
8265 my_css_save.stream_seeds[i].pipes[j] = pipes[j];
8266 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
8267 }
8268 break;
8269 }
8270 }
8271 } else {
8272 ia_css_stream_destroy(curr_stream);
8273 }
8274 } else {
8275 ia_css_stream_destroy(curr_stream);
8276 }
8277 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
8278 return err;
8279 }
8280
8281 int
ia_css_stream_destroy(struct ia_css_stream * stream)8282 ia_css_stream_destroy(struct ia_css_stream *stream)
8283 {
8284 int i;
8285 int err = 0;
8286
8287 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
8288 if (!stream) {
8289 err = -EINVAL;
8290 IA_CSS_LEAVE_ERR_PRIVATE(err);
8291 return err;
8292 }
8293
8294 ia_css_stream_isp_parameters_uninit(stream);
8295
8296 if ((stream->last_pipe) &&
8297 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) {
8298 if (IS_ISP2401) {
8299 for (i = 0; i < stream->num_pipes; i++) {
8300 struct ia_css_pipe *entry = stream->pipes[i];
8301 unsigned int sp_thread_id;
8302 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
8303
8304 assert(entry);
8305 if (entry) {
8306 /* get the SP thread id */
8307 if (!ia_css_pipeline_get_sp_thread_id(
8308 ia_css_pipe_get_pipe_num(entry), &sp_thread_id))
8309 return -EINVAL;
8310
8311 /* get the target input terminal */
8312 sp_pipeline_input_terminal =
8313 &sh_css_sp_group.pipe_io[sp_thread_id].input;
8314
8315 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
8316 ia_css_isys_stream_h isys_stream =
8317 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i];
8318 if (stream->config.isys_config[i].valid && isys_stream->valid)
8319 ia_css_isys_stream_destroy(isys_stream);
8320 }
8321 }
8322 }
8323
8324 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
8325 for (i = 0; i < stream->num_pipes; i++) {
8326 struct ia_css_pipe *entry = stream->pipes[i];
8327 /*
8328 * free any mipi frames that are remaining:
8329 * some test stream create-destroy cycles do
8330 * not generate output frames
8331 * and the mipi buffer is not freed in the
8332 * deque function
8333 */
8334 if (entry)
8335 free_mipi_frames(entry);
8336 }
8337 }
8338 stream_unregister_with_csi_rx(stream);
8339 }
8340
8341 for (i = 0; i < stream->num_pipes; i++) {
8342 struct ia_css_pipe *curr_pipe = stream->pipes[i];
8343
8344 assert(curr_pipe);
8345 ia_css_pipe_map_queue(curr_pipe, false);
8346 }
8347
8348 err = map_sp_threads(stream, false);
8349 if (err) {
8350 IA_CSS_LEAVE_ERR_PRIVATE(err);
8351 return err;
8352 }
8353 }
8354
8355 /* remove references from pipes to stream */
8356 for (i = 0; i < stream->num_pipes; i++) {
8357 struct ia_css_pipe *entry = stream->pipes[i];
8358
8359 assert(entry);
8360 if (entry) {
8361 /* clear reference to stream */
8362 entry->stream = NULL;
8363 /* check internal copy pipe */
8364 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
8365 entry->pipe_settings.preview.copy_pipe) {
8366 IA_CSS_LOG("clearing stream on internal preview copy pipe");
8367 entry->pipe_settings.preview.copy_pipe->stream = NULL;
8368 }
8369 if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
8370 entry->pipe_settings.video.copy_pipe) {
8371 IA_CSS_LOG("clearing stream on internal video copy pipe");
8372 entry->pipe_settings.video.copy_pipe->stream = NULL;
8373 }
8374 err = sh_css_pipe_unload_binaries(entry);
8375 }
8376 }
8377 /* free associated memory of stream struct */
8378 kfree(stream->pipes);
8379 stream->pipes = NULL;
8380 stream->num_pipes = 0;
8381
8382 /* working mode: take out of the seed list */
8383 if (my_css_save.mode == sh_css_mode_working) {
8384 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
8385 if (my_css_save.stream_seeds[i].stream == stream) {
8386 IA_CSS_LOG("took out stream %d", i);
8387 my_css_save.stream_seeds[i].stream = NULL;
8388 break;
8389 }
8390 }
8391 }
8392
8393 kfree(stream);
8394 IA_CSS_LEAVE_ERR(err);
8395
8396 return err;
8397 }
8398
8399 int
ia_css_stream_get_info(const struct ia_css_stream * stream,struct ia_css_stream_info * stream_info)8400 ia_css_stream_get_info(const struct ia_css_stream *stream,
8401 struct ia_css_stream_info *stream_info)
8402 {
8403 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
8404 assert(stream);
8405 assert(stream_info);
8406
8407 *stream_info = stream->info;
8408 return 0;
8409 }
8410
8411 int
ia_css_stream_start(struct ia_css_stream * stream)8412 ia_css_stream_start(struct ia_css_stream *stream)
8413 {
8414 int err = 0;
8415
8416 IA_CSS_ENTER("stream = %p", stream);
8417 if ((!stream) || (!stream->last_pipe)) {
8418 IA_CSS_LEAVE_ERR(-EINVAL);
8419 return -EINVAL;
8420 }
8421 IA_CSS_LOG("starting %d", stream->last_pipe->mode);
8422
8423 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
8424
8425 /* Create host side pipeline. */
8426 err = create_host_pipeline(stream);
8427 if (err) {
8428 IA_CSS_LEAVE_ERR(err);
8429 return err;
8430 }
8431
8432 if (IS_ISP2401 &&
8433 ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
8434 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)))
8435 stream_register_with_csi_rx(stream);
8436
8437 /* Initialize mipi size checks */
8438 if (!IS_ISP2401 && stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
8439 unsigned int idx;
8440 unsigned int port = (unsigned int)(stream->config.source.port.port);
8441
8442 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
8443 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] =
8444 sh_css_get_mipi_sizes_for_check(port, idx);
8445 }
8446 }
8447
8448 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) {
8449 if (IS_ISP2401)
8450 err = sh_css_config_input_network_2401(stream);
8451 else
8452 err = sh_css_config_input_network_2400(stream);
8453 if (err)
8454 return err;
8455 }
8456
8457 err = sh_css_pipe_start(stream);
8458 IA_CSS_LEAVE_ERR(err);
8459 return err;
8460 }
8461
8462 int
ia_css_stream_stop(struct ia_css_stream * stream)8463 ia_css_stream_stop(struct ia_css_stream *stream)
8464 {
8465 int err = 0;
8466
8467 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
8468 assert(stream);
8469 assert(stream->last_pipe);
8470 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
8471 stream->last_pipe->mode);
8472
8473 /* De-initialize mipi size checks */
8474 if (!IS_ISP2401 && stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
8475 unsigned int idx;
8476 unsigned int port = (unsigned int)(stream->config.source.port.port);
8477
8478 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++)
8479 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
8480 }
8481
8482 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
8483 if (err)
8484 return err;
8485
8486 /*
8487 * Ideally, unmapping should happen after pipeline_stop, but current
8488 * semantics do not allow that.
8489 */
8490 /* err = map_sp_threads(stream, false); */
8491
8492 return err;
8493 }
8494
8495 bool
ia_css_stream_has_stopped(struct ia_css_stream * stream)8496 ia_css_stream_has_stopped(struct ia_css_stream *stream)
8497 {
8498 bool stopped;
8499
8500 assert(stream);
8501
8502 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
8503
8504 return stopped;
8505 }
8506
8507 /* ISP2400 */
8508 /*
8509 * Destroy the stream and all the pipes related to it.
8510 * The stream handle is used to identify the correct entry in the css_save struct
8511 */
8512 int
ia_css_stream_unload(struct ia_css_stream * stream)8513 ia_css_stream_unload(struct ia_css_stream *stream)
8514 {
8515 int i;
8516
8517 assert(stream);
8518 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter,\n");
8519 /* some checks */
8520 assert(stream);
8521 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
8522 if (my_css_save.stream_seeds[i].stream == stream) {
8523 int j;
8524
8525 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8526 "ia_css_stream_unload(): unloading %d (%p)\n", i,
8527 my_css_save.stream_seeds[i].stream);
8528 ia_css_stream_destroy(stream);
8529 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
8530 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
8531 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8532 "ia_css_stream_unload(): after unloading %d (%p)\n", i,
8533 my_css_save.stream_seeds[i].stream);
8534 break;
8535 }
8536 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit,\n");
8537 return 0;
8538 }
8539
8540 int
ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe * pipe,enum ia_css_pipe_id * pipe_id)8541 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe,
8542 enum ia_css_pipe_id *pipe_id)
8543 {
8544 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
8545 if (pipe)
8546 *pipe_id = pipe->mode;
8547 else
8548 *pipe_id = IA_CSS_PIPE_ID_COPY;
8549
8550 return 0;
8551 }
8552
8553 enum atomisp_input_format
ia_css_stream_get_format(const struct ia_css_stream * stream)8554 ia_css_stream_get_format(const struct ia_css_stream *stream)
8555 {
8556 return stream->config.input_config.format;
8557 }
8558
8559 bool
ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream * stream)8560 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream)
8561 {
8562 return (stream->config.pixels_per_clock == 2);
8563 }
8564
8565 struct ia_css_binary *
ia_css_stream_get_shading_correction_binary(const struct ia_css_stream * stream)8566 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
8567 *stream)
8568 {
8569 struct ia_css_pipe *pipe;
8570
8571 assert(stream);
8572
8573 pipe = stream->pipes[0];
8574
8575 if (stream->num_pipes == 2) {
8576 assert(stream->pipes[1]);
8577 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
8578 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
8579 pipe = stream->pipes[1];
8580 }
8581
8582 return ia_css_pipe_get_shading_correction_binary(pipe);
8583 }
8584
8585 struct ia_css_binary *
ia_css_stream_get_dvs_binary(const struct ia_css_stream * stream)8586 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream)
8587 {
8588 int i;
8589 struct ia_css_pipe *video_pipe = NULL;
8590
8591 /* First we find the video pipe */
8592 for (i = 0; i < stream->num_pipes; i++) {
8593 struct ia_css_pipe *pipe = stream->pipes[i];
8594
8595 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
8596 video_pipe = pipe;
8597 break;
8598 }
8599 }
8600 if (video_pipe)
8601 return &video_pipe->pipe_settings.video.video_binary;
8602 return NULL;
8603 }
8604
8605 struct ia_css_binary *
ia_css_stream_get_3a_binary(const struct ia_css_stream * stream)8606 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream)
8607 {
8608 struct ia_css_pipe *pipe;
8609 struct ia_css_binary *s3a_binary = NULL;
8610
8611 assert(stream);
8612
8613 pipe = stream->pipes[0];
8614
8615 if (stream->num_pipes == 2) {
8616 assert(stream->pipes[1]);
8617 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
8618 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
8619 pipe = stream->pipes[1];
8620 }
8621
8622 s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
8623
8624 return s3a_binary;
8625 }
8626
8627 int
ia_css_stream_set_output_padded_width(struct ia_css_stream * stream,unsigned int output_padded_width)8628 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream,
8629 unsigned int output_padded_width)
8630 {
8631 struct ia_css_pipe *pipe;
8632
8633 assert(stream);
8634
8635 pipe = stream->last_pipe;
8636
8637 assert(pipe);
8638
8639 /* set the config also just in case (redundant info? why do we save config in pipe?) */
8640 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
8641 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
8642
8643 return 0;
8644 }
8645
8646 static struct ia_css_binary *
ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe * pipe)8647 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe)
8648 {
8649 struct ia_css_binary *binary = NULL;
8650
8651 assert(pipe);
8652
8653 switch (pipe->config.mode) {
8654 case IA_CSS_PIPE_MODE_PREVIEW:
8655 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
8656 break;
8657 case IA_CSS_PIPE_MODE_VIDEO:
8658 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
8659 break;
8660 case IA_CSS_PIPE_MODE_CAPTURE:
8661 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
8662 unsigned int i;
8663
8664 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
8665 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
8666 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
8667 break;
8668 }
8669 }
8670 } else if (pipe->config.default_capture_config.mode ==
8671 IA_CSS_CAPTURE_MODE_BAYER)
8672 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
8673 else if (pipe->config.default_capture_config.mode ==
8674 IA_CSS_CAPTURE_MODE_ADVANCED ||
8675 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
8676 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
8677 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
8678 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
8679 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
8680 }
8681 break;
8682 default:
8683 break;
8684 }
8685
8686 if (binary && binary->info->sp.enable.sc)
8687 return binary;
8688
8689 return NULL;
8690 }
8691
8692 static struct ia_css_binary *
ia_css_pipe_get_s3a_binary(const struct ia_css_pipe * pipe)8693 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe)
8694 {
8695 struct ia_css_binary *binary = NULL;
8696
8697 assert(pipe);
8698
8699 switch (pipe->config.mode) {
8700 case IA_CSS_PIPE_MODE_PREVIEW:
8701 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
8702 break;
8703 case IA_CSS_PIPE_MODE_VIDEO:
8704 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
8705 break;
8706 case IA_CSS_PIPE_MODE_CAPTURE:
8707 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
8708 unsigned int i;
8709
8710 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
8711 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
8712 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
8713 break;
8714 }
8715 }
8716 } else if (pipe->config.default_capture_config.mode ==
8717 IA_CSS_CAPTURE_MODE_BAYER) {
8718 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
8719 } else if (pipe->config.default_capture_config.mode ==
8720 IA_CSS_CAPTURE_MODE_ADVANCED ||
8721 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
8722 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
8723 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
8724 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
8725 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
8726 else
8727 assert(0);
8728 }
8729 break;
8730 default:
8731 break;
8732 }
8733
8734 if (binary && !binary->info->sp.enable.s3a)
8735 binary = NULL;
8736
8737 return binary;
8738 }
8739
8740 static struct ia_css_binary *
ia_css_pipe_get_sdis_binary(const struct ia_css_pipe * pipe)8741 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe)
8742 {
8743 struct ia_css_binary *binary = NULL;
8744
8745 assert(pipe);
8746
8747 switch (pipe->config.mode) {
8748 case IA_CSS_PIPE_MODE_VIDEO:
8749 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
8750 break;
8751 default:
8752 break;
8753 }
8754
8755 if (binary && !binary->info->sp.enable.dis)
8756 binary = NULL;
8757
8758 return binary;
8759 }
8760
8761 struct ia_css_pipeline *
ia_css_pipe_get_pipeline(const struct ia_css_pipe * pipe)8762 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe)
8763 {
8764 assert(pipe);
8765
8766 return (struct ia_css_pipeline *)&pipe->pipeline;
8767 }
8768
8769 unsigned int
ia_css_pipe_get_pipe_num(const struct ia_css_pipe * pipe)8770 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe)
8771 {
8772 assert(pipe);
8773
8774 /*
8775 * KW was not sure this function was not returning a value
8776 * that was out of range; so added an assert, and, for the
8777 * case when asserts are not enabled, clip to the largest
8778 * value; pipe_num is unsigned so the value cannot be too small
8779 */
8780 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
8781
8782 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
8783 return (IA_CSS_PIPELINE_NUM_MAX - 1);
8784
8785 return pipe->pipe_num;
8786 }
8787
8788 unsigned int
ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe * pipe)8789 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe)
8790 {
8791 assert(pipe);
8792
8793 return (unsigned int)pipe->config.isp_pipe_version;
8794 }
8795
8796 #define SP_START_TIMEOUT_US 30000000
8797
8798 int
ia_css_start_sp(void)8799 ia_css_start_sp(void)
8800 {
8801 unsigned long timeout;
8802 int err = 0;
8803
8804 IA_CSS_ENTER("");
8805 sh_css_sp_start_isp();
8806
8807 /* waiting for the SP is completely started */
8808 timeout = SP_START_TIMEOUT_US;
8809 while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) {
8810 timeout--;
8811 udelay(1);
8812 }
8813 if (timeout == 0) {
8814 IA_CSS_ERROR("timeout during SP initialization");
8815 return -EINVAL;
8816 }
8817
8818 /* Workaround, in order to run two streams in parallel. See TASK 4271*/
8819 /* TODO: Fix this. */
8820
8821 sh_css_init_host_sp_control_vars();
8822
8823 /* buffers should be initialized only when sp is started */
8824 /* AM: At the moment it will be done only when there is no stream active. */
8825
8826 sh_css_setup_queues();
8827 ia_css_bufq_dump_queue_info();
8828
8829 IA_CSS_LEAVE_ERR(err);
8830 return err;
8831 }
8832
8833 /*
8834 * Time to wait SP for termincate. Only condition when this can happen
8835 * is a fatal hw failure, but we must be able to detect this and emit
8836 * a proper error trace.
8837 */
8838 #define SP_SHUTDOWN_TIMEOUT_US 200000
8839
8840 int
ia_css_stop_sp(void)8841 ia_css_stop_sp(void)
8842 {
8843 unsigned long timeout;
8844 int err = 0;
8845
8846 IA_CSS_ENTER("void");
8847
8848 if (!sh_css_sp_is_running()) {
8849 err = -EINVAL;
8850 IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
8851
8852 /* Return an error - stop SP should not have been called by driver */
8853 return err;
8854 }
8855
8856 /* For now, stop whole SP */
8857 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) {
8858 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8859 ia_css_debug_dump_sp_sw_debug_info();
8860 }
8861
8862 sh_css_sp_set_sp_running(false);
8863
8864 timeout = SP_SHUTDOWN_TIMEOUT_US;
8865 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) {
8866 timeout--;
8867 udelay(1);
8868 }
8869 if (ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED)
8870 IA_CSS_WARNING("SP has not terminated (SW)");
8871
8872 if (timeout == 0) {
8873 IA_CSS_WARNING("SP is not idle");
8874 ia_css_debug_dump_sp_sw_debug_info();
8875 }
8876 timeout = SP_SHUTDOWN_TIMEOUT_US;
8877 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) {
8878 timeout--;
8879 udelay(1);
8880 }
8881 if (timeout == 0) {
8882 IA_CSS_WARNING("ISP is not idle");
8883 ia_css_debug_dump_sp_sw_debug_info();
8884 }
8885
8886 sh_css_hmm_buffer_record_uninit();
8887
8888 /* clear pending param sets from refcount */
8889 sh_css_param_clear_param_sets();
8890
8891 IA_CSS_LEAVE_ERR(err);
8892 return err;
8893 }
8894
8895 int
ia_css_update_continuous_frames(struct ia_css_stream * stream)8896 ia_css_update_continuous_frames(struct ia_css_stream *stream)
8897 {
8898 struct ia_css_pipe *pipe;
8899 unsigned int i;
8900
8901 ia_css_debug_dtrace(
8902 IA_CSS_DEBUG_TRACE,
8903 "sh_css_update_continuous_frames() enter:\n");
8904
8905 if (!stream) {
8906 ia_css_debug_dtrace(
8907 IA_CSS_DEBUG_TRACE,
8908 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
8909 return -EINVAL;
8910 }
8911
8912 pipe = stream->continuous_pipe;
8913
8914 for (i = stream->config.init_num_cont_raw_buf;
8915 i < stream->config.target_num_cont_raw_buf; i++)
8916 sh_css_update_host2sp_offline_frame(i,
8917 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
8918
8919 sh_css_update_host2sp_cont_num_raw_frames
8920 (stream->config.target_num_cont_raw_buf, true);
8921 ia_css_debug_dtrace(
8922 IA_CSS_DEBUG_TRACE,
8923 "sh_css_update_continuous_frames() leave: return_void\n");
8924
8925 return 0;
8926 }
8927
ia_css_pipe_map_queue(struct ia_css_pipe * pipe,bool map)8928 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
8929 {
8930 unsigned int thread_id;
8931 unsigned int pipe_num;
8932 bool need_input_queue;
8933
8934 IA_CSS_ENTER("");
8935 assert(pipe);
8936
8937 pipe_num = pipe->pipe_num;
8938
8939 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
8940
8941 if (IS_ISP2401)
8942 need_input_queue = true;
8943 else
8944 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
8945
8946 /* map required buffer queues to resources */
8947 /* TODO: to be improved */
8948 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
8949 if (need_input_queue)
8950 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
8951 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
8952 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
8953 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
8954 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
8955 if (pipe->pipe_settings.preview.preview_binary.info &&
8956 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
8957 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
8958 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
8959 unsigned int i;
8960
8961 if (need_input_queue)
8962 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
8963 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
8964 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
8965 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
8966 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
8967 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
8968 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
8969 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
8970 if (pipe->pipe_settings.capture.primary_binary[i].info &&
8971 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
8972 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
8973 break;
8974 }
8975 }
8976 } else if (pipe->config.default_capture_config.mode ==
8977 IA_CSS_CAPTURE_MODE_ADVANCED ||
8978 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
8979 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
8980 if (pipe->pipe_settings.capture.pre_isp_binary.info &&
8981 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
8982 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
8983 }
8984 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
8985 if (need_input_queue)
8986 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
8987 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
8988 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
8989 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
8990 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
8991 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
8992 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
8993 if (pipe->pipe_settings.video.video_binary.info &&
8994 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
8995 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
8996 if (pipe->pipe_settings.video.video_binary.info &&
8997 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
8998 ))
8999 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
9000 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
9001 if (need_input_queue)
9002 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
9003 if (!pipe->stream->config.continuous)
9004 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
9005 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
9006 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
9007 unsigned int idx;
9008
9009 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
9010 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
9011 if (pipe->enable_viewfinder[idx])
9012 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
9013 }
9014 if (need_input_queue)
9015 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
9016 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
9017 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
9018 }
9019 IA_CSS_LEAVE("");
9020 }
9021
9022
9023 int
ia_css_unlock_raw_frame(struct ia_css_stream * stream,uint32_t exp_id)9024 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id)
9025 {
9026 int ret;
9027
9028 IA_CSS_ENTER("");
9029
9030 /*
9031 * Only continuous streams have a tagger to which we can send the
9032 * unlock message.
9033 */
9034 if (!stream || !stream->config.continuous) {
9035 IA_CSS_ERROR("invalid stream pointer");
9036 return -EINVAL;
9037 }
9038
9039 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
9040 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) {
9041 IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id);
9042 return -EINVAL;
9043 }
9044
9045 /*
9046 * Send the event. Since we verified that the exp_id is valid,
9047 * we can safely assign it to an 8-bit argument here.
9048 */
9049 ret = ia_css_bufq_enqueue_psys_event(
9050 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
9051
9052 IA_CSS_LEAVE_ERR(ret);
9053 return ret;
9054 }
9055
9056 static void
sh_css_hmm_buffer_record_init(void)9057 sh_css_hmm_buffer_record_init(void)
9058 {
9059 int i;
9060
9061 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++)
9062 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
9063 }
9064
9065 static void
sh_css_hmm_buffer_record_uninit(void)9066 sh_css_hmm_buffer_record_uninit(void)
9067 {
9068 int i;
9069 struct sh_css_hmm_buffer_record *buffer_record = NULL;
9070
9071 buffer_record = &hmm_buffer_record[0];
9072 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
9073 if (buffer_record->in_use) {
9074 if (buffer_record->h_vbuf)
9075 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
9076 sh_css_hmm_buffer_record_reset(buffer_record);
9077 }
9078 buffer_record++;
9079 }
9080 }
9081
9082 static void
sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record * buffer_record)9083 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record)
9084 {
9085 assert(buffer_record);
9086 buffer_record->in_use = false;
9087 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
9088 buffer_record->h_vbuf = NULL;
9089 buffer_record->kernel_ptr = 0;
9090 }
9091
9092 static struct sh_css_hmm_buffer_record
sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle * h_vbuf,enum ia_css_buffer_type type,hrt_address kernel_ptr)9093 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
9094 enum ia_css_buffer_type type,
9095 hrt_address kernel_ptr)
9096 {
9097 int i;
9098 struct sh_css_hmm_buffer_record *buffer_record = NULL;
9099 struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
9100
9101 assert(h_vbuf);
9102 assert((type > IA_CSS_BUFFER_TYPE_INVALID) &&
9103 (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
9104 assert(kernel_ptr != 0);
9105
9106 buffer_record = &hmm_buffer_record[0];
9107 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
9108 if (!buffer_record->in_use) {
9109 buffer_record->in_use = true;
9110 buffer_record->type = type;
9111 buffer_record->h_vbuf = h_vbuf;
9112 buffer_record->kernel_ptr = kernel_ptr;
9113 out_buffer_record = buffer_record;
9114 break;
9115 }
9116 buffer_record++;
9117 }
9118
9119 return out_buffer_record;
9120 }
9121
9122 static struct sh_css_hmm_buffer_record
sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,enum ia_css_buffer_type type)9123 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
9124 enum ia_css_buffer_type type)
9125 {
9126 int i;
9127 struct sh_css_hmm_buffer_record *buffer_record = NULL;
9128 bool found_record = false;
9129
9130 buffer_record = &hmm_buffer_record[0];
9131 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
9132 if ((buffer_record->in_use) &&
9133 (buffer_record->type == type) &&
9134 (buffer_record->h_vbuf) &&
9135 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
9136 found_record = true;
9137 break;
9138 }
9139 buffer_record++;
9140 }
9141
9142 if (found_record)
9143 return buffer_record;
9144 else
9145 return NULL;
9146 }
9147