1 /*
2 * Copyright (C) 2019 Allwinnertech Co.Ltd
3 * Authors: zhengwanyu
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 */
11 #include <drm/drmP.h>
12 #include <drm/drm_edid.h>
13 #include <drm/drm_modes.h>
14
15 #include "hdmi_core/api/core_api.h"
16 #include "sunxi_drm_connector.h"
17
18 #if defined(CONFIG_AW_DRM_HDMI14)
19 #include "sunxi_device/sunxi_hdmi14.h"
20 #elif defined(CONFIG_AW_DRM_HDMI20)
21 #include "sunxi_device/sunxi_hdmi20.h"
22 #endif
23
24 //static unsigned char sunxi_edid[1024];
25
26 extern struct sunxi_drm_hdmi_connector *
27 to_sunxi_hdmi_connector(struct drm_connector *conn);
28
29 extern void
30 sunxi_drm_hdmi_set_working_mode(
31 struct sunxi_drm_connector *sconn,
32 struct sunxi_hdmi_work_mode *work_mode);
33
edid_bit_field(const u16 data,u8 shift,u8 width)34 static u8 edid_bit_field(const u16 data, u8 shift, u8 width)
35 {
36 return (data >> shift) & ((((u16) 1) << width) - 1);
37 }
38
edid_concat_bits(u8 bHi,u8 oHi,u8 nHi,u8 bLo,u8 oLo,u8 nLo)39 static u16 edid_concat_bits(u8 bHi, u8 oHi, u8 nHi, u8 bLo, u8 oLo, u8 nLo)
40 {
41 return (edid_bit_field(bHi, oHi, nHi) << nLo) | edid_bit_field(bLo, oLo, nLo);
42 }
43
edid_byte_to_word(const u8 hi,const u8 lo)44 static u16 edid_byte_to_word(const u8 hi, const u8 lo)
45 {
46 return edid_concat_bits(hi, 0, 8, lo, 0, 8);
47 }
48
edid_byte_to_dword(u8 b3,u8 b2,u8 b1,u8 b0)49 static u32 edid_byte_to_dword(u8 b3, u8 b2, u8 b1, u8 b0)
50 {
51 u32 retval = 0;
52
53 retval |= b0 << (0 * 8);
54 retval |= b1 << (1 * 8);
55 retval |= b2 << (2 * 8);
56 retval |= b3 << (3 * 8);
57 return retval;
58 }
59
60 static void speaker_alloc_data_block_reset(
61 speakerAllocationDataBlock_t *sadb);
62 static void video_cap_data_block_reset(
63 videoCapabilityDataBlock_t *vcdb);
64
dtd_parse(dtd_t * dtd,u8 data[18])65 static int dtd_parse(dtd_t *dtd, u8 data[18])
66 {
67 /* */
68
69 dtd->mCode = -1;
70 dtd->mPixelRepetitionInput = 0;
71 dtd->mLimitedToYcc420 = 0;
72 dtd->mYcc420 = 0;
73
74 dtd->mPixelClock = 1000 * edid_byte_to_word(data[1], data[0]);/*[10000Hz]*/
75 if (dtd->mPixelClock < 0x01) { /* 0x0000 is defined as reserved */
76 return false;
77 }
78
79 dtd->mHActive = edid_concat_bits(data[4], 4, 4, data[2], 0, 8);
80 dtd->mHBlanking = edid_concat_bits(data[4], 0, 4, data[3], 0, 8);
81 dtd->mHSyncOffset = edid_concat_bits(data[11], 6, 2, data[8], 0, 8);
82 dtd->mHSyncPulseWidth = edid_concat_bits(data[11], 4, 2, data[9], 0, 8);
83 dtd->mHImageSize = edid_concat_bits(data[14], 4, 4, data[12], 0, 8);
84 dtd->mHBorder = data[15];
85
86 dtd->mVActive = edid_concat_bits(data[7], 4, 4, data[5], 0, 8);
87 dtd->mVBlanking = edid_concat_bits(data[7], 0, 4, data[6], 0, 8);
88 dtd->mVSyncOffset = edid_concat_bits(data[11], 2, 2, data[10], 4, 4);
89 dtd->mVSyncPulseWidth = edid_concat_bits(data[11], 0, 2, data[10], 0, 4);
90 dtd->mVImageSize = edid_concat_bits(data[14], 0, 4, data[13], 0, 8);
91 dtd->mVBorder = data[16];
92
93 if (edid_bit_field(data[17], 4, 1) != 1) {/*if not DIGITAL SYNC SIGNAL DEF*/
94 DRM_ERROR("Error:Invalid DTD Parameters\n");
95 return false;
96 }
97 if (edid_bit_field(data[17], 3, 1) != 1) {/*if not DIGITAL SEPATATE SYNC*/
98 DRM_ERROR("Error:Invalid DTD Parameters\n");
99 return false;
100 }
101 /* no stereo viewing support in HDMI */
102 dtd->mInterlaced = edid_bit_field(data[17], 7, 1) == 1;
103 dtd->mVSyncPolarity = edid_bit_field(data[17], 2, 1) == 1;
104 dtd->mHSyncPolarity = edid_bit_field(data[17], 1, 1) == 1;
105 return true;
106 }
107
monitor_range_limits_reset(monitorRangeLimits_t * mrl)108 static void monitor_range_limits_reset(monitorRangeLimits_t *mrl)
109 {
110 mrl->mMinVerticalRate = 0;
111 mrl->mMaxVerticalRate = 0;
112 mrl->mMinHorizontalRate = 0;
113 mrl->mMaxHorizontalRate = 0;
114 mrl->mMaxPixelClock = 0;
115 mrl->mValid = false;
116 }
117
colorimetry_data_block_reset(colorimetryDataBlock_t * cdb)118 static void colorimetry_data_block_reset(colorimetryDataBlock_t *cdb)
119 {
120 cdb->mByte3 = 0;
121 cdb->mByte4 = 0;
122 cdb->mValid = false;
123 }
124
125
colorimetry_data_block_parse(colorimetryDataBlock_t * cdb,u8 * data)126 static int colorimetry_data_block_parse(colorimetryDataBlock_t *cdb, u8 *data)
127 {
128 colorimetry_data_block_reset(cdb);
129 if ((data != 0) && (edid_bit_field(data[0], 0, 5) == 0x03) &&
130 (edid_bit_field(data[0], 5, 3) == 0x07)
131 && (edid_bit_field(data[1], 0, 7) == 0x05)) {
132 cdb->mByte3 = data[2];
133 cdb->mByte4 = data[3];
134 cdb->mValid = true;
135 return true;
136 }
137 return false;
138 }
139
hdr_metadata_data_block_reset(struct hdr_static_metadata_data_block * hdr_metadata)140 static void hdr_metadata_data_block_reset(
141 struct hdr_static_metadata_data_block *hdr_metadata)
142 {
143 memset(hdr_metadata, 0, sizeof(struct hdr_static_metadata_data_block));
144 }
145
hdr_static_metadata_block_parse(struct hdr_static_metadata_data_block * hdr_metadata,u8 * data)146 static int hdr_static_metadata_block_parse(
147 struct hdr_static_metadata_data_block *hdr_metadata, u8 *data)
148 {
149 hdr_metadata_data_block_reset(hdr_metadata);
150 if ((data != 0) && (edid_bit_field(data[0], 0, 5) > 1)
151 && (edid_bit_field(data[0], 5, 3) == 0x07)
152 && (data[1] == 0x06)) {
153 hdr_metadata->et_n = edid_bit_field(data[2], 0, 5);
154 hdr_metadata->sm_n = data[3];
155
156 if (edid_bit_field(data[0], 0, 5) > 3)
157 hdr_metadata->dc_max_lum_data = data[4];
158 if (edid_bit_field(data[0], 0, 5) > 4)
159 hdr_metadata->dc_max_fa_lum_data = data[5];
160 if (edid_bit_field(data[0], 0, 5) > 5)
161 hdr_metadata->dc_min_lum_data = data[6];
162
163 return true;
164 }
165 return false;
166 }
167
hdmiforumvsdb_reset(hdmiforumvsdb_t * forumvsdb)168 static void hdmiforumvsdb_reset(hdmiforumvsdb_t *forumvsdb)
169 {
170 forumvsdb->mValid = false;
171 forumvsdb->mIeee_Oui = 0;
172 forumvsdb->mVersion = 0;
173 forumvsdb->mMaxTmdsCharRate = 0;
174 forumvsdb->mSCDC_Present = false;
175 forumvsdb->mRR_Capable = false;
176 forumvsdb->mLTS_340Mcs_scramble = false;
177 forumvsdb->mIndependentView = false;
178 forumvsdb->mDualView = false;
179 forumvsdb->m3D_OSD_Disparity = false;
180 forumvsdb->mDC_30bit_420 = false;
181 forumvsdb->mDC_36bit_420 = false;
182 forumvsdb->mDC_48bit_420 = false;
183 }
184
hdmiforumvsdb_parse(hdmiforumvsdb_t * forumvsdb,u8 * data)185 static int hdmiforumvsdb_parse(hdmiforumvsdb_t *forumvsdb,
186 u8 *data)
187 {
188 u16 blockLength;
189
190 hdmiforumvsdb_reset(forumvsdb);
191 if (data == 0)
192 return false;
193
194 if (edid_bit_field(data[0], 5, 3) != 0x3) {
195 DRM_ERROR("Error:Invalid datablock tag\n");
196 return false;
197 }
198 blockLength = edid_bit_field(data[0], 0, 5);
199 if (blockLength < 7) {
200 DRM_ERROR("Error:Invalid minimum length\n");
201 return false;
202 }
203 if (edid_byte_to_dword(0x00, data[3], data[2], data[1]) !=
204 0xC45DD8) {
205 DRM_ERROR("Error:HDMI IEEE registration identifier not valid\n");
206 return false;
207 }
208 forumvsdb->mVersion = edid_bit_field(data[4], 0, 7);
209 forumvsdb->mMaxTmdsCharRate = edid_bit_field(data[5], 0, 7);
210 forumvsdb->mSCDC_Present = edid_bit_field(data[6], 7, 1);
211 forumvsdb->mRR_Capable = edid_bit_field(data[6], 6, 1);
212 forumvsdb->mLTS_340Mcs_scramble = edid_bit_field(data[6], 3, 1);
213 forumvsdb->mIndependentView = edid_bit_field(data[6], 2, 1);
214 forumvsdb->mDualView = edid_bit_field(data[6], 1, 1);
215 forumvsdb->m3D_OSD_Disparity = edid_bit_field(data[6], 0, 1);
216 forumvsdb->mDC_30bit_420 = edid_bit_field(data[7], 2, 1);
217 forumvsdb->mDC_36bit_420 = edid_bit_field(data[7], 1, 1);
218 forumvsdb->mDC_48bit_420 = edid_bit_field(data[7], 0, 1);
219 forumvsdb->mValid = true;
220
221 #if 0
222 DRM_DEBUG_DRIVER("version %d\n", edid_bit_field(data[4], 0, 7));
223 DRM_DEBUG_DRIVER("Max_TMDS_Charater_rate %d\n",
224 edid_bit_field(data[5], 0, 7));
225 DRM_DEBUG_DRIVER("SCDC_Present %d\n", edid_bit_field(data[6], 7, 1));
226 DRM_DEBUG_DRIVER("RR_Capable %d\n", edid_bit_field(data[6], 6, 1));
227 DRM_DEBUG_DRIVER("LTE_340Mcsc_scramble %d\n",
228 edid_bit_field(data[6], 3, 1));
229 DRM_DEBUG_DRIVER("Independent_View %d\n", edid_bit_field(data[6], 2, 1));
230 DRM_DEBUG_DRIVER("Dual_View %d\n", edid_bit_field(data[6], 1, 1));
231 DRM_DEBUG_DRIVER("3D_OSD_Disparity %d\n", edid_bit_field(data[6], 0, 1));
232 DRM_DEBUG_DRIVER("DC_48bit_420 %d\n", edid_bit_field(data[7], 2, 1));
233 DRM_DEBUG_DRIVER("DC_36bit_420 %d\n", edid_bit_field(data[7], 1, 1));
234 DRM_DEBUG_DRIVER("DC_30bit_420 %d\n", edid_bit_field(data[7], 0, 1));
235 #endif
236 return true;
237 }
238
hdmivsdb_reset(hdmivsdb_t * vsdb)239 static void hdmivsdb_reset(hdmivsdb_t *vsdb)
240 {
241 int i, j = 0;
242
243 vsdb->mPhysicalAddress = 0;
244 vsdb->mSupportsAi = false;
245 vsdb->mDeepColor30 = false;
246 vsdb->mDeepColor36 = false;
247 vsdb->mDeepColor48 = false;
248 vsdb->mDeepColorY444 = false;
249 vsdb->mDviDual = false;
250 vsdb->mMaxTmdsClk = 0;
251 vsdb->mVideoLatency = 0;
252 vsdb->mAudioLatency = 0;
253 vsdb->mInterlacedVideoLatency = 0;
254 vsdb->mInterlacedAudioLatency = 0;
255 vsdb->mId = 0;
256 vsdb->mContentTypeSupport = 0;
257 vsdb->mHdmiVicCount = 0;
258 for (i = 0; i < MAX_HDMI_VIC; i++)
259 vsdb->mHdmiVic[i] = 0;
260
261 vsdb->m3dPresent = false;
262 for (i = 0; i < MAX_VIC_WITH_3D; i++) {
263 for (j = 0; j < MAX_HDMI_3DSTRUCT; j++)
264 vsdb->mVideo3dStruct[i][j] = 0;
265 }
266 for (i = 0; i < MAX_VIC_WITH_3D; i++) {
267 for (j = 0; j < MAX_HDMI_3DSTRUCT; j++)
268 vsdb->mDetail3d[i][j] = ~0;
269 }
270 vsdb->mValid = false;
271 }
272
edid_parser_CeaExtReset(sink_edid_t * edidExt)273 static int edid_parser_CeaExtReset(sink_edid_t *edidExt)
274 {
275 unsigned i = 0;
276
277 edidExt->edid_m20Sink = false;
278 #if 1
279 for (i = 0; i < sizeof(edidExt->edid_mMonitorName); i++)
280 edidExt->edid_mMonitorName[i] = 0;
281
282 edidExt->edid_mBasicAudioSupport = false;
283 edidExt->edid_mUnderscanSupport = false;
284 edidExt->edid_mYcc422Support = false;
285 edidExt->edid_mYcc444Support = false;
286 edidExt->edid_mYcc420Support = false;
287 edidExt->edid_mDtdIndex = 0;
288 edidExt->edid_mSadIndex = 0;
289 edidExt->edid_mSvdIndex = 0;
290 #endif
291 hdmivsdb_reset(&edidExt->edid_mHdmivsdb);
292 hdmiforumvsdb_reset(&edidExt->edid_mHdmiForumvsdb);
293 monitor_range_limits_reset(&edidExt->edid_mMonitorRangeLimits);
294 video_cap_data_block_reset(&edidExt->edid_mVideoCapabilityDataBlock);
295 colorimetry_data_block_reset(&edidExt->edid_mColorimetryDataBlock);
296 hdr_metadata_data_block_reset(&edidExt->edid_hdr_static_metadata_data_block);
297 speaker_alloc_data_block_reset(
298 &edidExt->edid_mSpeakerAllocationDataBlock);
299 return true;
300 }
301
302
hdmivsdb_parse(hdmivsdb_t * vsdb,u8 * data)303 static int hdmivsdb_parse(hdmivsdb_t *vsdb, u8 *data)
304 {
305 u8 blockLength = 0;
306 unsigned videoInfoStart = 0;
307 unsigned hdmi3dStart = 0;
308 unsigned hdmiVicLen = 0;
309 unsigned hdmi3dLen = 0;
310 unsigned spanned3d = 0;
311 unsigned i = 0;
312 unsigned j = 0;
313
314 hdmivsdb_reset(vsdb);
315 if (data == 0)
316 return false;
317
318 if (edid_bit_field(data[0], 5, 3) != 0x3) {
319 DRM_ERROR("Error:Invalid datablock tag\n");
320 return false;
321 }
322 blockLength = edid_bit_field(data[0], 0, 5);
323 if (blockLength < 5) {
324 DRM_ERROR("Error:Invalid minimum length\n");
325 return false;
326 }
327 if (edid_byte_to_dword(0x00, data[3], data[2], data[1]) != 0x000C03) {
328 DRM_ERROR("Error:HDMI IEEE registration identifier not valid\n");
329 return false;
330 }
331 hdmivsdb_reset(vsdb);
332 vsdb->mId = 0x000C03;
333 vsdb->mPhysicalAddress = edid_byte_to_word(data[4], data[5]);
334 /* parse extension fields if they exist */
335 if (blockLength > 5) {
336 vsdb->mSupportsAi = edid_bit_field(data[6], 7, 1) == 1;
337 vsdb->mDeepColor48 = edid_bit_field(data[6], 6, 1) == 1;
338 vsdb->mDeepColor36 = edid_bit_field(data[6], 5, 1) == 1;
339 vsdb->mDeepColor30 = edid_bit_field(data[6], 4, 1) == 1;
340 vsdb->mDeepColorY444 = edid_bit_field(data[6], 3, 1) == 1;
341 vsdb->mDviDual = edid_bit_field(data[6], 0, 1) == 1;
342 } else {
343 vsdb->mSupportsAi = false;
344 vsdb->mDeepColor48 = false;
345 vsdb->mDeepColor36 = false;
346 vsdb->mDeepColor30 = false;
347 vsdb->mDeepColorY444 = false;
348 vsdb->mDviDual = false;
349 }
350 vsdb->mMaxTmdsClk = (blockLength > 6) ? data[7] : 0;
351 vsdb->mVideoLatency = 0;
352 vsdb->mAudioLatency = 0;
353 vsdb->mInterlacedVideoLatency = 0;
354 vsdb->mInterlacedAudioLatency = 0;
355 if (blockLength > 7) {
356 if (edid_bit_field(data[8], 7, 1) == 1) {
357 if (blockLength < 10) {
358 DRM_ERROR("Error:Invalid length - latencies are not valid\n");
359 return false;
360 }
361 if (edid_bit_field(data[8], 6, 1) == 1) {
362 if (blockLength < 12) {
363 DRM_ERROR("Error:Invalid length - Interlaced latencies are not valid\n");
364 return false;
365 } else {
366 vsdb->mVideoLatency = data[9];
367 vsdb->mAudioLatency = data[10];
368 vsdb->mInterlacedVideoLatency
369 = data[11];
370 vsdb->mInterlacedAudioLatency
371 = data[12];
372 videoInfoStart = 13;
373 }
374 } else {
375 vsdb->mVideoLatency = data[9];
376 vsdb->mAudioLatency = data[10];
377 vsdb->mInterlacedVideoLatency = 0;
378 vsdb->mInterlacedAudioLatency = 0;
379 videoInfoStart = 11;
380 }
381 } else { /* no latency data */
382 vsdb->mVideoLatency = 0;
383 vsdb->mAudioLatency = 0;
384 vsdb->mInterlacedVideoLatency = 0;
385 vsdb->mInterlacedAudioLatency = 0;
386 videoInfoStart = 9;
387 }
388 vsdb->mContentTypeSupport = edid_bit_field(data[8], 0, 4);
389 }
390 /* additional video format capabilities are described */
391 if (edid_bit_field(data[8], 5, 1) == 1) {
392 vsdb->mImageSize = edid_bit_field(data[videoInfoStart], 3, 2);
393 hdmiVicLen = edid_bit_field(data[videoInfoStart + 1], 5, 3);
394 hdmi3dLen = edid_bit_field(data[videoInfoStart + 1], 0, 5);
395 for (i = 0; i < hdmiVicLen; i++)
396 vsdb->mHdmiVic[i] = data[videoInfoStart + 2 + i];
397
398 vsdb->mHdmiVicCount = hdmiVicLen;
399 if (edid_bit_field(data[videoInfoStart], 7, 1) == 1) {/*3d present*/
400 vsdb->m3dPresent = true;
401 hdmi3dStart = videoInfoStart + hdmiVicLen + 2;
402 /* 3d multi 00 -> both 3d_structure_all
403 and 3d_mask_15 are NOT present */
404 /* 3d mutli 11 -> reserved */
405 if (edid_bit_field(data[videoInfoStart], 5, 2) == 1) {
406 /* 3d multi 01 */
407 /* 3d_structure_all is present but 3d_mask_15 not present */
408 for (j = 0; j < 16; j++) {
409 /* j spans 3d structures */
410 if (edid_bit_field(data[hdmi3dStart
411 + (j / 8)], (j % 8), 1) == 1) {
412 for (i = 0; i < 16; i++)
413 vsdb->mVideo3dStruct[i][(j < 8) ? j+8 : j - 8] = 1;
414 }
415 }
416 spanned3d = 2;
417 /*hdmi3dStart += 2;
418 hdmi3dLen -= 2; */
419 } else if (edid_bit_field(data[videoInfoStart], 5, 2) == 2) {
420 /* 3d multi 10 */
421 /* 3d_structure_all and 3d_mask_15 are present */
422 for (j = 0; j < 16; j++) {
423 for (i = 0; i < 16; i++) {
424 if (edid_bit_field(data[hdmi3dStart + 2 + (i / 8)], (i % 8), 1) == 1)
425 vsdb->mVideo3dStruct[(i < 8) ? i + 8 : i - 8][(j < 8) ? j + 8 : j - 8] = edid_bit_field(data[hdmi3dStart + (j / 8)], (j % 8), 1);
426 }
427 }
428 spanned3d = 4;
429 }
430 if (hdmi3dLen > spanned3d) {
431 hdmi3dStart += spanned3d;
432 for (i = 0, j = 0; i < (hdmi3dLen - spanned3d); i++) {
433 vsdb->mVideo3dStruct[edid_bit_field(data[hdmi3dStart + i + j], 4, 4)][edid_bit_field(data[hdmi3dStart + i + j], 0, 4)] = 1;
434 if (edid_bit_field(data[hdmi3dStart + i + j], 4, 4) > 7) {
435 j++;
436 vsdb->mDetail3d[edid_bit_field(data[hdmi3dStart + i + j], 4, 4)][edid_bit_field(data[hdmi3dStart + i + j], 4, 4)] = edid_bit_field(data[hdmi3dStart + i + j], 4, 4);
437 }
438 }
439 }
440 } else { /* 3d NOT present */
441 vsdb->m3dPresent = false;
442 }
443 }
444 vsdb->mValid = true;
445 return true;
446 }
447
sad_reset(shortAudioDesc_t * sad)448 static void sad_reset(shortAudioDesc_t *sad)
449 {
450 sad->mFormat = 0;
451 sad->mMaxChannels = 0;
452 sad->mSampleRates = 0;
453 sad->mByte3 = 0;
454 }
455
sad_parse(shortAudioDesc_t * sad,u8 * data)456 static int sad_parse(shortAudioDesc_t *sad, u8 *data)
457 {
458 sad_reset(sad);
459 if (data != 0) {
460 sad->mFormat = edid_bit_field(data[0], 3, 4);
461 sad->mMaxChannels = edid_bit_field(data[0], 0, 3) + 1;
462 sad->mSampleRates = edid_bit_field(data[1], 0, 7);
463 sad->mByte3 = data[2];
464 return true;
465 }
466 return false;
467 }
468
469 #if 0
470 static int sad_support32k(shortAudioDesc_t *sad)
471 {
472 return (edid_bit_field(sad->mSampleRates, 0, 1) == 1) ? true : false;
473 }
474
475 static int sad_support44k1(shortAudioDesc_t *sad)
476 {
477 return (edid_bit_field(sad->mSampleRates, 1, 1) == 1) ? true : false;
478 }
479
480 static int sad_support48k(shortAudioDesc_t *sad)
481 {
482 return (edid_bit_field(sad->mSampleRates, 2, 1) == 1) ? true : false;
483 }
484
485 static int sad_support88k2(shortAudioDesc_t *sad)
486 {
487 return (edid_bit_field(sad->mSampleRates, 3, 1) ==
488 1) ? true : false;
489 }
490
491 static int sad_support96k(shortAudioDesc_t *sad)
492 {
493 return (edid_bit_field(sad->mSampleRates, 4, 1) == 1) ? true : false;
494 }
495
496 static int sad_support176k4(shortAudioDesc_t *sad)
497 {
498 return (edid_bit_field(sad->mSampleRates, 5, 1) == 1) ? true : false;
499 }
500
501 static int sad_support192k(shortAudioDesc_t *sad)
502 {
503 return (edid_bit_field(sad->mSampleRates, 6, 1) == 1) ? true : false;
504 }
505
506 static int sad_support16bit(shortAudioDesc_t *sad)
507 {
508 if (sad->mFormat == 1)
509 return (edid_bit_field(sad->mByte3, 0, 1) == 1) ? true : false;
510
511 DRM_DEBUG_DRIVER("%s:Information is not valid for this format\n", __func__);
512 return false;
513 }
514
515 static int sad_support20bit(shortAudioDesc_t *sad)
516 {
517 if (sad->mFormat == 1)
518 return (edid_bit_field(sad->mByte3, 1, 1) == 1) ? true : false;
519 DRM_DEBUG_DRIVER("%s:Information is not valid for this format\n", __func__);
520 return false;
521 }
522
523 static int sad_support24bit(shortAudioDesc_t *sad)
524 {
525 if (sad->mFormat == 1)
526 return (edid_bit_field(sad->mByte3, 2, 1) == 1) ? true : false;
527 DRM_DEBUG_DRIVER("%s:Information is not valid for this format\n", __func__);
528 return false;
529 }
530 #endif
531
svd_reset(shortVideoDesc_t * svd)532 static void svd_reset(shortVideoDesc_t *svd)
533 {
534 svd->mNative = false;
535 svd->mCode = 0;
536 }
537
svd_parse(shortVideoDesc_t * svd,u8 data)538 static int svd_parse(shortVideoDesc_t *svd, u8 data)
539 {
540 svd_reset(svd);
541 svd->mNative = (edid_bit_field(data, 7, 1) == 1) ? true : false;
542 svd->mCode = edid_bit_field(data, 0, 7);
543 svd->mLimitedToYcc420 = 0;
544 svd->mYcc420 = 0;
545 return true;
546 }
547
548
speaker_alloc_data_block_reset(speakerAllocationDataBlock_t * sadb)549 static void speaker_alloc_data_block_reset(
550 speakerAllocationDataBlock_t *sadb)
551 {
552 sadb->mByte1 = 0;
553 sadb->mValid = false;
554 }
555
speaker_alloc_data_block_parse(speakerAllocationDataBlock_t * sadb,u8 * data)556 static int speaker_alloc_data_block_parse(
557 speakerAllocationDataBlock_t *sadb, u8 *data)
558 {
559 speaker_alloc_data_block_reset(sadb);
560 if ((data != 0) && (edid_bit_field(data[0], 0, 5) == 0x03) &&
561 (edid_bit_field(data[0], 5, 3) == 0x04)) {
562 sadb->mByte1 = data[1];
563 sadb->mValid = true;
564 return true;
565 }
566 return false;
567 }
568
video_cap_data_block_reset(videoCapabilityDataBlock_t * vcdb)569 static void video_cap_data_block_reset(videoCapabilityDataBlock_t *vcdb)
570 {
571 vcdb->mQuantizationRangeSelectable = false;
572 vcdb->mPreferredTimingScanInfo = 0;
573 vcdb->mItScanInfo = 0;
574 vcdb->mCeScanInfo = 0;
575 vcdb->mValid = false;
576 }
577
video_cap_data_block_parse(videoCapabilityDataBlock_t * vcdb,u8 * data)578 static int video_cap_data_block_parse(videoCapabilityDataBlock_t *vcdb, u8 *data)
579 {
580 video_cap_data_block_reset(vcdb);
581 /* check tag code and extended tag */
582 if ((data != 0) && (edid_bit_field(data[0], 5, 3) == 0x7) &&
583 (edid_bit_field(data[1], 0, 8) == 0x0) &&
584 (edid_bit_field(data[0], 0, 5) == 0x2)) {
585 /* so far VCDB is 2 bytes long */
586 vcdb->mCeScanInfo = edid_bit_field(data[2], 0, 2);
587 vcdb->mItScanInfo = edid_bit_field(data[2], 2, 2);
588 vcdb->mPreferredTimingScanInfo = edid_bit_field(data[2], 4, 2);
589 vcdb->mQuantizationRangeSelectable =
590 (edid_bit_field(data[2], 6, 1) == 1) ? true : false;
591 vcdb->mValid = true;
592 return true;
593 }
594 return false;
595 }
596
597 #if 0
598 static int _edid_checksum(u8 *edid)
599 {
600 int i, checksum = 0;
601
602 for (i = 0; i < EDID_LENGTH; i++)
603 checksum += edid[i];
604
605 return checksum % 256; /* CEA-861 Spec */
606 }
607 #endif
608
edid_parser_updateYcc420(sink_edid_t * edidExt,u8 Ycc420All,u8 LimitedToYcc420All)609 static void edid_parser_updateYcc420(sink_edid_t *edidExt,
610 u8 Ycc420All, u8 LimitedToYcc420All)
611 {
612 u16 edid_cnt = 0;
613
614 for (edid_cnt = 0; edid_cnt < edidExt->edid_mSvdIndex; edid_cnt++) {
615 switch (edidExt->edid_mSvd[edid_cnt].mCode) {
616 case 96:
617 case 97:
618 case 101:
619 case 102:
620 case 106:
621 case 107:
622 Ycc420All == 1 ?
623 edidExt->edid_mSvd[edid_cnt].mYcc420 = Ycc420All : 0;
624 LimitedToYcc420All == 1 ?
625 edidExt->edid_mSvd[edid_cnt].mLimitedToYcc420 =
626 LimitedToYcc420All : 0;
627 break;
628 }
629 }
630 }
631
632
_edid_struture_parser(struct edid * edid,sink_edid_t * sink)633 static int _edid_struture_parser(struct edid *edid,
634 sink_edid_t *sink)
635 {
636 int i;
637 char *monitorName;
638
639 if (edid->header[0] != 0) {
640 DRM_ERROR(":Error:Invalid Header\n");
641 return -1;
642 }
643
644 DRM_DEBUG_DRIVER("\n\nEDID Block0 detailed discriptor:\n");
645 for (i = 0; i < 4; i++) {
646 struct detailed_timing *detailed_timing = &(edid->detailed_timings[i]);
647
648 if (detailed_timing->pixel_clock == 0) {
649 struct detailed_non_pixel *npixel = &(detailed_timing->data.other_data);
650
651 switch (npixel->type) {
652 case EDID_DETAIL_MONITOR_NAME:
653 monitorName = (char *) &(npixel->data.str.str);
654 DRM_DEBUG_DRIVER("Monitor name: %s\n", monitorName);
655 break;
656 case EDID_DETAIL_MONITOR_RANGE:
657 break;
658
659 }
660 } else { /* Detailed Timing Definition */
661 struct detailed_pixel_timing *ptiming = &(detailed_timing->data.pixel_data);
662 DRM_DEBUG_DRIVER("\npixel_clock:%d\n", detailed_timing->pixel_clock * 10000);
663 DRM_DEBUG_DRIVER("hactive * vactive: %d * %d\n",
664 (((ptiming->hactive_hblank_hi >> 4) & 0x0f) << 8)
665 | ptiming->hactive_lo,
666 (((ptiming->vactive_vblank_hi >> 4) & 0x0f) << 8)
667 | ptiming->vactive_lo);
668 }
669 }
670 return true;
671 }
672
edid_parser_ParseDataBlock(u8 * data,sink_edid_t * edidExt)673 static int edid_parser_ParseDataBlock(u8 *data, sink_edid_t *edidExt)
674 {
675 u8 c = 0;
676 shortAudioDesc_t tmpSad;
677 shortVideoDesc_t tmpSvd;
678 u8 tmpYcc420All = 0;
679 u8 tmpLimitedYcc420All = 0;
680 u32 ieeeId = 0;
681 u8 extendedTag = 0;
682 int i = 0;
683 int edid_cnt = 0;
684 int svdNr = 0;
685 int icnt = 0;
686 u8 tag = edid_bit_field(data[0], 5, 3);
687 u8 length = edid_bit_field(data[0], 0, 5);
688
689 tmpSvd.mLimitedToYcc420 = 0;
690 tmpSvd.mYcc420 = 0;
691
692
693 switch (tag) {
694 case 0x1: /* Audio Data Block */
695 DRM_DEBUG_DRIVER("EDID: Audio datablock parsing\n");
696 for (c = 1; c < (length + 1); c += 3) {
697 sad_parse(&tmpSad, data + c);
698 if (edidExt->edid_mSadIndex < (sizeof(edidExt->edid_mSad) / sizeof(shortAudioDesc_t)))
699 edidExt->edid_mSad[edidExt->edid_mSadIndex++] = tmpSad;
700 else
701 DRM_ERROR("buffer full - SAD ignored\n");
702 }
703 break;
704 case 0x2: /* Video Data Block */
705 DRM_DEBUG_DRIVER("EDID: Video datablock parsing\n");
706 for (c = 1; c < (length + 1); c++) {
707 svd_parse(&tmpSvd, data[c]);
708 if (edidExt->edid_mSvdIndex < (sizeof(edidExt->edid_mSvd) / sizeof(shortVideoDesc_t)))
709 edidExt->edid_mSvd[edidExt->edid_mSvdIndex++] = tmpSvd;
710 else
711 DRM_ERROR("buffer full - SVD ignored\n");
712 }
713 break;
714 case 0x3: /* Vendor Specific Data Block HDMI or HF */
715 DRM_DEBUG_DRIVER("\nEDID: VSDB HDMI and HDMI-F\n ");
716 ieeeId = edid_byte_to_dword(0x00, data[3], data[2], data[1]);
717 if (ieeeId == 0x000C03) { /* HDMI */
718 if (hdmivsdb_parse(&edidExt->edid_mHdmivsdb, data) != true) {
719 DRM_ERROR("Error:HDMI Vendor Specific Data Block corrupt\n");
720 break;
721 }
722 DRM_DEBUG_DRIVER("EDID HDMI VSDB parsed\n");
723 } else {
724 if (ieeeId == 0xC45DD8) { /* HDMI-F */
725 DRM_DEBUG_DRIVER("Sink is HDMI 2.0 because haves HF-VSDB\n");
726 edidExt->edid_m20Sink = true;
727 if (hdmiforumvsdb_parse(&edidExt->edid_mHdmiForumvsdb, data) != true) {
728 DRM_ERROR("Error:HDMI Vendor Specific Data Block corrupt\n");
729 break;
730 }
731 } else {
732 DRM_DEBUG_DRIVER("Vendor Specific Data Block not parsed ieeeId: 0x%x\n",
733 ieeeId);
734 }
735 }
736 DRM_DEBUG_DRIVER("\n");
737 break;
738 case 0x4: /* Speaker Allocation Data Block */
739 DRM_DEBUG_DRIVER("SAD block parsing\n");
740 if (speaker_alloc_data_block_parse(&edidExt->edid_mSpeakerAllocationDataBlock, data) != true)
741 DRM_ERROR("Error:Speaker Allocation Data Block corrupt\n");
742 break;
743 case 0x7:{
744 DRM_DEBUG_DRIVER("EDID CEA Extended field 0x07\n");
745 extendedTag = data[1];
746 switch (extendedTag) {
747 case 0x00: /* Video Capability Data Block */
748 DRM_DEBUG_DRIVER("Video Capability Data Block\n");
749 if (video_cap_data_block_parse(&edidExt->edid_mVideoCapabilityDataBlock, data) != true)
750 DRM_DEBUG_DRIVER("Error:Video Capability Data Block corrupt\n");
751 break;
752 case 0x04: /* HDMI Video Data Block */
753 DRM_DEBUG_DRIVER("HDMI Video Data Block\n");
754 break;
755 case 0x05: /* Colorimetry Data Block */
756 DRM_DEBUG_DRIVER("Colorimetry Data Block\n");
757 if (colorimetry_data_block_parse(&edidExt->edid_mColorimetryDataBlock, data) != true)
758 DRM_DEBUG_DRIVER("Error:Colorimetry Data Block corrupt\n");
759 break;
760 case 0x06: /* HDR Static Metadata Data Block */
761 DRM_DEBUG_DRIVER("HDR Static Metadata Data Block\n");
762 if (hdr_static_metadata_block_parse(&edidExt->edid_hdr_static_metadata_data_block, data) != true)
763 DRM_DEBUG_DRIVER("HDR Static Metadata Data Block corrupt\n");
764 break;
765 case 0x12: /* HDMI Audio Data Block */
766 DRM_DEBUG_DRIVER("HDMI Audio Data Block\n");
767 break;
768 case 0xe:
769 /** If it is a YCC420 VDB then VICs can ONLY be displayed in YCC 4:2:0 */
770 DRM_DEBUG_DRIVER("YCBCR 4:2:0 Video Data Block\n");
771 /** If Sink has YCC Datablocks it is HDMI 2.0 */
772 edidExt->edid_m20Sink = true;
773 tmpLimitedYcc420All = (edid_bit_field(data[0], 0, 5) == 1 ? 1 : 0);
774 edid_parser_updateYcc420(edidExt, tmpYcc420All, tmpLimitedYcc420All);
775 for (i = 0; i < (edid_bit_field(data[0], 0, 5) - 1); i++) {
776 /** Length includes the tag byte*/
777 tmpSvd.mCode = data[2 + i];
778 tmpSvd.mNative = 0;
779 tmpSvd.mLimitedToYcc420 = 1;
780 for (edid_cnt = 0; edid_cnt < edidExt->edid_mSvdIndex; edid_cnt++) {
781 if (edidExt->edid_mSvd[edid_cnt].mCode == tmpSvd.mCode) {
782 edidExt->edid_mSvd[edid_cnt] = tmpSvd;
783 goto concluded;
784 }
785 }
786 if (edidExt->edid_mSvdIndex <
787 (sizeof(edidExt->edid_mSvd) / sizeof(shortVideoDesc_t))) {
788 edidExt->edid_mSvd[edidExt->edid_mSvdIndex] = tmpSvd;
789 edidExt->edid_mSvdIndex++;
790 } else {
791 DRM_DEBUG_DRIVER("buffer full - YCC 420 DTD ignored\n");
792 }
793 concluded:;
794 }
795 break;
796 case 0x0f:
797 /** If it is a YCC420 CDB then VIC can ALSO be displayed in YCC 4:2:0 */
798 edidExt->edid_m20Sink = true;
799 DRM_DEBUG_DRIVER("YCBCR 4:2:0 Capability Map Data Block\n");
800 /* If YCC420 CMDB is bigger than 1, then there is SVD info to parse */
801 if (edid_bit_field(data[0], 0, 5) > 1) {
802 for (icnt = 0; icnt < 8; icnt++) {
803 /** Lenght includes the tag byte*/
804 if ((edid_bit_field(data[2], 1 >> icnt, 1) & 0x01)) {
805 svdNr = icnt;
806 tmpSvd.mCode = edidExt->edid_mSvd[svdNr - 1].mCode;
807 tmpSvd.mYcc420 = 1;
808 edidExt->edid_mSvd[svdNr - 1] = tmpSvd;
809 }
810 }
811 /* Otherwise, all SVDs present at the Video Data Block support YCC420*/
812 } else {
813 tmpYcc420All = (edid_bit_field(data[0], 0, 5) == 1 ? 1 : 0);
814 edid_parser_updateYcc420(edidExt, tmpYcc420All, tmpLimitedYcc420All);
815 }
816 break;
817 default:
818 DRM_ERROR("Error:Extended Data Block not parsed %d\n",
819 extendedTag);
820 break;
821 }
822 break;
823 }
824 default:
825 DRM_ERROR("Error:Data Block not parsed %d\n", tag);
826 break;
827 }
828 return length + 1;
829 }
830
831
_edid_cea_extension_parser(u8 * buffer,sink_edid_t * edidExt)832 static int _edid_cea_extension_parser(u8 *buffer, sink_edid_t *edidExt)
833 {
834 int i = 0;
835 int c = 0;
836 dtd_t tmpDtd;
837 u8 offset = buffer[2];
838
839 if (buffer[1] < 0x03) {
840 DRM_ERROR("Error:Invalid version for CEA Extension block,only rev 3 or higher is supported");
841 return -1;
842 }
843
844 edidExt->edid_mYcc422Support = edid_bit_field(buffer[3], 4, 1) == 1;
845 edidExt->edid_mYcc444Support = edid_bit_field(buffer[3], 5, 1) == 1;
846 edidExt->edid_mBasicAudioSupport = edid_bit_field(buffer[3], 6, 1) == 1;
847 edidExt->edid_mUnderscanSupport = edid_bit_field(buffer[3], 7, 1) == 1;
848 if (offset != 4) {
849 for (i = 4; i < offset; i += edid_parser_ParseDataBlock(buffer + i, edidExt))
850 ;
851 }
852
853 memcpy(edidExt->detailed_timings, buffer + 84, sizeof(edidExt->detailed_timings));
854
855 /* last is checksum */
856 for (i = offset, c = 0; i < (sizeof(buffer) - 1) && c < 6; i += 12, c++) {
857 if (dtd_parse(&tmpDtd, buffer + i) == true) {
858 if (edidExt->edid_mDtdIndex < ((sizeof(edidExt->edid_mDtd) / sizeof(dtd_t)))) {
859 edidExt->edid_mDtd[edidExt->edid_mDtdIndex++] = tmpDtd;
860 DRM_DEBUG_DRIVER("edid_mDtd code %d\n", edidExt->edid_mDtd[edidExt->edid_mDtdIndex].mCode);
861 DRM_DEBUG_DRIVER("edid_mDtd limited to Ycc420? %d\n", edidExt->edid_mDtd[edidExt->edid_mDtdIndex].mLimitedToYcc420);
862 DRM_DEBUG_DRIVER("edid_mDtd supports Ycc420? %d\n", edidExt->edid_mDtd[edidExt->edid_mDtdIndex].mYcc420);
863 } else {
864 DRM_DEBUG_DRIVER("buffer full - DTD ignored\n");
865 }
866 }
867 }
868 return true;
869 }
870
edid_parser(u8 * buffer,sink_edid_t * edidExt,u16 edid_size)871 static int edid_parser(u8 *buffer, sink_edid_t *edidExt,
872 u16 edid_size)
873 {
874 int ret = 0;
875
876 switch (buffer[0]) {
877 case 0x00:
878 ret = _edid_struture_parser((struct edid *) buffer,
879 edidExt);
880 break;
881 case CEA_EXT:
882 ret = _edid_cea_extension_parser(buffer, edidExt);
883 break;
884 case VTB_EXT:
885 case DI_EXT:
886 case LS_EXT:
887 case MI_EXT:
888 default:
889 DRM_DEBUG_DRIVER("Block 0x%02x not supported\n", buffer[0]);
890 }
891 if (ret == true)
892 return true;
893
894 return false;
895 }
896
sunxi_edid_parse_cap(struct edid * edid,sink_edid_t * sink)897 void sunxi_edid_parse_cap(struct edid *edid, sink_edid_t *sink)
898 {
899 memset(sink, 0, sizeof(sink_edid_t));
900
901 edid_parser_CeaExtReset(sink);
902
903 if (edid_parser((u8 *)edid, sink, 128) == false) {
904 DRM_ERROR("Error:Could not parse EDID\n");
905 return;
906 }
907
908
909 if (edid->extensions) {
910 int edid_ext_cnt = 1;
911
912 while (edid_ext_cnt <= edid->extensions) {
913 DRM_DEBUG_DRIVER("EDID Extension %d\n", edid_ext_cnt);
914 if (edid_ext_cnt < 2) {
915 if (edid_parser((u8 *)&edid[edid_ext_cnt], sink, 128) == false)
916 DRM_ERROR("Could not parse EDID EXTENSIONS:%d\n", edid_ext_cnt);
917 }
918
919 edid_ext_cnt++;
920 }
921 }
922 }
923
sunixi_hdmi_edid_is_zero(const u8 * in_edid,int length)924 static bool sunixi_hdmi_edid_is_zero(const u8 *in_edid, int length)
925 {
926 if (memchr_inv(in_edid, 0, length))
927 return false;
928
929 return true;
930 }
931
sunxi_drm_do_get_edid(struct drm_connector * connector)932 struct edid *sunxi_drm_do_get_edid(struct drm_connector *connector)
933 {
934 int i, j = 0, valid_extensions = 0;
935 u8 *block, *new;
936 struct sunxi_drm_connector *sunxi_con = to_sunxi_connector(connector);
937 struct sunxi_hdmi_funcs *hdmi_funcs = sunxi_con->hw_funcs;
938 bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
939
940 block = kmalloc(EDID_LENGTH, GFP_KERNEL | __GFP_ZERO);
941 if (block == NULL)
942 return NULL;
943 //block = sunxi_edid;
944
945 /* base block fetch, try maximun 4 times agin */
946 for (i = 0; i < 4; i++) {
947 if (hdmi_funcs->get_edid_block(NULL, block, 0, EDID_LENGTH)) {
948 DRM_ERROR("get_edid_block:0 failed\n");
949 goto out;
950 }
951
952 if (drm_edid_block_valid(block, 0, print_bad_edid,
953 &connector->edid_corrupt))
954 break;
955
956 DRM_ERROR("drm_edid_block0 is INVALID!!!\n");
957
958 if (i == 0 && sunixi_hdmi_edid_is_zero(block, EDID_LENGTH)) {
959 connector->null_edid_counter++;
960 goto carp;
961 }
962 }
963
964 if (i == 4) {
965 DRM_ERROR("read EDID Failed!!!\n");
966 goto carp;
967 }
968
969 /* if there's no extensions, we're done */
970 if (block[0x7e] == 0) {
971 DRM_DEBUG_DRIVER("WARN: Sink's EDID has NO extension block");
972 return (struct edid *)block;
973 }
974 DRM_DEBUG_DRIVER("EDID EXT BLOCK NUM:%d\n", block[0x7e]);
975
976 new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH,
977 GFP_KERNEL | __GFP_ZERO);
978 if (!new)
979 goto out;
980 block = new;
981
982 for (j = 1; j <= block[0x7e]; j++) {
983 for (i = 0; i < 4; i++) {
984 if (hdmi_funcs->get_edid_block(NULL,
985 block + (valid_extensions + 1) * EDID_LENGTH,
986 j, EDID_LENGTH))
987 goto out;
988 if (drm_edid_block_valid(block + (valid_extensions + 1)
989 * EDID_LENGTH, j,
990 print_bad_edid,
991 NULL)) {
992 valid_extensions++;
993 break;
994 }
995 }
996
997 if (i == 4 && print_bad_edid) {
998 dev_warn(connector->dev->dev,
999 "%s: Ignoring invalid EDID block %d.\n",
1000 connector->name, j);
1001
1002 connector->bad_edid_counter++;
1003 }
1004 }
1005
1006 if (valid_extensions != block[0x7e]) {
1007 block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
1008 block[0x7e] = valid_extensions;
1009 new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
1010 if (!new)
1011 goto out;
1012 block = new;
1013 }
1014
1015 return (struct edid *)block;
1016
1017 carp:
1018 if (print_bad_edid) {
1019 dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
1020 connector->name, j);
1021 }
1022 connector->bad_edid_counter++;
1023
1024 out:
1025 kfree(block);
1026 return NULL;
1027 }
1028
sunxi_drm_hdmi_edid_get_modes(struct drm_connector * connector,sink_edid_t * sink)1029 int sunxi_drm_hdmi_edid_get_modes(
1030 struct drm_connector *connector, sink_edid_t *sink)
1031 {
1032 int ret = 0;
1033 struct edid *edid = NULL;
1034
1035 /*read edid*/
1036 edid = sunxi_drm_do_get_edid(connector);
1037 if (edid) {
1038 /*parse or check edid*/
1039 drm_get_displayid(connector, edid);
1040 drm_connector_update_edid_property(connector, edid);
1041 ret = drm_add_edid_modes(connector, edid);
1042 //drm_edid_to_eld(connector, edid);
1043
1044 sunxi_edid_parse_cap(edid, sink);
1045 }
1046
1047 kfree(edid);
1048
1049 return ret;
1050 }
1051