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_common.h"
11 #include "hdmi_core.h"
12 #include "hdmi_dfm.h"
13 #include "hdmi_ncts.h"
14
15 #define HDMI_FRL_TRAIN_STEP_RESULT_HANDLE_MAX_TRIES 3
16 #define HDMI_FRL_TRAIN_STEP_READR_CHECK_MAX_TRIES 10
17 #define HDMI_FRL_CHECK_SINK_STATUS_DELAY_TIME 2000
18
19 #define HDF_LOG_TAG hdmi_frl_c
20
HdmiFrlGetSinkVersion(struct HdmiScdc * scdc)21 static uint8_t HdmiFrlGetSinkVersion(struct HdmiScdc *scdc)
22 {
23 uint8_t version = 0;
24
25 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_GET_SINK_VER, &version, sizeof(version)) != HDF_SUCCESS) {
26 HDF_LOGD("frl get sink version fail");
27 return 0;
28 }
29 return version;
30 }
31
HdmiFrlGetFltUpdate(struct HdmiScdc * scdc)32 static bool HdmiFrlGetFltUpdate(struct HdmiScdc *scdc)
33 {
34 bool fltUpdate = false;
35 uint8_t flag = 0;
36
37 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_GET_FLT_UPDATE, &flag, sizeof(flag)) != HDF_SUCCESS) {
38 HDF_LOGD("frl get flt update fail");
39 return fltUpdate;
40 }
41
42 fltUpdate = (flag & HDMI_SCDC_FLT_UPDATE_MARK) ? true : false;
43 return fltUpdate;
44 }
45
HdmiFrlGetFrlStart(struct HdmiScdc * scdc)46 static bool HdmiFrlGetFrlStart(struct HdmiScdc *scdc)
47 {
48 bool frlStart = false;
49 uint8_t flag = 0;
50
51 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_GET_FLT_UPDATE, &flag, sizeof(flag)) != HDF_SUCCESS) {
52 HDF_LOGD("frl get frl start fail");
53 return frlStart;
54 }
55
56 frlStart = (flag & HDMI_SCDC_FRL_START_MARK) ? true : false;
57 return frlStart;
58 }
59
HdmiFrlGetFltReady(struct HdmiScdc * scdc)60 static bool HdmiFrlGetFltReady(struct HdmiScdc *scdc)
61 {
62 bool fltReady = false;
63 uint8_t flag = 0;
64
65 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_GET_FLT_READY, &flag, sizeof(flag)) != HDF_SUCCESS) {
66 HDF_LOGD("frl get flt ready fail");
67 return fltReady;
68 }
69
70 fltReady = (flag & HDMI_SCDC_FLT_READY_MARK) ? true : false;
71 return fltReady;
72 }
73
HdmiFrlGetTestConfig1(struct HdmiScdc * scdc)74 static uint8_t HdmiFrlGetTestConfig1(struct HdmiScdc *scdc)
75 {
76 uint8_t cfg = 0;
77
78 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_GET_TEST_CONFIG_1, &cfg, sizeof(cfg)) != HDF_SUCCESS) {
79 HDF_LOGD("frl get test cfg1 fail");
80 return 0;
81 }
82 return cfg;
83 }
84
HdmiFrlSetFltUpdate(const struct HdmiScdc * scdc,bool fltUpdate)85 static void HdmiFrlSetFltUpdate(const struct HdmiScdc *scdc, bool fltUpdate)
86 {
87 uint8_t flag = 0;
88
89 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_GET_FLT_UPDATE, &flag, sizeof(flag)) != HDF_SUCCESS) {
90 HDF_LOGD("frl get flt update fail");
91 return;
92 }
93
94 if (fltUpdate == true) {
95 flag |= HDMI_SCDC_FLT_UPDATE_MARK;
96 } else {
97 flag &= (~HDMI_SCDC_FLT_UPDATE_MARK);
98 }
99 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_SET_FLT_UPDATE, &flag, sizeof(flag)) != HDF_SUCCESS) {
100 HDF_LOGD("frl set flt update fail");
101 }
102 }
103
HdmiFrlSetFrlStart(const struct HdmiScdc * scdc,bool frlStart)104 static void HdmiFrlSetFrlStart(const struct HdmiScdc *scdc, bool frlStart)
105 {
106 uint8_t flag = 0;
107
108 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_GET_FLT_UPDATE, &flag, sizeof(flag)) != HDF_SUCCESS) {
109 HDF_LOGD("frl get frl start fail");
110 return;
111 }
112
113 if (frlStart == true) {
114 flag |= HDMI_SCDC_FRL_START_MARK;
115 } else {
116 flag &= (~HDMI_SCDC_FRL_START_MARK);
117 }
118
119 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_GET_FLT_UPDATE, &flag, sizeof(flag)) != HDF_SUCCESS) {
120 HDF_LOGD("frl set frl start fail");
121 }
122 }
123
HdmiFrlSetConfig1(const struct HdmiScdc * scdc,uint8_t * data)124 static void HdmiFrlSetConfig1(const struct HdmiScdc *scdc, uint8_t *data)
125 {
126 if (HdmiScdcOptMsgHandle(scdc, HDMI_SCDC_OPT_SET_CONFIG1, data, sizeof(*data)) != HDF_SUCCESS) {
127 HDF_LOGD("frl set cfg1 fail");
128 }
129 }
130
HdmiFrlSetTrainRate(const struct HdmiFrl * frl)131 static void HdmiFrlSetTrainRate(const struct HdmiFrl *frl)
132 {
133 union HdmiScdcsConfig1 cfg = {0};
134 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
135
136 if (cntlr == NULL) {
137 HDF_LOGE("frl set train rate fail");
138 return;
139 }
140
141 if (frl->info.mode == HDMI_FRL_MODE_FRL) {
142 cfg.bits.frlRate = frl->info.curFrlRate;
143 cfg.bits.ffeLevels = HDMI_FRL_TXFFE_MODE_0;
144 }
145 HdmiFrlSetConfig1(cntlr->scdc, &(cfg.data));
146 }
147
HdmiFrlCheckFrlCapability(struct HdmiFrl * frl)148 static bool HdmiFrlCheckFrlCapability(struct HdmiFrl *frl)
149 {
150 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
151 uint8_t sinkScdcVerion;
152 uint8_t sinkMaxFrlRate;
153
154 sinkScdcVerion = HdmiFrlGetSinkVersion(cntlr->scdc);
155 if (HdmiEdidSupportFrl(cntlr->hdmi) != true ||
156 cntlr->cap.baseCap.bits.hdmi21 == 0 ||
157 cntlr->cap.baseCap.bits.frl == 0 ||
158 sinkScdcVerion == 0) {
159 frl->info.maxFrlRate = 0;
160 return HDF_ERR_NOT_SUPPORT;
161 }
162 sinkMaxFrlRate = HdmiEdidGetMaxFrlRate(cntlr->hdmi);
163 frl->info.maxFrlRate = (sinkMaxFrlRate > cntlr->cap.maxFrlRate) ? cntlr->cap.maxFrlRate : sinkMaxFrlRate;
164 return HDF_SUCCESS;
165 }
166
HdmiFrlCheckFrlStrategy(enum HdmiFrlStrategyMode strategy,uint32_t pixelClock,uint32_t tmdsClock,enum HdmiVideoFormatType formatType)167 static bool HdmiFrlCheckFrlStrategy(enum HdmiFrlStrategyMode strategy, uint32_t pixelClock,
168 uint32_t tmdsClock, enum HdmiVideoFormatType formatType)
169 {
170 bool support = true;
171
172 switch (strategy) {
173 case HDMI_FRL_STRATEGY_MODE_1:
174 if (pixelClock <= HDMI_HDMI20_MAX_TMDS_RATE && tmdsClock <= HDMI_HDMI20_MAX_TMDS_RATE) {
175 support = false;
176 }
177 break;
178 case HDMI_FRL_STRATEGY_MODE_2:
179 if (tmdsClock <= HDMI_HDMI14_MAX_TMDS_RATE) {
180 support = false;
181 }
182 break;
183 case HDMI_FRL_STRATEGY_MODE_3:
184 if (formatType == HDMI_VIDEO_FORMA_INTERLACE) {
185 support = false;
186 }
187 break;
188 default:
189 HDF_LOGE("strategy %d is not support", strategy);
190 break;
191 }
192 return support;
193 }
194
HdmiFrlFillRateInfo(uint32_t * frlBitRate,uint32_t * frlLaneNum,uint32_t frlRate)195 static void HdmiFrlFillRateInfo(uint32_t *frlBitRate, uint32_t *frlLaneNum, uint32_t frlRate)
196 {
197 *frlLaneNum = HDMI_FRL_4_LANES;
198 if (frlRate <= HDMI_FRL_WORK_MODE_3L6G) {
199 *frlLaneNum = HDMI_FRL_3_LANES;
200 }
201
202 switch (frlRate) {
203 case HDMI_FRL_WORK_MODE_3L3G:
204 *frlBitRate = HDMI_FRL_BIT_RATE_3;
205 break;
206 case HDMI_FRL_WORK_MODE_3L6G:
207 case HDMI_FRL_WORK_MODE_4L6G:
208 *frlBitRate = HDMI_FRL_BIT_RATE_6;
209 break;
210 case HDMI_FRL_WORK_MODE_4L8G:
211 *frlBitRate = HDMI_FRL_BIT_RATE_8;
212 break;
213 case HDMI_FRL_WORK_MODE_4L10G:
214 *frlBitRate = HDMI_FRL_BIT_RATE_10;
215 break;
216 case HDMI_FRL_WORK_MODE_4L12G:
217 *frlBitRate = HDMI_FRL_BIT_RATE_12;
218 break;
219 default:
220 break;
221 }
222 }
223
HdnmiFrlCheckFrlMode(struct HdmiFrl * frl)224 static bool HdnmiFrlCheckFrlMode(struct HdmiFrl *frl)
225 {
226 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
227 struct HdmiVideoDefInfo *videoInfo = NULL;
228 struct HdmiDfmParam param = {0};
229 bool enable3d;
230 uint32_t i;
231
232 enable3d = (cntlr->attr.videoAttr._3dStruct >= HDMI_VS_VIDEO_3D_BUTT) ? false : true;
233 videoInfo = HdmiCommonGetVideoDefInfo(cntlr->attr.videoAttr.timing, cntlr->attr.videoAttr.aspect, enable3d);
234 if (videoInfo == NULL) {
235 HDF_LOGD("have no this video param, use tmds to transmit.");
236 return false;
237 }
238 HDF_LOGD("use frl to transmit, vic is %d.", videoInfo->vic);
239
240 frl->info.tmdsClock = cntlr->attr.videoAttr.tmdsClock;
241 if (HdmiFrlCheckFrlStrategy(frl->info.strategy, cntlr->attr.videoAttr.pixelClock,
242 frl->info.tmdsClock, videoInfo->formatType) == false) {
243 return false;
244 }
245
246 if (frl->info.maxFrlRate > HDMI_FRL_WORK_MODE_4L12G) {
247 HDF_LOGD("max frl rate is wrong(%u)", frl->info.maxFrlRate);
248 frl->info.maxFrlRate = HDMI_FRL_WORK_MODE_4L12G;
249 return true;
250 }
251
252 /* Check whether a particular video format can be transmitted in a particular FRL configuration. */
253 HdmiDfmFillParam(¶m, videoInfo, &(cntlr->attr.audioAttr), cntlr->attr.commAttr.colorSpace,
254 cntlr->attr.commAttr.deepColor);
255 for (i = frl->info.maxFrlRate; i > 0; i--) {
256 HdmiFrlFillRateInfo(&(param.bitRate), &(param.laneNum), i);
257 if (HdmiDfmFormatSupport(¶m) == true) {
258 frl->info.minFrlRate = i;
259 HDF_LOGD("min_rate: %d", i);
260 } else {
261 break;
262 }
263 }
264 if (i == frl->info.maxFrlRate) {
265 return false;
266 }
267 return true;
268 }
269
HdmiFrlIsCtsMode(struct HdmiFrl * frl)270 static bool HdmiFrlIsCtsMode(struct HdmiFrl *frl)
271 {
272 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
273 union HdmiScdcsTestConfig1 cfg = {0};
274
275 cfg.data = HdmiFrlGetTestConfig1(cntlr->scdc);
276 if ((cfg.bits.frlMax > 0 && cfg.bits.dscFrlMax == 0) ||
277 (cfg.bits.frlMax == 0 && cfg.bits.dscFrlMax > 0)) {
278 return true;
279 }
280 return false;
281 }
282
HdmiFrlGetCurRate(struct HdmiFrl * frl)283 static int32_t HdmiFrlGetCurRate(struct HdmiFrl *frl)
284 {
285 uint8_t curFrlrate = frl->info.curFrlRate;
286
287 if (frl->info.ctsMode == true) {
288 frl->info.preFrlRate = curFrlrate;
289 curFrlrate = frl->info.maxFrlRate;
290 } else {
291 if (frl->info.preFrlRate != 0) {
292 curFrlrate = frl->info.preFrlRate;
293 frl->info.preFrlRate = 0;
294 } else {
295 if (frl->info.rateSelect == HDMI_FRL_RATE_BIG) {
296 curFrlrate--;
297 } else {
298 curFrlrate++;
299 }
300 }
301 }
302
303 if ((curFrlrate > frl->info.maxFrlRate) ||
304 (curFrlrate < frl->info.minFrlRate)) {
305 return HDF_FAILURE;
306 }
307 frl->info.curFrlRate = curFrlrate;
308 return HDF_SUCCESS;
309 }
310
HdmiFrlAudioNctsSet(const struct HdmiFrl * frl)311 static void HdmiFrlAudioNctsSet(const struct HdmiFrl *frl)
312 {
313 struct HdmiFrlAudioNctsConfig cfg = {0};
314 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
315
316 if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->audioNctsSet == NULL) {
317 HDF_LOGD("not support set frl audio ncts.");
318 return;
319 }
320
321 cfg.mode = frl->info.mode;
322 cfg.sampleRate = cntlr->attr.audioAttr.sampleRate;
323 if (cfg.mode == HDMI_FRL_MODE_FRL) {
324 cfg.frlRate = frl->info.curFrlRate;
325 } else {
326 cfg.pixelClk = cntlr->attr.videoAttr.pixelClock;
327 cfg.n = HdmiGetN(cfg.sampleRate, cfg.pixelClk);
328 cfg.cts = HdmiGetCts(cfg.sampleRate, cfg.pixelClk);
329 }
330 HdmiCntlrLock(cntlr);
331 cntlr->ops->audioNctsSet(cntlr, &cfg);
332 HdmiCntlrUnlock(cntlr);
333 }
334
HdmiFrlTxffeSet(const struct HdmiFrl * frl)335 static void HdmiFrlTxffeSet(const struct HdmiFrl *frl)
336 {
337 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
338 struct HdmiPhyCfg cfg = {0};
339
340 if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->phyOutputSet == NULL) {
341 HDF_LOGD("not support phy output set.");
342 return;
343 }
344
345 cfg.modeCfg = HDMI_PHY_MODE_TXFFE;
346 cfg.rate = (enum HdmiFrlWorkMode)frl->info.curFrlRate;
347 HdmiCntlrLock(cntlr);
348 cntlr->ops->phyOutputSet(cntlr, &cfg);
349 HdmiCntlrUnlock(cntlr);
350 }
351
HdmiFrlphyConfigSet(const struct HdmiFrl * frl)352 static void HdmiFrlphyConfigSet(const struct HdmiFrl *frl)
353 {
354 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
355 struct HdmiPhyCfg cfg = {0};
356
357 if (cntlr == NULL || cntlr->ops == NULL) {
358 return;
359 }
360
361 cfg.tmdsClk = cntlr->attr.videoAttr.tmdsClock;
362 cfg.pixelClk = cntlr->attr.videoAttr.pixelClock;
363 cfg.deepColor = cntlr->attr.videoAttr.deepColor;
364 cfg.colorSpace = cntlr->attr.commAttr.colorSpace;
365 if (frl->info.mode == HDMI_FRL_MODE_FRL) {
366 cfg.modeCfg = HDMI_PHY_MODE_FRL;
367 cfg.rate = (enum HdmiFrlWorkMode)frl->info.curFrlRate;
368 }
369
370 if (cntlr->ops->phyOutputEnable != NULL) {
371 HdmiCntlrLock(cntlr);
372 cntlr->ops->phyOutputEnable(cntlr, false);
373 HdmiCntlrUnlock(cntlr);
374 }
375 if (cntlr->ops->phyOutputSet != NULL) {
376 HdmiCntlrLock(cntlr);
377 cntlr->ops->phyOutputSet(cntlr, &cfg);
378 HdmiCntlrUnlock(cntlr);
379 }
380 if (cntlr->ops->phyOutputEnable != NULL) {
381 HdmiCntlrLock(cntlr);
382 cntlr->ops->phyOutputEnable(cntlr, true);
383 HdmiCntlrUnlock(cntlr);
384 }
385 }
386
HdmiFrlStateMachineChangeState(struct HdmiFrl * frl,enum HdmiFrlTrainStep state)387 static void HdmiFrlStateMachineChangeState(struct HdmiFrl *frl, enum HdmiFrlTrainStep state)
388 {
389 /* change state machine's state */
390 frl->info.machineInfo.trainingState = state;
391 /* restart timer */
392 frl->info.machineInfo.startTime = OsalGetSysTimeMs();
393 }
394
HdmiFrlTrainingReadyCheck(struct HdmiFrl * frl)395 static void HdmiFrlTrainingReadyCheck(struct HdmiFrl *frl)
396 {
397 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
398
399 if (HdmiFrlGetFltReady(cntlr->scdc) == true) {
400 HDF_LOGD("step, ready chack pass, start training.");
401 HdmiFrlphyConfigSet(frl);
402 HdmiFrlSetTrainRate(frl);
403 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_START);
404 }
405 }
406
HdmiFrlConfigAndStartTraining(struct HdmiFrl * frl)407 static void HdmiFrlConfigAndStartTraining(struct HdmiFrl *frl)
408 {
409 struct HdmiFrlTrainConfig cfg = {0};
410 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
411 union HdmiScdcsTestConfig1 testCfg = {0};
412
413 if (cntlr == NULL || cntlr->ops == NULL) {
414 return;
415 }
416
417 cfg.frlRate = frl->info.curFrlRate;
418 cfg.txffe = HDMI_FRL_TXFFE_MODE_0;
419 testCfg.data = HdmiFrlGetTestConfig1(cntlr->scdc);
420 if (testCfg.bits.fltNoTimeout > 0) {
421 cfg.frlNoTimeout = true;
422 }
423 cfg.trainTimeout = frl->info.machineInfo.trainTimeout;
424
425 if (cntlr->ops->frlTrainingConfigSet != NULL) {
426 HdmiCntlrLock(cntlr);
427 cntlr->ops->frlTrainingConfigSet(cntlr, &cfg);
428 HdmiCntlrUnlock(cntlr);
429 }
430 if (cntlr->ops->frlEnable != NULL) {
431 HdmiCntlrLock(cntlr);
432 cntlr->ops->frlEnable(cntlr, false);
433 HdmiCntlrUnlock(cntlr);
434 }
435 if (cntlr->ops->frlTrainingStart != NULL) {
436 HdmiCntlrLock(cntlr);
437 cntlr->ops->frlTrainingStart(cntlr);
438 HdmiCntlrUnlock(cntlr);
439 }
440 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_RESULT_CHECK);
441 return;
442 }
443
HdmiFrlTrainingResultCheck(struct HdmiFrl * frl)444 static void HdmiFrlTrainingResultCheck(struct HdmiFrl *frl)
445 {
446 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
447 struct HdmiFrlTrainRslt rslt = {0};
448
449 if (cntlr != NULL && cntlr->ops != NULL && cntlr->ops->frlGetTriningRslt != NULL) {
450 cntlr->ops->frlGetTriningRslt(cntlr, &rslt);
451 }
452
453 if (rslt.status == HDMI_FRL_TRAIN_STATUS_SUCC) {
454 frl->info.trainingFailCnt = 0;
455 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_RESULT_HANDLE);
456 } else if (rslt.failReason == HDMI_FRL_TRAIN_FAIL_FFE_CHANGE) {
457 frl->info.trainingFailCnt = 0;
458 HdmiFrlTxffeSet(frl);
459 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_START);
460 } else if (rslt.failReason == HDMI_FRL_TRAIN_FAIL_RATE_CHANGE) {
461 frl->info.trainingFailCnt = 0;
462 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_RATE_CHANGE);
463 } else {
464 (frl->info.trainingFailCnt)++;
465 }
466 }
467
HdmiFrlTrainingException(struct HdmiFrl * frl)468 static void HdmiFrlTrainingException(struct HdmiFrl *frl)
469 {
470 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
471 struct HdmiPhyCfg cfg = {0};
472
473 if (cntlr == NULL || cntlr->ops == NULL) {
474 return;
475 }
476
477 if (cntlr->ops->phyOutputEnable != NULL) {
478 cntlr->ops->phyOutputEnable(cntlr, false);
479 }
480
481 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_STOP);
482 frl->info.start = false;
483 /* TMDS config. */
484 cfg.pixelClk = cntlr->attr.videoAttr.pixelClock;
485 cfg.tmdsClk = cntlr->attr.videoAttr.tmdsClock;
486 cfg.deepColor = cntlr->attr.videoAttr.deepColor;
487 cfg.modeCfg = HDMI_PHY_MODE_TMDS;
488 cfg.colorSpace = cntlr->attr.commAttr.colorSpace;
489 HDF_LOGD("FRL change to TMDS.");
490 if (cfg.tmdsClk > HDMI_HDMI20_MAX_TMDS_RATE) {
491 HDF_LOGE("TMDS clk > 600M. can't work TMDS mode.");
492 return;
493 }
494 frl->info.mode = HDMI_FRL_MODE_TMDS;
495 HdmiFrlSetTrainRate(frl);
496 HdmiFrlAudioNctsSet(frl);
497
498 if (cntlr->ops->phyOutputSet != NULL) {
499 cntlr->ops->phyOutputSet(cntlr, &cfg);
500 }
501 if (cntlr->ops->phyOutputEnable != NULL) {
502 cntlr->ops->phyOutputEnable(cntlr, true);
503 }
504 }
505
HdmiFrlTrainingRateChange(struct HdmiFrl * frl)506 static void HdmiFrlTrainingRateChange(struct HdmiFrl *frl)
507 {
508 frl->info.ctsMode = HdmiFrlIsCtsMode(frl);
509 if (HdmiFrlGetCurRate(frl) != HDF_SUCCESS) {
510 HDF_LOGE("FRL rate %u get failed!\n", frl->info.curFrlRate);
511 HdmiFrlTrainingException(frl);
512 return;
513 }
514 /* FRL rate change */
515 HdmiFrlphyConfigSet(frl);
516 HdmiFrlSetTrainRate(frl);
517 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_START);
518 }
519
HdmiFrlTrainingPassedCheck(struct HdmiFrl * frl)520 static void HdmiFrlTrainingPassedCheck(struct HdmiFrl *frl)
521 {
522 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
523
524 if (cntlr == NULL || cntlr->ops == NULL) {
525 return;
526 }
527
528 if (frl->info.start == false ||
529 HdmiFrlGetFrlStart(cntlr->scdc) == false) {
530 return;
531 }
532
533 HDF_LOGD("FRL training passed.");
534 frl->info.work = true;
535 /* n/cts config */
536 HdmiFrlAudioNctsSet(frl);
537 OsalMSleep(1);
538 if (cntlr->ops->phyOutputEnable != NULL) {
539 HdmiCntlrLock(cntlr);
540 cntlr->ops->phyOutputEnable(cntlr, frl->info.work);
541 HdmiCntlrUnlock(cntlr);
542 }
543 OsalMSleep(1);
544 HdmiFrlSetFrlStart(cntlr->scdc, true);
545 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_RETRAIN_CHECK);
546 }
547
HdmiFrlRetrainingCheck(struct HdmiFrl * frl)548 static void HdmiFrlRetrainingCheck(struct HdmiFrl *frl)
549 {
550 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
551
552 if (cntlr == NULL || cntlr->ops == NULL) {
553 return;
554 }
555 if (HdmiFrlGetFltUpdate(cntlr->scdc) == false) {
556 return;
557 }
558
559 HDF_LOGD("FRL retraining flt_update get OK");
560 HdmiFrlSetFltUpdate(cntlr->scdc, true);
561 frl->info.work = false;
562 if (cntlr->ops->phyOutputEnable != NULL) {
563 HdmiCntlrLock(cntlr);
564 cntlr->ops->phyOutputEnable(cntlr, frl->info.work);
565 HdmiCntlrUnlock(cntlr);
566 }
567 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_START);
568 }
569
HdmiFrlTrainingStop(struct HdmiFrl * frl)570 static void HdmiFrlTrainingStop(struct HdmiFrl *frl)
571 {
572 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
573
574 if (cntlr == NULL || cntlr->ops == NULL) {
575 return;
576 }
577
578 frl->info.work = false;
579 if (cntlr->ops->phyOutputEnable != NULL) {
580 HdmiCntlrLock(cntlr);
581 cntlr->ops->phyOutputEnable(cntlr, frl->info.work);
582 HdmiCntlrUnlock(cntlr);
583 }
584 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_BUTT);
585 }
586
HdmiFrlTrainingStateMachineHandle(struct HdmiFrl * frl)587 void HdmiFrlTrainingStateMachineHandle(struct HdmiFrl *frl)
588 {
589 if (frl == NULL) {
590 HDF_LOGE("FRL trining, not support FRL.");
591 return;
592 }
593
594 switch (frl->info.machineInfo.trainingState) {
595 case HDMI_FRL_TRAIN_STEP_READR_CHECK:
596 HdmiFrlTrainingReadyCheck(frl);
597 break;
598 case HDMI_FRL_TRAIN_STEP_TRAIN_START:
599 HdmiFrlConfigAndStartTraining(frl);
600 break;
601 case HDMI_FRL_TRAIN_STEP_RESULT_CHECK:
602 HdmiFrlTrainingResultCheck(frl);
603 break;
604 case HDMI_FRL_TRAIN_STEP_RATE_CHANGE:
605 HdmiFrlTrainingRateChange(frl);
606 break;
607 case HDMI_FRL_TRAIN_STEP_RESULT_HANDLE:
608 HdmiFrlTrainingPassedCheck(frl);
609 break;
610 case HDMI_FRL_TRAIN_STEP_RETRAIN_CHECK:
611 HdmiFrlRetrainingCheck(frl);
612 break;
613 case HDMI_FRL_TRAIN_STEP_TRAIN_STOP:
614 HdmiFrlTrainingStop(frl);
615 break;
616 default:
617 break;
618 }
619 }
620
HdmiFrlTrainingReadyCheckTimeout(struct HdmiFrl * frl)621 static void HdmiFrlTrainingReadyCheckTimeout(struct HdmiFrl *frl)
622 {
623 uint64_t curTime = OsalGetSysTimeMs();
624 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
625
626 if ((curTime - frl->info.machineInfo.startTime) > frl->info.machineInfo.waitReadyTime) {
627 if (HdmiFrlGetFltReady(cntlr->scdc) == true) {
628 HDF_LOGD("step, ready chack pass, start training.");
629 frl->info.machineInfo.timeoutCnt = 0;
630 HdmiFrlphyConfigSet(frl);
631 HdmiFrlSetTrainRate(frl);
632 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_START);
633 } else {
634 (frl->info.machineInfo.timeoutCnt)++;
635 /* */
636 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_READR_CHECK);
637 }
638 } else {
639 /* wait for a maximum of 10 times, (wait_ready_ms * 10) ms */
640 if (frl->info.machineInfo.timeoutCnt < HDMI_FRL_TRAIN_STEP_READR_CHECK_MAX_TRIES) {
641 return;
642 }
643 HDF_LOGD("FRL training READY_CHECK exception.");
644 frl->info.machineInfo.timeoutCnt = 0;
645 HdmiFrlTrainingException(frl);
646 }
647 }
648
HdmiFrlTrainingResultCheckTimeout(struct HdmiFrl * frl)649 static void HdmiFrlTrainingResultCheckTimeout(struct HdmiFrl *frl)
650 {
651 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
652 struct HdmiFrlTrainRslt rslt = {0};
653
654 if (cntlr != NULL && cntlr->ops != NULL && cntlr->ops->frlGetTriningRslt != NULL) {
655 cntlr->ops->frlGetTriningRslt(cntlr, &rslt);
656 }
657
658 if (rslt.status == HDMI_FRL_TRAIN_STATUS_SUCC) {
659 frl->info.trainingFailCnt = 0;
660 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_RESULT_HANDLE);
661 } else if (rslt.failReason == HDMI_FRL_TRAIN_FAIL_FFE_CHANGE) {
662 frl->info.trainingFailCnt = 0;
663 HdmiFrlTxffeSet(frl);
664 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_START);
665 } else if (rslt.failReason == HDMI_FRL_TRAIN_FAIL_RATE_CHANGE) {
666 frl->info.trainingFailCnt = 0;
667 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_RATE_CHANGE);
668 } else {
669 (frl->info.trainingFailCnt)++;
670 if (frl->info.trainingFailCnt > frl->info.trainingMaxFailTimes) {
671 frl->info.trainingFailCnt = 0;
672 HdmiFrlTrainingException(frl);
673 } else {
674 /* not reach max fail times, re-training. */
675 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_START);
676 }
677 }
678 }
679
HdmiFrlTrainingResultHandleTimeout(struct HdmiFrl * frl)680 static void HdmiFrlTrainingResultHandleTimeout(struct HdmiFrl *frl)
681 {
682 uint64_t curTime;
683 bool frlStart;
684 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
685
686 if (cntlr == NULL || cntlr->ops == NULL) {
687 return;
688 }
689
690 do {
691 frlStart = HdmiFrlGetFrlStart(cntlr->scdc);
692 if (frlStart == true && frl->info.start == true) {
693 frl->info.work = true;
694 /* n/cts config */
695 HdmiFrlAudioNctsSet(frl);
696 if (cntlr->ops->phyOutputEnable != NULL) {
697 cntlr->ops->phyOutputEnable(cntlr, frl->info.work);
698 }
699 HdmiFrlSetFrlStart(cntlr->scdc, true);
700 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_RETRAIN_CHECK);
701 break;
702 } else if (frlStart == false && HdmiFrlGetFltUpdate(cntlr->scdc) == true) {
703 HdmiFrlSetFltUpdate(cntlr->scdc, true);
704 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_START);
705 break;
706 }
707
708 curTime = OsalGetSysTimeMs();
709 if ((curTime - frl->info.machineInfo.startTime) > frl->info.machineInfo.waitHandleTime) {
710 (frl->info.machineInfo.timeoutCnt)++;
711 break;
712 }
713 /* check the sink's status every 2ms required by protocol */
714 OsalUDelay(HDMI_FRL_CHECK_SINK_STATUS_DELAY_TIME);
715 } while (true);
716
717 if (frl->info.machineInfo.timeoutCnt >= HDMI_FRL_TRAIN_STEP_RESULT_HANDLE_MAX_TRIES) {
718 HDF_LOGE("FRL training timeout.");
719 frl->info.machineInfo.timeoutCnt = 0;
720 HdmiFrlTrainingException(frl);
721 }
722 }
723
HdmiFrlRetrainingCheckTimeout(struct HdmiFrl * frl)724 static void HdmiFrlRetrainingCheckTimeout(struct HdmiFrl *frl)
725 {
726 uint64_t curTime = OsalGetSysTimeMs();
727 struct HdmiCntlr *cntlr = (struct HdmiCntlr *)frl->priv;
728
729 if (cntlr == NULL || cntlr->ops == NULL) {
730 return;
731 }
732 if ((curTime - frl->info.machineInfo.startTime) <= frl->info.machineInfo.waitRetrainTime) {
733 return;
734 }
735 if (HdmiFrlGetFltUpdate(cntlr->scdc) != true) {
736 return;
737 }
738
739 HdmiFrlSetFltUpdate(cntlr->scdc, true);
740 frl->info.work = true;
741 if (cntlr->ops->phyOutputEnable != NULL) {
742 cntlr->ops->phyOutputEnable(cntlr, frl->info.work);
743 }
744 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_TRAIN_START);
745 }
746
HdmiFrlTrainingStateMachineTimeoutHandle(struct HdmiFrl * frl)747 void HdmiFrlTrainingStateMachineTimeoutHandle(struct HdmiFrl *frl)
748 {
749 if (frl == NULL || frl->priv == NULL) {
750 HDF_LOGE("FRL trining, not support FRL.");
751 return;
752 }
753
754 switch (frl->info.machineInfo.trainingState) {
755 case HDMI_FRL_TRAIN_STEP_READR_CHECK:
756 HdmiFrlTrainingReadyCheckTimeout(frl);
757 break;
758 case HDMI_FRL_TRAIN_STEP_TRAIN_START:
759 HdmiFrlConfigAndStartTraining(frl);
760 break;
761 case HDMI_FRL_TRAIN_STEP_RESULT_CHECK:
762 HdmiFrlTrainingResultCheckTimeout(frl);
763 break;
764 case HDMI_FRL_TRAIN_STEP_RATE_CHANGE:
765 HdmiFrlTrainingRateChange(frl);
766 break;
767 case HDMI_FRL_TRAIN_STEP_RESULT_HANDLE:
768 HdmiFrlTrainingResultHandleTimeout(frl);
769 break;
770 case HDMI_FRL_TRAIN_STEP_RETRAIN_CHECK:
771 HdmiFrlRetrainingCheckTimeout(frl);
772 break;
773 case HDMI_FRL_TRAIN_STEP_TRAIN_STOP:
774 HdmiFrlTrainingStop(frl);
775 break;
776 default:
777 break;
778 }
779 }
780
HdmiFrlEnable(struct HdmiFrl * frl,bool enable)781 void HdmiFrlEnable(struct HdmiFrl *frl, bool enable)
782 {
783 if (frl == NULL || frl->priv == NULL) {
784 return;
785 }
786
787 frl->info.start = enable;
788 frl->info.machineInfo.start = enable;
789 frl->info.machineInfo.machineState = (enable == true) ? HDMI_FRL_STATE_MACHINE_START : HDMI_FRL_STATE_MACHINE_STOP;
790 frl->info.ctsMode = HdmiFrlIsCtsMode(frl);
791 if (frl->info.ctsMode == true) {
792 HdmiFrlGetCurRate(frl);
793 HDF_LOGD("frl cur rate %d", frl->info.curFrlRate);
794 }
795 HdmiFrlStateMachineChangeState(frl, HDMI_FRL_TRAIN_STEP_READR_CHECK);
796 }
797
HdmiFrlModeSelect(struct HdmiFrl * frl)798 int32_t HdmiFrlModeSelect(struct HdmiFrl *frl)
799 {
800 int32_t ret;
801 struct HdmiCntlr *cntlr = NULL;
802 struct HdmiVideoAttr *videoAttr = NULL;
803
804 if (frl == NULL || frl->priv == NULL) {
805 return HDF_ERR_INVALID_PARAM;
806 }
807
808 ret = HdmiFrlCheckFrlCapability(frl);
809 if (ret != HDF_SUCCESS) {
810 HDF_LOGD("frl check capability fail, change to TMDS.");
811 frl->info.mode = HDMI_FRL_MODE_TMDS;
812 return ret;
813 } else {
814 if (HdnmiFrlCheckFrlMode(frl) == true) {
815 HDF_LOGD("frl check frl mode succ.");
816 frl->info.mode = HDMI_FRL_MODE_FRL;
817 } else {
818 HDF_LOGD("frl check frl mode fail, change to TMDS.");
819 frl->info.mode = HDMI_FRL_MODE_TMDS;
820 }
821 }
822
823 cntlr = (struct HdmiCntlr *)frl->priv;
824 videoAttr = &(cntlr->attr.videoAttr);
825 if (frl->info.mode == HDMI_FRL_MODE_TMDS) {
826 if (videoAttr->tmdsClock > HDMI_HDMI20_MAX_TMDS_RATE) {
827 HDF_LOGE("FRL mode select, tmds Clock exceed max.");
828 return HDF_FAILURE;
829 }
830 if (HdmiEdidScdcSupport(cntlr->hdmi) == true) {
831 HdmiFrlSetTrainRate(frl);
832 }
833 return HDF_SUCCESS;
834 }
835
836 /* FRL mode. */
837 frl->info.curFrlRate = (frl->info.rateSelect == HDMI_FRL_RATE_BIG) ?
838 frl->info.maxFrlRate : frl->info.minFrlRate;
839 cntlr->tmdsMode = HDMI_TMDS_MODE_HDMI_2_0;
840 if (cntlr->ops != NULL && cntlr->ops->tmdsModeSet != NULL) {
841 HdmiCntlrLock(cntlr);
842 cntlr->ops->tmdsModeSet(cntlr, cntlr->tmdsMode);
843 HdmiCntlrUnlock(cntlr);
844 }
845 frl->info.ctsMode = false;
846 return HDF_SUCCESS;
847 }
848
HdmiFrlModeChanged(struct HdmiFrl * frl)849 bool HdmiFrlModeChanged(struct HdmiFrl *frl)
850 {
851 if (frl == NULL) {
852 return false;
853 }
854
855 if (frl->info.perMode != frl->info.mode) {
856 frl->info.perMode = frl->info.mode;
857 return true;
858 }
859 return false;
860 }
861
HdmiFrlSupport(struct HdmiFrl * frl)862 bool HdmiFrlSupport(struct HdmiFrl *frl)
863 {
864 if (frl == NULL) {
865 return false;
866 }
867
868 if (frl->info.mode == HDMI_FRL_MODE_FRL) {
869 return true;
870 }
871 return false;
872 }
873