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(
3228 const struct ia_css_stream_config *config)
3229{
3230 assert(config);
3231 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR)
3232 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3233 return 1;
3234
3235 return 0;
3236}
3237
3238static unsigned int
3239get_crop_columns_for_bayer_order(
3240 const struct ia_css_stream_config *config)
3241{
3242 assert(config);
3243 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB)
3244 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3245 return 1;
3246
3247 return 0;
3248}
3249
3250
3251
3252static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
3253 unsigned int *extra_row, unsigned int *extra_column)
3254{
3255 enum ia_css_pipe_id pipe_id = pipe->mode;
3256 unsigned int left_cropping = 0, top_cropping = 0;
3257 unsigned int i;
3258 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
3259
3260
3261
3262
3263
3264 switch (pipe_id) {
3265 case IA_CSS_PIPE_ID_PREVIEW:
3266 if (pipe->pipe_settings.preview.preview_binary.info) {
3267 left_cropping =
3268 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
3269 top_cropping =
3270 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
3271 }
3272 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
3273 break;
3274 case IA_CSS_PIPE_ID_VIDEO:
3275 if (pipe->pipe_settings.video.video_binary.info) {
3276 left_cropping =
3277 pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
3278 top_cropping =
3279 pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
3280 }
3281 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
3282 break;
3283 case IA_CSS_PIPE_ID_CAPTURE:
3284 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
3285 if (pipe->pipe_settings.capture.primary_binary[i].info) {
3286 left_cropping +=
3287 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
3288 top_cropping +=
3289 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
3290 }
3291 dvs_env.width +=
3292 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
3293 dvs_env.height +=
3294 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
3295 }
3296 break;
3297 default:
3298 break;
3299 }
3300
3301 *extra_row = top_cropping + dvs_env.height;
3302 *extra_column = left_cropping + dvs_env.width;
3303}
3304
3305void
3306ia_css_get_crop_offsets(
3307 struct ia_css_pipe *pipe,
3308 struct ia_css_frame_info *in_frame)
3309{
3310 unsigned int row = 0;
3311 unsigned int column = 0;
3312 struct ia_css_resolution *input_res;
3313 struct ia_css_resolution *effective_res;
3314 unsigned int extra_row = 0, extra_col = 0;
3315 unsigned int min_reqd_height, min_reqd_width;
3316
3317 assert(pipe);
3318 assert(pipe->stream);
3319 assert(in_frame);
3320
3321 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3322 pipe, pipe->config.input_effective_res.width,
3323 pipe->config.input_effective_res.height);
3324
3325 input_res = &pipe->stream->config.input_config.input_res;
3326#ifndef ISP2401
3327 effective_res = &pipe->stream->config.input_config.effective_res;
3328#else
3329 effective_res = &pipe->config.input_effective_res;
3330#endif
3331
3332 get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
3333
3334 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
3335
3336 min_reqd_height = effective_res->height + extra_row;
3337 min_reqd_width = effective_res->width + extra_col;
3338
3339 if (input_res->height > min_reqd_height) {
3340 row = (input_res->height - min_reqd_height) / 2;
3341 row &= ~0x1;
3342 }
3343 if (input_res->width > min_reqd_width) {
3344 column = (input_res->width - min_reqd_width) / 2;
3345 column &= ~0x1;
3346 }
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357 column += get_crop_columns_for_bayer_order(&pipe->stream->config);
3358 row += get_crop_lines_for_bayer_order(&pipe->stream->config);
3359
3360 in_frame->crop_info.start_column = column;
3361 in_frame->crop_info.start_line = row;
3362
3363 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
3364
3365 return;
3366}
3367#endif
3368
3369static int
3370init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
3371 struct ia_css_frame *frame, enum ia_css_frame_format format)
3372{
3373 struct ia_css_frame *in_frame;
3374 int err = 0;
3375 unsigned int thread_id;
3376 enum sh_css_queue_id queue_id;
3377
3378 assert(frame);
3379 in_frame = frame;
3380
3381 in_frame->info.format = format;
3382
3383#ifdef ISP2401
3384 if (format == IA_CSS_FRAME_FORMAT_RAW)
3385 in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ?
3386 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3387#endif
3388
3389 in_frame->info.res.width = pipe->stream->config.input_config.input_res.width;
3390 in_frame->info.res.height = pipe->stream->config.input_config.input_res.height;
3391 in_frame->info.raw_bit_depth =
3392 ia_css_pipe_util_pipe_input_format_bpp(pipe);
3393 ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0);
3394 in_frame->contiguous = false;
3395 in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3396 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3397 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3398 in_frame->dynamic_queue_id = queue_id;
3399 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3400#ifdef ISP2401
3401 ia_css_get_crop_offsets(pipe, &in_frame->info);
3402#endif
3403 err = ia_css_frame_init_planes(in_frame);
3404
3405 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3406 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order);
3407
3408 return err;
3409}
3410
3411static int
3412init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3413 struct ia_css_frame *out_frame, unsigned int idx)
3414{
3415 int err = 0;
3416 unsigned int thread_id;
3417 enum sh_css_queue_id queue_id;
3418
3419 assert(out_frame);
3420
3421 sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx);
3422 out_frame->contiguous = false;
3423 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3424 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3425 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3426 out_frame->dynamic_queue_id = queue_id;
3427 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3428 err = ia_css_frame_init_planes(out_frame);
3429
3430 return err;
3431}
3432
3433
3434static int create_host_video_pipeline(struct ia_css_pipe *pipe)
3435{
3436 struct ia_css_pipeline_stage_desc stage_desc;
3437 struct ia_css_binary *copy_binary, *video_binary,
3438 *yuv_scaler_binary, *vf_pp_binary;
3439 struct ia_css_pipeline_stage *copy_stage = NULL;
3440 struct ia_css_pipeline_stage *video_stage = NULL;
3441 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
3442 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3443 struct ia_css_pipeline *me;
3444 struct ia_css_frame *in_frame = NULL;
3445 struct ia_css_frame *out_frame;
3446 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3447 struct ia_css_frame *vf_frame = NULL;
3448 int err = 0;
3449 bool need_copy = false;
3450 bool need_vf_pp = false;
3451 bool need_yuv_pp = false;
3452 bool need_in_frameinfo_memory = false;
3453
3454 unsigned int i, num_yuv_scaler;
3455 bool *is_output_stage = NULL;
3456
3457 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3458 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3459 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3460 return -EINVAL;
3461 }
3462 ia_css_pipe_util_create_output_frames(out_frames);
3463 out_frame = &pipe->out_frame_struct;
3464
3465
3466 me = &pipe->pipeline;
3467 ia_css_pipeline_clean(me);
3468
3469 me->dvs_frame_delay = pipe->dvs_frame_delay;
3470
3471#ifdef ISP2401
3472
3473
3474
3475 need_in_frameinfo_memory = !(pipe->stream->config.online ||
3476 pipe->stream->config.continuous);
3477#else
3478
3479 need_in_frameinfo_memory = pipe->stream->config.mode ==
3480 IA_CSS_INPUT_MODE_MEMORY;
3481#endif
3482
3483
3484 if (need_in_frameinfo_memory) {
3485 in_frame = &pipe->in_frame_struct;
3486 err = init_in_frameinfo_memory_defaults(pipe, in_frame,
3487 IA_CSS_FRAME_FORMAT_RAW);
3488 if (err)
3489 goto ERR;
3490 }
3491
3492 out_frame->data = 0;
3493 err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3494 if (err)
3495 goto ERR;
3496
3497 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3498 vf_frame = &pipe->vf_frame_struct;
3499 vf_frame->data = 0;
3500 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3501 if (err)
3502 goto ERR;
3503 }
3504
3505 copy_binary = &pipe->pipe_settings.video.copy_binary;
3506 video_binary = &pipe->pipe_settings.video.video_binary;
3507 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3508
3509 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3510 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler;
3511 is_output_stage = pipe->pipe_settings.video.is_output_stage;
3512
3513 need_copy = (copy_binary && copy_binary->info);
3514 need_vf_pp = (vf_pp_binary && vf_pp_binary->info);
3515 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
3516
3517 if (need_copy) {
3518 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3519 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3520 out_frames, NULL, NULL);
3521 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3522 ©_stage);
3523 if (err)
3524 goto ERR;
3525 in_frame = me->stages->args.out_frame[0];
3526 } else if (pipe->stream->config.continuous) {
3527#ifdef ISP2401
3528
3529
3530
3531 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3532#else
3533 in_frame = pipe->continuous_frames[0];
3534#endif
3535 }
3536
3537 ia_css_pipe_util_set_output_frames(out_frames, 0,
3538 need_yuv_pp ? NULL : out_frame);
3539
3540
3541
3542 if (need_vf_pp) {
3543 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3544 out_frames, in_frame, NULL);
3545 } else {
3546 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3547 out_frames, in_frame, vf_frame);
3548 }
3549 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3550 &video_stage);
3551 if (err)
3552 goto ERR;
3553
3554
3555 if (video_stage) {
3556 video_stage->args.copy_vf =
3557 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3558 video_stage->args.copy_output = video_stage->args.copy_vf;
3559 }
3560
3561
3562
3563 if (need_vf_pp && video_stage) {
3564 in_frame = video_stage->args.out_vf_frame;
3565 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3566 &vf_pp_stage);
3567 if (err)
3568 goto ERR;
3569 }
3570 if (video_stage) {
3571 int frm;
3572
3573 for (frm = 0; frm < NUM_TNR_FRAMES; frm++) {
3574 video_stage->args.tnr_frames[frm] =
3575 pipe->pipe_settings.video.tnr_frames[frm];
3576 }
3577 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3578 video_stage->args.delay_frames[frm] =
3579 pipe->pipe_settings.video.delay_frames[frm];
3580 }
3581 }
3582
3583
3584 if (!need_vf_pp && video_stage && pipe->config.acc_extension &&
3585 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT)) {
3586 struct ia_css_frame *out = NULL;
3587 struct ia_css_frame *in = NULL;
3588
3589 if ((pipe->config.acc_extension->info.isp.sp.enable.output) &&
3590 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) &&
3591 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) {
3592
3593 out = video_stage->args.out_frame[0];
3594 err = ia_css_frame_allocate_from_info(&in, &pipe->output_info[0]);
3595 if (err)
3596 goto ERR;
3597 video_stage->args.out_frame[0] = in;
3598 }
3599
3600 err = add_firmwares(me, video_binary, pipe->output_stage,
3601 last_output_firmware(pipe->output_stage),
3602 IA_CSS_BINARY_MODE_VIDEO,
3603 in, out, NULL, &video_stage, NULL);
3604 if (err)
3605 goto ERR;
3606 }
3607
3608 if (need_yuv_pp && video_stage) {
3609 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3610 struct ia_css_frame *tmp_out_frame = NULL;
3611
3612 for (i = 0; i < num_yuv_scaler; i++) {
3613 tmp_out_frame = is_output_stage[i] ? out_frame : NULL;
3614
3615 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
3616 tmp_out_frame, NULL,
3617 &yuv_scaler_binary[i],
3618 &yuv_scaler_stage);
3619
3620 if (err) {
3621 IA_CSS_LEAVE_ERR_PRIVATE(err);
3622 return err;
3623 }
3624
3625 if (yuv_scaler_stage)
3626 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3627 }
3628 }
3629
3630 pipe->pipeline.acquire_isp_each_stage = false;
3631 ia_css_pipeline_finalize_stages(&pipe->pipeline,
3632 pipe->stream->config.continuous);
3633
3634ERR:
3635 IA_CSS_LEAVE_ERR_PRIVATE(err);
3636 return err;
3637}
3638
3639static int
3640create_host_acc_pipeline(struct ia_css_pipe *pipe)
3641{
3642 int err = 0;
3643 const struct ia_css_fw_info *fw;
3644 unsigned int i;
3645
3646 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3647 if ((!pipe) || (!pipe->stream)) {
3648 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3649 return -EINVAL;
3650 }
3651
3652 pipe->pipeline.num_execs = pipe->config.acc_num_execs;
3653
3654 if (pipe->config.acc_extension)
3655 pipe->pipeline.pipe_qos_config = 0;
3656
3657 fw = pipe->vf_stage;
3658 for (i = 0; fw; fw = fw->next) {
3659 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3660 if (err)
3661 goto ERR;
3662 }
3663
3664 for (i = 0; i < pipe->config.num_acc_stages; i++) {
3665 struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
3666
3667 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3668 if (err)
3669 goto ERR;
3670 }
3671
3672 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3673
3674ERR:
3675 IA_CSS_LEAVE_ERR_PRIVATE(err);
3676 return err;
3677}
3678
3679
3680static int
3681create_host_preview_pipeline(struct ia_css_pipe *pipe)
3682{
3683 struct ia_css_pipeline_stage *copy_stage = NULL;
3684 struct ia_css_pipeline_stage *preview_stage = NULL;
3685 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3686 struct ia_css_pipeline_stage_desc stage_desc;
3687 struct ia_css_pipeline *me = NULL;
3688 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3689 struct ia_css_frame *in_frame = NULL;
3690 int err = 0;
3691 struct ia_css_frame *out_frame;
3692 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3693 bool need_in_frameinfo_memory = false;
3694#ifdef ISP2401
3695 bool sensor = false;
3696 bool buffered_sensor = false;
3697 bool online = false;
3698 bool continuous = false;
3699#endif
3700
3701 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3702 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3703 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3704 return -EINVAL;
3705 }
3706
3707 ia_css_pipe_util_create_output_frames(out_frames);
3708
3709 me = &pipe->pipeline;
3710 ia_css_pipeline_clean(me);
3711
3712#ifdef ISP2401
3713
3714
3715
3716
3717
3718
3719
3720 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3721 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3722 online = pipe->stream->config.online;
3723 continuous = pipe->stream->config.continuous;
3724 need_in_frameinfo_memory =
3725 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
3726#else
3727
3728 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3729#endif
3730 if (need_in_frameinfo_memory) {
3731 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
3732 IA_CSS_FRAME_FORMAT_RAW);
3733 if (err)
3734 goto ERR;
3735
3736 in_frame = &me->in_frame;
3737 } else {
3738 in_frame = NULL;
3739 }
3740
3741 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3742 if (err)
3743 goto ERR;
3744 out_frame = &me->out_frame[0];
3745
3746 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3747 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3748 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3749 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3750
3751 if (pipe->pipe_settings.preview.copy_binary.info) {
3752 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3753 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3754 out_frames, NULL, NULL);
3755 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3756 ©_stage);
3757 if (err)
3758 goto ERR;
3759 in_frame = me->stages->args.out_frame[0];
3760 } else if (pipe->stream->config.continuous) {
3761#ifdef ISP2401
3762
3763
3764
3765 if (continuous || !online)
3766 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3767
3768#else
3769 in_frame = pipe->continuous_frames[0];
3770#endif
3771 }
3772
3773 if (vf_pp_binary) {
3774 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3775 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3776 out_frames, in_frame, NULL);
3777 } else {
3778 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3779 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3780 out_frames, in_frame, NULL);
3781 }
3782 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3783 &preview_stage);
3784 if (err)
3785 goto ERR;
3786
3787 preview_stage->args.copy_vf =
3788 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3789 preview_stage->args.copy_output = !preview_stage->args.copy_vf;
3790 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) {
3791
3792 preview_stage->args.out_vf_frame =
3793 preview_stage->args.out_frame[0];
3794 }
3795 if (vf_pp_binary) {
3796 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
3797 in_frame = preview_stage->args.out_vf_frame;
3798 else
3799 in_frame = preview_stage->args.out_frame[0];
3800 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
3801 &vf_pp_stage);
3802 if (err)
3803 goto ERR;
3804 }
3805
3806 pipe->pipeline.acquire_isp_each_stage = false;
3807 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3808
3809ERR:
3810 IA_CSS_LEAVE_ERR_PRIVATE(err);
3811 return err;
3812}
3813
3814static void send_raw_frames(struct ia_css_pipe *pipe)
3815{
3816 if (pipe->stream->config.continuous) {
3817 unsigned int i;
3818
3819 sh_css_update_host2sp_cont_num_raw_frames
3820 (pipe->stream->config.init_num_cont_raw_buf, true);
3821 sh_css_update_host2sp_cont_num_raw_frames
3822 (pipe->stream->config.target_num_cont_raw_buf, false);
3823
3824
3825 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
3826 sh_css_update_host2sp_offline_frame(i,
3827 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
3828 }
3829 }
3830
3831 return;
3832}
3833
3834static int
3835preview_start(struct ia_css_pipe *pipe)
3836{
3837 int err = 0;
3838 struct ia_css_pipe *copy_pipe, *capture_pipe;
3839 struct ia_css_pipe *acc_pipe;
3840 enum sh_css_pipe_config_override copy_ovrd;
3841 enum ia_css_input_mode preview_pipe_input_mode;
3842 const struct ia_css_coordinate *coord = NULL;
3843 const struct ia_css_isp_parameters *params = NULL;
3844
3845 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3846 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3847 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3848 return -EINVAL;
3849 }
3850
3851 preview_pipe_input_mode = pipe->stream->config.mode;
3852
3853 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
3854 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
3855 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
3856
3857 sh_css_metrics_start_frame();
3858
3859
3860 err = send_mipi_frames(pipe);
3861 if (err) {
3862 IA_CSS_LEAVE_ERR_PRIVATE(err);
3863 return err;
3864 }
3865 send_raw_frames(pipe);
3866
3867 {
3868 unsigned int thread_id;
3869
3870 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3871 copy_ovrd = 1 << thread_id;
3872
3873 if (pipe->stream->cont_capt) {
3874 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
3875 &thread_id);
3876 copy_ovrd |= 1 << thread_id;
3877 }
3878 }
3879
3880 if (IS_ISP2401) {
3881 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
3882 params = pipe->stream->isp_params_configs;
3883 }
3884
3885
3886 if (pipe->stream->config.continuous) {
3887 sh_css_sp_init_pipeline(©_pipe->pipeline,
3888 IA_CSS_PIPE_ID_COPY,
3889 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
3890 false,
3891 pipe->stream->config.pixels_per_clock == 2, false,
3892 false, pipe->required_bds_factor,
3893 copy_ovrd,
3894 pipe->stream->config.mode,
3895 &pipe->stream->config.metadata_config,
3896 &pipe->stream->info.metadata_info,
3897 pipe->stream->config.source.port.port,
3898 coord,
3899 params);
3900
3901
3902
3903 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
3904 }
3905
3906
3907 if (pipe->stream->cont_capt) {
3908 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
3909 IA_CSS_PIPE_ID_CAPTURE,
3910 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
3911 capture_pipe->config.default_capture_config.enable_xnr != 0,
3912 capture_pipe->stream->config.pixels_per_clock == 2,
3913 true,
3914 false,
3915 capture_pipe->required_bds_factor,
3916 0,
3917 IA_CSS_INPUT_MODE_MEMORY,
3918 &pipe->stream->config.metadata_config,
3919 &pipe->stream->info.metadata_info,
3920 (enum mipi_port_id)0,
3921 coord,
3922 params);
3923 }
3924
3925 if (acc_pipe) {
3926 sh_css_sp_init_pipeline(&acc_pipe->pipeline,
3927 IA_CSS_PIPE_ID_ACC,
3928 (uint8_t)ia_css_pipe_get_pipe_num(acc_pipe),
3929 false,
3930 pipe->stream->config.pixels_per_clock == 2,
3931 false,
3932 false,
3933 pipe->required_bds_factor,
3934 0,
3935 IA_CSS_INPUT_MODE_MEMORY,
3936 NULL,
3937 NULL,
3938 (enum mipi_port_id)0,
3939 coord,
3940 params);
3941 }
3942
3943 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
3944
3945 IA_CSS_LEAVE_ERR_PRIVATE(err);
3946 return err;
3947}
3948
3949int
3950ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
3951 const struct ia_css_buffer *buffer)
3952{
3953 int return_err = 0;
3954 unsigned int thread_id;
3955 enum sh_css_queue_id queue_id;
3956 struct ia_css_pipeline *pipeline;
3957 struct ia_css_pipeline_stage *stage;
3958 struct ia_css_rmgr_vbuf_handle p_vbuf;
3959 struct ia_css_rmgr_vbuf_handle *h_vbuf;
3960 struct sh_css_hmm_buffer ddr_buffer;
3961 enum ia_css_buffer_type buf_type;
3962 enum ia_css_pipe_id pipe_id;
3963 bool ret_err;
3964
3965 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
3966
3967 if ((!pipe) || (!buffer)) {
3968 IA_CSS_LEAVE_ERR(-EINVAL);
3969 return -EINVAL;
3970 }
3971
3972 buf_type = buffer->type;
3973
3974
3975#if 0
3976 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
3977 bool found_pipe = false;
3978
3979 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
3980 if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) &&
3981 (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) {
3982 buf_type += i;
3983 found_pipe = true;
3984 break;
3985 }
3986 }
3987 if (!found_pipe)
3988 return -EINVAL;
3989 }
3990 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) {
3991 bool found_pipe = false;
3992
3993 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
3994 if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) &&
3995 (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) {
3996 buf_type += i;
3997 found_pipe = true;
3998 break;
3999 }
4000 }
4001 if (!found_pipe)
4002 return -EINVAL;
4003 }
4004#endif
4005 pipe_id = pipe->mode;
4006
4007 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4008
4009 assert(pipe_id < IA_CSS_PIPE_ID_NUM);
4010 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
4011 if (buf_type == IA_CSS_BUFFER_TYPE_INVALID ||
4012 buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE ||
4013 pipe_id >= IA_CSS_PIPE_ID_NUM) {
4014 IA_CSS_LEAVE_ERR(-EINVAL);
4015 return -EINVAL;
4016 }
4017
4018 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4019 if (!ret_err) {
4020 IA_CSS_LEAVE_ERR(-EINVAL);
4021 return -EINVAL;
4022 }
4023
4024 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4025 if (!ret_err) {
4026 IA_CSS_LEAVE_ERR(-EINVAL);
4027 return -EINVAL;
4028 }
4029
4030 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
4031 IA_CSS_LEAVE_ERR(-EINVAL);
4032 return -EINVAL;
4033 }
4034
4035 if (!sh_css_sp_is_running()) {
4036 IA_CSS_LOG("SP is not running!");
4037 IA_CSS_LEAVE_ERR(-EBUSY);
4038
4039 return -EBUSY;
4040 }
4041
4042 pipeline = &pipe->pipeline;
4043
4044 assert(pipeline ||
4045 pipe_id == IA_CSS_PIPE_ID_COPY ||
4046 pipe_id == IA_CSS_PIPE_ID_ACC);
4047
4048 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr));
4049 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
4050 ddr_buffer.cookie_ptr = buffer->driver_cookie;
4051 ddr_buffer.timing_data = buffer->timing_data;
4052
4053 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) {
4054 if (!buffer->data.stats_3a) {
4055 IA_CSS_LEAVE_ERR(-EINVAL);
4056 return -EINVAL;
4057 }
4058 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
4059 ddr_buffer.payload.s3a = *buffer->data.stats_3a;
4060 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) {
4061 if (!buffer->data.stats_dvs) {
4062 IA_CSS_LEAVE_ERR(-EINVAL);
4063 return -EINVAL;
4064 }
4065 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
4066 ddr_buffer.payload.dis = *buffer->data.stats_dvs;
4067 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
4068 if (!buffer->data.metadata) {
4069 IA_CSS_LEAVE_ERR(-EINVAL);
4070 return -EINVAL;
4071 }
4072 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
4073 ddr_buffer.payload.metadata = *buffer->data.metadata;
4074 } else if (buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME ||
4075 buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
4076 buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME ||
4077 buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME ||
4078 buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME) {
4079 if (!buffer->data.frame) {
4080 IA_CSS_LEAVE_ERR(-EINVAL);
4081 return -EINVAL;
4082 }
4083 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame);
4084 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
4085 ddr_buffer.payload.frame.flashed = 0;
4086
4087 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4088 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4089 buf_type, buffer->data.frame->data);
4090
4091#if CONFIG_ON_FRAME_ENQUEUE()
4092 return_err = set_config_on_frame_enqueue(
4093 &buffer->data.frame->info,
4094 &ddr_buffer.payload.frame);
4095 if (return_err) {
4096 IA_CSS_LEAVE_ERR(return_err);
4097 return return_err;
4098 }
4099#endif
4100 }
4101
4102
4103 p_vbuf.vptr = 0;
4104 p_vbuf.count = 0;
4105 p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
4106 h_vbuf = &p_vbuf;
4107
4108 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
4109
4110 if ((!h_vbuf) || (h_vbuf->vptr == 0x0)) {
4111 IA_CSS_LEAVE_ERR(-EINVAL);
4112 return -EINVAL;
4113 }
4114
4115 hmm_store(h_vbuf->vptr,
4116 (void *)(&ddr_buffer),
4117 sizeof(struct sh_css_hmm_buffer));
4118 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS ||
4119 buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS ||
4120 buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS) {
4121 if (!pipeline) {
4122 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4123 IA_CSS_LOG("pipeline is empty!");
4124 IA_CSS_LEAVE_ERR(-EINVAL);
4125 return -EINVAL;
4126 }
4127
4128 for (stage = pipeline->stages; stage; stage = stage->next) {
4129
4130
4131 if (STATS_ENABLED(stage)) {
4132
4133 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4134 queue_id,
4135 (uint32_t)h_vbuf->vptr);
4136 }
4137 }
4138 } else if (buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME ||
4139 buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
4140 buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME ||
4141 buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME ||
4142 buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME ||
4143 buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
4144 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4145 queue_id,
4146 (uint32_t)h_vbuf->vptr);
4147#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4148 if (!return_err &&
4149 buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4150 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
4151 ddr_buffer.payload.frame.frame_data,
4152 queue_id, thread_id);
4153 }
4154#endif
4155 }
4156
4157 if (!return_err) {
4158 if (sh_css_hmm_buffer_record_acquire(
4159 h_vbuf, buf_type,
4160 HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4161 IA_CSS_LOG("send vbuf=%p", h_vbuf);
4162 } else {
4163 return_err = -EINVAL;
4164 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
4165 }
4166 }
4167
4168
4169
4170
4171
4172 if (!return_err) {
4173 if (!sh_css_sp_is_running()) {
4174
4175 IA_CSS_LOG("SP is not running!");
4176 IA_CSS_LEAVE_ERR(-EBUSY);
4177 return -EBUSY;
4178 }
4179 return_err = ia_css_bufq_enqueue_psys_event(
4180 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
4181 (uint8_t)thread_id,
4182 queue_id,
4183 0);
4184 } else {
4185 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4186 IA_CSS_ERROR("buffer not enqueued");
4187 }
4188
4189 IA_CSS_LEAVE("return value = %d", return_err);
4190
4191 return return_err;
4192}
4193
4194
4195
4196
4197int
4198ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
4199 struct ia_css_buffer *buffer)
4200{
4201 int return_err;
4202 enum sh_css_queue_id queue_id;
4203 ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0;
4204 struct sh_css_hmm_buffer ddr_buffer;
4205 enum ia_css_buffer_type buf_type;
4206 enum ia_css_pipe_id pipe_id;
4207 unsigned int thread_id;
4208 hrt_address kernel_ptr = 0;
4209 bool ret_err;
4210
4211 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4212
4213 if ((!pipe) || (!buffer)) {
4214 IA_CSS_LEAVE_ERR(-EINVAL);
4215 return -EINVAL;
4216 }
4217
4218 pipe_id = pipe->mode;
4219
4220 buf_type = buffer->type;
4221
4222 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4223
4224 ddr_buffer.kernel_ptr = 0;
4225
4226 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4227 if (!ret_err) {
4228 IA_CSS_LEAVE_ERR(-EINVAL);
4229 return -EINVAL;
4230 }
4231
4232 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4233 if (!ret_err) {
4234 IA_CSS_LEAVE_ERR(-EINVAL);
4235 return -EINVAL;
4236 }
4237
4238 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
4239 IA_CSS_LEAVE_ERR(-EINVAL);
4240 return -EINVAL;
4241 }
4242
4243 if (!sh_css_sp_is_running()) {
4244 IA_CSS_LOG("SP is not running!");
4245 IA_CSS_LEAVE_ERR(-EBUSY);
4246
4247 return -EBUSY;
4248 }
4249
4250 return_err = ia_css_bufq_dequeue_buffer(queue_id,
4251 (uint32_t *)&ddr_buffer_addr);
4252
4253 if (!return_err) {
4254 struct ia_css_frame *frame;
4255 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
4256
4257 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
4258
4259
4260 hmm_buffer_record = sh_css_hmm_buffer_record_validate(
4261 ddr_buffer_addr, buf_type);
4262 if (hmm_buffer_record) {
4263
4264
4265
4266
4267 kernel_ptr = hmm_buffer_record->kernel_ptr;
4268 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
4269 sh_css_hmm_buffer_record_reset(hmm_buffer_record);
4270 } else {
4271 IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)",
4272 ddr_buffer_addr, buf_type);
4273 IA_CSS_LEAVE_ERR(-EINVAL);
4274 return -EINVAL;
4275 }
4276
4277 hmm_load(ddr_buffer_addr,
4278 &ddr_buffer,
4279 sizeof(struct sh_css_hmm_buffer));
4280
4281
4282
4283
4284 if ((ddr_buffer.kernel_ptr == 0) ||
4285 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4286 IA_CSS_ERROR("kernel_ptr invalid");
4287 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
4288 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
4289 IA_CSS_ERROR("buf_type: %d\n", buf_type);
4290 IA_CSS_LEAVE_ERR(-EINVAL);
4291 return -EINVAL;
4292 }
4293
4294 if (ddr_buffer.kernel_ptr != 0) {
4295
4296
4297 buffer->exp_id = 0;
4298 buffer->driver_cookie = ddr_buffer.cookie_ptr;
4299 buffer->timing_data = ddr_buffer.timing_data;
4300
4301 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
4302 buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) {
4303 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
4304 }
4305
4306 switch (buf_type) {
4307 case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
4308 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
4309 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
4310 if (pipe && pipe->stop_requested) {
4311#if !defined(ISP2401)
4312
4313
4314
4315 return_err = free_mipi_frames(pipe);
4316 if (return_err) {
4317 IA_CSS_LOG("free_mipi_frames() failed");
4318 IA_CSS_LEAVE_ERR(return_err);
4319 return return_err;
4320 }
4321#endif
4322 pipe->stop_requested = false;
4323 }
4324 fallthrough;
4325 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
4326 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
4327 frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4328 buffer->data.frame = frame;
4329 buffer->exp_id = ddr_buffer.payload.frame.exp_id;
4330 frame->exp_id = ddr_buffer.payload.frame.exp_id;
4331 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
4332 if (ddr_buffer.payload.frame.flashed == 1)
4333 frame->flash_state =
4334 IA_CSS_FRAME_FLASH_STATE_PARTIAL;
4335 if (ddr_buffer.payload.frame.flashed == 2)
4336 frame->flash_state =
4337 IA_CSS_FRAME_FLASH_STATE_FULL;
4338 frame->valid = pipe->num_invalid_frames == 0;
4339 if (!frame->valid)
4340 pipe->num_invalid_frames--;
4341
4342 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
4343#ifdef ISP2401
4344 frame->planes.binary.size = frame->data_bytes;
4345#else
4346 frame->planes.binary.size =
4347 sh_css_sp_get_binary_copy_size();
4348#endif
4349 }
4350#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4351 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4352 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4353 frame->data, frame->isp_config_id, thread_id);
4354 }
4355#endif
4356
4357 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4358 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4359 buf_type, buffer->data.frame->data);
4360
4361 break;
4362 case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
4363 buffer->data.stats_3a =
4364 (struct ia_css_isp_3a_statistics *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4365 buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
4366 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
4367 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
4368 break;
4369 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
4370 buffer->data.stats_dvs =
4371 (struct ia_css_isp_dvs_statistics *)
4372 HOST_ADDRESS(ddr_buffer.kernel_ptr);
4373 buffer->exp_id = ddr_buffer.payload.dis.exp_id;
4374 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
4375 break;
4376 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
4377 break;
4378 case IA_CSS_BUFFER_TYPE_METADATA:
4379 buffer->data.metadata =
4380 (struct ia_css_metadata *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4381 buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
4382 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
4383 break;
4384 default:
4385 return_err = -EINVAL;
4386 break;
4387 }
4388 }
4389 }
4390
4391
4392
4393
4394
4395 if (!return_err) {
4396 if (!sh_css_sp_is_running()) {
4397 IA_CSS_LOG("SP is not running!");
4398 IA_CSS_LEAVE_ERR(-EBUSY);
4399
4400 return -EBUSY;
4401 }
4402 ia_css_bufq_enqueue_psys_event(
4403 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
4404 0,
4405 queue_id,
4406 0);
4407 }
4408 IA_CSS_LEAVE("buffer=%p", buffer);
4409
4410 return return_err;
4411}
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
4424 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE,
4425 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE,
4426 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE,
4427 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE,
4428 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE,
4429 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE,
4430 IA_CSS_EVENT_TYPE_PIPELINE_DONE,
4431 IA_CSS_EVENT_TYPE_FRAME_TAGGED,
4432 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE,
4433 IA_CSS_EVENT_TYPE_METADATA_DONE,
4434 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE,
4435 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE,
4436 IA_CSS_EVENT_TYPE_TIMER,
4437 IA_CSS_EVENT_TYPE_PORT_EOF,
4438 IA_CSS_EVENT_TYPE_FW_WARNING,
4439 IA_CSS_EVENT_TYPE_FW_ASSERT,
4440 0,
4441};
4442
4443int
4444ia_css_dequeue_event(struct ia_css_event *event)
4445{
4446 return ia_css_dequeue_psys_event(event);
4447}
4448
4449int
4450ia_css_dequeue_psys_event(struct ia_css_event *event)
4451{
4452 enum ia_css_pipe_id pipe_id = 0;
4453 u8 payload[4] = {0, 0, 0, 0};
4454 int ret_err;
4455
4456
4457
4458
4459
4460
4461
4462
4463 if (!event)
4464 return -EINVAL;
4465
4466
4467 if (!sh_css_sp_is_running())
4468 return -EBUSY;
4469
4470
4471 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4472 if (ret_err)
4473 return ret_err;
4474
4475 IA_CSS_LOG("event dequeued from psys event queue");
4476
4477
4478 ia_css_bufq_enqueue_psys_event(
4479 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4480
4481
4482
4483
4484 event->type = convert_event_sp_to_host_domain[payload[0]];
4485
4486 event->pipe = NULL;
4487 event->port = MIPI_PORT0_ID;
4488 event->exp_id = 0;
4489 event->fw_warning = IA_CSS_FW_WARNING_NONE;
4490 event->fw_handle = 0;
4491 event->timer_data = 0;
4492 event->timer_code = 0;
4493 event->timer_subcode = 0;
4494
4495 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4496
4497 u32 tmp_data;
4498
4499 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4500 event->timer_code = payload[2];
4501 payload[0] = payload[1] = payload[2] = payload[3] = 0;
4502 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4503 if (ret_err) {
4504
4505
4506
4507 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4508 return ret_err;
4509 }
4510 ia_css_bufq_enqueue_psys_event(
4511 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4512 event->type = convert_event_sp_to_host_domain[payload[0]];
4513
4514 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4515
4516 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4517 event->timer_data |= (tmp_data << 16);
4518 event->timer_subcode = payload[2];
4519 } else {
4520
4521
4522
4523
4524
4525 event->timer_data = 0;
4526 event->timer_code = 0;
4527 event->timer_subcode = 0;
4528 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4529 }
4530 }
4531 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) {
4532 event->port = (enum mipi_port_id)payload[1];
4533 event->exp_id = payload[3];
4534 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4535 event->fw_warning = (enum ia_css_fw_warning)payload[1];
4536
4537 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
4538 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
4539 event->exp_id = payload[3];
4540 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) {
4541 event->fw_assert_module_id = payload[1];
4542 event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4543
4544 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) {
4545
4546
4547
4548 event->pipe = find_pipe_by_num(payload[1]);
4549 pipe_id = (enum ia_css_pipe_id)payload[2];
4550
4551 if (!event->pipe)
4552 return -EBUSY;
4553
4554 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4555
4556 int i, n;
4557
4558 n = event->pipe->stream->num_pipes;
4559 for (i = 0; i < n; i++) {
4560 struct ia_css_pipe *p =
4561 event->pipe->stream->pipes[i];
4562 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4563 event->pipe = p;
4564 break;
4565 }
4566 }
4567 event->exp_id = payload[3];
4568 }
4569 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4570
4571 u32 stage_num = (uint32_t)payload[3];
4572
4573 ret_err = ia_css_pipeline_get_fw_from_stage(
4574 &event->pipe->pipeline,
4575 stage_num,
4576 &event->fw_handle);
4577 if (ret_err) {
4578 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4579 stage_num);
4580 return ret_err;
4581 }
4582 }
4583 }
4584
4585 if (event->pipe)
4586 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4587 else
4588 IA_CSS_LEAVE("event_id=%d", event->type);
4589
4590 return 0;
4591}
4592
4593int
4594ia_css_dequeue_isys_event(struct ia_css_event *event)
4595{
4596 u8 payload[4] = {0, 0, 0, 0};
4597 int err = 0;
4598
4599
4600
4601
4602 if (!event)
4603 return -EINVAL;
4604
4605
4606 if (!sh_css_sp_is_running())
4607 return -EBUSY;
4608
4609 err = ia_css_bufq_dequeue_isys_event(payload);
4610 if (err)
4611 return err;
4612
4613 IA_CSS_LOG("event dequeued from isys event queue");
4614
4615
4616 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4617
4618
4619 event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4620
4621 event->pipe = NULL;
4622 event->port = payload[1];
4623 event->exp_id = payload[3];
4624
4625 IA_CSS_LEAVE_ERR(err);
4626 return err;
4627}
4628
4629static void
4630acc_start(struct ia_css_pipe *pipe)
4631{
4632 assert(pipe);
4633 assert(pipe->stream);
4634
4635 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
4636 pipe->stream->config.mode);
4637}
4638
4639static int
4640sh_css_pipe_start(struct ia_css_stream *stream)
4641{
4642 int err = 0;
4643
4644 struct ia_css_pipe *pipe;
4645 enum ia_css_pipe_id pipe_id;
4646 unsigned int thread_id;
4647
4648 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4649
4650 if (!stream) {
4651 IA_CSS_LEAVE_ERR(-EINVAL);
4652 return -EINVAL;
4653 }
4654 pipe = stream->last_pipe;
4655 if (!pipe) {
4656 IA_CSS_LEAVE_ERR(-EINVAL);
4657 return -EINVAL;
4658 }
4659
4660 pipe_id = pipe->mode;
4661
4662 if (stream->started) {
4663 IA_CSS_WARNING("Cannot start stream that is already started");
4664 IA_CSS_LEAVE_ERR(err);
4665 return err;
4666 }
4667
4668 pipe->stop_requested = false;
4669
4670 switch (pipe_id) {
4671 case IA_CSS_PIPE_ID_PREVIEW:
4672 err = preview_start(pipe);
4673 break;
4674 case IA_CSS_PIPE_ID_VIDEO:
4675 err = video_start(pipe);
4676 break;
4677 case IA_CSS_PIPE_ID_CAPTURE:
4678 err = capture_start(pipe);
4679 break;
4680 case IA_CSS_PIPE_ID_YUVPP:
4681 err = yuvpp_start(pipe);
4682 break;
4683 case IA_CSS_PIPE_ID_ACC:
4684 acc_start(pipe);
4685 break;
4686 default:
4687 err = -EINVAL;
4688 }
4689
4690 if (!stream->config.continuous) {
4691 int i;
4692
4693 for (i = 1; i < stream->num_pipes && 0 == err ; i++) {
4694 switch (stream->pipes[i]->mode) {
4695 case IA_CSS_PIPE_ID_PREVIEW:
4696 stream->pipes[i]->stop_requested = false;
4697 err = preview_start(stream->pipes[i]);
4698 break;
4699 case IA_CSS_PIPE_ID_VIDEO:
4700 stream->pipes[i]->stop_requested = false;
4701 err = video_start(stream->pipes[i]);
4702 break;
4703 case IA_CSS_PIPE_ID_CAPTURE:
4704 stream->pipes[i]->stop_requested = false;
4705 err = capture_start(stream->pipes[i]);
4706 break;
4707 case IA_CSS_PIPE_ID_YUVPP:
4708 stream->pipes[i]->stop_requested = false;
4709 err = yuvpp_start(stream->pipes[i]);
4710 break;
4711 case IA_CSS_PIPE_ID_ACC:
4712 stream->pipes[i]->stop_requested = false;
4713 acc_start(stream->pipes[i]);
4714 break;
4715 default:
4716 err = -EINVAL;
4717 }
4718 }
4719 }
4720 if (err) {
4721 IA_CSS_LEAVE_ERR_PRIVATE(err);
4722 return err;
4723 }
4724
4725
4726
4727
4728
4729
4730 if (!copy_on_sp(pipe)) {
4731 sh_css_invalidate_params(stream);
4732 err = sh_css_param_update_isp_params(pipe,
4733 stream->isp_params_configs, true, NULL);
4734 if (err) {
4735 IA_CSS_LEAVE_ERR_PRIVATE(err);
4736 return err;
4737 }
4738 }
4739
4740 ia_css_debug_pipe_graph_dump_epilogue();
4741
4742 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4743
4744 if (!sh_css_sp_is_running()) {
4745 IA_CSS_LEAVE_ERR_PRIVATE(-EBUSY);
4746
4747 return -EBUSY;
4748 }
4749 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
4750 (uint8_t)thread_id, 0, 0);
4751
4752
4753 if (!stream->config.continuous) {
4754 int i;
4755
4756 for (i = 1; i < stream->num_pipes; i++) {
4757 ia_css_pipeline_get_sp_thread_id(
4758 ia_css_pipe_get_pipe_num(stream->pipes[i]),
4759 &thread_id);
4760 ia_css_bufq_enqueue_psys_event(
4761 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4762 (uint8_t)thread_id, 0, 0);
4763 }
4764 }
4765
4766
4767 if (pipe->stream->config.continuous) {
4768 struct ia_css_pipe *copy_pipe = NULL;
4769
4770 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4771 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4772 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4773 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4774
4775 if (!copy_pipe) {
4776 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4777 return -EINVAL;
4778 }
4779 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe),
4780 &thread_id);
4781
4782 ia_css_bufq_enqueue_psys_event(
4783 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4784 (uint8_t)thread_id, 0, 0);
4785 }
4786 if (pipe->stream->cont_capt) {
4787 struct ia_css_pipe *capture_pipe = NULL;
4788
4789 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4790 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4791 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4792 capture_pipe = pipe->pipe_settings.video.capture_pipe;
4793
4794 if (!capture_pipe) {
4795 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4796 return -EINVAL;
4797 }
4798 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
4799 &thread_id);
4800
4801 ia_css_bufq_enqueue_psys_event(
4802 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4803 (uint8_t)thread_id, 0, 0);
4804 }
4805
4806
4807 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
4808 struct ia_css_pipe *acc_pipe = NULL;
4809
4810 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
4811
4812 if (acc_pipe) {
4813 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe),
4814 &thread_id);
4815
4816 ia_css_bufq_enqueue_psys_event(
4817 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4818 (uint8_t)thread_id, 0, 0);
4819 }
4820 }
4821
4822 stream->started = true;
4823
4824 IA_CSS_LEAVE_ERR_PRIVATE(err);
4825 return err;
4826}
4827
4828
4829void
4830sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
4831{
4832 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4833 "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
4834
4835 my_css.stop_copy_preview = stop_copy_preview;
4836}
4837
4838bool
4839sh_css_continuous_is_enabled(uint8_t pipe_num)
4840{
4841 struct ia_css_pipe *pipe;
4842 bool continuous;
4843
4844 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4845 "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
4846
4847 pipe = find_pipe_by_num(pipe_num);
4848 continuous = pipe && pipe->stream->config.continuous;
4849 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4850 "sh_css_continuous_is_enabled() leave: enable=%d\n",
4851 continuous);
4852 return continuous;
4853}
4854
4855
4856int
4857ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream,
4858 int *buffer_depth)
4859{
4860 if (!buffer_depth)
4861 return -EINVAL;
4862 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
4863 (void)stream;
4864 *buffer_depth = NUM_CONTINUOUS_FRAMES;
4865 return 0;
4866}
4867
4868int
4869ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
4870{
4871 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth);
4872 (void)stream;
4873 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
4874 return -EINVAL;
4875
4876 stream->config.target_num_cont_raw_buf = buffer_depth;
4877
4878 return 0;
4879}
4880
4881
4882int
4883ia_css_stream_get_buffer_depth(struct ia_css_stream *stream,
4884 int *buffer_depth)
4885{
4886 if (!buffer_depth)
4887 return -EINVAL;
4888 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
4889 (void)stream;
4890 *buffer_depth = stream->config.target_num_cont_raw_buf;
4891 return 0;
4892}
4893
4894
4895
4896
4897
4898
4899
4900
4901static int
4902sh_css_pipes_stop(struct ia_css_stream *stream)
4903{
4904 int err = 0;
4905 struct ia_css_pipe *main_pipe;
4906 enum ia_css_pipe_id main_pipe_id;
4907 int i;
4908
4909 if (!stream) {
4910 IA_CSS_LOG("stream does NOT exist!");
4911 err = -EINVAL;
4912 goto ERR;
4913 }
4914
4915 main_pipe = stream->last_pipe;
4916 if (!main_pipe) {
4917 IA_CSS_LOG("main_pipe does NOT exist!");
4918 err = -EINVAL;
4919 goto ERR;
4920 }
4921
4922 main_pipe_id = main_pipe->mode;
4923 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
4924
4925
4926
4927
4928
4929 for (i = 0; i < stream->num_pipes; i++) {
4930
4931 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
4932 stream->pipes[i]->pipeline.pipe_id);
4933 err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline);
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950 if (err)
4951 goto ERR;
4952 }
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963 if (main_pipe->stream->config.continuous) {
4964 struct ia_css_pipe *copy_pipe = NULL;
4965
4966
4967 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4968 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
4969 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
4970 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
4971
4972
4973 if (!copy_pipe) {
4974 IA_CSS_LOG("Copy Pipe does NOT exist!");
4975 err = -EINVAL;
4976 goto ERR;
4977 }
4978
4979
4980 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
4981 copy_pipe->pipeline.pipe_id);
4982 err = ia_css_pipeline_request_stop(©_pipe->pipeline);
4983 }
4984
4985ERR:
4986 IA_CSS_LEAVE_ERR_PRIVATE(err);
4987 return err;
4988}
4989
4990
4991
4992
4993
4994
4995
4996
4997static bool
4998sh_css_pipes_have_stopped(struct ia_css_stream *stream)
4999{
5000 bool rval = true;
5001
5002 struct ia_css_pipe *main_pipe;
5003 enum ia_css_pipe_id main_pipe_id;
5004
5005 int i;
5006
5007 if (!stream) {
5008 IA_CSS_LOG("stream does NOT exist!");
5009 rval = false;
5010 goto RET;
5011 }
5012
5013 main_pipe = stream->last_pipe;
5014
5015 if (!main_pipe) {
5016 IA_CSS_LOG("main_pipe does NOT exist!");
5017 rval = false;
5018 goto RET;
5019 }
5020
5021 main_pipe_id = main_pipe->mode;
5022 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5023
5024
5025
5026
5027
5028 for (i = 0; i < stream->num_pipes; i++) {
5029 rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline);
5030 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5031 stream->pipes[i]->pipeline.pipe_id,
5032 rval);
5033 }
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044 if (main_pipe->stream->config.continuous) {
5045 struct ia_css_pipe *copy_pipe = NULL;
5046
5047
5048 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5049 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5050 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5051 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5052
5053
5054 if (!copy_pipe) {
5055 IA_CSS_LOG("Copy Pipe does NOT exist!");
5056
5057 rval = false;
5058 goto RET;
5059 }
5060
5061
5062 rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline);
5063 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5064 copy_pipe->pipeline.pipe_id,
5065 rval);
5066 }
5067
5068RET:
5069 IA_CSS_LEAVE_PRIVATE("rval=%d", rval);
5070 return rval;
5071}
5072
5073#if !defined(ISP2401)
5074unsigned int
5075sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
5076{
5077 OP___assert(port < N_CSI_PORTS);
5078 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
5079 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5080 "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
5081 port, idx, my_css.mipi_sizes_for_check[port][idx]);
5082 return my_css.mipi_sizes_for_check[port][idx];
5083}
5084#endif
5085
5086static int sh_css_pipe_configure_output(
5087 struct ia_css_pipe *pipe,
5088 unsigned int width,
5089 unsigned int height,
5090 unsigned int padded_width,
5091 enum ia_css_frame_format format,
5092 unsigned int idx)
5093{
5094 int err = 0;
5095
5096 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, padded width = %d, format = %d, idx = %d",
5097 pipe, width, height, padded_width, format, idx);
5098 if (!pipe) {
5099 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5100 return -EINVAL;
5101 }
5102
5103 err = ia_css_util_check_res(width, height);
5104 if (err) {
5105 IA_CSS_LEAVE_ERR_PRIVATE(err);
5106 return err;
5107 }
5108 if (pipe->output_info[idx].res.width != width ||
5109 pipe->output_info[idx].res.height != height ||
5110 pipe->output_info[idx].format != format) {
5111 ia_css_frame_info_init(
5112 &pipe->output_info[idx],
5113 width,
5114 height,
5115 format,
5116 padded_width);
5117 }
5118 IA_CSS_LEAVE_ERR_PRIVATE(0);
5119 return 0;
5120}
5121
5122static int
5123sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
5124 struct ia_css_shading_info *shading_info,
5125 struct ia_css_pipe_config *pipe_config)
5126{
5127 int err = 0;
5128 struct ia_css_binary *binary = NULL;
5129
5130 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5131 "sh_css_pipe_get_shading_info() enter:\n");
5132
5133 binary = ia_css_pipe_get_shading_correction_binary(pipe);
5134
5135 if (binary) {
5136 err = ia_css_binary_get_shading_info(binary,
5137 IA_CSS_SHADING_CORRECTION_TYPE_1,
5138 pipe->required_bds_factor,
5139 (const struct ia_css_stream_config *)&pipe->stream->config,
5140 shading_info, pipe_config);
5141
5142
5143
5144
5145 } else {
5146
5147
5148
5149
5150
5151 memset(shading_info, 0, sizeof(*shading_info));
5152 }
5153 return err;
5154}
5155
5156static int
5157sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
5158 struct ia_css_grid_info *info)
5159{
5160 int err = 0;
5161 struct ia_css_binary *binary = NULL;
5162
5163 assert(pipe);
5164 assert(info);
5165
5166 IA_CSS_ENTER_PRIVATE("");
5167
5168 binary = ia_css_pipe_get_s3a_binary(pipe);
5169
5170 if (binary) {
5171 err = ia_css_binary_3a_grid_info(binary, info, pipe);
5172 if (err)
5173 goto ERR;
5174 } else {
5175 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
5176 }
5177
5178 binary = ia_css_pipe_get_sdis_binary(pipe);
5179
5180 if (binary) {
5181 ia_css_binary_dvs_grid_info(binary, info, pipe);
5182 ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
5183 } else {
5184 memset(&info->dvs_grid.dvs_grid_info, 0,
5185 sizeof(info->dvs_grid.dvs_grid_info));
5186 memset(&info->dvs_grid.dvs_stat_grid_info, 0,
5187 sizeof(info->dvs_grid.dvs_stat_grid_info));
5188 }
5189
5190 if (binary) {
5191
5192 info->isp_in_width = binary->internal_frame_info.res.width;
5193 info->isp_in_height = binary->internal_frame_info.res.height;
5194 }
5195
5196 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
5197
5198ERR :
5199 IA_CSS_LEAVE_ERR_PRIVATE(err);
5200 return err;
5201}
5202
5203
5204
5205
5206
5207
5208static int
5209ia_css_pipe_check_format(struct ia_css_pipe *pipe,
5210 enum ia_css_frame_format format)
5211{
5212 const enum ia_css_frame_format *supported_formats;
5213 int number_of_formats;
5214 int found = 0;
5215 int i;
5216
5217 IA_CSS_ENTER_PRIVATE("");
5218
5219 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) {
5220 IA_CSS_ERROR("Pipe or binary info is not set");
5221 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5222 return -EINVAL;
5223 }
5224
5225 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
5226 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format);
5227
5228 for (i = 0; i < number_of_formats && !found; i++) {
5229 if (supported_formats[i] == format) {
5230 found = 1;
5231 break;
5232 }
5233 }
5234 if (!found) {
5235 IA_CSS_ERROR("Requested format is not supported by binary");
5236 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5237 return -EINVAL;
5238 }
5239 IA_CSS_LEAVE_ERR_PRIVATE(0);
5240 return 0;
5241}
5242
5243static int load_video_binaries(struct ia_css_pipe *pipe)
5244{
5245 struct ia_css_frame_info video_in_info, tnr_info,
5246 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
5247 bool online;
5248 int err = 0;
5249 bool continuous = pipe->stream->config.continuous;
5250 unsigned int i;
5251 unsigned int num_output_pins;
5252 struct ia_css_frame_info video_bin_out_info;
5253 bool need_scaler = false;
5254 bool vf_res_different_than_output = false;
5255 bool need_vf_pp = false;
5256 int vf_ds_log2;
5257 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video;
5258
5259 IA_CSS_ENTER_PRIVATE("");
5260 assert(pipe);
5261 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
5262
5263
5264
5265
5266 if (mycs->video_binary.info)
5267 return 0;
5268
5269 online = pipe->stream->config.online;
5270 pipe_out_info = &pipe->output_info[0];
5271 pipe_vf_out_info = &pipe->vf_output_info[0];
5272
5273 assert(pipe_out_info);
5274
5275
5276
5277
5278
5279
5280 err = ia_css_util_check_input(&pipe->stream->config, false, false);
5281 if (err)
5282 return err;
5283
5284 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
5285 return -EINVAL;
5286 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5287 err = ia_css_util_check_vf_out_info(pipe_out_info,
5288 pipe_vf_out_info);
5289 if (err)
5290 return err;
5291 } else {
5292 err = ia_css_frame_check_info(pipe_out_info);
5293 if (err)
5294 return err;
5295 }
5296
5297 if (pipe->out_yuv_ds_input_info.res.width)
5298 video_bin_out_info = pipe->out_yuv_ds_input_info;
5299 else
5300 video_bin_out_info = *pipe_out_info;
5301
5302
5303 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5304 video_vf_info = pipe_vf_out_info;
5305 vf_res_different_than_output = (video_vf_info->res.width !=
5306 video_bin_out_info.res.width) ||
5307 (video_vf_info->res.height != video_bin_out_info.res.height);
5308 } else {
5309 video_vf_info = NULL;
5310 }
5311
5312 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
5313
5314
5315
5316 if (need_scaler) {
5317 struct ia_css_cas_binary_descr cas_scaler_descr = { };
5318
5319
5320
5321 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
5322
5323 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5324 &video_bin_out_info,
5325 pipe_out_info,
5326 NULL,
5327 &cas_scaler_descr);
5328 if (err)
5329 return err;
5330 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5331 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
5332 sizeof(struct ia_css_binary), GFP_KERNEL);
5333 if (!mycs->yuv_scaler_binary) {
5334 err = -ENOMEM;
5335 return err;
5336 }
5337 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage
5338 * sizeof(bool), GFP_KERNEL);
5339 if (!mycs->is_output_stage) {
5340 err = -ENOMEM;
5341 return err;
5342 }
5343 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5344 struct ia_css_binary_descr yuv_scaler_descr;
5345
5346 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5347 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5348 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5349 &cas_scaler_descr.out_info[i],
5350 &cas_scaler_descr.internal_out_info[i],
5351 &cas_scaler_descr.vf_info[i]);
5352 err = ia_css_binary_find(&yuv_scaler_descr,
5353 &mycs->yuv_scaler_binary[i]);
5354 if (err) {
5355 kfree(mycs->is_output_stage);
5356 mycs->is_output_stage = NULL;
5357 return err;
5358 }
5359 }
5360 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5361 }
5362
5363 {
5364 struct ia_css_binary_descr video_descr;
5365 enum ia_css_frame_format vf_info_format;
5366
5367 err = ia_css_pipe_get_video_binarydesc(pipe,
5368 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info,
5369 video_vf_info,
5370 pipe->stream->config.left_padding);
5371 if (err)
5372 return err;
5373
5374
5375
5376
5377
5378
5379 err = ia_css_binary_find(&video_descr,
5380 &mycs->video_binary);
5381
5382 if (err) {
5383
5384 if (video_vf_info)
5385 need_vf_pp = true;
5386 else
5387 return err;
5388 } else if (video_vf_info) {
5389
5390
5391 num_output_pins = mycs->video_binary.info->num_output_pins;
5392 vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
5393
5394
5395
5396 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
5397
5398
5399
5400 need_vf_pp |= ((num_output_pins == 1) &&
5401 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
5402 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
5403 }
5404
5405 if (need_vf_pp) {
5406
5407 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5408 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5409
5410 vf_info_format = video_vf_info->format;
5411
5412 if (!pipe->config.enable_vfpp_bci)
5413 ia_css_frame_info_set_format(video_vf_info,
5414 IA_CSS_FRAME_FORMAT_YUV_LINE);
5415
5416 ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
5417
5418 err = ia_css_binary_find(&video_descr,
5419 &mycs->video_binary);
5420
5421
5422 ia_css_frame_info_set_format(video_vf_info,
5423 vf_info_format);
5424 if (err)
5425 return err;
5426 }
5427 }
5428
5429
5430
5431 if (!mycs->video_binary.info->sp.enable.ref_frame)
5432 pipe->dvs_frame_delay = 0;
5433
5434
5435
5436 pipe->num_invalid_frames = pipe->dvs_frame_delay;
5437 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
5438
5439
5440
5441
5442 if (video_vf_info)
5443 pipe->num_invalid_frames *= 2;
5444
5445 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5446 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5447 pipe->num_invalid_frames, pipe->dvs_frame_delay);
5448
5449
5450#if !defined(ISP2401)
5451
5452 if (!online && !continuous) {
5453
5454
5455
5456 err = load_copy_binary(pipe,
5457 &mycs->copy_binary,
5458 &mycs->video_binary);
5459 if (err)
5460 return err;
5461 }
5462#else
5463 (void)continuous;
5464#endif
5465
5466#if !defined(HAS_OUTPUT_SYSTEM)
5467 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
5468 struct ia_css_binary_descr vf_pp_descr;
5469
5470 if (mycs->video_binary.vf_frame_info.format
5471 == IA_CSS_FRAME_FORMAT_YUV_LINE) {
5472 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5473 &mycs->video_binary.vf_frame_info,
5474 pipe_vf_out_info);
5475 } else {
5476
5477
5478 assert(pipe->config.enable_vfpp_bci);
5479 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
5480 &mycs->video_binary.vf_frame_info,
5481 pipe_vf_out_info, NULL, NULL);
5482 }
5483
5484 err = ia_css_binary_find(&vf_pp_descr,
5485 &mycs->vf_pp_binary);
5486 if (err)
5487 return err;
5488 }
5489#endif
5490
5491 err = allocate_delay_frames(pipe);
5492
5493 if (err)
5494 return err;
5495
5496 if (mycs->video_binary.info->sp.enable.block_output) {
5497 unsigned int tnr_width;
5498 unsigned int tnr_height;
5499
5500 tnr_info = mycs->video_binary.out_frame_info[0];
5501
5502 if (IS_ISP2401) {
5503
5504
5505
5506
5507 if (pipe->config.output_system_in_res.width &&
5508 pipe->config.output_system_in_res.height) {
5509 tnr_width = pipe->config.output_system_in_res.width;
5510 tnr_height = pipe->config.output_system_in_res.height;
5511 } else {
5512 tnr_width = tnr_info.res.width;
5513 tnr_height = tnr_info.res.height;
5514 }
5515
5516
5517 tnr_info.res.width = CEIL_MUL(tnr_width,
5518 (mycs->video_binary.info->sp.block.block_width * ISP_NWAY));
5519 tnr_info.padded_width = tnr_info.res.width;
5520 } else {
5521 tnr_height = tnr_info.res.height;
5522 }
5523
5524
5525 tnr_info.res.height = CEIL_MUL(tnr_height,
5526 mycs->video_binary.info->sp.block.output_block_height);
5527 } else {
5528 tnr_info = mycs->video_binary.internal_frame_info;
5529 }
5530 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE;
5531 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH;
5532
5533 for (i = 0; i < NUM_TNR_FRAMES; i++) {
5534 if (mycs->tnr_frames[i]) {
5535 ia_css_frame_free(mycs->tnr_frames[i]);
5536 mycs->tnr_frames[i] = NULL;
5537 }
5538 err = ia_css_frame_allocate_from_info(
5539 &mycs->tnr_frames[i],
5540 &tnr_info);
5541 if (err)
5542 return err;
5543 }
5544 IA_CSS_LEAVE_PRIVATE("");
5545 return 0;
5546}
5547
5548static int
5549unload_video_binaries(struct ia_css_pipe *pipe)
5550{
5551 unsigned int i;
5552
5553 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5554
5555 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5556 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5557 return -EINVAL;
5558 }
5559 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary);
5560 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary);
5561 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5562
5563 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++)
5564 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]);
5565
5566 kfree(pipe->pipe_settings.video.is_output_stage);
5567 pipe->pipe_settings.video.is_output_stage = NULL;
5568 kfree(pipe->pipe_settings.video.yuv_scaler_binary);
5569 pipe->pipe_settings.video.yuv_scaler_binary = NULL;
5570
5571 IA_CSS_LEAVE_ERR_PRIVATE(0);
5572 return 0;
5573}
5574
5575static int video_start(struct ia_css_pipe *pipe)
5576{
5577 int err = 0;
5578 struct ia_css_pipe *copy_pipe, *capture_pipe;
5579 enum sh_css_pipe_config_override copy_ovrd;
5580 enum ia_css_input_mode video_pipe_input_mode;
5581
5582 const struct ia_css_coordinate *coord = NULL;
5583 const struct ia_css_isp_parameters *params = NULL;
5584
5585 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5586 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5587 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5588 return -EINVAL;
5589 }
5590
5591 video_pipe_input_mode = pipe->stream->config.mode;
5592
5593 copy_pipe = pipe->pipe_settings.video.copy_pipe;
5594 capture_pipe = pipe->pipe_settings.video.capture_pipe;
5595
5596 sh_css_metrics_start_frame();
5597
5598
5599
5600 err = send_mipi_frames(pipe);
5601 if (err)
5602 return err;
5603
5604 send_raw_frames(pipe);
5605 {
5606 unsigned int thread_id;
5607
5608 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
5609 copy_ovrd = 1 << thread_id;
5610
5611 if (pipe->stream->cont_capt) {
5612 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5613 &thread_id);
5614 copy_ovrd |= 1 << thread_id;
5615 }
5616 }
5617
5618 if (IS_ISP2401) {
5619 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
5620 params = pipe->stream->isp_params_configs;
5621 }
5622
5623
5624 if (pipe->stream->config.continuous) {
5625 sh_css_sp_init_pipeline(©_pipe->pipeline,
5626 IA_CSS_PIPE_ID_COPY,
5627 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
5628 false,
5629 pipe->stream->config.pixels_per_clock == 2, false,
5630 false, pipe->required_bds_factor,
5631 copy_ovrd,
5632 pipe->stream->config.mode,
5633 &pipe->stream->config.metadata_config,
5634 &pipe->stream->info.metadata_info,
5635 pipe->stream->config.source.port.port,
5636 coord,
5637 params);
5638
5639
5640
5641 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
5642 }
5643
5644
5645 if (pipe->stream->cont_capt) {
5646 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
5647 IA_CSS_PIPE_ID_CAPTURE,
5648 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
5649 capture_pipe->config.default_capture_config.enable_xnr != 0,
5650 capture_pipe->stream->config.pixels_per_clock == 2,
5651 true,
5652 false,
5653 capture_pipe->required_bds_factor,
5654 0,
5655 IA_CSS_INPUT_MODE_MEMORY,
5656 &pipe->stream->config.metadata_config,
5657 &pipe->stream->info.metadata_info,
5658 (enum mipi_port_id)0,
5659 coord,
5660 params);
5661 }
5662
5663 start_pipe(pipe, copy_ovrd, video_pipe_input_mode);
5664
5665 IA_CSS_LEAVE_ERR_PRIVATE(err);
5666 return err;
5667}
5668
5669static
5670int sh_css_pipe_get_viewfinder_frame_info(
5671 struct ia_css_pipe *pipe,
5672 struct ia_css_frame_info *info,
5673 unsigned int idx)
5674{
5675 assert(pipe);
5676 assert(info);
5677
5678
5679 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5680 "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
5681
5682 if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE &&
5683 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
5684 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER))
5685 return -EINVAL;
5686
5687 *info = pipe->vf_output_info[idx];
5688
5689 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5690 "sh_css_pipe_get_viewfinder_frame_info() leave: \
5691 info.res.width=%d, info.res.height=%d, \
5692 info.padded_width=%d, info.format=%d, \
5693 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
5694 info->res.width, info->res.height,
5695 info->padded_width, info->format,
5696 info->raw_bit_depth, info->raw_bayer_order);
5697
5698 return 0;
5699}
5700
5701static int
5702sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
5703 unsigned int height, unsigned int min_width,
5704 enum ia_css_frame_format format,
5705 unsigned int idx)
5706{
5707 int err = 0;
5708
5709 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
5710 pipe, width, height, min_width, format, idx);
5711
5712 if (!pipe) {
5713 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5714 return -EINVAL;
5715 }
5716
5717 err = ia_css_util_check_res(width, height);
5718 if (err) {
5719 IA_CSS_LEAVE_ERR_PRIVATE(err);
5720 return err;
5721 }
5722 if (pipe->vf_output_info[idx].res.width != width ||
5723 pipe->vf_output_info[idx].res.height != height ||
5724 pipe->vf_output_info[idx].format != format)
5725 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
5726 format, min_width);
5727
5728 IA_CSS_LEAVE_ERR_PRIVATE(0);
5729 return 0;
5730}
5731
5732static int load_copy_binaries(struct ia_css_pipe *pipe)
5733{
5734 int err = 0;
5735
5736 assert(pipe);
5737 IA_CSS_ENTER_PRIVATE("");
5738
5739 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5740 pipe->mode == IA_CSS_PIPE_ID_COPY);
5741 if (pipe->pipe_settings.capture.copy_binary.info)
5742 return 0;
5743
5744 err = ia_css_frame_check_info(&pipe->output_info[0]);
5745 if (err)
5746 goto ERR;
5747
5748 err = verify_copy_out_frame_format(pipe);
5749 if (err)
5750 goto ERR;
5751
5752 err = load_copy_binary(pipe,
5753 &pipe->pipe_settings.capture.copy_binary,
5754 NULL);
5755
5756ERR:
5757 IA_CSS_LEAVE_ERR_PRIVATE(err);
5758 return err;
5759}
5760
5761static bool need_capture_pp(
5762 const struct ia_css_pipe *pipe)
5763{
5764 const struct ia_css_frame_info *out_info = &pipe->output_info[0];
5765
5766 IA_CSS_ENTER_LEAVE_PRIVATE("");
5767 assert(pipe);
5768 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
5769
5770 if (IS_ISP2401) {
5771
5772 if (need_capt_ldc(pipe))
5773 return false;
5774 }
5775
5776
5777
5778
5779
5780
5781
5782 if (pipe->out_yuv_ds_input_info.res.width &&
5783 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) ||
5784 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height)))
5785 return true;
5786
5787 if (pipe->config.default_capture_config.enable_xnr != 0)
5788 return true;
5789
5790 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) ||
5791 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) ||
5792 pipe->config.enable_dz)
5793 return true;
5794
5795 return false;
5796}
5797
5798static bool need_capt_ldc(
5799 const struct ia_css_pipe *pipe)
5800{
5801 IA_CSS_ENTER_LEAVE_PRIVATE("");
5802 assert(pipe);
5803 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
5804 return (pipe->extra_config.enable_dvs_6axis) ? true : false;
5805}
5806
5807static int set_num_primary_stages(unsigned int *num,
5808 enum ia_css_pipe_version version)
5809{
5810 int err = 0;
5811
5812 if (!num)
5813 return -EINVAL;
5814
5815 switch (version) {
5816 case IA_CSS_PIPE_VERSION_2_6_1:
5817 *num = NUM_PRIMARY_HQ_STAGES;
5818 break;
5819 case IA_CSS_PIPE_VERSION_2_2:
5820 case IA_CSS_PIPE_VERSION_1:
5821 *num = NUM_PRIMARY_STAGES;
5822 break;
5823 default:
5824 err = -EINVAL;
5825 break;
5826 }
5827
5828 return err;
5829}
5830
5831static int load_primary_binaries(
5832 struct ia_css_pipe *pipe)
5833{
5834 bool online = false;
5835 bool need_pp = false;
5836 bool need_isp_copy_binary = false;
5837 bool need_ldc = false;
5838#ifdef ISP2401
5839 bool sensor = false;
5840#else
5841 bool memory, continuous;
5842#endif
5843 struct ia_css_frame_info prim_in_info,
5844 prim_out_info,
5845 capt_pp_out_info, vf_info,
5846 *vf_pp_in_info, *pipe_out_info,
5847 *pipe_vf_out_info, *capt_pp_in_info,
5848 capt_ldc_out_info;
5849 int err = 0;
5850 struct ia_css_capture_settings *mycs;
5851 unsigned int i;
5852 bool need_extra_yuv_scaler = false;
5853 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES];
5854
5855 IA_CSS_ENTER_PRIVATE("");
5856 assert(pipe);
5857 assert(pipe->stream);
5858 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5859 pipe->mode == IA_CSS_PIPE_ID_COPY);
5860
5861 online = pipe->stream->config.online;
5862#ifdef ISP2401
5863 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
5864#else
5865 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
5866 continuous = pipe->stream->config.continuous;
5867#endif
5868
5869 mycs = &pipe->pipe_settings.capture;
5870 pipe_out_info = &pipe->output_info[0];
5871 pipe_vf_out_info = &pipe->vf_output_info[0];
5872
5873 if (mycs->primary_binary[0].info)
5874 return 0;
5875
5876 err = set_num_primary_stages(&mycs->num_primary_stage,
5877 pipe->config.isp_pipe_version);
5878 if (err) {
5879 IA_CSS_LEAVE_ERR_PRIVATE(err);
5880 return err;
5881 }
5882
5883 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5884 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info);
5885 if (err) {
5886 IA_CSS_LEAVE_ERR_PRIVATE(err);
5887 return err;
5888 }
5889 } else {
5890 err = ia_css_frame_check_info(pipe_out_info);
5891 if (err) {
5892 IA_CSS_LEAVE_ERR_PRIVATE(err);
5893 return err;
5894 }
5895 }
5896 need_pp = need_capture_pp(pipe);
5897
5898
5899
5900
5901 vf_info = *pipe_vf_out_info;
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
5914
5915
5916
5917
5918
5919 capt_pp_out_info = pipe->out_yuv_ds_input_info;
5920 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420;
5921 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP;
5922 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP;
5923 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0);
5924
5925 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res,
5926 pipe_out_info->res);
5927
5928 if (need_extra_yuv_scaler) {
5929 struct ia_css_cas_binary_descr cas_scaler_descr = { };
5930
5931 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5932 &capt_pp_out_info,
5933 pipe_out_info,
5934 NULL,
5935 &cas_scaler_descr);
5936 if (err) {
5937 IA_CSS_LEAVE_ERR_PRIVATE(err);
5938 return err;
5939 }
5940 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5941 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
5942 sizeof(struct ia_css_binary), GFP_KERNEL);
5943 if (!mycs->yuv_scaler_binary) {
5944 err = -ENOMEM;
5945 IA_CSS_LEAVE_ERR_PRIVATE(err);
5946 return err;
5947 }
5948 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
5949 sizeof(bool), GFP_KERNEL);
5950 if (!mycs->is_output_stage) {
5951 err = -ENOMEM;
5952 IA_CSS_LEAVE_ERR_PRIVATE(err);
5953 return err;
5954 }
5955 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5956 struct ia_css_binary_descr yuv_scaler_descr;
5957
5958 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5959 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5960 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5961 &cas_scaler_descr.out_info[i],
5962 &cas_scaler_descr.internal_out_info[i],
5963 &cas_scaler_descr.vf_info[i]);
5964 err = ia_css_binary_find(&yuv_scaler_descr,
5965 &mycs->yuv_scaler_binary[i]);
5966 if (err) {
5967 IA_CSS_LEAVE_ERR_PRIVATE(err);
5968 return err;
5969 }
5970 }
5971 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5972
5973 } else {
5974 capt_pp_out_info = pipe->output_info[0];
5975 }
5976
5977
5978 need_ldc = need_capt_ldc(pipe);
5979 if (IS_ISP2401 && need_ldc) {
5980
5981 struct ia_css_binary_descr capt_ldc_descr;
5982
5983 ia_css_pipe_get_ldc_binarydesc(pipe,
5984 &capt_ldc_descr, &prim_out_info,
5985 &capt_pp_out_info);
5986
5987 err = ia_css_binary_find(&capt_ldc_descr,
5988 &mycs->capture_ldc_binary);
5989 if (err) {
5990 IA_CSS_LEAVE_ERR_PRIVATE(err);
5991 return err;
5992 }
5993 need_pp = false;
5994 need_ldc = false;
5995 }
5996
5997
5998
5999 if (need_pp) {
6000 struct ia_css_binary_descr capture_pp_descr;
6001
6002 if (!IS_ISP2401)
6003 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info;
6004 else
6005 capt_pp_in_info = &prim_out_info;
6006
6007 ia_css_pipe_get_capturepp_binarydesc(pipe,
6008 &capture_pp_descr,
6009 capt_pp_in_info,
6010 &capt_pp_out_info,
6011 &vf_info);
6012
6013 err = ia_css_binary_find(&capture_pp_descr,
6014 &mycs->capture_pp_binary);
6015 if (err) {
6016 IA_CSS_LEAVE_ERR_PRIVATE(err);
6017 return err;
6018 }
6019
6020 if (need_ldc) {
6021 struct ia_css_binary_descr capt_ldc_descr;
6022
6023 ia_css_pipe_get_ldc_binarydesc(pipe,
6024 &capt_ldc_descr,
6025 &prim_out_info,
6026 &capt_ldc_out_info);
6027
6028 err = ia_css_binary_find(&capt_ldc_descr,
6029 &mycs->capture_ldc_binary);
6030 if (err) {
6031 IA_CSS_LEAVE_ERR_PRIVATE(err);
6032 return err;
6033 }
6034 }
6035 } else {
6036 prim_out_info = *pipe_out_info;
6037 }
6038
6039
6040 for (i = 0; i < mycs->num_primary_stage; i++) {
6041 struct ia_css_frame_info *local_vf_info = NULL;
6042
6043 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] &&
6044 (i == mycs->num_primary_stage - 1))
6045 local_vf_info = &vf_info;
6046 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i],
6047 &prim_in_info, &prim_out_info,
6048 local_vf_info, i);
6049 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
6050 if (err) {
6051 IA_CSS_LEAVE_ERR_PRIVATE(err);
6052 return err;
6053 }
6054 }
6055
6056
6057 if (need_pp)
6058 vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info;
6059 else
6060 vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info;
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6073 struct ia_css_binary_descr vf_pp_descr;
6074
6075 ia_css_pipe_get_vfpp_binarydesc(pipe,
6076 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6077 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary);
6078 if (err) {
6079 IA_CSS_LEAVE_ERR_PRIVATE(err);
6080 return err;
6081 }
6082 }
6083 err = allocate_delay_frames(pipe);
6084
6085 if (err)
6086 return err;
6087
6088#ifdef ISP2401
6089
6090
6091
6092 need_isp_copy_binary = !online && sensor;
6093#else
6094 need_isp_copy_binary = !online && !continuous && !memory;
6095#endif
6096
6097
6098 if (need_isp_copy_binary) {
6099 err = load_copy_binary(pipe,
6100 &mycs->copy_binary,
6101 &mycs->primary_binary[0]);
6102 if (err) {
6103 IA_CSS_LEAVE_ERR_PRIVATE(err);
6104 return err;
6105 }
6106 }
6107
6108 return 0;
6109}
6110
6111static int
6112allocate_delay_frames(struct ia_css_pipe *pipe)
6113{
6114 unsigned int num_delay_frames = 0, i = 0;
6115 unsigned int dvs_frame_delay = 0;
6116 struct ia_css_frame_info ref_info;
6117 int err = 0;
6118 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO;
6119 struct ia_css_frame **delay_frames = NULL;
6120
6121 IA_CSS_ENTER_PRIVATE("");
6122
6123 if (!pipe) {
6124 IA_CSS_ERROR("Invalid args - pipe %p", pipe);
6125 return -EINVAL;
6126 }
6127
6128 mode = pipe->mode;
6129 dvs_frame_delay = pipe->dvs_frame_delay;
6130
6131 if (dvs_frame_delay > 0)
6132 num_delay_frames = dvs_frame_delay + 1;
6133
6134 switch (mode) {
6135 case IA_CSS_PIPE_ID_CAPTURE: {
6136 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
6137 (void)mycs_capture;
6138 return err;
6139 }
6140 break;
6141 case IA_CSS_PIPE_ID_VIDEO: {
6142 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video;
6143
6144 ref_info = mycs_video->video_binary.internal_frame_info;
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6157 delay_frames = mycs_video->delay_frames;
6158 }
6159 break;
6160 case IA_CSS_PIPE_ID_PREVIEW: {
6161 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview;
6162
6163 ref_info = mycs_preview->preview_binary.internal_frame_info;
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6176 delay_frames = mycs_preview->delay_frames;
6177 }
6178 break;
6179 default:
6180 return -EINVAL;
6181 }
6182
6183 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
6184
6185 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
6186 for (i = 0; i < num_delay_frames; i++) {
6187 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info);
6188 if (err)
6189 return err;
6190 }
6191 IA_CSS_LEAVE_PRIVATE("");
6192 return 0;
6193}
6194
6195static int load_advanced_binaries(struct ia_css_pipe *pipe)
6196{
6197 struct ia_css_frame_info pre_in_info, gdc_in_info,
6198 post_in_info, post_out_info,
6199 vf_info, *vf_pp_in_info, *pipe_out_info,
6200 *pipe_vf_out_info;
6201 bool need_pp;
6202 bool need_isp_copy = true;
6203 int err = 0;
6204
6205 IA_CSS_ENTER_PRIVATE("");
6206
6207 assert(pipe);
6208 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6209 pipe->mode == IA_CSS_PIPE_ID_COPY);
6210 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6211 return 0;
6212 pipe_out_info = &pipe->output_info[0];
6213 pipe_vf_out_info = &pipe->vf_output_info[0];
6214
6215 vf_info = *pipe_vf_out_info;
6216 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info);
6217 if (err)
6218 return err;
6219 need_pp = need_capture_pp(pipe);
6220
6221 ia_css_frame_info_set_format(&vf_info,
6222 IA_CSS_FRAME_FORMAT_YUV_LINE);
6223
6224
6225
6226 if (need_pp) {
6227 struct ia_css_binary_descr capture_pp_descr;
6228
6229 ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr,
6230 &post_out_info,
6231 pipe_out_info, &vf_info);
6232 err = ia_css_binary_find(&capture_pp_descr,
6233 &pipe->pipe_settings.capture.capture_pp_binary);
6234 if (err)
6235 return err;
6236 } else {
6237 post_out_info = *pipe_out_info;
6238 }
6239
6240
6241 {
6242 struct ia_css_binary_descr post_gdc_descr;
6243
6244 ia_css_pipe_get_post_gdc_binarydesc(pipe, &post_gdc_descr,
6245 &post_in_info,
6246 &post_out_info, &vf_info);
6247 err = ia_css_binary_find(&post_gdc_descr,
6248 &pipe->pipe_settings.capture.post_isp_binary);
6249 if (err)
6250 return err;
6251 }
6252
6253
6254 {
6255 struct ia_css_binary_descr gdc_descr;
6256
6257 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
6258 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6259 err = ia_css_binary_find(&gdc_descr,
6260 &pipe->pipe_settings.capture.anr_gdc_binary);
6261 if (err)
6262 return err;
6263 }
6264 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6265 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6266
6267
6268 {
6269 struct ia_css_binary_descr pre_gdc_descr;
6270
6271 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
6272 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6273 err = ia_css_binary_find(&pre_gdc_descr,
6274 &pipe->pipe_settings.capture.pre_isp_binary);
6275 if (err)
6276 return err;
6277 }
6278 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6279 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6280
6281
6282 if (need_pp) {
6283 vf_pp_in_info =
6284 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6285 } else {
6286 vf_pp_in_info =
6287 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6288 }
6289
6290 {
6291 struct ia_css_binary_descr vf_pp_descr;
6292
6293 ia_css_pipe_get_vfpp_binarydesc(pipe,
6294 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6295 err = ia_css_binary_find(&vf_pp_descr,
6296 &pipe->pipe_settings.capture.vf_pp_binary);
6297 if (err)
6298 return err;
6299 }
6300
6301
6302#ifdef ISP2401
6303
6304 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6305#endif
6306 if (need_isp_copy)
6307 load_copy_binary(pipe,
6308 &pipe->pipe_settings.capture.copy_binary,
6309 &pipe->pipe_settings.capture.pre_isp_binary);
6310
6311 return err;
6312}
6313
6314static int load_bayer_isp_binaries(struct ia_css_pipe *pipe)
6315{
6316 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
6317 int err = 0;
6318 struct ia_css_binary_descr pre_de_descr;
6319
6320 IA_CSS_ENTER_PRIVATE("");
6321 assert(pipe);
6322 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6323 pipe->mode == IA_CSS_PIPE_ID_COPY);
6324 pipe_out_info = &pipe->output_info[0];
6325
6326 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6327 return 0;
6328
6329 err = ia_css_frame_check_info(pipe_out_info);
6330 if (err)
6331 return err;
6332
6333 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
6334 &pre_isp_in_info,
6335 pipe_out_info);
6336
6337 err = ia_css_binary_find(&pre_de_descr,
6338 &pipe->pipe_settings.capture.pre_isp_binary);
6339
6340 return err;
6341}
6342
6343static int load_low_light_binaries(struct ia_css_pipe *pipe)
6344{
6345 struct ia_css_frame_info pre_in_info, anr_in_info,
6346 post_in_info, post_out_info,
6347 vf_info, *pipe_vf_out_info, *pipe_out_info,
6348 *vf_pp_in_info;
6349 bool need_pp;
6350 bool need_isp_copy = true;
6351 int err = 0;
6352
6353 IA_CSS_ENTER_PRIVATE("");
6354 assert(pipe);
6355 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6356 pipe->mode == IA_CSS_PIPE_ID_COPY);
6357
6358 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6359 return 0;
6360 pipe_vf_out_info = &pipe->vf_output_info[0];
6361 pipe_out_info = &pipe->output_info[0];
6362
6363 vf_info = *pipe_vf_out_info;
6364 err = ia_css_util_check_vf_out_info(pipe_out_info,
6365 &vf_info);
6366 if (err)
6367 return err;
6368 need_pp = need_capture_pp(pipe);
6369
6370 ia_css_frame_info_set_format(&vf_info,
6371 IA_CSS_FRAME_FORMAT_YUV_LINE);
6372
6373
6374
6375 if (need_pp) {
6376 struct ia_css_binary_descr capture_pp_descr;
6377
6378 ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr,
6379 &post_out_info,
6380 pipe_out_info, &vf_info);
6381 err = ia_css_binary_find(&capture_pp_descr,
6382 &pipe->pipe_settings.capture.capture_pp_binary);
6383 if (err)
6384 return err;
6385 } else {
6386 post_out_info = *pipe_out_info;
6387 }
6388
6389
6390 {
6391 struct ia_css_binary_descr post_anr_descr;
6392
6393 ia_css_pipe_get_post_anr_binarydesc(pipe,
6394 &post_anr_descr, &post_in_info, &post_out_info, &vf_info);
6395 err = ia_css_binary_find(&post_anr_descr,
6396 &pipe->pipe_settings.capture.post_isp_binary);
6397 if (err)
6398 return err;
6399 }
6400
6401
6402 {
6403 struct ia_css_binary_descr anr_descr;
6404
6405 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
6406 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6407 err = ia_css_binary_find(&anr_descr,
6408 &pipe->pipe_settings.capture.anr_gdc_binary);
6409 if (err)
6410 return err;
6411 }
6412 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6413 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6414
6415
6416 {
6417 struct ia_css_binary_descr pre_anr_descr;
6418
6419 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
6420 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6421 err = ia_css_binary_find(&pre_anr_descr,
6422 &pipe->pipe_settings.capture.pre_isp_binary);
6423 if (err)
6424 return err;
6425 }
6426 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6427 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6428
6429
6430 if (need_pp) {
6431 vf_pp_in_info =
6432 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6433 } else {
6434 vf_pp_in_info =
6435 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6436 }
6437
6438 {
6439 struct ia_css_binary_descr vf_pp_descr;
6440
6441 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
6442 vf_pp_in_info, pipe_vf_out_info);
6443 err = ia_css_binary_find(&vf_pp_descr,
6444 &pipe->pipe_settings.capture.vf_pp_binary);
6445 if (err)
6446 return err;
6447 }
6448
6449
6450#ifdef ISP2401
6451
6452 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6453#endif
6454 if (need_isp_copy)
6455 err = load_copy_binary(pipe,
6456 &pipe->pipe_settings.capture.copy_binary,
6457 &pipe->pipe_settings.capture.pre_isp_binary);
6458
6459 return err;
6460}
6461
6462static bool copy_on_sp(struct ia_css_pipe *pipe)
6463{
6464 bool rval;
6465
6466 assert(pipe);
6467 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n");
6468
6469 rval = true;
6470
6471 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6472
6473 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
6474
6475 rval &= ((pipe->stream->config.input_config.format ==
6476 ATOMISP_INPUT_FORMAT_BINARY_8) ||
6477 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
6478
6479 return rval;
6480}
6481
6482static int load_capture_binaries(struct ia_css_pipe *pipe)
6483{
6484 int err = 0;
6485 bool must_be_raw;
6486
6487 IA_CSS_ENTER_PRIVATE("");
6488 assert(pipe);
6489 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6490 pipe->mode == IA_CSS_PIPE_ID_COPY);
6491
6492 if (pipe->pipe_settings.capture.primary_binary[0].info) {
6493 IA_CSS_LEAVE_ERR_PRIVATE(0);
6494 return 0;
6495 }
6496
6497
6498
6499 must_be_raw =
6500 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
6501 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ||
6502 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT;
6503 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false);
6504 if (err) {
6505 IA_CSS_LEAVE_ERR_PRIVATE(err);
6506 return err;
6507 }
6508 if (copy_on_sp(pipe) &&
6509 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
6510 ia_css_frame_info_init(
6511 &pipe->output_info[0],
6512 JPEG_BYTES,
6513 1,
6514 IA_CSS_FRAME_FORMAT_BINARY_8,
6515 0);
6516 IA_CSS_LEAVE_ERR_PRIVATE(0);
6517 return 0;
6518 }
6519
6520 switch (pipe->config.default_capture_config.mode) {
6521 case IA_CSS_CAPTURE_MODE_RAW:
6522 err = load_copy_binaries(pipe);
6523#if defined(ISP2401)
6524 if (!err)
6525 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6526#endif
6527 break;
6528 case IA_CSS_CAPTURE_MODE_BAYER:
6529 err = load_bayer_isp_binaries(pipe);
6530 break;
6531 case IA_CSS_CAPTURE_MODE_PRIMARY:
6532 err = load_primary_binaries(pipe);
6533 break;
6534 case IA_CSS_CAPTURE_MODE_ADVANCED:
6535 err = load_advanced_binaries(pipe);
6536 break;
6537 case IA_CSS_CAPTURE_MODE_LOW_LIGHT:
6538 err = load_low_light_binaries(pipe);
6539 break;
6540 }
6541 if (err) {
6542 IA_CSS_LEAVE_ERR_PRIVATE(err);
6543 return err;
6544 }
6545
6546 IA_CSS_LEAVE_ERR_PRIVATE(err);
6547 return err;
6548}
6549
6550static int
6551unload_capture_binaries(struct ia_css_pipe *pipe)
6552{
6553 unsigned int i;
6554
6555 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6556
6557 if (!pipe || (pipe->mode != IA_CSS_PIPE_ID_CAPTURE &&
6558 pipe->mode != IA_CSS_PIPE_ID_COPY)) {
6559 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6560 return -EINVAL;
6561 }
6562 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary);
6563 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++)
6564 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]);
6565 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary);
6566 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary);
6567 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary);
6568 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary);
6569 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary);
6570 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary);
6571
6572 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++)
6573 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]);
6574
6575 kfree(pipe->pipe_settings.capture.is_output_stage);
6576 pipe->pipe_settings.capture.is_output_stage = NULL;
6577 kfree(pipe->pipe_settings.capture.yuv_scaler_binary);
6578 pipe->pipe_settings.capture.yuv_scaler_binary = NULL;
6579
6580 IA_CSS_LEAVE_ERR_PRIVATE(0);
6581 return 0;
6582}
6583
6584static bool
6585need_downscaling(const struct ia_css_resolution in_res,
6586 const struct ia_css_resolution out_res)
6587{
6588 if (in_res.width > out_res.width || in_res.height > out_res.height)
6589 return true;
6590
6591 return false;
6592}
6593
6594static bool
6595need_yuv_scaler_stage(const struct ia_css_pipe *pipe)
6596{
6597 unsigned int i;
6598 struct ia_css_resolution in_res, out_res;
6599
6600 bool need_format_conversion = false;
6601
6602 IA_CSS_ENTER_PRIVATE("");
6603 assert(pipe);
6604 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6605
6606
6607 need_format_conversion =
6608 ((pipe->stream->config.input_config.format ==
6609 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) &&
6610 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
6611
6612 in_res = pipe->config.input_effective_res;
6613
6614 if (pipe->config.enable_dz)
6615 return true;
6616
6617 if ((pipe->output_info[0].res.width != 0) && need_format_conversion)
6618 return true;
6619
6620 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6621 out_res = pipe->output_info[i].res;
6622
6623
6624 if ((out_res.width != 0) && need_downscaling(in_res, out_res))
6625 return true;
6626 }
6627
6628 return false;
6629}
6630
6631
6632
6633
6634static int ia_css_pipe_create_cas_scaler_desc_single_output(
6635 struct ia_css_frame_info *cas_scaler_in_info,
6636 struct ia_css_frame_info *cas_scaler_out_info,
6637 struct ia_css_frame_info *cas_scaler_vf_info,
6638 struct ia_css_cas_binary_descr *descr)
6639{
6640 unsigned int i;
6641 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
6642 int err = 0;
6643 struct ia_css_frame_info tmp_in_info;
6644
6645 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6646
6647 assert(cas_scaler_in_info);
6648 assert(cas_scaler_out_info);
6649
6650 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6651 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6652
6653
6654 descr->num_output_stage = 1;
6655
6656 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width,
6657 cas_scaler_out_info->res.width);
6658 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height,
6659 cas_scaler_out_info->res.height);
6660
6661 assert(hor_ds_factor == ver_ds_factor);
6662
6663 i = 1;
6664 while (i < hor_ds_factor) {
6665 descr->num_stage++;
6666 i *= max_scale_factor_per_stage;
6667 }
6668
6669 descr->in_info = kmalloc(descr->num_stage *
6670 sizeof(struct ia_css_frame_info),
6671 GFP_KERNEL);
6672 if (!descr->in_info) {
6673 err = -ENOMEM;
6674 goto ERR;
6675 }
6676 descr->internal_out_info = kmalloc(descr->num_stage *
6677 sizeof(struct ia_css_frame_info),
6678 GFP_KERNEL);
6679 if (!descr->internal_out_info) {
6680 err = -ENOMEM;
6681 goto ERR;
6682 }
6683 descr->out_info = kmalloc(descr->num_stage *
6684 sizeof(struct ia_css_frame_info),
6685 GFP_KERNEL);
6686 if (!descr->out_info) {
6687 err = -ENOMEM;
6688 goto ERR;
6689 }
6690 descr->vf_info = kmalloc(descr->num_stage *
6691 sizeof(struct ia_css_frame_info),
6692 GFP_KERNEL);
6693 if (!descr->vf_info) {
6694 err = -ENOMEM;
6695 goto ERR;
6696 }
6697 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool),
6698 GFP_KERNEL);
6699 if (!descr->is_output_stage) {
6700 err = -ENOMEM;
6701 goto ERR;
6702 }
6703
6704 tmp_in_info = *cas_scaler_in_info;
6705 for (i = 0; i < descr->num_stage; i++) {
6706 descr->in_info[i] = tmp_in_info;
6707 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
6708 cas_scaler_out_info->res.width) {
6709 descr->is_output_stage[i] = true;
6710 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
6711 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width;
6712 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height;
6713 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width;
6714 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6715 } else {
6716 assert(i == (descr->num_stage - 1));
6717 descr->internal_out_info[i].res.width = 0;
6718 descr->internal_out_info[i].res.height = 0;
6719 }
6720 descr->out_info[i].res.width = cas_scaler_out_info->res.width;
6721 descr->out_info[i].res.height = cas_scaler_out_info->res.height;
6722 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width;
6723 descr->out_info[i].format = cas_scaler_out_info->format;
6724 if (cas_scaler_vf_info) {
6725 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width;
6726 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height;
6727 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width;
6728 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
6729 } else {
6730 descr->vf_info[i].res.width = 0;
6731 descr->vf_info[i].res.height = 0;
6732 descr->vf_info[i].padded_width = 0;
6733 }
6734 } else {
6735 descr->is_output_stage[i] = false;
6736 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
6737 max_scale_factor_per_stage;
6738 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
6739 max_scale_factor_per_stage;
6740 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6741 ia_css_frame_info_init(&descr->internal_out_info[i],
6742 tmp_in_info.res.width / max_scale_factor_per_stage,
6743 tmp_in_info.res.height / max_scale_factor_per_stage,
6744 IA_CSS_FRAME_FORMAT_YUV420, 0);
6745 descr->out_info[i].res.width = 0;
6746 descr->out_info[i].res.height = 0;
6747 descr->vf_info[i].res.width = 0;
6748 descr->vf_info[i].res.height = 0;
6749 }
6750 tmp_in_info = descr->internal_out_info[i];
6751 }
6752ERR:
6753 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6754 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
6755 err);
6756 return err;
6757}
6758
6759
6760static int
6761ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe *pipe,
6762 struct ia_css_cas_binary_descr *descr)
6763{
6764 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6765 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6766 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6767 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6768 unsigned int i, j;
6769 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6770 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6771 scale_factor = 0;
6772 unsigned int num_stages = 0;
6773 int err = 0;
6774
6775 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6776
6777 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6778 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6779
6780 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6781 out_info[i] = NULL;
6782 vf_out_info[i] = NULL;
6783 hor_scale_factor[i] = 0;
6784 ver_scale_factor[i] = 0;
6785 }
6786
6787 in_info.res = pipe->config.input_effective_res;
6788 in_info.padded_width = in_info.res.width;
6789 descr->num_output_stage = 0;
6790
6791 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6792 if (pipe->output_info[i].res.width != 0) {
6793 out_info[i] = &pipe->output_info[i];
6794 if (pipe->vf_output_info[i].res.width != 0)
6795 vf_out_info[i] = &pipe->vf_output_info[i];
6796 descr->num_output_stage += 1;
6797 }
6798
6799 if (out_info[i]) {
6800 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width);
6801 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height);
6802
6803 assert(hor_scale_factor[i] == ver_scale_factor[i]);
6804 scale_factor = 1;
6805 do {
6806 num_stages++;
6807 scale_factor *= max_scale_factor_per_stage;
6808 } while (scale_factor < hor_scale_factor[i]);
6809
6810 in_info.res = out_info[i]->res;
6811 }
6812 }
6813
6814 if (need_yuv_scaler_stage(pipe) && (num_stages == 0))
6815 num_stages = 1;
6816
6817 descr->num_stage = num_stages;
6818
6819 descr->in_info = kmalloc_array(descr->num_stage,
6820 sizeof(struct ia_css_frame_info),
6821 GFP_KERNEL);
6822 if (!descr->in_info) {
6823 err = -ENOMEM;
6824 goto ERR;
6825 }
6826 descr->internal_out_info = kmalloc(descr->num_stage *
6827 sizeof(struct ia_css_frame_info),
6828 GFP_KERNEL);
6829 if (!descr->internal_out_info) {
6830 err = -ENOMEM;
6831 goto ERR;
6832 }
6833 descr->out_info = kmalloc(descr->num_stage *
6834 sizeof(struct ia_css_frame_info),
6835 GFP_KERNEL);
6836 if (!descr->out_info) {
6837 err = -ENOMEM;
6838 goto ERR;
6839 }
6840 descr->vf_info = kmalloc(descr->num_stage *
6841 sizeof(struct ia_css_frame_info),
6842 GFP_KERNEL);
6843 if (!descr->vf_info) {
6844 err = -ENOMEM;
6845 goto ERR;
6846 }
6847 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool),
6848 GFP_KERNEL);
6849 if (!descr->is_output_stage) {
6850 err = -ENOMEM;
6851 goto ERR;
6852 }
6853
6854 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6855 if (out_info[i]) {
6856 if (i > 0) {
6857 assert((out_info[i - 1]->res.width >= out_info[i]->res.width) &&
6858 (out_info[i - 1]->res.height >= out_info[i]->res.height));
6859 }
6860 }
6861 }
6862
6863 tmp_in_info.res = pipe->config.input_effective_res;
6864 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420;
6865 for (i = 0, j = 0; i < descr->num_stage; i++) {
6866 assert(j < 2);
6867 assert(out_info[j]);
6868
6869 descr->in_info[i] = tmp_in_info;
6870 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
6871 out_info[j]->res.width) {
6872 descr->is_output_stage[i] = true;
6873 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
6874 descr->internal_out_info[i].res.width = out_info[j]->res.width;
6875 descr->internal_out_info[i].res.height = out_info[j]->res.height;
6876 descr->internal_out_info[i].padded_width = out_info[j]->padded_width;
6877 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6878 } else {
6879 assert(i == (descr->num_stage - 1));
6880 descr->internal_out_info[i].res.width = 0;
6881 descr->internal_out_info[i].res.height = 0;
6882 }
6883 descr->out_info[i].res.width = out_info[j]->res.width;
6884 descr->out_info[i].res.height = out_info[j]->res.height;
6885 descr->out_info[i].padded_width = out_info[j]->padded_width;
6886 descr->out_info[i].format = out_info[j]->format;
6887 if (vf_out_info[j]) {
6888 descr->vf_info[i].res.width = vf_out_info[j]->res.width;
6889 descr->vf_info[i].res.height = vf_out_info[j]->res.height;
6890 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width;
6891 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
6892 } else {
6893 descr->vf_info[i].res.width = 0;
6894 descr->vf_info[i].res.height = 0;
6895 descr->vf_info[i].padded_width = 0;
6896 }
6897 j++;
6898 } else {
6899 descr->is_output_stage[i] = false;
6900 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
6901 max_scale_factor_per_stage;
6902 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
6903 max_scale_factor_per_stage;
6904 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6905 ia_css_frame_info_init(&descr->internal_out_info[i],
6906 tmp_in_info.res.width / max_scale_factor_per_stage,
6907 tmp_in_info.res.height / max_scale_factor_per_stage,
6908 IA_CSS_FRAME_FORMAT_YUV420, 0);
6909 descr->out_info[i].res.width = 0;
6910 descr->out_info[i].res.height = 0;
6911 descr->vf_info[i].res.width = 0;
6912 descr->vf_info[i].res.height = 0;
6913 }
6914 tmp_in_info = descr->internal_out_info[i];
6915 }
6916ERR:
6917 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6918 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
6919 err);
6920 return err;
6921}
6922
6923static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
6924 *descr)
6925{
6926 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6927 "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
6928 kfree(descr->in_info);
6929 descr->in_info = NULL;
6930 kfree(descr->internal_out_info);
6931 descr->internal_out_info = NULL;
6932 kfree(descr->out_info);
6933 descr->out_info = NULL;
6934 kfree(descr->vf_info);
6935 descr->vf_info = NULL;
6936 kfree(descr->is_output_stage);
6937 descr->is_output_stage = NULL;
6938 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6939 "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
6940}
6941
6942static int
6943load_yuvpp_binaries(struct ia_css_pipe *pipe)
6944{
6945 int err = 0;
6946 bool need_scaler = false;
6947 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6948 struct ia_css_yuvpp_settings *mycs;
6949 struct ia_css_binary *next_binary;
6950 struct ia_css_cas_binary_descr cas_scaler_descr = { };
6951 unsigned int i, j;
6952 bool need_isp_copy_binary = false;
6953
6954 IA_CSS_ENTER_PRIVATE("");
6955 assert(pipe);
6956 assert(pipe->stream);
6957 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6958
6959 if (pipe->pipe_settings.yuvpp.copy_binary.info)
6960 goto ERR;
6961
6962
6963 err = ia_css_util_check_input(&pipe->stream->config, false, false);
6964 if (err)
6965 goto ERR;
6966
6967 mycs = &pipe->pipe_settings.yuvpp;
6968
6969 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6970 if (pipe->vf_output_info[i].res.width != 0) {
6971 err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
6972 &pipe->vf_output_info[i]);
6973 if (err)
6974 goto ERR;
6975 }
6976 vf_pp_in_info[i] = NULL;
6977 }
6978
6979 need_scaler = need_yuv_scaler_stage(pipe);
6980
6981
6982
6983 if (need_scaler) {
6984 struct ia_css_binary_descr yuv_scaler_descr;
6985
6986 err = ia_css_pipe_create_cas_scaler_desc(pipe,
6987 &cas_scaler_descr);
6988 if (err)
6989 goto ERR;
6990 mycs->num_output = cas_scaler_descr.num_output_stage;
6991 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
6992 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
6993 sizeof(struct ia_css_binary),
6994 GFP_KERNEL);
6995 if (!mycs->yuv_scaler_binary) {
6996 err = -ENOMEM;
6997 goto ERR;
6998 }
6999 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
7000 sizeof(bool), GFP_KERNEL);
7001 if (!mycs->is_output_stage) {
7002 err = -ENOMEM;
7003 goto ERR;
7004 }
7005 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
7006 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
7007 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
7008 &yuv_scaler_descr,
7009 &cas_scaler_descr.in_info[i],
7010 &cas_scaler_descr.out_info[i],
7011 &cas_scaler_descr.internal_out_info[i],
7012 &cas_scaler_descr.vf_info[i]);
7013 err = ia_css_binary_find(&yuv_scaler_descr,
7014 &mycs->yuv_scaler_binary[i]);
7015 if (err)
7016 goto ERR;
7017 }
7018 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7019 } else {
7020 mycs->num_output = 1;
7021 }
7022
7023 if (need_scaler)
7024 next_binary = &mycs->yuv_scaler_binary[0];
7025 else
7026 next_binary = NULL;
7027
7028#if defined(ISP2401)
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046 need_isp_copy_binary =
7047 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
7048#else
7049 need_isp_copy_binary = true;
7050#endif
7051
7052 if (need_isp_copy_binary) {
7053 err = load_copy_binary(pipe,
7054 &mycs->copy_binary,
7055 next_binary);
7056
7057 if (err)
7058 goto ERR;
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
7079 }
7080
7081
7082 if (need_scaler) {
7083 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
7084 if (mycs->is_output_stage[i]) {
7085 assert(j < 2);
7086 vf_pp_in_info[j] =
7087 &mycs->yuv_scaler_binary[i].vf_frame_info;
7088 j++;
7089 }
7090 }
7091 mycs->num_vf_pp = j;
7092 } else {
7093 vf_pp_in_info[0] =
7094 &mycs->copy_binary.vf_frame_info;
7095 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
7096 vf_pp_in_info[i] = NULL;
7097
7098 mycs->num_vf_pp = 1;
7099 }
7100 mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp *
7101 sizeof(struct ia_css_binary),
7102 GFP_KERNEL);
7103 if (!mycs->vf_pp_binary) {
7104 err = -ENOMEM;
7105 goto ERR;
7106 }
7107
7108 {
7109 struct ia_css_binary_descr vf_pp_descr;
7110
7111 for (i = 0; i < mycs->num_vf_pp; i++) {
7112 if (pipe->vf_output_info[i].res.width != 0) {
7113 ia_css_pipe_get_vfpp_binarydesc(pipe,
7114 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
7115 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]);
7116 if (err)
7117 goto ERR;
7118 }
7119 }
7120 }
7121
7122 if (err)
7123 goto ERR;
7124
7125ERR:
7126 if (need_scaler)
7127 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7128
7129 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
7130 err);
7131 return err;
7132}
7133
7134static int
7135unload_yuvpp_binaries(struct ia_css_pipe *pipe)
7136{
7137 unsigned int i;
7138
7139 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7140
7141 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7142 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7143 return -EINVAL;
7144 }
7145 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
7146 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++)
7147 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
7148
7149 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++)
7150 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
7151
7152 kfree(pipe->pipe_settings.yuvpp.is_output_stage);
7153 pipe->pipe_settings.yuvpp.is_output_stage = NULL;
7154 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
7155 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL;
7156 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary);
7157 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL;
7158
7159 IA_CSS_LEAVE_ERR_PRIVATE(0);
7160 return 0;
7161}
7162
7163static int yuvpp_start(struct ia_css_pipe *pipe)
7164{
7165 int err = 0;
7166 enum sh_css_pipe_config_override copy_ovrd;
7167 enum ia_css_input_mode yuvpp_pipe_input_mode;
7168
7169 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7170 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7171 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7172 return -EINVAL;
7173 }
7174
7175 yuvpp_pipe_input_mode = pipe->stream->config.mode;
7176
7177 sh_css_metrics_start_frame();
7178
7179
7180
7181 err = send_mipi_frames(pipe);
7182 if (err) {
7183 IA_CSS_LEAVE_ERR_PRIVATE(err);
7184 return err;
7185 }
7186
7187 {
7188 unsigned int thread_id;
7189
7190 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7191 copy_ovrd = 1 << thread_id;
7192 }
7193
7194 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode);
7195
7196 IA_CSS_LEAVE_ERR_PRIVATE(err);
7197 return err;
7198}
7199
7200static int
7201sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe)
7202{
7203 int err = 0;
7204
7205 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7206
7207 if (!pipe) {
7208 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7209 return -EINVAL;
7210 }
7211
7212 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
7213 IA_CSS_LEAVE_ERR_PRIVATE(0);
7214 return 0;
7215 }
7216
7217 switch (pipe->mode) {
7218 case IA_CSS_PIPE_ID_PREVIEW:
7219 err = unload_preview_binaries(pipe);
7220 break;
7221 case IA_CSS_PIPE_ID_VIDEO:
7222 err = unload_video_binaries(pipe);
7223 break;
7224 case IA_CSS_PIPE_ID_CAPTURE:
7225 err = unload_capture_binaries(pipe);
7226 break;
7227 case IA_CSS_PIPE_ID_YUVPP:
7228 err = unload_yuvpp_binaries(pipe);
7229 break;
7230 default:
7231 break;
7232 }
7233 IA_CSS_LEAVE_ERR_PRIVATE(err);
7234 return err;
7235}
7236
7237static int
7238sh_css_pipe_load_binaries(struct ia_css_pipe *pipe)
7239{
7240 int err = 0;
7241
7242 assert(pipe);
7243 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n");
7244
7245
7246 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7247 return err;
7248
7249 switch (pipe->mode) {
7250 case IA_CSS_PIPE_ID_PREVIEW:
7251 err = load_preview_binaries(pipe);
7252 break;
7253 case IA_CSS_PIPE_ID_VIDEO:
7254 err = load_video_binaries(pipe);
7255 break;
7256 case IA_CSS_PIPE_ID_CAPTURE:
7257 err = load_capture_binaries(pipe);
7258 break;
7259 case IA_CSS_PIPE_ID_YUVPP:
7260 err = load_yuvpp_binaries(pipe);
7261 break;
7262 case IA_CSS_PIPE_ID_ACC:
7263 break;
7264 default:
7265 err = -EINVAL;
7266 break;
7267 }
7268 if (err) {
7269 if (sh_css_pipe_unload_binaries(pipe)) {
7270
7271
7272 err = -EINVAL;
7273 }
7274 }
7275 return err;
7276}
7277
7278static int
7279create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
7280{
7281 struct ia_css_pipeline *me;
7282 int err = 0;
7283 struct ia_css_pipeline_stage *vf_pp_stage = NULL,
7284 *copy_stage = NULL,
7285 *yuv_scaler_stage = NULL;
7286 struct ia_css_binary *copy_binary,
7287 *vf_pp_binary,
7288 *yuv_scaler_binary;
7289 bool need_scaler = false;
7290 unsigned int num_stage, num_output_stage;
7291 unsigned int i, j;
7292
7293 struct ia_css_frame *in_frame = NULL;
7294 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7295 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7296 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7297 struct ia_css_pipeline_stage_desc stage_desc;
7298 bool need_in_frameinfo_memory = false;
7299#ifdef ISP2401
7300 bool sensor = false;
7301 bool buffered_sensor = false;
7302 bool online = false;
7303 bool continuous = false;
7304#endif
7305
7306 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7307 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7308 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7309 return -EINVAL;
7310 }
7311 me = &pipe->pipeline;
7312 ia_css_pipeline_clean(me);
7313 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7314 out_frame[i] = NULL;
7315 vf_frame[i] = NULL;
7316 }
7317 ia_css_pipe_util_create_output_frames(bin_out_frame);
7318 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler;
7319 num_output_stage = pipe->pipe_settings.yuvpp.num_output;
7320
7321#ifdef ISP2401
7322
7323
7324
7325
7326
7327
7328 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
7329 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
7330 online = pipe->stream->config.online;
7331 continuous = pipe->stream->config.continuous;
7332 need_in_frameinfo_memory =
7333 !((sensor && (online || continuous)) || (buffered_sensor && continuous));
7334#else
7335
7336 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7337#endif
7338
7339
7340
7341 if (need_in_frameinfo_memory) {
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351 int in_frame_format;
7352
7353 if (pipe->stream->config.input_config.format ==
7354 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
7355 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
7356 } else if (pipe->stream->config.input_config.format ==
7357 ATOMISP_INPUT_FORMAT_YUV422_8) {
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375 in_frame_format = IA_CSS_FRAME_FORMAT_RAW;
7376 } else {
7377 in_frame_format = IA_CSS_FRAME_FORMAT_NV12;
7378 }
7379
7380 err = init_in_frameinfo_memory_defaults(pipe,
7381 &me->in_frame,
7382 in_frame_format);
7383
7384 if (err) {
7385 IA_CSS_LEAVE_ERR_PRIVATE(err);
7386 return err;
7387 }
7388
7389 in_frame = &me->in_frame;
7390 } else {
7391 in_frame = NULL;
7392 }
7393
7394 for (i = 0; i < num_output_stage; i++) {
7395 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
7396 if (pipe->output_info[i].res.width != 0) {
7397 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
7398 if (err) {
7399 IA_CSS_LEAVE_ERR_PRIVATE(err);
7400 return err;
7401 }
7402 out_frame[i] = &me->out_frame[i];
7403 }
7404
7405
7406 if (pipe->vf_output_info[i].res.width != 0) {
7407 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i);
7408 if (err) {
7409 IA_CSS_LEAVE_ERR_PRIVATE(err);
7410 return err;
7411 }
7412 vf_frame[i] = &me->vf_frame[i];
7413 }
7414 }
7415
7416 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7417 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary;
7418 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
7419 need_scaler = need_yuv_scaler_stage(pipe);
7420
7421 if (pipe->pipe_settings.yuvpp.copy_binary.info) {
7422 struct ia_css_frame *in_frame_local = NULL;
7423
7424#ifdef ISP2401
7425
7426 if (!online)
7427 in_frame_local = in_frame;
7428#endif
7429
7430 if (need_scaler) {
7431 ia_css_pipe_util_set_output_frames(bin_out_frame,
7432 0, NULL);
7433 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7434 copy_binary,
7435 bin_out_frame,
7436 in_frame_local,
7437 NULL);
7438 } else {
7439 ia_css_pipe_util_set_output_frames(bin_out_frame,
7440 0, out_frame[0]);
7441 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7442 copy_binary,
7443 bin_out_frame,
7444 in_frame_local,
7445 NULL);
7446 }
7447
7448 err = ia_css_pipeline_create_and_add_stage(me,
7449 &stage_desc,
7450 ©_stage);
7451
7452 if (err) {
7453 IA_CSS_LEAVE_ERR_PRIVATE(err);
7454 return err;
7455 }
7456
7457 if (copy_stage) {
7458
7459 copy_stage->args.copy_vf = !need_scaler;
7460
7461 copy_stage->args.copy_output = true;
7462
7463 in_frame = copy_stage->args.out_frame[0];
7464 }
7465 }
7466
7467 if (need_scaler) {
7468 struct ia_css_frame *tmp_out_frame = NULL;
7469 struct ia_css_frame *tmp_vf_frame = NULL;
7470 struct ia_css_frame *tmp_in_frame = in_frame;
7471
7472 for (i = 0, j = 0; i < num_stage; i++) {
7473 assert(j < num_output_stage);
7474 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7475 tmp_out_frame = out_frame[j];
7476 tmp_vf_frame = vf_frame[j];
7477 } else {
7478 tmp_out_frame = NULL;
7479 tmp_vf_frame = NULL;
7480 }
7481
7482 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
7483 tmp_out_frame,
7484 NULL,
7485 &yuv_scaler_binary[i],
7486 &yuv_scaler_stage);
7487
7488 if (err) {
7489 IA_CSS_LEAVE_ERR_PRIVATE(err);
7490 return err;
7491 }
7492
7493 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7494 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7495 if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
7496 in_frame = yuv_scaler_stage->args.out_vf_frame;
7497 err = add_vf_pp_stage(pipe, in_frame,
7498 tmp_vf_frame,
7499 &vf_pp_binary[j],
7500 &vf_pp_stage);
7501
7502 if (err) {
7503 IA_CSS_LEAVE_ERR_PRIVATE(err);
7504 return err;
7505 }
7506 }
7507 j++;
7508 }
7509 }
7510 } else if (copy_stage) {
7511 if (vf_frame[0] && vf_frame[0]->info.res.width != 0) {
7512 in_frame = copy_stage->args.out_vf_frame;
7513 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0],
7514 &vf_pp_binary[0], &vf_pp_stage);
7515 }
7516 if (err) {
7517 IA_CSS_LEAVE_ERR_PRIVATE(err);
7518 return err;
7519 }
7520 }
7521
7522 ia_css_pipeline_finalize_stages(&pipe->pipeline,
7523 pipe->stream->config.continuous);
7524
7525 IA_CSS_LEAVE_ERR_PRIVATE(0);
7526
7527 return 0;
7528}
7529
7530static int
7531create_host_copy_pipeline(struct ia_css_pipe *pipe,
7532 unsigned int max_input_width,
7533 struct ia_css_frame *out_frame)
7534{
7535 struct ia_css_pipeline *me;
7536 int err = 0;
7537 struct ia_css_pipeline_stage_desc stage_desc;
7538
7539 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7540 "create_host_copy_pipeline() enter:\n");
7541
7542
7543 me = &pipe->pipeline;
7544 ia_css_pipeline_clean(me);
7545
7546
7547 out_frame->contiguous = false;
7548 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7549
7550 if (copy_on_sp(pipe) &&
7551 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
7552 ia_css_frame_info_init(&out_frame->info, JPEG_BYTES, 1,
7553 IA_CSS_FRAME_FORMAT_BINARY_8, 0);
7554 } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) {
7555 out_frame->info.raw_bit_depth =
7556 ia_css_pipe_util_pipe_input_format_bpp(pipe);
7557 }
7558
7559 me->num_stages = 1;
7560 me->pipe_id = IA_CSS_PIPE_ID_COPY;
7561 pipe->mode = IA_CSS_PIPE_ID_COPY;
7562
7563 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7564 IA_CSS_PIPELINE_RAW_COPY,
7565 max_input_width);
7566 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, NULL);
7567
7568 ia_css_pipeline_finalize_stages(&pipe->pipeline,
7569 pipe->stream->config.continuous);
7570
7571 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7572 "create_host_copy_pipeline() leave:\n");
7573
7574 return err;
7575}
7576
7577static int
7578create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe)
7579{
7580 struct ia_css_pipeline *me = &pipe->pipeline;
7581 int err = 0;
7582 struct ia_css_pipeline_stage_desc stage_desc;
7583 struct ia_css_frame *out_frame = &me->out_frame[0];
7584 struct ia_css_pipeline_stage *out_stage = NULL;
7585 unsigned int thread_id;
7586 enum sh_css_queue_id queue_id;
7587 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS;
7588
7589 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7590 "create_host_isyscopy_capture_pipeline() enter:\n");
7591 ia_css_pipeline_clean(me);
7592
7593
7594 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0);
7595 if (err)
7596 return err;
7597 out_frame->contiguous = false;
7598 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7599 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7600 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id);
7601 out_frame->dynamic_queue_id = queue_id;
7602 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
7603
7604 me->num_stages = 1;
7605 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
7606 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
7607 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7608 IA_CSS_PIPELINE_ISYS_COPY,
7609 max_input_width);
7610 err = ia_css_pipeline_create_and_add_stage(me,
7611 &stage_desc, &out_stage);
7612 if (err)
7613 return err;
7614
7615 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous);
7616
7617 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7618 "create_host_isyscopy_capture_pipeline() leave:\n");
7619
7620 return err;
7621}
7622
7623static int
7624create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
7625{
7626 struct ia_css_pipeline *me;
7627 int err = 0;
7628 enum ia_css_capture_mode mode;
7629 struct ia_css_pipeline_stage *current_stage = NULL;
7630 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
7631 struct ia_css_binary *copy_binary,
7632 *primary_binary[MAX_NUM_PRIMARY_STAGES],
7633 *vf_pp_binary,
7634 *pre_isp_binary,
7635 *anr_gdc_binary,
7636 *post_isp_binary,
7637 *yuv_scaler_binary,
7638 *capture_pp_binary,
7639 *capture_ldc_binary;
7640 bool need_pp = false;
7641 bool raw;
7642
7643 struct ia_css_frame *in_frame;
7644 struct ia_css_frame *out_frame;
7645 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7646 struct ia_css_frame *vf_frame;
7647 struct ia_css_pipeline_stage_desc stage_desc;
7648 bool need_in_frameinfo_memory = false;
7649#ifdef ISP2401
7650 bool sensor = false;
7651 bool buffered_sensor = false;
7652 bool online = false;
7653 bool continuous = false;
7654#endif
7655 unsigned int i, num_yuv_scaler, num_primary_stage;
7656 bool need_yuv_pp = false;
7657 bool *is_output_stage = NULL;
7658 bool need_ldc = false;
7659
7660 IA_CSS_ENTER_PRIVATE("");
7661 assert(pipe);
7662 assert(pipe->stream);
7663 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
7664 pipe->mode == IA_CSS_PIPE_ID_COPY);
7665
7666 me = &pipe->pipeline;
7667 mode = pipe->config.default_capture_config.mode;
7668 raw = (mode == IA_CSS_CAPTURE_MODE_RAW);
7669 ia_css_pipeline_clean(me);
7670 ia_css_pipe_util_create_output_frames(out_frames);
7671
7672#ifdef ISP2401
7673
7674
7675
7676
7677
7678
7679
7680 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
7681 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
7682 online = pipe->stream->config.online;
7683 continuous = pipe->stream->config.continuous;
7684 need_in_frameinfo_memory =
7685 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
7686#else
7687
7688 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7689#endif
7690 if (need_in_frameinfo_memory) {
7691 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
7692 IA_CSS_FRAME_FORMAT_RAW);
7693 if (err) {
7694 IA_CSS_LEAVE_ERR_PRIVATE(err);
7695 return err;
7696 }
7697
7698 in_frame = &me->in_frame;
7699 } else {
7700 in_frame = NULL;
7701 }
7702
7703 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
7704 if (err) {
7705 IA_CSS_LEAVE_ERR_PRIVATE(err);
7706 return err;
7707 }
7708 out_frame = &me->out_frame[0];
7709
7710
7711 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
7712 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
7713
7714 vf_frame = NULL;
7715 } else {
7716 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
7717 vf_frame = &me->vf_frame[0];
7718 }
7719 } else {
7720 vf_frame = NULL;
7721 }
7722
7723 copy_binary = &pipe->pipe_settings.capture.copy_binary;
7724 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
7725 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) {
7726 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7727 return -EINVAL;
7728 }
7729
7730 for (i = 0; i < num_primary_stage; i++)
7731 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
7732
7733 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary;
7734 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary;
7735 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary;
7736 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary;
7737 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary;
7738 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary;
7739 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler;
7740 is_output_stage = pipe->pipe_settings.capture.is_output_stage;
7741 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary;
7742
7743 need_pp = (need_capture_pp(pipe) || pipe->output_stage) &&
7744 mode != IA_CSS_CAPTURE_MODE_RAW &&
7745 mode != IA_CSS_CAPTURE_MODE_BAYER;
7746 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
7747 need_ldc = (capture_ldc_binary && capture_ldc_binary->info);
7748
7749 if (pipe->pipe_settings.capture.copy_binary.info) {
7750 if (raw) {
7751 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
7752#if defined(ISP2401)
7753 if (!continuous) {
7754 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7755 copy_binary,
7756 out_frames,
7757 in_frame,
7758 NULL);
7759 } else {
7760 in_frame = pipe->stream->last_pipe->continuous_frames[0];
7761 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7762 copy_binary,
7763 out_frames,
7764 in_frame,
7765 NULL);
7766 }
7767#else
7768 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7769 copy_binary,
7770 out_frames,
7771 NULL, NULL);
7772#endif
7773 } else {
7774 ia_css_pipe_util_set_output_frames(out_frames, 0,
7775 in_frame);
7776 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7777 copy_binary,
7778 out_frames,
7779 NULL, NULL);
7780 }
7781
7782 err = ia_css_pipeline_create_and_add_stage(me,
7783 &stage_desc,
7784 ¤t_stage);
7785 if (err) {
7786 IA_CSS_LEAVE_ERR_PRIVATE(err);
7787 return err;
7788 }
7789 } else if (pipe->stream->config.continuous) {
7790 in_frame = pipe->stream->last_pipe->continuous_frames[0];
7791 }
7792
7793 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
7794 struct ia_css_frame *local_in_frame = NULL;
7795 struct ia_css_frame *local_out_frame = NULL;
7796
7797 for (i = 0; i < num_primary_stage; i++) {
7798 if (i == 0)
7799 local_in_frame = in_frame;
7800 else
7801 local_in_frame = NULL;
7802#ifndef ISP2401
7803 if (!need_pp && (i == num_primary_stage - 1))
7804#else
7805 if (!need_pp && (i == num_primary_stage - 1) && !need_ldc)
7806#endif
7807 local_out_frame = out_frame;
7808 else
7809 local_out_frame = NULL;
7810 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame);
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7822 primary_binary[i],
7823 out_frames,
7824 local_in_frame,
7825 NULL);
7826 err = ia_css_pipeline_create_and_add_stage(me,
7827 &stage_desc,
7828 ¤t_stage);
7829 if (err) {
7830 IA_CSS_LEAVE_ERR_PRIVATE(err);
7831 return err;
7832 }
7833 }
7834
7835
7836 current_stage->args.copy_vf =
7837 primary_binary[0]->info->sp.pipeline.mode ==
7838 IA_CSS_BINARY_MODE_COPY;
7839 current_stage->args.copy_output = current_stage->args.copy_vf;
7840 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
7841 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
7842 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7843 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
7844 out_frames, in_frame, NULL);
7845 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7846 NULL);
7847 if (err) {
7848 IA_CSS_LEAVE_ERR_PRIVATE(err);
7849 return err;
7850 }
7851 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7852 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
7853 out_frames, NULL, NULL);
7854 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7855 NULL);
7856 if (err) {
7857 IA_CSS_LEAVE_ERR_PRIVATE(err);
7858 return err;
7859 }
7860
7861 if (need_pp) {
7862 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7863 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7864 post_isp_binary,
7865 out_frames,
7866 NULL, NULL);
7867 } else {
7868 ia_css_pipe_util_set_output_frames(out_frames, 0,
7869 out_frame);
7870 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7871 post_isp_binary,
7872 out_frames,
7873 NULL, NULL);
7874 }
7875
7876 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7877 ¤t_stage);
7878 if (err) {
7879 IA_CSS_LEAVE_ERR_PRIVATE(err);
7880 return err;
7881 }
7882 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) {
7883 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
7884 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
7885 out_frames, in_frame, NULL);
7886 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7887 NULL);
7888 if (err) {
7889 IA_CSS_LEAVE_ERR_PRIVATE(err);
7890 return err;
7891 }
7892 }
7893
7894#ifndef ISP2401
7895 if (need_pp && current_stage) {
7896 struct ia_css_frame *local_in_frame = NULL;
7897
7898 local_in_frame = current_stage->args.out_frame[0];
7899
7900 if (need_ldc) {
7901 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7902 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7903 capture_ldc_binary,
7904 out_frames,
7905 local_in_frame,
7906 NULL);
7907 err = ia_css_pipeline_create_and_add_stage(me,
7908 &stage_desc,
7909 ¤t_stage);
7910 local_in_frame = current_stage->args.out_frame[0];
7911 }
7912 err = add_capture_pp_stage(pipe, me, local_in_frame,
7913 need_yuv_pp ? NULL : out_frame,
7914#else
7915
7916 if (need_ldc && current_stage) {
7917 in_frame = current_stage->args.out_frame[0];
7918 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
7919 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
7920 out_frames, in_frame, NULL);
7921 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7922 NULL);
7923 } else if (need_pp && current_stage) {
7924 in_frame = current_stage->args.out_frame[0];
7925 err = add_capture_pp_stage(pipe, me, in_frame,
7926 need_yuv_pp ? NULL : out_frame,
7927#endif
7928 capture_pp_binary,
7929 ¤t_stage);
7930 if (err) {
7931 IA_CSS_LEAVE_ERR_PRIVATE(err);
7932 return err;
7933 }
7934 }
7935
7936 if (need_yuv_pp && current_stage) {
7937 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
7938 struct ia_css_frame *tmp_out_frame = NULL;
7939
7940 for (i = 0; i < num_yuv_scaler; i++) {
7941 if (is_output_stage[i])
7942 tmp_out_frame = out_frame;
7943 else
7944 tmp_out_frame = NULL;
7945
7946 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
7947 tmp_out_frame, NULL,
7948 &yuv_scaler_binary[i],
7949 &yuv_scaler_stage);
7950 if (err) {
7951 IA_CSS_LEAVE_ERR_PRIVATE(err);
7952 return err;
7953 }
7954
7955 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7956 }
7957 }
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968 if (mode != IA_CSS_CAPTURE_MODE_RAW &&
7969 mode != IA_CSS_CAPTURE_MODE_BAYER &&
7970 current_stage && vf_frame) {
7971 in_frame = current_stage->args.out_vf_frame;
7972 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
7973 ¤t_stage);
7974 if (err) {
7975 IA_CSS_LEAVE_ERR_PRIVATE(err);
7976 return err;
7977 }
7978 }
7979 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7980
7981 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7982 "create_host_regular_capture_pipeline() leave:\n");
7983
7984 return 0;
7985}
7986
7987static int
7988create_host_capture_pipeline(struct ia_css_pipe *pipe)
7989{
7990 int err = 0;
7991
7992 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7993
7994 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7995 err = create_host_isyscopy_capture_pipeline(pipe);
7996 else
7997 err = create_host_regular_capture_pipeline(pipe);
7998 if (err) {
7999 IA_CSS_LEAVE_ERR_PRIVATE(err);
8000 return err;
8001 }
8002
8003 IA_CSS_LEAVE_ERR_PRIVATE(err);
8004
8005 return err;
8006}
8007
8008static int capture_start(struct ia_css_pipe *pipe)
8009{
8010 struct ia_css_pipeline *me;
8011
8012 int err = 0;
8013 enum sh_css_pipe_config_override copy_ovrd;
8014
8015 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8016 if (!pipe) {
8017 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8018 return -EINVAL;
8019 }
8020
8021 me = &pipe->pipeline;
8022
8023 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
8024 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) &&
8025 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
8026 if (copy_on_sp(pipe)) {
8027 err = start_copy_on_sp(pipe, &me->out_frame[0]);
8028 IA_CSS_LEAVE_ERR_PRIVATE(err);
8029 return err;
8030 }
8031 }
8032
8033#if !defined(ISP2401)
8034
8035 err = send_mipi_frames(pipe);
8036 if (err) {
8037 IA_CSS_LEAVE_ERR_PRIVATE(err);
8038 return err;
8039 }
8040#elif defined(ISP2401)
8041 if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
8042 err = send_mipi_frames(pipe);
8043 if (err) {
8044 IA_CSS_LEAVE_ERR_PRIVATE(err);
8045 return err;
8046 }
8047 }
8048
8049#endif
8050
8051 {
8052 unsigned int thread_id;
8053
8054 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
8055 copy_ovrd = 1 << thread_id;
8056 }
8057 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode);
8058
8059#if !defined(ISP2401)
8060
8061
8062
8063
8064
8065 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY &&
8066 pipe->stream->reconfigure_css_rx) {
8067 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
8068 pipe->stream->config.mode);
8069 pipe->stream->reconfigure_css_rx = false;
8070 }
8071#endif
8072
8073 IA_CSS_LEAVE_ERR_PRIVATE(err);
8074 return err;
8075}
8076
8077static int
8078sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
8079 struct ia_css_frame_info *info,
8080 unsigned int idx)
8081{
8082 assert(pipe);
8083 assert(info);
8084
8085 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8086 "sh_css_pipe_get_output_frame_info() enter:\n");
8087
8088 *info = pipe->output_info[idx];
8089 if (copy_on_sp(pipe) &&
8090 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
8091 ia_css_frame_info_init(
8092 info,
8093 JPEG_BYTES,
8094 1,
8095 IA_CSS_FRAME_FORMAT_BINARY_8,
8096 0);
8097 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
8098 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) {
8099 info->raw_bit_depth =
8100 ia_css_pipe_util_pipe_input_format_bpp(pipe);
8101 }
8102
8103 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8104 "sh_css_pipe_get_output_frame_info() leave:\n");
8105 return 0;
8106}
8107
8108void
8109ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
8110 const unsigned short *data,
8111 unsigned int width,
8112 unsigned int height)
8113{
8114 assert(stream);
8115
8116 ia_css_inputfifo_send_input_frame(
8117 data, width, height,
8118 stream->config.channel_id,
8119 stream->config.input_config.format,
8120 stream->config.pixels_per_clock == 2);
8121}
8122
8123void
8124ia_css_stream_start_input_frame(const struct ia_css_stream *stream)
8125{
8126 assert(stream);
8127
8128 ia_css_inputfifo_start_frame(
8129 stream->config.channel_id,
8130 stream->config.input_config.format,
8131 stream->config.pixels_per_clock == 2);
8132}
8133
8134void
8135ia_css_stream_send_input_line(const struct ia_css_stream *stream,
8136 const unsigned short *data,
8137 unsigned int width,
8138 const unsigned short *data2,
8139 unsigned int width2)
8140{
8141 assert(stream);
8142
8143 ia_css_inputfifo_send_line(stream->config.channel_id,
8144 data, width, data2, width2);
8145}
8146
8147void
8148ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
8149 enum atomisp_input_format format,
8150 const unsigned short *data,
8151 unsigned int width)
8152{
8153 assert(stream);
8154 if (!data || width == 0)
8155 return;
8156 ia_css_inputfifo_send_embedded_line(stream->config.channel_id,
8157 format, data, width);
8158}
8159
8160void
8161ia_css_stream_end_input_frame(const struct ia_css_stream *stream)
8162{
8163 assert(stream);
8164
8165 ia_css_inputfifo_end_frame(stream->config.channel_id);
8166}
8167
8168static void
8169append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
8170{
8171 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware);
8172 if (!l) {
8173 IA_CSS_ERROR("NULL fw_info");
8174 IA_CSS_LEAVE_PRIVATE("");
8175 return;
8176 }
8177 while (*l)
8178 l = &(*l)->next;
8179 *l = firmware;
8180
8181 IA_CSS_LEAVE_PRIVATE("");
8182}
8183
8184static void
8185remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
8186{
8187 assert(*l);
8188 assert(firmware);
8189 (void)l;
8190 (void)firmware;
8191 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n");
8192
8193 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n");
8194 return;
8195}
8196
8197static int upload_isp_code(struct ia_css_fw_info *firmware)
8198{
8199 ia_css_ptr binary;
8200
8201 if (!firmware) {
8202 IA_CSS_ERROR("NULL input parameter");
8203 return -EINVAL;
8204 }
8205 binary = firmware->info.isp.xmem_addr;
8206
8207 if (!binary) {
8208 unsigned int size = firmware->blob.size;
8209 const unsigned char *blob;
8210 const unsigned char *binary_name;
8211
8212 binary_name =
8213 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME(
8214 firmware));
8215 blob = binary_name +
8216 strlen((const char *)binary_name) +
8217 1;
8218 binary = sh_css_load_blob(blob, size);
8219 firmware->info.isp.xmem_addr = binary;
8220 }
8221
8222 if (!binary)
8223 return -ENOMEM;
8224 return 0;
8225}
8226
8227static int
8228acc_load_extension(struct ia_css_fw_info *firmware)
8229{
8230 int err;
8231 struct ia_css_fw_info *hd = firmware;
8232
8233 while (hd) {
8234 err = upload_isp_code(hd);
8235 if (err)
8236 return err;
8237 hd = hd->next;
8238 }
8239
8240 if (!firmware)
8241 return -EINVAL;
8242 firmware->loaded = true;
8243 return 0;
8244}
8245
8246static void
8247acc_unload_extension(struct ia_css_fw_info *firmware)
8248{
8249 struct ia_css_fw_info *hd = firmware;
8250 struct ia_css_fw_info *hdn = NULL;
8251
8252 if (!firmware)
8253 return;
8254
8255 while (hd) {
8256 hdn = (hd->next) ? &(*hd->next) : NULL;
8257 if (hd->info.isp.xmem_addr) {
8258 hmm_free(hd->info.isp.xmem_addr);
8259 hd->info.isp.xmem_addr = mmgr_NULL;
8260 }
8261 hd->isp_code = NULL;
8262 hd->next = NULL;
8263 hd = hdn;
8264 }
8265
8266 firmware->loaded = false;
8267}
8268
8269
8270static int
8271ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
8272 struct ia_css_fw_info *firmware)
8273{
8274 int err = 0;
8275
8276 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8277
8278 if ((!firmware) || (!pipe)) {
8279 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8280 return -EINVAL;
8281 }
8282
8283 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8284 append_firmware(&pipe->output_stage, firmware);
8285 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8286 append_firmware(&pipe->vf_stage, firmware);
8287 err = acc_load_extension(firmware);
8288
8289 IA_CSS_LEAVE_ERR_PRIVATE(err);
8290 return err;
8291}
8292
8293
8294static void
8295ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
8296 struct ia_css_fw_info *firmware)
8297{
8298 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8299
8300 if ((!firmware) || (!pipe)) {
8301 IA_CSS_ERROR("NULL input parameters");
8302 IA_CSS_LEAVE_PRIVATE("");
8303 return;
8304 }
8305
8306 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8307 remove_firmware(&pipe->output_stage, firmware);
8308 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8309 remove_firmware(&pipe->vf_stage, firmware);
8310 acc_unload_extension(firmware);
8311
8312 IA_CSS_LEAVE_PRIVATE("");
8313}
8314
8315bool
8316ia_css_pipeline_uses_params(struct ia_css_pipeline *me)
8317{
8318 struct ia_css_pipeline_stage *stage;
8319
8320 assert(me);
8321
8322 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8323 "ia_css_pipeline_uses_params() enter: me=%p\n", me);
8324
8325 for (stage = me->stages; stage; stage = stage->next)
8326 if (stage->binary_info && stage->binary_info->enable.params) {
8327 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8328 "ia_css_pipeline_uses_params() leave: return_bool=true\n");
8329 return true;
8330 }
8331 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8332 "ia_css_pipeline_uses_params() leave: return_bool=false\n");
8333 return false;
8334}
8335
8336static int
8337sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
8338 const void *acc_fw)
8339{
8340 struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw;
8341
8342 int err = 0;
8343
8344 if (!fw->loaded)
8345 err = acc_load_extension(fw);
8346
8347 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8348 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n",
8349 pipeline, acc_fw);
8350
8351 if (!err) {
8352 struct ia_css_pipeline_stage_desc stage_desc;
8353
8354 ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw);
8355 err = ia_css_pipeline_create_and_add_stage(pipeline,
8356 &stage_desc,
8357 NULL);
8358 }
8359
8360 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8361 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n", err);
8362 return err;
8363}
8364
8365
8366
8367
8368
8369int ia_css_stream_capture_frame(struct ia_css_stream *stream,
8370 unsigned int exp_id)
8371{
8372 struct sh_css_tag_descr tag_descr;
8373 u32 encoded_tag_descr;
8374 int err;
8375
8376 assert(stream);
8377 IA_CSS_ENTER("exp_id=%d", exp_id);
8378
8379
8380 if (exp_id == 0 || !stream->config.continuous) {
8381 IA_CSS_LEAVE_ERR(-EINVAL);
8382 return -EINVAL;
8383 }
8384
8385 if (!sh_css_sp_is_running()) {
8386
8387 IA_CSS_LEAVE_ERR(-EBUSY);
8388 return -EBUSY;
8389 }
8390
8391
8392 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr);
8393
8394 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8395
8396
8397
8398
8399 err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr);
8400
8401 IA_CSS_LEAVE_ERR(err);
8402 return err;
8403}
8404
8405
8406
8407
8408
8409int ia_css_stream_capture(struct ia_css_stream *stream, int num_captures,
8410 unsigned int skip, int offset)
8411{
8412 struct sh_css_tag_descr tag_descr;
8413 unsigned int encoded_tag_descr;
8414 int return_err;
8415
8416 if (!stream)
8417 return -EINVAL;
8418
8419 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8420 "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n",
8421 num_captures, skip, offset);
8422
8423
8424 if (num_captures < SH_CSS_MINIMUM_TAG_ID) {
8425 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8426 "ia_css_stream_capture() leave: return_err=%d\n",
8427 -EINVAL);
8428 return -EINVAL;
8429 }
8430
8431
8432 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr);
8433
8434
8435 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8436
8437 if (!sh_css_sp_is_running()) {
8438
8439 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8440 "ia_css_stream_capture() leaving:queues unavailable\n");
8441 return -EBUSY;
8442 }
8443
8444
8445
8446
8447
8448 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr);
8449
8450 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8451 "ia_css_stream_capture() leave: return_err=%d\n",
8452 return_err);
8453
8454 return return_err;
8455}
8456
8457void ia_css_stream_request_flash(struct ia_css_stream *stream)
8458{
8459 (void)stream;
8460
8461 assert(stream);
8462 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8463 "ia_css_stream_request_flash() enter: void\n");
8464
8465#ifndef ISP2401
8466 sh_css_write_host2sp_command(host2sp_cmd_start_flash);
8467#else
8468 if (sh_css_sp_is_running()) {
8469 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) {
8470 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8471 ia_css_debug_dump_sp_sw_debug_info();
8472 ia_css_debug_dump_debug_info(NULL);
8473 }
8474 } else {
8475 IA_CSS_LOG("SP is not running!");
8476 }
8477
8478#endif
8479 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8480 "ia_css_stream_request_flash() leave: return_void\n");
8481}
8482
8483static void
8484sh_css_init_host_sp_control_vars(void)
8485{
8486 const struct ia_css_fw_info *fw;
8487 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
8488
8489 unsigned int HIVE_ADDR_host_sp_queues_initialized;
8490 unsigned int HIVE_ADDR_sp_sleep_mode;
8491 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8492#ifndef ISP2401
8493 unsigned int HIVE_ADDR_sp_stop_copy_preview;
8494#endif
8495 unsigned int HIVE_ADDR_host_sp_com;
8496 unsigned int o = offsetof(struct host_sp_communication, host2sp_command)
8497 / sizeof(int);
8498
8499 unsigned int i;
8500
8501 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8502 "sh_css_init_host_sp_control_vars() enter: void\n");
8503
8504 fw = &sh_css_sp_fw;
8505 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
8506
8507 HIVE_ADDR_host_sp_queues_initialized =
8508 fw->info.sp.host_sp_queues_initialized;
8509 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode;
8510 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb;
8511#ifndef ISP2401
8512 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview;
8513#endif
8514 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
8515
8516 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
8517
8518 (void)HIVE_ADDR_sp_sleep_mode;
8519 (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8520#ifndef ISP2401
8521 (void)HIVE_ADDR_sp_stop_copy_preview;
8522#endif
8523 (void)HIVE_ADDR_host_sp_com;
8524
8525 sp_dmem_store_uint32(SP0_ID,
8526 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
8527 (uint32_t)(0));
8528
8529 sp_dmem_store_uint32(SP0_ID,
8530 (unsigned int)sp_address_of(host_sp_queues_initialized),
8531 (uint32_t)(0));
8532 sp_dmem_store_uint32(SP0_ID,
8533 (unsigned int)sp_address_of(sp_sleep_mode),
8534 (uint32_t)(0));
8535 sp_dmem_store_uint32(SP0_ID,
8536 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
8537 (uint32_t)(false));
8538#ifndef ISP2401
8539 sp_dmem_store_uint32(SP0_ID,
8540 (unsigned int)sp_address_of(sp_stop_copy_preview),
8541 my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0));
8542#endif
8543 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
8544
8545 for (i = 0; i < N_CSI_PORTS; i++) {
8546 sh_css_update_host2sp_num_mipi_frames
8547 (my_css.num_mipi_frames[i]);
8548 }
8549
8550 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8551 "sh_css_init_host_sp_control_vars() leave: return_void\n");
8552}
8553
8554
8555
8556
8557
8558static const struct
8559ia_css_pipe_config ia_css_pipe_default_config = DEFAULT_PIPE_CONFIG;
8560
8561void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config)
8562{
8563 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n");
8564 memcpy(pipe_config, &ia_css_pipe_default_config, sizeof(*pipe_config));
8565}
8566
8567void
8568ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config *extra_config)
8569{
8570 if (!extra_config) {
8571 IA_CSS_ERROR("NULL input parameter");
8572 return;
8573 }
8574
8575 extra_config->enable_raw_binning = false;
8576 extra_config->enable_yuv_ds = false;
8577 extra_config->enable_high_speed = false;
8578 extra_config->enable_dvs_6axis = false;
8579 extra_config->enable_reduced_pipe = false;
8580 extra_config->disable_vf_pp = false;
8581 extra_config->enable_fractional_ds = false;
8582}
8583
8584void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config)
8585{
8586 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n");
8587 assert(stream_config);
8588 memset(stream_config, 0, sizeof(*stream_config));
8589 stream_config->online = true;
8590 stream_config->left_padding = -1;
8591 stream_config->pixels_per_clock = 1;
8592
8593
8594
8595 stream_config->source.port.rxcount = 0x04040404;
8596}
8597
8598static int
8599ia_css_acc_pipe_create(struct ia_css_pipe *pipe)
8600{
8601 int err = 0;
8602
8603 if (!pipe) {
8604 IA_CSS_ERROR("NULL input parameter");
8605 return -EINVAL;
8606 }
8607
8608
8609 if (pipe->config.acc_num_execs == 0)
8610 pipe->config.acc_num_execs = 1;
8611
8612 if (pipe->config.acc_extension)
8613 err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension);
8614
8615 return err;
8616}
8617
8618int ia_css_pipe_create(const struct ia_css_pipe_config *config,
8619 struct ia_css_pipe **pipe)
8620{
8621 int err = 0;
8622
8623 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe);
8624
8625 if (!config || !pipe) {
8626 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8627 return -EINVAL;
8628 }
8629
8630 err = ia_css_pipe_create_extra(config, NULL, pipe);
8631
8632 if (err == 0)
8633 IA_CSS_LOG("pipe created successfully = %p", *pipe);
8634
8635 IA_CSS_LEAVE_ERR_PRIVATE(err);
8636
8637 return err;
8638}
8639
8640int
8641ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
8642 const struct ia_css_pipe_extra_config *extra_config,
8643 struct ia_css_pipe **pipe)
8644{
8645 int err = -EINVAL;
8646 struct ia_css_pipe *internal_pipe = NULL;
8647 unsigned int i;
8648
8649 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
8650
8651
8652 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) {
8653 IA_CSS_LEAVE_ERR_PRIVATE(-ENOSPC);
8654 return -EINVAL;
8655 }
8656
8657 if ((!pipe) || (!config)) {
8658 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8659 return -EINVAL;
8660 }
8661
8662 ia_css_debug_dump_pipe_config(config);
8663 ia_css_debug_dump_pipe_extra_config(extra_config);
8664
8665 err = create_pipe(config->mode, &internal_pipe, false);
8666 if (err) {
8667 IA_CSS_LEAVE_ERR_PRIVATE(err);
8668 return err;
8669 }
8670
8671
8672 internal_pipe->config = *config;
8673 if (extra_config)
8674 internal_pipe->extra_config = *extra_config;
8675 else
8676 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
8677
8678 if (config->mode == IA_CSS_PIPE_MODE_ACC) {
8679
8680
8681
8682 *pipe = internal_pipe;
8683 if (!internal_pipe->config.acc_extension &&
8684 internal_pipe->config.num_acc_stages ==
8685 0) {
8686 *pipe = NULL;
8687 IA_CSS_LEAVE_ERR_PRIVATE(0);
8688 return 0;
8689 }
8690 return ia_css_acc_pipe_create(internal_pipe);
8691 }
8692
8693
8694 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2)
8695 internal_pipe->dvs_frame_delay = 2;
8696 else
8697 internal_pipe->dvs_frame_delay = 1;
8698
8699
8700
8701
8702
8703
8704 if (internal_pipe->extra_config.enable_raw_binning &&
8705 internal_pipe->config.bayer_ds_out_res.width) {
8706
8707 }
8708
8709
8710 if ((internal_pipe->config.vf_pp_in_res.width ||
8711 internal_pipe->config.capt_pp_in_res.width)) {
8712 enum ia_css_frame_format format;
8713
8714 if (internal_pipe->config.vf_pp_in_res.width) {
8715 format = IA_CSS_FRAME_FORMAT_YUV_LINE;
8716 ia_css_frame_info_init(
8717 &internal_pipe->vf_yuv_ds_input_info,
8718 internal_pipe->config.vf_pp_in_res.width,
8719 internal_pipe->config.vf_pp_in_res.height,
8720 format, 0);
8721 }
8722 if (internal_pipe->config.capt_pp_in_res.width) {
8723 format = IA_CSS_FRAME_FORMAT_YUV420;
8724 ia_css_frame_info_init(
8725 &internal_pipe->out_yuv_ds_input_info,
8726 internal_pipe->config.capt_pp_in_res.width,
8727 internal_pipe->config.capt_pp_in_res.height,
8728 format, 0);
8729 }
8730 }
8731 if (internal_pipe->config.vf_pp_in_res.width &&
8732 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
8733 ia_css_frame_info_init(
8734 &internal_pipe->vf_yuv_ds_input_info,
8735 internal_pipe->config.vf_pp_in_res.width,
8736 internal_pipe->config.vf_pp_in_res.height,
8737 IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
8738 }
8739
8740 if (internal_pipe->config.bayer_ds_out_res.width) {
8741 ia_css_frame_info_init(
8742 &internal_pipe->bds_output_info,
8743 internal_pipe->config.bayer_ds_out_res.width,
8744 internal_pipe->config.bayer_ds_out_res.height,
8745 IA_CSS_FRAME_FORMAT_RAW, 0);
8746 }
8747
8748
8749 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
8750 if (internal_pipe->config.output_info[i].res.width) {
8751 err = sh_css_pipe_configure_output(
8752 internal_pipe,
8753 internal_pipe->config.output_info[i].res.width,
8754 internal_pipe->config.output_info[i].res.height,
8755 internal_pipe->config.output_info[i].padded_width,
8756 internal_pipe->config.output_info[i].format,
8757 i);
8758 if (err) {
8759 IA_CSS_LEAVE_ERR_PRIVATE(err);
8760 kvfree(internal_pipe);
8761 internal_pipe = NULL;
8762 return err;
8763 }
8764 }
8765
8766
8767 internal_pipe->enable_viewfinder[i] =
8768 (internal_pipe->config.vf_output_info[i].res.width != 0);
8769 if (internal_pipe->config.vf_output_info[i].res.width) {
8770 err = sh_css_pipe_configure_viewfinder(
8771 internal_pipe,
8772 internal_pipe->config.vf_output_info[i].res.width,
8773 internal_pipe->config.vf_output_info[i].res.height,
8774 internal_pipe->config.vf_output_info[i].padded_width,
8775 internal_pipe->config.vf_output_info[i].format,
8776 i);
8777 if (err) {
8778 IA_CSS_LEAVE_ERR_PRIVATE(err);
8779 kvfree(internal_pipe);
8780 internal_pipe = NULL;
8781 return err;
8782 }
8783 }
8784 }
8785 if (internal_pipe->config.acc_extension) {
8786 err = ia_css_pipe_load_extension(internal_pipe,
8787 internal_pipe->config.acc_extension);
8788 if (err) {
8789 IA_CSS_LEAVE_ERR_PRIVATE(err);
8790 kvfree(internal_pipe);
8791 return err;
8792 }
8793 }
8794
8795 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info));
8796
8797
8798 *pipe = internal_pipe;
8799 IA_CSS_LEAVE_ERR_PRIVATE(0);
8800 return 0;
8801}
8802
8803int
8804ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
8805 struct ia_css_pipe_info *pipe_info)
8806{
8807 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8808 "ia_css_pipe_get_info()\n");
8809 if (!pipe_info) {
8810 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
8811 "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
8812 return -EINVAL;
8813 }
8814 if (!pipe || !pipe->stream) {
8815 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
8816 "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n");
8817 return -EINVAL;
8818 }
8819
8820 *pipe_info = pipe->info;
8821 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n");
8822 return 0;
8823}
8824
8825bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info)
8826{
8827 unsigned int i;
8828
8829 if (pipe_info) {
8830 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) {
8831 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable)
8832 return true;
8833 }
8834 }
8835
8836 return false;
8837}
8838
8839int
8840ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
8841 int pin_index,
8842 enum ia_css_frame_format new_format)
8843{
8844 int err = 0;
8845
8846 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
8847
8848 if (!pipe) {
8849 IA_CSS_ERROR("pipe is not set");
8850 err = -EINVAL;
8851 IA_CSS_LEAVE_ERR_PRIVATE(err);
8852 return err;
8853 }
8854 if (0 != pin_index && 1 != pin_index) {
8855 IA_CSS_ERROR("pin index is not valid");
8856 err = -EINVAL;
8857 IA_CSS_LEAVE_ERR_PRIVATE(err);
8858 return err;
8859 }
8860 if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY) {
8861 IA_CSS_ERROR("new format is not valid");
8862 err = -EINVAL;
8863 IA_CSS_LEAVE_ERR_PRIVATE(err);
8864 return err;
8865 } else {
8866 err = ia_css_pipe_check_format(pipe, new_format);
8867 if (!err) {
8868 if (pin_index == 0)
8869 pipe->output_info[0].format = new_format;
8870 else
8871 pipe->vf_output_info[0].format = new_format;
8872 }
8873 }
8874 IA_CSS_LEAVE_ERR_PRIVATE(err);
8875 return err;
8876}
8877
8878#if !defined(ISP2401)
8879
8880static int
8881ia_css_stream_configure_rx(struct ia_css_stream *stream)
8882{
8883 struct ia_css_input_port *config;
8884
8885 assert(stream);
8886
8887 config = &stream->config.source.port;
8888
8889 if (config->num_lanes == 1)
8890 stream->csi_rx_config.mode = MONO_1L_1L_0L;
8891 else if (config->num_lanes == 2)
8892 stream->csi_rx_config.mode = MONO_2L_1L_0L;
8893 else if (config->num_lanes == 3)
8894 stream->csi_rx_config.mode = MONO_3L_1L_0L;
8895 else if (config->num_lanes == 4)
8896 stream->csi_rx_config.mode = MONO_4L_1L_0L;
8897 else if (config->num_lanes != 0)
8898 return -EINVAL;
8899
8900 if (config->port > MIPI_PORT2_ID)
8901 return -EINVAL;
8902 stream->csi_rx_config.port =
8903 ia_css_isys_port_to_mipi_port(config->port);
8904 stream->csi_rx_config.timeout = config->timeout;
8905 stream->csi_rx_config.initcount = 0;
8906 stream->csi_rx_config.synccount = 0x28282828;
8907 stream->csi_rx_config.rxcount = config->rxcount;
8908 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
8909 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
8910 else
8911
8912
8913 return -EINVAL;
8914
8915 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
8916 stream->reconfigure_css_rx = true;
8917 return 0;
8918}
8919#endif
8920
8921static struct ia_css_pipe *
8922find_pipe(struct ia_css_pipe *pipes[], unsigned int num_pipes,
8923 enum ia_css_pipe_mode mode, bool copy_pipe)
8924{
8925 unsigned int i;
8926
8927 assert(pipes);
8928 for (i = 0; i < num_pipes; i++) {
8929 assert(pipes[i]);
8930 if (pipes[i]->config.mode != mode)
8931 continue;
8932 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY)
8933 continue;
8934 return pipes[i];
8935 }
8936 return NULL;
8937}
8938
8939static int
8940ia_css_acc_stream_create(struct ia_css_stream *stream)
8941{
8942 int i;
8943 int err = 0;
8944
8945 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
8946
8947 if (!stream) {
8948 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8949 return -EINVAL;
8950 }
8951
8952 for (i = 0; i < stream->num_pipes; i++) {
8953 struct ia_css_pipe *pipe = stream->pipes[i];
8954
8955 if (!pipe) {
8956 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8957 return -EINVAL;
8958 }
8959
8960 pipe->stream = stream;
8961 }
8962
8963
8964 err = map_sp_threads(stream, true);
8965 if (err) {
8966 IA_CSS_LEAVE_ERR_PRIVATE(err);
8967 return err;
8968 }
8969
8970 for (i = 0; i < stream->num_pipes; i++) {
8971 struct ia_css_pipe *pipe = stream->pipes[i];
8972
8973 assert(pipe);
8974 ia_css_pipe_map_queue(pipe, true);
8975 }
8976
8977 err = create_host_pipeline_structure(stream);
8978 if (err) {
8979 IA_CSS_LEAVE_ERR_PRIVATE(err);
8980 return err;
8981 }
8982
8983 stream->started = false;
8984
8985 IA_CSS_LEAVE_ERR_PRIVATE(0);
8986
8987 return 0;
8988}
8989
8990static int
8991metadata_info_init(const struct ia_css_metadata_config *mdc,
8992 struct ia_css_metadata_info *md)
8993{
8994
8995 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
8996 return -EINVAL;
8997
8998 md->resolution = mdc->resolution;
8999
9000
9001 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES);
9002 md->size = mdc->resolution.height * md->stride;
9003 return 0;
9004}
9005
9006
9007static int check_pipe_resolutions(const struct ia_css_pipe *pipe)
9008{
9009 int err = 0;
9010
9011 IA_CSS_ENTER_PRIVATE("");
9012
9013 if (!pipe || !pipe->stream) {
9014 IA_CSS_ERROR("null arguments");
9015 err = -EINVAL;
9016 goto EXIT;
9017 }
9018
9019 if (ia_css_util_check_res(pipe->config.input_effective_res.width,
9020 pipe->config.input_effective_res.height) != 0) {
9021 IA_CSS_ERROR("effective resolution not supported");
9022 err = -EINVAL;
9023 goto EXIT;
9024 }
9025 if (!ia_css_util_resolution_is_zero(
9026 pipe->stream->config.input_config.input_res)) {
9027 if (!ia_css_util_res_leq(pipe->config.input_effective_res,
9028 pipe->stream->config.input_config.input_res)) {
9029 IA_CSS_ERROR("effective resolution is larger than input resolution");
9030 err = -EINVAL;
9031 goto EXIT;
9032 }
9033 }
9034 if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) {
9035 IA_CSS_ERROR("output resolution must be even");
9036 err = -EINVAL;
9037 goto EXIT;
9038 }
9039 if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) {
9040 IA_CSS_ERROR("VF resolution must be even");
9041 err = -EINVAL;
9042 goto EXIT;
9043 }
9044EXIT:
9045 IA_CSS_LEAVE_ERR_PRIVATE(err);
9046 return err;
9047}
9048
9049int
9050ia_css_stream_create(const struct ia_css_stream_config *stream_config,
9051 int num_pipes,
9052 struct ia_css_pipe *pipes[],
9053 struct ia_css_stream **stream)
9054{
9055 struct ia_css_pipe *curr_pipe;
9056 struct ia_css_stream *curr_stream = NULL;
9057 bool spcopyonly;
9058 bool sensor_binning_changed;
9059 int i, j;
9060 int err = -EINVAL;
9061 struct ia_css_metadata_info md_info;
9062 struct ia_css_resolution effective_res;
9063#ifdef ISP2401
9064 bool aspect_ratio_crop_enabled = false;
9065#endif
9066
9067 IA_CSS_ENTER("num_pipes=%d", num_pipes);
9068 ia_css_debug_dump_stream_config(stream_config, num_pipes);
9069
9070
9071 if (num_pipes == 0 ||
9072 !stream ||
9073 !pipes) {
9074 err = -EINVAL;
9075 IA_CSS_LEAVE_ERR(err);
9076 return err;
9077 }
9078
9079#if !defined(ISP2401)
9080
9081 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
9082 stream_config->metadata_config.resolution.height > 0) {
9083 err = -EINVAL;
9084 IA_CSS_LEAVE_ERR(err);
9085 return err;
9086 }
9087#endif
9088
9089#ifdef ISP2401
9090 if (stream_config->online && stream_config->pack_raw_pixels) {
9091 IA_CSS_LOG("online and pack raw is invalid on input system 2401");
9092 err = -EINVAL;
9093 IA_CSS_LEAVE_ERR(err);
9094 return err;
9095 }
9096#endif
9097
9098 ia_css_debug_pipe_graph_dump_stream_config(stream_config);
9099
9100
9101 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
9102#ifdef ISP2401
9103 if (!stream_config->online)
9104#endif
9105 {
9106 unsigned int port = (unsigned int)stream_config->source.port.port;
9107
9108 if (port >= N_MIPI_PORT_ID) {
9109 err = -EINVAL;
9110 IA_CSS_LEAVE_ERR(err);
9111 return err;
9112 }
9113
9114 if (my_css.size_mem_words != 0) {
9115 my_css.mipi_frame_size[port] = my_css.size_mem_words;
9116 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) {
9117 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words;
9118 } else {
9119 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9120 "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
9121 assert(stream_config->mipi_buffer_config.size_mem_words != 0);
9122 err = -EINVAL;
9123 IA_CSS_LEAVE_ERR(err);
9124 return err;
9125 }
9126
9127 if (my_css.size_mem_words != 0) {
9128 my_css.num_mipi_frames[port] =
9129 2;
9130 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) {
9131 my_css.num_mipi_frames[port] =
9132 stream_config->mipi_buffer_config.nof_mipi_buffers;
9133 } else {
9134 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9135 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
9136 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0);
9137 err = -EINVAL;
9138 IA_CSS_LEAVE_ERR(err);
9139 return err;
9140 }
9141 }
9142
9143
9144 err = metadata_info_init(&stream_config->metadata_config, &md_info);
9145 if (err) {
9146 IA_CSS_LEAVE_ERR(err);
9147 return err;
9148 }
9149
9150
9151 curr_stream = kzalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
9152 if (!curr_stream) {
9153 err = -ENOMEM;
9154 IA_CSS_LEAVE_ERR(err);
9155 return err;
9156 }
9157
9158 curr_stream->info.metadata_info = md_info;
9159
9160
9161 curr_stream->num_pipes = num_pipes;
9162 curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL);
9163 if (!curr_stream->pipes) {
9164 curr_stream->num_pipes = 0;
9165 kfree(curr_stream);
9166 curr_stream = NULL;
9167 err = -ENOMEM;
9168 IA_CSS_LEAVE_ERR(err);
9169 return err;
9170 }
9171
9172 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY);
9173 for (i = 0; i < num_pipes; i++)
9174 curr_stream->pipes[i] = pipes[i];
9175 curr_stream->last_pipe = curr_stream->pipes[0];
9176
9177 curr_stream->config = *stream_config;
9178
9179#if defined(ISP2401)
9180 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
9181 stream_config->online)
9182 curr_stream->config.online = false;
9183#endif
9184
9185#ifdef ISP2401
9186 if (curr_stream->config.online) {
9187 curr_stream->config.source.port.num_lanes =
9188 stream_config->source.port.num_lanes;
9189 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9190 }
9191#endif
9192
9193 if (curr_stream->config.target_num_cont_raw_buf == 0)
9194 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
9195 if (curr_stream->config.init_num_cont_raw_buf == 0)
9196 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf;
9197
9198
9199 if (curr_stream->config.ia_css_enable_raw_buffer_locking)
9200 sh_css_sp_configure_enable_raw_pool_locking(
9201 curr_stream->config.lock_all);
9202
9203
9204 switch (curr_stream->config.mode) {
9205 case IA_CSS_INPUT_MODE_SENSOR:
9206 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
9207#if !defined(ISP2401)
9208 ia_css_stream_configure_rx(curr_stream);
9209#endif
9210 break;
9211 case IA_CSS_INPUT_MODE_TPG:
9212#if !defined(ISP2401)
9213 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
9214 curr_stream->config.source.tpg.x_mask,
9215 curr_stream->config.source.tpg.y_mask,
9216 curr_stream->config.source.tpg.x_delta,
9217 curr_stream->config.source.tpg.y_delta,
9218 curr_stream->config.source.tpg.xy_mask);
9219
9220 sh_css_sp_configure_tpg(
9221 curr_stream->config.source.tpg.x_mask,
9222 curr_stream->config.source.tpg.y_mask,
9223 curr_stream->config.source.tpg.x_delta,
9224 curr_stream->config.source.tpg.y_delta,
9225 curr_stream->config.source.tpg.xy_mask);
9226#endif
9227 break;
9228 case IA_CSS_INPUT_MODE_PRBS:
9229#if !defined(ISP2401)
9230 IA_CSS_LOG("mode prbs");
9231 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed);
9232#endif
9233 break;
9234 case IA_CSS_INPUT_MODE_MEMORY:
9235 IA_CSS_LOG("mode memory");
9236 curr_stream->reconfigure_css_rx = false;
9237 break;
9238 default:
9239 IA_CSS_LOG("mode sensor/default");
9240 }
9241
9242#ifdef ISP2401
9243 err = aspect_ratio_crop_init(curr_stream, pipes,
9244 &aspect_ratio_crop_enabled);
9245 if (err) {
9246 IA_CSS_LEAVE_ERR(err);
9247 goto ERR;
9248 }
9249#endif
9250 for (i = 0; i < num_pipes; i++) {
9251 struct ia_css_resolution effective_res;
9252
9253 curr_pipe = pipes[i];
9254
9255 curr_pipe->stream = curr_stream;
9256
9257
9258 effective_res = curr_pipe->config.input_effective_res;
9259 if (effective_res.height == 0 || effective_res.width == 0) {
9260 effective_res = curr_pipe->stream->config.input_config.effective_res;
9261
9262#if defined(ISP2401)
9263
9264
9265 if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) {
9266 struct ia_css_resolution crop_res;
9267
9268 err = aspect_ratio_crop(curr_pipe, &crop_res);
9269 if (!err) {
9270 effective_res = crop_res;
9271 } else {
9272
9273
9274 IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err);
9275 }
9276 }
9277#endif
9278 curr_pipe->config.input_effective_res = effective_res;
9279 }
9280 IA_CSS_LOG("effective_res=%dx%d",
9281 effective_res.width,
9282 effective_res.height);
9283 }
9284
9285 if (IS_ISP2401) {
9286 for (i = 0; i < num_pipes; i++) {
9287 if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC &&
9288 pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) {
9289 err = check_pipe_resolutions(pipes[i]);
9290 if (err)
9291 goto ERR;
9292 }
9293 }
9294 }
9295
9296 err = ia_css_stream_isp_parameters_init(curr_stream);
9297 if (err)
9298 goto ERR;
9299 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
9300
9301 if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) {
9302 *stream = curr_stream;
9303 err = ia_css_acc_stream_create(curr_stream);
9304 goto ERR;
9305 }
9306
9307 if (!spcopyonly) {
9308 sensor_binning_changed =
9309 sh_css_params_set_binning_factor(curr_stream,
9310 curr_stream->config.sensor_binning_factor);
9311 } else {
9312 sensor_binning_changed = false;
9313 }
9314
9315 IA_CSS_LOG("sensor_binning=%d, changed=%d",
9316 curr_stream->config.sensor_binning_factor, sensor_binning_changed);
9317
9318 IA_CSS_LOG("num_pipes=%d", num_pipes);
9319 curr_stream->cont_capt = false;
9320
9321
9322 if (curr_stream->config.continuous) {
9323
9324 struct ia_css_pipe *preview_pipe;
9325 struct ia_css_pipe *video_pipe;
9326 struct ia_css_pipe *acc_pipe;
9327 struct ia_css_pipe *capture_pipe = NULL;
9328 struct ia_css_pipe *copy_pipe = NULL;
9329
9330 if (num_pipes >= 2) {
9331 curr_stream->cont_capt = true;
9332 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder;
9333
9334 if (!IS_ISP2401)
9335 curr_stream->stop_copy_preview = my_css.stop_copy_preview;
9336 }
9337
9338
9339 preview_pipe = find_pipe(pipes, num_pipes,
9340 IA_CSS_PIPE_MODE_PREVIEW, false);
9341 video_pipe = find_pipe(pipes, num_pipes,
9342 IA_CSS_PIPE_MODE_VIDEO, false);
9343 acc_pipe = find_pipe(pipes, num_pipes, IA_CSS_PIPE_MODE_ACC,
9344 false);
9345 if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt)
9346 curr_stream->cont_capt =
9347 false;
9348 if (curr_stream->cont_capt) {
9349 capture_pipe = find_pipe(pipes, num_pipes,
9350 IA_CSS_PIPE_MODE_CAPTURE,
9351 false);
9352 if (!capture_pipe) {
9353 err = -EINVAL;
9354 goto ERR;
9355 }
9356 }
9357
9358 if (preview_pipe && video_pipe) {
9359 err = -EINVAL;
9360 goto ERR;
9361 }
9362
9363 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) {
9364 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9365 if (err)
9366 goto ERR;
9367 ia_css_pipe_config_defaults(©_pipe->config);
9368 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
9369 copy_pipe->stream = curr_stream;
9370 }
9371 if (preview_pipe && curr_stream->cont_capt)
9372 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
9373
9374 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
9375 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9376 if (err)
9377 goto ERR;
9378 ia_css_pipe_config_defaults(©_pipe->config);
9379 video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
9380 copy_pipe->stream = curr_stream;
9381 }
9382 if (video_pipe && curr_stream->cont_capt)
9383 video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
9384
9385 if (preview_pipe && acc_pipe)
9386 preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe;
9387 }
9388 for (i = 0; i < num_pipes; i++) {
9389 curr_pipe = pipes[i];
9390
9391 curr_pipe->stream = curr_stream;
9392
9393 if (!IS_ISP2401) {
9394
9395
9396 effective_res = curr_pipe->config.input_effective_res;
9397 err = ia_css_util_check_res(
9398 effective_res.width,
9399 effective_res.height);
9400 if (err)
9401 goto ERR;
9402 }
9403
9404 if (sensor_binning_changed)
9405 sh_css_pipe_free_shading_table(curr_pipe);
9406 }
9407
9408
9409 for (i = 0; i < num_pipes; i++) {
9410 struct ia_css_pipe_info *pipe_info = NULL;
9411
9412 curr_pipe = pipes[i];
9413
9414 err = sh_css_pipe_load_binaries(curr_pipe);
9415 if (err)
9416 goto ERR;
9417
9418
9419 pipe_info = &curr_pipe->info;
9420 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9421 err = sh_css_pipe_get_output_frame_info(curr_pipe,
9422 &pipe_info->output_info[j], j);
9423 if (err)
9424 goto ERR;
9425 }
9426
9427 if (IS_ISP2401)
9428 pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res;
9429
9430 if (!spcopyonly) {
9431 if (!IS_ISP2401)
9432 err = sh_css_pipe_get_shading_info(curr_pipe,
9433 &pipe_info->shading_info,
9434 NULL);
9435 else
9436 err = sh_css_pipe_get_shading_info(curr_pipe,
9437 &pipe_info->shading_info,
9438 &curr_pipe->config);
9439
9440 if (err)
9441 goto ERR;
9442 err = sh_css_pipe_get_grid_info(curr_pipe,
9443 &pipe_info->grid_info);
9444 if (err)
9445 goto ERR;
9446 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9447 sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
9448 &pipe_info->vf_output_info[j],
9449 j);
9450 if (err)
9451 goto ERR;
9452 }
9453 }
9454
9455 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe;
9456 }
9457
9458 curr_stream->started = false;
9459
9460
9461 err = map_sp_threads(curr_stream, true);
9462 if (err) {
9463 IA_CSS_LOG("map_sp_threads: return_err=%d", err);
9464 goto ERR;
9465 }
9466
9467 for (i = 0; i < num_pipes; i++) {
9468 curr_pipe = pipes[i];
9469 ia_css_pipe_map_queue(curr_pipe, true);
9470 }
9471
9472
9473 err = create_host_pipeline_structure(curr_stream);
9474 if (err) {
9475 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
9476 goto ERR;
9477 }
9478
9479
9480 *stream = curr_stream;
9481
9482ERR:
9483 if (!err) {
9484
9485 if (my_css_save.mode == sh_css_mode_working) {
9486 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9487 if (!my_css_save.stream_seeds[i].stream) {
9488 IA_CSS_LOG("entered stream into loc=%d", i);
9489 my_css_save.stream_seeds[i].orig_stream = stream;
9490 my_css_save.stream_seeds[i].stream = curr_stream;
9491 my_css_save.stream_seeds[i].num_pipes = num_pipes;
9492 my_css_save.stream_seeds[i].stream_config = *stream_config;
9493 for (j = 0; j < num_pipes; j++) {
9494 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
9495 my_css_save.stream_seeds[i].pipes[j] = pipes[j];
9496 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
9497 }
9498 break;
9499 }
9500 }
9501 } else {
9502 ia_css_stream_destroy(curr_stream);
9503 }
9504 } else {
9505 ia_css_stream_destroy(curr_stream);
9506 }
9507 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
9508 return err;
9509}
9510
9511int
9512ia_css_stream_destroy(struct ia_css_stream *stream)
9513{
9514 int i;
9515 int err = 0;
9516
9517 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9518 if (!stream) {
9519 err = -EINVAL;
9520 IA_CSS_LEAVE_ERR_PRIVATE(err);
9521 return err;
9522 }
9523
9524 ia_css_stream_isp_parameters_uninit(stream);
9525
9526 if ((stream->last_pipe) &&
9527 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) {
9528#if defined(ISP2401)
9529 bool free_mpi;
9530
9531 for (i = 0; i < stream->num_pipes; i++) {
9532 struct ia_css_pipe *entry = stream->pipes[i];
9533 unsigned int sp_thread_id;
9534 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
9535
9536 assert(entry);
9537 if (entry) {
9538
9539 if (!ia_css_pipeline_get_sp_thread_id(
9540 ia_css_pipe_get_pipe_num(entry), &sp_thread_id))
9541 return -EINVAL;
9542
9543 sp_pipeline_input_terminal =
9544 &sh_css_sp_group.pipe_io[sp_thread_id].input;
9545
9546 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
9547 ia_css_isys_stream_h isys_stream =
9548 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i];
9549 if (stream->config.isys_config[i].valid && isys_stream->valid)
9550 ia_css_isys_stream_destroy(isys_stream);
9551 }
9552 }
9553 }
9554 free_mpi = stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9555 if (IS_ISP2401) {
9556 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_TPG;
9557 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_PRBS;
9558 }
9559
9560 if (free_mpi) {
9561 for (i = 0; i < stream->num_pipes; i++) {
9562 struct ia_css_pipe *entry = stream->pipes[i];
9563
9564
9565
9566
9567 if (entry)
9568 free_mipi_frames(entry);
9569 }
9570 }
9571 stream_unregister_with_csi_rx(stream);
9572#endif
9573
9574 for (i = 0; i < stream->num_pipes; i++) {
9575 struct ia_css_pipe *curr_pipe = stream->pipes[i];
9576
9577 assert(curr_pipe);
9578 ia_css_pipe_map_queue(curr_pipe, false);
9579 }
9580
9581 err = map_sp_threads(stream, false);
9582 if (err) {
9583 IA_CSS_LEAVE_ERR_PRIVATE(err);
9584 return err;
9585 }
9586 }
9587
9588
9589 for (i = 0; i < stream->num_pipes; i++) {
9590 struct ia_css_pipe *entry = stream->pipes[i];
9591
9592 assert(entry);
9593 if (entry) {
9594
9595 entry->stream = NULL;
9596
9597 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
9598 entry->pipe_settings.preview.copy_pipe) {
9599 IA_CSS_LOG("clearing stream on internal preview copy pipe");
9600 entry->pipe_settings.preview.copy_pipe->stream = NULL;
9601 }
9602 if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
9603 entry->pipe_settings.video.copy_pipe) {
9604 IA_CSS_LOG("clearing stream on internal video copy pipe");
9605 entry->pipe_settings.video.copy_pipe->stream = NULL;
9606 }
9607 err = sh_css_pipe_unload_binaries(entry);
9608 }
9609 }
9610
9611 kfree(stream->pipes);
9612 stream->pipes = NULL;
9613 stream->num_pipes = 0;
9614
9615
9616 if (my_css_save.mode == sh_css_mode_working) {
9617 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9618 if (my_css_save.stream_seeds[i].stream == stream) {
9619 IA_CSS_LOG("took out stream %d", i);
9620 my_css_save.stream_seeds[i].stream = NULL;
9621 break;
9622 }
9623 }
9624 }
9625
9626 kfree(stream);
9627 IA_CSS_LEAVE_ERR(err);
9628
9629 return err;
9630}
9631
9632int
9633ia_css_stream_get_info(const struct ia_css_stream *stream,
9634 struct ia_css_stream_info *stream_info)
9635{
9636 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
9637 assert(stream);
9638 assert(stream_info);
9639
9640 *stream_info = stream->info;
9641 return 0;
9642}
9643
9644
9645
9646
9647
9648
9649
9650int
9651ia_css_stream_load(struct ia_css_stream *stream)
9652{
9653 int i, j, err;
9654
9655 if (IS_ISP2401) {
9656
9657 (void)stream;
9658 return -ENOTSUPP;
9659 }
9660
9661 assert(stream);
9662 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n");
9663 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9664 if (my_css_save.stream_seeds[i].stream != stream)
9665 continue;
9666
9667 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) {
9668 int k;
9669
9670 err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j],
9671 &my_css_save.stream_seeds[i].pipes[j]);
9672 if (!err)
9673 continue;
9674
9675 for (k = 0; k < j; k++)
9676 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
9677 return err;
9678 }
9679 err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config,
9680 my_css_save.stream_seeds[i].num_pipes,
9681 my_css_save.stream_seeds[i].pipes,
9682 &my_css_save.stream_seeds[i].stream);
9683 if (!err)
9684 break;
9685
9686 ia_css_stream_destroy(stream);
9687 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
9688 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
9689 return err;
9690 }
9691
9692 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit,\n");
9693 return 0;
9694}
9695
9696int
9697ia_css_stream_start(struct ia_css_stream *stream)
9698{
9699 int err = 0;
9700
9701 IA_CSS_ENTER("stream = %p", stream);
9702 if ((!stream) || (!stream->last_pipe)) {
9703 IA_CSS_LEAVE_ERR(-EINVAL);
9704 return -EINVAL;
9705 }
9706 IA_CSS_LOG("starting %d", stream->last_pipe->mode);
9707
9708 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
9709
9710
9711 err = create_host_pipeline(stream);
9712 if (err) {
9713 IA_CSS_LEAVE_ERR(err);
9714 return err;
9715 }
9716
9717#if defined(ISP2401)
9718 if ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
9719 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
9720 stream_register_with_csi_rx(stream);
9721#endif
9722
9723#if !defined(ISP2401)
9724
9725 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
9726 unsigned int idx;
9727 unsigned int port = (unsigned int)(stream->config.source.port.port);
9728
9729 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
9730 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] =
9731 sh_css_get_mipi_sizes_for_check(port, idx);
9732 }
9733 }
9734#endif
9735
9736 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) {
9737 err = sh_css_config_input_network(stream);
9738 if (err)
9739 return err;
9740 }
9741
9742 err = sh_css_pipe_start(stream);
9743 IA_CSS_LEAVE_ERR(err);
9744 return err;
9745}
9746
9747int
9748ia_css_stream_stop(struct ia_css_stream *stream)
9749{
9750 int err = 0;
9751
9752 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
9753 assert(stream);
9754 assert(stream->last_pipe);
9755 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
9756 stream->last_pipe->mode);
9757
9758#if !defined(ISP2401)
9759
9760 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
9761 unsigned int idx;
9762 unsigned int port = (unsigned int)(stream->config.source.port.port);
9763
9764 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++)
9765 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
9766 }
9767#endif
9768
9769 if (!IS_ISP2401)
9770 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
9771 else
9772 err = sh_css_pipes_stop(stream);
9773
9774 if (err)
9775 return err;
9776
9777
9778
9779
9780
9781 return err;
9782}
9783
9784bool
9785ia_css_stream_has_stopped(struct ia_css_stream *stream)
9786{
9787 bool stopped;
9788
9789 assert(stream);
9790
9791 if (!IS_ISP2401)
9792 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
9793 else
9794 stopped = sh_css_pipes_have_stopped(stream);
9795
9796 return stopped;
9797}
9798
9799
9800
9801
9802
9803
9804int
9805ia_css_stream_unload(struct ia_css_stream *stream)
9806{
9807 int i;
9808
9809 assert(stream);
9810 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter,\n");
9811
9812 assert(stream);
9813 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
9814 if (my_css_save.stream_seeds[i].stream == stream) {
9815 int j;
9816
9817 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9818 "ia_css_stream_unload(): unloading %d (%p)\n", i,
9819 my_css_save.stream_seeds[i].stream);
9820 ia_css_stream_destroy(stream);
9821 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
9822 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
9823 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9824 "ia_css_stream_unload(): after unloading %d (%p)\n", i,
9825 my_css_save.stream_seeds[i].stream);
9826 break;
9827 }
9828 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit,\n");
9829 return 0;
9830}
9831
9832int
9833ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe,
9834 enum ia_css_pipe_id *pipe_id)
9835{
9836 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
9837 if (pipe)
9838 *pipe_id = pipe->mode;
9839 else
9840 *pipe_id = IA_CSS_PIPE_ID_COPY;
9841
9842 return 0;
9843}
9844
9845enum atomisp_input_format
9846ia_css_stream_get_format(const struct ia_css_stream *stream)
9847{
9848 return stream->config.input_config.format;
9849}
9850
9851bool
9852ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream)
9853{
9854 return (stream->config.pixels_per_clock == 2);
9855}
9856
9857struct ia_css_binary *
9858ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
9859 *stream)
9860{
9861 struct ia_css_pipe *pipe;
9862
9863 assert(stream);
9864
9865 pipe = stream->pipes[0];
9866
9867 if (stream->num_pipes == 2) {
9868 assert(stream->pipes[1]);
9869 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
9870 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
9871 pipe = stream->pipes[1];
9872 }
9873
9874 return ia_css_pipe_get_shading_correction_binary(pipe);
9875}
9876
9877struct ia_css_binary *
9878ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream)
9879{
9880 int i;
9881 struct ia_css_pipe *video_pipe = NULL;
9882
9883
9884 for (i = 0; i < stream->num_pipes; i++) {
9885 struct ia_css_pipe *pipe = stream->pipes[i];
9886
9887 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
9888 video_pipe = pipe;
9889 break;
9890 }
9891 }
9892 if (video_pipe)
9893 return &video_pipe->pipe_settings.video.video_binary;
9894 return NULL;
9895}
9896
9897struct ia_css_binary *
9898ia_css_stream_get_3a_binary(const struct ia_css_stream *stream)
9899{
9900 struct ia_css_pipe *pipe;
9901 struct ia_css_binary *s3a_binary = NULL;
9902
9903 assert(stream);
9904
9905 pipe = stream->pipes[0];
9906
9907 if (stream->num_pipes == 2) {
9908 assert(stream->pipes[1]);
9909 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
9910 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
9911 pipe = stream->pipes[1];
9912 }
9913
9914 s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
9915
9916 return s3a_binary;
9917}
9918
9919int
9920ia_css_stream_set_output_padded_width(struct ia_css_stream *stream,
9921 unsigned int output_padded_width)
9922{
9923 struct ia_css_pipe *pipe;
9924
9925 assert(stream);
9926
9927 pipe = stream->last_pipe;
9928
9929 assert(pipe);
9930
9931
9932 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
9933 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
9934
9935 return 0;
9936}
9937
9938static struct ia_css_binary *
9939ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe)
9940{
9941 struct ia_css_binary *binary = NULL;
9942
9943 assert(pipe);
9944
9945 switch (pipe->config.mode) {
9946 case IA_CSS_PIPE_MODE_PREVIEW:
9947 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
9948 break;
9949 case IA_CSS_PIPE_MODE_VIDEO:
9950 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
9951 break;
9952 case IA_CSS_PIPE_MODE_CAPTURE:
9953 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
9954 unsigned int i;
9955
9956 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
9957 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
9958 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
9959 break;
9960 }
9961 }
9962 } else if (pipe->config.default_capture_config.mode ==
9963 IA_CSS_CAPTURE_MODE_BAYER)
9964 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
9965 else if (pipe->config.default_capture_config.mode ==
9966 IA_CSS_CAPTURE_MODE_ADVANCED ||
9967 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
9968 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
9969 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
9970 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
9971 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
9972 }
9973 break;
9974 default:
9975 break;
9976 }
9977
9978 if (binary && binary->info->sp.enable.sc)
9979 return binary;
9980
9981 return NULL;
9982}
9983
9984static struct ia_css_binary *
9985ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe)
9986{
9987 struct ia_css_binary *binary = NULL;
9988
9989 assert(pipe);
9990
9991 switch (pipe->config.mode) {
9992 case IA_CSS_PIPE_MODE_PREVIEW:
9993 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
9994 break;
9995 case IA_CSS_PIPE_MODE_VIDEO:
9996 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
9997 break;
9998 case IA_CSS_PIPE_MODE_CAPTURE:
9999 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10000 unsigned int i;
10001
10002 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10003 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10004 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10005 break;
10006 }
10007 }
10008 } else if (pipe->config.default_capture_config.mode ==
10009 IA_CSS_CAPTURE_MODE_BAYER) {
10010 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10011 } else if (pipe->config.default_capture_config.mode ==
10012 IA_CSS_CAPTURE_MODE_ADVANCED ||
10013 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10014 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10015 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10016 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10017 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10018 else
10019 assert(0);
10020 }
10021 break;
10022 default:
10023 break;
10024 }
10025
10026 if (binary && !binary->info->sp.enable.s3a)
10027 binary = NULL;
10028
10029 return binary;
10030}
10031
10032static struct ia_css_binary *
10033ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe)
10034{
10035 struct ia_css_binary *binary = NULL;
10036
10037 assert(pipe);
10038
10039 switch (pipe->config.mode) {
10040 case IA_CSS_PIPE_MODE_VIDEO:
10041 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10042 break;
10043 default:
10044 break;
10045 }
10046
10047 if (binary && !binary->info->sp.enable.dis)
10048 binary = NULL;
10049
10050 return binary;
10051}
10052
10053struct ia_css_pipeline *
10054ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe)
10055{
10056 assert(pipe);
10057
10058 return (struct ia_css_pipeline *)&pipe->pipeline;
10059}
10060
10061unsigned int
10062ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe)
10063{
10064 assert(pipe);
10065
10066
10067
10068
10069
10070
10071 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
10072
10073 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
10074 return (IA_CSS_PIPELINE_NUM_MAX - 1);
10075
10076 return pipe->pipe_num;
10077}
10078
10079unsigned int
10080ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe)
10081{
10082 assert(pipe);
10083
10084 return (unsigned int)pipe->config.isp_pipe_version;
10085}
10086
10087#define SP_START_TIMEOUT_US 30000000
10088
10089int
10090ia_css_start_sp(void)
10091{
10092 unsigned long timeout;
10093 int err = 0;
10094
10095 IA_CSS_ENTER("");
10096 sh_css_sp_start_isp();
10097
10098
10099 timeout = SP_START_TIMEOUT_US;
10100 while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) {
10101 timeout--;
10102 udelay(1);
10103 }
10104 if (timeout == 0) {
10105 IA_CSS_ERROR("timeout during SP initialization");
10106 return -EINVAL;
10107 }
10108
10109
10110
10111
10112 sh_css_init_host_sp_control_vars();
10113
10114
10115
10116
10117 sh_css_setup_queues();
10118 ia_css_bufq_dump_queue_info();
10119
10120 IA_CSS_LEAVE_ERR(err);
10121 return err;
10122}
10123
10124
10125
10126
10127
10128
10129#define SP_SHUTDOWN_TIMEOUT_US 200000
10130
10131int
10132ia_css_stop_sp(void)
10133{
10134 unsigned long timeout;
10135 int err = 0;
10136
10137 IA_CSS_ENTER("void");
10138
10139 if (!sh_css_sp_is_running()) {
10140 err = -EINVAL;
10141 IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
10142
10143
10144 return err;
10145 }
10146
10147
10148 if (!IS_ISP2401) {
10149 sh_css_write_host2sp_command(host2sp_cmd_terminate);
10150 } else {
10151 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) {
10152 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
10153 ia_css_debug_dump_sp_sw_debug_info();
10154 ia_css_debug_dump_debug_info(NULL);
10155 }
10156 }
10157
10158 sh_css_sp_set_sp_running(false);
10159
10160 timeout = SP_SHUTDOWN_TIMEOUT_US;
10161 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) {
10162 timeout--;
10163 udelay(1);
10164 }
10165 if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
10166 IA_CSS_WARNING("SP has not terminated (SW)");
10167
10168 if (timeout == 0) {
10169 IA_CSS_WARNING("SP is not idle");
10170 ia_css_debug_dump_sp_sw_debug_info();
10171 }
10172 timeout = SP_SHUTDOWN_TIMEOUT_US;
10173 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) {
10174 timeout--;
10175 udelay(1);
10176 }
10177 if (timeout == 0) {
10178 IA_CSS_WARNING("ISP is not idle");
10179 ia_css_debug_dump_sp_sw_debug_info();
10180 }
10181
10182 sh_css_hmm_buffer_record_uninit();
10183
10184
10185 sh_css_param_clear_param_sets();
10186
10187 IA_CSS_LEAVE_ERR(err);
10188 return err;
10189}
10190
10191int
10192ia_css_update_continuous_frames(struct ia_css_stream *stream)
10193{
10194 struct ia_css_pipe *pipe;
10195 unsigned int i;
10196
10197 ia_css_debug_dtrace(
10198 IA_CSS_DEBUG_TRACE,
10199 "sh_css_update_continuous_frames() enter:\n");
10200
10201 if (!stream) {
10202 ia_css_debug_dtrace(
10203 IA_CSS_DEBUG_TRACE,
10204 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
10205 return -EINVAL;
10206 }
10207
10208 pipe = stream->continuous_pipe;
10209
10210 for (i = stream->config.init_num_cont_raw_buf;
10211 i < stream->config.target_num_cont_raw_buf; i++)
10212 sh_css_update_host2sp_offline_frame(i,
10213 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
10214
10215 sh_css_update_host2sp_cont_num_raw_frames
10216 (stream->config.target_num_cont_raw_buf, true);
10217 ia_css_debug_dtrace(
10218 IA_CSS_DEBUG_TRACE,
10219 "sh_css_update_continuous_frames() leave: return_void\n");
10220
10221 return 0;
10222}
10223
10224void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
10225{
10226 unsigned int thread_id;
10227 unsigned int pipe_num;
10228 bool need_input_queue;
10229
10230 IA_CSS_ENTER("");
10231 assert(pipe);
10232
10233 pipe_num = pipe->pipe_num;
10234
10235 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
10236
10237#if defined(ISP2401)
10238 need_input_queue = true;
10239#else
10240 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
10241#endif
10242
10243
10244
10245 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
10246 if (need_input_queue)
10247 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10248 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10249 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10250 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10251#if defined SH_CSS_ENABLE_METADATA
10252 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10253#endif
10254 if (pipe->pipe_settings.preview.preview_binary.info &&
10255 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
10256 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10257 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
10258 unsigned int i;
10259
10260 if (need_input_queue)
10261 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10262 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10263 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10264 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10265 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10266#if defined SH_CSS_ENABLE_METADATA
10267 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10268#endif
10269 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10270 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10271 if (pipe->pipe_settings.capture.primary_binary[i].info &&
10272 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10273 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10274 break;
10275 }
10276 }
10277 } else if (pipe->config.default_capture_config.mode ==
10278 IA_CSS_CAPTURE_MODE_ADVANCED ||
10279 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
10280 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
10281 if (pipe->pipe_settings.capture.pre_isp_binary.info &&
10282 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
10283 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10284 }
10285 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
10286 if (need_input_queue)
10287 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10288 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10289 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
10290 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10291 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10292 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10293#if defined SH_CSS_ENABLE_METADATA
10294 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10295#endif
10296 if (pipe->pipe_settings.video.video_binary.info &&
10297 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
10298 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10299 if (pipe->pipe_settings.video.video_binary.info &&
10300 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
10301 ))
10302 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
10303 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
10304 if (need_input_queue)
10305 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10306 if (!pipe->stream->config.continuous)
10307 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10308#if defined SH_CSS_ENABLE_METADATA
10309 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10310#endif
10311 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) {
10312 if (need_input_queue)
10313 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10314 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10315 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10316 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10317#if defined SH_CSS_ENABLE_METADATA
10318 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10319#endif
10320 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
10321 unsigned int idx;
10322
10323 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
10324 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
10325 if (pipe->enable_viewfinder[idx])
10326 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
10327 }
10328 if (need_input_queue)
10329 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10330 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10331#if defined SH_CSS_ENABLE_METADATA
10332 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10333#endif
10334 }
10335 IA_CSS_LEAVE("");
10336}
10337
10338#if CONFIG_ON_FRAME_ENQUEUE()
10339static int set_config_on_frame_enqueue(struct ia_css_frame_info
10340 *info, struct frame_data_wrapper *frame)
10341{
10342 frame->config_on_frame_enqueue.padded_width = 0;
10343
10344
10345
10346 switch (info->format) {
10347 case IA_CSS_FRAME_FORMAT_YUV420:
10348 case IA_CSS_FRAME_FORMAT_NV12:
10349 if (info->padded_width > info->res.width)
10350 frame->config_on_frame_enqueue.padded_width = info->padded_width;
10351 else if ((info->padded_width < info->res.width) && (info->padded_width > 0))
10352 return -EINVAL;
10353
10354
10355 break;
10356 default:
10357 break;
10358 }
10359
10360 return 0;
10361}
10362#endif
10363
10364int
10365ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id)
10366{
10367 int ret;
10368
10369 IA_CSS_ENTER("");
10370
10371
10372
10373 if (!stream || !stream->config.continuous) {
10374 IA_CSS_ERROR("invalid stream pointer");
10375 return -EINVAL;
10376 }
10377
10378 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
10379 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) {
10380 IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id);
10381 return -EINVAL;
10382 }
10383
10384
10385
10386 ret = ia_css_bufq_enqueue_psys_event(
10387 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
10388
10389 IA_CSS_LEAVE_ERR(ret);
10390 return ret;
10391}
10392
10393
10394
10395
10396int
10397ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10398 bool enable)
10399{
10400 unsigned int thread_id;
10401 struct ia_css_pipeline_stage *stage;
10402 int err = 0;
10403
10404 IA_CSS_ENTER("");
10405
10406
10407 if (!pipe || !pipe->stream) {
10408 IA_CSS_ERROR("Invalid Pipe.");
10409 err = -EINVAL;
10410 } else if (!(pipe->config.acc_extension)) {
10411 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
10412 err = -EINVAL;
10413 } else if (!sh_css_sp_is_running()) {
10414 IA_CSS_ERROR("Leaving: queue unavailable.");
10415 err = -EBUSY;
10416 } else {
10417
10418 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10419 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10420 if (!err) {
10421
10422 err = ia_css_bufq_enqueue_psys_event(
10423 (uint8_t)IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
10424 (uint8_t)thread_id,
10425 (uint8_t)stage->stage_num,
10426 enable ? 1 : 0);
10427 if (!err) {
10428 if (enable)
10429 SH_CSS_QOS_STAGE_ENABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10430 else
10431 SH_CSS_QOS_STAGE_DISABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10432 }
10433 }
10434 }
10435 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable);
10436 return err;
10437}
10438
10439
10440
10441
10442int
10443ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10444 bool *enable)
10445{
10446 struct ia_css_pipeline_stage *stage;
10447 unsigned int thread_id;
10448 int err = 0;
10449
10450 IA_CSS_ENTER("");
10451
10452
10453 if (!pipe || !pipe->stream) {
10454 IA_CSS_ERROR("Invalid Pipe.");
10455 err = -EINVAL;
10456 } else if (!(pipe->config.acc_extension)) {
10457 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10458 err = -EINVAL;
10459 } else if (!sh_css_sp_is_running()) {
10460 IA_CSS_ERROR("Leaving: queue unavailable.");
10461 err = -EBUSY;
10462 } else {
10463
10464 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10465 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10466
10467 if (!err) {
10468
10469 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10470 stage->stage_num)) ? true : false;
10471 }
10472 }
10473 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable);
10474 return err;
10475}
10476
10477
10478int
10479ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
10480 u32 fw_handle,
10481 struct ia_css_isp_param_css_segments *css_seg,
10482 struct ia_css_isp_param_isp_segments *isp_seg)
10483{
10484 unsigned int HIVE_ADDR_sp_group;
10485 static struct sh_css_sp_group sp_group;
10486 static struct sh_css_sp_stage sp_stage;
10487 static struct sh_css_isp_stage isp_stage;
10488 const struct ia_css_fw_info *fw;
10489 unsigned int thread_id;
10490 struct ia_css_pipeline_stage *stage;
10491 int err = 0;
10492 int stage_num = 0;
10493 enum ia_css_isp_memories mem;
10494 bool enabled;
10495
10496 IA_CSS_ENTER("");
10497
10498 fw = &sh_css_sp_fw;
10499
10500
10501 if (!pipe || !pipe->stream) {
10502 IA_CSS_ERROR("Invalid Pipe.");
10503 err = -EINVAL;
10504 } else if (!(pipe->config.acc_extension)) {
10505 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10506 err = -EINVAL;
10507 } else if (!sh_css_sp_is_running()) {
10508 IA_CSS_ERROR("Leaving: queue unavailable.");
10509 err = -EBUSY;
10510 } else {
10511
10512 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10513 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10514 if (!err) {
10515
10516 enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10517 stage->stage_num)) ? true : false;
10518
10519 if (enabled) {
10520 IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
10521 err = -EBUSY;
10522 } else {
10523 stage_num = stage->stage_num;
10524
10525 HIVE_ADDR_sp_group = fw->info.sp.group;
10526 sp_dmem_load(SP0_ID,
10527 (unsigned int)sp_address_of(sp_group),
10528 &sp_group,
10529 sizeof(struct sh_css_sp_group));
10530 hmm_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num],
10531 &sp_stage, sizeof(struct sh_css_sp_stage));
10532
10533 hmm_load(sp_stage.isp_stage_addr,
10534 &isp_stage, sizeof(struct sh_css_isp_stage));
10535
10536 for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) {
10537 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10538 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10539 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10540 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10541 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address
10542 =
10543 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10544 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size
10545 =
10546 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10547 }
10548
10549 hmm_store(sp_stage.isp_stage_addr,
10550 &isp_stage,
10551 sizeof(struct sh_css_isp_stage));
10552 }
10553 }
10554 }
10555 IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle);
10556 return err;
10557}
10558
10559#ifdef ISP2401
10560static int
10561aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
10562 struct ia_css_pipe *pipes[],
10563 bool *do_crop_status)
10564{
10565 int err = 0;
10566 int i;
10567 struct ia_css_pipe *curr_pipe;
10568 u32 pipe_mask = 0;
10569
10570 if ((!curr_stream) ||
10571 (curr_stream->num_pipes == 0) ||
10572 (!pipes) ||
10573 (!do_crop_status)) {
10574 err = -EINVAL;
10575 IA_CSS_LEAVE_ERR(err);
10576 return err;
10577 }
10578
10579 for (i = 0; i < curr_stream->num_pipes; i++) {
10580 curr_pipe = pipes[i];
10581 pipe_mask |= (1 << curr_pipe->config.mode);
10582 }
10583
10584 *do_crop_status =
10585 (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) ||
10586 (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) &&
10587 (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) &&
10588 curr_stream->config.continuous);
10589 return 0;
10590}
10591
10592static bool
10593aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe)
10594{
10595 bool status = false;
10596
10597 if ((curr_pipe) && enabled) {
10598 if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) ||
10599 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) ||
10600 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE))
10601 status = true;
10602 }
10603
10604 return status;
10605}
10606
10607static int
10608aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
10609 struct ia_css_resolution *effective_res)
10610{
10611 int err = 0;
10612 struct ia_css_resolution crop_res;
10613 struct ia_css_resolution *in_res = NULL;
10614 struct ia_css_resolution *out_res = NULL;
10615 bool use_bds_output_info = false;
10616 bool use_vf_pp_in_res = false;
10617 bool use_capt_pp_in_res = false;
10618
10619 if ((!curr_pipe) ||
10620 (!effective_res)) {
10621 err = -EINVAL;
10622 IA_CSS_LEAVE_ERR(err);
10623 return err;
10624 }
10625
10626 if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) &&
10627 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) &&
10628 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) {
10629 err = -EINVAL;
10630 IA_CSS_LEAVE_ERR(err);
10631 return err;
10632 }
10633
10634 use_bds_output_info =
10635 ((curr_pipe->bds_output_info.res.width != 0) &&
10636 (curr_pipe->bds_output_info.res.height != 0));
10637
10638 use_vf_pp_in_res =
10639 ((curr_pipe->config.vf_pp_in_res.width != 0) &&
10640 (curr_pipe->config.vf_pp_in_res.height != 0));
10641
10642 use_capt_pp_in_res =
10643 ((curr_pipe->config.capt_pp_in_res.width != 0) &&
10644 (curr_pipe->config.capt_pp_in_res.height != 0));
10645
10646 in_res = &curr_pipe->stream->config.input_config.effective_res;
10647 out_res = &curr_pipe->output_info[0].res;
10648
10649 switch (curr_pipe->config.mode) {
10650 case IA_CSS_PIPE_MODE_PREVIEW:
10651 if (use_bds_output_info)
10652 out_res = &curr_pipe->bds_output_info.res;
10653 else if (use_vf_pp_in_res)
10654 out_res = &curr_pipe->config.vf_pp_in_res;
10655 break;
10656 case IA_CSS_PIPE_MODE_VIDEO:
10657 if (use_bds_output_info)
10658 out_res = &curr_pipe->bds_output_info.res;
10659 break;
10660 case IA_CSS_PIPE_MODE_CAPTURE:
10661 if (use_capt_pp_in_res)
10662 out_res = &curr_pipe->config.capt_pp_in_res;
10663 break;
10664 case IA_CSS_PIPE_MODE_ACC:
10665 case IA_CSS_PIPE_MODE_COPY:
10666 case IA_CSS_PIPE_MODE_YUVPP:
10667 default:
10668 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
10669 curr_pipe->config.mode);
10670 assert(0);
10671 break;
10672 }
10673
10674 err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res);
10675 if (!err)
10676 *effective_res = crop_res;
10677 else
10678
10679
10680 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err);
10681
10682 return err;
10683}
10684#endif
10685
10686static void
10687sh_css_hmm_buffer_record_init(void)
10688{
10689 int i;
10690
10691 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++)
10692 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
10693}
10694
10695static void
10696sh_css_hmm_buffer_record_uninit(void)
10697{
10698 int i;
10699 struct sh_css_hmm_buffer_record *buffer_record = NULL;
10700
10701 buffer_record = &hmm_buffer_record[0];
10702 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
10703 if (buffer_record->in_use) {
10704 if (buffer_record->h_vbuf)
10705 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
10706 sh_css_hmm_buffer_record_reset(buffer_record);
10707 }
10708 buffer_record++;
10709 }
10710}
10711
10712static void
10713sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record)
10714{
10715 assert(buffer_record);
10716 buffer_record->in_use = false;
10717 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
10718 buffer_record->h_vbuf = NULL;
10719 buffer_record->kernel_ptr = 0;
10720}
10721
10722static struct sh_css_hmm_buffer_record
10723*sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
10724 enum ia_css_buffer_type type,
10725 hrt_address kernel_ptr)
10726{
10727 int i;
10728 struct sh_css_hmm_buffer_record *buffer_record = NULL;
10729 struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
10730
10731 assert(h_vbuf);
10732 assert((type > IA_CSS_BUFFER_TYPE_INVALID) &&
10733 (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
10734 assert(kernel_ptr != 0);
10735
10736 buffer_record = &hmm_buffer_record[0];
10737 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
10738 if (!buffer_record->in_use) {
10739 buffer_record->in_use = true;
10740 buffer_record->type = type;
10741 buffer_record->h_vbuf = h_vbuf;
10742 buffer_record->kernel_ptr = kernel_ptr;
10743 out_buffer_record = buffer_record;
10744 break;
10745 }
10746 buffer_record++;
10747 }
10748
10749 return out_buffer_record;
10750}
10751
10752static struct sh_css_hmm_buffer_record
10753*sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
10754 enum ia_css_buffer_type type)
10755{
10756 int i;
10757 struct sh_css_hmm_buffer_record *buffer_record = NULL;
10758 bool found_record = false;
10759
10760 buffer_record = &hmm_buffer_record[0];
10761 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
10762 if ((buffer_record->in_use) &&
10763 (buffer_record->type == type) &&
10764 (buffer_record->h_vbuf) &&
10765 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
10766 found_record = true;
10767 break;
10768 }
10769 buffer_record++;
10770 }
10771
10772 if (found_record)
10773 return buffer_record;
10774 else
10775 return NULL;
10776}
10777