• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 
12 #define HDF_LOG_TAG hdmi_scdc_c
13 
14 #define HDMI_SCDC_READ_SOURCE_VERSION_TIMES 2
15 
HdmiScdcRead(const struct HdmiScdc * scdc,enum HdmiScdcsOffset offset,uint8_t * buffer,uint32_t len)16 static int32_t HdmiScdcRead(const struct HdmiScdc *scdc, enum HdmiScdcsOffset offset, uint8_t *buffer, uint32_t len)
17 {
18     struct HdmiDdcCfg cfg = {0};
19     struct HdmiCntlr *cntlr = NULL;
20 
21     if (scdc == NULL || scdc->priv == NULL) {
22         return HDF_ERR_INVALID_PARAM;
23     }
24 
25     cntlr = (struct HdmiCntlr *)scdc->priv;
26     cfg.type = HDMI_DDC_DEV_SCDC;
27     cfg.readFlag = true;
28     cfg.devAddr = HDMI_DDC_SCDC_DEV_ADDRESS;
29     cfg.data = buffer;
30     cfg.dataLen = len;
31     cfg.offset = offset;
32     cfg.mode = HDMI_DDC_MODE_READ_MUTIL_NO_ACK;
33     return HdmiDdcTransfer(&(cntlr->ddc), &cfg);
34 }
35 
HdmiScdcWrite(const struct HdmiScdc * scdc,enum HdmiScdcsOffset offset,uint8_t * buffer,uint32_t len)36 static int32_t HdmiScdcWrite(const struct HdmiScdc *scdc, enum HdmiScdcsOffset offset, uint8_t *buffer, uint32_t len)
37 {
38     struct HdmiDdcCfg cfg = {0};
39     struct HdmiCntlr *cntlr = NULL;
40 
41     if (scdc == NULL || scdc->priv == NULL) {
42         return HDF_ERR_INVALID_PARAM;
43     }
44 
45     cntlr = (struct HdmiCntlr *)scdc->priv;
46     cfg.type = HDMI_DDC_DEV_SCDC;
47     cfg.readFlag = false;
48     cfg.devAddr = HDMI_DDC_SCDC_DEV_ADDRESS;
49     cfg.data = buffer;
50     cfg.dataLen = len;
51     cfg.offset = offset;
52     cfg.mode = HDMI_DDC_MODE_WRITE_MUTIL_ACK;
53     return HdmiDdcTransfer(&(cntlr->ddc), &cfg);
54 }
55 
HdmiScdcReadByte(const struct HdmiScdc * scdc,enum HdmiScdcsOffset offset,uint8_t * byte)56 static int32_t HdmiScdcReadByte(const struct HdmiScdc *scdc, enum HdmiScdcsOffset offset, uint8_t *byte)
57 {
58     return HdmiScdcRead(scdc, offset, byte, sizeof(*byte));
59 }
60 
HdmiScdcWriteByte(const struct HdmiScdc * scdc,enum HdmiScdcsOffset offset,uint8_t * byte)61 static int32_t HdmiScdcWriteByte(const struct HdmiScdc *scdc, enum HdmiScdcsOffset offset, uint8_t *byte)
62 {
63     return HdmiScdcWrite(scdc, offset, byte, sizeof(*byte));
64 }
65 
66 /* read opt */
HdmiScdcReadSinkVersion(const struct HdmiScdc * scdc,uint8_t * sinkVer)67 static int32_t HdmiScdcReadSinkVersion(const struct HdmiScdc *scdc, uint8_t *sinkVer)
68 {
69     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_SINK_VERSION, sinkVer);
70 }
71 
HdmiScdcReadSourceVersion(const struct HdmiScdc * scdc,uint8_t * srcVer)72 static int32_t HdmiScdcReadSourceVersion(const struct HdmiScdc *scdc, uint8_t *srcVer)
73 {
74     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_SOURCE_VERSION, srcVer);
75 }
76 
HdmiScdcReadUpdate0(const struct HdmiScdc * scdc,uint8_t * flag)77 static int32_t HdmiScdcReadUpdate0(const struct HdmiScdc *scdc, uint8_t *flag)
78 {
79     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_UPDATE_0, flag);
80 }
81 
HdmiScdcReadScramblerStatus(const struct HdmiScdc * scdc,uint8_t * status)82 static int32_t HdmiScdcReadScramblerStatus(const struct HdmiScdc *scdc, uint8_t *status)
83 {
84     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_SCRAMBLER_STATUS, status);
85 }
86 
HdmiScdcReadTmdsConfig(const struct HdmiScdc * scdc,uint8_t * tmdsCfg)87 static int32_t HdmiScdcReadTmdsConfig(const struct HdmiScdc *scdc, uint8_t *tmdsCfg)
88 {
89     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_TMDS_CONFIG, tmdsCfg);
90 }
91 
HdmiScdcReadConfig0(const struct HdmiScdc * scdc,uint8_t * cfg)92 int32_t HdmiScdcReadConfig0(const struct HdmiScdc *scdc, uint8_t *cfg)
93 {
94     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_CONFIG_0, cfg);
95 }
96 
HdmiScdcReadConfig1(const struct HdmiScdc * scdc,uint8_t * cfg)97 static int32_t HdmiScdcReadConfig1(const struct HdmiScdc *scdc, uint8_t *cfg)
98 {
99     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_CONFIG_1, cfg);
100 }
101 
HdmiScdcReadTestConfig0(const struct HdmiScdc * scdc,uint8_t * testCfg)102 int32_t HdmiScdcReadTestConfig0(const struct HdmiScdc *scdc, uint8_t *testCfg)
103 {
104     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_TEST_CONFIG_0, testCfg);
105 }
106 
HdmiScdcReadTestConfig1(const struct HdmiScdc * scdc,uint8_t * testCfg)107 static int32_t HdmiScdcReadTestConfig1(const struct HdmiScdc *scdc, uint8_t *testCfg)
108 {
109     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_TEST_CONFIG_1, testCfg);
110 }
111 
HdmiScdcReadStatusFlag0(const struct HdmiScdc * scdc,uint8_t * flag)112 static int32_t HdmiScdcReadStatusFlag0(const struct HdmiScdc *scdc, uint8_t *flag)
113 {
114     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_STASTUS_FLAG_0, flag);
115 }
116 
HdmiScdcReadStatusFlag1(const struct HdmiScdc * scdc,uint8_t * flag)117 int32_t HdmiScdcReadStatusFlag1(const struct HdmiScdc *scdc, uint8_t *flag)
118 {
119     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_STASTUS_FLAG_1, flag);
120 }
121 
HdmiScdcReadStatusFlag2(const struct HdmiScdc * scdc,uint8_t * flag)122 int32_t HdmiScdcReadStatusFlag2(const struct HdmiScdc *scdc, uint8_t *flag)
123 {
124     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_STASTUS_FLAG_2, flag);
125 }
126 
127 /* write opt */
HdmiScdcWriteSourceVersion(const struct HdmiScdc * scdc,uint8_t * srcVer)128 static int32_t HdmiScdcWriteSourceVersion(const struct HdmiScdc *scdc, uint8_t *srcVer)
129 {
130     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_SOURCE_VERSION, srcVer);
131 }
132 
HdmiScdcWriteUpdate0(const struct HdmiScdc * scdc,uint8_t * flag)133 static int32_t HdmiScdcWriteUpdate0(const struct HdmiScdc *scdc, uint8_t *flag)
134 {
135     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_UPDATE_0, flag);
136 }
137 
HdmiScdcWriteTmdsConfig(const struct HdmiScdc * scdc,uint8_t * tmdsCfg)138 static int32_t HdmiScdcWriteTmdsConfig(const struct HdmiScdc *scdc, uint8_t *tmdsCfg)
139 {
140     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_TMDS_CONFIG, tmdsCfg);
141 }
142 
HdmiScdcWriteConfig0(const struct HdmiScdc * scdc,uint8_t * cfg)143 static int32_t HdmiScdcWriteConfig0(const struct HdmiScdc *scdc, uint8_t *cfg)
144 {
145     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_CONFIG_0, cfg);
146 }
147 
HdmiScdcWriteConfig1(const struct HdmiScdc * scdc,uint8_t * cfg)148 static int32_t HdmiScdcWriteConfig1(const struct HdmiScdc *scdc, uint8_t *cfg)
149 {
150     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_CONFIG_1, cfg);
151 }
152 
HdmiScdcWriteTestConfig0(const struct HdmiScdc * scdc,uint8_t * testCfg)153 static int32_t HdmiScdcWriteTestConfig0(const struct HdmiScdc *scdc, uint8_t *testCfg)
154 {
155     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_TEST_CONFIG_0, testCfg);
156 }
157 
158 /* cntlr ops */
HdmiCntlrScdcSourceScrambleGet(struct HdmiCntlr * cntlr)159 static bool HdmiCntlrScdcSourceScrambleGet(struct HdmiCntlr *cntlr)
160 {
161     bool ret = false;
162 
163     if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->scdcSourceScrambleGet == NULL) {
164         return ret;
165     }
166     HdmiCntlrLock(cntlr);
167     ret = cntlr->ops->scdcSourceScrambleGet(cntlr);
168     HdmiCntlrUnlock(cntlr);
169     return ret;
170 }
171 
HdmiCntlrScdcSourceScrambleSet(struct HdmiCntlr * cntlr,bool enable)172 static int32_t HdmiCntlrScdcSourceScrambleSet(struct HdmiCntlr *cntlr, bool enable)
173 {
174     int32_t ret;
175 
176     if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->scdcSourceScrambleSet == NULL) {
177         return HDF_ERR_INVALID_OBJECT;
178     }
179     HdmiCntlrLock(cntlr);
180     ret = cntlr->ops->scdcSourceScrambleSet(cntlr, enable);
181     HdmiCntlrUnlock(cntlr);
182     return ret;
183 }
184 
185 /* scdc opt */
HdmiScdcRrDisable(struct HdmiScdc * scdc)186 int32_t HdmiScdcRrDisable(struct HdmiScdc *scdc)
187 {
188     union HdmiScdcsConfig0 cfg = {0};
189     union HdmiScdcsTestConfig0 testCfg = {0};
190     int32_t ret;
191 
192     if (scdc == NULL) {
193         return HDF_ERR_INVALID_PARAM;
194     }
195 
196     ret = HdmiScdcWriteConfig0(scdc, &(cfg.data));
197     if (ret != HDF_SUCCESS) {
198         HDF_LOGE("scdc write config0 fail");
199         return ret;
200     }
201     scdc->status.cfg0 = cfg;
202 
203     ret = HdmiScdcWriteTestConfig0(scdc, &(testCfg.data));
204     if (ret != HDF_SUCCESS) {
205         HDF_LOGE("scdc write test config0 fail");
206         return ret;
207     }
208     scdc->status.testCfg0 = testCfg;
209     return HDF_SUCCESS;
210 }
211 
HdmiScdcScrambleSet(struct HdmiScdc * scdc,struct HdmiScdcScrambleCap * scramble)212 int32_t HdmiScdcScrambleSet(struct HdmiScdc *scdc, struct HdmiScdcScrambleCap *scramble)
213 {
214     union HdmiScdcsTmdsConfig cfg = {0};
215     int32_t ret;
216 
217     if (scdc == NULL) {
218         return HDF_ERR_INVALID_PARAM;
219     }
220 
221     ret = HdmiCntlrScdcSourceScrambleSet((struct HdmiCntlr *)scdc->priv, scramble->sourceScramble);
222     if (ret != HDF_SUCCESS) {
223         HDF_LOGE("scdc source scrambler set fail");
224         return ret;
225     }
226 
227     if (scramble->sinkScramble == true) {
228         cfg.bits.scramblingEnable = 1;
229     }
230     if (scramble->tmdsBitClockRatio40 == true) {
231         cfg.bits.tmdsBitClockRatio = 1;
232     }
233     ret = HdmiScdcWriteTmdsConfig(scdc, &(cfg.data));
234     if (ret != HDF_SUCCESS) {
235         HDF_LOGE("scdc write tmds config fail");
236         return ret;
237     }
238     return HDF_SUCCESS;
239 }
240 
HdmiScdcScrambleGet(struct HdmiScdc * scdc,struct HdmiScdcScrambleCap * scramble)241 int32_t HdmiScdcScrambleGet(struct HdmiScdc *scdc, struct HdmiScdcScrambleCap *scramble)
242 {
243     union HdmiScdcsScramblerStatus status = {0};
244     union HdmiScdcsTmdsConfig cfg = {0};
245     int32_t ret;
246 
247     if (scdc == NULL) {
248         return HDF_ERR_INVALID_PARAM;
249     }
250 
251     ret = HdmiScdcReadScramblerStatus(scdc, &(status.data));
252     if (ret != HDF_SUCCESS) {
253         HDF_LOGE("scdc read scrambler status fail");
254         return ret;
255     }
256     scramble->sinkScramble = (status.bits.scramblingStatus ? true : false);
257 
258     ret = HdmiScdcReadTmdsConfig(scdc, &(cfg.data));
259     if (ret != HDF_SUCCESS) {
260         HDF_LOGE("scdc read tmds config fail");
261         return ret;
262     }
263     scramble->tmdsBitClockRatio40 = (cfg.bits.tmdsBitClockRatio ? true : false);
264     scramble->sourceScramble = HdmiCntlrScdcSourceScrambleGet(scdc->priv);
265 
266     scdc->status.tmdsCfg = cfg;
267     scdc->status.scramblerStatus = status;
268     return HDF_SUCCESS;
269 }
270 
HdmiScdcSinkSupport(struct HdmiScdc * scdc)271 bool HdmiScdcSinkSupport(struct HdmiScdc *scdc)
272 {
273     uint8_t srcVer;
274     uint8_t i;
275     int32_t ret;
276 
277     if (scdc == NULL) {
278         return HDF_ERR_INVALID_PARAM;
279     }
280 
281     for (i = 0; i < HDMI_SCDC_READ_SOURCE_VERSION_TIMES; i++) {
282         srcVer = HDMI_SCDC_HDMI20_VERSION;
283         ret = HdmiScdcWriteSourceVersion(scdc, &srcVer);
284         if (ret != HDF_SUCCESS) {
285             HDF_LOGE("scdc write source version fail");
286             return false;
287         }
288         ret = HdmiScdcReadSourceVersion(scdc, &srcVer);
289         if (ret != HDF_SUCCESS) {
290             HDF_LOGE("scdc read source version fail");
291             return false;
292         }
293     }
294     scdc->status.sourceVersion = HDMI_SCDC_HDMI20_VERSION;
295     return true;
296 }
297 
HdmiScdcOptMsgHandle(const struct HdmiScdc * scdc,enum HdmiScdcOptMsg msg,uint8_t * buffer,uint32_t len)298 int32_t HdmiScdcOptMsgHandle(const struct HdmiScdc *scdc, enum HdmiScdcOptMsg msg, uint8_t *buffer, uint32_t len)
299 {
300     int32_t ret;
301 
302     if (scdc == NULL || buffer == NULL || len == 0) {
303         return HDF_ERR_INVALID_PARAM;
304     }
305 
306     switch (msg) {
307         case HDMI_SCDC_OPT_SET_SOURCE_VER:
308             ret = HdmiScdcWriteSourceVersion(scdc, buffer);
309             break;
310         case HDMI_SCDC_OPT_GET_SOURCE_VER:
311             ret = HdmiScdcReadSourceVersion(scdc, buffer);
312             break;
313         case HDMI_SCDC_OPT_GET_SINK_VER:
314             ret = HdmiScdcReadSinkVersion(scdc, buffer);
315             break;
316         case HDMI_SCDC_OPT_SET_FLT_UPDATE:
317         case HDMI_SCDC_OPT_SET_FRL_START:
318             ret = HdmiScdcWriteUpdate0(scdc, buffer);
319             break;
320         case HDMI_SCDC_OPT_GET_FLT_UPDATE:
321         case HDMI_SCDC_OPT_GET_FRL_START:
322             ret = HdmiScdcReadUpdate0(scdc, buffer);
323             break;
324         case HDMI_SCDC_OPT_SET_CONFIG1:
325             ret = HdmiScdcWriteConfig1(scdc, buffer);
326             break;
327         case HDMI_SCDC_OPT_GET_CONFIG1:
328             ret = HdmiScdcReadConfig1(scdc, buffer);
329             break;
330         case HDMI_SCDC_OPT_GET_TEST_CONFIG_1:
331             ret = HdmiScdcReadTestConfig1(scdc, buffer);
332             break;
333         case HDMI_SCDC_OPT_GET_FLT_READY:
334             ret = HdmiScdcReadStatusFlag0(scdc, buffer);
335             break;
336         case HDMI_SCDC_OPT_GET_LTP_REQ:
337             ret = HdmiScdcRead(scdc, HDMI_SCDCS_OFFSET_STASTUS_FLAG_1, buffer, len);
338             break;
339         default:
340             HDF_LOGE("scdc msg handle, msg %d not support.", msg);
341             ret = HDF_ERR_NOT_SUPPORT;
342             break;
343     }
344 
345     return ret;
346 }
347 
HdmiScdcFillScrambleCap(struct HdmiScdc * scdc,struct HdmiScdcScrambleCap * scramble,enum HdmiTmdsModeType * tmdsMode)348 int32_t HdmiScdcFillScrambleCap(struct HdmiScdc *scdc, struct HdmiScdcScrambleCap *scramble,
349     enum HdmiTmdsModeType *tmdsMode)
350 {
351     struct HdmiCntlr *cntlr = NULL;
352     struct HdmiCommonAttr *commAttr = NULL;
353     struct HdmiVideoAttr *videoAttr = NULL;
354 
355     if (scdc == NULL || scdc->priv == NULL || scramble == NULL || tmdsMode == NULL) {
356         HDF_LOGD("scdc fill scramble cap: param is null");
357         return HDF_ERR_INVALID_PARAM;
358     }
359 
360     cntlr = (struct HdmiCntlr *)scdc->priv;
361     commAttr = &(cntlr->attr.commAttr);
362     videoAttr = &(cntlr->attr.videoAttr);
363     if (commAttr->enableHdmi == false) {
364         /* DVI mode */
365         *tmdsMode = HDMI_TMDS_MODE_DVI;
366         scramble->sinkScramble = false;
367         scramble->sourceScramble = false;
368         scramble->tmdsBitClockRatio40 = false;
369         if (videoAttr->tmdsClock > HDMI_HDMI14_MAX_TMDS_RATE) {
370             HDF_LOGE("tmds clock %u can't support in DVI mode.", videoAttr->tmdsClock);
371             return HDF_ERR_INVALID_PARAM;
372         }
373     } else if (videoAttr->tmdsClock > HDMI_HDMI14_MAX_TMDS_RATE) {
374         *tmdsMode = HDMI_TMDS_MODE_HDMI_2_0;
375         scramble->sinkScramble   = true;
376         scramble->sourceScramble = true;
377         scramble->tmdsBitClockRatio40 = true;
378     } else {
379         *tmdsMode = HDMI_TMDS_MODE_HDMI_1_4;
380         scramble->sinkScramble   = false;
381         scramble->sourceScramble = false;
382         scramble->tmdsBitClockRatio40 = false;
383     }
384     return HDF_SUCCESS;
385 }
386