• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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