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