1d8297779SMing Qian // SPDX-License-Identifier: GPL-2.0 2d8297779SMing Qian /* 3d8297779SMing Qian * Copyright 2020-2021 NXP 4d8297779SMing Qian */ 5d8297779SMing Qian 6d8297779SMing Qian #include <linux/init.h> 7d8297779SMing Qian #include <linux/interconnect.h> 8d8297779SMing Qian #include <linux/ioctl.h> 9d8297779SMing Qian #include <linux/list.h> 10d8297779SMing Qian #include <linux/kernel.h> 11d8297779SMing Qian #include <linux/module.h> 12d8297779SMing Qian #include <linux/of_device.h> 13d8297779SMing Qian #include <linux/of_address.h> 14d8297779SMing Qian #include <linux/platform_device.h> 1505a03effSMing Qian #include <linux/time64.h> 16d8297779SMing Qian #include <media/videobuf2-v4l2.h> 17d8297779SMing Qian #include <media/videobuf2-dma-contig.h> 18d8297779SMing Qian #include "vpu.h" 19d8297779SMing Qian #include "vpu_rpc.h" 20d8297779SMing Qian #include "vpu_defs.h" 21d8297779SMing Qian #include "vpu_helpers.h" 22d8297779SMing Qian #include "vpu_cmds.h" 23d8297779SMing Qian #include "vpu_v4l2.h" 24d8297779SMing Qian #include "vpu_imx8q.h" 25d8297779SMing Qian #include "vpu_windsor.h" 26d8297779SMing Qian 27d8297779SMing Qian #define CMD_SIZE 2560 28d8297779SMing Qian #define MSG_SIZE 25600 29d8297779SMing Qian #define WINDSOR_USER_DATA_WORDS 16 30d8297779SMing Qian #define WINDSOR_MAX_SRC_FRAMES 0x6 31d8297779SMing Qian #define WINDSOR_MAX_REF_FRAMES 0x3 32d8297779SMing Qian #define WINDSOR_BITRATE_UNIT 1024 33d8297779SMing Qian #define WINDSOR_H264_EXTENDED_SAR 255 34d8297779SMing Qian 35d8297779SMing Qian enum { 36d8297779SMing Qian GTB_ENC_CMD_NOOP = 0x0, 37d8297779SMing Qian GTB_ENC_CMD_STREAM_START, 38d8297779SMing Qian GTB_ENC_CMD_FRAME_ENCODE, 39d8297779SMing Qian GTB_ENC_CMD_FRAME_SKIP, 40d8297779SMing Qian GTB_ENC_CMD_STREAM_STOP, 41d8297779SMing Qian GTB_ENC_CMD_PARAMETER_UPD, 42d8297779SMing Qian GTB_ENC_CMD_TERMINATE, 43d8297779SMing Qian GTB_ENC_CMD_SNAPSHOT, 44d8297779SMing Qian GTB_ENC_CMD_ROLL_SNAPSHOT, 45d8297779SMing Qian GTB_ENC_CMD_LOCK_SCHEDULER, 46d8297779SMing Qian GTB_ENC_CMD_UNLOCK_SCHEDULER, 47d8297779SMing Qian GTB_ENC_CMD_CONFIGURE_CODEC, 48d8297779SMing Qian GTB_ENC_CMD_DEAD_MARK, 49d8297779SMing Qian GTB_ENC_CMD_FIRM_RESET, 50d8297779SMing Qian GTB_ENC_CMD_FW_STATUS, 51d8297779SMing Qian GTB_ENC_CMD_RESERVED 52d8297779SMing Qian }; 53d8297779SMing Qian 54d8297779SMing Qian enum { 55d8297779SMing Qian VID_API_EVENT_UNDEFINED = 0x0, 56d8297779SMing Qian VID_API_ENC_EVENT_RESET_DONE = 0x1, 57d8297779SMing Qian VID_API_ENC_EVENT_START_DONE, 58d8297779SMing Qian VID_API_ENC_EVENT_STOP_DONE, 59d8297779SMing Qian VID_API_ENC_EVENT_TERMINATE_DONE, 60d8297779SMing Qian VID_API_ENC_EVENT_FRAME_INPUT_DONE, 61d8297779SMing Qian VID_API_ENC_EVENT_FRAME_DONE, 62d8297779SMing Qian VID_API_ENC_EVENT_FRAME_RELEASE, 63d8297779SMing Qian VID_API_ENC_EVENT_PARA_UPD_DONE, 64d8297779SMing Qian VID_API_ENC_EVENT_MEM_REQUEST, 65d8297779SMing Qian VID_API_ENC_EVENT_FIRMWARE_XCPT, 66d8297779SMing Qian VID_API_ENC_EVENT_RESERVED 67d8297779SMing Qian }; 68d8297779SMing Qian 69d8297779SMing Qian enum { 70d8297779SMing Qian MEDIAIP_ENC_PIC_TYPE_B_FRAME = 0, 71d8297779SMing Qian MEDIAIP_ENC_PIC_TYPE_P_FRAME, 72d8297779SMing Qian MEDIAIP_ENC_PIC_TYPE_I_FRAME, 73d8297779SMing Qian MEDIAIP_ENC_PIC_TYPE_IDR_FRAME, 74d8297779SMing Qian MEDIAIP_ENC_PIC_TYPE_BI_FRAME 75d8297779SMing Qian }; 76d8297779SMing Qian 77d8297779SMing Qian struct windsor_iface { 78d8297779SMing Qian u32 exec_base_addr; 79d8297779SMing Qian u32 exec_area_size; 80d8297779SMing Qian struct vpu_rpc_buffer_desc cmd_buffer_desc; 81d8297779SMing Qian struct vpu_rpc_buffer_desc msg_buffer_desc; 82d8297779SMing Qian u32 cmd_int_enable[VID_API_NUM_STREAMS]; 83d8297779SMing Qian u32 fw_version; 84d8297779SMing Qian u32 mvd_fw_offset; 85d8297779SMing Qian u32 max_streams; 86d8297779SMing Qian u32 ctrl_iface[VID_API_NUM_STREAMS]; 87d8297779SMing Qian struct vpu_rpc_system_config system_config; 88d8297779SMing Qian u32 api_version; 89d8297779SMing Qian struct vpu_rpc_buffer_desc log_buffer_desc; 90d8297779SMing Qian }; 91d8297779SMing Qian 92d8297779SMing Qian struct windsor_ctrl_iface { 93d8297779SMing Qian u32 enc_yuv_buffer_desc; 94d8297779SMing Qian u32 enc_stream_buffer_desc; 95d8297779SMing Qian u32 enc_expert_mode_param; 96d8297779SMing Qian u32 enc_param; 97d8297779SMing Qian u32 enc_mem_pool; 98d8297779SMing Qian u32 enc_encoding_status; 99d8297779SMing Qian u32 enc_dsa_status; 100d8297779SMing Qian }; 101d8297779SMing Qian 102d8297779SMing Qian struct vpu_enc_yuv_desc { 103d8297779SMing Qian u32 frame_id; 104d8297779SMing Qian u32 luma_base; 105d8297779SMing Qian u32 chroma_base; 106d8297779SMing Qian u32 param_idx; 107d8297779SMing Qian u32 key_frame; 108d8297779SMing Qian }; 109d8297779SMing Qian 110d8297779SMing Qian struct vpu_enc_calib_params { 111d8297779SMing Qian u32 use_ame; 112d8297779SMing Qian 113d8297779SMing Qian u32 cme_mvx_max; 114d8297779SMing Qian u32 cme_mvy_max; 115d8297779SMing Qian u32 ame_prefresh_y0; 116d8297779SMing Qian u32 ame_prefresh_y1; 117d8297779SMing Qian u32 fme_min_sad; 118d8297779SMing Qian u32 cme_min_sad; 119d8297779SMing Qian 120d8297779SMing Qian u32 fme_pred_int_weight; 121d8297779SMing Qian u32 fme_pred_hp_weight; 122d8297779SMing Qian u32 fme_pred_qp_weight; 123d8297779SMing Qian u32 fme_cost_weight; 124d8297779SMing Qian u32 fme_act_thold; 125d8297779SMing Qian u32 fme_sad_thold; 126d8297779SMing Qian u32 fme_zero_sad_thold; 127d8297779SMing Qian 128d8297779SMing Qian u32 fme_lrg_mvx_lmt; 129d8297779SMing Qian u32 fme_lrg_mvy_lmt; 130d8297779SMing Qian u32 fme_force_mode; 131d8297779SMing Qian u32 fme_force4mvcost; 132d8297779SMing Qian u32 fme_force2mvcost; 133d8297779SMing Qian 134d8297779SMing Qian u32 h264_inter_thrd; 135d8297779SMing Qian 136d8297779SMing Qian u32 i16x16_mode_cost; 137d8297779SMing Qian u32 i4x4_mode_lambda; 138d8297779SMing Qian u32 i8x8_mode_lambda; 139d8297779SMing Qian 140d8297779SMing Qian u32 inter_mod_mult; 141d8297779SMing Qian u32 inter_sel_mult; 142d8297779SMing Qian u32 inter_bid_cost; 143d8297779SMing Qian u32 inter_bwd_cost; 144d8297779SMing Qian u32 inter_4mv_cost; 145d8297779SMing Qian s32 one_mv_i16_cost; 146d8297779SMing Qian s32 one_mv_i4x4_cost; 147d8297779SMing Qian s32 one_mv_i8x8_cost; 148d8297779SMing Qian s32 two_mv_i16_cost; 149d8297779SMing Qian s32 two_mv_i4x4_cost; 150d8297779SMing Qian s32 two_mv_i8x8_cost; 151d8297779SMing Qian s32 four_mv_i16_cost; 152d8297779SMing Qian s32 four_mv_i4x4_cost; 153d8297779SMing Qian s32 four_mv_i8x8_cost; 154d8297779SMing Qian 155d8297779SMing Qian u32 intra_pred_enab; 156d8297779SMing Qian u32 intra_chr_pred; 157d8297779SMing Qian u32 intra16_pred; 158d8297779SMing Qian u32 intra4x4_pred; 159d8297779SMing Qian u32 intra8x8_pred; 160d8297779SMing Qian 161d8297779SMing Qian u32 cb_base; 162d8297779SMing Qian u32 cb_size; 163d8297779SMing Qian u32 cb_head_room; 164d8297779SMing Qian 165d8297779SMing Qian u32 mem_page_width; 166d8297779SMing Qian u32 mem_page_height; 167d8297779SMing Qian u32 mem_total_size; 168d8297779SMing Qian u32 mem_chunk_phys_addr; 169d8297779SMing Qian u32 mem_chunk_virt_addr; 170d8297779SMing Qian u32 mem_chunk_size; 171d8297779SMing Qian u32 mem_y_stride; 172d8297779SMing Qian u32 mem_uv_stride; 173d8297779SMing Qian 174d8297779SMing Qian u32 split_wr_enab; 175d8297779SMing Qian u32 split_wr_req_size; 176d8297779SMing Qian u32 split_rd_enab; 177d8297779SMing Qian u32 split_rd_req_size; 178d8297779SMing Qian }; 179d8297779SMing Qian 180d8297779SMing Qian struct vpu_enc_config_params { 181d8297779SMing Qian u32 param_change; 182d8297779SMing Qian u32 start_frame; 183d8297779SMing Qian u32 end_frame; 184d8297779SMing Qian u32 userdata_enable; 185d8297779SMing Qian u32 userdata_id[4]; 186d8297779SMing Qian u32 userdata_message[WINDSOR_USER_DATA_WORDS]; 187d8297779SMing Qian u32 userdata_length; 188d8297779SMing Qian u32 h264_profile_idc; 189d8297779SMing Qian u32 h264_level_idc; 190d8297779SMing Qian u32 h264_au_delimiter; 191d8297779SMing Qian u32 h264_seq_end_code; 192d8297779SMing Qian u32 h264_recovery_points; 193d8297779SMing Qian u32 h264_vui_parameters; 194d8297779SMing Qian u32 h264_aspect_ratio_present; 195d8297779SMing Qian u32 h264_aspect_ratio_sar_width; 196d8297779SMing Qian u32 h264_aspect_ratio_sar_height; 197d8297779SMing Qian u32 h264_overscan_present; 198d8297779SMing Qian u32 h264_video_type_present; 199d8297779SMing Qian u32 h264_video_format; 200d8297779SMing Qian u32 h264_video_full_range; 201d8297779SMing Qian u32 h264_video_colour_descriptor; 202d8297779SMing Qian u32 h264_video_colour_primaries; 203d8297779SMing Qian u32 h264_video_transfer_char; 204d8297779SMing Qian u32 h264_video_matrix_coeff; 205d8297779SMing Qian u32 h264_chroma_loc_info_present; 206d8297779SMing Qian u32 h264_chroma_loc_type_top; 207d8297779SMing Qian u32 h264_chroma_loc_type_bot; 208d8297779SMing Qian u32 h264_timing_info_present; 209d8297779SMing Qian u32 h264_buffering_period_present; 210d8297779SMing Qian u32 h264_low_delay_hrd_flag; 211d8297779SMing Qian u32 aspect_ratio; 212d8297779SMing Qian u32 test_mode; // Automated firmware test mode 213d8297779SMing Qian u32 dsa_test_mode; // Automated test mode for the DSA. 214d8297779SMing Qian u32 fme_test_mode; // Automated test mode for the fme 215d8297779SMing Qian u32 cbr_row_mode; //0: FW mode; 1: HW mode 216d8297779SMing Qian u32 windsor_mode; //0: normal mode; 1: intra only mode; 2: intra+0MV mode 217d8297779SMing Qian u32 encode_mode; // H264, VC1, MPEG2, DIVX 218d8297779SMing Qian u32 frame_width; // display width 219d8297779SMing Qian u32 frame_height; // display height 220d8297779SMing Qian u32 enc_frame_width; // encoding width, should be 16-pix align 221d8297779SMing Qian u32 enc_frame_height; // encoding height, should be 16-pix aligned 222d8297779SMing Qian u32 frame_rate_num; 223d8297779SMing Qian u32 frame_rate_den; 224d8297779SMing Qian u32 vi_field_source; 225d8297779SMing Qian u32 vi_frame_width; 226d8297779SMing Qian u32 vi_frame_height; 227d8297779SMing Qian u32 crop_frame_width; 228d8297779SMing Qian u32 crop_frame_height; 229d8297779SMing Qian u32 crop_x_start_posn; 230d8297779SMing Qian u32 crop_y_start_posn; 231d8297779SMing Qian u32 mode422; 232d8297779SMing Qian u32 mode_yuy2; 233d8297779SMing Qian u32 dsa_luma_en; 234d8297779SMing Qian u32 dsa_chroma_en; 235d8297779SMing Qian u32 dsa_ext_hfilt_en; 236d8297779SMing Qian u32 dsa_di_en; 237d8297779SMing Qian u32 dsa_di_top_ref; 238d8297779SMing Qian u32 dsa_vertf_disable; 239d8297779SMing Qian u32 dsa_disable_pwb; 240d8297779SMing Qian u32 dsa_hor_phase; 241d8297779SMing Qian u32 dsa_ver_phase; 242d8297779SMing Qian u32 dsa_iac_enable; 243d8297779SMing Qian u32 iac_sc_threshold; 244d8297779SMing Qian u32 iac_vm_threshold; 245d8297779SMing Qian u32 iac_skip_mode; 246d8297779SMing Qian u32 iac_grp_width; 247d8297779SMing Qian u32 iac_grp_height; 248d8297779SMing Qian u32 rate_control_mode; 249d8297779SMing Qian u32 rate_control_resolution; 250d8297779SMing Qian u32 buffer_size; 251d8297779SMing Qian u32 buffer_level_init; 252d8297779SMing Qian u32 buffer_I_bit_budget; 253d8297779SMing Qian u32 top_field_first; 254d8297779SMing Qian u32 intra_lum_qoffset; 255d8297779SMing Qian u32 intra_chr_qoffset; 256d8297779SMing Qian u32 inter_lum_qoffset; 257d8297779SMing Qian u32 inter_chr_qoffset; 258d8297779SMing Qian u32 use_def_scaling_mtx; 259d8297779SMing Qian u32 inter_8x8_enab; 260d8297779SMing Qian u32 inter_4x4_enab; 261d8297779SMing Qian u32 fme_enable_qpel; 262d8297779SMing Qian u32 fme_enable_hpel; 263d8297779SMing Qian u32 fme_nozeromv; 264d8297779SMing Qian u32 fme_predmv_en; 265d8297779SMing Qian u32 fme_pred_2mv4mv; 266d8297779SMing Qian u32 fme_smallsadthresh; 267d8297779SMing Qian u32 ame_en_lmvc; 268d8297779SMing Qian u32 ame_x_mult; 269d8297779SMing Qian u32 cme_enable_4mv; 270d8297779SMing Qian u32 cme_enable_1mv; 271d8297779SMing Qian u32 hme_enable_16x8mv; 272d8297779SMing Qian u32 hme_enable_8x16mv; 273d8297779SMing Qian u32 cme_mv_weight; 274d8297779SMing Qian u32 cme_mv_cost; 275d8297779SMing Qian u32 ame_mult_mv; 276d8297779SMing Qian u32 ame_shift_mv; 277d8297779SMing Qian u32 hme_forceto1mv_en; 278d8297779SMing Qian u32 hme_2mv_cost; 279d8297779SMing Qian u32 hme_pred_mode; 280d8297779SMing Qian u32 hme_sc_rnge; 281d8297779SMing Qian u32 hme_sw_rnge; 282d8297779SMing Qian u32 output_format; 283d8297779SMing Qian u32 timestamp_enab; 284d8297779SMing Qian u32 initial_pts_enab; 285d8297779SMing Qian u32 initial_pts; 286d8297779SMing Qian }; 287d8297779SMing Qian 288d8297779SMing Qian struct vpu_enc_static_params { 289d8297779SMing Qian u32 param_change; 290d8297779SMing Qian u32 gop_length; 291d8297779SMing Qian u32 rate_control_bitrate; 292d8297779SMing Qian u32 rate_control_bitrate_min; 293d8297779SMing Qian u32 rate_control_bitrate_max; 294d8297779SMing Qian u32 rate_control_content_models; 295d8297779SMing Qian u32 rate_control_iframe_maxsize; 296d8297779SMing Qian u32 rate_control_qp_init; 297d8297779SMing Qian u32 rate_control_islice_qp; 298d8297779SMing Qian u32 rate_control_pslice_qp; 299d8297779SMing Qian u32 rate_control_bslice_qp; 300d8297779SMing Qian u32 adaptive_quantization; 301d8297779SMing Qian u32 aq_variance; 302d8297779SMing Qian u32 cost_optimization; 303d8297779SMing Qian u32 fdlp_mode; 304d8297779SMing Qian u32 enable_isegbframes; 305d8297779SMing Qian u32 enable_adaptive_keyratio; 306d8297779SMing Qian u32 keyratio_imin; 307d8297779SMing Qian u32 keyratio_imax; 308d8297779SMing Qian u32 keyratio_pmin; 309d8297779SMing Qian u32 keyratio_pmax; 310d8297779SMing Qian u32 keyratio_bmin; 311d8297779SMing Qian u32 keyratio_bmax; 312d8297779SMing Qian s32 keyratio_istep; 313d8297779SMing Qian s32 keyratio_pstep; 314d8297779SMing Qian s32 keyratio_bstep; 315d8297779SMing Qian u32 enable_paff; 316d8297779SMing Qian u32 enable_b_frame_ref; 317d8297779SMing Qian u32 enable_adaptive_gop; 318d8297779SMing Qian u32 enable_closed_gop; 319d8297779SMing Qian u32 open_gop_refresh_freq; 320d8297779SMing Qian u32 enable_adaptive_sc; 321d8297779SMing Qian u32 enable_fade_detection; 322d8297779SMing Qian s32 fade_detection_threshold; 323d8297779SMing Qian u32 enable_repeat_b; 324d8297779SMing Qian u32 enable_low_delay_b; 325d8297779SMing Qian }; 326d8297779SMing Qian 327d8297779SMing Qian struct vpu_enc_dynamic_params { 328d8297779SMing Qian u32 param_change; 329d8297779SMing Qian u32 rows_per_slice; 330d8297779SMing Qian u32 mbaff_enable; 331d8297779SMing Qian u32 dbf_enable; 332d8297779SMing Qian u32 field_source; 333d8297779SMing Qian u32 gop_b_length; 334d8297779SMing Qian u32 mb_group_size; 335d8297779SMing Qian u32 cbr_rows_per_group; 336d8297779SMing Qian u32 skip_enable; 337d8297779SMing Qian u32 pts_bits_0_to_31; 338d8297779SMing Qian u32 pts_bit_32; 339d8297779SMing Qian u32 rm_expsv_cff; 340d8297779SMing Qian u32 const_ipred; 341d8297779SMing Qian s32 chr_qp_offset; 342d8297779SMing Qian u32 intra_mb_qp_offset; 343d8297779SMing Qian u32 h264_cabac_init_method; 344d8297779SMing Qian u32 h264_cabac_init_idc; 345d8297779SMing Qian u32 h264_cabac_enable; 346d8297779SMing Qian s32 alpha_c0_offset_div2; 347d8297779SMing Qian s32 beta_offset_div2; 348d8297779SMing Qian u32 intra_prefresh_y0; 349d8297779SMing Qian u32 intra_prefresh_y1; 350d8297779SMing Qian u32 dbg_dump_rec_src; 351d8297779SMing Qian }; 352d8297779SMing Qian 353d8297779SMing Qian struct vpu_enc_expert_mode_param { 354d8297779SMing Qian struct vpu_enc_calib_params calib_param; 355d8297779SMing Qian struct vpu_enc_config_params config_param; 356d8297779SMing Qian struct vpu_enc_static_params static_param; 357d8297779SMing Qian struct vpu_enc_dynamic_params dynamic_param; 358d8297779SMing Qian }; 359d8297779SMing Qian 360d8297779SMing Qian enum MEDIAIP_ENC_FMT { 361d8297779SMing Qian MEDIAIP_ENC_FMT_H264 = 0, 362d8297779SMing Qian MEDIAIP_ENC_FMT_VC1, 363d8297779SMing Qian MEDIAIP_ENC_FMT_MPEG2, 364d8297779SMing Qian MEDIAIP_ENC_FMT_MPEG4SP, 365d8297779SMing Qian MEDIAIP_ENC_FMT_H263, 366d8297779SMing Qian MEDIAIP_ENC_FMT_MPEG1, 367d8297779SMing Qian MEDIAIP_ENC_FMT_SHORT_HEADER, 368d8297779SMing Qian MEDIAIP_ENC_FMT_NULL 369d8297779SMing Qian }; 370d8297779SMing Qian 371d8297779SMing Qian enum MEDIAIP_ENC_PROFILE { 372d8297779SMing Qian MEDIAIP_ENC_PROF_MPEG2_SP = 0, 373d8297779SMing Qian MEDIAIP_ENC_PROF_MPEG2_MP, 374d8297779SMing Qian MEDIAIP_ENC_PROF_MPEG2_HP, 375d8297779SMing Qian MEDIAIP_ENC_PROF_H264_BP, 376d8297779SMing Qian MEDIAIP_ENC_PROF_H264_MP, 377d8297779SMing Qian MEDIAIP_ENC_PROF_H264_HP, 378d8297779SMing Qian MEDIAIP_ENC_PROF_MPEG4_SP, 379d8297779SMing Qian MEDIAIP_ENC_PROF_MPEG4_ASP, 380d8297779SMing Qian MEDIAIP_ENC_PROF_VC1_SP, 381d8297779SMing Qian MEDIAIP_ENC_PROF_VC1_MP, 382d8297779SMing Qian MEDIAIP_ENC_PROF_VC1_AP 383d8297779SMing Qian }; 384d8297779SMing Qian 385d8297779SMing Qian enum MEDIAIP_ENC_BITRATE_MODE { 386d8297779SMing Qian MEDIAIP_ENC_BITRATE_MODE_VBR = 0x00000001, 387d8297779SMing Qian MEDIAIP_ENC_BITRATE_MODE_CBR = 0x00000002, 388d8297779SMing Qian MEDIAIP_ENC_BITRATE_MODE_CONSTANT_QP = 0x00000004 389d8297779SMing Qian }; 390d8297779SMing Qian 391d8297779SMing Qian struct vpu_enc_memory_resource { 392d8297779SMing Qian u32 phys; 393d8297779SMing Qian u32 virt; 394d8297779SMing Qian u32 size; 395d8297779SMing Qian }; 396d8297779SMing Qian 397d8297779SMing Qian struct vpu_enc_param { 398d8297779SMing Qian enum MEDIAIP_ENC_FMT codec_mode; 399d8297779SMing Qian enum MEDIAIP_ENC_PROFILE profile; 400d8297779SMing Qian u32 level; 401d8297779SMing Qian 402d8297779SMing Qian struct vpu_enc_memory_resource enc_mem_desc; 403d8297779SMing Qian 404d8297779SMing Qian u32 frame_rate; 405d8297779SMing Qian u32 src_stride; 406d8297779SMing Qian u32 src_width; 407d8297779SMing Qian u32 src_height; 408d8297779SMing Qian u32 src_offset_x; 409d8297779SMing Qian u32 src_offset_y; 410d8297779SMing Qian u32 src_crop_width; 411d8297779SMing Qian u32 src_crop_height; 412d8297779SMing Qian u32 out_width; 413d8297779SMing Qian u32 out_height; 414d8297779SMing Qian u32 iframe_interval; 415d8297779SMing Qian u32 bframes; 416d8297779SMing Qian u32 low_latency_mode; 417d8297779SMing Qian 418d8297779SMing Qian enum MEDIAIP_ENC_BITRATE_MODE bitrate_mode; 419d8297779SMing Qian u32 target_bitrate; 420d8297779SMing Qian u32 max_bitrate; 421d8297779SMing Qian u32 min_bitrate; 422d8297779SMing Qian u32 init_slice_qp; 423d8297779SMing Qian }; 424d8297779SMing Qian 425d8297779SMing Qian struct vpu_enc_mem_pool { 426d8297779SMing Qian struct vpu_enc_memory_resource enc_frames[WINDSOR_MAX_SRC_FRAMES]; 427d8297779SMing Qian struct vpu_enc_memory_resource ref_frames[WINDSOR_MAX_REF_FRAMES]; 428d8297779SMing Qian struct vpu_enc_memory_resource act_frame; 429d8297779SMing Qian }; 430d8297779SMing Qian 431d8297779SMing Qian struct vpu_enc_encoding_status { 432d8297779SMing Qian u32 frame_id; 433d8297779SMing Qian u32 error_flag; //Error type 434d8297779SMing Qian u32 mb_y; 435d8297779SMing Qian u32 mb_x; 436d8297779SMing Qian u32 reserved[12]; 437d8297779SMing Qian 438d8297779SMing Qian }; 439d8297779SMing Qian 440d8297779SMing Qian struct vpu_enc_dsa_status { 441d8297779SMing Qian u32 frame_id; 442d8297779SMing Qian u32 dsa_cyle; 443d8297779SMing Qian u32 mb_y; 444d8297779SMing Qian u32 mb_x; 445d8297779SMing Qian u32 reserved[4]; 446d8297779SMing Qian }; 447d8297779SMing Qian 448d8297779SMing Qian struct vpu_enc_ctrl { 449d8297779SMing Qian struct vpu_enc_yuv_desc *yuv_desc; 450d8297779SMing Qian struct vpu_rpc_buffer_desc *stream_desc; 451d8297779SMing Qian struct vpu_enc_expert_mode_param *expert; 452d8297779SMing Qian struct vpu_enc_param *param; 453d8297779SMing Qian struct vpu_enc_mem_pool *pool; 454d8297779SMing Qian struct vpu_enc_encoding_status *status; 455d8297779SMing Qian struct vpu_enc_dsa_status *dsa; 456d8297779SMing Qian }; 457d8297779SMing Qian 458d8297779SMing Qian struct vpu_enc_host_ctrls { 459d8297779SMing Qian struct vpu_enc_ctrl ctrls[VID_API_NUM_STREAMS]; 460d8297779SMing Qian }; 461d8297779SMing Qian 462d8297779SMing Qian struct windsor_pic_info { 463d8297779SMing Qian u32 frame_id; 464d8297779SMing Qian u32 pic_encod_done; 465d8297779SMing Qian u32 pic_type; 466d8297779SMing Qian u32 skipped_frame; 467d8297779SMing Qian u32 error_flag; 468d8297779SMing Qian u32 psnr; 469d8297779SMing Qian u32 flush_done; 470d8297779SMing Qian u32 mb_y; 471d8297779SMing Qian u32 mb_x; 472d8297779SMing Qian u32 frame_size; 473d8297779SMing Qian u32 frame_enc_ttl_cycles; 474d8297779SMing Qian u32 frame_enc_ttl_frm_cycles; 475d8297779SMing Qian u32 frame_enc_ttl_slc_cycles; 476d8297779SMing Qian u32 frame_enc_ttl_enc_cycles; 477d8297779SMing Qian u32 frame_enc_ttl_hme_cycles; 478d8297779SMing Qian u32 frame_enc_ttl_dsa_cycles; 479d8297779SMing Qian u32 frame_enc_fw_cycles; 480d8297779SMing Qian u32 frame_crc; 481d8297779SMing Qian u32 num_interrupts_1; 482d8297779SMing Qian u32 num_interrupts_2; 483d8297779SMing Qian u32 poc; 484d8297779SMing Qian u32 ref_info; 485d8297779SMing Qian u32 pic_num; 486d8297779SMing Qian u32 pic_activity; 487d8297779SMing Qian u32 scene_change; 488d8297779SMing Qian u32 mb_stats; 489d8297779SMing Qian u32 enc_cache_count0; 490d8297779SMing Qian u32 enc_cache_count1; 491d8297779SMing Qian u32 mtl_wr_strb_cnt; 492d8297779SMing Qian u32 mtl_rd_strb_cnt; 493d8297779SMing Qian u32 str_buff_wptr; 494d8297779SMing Qian u32 diagnosticEvents; 495d8297779SMing Qian u32 proc_iacc_tot_rd_cnt; 496d8297779SMing Qian u32 proc_dacc_tot_rd_cnt; 497d8297779SMing Qian u32 proc_dacc_tot_wr_cnt; 498d8297779SMing Qian u32 proc_dacc_reg_rd_cnt; 499d8297779SMing Qian u32 proc_dacc_reg_wr_cnt; 500d8297779SMing Qian u32 proc_dacc_rng_rd_cnt; 501d8297779SMing Qian u32 proc_dacc_rng_wr_cnt; 502d8297779SMing Qian s32 tv_s; 503d8297779SMing Qian u32 tv_ns; 504d8297779SMing Qian }; 505d8297779SMing Qian 506d8297779SMing Qian u32 vpu_windsor_get_data_size(void) 507d8297779SMing Qian { 508d8297779SMing Qian return sizeof(struct vpu_enc_host_ctrls); 509d8297779SMing Qian } 510d8297779SMing Qian 511d8297779SMing Qian static struct vpu_enc_yuv_desc *get_yuv_desc(struct vpu_shared_addr *shared, 512d8297779SMing Qian u32 instance) 513d8297779SMing Qian { 514d8297779SMing Qian struct vpu_enc_host_ctrls *hcs = shared->priv; 515d8297779SMing Qian 516d8297779SMing Qian return hcs->ctrls[instance].yuv_desc; 517d8297779SMing Qian } 518d8297779SMing Qian 519d8297779SMing Qian static struct vpu_enc_mem_pool *get_mem_pool(struct vpu_shared_addr *shared, 520d8297779SMing Qian u32 instance) 521d8297779SMing Qian { 522d8297779SMing Qian struct vpu_enc_host_ctrls *hcs = shared->priv; 523d8297779SMing Qian 524d8297779SMing Qian return hcs->ctrls[instance].pool; 525d8297779SMing Qian } 526d8297779SMing Qian 527d8297779SMing Qian static struct vpu_rpc_buffer_desc *get_stream_buf_desc(struct vpu_shared_addr *shared, 528d8297779SMing Qian u32 instance) 529d8297779SMing Qian { 530d8297779SMing Qian struct vpu_enc_host_ctrls *hcs = shared->priv; 531d8297779SMing Qian 532d8297779SMing Qian return hcs->ctrls[instance].stream_desc; 533d8297779SMing Qian } 534d8297779SMing Qian 535d8297779SMing Qian static struct vpu_enc_expert_mode_param *get_expert_param(struct vpu_shared_addr *shared, 536d8297779SMing Qian u32 instance) 537d8297779SMing Qian { 538d8297779SMing Qian struct vpu_enc_host_ctrls *hcs = shared->priv; 539d8297779SMing Qian 540d8297779SMing Qian return hcs->ctrls[instance].expert; 541d8297779SMing Qian } 542d8297779SMing Qian 543d8297779SMing Qian static struct vpu_enc_param *get_enc_param(struct vpu_shared_addr *shared, u32 instance) 544d8297779SMing Qian { 545d8297779SMing Qian struct vpu_enc_host_ctrls *hcs = shared->priv; 546d8297779SMing Qian 547d8297779SMing Qian return hcs->ctrls[instance].param; 548d8297779SMing Qian } 549d8297779SMing Qian 550d8297779SMing Qian static u32 get_ptr(u32 ptr) 551d8297779SMing Qian { 552d8297779SMing Qian return (ptr | 0x80000000); 553d8297779SMing Qian } 554d8297779SMing Qian 555d8297779SMing Qian void vpu_windsor_init_rpc(struct vpu_shared_addr *shared, 556d8297779SMing Qian struct vpu_buffer *rpc, dma_addr_t boot_addr) 557d8297779SMing Qian { 558d8297779SMing Qian unsigned long base_phy_addr; 559d8297779SMing Qian unsigned long phy_addr; 560d8297779SMing Qian unsigned long offset; 561d8297779SMing Qian struct windsor_iface *iface; 562d8297779SMing Qian struct windsor_ctrl_iface *ctrl; 563d8297779SMing Qian struct vpu_enc_host_ctrls *hcs; 564d8297779SMing Qian unsigned int i; 565d8297779SMing Qian 566d8297779SMing Qian if (rpc->phys < boot_addr) 567d8297779SMing Qian return; 568d8297779SMing Qian 569d8297779SMing Qian base_phy_addr = rpc->phys - boot_addr; 570d8297779SMing Qian iface = rpc->virt; 571d8297779SMing Qian shared->iface = iface; 572d8297779SMing Qian shared->boot_addr = boot_addr; 573d8297779SMing Qian hcs = shared->priv; 574d8297779SMing Qian 575d8297779SMing Qian iface->exec_base_addr = base_phy_addr; 576d8297779SMing Qian iface->exec_area_size = rpc->length; 577d8297779SMing Qian 578d8297779SMing Qian offset = sizeof(struct windsor_iface); 579d8297779SMing Qian phy_addr = base_phy_addr + offset; 580d8297779SMing Qian shared->cmd_desc = &iface->cmd_buffer_desc; 581d8297779SMing Qian shared->cmd_mem_vir = rpc->virt + offset; 582d8297779SMing Qian iface->cmd_buffer_desc.start = 583d8297779SMing Qian iface->cmd_buffer_desc.rptr = 584d8297779SMing Qian iface->cmd_buffer_desc.wptr = phy_addr; 585d8297779SMing Qian iface->cmd_buffer_desc.end = iface->cmd_buffer_desc.start + CMD_SIZE; 586d8297779SMing Qian 587d8297779SMing Qian offset += CMD_SIZE; 588d8297779SMing Qian phy_addr = base_phy_addr + offset; 589d8297779SMing Qian shared->msg_desc = &iface->msg_buffer_desc; 590d8297779SMing Qian shared->msg_mem_vir = rpc->virt + offset; 591d8297779SMing Qian iface->msg_buffer_desc.start = 592d8297779SMing Qian iface->msg_buffer_desc.wptr = 593d8297779SMing Qian iface->msg_buffer_desc.rptr = phy_addr; 594d8297779SMing Qian iface->msg_buffer_desc.end = iface->msg_buffer_desc.start + MSG_SIZE; 595d8297779SMing Qian 596d8297779SMing Qian offset += MSG_SIZE; 597d8297779SMing Qian for (i = 0; i < ARRAY_SIZE(iface->ctrl_iface); i++) { 598d8297779SMing Qian iface->ctrl_iface[i] = base_phy_addr + offset; 599d8297779SMing Qian offset += sizeof(struct windsor_ctrl_iface); 600d8297779SMing Qian } 601d8297779SMing Qian for (i = 0; i < ARRAY_SIZE(iface->ctrl_iface); i++) { 602d8297779SMing Qian ctrl = rpc->virt + (iface->ctrl_iface[i] - base_phy_addr); 603d8297779SMing Qian 604d8297779SMing Qian ctrl->enc_yuv_buffer_desc = base_phy_addr + offset; 605d8297779SMing Qian hcs->ctrls[i].yuv_desc = rpc->virt + offset; 606d8297779SMing Qian offset += sizeof(struct vpu_enc_yuv_desc); 607d8297779SMing Qian 608d8297779SMing Qian ctrl->enc_stream_buffer_desc = base_phy_addr + offset; 609d8297779SMing Qian hcs->ctrls[i].stream_desc = rpc->virt + offset; 610d8297779SMing Qian offset += sizeof(struct vpu_rpc_buffer_desc); 611d8297779SMing Qian 612d8297779SMing Qian ctrl->enc_expert_mode_param = base_phy_addr + offset; 613d8297779SMing Qian hcs->ctrls[i].expert = rpc->virt + offset; 614d8297779SMing Qian offset += sizeof(struct vpu_enc_expert_mode_param); 615d8297779SMing Qian 616d8297779SMing Qian ctrl->enc_param = base_phy_addr + offset; 617d8297779SMing Qian hcs->ctrls[i].param = rpc->virt + offset; 618d8297779SMing Qian offset += sizeof(struct vpu_enc_param); 619d8297779SMing Qian 620d8297779SMing Qian ctrl->enc_mem_pool = base_phy_addr + offset; 621d8297779SMing Qian hcs->ctrls[i].pool = rpc->virt + offset; 622d8297779SMing Qian offset += sizeof(struct vpu_enc_mem_pool); 623d8297779SMing Qian 624d8297779SMing Qian ctrl->enc_encoding_status = base_phy_addr + offset; 625d8297779SMing Qian hcs->ctrls[i].status = rpc->virt + offset; 626d8297779SMing Qian offset += sizeof(struct vpu_enc_encoding_status); 627d8297779SMing Qian 628d8297779SMing Qian ctrl->enc_dsa_status = base_phy_addr + offset; 629d8297779SMing Qian hcs->ctrls[i].dsa = rpc->virt + offset; 630d8297779SMing Qian offset += sizeof(struct vpu_enc_dsa_status); 631d8297779SMing Qian } 632d8297779SMing Qian 633d8297779SMing Qian rpc->bytesused = offset; 634d8297779SMing Qian } 635d8297779SMing Qian 636d8297779SMing Qian void vpu_windsor_set_log_buf(struct vpu_shared_addr *shared, struct vpu_buffer *log) 637d8297779SMing Qian { 638d8297779SMing Qian struct windsor_iface *iface = shared->iface; 639d8297779SMing Qian 640d8297779SMing Qian iface->log_buffer_desc.start = 641d8297779SMing Qian iface->log_buffer_desc.wptr = 642d8297779SMing Qian iface->log_buffer_desc.rptr = log->phys - shared->boot_addr; 643d8297779SMing Qian iface->log_buffer_desc.end = iface->log_buffer_desc.start + log->length; 644d8297779SMing Qian } 645d8297779SMing Qian 646d8297779SMing Qian void vpu_windsor_set_system_cfg(struct vpu_shared_addr *shared, 647d8297779SMing Qian u32 regs_base, void __iomem *regs, u32 core_id) 648d8297779SMing Qian { 649d8297779SMing Qian struct windsor_iface *iface = shared->iface; 650d8297779SMing Qian struct vpu_rpc_system_config *config = &iface->system_config; 651d8297779SMing Qian 652d8297779SMing Qian vpu_imx8q_set_system_cfg_common(config, regs_base, core_id); 653d8297779SMing Qian } 654d8297779SMing Qian 655d8297779SMing Qian int vpu_windsor_get_stream_buffer_size(struct vpu_shared_addr *shared) 656d8297779SMing Qian { 657d8297779SMing Qian return 0x300000; 658d8297779SMing Qian } 659d8297779SMing Qian 660d8297779SMing Qian static struct vpu_pair windsor_cmds[] = { 661*08274443SMing Qian {VPU_CMD_ID_NOOP, GTB_ENC_CMD_NOOP}, 662d8297779SMing Qian {VPU_CMD_ID_CONFIGURE_CODEC, GTB_ENC_CMD_CONFIGURE_CODEC}, 663d8297779SMing Qian {VPU_CMD_ID_START, GTB_ENC_CMD_STREAM_START}, 664d8297779SMing Qian {VPU_CMD_ID_STOP, GTB_ENC_CMD_STREAM_STOP}, 665d8297779SMing Qian {VPU_CMD_ID_FRAME_ENCODE, GTB_ENC_CMD_FRAME_ENCODE}, 666d8297779SMing Qian {VPU_CMD_ID_SNAPSHOT, GTB_ENC_CMD_SNAPSHOT}, 667d8297779SMing Qian {VPU_CMD_ID_FIRM_RESET, GTB_ENC_CMD_FIRM_RESET}, 668d8297779SMing Qian {VPU_CMD_ID_UPDATE_PARAMETER, GTB_ENC_CMD_PARAMETER_UPD}, 669d8297779SMing Qian {VPU_CMD_ID_DEBUG, GTB_ENC_CMD_FW_STATUS} 670d8297779SMing Qian }; 671d8297779SMing Qian 672d8297779SMing Qian static struct vpu_pair windsor_msgs[] = { 673d8297779SMing Qian {VPU_MSG_ID_RESET_DONE, VID_API_ENC_EVENT_RESET_DONE}, 674d8297779SMing Qian {VPU_MSG_ID_START_DONE, VID_API_ENC_EVENT_START_DONE}, 675d8297779SMing Qian {VPU_MSG_ID_STOP_DONE, VID_API_ENC_EVENT_STOP_DONE}, 676d8297779SMing Qian {VPU_MSG_ID_FRAME_INPUT_DONE, VID_API_ENC_EVENT_FRAME_INPUT_DONE}, 677d8297779SMing Qian {VPU_MSG_ID_ENC_DONE, VID_API_ENC_EVENT_FRAME_DONE}, 678d8297779SMing Qian {VPU_MSG_ID_FRAME_RELEASE, VID_API_ENC_EVENT_FRAME_RELEASE}, 679d8297779SMing Qian {VPU_MSG_ID_MEM_REQUEST, VID_API_ENC_EVENT_MEM_REQUEST}, 680d8297779SMing Qian {VPU_MSG_ID_PARAM_UPD_DONE, VID_API_ENC_EVENT_PARA_UPD_DONE}, 681d8297779SMing Qian {VPU_MSG_ID_FIRMWARE_XCPT, VID_API_ENC_EVENT_FIRMWARE_XCPT}, 682d8297779SMing Qian }; 683d8297779SMing Qian 684d8297779SMing Qian int vpu_windsor_pack_cmd(struct vpu_rpc_event *pkt, u32 index, u32 id, void *data) 685d8297779SMing Qian { 686d8297779SMing Qian int ret; 687d8297779SMing Qian 688d8297779SMing Qian ret = vpu_find_dst_by_src(windsor_cmds, ARRAY_SIZE(windsor_cmds), id); 689d8297779SMing Qian if (ret < 0) 690d8297779SMing Qian return ret; 691d8297779SMing Qian pkt->hdr.id = ret; 692d8297779SMing Qian pkt->hdr.num = 0; 693d8297779SMing Qian pkt->hdr.index = index; 694d8297779SMing Qian if (id == VPU_CMD_ID_FRAME_ENCODE) { 69505a03effSMing Qian s64 timestamp = *(s64 *)data; 69605a03effSMing Qian struct timespec64 ts = ns_to_timespec64(timestamp); 69705a03effSMing Qian 698d8297779SMing Qian pkt->hdr.num = 2; 69905a03effSMing Qian pkt->data[0] = ts.tv_sec; 70005a03effSMing Qian pkt->data[1] = ts.tv_nsec; 701d8297779SMing Qian } 702d8297779SMing Qian 703d8297779SMing Qian return 0; 704d8297779SMing Qian } 705d8297779SMing Qian 706d8297779SMing Qian int vpu_windsor_convert_msg_id(u32 id) 707d8297779SMing Qian { 708d8297779SMing Qian return vpu_find_src_by_dst(windsor_msgs, ARRAY_SIZE(windsor_msgs), id); 709d8297779SMing Qian } 710d8297779SMing Qian 711d8297779SMing Qian static void vpu_windsor_unpack_pic_info(struct vpu_rpc_event *pkt, void *data) 712d8297779SMing Qian { 713d8297779SMing Qian struct vpu_enc_pic_info *info = data; 714d8297779SMing Qian struct windsor_pic_info *windsor = (struct windsor_pic_info *)pkt->data; 71505a03effSMing Qian struct timespec64 ts = { windsor->tv_s, windsor->tv_ns }; 716d8297779SMing Qian 717d8297779SMing Qian info->frame_id = windsor->frame_id; 718d8297779SMing Qian switch (windsor->pic_type) { 719d8297779SMing Qian case MEDIAIP_ENC_PIC_TYPE_I_FRAME: 720d8297779SMing Qian case MEDIAIP_ENC_PIC_TYPE_IDR_FRAME: 721d8297779SMing Qian info->pic_type = V4L2_BUF_FLAG_KEYFRAME; 722d8297779SMing Qian break; 723d8297779SMing Qian case MEDIAIP_ENC_PIC_TYPE_P_FRAME: 724d8297779SMing Qian info->pic_type = V4L2_BUF_FLAG_PFRAME; 725d8297779SMing Qian break; 726d8297779SMing Qian case MEDIAIP_ENC_PIC_TYPE_B_FRAME: 727d8297779SMing Qian info->pic_type = V4L2_BUF_FLAG_BFRAME; 728d8297779SMing Qian break; 729d8297779SMing Qian default: 730d8297779SMing Qian break; 731d8297779SMing Qian } 732d8297779SMing Qian info->skipped_frame = windsor->skipped_frame; 733d8297779SMing Qian info->error_flag = windsor->error_flag; 734d8297779SMing Qian info->psnr = windsor->psnr; 735d8297779SMing Qian info->frame_size = windsor->frame_size; 736d8297779SMing Qian info->wptr = get_ptr(windsor->str_buff_wptr); 737d8297779SMing Qian info->crc = windsor->frame_crc; 73805a03effSMing Qian info->timestamp = timespec64_to_ns(&ts); 739d8297779SMing Qian } 740d8297779SMing Qian 741d8297779SMing Qian static void vpu_windsor_unpack_mem_req(struct vpu_rpc_event *pkt, void *data) 742d8297779SMing Qian { 743d8297779SMing Qian struct vpu_pkt_mem_req_data *req_data = data; 744d8297779SMing Qian 745d8297779SMing Qian req_data->enc_frame_size = pkt->data[0]; 746d8297779SMing Qian req_data->enc_frame_num = pkt->data[1]; 747d8297779SMing Qian req_data->ref_frame_size = pkt->data[2]; 748d8297779SMing Qian req_data->ref_frame_num = pkt->data[3]; 749d8297779SMing Qian req_data->act_buf_size = pkt->data[4]; 750d8297779SMing Qian req_data->act_buf_num = 1; 751d8297779SMing Qian } 752d8297779SMing Qian 753d8297779SMing Qian int vpu_windsor_unpack_msg_data(struct vpu_rpc_event *pkt, void *data) 754d8297779SMing Qian { 755d8297779SMing Qian if (!pkt || !data) 756d8297779SMing Qian return -EINVAL; 757d8297779SMing Qian 758d8297779SMing Qian switch (pkt->hdr.id) { 759d8297779SMing Qian case VID_API_ENC_EVENT_FRAME_DONE: 760d8297779SMing Qian vpu_windsor_unpack_pic_info(pkt, data); 761d8297779SMing Qian break; 762d8297779SMing Qian case VID_API_ENC_EVENT_MEM_REQUEST: 763d8297779SMing Qian vpu_windsor_unpack_mem_req(pkt, data); 764d8297779SMing Qian break; 765d8297779SMing Qian case VID_API_ENC_EVENT_FRAME_RELEASE: 766d8297779SMing Qian *(u32 *)data = pkt->data[0]; 767d8297779SMing Qian break; 768d8297779SMing Qian default: 769d8297779SMing Qian break; 770d8297779SMing Qian } 771d8297779SMing Qian 772d8297779SMing Qian return 0; 773d8297779SMing Qian } 774d8297779SMing Qian 775d8297779SMing Qian static int vpu_windsor_fill_yuv_frame(struct vpu_shared_addr *shared, 776d8297779SMing Qian u32 instance, 777d8297779SMing Qian struct vb2_buffer *vb) 778d8297779SMing Qian { 779d21ce554SMing Qian struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 780d21ce554SMing Qian struct vpu_format *out_fmt; 781d8297779SMing Qian struct vpu_enc_yuv_desc *desc; 782d8297779SMing Qian struct vb2_v4l2_buffer *vbuf; 783d8297779SMing Qian 784d8297779SMing Qian if (instance >= VID_API_NUM_STREAMS) 785d8297779SMing Qian return -EINVAL; 786d8297779SMing Qian 787d8297779SMing Qian desc = get_yuv_desc(shared, instance); 788d21ce554SMing Qian out_fmt = vpu_get_format(inst, vb->type); 789d8297779SMing Qian 790d8297779SMing Qian vbuf = to_vb2_v4l2_buffer(vb); 791d8297779SMing Qian desc->frame_id = vbuf->sequence; 792d8297779SMing Qian if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME) 793d8297779SMing Qian desc->key_frame = 1; 794d8297779SMing Qian else 795d8297779SMing Qian desc->key_frame = 0; 796d8297779SMing Qian desc->luma_base = vpu_get_vb_phy_addr(vb, 0); 797d21ce554SMing Qian if (vb->num_planes > 1) 798d8297779SMing Qian desc->chroma_base = vpu_get_vb_phy_addr(vb, 1); 799d21ce554SMing Qian else 800d21ce554SMing Qian desc->chroma_base = desc->luma_base + out_fmt->sizeimage[0]; 801d8297779SMing Qian 802d8297779SMing Qian return 0; 803d8297779SMing Qian } 804d8297779SMing Qian 805d8297779SMing Qian int vpu_windsor_input_frame(struct vpu_shared_addr *shared, 806d8297779SMing Qian struct vpu_inst *inst, struct vb2_buffer *vb) 807d8297779SMing Qian { 808d8297779SMing Qian vpu_windsor_fill_yuv_frame(shared, inst->id, vb); 809d8297779SMing Qian return vpu_session_encode_frame(inst, vb->timestamp); 810d8297779SMing Qian } 811d8297779SMing Qian 812d8297779SMing Qian int vpu_windsor_config_memory_resource(struct vpu_shared_addr *shared, 813d8297779SMing Qian u32 instance, 814d8297779SMing Qian u32 type, 815d8297779SMing Qian u32 index, 816d8297779SMing Qian struct vpu_buffer *buf) 817d8297779SMing Qian { 818d8297779SMing Qian struct vpu_enc_mem_pool *pool; 819d8297779SMing Qian struct vpu_enc_memory_resource *res; 820d8297779SMing Qian 821d8297779SMing Qian if (instance >= VID_API_NUM_STREAMS) 822d8297779SMing Qian return -EINVAL; 823d8297779SMing Qian 824d8297779SMing Qian pool = get_mem_pool(shared, instance); 825d8297779SMing Qian 826d8297779SMing Qian switch (type) { 827d8297779SMing Qian case MEM_RES_ENC: 828a9f7224cSMing Qian if (index >= ARRAY_SIZE(pool->enc_frames)) 829a9f7224cSMing Qian return -EINVAL; 830d8297779SMing Qian res = &pool->enc_frames[index]; 831d8297779SMing Qian break; 832d8297779SMing Qian case MEM_RES_REF: 833a9f7224cSMing Qian if (index >= ARRAY_SIZE(pool->ref_frames)) 834a9f7224cSMing Qian return -EINVAL; 835d8297779SMing Qian res = &pool->ref_frames[index]; 836d8297779SMing Qian break; 837d8297779SMing Qian case MEM_RES_ACT: 838a9f7224cSMing Qian if (index) 839a9f7224cSMing Qian return -EINVAL; 840d8297779SMing Qian res = &pool->act_frame; 841d8297779SMing Qian break; 842d8297779SMing Qian default: 843d8297779SMing Qian return -EINVAL; 844d8297779SMing Qian } 845d8297779SMing Qian 846d8297779SMing Qian res->phys = buf->phys; 847d8297779SMing Qian res->virt = buf->phys - shared->boot_addr; 848d8297779SMing Qian res->size = buf->length; 849d8297779SMing Qian 850d8297779SMing Qian return 0; 851d8297779SMing Qian } 852d8297779SMing Qian 853d8297779SMing Qian int vpu_windsor_config_stream_buffer(struct vpu_shared_addr *shared, 854d8297779SMing Qian u32 instance, 855d8297779SMing Qian struct vpu_buffer *buf) 856d8297779SMing Qian { 857d8297779SMing Qian struct vpu_rpc_buffer_desc *desc; 858d8297779SMing Qian struct vpu_enc_expert_mode_param *expert; 859d8297779SMing Qian 860d8297779SMing Qian desc = get_stream_buf_desc(shared, instance); 861d8297779SMing Qian expert = get_expert_param(shared, instance); 862d8297779SMing Qian 863d8297779SMing Qian desc->start = buf->phys; 864d8297779SMing Qian desc->wptr = buf->phys; 865d8297779SMing Qian desc->rptr = buf->phys; 866d8297779SMing Qian desc->end = buf->phys + buf->length; 867d8297779SMing Qian 868d8297779SMing Qian expert->calib_param.mem_chunk_phys_addr = 0; 869d8297779SMing Qian expert->calib_param.mem_chunk_virt_addr = 0; 870d8297779SMing Qian expert->calib_param.mem_chunk_size = 0; 871d8297779SMing Qian expert->calib_param.cb_base = buf->phys; 872d8297779SMing Qian expert->calib_param.cb_size = buf->length; 873d8297779SMing Qian 874d8297779SMing Qian return 0; 875d8297779SMing Qian } 876d8297779SMing Qian 877d8297779SMing Qian int vpu_windsor_update_stream_buffer(struct vpu_shared_addr *shared, 878d8297779SMing Qian u32 instance, u32 ptr, bool write) 879d8297779SMing Qian { 880d8297779SMing Qian struct vpu_rpc_buffer_desc *desc; 881d8297779SMing Qian 882d8297779SMing Qian desc = get_stream_buf_desc(shared, instance); 883d8297779SMing Qian 884d8297779SMing Qian /*update wptr/rptr after data is written or read*/ 885d8297779SMing Qian mb(); 886d8297779SMing Qian if (write) 887d8297779SMing Qian desc->wptr = ptr; 888d8297779SMing Qian else 889d8297779SMing Qian desc->rptr = ptr; 890d8297779SMing Qian 891d8297779SMing Qian return 0; 892d8297779SMing Qian } 893d8297779SMing Qian 894d8297779SMing Qian int vpu_windsor_get_stream_buffer_desc(struct vpu_shared_addr *shared, 895d8297779SMing Qian u32 instance, struct vpu_rpc_buffer_desc *desc) 896d8297779SMing Qian { 897d8297779SMing Qian struct vpu_rpc_buffer_desc *rpc_desc; 898d8297779SMing Qian 899d8297779SMing Qian rpc_desc = get_stream_buf_desc(shared, instance); 900d8297779SMing Qian if (desc) { 901d8297779SMing Qian desc->wptr = get_ptr(rpc_desc->wptr); 902d8297779SMing Qian desc->rptr = get_ptr(rpc_desc->rptr); 903d8297779SMing Qian desc->start = get_ptr(rpc_desc->start); 904d8297779SMing Qian desc->end = get_ptr(rpc_desc->end); 905d8297779SMing Qian } 906d8297779SMing Qian 907d8297779SMing Qian return 0; 908d8297779SMing Qian } 909d8297779SMing Qian 910d8297779SMing Qian u32 vpu_windsor_get_version(struct vpu_shared_addr *shared) 911d8297779SMing Qian { 912d8297779SMing Qian struct windsor_iface *iface = shared->iface; 913d8297779SMing Qian 914d8297779SMing Qian return iface->fw_version; 915d8297779SMing Qian } 916d8297779SMing Qian 917d8297779SMing Qian static int vpu_windsor_set_frame_rate(struct vpu_enc_expert_mode_param *expert, 918d8297779SMing Qian struct vpu_encode_params *params) 919d8297779SMing Qian { 920d8297779SMing Qian expert->config_param.frame_rate_num = params->frame_rate.numerator; 921d8297779SMing Qian expert->config_param.frame_rate_den = params->frame_rate.denominator; 922d8297779SMing Qian 923d8297779SMing Qian return 0; 924d8297779SMing Qian } 925d8297779SMing Qian 926d8297779SMing Qian static int vpu_windsor_set_format(struct vpu_enc_param *param, u32 pixelformat) 927d8297779SMing Qian { 928d8297779SMing Qian switch (pixelformat) { 929d8297779SMing Qian case V4L2_PIX_FMT_H264: 930d8297779SMing Qian param->codec_mode = MEDIAIP_ENC_FMT_H264; 931d8297779SMing Qian break; 932d8297779SMing Qian default: 933d8297779SMing Qian return -EINVAL; 934d8297779SMing Qian } 935d8297779SMing Qian 936d8297779SMing Qian return 0; 937d8297779SMing Qian } 938d8297779SMing Qian 939d8297779SMing Qian static int vpu_windsor_set_profile(struct vpu_enc_param *param, u32 profile) 940d8297779SMing Qian { 941d8297779SMing Qian switch (profile) { 942d8297779SMing Qian case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: 943d8297779SMing Qian param->profile = MEDIAIP_ENC_PROF_H264_BP; 944d8297779SMing Qian break; 945d8297779SMing Qian case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: 946d8297779SMing Qian param->profile = MEDIAIP_ENC_PROF_H264_MP; 947d8297779SMing Qian break; 948d8297779SMing Qian case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: 949d8297779SMing Qian param->profile = MEDIAIP_ENC_PROF_H264_HP; 950d8297779SMing Qian break; 951d8297779SMing Qian default: 952d8297779SMing Qian return -EINVAL; 953d8297779SMing Qian } 954d8297779SMing Qian 955d8297779SMing Qian return 0; 956d8297779SMing Qian } 957d8297779SMing Qian 958d8297779SMing Qian static const u32 h264_level[] = { 959d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_1_0] = 10, 960d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_1B] = 14, 961d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_1_1] = 11, 962d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_1_2] = 12, 963d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_1_3] = 13, 964d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_2_0] = 20, 965d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_2_1] = 21, 966d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_2_2] = 22, 967d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_3_0] = 30, 968d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_3_1] = 31, 969d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_3_2] = 32, 970d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_4_0] = 40, 971d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_4_1] = 41, 972d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_4_2] = 42, 973d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_5_0] = 50, 974d8297779SMing Qian [V4L2_MPEG_VIDEO_H264_LEVEL_5_1] = 51 975d8297779SMing Qian }; 976d8297779SMing Qian 977d8297779SMing Qian static int vpu_windsor_set_level(struct vpu_enc_param *param, u32 level) 978d8297779SMing Qian { 979d8297779SMing Qian if (level >= ARRAY_SIZE(h264_level)) 980d8297779SMing Qian return -EINVAL; 981d8297779SMing Qian 982d8297779SMing Qian param->level = h264_level[level]; 983d8297779SMing Qian 984d8297779SMing Qian return 0; 985d8297779SMing Qian } 986d8297779SMing Qian 987d8297779SMing Qian static int vpu_windsor_set_size(struct vpu_enc_param *windsor, 988d8297779SMing Qian struct vpu_encode_params *params) 989d8297779SMing Qian { 990d8297779SMing Qian windsor->src_stride = params->src_stride; 991d8297779SMing Qian windsor->src_width = params->src_width; 992d8297779SMing Qian windsor->src_height = params->src_height; 993d8297779SMing Qian windsor->src_offset_x = params->crop.left; 994d8297779SMing Qian windsor->src_offset_y = params->crop.top; 995d8297779SMing Qian windsor->src_crop_width = params->crop.width; 996d8297779SMing Qian windsor->src_crop_height = params->crop.height; 997d8297779SMing Qian windsor->out_width = params->out_width; 998d8297779SMing Qian windsor->out_height = params->out_height; 999d8297779SMing Qian 1000d8297779SMing Qian return 0; 1001d8297779SMing Qian } 1002d8297779SMing Qian 1003d8297779SMing Qian static int vpu_windsor_set_gop(struct vpu_enc_param *param, u32 gop) 1004d8297779SMing Qian { 1005d8297779SMing Qian param->iframe_interval = gop; 1006d8297779SMing Qian 1007d8297779SMing Qian return 0; 1008d8297779SMing Qian } 1009d8297779SMing Qian 1010d8297779SMing Qian static int vpu_windsor_set_bframes(struct vpu_enc_param *param, u32 bframes) 1011d8297779SMing Qian { 1012d8297779SMing Qian if (bframes) { 1013d8297779SMing Qian param->low_latency_mode = 0; 1014d8297779SMing Qian param->bframes = bframes; 1015d8297779SMing Qian } else { 1016d8297779SMing Qian param->low_latency_mode = 1; 1017d8297779SMing Qian param->bframes = 0; 1018d8297779SMing Qian } 1019d8297779SMing Qian 1020d8297779SMing Qian return 0; 1021d8297779SMing Qian } 1022d8297779SMing Qian 1023d8297779SMing Qian static int vpu_windsor_set_bitrate_mode(struct vpu_enc_param *param, u32 rc_enable, u32 mode) 1024d8297779SMing Qian { 1025d8297779SMing Qian if (!rc_enable) 1026d8297779SMing Qian param->bitrate_mode = MEDIAIP_ENC_BITRATE_MODE_CONSTANT_QP; 1027d8297779SMing Qian else if (mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) 1028d8297779SMing Qian param->bitrate_mode = MEDIAIP_ENC_BITRATE_MODE_VBR; 1029d8297779SMing Qian else 1030d8297779SMing Qian param->bitrate_mode = MEDIAIP_ENC_BITRATE_MODE_CBR; 1031d8297779SMing Qian 1032d8297779SMing Qian return 0; 1033d8297779SMing Qian } 1034d8297779SMing Qian 1035d8297779SMing Qian static u32 vpu_windsor_bitrate(u32 bitrate) 1036d8297779SMing Qian { 1037d8297779SMing Qian return DIV_ROUND_CLOSEST(bitrate, WINDSOR_BITRATE_UNIT); 1038d8297779SMing Qian } 1039d8297779SMing Qian 1040d8297779SMing Qian static int vpu_windsor_set_bitrate(struct vpu_enc_param *windsor, 1041d8297779SMing Qian struct vpu_encode_params *params) 1042d8297779SMing Qian { 1043d8297779SMing Qian windsor->target_bitrate = vpu_windsor_bitrate(params->bitrate); 1044d8297779SMing Qian windsor->min_bitrate = vpu_windsor_bitrate(params->bitrate_min); 1045d8297779SMing Qian windsor->max_bitrate = vpu_windsor_bitrate(params->bitrate_max); 1046d8297779SMing Qian 1047d8297779SMing Qian return 0; 1048d8297779SMing Qian } 1049d8297779SMing Qian 1050d8297779SMing Qian static int vpu_windsor_set_qp(struct vpu_enc_expert_mode_param *expert, 1051d8297779SMing Qian struct vpu_encode_params *params) 1052d8297779SMing Qian { 1053d8297779SMing Qian expert->static_param.rate_control_islice_qp = params->i_frame_qp; 1054d8297779SMing Qian expert->static_param.rate_control_pslice_qp = params->p_frame_qp; 1055d8297779SMing Qian expert->static_param.rate_control_bslice_qp = params->b_frame_qp; 1056d8297779SMing Qian 1057d8297779SMing Qian return 0; 1058d8297779SMing Qian } 1059d8297779SMing Qian 1060d8297779SMing Qian static int vpu_windsor_set_sar(struct vpu_enc_expert_mode_param *expert, 1061d8297779SMing Qian struct vpu_encode_params *params) 1062d8297779SMing Qian { 1063d8297779SMing Qian expert->config_param.h264_aspect_ratio_present = params->sar.enable; 1064d8297779SMing Qian if (params->sar.idc == V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED) 1065d8297779SMing Qian expert->config_param.aspect_ratio = WINDSOR_H264_EXTENDED_SAR; 1066d8297779SMing Qian else 1067d8297779SMing Qian expert->config_param.aspect_ratio = params->sar.idc; 1068d8297779SMing Qian expert->config_param.h264_aspect_ratio_sar_width = params->sar.width; 1069d8297779SMing Qian expert->config_param.h264_aspect_ratio_sar_height = params->sar.height; 1070d8297779SMing Qian 1071d8297779SMing Qian return 0; 1072d8297779SMing Qian } 1073d8297779SMing Qian 1074d8297779SMing Qian static int vpu_windsor_set_color(struct vpu_enc_expert_mode_param *expert, 1075d8297779SMing Qian struct vpu_encode_params *params) 1076d8297779SMing Qian { 1077d8297779SMing Qian expert->config_param.h264_video_type_present = 1; 1078d8297779SMing Qian expert->config_param.h264_video_format = 5; 1079d8297779SMing Qian expert->config_param.h264_video_colour_descriptor = 1; 1080d8297779SMing Qian expert->config_param.h264_video_colour_primaries = 1081d8297779SMing Qian vpu_color_cvrt_primaries_v2i(params->color.primaries); 1082d8297779SMing Qian expert->config_param.h264_video_transfer_char = 1083d8297779SMing Qian vpu_color_cvrt_transfers_v2i(params->color.transfer); 1084d8297779SMing Qian expert->config_param.h264_video_matrix_coeff = 1085d8297779SMing Qian vpu_color_cvrt_matrix_v2i(params->color.matrix); 1086d8297779SMing Qian expert->config_param.h264_video_full_range = 1087d8297779SMing Qian vpu_color_cvrt_full_range_v2i(params->color.full_range); 1088d8297779SMing Qian return 0; 1089d8297779SMing Qian } 1090d8297779SMing Qian 1091d8297779SMing Qian static int vpu_windsor_update_bitrate(struct vpu_shared_addr *shared, 1092d8297779SMing Qian u32 instance, struct vpu_encode_params *params) 1093d8297779SMing Qian { 1094d8297779SMing Qian struct vpu_enc_param *windsor; 1095d8297779SMing Qian struct vpu_enc_expert_mode_param *expert; 1096d8297779SMing Qian 1097d8297779SMing Qian windsor = get_enc_param(shared, instance); 1098d8297779SMing Qian expert = get_expert_param(shared, instance); 1099d8297779SMing Qian 1100d8297779SMing Qian if (windsor->bitrate_mode != MEDIAIP_ENC_BITRATE_MODE_CBR) 1101d8297779SMing Qian return 0; 1102d8297779SMing Qian if (!params->rc_enable) 1103d8297779SMing Qian return 0; 1104d8297779SMing Qian if (vpu_windsor_bitrate(params->bitrate) == windsor->target_bitrate) 1105d8297779SMing Qian return 0; 1106d8297779SMing Qian 1107d8297779SMing Qian vpu_windsor_set_bitrate(windsor, params); 1108d8297779SMing Qian expert->static_param.rate_control_bitrate = windsor->target_bitrate; 1109d8297779SMing Qian expert->static_param.rate_control_bitrate_min = windsor->min_bitrate; 1110d8297779SMing Qian expert->static_param.rate_control_bitrate_max = windsor->max_bitrate; 1111d8297779SMing Qian 1112d8297779SMing Qian return 0; 1113d8297779SMing Qian } 1114d8297779SMing Qian 1115d8297779SMing Qian static int vpu_windsor_set_params(struct vpu_shared_addr *shared, 1116d8297779SMing Qian u32 instance, struct vpu_encode_params *params) 1117d8297779SMing Qian { 1118d8297779SMing Qian struct vpu_enc_param *windsor; 1119d8297779SMing Qian int ret; 1120d8297779SMing Qian 1121d8297779SMing Qian windsor = get_enc_param(shared, instance); 1122d8297779SMing Qian 1123d8297779SMing Qian if (params->input_format != V4L2_PIX_FMT_NV12 && 1124d8297779SMing Qian params->input_format != V4L2_PIX_FMT_NV12M) 1125d8297779SMing Qian return -EINVAL; 1126d8297779SMing Qian 1127d8297779SMing Qian ret = vpu_windsor_set_format(windsor, params->codec_format); 1128d8297779SMing Qian if (ret) 1129d8297779SMing Qian return ret; 1130d8297779SMing Qian vpu_windsor_set_profile(windsor, params->profile); 1131d8297779SMing Qian vpu_windsor_set_level(windsor, params->level); 1132d8297779SMing Qian vpu_windsor_set_size(windsor, params); 1133d8297779SMing Qian vpu_windsor_set_gop(windsor, params->gop_length); 1134d8297779SMing Qian vpu_windsor_set_bframes(windsor, params->bframes); 1135d8297779SMing Qian vpu_windsor_set_bitrate_mode(windsor, params->rc_enable, params->rc_mode); 1136d8297779SMing Qian vpu_windsor_set_bitrate(windsor, params); 1137d8297779SMing Qian windsor->init_slice_qp = params->i_frame_qp; 1138d8297779SMing Qian 1139d8297779SMing Qian if (!params->frame_rate.numerator) 1140d8297779SMing Qian return -EINVAL; 1141d8297779SMing Qian windsor->frame_rate = params->frame_rate.denominator / params->frame_rate.numerator; 1142d8297779SMing Qian 1143d8297779SMing Qian return 0; 1144d8297779SMing Qian } 1145d8297779SMing Qian 1146d8297779SMing Qian static int vpu_windsor_update_params(struct vpu_shared_addr *shared, 1147d8297779SMing Qian u32 instance, struct vpu_encode_params *params) 1148d8297779SMing Qian { 1149d8297779SMing Qian struct vpu_enc_expert_mode_param *expert; 1150d8297779SMing Qian 1151d8297779SMing Qian expert = get_expert_param(shared, instance); 1152d8297779SMing Qian 1153d8297779SMing Qian vpu_windsor_set_frame_rate(expert, params); 1154d8297779SMing Qian vpu_windsor_set_qp(expert, params); 1155d8297779SMing Qian vpu_windsor_set_sar(expert, params); 1156d8297779SMing Qian vpu_windsor_set_color(expert, params); 1157d8297779SMing Qian vpu_windsor_update_bitrate(shared, instance, params); 1158d8297779SMing Qian /*expert->config_param.iac_sc_threshold = 0;*/ 1159d8297779SMing Qian 1160d8297779SMing Qian return 0; 1161d8297779SMing Qian } 1162d8297779SMing Qian 1163d8297779SMing Qian int vpu_windsor_set_encode_params(struct vpu_shared_addr *shared, 1164d8297779SMing Qian u32 instance, struct vpu_encode_params *params, u32 update) 1165d8297779SMing Qian { 1166d8297779SMing Qian if (!params) 1167d8297779SMing Qian return -EINVAL; 1168d8297779SMing Qian 1169d8297779SMing Qian if (!update) 1170d8297779SMing Qian return vpu_windsor_set_params(shared, instance, params); 1171d8297779SMing Qian else 1172d8297779SMing Qian return vpu_windsor_update_params(shared, instance, params); 1173d8297779SMing Qian } 1174d8297779SMing Qian 1175d8297779SMing Qian u32 vpu_windsor_get_max_instance_count(struct vpu_shared_addr *shared) 1176d8297779SMing Qian { 1177d8297779SMing Qian struct windsor_iface *iface = shared->iface; 1178d8297779SMing Qian 1179d8297779SMing Qian return iface->max_streams; 1180d8297779SMing Qian } 1181