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