• 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_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(&param, 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(&param) == 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