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