1 #include "rockchip-hdmi.h"
2 #include "../../fbdev/edid.h"
7 #define EDBG(format, ...)
11 E_HDMI_EDID_SUCCESS = 0,
16 E_HDMI_EDID_UNKOWNDATA,
20 static int hdmi_edid_checksum(unsigned char *buf)
25 for (i = 0; i < HDMI_EDID_BLOCK_SIZE; i++)
31 return E_HDMI_EDID_SUCCESS;
33 return E_HDMI_EDID_CHECKSUM;
37 * @Des Parse Detail Timing Descriptor.
38 * @Param buf : pointer to DTD data.
39 * @Param pvic: VIC of DTD descripted.
41 static int hdmi_edid_parse_dtd(unsigned char *block, struct fb_videomode *mode)
43 mode->xres = H_ACTIVE;
44 mode->yres = V_ACTIVE;
45 mode->pixclock = PIXEL_CLOCK;
46 mode->right_margin = H_SYNC_OFFSET;
47 mode->left_margin = (H_ACTIVE + H_BLANKING) -
48 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
49 mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
51 mode->lower_margin = V_SYNC_OFFSET;
52 mode->hsync_len = H_SYNC_WIDTH;
53 mode->vsync_len = V_SYNC_WIDTH;
55 mode->sync |= FB_SYNC_HOR_HIGH_ACT;
57 mode->sync |= FB_SYNC_VERT_HIGH_ACT;
58 mode->refresh = PIXEL_CLOCK / ((H_ACTIVE + H_BLANKING) *
59 (V_ACTIVE + V_BLANKING));
62 mode->upper_margin *= 2;
63 mode->lower_margin *= 2;
65 mode->vmode |= FB_VMODE_INTERLACED;
67 mode->flag = FB_MODE_IS_DETAILED;
69 EDBG("<<<<<<<<Detailed Time>>>>>>>>>\n");
70 EDBG("%d KHz Refresh %d Hz",
71 PIXEL_CLOCK / 1000, mode->refresh);
72 EDBG("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
73 H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
74 EDBG("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
75 V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
76 EDBG("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
77 (VSYNC_POSITIVE) ? "+" : "-");
78 return E_HDMI_EDID_SUCCESS;
81 static int edid_parse_prop_value(unsigned char *buf,
82 struct hdmi_edid *pedid)
84 unsigned char *block = &buf[0x36];
86 pedid->value.vid = ((buf[ID_MANUFACTURER_NAME_END] << 8) |
87 (buf[ID_MANUFACTURER_NAME]));
88 pedid->value.pid = ((buf[ID_MODEL + 1] << 8) |
90 pedid->value.sn = ((buf[ID_SERIAL_NUMBER + 3] << 24) |
91 (buf[ID_SERIAL_NUMBER + 2] << 16) |
92 (buf[ID_SERIAL_NUMBER + 1] << 8) |
93 buf[ID_SERIAL_NUMBER]);
94 pedid->value.xres = H_ACTIVE;
95 pedid->value.yres = V_ACTIVE;
97 pr_info("%s:read:vid=0x%x,pid=0x%x,sn=0x%x,xres=%d,yres=%d\n",
98 __func__, pedid->value.vid, pedid->value.pid,
99 pedid->value.sn, pedid->value.xres, pedid->value.yres);
104 int hdmi_edid_parse_base(struct hdmi *hdmi, unsigned char *buf,
105 int *extend_num, struct hdmi_edid *pedid)
107 int rc = E_HDMI_EDID_SUCCESS;
109 if (!buf || !extend_num)
110 return E_HDMI_EDID_PARAM;
112 *extend_num = buf[0x7e];
114 EDBG("[EDID] extend block num is %d\n", buf[0x7e]);
117 /* Check first 8 byte to ensure it is an edid base block. */
118 if (buf[0] != 0x00 ||
126 pr_err("[EDID] check header error\n");
127 rc = E_HDMI_EDID_HEAD;
132 rc = hdmi_edid_checksum(buf);
133 if (rc != E_HDMI_EDID_SUCCESS) {
134 pr_err("[EDID] base block checksum error\n");
135 rc = E_HDMI_EDID_CHECKSUM;
139 pedid->specs = kzalloc(sizeof(*pedid->specs), GFP_KERNEL);
141 return E_HDMI_EDID_NOMEMORY;
143 fb_edid_to_monspecs(buf, pedid->specs);
145 if (hdmi->edid_auto_support)
146 edid_parse_prop_value(buf, pedid);
149 /* For some sink, edid checksum is failed because several
150 * byte is wrong. To fix this case, we think it is a good
151 * edid if 1 <= *extend_num <= 4.
153 if ((rc != E_HDMI_EDID_SUCCESS) &&
154 (*extend_num < 1 || *extend_num > 4))
157 return E_HDMI_EDID_SUCCESS;
160 /* Parse CEA Short Video Descriptor */
161 static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)
165 count = buf[0] & 0x1F;
166 for (i = 0; i < count; i++) {
167 EDBG("[CEA] %02x VID %d native %d\n",
168 buf[1 + i], buf[1 + i] & 0x7f, buf[1 + i] >> 7);
169 vic = buf[1 + i] & 0x7f;
170 hdmi_add_vic(vic, &pedid->modelist);
175 /* Parse CEA Short Audio Descriptor */
176 static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)
180 count = buf[0] & 0x1F;
181 pedid->audio = kmalloc((count / 3) * sizeof(struct hdmi_audio),
184 return E_HDMI_EDID_NOMEMORY;
186 pedid->audio_num = count / 3;
187 for (i = 0; i < pedid->audio_num; i++) {
188 pedid->audio[i].type = (buf[1 + i * 3] >> 3) & 0x0F;
189 pedid->audio[i].channel = (buf[1 + i * 3] & 0x07) + 1;
190 pedid->audio[i].rate = buf[1 + i * 3 + 1];
191 if (pedid->audio[i].type == HDMI_AUDIO_LPCM)
192 pedid->audio[i].word_length = buf[1 + i * 3 + 2];
194 return E_HDMI_EDID_SUCCESS;
197 static int hdmi_edid_parse_3dinfo(unsigned char *buf, struct list_head *head)
199 int i, j, len = 0, format_3d, vic_mask;
200 unsigned char offset = 2, vic_2d, structure_3d;
201 struct list_head *pos;
202 struct display_modelist *modelist;
205 len = (buf[1] & 0xe0) >> 5;
206 for (i = 0; i < len; i++) {
208 vic_2d = (buf[offset] == 4) ?
209 98 : (96 - buf[offset]);
210 hdmi_add_vic(vic_2d, head);
218 len += (buf[1] & 0x1F) + 2;
219 if (((buf[0] & 0x60) == 0x40) || ((buf[0] & 0x60) == 0x20)) {
220 format_3d = buf[offset++] << 8;
221 format_3d |= buf[offset++];
222 if ((buf[0] & 0x60) == 0x20) {
225 vic_mask = buf[offset++] << 8;
226 vic_mask |= buf[offset++];
233 for (i = 0; i < 16; i++) {
234 if (vic_mask & (1 << i)) {
236 for (pos = (head)->next; pos != (head);
240 list_entry(pos, struct display_modelist, list);
241 modelist->format_3d = format_3d;
247 while (offset < len) {
248 vic_2d = (buf[offset] & 0xF0) >> 4;
249 structure_3d = (buf[offset++] & 0x0F);
251 for (pos = (head)->next; pos != (head);
256 list_entry(pos, struct display_modelist, list);
257 modelist->format_3d |=
259 if (structure_3d & 0x08)
260 modelist->detail_3d =
261 (buf[offset++] & 0xF0) >> 4;
266 /* mandatory formats */
267 for (pos = (head)->next; pos != (head); pos = pos->next) {
268 modelist = list_entry(pos,
269 struct display_modelist,
271 if (modelist->vic == HDMI_1920X1080P_24HZ ||
272 modelist->vic == HDMI_1280X720P_60HZ ||
273 modelist->vic == HDMI_1280X720P_50HZ) {
274 modelist->format_3d |=
275 (1 << HDMI_3D_FRAME_PACKING) |
276 (1 << HDMI_3D_TOP_BOOTOM);
277 } else if (modelist->vic == HDMI_1920X1080I_60HZ ||
278 modelist->vic == HDMI_1920X1080I_50HZ) {
279 modelist->format_3d |=
280 (1 << HDMI_3D_SIDE_BY_SIDE_HALF);
288 static int hdmi_edmi_parse_vsdb(unsigned char *buf, struct hdmi_edid *pedid,
289 int cur_offset, int IEEEOUI)
291 int count, buf_offset;
293 count = buf[cur_offset] & 0x1F;
296 pedid->sink_hdmi = 1;
297 pedid->cecaddress = buf[cur_offset + 5];
298 pedid->cecaddress |= buf[cur_offset + 4] << 8;
299 EDBG("[CEA] CEC Physical address is 0x%08x.\n",
302 pedid->deepcolor = (buf[cur_offset + 6] >> 3) & 0x0F;
304 pedid->maxtmdsclock = buf[cur_offset + 7] * 5000000;
305 EDBG("[CEA] maxtmdsclock is %d.\n",
306 pedid->maxtmdsclock);
309 pedid->fields_present = buf[cur_offset + 8];
310 EDBG("[CEA] fields_present is 0x%02x.\n",
311 pedid->fields_present);
313 buf_offset = cur_offset + 9;
314 if (pedid->fields_present & 0x80) {
315 pedid->video_latency = buf[buf_offset++];
316 pedid->audio_latency = buf[buf_offset++];
318 if (pedid->fields_present & 0x40) {
319 pedid->interlaced_video_latency = buf[buf_offset++];
320 pedid->interlaced_audio_latency = buf[buf_offset++];
322 if (pedid->fields_present & 0x20) {
323 hdmi_edid_parse_3dinfo(buf + buf_offset,
328 pedid->sink_hdmi = 1;
329 pedid->hf_vsdb_version = buf[cur_offset + 4];
330 switch (pedid->hf_vsdb_version) {
331 case 1:/*compliant with HDMI Specification 2.0*/
332 pedid->maxtmdsclock =
333 buf[cur_offset + 5] * 5000000;
334 EDBG("[CEA] maxtmdsclock is %d.\n",
335 pedid->maxtmdsclock);
336 pedid->scdc_present = buf[cur_offset + 6] >> 7;
338 (buf[cur_offset + 6] & 0x40) >> 6;
339 pedid->lte_340mcsc_scramble =
340 (buf[cur_offset + 6] & 0x08) >> 3;
341 pedid->independent_view =
342 (buf[cur_offset + 6] & 0x04) >> 2;
344 (buf[cur_offset + 6] & 0x02) >> 1;
345 pedid->osd_disparity_3d =
346 buf[cur_offset + 6] & 0x01;
347 pedid->deepcolor_420 =
348 (buf[cur_offset + 7] & 0x7) << 1;
351 pr_info("hf_vsdb_version = %d\n",
352 pedid->hf_vsdb_version);
357 pr_info("IEEOUT = 0x%x\n", IEEEOUI);
363 static void hdmi_edid_parse_yuv420cmdb(unsigned char *buf, int count,
364 struct list_head *head)
366 struct list_head *pos;
367 struct display_modelist *modelist;
368 int i, j, yuv420_mask = 0, vic;
371 list_for_each(pos, head) {
373 list_entry(pos, struct display_modelist, list);
374 vic = modelist->vic | HDMI_VIDEO_YUV420;
375 hdmi_add_vic(vic, head);
378 for (i = 0; i < count - 1; i++) {
379 EDBG("vic which support yuv420 mode is %x\n", buf[i]);
380 yuv420_mask |= buf[i] << (8 * i);
382 for (i = 0; i < 32; i++) {
383 if (!(yuv420_mask & (1 << i)))
386 list_for_each(pos, head) {
389 list_entry(pos, struct display_modelist, list);
390 vic = modelist->vic |
392 hdmi_add_vic(vic, head);
400 /* Parse CEA 861 Serial Extension. */
401 static int hdmi_edid_parse_extensions_cea(unsigned char *buf,
402 struct hdmi_edid *pedid)
404 unsigned int ddc_offset, native_dtd_num, cur_offset = 4;
405 unsigned int tag, IEEEOUI = 0, count, i;
406 struct fb_videomode *vmode;
409 return E_HDMI_EDID_PARAM;
411 /* Check ces extension version */
413 pr_err("[CEA] error version.\n");
414 return E_HDMI_EDID_VERSION;
418 pedid->baseaudio_support = (buf[3] >> 6) & 0x01;
419 pedid->ycbcr444 = (buf[3] >> 5) & 0x01;
420 pedid->ycbcr422 = (buf[3] >> 4) & 0x01;
421 native_dtd_num = buf[3] & 0x0F;
422 /* Parse data block */
423 while (cur_offset < ddc_offset) {
424 tag = buf[cur_offset] >> 5;
425 count = buf[cur_offset] & 0x1F;
427 case 0x02: /* Video Data Block */
428 EDBG("[CEA] Video Data Block.\n");
429 hdmi_edid_get_cea_svd(buf + cur_offset, pedid);
431 case 0x01: /* Audio Data Block */
432 EDBG("[CEA] Audio Data Block.\n");
433 hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);
435 case 0x04: /* Speaker Allocation Data Block */
436 EDBG("[CEA] Speaker Allocatio Data Block.\n");
438 case 0x03: /* Vendor Specific Data Block */
439 EDBG("[CEA] Vendor Specific Data Block.\n");
441 IEEEOUI = buf[cur_offset + 3];
443 IEEEOUI += buf[cur_offset + 2];
445 IEEEOUI += buf[cur_offset + 1];
446 EDBG("[CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);
448 hdmi_edmi_parse_vsdb(buf, pedid,
449 cur_offset, IEEEOUI);
451 case 0x05: /* VESA DTC Data Block */
452 EDBG("[CEA] VESA DTC Data Block.\n");
454 case 0x07: /* Use Extended Tag */
455 EDBG("[CEA] Use Extended Tag Data Block %02x.\n",
456 buf[cur_offset + 1]);
457 switch (buf[cur_offset + 1]) {
459 EDBG("[CEA] Video Capability Data Block\n");
460 EDBG("value is %02x\n", buf[cur_offset + 2]);
463 EDBG("[CEA] Colorimetry Data Block\n");
464 EDBG("value is %02x\n", buf[cur_offset + 2]);
465 pedid->colorimetry = buf[cur_offset + 2];
468 EDBG("[CEA] HDR Static Metedata data Block\n");
469 for (i = 0; i < count - 1; i++)
471 buf[cur_offset + 2 + i];
474 EDBG("[CEA] YCBCR 4:2:0 Video Data Block\n");
475 for (i = 0; i < count - 1; i++) {
477 buf[cur_offset + 2 + i]);
479 IEEEOUI = buf[cur_offset + 2 + i] |
481 hdmi_add_vic(IEEEOUI,
486 EDBG("[CEA] YCBCR 4:2:0 Capability Map Data\n");
487 hdmi_edid_parse_yuv420cmdb(&buf[cur_offset + 2],
495 pr_err("[CEA] unkowned data block tag.\n");
498 cur_offset += (buf[cur_offset] & 0x1F) + 1;
502 vmode = kmalloc(sizeof(*vmode), GFP_KERNEL);
505 return E_HDMI_EDID_SUCCESS;
506 while (ddc_offset < HDMI_EDID_BLOCK_SIZE - 2) {
507 if (!buf[ddc_offset] && !buf[ddc_offset + 1])
509 memset(vmode, 0, sizeof(struct fb_videomode));
510 hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
511 hdmi_add_vic(hdmi_videomode_to_vic(vmode), &pedid->modelist);
516 return E_HDMI_EDID_SUCCESS;
519 int hdmi_edid_parse_extensions(unsigned char *buf, struct hdmi_edid *pedid)
524 return E_HDMI_EDID_PARAM;
527 rc = hdmi_edid_checksum(buf);
528 if (rc != E_HDMI_EDID_SUCCESS) {
529 pr_err("[EDID] extensions block checksum error\n");
530 return E_HDMI_EDID_CHECKSUM;
535 EDBG("[EDID-EXTEND] Iextensions block map.\n");
538 EDBG("[EDID-EXTEND] CEA 861 Series Extension.\n");
539 hdmi_edid_parse_extensions_cea(buf, pedid);
542 EDBG("[EDID-EXTEND] Video Timing Block Extension.\n");
545 EDBG("[EDID-EXTEND] Display Information Extension.\n");
548 EDBG("[EDID-EXTEND] Localized String Extension.\n");
551 EDBG("[EDID-EXTEND] Digital Packet Video Link Extension.\n");
554 pr_err("[EDID-EXTEND] Unkowned Extension.\n");
555 return E_HDMI_EDID_UNKOWNDATA;
558 return E_HDMI_EDID_SUCCESS;