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 int hdmi_edid_parse_base(unsigned char *buf,
82 int *extend_num, struct hdmi_edid *pedid)
84 int rc = E_HDMI_EDID_SUCCESS;
86 if (!buf || !extend_num)
87 return E_HDMI_EDID_PARAM;
89 *extend_num = buf[0x7e];
91 EDBG("[EDID] extend block num is %d\n", buf[0x7e]);
94 /* Check first 8 byte to ensure it is an edid base block. */
103 pr_err("[EDID] check header error\n");
104 rc = E_HDMI_EDID_HEAD;
109 rc = hdmi_edid_checksum(buf);
110 if (rc != E_HDMI_EDID_SUCCESS) {
111 pr_err("[EDID] base block checksum error\n");
112 rc = E_HDMI_EDID_CHECKSUM;
116 pedid->specs = kzalloc(sizeof(*pedid->specs), GFP_KERNEL);
118 return E_HDMI_EDID_NOMEMORY;
120 fb_edid_to_monspecs(buf, pedid->specs);
123 /* For some sink, edid checksum is failed because several
124 * byte is wrong. To fix this case, we think it is a good
125 * edid if 1 <= *extend_num <= 4.
127 if ((rc != E_HDMI_EDID_SUCCESS) &&
128 (*extend_num < 1 || *extend_num > 4))
131 return E_HDMI_EDID_SUCCESS;
134 /* Parse CEA Short Video Descriptor */
135 static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)
139 count = buf[0] & 0x1F;
140 for (i = 0; i < count; i++) {
141 EDBG("[CEA] %02x VID %d native %d\n",
142 buf[1 + i], buf[1 + i] & 0x7f, buf[1 + i] >> 7);
143 vic = buf[1 + i] & 0x7f;
144 hdmi_add_vic(vic, &pedid->modelist);
149 /* Parse CEA Short Audio Descriptor */
150 static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)
154 count = buf[0] & 0x1F;
155 pedid->audio = kmalloc((count / 3) * sizeof(struct hdmi_audio),
158 return E_HDMI_EDID_NOMEMORY;
160 pedid->audio_num = count / 3;
161 for (i = 0; i < pedid->audio_num; i++) {
162 pedid->audio[i].type = (buf[1 + i * 3] >> 3) & 0x0F;
163 pedid->audio[i].channel = (buf[1 + i * 3] & 0x07) + 1;
164 pedid->audio[i].rate = buf[1 + i * 3 + 1];
165 if (pedid->audio[i].type == HDMI_AUDIO_LPCM)
166 pedid->audio[i].word_length = buf[1 + i * 3 + 2];
168 return E_HDMI_EDID_SUCCESS;
171 static int hdmi_edid_parse_3dinfo(unsigned char *buf, struct list_head *head)
173 int i, j, len = 0, format_3d, vic_mask;
174 unsigned char offset = 2, vic_2d, structure_3d;
175 struct list_head *pos;
176 struct display_modelist *modelist;
179 len = (buf[1] & 0xe0) >> 5;
180 for (i = 0; i < len; i++) {
182 vic_2d = (buf[offset] == 4) ?
183 98 : (96 - buf[offset]);
184 hdmi_add_vic(vic_2d, head);
192 len += (buf[1] & 0x1F) + 2;
193 if (((buf[0] & 0x60) == 0x40) || ((buf[0] & 0x60) == 0x20)) {
194 format_3d = buf[offset++] << 8;
195 format_3d |= buf[offset++];
196 if ((buf[0] & 0x60) == 0x20) {
199 vic_mask = buf[offset++] << 8;
200 vic_mask |= buf[offset++];
207 for (i = 0; i < 16; i++) {
208 if (vic_mask & (1 << i)) {
210 for (pos = (head)->next; pos != (head);
214 list_entry(pos, struct display_modelist, list);
215 modelist->format_3d = format_3d;
221 while (offset < len) {
222 vic_2d = (buf[offset] & 0xF0) >> 4;
223 structure_3d = (buf[offset++] & 0x0F);
225 for (pos = (head)->next; pos != (head);
230 list_entry(pos, struct display_modelist, list);
231 modelist->format_3d |=
233 if (structure_3d & 0x08)
234 modelist->detail_3d =
235 (buf[offset++] & 0xF0) >> 4;
240 /* mandatory formats */
241 for (pos = (head)->next; pos != (head); pos = pos->next) {
242 modelist = list_entry(pos,
243 struct display_modelist,
245 if (modelist->vic == HDMI_1920X1080P_24HZ ||
246 modelist->vic == HDMI_1280X720P_60HZ ||
247 modelist->vic == HDMI_1280X720P_50HZ) {
248 modelist->format_3d |=
249 (1 << HDMI_3D_FRAME_PACKING) |
250 (1 << HDMI_3D_TOP_BOOTOM);
251 } else if (modelist->vic == HDMI_1920X1080I_60HZ ||
252 modelist->vic == HDMI_1920X1080I_50HZ) {
253 modelist->format_3d |=
254 (1 << HDMI_3D_SIDE_BY_SIDE_HALF);
262 static int hdmi_edmi_parse_vsdb(unsigned char *buf, struct hdmi_edid *pedid,
263 int cur_offset, int IEEEOUI)
265 int count, buf_offset;
267 count = buf[cur_offset] & 0x1F;
270 pedid->sink_hdmi = 1;
271 pedid->cecaddress = buf[cur_offset + 5];
272 pedid->cecaddress |= buf[cur_offset + 4] << 8;
273 EDBG("[CEA] CEC Physical address is 0x%08x.\n",
276 pedid->deepcolor = (buf[cur_offset + 6] >> 3) & 0x0F;
278 pedid->maxtmdsclock = buf[cur_offset + 7] * 5000000;
279 EDBG("[CEA] maxtmdsclock is %d.\n",
280 pedid->maxtmdsclock);
283 pedid->fields_present = buf[cur_offset + 8];
284 EDBG("[CEA] fields_present is 0x%02x.\n",
285 pedid->fields_present);
287 buf_offset = cur_offset + 9;
288 if (pedid->fields_present & 0x80) {
289 pedid->video_latency = buf[buf_offset++];
290 pedid->audio_latency = buf[buf_offset++];
292 if (pedid->fields_present & 0x40) {
293 pedid->interlaced_video_latency = buf[buf_offset++];
294 pedid->interlaced_audio_latency = buf[buf_offset++];
296 if (pedid->fields_present & 0x20) {
297 hdmi_edid_parse_3dinfo(buf + buf_offset,
302 pedid->sink_hdmi = 1;
303 pedid->hf_vsdb_version = buf[cur_offset + 4];
304 switch (pedid->hf_vsdb_version) {
305 case 1:/*compliant with HDMI Specification 2.0*/
306 pedid->maxtmdsclock =
307 buf[cur_offset + 5] * 5000000;
308 EDBG("[CEA] maxtmdsclock is %d.\n",
309 pedid->maxtmdsclock);
310 pedid->scdc_present = buf[cur_offset + 6] >> 7;
312 (buf[cur_offset + 6] & 0x40) >> 6;
313 pedid->lte_340mcsc_scramble =
314 (buf[cur_offset + 6] & 0x08) >> 3;
315 pedid->independent_view =
316 (buf[cur_offset + 6] & 0x04) >> 2;
318 (buf[cur_offset + 6] & 0x02) >> 1;
319 pedid->osd_disparity_3d =
320 buf[cur_offset + 6] & 0x01;
321 pedid->deepcolor_420 =
322 (buf[cur_offset + 7] & 0x7) << 1;
325 pr_info("hf_vsdb_version = %d\n",
326 pedid->hf_vsdb_version);
331 pr_info("IEEOUT = 0x%x\n", IEEEOUI);
337 static void hdmi_edid_parse_yuv420cmdb(unsigned char *buf, int count,
338 struct list_head *head)
340 struct list_head *pos;
341 struct display_modelist *modelist;
342 int i, j, yuv420_mask, vic;
344 for (i = 0; i < count - 1; i++) {
345 EDBG("vic which support yuv420 mode is %x\n", buf[i]);
346 yuv420_mask |= buf[i] << (8 * i);
348 for (i = 0; i < 32; i++) {
349 if (yuv420_mask & (1 << i)) {
351 for (pos = head->next; pos != (head); pos = pos->next) {
354 list_entry(pos, struct display_modelist, list);
355 vic = modelist->vic |
357 hdmi_add_vic(vic, head);
365 /* Parse CEA 861 Serial Extension. */
366 static int hdmi_edid_parse_extensions_cea(unsigned char *buf,
367 struct hdmi_edid *pedid)
369 unsigned int ddc_offset, native_dtd_num, cur_offset = 4;
370 unsigned int tag, IEEEOUI = 0, count, i;
371 struct fb_videomode *vmode;
374 return E_HDMI_EDID_PARAM;
376 /* Check ces extension version */
378 pr_err("[CEA] error version.\n");
379 return E_HDMI_EDID_VERSION;
383 pedid->baseaudio_support = (buf[3] >> 6) & 0x01;
384 pedid->ycbcr444 = (buf[3] >> 5) & 0x01;
385 pedid->ycbcr422 = (buf[3] >> 4) & 0x01;
386 native_dtd_num = buf[3] & 0x0F;
387 /* Parse data block */
388 while (cur_offset < ddc_offset) {
389 tag = buf[cur_offset] >> 5;
390 count = buf[cur_offset] & 0x1F;
392 case 0x02: /* Video Data Block */
393 EDBG("[CEA] Video Data Block.\n");
394 hdmi_edid_get_cea_svd(buf + cur_offset, pedid);
396 case 0x01: /* Audio Data Block */
397 EDBG("[CEA] Audio Data Block.\n");
398 hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);
400 case 0x04: /* Speaker Allocation Data Block */
401 EDBG("[CEA] Speaker Allocatio Data Block.\n");
403 case 0x03: /* Vendor Specific Data Block */
404 EDBG("[CEA] Vendor Specific Data Block.\n");
406 IEEEOUI = buf[cur_offset + 3];
408 IEEEOUI += buf[cur_offset + 2];
410 IEEEOUI += buf[cur_offset + 1];
411 EDBG("[CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);
413 hdmi_edmi_parse_vsdb(buf, pedid,
414 cur_offset, IEEEOUI);
416 case 0x05: /* VESA DTC Data Block */
417 EDBG("[CEA] VESA DTC Data Block.\n");
419 case 0x07: /* Use Extended Tag */
420 EDBG("[CEA] Use Extended Tag Data Block %02x.\n",
421 buf[cur_offset + 1]);
422 switch (buf[cur_offset + 1]) {
424 EDBG("[CEA] Video Capability Data Block\n");
425 EDBG("value is %02x\n", buf[cur_offset + 2]);
428 EDBG("[CEA] Colorimetry Data Block\n");
429 EDBG("value is %02x\n", buf[cur_offset + 2]);
430 pedid->colorimetry = buf[cur_offset + 2];
433 EDBG("[CEA] YCBCR 4:2:0 Video Data Block\n");
434 for (i = 0; i < count - 1; i++) {
436 buf[cur_offset + 2 + i]);
438 IEEEOUI = buf[cur_offset + 2 + i] |
440 hdmi_add_vic(IEEEOUI,
445 EDBG("[CEA] YCBCR 4:2:0 Capability Map Data\n");
446 hdmi_edid_parse_yuv420cmdb(&buf[cur_offset + 2],
454 pr_err("[CEA] unkowned data block tag.\n");
457 cur_offset += (buf[cur_offset] & 0x1F) + 1;
461 vmode = kmalloc(sizeof(*vmode), GFP_KERNEL);
464 return E_HDMI_EDID_SUCCESS;
465 while (ddc_offset < HDMI_EDID_BLOCK_SIZE - 2) {
466 if (!buf[ddc_offset] && !buf[ddc_offset + 1])
468 memset(vmode, 0, sizeof(struct fb_videomode));
469 hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
470 hdmi_add_vic(hdmi_videomode_to_vic(vmode), &pedid->modelist);
475 return E_HDMI_EDID_SUCCESS;
478 int hdmi_edid_parse_extensions(unsigned char *buf, struct hdmi_edid *pedid)
483 return E_HDMI_EDID_PARAM;
486 rc = hdmi_edid_checksum(buf);
487 if (rc != E_HDMI_EDID_SUCCESS) {
488 pr_err("[EDID] extensions block checksum error\n");
489 return E_HDMI_EDID_CHECKSUM;
494 EDBG("[EDID-EXTEND] Iextensions block map.\n");
497 EDBG("[EDID-EXTEND] CEA 861 Series Extension.\n");
498 hdmi_edid_parse_extensions_cea(buf, pedid);
501 EDBG("[EDID-EXTEND] Video Timing Block Extension.\n");
504 EDBG("[EDID-EXTEND] Display Information Extension.\n");
507 EDBG("[EDID-EXTEND] Localized String Extension.\n");
510 EDBG("[EDID-EXTEND] Digital Packet Video Link Extension.\n");
513 pr_err("[EDID-EXTEND] Unkowned Extension.\n");
514 return E_HDMI_EDID_UNKOWNDATA;
517 return E_HDMI_EDID_SUCCESS;