• 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 
12 #define HDF_LOG_TAG hdmi_scdc_c
13 
14 #define HDMI_SCDC_READ_SOURCE_VERSION_TIMES 2
15 
HdmiScdcRead(struct HdmiScdc * scdc,enum HdmiScdcsOffset offset,uint8_t * buffer,uint32_t len)16 int32_t HdmiScdcRead(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(struct HdmiScdc * scdc,enum HdmiScdcsOffset offset,uint8_t * buffer,uint32_t len)36 int32_t HdmiScdcWrite(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(struct HdmiScdc * scdc,enum HdmiScdcsOffset offset,uint8_t * byte)56 int32_t HdmiScdcReadByte(struct HdmiScdc *scdc, enum HdmiScdcsOffset offset, uint8_t *byte)
57 {
58     return HdmiScdcRead(scdc, offset, byte, sizeof(*byte));
59 }
60 
HdmiScdcWriteByte(struct HdmiScdc * scdc,enum HdmiScdcsOffset offset,uint8_t * byte)61 int32_t HdmiScdcWriteByte(struct HdmiScdc *scdc, enum HdmiScdcsOffset offset, uint8_t *byte)
62 {
63     return HdmiScdcWrite(scdc, offset, byte, sizeof(*byte));
64 }
65 
66 /* read opt */
HdmiScdcReadSinkVersion(struct HdmiScdc * scdc,uint8_t * sinkVer)67 int32_t HdmiScdcReadSinkVersion(struct HdmiScdc *scdc, uint8_t *sinkVer)
68 {
69     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_SINK_VERSION, sinkVer);
70 }
71 
HdmiScdcReadSourceVersion(struct HdmiScdc * scdc,uint8_t * srcVer)72 int32_t HdmiScdcReadSourceVersion(struct HdmiScdc *scdc, uint8_t *srcVer)
73 {
74     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_SOURCE_VERSION, srcVer);
75 }
76 
HdmiScdcReadUpdate0(struct HdmiScdc * scdc,uint8_t * flag)77 int32_t HdmiScdcReadUpdate0(struct HdmiScdc *scdc, uint8_t *flag)
78 {
79     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_UPDATE_0, flag);
80 }
81 
HdmiScdcReadScramblerStatus(struct HdmiScdc * scdc,uint8_t * status)82 int32_t HdmiScdcReadScramblerStatus(struct HdmiScdc *scdc, uint8_t *status)
83 {
84     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_SCRAMBLER_STATUS, status);
85 }
86 
HdmiScdcReadTmdsConfig(struct HdmiScdc * scdc,uint8_t * tmdsCfg)87 int32_t HdmiScdcReadTmdsConfig(struct HdmiScdc *scdc, uint8_t *tmdsCfg)
88 {
89     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_TMDS_CONFIG, tmdsCfg);
90 }
91 
HdmiScdcReadConfig0(struct HdmiScdc * scdc,uint8_t * cfg)92 int32_t HdmiScdcReadConfig0(struct HdmiScdc *scdc, uint8_t *cfg)
93 {
94     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_CONFIG_0, cfg);
95 }
96 
HdmiScdcReadConfig1(struct HdmiScdc * scdc,uint8_t * cfg)97 int32_t HdmiScdcReadConfig1(struct HdmiScdc *scdc, uint8_t *cfg)
98 {
99     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_CONFIG_1, cfg);
100 }
101 
HdmiScdcReadTestConfig0(struct HdmiScdc * scdc,uint8_t * testCfg)102 int32_t HdmiScdcReadTestConfig0(struct HdmiScdc *scdc, uint8_t *testCfg)
103 {
104     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_TEST_CONFIG_0, testCfg);
105 }
106 
HdmiScdcReadTestConfig1(struct HdmiScdc * scdc,uint8_t * testCfg)107 int32_t HdmiScdcReadTestConfig1(struct HdmiScdc *scdc, uint8_t *testCfg)
108 {
109     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_TEST_CONFIG_1, testCfg);
110 }
111 
HdmiScdcReadStatusFlag0(struct HdmiScdc * scdc,uint8_t * flag)112 int32_t HdmiScdcReadStatusFlag0(struct HdmiScdc *scdc, uint8_t *flag)
113 {
114     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_STASTUS_FLAG_0, flag);
115 }
116 
HdmiScdcReadStatusFlag1(struct HdmiScdc * scdc,uint8_t * flag)117 int32_t HdmiScdcReadStatusFlag1(struct HdmiScdc *scdc, uint8_t *flag)
118 {
119     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_STASTUS_FLAG_1, flag);
120 }
121 
HdmiScdcReadStatusFlag2(struct HdmiScdc * scdc,uint8_t * flag)122 int32_t HdmiScdcReadStatusFlag2(struct HdmiScdc *scdc, uint8_t *flag)
123 {
124     return HdmiScdcReadByte(scdc, HDMI_SCDCS_OFFSET_STASTUS_FLAG_2, flag);
125 }
126 
127 /* write opt */
HdmiScdcWriteSourceVersion(struct HdmiScdc * scdc,uint8_t * srcVer)128 int32_t HdmiScdcWriteSourceVersion(struct HdmiScdc *scdc, uint8_t *srcVer)
129 {
130     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_SOURCE_VERSION, srcVer);
131 }
132 
HdmiScdcWriteUpdate0(struct HdmiScdc * scdc,uint8_t * flag)133 int32_t HdmiScdcWriteUpdate0(struct HdmiScdc *scdc, uint8_t *flag)
134 {
135     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_UPDATE_0, flag);
136 }
137 
HdmiScdcWriteTmdsConfig(struct HdmiScdc * scdc,uint8_t * tmdsCfg)138 int32_t HdmiScdcWriteTmdsConfig(struct HdmiScdc *scdc, uint8_t *tmdsCfg)
139 {
140     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_TMDS_CONFIG, tmdsCfg);
141 }
142 
HdmiScdcWriteConfig0(struct HdmiScdc * scdc,uint8_t * cfg)143 int32_t HdmiScdcWriteConfig0(struct HdmiScdc *scdc, uint8_t *cfg)
144 {
145     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_CONFIG_0, cfg);
146 }
147 
HdmiScdcWriteConfig1(struct HdmiScdc * scdc,uint8_t * cfg)148 int32_t HdmiScdcWriteConfig1(struct HdmiScdc *scdc, uint8_t *cfg)
149 {
150     return HdmiScdcWriteByte(scdc, HDMI_SCDCS_OFFSET_CONFIG_1, cfg);
151 }
152 
HdmiScdcWriteTestConfig0(struct HdmiScdc * scdc,uint8_t * testCfg)153 int32_t HdmiScdcWriteTestConfig0(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 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 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, i;
274     int32_t ret;
275 
276     if (scdc == NULL) {
277         return HDF_ERR_INVALID_PARAM;
278     }
279 
280     for (i = 0; i < HDMI_SCDC_READ_SOURCE_VERSION_TIMES; i++) {
281         srcVer = HDMI_SCDC_HDMI20_VERSION;
282         ret = HdmiScdcWriteSourceVersion(scdc, &srcVer);
283         if (ret != HDF_SUCCESS) {
284             HDF_LOGE("scdc write source version fail");
285             return false;
286         }
287         ret = HdmiScdcReadSourceVersion(scdc, &srcVer);
288         if (ret != HDF_SUCCESS) {
289             HDF_LOGE("scdc read source version fail");
290             return false;
291         }
292     }
293     scdc->status.sourceVersion = HDMI_SCDC_HDMI20_VERSION;
294     return true;
295 }
296 
HdmiScdcOptMsgHandle(struct HdmiScdc * scdc,enum HdmiScdcOptMsg msg,uint8_t * buffer,uint32_t len)297 int32_t HdmiScdcOptMsgHandle(struct HdmiScdc *scdc, enum HdmiScdcOptMsg msg, uint8_t *buffer, uint32_t len)
298 {
299     int32_t ret;
300 
301     if (scdc == NULL || buffer == NULL || len == 0) {
302         return HDF_ERR_INVALID_PARAM;
303     }
304 
305     switch (msg) {
306         case HDMI_SCDC_OPT_SET_SOURCE_VER:
307             ret = HdmiScdcWriteSourceVersion(scdc, buffer);
308             break;
309         case HDMI_SCDC_OPT_GET_SOURCE_VER:
310             ret = HdmiScdcReadSourceVersion(scdc, buffer);
311             break;
312         case HDMI_SCDC_OPT_GET_SINK_VER:
313             ret = HdmiScdcReadSinkVersion(scdc, buffer);
314             break;
315         case HDMI_SCDC_OPT_SET_FLT_UPDATE:
316         case HDMI_SCDC_OPT_SET_FRL_START:
317             ret = HdmiScdcWriteUpdate0(scdc, buffer);
318             break;
319         case HDMI_SCDC_OPT_GET_FLT_UPDATE:
320         case HDMI_SCDC_OPT_GET_FRL_START:
321             ret = HdmiScdcReadUpdate0(scdc, buffer);
322             break;
323         case HDMI_SCDC_OPT_SET_CONFIG1:
324             ret = HdmiScdcWriteConfig1(scdc, buffer);
325             break;
326         case HDMI_SCDC_OPT_GET_CONFIG1:
327             ret = HdmiScdcReadConfig1(scdc, buffer);
328             break;
329         case HDMI_SCDC_OPT_GET_TEST_CONFIG_1:
330             ret = HdmiScdcReadTestConfig1(scdc, buffer);
331             break;
332         case HDMI_SCDC_OPT_GET_FLT_READY:
333             ret = HdmiScdcReadStatusFlag0(scdc, buffer);
334             break;
335         case HDMI_SCDC_OPT_GET_LTP_REQ:
336             ret = HdmiScdcRead(scdc, HDMI_SCDCS_OFFSET_STASTUS_FLAG_1, buffer, len);
337             break;
338         default:
339             HDF_LOGE("scdc msg handle, msg %d not support.", msg);
340             ret = HDF_ERR_NOT_SUPPORT;
341             break;
342     }
343 
344     return ret;
345 }
346 
HdmiScdcFillScrambleCap(struct HdmiScdc * scdc,struct HdmiScdcScrambleCap * scramble,enum HdmiTmdsModeType * tmdsMode)347 int32_t HdmiScdcFillScrambleCap(struct HdmiScdc *scdc, struct HdmiScdcScrambleCap *scramble,
348     enum HdmiTmdsModeType *tmdsMode)
349 {
350     struct HdmiCntlr *cntlr = NULL;
351     struct HdmiCommonAttr *commAttr = NULL;
352     struct HdmiVideoAttr *videoAttr = NULL;
353 
354     if (scdc == NULL || scdc->priv == NULL || scramble == NULL || tmdsMode == NULL) {
355         HDF_LOGD("scdc fill scramble cap: param is null");
356         return HDF_ERR_INVALID_PARAM;
357     }
358 
359     cntlr = (struct HdmiCntlr *)scdc->priv;
360     commAttr = &(cntlr->attr.commAttr);
361     videoAttr = &(cntlr->attr.videoAttr);
362     if (commAttr->enableHdmi == false) {
363         /* DVI mode */
364         *tmdsMode = HDMI_TMDS_MODE_DVI;
365         scramble->sinkScramble = false;
366         scramble->sourceScramble = false;
367         scramble->tmdsBitClockRatio40 = false;
368         if (videoAttr->tmdsClock > HDMI_HDMI14_MAX_TMDS_RATE) {
369             HDF_LOGE("tmds clock %u can't support in DVI mode.", videoAttr->tmdsClock);
370             return HDF_ERR_INVALID_PARAM;
371         }
372     } else if (videoAttr->tmdsClock > HDMI_HDMI14_MAX_TMDS_RATE) {
373         *tmdsMode = HDMI_TMDS_MODE_HDMI_2_0;
374         scramble->sinkScramble   = true;
375         scramble->sourceScramble = true;
376         scramble->tmdsBitClockRatio40 = true;
377     } else {
378         *tmdsMode = HDMI_TMDS_MODE_HDMI_1_4;
379         scramble->sinkScramble   = false;
380         scramble->sourceScramble = false;
381         scramble->tmdsBitClockRatio40 = false;
382     }
383     return HDF_SUCCESS;
384 }
385