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