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