1e7b8153eSMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0
2e7b8153eSMauro Carvalho Chehab /*
3e7b8153eSMauro Carvalho Chehab * Copyright (C) STMicroelectronics SA 2015
4e7b8153eSMauro Carvalho Chehab * Authors: Yannick Fertre <yannick.fertre@st.com>
5e7b8153eSMauro Carvalho Chehab * Hugues Fruchet <hugues.fruchet@st.com>
6e7b8153eSMauro Carvalho Chehab */
7e7b8153eSMauro Carvalho Chehab
8e7b8153eSMauro Carvalho Chehab #include "hva.h"
9e7b8153eSMauro Carvalho Chehab #include "hva-hw.h"
10e7b8153eSMauro Carvalho Chehab
11e7b8153eSMauro Carvalho Chehab #define MAX_SPS_PPS_SIZE 128
12e7b8153eSMauro Carvalho Chehab
13e7b8153eSMauro Carvalho Chehab #define BITSTREAM_OFFSET_MASK 0x7F
14e7b8153eSMauro Carvalho Chehab
15e7b8153eSMauro Carvalho Chehab /* video max size*/
16e7b8153eSMauro Carvalho Chehab #define H264_MAX_SIZE_W 1920
17e7b8153eSMauro Carvalho Chehab #define H264_MAX_SIZE_H 1920
18e7b8153eSMauro Carvalho Chehab
19e7b8153eSMauro Carvalho Chehab /* macroBlocs number (width & height) */
20e7b8153eSMauro Carvalho Chehab #define MB_W(w) ((w + 0xF) / 0x10)
21e7b8153eSMauro Carvalho Chehab #define MB_H(h) ((h + 0xF) / 0x10)
22e7b8153eSMauro Carvalho Chehab
23e7b8153eSMauro Carvalho Chehab /* formula to get temporal or spatial data size */
24e7b8153eSMauro Carvalho Chehab #define DATA_SIZE(w, h) (MB_W(w) * MB_H(h) * 16)
25e7b8153eSMauro Carvalho Chehab
26e7b8153eSMauro Carvalho Chehab #define SEARCH_WINDOW_BUFFER_MAX_SIZE(w) ((4 * MB_W(w) + 42) * 256 * 3 / 2)
27e7b8153eSMauro Carvalho Chehab #define CABAC_CONTEXT_BUFFER_MAX_SIZE(w) (MB_W(w) * 16)
28e7b8153eSMauro Carvalho Chehab #define CTX_MB_BUFFER_MAX_SIZE(w) (MB_W(w) * 16 * 8)
29e7b8153eSMauro Carvalho Chehab #define SLICE_HEADER_SIZE (4 * 16)
30e7b8153eSMauro Carvalho Chehab #define BRC_DATA_SIZE (5 * 16)
31e7b8153eSMauro Carvalho Chehab
32e7b8153eSMauro Carvalho Chehab /* source buffer copy in YUV 420 MB-tiled format with size=16*256*3/2 */
33e7b8153eSMauro Carvalho Chehab #define CURRENT_WINDOW_BUFFER_MAX_SIZE (16 * 256 * 3 / 2)
34e7b8153eSMauro Carvalho Chehab
35e7b8153eSMauro Carvalho Chehab /*
36e7b8153eSMauro Carvalho Chehab * 4 lines of pixels (in Luma, Chroma blue and Chroma red) of top MB
37e7b8153eSMauro Carvalho Chehab * for deblocking with size=4*16*MBx*2
38e7b8153eSMauro Carvalho Chehab */
39e7b8153eSMauro Carvalho Chehab #define LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(w) (4 * 16 * MB_W(w) * 2)
40e7b8153eSMauro Carvalho Chehab
41e7b8153eSMauro Carvalho Chehab /* factor for bitrate and cpb buffer size max values if profile >= high */
42e7b8153eSMauro Carvalho Chehab #define H264_FACTOR_HIGH 1200
43e7b8153eSMauro Carvalho Chehab
44e7b8153eSMauro Carvalho Chehab /* factor for bitrate and cpb buffer size max values if profile < high */
45e7b8153eSMauro Carvalho Chehab #define H264_FACTOR_BASELINE 1000
46e7b8153eSMauro Carvalho Chehab
47e7b8153eSMauro Carvalho Chehab /* number of bytes for NALU_TYPE_FILLER_DATA header and footer */
48e7b8153eSMauro Carvalho Chehab #define H264_FILLER_DATA_SIZE 6
49e7b8153eSMauro Carvalho Chehab
50e7b8153eSMauro Carvalho Chehab struct h264_profile {
51e7b8153eSMauro Carvalho Chehab enum v4l2_mpeg_video_h264_level level;
52e7b8153eSMauro Carvalho Chehab u32 max_mb_per_seconds;
53e7b8153eSMauro Carvalho Chehab u32 max_frame_size;
54e7b8153eSMauro Carvalho Chehab u32 max_bitrate;
55e7b8153eSMauro Carvalho Chehab u32 max_cpb_size;
56e7b8153eSMauro Carvalho Chehab u32 min_comp_ratio;
57e7b8153eSMauro Carvalho Chehab };
58e7b8153eSMauro Carvalho Chehab
59e7b8153eSMauro Carvalho Chehab static const struct h264_profile h264_infos_list[] = {
60e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_1_0, 1485, 99, 64, 175, 2},
61e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_1B, 1485, 99, 128, 350, 2},
62e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_1_1, 3000, 396, 192, 500, 2},
63e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_1_2, 6000, 396, 384, 1000, 2},
64e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_1_3, 11880, 396, 768, 2000, 2},
65e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_2_0, 11880, 396, 2000, 2000, 2},
66e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_2_1, 19800, 792, 4000, 4000, 2},
67e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_2_2, 20250, 1620, 4000, 4000, 2},
68e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_3_0, 40500, 1620, 10000, 10000, 2},
69e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_3_1, 108000, 3600, 14000, 14000, 4},
70e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_3_2, 216000, 5120, 20000, 20000, 4},
71e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 245760, 8192, 20000, 25000, 4},
72e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_4_1, 245760, 8192, 50000, 62500, 2},
73e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_4_2, 522240, 8704, 50000, 62500, 2},
74e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_5_0, 589824, 22080, 135000, 135000, 2},
75e7b8153eSMauro Carvalho Chehab {V4L2_MPEG_VIDEO_H264_LEVEL_5_1, 983040, 36864, 240000, 240000, 2}
76e7b8153eSMauro Carvalho Chehab };
77e7b8153eSMauro Carvalho Chehab
78e7b8153eSMauro Carvalho Chehab enum hva_brc_type {
79e7b8153eSMauro Carvalho Chehab BRC_TYPE_NONE = 0,
80e7b8153eSMauro Carvalho Chehab BRC_TYPE_CBR = 1,
81e7b8153eSMauro Carvalho Chehab BRC_TYPE_VBR = 2,
82e7b8153eSMauro Carvalho Chehab BRC_TYPE_VBR_LOW_DELAY = 3
83e7b8153eSMauro Carvalho Chehab };
84e7b8153eSMauro Carvalho Chehab
85e7b8153eSMauro Carvalho Chehab enum hva_entropy_coding_mode {
86e7b8153eSMauro Carvalho Chehab CAVLC = 0,
87e7b8153eSMauro Carvalho Chehab CABAC = 1
88e7b8153eSMauro Carvalho Chehab };
89e7b8153eSMauro Carvalho Chehab
90e7b8153eSMauro Carvalho Chehab enum hva_picture_coding_type {
91e7b8153eSMauro Carvalho Chehab PICTURE_CODING_TYPE_I = 0,
92e7b8153eSMauro Carvalho Chehab PICTURE_CODING_TYPE_P = 1,
93e7b8153eSMauro Carvalho Chehab PICTURE_CODING_TYPE_B = 2
94e7b8153eSMauro Carvalho Chehab };
95e7b8153eSMauro Carvalho Chehab
96e7b8153eSMauro Carvalho Chehab enum hva_h264_sampling_mode {
97e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_NV12 = 0,
98e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_UYVY = 1,
99e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_RGB3 = 3,
100e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_XRGB4 = 4,
101e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_NV21 = 8,
102e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_VYUY = 9,
103e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_BGR3 = 11,
104e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_XBGR4 = 12,
105e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_RGBX4 = 20,
106e7b8153eSMauro Carvalho Chehab SAMPLING_MODE_BGRX4 = 28
107e7b8153eSMauro Carvalho Chehab };
108e7b8153eSMauro Carvalho Chehab
109e7b8153eSMauro Carvalho Chehab enum hva_h264_nalu_type {
110e7b8153eSMauro Carvalho Chehab NALU_TYPE_UNKNOWN = 0,
111e7b8153eSMauro Carvalho Chehab NALU_TYPE_SLICE = 1,
112e7b8153eSMauro Carvalho Chehab NALU_TYPE_SLICE_DPA = 2,
113e7b8153eSMauro Carvalho Chehab NALU_TYPE_SLICE_DPB = 3,
114e7b8153eSMauro Carvalho Chehab NALU_TYPE_SLICE_DPC = 4,
115e7b8153eSMauro Carvalho Chehab NALU_TYPE_SLICE_IDR = 5,
116e7b8153eSMauro Carvalho Chehab NALU_TYPE_SEI = 6,
117e7b8153eSMauro Carvalho Chehab NALU_TYPE_SPS = 7,
118e7b8153eSMauro Carvalho Chehab NALU_TYPE_PPS = 8,
119e7b8153eSMauro Carvalho Chehab NALU_TYPE_AU_DELIMITER = 9,
120e7b8153eSMauro Carvalho Chehab NALU_TYPE_SEQ_END = 10,
121e7b8153eSMauro Carvalho Chehab NALU_TYPE_STREAM_END = 11,
122e7b8153eSMauro Carvalho Chehab NALU_TYPE_FILLER_DATA = 12,
123e7b8153eSMauro Carvalho Chehab NALU_TYPE_SPS_EXT = 13,
124e7b8153eSMauro Carvalho Chehab NALU_TYPE_PREFIX_UNIT = 14,
125e7b8153eSMauro Carvalho Chehab NALU_TYPE_SUBSET_SPS = 15,
126e7b8153eSMauro Carvalho Chehab NALU_TYPE_SLICE_AUX = 19,
127e7b8153eSMauro Carvalho Chehab NALU_TYPE_SLICE_EXT = 20
128e7b8153eSMauro Carvalho Chehab };
129e7b8153eSMauro Carvalho Chehab
130e7b8153eSMauro Carvalho Chehab enum hva_h264_sei_payload_type {
131e7b8153eSMauro Carvalho Chehab SEI_BUFFERING_PERIOD = 0,
132e7b8153eSMauro Carvalho Chehab SEI_PICTURE_TIMING = 1,
133e7b8153eSMauro Carvalho Chehab SEI_STEREO_VIDEO_INFO = 21,
134e7b8153eSMauro Carvalho Chehab SEI_FRAME_PACKING_ARRANGEMENT = 45
135e7b8153eSMauro Carvalho Chehab };
136e7b8153eSMauro Carvalho Chehab
137e7b8153eSMauro Carvalho Chehab /*
138e7b8153eSMauro Carvalho Chehab * stereo Video Info struct
139e7b8153eSMauro Carvalho Chehab */
140e7b8153eSMauro Carvalho Chehab struct hva_h264_stereo_video_sei {
141e7b8153eSMauro Carvalho Chehab u8 field_views_flag;
142e7b8153eSMauro Carvalho Chehab u8 top_field_is_left_view_flag;
143e7b8153eSMauro Carvalho Chehab u8 current_frame_is_left_view_flag;
144e7b8153eSMauro Carvalho Chehab u8 next_frame_is_second_view_flag;
145e7b8153eSMauro Carvalho Chehab u8 left_view_self_contained_flag;
146e7b8153eSMauro Carvalho Chehab u8 right_view_self_contained_flag;
147e7b8153eSMauro Carvalho Chehab };
148e7b8153eSMauro Carvalho Chehab
149e7b8153eSMauro Carvalho Chehab /*
150e7b8153eSMauro Carvalho Chehab * struct hva_h264_td
151e7b8153eSMauro Carvalho Chehab *
152e7b8153eSMauro Carvalho Chehab * @frame_width: width in pixels of the buffer containing the input frame
153e7b8153eSMauro Carvalho Chehab * @frame_height: height in pixels of the buffer containing the input frame
154e7b8153eSMauro Carvalho Chehab * @frame_num: the parameter to be written in the slice header
155e7b8153eSMauro Carvalho Chehab * @picture_coding_type: type I, P or B
156e7b8153eSMauro Carvalho Chehab * @pic_order_cnt_type: POC mode, as defined in H264 std : can be 0,1,2
157e7b8153eSMauro Carvalho Chehab * @first_picture_in_sequence: flag telling to encoder that this is the
158e7b8153eSMauro Carvalho Chehab * first picture in a video sequence.
159e7b8153eSMauro Carvalho Chehab * Used for VBR
160e7b8153eSMauro Carvalho Chehab * @slice_size_type: 0 = no constraint to close the slice
161e7b8153eSMauro Carvalho Chehab * 1= a slice is closed as soon as the slice_mb_size limit
162e7b8153eSMauro Carvalho Chehab * is reached
163e7b8153eSMauro Carvalho Chehab * 2= a slice is closed as soon as the slice_byte_size limit
164e7b8153eSMauro Carvalho Chehab * is reached
165e7b8153eSMauro Carvalho Chehab * 3= a slice is closed as soon as either the slice_byte_size
166e7b8153eSMauro Carvalho Chehab * limit or the slice_mb_size limit is reached
167e7b8153eSMauro Carvalho Chehab * @slice_mb_size: defines the slice size in number of macroblocks
168e7b8153eSMauro Carvalho Chehab * (used when slice_size_type=1 or slice_size_type=3)
169e7b8153eSMauro Carvalho Chehab * @ir_param_option: defines the number of macroblocks per frame to be
170e7b8153eSMauro Carvalho Chehab * refreshed by AIR algorithm OR the refresh period
171e7b8153eSMauro Carvalho Chehab * by CIR algorithm
172e7b8153eSMauro Carvalho Chehab * @intra_refresh_type: enables the adaptive intra refresh algorithm.
173e7b8153eSMauro Carvalho Chehab * Disable=0 / Adaptative=1 and Cycle=2 as intra refresh
174e7b8153eSMauro Carvalho Chehab * @use_constrained_intra_flag: constrained_intra_pred_flag from PPS
175e7b8153eSMauro Carvalho Chehab * @transform_mode: controls the use of 4x4/8x8 transform mode
176e7b8153eSMauro Carvalho Chehab * @disable_deblocking_filter_idc:
177e7b8153eSMauro Carvalho Chehab * 0: specifies that all luma and chroma block edges of
178e7b8153eSMauro Carvalho Chehab * the slice are filtered.
179e7b8153eSMauro Carvalho Chehab * 1: specifies that deblocking is disabled for all block
180e7b8153eSMauro Carvalho Chehab * edges of the slice.
181e7b8153eSMauro Carvalho Chehab * 2: specifies that all luma and chroma block edges of
182e7b8153eSMauro Carvalho Chehab * the slice are filtered with exception of the block edges
183e7b8153eSMauro Carvalho Chehab * that coincide with slice boundaries
184e7b8153eSMauro Carvalho Chehab * @slice_alpha_c0_offset_div2: to be written in slice header,
185e7b8153eSMauro Carvalho Chehab * controls deblocking
186e7b8153eSMauro Carvalho Chehab * @slice_beta_offset_div2: to be written in slice header,
187e7b8153eSMauro Carvalho Chehab * controls deblocking
188e7b8153eSMauro Carvalho Chehab * @encoder_complexity: encoder complexity control (IME).
189e7b8153eSMauro Carvalho Chehab * 0 = I_16x16, P_16x16, Full ME Complexity
190e7b8153eSMauro Carvalho Chehab * 1 = I_16x16, I_NxN, P_16x16, Full ME Complexity
191e7b8153eSMauro Carvalho Chehab * 2 = I_16x16, I_NXN, P_16x16, P_WxH, Full ME Complexity
192e7b8153eSMauro Carvalho Chehab * 4 = I_16x16, P_16x16, Reduced ME Complexity
193e7b8153eSMauro Carvalho Chehab * 5 = I_16x16, I_NxN, P_16x16, Reduced ME Complexity
194e7b8153eSMauro Carvalho Chehab * 6 = I_16x16, I_NXN, P_16x16, P_WxH, Reduced ME Complexity
195e7b8153eSMauro Carvalho Chehab * @chroma_qp_index_offset: coming from picture parameter set
196e7b8153eSMauro Carvalho Chehab * (PPS see [H.264 STD] 7.4.2.2)
197e7b8153eSMauro Carvalho Chehab * @entropy_coding_mode: entropy coding mode.
198e7b8153eSMauro Carvalho Chehab * 0 = CAVLC
199e7b8153eSMauro Carvalho Chehab * 1 = CABAC
200e7b8153eSMauro Carvalho Chehab * @brc_type: selects the bit-rate control algorithm
201e7b8153eSMauro Carvalho Chehab * 0 = constant Qp, (no BRC)
202e7b8153eSMauro Carvalho Chehab * 1 = CBR
203e7b8153eSMauro Carvalho Chehab * 2 = VBR
204e7b8153eSMauro Carvalho Chehab * @quant: Quantization param used in case of fix QP encoding (no BRC)
205e7b8153eSMauro Carvalho Chehab * @non_VCL_NALU_Size: size of non-VCL NALUs (SPS, PPS, filler),
206e7b8153eSMauro Carvalho Chehab * used by BRC
207e7b8153eSMauro Carvalho Chehab * @cpb_buffer_size: size of Coded Picture Buffer, used by BRC
208e7b8153eSMauro Carvalho Chehab * @bit_rate: target bitrate, for BRC
209e7b8153eSMauro Carvalho Chehab * @qp_min: min QP threshold
210e7b8153eSMauro Carvalho Chehab * @qp_max: max QP threshold
211e7b8153eSMauro Carvalho Chehab * @framerate_num: target framerate numerator , used by BRC
212e7b8153eSMauro Carvalho Chehab * @framerate_den: target framerate denomurator , used by BRC
213e7b8153eSMauro Carvalho Chehab * @delay: End-to-End Initial Delay
214e7b8153eSMauro Carvalho Chehab * @strict_HRD_compliancy: flag for HDR compliancy (1)
215e7b8153eSMauro Carvalho Chehab * May impact quality encoding
216e7b8153eSMauro Carvalho Chehab * @addr_source_buffer: address of input frame buffer for current frame
217e7b8153eSMauro Carvalho Chehab * @addr_fwd_Ref_Buffer: address of reference frame buffer
218e7b8153eSMauro Carvalho Chehab * @addr_rec_buffer: address of reconstructed frame buffer
219e7b8153eSMauro Carvalho Chehab * @addr_output_bitstream_start: output bitstream start address
220e7b8153eSMauro Carvalho Chehab * @addr_output_bitstream_end: output bitstream end address
221e7b8153eSMauro Carvalho Chehab * @addr_external_sw : address of external search window
222e7b8153eSMauro Carvalho Chehab * @addr_lctx : address of context picture buffer
223e7b8153eSMauro Carvalho Chehab * @addr_local_rec_buffer: address of local reconstructed buffer
224e7b8153eSMauro Carvalho Chehab * @addr_spatial_context: address of spatial context buffer
225e7b8153eSMauro Carvalho Chehab * @bitstream_offset: offset in bits between aligned bitstream start
226e7b8153eSMauro Carvalho Chehab * address and first bit to be written by HVA.
227e7b8153eSMauro Carvalho Chehab * Range value is [0..63]
228e7b8153eSMauro Carvalho Chehab * @sampling_mode: Input picture format .
229e7b8153eSMauro Carvalho Chehab * 0: YUV420 semi_planar Interleaved
230e7b8153eSMauro Carvalho Chehab * 1: YUV422 raster Interleaved
231e7b8153eSMauro Carvalho Chehab * @addr_param_out: address of output parameters structure
232e7b8153eSMauro Carvalho Chehab * @addr_scaling_matrix: address to the coefficient of
233e7b8153eSMauro Carvalho Chehab * the inverse scaling matrix
234e7b8153eSMauro Carvalho Chehab * @addr_scaling_matrix_dir: address to the coefficient of
235e7b8153eSMauro Carvalho Chehab * the direct scaling matrix
236e7b8153eSMauro Carvalho Chehab * @addr_cabac_context_buffer: address of cabac context buffer
237e7b8153eSMauro Carvalho Chehab * @GmvX: Input information about the horizontal global displacement of
238e7b8153eSMauro Carvalho Chehab * the encoded frame versus the previous one
239e7b8153eSMauro Carvalho Chehab * @GmvY: Input information about the vertical global displacement of
240e7b8153eSMauro Carvalho Chehab * the encoded frame versus the previous one
241e7b8153eSMauro Carvalho Chehab * @window_width: width in pixels of the window to be encoded inside
242e7b8153eSMauro Carvalho Chehab * the input frame
243e7b8153eSMauro Carvalho Chehab * @window_height: width in pixels of the window to be encoded inside
244e7b8153eSMauro Carvalho Chehab * the input frame
245e7b8153eSMauro Carvalho Chehab * @window_horizontal_offset: horizontal offset in pels for input window
246e7b8153eSMauro Carvalho Chehab * within input frame
247e7b8153eSMauro Carvalho Chehab * @window_vertical_offset: vertical offset in pels for input window
248e7b8153eSMauro Carvalho Chehab * within input frame
249e7b8153eSMauro Carvalho Chehab * @addr_roi: Map of QP offset for the Region of Interest algorithm and
250e7b8153eSMauro Carvalho Chehab * also used for Error map.
251e7b8153eSMauro Carvalho Chehab * Bit 0-6 used for qp offset (value -64 to 63).
252e7b8153eSMauro Carvalho Chehab * Bit 7 used to force intra
253e7b8153eSMauro Carvalho Chehab * @addr_slice_header: address to slice header
254e7b8153eSMauro Carvalho Chehab * @slice_header_size_in_bits: size in bits of the Slice header
255e7b8153eSMauro Carvalho Chehab * @slice_header_offset0: Slice header offset where to insert
256e7b8153eSMauro Carvalho Chehab * first_Mb_in_slice
257e7b8153eSMauro Carvalho Chehab * @slice_header_offset1: Slice header offset where to insert
258e7b8153eSMauro Carvalho Chehab * slice_qp_delta
259e7b8153eSMauro Carvalho Chehab * @slice_header_offset2: Slice header offset where to insert
260e7b8153eSMauro Carvalho Chehab * num_MBs_in_slice
261e7b8153eSMauro Carvalho Chehab * @slice_synchro_enable: enable "slice ready" interrupt after each slice
262e7b8153eSMauro Carvalho Chehab * @max_slice_number: Maximum number of slice in a frame
263e7b8153eSMauro Carvalho Chehab * (0 is strictly forbidden)
264e7b8153eSMauro Carvalho Chehab * @rgb2_yuv_y_coeff: Four coefficients (C0C1C2C3) to convert from RGB to
265e7b8153eSMauro Carvalho Chehab * YUV for the Y component.
266e7b8153eSMauro Carvalho Chehab * Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0)
267e7b8153eSMauro Carvalho Chehab * @rgb2_yuv_u_coeff: four coefficients (C0C1C2C3) to convert from RGB to
268e7b8153eSMauro Carvalho Chehab * YUV for the Y component.
269e7b8153eSMauro Carvalho Chehab * Y = C0*R + C1*G + C2*B + C3 (C0 is on byte 0)
270e7b8153eSMauro Carvalho Chehab * @rgb2_yuv_v_coeff: Four coefficients (C0C1C2C3) to convert from RGB to
271e7b8153eSMauro Carvalho Chehab * YUV for the U (Cb) component.
272e7b8153eSMauro Carvalho Chehab * U = C0*R + C1*G + C2*B + C3 (C0 is on byte 0)
273e7b8153eSMauro Carvalho Chehab * @slice_byte_size: maximum slice size in bytes
274e7b8153eSMauro Carvalho Chehab * (used when slice_size_type=2 or slice_size_type=3)
275e7b8153eSMauro Carvalho Chehab * @max_air_intra_mb_nb: Maximum number of intra macroblock in a frame
276e7b8153eSMauro Carvalho Chehab * for the AIR algorithm
277e7b8153eSMauro Carvalho Chehab * @brc_no_skip: Disable skipping in the Bitrate Controller
278e7b8153eSMauro Carvalho Chehab * @addr_brc_in_out_parameter: address of static buffer for BRC parameters
279e7b8153eSMauro Carvalho Chehab */
280e7b8153eSMauro Carvalho Chehab struct hva_h264_td {
281e7b8153eSMauro Carvalho Chehab u16 frame_width;
282e7b8153eSMauro Carvalho Chehab u16 frame_height;
283e7b8153eSMauro Carvalho Chehab u32 frame_num;
284e7b8153eSMauro Carvalho Chehab u16 picture_coding_type;
285e7b8153eSMauro Carvalho Chehab u16 reserved1;
286e7b8153eSMauro Carvalho Chehab u16 pic_order_cnt_type;
287e7b8153eSMauro Carvalho Chehab u16 first_picture_in_sequence;
288e7b8153eSMauro Carvalho Chehab u16 slice_size_type;
289e7b8153eSMauro Carvalho Chehab u16 reserved2;
290e7b8153eSMauro Carvalho Chehab u32 slice_mb_size;
291e7b8153eSMauro Carvalho Chehab u16 ir_param_option;
292e7b8153eSMauro Carvalho Chehab u16 intra_refresh_type;
293e7b8153eSMauro Carvalho Chehab u16 use_constrained_intra_flag;
294e7b8153eSMauro Carvalho Chehab u16 transform_mode;
295e7b8153eSMauro Carvalho Chehab u16 disable_deblocking_filter_idc;
296e7b8153eSMauro Carvalho Chehab s16 slice_alpha_c0_offset_div2;
297e7b8153eSMauro Carvalho Chehab s16 slice_beta_offset_div2;
298e7b8153eSMauro Carvalho Chehab u16 encoder_complexity;
299e7b8153eSMauro Carvalho Chehab s16 chroma_qp_index_offset;
300e7b8153eSMauro Carvalho Chehab u16 entropy_coding_mode;
301e7b8153eSMauro Carvalho Chehab u16 brc_type;
302e7b8153eSMauro Carvalho Chehab u16 quant;
303e7b8153eSMauro Carvalho Chehab u32 non_vcl_nalu_size;
304e7b8153eSMauro Carvalho Chehab u32 cpb_buffer_size;
305e7b8153eSMauro Carvalho Chehab u32 bit_rate;
306e7b8153eSMauro Carvalho Chehab u16 qp_min;
307e7b8153eSMauro Carvalho Chehab u16 qp_max;
308e7b8153eSMauro Carvalho Chehab u16 framerate_num;
309e7b8153eSMauro Carvalho Chehab u16 framerate_den;
310e7b8153eSMauro Carvalho Chehab u16 delay;
311e7b8153eSMauro Carvalho Chehab u16 strict_hrd_compliancy;
312e7b8153eSMauro Carvalho Chehab u32 addr_source_buffer;
313e7b8153eSMauro Carvalho Chehab u32 addr_fwd_ref_buffer;
314e7b8153eSMauro Carvalho Chehab u32 addr_rec_buffer;
315e7b8153eSMauro Carvalho Chehab u32 addr_output_bitstream_start;
316e7b8153eSMauro Carvalho Chehab u32 addr_output_bitstream_end;
317e7b8153eSMauro Carvalho Chehab u32 addr_external_sw;
318e7b8153eSMauro Carvalho Chehab u32 addr_lctx;
319e7b8153eSMauro Carvalho Chehab u32 addr_local_rec_buffer;
320e7b8153eSMauro Carvalho Chehab u32 addr_spatial_context;
321e7b8153eSMauro Carvalho Chehab u16 bitstream_offset;
322e7b8153eSMauro Carvalho Chehab u16 sampling_mode;
323e7b8153eSMauro Carvalho Chehab u32 addr_param_out;
324e7b8153eSMauro Carvalho Chehab u32 addr_scaling_matrix;
325e7b8153eSMauro Carvalho Chehab u32 addr_scaling_matrix_dir;
326e7b8153eSMauro Carvalho Chehab u32 addr_cabac_context_buffer;
327e7b8153eSMauro Carvalho Chehab u32 reserved3;
328e7b8153eSMauro Carvalho Chehab u32 reserved4;
329e7b8153eSMauro Carvalho Chehab s16 gmv_x;
330e7b8153eSMauro Carvalho Chehab s16 gmv_y;
331e7b8153eSMauro Carvalho Chehab u16 window_width;
332e7b8153eSMauro Carvalho Chehab u16 window_height;
333e7b8153eSMauro Carvalho Chehab u16 window_horizontal_offset;
334e7b8153eSMauro Carvalho Chehab u16 window_vertical_offset;
335e7b8153eSMauro Carvalho Chehab u32 addr_roi;
336e7b8153eSMauro Carvalho Chehab u32 addr_slice_header;
337e7b8153eSMauro Carvalho Chehab u16 slice_header_size_in_bits;
338e7b8153eSMauro Carvalho Chehab u16 slice_header_offset0;
339e7b8153eSMauro Carvalho Chehab u16 slice_header_offset1;
340e7b8153eSMauro Carvalho Chehab u16 slice_header_offset2;
341e7b8153eSMauro Carvalho Chehab u32 reserved5;
342e7b8153eSMauro Carvalho Chehab u32 reserved6;
343e7b8153eSMauro Carvalho Chehab u16 reserved7;
344e7b8153eSMauro Carvalho Chehab u16 reserved8;
345e7b8153eSMauro Carvalho Chehab u16 slice_synchro_enable;
346e7b8153eSMauro Carvalho Chehab u16 max_slice_number;
347e7b8153eSMauro Carvalho Chehab u32 rgb2_yuv_y_coeff;
348e7b8153eSMauro Carvalho Chehab u32 rgb2_yuv_u_coeff;
349e7b8153eSMauro Carvalho Chehab u32 rgb2_yuv_v_coeff;
350e7b8153eSMauro Carvalho Chehab u32 slice_byte_size;
351e7b8153eSMauro Carvalho Chehab u16 max_air_intra_mb_nb;
352e7b8153eSMauro Carvalho Chehab u16 brc_no_skip;
353e7b8153eSMauro Carvalho Chehab u32 addr_temporal_context;
354e7b8153eSMauro Carvalho Chehab u32 addr_brc_in_out_parameter;
355e7b8153eSMauro Carvalho Chehab };
356e7b8153eSMauro Carvalho Chehab
357e7b8153eSMauro Carvalho Chehab /*
358e7b8153eSMauro Carvalho Chehab * struct hva_h264_slice_po
359e7b8153eSMauro Carvalho Chehab *
360e7b8153eSMauro Carvalho Chehab * @ slice_size: slice size
361e7b8153eSMauro Carvalho Chehab * @ slice_start_time: start time
362e7b8153eSMauro Carvalho Chehab * @ slice_stop_time: stop time
363e7b8153eSMauro Carvalho Chehab * @ slice_num: slice number
364e7b8153eSMauro Carvalho Chehab */
365e7b8153eSMauro Carvalho Chehab struct hva_h264_slice_po {
366e7b8153eSMauro Carvalho Chehab u32 slice_size;
367e7b8153eSMauro Carvalho Chehab u32 slice_start_time;
368e7b8153eSMauro Carvalho Chehab u32 slice_end_time;
369e7b8153eSMauro Carvalho Chehab u32 slice_num;
370e7b8153eSMauro Carvalho Chehab };
371e7b8153eSMauro Carvalho Chehab
372e7b8153eSMauro Carvalho Chehab /*
373e7b8153eSMauro Carvalho Chehab * struct hva_h264_po
374e7b8153eSMauro Carvalho Chehab *
375e7b8153eSMauro Carvalho Chehab * @ bitstream_size: bitstream size
376e7b8153eSMauro Carvalho Chehab * @ dct_bitstream_size: dtc bitstream size
377e7b8153eSMauro Carvalho Chehab * @ stuffing_bits: number of stuffing bits inserted by the encoder
378e7b8153eSMauro Carvalho Chehab * @ removal_time: removal time of current frame (nb of ticks 1/framerate)
379e7b8153eSMauro Carvalho Chehab * @ hvc_start_time: hvc start time
380e7b8153eSMauro Carvalho Chehab * @ hvc_stop_time: hvc stop time
381e7b8153eSMauro Carvalho Chehab * @ slice_count: slice count
382e7b8153eSMauro Carvalho Chehab */
383e7b8153eSMauro Carvalho Chehab struct hva_h264_po {
384e7b8153eSMauro Carvalho Chehab u32 bitstream_size;
385e7b8153eSMauro Carvalho Chehab u32 dct_bitstream_size;
386e7b8153eSMauro Carvalho Chehab u32 stuffing_bits;
387e7b8153eSMauro Carvalho Chehab u32 removal_time;
388e7b8153eSMauro Carvalho Chehab u32 hvc_start_time;
389e7b8153eSMauro Carvalho Chehab u32 hvc_stop_time;
390e7b8153eSMauro Carvalho Chehab u32 slice_count;
391e7b8153eSMauro Carvalho Chehab u32 reserved0;
392e7b8153eSMauro Carvalho Chehab struct hva_h264_slice_po slice_params[16];
393e7b8153eSMauro Carvalho Chehab };
394e7b8153eSMauro Carvalho Chehab
395e7b8153eSMauro Carvalho Chehab struct hva_h264_task {
396e7b8153eSMauro Carvalho Chehab struct hva_h264_td td;
397e7b8153eSMauro Carvalho Chehab struct hva_h264_po po;
398e7b8153eSMauro Carvalho Chehab };
399e7b8153eSMauro Carvalho Chehab
400e7b8153eSMauro Carvalho Chehab /*
401e7b8153eSMauro Carvalho Chehab * struct hva_h264_ctx
402e7b8153eSMauro Carvalho Chehab *
403e7b8153eSMauro Carvalho Chehab * @seq_info: sequence information buffer
404e7b8153eSMauro Carvalho Chehab * @ref_frame: reference frame buffer
405e7b8153eSMauro Carvalho Chehab * @rec_frame: reconstructed frame buffer
406e7b8153eSMauro Carvalho Chehab * @task: task descriptor
407e7b8153eSMauro Carvalho Chehab */
408e7b8153eSMauro Carvalho Chehab struct hva_h264_ctx {
409e7b8153eSMauro Carvalho Chehab struct hva_buffer *seq_info;
410e7b8153eSMauro Carvalho Chehab struct hva_buffer *ref_frame;
411e7b8153eSMauro Carvalho Chehab struct hva_buffer *rec_frame;
412e7b8153eSMauro Carvalho Chehab struct hva_buffer *task;
413e7b8153eSMauro Carvalho Chehab };
414e7b8153eSMauro Carvalho Chehab
hva_h264_fill_slice_header(struct hva_ctx * pctx,u8 * slice_header_addr,struct hva_controls * ctrls,int frame_num,u16 * header_size,u16 * header_offset0,u16 * header_offset1,u16 * header_offset2)415e7b8153eSMauro Carvalho Chehab static int hva_h264_fill_slice_header(struct hva_ctx *pctx,
416e7b8153eSMauro Carvalho Chehab u8 *slice_header_addr,
417e7b8153eSMauro Carvalho Chehab struct hva_controls *ctrls,
418e7b8153eSMauro Carvalho Chehab int frame_num,
419e7b8153eSMauro Carvalho Chehab u16 *header_size,
420e7b8153eSMauro Carvalho Chehab u16 *header_offset0,
421e7b8153eSMauro Carvalho Chehab u16 *header_offset1,
422e7b8153eSMauro Carvalho Chehab u16 *header_offset2)
423e7b8153eSMauro Carvalho Chehab {
424e7b8153eSMauro Carvalho Chehab /*
425e7b8153eSMauro Carvalho Chehab * with this HVA hardware version, part of the slice header is computed
426e7b8153eSMauro Carvalho Chehab * on host and part by hardware.
427e7b8153eSMauro Carvalho Chehab * The part of host is precomputed and available through this array.
428e7b8153eSMauro Carvalho Chehab */
429e7b8153eSMauro Carvalho Chehab struct device *dev = ctx_to_dev(pctx);
430e7b8153eSMauro Carvalho Chehab int cabac = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
431e7b8153eSMauro Carvalho Chehab static const unsigned char slice_header[] = {
432e7b8153eSMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x01,
433e7b8153eSMauro Carvalho Chehab 0x41, 0x34, 0x07, 0x00
434e7b8153eSMauro Carvalho Chehab };
435e7b8153eSMauro Carvalho Chehab int idr_pic_id = frame_num % 2;
436e7b8153eSMauro Carvalho Chehab enum hva_picture_coding_type type;
437e7b8153eSMauro Carvalho Chehab u32 frame_order = frame_num % ctrls->gop_size;
438e7b8153eSMauro Carvalho Chehab
439e7b8153eSMauro Carvalho Chehab if (!(frame_num % ctrls->gop_size))
440e7b8153eSMauro Carvalho Chehab type = PICTURE_CODING_TYPE_I;
441e7b8153eSMauro Carvalho Chehab else
442e7b8153eSMauro Carvalho Chehab type = PICTURE_CODING_TYPE_P;
443e7b8153eSMauro Carvalho Chehab
444e7b8153eSMauro Carvalho Chehab memcpy(slice_header_addr, slice_header, sizeof(slice_header));
445e7b8153eSMauro Carvalho Chehab
446e7b8153eSMauro Carvalho Chehab *header_size = 56;
447e7b8153eSMauro Carvalho Chehab *header_offset0 = 40;
448e7b8153eSMauro Carvalho Chehab *header_offset1 = 13;
449e7b8153eSMauro Carvalho Chehab *header_offset2 = 0;
450e7b8153eSMauro Carvalho Chehab
451e7b8153eSMauro Carvalho Chehab if (type == PICTURE_CODING_TYPE_I) {
452e7b8153eSMauro Carvalho Chehab slice_header_addr[4] = 0x65;
453e7b8153eSMauro Carvalho Chehab slice_header_addr[5] = 0x11;
454e7b8153eSMauro Carvalho Chehab
455e7b8153eSMauro Carvalho Chehab /* toggle the I frame */
456e7b8153eSMauro Carvalho Chehab if ((frame_num / ctrls->gop_size) % 2) {
457e7b8153eSMauro Carvalho Chehab *header_size += 4;
458e7b8153eSMauro Carvalho Chehab *header_offset1 += 4;
459e7b8153eSMauro Carvalho Chehab slice_header_addr[6] = 0x04;
460e7b8153eSMauro Carvalho Chehab slice_header_addr[7] = 0x70;
461e7b8153eSMauro Carvalho Chehab
462e7b8153eSMauro Carvalho Chehab } else {
463e7b8153eSMauro Carvalho Chehab *header_size += 2;
464e7b8153eSMauro Carvalho Chehab *header_offset1 += 2;
465e7b8153eSMauro Carvalho Chehab slice_header_addr[6] = 0x09;
466e7b8153eSMauro Carvalho Chehab slice_header_addr[7] = 0xC0;
467e7b8153eSMauro Carvalho Chehab }
468e7b8153eSMauro Carvalho Chehab } else {
469e7b8153eSMauro Carvalho Chehab if (ctrls->entropy_mode == cabac) {
470e7b8153eSMauro Carvalho Chehab *header_size += 1;
471e7b8153eSMauro Carvalho Chehab *header_offset1 += 1;
472e7b8153eSMauro Carvalho Chehab slice_header_addr[7] = 0x80;
473e7b8153eSMauro Carvalho Chehab }
474e7b8153eSMauro Carvalho Chehab /*
475e7b8153eSMauro Carvalho Chehab * update slice header with P frame order
476e7b8153eSMauro Carvalho Chehab * frame order is limited to 16 (coded on 4bits only)
477e7b8153eSMauro Carvalho Chehab */
478e7b8153eSMauro Carvalho Chehab slice_header_addr[5] += ((frame_order & 0x0C) >> 2);
479e7b8153eSMauro Carvalho Chehab slice_header_addr[6] += ((frame_order & 0x03) << 6);
480e7b8153eSMauro Carvalho Chehab }
481e7b8153eSMauro Carvalho Chehab
482e7b8153eSMauro Carvalho Chehab dev_dbg(dev,
483e7b8153eSMauro Carvalho Chehab "%s %s slice header order %d idrPicId %d header size %d\n",
484e7b8153eSMauro Carvalho Chehab pctx->name, __func__, frame_order, idr_pic_id, *header_size);
485e7b8153eSMauro Carvalho Chehab return 0;
486e7b8153eSMauro Carvalho Chehab }
487e7b8153eSMauro Carvalho Chehab
hva_h264_fill_data_nal(struct hva_ctx * pctx,unsigned int stuffing_bytes,u8 * addr,unsigned int stream_size,unsigned int * size)488e7b8153eSMauro Carvalho Chehab static int hva_h264_fill_data_nal(struct hva_ctx *pctx,
489e7b8153eSMauro Carvalho Chehab unsigned int stuffing_bytes, u8 *addr,
490e7b8153eSMauro Carvalho Chehab unsigned int stream_size, unsigned int *size)
491e7b8153eSMauro Carvalho Chehab {
492e7b8153eSMauro Carvalho Chehab struct device *dev = ctx_to_dev(pctx);
493e7b8153eSMauro Carvalho Chehab static const u8 start[] = { 0x00, 0x00, 0x00, 0x01 };
494e7b8153eSMauro Carvalho Chehab
495e7b8153eSMauro Carvalho Chehab dev_dbg(dev, "%s %s stuffing bytes %d\n", pctx->name, __func__,
496e7b8153eSMauro Carvalho Chehab stuffing_bytes);
497e7b8153eSMauro Carvalho Chehab
498e7b8153eSMauro Carvalho Chehab if ((*size + stuffing_bytes + H264_FILLER_DATA_SIZE) > stream_size) {
499e7b8153eSMauro Carvalho Chehab dev_dbg(dev, "%s %s too many stuffing bytes %d\n",
500e7b8153eSMauro Carvalho Chehab pctx->name, __func__, stuffing_bytes);
501e7b8153eSMauro Carvalho Chehab return 0;
502e7b8153eSMauro Carvalho Chehab }
503e7b8153eSMauro Carvalho Chehab
504e7b8153eSMauro Carvalho Chehab /* start code */
505e7b8153eSMauro Carvalho Chehab memcpy(addr + *size, start, sizeof(start));
506e7b8153eSMauro Carvalho Chehab *size += sizeof(start);
507e7b8153eSMauro Carvalho Chehab
508e7b8153eSMauro Carvalho Chehab /* nal_unit_type */
509e7b8153eSMauro Carvalho Chehab addr[*size] = NALU_TYPE_FILLER_DATA;
510e7b8153eSMauro Carvalho Chehab *size += 1;
511e7b8153eSMauro Carvalho Chehab
512e7b8153eSMauro Carvalho Chehab memset(addr + *size, 0xff, stuffing_bytes);
513e7b8153eSMauro Carvalho Chehab *size += stuffing_bytes;
514e7b8153eSMauro Carvalho Chehab
515e7b8153eSMauro Carvalho Chehab addr[*size] = 0x80;
516e7b8153eSMauro Carvalho Chehab *size += 1;
517e7b8153eSMauro Carvalho Chehab
518e7b8153eSMauro Carvalho Chehab return 0;
519e7b8153eSMauro Carvalho Chehab }
520e7b8153eSMauro Carvalho Chehab
hva_h264_fill_sei_nal(struct hva_ctx * pctx,enum hva_h264_sei_payload_type type,u8 * addr,u32 * size)521e7b8153eSMauro Carvalho Chehab static int hva_h264_fill_sei_nal(struct hva_ctx *pctx,
522e7b8153eSMauro Carvalho Chehab enum hva_h264_sei_payload_type type,
523e7b8153eSMauro Carvalho Chehab u8 *addr, u32 *size)
524e7b8153eSMauro Carvalho Chehab {
525e7b8153eSMauro Carvalho Chehab struct device *dev = ctx_to_dev(pctx);
526e7b8153eSMauro Carvalho Chehab static const u8 start[] = { 0x00, 0x00, 0x00, 0x01 };
527e7b8153eSMauro Carvalho Chehab struct hva_h264_stereo_video_sei info;
528e7b8153eSMauro Carvalho Chehab u8 offset = 7;
529e7b8153eSMauro Carvalho Chehab u8 msg = 0;
530e7b8153eSMauro Carvalho Chehab
531e7b8153eSMauro Carvalho Chehab /* start code */
532e7b8153eSMauro Carvalho Chehab memcpy(addr + *size, start, sizeof(start));
533e7b8153eSMauro Carvalho Chehab *size += sizeof(start);
534e7b8153eSMauro Carvalho Chehab
535e7b8153eSMauro Carvalho Chehab /* nal_unit_type */
536e7b8153eSMauro Carvalho Chehab addr[*size] = NALU_TYPE_SEI;
537e7b8153eSMauro Carvalho Chehab *size += 1;
538e7b8153eSMauro Carvalho Chehab
539e7b8153eSMauro Carvalho Chehab /* payload type */
540e7b8153eSMauro Carvalho Chehab addr[*size] = type;
541e7b8153eSMauro Carvalho Chehab *size += 1;
542e7b8153eSMauro Carvalho Chehab
543e7b8153eSMauro Carvalho Chehab switch (type) {
544e7b8153eSMauro Carvalho Chehab case SEI_STEREO_VIDEO_INFO:
545e7b8153eSMauro Carvalho Chehab memset(&info, 0, sizeof(info));
546e7b8153eSMauro Carvalho Chehab
547e7b8153eSMauro Carvalho Chehab /* set to top/bottom frame packing arrangement */
548e7b8153eSMauro Carvalho Chehab info.field_views_flag = 1;
549e7b8153eSMauro Carvalho Chehab info.top_field_is_left_view_flag = 1;
550e7b8153eSMauro Carvalho Chehab
551e7b8153eSMauro Carvalho Chehab /* payload size */
552e7b8153eSMauro Carvalho Chehab addr[*size] = 1;
553e7b8153eSMauro Carvalho Chehab *size += 1;
554e7b8153eSMauro Carvalho Chehab
555e7b8153eSMauro Carvalho Chehab /* payload */
556e7b8153eSMauro Carvalho Chehab msg = info.field_views_flag << offset--;
557e7b8153eSMauro Carvalho Chehab
558e7b8153eSMauro Carvalho Chehab if (info.field_views_flag) {
559e7b8153eSMauro Carvalho Chehab msg |= info.top_field_is_left_view_flag <<
560e7b8153eSMauro Carvalho Chehab offset--;
561e7b8153eSMauro Carvalho Chehab } else {
562e7b8153eSMauro Carvalho Chehab msg |= info.current_frame_is_left_view_flag <<
563e7b8153eSMauro Carvalho Chehab offset--;
564e7b8153eSMauro Carvalho Chehab msg |= info.next_frame_is_second_view_flag <<
565e7b8153eSMauro Carvalho Chehab offset--;
566e7b8153eSMauro Carvalho Chehab }
567e7b8153eSMauro Carvalho Chehab msg |= info.left_view_self_contained_flag << offset--;
568e7b8153eSMauro Carvalho Chehab msg |= info.right_view_self_contained_flag << offset--;
569e7b8153eSMauro Carvalho Chehab
570e7b8153eSMauro Carvalho Chehab addr[*size] = msg;
571e7b8153eSMauro Carvalho Chehab *size += 1;
572e7b8153eSMauro Carvalho Chehab
573e7b8153eSMauro Carvalho Chehab addr[*size] = 0x80;
574e7b8153eSMauro Carvalho Chehab *size += 1;
575e7b8153eSMauro Carvalho Chehab
576e7b8153eSMauro Carvalho Chehab return 0;
577e7b8153eSMauro Carvalho Chehab case SEI_BUFFERING_PERIOD:
578e7b8153eSMauro Carvalho Chehab case SEI_PICTURE_TIMING:
579e7b8153eSMauro Carvalho Chehab case SEI_FRAME_PACKING_ARRANGEMENT:
580e7b8153eSMauro Carvalho Chehab default:
581e7b8153eSMauro Carvalho Chehab dev_err(dev, "%s sei nal type not supported %d\n",
582e7b8153eSMauro Carvalho Chehab pctx->name, type);
583e7b8153eSMauro Carvalho Chehab return -EINVAL;
584e7b8153eSMauro Carvalho Chehab }
585e7b8153eSMauro Carvalho Chehab }
586e7b8153eSMauro Carvalho Chehab
hva_h264_prepare_task(struct hva_ctx * pctx,struct hva_h264_task * task,struct hva_frame * frame,struct hva_stream * stream)587e7b8153eSMauro Carvalho Chehab static int hva_h264_prepare_task(struct hva_ctx *pctx,
588e7b8153eSMauro Carvalho Chehab struct hva_h264_task *task,
589e7b8153eSMauro Carvalho Chehab struct hva_frame *frame,
590e7b8153eSMauro Carvalho Chehab struct hva_stream *stream)
591e7b8153eSMauro Carvalho Chehab {
592e7b8153eSMauro Carvalho Chehab struct hva_dev *hva = ctx_to_hdev(pctx);
593e7b8153eSMauro Carvalho Chehab struct device *dev = ctx_to_dev(pctx);
594*afa8516cSSu Hui struct hva_h264_ctx *ctx = pctx->priv;
595e7b8153eSMauro Carvalho Chehab struct hva_buffer *seq_info = ctx->seq_info;
596e7b8153eSMauro Carvalho Chehab struct hva_buffer *fwd_ref_frame = ctx->ref_frame;
597e7b8153eSMauro Carvalho Chehab struct hva_buffer *loc_rec_frame = ctx->rec_frame;
598e7b8153eSMauro Carvalho Chehab struct hva_h264_td *td = &task->td;
599e7b8153eSMauro Carvalho Chehab struct hva_controls *ctrls = &pctx->ctrls;
600e7b8153eSMauro Carvalho Chehab struct v4l2_fract *time_per_frame = &pctx->ctrls.time_per_frame;
601e7b8153eSMauro Carvalho Chehab int cavlc = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
602e7b8153eSMauro Carvalho Chehab u32 frame_num = pctx->stream_num;
603e7b8153eSMauro Carvalho Chehab u32 addr_esram = hva->esram_addr;
604e7b8153eSMauro Carvalho Chehab enum v4l2_mpeg_video_h264_level level;
605e7b8153eSMauro Carvalho Chehab dma_addr_t paddr = 0;
606e7b8153eSMauro Carvalho Chehab u8 *slice_header_vaddr;
607e7b8153eSMauro Carvalho Chehab u32 frame_width = frame->info.aligned_width;
608e7b8153eSMauro Carvalho Chehab u32 frame_height = frame->info.aligned_height;
609e7b8153eSMauro Carvalho Chehab u32 max_cpb_buffer_size;
610e7b8153eSMauro Carvalho Chehab unsigned int payload = stream->bytesused;
611e7b8153eSMauro Carvalho Chehab u32 max_bitrate;
612e7b8153eSMauro Carvalho Chehab
613e7b8153eSMauro Carvalho Chehab /* check width and height parameters */
614e7b8153eSMauro Carvalho Chehab if ((frame_width > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H)) ||
615e7b8153eSMauro Carvalho Chehab (frame_height > max(H264_MAX_SIZE_W, H264_MAX_SIZE_H))) {
616e7b8153eSMauro Carvalho Chehab dev_err(dev,
617e7b8153eSMauro Carvalho Chehab "%s width(%d) or height(%d) exceeds limits (%dx%d)\n",
618e7b8153eSMauro Carvalho Chehab pctx->name, frame_width, frame_height,
619e7b8153eSMauro Carvalho Chehab H264_MAX_SIZE_W, H264_MAX_SIZE_H);
620e7b8153eSMauro Carvalho Chehab pctx->frame_errors++;
621e7b8153eSMauro Carvalho Chehab return -EINVAL;
622e7b8153eSMauro Carvalho Chehab }
623e7b8153eSMauro Carvalho Chehab
624e7b8153eSMauro Carvalho Chehab level = ctrls->level;
625e7b8153eSMauro Carvalho Chehab
626e7b8153eSMauro Carvalho Chehab memset(td, 0, sizeof(struct hva_h264_td));
627e7b8153eSMauro Carvalho Chehab
628e7b8153eSMauro Carvalho Chehab td->frame_width = frame_width;
629e7b8153eSMauro Carvalho Chehab td->frame_height = frame_height;
630e7b8153eSMauro Carvalho Chehab
631e7b8153eSMauro Carvalho Chehab /* set frame alignment */
632e7b8153eSMauro Carvalho Chehab td->window_width = frame_width;
633e7b8153eSMauro Carvalho Chehab td->window_height = frame_height;
634e7b8153eSMauro Carvalho Chehab td->window_horizontal_offset = 0;
635e7b8153eSMauro Carvalho Chehab td->window_vertical_offset = 0;
636e7b8153eSMauro Carvalho Chehab
637e7b8153eSMauro Carvalho Chehab td->first_picture_in_sequence = (!frame_num) ? 1 : 0;
638e7b8153eSMauro Carvalho Chehab
639e7b8153eSMauro Carvalho Chehab /* pic_order_cnt_type hard coded to '2' as only I & P frames */
640e7b8153eSMauro Carvalho Chehab td->pic_order_cnt_type = 2;
641e7b8153eSMauro Carvalho Chehab
642e7b8153eSMauro Carvalho Chehab /* useConstrainedIntraFlag set to false for better coding efficiency */
643e7b8153eSMauro Carvalho Chehab td->use_constrained_intra_flag = false;
644e7b8153eSMauro Carvalho Chehab td->brc_type = (ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
645e7b8153eSMauro Carvalho Chehab ? BRC_TYPE_CBR : BRC_TYPE_VBR;
646e7b8153eSMauro Carvalho Chehab
647e7b8153eSMauro Carvalho Chehab td->entropy_coding_mode = (ctrls->entropy_mode == cavlc) ? CAVLC :
648e7b8153eSMauro Carvalho Chehab CABAC;
649e7b8153eSMauro Carvalho Chehab
650e7b8153eSMauro Carvalho Chehab td->bit_rate = ctrls->bitrate;
651e7b8153eSMauro Carvalho Chehab
652e7b8153eSMauro Carvalho Chehab /* set framerate, framerate = 1 n/ time per frame */
653e7b8153eSMauro Carvalho Chehab if (time_per_frame->numerator >= 536) {
654e7b8153eSMauro Carvalho Chehab /*
655e7b8153eSMauro Carvalho Chehab * due to a hardware bug, framerate denominator can't exceed
656e7b8153eSMauro Carvalho Chehab * 536 (BRC overflow). Compute nearest framerate
657e7b8153eSMauro Carvalho Chehab */
658e7b8153eSMauro Carvalho Chehab td->framerate_den = 1;
659e7b8153eSMauro Carvalho Chehab td->framerate_num = (time_per_frame->denominator +
660e7b8153eSMauro Carvalho Chehab (time_per_frame->numerator >> 1) - 1) /
661e7b8153eSMauro Carvalho Chehab time_per_frame->numerator;
662e7b8153eSMauro Carvalho Chehab
663e7b8153eSMauro Carvalho Chehab /*
664e7b8153eSMauro Carvalho Chehab * update bitrate to introduce a correction due to
665e7b8153eSMauro Carvalho Chehab * the new framerate
666e7b8153eSMauro Carvalho Chehab * new bitrate = (old bitrate * new framerate) / old framerate
667e7b8153eSMauro Carvalho Chehab */
668e7b8153eSMauro Carvalho Chehab td->bit_rate /= time_per_frame->numerator;
669e7b8153eSMauro Carvalho Chehab td->bit_rate *= time_per_frame->denominator;
670e7b8153eSMauro Carvalho Chehab td->bit_rate /= td->framerate_num;
671e7b8153eSMauro Carvalho Chehab } else {
672e7b8153eSMauro Carvalho Chehab td->framerate_den = time_per_frame->numerator;
673e7b8153eSMauro Carvalho Chehab td->framerate_num = time_per_frame->denominator;
674e7b8153eSMauro Carvalho Chehab }
675e7b8153eSMauro Carvalho Chehab
676e7b8153eSMauro Carvalho Chehab /* compute maximum bitrate depending on profile */
677e7b8153eSMauro Carvalho Chehab if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)
678e7b8153eSMauro Carvalho Chehab max_bitrate = h264_infos_list[level].max_bitrate *
679e7b8153eSMauro Carvalho Chehab H264_FACTOR_HIGH;
680e7b8153eSMauro Carvalho Chehab else
681e7b8153eSMauro Carvalho Chehab max_bitrate = h264_infos_list[level].max_bitrate *
682e7b8153eSMauro Carvalho Chehab H264_FACTOR_BASELINE;
683e7b8153eSMauro Carvalho Chehab
684e7b8153eSMauro Carvalho Chehab /* check if bitrate doesn't exceed max size */
685e7b8153eSMauro Carvalho Chehab if (td->bit_rate > max_bitrate) {
686e7b8153eSMauro Carvalho Chehab dev_dbg(dev,
687e7b8153eSMauro Carvalho Chehab "%s bitrate (%d) larger than level and profile allow, clip to %d\n",
688e7b8153eSMauro Carvalho Chehab pctx->name, td->bit_rate, max_bitrate);
689e7b8153eSMauro Carvalho Chehab td->bit_rate = max_bitrate;
690e7b8153eSMauro Carvalho Chehab }
691e7b8153eSMauro Carvalho Chehab
692e7b8153eSMauro Carvalho Chehab /* convert cpb_buffer_size in bits */
693e7b8153eSMauro Carvalho Chehab td->cpb_buffer_size = ctrls->cpb_size * 8000;
694e7b8153eSMauro Carvalho Chehab
695e7b8153eSMauro Carvalho Chehab /* compute maximum cpb buffer size depending on profile */
696e7b8153eSMauro Carvalho Chehab if (ctrls->profile >= V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)
697e7b8153eSMauro Carvalho Chehab max_cpb_buffer_size =
698e7b8153eSMauro Carvalho Chehab h264_infos_list[level].max_cpb_size * H264_FACTOR_HIGH;
699e7b8153eSMauro Carvalho Chehab else
700e7b8153eSMauro Carvalho Chehab max_cpb_buffer_size =
701e7b8153eSMauro Carvalho Chehab h264_infos_list[level].max_cpb_size * H264_FACTOR_BASELINE;
702e7b8153eSMauro Carvalho Chehab
703e7b8153eSMauro Carvalho Chehab /* check if cpb buffer size doesn't exceed max size */
704e7b8153eSMauro Carvalho Chehab if (td->cpb_buffer_size > max_cpb_buffer_size) {
705e7b8153eSMauro Carvalho Chehab dev_dbg(dev,
706e7b8153eSMauro Carvalho Chehab "%s cpb size larger than level %d allows, clip to %d\n",
707e7b8153eSMauro Carvalho Chehab pctx->name, td->cpb_buffer_size, max_cpb_buffer_size);
708e7b8153eSMauro Carvalho Chehab td->cpb_buffer_size = max_cpb_buffer_size;
709e7b8153eSMauro Carvalho Chehab }
710e7b8153eSMauro Carvalho Chehab
711e7b8153eSMauro Carvalho Chehab /* enable skipping in the Bitrate Controller */
712e7b8153eSMauro Carvalho Chehab td->brc_no_skip = 0;
713e7b8153eSMauro Carvalho Chehab
714e7b8153eSMauro Carvalho Chehab /* initial delay */
715e7b8153eSMauro Carvalho Chehab if ((ctrls->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) &&
716e7b8153eSMauro Carvalho Chehab td->bit_rate)
717e7b8153eSMauro Carvalho Chehab td->delay = 1000 * (td->cpb_buffer_size / td->bit_rate);
718e7b8153eSMauro Carvalho Chehab else
719e7b8153eSMauro Carvalho Chehab td->delay = 0;
720e7b8153eSMauro Carvalho Chehab
721e7b8153eSMauro Carvalho Chehab switch (frame->info.pixelformat) {
722e7b8153eSMauro Carvalho Chehab case V4L2_PIX_FMT_NV12:
723e7b8153eSMauro Carvalho Chehab td->sampling_mode = SAMPLING_MODE_NV12;
724e7b8153eSMauro Carvalho Chehab break;
725e7b8153eSMauro Carvalho Chehab case V4L2_PIX_FMT_NV21:
726e7b8153eSMauro Carvalho Chehab td->sampling_mode = SAMPLING_MODE_NV21;
727e7b8153eSMauro Carvalho Chehab break;
728e7b8153eSMauro Carvalho Chehab default:
729e7b8153eSMauro Carvalho Chehab dev_err(dev, "%s invalid source pixel format\n",
730e7b8153eSMauro Carvalho Chehab pctx->name);
731e7b8153eSMauro Carvalho Chehab pctx->frame_errors++;
732e7b8153eSMauro Carvalho Chehab return -EINVAL;
733e7b8153eSMauro Carvalho Chehab }
734e7b8153eSMauro Carvalho Chehab
735e7b8153eSMauro Carvalho Chehab /*
736e7b8153eSMauro Carvalho Chehab * fill matrix color converter (RGB to YUV)
737e7b8153eSMauro Carvalho Chehab * Y = 0,299 R + 0,587 G + 0,114 B
738e7b8153eSMauro Carvalho Chehab * Cb = -0,1687 R -0,3313 G + 0,5 B + 128
739e7b8153eSMauro Carvalho Chehab * Cr = 0,5 R - 0,4187 G - 0,0813 B + 128
740e7b8153eSMauro Carvalho Chehab */
741e7b8153eSMauro Carvalho Chehab td->rgb2_yuv_y_coeff = 0x12031008;
742e7b8153eSMauro Carvalho Chehab td->rgb2_yuv_u_coeff = 0x800EF7FB;
743e7b8153eSMauro Carvalho Chehab td->rgb2_yuv_v_coeff = 0x80FEF40E;
744e7b8153eSMauro Carvalho Chehab
745e7b8153eSMauro Carvalho Chehab /* enable/disable transform mode */
746e7b8153eSMauro Carvalho Chehab td->transform_mode = ctrls->dct8x8;
747e7b8153eSMauro Carvalho Chehab
748e7b8153eSMauro Carvalho Chehab /* encoder complexity fix to 2, ENCODE_I_16x16_I_NxN_P_16x16_P_WxH */
749e7b8153eSMauro Carvalho Chehab td->encoder_complexity = 2;
750e7b8153eSMauro Carvalho Chehab
751e7b8153eSMauro Carvalho Chehab /* quant fix to 28, default VBR value */
752e7b8153eSMauro Carvalho Chehab td->quant = 28;
753e7b8153eSMauro Carvalho Chehab
754e7b8153eSMauro Carvalho Chehab if (td->framerate_den == 0) {
755e7b8153eSMauro Carvalho Chehab dev_err(dev, "%s invalid framerate\n", pctx->name);
756e7b8153eSMauro Carvalho Chehab pctx->frame_errors++;
757e7b8153eSMauro Carvalho Chehab return -EINVAL;
758e7b8153eSMauro Carvalho Chehab }
759e7b8153eSMauro Carvalho Chehab
760e7b8153eSMauro Carvalho Chehab /* if automatic framerate, deactivate bitrate controller */
761e7b8153eSMauro Carvalho Chehab if (td->framerate_num == 0)
762e7b8153eSMauro Carvalho Chehab td->brc_type = 0;
763e7b8153eSMauro Carvalho Chehab
764e7b8153eSMauro Carvalho Chehab /* compliancy fix to true */
765e7b8153eSMauro Carvalho Chehab td->strict_hrd_compliancy = 1;
766e7b8153eSMauro Carvalho Chehab
767e7b8153eSMauro Carvalho Chehab /* set minimum & maximum quantizers */
768e7b8153eSMauro Carvalho Chehab td->qp_min = clamp_val(ctrls->qpmin, 0, 51);
769e7b8153eSMauro Carvalho Chehab td->qp_max = clamp_val(ctrls->qpmax, 0, 51);
770e7b8153eSMauro Carvalho Chehab
771e7b8153eSMauro Carvalho Chehab td->addr_source_buffer = frame->paddr;
772e7b8153eSMauro Carvalho Chehab td->addr_fwd_ref_buffer = fwd_ref_frame->paddr;
773e7b8153eSMauro Carvalho Chehab td->addr_rec_buffer = loc_rec_frame->paddr;
774e7b8153eSMauro Carvalho Chehab
775e7b8153eSMauro Carvalho Chehab td->addr_output_bitstream_end = (u32)stream->paddr + stream->size;
776e7b8153eSMauro Carvalho Chehab
777e7b8153eSMauro Carvalho Chehab td->addr_output_bitstream_start = (u32)stream->paddr;
778e7b8153eSMauro Carvalho Chehab td->bitstream_offset = (((u32)stream->paddr & 0xF) << 3) &
779e7b8153eSMauro Carvalho Chehab BITSTREAM_OFFSET_MASK;
780e7b8153eSMauro Carvalho Chehab
781e7b8153eSMauro Carvalho Chehab td->addr_param_out = (u32)ctx->task->paddr +
782e7b8153eSMauro Carvalho Chehab offsetof(struct hva_h264_task, po);
783e7b8153eSMauro Carvalho Chehab
784e7b8153eSMauro Carvalho Chehab /* swap spatial and temporal context */
785e7b8153eSMauro Carvalho Chehab if (frame_num % 2) {
786e7b8153eSMauro Carvalho Chehab paddr = seq_info->paddr;
787e7b8153eSMauro Carvalho Chehab td->addr_spatial_context = ALIGN(paddr, 0x100);
788e7b8153eSMauro Carvalho Chehab paddr = seq_info->paddr + DATA_SIZE(frame_width,
789e7b8153eSMauro Carvalho Chehab frame_height);
790e7b8153eSMauro Carvalho Chehab td->addr_temporal_context = ALIGN(paddr, 0x100);
791e7b8153eSMauro Carvalho Chehab } else {
792e7b8153eSMauro Carvalho Chehab paddr = seq_info->paddr;
793e7b8153eSMauro Carvalho Chehab td->addr_temporal_context = ALIGN(paddr, 0x100);
794e7b8153eSMauro Carvalho Chehab paddr = seq_info->paddr + DATA_SIZE(frame_width,
795e7b8153eSMauro Carvalho Chehab frame_height);
796e7b8153eSMauro Carvalho Chehab td->addr_spatial_context = ALIGN(paddr, 0x100);
797e7b8153eSMauro Carvalho Chehab }
798e7b8153eSMauro Carvalho Chehab
799e7b8153eSMauro Carvalho Chehab paddr = seq_info->paddr + 2 * DATA_SIZE(frame_width, frame_height);
800e7b8153eSMauro Carvalho Chehab
801e7b8153eSMauro Carvalho Chehab td->addr_brc_in_out_parameter = ALIGN(paddr, 0x100);
802e7b8153eSMauro Carvalho Chehab
803e7b8153eSMauro Carvalho Chehab paddr = td->addr_brc_in_out_parameter + BRC_DATA_SIZE;
804e7b8153eSMauro Carvalho Chehab td->addr_slice_header = ALIGN(paddr, 0x100);
805e7b8153eSMauro Carvalho Chehab td->addr_external_sw = ALIGN(addr_esram, 0x100);
806e7b8153eSMauro Carvalho Chehab
807e7b8153eSMauro Carvalho Chehab addr_esram += SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width);
808e7b8153eSMauro Carvalho Chehab td->addr_local_rec_buffer = ALIGN(addr_esram, 0x100);
809e7b8153eSMauro Carvalho Chehab
810e7b8153eSMauro Carvalho Chehab addr_esram += LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width);
811e7b8153eSMauro Carvalho Chehab td->addr_lctx = ALIGN(addr_esram, 0x100);
812e7b8153eSMauro Carvalho Chehab
813e7b8153eSMauro Carvalho Chehab addr_esram += CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height));
814e7b8153eSMauro Carvalho Chehab td->addr_cabac_context_buffer = ALIGN(addr_esram, 0x100);
815e7b8153eSMauro Carvalho Chehab
816e7b8153eSMauro Carvalho Chehab if (!(frame_num % ctrls->gop_size)) {
817e7b8153eSMauro Carvalho Chehab td->picture_coding_type = PICTURE_CODING_TYPE_I;
818e7b8153eSMauro Carvalho Chehab stream->vbuf.flags |= V4L2_BUF_FLAG_KEYFRAME;
819e7b8153eSMauro Carvalho Chehab } else {
820e7b8153eSMauro Carvalho Chehab td->picture_coding_type = PICTURE_CODING_TYPE_P;
821e7b8153eSMauro Carvalho Chehab stream->vbuf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
822e7b8153eSMauro Carvalho Chehab }
823e7b8153eSMauro Carvalho Chehab
824e7b8153eSMauro Carvalho Chehab /* fill the slice header part */
825e7b8153eSMauro Carvalho Chehab slice_header_vaddr = seq_info->vaddr + (td->addr_slice_header -
826e7b8153eSMauro Carvalho Chehab seq_info->paddr);
827e7b8153eSMauro Carvalho Chehab
828e7b8153eSMauro Carvalho Chehab hva_h264_fill_slice_header(pctx, slice_header_vaddr, ctrls, frame_num,
829e7b8153eSMauro Carvalho Chehab &td->slice_header_size_in_bits,
830e7b8153eSMauro Carvalho Chehab &td->slice_header_offset0,
831e7b8153eSMauro Carvalho Chehab &td->slice_header_offset1,
832e7b8153eSMauro Carvalho Chehab &td->slice_header_offset2);
833e7b8153eSMauro Carvalho Chehab
834e7b8153eSMauro Carvalho Chehab td->chroma_qp_index_offset = 2;
835e7b8153eSMauro Carvalho Chehab td->slice_synchro_enable = 0;
836e7b8153eSMauro Carvalho Chehab td->max_slice_number = 1;
837e7b8153eSMauro Carvalho Chehab
838e7b8153eSMauro Carvalho Chehab /*
839e7b8153eSMauro Carvalho Chehab * check the sps/pps header size for key frame only
840e7b8153eSMauro Carvalho Chehab * sps/pps header was previously fill by libv4l
841e7b8153eSMauro Carvalho Chehab * during qbuf of stream buffer
842e7b8153eSMauro Carvalho Chehab */
843e7b8153eSMauro Carvalho Chehab if ((stream->vbuf.flags == V4L2_BUF_FLAG_KEYFRAME) &&
844e7b8153eSMauro Carvalho Chehab (payload > MAX_SPS_PPS_SIZE)) {
845e7b8153eSMauro Carvalho Chehab dev_err(dev, "%s invalid sps/pps size %d\n", pctx->name,
846e7b8153eSMauro Carvalho Chehab payload);
847e7b8153eSMauro Carvalho Chehab pctx->frame_errors++;
848e7b8153eSMauro Carvalho Chehab return -EINVAL;
849e7b8153eSMauro Carvalho Chehab }
850e7b8153eSMauro Carvalho Chehab
851e7b8153eSMauro Carvalho Chehab if (stream->vbuf.flags != V4L2_BUF_FLAG_KEYFRAME)
852e7b8153eSMauro Carvalho Chehab payload = 0;
853e7b8153eSMauro Carvalho Chehab
854e7b8153eSMauro Carvalho Chehab /* add SEI nal (video stereo info) */
855e7b8153eSMauro Carvalho Chehab if (ctrls->sei_fp && hva_h264_fill_sei_nal(pctx, SEI_STEREO_VIDEO_INFO,
856e7b8153eSMauro Carvalho Chehab (u8 *)stream->vaddr,
857e7b8153eSMauro Carvalho Chehab &payload)) {
858e7b8153eSMauro Carvalho Chehab dev_err(dev, "%s fail to get SEI nal\n", pctx->name);
859e7b8153eSMauro Carvalho Chehab pctx->frame_errors++;
860e7b8153eSMauro Carvalho Chehab return -EINVAL;
861e7b8153eSMauro Carvalho Chehab }
862e7b8153eSMauro Carvalho Chehab
863e7b8153eSMauro Carvalho Chehab /* fill size of non-VCL NAL units (SPS, PPS, filler and SEI) */
864e7b8153eSMauro Carvalho Chehab td->non_vcl_nalu_size = payload * 8;
865e7b8153eSMauro Carvalho Chehab
866e7b8153eSMauro Carvalho Chehab /* compute bitstream offset & new start address of bitstream */
867e7b8153eSMauro Carvalho Chehab td->addr_output_bitstream_start += ((payload >> 4) << 4);
868e7b8153eSMauro Carvalho Chehab td->bitstream_offset += (payload - ((payload >> 4) << 4)) * 8;
869e7b8153eSMauro Carvalho Chehab
870e7b8153eSMauro Carvalho Chehab stream->bytesused = payload;
871e7b8153eSMauro Carvalho Chehab
872e7b8153eSMauro Carvalho Chehab return 0;
873e7b8153eSMauro Carvalho Chehab }
874e7b8153eSMauro Carvalho Chehab
hva_h264_get_stream_size(struct hva_h264_task * task)875e7b8153eSMauro Carvalho Chehab static unsigned int hva_h264_get_stream_size(struct hva_h264_task *task)
876e7b8153eSMauro Carvalho Chehab {
877e7b8153eSMauro Carvalho Chehab struct hva_h264_po *po = &task->po;
878e7b8153eSMauro Carvalho Chehab
879e7b8153eSMauro Carvalho Chehab return po->bitstream_size;
880e7b8153eSMauro Carvalho Chehab }
881e7b8153eSMauro Carvalho Chehab
hva_h264_get_stuffing_bytes(struct hva_h264_task * task)882e7b8153eSMauro Carvalho Chehab static u32 hva_h264_get_stuffing_bytes(struct hva_h264_task *task)
883e7b8153eSMauro Carvalho Chehab {
884e7b8153eSMauro Carvalho Chehab struct hva_h264_po *po = &task->po;
885e7b8153eSMauro Carvalho Chehab
886e7b8153eSMauro Carvalho Chehab return po->stuffing_bits >> 3;
887e7b8153eSMauro Carvalho Chehab }
888e7b8153eSMauro Carvalho Chehab
hva_h264_open(struct hva_ctx * pctx)889e7b8153eSMauro Carvalho Chehab static int hva_h264_open(struct hva_ctx *pctx)
890e7b8153eSMauro Carvalho Chehab {
891e7b8153eSMauro Carvalho Chehab struct device *dev = ctx_to_dev(pctx);
892e7b8153eSMauro Carvalho Chehab struct hva_h264_ctx *ctx;
893e7b8153eSMauro Carvalho Chehab struct hva_dev *hva = ctx_to_hdev(pctx);
894e7b8153eSMauro Carvalho Chehab u32 frame_width = pctx->frameinfo.aligned_width;
895e7b8153eSMauro Carvalho Chehab u32 frame_height = pctx->frameinfo.aligned_height;
896e7b8153eSMauro Carvalho Chehab u32 size;
897e7b8153eSMauro Carvalho Chehab int ret;
898e7b8153eSMauro Carvalho Chehab
899e7b8153eSMauro Carvalho Chehab /* check esram size necessary to encode a frame */
900e7b8153eSMauro Carvalho Chehab size = SEARCH_WINDOW_BUFFER_MAX_SIZE(frame_width) +
901e7b8153eSMauro Carvalho Chehab LOCAL_RECONSTRUCTED_BUFFER_MAX_SIZE(frame_width) +
902e7b8153eSMauro Carvalho Chehab CTX_MB_BUFFER_MAX_SIZE(max(frame_width, frame_height)) +
903e7b8153eSMauro Carvalho Chehab CABAC_CONTEXT_BUFFER_MAX_SIZE(frame_width);
904e7b8153eSMauro Carvalho Chehab
905e7b8153eSMauro Carvalho Chehab if (hva->esram_size < size) {
906e7b8153eSMauro Carvalho Chehab dev_err(dev, "%s not enough esram (max:%d request:%d)\n",
907e7b8153eSMauro Carvalho Chehab pctx->name, hva->esram_size, size);
908e7b8153eSMauro Carvalho Chehab ret = -EINVAL;
909e7b8153eSMauro Carvalho Chehab goto err;
910e7b8153eSMauro Carvalho Chehab }
911e7b8153eSMauro Carvalho Chehab
912e7b8153eSMauro Carvalho Chehab /* allocate context for codec */
913e7b8153eSMauro Carvalho Chehab ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
914e7b8153eSMauro Carvalho Chehab if (!ctx) {
915e7b8153eSMauro Carvalho Chehab ret = -ENOMEM;
916e7b8153eSMauro Carvalho Chehab goto err;
917e7b8153eSMauro Carvalho Chehab }
918e7b8153eSMauro Carvalho Chehab
919e7b8153eSMauro Carvalho Chehab /* allocate sequence info buffer */
920e7b8153eSMauro Carvalho Chehab ret = hva_mem_alloc(pctx,
921e7b8153eSMauro Carvalho Chehab 2 * DATA_SIZE(frame_width, frame_height) +
922e7b8153eSMauro Carvalho Chehab SLICE_HEADER_SIZE +
923e7b8153eSMauro Carvalho Chehab BRC_DATA_SIZE,
924e7b8153eSMauro Carvalho Chehab "hva sequence info",
925e7b8153eSMauro Carvalho Chehab &ctx->seq_info);
926e7b8153eSMauro Carvalho Chehab if (ret) {
927e7b8153eSMauro Carvalho Chehab dev_err(dev,
928e7b8153eSMauro Carvalho Chehab "%s failed to allocate sequence info buffer\n",
929e7b8153eSMauro Carvalho Chehab pctx->name);
930e7b8153eSMauro Carvalho Chehab goto err_ctx;
931e7b8153eSMauro Carvalho Chehab }
932e7b8153eSMauro Carvalho Chehab
933e7b8153eSMauro Carvalho Chehab /* allocate reference frame buffer */
934e7b8153eSMauro Carvalho Chehab ret = hva_mem_alloc(pctx,
935e7b8153eSMauro Carvalho Chehab frame_width * frame_height * 3 / 2,
936e7b8153eSMauro Carvalho Chehab "hva reference frame",
937e7b8153eSMauro Carvalho Chehab &ctx->ref_frame);
938e7b8153eSMauro Carvalho Chehab if (ret) {
939e7b8153eSMauro Carvalho Chehab dev_err(dev, "%s failed to allocate reference frame buffer\n",
940e7b8153eSMauro Carvalho Chehab pctx->name);
941e7b8153eSMauro Carvalho Chehab goto err_seq_info;
942e7b8153eSMauro Carvalho Chehab }
943e7b8153eSMauro Carvalho Chehab
944e7b8153eSMauro Carvalho Chehab /* allocate reconstructed frame buffer */
945e7b8153eSMauro Carvalho Chehab ret = hva_mem_alloc(pctx,
946e7b8153eSMauro Carvalho Chehab frame_width * frame_height * 3 / 2,
947e7b8153eSMauro Carvalho Chehab "hva reconstructed frame",
948e7b8153eSMauro Carvalho Chehab &ctx->rec_frame);
949e7b8153eSMauro Carvalho Chehab if (ret) {
950e7b8153eSMauro Carvalho Chehab dev_err(dev,
951e7b8153eSMauro Carvalho Chehab "%s failed to allocate reconstructed frame buffer\n",
952e7b8153eSMauro Carvalho Chehab pctx->name);
953e7b8153eSMauro Carvalho Chehab goto err_ref_frame;
954e7b8153eSMauro Carvalho Chehab }
955e7b8153eSMauro Carvalho Chehab
956e7b8153eSMauro Carvalho Chehab /* allocate task descriptor */
957e7b8153eSMauro Carvalho Chehab ret = hva_mem_alloc(pctx,
958e7b8153eSMauro Carvalho Chehab sizeof(struct hva_h264_task),
959e7b8153eSMauro Carvalho Chehab "hva task descriptor",
960e7b8153eSMauro Carvalho Chehab &ctx->task);
961e7b8153eSMauro Carvalho Chehab if (ret) {
962e7b8153eSMauro Carvalho Chehab dev_err(dev,
963e7b8153eSMauro Carvalho Chehab "%s failed to allocate task descriptor\n",
964e7b8153eSMauro Carvalho Chehab pctx->name);
965e7b8153eSMauro Carvalho Chehab goto err_rec_frame;
966e7b8153eSMauro Carvalho Chehab }
967e7b8153eSMauro Carvalho Chehab
968e7b8153eSMauro Carvalho Chehab pctx->priv = (void *)ctx;
969e7b8153eSMauro Carvalho Chehab
970e7b8153eSMauro Carvalho Chehab return 0;
971e7b8153eSMauro Carvalho Chehab
972e7b8153eSMauro Carvalho Chehab err_rec_frame:
973e7b8153eSMauro Carvalho Chehab hva_mem_free(pctx, ctx->rec_frame);
974e7b8153eSMauro Carvalho Chehab err_ref_frame:
975e7b8153eSMauro Carvalho Chehab hva_mem_free(pctx, ctx->ref_frame);
976e7b8153eSMauro Carvalho Chehab err_seq_info:
977e7b8153eSMauro Carvalho Chehab hva_mem_free(pctx, ctx->seq_info);
978e7b8153eSMauro Carvalho Chehab err_ctx:
979e7b8153eSMauro Carvalho Chehab devm_kfree(dev, ctx);
980e7b8153eSMauro Carvalho Chehab err:
981e7b8153eSMauro Carvalho Chehab pctx->sys_errors++;
982e7b8153eSMauro Carvalho Chehab return ret;
983e7b8153eSMauro Carvalho Chehab }
984e7b8153eSMauro Carvalho Chehab
hva_h264_close(struct hva_ctx * pctx)985e7b8153eSMauro Carvalho Chehab static int hva_h264_close(struct hva_ctx *pctx)
986e7b8153eSMauro Carvalho Chehab {
987*afa8516cSSu Hui struct hva_h264_ctx *ctx = pctx->priv;
988e7b8153eSMauro Carvalho Chehab struct device *dev = ctx_to_dev(pctx);
989e7b8153eSMauro Carvalho Chehab
990e7b8153eSMauro Carvalho Chehab if (ctx->seq_info)
991e7b8153eSMauro Carvalho Chehab hva_mem_free(pctx, ctx->seq_info);
992e7b8153eSMauro Carvalho Chehab
993e7b8153eSMauro Carvalho Chehab if (ctx->ref_frame)
994e7b8153eSMauro Carvalho Chehab hva_mem_free(pctx, ctx->ref_frame);
995e7b8153eSMauro Carvalho Chehab
996e7b8153eSMauro Carvalho Chehab if (ctx->rec_frame)
997e7b8153eSMauro Carvalho Chehab hva_mem_free(pctx, ctx->rec_frame);
998e7b8153eSMauro Carvalho Chehab
999e7b8153eSMauro Carvalho Chehab if (ctx->task)
1000e7b8153eSMauro Carvalho Chehab hva_mem_free(pctx, ctx->task);
1001e7b8153eSMauro Carvalho Chehab
1002e7b8153eSMauro Carvalho Chehab devm_kfree(dev, ctx);
1003e7b8153eSMauro Carvalho Chehab
1004e7b8153eSMauro Carvalho Chehab return 0;
1005e7b8153eSMauro Carvalho Chehab }
1006e7b8153eSMauro Carvalho Chehab
hva_h264_encode(struct hva_ctx * pctx,struct hva_frame * frame,struct hva_stream * stream)1007e7b8153eSMauro Carvalho Chehab static int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame,
1008e7b8153eSMauro Carvalho Chehab struct hva_stream *stream)
1009e7b8153eSMauro Carvalho Chehab {
1010*afa8516cSSu Hui struct hva_h264_ctx *ctx = pctx->priv;
1011*afa8516cSSu Hui struct hva_h264_task *task = ctx->task->vaddr;
1012e7b8153eSMauro Carvalho Chehab u32 stuffing_bytes = 0;
1013e7b8153eSMauro Carvalho Chehab int ret = 0;
1014e7b8153eSMauro Carvalho Chehab
1015e7b8153eSMauro Carvalho Chehab ret = hva_h264_prepare_task(pctx, task, frame, stream);
1016e7b8153eSMauro Carvalho Chehab if (ret)
1017e7b8153eSMauro Carvalho Chehab goto err;
1018e7b8153eSMauro Carvalho Chehab
1019e7b8153eSMauro Carvalho Chehab ret = hva_hw_execute_task(pctx, H264_ENC, ctx->task);
1020e7b8153eSMauro Carvalho Chehab if (ret)
1021e7b8153eSMauro Carvalho Chehab goto err;
1022e7b8153eSMauro Carvalho Chehab
1023e7b8153eSMauro Carvalho Chehab pctx->stream_num++;
1024e7b8153eSMauro Carvalho Chehab stream->bytesused += hva_h264_get_stream_size(task);
1025e7b8153eSMauro Carvalho Chehab
1026e7b8153eSMauro Carvalho Chehab stuffing_bytes = hva_h264_get_stuffing_bytes(task);
1027e7b8153eSMauro Carvalho Chehab
1028e7b8153eSMauro Carvalho Chehab if (stuffing_bytes)
1029e7b8153eSMauro Carvalho Chehab hva_h264_fill_data_nal(pctx, stuffing_bytes,
1030e7b8153eSMauro Carvalho Chehab (u8 *)stream->vaddr,
1031e7b8153eSMauro Carvalho Chehab stream->size,
1032e7b8153eSMauro Carvalho Chehab &stream->bytesused);
1033e7b8153eSMauro Carvalho Chehab
1034e7b8153eSMauro Carvalho Chehab /* switch reference & reconstructed frame */
1035e7b8153eSMauro Carvalho Chehab swap(ctx->ref_frame, ctx->rec_frame);
1036e7b8153eSMauro Carvalho Chehab
1037e7b8153eSMauro Carvalho Chehab return 0;
1038e7b8153eSMauro Carvalho Chehab err:
1039e7b8153eSMauro Carvalho Chehab stream->bytesused = 0;
1040e7b8153eSMauro Carvalho Chehab return ret;
1041e7b8153eSMauro Carvalho Chehab }
1042e7b8153eSMauro Carvalho Chehab
1043e7b8153eSMauro Carvalho Chehab const struct hva_enc nv12h264enc = {
1044e7b8153eSMauro Carvalho Chehab .name = "H264(NV12)",
1045e7b8153eSMauro Carvalho Chehab .pixelformat = V4L2_PIX_FMT_NV12,
1046e7b8153eSMauro Carvalho Chehab .streamformat = V4L2_PIX_FMT_H264,
1047e7b8153eSMauro Carvalho Chehab .max_width = H264_MAX_SIZE_W,
1048e7b8153eSMauro Carvalho Chehab .max_height = H264_MAX_SIZE_H,
1049e7b8153eSMauro Carvalho Chehab .open = hva_h264_open,
1050e7b8153eSMauro Carvalho Chehab .close = hva_h264_close,
1051e7b8153eSMauro Carvalho Chehab .encode = hva_h264_encode,
1052e7b8153eSMauro Carvalho Chehab };
1053e7b8153eSMauro Carvalho Chehab
1054e7b8153eSMauro Carvalho Chehab const struct hva_enc nv21h264enc = {
1055e7b8153eSMauro Carvalho Chehab .name = "H264(NV21)",
1056e7b8153eSMauro Carvalho Chehab .pixelformat = V4L2_PIX_FMT_NV21,
1057e7b8153eSMauro Carvalho Chehab .streamformat = V4L2_PIX_FMT_H264,
1058e7b8153eSMauro Carvalho Chehab .max_width = H264_MAX_SIZE_W,
1059e7b8153eSMauro Carvalho Chehab .max_height = H264_MAX_SIZE_H,
1060e7b8153eSMauro Carvalho Chehab .open = hva_h264_open,
1061e7b8153eSMauro Carvalho Chehab .close = hva_h264_close,
1062e7b8153eSMauro Carvalho Chehab .encode = hva_h264_encode,
1063e7b8153eSMauro Carvalho Chehab };
1064