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