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