b8c4b3949549b2cfbb459c2ecd5bf37296e7f4a7
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rockchip-hdmi-edid.c
1 #include "rockchip-hdmi.h"
2 #include "../../fbdev/edid.h"
3
4 #ifdef EDIDDEBUG
5 #define EDBG    DBG
6 #else
7 #define EDBG(format, ...)
8 #endif
9
10 enum {
11         E_HDMI_EDID_SUCCESS = 0,
12         E_HDMI_EDID_PARAM,
13         E_HDMI_EDID_HEAD,
14         E_HDMI_EDID_CHECKSUM,
15         E_HDMI_EDID_VERSION,
16         E_HDMI_EDID_UNKOWNDATA,
17         E_HDMI_EDID_NOMEMORY
18 };
19
20 static int hdmi_edid_checksum(unsigned char *buf)
21 {
22         int i;
23         int checksum = 0;
24
25         for (i = 0; i < HDMI_EDID_BLOCK_SIZE; i++)
26                 checksum += buf[i];
27
28         checksum &= 0xff;
29
30         if (checksum == 0)
31                 return E_HDMI_EDID_SUCCESS;
32         else
33                 return E_HDMI_EDID_CHECKSUM;
34 }
35
36 /*
37  *      @Des    Parse Detail Timing Descriptor.
38  *      @Param  buf     :       pointer to DTD data.
39  *      @Param  pvic:   VIC of DTD descripted.
40  */
41 static int hdmi_edid_parse_dtd(unsigned char *block, struct fb_videomode *mode)
42 {
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 -
50                 V_SYNC_WIDTH;
51         mode->lower_margin = V_SYNC_OFFSET;
52         mode->hsync_len = H_SYNC_WIDTH;
53         mode->vsync_len = V_SYNC_WIDTH;
54         if (HSYNC_POSITIVE)
55                 mode->sync |= FB_SYNC_HOR_HIGH_ACT;
56         if (VSYNC_POSITIVE)
57                 mode->sync |= FB_SYNC_VERT_HIGH_ACT;
58         mode->refresh = PIXEL_CLOCK / ((H_ACTIVE + H_BLANKING) *
59                                        (V_ACTIVE + V_BLANKING));
60         if (INTERLACED) {
61                 mode->yres *= 2;
62                 mode->upper_margin *= 2;
63                 mode->lower_margin *= 2;
64                 mode->vsync_len *= 2;
65                 mode->vmode |= FB_VMODE_INTERLACED;
66         }
67         mode->flag = FB_MODE_IS_DETAILED;
68
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;
79 }
80
81 int hdmi_edid_parse_base(unsigned char *buf,
82                          int *extend_num, struct hdmi_edid *pedid)
83 {
84         int rc = E_HDMI_EDID_SUCCESS;
85
86         if (!buf || !extend_num)
87                 return E_HDMI_EDID_PARAM;
88
89         *extend_num = buf[0x7e];
90         #ifdef DEBUG
91         EDBG("[EDID] extend block num is %d\n", buf[0x7e]);
92         #endif
93
94         /* Check first 8 byte to ensure it is an edid base block. */
95         if (buf[0] != 0x00 ||
96             buf[1] != 0xFF ||
97             buf[2] != 0xFF ||
98             buf[3] != 0xFF ||
99             buf[4] != 0xFF ||
100             buf[5] != 0xFF ||
101             buf[6] != 0xFF ||
102             buf[7] != 0x00) {
103                 pr_err("[EDID] check header error\n");
104                 rc = E_HDMI_EDID_HEAD;
105                 goto out;
106         }
107
108         /* Checksum */
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;
113                 goto out;
114         }
115
116         pedid->specs = kzalloc(sizeof(*pedid->specs), GFP_KERNEL);
117         if (!pedid->specs)
118                 return E_HDMI_EDID_NOMEMORY;
119
120         fb_edid_to_monspecs(buf, pedid->specs);
121
122 out:
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.
126          */
127         if ((rc != E_HDMI_EDID_SUCCESS) &&
128             (*extend_num < 1 || *extend_num > 4))
129                 return rc;
130         else
131                 return E_HDMI_EDID_SUCCESS;
132 }
133
134 /* Parse CEA Short Video Descriptor */
135 static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)
136 {
137         int count, i, vic;
138
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);
145         }
146         return 0;
147 }
148
149 /* Parse CEA Short Audio Descriptor */
150 static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)
151 {
152         int i, count;
153
154         count = buf[0] & 0x1F;
155         pedid->audio = kmalloc((count / 3) * sizeof(struct hdmi_audio),
156                                GFP_KERNEL);
157         if (!pedid->audio)
158                 return E_HDMI_EDID_NOMEMORY;
159
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];
167         }
168         return E_HDMI_EDID_SUCCESS;
169 }
170
171 static int hdmi_edid_parse_3dinfo(unsigned char *buf, struct list_head *head)
172 {
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;
177
178         if (buf[1] & 0xe0) {
179                 len = (buf[1] & 0xe0) >> 5;
180                 for (i = 0; i < len; i++) {
181                         if (buf[offset]) {
182                                 vic_2d = (buf[offset] == 4) ?
183                                          98 : (96 - buf[offset]);
184                                 hdmi_add_vic(vic_2d, head);
185                         }
186                         offset++;
187                 }
188         }
189
190         if (buf[0] & 0x80) {
191                 /* 3d supported */
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) {
197                                 vic_mask = 0xFFFF;
198                         } else {
199                                 vic_mask  = buf[offset++] << 8;
200                                 vic_mask |= buf[offset++];
201                         }
202                 } else {
203                         format_3d = 0;
204                         vic_mask = 0;
205                 }
206
207                 for (i = 0; i < 16; i++) {
208                         if (vic_mask & (1 << i)) {
209                                 j = 0;
210                                 for (pos = (head)->next; pos != (head);
211                                         pos = pos->next) {
212                                         if (j++ == i) {
213                                                 modelist =
214                         list_entry(pos, struct display_modelist, list);
215                                                 modelist->format_3d = format_3d;
216                                                 break;
217                                         }
218                                 }
219                         }
220                 }
221                 while (offset < len) {
222                         vic_2d = (buf[offset] & 0xF0) >> 4;
223                         structure_3d = (buf[offset++] & 0x0F);
224                         j = 0;
225                         for (pos = (head)->next; pos != (head);
226                                 pos = pos->next) {
227                                 j++;
228                                 if (j == vic_2d) {
229                                         modelist =
230                                 list_entry(pos, struct display_modelist, list);
231                                         modelist->format_3d |=
232                                                 (1 << structure_3d);
233                                         if (structure_3d & 0x08)
234                                                 modelist->detail_3d =
235                                                 (buf[offset++] & 0xF0) >> 4;
236                                         break;
237                                 }
238                         }
239                 }
240                 /* mandatory formats */
241                 for (pos = (head)->next; pos != (head); pos = pos->next) {
242                         modelist = list_entry(pos,
243                                               struct display_modelist,
244                                               list);
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);
255                         }
256                 }
257         }
258
259         return 0;
260 }
261
262 static int hdmi_edmi_parse_vsdb(unsigned char *buf, struct hdmi_edid *pedid,
263                                 int cur_offset, int IEEEOUI)
264 {
265         int count, buf_offset;
266
267         count = buf[cur_offset] & 0x1F;
268         switch (IEEEOUI) {
269         case 0x0c03:
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",
274                      pedid->cecaddress);
275                 if (count > 6)
276                         pedid->deepcolor = (buf[cur_offset + 6] >> 3) & 0x0F;
277                 if (count > 7) {
278                         pedid->maxtmdsclock = buf[cur_offset + 7] * 5000000;
279                         EDBG("[CEA] maxtmdsclock is %d.\n",
280                              pedid->maxtmdsclock);
281                 }
282                 if (count > 8) {
283                         pedid->fields_present = buf[cur_offset + 8];
284                         EDBG("[CEA] fields_present is 0x%02x.\n",
285                              pedid->fields_present);
286                 }
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++];
291                 }
292                 if (pedid->fields_present & 0x40) {
293                         pedid->interlaced_video_latency = buf[buf_offset++];
294                         pedid->interlaced_audio_latency = buf[buf_offset++];
295                 }
296                 if (pedid->fields_present & 0x20) {
297                         hdmi_edid_parse_3dinfo(buf + buf_offset,
298                                                &pedid->modelist);
299                 }
300                 break;
301         case 0xc45dd8:
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;
311                         pedid->rr_capable =
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;
317                         pedid->dual_view =
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;
323                         break;
324                 default:
325                         pr_info("hf_vsdb_version = %d\n",
326                                 pedid->hf_vsdb_version);
327                         break;
328                 }
329                 break;
330         default:
331                 pr_info("IEEOUT = 0x%x\n", IEEEOUI);
332                 break;
333         }
334         return 0;
335 }
336
337 static void hdmi_edid_parse_yuv420cmdb(unsigned char *buf, int count,
338                                        struct list_head *head)
339 {
340         struct list_head *pos;
341         struct display_modelist *modelist;
342         int i, j, yuv420_mask = 0, vic;
343
344         if (count == 1) {
345                 list_for_each(pos, head) {
346                         modelist =
347                                 list_entry(pos, struct display_modelist, list);
348                         vic = modelist->vic | HDMI_VIDEO_YUV420;
349                         hdmi_add_vic(vic, head);
350                 }
351         } else {
352                 for (i = 0; i < count - 1; i++) {
353                         EDBG("vic which support yuv420 mode is %x\n", buf[i]);
354                         yuv420_mask |= buf[i] << (8 * i);
355                 }
356                 for (i = 0; i < 32; i++) {
357                         if (!(yuv420_mask & (1 << i)))
358                                 continue;
359                         j = 0;
360                         list_for_each(pos, head) {
361                                 if (j++ == i) {
362                                         modelist =
363                                 list_entry(pos, struct display_modelist, list);
364                                         vic = modelist->vic |
365                                               HDMI_VIDEO_YUV420;
366                                         hdmi_add_vic(vic, head);
367                                         break;
368                                 }
369                         }
370                 }
371         }
372 }
373
374 /* Parse CEA 861 Serial Extension. */
375 static int hdmi_edid_parse_extensions_cea(unsigned char *buf,
376                                           struct hdmi_edid *pedid)
377 {
378         unsigned int ddc_offset, native_dtd_num, cur_offset = 4;
379         unsigned int tag, IEEEOUI = 0, count, i;
380         struct fb_videomode *vmode;
381
382         if (!buf)
383                 return E_HDMI_EDID_PARAM;
384
385         /* Check ces extension version */
386         if (buf[1] != 3) {
387                 pr_err("[CEA] error version.\n");
388                 return E_HDMI_EDID_VERSION;
389         }
390
391         ddc_offset = buf[2];
392         pedid->baseaudio_support = (buf[3] >> 6) & 0x01;
393         pedid->ycbcr444 = (buf[3] >> 5) & 0x01;
394         pedid->ycbcr422 = (buf[3] >> 4) & 0x01;
395         native_dtd_num = buf[3] & 0x0F;
396         /* Parse data block */
397         while (cur_offset < ddc_offset) {
398                 tag = buf[cur_offset] >> 5;
399                 count = buf[cur_offset] & 0x1F;
400                 switch (tag) {
401                 case 0x02:      /* Video Data Block */
402                         EDBG("[CEA] Video Data Block.\n");
403                         hdmi_edid_get_cea_svd(buf + cur_offset, pedid);
404                         break;
405                 case 0x01:      /* Audio Data Block */
406                         EDBG("[CEA] Audio Data Block.\n");
407                         hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);
408                         break;
409                 case 0x04:      /* Speaker Allocation Data Block */
410                         EDBG("[CEA] Speaker Allocatio Data Block.\n");
411                         break;
412                 case 0x03:      /* Vendor Specific Data Block */
413                         EDBG("[CEA] Vendor Specific Data Block.\n");
414
415                         IEEEOUI = buf[cur_offset + 3];
416                         IEEEOUI <<= 8;
417                         IEEEOUI += buf[cur_offset + 2];
418                         IEEEOUI <<= 8;
419                         IEEEOUI += buf[cur_offset + 1];
420                         EDBG("[CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);
421
422                         hdmi_edmi_parse_vsdb(buf, pedid,
423                                              cur_offset, IEEEOUI);
424                         break;
425                 case 0x05:      /* VESA DTC Data Block */
426                         EDBG("[CEA] VESA DTC Data Block.\n");
427                         break;
428                 case 0x07:      /* Use Extended Tag */
429                         EDBG("[CEA] Use Extended Tag Data Block %02x.\n",
430                              buf[cur_offset + 1]);
431                         switch (buf[cur_offset + 1]) {
432                         case 0x00:
433                                 EDBG("[CEA] Video Capability Data Block\n");
434                                 EDBG("value is %02x\n", buf[cur_offset + 2]);
435                                 break;
436                         case 0x05:
437                                 EDBG("[CEA] Colorimetry Data Block\n");
438                                 EDBG("value is %02x\n", buf[cur_offset + 2]);
439                                 pedid->colorimetry = buf[cur_offset + 2];
440                                 break;
441                         case 0x0e:
442                                 EDBG("[CEA] YCBCR 4:2:0 Video Data Block\n");
443                                 for (i = 0; i < count - 1; i++) {
444                                         EDBG("mode is %d\n",
445                                              buf[cur_offset + 2 + i]);
446                                         pedid->ycbcr420 = 1;
447                                         IEEEOUI = buf[cur_offset + 2 + i] |
448                                                   HDMI_VIDEO_YUV420;
449                                         hdmi_add_vic(IEEEOUI,
450                                                      &pedid->modelist);
451                                 }
452                                 break;
453                         case 0x0f:
454                                 EDBG("[CEA] YCBCR 4:2:0 Capability Map Data\n");
455                                 hdmi_edid_parse_yuv420cmdb(&buf[cur_offset + 2],
456                                                            count,
457                                                            &pedid->modelist);
458                                 pedid->ycbcr420 = 1;
459                                 break;
460                         }
461                         break;
462                 default:
463                         pr_err("[CEA] unkowned data block tag.\n");
464                         break;
465                 }
466                 cur_offset += (buf[cur_offset] & 0x1F) + 1;
467         }
468
469         /* Parse DTD */
470         vmode = kmalloc(sizeof(*vmode), GFP_KERNEL);
471
472         if (!vmode)
473                 return E_HDMI_EDID_SUCCESS;
474         while (ddc_offset < HDMI_EDID_BLOCK_SIZE - 2) {
475                 if (!buf[ddc_offset] && !buf[ddc_offset + 1])
476                         break;
477                 memset(vmode, 0, sizeof(struct fb_videomode));
478                 hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
479                 hdmi_add_vic(hdmi_videomode_to_vic(vmode), &pedid->modelist);
480                 ddc_offset += 18;
481         }
482         kfree(vmode);
483
484         return E_HDMI_EDID_SUCCESS;
485 }
486
487 int hdmi_edid_parse_extensions(unsigned char *buf, struct hdmi_edid *pedid)
488 {
489         int rc;
490
491         if (!buf || !pedid)
492                 return E_HDMI_EDID_PARAM;
493
494         /* Checksum */
495         rc = hdmi_edid_checksum(buf);
496         if (rc != E_HDMI_EDID_SUCCESS) {
497                 pr_err("[EDID] extensions block checksum error\n");
498                 return E_HDMI_EDID_CHECKSUM;
499         }
500
501         switch (buf[0]) {
502         case 0xF0:
503                 EDBG("[EDID-EXTEND] Iextensions block map.\n");
504                 break;
505         case 0x02:
506                 EDBG("[EDID-EXTEND] CEA 861 Series Extension.\n");
507                 hdmi_edid_parse_extensions_cea(buf, pedid);
508                 break;
509         case 0x10:
510                 EDBG("[EDID-EXTEND] Video Timing Block Extension.\n");
511                 break;
512         case 0x40:
513                 EDBG("[EDID-EXTEND] Display Information Extension.\n");
514                 break;
515         case 0x50:
516                 EDBG("[EDID-EXTEND] Localized String Extension.\n");
517                 break;
518         case 0x60:
519                 EDBG("[EDID-EXTEND] Digital Packet Video Link Extension.\n");
520                 break;
521         default:
522                 pr_err("[EDID-EXTEND] Unkowned Extension.\n");
523                 return E_HDMI_EDID_UNKOWNDATA;
524         }
525
526         return E_HDMI_EDID_SUCCESS;
527 }