• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "hdf_log.h"
10 #include "hdmi_core.h"
11 #include "securec.h"
12 
13 #define HDF_LOG_TAG hdmi_hdr_c
14 
HdmiHdrAttrChange(struct HdmiHdrAttr * curAttr,struct HdmiHdrAttr * oldAttr)15 static bool HdmiHdrAttrChange(struct HdmiHdrAttr *curAttr, struct HdmiHdrAttr *oldAttr)
16 {
17     if (memcmp(curAttr, oldAttr, sizeof(struct HdmiHdrAttr)) == 0) {
18         return false;
19     }
20     return true;
21 }
22 
HdmiHdrColorimetryUpdate(struct HdmiVideoAttr * videoAttr,enum HdmiHdrColormetry colorimetry)23 static void HdmiHdrColorimetryUpdate(struct HdmiVideoAttr *videoAttr, enum HdmiHdrColormetry colorimetry)
24 {
25     if (colorimetry >= HDMI_HDR_COLORIMETRY_EXTENDED) {
26         videoAttr->colorimetry = HDMI_COLORIMETRY_EXTENDED;
27         videoAttr->extColorimetry = (enum HdmiExtendedColorimetry)(colorimetry -
28             HDMI_HDR_EXTENDED_COLORIMETRY_XV_YCC_601);
29     } else {
30         videoAttr->colorimetry = (enum HdmiColorimetry)colorimetry;
31         videoAttr->extColorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
32     }
33 }
34 
HdmiHdrZeroDrmInfoFrameTimerSet(struct HdmiCntlr * cntlr,bool start)35 static void HdmiHdrZeroDrmInfoFrameTimerSet(struct HdmiCntlr *cntlr, bool start)
36 {
37     struct HdmiHdrInfo *hdrInfo = &(cntlr->hdr->info);
38     struct HdmiHdrAttr *hdrAttr = &(cntlr->attr.hdrAttr);
39 
40     hdrInfo->zeroDrmIfTimer.start = false;
41     hdrInfo->zeroDrmIfTimer.timerType = HDMI_HDR_TIMER_ZERO_DRMIF;
42     hdrInfo->zeroDrmIfTimer.time = HDMI_ZERO_DRMIF_SEND_TIME;
43     HdmiCntlrHdrTimerSet(cntlr, &(hdrInfo->zeroDrmIfTimer));
44     if (start == false) {
45         return;
46     }
47 
48     hdrAttr->eotfType = HDMI_EOTF_SDR_LUMIN;
49     hdrAttr->metadataType = HDMI_DRM_STATIC_METADATA_TYPE_1;
50     if (memset_s(&(hdrAttr->descriptor), sizeof(hdrAttr->descriptor), 0, sizeof(hdrAttr->descriptor)) != EOK) {
51         HDF_LOGE("memset_s fail");
52         return;
53     }
54     (void)HdmiDrmInfoFrameSend(&(cntlr->infoFrame), true);
55 
56     hdrInfo->zeroDrmIfTimer.start = true;
57     HdmiCntlrHdrTimerSet(cntlr, &(hdrInfo->zeroDrmIfTimer));
58 }
59 
HdmiHdrModeChangeTimerSet(struct HdmiCntlr * cntlr,bool start)60 static void HdmiHdrModeChangeTimerSet(struct HdmiCntlr *cntlr, bool start)
61 {
62     struct HdmiHdrInfo *hdrInfo = &(cntlr->hdr->info);
63 
64     hdrInfo->stateChangeTimer.start = false;
65     hdrInfo->stateChangeTimer.timerType = HDMI_HDR_TIMER_SDR_TO_HDR10;
66     hdrInfo->stateChangeTimer.time = HDMI_HDR_STATE_CHANGE_TIME;
67     HdmiCntlrHdrTimerSet(cntlr, &(hdrInfo->stateChangeTimer));
68     if (start == false) {
69         return;
70     }
71 
72     hdrInfo->stateChangeTimer.start = true;
73     HdmiCntlrHdrTimerSet(cntlr, &(hdrInfo->stateChangeTimer));
74 }
75 
HdmiDisableHdr(struct HdmiCntlr * cntlr,const struct HdmiHdrAttr * curAttr)76 static int32_t HdmiDisableHdr(struct HdmiCntlr *cntlr, const struct HdmiHdrAttr *curAttr)
77 {
78     int32_t ret = HDF_SUCCESS;
79     struct HdmiHdrAttr *oldAttr = &(cntlr->attr.hdrAttr);
80     struct HdmiVideoAttr *videoAttr = &(cntlr->attr.videoAttr);
81     struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr);
82     struct HdmiHdrInfo *hdrInfo = &(cntlr->hdr->info);
83 
84     switch (oldAttr->mode) {
85         case HDMI_HDR_MODE_DISABLE:
86             break;
87         case HDMI_HDR_MODE_CEA_861_3:
88             *oldAttr = *curAttr;
89             if (hdrInfo->state != HDMI_HDR_STATE_NONE) {
90                 /* to solve the problem of some TV can not switch smoothly from HDR10 to non-HDR10. */
91                 if (hdrInfo->state == HDMI_HDR_STATE_OE) {
92                     HdmiCntlrAudioMuteEnable(cntlr, false);
93                     HdmiCntlrBlackDataSet(cntlr, true);
94                 }
95                 HdmiCntlrAvmuteSet(cntlr, true);
96                 if (hdrInfo->state == HDMI_HDR_STATE_OE) {
97                     HdmiCntlrPhyOutputEnablet(cntlr, false);
98                 }
99                 HdmiHdrModeChangeTimerSet(cntlr,  true);
100                 HdmiCntlrHdrTimerSet(cntlr, &(hdrInfo->stateChangeTimer));
101                 (void)HdmiDrmInfoFrameSend(&(cntlr->infoFrame), false);
102             } else {
103                 /* start timer, send zero DRMIF and stop after 2 seconds. */
104                 HdmiHdrZeroDrmInfoFrameTimerSet(cntlr,  true);
105             }
106             break;
107         case HDMI_HDR_MODE_CEA_861_3_AUTHEN:
108         case HDMI_HDR_MODE_DOLBY_NORMAL:
109         case HDMI_HDR_MODE_DOLBY_TUNNELING:
110             if (oldAttr->mode != HDMI_HDR_MODE_DOLBY_NORMAL) {
111                 commAttr->colorSpace = HDMI_COLOR_SPACE_YCBCR444;
112             }
113             videoAttr->quantization = HDMI_QUANTIZATION_RANGE_DEFAULT;
114             videoAttr->yccQuantization = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
115             break;
116         default:
117             ret = HDF_FAILURE;
118             break;
119     }
120     return ret;
121 }
122 
HdmiChangeToHdr(struct HdmiCntlr * cntlr,struct HdmiCommonAttr * commAttr)123 static void HdmiChangeToHdr(struct HdmiCntlr *cntlr, struct HdmiCommonAttr *commAttr)
124 {
125     struct HdmiHdrAttr *hdrAttr = &(cntlr->attr.hdrAttr);
126     struct HdmiHdrInfo *hdrInfo = &(cntlr->hdr->info);
127 
128     HdmiHdrZeroDrmInfoFrameTimerSet(cntlr, false);
129     if (hdrAttr->userMode != HDMI_HDR_USERMODE_HDR10) {
130         HDF_LOGE("usermode is not HDR10/HLG.");
131         return;
132     }
133     commAttr->drm = true;
134 
135     if (hdrInfo->state != HDMI_HDR_STATE_NONE) {
136         /* to solve the problem of some TV can not switch smoothly from non-HDR10 to HDR10. */
137         if (hdrInfo->state == HDMI_HDR_STATE_OE) {
138             HdmiCntlrAudioMuteEnable(cntlr, false);
139             HdmiCntlrBlackDataSet(cntlr, true);
140         }
141         HdmiCntlrAvmuteSet(cntlr, true);
142         if (hdrInfo->state == HDMI_HDR_STATE_OE) {
143             HdmiCntlrPhyOutputEnablet(cntlr, false);
144         }
145         hdrInfo->stateChangeTimer.start = true;
146         hdrInfo->stateChangeTimer.timerType = HDMI_HDR_TIMER_SDR_TO_HDR10;
147         hdrInfo->stateChangeTimer.time = HDMI_HDR_STATE_CHANGE_TIME;
148         HdmiCntlrHdrTimerSet(cntlr, &(hdrInfo->stateChangeTimer));
149     }
150 }
151 
HdmiHdrModeSelect(struct HdmiCntlr * cntlr)152 static int32_t HdmiHdrModeSelect(struct HdmiCntlr *cntlr)
153 {
154     struct HdmiHdrAttr *hdrAttr = &(cntlr->attr.hdrAttr);
155     struct HdmiCommonAttr *commAttr = &(cntlr->attr.commAttr);
156 
157     switch (hdrAttr->mode) {
158         case HDMI_HDR_MODE_CEA_861_3:
159             HdmiChangeToHdr(cntlr, commAttr);
160             commAttr->vsifDolby = false;
161             break;
162         case HDMI_HDR_MODE_CEA_861_3_AUTHEN:
163             /* HDR10 authen mode, HDMI must bypass. */
164             if (hdrAttr->userMode != HDMI_HDR_USERMODE_DOLBY) {
165                 HDF_LOGE("user mode is not dolby");
166                 return HDF_FAILURE;
167             }
168             commAttr->drm = true;
169             commAttr->vsifDolby = false;
170             break;
171         case HDMI_HDR_MODE_DOLBY_NORMAL:
172         case HDMI_HDR_MODE_DOLBY_TUNNELING:
173             if (hdrAttr->userMode != HDMI_HDR_USERMODE_DOLBY) {
174                 HDF_LOGE("user mode is not dolby");
175                 return HDF_FAILURE;
176             }
177             commAttr->drm = false;
178             commAttr->vsifDolby = true;
179             break;
180         default:
181             return HDF_FAILURE;
182     }
183 
184     return HDF_SUCCESS;
185 }
186 
HdmiHdrAttrHandle(struct HdmiHdr * hdr,struct HdmiHdrAttr * curAttr)187 int32_t HdmiHdrAttrHandle(struct HdmiHdr *hdr, struct HdmiHdrAttr *curAttr)
188 {
189     struct HdmiHdrAttr *oldAttr = NULL;
190     struct HdmiCommonAttr *commAttr = NULL;
191     struct HdmiCntlr *cntlr = NULL;
192     int32_t ret = HDF_FAILURE;
193 
194     if (hdr == NULL || hdr->priv == NULL) {
195         HDF_LOGE("hdr attr handle, input param invalid.");
196         return HDF_ERR_INVALID_PARAM;
197     }
198 
199     cntlr = (struct HdmiCntlr *)hdr->priv;
200     oldAttr = &(cntlr->attr.hdrAttr);
201     commAttr = &(cntlr->attr.commAttr);
202     if (HdmiHdrAttrChange(curAttr, oldAttr) == false) {
203         HDF_LOGD("hdr attr not change");
204         return HDF_SUCCESS;
205     }
206     if (oldAttr->colorimetry != curAttr->colorimetry) {
207         HdmiHdrColorimetryUpdate(&(cntlr->attr.videoAttr), curAttr->colorimetry);
208     }
209 
210     /* change to SDR */
211     if (curAttr->mode == HDMI_HDR_MODE_DISABLE) {
212         if (HdmiDisableHdr(cntlr, curAttr) == HDF_SUCCESS) {
213             commAttr->vsifDolby = false;
214             cntlr->attr.hdrAttr = *curAttr;
215             (void)HdmiAviInfoFrameSend(&(cntlr->infoFrame), (commAttr->enableHdmi && commAttr->avi));
216             (void)HdmiVsInfoFrameSend(&(cntlr->infoFrame), commAttr->enableHdmi, commAttr->vsifDolby);
217             HdmiCntlrVideoPathSet(cntlr, &(cntlr->attr.videoAttr));
218             return ret;
219         } else {
220             return HDF_FAILURE;
221         }
222     }
223 
224     /* change to HDR */
225     cntlr->attr.hdrAttr = *curAttr;
226     ret = HdmiHdrModeSelect(cntlr);
227     if (ret != HDF_SUCCESS) {
228         return ret;
229     }
230     (void)HdmiDrmInfoFrameSend(&(cntlr->infoFrame), (commAttr->enableHdmi && commAttr->drm));
231     (void)HdmiAviInfoFrameSend(&(cntlr->infoFrame), (commAttr->enableHdmi && commAttr->avi));
232     (void)HdmiVsInfoFrameSend(&(cntlr->infoFrame), commAttr->enableHdmi, commAttr->vsifDolby);
233     HdmiCntlrVideoPathSet(cntlr, &(cntlr->attr.videoAttr));
234     return ret;
235 }
236 
HdmiHdrDrmInfoFrameStop(struct HdmiHdr * hdr)237 int32_t HdmiHdrDrmInfoFrameStop(struct HdmiHdr *hdr)
238 {
239     struct HdmiCntlr *cntlr = NULL;
240 
241     HDF_LOGD("zero DRM infoFrame send timeout.");
242     if (hdr == NULL || hdr->priv == NULL) {
243         HDF_LOGE("hdr stop drm, input param invalid.");
244         return HDF_ERR_INVALID_PARAM;
245     }
246     cntlr = (struct HdmiCntlr *)hdr->priv;
247 
248     if (cntlr->attr.hdrAttr.mode != HDMI_HDR_MODE_CEA_861_3) {
249         return HdmiDrmInfoFrameSend(&(cntlr->infoFrame), false);
250     }
251     return HDF_SUCCESS;
252 }
253 
HdmiHdrModeChangeTimeout(struct HdmiHdr * hdr)254 int32_t HdmiHdrModeChangeTimeout(struct HdmiHdr *hdr)
255 {
256     struct HdmiCntlr *cntlr = NULL;
257 
258     HDF_LOGD("hdr mode change timeout.");
259     if (hdr == NULL || hdr->priv == NULL) {
260         HDF_LOGE("hdr mode change timeout, input param invalid.");
261         return HDF_ERR_INVALID_PARAM;
262     }
263     cntlr = (struct HdmiCntlr *)hdr->priv;
264 
265     if (hdr->info.state == HDMI_HDR_STATE_OE) {
266         HdmiCntlrPhyOutputEnablet(cntlr, true);
267     }
268     HdmiCntlrAvmuteSet(cntlr, false);
269     if (hdr->info.state == HDMI_HDR_STATE_OE) {
270         HdmiCntlrBlackDataSet(cntlr, false);
271         HdmiCntlrAudioMuteEnable(cntlr, true);
272     }
273     return HDF_SUCCESS;
274 }
275