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