18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) STMicroelectronics SA 2015
48c2ecf20Sopenharmony_ci * Authors: Yannick Fertre <yannick.fertre@st.com>
58c2ecf20Sopenharmony_ci *          Hugues Fruchet <hugues.fruchet@st.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "hva.h"
98c2ecf20Sopenharmony_ci#include "hva-hw.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define MAX_SPS_PPS_SIZE 128
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define BITSTREAM_OFFSET_MASK 0x7F
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/* video max size*/
168c2ecf20Sopenharmony_ci#define H264_MAX_SIZE_W 1920
178c2ecf20Sopenharmony_ci#define H264_MAX_SIZE_H 1920
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/* macroBlocs number (width & height) */
208c2ecf20Sopenharmony_ci#define MB_W(w) ((w + 0xF)  / 0x10)
218c2ecf20Sopenharmony_ci#define MB_H(h) ((h + 0xF)  / 0x10)
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* formula to get temporal or spatial data size */
248c2ecf20Sopenharmony_ci#define DATA_SIZE(w, h) (MB_W(w) * MB_H(h) * 16)
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define SEARCH_WINDOW_BUFFER_MAX_SIZE(w) ((4 * MB_W(w) + 42) * 256 * 3 / 2)
278c2ecf20Sopenharmony_ci#define CABAC_CONTEXT_BUFFER_MAX_SIZE(w) (MB_W(w) * 16)
288c2ecf20Sopenharmony_ci#define CTX_MB_BUFFER_MAX_SIZE(w) (MB_W(w) * 16 * 8)
298c2ecf20Sopenharmony_ci#define SLICE_HEADER_SIZE (4 * 16)
308c2ecf20Sopenharmony_ci#define BRC_DATA_SIZE (5 * 16)
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* source buffer copy in YUV 420 MB-tiled format with size=16*256*3/2 */
338c2ecf20Sopenharmony_ci#define CURRENT_WINDOW_BUFFER_MAX_SIZE (16 * 256 * 3 / 2)
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/*
368c2ecf20Sopenharmony_ci * 4 lines of pixels (in Luma, Chroma blue and Chroma red) of top MB
378c2ecf20Sopenharmony_ci * for deblocking with size=4*16*MBx*2
388c2ecf20Sopenharmony_ci */
398c2ecf20Sopenharmony_ci#define LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(w) (4 * 16 * MB_W(w) * 2)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/* factor for bitrate and cpb buffer size max values if profile >= high */
428c2ecf20Sopenharmony_ci#define H264_FACTOR_HIGH 1200
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/* factor for bitrate and cpb buffer size max values if profile < high */
458c2ecf20Sopenharmony_ci#define H264_FACTOR_BASELINE 1000
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/* number of bytes for NALU_TYPE_FILLER_DATA header and footer */
488c2ecf20Sopenharmony_ci#define H264_FILLER_DATA_SIZE 6
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistruct h264_profile {
518c2ecf20Sopenharmony_ci	enum v4l2_mpeg_video_h264_level level;
528c2ecf20Sopenharmony_ci	u32 max_mb_per_seconds;
538c2ecf20Sopenharmony_ci	u32 max_frame_size;
548c2ecf20Sopenharmony_ci	u32 max_bitrate;
558c2ecf20Sopenharmony_ci	u32 max_cpb_size;
568c2ecf20Sopenharmony_ci	u32 min_comp_ratio;
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic const struct h264_profile h264_infos_list[] = {
608c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_1_0, 1485, 99, 64, 175, 2},
618c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_1B, 1485, 99, 128, 350, 2},
628c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_1_1, 3000, 396, 192, 500, 2},
638c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_1_2, 6000, 396, 384, 1000, 2},
648c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_1_3, 11880, 396, 768, 2000, 2},
658c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_2_0, 11880, 396, 2000, 2000, 2},
668c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_2_1, 19800, 792, 4000, 4000, 2},
678c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_2_2, 20250, 1620, 4000, 4000, 2},
688c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_3_0, 40500, 1620, 10000, 10000, 2},
698c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_3_1, 108000, 3600, 14000, 14000, 4},
708c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_3_2, 216000, 5120, 20000, 20000, 4},
718c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 245760, 8192, 20000, 25000, 4},
728c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_4_1, 245760, 8192, 50000, 62500, 2},
738c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_4_2, 522240, 8704, 50000, 62500, 2},
748c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_5_0, 589824, 22080, 135000, 135000, 2},
758c2ecf20Sopenharmony_ci	{V4L2_MPEG_VIDEO_H264_LEVEL_5_1, 983040, 36864, 240000, 240000, 2}
768c2ecf20Sopenharmony_ci};
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cienum hva_brc_type {
798c2ecf20Sopenharmony_ci	BRC_TYPE_NONE = 0,
808c2ecf20Sopenharmony_ci	BRC_TYPE_CBR = 1,
818c2ecf20Sopenharmony_ci	BRC_TYPE_VBR = 2,
828c2ecf20Sopenharmony_ci	BRC_TYPE_VBR_LOW_DELAY = 3
838c2ecf20Sopenharmony_ci};
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cienum hva_entropy_coding_mode {
868c2ecf20Sopenharmony_ci	CAVLC = 0,
878c2ecf20Sopenharmony_ci	CABAC = 1
888c2ecf20Sopenharmony_ci};
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cienum hva_picture_coding_type {
918c2ecf20Sopenharmony_ci	PICTURE_CODING_TYPE_I = 0,
928c2ecf20Sopenharmony_ci	PICTURE_CODING_TYPE_P = 1,
938c2ecf20Sopenharmony_ci	PICTURE_CODING_TYPE_B = 2
948c2ecf20Sopenharmony_ci};
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cienum hva_h264_sampling_mode {
978c2ecf20Sopenharmony_ci	SAMPLING_MODE_NV12 = 0,
988c2ecf20Sopenharmony_ci	SAMPLING_MODE_UYVY = 1,
998c2ecf20Sopenharmony_ci	SAMPLING_MODE_RGB3 = 3,
1008c2ecf20Sopenharmony_ci	SAMPLING_MODE_XRGB4 = 4,
1018c2ecf20Sopenharmony_ci	SAMPLING_MODE_NV21 = 8,
1028c2ecf20Sopenharmony_ci	SAMPLING_MODE_VYUY = 9,
1038c2ecf20Sopenharmony_ci	SAMPLING_MODE_BGR3 = 11,
1048c2ecf20Sopenharmony_ci	SAMPLING_MODE_XBGR4 = 12,
1058c2ecf20Sopenharmony_ci	SAMPLING_MODE_RGBX4 = 20,
1068c2ecf20Sopenharmony_ci	SAMPLING_MODE_BGRX4 = 28
1078c2ecf20Sopenharmony_ci};
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cienum hva_h264_nalu_type {
1108c2ecf20Sopenharmony_ci	NALU_TYPE_UNKNOWN = 0,
1118c2ecf20Sopenharmony_ci	NALU_TYPE_SLICE = 1,
1128c2ecf20Sopenharmony_ci	NALU_TYPE_SLICE_DPA = 2,
1138c2ecf20Sopenharmony_ci	NALU_TYPE_SLICE_DPB = 3,
1148c2ecf20Sopenharmony_ci	NALU_TYPE_SLICE_DPC = 4,
1158c2ecf20Sopenharmony_ci	NALU_TYPE_SLICE_IDR = 5,
1168c2ecf20Sopenharmony_ci	NALU_TYPE_SEI = 6,
1178c2ecf20Sopenharmony_ci	NALU_TYPE_SPS = 7,
1188c2ecf20Sopenharmony_ci	NALU_TYPE_PPS = 8,
1198c2ecf20Sopenharmony_ci	NALU_TYPE_AU_DELIMITER = 9,
1208c2ecf20Sopenharmony_ci	NALU_TYPE_SEQ_END = 10,
1218c2ecf20Sopenharmony_ci	NALU_TYPE_STREAM_END = 11,
1228c2ecf20Sopenharmony_ci	NALU_TYPE_FILLER_DATA = 12,
1238c2ecf20Sopenharmony_ci	NALU_TYPE_SPS_EXT = 13,
1248c2ecf20Sopenharmony_ci	NALU_TYPE_PREFIX_UNIT = 14,
1258c2ecf20Sopenharmony_ci	NALU_TYPE_SUBSET_SPS = 15,
1268c2ecf20Sopenharmony_ci	NALU_TYPE_SLICE_AUX = 19,
1278c2ecf20Sopenharmony_ci	NALU_TYPE_SLICE_EXT = 20
1288c2ecf20Sopenharmony_ci};
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cienum hva_h264_sei_payload_type {
1318c2ecf20Sopenharmony_ci	SEI_BUFFERING_PERIOD = 0,
1328c2ecf20Sopenharmony_ci	SEI_PICTURE_TIMING = 1,
1338c2ecf20Sopenharmony_ci	SEI_STEREO_VIDEO_INFO = 21,
1348c2ecf20Sopenharmony_ci	SEI_FRAME_PACKING_ARRANGEMENT = 45
1358c2ecf20Sopenharmony_ci};
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci/*
1388c2ecf20Sopenharmony_ci * stereo Video Info struct
1398c2ecf20Sopenharmony_ci */
1408c2ecf20Sopenharmony_cistruct hva_h264_stereo_video_sei {
1418c2ecf20Sopenharmony_ci	u8 field_views_flag;
1428c2ecf20Sopenharmony_ci	u8 top_field_is_left_view_flag;
1438c2ecf20Sopenharmony_ci	u8 current_frame_is_left_view_flag;
1448c2ecf20Sopenharmony_ci	u8 next_frame_is_second_view_flag;
1458c2ecf20Sopenharmony_ci	u8 left_view_self_contained_flag;
1468c2ecf20Sopenharmony_ci	u8 right_view_self_contained_flag;
1478c2ecf20Sopenharmony_ci};
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci/*
1508c2ecf20Sopenharmony_ci * struct hva_h264_td
1518c2ecf20Sopenharmony_ci *
1528c2ecf20Sopenharmony_ci * @frame_width: width in pixels of the buffer containing the input frame
1538c2ecf20Sopenharmony_ci * @frame_height: height in pixels of the buffer containing the input frame
1548c2ecf20Sopenharmony_ci * @frame_num: the parameter to be written in the slice header
1558c2ecf20Sopenharmony_ci * @picture_coding_type: type I, P or B
1568c2ecf20Sopenharmony_ci * @pic_order_cnt_type: POC mode, as defined in H264 std : can be 0,1,2
1578c2ecf20Sopenharmony_ci * @first_picture_in_sequence: flag telling to encoder that this is the
1588c2ecf20Sopenharmony_ci *			       first picture in a video sequence.
1598c2ecf20Sopenharmony_ci *			       Used for VBR
1608c2ecf20Sopenharmony_ci * @slice_size_type: 0 = no constraint to close the slice
1618c2ecf20Sopenharmony_ci *		     1= a slice is closed as soon as the slice_mb_size limit
1628c2ecf20Sopenharmony_ci *			is reached
1638c2ecf20Sopenharmony_ci *		     2= a slice is closed as soon as the slice_byte_size limit
1648c2ecf20Sopenharmony_ci *			is reached
1658c2ecf20Sopenharmony_ci *		     3= a slice is closed as soon as either the slice_byte_size
1668c2ecf20Sopenharmony_ci *			limit or the slice_mb_size limit is reached
1678c2ecf20Sopenharmony_ci * @slice_mb_size: defines the slice size in number of macroblocks
1688c2ecf20Sopenharmony_ci *		   (used when slice_size_type=1 or slice_size_type=3)
1698c2ecf20Sopenharmony_ci * @ir_param_option: defines the number of macroblocks per frame to be
1708c2ecf20Sopenharmony_ci *		     refreshed by AIR algorithm OR the refresh period
1718c2ecf20Sopenharmony_ci *		     by CIR algorithm
1728c2ecf20Sopenharmony_ci * @intra_refresh_type: enables the adaptive intra refresh algorithm.
1738c2ecf20Sopenharmony_ci *			Disable=0 / Adaptative=1 and Cycle=2 as intra refresh
1748c2ecf20Sopenharmony_ci * @use_constrained_intra_flag: constrained_intra_pred_flag from PPS
1758c2ecf20Sopenharmony_ci * @transform_mode: controls the use of 4x4/8x8 transform mode
1768c2ecf20Sopenharmony_ci * @disable_deblocking_filter_idc:
1778c2ecf20Sopenharmony_ci *		     0: specifies that all luma and chroma block edges of
1788c2ecf20Sopenharmony_ci *			the slice are filtered.
1798c2ecf20Sopenharmony_ci *		     1: specifies that deblocking is disabled for all block
1808c2ecf20Sopenharmony_ci *			edges of the slice.
1818c2ecf20Sopenharmony_ci *		     2: specifies that all luma and chroma block edges of
1828c2ecf20Sopenharmony_ci *			the slice are filtered with exception of the block edges
1838c2ecf20Sopenharmony_ci *			that coincide with slice boundaries
1848c2ecf20Sopenharmony_ci * @slice_alpha_c0_offset_div2: to be written in slice header,
1858c2ecf20Sopenharmony_ci *				controls deblocking
1868c2ecf20Sopenharmony_ci * @slice_beta_offset_div2: to be written in slice header,
1878c2ecf20Sopenharmony_ci *			    controls deblocking
1888c2ecf20Sopenharmony_ci * @encoder_complexity: encoder complexity control (IME).
1898c2ecf20Sopenharmony_ci *		     0 = I_16x16, P_16x16, Full ME Complexity
1908c2ecf20Sopenharmony_ci *		     1 = I_16x16, I_NxN, P_16x16, Full ME Complexity
1918c2ecf20Sopenharmony_ci *		     2 = I_16x16, I_NXN, P_16x16, P_WxH, Full ME Complexity
1928c2ecf20Sopenharmony_ci *		     4 = I_16x16, P_16x16, Reduced ME Complexity
1938c2ecf20Sopenharmony_ci *		     5 = I_16x16, I_NxN, P_16x16, Reduced ME Complexity
1948c2ecf20Sopenharmony_ci *		     6 = I_16x16, I_NXN, P_16x16, P_WxH, Reduced ME Complexity
1958c2ecf20Sopenharmony_ci *  @chroma_qp_index_offset: coming from picture parameter set
1968c2ecf20Sopenharmony_ci *			     (PPS see [H.264 STD] 7.4.2.2)
1978c2ecf20Sopenharmony_ci *  @entropy_coding_mode: entropy coding mode.
1988c2ecf20Sopenharmony_ci *			  0 = CAVLC
1998c2ecf20Sopenharmony_ci *			  1 = CABAC
2008c2ecf20Sopenharmony_ci * @brc_type: selects the bit-rate control algorithm
2018c2ecf20Sopenharmony_ci *		     0 = constant Qp, (no BRC)
2028c2ecf20Sopenharmony_ci *		     1 = CBR
2038c2ecf20Sopenharmony_ci *		     2 = VBR
2048c2ecf20Sopenharmony_ci * @quant: Quantization param used in case of fix QP encoding (no BRC)
2058c2ecf20Sopenharmony_ci * @non_VCL_NALU_Size: size of non-VCL NALUs (SPS, PPS, filler),
2068c2ecf20Sopenharmony_ci *		       used by BRC
2078c2ecf20Sopenharmony_ci * @cpb_buffer_size: size of Coded Picture Buffer, used by BRC
2088c2ecf20Sopenharmony_ci * @bit_rate: target bitrate, for BRC
2098c2ecf20Sopenharmony_ci * @qp_min: min QP threshold
2108c2ecf20Sopenharmony_ci * @qp_max: max QP threshold
2118c2ecf20Sopenharmony_ci * @framerate_num: target framerate numerator , used by BRC
2128c2ecf20Sopenharmony_ci * @framerate_den: target framerate denomurator , used by BRC
2138c2ecf20Sopenharmony_ci * @delay: End-to-End Initial Delay
2148c2ecf20Sopenharmony_ci * @strict_HRD_compliancy: flag for HDR compliancy (1)
2158c2ecf20Sopenharmony_ci *			   May impact quality encoding
2168c2ecf20Sopenharmony_ci * @addr_source_buffer: address of input frame buffer for current frame
2178c2ecf20Sopenharmony_ci * @addr_fwd_Ref_Buffer: address of reference frame buffer
2188c2ecf20Sopenharmony_ci * @addr_rec_buffer: address of reconstructed frame buffer
2198c2ecf20Sopenharmony_ci * @addr_output_bitstream_start: output bitstream start address
2208c2ecf20Sopenharmony_ci * @addr_output_bitstream_end: output bitstream end address
2218c2ecf20Sopenharmony_ci * @addr_external_sw : address of external search window
2228c2ecf20Sopenharmony_ci * @addr_lctx : address of context picture buffer
2238c2ecf20Sopenharmony_ci * @addr_local_rec_buffer: address of local reconstructed buffer
2248c2ecf20Sopenharmony_ci * @addr_spatial_context: address of spatial context buffer
2258c2ecf20Sopenharmony_ci * @bitstream_offset: offset in bits between aligned bitstream start
2268c2ecf20Sopenharmony_ci *		      address and first bit to be written by HVA.
2278c2ecf20Sopenharmony_ci *		      Range value is [0..63]
2288c2ecf20Sopenharmony_ci * @sampling_mode: Input picture format .
2298c2ecf20Sopenharmony_ci *		     0: YUV420 semi_planar Interleaved
2308c2ecf20Sopenharmony_ci *		     1: YUV422 raster Interleaved
2318c2ecf20Sopenharmony_ci * @addr_param_out: address of output parameters structure
2328c2ecf20Sopenharmony_ci * @addr_scaling_matrix: address to the coefficient of
2338c2ecf20Sopenharmony_ci *			 the inverse scaling matrix
2348c2ecf20Sopenharmony_ci * @addr_scaling_matrix_dir: address to the coefficient of
2358c2ecf20Sopenharmony_ci *			     the direct scaling matrix
2368c2ecf20Sopenharmony_ci * @addr_cabac_context_buffer: address of cabac context buffer
2378c2ecf20Sopenharmony_ci * @GmvX: Input information about the horizontal global displacement of
2388c2ecf20Sopenharmony_ci *	  the encoded frame versus the previous one
2398c2ecf20Sopenharmony_ci * @GmvY: Input information about the vertical global displacement of
2408c2ecf20Sopenharmony_ci *	  the encoded frame versus the previous one
2418c2ecf20Sopenharmony_ci * @window_width: width in pixels of the window to be encoded inside
2428c2ecf20Sopenharmony_ci *		  the input frame
2438c2ecf20Sopenharmony_ci * @window_height: width in pixels of the window to be encoded inside
2448c2ecf20Sopenharmony_ci *		   the input frame
2458c2ecf20Sopenharmony_ci * @window_horizontal_offset: horizontal offset in pels for input window
2468c2ecf20Sopenharmony_ci *			      within input frame
2478c2ecf20Sopenharmony_ci * @window_vertical_offset: vertical offset in pels for input window
2488c2ecf20Sopenharmony_ci *			    within input frame
2498c2ecf20Sopenharmony_ci * @addr_roi: Map of QP offset for the Region of Interest algorithm and
2508c2ecf20Sopenharmony_ci *	      also used for Error map.
2518c2ecf20Sopenharmony_ci *	      Bit 0-6 used for qp offset (value -64 to 63).
2528c2ecf20Sopenharmony_ci *	      Bit 7 used to force intra
2538c2ecf20Sopenharmony_ci * @addr_slice_header: address to slice header
2548c2ecf20Sopenharmony_ci * @slice_header_size_in_bits: size in bits of the Slice header
2558c2ecf20Sopenharmony_ci * @slice_header_offset0: Slice header offset where to insert
2568c2ecf20Sopenharmony_ci *			  first_Mb_in_slice
2578c2ecf20Sopenharmony_ci * @slice_header_offset1: Slice header offset where to insert
2588c2ecf20Sopenharmony_ci *			  slice_qp_delta
2598c2ecf20Sopenharmony_ci * @slice_header_offset2: Slice header offset where to insert
2608c2ecf20Sopenharmony_ci *			  num_MBs_in_slice
2618c2ecf20Sopenharmony_ci * @slice_synchro_enable: enable "slice ready" interrupt after each slice
2628c2ecf20Sopenharmony_ci * @max_slice_number: Maximum number of slice in a frame
2638c2ecf20Sopenharmony_ci *		      (0 is strictly forbidden)
2648c2ecf20Sopenharmony_ci * @rgb2_yuv_y_coeff: Four coefficients (C0C1C2C3) to convert from RGB to
2658c2ecf20Sopenharmony_ci *		      YUV for the Y component.
2668c2ecf20Sopenharmony_ci *		      Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0)
2678c2ecf20Sopenharmony_ci * @rgb2_yuv_u_coeff: four coefficients (C0C1C2C3) to convert from RGB to
2688c2ecf20Sopenharmony_ci *		      YUV for the Y component.
2698c2ecf20Sopenharmony_ci *		      Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0)
2708c2ecf20Sopenharmony_ci * @rgb2_yuv_v_coeff: Four coefficients (C0C1C2C3) to convert from RGB to
2718c2ecf20Sopenharmony_ci *		      YUV for the U (Cb) component.
2728c2ecf20Sopenharmony_ci *		      U = C0*R + C1*G + C2*B + C3 (C0 is on byte 0)
2738c2ecf20Sopenharmony_ci * @slice_byte_size: maximum slice size in bytes
2748c2ecf20Sopenharmony_ci *		     (used when slice_size_type=2 or slice_size_type=3)
2758c2ecf20Sopenharmony_ci * @max_air_intra_mb_nb: Maximum number of intra macroblock in a frame
2768c2ecf20Sopenharmony_ci *			 for the AIR algorithm
2778c2ecf20Sopenharmony_ci * @brc_no_skip: Disable skipping in the Bitrate Controller
2788c2ecf20Sopenharmony_ci * @addr_brc_in_out_parameter: address of static buffer for BRC parameters
2798c2ecf20Sopenharmony_ci */
2808c2ecf20Sopenharmony_cistruct hva_h264_td {
2818c2ecf20Sopenharmony_ci	u16 frame_width;
2828c2ecf20Sopenharmony_ci	u16 frame_height;
2838c2ecf20Sopenharmony_ci	u32 frame_num;
2848c2ecf20Sopenharmony_ci	u16 picture_coding_type;
2858c2ecf20Sopenharmony_ci	u16 reserved1;
2868c2ecf20Sopenharmony_ci	u16 pic_order_cnt_type;
2878c2ecf20Sopenharmony_ci	u16 first_picture_in_sequence;
2888c2ecf20Sopenharmony_ci	u16 slice_size_type;
2898c2ecf20Sopenharmony_ci	u16 reserved2;
2908c2ecf20Sopenharmony_ci	u32 slice_mb_size;
2918c2ecf20Sopenharmony_ci	u16 ir_param_option;
2928c2ecf20Sopenharmony_ci	u16 intra_refresh_type;
2938c2ecf20Sopenharmony_ci	u16 use_constrained_intra_flag;
2948c2ecf20Sopenharmony_ci	u16 transform_mode;
2958c2ecf20Sopenharmony_ci	u16 disable_deblocking_filter_idc;
2968c2ecf20Sopenharmony_ci	s16 slice_alpha_c0_offset_div2;
2978c2ecf20Sopenharmony_ci	s16 slice_beta_offset_div2;
2988c2ecf20Sopenharmony_ci	u16 encoder_complexity;
2998c2ecf20Sopenharmony_ci	s16 chroma_qp_index_offset;
3008c2ecf20Sopenharmony_ci	u16 entropy_coding_mode;
3018c2ecf20Sopenharmony_ci	u16 brc_type;
3028c2ecf20Sopenharmony_ci	u16 quant;
3038c2ecf20Sopenharmony_ci	u32 non_vcl_nalu_size;
3048c2ecf20Sopenharmony_ci	u32 cpb_buffer_size;
3058c2ecf20Sopenharmony_ci	u32 bit_rate;
3068c2ecf20Sopenharmony_ci	u16 qp_min;
3078c2ecf20Sopenharmony_ci	u16 qp_max;
3088c2ecf20Sopenharmony_ci	u16 framerate_num;
3098c2ecf20Sopenharmony_ci	u16 framerate_den;
3108c2ecf20Sopenharmony_ci	u16 delay;
3118c2ecf20Sopenharmony_ci	u16 strict_hrd_compliancy;
3128c2ecf20Sopenharmony_ci	u32 addr_source_buffer;
3138c2ecf20Sopenharmony_ci	u32 addr_fwd_ref_buffer;
3148c2ecf20Sopenharmony_ci	u32 addr_rec_buffer;
3158c2ecf20Sopenharmony_ci	u32 addr_output_bitstream_start;
3168c2ecf20Sopenharmony_ci	u32 addr_output_bitstream_end;
3178c2ecf20Sopenharmony_ci	u32 addr_external_sw;
3188c2ecf20Sopenharmony_ci	u32 addr_lctx;
3198c2ecf20Sopenharmony_ci	u32 addr_local_rec_buffer;
3208c2ecf20Sopenharmony_ci	u32 addr_spatial_context;
3218c2ecf20Sopenharmony_ci	u16 bitstream_offset;
3228c2ecf20Sopenharmony_ci	u16 sampling_mode;
3238c2ecf20Sopenharmony_ci	u32 addr_param_out;
3248c2ecf20Sopenharmony_ci	u32 addr_scaling_matrix;
3258c2ecf20Sopenharmony_ci	u32 addr_scaling_matrix_dir;
3268c2ecf20Sopenharmony_ci	u32 addr_cabac_context_buffer;
3278c2ecf20Sopenharmony_ci	u32 reserved3;
3288c2ecf20Sopenharmony_ci	u32 reserved4;
3298c2ecf20Sopenharmony_ci	s16 gmv_x;
3308c2ecf20Sopenharmony_ci	s16 gmv_y;
3318c2ecf20Sopenharmony_ci	u16 window_width;
3328c2ecf20Sopenharmony_ci	u16 window_height;
3338c2ecf20Sopenharmony_ci	u16 window_horizontal_offset;
3348c2ecf20Sopenharmony_ci	u16 window_vertical_offset;
3358c2ecf20Sopenharmony_ci	u32 addr_roi;
3368c2ecf20Sopenharmony_ci	u32 addr_slice_header;
3378c2ecf20Sopenharmony_ci	u16 slice_header_size_in_bits;
3388c2ecf20Sopenharmony_ci	u16 slice_header_offset0;
3398c2ecf20Sopenharmony_ci	u16 slice_header_offset1;
3408c2ecf20Sopenharmony_ci	u16 slice_header_offset2;
3418c2ecf20Sopenharmony_ci	u32 reserved5;
3428c2ecf20Sopenharmony_ci	u32 reserved6;
3438c2ecf20Sopenharmony_ci	u16 reserved7;
3448c2ecf20Sopenharmony_ci	u16 reserved8;
3458c2ecf20Sopenharmony_ci	u16 slice_synchro_enable;
3468c2ecf20Sopenharmony_ci	u16 max_slice_number;
3478c2ecf20Sopenharmony_ci	u32 rgb2_yuv_y_coeff;
3488c2ecf20Sopenharmony_ci	u32 rgb2_yuv_u_coeff;
3498c2ecf20Sopenharmony_ci	u32 rgb2_yuv_v_coeff;
3508c2ecf20Sopenharmony_ci	u32 slice_byte_size;
3518c2ecf20Sopenharmony_ci	u16 max_air_intra_mb_nb;
3528c2ecf20Sopenharmony_ci	u16 brc_no_skip;
3538c2ecf20Sopenharmony_ci	u32 addr_temporal_context;
3548c2ecf20Sopenharmony_ci	u32 addr_brc_in_out_parameter;
3558c2ecf20Sopenharmony_ci};
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci/*
3588c2ecf20Sopenharmony_ci * struct hva_h264_slice_po
3598c2ecf20Sopenharmony_ci *
3608c2ecf20Sopenharmony_ci * @ slice_size: slice size
3618c2ecf20Sopenharmony_ci * @ slice_start_time: start time
3628c2ecf20Sopenharmony_ci * @ slice_stop_time: stop time
3638c2ecf20Sopenharmony_ci * @ slice_num: slice number
3648c2ecf20Sopenharmony_ci */
3658c2ecf20Sopenharmony_cistruct hva_h264_slice_po {
3668c2ecf20Sopenharmony_ci	u32 slice_size;
3678c2ecf20Sopenharmony_ci	u32 slice_start_time;
3688c2ecf20Sopenharmony_ci	u32 slice_end_time;
3698c2ecf20Sopenharmony_ci	u32 slice_num;
3708c2ecf20Sopenharmony_ci};
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci/*
3738c2ecf20Sopenharmony_ci * struct hva_h264_po
3748c2ecf20Sopenharmony_ci *
3758c2ecf20Sopenharmony_ci * @ bitstream_size: bitstream size
3768c2ecf20Sopenharmony_ci * @ dct_bitstream_size: dtc bitstream size
3778c2ecf20Sopenharmony_ci * @ stuffing_bits: number of stuffing bits inserted by the encoder
3788c2ecf20Sopenharmony_ci * @ removal_time: removal time of current frame (nb of ticks 1/framerate)
3798c2ecf20Sopenharmony_ci * @ hvc_start_time: hvc start time
3808c2ecf20Sopenharmony_ci * @ hvc_stop_time: hvc stop time
3818c2ecf20Sopenharmony_ci * @ slice_count: slice count
3828c2ecf20Sopenharmony_ci */
3838c2ecf20Sopenharmony_cistruct hva_h264_po {
3848c2ecf20Sopenharmony_ci	u32 bitstream_size;
3858c2ecf20Sopenharmony_ci	u32 dct_bitstream_size;
3868c2ecf20Sopenharmony_ci	u32 stuffing_bits;
3878c2ecf20Sopenharmony_ci	u32 removal_time;
3888c2ecf20Sopenharmony_ci	u32 hvc_start_time;
3898c2ecf20Sopenharmony_ci	u32 hvc_stop_time;
3908c2ecf20Sopenharmony_ci	u32 slice_count;
3918c2ecf20Sopenharmony_ci	u32 reserved0;
3928c2ecf20Sopenharmony_ci	struct hva_h264_slice_po slice_params[16];
3938c2ecf20Sopenharmony_ci};
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_cistruct hva_h264_task {
3968c2ecf20Sopenharmony_ci	struct hva_h264_td td;
3978c2ecf20Sopenharmony_ci	struct hva_h264_po po;
3988c2ecf20Sopenharmony_ci};
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci/*
4018c2ecf20Sopenharmony_ci * struct hva_h264_ctx
4028c2ecf20Sopenharmony_ci *
4038c2ecf20Sopenharmony_ci * @seq_info:  sequence information buffer
4048c2ecf20Sopenharmony_ci * @ref_frame: reference frame buffer
4058c2ecf20Sopenharmony_ci * @rec_frame: reconstructed frame buffer
4068c2ecf20Sopenharmony_ci * @task:      task descriptor
4078c2ecf20Sopenharmony_ci */
4088c2ecf20Sopenharmony_cistruct hva_h264_ctx {
4098c2ecf20Sopenharmony_ci	struct hva_buffer *seq_info;
4108c2ecf20Sopenharmony_ci	struct hva_buffer *ref_frame;
4118c2ecf20Sopenharmony_ci	struct hva_buffer *rec_frame;
4128c2ecf20Sopenharmony_ci	struct hva_buffer *task;
4138c2ecf20Sopenharmony_ci};
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cistatic int hva_h264_fill_slice_header(struct hva_ctx *pctx,
4168c2ecf20Sopenharmony_ci				      u8 *slice_header_addr,
4178c2ecf20Sopenharmony_ci				      struct hva_controls *ctrls,
4188c2ecf20Sopenharmony_ci				      int frame_num,
4198c2ecf20Sopenharmony_ci				      u16 *header_size,
4208c2ecf20Sopenharmony_ci				      u16 *header_offset0,
4218c2ecf20Sopenharmony_ci				      u16 *header_offset1,
4228c2ecf20Sopenharmony_ci				      u16 *header_offset2)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	/*
4258c2ecf20Sopenharmony_ci	 * with this HVA hardware version, part of the slice header is computed
4268c2ecf20Sopenharmony_ci	 * on host and part by hardware.
4278c2ecf20Sopenharmony_ci	 * The part of host is precomputed and available through this array.
4288c2ecf20Sopenharmony_ci	 */
4298c2ecf20Sopenharmony_ci	struct device *dev = ctx_to_dev(pctx);
4308c2ecf20Sopenharmony_ci	int  cabac = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
4318c2ecf20Sopenharmony_ci	const unsigned char slice_header[] = { 0x00, 0x00, 0x00, 0x01,
4328c2ecf20Sopenharmony_ci					       0x41, 0x34, 0x07, 0x00};
4338c2ecf20Sopenharmony_ci	int idr_pic_id = frame_num % 2;
4348c2ecf20Sopenharmony_ci	enum hva_picture_coding_type type;
4358c2ecf20Sopenharmony_ci	u32 frame_order = frame_num % ctrls->gop_size;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	if (!(frame_num % ctrls->gop_size))
4388c2ecf20Sopenharmony_ci		type = PICTURE_CODING_TYPE_I;
4398c2ecf20Sopenharmony_ci	else
4408c2ecf20Sopenharmony_ci		type = PICTURE_CODING_TYPE_P;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	memcpy(slice_header_addr, slice_header, sizeof(slice_header));
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	*header_size = 56;
4458c2ecf20Sopenharmony_ci	*header_offset0 = 40;
4468c2ecf20Sopenharmony_ci	*header_offset1 = 13;
4478c2ecf20Sopenharmony_ci	*header_offset2 = 0;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	if (type == PICTURE_CODING_TYPE_I) {
4508c2ecf20Sopenharmony_ci		slice_header_addr[4] = 0x65;
4518c2ecf20Sopenharmony_ci		slice_header_addr[5] = 0x11;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci		/* toggle the I frame */
4548c2ecf20Sopenharmony_ci		if ((frame_num / ctrls->gop_size) % 2) {
4558c2ecf20Sopenharmony_ci			*header_size += 4;
4568c2ecf20Sopenharmony_ci			*header_offset1 += 4;
4578c2ecf20Sopenharmony_ci			slice_header_addr[6] = 0x04;
4588c2ecf20Sopenharmony_ci			slice_header_addr[7] = 0x70;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci		} else {
4618c2ecf20Sopenharmony_ci			*header_size += 2;
4628c2ecf20Sopenharmony_ci			*header_offset1 += 2;
4638c2ecf20Sopenharmony_ci			slice_header_addr[6] = 0x09;
4648c2ecf20Sopenharmony_ci			slice_header_addr[7] = 0xC0;
4658c2ecf20Sopenharmony_ci		}
4668c2ecf20Sopenharmony_ci	} else {
4678c2ecf20Sopenharmony_ci		if (ctrls->entropy_mode == cabac) {
4688c2ecf20Sopenharmony_ci			*header_size += 1;
4698c2ecf20Sopenharmony_ci			*header_offset1 += 1;
4708c2ecf20Sopenharmony_ci			slice_header_addr[7] = 0x80;
4718c2ecf20Sopenharmony_ci		}
4728c2ecf20Sopenharmony_ci		/*
4738c2ecf20Sopenharmony_ci		 * update slice header with P frame order
4748c2ecf20Sopenharmony_ci		 * frame order is limited to 16 (coded on 4bits only)
4758c2ecf20Sopenharmony_ci		 */
4768c2ecf20Sopenharmony_ci		slice_header_addr[5] += ((frame_order & 0x0C) >> 2);
4778c2ecf20Sopenharmony_ci		slice_header_addr[6] += ((frame_order & 0x03) << 6);
4788c2ecf20Sopenharmony_ci	}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	dev_dbg(dev,
4818c2ecf20Sopenharmony_ci		"%s   %s slice header order %d idrPicId %d header size %d\n",
4828c2ecf20Sopenharmony_ci		pctx->name, __func__, frame_order, idr_pic_id, *header_size);
4838c2ecf20Sopenharmony_ci	return 0;
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_cistatic int hva_h264_fill_data_nal(struct hva_ctx *pctx,
4878c2ecf20Sopenharmony_ci				  unsigned int stuffing_bytes, u8 *addr,
4888c2ecf20Sopenharmony_ci				  unsigned int stream_size, unsigned int *size)
4898c2ecf20Sopenharmony_ci{
4908c2ecf20Sopenharmony_ci	struct device *dev = ctx_to_dev(pctx);
4918c2ecf20Sopenharmony_ci	const u8 start[] = { 0x00, 0x00, 0x00, 0x01 };
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s   %s stuffing bytes %d\n", pctx->name, __func__,
4948c2ecf20Sopenharmony_ci		stuffing_bytes);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	if ((*size + stuffing_bytes + H264_FILLER_DATA_SIZE) > stream_size) {
4978c2ecf20Sopenharmony_ci		dev_dbg(dev, "%s   %s too many stuffing bytes %d\n",
4988c2ecf20Sopenharmony_ci			pctx->name, __func__, stuffing_bytes);
4998c2ecf20Sopenharmony_ci		return 0;
5008c2ecf20Sopenharmony_ci	}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	/* start code */
5038c2ecf20Sopenharmony_ci	memcpy(addr + *size, start, sizeof(start));
5048c2ecf20Sopenharmony_ci	*size += sizeof(start);
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	/* nal_unit_type */
5078c2ecf20Sopenharmony_ci	addr[*size] = NALU_TYPE_FILLER_DATA;
5088c2ecf20Sopenharmony_ci	*size += 1;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	memset(addr + *size, 0xff, stuffing_bytes);
5118c2ecf20Sopenharmony_ci	*size += stuffing_bytes;
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	addr[*size] = 0x80;
5148c2ecf20Sopenharmony_ci	*size += 1;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	return 0;
5178c2ecf20Sopenharmony_ci}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_cistatic int hva_h264_fill_sei_nal(struct hva_ctx *pctx,
5208c2ecf20Sopenharmony_ci				 enum hva_h264_sei_payload_type type,
5218c2ecf20Sopenharmony_ci				 u8 *addr, u32 *size)
5228c2ecf20Sopenharmony_ci{
5238c2ecf20Sopenharmony_ci	struct device *dev = ctx_to_dev(pctx);
5248c2ecf20Sopenharmony_ci	const u8 start[] = { 0x00, 0x00, 0x00, 0x01 };
5258c2ecf20Sopenharmony_ci	struct hva_h264_stereo_video_sei info;
5268c2ecf20Sopenharmony_ci	u8 offset = 7;
5278c2ecf20Sopenharmony_ci	u8 msg = 0;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	/* start code */
5308c2ecf20Sopenharmony_ci	memcpy(addr + *size, start, sizeof(start));
5318c2ecf20Sopenharmony_ci	*size += sizeof(start);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	/* nal_unit_type */
5348c2ecf20Sopenharmony_ci	addr[*size] = NALU_TYPE_SEI;
5358c2ecf20Sopenharmony_ci	*size += 1;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	/* payload type */
5388c2ecf20Sopenharmony_ci	addr[*size] = type;
5398c2ecf20Sopenharmony_ci	*size += 1;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	switch (type) {
5428c2ecf20Sopenharmony_ci	case SEI_STEREO_VIDEO_INFO:
5438c2ecf20Sopenharmony_ci		memset(&info, 0, sizeof(info));
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci		/* set to top/bottom frame packing arrangement */
5468c2ecf20Sopenharmony_ci		info.field_views_flag = 1;
5478c2ecf20Sopenharmony_ci		info.top_field_is_left_view_flag = 1;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci		/* payload size */
5508c2ecf20Sopenharmony_ci		addr[*size] = 1;
5518c2ecf20Sopenharmony_ci		*size += 1;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci		/* payload */
5548c2ecf20Sopenharmony_ci		msg = info.field_views_flag << offset--;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci		if (info.field_views_flag) {
5578c2ecf20Sopenharmony_ci			msg |= info.top_field_is_left_view_flag <<
5588c2ecf20Sopenharmony_ci			       offset--;
5598c2ecf20Sopenharmony_ci		} else {
5608c2ecf20Sopenharmony_ci			msg |= info.current_frame_is_left_view_flag <<
5618c2ecf20Sopenharmony_ci			       offset--;
5628c2ecf20Sopenharmony_ci			msg |= info.next_frame_is_second_view_flag <<
5638c2ecf20Sopenharmony_ci			       offset--;
5648c2ecf20Sopenharmony_ci		}
5658c2ecf20Sopenharmony_ci		msg |= info.left_view_self_contained_flag << offset--;
5668c2ecf20Sopenharmony_ci		msg |= info.right_view_self_contained_flag << offset--;
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci		addr[*size] = msg;
5698c2ecf20Sopenharmony_ci		*size += 1;
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci		addr[*size] = 0x80;
5728c2ecf20Sopenharmony_ci		*size += 1;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci		return 0;
5758c2ecf20Sopenharmony_ci	case SEI_BUFFERING_PERIOD:
5768c2ecf20Sopenharmony_ci	case SEI_PICTURE_TIMING:
5778c2ecf20Sopenharmony_ci	case SEI_FRAME_PACKING_ARRANGEMENT:
5788c2ecf20Sopenharmony_ci	default:
5798c2ecf20Sopenharmony_ci		dev_err(dev, "%s   sei nal type not supported %d\n",
5808c2ecf20Sopenharmony_ci			pctx->name, type);
5818c2ecf20Sopenharmony_ci		return -EINVAL;
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ci}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_cistatic int hva_h264_prepare_task(struct hva_ctx *pctx,
5868c2ecf20Sopenharmony_ci				 struct hva_h264_task *task,
5878c2ecf20Sopenharmony_ci				 struct hva_frame *frame,
5888c2ecf20Sopenharmony_ci				 struct hva_stream *stream)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	struct hva_dev *hva = ctx_to_hdev(pctx);
5918c2ecf20Sopenharmony_ci	struct device *dev = ctx_to_dev(pctx);
5928c2ecf20Sopenharmony_ci	struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv;
5938c2ecf20Sopenharmony_ci	struct hva_buffer *seq_info = ctx->seq_info;
5948c2ecf20Sopenharmony_ci	struct hva_buffer *fwd_ref_frame = ctx->ref_frame;
5958c2ecf20Sopenharmony_ci	struct hva_buffer *loc_rec_frame = ctx->rec_frame;
5968c2ecf20Sopenharmony_ci	struct hva_h264_td *td = &task->td;
5978c2ecf20Sopenharmony_ci	struct hva_controls *ctrls = &pctx->ctrls;
5988c2ecf20Sopenharmony_ci	struct v4l2_fract *time_per_frame = &pctx->ctrls.time_per_frame;
5998c2ecf20Sopenharmony_ci	int cavlc =  V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
6008c2ecf20Sopenharmony_ci	u32 frame_num = pctx->stream_num;
6018c2ecf20Sopenharmony_ci	u32 addr_esram = hva->esram_addr;
6028c2ecf20Sopenharmony_ci	enum v4l2_mpeg_video_h264_level level;
6038c2ecf20Sopenharmony_ci	dma_addr_t paddr = 0;
6048c2ecf20Sopenharmony_ci	u8 *slice_header_vaddr;
6058c2ecf20Sopenharmony_ci	u32 frame_width = frame->info.aligned_width;
6068c2ecf20Sopenharmony_ci	u32 frame_height = frame->info.aligned_height;
6078c2ecf20Sopenharmony_ci	u32 max_cpb_buffer_size;
6088c2ecf20Sopenharmony_ci	unsigned int payload = stream->bytesused;
6098c2ecf20Sopenharmony_ci	u32 max_bitrate;
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	/* check width and height parameters */
6128c2ecf20Sopenharmony_ci	if ((frame_width > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H)) ||
6138c2ecf20Sopenharmony_ci	    (frame_height > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H))) {
6148c2ecf20Sopenharmony_ci		dev_err(dev,
6158c2ecf20Sopenharmony_ci			"%s   width(%d) or height(%d) exceeds limits (%dx%d)\n",
6168c2ecf20Sopenharmony_ci			pctx->name, frame_width, frame_height,
6178c2ecf20Sopenharmony_ci			H264_MAX_SIZE_W, H264_MAX_SIZE_H);
6188c2ecf20Sopenharmony_ci		pctx->frame_errors++;
6198c2ecf20Sopenharmony_ci		return -EINVAL;
6208c2ecf20Sopenharmony_ci	}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	level = ctrls->level;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	memset(td, 0, sizeof(struct hva_h264_td));
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	td->frame_width = frame_width;
6278c2ecf20Sopenharmony_ci	td->frame_height = frame_height;
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	/* set frame alignment */
6308c2ecf20Sopenharmony_ci	td->window_width =  frame_width;
6318c2ecf20Sopenharmony_ci	td->window_height = frame_height;
6328c2ecf20Sopenharmony_ci	td->window_horizontal_offset = 0;
6338c2ecf20Sopenharmony_ci	td->window_vertical_offset = 0;
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	td->first_picture_in_sequence = (!frame_num) ? 1 : 0;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	/* pic_order_cnt_type hard coded to '2' as only I & P frames */
6388c2ecf20Sopenharmony_ci	td->pic_order_cnt_type = 2;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	/* useConstrainedIntraFlag set to false for better coding efficiency */
6418c2ecf20Sopenharmony_ci	td->use_constrained_intra_flag = false;
6428c2ecf20Sopenharmony_ci	td->brc_type = (ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
6438c2ecf20Sopenharmony_ci			? BRC_TYPE_CBR : BRC_TYPE_VBR;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	td->entropy_coding_mode = (ctrls->entropy_mode == cavlc) ? CAVLC :
6468c2ecf20Sopenharmony_ci				  CABAC;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	td->bit_rate = ctrls->bitrate;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	/* set framerate, framerate = 1 n/ time per frame */
6518c2ecf20Sopenharmony_ci	if (time_per_frame->numerator >= 536) {
6528c2ecf20Sopenharmony_ci		/*
6538c2ecf20Sopenharmony_ci		 * due to a hardware bug, framerate denominator can't exceed
6548c2ecf20Sopenharmony_ci		 * 536 (BRC overflow). Compute nearest framerate
6558c2ecf20Sopenharmony_ci		 */
6568c2ecf20Sopenharmony_ci		td->framerate_den = 1;
6578c2ecf20Sopenharmony_ci		td->framerate_num = (time_per_frame->denominator +
6588c2ecf20Sopenharmony_ci				    (time_per_frame->numerator >> 1) - 1) /
6598c2ecf20Sopenharmony_ci				    time_per_frame->numerator;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci		/*
6628c2ecf20Sopenharmony_ci		 * update bitrate to introduce a correction due to
6638c2ecf20Sopenharmony_ci		 * the new framerate
6648c2ecf20Sopenharmony_ci		 * new bitrate = (old bitrate * new framerate) / old framerate
6658c2ecf20Sopenharmony_ci		 */
6668c2ecf20Sopenharmony_ci		td->bit_rate /= time_per_frame->numerator;
6678c2ecf20Sopenharmony_ci		td->bit_rate *= time_per_frame->denominator;
6688c2ecf20Sopenharmony_ci		td->bit_rate /= td->framerate_num;
6698c2ecf20Sopenharmony_ci	} else {
6708c2ecf20Sopenharmony_ci		td->framerate_den = time_per_frame->numerator;
6718c2ecf20Sopenharmony_ci		td->framerate_num = time_per_frame->denominator;
6728c2ecf20Sopenharmony_ci	}
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	/* compute maximum bitrate depending on profile */
6758c2ecf20Sopenharmony_ci	if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)
6768c2ecf20Sopenharmony_ci		max_bitrate = h264_infos_list[level].max_bitrate *
6778c2ecf20Sopenharmony_ci			      H264_FACTOR_HIGH;
6788c2ecf20Sopenharmony_ci	else
6798c2ecf20Sopenharmony_ci		max_bitrate = h264_infos_list[level].max_bitrate *
6808c2ecf20Sopenharmony_ci			      H264_FACTOR_BASELINE;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	/* check if bitrate doesn't exceed max size */
6838c2ecf20Sopenharmony_ci	if (td->bit_rate > max_bitrate) {
6848c2ecf20Sopenharmony_ci		dev_dbg(dev,
6858c2ecf20Sopenharmony_ci			"%s   bitrate (%d) larger than level and profile allow, clip to %d\n",
6868c2ecf20Sopenharmony_ci			pctx->name, td->bit_rate, max_bitrate);
6878c2ecf20Sopenharmony_ci		td->bit_rate = max_bitrate;
6888c2ecf20Sopenharmony_ci	}
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	/* convert cpb_buffer_size in bits */
6918c2ecf20Sopenharmony_ci	td->cpb_buffer_size = ctrls->cpb_size * 8000;
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	/* compute maximum cpb buffer size depending on profile */
6948c2ecf20Sopenharmony_ci	if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)
6958c2ecf20Sopenharmony_ci		max_cpb_buffer_size =
6968c2ecf20Sopenharmony_ci		    h264_infos_list[level].max_cpb_size * H264_FACTOR_HIGH;
6978c2ecf20Sopenharmony_ci	else
6988c2ecf20Sopenharmony_ci		max_cpb_buffer_size =
6998c2ecf20Sopenharmony_ci		    h264_infos_list[level].max_cpb_size * H264_FACTOR_BASELINE;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	/* check if cpb buffer size doesn't exceed max size */
7028c2ecf20Sopenharmony_ci	if (td->cpb_buffer_size > max_cpb_buffer_size) {
7038c2ecf20Sopenharmony_ci		dev_dbg(dev,
7048c2ecf20Sopenharmony_ci			"%s   cpb size larger than level %d allows, clip to %d\n",
7058c2ecf20Sopenharmony_ci			pctx->name, td->cpb_buffer_size, max_cpb_buffer_size);
7068c2ecf20Sopenharmony_ci		td->cpb_buffer_size = max_cpb_buffer_size;
7078c2ecf20Sopenharmony_ci	}
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	/* enable skipping in the Bitrate Controller */
7108c2ecf20Sopenharmony_ci	td->brc_no_skip = 0;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	/* initial delay */
7138c2ecf20Sopenharmony_ci	if ((ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) &&
7148c2ecf20Sopenharmony_ci	    td->bit_rate)
7158c2ecf20Sopenharmony_ci		td->delay = 1000 * (td->cpb_buffer_size / td->bit_rate);
7168c2ecf20Sopenharmony_ci	else
7178c2ecf20Sopenharmony_ci		td->delay = 0;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	switch (frame->info.pixelformat) {
7208c2ecf20Sopenharmony_ci	case V4L2_PIX_FMT_NV12:
7218c2ecf20Sopenharmony_ci		td->sampling_mode = SAMPLING_MODE_NV12;
7228c2ecf20Sopenharmony_ci		break;
7238c2ecf20Sopenharmony_ci	case V4L2_PIX_FMT_NV21:
7248c2ecf20Sopenharmony_ci		td->sampling_mode = SAMPLING_MODE_NV21;
7258c2ecf20Sopenharmony_ci		break;
7268c2ecf20Sopenharmony_ci	default:
7278c2ecf20Sopenharmony_ci		dev_err(dev, "%s   invalid source pixel format\n",
7288c2ecf20Sopenharmony_ci			pctx->name);
7298c2ecf20Sopenharmony_ci		pctx->frame_errors++;
7308c2ecf20Sopenharmony_ci		return -EINVAL;
7318c2ecf20Sopenharmony_ci	}
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	/*
7348c2ecf20Sopenharmony_ci	 * fill matrix color converter (RGB to YUV)
7358c2ecf20Sopenharmony_ci	 * Y = 0,299 R + 0,587 G + 0,114 B
7368c2ecf20Sopenharmony_ci	 * Cb = -0,1687 R -0,3313 G + 0,5 B + 128
7378c2ecf20Sopenharmony_ci	 * Cr = 0,5 R - 0,4187 G - 0,0813 B + 128
7388c2ecf20Sopenharmony_ci	 */
7398c2ecf20Sopenharmony_ci	td->rgb2_yuv_y_coeff = 0x12031008;
7408c2ecf20Sopenharmony_ci	td->rgb2_yuv_u_coeff = 0x800EF7FB;
7418c2ecf20Sopenharmony_ci	td->rgb2_yuv_v_coeff = 0x80FEF40E;
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	/* enable/disable transform mode */
7448c2ecf20Sopenharmony_ci	td->transform_mode = ctrls->dct8x8;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	/* encoder complexity fix to 2, ENCODE_I_16x16_I_NxN_P_16x16_P_WxH */
7478c2ecf20Sopenharmony_ci	td->encoder_complexity = 2;
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	/* quant fix to 28, default VBR value */
7508c2ecf20Sopenharmony_ci	td->quant = 28;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	if (td->framerate_den == 0) {
7538c2ecf20Sopenharmony_ci		dev_err(dev, "%s   invalid framerate\n", pctx->name);
7548c2ecf20Sopenharmony_ci		pctx->frame_errors++;
7558c2ecf20Sopenharmony_ci		return -EINVAL;
7568c2ecf20Sopenharmony_ci	}
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	/* if automatic framerate, deactivate bitrate controller */
7598c2ecf20Sopenharmony_ci	if (td->framerate_num == 0)
7608c2ecf20Sopenharmony_ci		td->brc_type = 0;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	/* compliancy fix to true */
7638c2ecf20Sopenharmony_ci	td->strict_hrd_compliancy = 1;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	/* set minimum & maximum quantizers */
7668c2ecf20Sopenharmony_ci	td->qp_min = clamp_val(ctrls->qpmin, 0, 51);
7678c2ecf20Sopenharmony_ci	td->qp_max = clamp_val(ctrls->qpmax, 0, 51);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	td->addr_source_buffer = frame->paddr;
7708c2ecf20Sopenharmony_ci	td->addr_fwd_ref_buffer = fwd_ref_frame->paddr;
7718c2ecf20Sopenharmony_ci	td->addr_rec_buffer = loc_rec_frame->paddr;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	td->addr_output_bitstream_end = (u32)stream->paddr + stream->size;
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	td->addr_output_bitstream_start = (u32)stream->paddr;
7768c2ecf20Sopenharmony_ci	td->bitstream_offset = (((u32)stream->paddr & 0xF) << 3) &
7778c2ecf20Sopenharmony_ci			       BITSTREAM_OFFSET_MASK;
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	td->addr_param_out = (u32)ctx->task->paddr +
7808c2ecf20Sopenharmony_ci			     offsetof(struct hva_h264_task, po);
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	/* swap spatial and temporal context */
7838c2ecf20Sopenharmony_ci	if (frame_num % 2) {
7848c2ecf20Sopenharmony_ci		paddr = seq_info->paddr;
7858c2ecf20Sopenharmony_ci		td->addr_spatial_context =  ALIGN(paddr, 0x100);
7868c2ecf20Sopenharmony_ci		paddr = seq_info->paddr + DATA_SIZE(frame_width,
7878c2ecf20Sopenharmony_ci							frame_height);
7888c2ecf20Sopenharmony_ci		td->addr_temporal_context = ALIGN(paddr, 0x100);
7898c2ecf20Sopenharmony_ci	} else {
7908c2ecf20Sopenharmony_ci		paddr = seq_info->paddr;
7918c2ecf20Sopenharmony_ci		td->addr_temporal_context = ALIGN(paddr, 0x100);
7928c2ecf20Sopenharmony_ci		paddr = seq_info->paddr + DATA_SIZE(frame_width,
7938c2ecf20Sopenharmony_ci							frame_height);
7948c2ecf20Sopenharmony_ci		td->addr_spatial_context =  ALIGN(paddr, 0x100);
7958c2ecf20Sopenharmony_ci	}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	paddr = seq_info->paddr + 2 * DATA_SIZE(frame_width, frame_height);
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	td->addr_brc_in_out_parameter =  ALIGN(paddr, 0x100);
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	paddr = td->addr_brc_in_out_parameter + BRC_DATA_SIZE;
8028c2ecf20Sopenharmony_ci	td->addr_slice_header =  ALIGN(paddr, 0x100);
8038c2ecf20Sopenharmony_ci	td->addr_external_sw =  ALIGN(addr_esram, 0x100);
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	addr_esram += SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width);
8068c2ecf20Sopenharmony_ci	td->addr_local_rec_buffer = ALIGN(addr_esram, 0x100);
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	addr_esram += LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width);
8098c2ecf20Sopenharmony_ci	td->addr_lctx = ALIGN(addr_esram, 0x100);
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	addr_esram += CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height));
8128c2ecf20Sopenharmony_ci	td->addr_cabac_context_buffer = ALIGN(addr_esram, 0x100);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	if (!(frame_num % ctrls->gop_size)) {
8158c2ecf20Sopenharmony_ci		td->picture_coding_type = PICTURE_CODING_TYPE_I;
8168c2ecf20Sopenharmony_ci		stream->vbuf.flags |= V4L2_BUF_FLAG_KEYFRAME;
8178c2ecf20Sopenharmony_ci	} else {
8188c2ecf20Sopenharmony_ci		td->picture_coding_type = PICTURE_CODING_TYPE_P;
8198c2ecf20Sopenharmony_ci		stream->vbuf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
8208c2ecf20Sopenharmony_ci	}
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	/* fill the slice header part */
8238c2ecf20Sopenharmony_ci	slice_header_vaddr = seq_info->vaddr + (td->addr_slice_header -
8248c2ecf20Sopenharmony_ci			     seq_info->paddr);
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	hva_h264_fill_slice_header(pctx, slice_header_vaddr, ctrls, frame_num,
8278c2ecf20Sopenharmony_ci				   &td->slice_header_size_in_bits,
8288c2ecf20Sopenharmony_ci				   &td->slice_header_offset0,
8298c2ecf20Sopenharmony_ci				   &td->slice_header_offset1,
8308c2ecf20Sopenharmony_ci				   &td->slice_header_offset2);
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	td->chroma_qp_index_offset = 2;
8338c2ecf20Sopenharmony_ci	td->slice_synchro_enable = 0;
8348c2ecf20Sopenharmony_ci	td->max_slice_number = 1;
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	/*
8378c2ecf20Sopenharmony_ci	 * check the sps/pps header size for key frame only
8388c2ecf20Sopenharmony_ci	 * sps/pps header was previously fill by libv4l
8398c2ecf20Sopenharmony_ci	 * during qbuf of stream buffer
8408c2ecf20Sopenharmony_ci	 */
8418c2ecf20Sopenharmony_ci	if ((stream->vbuf.flags == V4L2_BUF_FLAG_KEYFRAME) &&
8428c2ecf20Sopenharmony_ci	    (payload > MAX_SPS_PPS_SIZE)) {
8438c2ecf20Sopenharmony_ci		dev_err(dev, "%s   invalid sps/pps size %d\n", pctx->name,
8448c2ecf20Sopenharmony_ci			payload);
8458c2ecf20Sopenharmony_ci		pctx->frame_errors++;
8468c2ecf20Sopenharmony_ci		return -EINVAL;
8478c2ecf20Sopenharmony_ci	}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (stream->vbuf.flags != V4L2_BUF_FLAG_KEYFRAME)
8508c2ecf20Sopenharmony_ci		payload = 0;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	/* add SEI nal (video stereo info) */
8538c2ecf20Sopenharmony_ci	if (ctrls->sei_fp && hva_h264_fill_sei_nal(pctx, SEI_STEREO_VIDEO_INFO,
8548c2ecf20Sopenharmony_ci						   (u8 *)stream->vaddr,
8558c2ecf20Sopenharmony_ci						   &payload)) {
8568c2ecf20Sopenharmony_ci		dev_err(dev, "%s   fail to get SEI nal\n", pctx->name);
8578c2ecf20Sopenharmony_ci		pctx->frame_errors++;
8588c2ecf20Sopenharmony_ci		return -EINVAL;
8598c2ecf20Sopenharmony_ci	}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	/* fill size of non-VCL NAL units (SPS, PPS, filler and SEI) */
8628c2ecf20Sopenharmony_ci	td->non_vcl_nalu_size = payload * 8;
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	/* compute bitstream offset & new start address of bitstream */
8658c2ecf20Sopenharmony_ci	td->addr_output_bitstream_start += ((payload >> 4) << 4);
8668c2ecf20Sopenharmony_ci	td->bitstream_offset += (payload - ((payload >> 4) << 4)) * 8;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	stream->bytesused = payload;
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci	return 0;
8718c2ecf20Sopenharmony_ci}
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_cistatic unsigned int hva_h264_get_stream_size(struct hva_h264_task *task)
8748c2ecf20Sopenharmony_ci{
8758c2ecf20Sopenharmony_ci	struct hva_h264_po *po = &task->po;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	return po->bitstream_size;
8788c2ecf20Sopenharmony_ci}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_cistatic u32 hva_h264_get_stuffing_bytes(struct hva_h264_task *task)
8818c2ecf20Sopenharmony_ci{
8828c2ecf20Sopenharmony_ci	struct hva_h264_po *po = &task->po;
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_ci	return po->stuffing_bits >> 3;
8858c2ecf20Sopenharmony_ci}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_cistatic int hva_h264_open(struct hva_ctx *pctx)
8888c2ecf20Sopenharmony_ci{
8898c2ecf20Sopenharmony_ci	struct device *dev = ctx_to_dev(pctx);
8908c2ecf20Sopenharmony_ci	struct hva_h264_ctx *ctx;
8918c2ecf20Sopenharmony_ci	struct hva_dev *hva = ctx_to_hdev(pctx);
8928c2ecf20Sopenharmony_ci	u32 frame_width = pctx->frameinfo.aligned_width;
8938c2ecf20Sopenharmony_ci	u32 frame_height = pctx->frameinfo.aligned_height;
8948c2ecf20Sopenharmony_ci	u32 size;
8958c2ecf20Sopenharmony_ci	int ret;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	/* check esram size necessary to encode a frame */
8988c2ecf20Sopenharmony_ci	size = SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width) +
8998c2ecf20Sopenharmony_ci	       LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width) +
9008c2ecf20Sopenharmony_ci	       CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height)) +
9018c2ecf20Sopenharmony_ci	       CABAC_CONTEXT_BUFFER_MAX_SIZE(frame_width);
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	if (hva->esram_size < size) {
9048c2ecf20Sopenharmony_ci		dev_err(dev, "%s   not enough esram (max:%d request:%d)\n",
9058c2ecf20Sopenharmony_ci			pctx->name, hva->esram_size, size);
9068c2ecf20Sopenharmony_ci		ret = -EINVAL;
9078c2ecf20Sopenharmony_ci		goto err;
9088c2ecf20Sopenharmony_ci	}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	/* allocate context for codec */
9118c2ecf20Sopenharmony_ci	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
9128c2ecf20Sopenharmony_ci	if (!ctx) {
9138c2ecf20Sopenharmony_ci		ret = -ENOMEM;
9148c2ecf20Sopenharmony_ci		goto err;
9158c2ecf20Sopenharmony_ci	}
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	/* allocate sequence info buffer */
9188c2ecf20Sopenharmony_ci	ret = hva_mem_alloc(pctx,
9198c2ecf20Sopenharmony_ci			    2 * DATA_SIZE(frame_width, frame_height) +
9208c2ecf20Sopenharmony_ci			    SLICE_HEADER_SIZE +
9218c2ecf20Sopenharmony_ci			    BRC_DATA_SIZE,
9228c2ecf20Sopenharmony_ci			    "hva sequence info",
9238c2ecf20Sopenharmony_ci			    &ctx->seq_info);
9248c2ecf20Sopenharmony_ci	if (ret) {
9258c2ecf20Sopenharmony_ci		dev_err(dev,
9268c2ecf20Sopenharmony_ci			"%s   failed to allocate sequence info buffer\n",
9278c2ecf20Sopenharmony_ci			pctx->name);
9288c2ecf20Sopenharmony_ci		goto err_ctx;
9298c2ecf20Sopenharmony_ci	}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	/* allocate reference frame buffer */
9328c2ecf20Sopenharmony_ci	ret = hva_mem_alloc(pctx,
9338c2ecf20Sopenharmony_ci			    frame_width * frame_height * 3 / 2,
9348c2ecf20Sopenharmony_ci			    "hva reference frame",
9358c2ecf20Sopenharmony_ci			    &ctx->ref_frame);
9368c2ecf20Sopenharmony_ci	if (ret) {
9378c2ecf20Sopenharmony_ci		dev_err(dev, "%s   failed to allocate reference frame buffer\n",
9388c2ecf20Sopenharmony_ci			pctx->name);
9398c2ecf20Sopenharmony_ci		goto err_seq_info;
9408c2ecf20Sopenharmony_ci	}
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	/* allocate reconstructed frame buffer */
9438c2ecf20Sopenharmony_ci	ret = hva_mem_alloc(pctx,
9448c2ecf20Sopenharmony_ci			    frame_width * frame_height * 3 / 2,
9458c2ecf20Sopenharmony_ci			    "hva reconstructed frame",
9468c2ecf20Sopenharmony_ci			    &ctx->rec_frame);
9478c2ecf20Sopenharmony_ci	if (ret) {
9488c2ecf20Sopenharmony_ci		dev_err(dev,
9498c2ecf20Sopenharmony_ci			"%s   failed to allocate reconstructed frame buffer\n",
9508c2ecf20Sopenharmony_ci			pctx->name);
9518c2ecf20Sopenharmony_ci		goto err_ref_frame;
9528c2ecf20Sopenharmony_ci	}
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	/* allocate task descriptor */
9558c2ecf20Sopenharmony_ci	ret = hva_mem_alloc(pctx,
9568c2ecf20Sopenharmony_ci			    sizeof(struct hva_h264_task),
9578c2ecf20Sopenharmony_ci			    "hva task descriptor",
9588c2ecf20Sopenharmony_ci			    &ctx->task);
9598c2ecf20Sopenharmony_ci	if (ret) {
9608c2ecf20Sopenharmony_ci		dev_err(dev,
9618c2ecf20Sopenharmony_ci			"%s   failed to allocate task descriptor\n",
9628c2ecf20Sopenharmony_ci			pctx->name);
9638c2ecf20Sopenharmony_ci		goto err_rec_frame;
9648c2ecf20Sopenharmony_ci	}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	pctx->priv = (void *)ctx;
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	return 0;
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_cierr_rec_frame:
9718c2ecf20Sopenharmony_ci	hva_mem_free(pctx, ctx->rec_frame);
9728c2ecf20Sopenharmony_cierr_ref_frame:
9738c2ecf20Sopenharmony_ci	hva_mem_free(pctx, ctx->ref_frame);
9748c2ecf20Sopenharmony_cierr_seq_info:
9758c2ecf20Sopenharmony_ci	hva_mem_free(pctx, ctx->seq_info);
9768c2ecf20Sopenharmony_cierr_ctx:
9778c2ecf20Sopenharmony_ci	devm_kfree(dev, ctx);
9788c2ecf20Sopenharmony_cierr:
9798c2ecf20Sopenharmony_ci	pctx->sys_errors++;
9808c2ecf20Sopenharmony_ci	return ret;
9818c2ecf20Sopenharmony_ci}
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_cistatic int hva_h264_close(struct hva_ctx *pctx)
9848c2ecf20Sopenharmony_ci{
9858c2ecf20Sopenharmony_ci	struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv;
9868c2ecf20Sopenharmony_ci	struct device *dev = ctx_to_dev(pctx);
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	if (ctx->seq_info)
9898c2ecf20Sopenharmony_ci		hva_mem_free(pctx, ctx->seq_info);
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	if (ctx->ref_frame)
9928c2ecf20Sopenharmony_ci		hva_mem_free(pctx, ctx->ref_frame);
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	if (ctx->rec_frame)
9958c2ecf20Sopenharmony_ci		hva_mem_free(pctx, ctx->rec_frame);
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	if (ctx->task)
9988c2ecf20Sopenharmony_ci		hva_mem_free(pctx, ctx->task);
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	devm_kfree(dev, ctx);
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	return 0;
10038c2ecf20Sopenharmony_ci}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_cistatic int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame,
10068c2ecf20Sopenharmony_ci			   struct hva_stream *stream)
10078c2ecf20Sopenharmony_ci{
10088c2ecf20Sopenharmony_ci	struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv;
10098c2ecf20Sopenharmony_ci	struct hva_h264_task *task = (struct hva_h264_task *)ctx->task->vaddr;
10108c2ecf20Sopenharmony_ci	u32 stuffing_bytes = 0;
10118c2ecf20Sopenharmony_ci	int ret = 0;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	ret = hva_h264_prepare_task(pctx, task, frame, stream);
10148c2ecf20Sopenharmony_ci	if (ret)
10158c2ecf20Sopenharmony_ci		goto err;
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	ret = hva_hw_execute_task(pctx, H264_ENC, ctx->task);
10188c2ecf20Sopenharmony_ci	if (ret)
10198c2ecf20Sopenharmony_ci		goto err;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	pctx->stream_num++;
10228c2ecf20Sopenharmony_ci	stream->bytesused += hva_h264_get_stream_size(task);
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	stuffing_bytes = hva_h264_get_stuffing_bytes(task);
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	if (stuffing_bytes)
10278c2ecf20Sopenharmony_ci		hva_h264_fill_data_nal(pctx, stuffing_bytes,
10288c2ecf20Sopenharmony_ci				       (u8 *)stream->vaddr,
10298c2ecf20Sopenharmony_ci				       stream->size,
10308c2ecf20Sopenharmony_ci				       &stream->bytesused);
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	/* switch reference & reconstructed frame */
10338c2ecf20Sopenharmony_ci	swap(ctx->ref_frame, ctx->rec_frame);
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	return 0;
10368c2ecf20Sopenharmony_cierr:
10378c2ecf20Sopenharmony_ci	stream->bytesused = 0;
10388c2ecf20Sopenharmony_ci	return ret;
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ciconst struct hva_enc nv12h264enc = {
10428c2ecf20Sopenharmony_ci	.name = "H264(NV12)",
10438c2ecf20Sopenharmony_ci	.pixelformat = V4L2_PIX_FMT_NV12,
10448c2ecf20Sopenharmony_ci	.streamformat = V4L2_PIX_FMT_H264,
10458c2ecf20Sopenharmony_ci	.max_width = H264_MAX_SIZE_W,
10468c2ecf20Sopenharmony_ci	.max_height = H264_MAX_SIZE_H,
10478c2ecf20Sopenharmony_ci	.open = hva_h264_open,
10488c2ecf20Sopenharmony_ci	.close = hva_h264_close,
10498c2ecf20Sopenharmony_ci	.encode = hva_h264_encode,
10508c2ecf20Sopenharmony_ci};
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ciconst struct hva_enc nv21h264enc = {
10538c2ecf20Sopenharmony_ci	.name = "H264(NV21)",
10548c2ecf20Sopenharmony_ci	.pixelformat = V4L2_PIX_FMT_NV21,
10558c2ecf20Sopenharmony_ci	.streamformat = V4L2_PIX_FMT_H264,
10568c2ecf20Sopenharmony_ci	.max_width = H264_MAX_SIZE_W,
10578c2ecf20Sopenharmony_ci	.max_height = H264_MAX_SIZE_H,
10588c2ecf20Sopenharmony_ci	.open = hva_h264_open,
10598c2ecf20Sopenharmony_ci	.close = hva_h264_close,
10608c2ecf20Sopenharmony_ci	.encode = hva_h264_encode,
10618c2ecf20Sopenharmony_ci};
1062