1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 #include "drv_hdmi_infoframe.h"
19 #include "drv_hdmi_intf.h"
20 #include "drv_hdmi_common.h"
21 #include "hdmi_hal.h"
22
23 #define HDMI_AVI_VERSION3 3
24 #define HDMI_AVI_VERSION4 4
25 #define HDMI_AVI_Y2_MASK (0x1 << 2)
26 #define AVI_INFORFRAME_CHARACTER_MASK_1 0x3
27 #define AVI_INFORFRAME_CHARACTER_MASK_2 0xf
28 #define AVI_INFORFRAME_CHARACTER_MASK_3 0x7
29 #define AVI_INFORFRAME_BAR_MODE_MASK 0xff
30 #define AVI_INFORFRAME_BAR_MODE_OFFSET 8
31 #define AVI_INFORFRAME_LENGTH 13
32 #define AUDIO_INFORFRAME_LENGTH 10
33 #define DYN_RAN_INFORFRAME_LENGTH 26
34 #define DRM_INFORFRAME_META_MASK 0xff
35 #define DRM_INFORFRAME_META_OFFSET 8
36 #define HDMI_INFOFRAME_BUFFER_SIZE 32
37 #define HDMI_INFOFRAME_CHECCKSUM 256
38
drv_hdmi_video_timing_lookup(hdmi_video_code_vic vic,hdmi_picture_aspect aspect)39 hdmi_video_timing drv_hdmi_video_timing_lookup(hdmi_video_code_vic vic, hdmi_picture_aspect aspect)
40 {
41 return drv_hdmi_video_timing_get(vic, aspect);
42 }
43
drv_hdmi_vsif_video_timing_lookup(hdmi_vsif_vic vic)44 hdmi_video_timing drv_hdmi_vsif_video_timing_lookup(hdmi_vsif_vic vic)
45 {
46 return drv_hdmi_vsif_video_timing_get(vic);
47 }
48
hdmi_infoframe_checksum(hi_void * buffer,hi_u32 size)49 static hi_void hdmi_infoframe_checksum(hi_void *buffer, hi_u32 size)
50 {
51 hi_u8 *ptr = HI_NULL;
52 hi_u8 checksum = 0;
53 hi_u32 i;
54
55 ptr = buffer;
56 /* compute checksum */
57 for (i = 0; i < size; i++) {
58 checksum += ptr[i];
59 }
60 if (checksum > 0) {
61 ptr[3] = HDMI_INFOFRAME_CHECCKSUM - checksum;
62 } else {
63 ptr[3] = 0;
64 }
65 }
66
67 /*
68 * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer
69 * @frame: HDMI AVI infoframe
70 * @buffer: destination buffer
71 * @size: size of buffer
72 * packs the information contained in the @frame structure into a binary
73 * representation that can be written into the corresponding controller
74 * registers. also computes the checksum as required by section 5.3.5 of
75 * the HDMI 1.4 specification.
76 * returns the number of bytes packed into the binary buffer or a negative
77 * error code on failure.
78 */
avi_header_pack(struct hdmi_avi_infoframe * frame,hi_void * buffer,hdmi_3d_mode _3d_mode)79 static hdmi_video_code_vic avi_header_pack(struct hdmi_avi_infoframe *frame, hi_void *buffer, hdmi_3d_mode _3d_mode)
80 {
81 hi_u8 *ptr = HI_NULL;
82 hi_bool _3d_enable = HI_FALSE;
83 hdmi_video_code_vic video_code;
84
85 _3d_enable = (_3d_mode != HDMI_3D_BUTT) ? HI_FALSE : HI_TRUE;
86 video_code = drv_hdmi_vic_search(frame->video_timing, frame->picture_aspect, _3d_enable);
87
88 ptr = buffer;
89 ptr[0] = frame->type;
90 if (((hi_u32)frame->colorspace & HDMI_AVI_Y2_MASK) || (video_code > HDMI_5120X2160P100_64_27)) {
91 /* Y2 = 1 or vic >= 128, version shall use 3 */
92 frame->version = HDMI_AVI_VERSION3;
93 } else if (frame->colorimetry == HDMI_COLORIMETRY_EXTEND &&
94 frame->extended_colorimetry == HDMI_EXTENDED_COLORIMETRY_ADDITIONAL) {
95 /* (C1,C0)=(1,1) and (EC2,EC1,EC0)=(1,1,1), version shall use 4 */
96 frame->version = HDMI_AVI_VERSION4;
97 }
98 ptr[1] = frame->version;
99 ptr[2] = frame->length;
100 ptr[3] = 0; /* checksum */
101
102 return video_code;
103 }
104
hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe * frame,hi_void * buffer,hi_u32 size,hdmi_3d_mode _3d_mode)105 static hi_s32 hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, hi_void *buffer,
106 hi_u32 size, hdmi_3d_mode _3d_mode)
107 {
108 hi_u32 length;
109 hi_u8 *ptr = HI_NULL;
110 hdmi_video_code_vic video_code;
111
112 length = frame->length + HDMI_INFOFRAME_HEADER_SIZE;
113 if (size < length) {
114 return -1;
115 }
116 (hi_void)memset_s(buffer, size, 0, size);
117 video_code = avi_header_pack(frame, buffer, _3d_mode);
118 /* start infoframe payload */
119 ptr = buffer;
120 ptr += HDMI_INFOFRAME_HEADER_SIZE;
121 ptr[0] = (((hi_u32)frame->colorspace & AVI_INFORFRAME_CHARACTER_MASK_1) << 5) | /* 5'b, bit[7:6] */
122 ((hi_u32)frame->scan_mode & AVI_INFORFRAME_CHARACTER_MASK_1);
123 if (frame->active_info_valid) {
124 hdmi_set_bit(ptr[0], 4); /* 4'b, bit[5] */
125 }
126 if (frame->horizontal_bar_valid) {
127 hdmi_set_bit(ptr[0], 3); /* 3'b, bit[4] */
128 }
129 if (frame->vertical_bar_valid) {
130 hdmi_set_bit(ptr[0], 2); /* 2'b, bit[3] */
131 }
132 ptr[1] = (((hi_u32)frame->colorimetry & AVI_INFORFRAME_CHARACTER_MASK_1) << 6) | /* 6-7 bit is colorimetry */
133 /* 4-5 is coded frame aspect ratio */
134 (((hi_u32)frame->picture_aspect & AVI_INFORFRAME_CHARACTER_MASK_1) << 4) |
135 ((hi_u32)frame->active_aspect & AVI_INFORFRAME_CHARACTER_MASK_2);
136 /* 4-7 bit is Extended Colorimetry */
137 ptr[2] = (((hi_u32)frame->extended_colorimetry & AVI_INFORFRAME_CHARACTER_MASK_3) << 4) |
138 /* 2-3 bit is RGB quantization range */
139 (((hi_u32)frame->quantization_range & AVI_INFORFRAME_CHARACTER_MASK_1) << 2) |
140 ((hi_u32)frame->nups & AVI_INFORFRAME_CHARACTER_MASK_1);
141 if (frame->itc) {
142 hdmi_set_bit(ptr[2], 7); /* 7'b, bit[8] */
143 }
144 ptr[3] = (hi_u32)video_code & 0xff; /* frame->video_code */
145 /* 6-7 bit is quantization range */
146 ptr[4] = (((hi_u32)frame->ycc_quantization_range & AVI_INFORFRAME_CHARACTER_MASK_1) << 6) |
147 (((hi_u32)frame->content_type & AVI_INFORFRAME_CHARACTER_MASK_1) << 4) | /* 4-5 bit is quantization range */
148 ((frame->pixel_repeat - 1) & AVI_INFORFRAME_CHARACTER_MASK_2); /* pixel repeat mode */
149 ptr[5] = frame->top_bar & AVI_INFORFRAME_BAR_MODE_MASK;
150 ptr[6] = (frame->top_bar >> AVI_INFORFRAME_BAR_MODE_OFFSET) & AVI_INFORFRAME_BAR_MODE_MASK;
151 ptr[7] = frame->bottom_bar & AVI_INFORFRAME_BAR_MODE_MASK;
152 ptr[8] = (frame->bottom_bar >> AVI_INFORFRAME_BAR_MODE_OFFSET) & AVI_INFORFRAME_BAR_MODE_MASK;
153 ptr[9] = frame->left_bar & AVI_INFORFRAME_BAR_MODE_MASK;
154 ptr[10] = (frame->left_bar >> AVI_INFORFRAME_BAR_MODE_OFFSET) & AVI_INFORFRAME_BAR_MODE_MASK;
155 ptr[11] = frame->right_bar & AVI_INFORFRAME_BAR_MODE_MASK;
156 ptr[12] = (frame->right_bar >> AVI_INFORFRAME_BAR_MODE_OFFSET) & AVI_INFORFRAME_BAR_MODE_MASK;
157 hdmi_infoframe_checksum(buffer, length);
158
159 return length;
160 }
161
162 #ifdef HDMI_HDR_SUPPORT
hdmi_drm_infoframe_pack(hdmi_drm_infoframe * frame,hi_void * buffer,hi_u32 size)163 hi_s32 hdmi_drm_infoframe_pack(hdmi_drm_infoframe *frame, hi_void *buffer, hi_u32 size)
164 {
165 hi_u32 length;
166 hi_u8 *ptr = HI_NULL;
167 hdmi_meta_des_1st *meta_des_1st = HI_NULL;
168
169 hdmi_if_null_return(frame, HI_FAILURE);
170 hdmi_if_null_return(buffer, HI_FAILURE);
171
172 ptr = buffer;
173 meta_des_1st = &frame->meta_descriptor.type1;
174 hdmi_if_null_return(meta_des_1st, HI_FAILURE);
175
176 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
177 if (size < length) {
178 return -1;
179 }
180 (hi_void)memset_s(buffer, size, 0, size);
181
182 ptr[0] = frame->type;
183 ptr[1] = frame->version;
184 ptr[2] = frame->length;
185 ptr[3] = 0; /* checksum */
186
187 /* start infoframe payload */
188 ptr += HDMI_INFOFRAME_HEADER_SIZE;
189 ptr[0] = frame->eotf_type;
190 ptr[1] = frame->metadata_type;
191 ptr[2] = meta_des_1st->primaries0_x & DRM_INFORFRAME_META_MASK;
192 ptr[3] = (meta_des_1st->primaries0_x >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
193 ptr[4] = meta_des_1st->primaries0_y & DRM_INFORFRAME_META_MASK;
194 ptr[5] = (meta_des_1st->primaries0_y >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
195 ptr[6] = meta_des_1st->primaries1_x & DRM_INFORFRAME_META_MASK;
196 ptr[7] = (meta_des_1st->primaries1_x >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
197 ptr[8] = meta_des_1st->primaries1_y & DRM_INFORFRAME_META_MASK;
198 ptr[9] = (meta_des_1st->primaries1_y >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
199 ptr[10] = meta_des_1st->primaries2_x & DRM_INFORFRAME_META_MASK;
200 ptr[11] = (meta_des_1st->primaries2_x >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
201 ptr[12] = meta_des_1st->primaries2_y & DRM_INFORFRAME_META_MASK;
202 ptr[13] = (meta_des_1st->primaries2_y >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
203 ptr[14] = meta_des_1st->white_point_x & DRM_INFORFRAME_META_MASK;
204 ptr[15] = (meta_des_1st->white_point_x >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
205 ptr[16] = meta_des_1st->white_point_y & DRM_INFORFRAME_META_MASK;
206 ptr[17] = (meta_des_1st->white_point_y >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
207 ptr[18] = meta_des_1st->max_luminance & DRM_INFORFRAME_META_MASK;
208 ptr[19] = (meta_des_1st->max_luminance >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
209 ptr[20] = meta_des_1st->min_luminance & DRM_INFORFRAME_META_MASK;
210 ptr[21] = (meta_des_1st->min_luminance >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
211 ptr[22] = meta_des_1st->max_light_level & DRM_INFORFRAME_META_MASK;
212 ptr[23] = (meta_des_1st->max_light_level >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
213 ptr[24] = meta_des_1st->average_light_level & DRM_INFORFRAME_META_MASK;
214 ptr[25] = (meta_des_1st->average_light_level >> DRM_INFORFRAME_META_OFFSET) & DRM_INFORFRAME_META_MASK;
215 hdmi_infoframe_checksum(buffer, length);
216
217 return length;
218 }
219 #endif
220
221 /*
222 * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
223 * @frame: HDMI audio infoframe
224 * @buffer: destination buffer
225 * @size: size of buffer
226 * packs the information contained in the @frame structure into a binary
227 * representation that can be written into the corresponding controller
228 * registers. also computes the checksum as required by section 5.3.5 of
229 * the HDMI 1.4 specification.
230 * returns the number of bytes packed into the binary buffer or a negative
231 * error code on failure.
232 */
hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe * frame,hi_void * buffer,hi_u32 size)233 static hi_s32 hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, hi_void *buffer, hi_u32 size)
234 {
235 hi_u32 length;
236 hi_u8 *ptr = HI_NULL;
237
238 ptr = buffer;
239 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
240 if (size < length) {
241 return -1;
242 }
243 (hi_void)memset_s(buffer, size, 0, size);
244
245 ptr[0] = frame->type;
246 ptr[1] = frame->version;
247 ptr[2] = frame->length;
248 ptr[3] = 0; /* checksum */
249
250 /* start infoframe payload */
251 ptr += HDMI_INFOFRAME_HEADER_SIZE;
252 ptr[0] = (((hi_u32)frame->coding_type & 0xf) << 4) | (frame->channels & 0x7); /* 4'b, bit[8:5] */
253 ptr[1] = (((hi_u32)frame->sample_frequency & 0x7) << 2) | ((hi_u32)frame->sample_size & 0x3); /* 2'b, bit[5:3] */
254 ptr[2] = (hi_u32)frame->coding_type_ext & 0x1f;
255 ptr[3] = frame->channel_allocation;
256 ptr[4] = (frame->level_shift_value & 0xf) << 3; /* 3'b, bit[7:4] */
257 ptr[4] |= (hi_u32)frame->lfe_playback_level & 0x3;
258 if (frame->downmix_inhibit) {
259 hdmi_set_bit(ptr[4], 7); /* 7'b, bit[8] */
260 }
261 hdmi_infoframe_checksum(buffer, length);
262
263 return length;
264 }
265
266 /*
267 * hdmi_vendor_specific_infoframe_pack() - write a HDMI vendor infoframe to binary buffer
268 * @frame: HDMI vendor infoframe
269 * @buffer: destination buffer
270 * @size: size of buffer
271 * packs the information contained in the @frame structure into a binary
272 * representation that can be written into the corresponding controller
273 * registers. also computes the checksum as required by section 5.3.5 of
274 * the HDMI 1.4 specification.
275 * returns the number of bytes packed into the binary buffer or a negative
276 * error code on failure.
277 */
hdmi_vendor_specific_infoframe_pack(struct hdmi_vendor_specific_infoframe * frame,hi_void * buffer,hi_u32 size)278 static hi_s32 hdmi_vendor_specific_infoframe_pack(struct hdmi_vendor_specific_infoframe *frame,
279 hi_void *buffer, hi_u32 size)
280 {
281 errno_t ret;
282 hi_u32 length;
283 hi_u8 *ptr = HI_NULL;
284
285 ptr = buffer;
286 length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
287 if (size < length) {
288 return -1;
289 }
290 (hi_void)memset_s(buffer, size, 0, size);
291
292 ptr[0] = frame->type;
293 ptr[1] = frame->version;
294 ptr[2] = frame->length;
295 ptr[3] = 0; /* checksum */
296
297 if (frame->vsif_content.h14_vsif_content.ieee == HDMI14_IEEE_OUI) {
298 hdmi_14_vsif_content *vsif_content = &frame->vsif_content.h14_vsif_content;
299 hdmi_user_vsif_content *user_content = &frame->vsif_content.cea861_vsif;
300
301 /* IEEE OUI */
302 ptr[4] = HDMI14_IEEE_OUI & 0xff;
303 ptr[5] = (HDMI14_IEEE_OUI >> 8) & 0xff; /* 8'b, bit[16:9] */
304 ptr[6] = (HDMI14_IEEE_OUI >> 16) & 0xff; /* 16'b, bit[8:1] */
305 /* hdmi video format */
306 ptr[7] = ((hi_u32)vsif_content->format & 0x7) << 5; /* 5'b, bit[8:6] */
307 if (vsif_content->format == HDMI_VIDEO_FORMAT_4K) {
308 ptr[8] = vsif_content->vic;
309 } else if (vsif_content->format == HDMI_VIDEO_FORMAT_3D) {
310 ptr[8] = ((hi_u32)vsif_content->_3d_structure & 0xf) << 4; /* 4'b, bit[8:5] */
311 }
312 /* if the 3D_Meta_present bit is clear(=0),mean that there have no 3D_Metadata */
313 if (vsif_content->_3d_meta_present == 0) {
314 /* have user data */
315 if ((user_content->len != 0) && (length + user_content->len <= size)) {
316 ptr[2] += user_content->len;
317 ret = memcpy_s(&ptr[length], (size - length), user_content->data, user_content->len);
318 hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
319 length += user_content->len;
320 }
321 }
322 }
323 hdmi_infoframe_checksum(buffer, length);
324
325 return length;
326 }
327
drv_hdmi_infoframe_send(hdmi_infoframe_type * info_frame,hdmi_infoframe_id infoframe_id,hdmi_infoframe * infoframe)328 hi_void drv_hdmi_infoframe_send(hdmi_infoframe_type *info_frame,
329 hdmi_infoframe_id infoframe_id, hdmi_infoframe *infoframe)
330 {
331 hi_u8 buffer[HDMI_INFOFRAME_BUFFER_SIZE] = {0};
332 hdmi_device *hdmi_dev = HI_NULL;
333
334 hdmi_if_null_return_void(info_frame);
335 hdmi_if_null_return_void(infoframe);
336
337 hdmi_dev = osal_container_of(info_frame, __typeof__(*hdmi_dev), info_frame);
338 hdmi_if_null_return_void(hdmi_dev);
339
340 /* pack infoframe */
341 switch (infoframe_id) {
342 case HDMI_INFOFRAME_TYPE_VENDOR:
343 infoframe->vendor_infoframe.type = HDMI_INFOFRAME_TYPE_VENDOR;
344 infoframe->vendor_infoframe.version = 1;
345 hdmi_vendor_specific_infoframe_pack(&infoframe->vendor_infoframe, buffer, HDMI_INFOFRAME_BUFFER_SIZE);
346 break;
347 case HDMI_INFOFRAME_TYPE_AVI:
348 infoframe->avi_infoframe.type = HDMI_INFOFRAME_TYPE_AVI;
349 infoframe->avi_infoframe.version = 2; /* avi infoframe version is 1 */
350 infoframe->avi_infoframe.length = AVI_INFORFRAME_LENGTH;
351 hdmi_avi_infoframe_pack(&infoframe->avi_infoframe, buffer, HDMI_INFOFRAME_BUFFER_SIZE,
352 hdmi_dev->attr.vo_attr.stereo_mode);
353 break;
354 case HDMI_INFOFRAME_TYPE_AUDIO:
355 infoframe->audio_infoframe.type = HDMI_INFOFRAME_TYPE_AUDIO;
356 infoframe->audio_infoframe.version = 1;
357 infoframe->audio_infoframe.length = AUDIO_INFORFRAME_LENGTH;
358 hdmi_audio_infoframe_pack(&infoframe->audio_infoframe, buffer, HDMI_INFOFRAME_BUFFER_SIZE);
359 break;
360 #ifdef HDMI_HDR_SUPPORT
361 case HDMI_INFOFRAME_TYPE_DRM:
362 infoframe->drm_infoframe.type = HDMI_INFOFRAME_TYPE_DRM;
363 infoframe->drm_infoframe.version = 1;
364 infoframe->drm_infoframe.length = DYN_RAN_INFORFRAME_LENGTH;
365 hdmi_drm_infoframe_pack(&infoframe->drm_infoframe, buffer, HDMI_INFOFRAME_BUFFER_SIZE);
366 break;
367 #endif
368 default:
369 return;
370 }
371 drv_hdmi_infoframe_enable_set(info_frame, infoframe_id, HI_FALSE);
372 hal_call_void(hal_hdmi_infoframe_set, hdmi_dev->hal, infoframe_id, buffer, HDMI_INFOFRAME_BUFFER_SIZE);
373 drv_hdmi_infoframe_enable_set(info_frame, infoframe_id, HI_TRUE);
374
375 return;
376 }
377
drv_hdmi_infoframe_enable_set(hdmi_infoframe_type * info_frame,hdmi_infoframe_id infoframe_id,hi_bool enable)378 hi_void drv_hdmi_infoframe_enable_set(hdmi_infoframe_type *info_frame, hdmi_infoframe_id infoframe_id,
379 hi_bool enable)
380 {
381 hdmi_device *hdmi_dev = HI_NULL;
382
383 hdmi_if_null_return_void(info_frame);
384
385 hdmi_dev = osal_container_of(info_frame, __typeof__(*hdmi_dev), info_frame);
386 hal_call_void(hal_hdmi_infoframe_enable_set, hdmi_dev->hal, infoframe_id, enable);
387
388 return;
389 }
390
391 #ifdef HDMI_HDR_SUPPORT
drv_hdmi_drm_infoframe_send(hdmi_infoframe_type * info_frame,hi_bool enable)392 hi_s32 drv_hdmi_drm_infoframe_send(hdmi_infoframe_type *info_frame, hi_bool enable)
393 {
394 errno_t ret;
395 hdmi_infoframe infoframe = {0};
396 hdmi_device *hdmi_dev = HI_NULL;
397 drv_hdmi_hdr_attr *hdr_attr = HI_NULL;
398 hdmi_drm_infoframe *drm_infoframe = HI_NULL;
399
400 hdmi_if_null_return(info_frame, HI_FAILURE);
401
402 if (!enable) {
403 drv_hdmi_infoframe_enable_set(info_frame, HDMI_INFOFRAME_TYPE_DRM, HI_FALSE);
404 return HI_SUCCESS;
405 }
406 hdmi_dev = osal_container_of(info_frame, __typeof__(*hdmi_dev), info_frame);
407 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
408
409 hdr_attr = &hdmi_dev->attr.hdr_attr;
410 drm_infoframe = &info_frame->drm_infoframe;
411 (hi_void)memset_s(drm_infoframe, sizeof(info_frame->drm_infoframe), 0, sizeof(hdmi_drm_infoframe));
412 drm_infoframe->eotf_type = hdr_attr->eotf_type;
413 drm_infoframe->metadata_type = hdr_attr->metadata_id;
414 drm_infoframe->meta_descriptor = hdr_attr->un_descriptor;
415 ret = memcpy_s(&infoframe.drm_infoframe, sizeof(infoframe.drm_infoframe),
416 drm_infoframe, sizeof(hdmi_drm_infoframe));
417 hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
418 drv_hdmi_infoframe_send(info_frame, HDMI_INFOFRAME_TYPE_DRM, &infoframe);
419
420 return HI_SUCCESS;
421 }
422 #endif
423
424 #ifdef HDMI_HDR_SUPPORT
avi_hdr_send(hdmi_avi_infoframe * avi_infoframe,hdmi_attr * attr)425 static hi_void avi_hdr_send(hdmi_avi_infoframe *avi_infoframe, hdmi_attr *attr)
426 {
427 drv_hdmi_hdr_attr *hdr_attr = HI_NULL;
428 hdmi_vo_attr *vo_attr = HI_NULL;
429 hdmi_app_attr *app_attr = HI_NULL;
430
431 hdr_attr = &attr->hdr_attr;
432 app_attr = &attr->app_attr;
433 vo_attr = &attr->vo_attr;
434 switch (hdr_attr->hdr_mode) {
435 case HDMI_HDR_MODE_CEA_861_3:
436 case HDMI_HDR_MODE_CEA_861_3_AUTHEN:
437 avi_infoframe->colorimetry = vo_attr->colorimetry;
438 avi_infoframe->extended_colorimetry = vo_attr->extended_colorimetry;
439 avi_infoframe->colorspace = app_attr->out_color_space;
440 if (hdr_attr->hdr_mode == HDMI_HDR_MODE_CEA_861_3_AUTHEN) {
441 avi_infoframe->colorspace = HDMI_COLORSPACE_YCBCR422;
442 }
443 avi_infoframe->quantization_range = vo_attr->rgb_quantization;
444 avi_infoframe->ycc_quantization_range = vo_attr->ycc_quantization;
445 hdmi_info("HDR mode, avi infoframe force to change outcolorspace(%u), extended_colorimetry(%u).\n",
446 avi_infoframe->colorspace, avi_infoframe->extended_colorimetry);
447 break;
448 case HDMI_HDR_MODE_DOLBY_NORMAL:
449 avi_infoframe->colorspace = HDMI_COLORSPACE_YCBCR422;
450 avi_infoframe->colorimetry = app_attr->xvycc_mode ? HDMI_COLORIMETRY_EXTEND : vo_attr->colorimetry;
451 avi_infoframe->extended_colorimetry = vo_attr->extended_colorimetry;
452 avi_infoframe->quantization_range = vo_attr->rgb_quantization;
453 avi_infoframe->ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_FULL;
454 hdmi_info("dolby normal, avi infoframe force to change outcolorspace(%u), ycc_quantization_range(%u).\n",
455 avi_infoframe->colorspace, avi_infoframe->ycc_quantization_range);
456 break;
457 case HDMI_HDR_MODE_DOLBY_TUNNELING:
458 avi_infoframe->colorspace = HDMI_COLORSPACE_RGB;
459 avi_infoframe->colorimetry = app_attr->xvycc_mode ? HDMI_COLORIMETRY_EXTEND : vo_attr->colorimetry;
460 avi_infoframe->extended_colorimetry = vo_attr->extended_colorimetry;
461 avi_infoframe->quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
462 avi_infoframe->ycc_quantization_range = vo_attr->ycc_quantization;
463 hdmi_info("dolby tunnel, avi infoframe force to change outcolorspace(%u), quantization_range(%u).\n",
464 avi_infoframe->colorspace, avi_infoframe->quantization_range);
465 break;
466 default:
467 avi_infoframe->extended_colorimetry = vo_attr->extended_colorimetry;
468 avi_infoframe->quantization_range = vo_attr->rgb_quantization;
469 avi_infoframe->ycc_quantization_range = vo_attr->ycc_quantization;
470 avi_infoframe->colorspace = app_attr->out_color_space;
471 avi_infoframe->colorimetry = app_attr->xvycc_mode ? HDMI_COLORIMETRY_EXTEND : vo_attr->colorimetry;
472 break;
473 }
474
475 return;
476 }
477 #endif
478
drv_hdmi_avi_infoframe_send(hdmi_infoframe_type * info_frame,hi_bool enable)479 hi_s32 drv_hdmi_avi_infoframe_send(hdmi_infoframe_type *info_frame, hi_bool enable)
480 {
481 errno_t ret;
482 hdmi_infoframe infoframe = {0};
483 hdmi_device *hdmi_dev = HI_NULL;
484 hdmi_vo_attr *vo_attr = HI_NULL;
485 hdmi_avi_infoframe *avi_infoframe = HI_NULL;
486
487 hdmi_if_null_return(info_frame, HI_FAILURE);
488 if (!enable) {
489 drv_hdmi_infoframe_enable_set(info_frame, HDMI_INFOFRAME_TYPE_AVI, HI_FALSE);
490 return HI_SUCCESS;
491 }
492
493 hdmi_dev = osal_container_of(info_frame, __typeof__(*hdmi_dev), info_frame);
494 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
495 vo_attr = &hdmi_dev->attr.vo_attr;
496
497 avi_infoframe = &info_frame->avi_infoframe;
498 (hi_void)memset_s(avi_infoframe, sizeof(info_frame->avi_infoframe), 0, sizeof(hdmi_avi_infoframe));
499 avi_infoframe->disp_fmt = vo_attr->disp_fmt;
500 avi_infoframe->video_timing = vo_attr->video_timing;
501 avi_infoframe->picture_aspect = vo_attr->picture_aspect;
502 avi_infoframe->active_aspect = vo_attr->active_aspect;
503 avi_infoframe->nups = vo_attr->picture_scaling;
504 avi_infoframe->pixel_repeat = vo_attr->pixel_repeat;
505 avi_infoframe->active_info_valid = HI_TRUE;
506
507 #ifdef HDMI_HDR_SUPPORT
508 avi_hdr_send(avi_infoframe, &hdmi_dev->attr);
509 #else
510 avi_infoframe->extended_colorimetry = vo_attr->extended_colorimetry;
511 avi_infoframe->quantization_range = vo_attr->rgb_quantization;
512 avi_infoframe->ycc_quantization_range = vo_attr->ycc_quantization;
513 avi_infoframe->colorspace = hdmi_dev->attr.app_attr.out_color_space;
514 avi_infoframe->colorimetry = hdmi_dev->attr.app_attr.xvycc_mode ? HDMI_COLORIMETRY_EXTEND : vo_attr->colorimetry;
515 #endif
516 ret = memcpy_s(&infoframe.avi_infoframe, sizeof(infoframe.avi_infoframe),
517 avi_infoframe, sizeof(hdmi_avi_infoframe));
518 hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
519 drv_hdmi_infoframe_send(info_frame, HDMI_INFOFRAME_TYPE_AVI, &infoframe);
520
521 return HI_SUCCESS;
522 }
523
vsif_length(const hdmi_14_vsif_content * h14_vsif_content,hi_bool dolby_enable)524 static hi_u8 vsif_length(const hdmi_14_vsif_content *h14_vsif_content, hi_bool dolby_enable)
525 {
526 hi_u8 length;
527
528 #ifdef HDMI_HDR_SUPPORT
529 if (dolby_enable) {
530 length = 0x18;
531 } else if (h14_vsif_content->format == HDMI_VIDEO_FORMAT_4K) {
532 length = 0x05;
533 } else if (h14_vsif_content->format == HDMI_VIDEO_FORMAT_3D) {
534 length = 0x07;
535 } else {
536 length = 0x04;
537 }
538 #else
539 length = 0x07;
540
541 hi_unused(h14_vsif_content);
542 hi_unused(dolby_enable);
543 #endif
544
545 return length;
546 }
547
drv_hdmi_vendor_infoframe_send(hdmi_infoframe_type * info_frame,hi_bool enable,hi_bool dolby_enable)548 hi_s32 drv_hdmi_vendor_infoframe_send(hdmi_infoframe_type *info_frame, hi_bool enable, hi_bool dolby_enable)
549 {
550 errno_t ret;
551 hdmi_infoframe infoframe = {0};
552 hdmi_vo_attr *vo_attr = HI_NULL;
553 hdmi_device *hdmi_dev = HI_NULL;
554 hdmi_vendor_infoframe *vsif = HI_NULL;
555 hdmi_14_vsif_content *h14_vsif_content = HI_NULL;
556 hi_u32 vic, cnt;
557 hdmi_video_4k_def *video = HI_NULL;
558
559 hdmi_if_null_return(info_frame, HI_FAILURE);
560
561 if (!enable) {
562 drv_hdmi_infoframe_enable_set(info_frame, HDMI_INFOFRAME_TYPE_VENDOR, HI_FALSE);
563 return HI_SUCCESS;
564 }
565 hdmi_dev = osal_container_of(info_frame, __typeof__(*hdmi_dev), info_frame);
566 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
567
568 vo_attr = &hdmi_dev->attr.vo_attr;
569 vsif = &info_frame->vendor_infoframe;
570 (hi_void)memset_s(vsif, sizeof(info_frame->vendor_infoframe), 0, sizeof(hdmi_vendor_infoframe));
571
572 h14_vsif_content = &vsif->vsif_content.h14_vsif_content;
573 h14_vsif_content->ieee = HDMI14_IEEE_OUI;
574 vic = drv_hdmi_vic_search(vo_attr->video_timing, vo_attr->picture_aspect, HI_FALSE); // find the real vic
575 if (((vic >= HDMI_3840X2160P24_16_9 && vic <= HDMI_3840X2160P30_16_9) || vic == HDMI_4096X2160P24_256_135) &&
576 vo_attr->stereo_mode == HDMI_3D_BUTT) {
577 h14_vsif_content->format = HDMI_VIDEO_FORMAT_4K;
578 for (cnt = 0; cnt <= CEA861_F_VIDEO_CODES_MAX_4K; cnt++) {
579 video = drv_hdmi_video_codes_4k_get(cnt);
580 if (video != HI_NULL && video->timing == vo_attr->video_timing) {
581 h14_vsif_content->vic = video->hdmi_vic;
582 break;
583 }
584 }
585 } else if (vo_attr->stereo_mode < HDMI_3D_BUTT) { // common 3D
586 h14_vsif_content->format = HDMI_VIDEO_FORMAT_3D;
587 h14_vsif_content->_3d_structure = vo_attr->stereo_mode;
588 } else {
589 h14_vsif_content->format = HDMI_VIDEO_FORMAT_NONE;
590 h14_vsif_content->_3d_structure = vo_attr->stereo_mode;
591 }
592 vsif->length = vsif_length(h14_vsif_content, dolby_enable);
593 /* add user vendor data */
594 vsif->vsif_content.cea861_vsif.len = hdmi_dev->vendor_data.len;
595 ret = memcpy_s(vsif->vsif_content.cea861_vsif.data, HDMI_VENDOR_USER_DATA_MAX_LEN,
596 hdmi_dev->vendor_data.data, hdmi_dev->vendor_data.len);
597 hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
598 ret = memcpy_s(&infoframe.vendor_infoframe, sizeof(hdmi_vendor_infoframe), vsif, sizeof(*vsif));
599 hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
600 drv_hdmi_infoframe_send(info_frame, HDMI_INFOFRAME_TYPE_VENDOR, &infoframe);
601
602 return HI_SUCCESS;
603 }
604
drv_hdmi_audio_infoframe_send(hdmi_infoframe_type * info_frame,hi_bool enable)605 hi_s32 drv_hdmi_audio_infoframe_send(hdmi_infoframe_type *info_frame, hi_bool enable)
606 {
607 errno_t ret;
608 hdmi_infoframe infoframe = {0};
609 hdmi_ao_attr *ao_attr = HI_NULL;
610 hdmi_device *hdmi_dev = HI_NULL;
611 hdmi_audio_infoframe *audio_infoframe = HI_NULL;
612
613 hdmi_if_null_return(info_frame, HI_FAILURE);
614
615 if (!enable) {
616 drv_hdmi_infoframe_enable_set(info_frame, HDMI_INFOFRAME_TYPE_AUDIO, HI_FALSE);
617 return HI_SUCCESS;
618 }
619 hdmi_dev = osal_container_of(info_frame, __typeof__(*hdmi_dev), info_frame);
620 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
621
622 ao_attr = &hdmi_dev->attr.ao_attr;
623 audio_infoframe = &info_frame->audio_infoframe;
624 (hi_void)memset_s(audio_infoframe, sizeof(info_frame->audio_infoframe), 0, sizeof(hdmi_audio_infoframe));
625
626 if (ao_attr->sound_intf == HDMI_AUDIO_INTF_SPDIF || ao_attr->sound_intf == HDMI_AUDIO_INTF_HBRA) {
627 hdmi_info("audio channel refer to stream \n");
628 } else {
629 hdmi_info("audio channel %u \n", ao_attr->channels);
630 audio_infoframe->channels = (ao_attr->channels >= 2) ? (ao_attr->channels - 1) : 0; /* 2,1,0, channels number */
631 }
632
633 if (ao_attr->audio_code == HDMI_AUDIO_CODING_TYPE_AC3 || ao_attr->audio_code == HDMI_AUDIO_CODING_TYPE_DTS ||
634 ao_attr->audio_code == HDMI_AUDIO_CODING_TYPE_EAC3 || ao_attr->audio_code == HDMI_AUDIO_CODING_TYPE_DTS_HD) {
635 audio_infoframe->coding_type = ao_attr->audio_code;
636 } else {
637 audio_infoframe->coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
638 }
639 hdmi_info("aduio code : %u \n", ao_attr->audio_code);
640
641 switch (ao_attr->channels) {
642 case HDMI_AUDIO_FORMAT_3CH:
643 audio_infoframe->channel_allocation = 0x01; /* 1 channel */
644 break;
645 case HDMI_AUDIO_FORMAT_6CH:
646 audio_infoframe->channel_allocation = 0x0b; /* 3, 4 channel */
647 break;
648 case HDMI_AUDIO_FORMAT_8CH:
649 audio_infoframe->channel_allocation = 0x13; /* 1, 2, 5 channel */
650 break;
651 default:
652 audio_infoframe->channel_allocation = 0x00; /* 0 channel */
653 break;
654 }
655 ret = memcpy_s(&infoframe.audio_infoframe, sizeof(infoframe.audio_infoframe),
656 audio_infoframe, sizeof(hdmi_audio_infoframe));
657 hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
658 drv_hdmi_infoframe_send(info_frame, HDMI_INFOFRAME_TYPE_AUDIO, &infoframe);
659
660 return HI_SUCCESS;
661 }
662
drv_hdmi_null_packet_send(hdmi_infoframe_type * info_frame,hi_bool enable)663 hi_s32 drv_hdmi_null_packet_send(hdmi_infoframe_type *info_frame, hi_bool enable)
664 {
665 hdmi_if_null_return(info_frame, HI_FAILURE);
666 drv_hdmi_infoframe_enable_set(info_frame, HDMI_INFOFRAME_TYPE_NULL, enable);
667 return HI_SUCCESS;
668 }
669
670