video: rockchip: add auto dp support for vr product
[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 static int edid_parse_prop_value(unsigned char *buf,
82                                  struct hdmi_edid *pedid)
83 {
84         unsigned char *block = &buf[0x36];
85
86         pedid->value.vid = ((buf[ID_MANUFACTURER_NAME_END] << 8) |
87                                 (buf[ID_MANUFACTURER_NAME]));
88         pedid->value.pid = ((buf[ID_MODEL + 1] << 8) |
89                                 (buf[ID_MODEL]));
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;
96
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);
100
101         return 0;
102 }
103
104 int hdmi_edid_parse_base(struct hdmi *hdmi, unsigned char *buf,
105                          int *extend_num, struct hdmi_edid *pedid)
106 {
107         int rc = E_HDMI_EDID_SUCCESS;
108
109         if (!buf || !extend_num)
110                 return E_HDMI_EDID_PARAM;
111
112         *extend_num = buf[0x7e];
113         #ifdef DEBUG
114         EDBG("[EDID] extend block num is %d\n", buf[0x7e]);
115         #endif
116
117         /* Check first 8 byte to ensure it is an edid base block. */
118         if (buf[0] != 0x00 ||
119             buf[1] != 0xFF ||
120             buf[2] != 0xFF ||
121             buf[3] != 0xFF ||
122             buf[4] != 0xFF ||
123             buf[5] != 0xFF ||
124             buf[6] != 0xFF ||
125             buf[7] != 0x00) {
126                 pr_err("[EDID] check header error\n");
127                 rc = E_HDMI_EDID_HEAD;
128                 goto out;
129         }
130
131         /* Checksum */
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;
136                 goto out;
137         }
138
139         pedid->specs = kzalloc(sizeof(*pedid->specs), GFP_KERNEL);
140         if (!pedid->specs)
141                 return E_HDMI_EDID_NOMEMORY;
142
143         fb_edid_to_monspecs(buf, pedid->specs);
144
145         if (hdmi->edid_auto_support)
146                 edid_parse_prop_value(buf, pedid);
147
148 out:
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.
152          */
153         if ((rc != E_HDMI_EDID_SUCCESS) &&
154             (*extend_num < 1 || *extend_num > 4))
155                 return rc;
156         else
157                 return E_HDMI_EDID_SUCCESS;
158 }
159
160 /* Parse CEA Short Video Descriptor */
161 static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)
162 {
163         int count, i, vic;
164
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);
171         }
172         return 0;
173 }
174
175 /* Parse CEA Short Audio Descriptor */
176 static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)
177 {
178         int i, count;
179
180         count = buf[0] & 0x1F;
181         pedid->audio = kmalloc((count / 3) * sizeof(struct hdmi_audio),
182                                GFP_KERNEL);
183         if (!pedid->audio)
184                 return E_HDMI_EDID_NOMEMORY;
185
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];
193         }
194         return E_HDMI_EDID_SUCCESS;
195 }
196
197 static int hdmi_edid_parse_3dinfo(unsigned char *buf, struct list_head *head)
198 {
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;
203
204         if (buf[1] & 0xe0) {
205                 len = (buf[1] & 0xe0) >> 5;
206                 for (i = 0; i < len; i++) {
207                         if (buf[offset]) {
208                                 vic_2d = (buf[offset] == 4) ?
209                                          98 : (96 - buf[offset]);
210                                 hdmi_add_vic(vic_2d, head);
211                         }
212                         offset++;
213                 }
214         }
215
216         if (buf[0] & 0x80) {
217                 /* 3d supported */
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) {
223                                 vic_mask = 0xFFFF;
224                         } else {
225                                 vic_mask  = buf[offset++] << 8;
226                                 vic_mask |= buf[offset++];
227                         }
228                 } else {
229                         format_3d = 0;
230                         vic_mask = 0;
231                 }
232
233                 for (i = 0; i < 16; i++) {
234                         if (vic_mask & (1 << i)) {
235                                 j = 0;
236                                 for (pos = (head)->next; pos != (head);
237                                         pos = pos->next) {
238                                         if (j++ == i) {
239                                                 modelist =
240                         list_entry(pos, struct display_modelist, list);
241                                                 modelist->format_3d = format_3d;
242                                                 break;
243                                         }
244                                 }
245                         }
246                 }
247                 while (offset < len) {
248                         vic_2d = (buf[offset] & 0xF0) >> 4;
249                         structure_3d = (buf[offset++] & 0x0F);
250                         j = 0;
251                         for (pos = (head)->next; pos != (head);
252                                 pos = pos->next) {
253                                 j++;
254                                 if (j == vic_2d) {
255                                         modelist =
256                                 list_entry(pos, struct display_modelist, list);
257                                         modelist->format_3d |=
258                                                 (1 << structure_3d);
259                                         if (structure_3d & 0x08)
260                                                 modelist->detail_3d =
261                                                 (buf[offset++] & 0xF0) >> 4;
262                                         break;
263                                 }
264                         }
265                 }
266                 /* mandatory formats */
267                 for (pos = (head)->next; pos != (head); pos = pos->next) {
268                         modelist = list_entry(pos,
269                                               struct display_modelist,
270                                               list);
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);
281                         }
282                 }
283         }
284
285         return 0;
286 }
287
288 static int hdmi_edmi_parse_vsdb(unsigned char *buf, struct hdmi_edid *pedid,
289                                 int cur_offset, int IEEEOUI)
290 {
291         int count, buf_offset;
292
293         count = buf[cur_offset] & 0x1F;
294         switch (IEEEOUI) {
295         case 0x0c03:
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",
300                      pedid->cecaddress);
301                 if (count > 6)
302                         pedid->deepcolor = (buf[cur_offset + 6] >> 3) & 0x0F;
303                 if (count > 7) {
304                         pedid->maxtmdsclock = buf[cur_offset + 7] * 5000000;
305                         EDBG("[CEA] maxtmdsclock is %d.\n",
306                              pedid->maxtmdsclock);
307                 }
308                 if (count > 8) {
309                         pedid->fields_present = buf[cur_offset + 8];
310                         EDBG("[CEA] fields_present is 0x%02x.\n",
311                              pedid->fields_present);
312                 }
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++];
317                 }
318                 if (pedid->fields_present & 0x40) {
319                         pedid->interlaced_video_latency = buf[buf_offset++];
320                         pedid->interlaced_audio_latency = buf[buf_offset++];
321                 }
322                 if (pedid->fields_present & 0x20) {
323                         hdmi_edid_parse_3dinfo(buf + buf_offset,
324                                                &pedid->modelist);
325                 }
326                 break;
327         case 0xc45dd8:
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;
337                         pedid->rr_capable =
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;
343                         pedid->dual_view =
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;
349                         break;
350                 default:
351                         pr_info("hf_vsdb_version = %d\n",
352                                 pedid->hf_vsdb_version);
353                         break;
354                 }
355                 break;
356         default:
357                 pr_info("IEEOUT = 0x%x\n", IEEEOUI);
358                 break;
359         }
360         return 0;
361 }
362
363 static void hdmi_edid_parse_yuv420cmdb(unsigned char *buf, int count,
364                                        struct list_head *head)
365 {
366         struct list_head *pos;
367         struct display_modelist *modelist;
368         int i, j, yuv420_mask = 0, vic;
369
370         if (count == 1) {
371                 list_for_each(pos, head) {
372                         modelist =
373                                 list_entry(pos, struct display_modelist, list);
374                         vic = modelist->vic | HDMI_VIDEO_YUV420;
375                         hdmi_add_vic(vic, head);
376                 }
377         } else {
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);
381                 }
382                 for (i = 0; i < 32; i++) {
383                         if (!(yuv420_mask & (1 << i)))
384                                 continue;
385                         j = 0;
386                         list_for_each(pos, head) {
387                                 if (j++ == i) {
388                                         modelist =
389                                 list_entry(pos, struct display_modelist, list);
390                                         vic = modelist->vic |
391                                               HDMI_VIDEO_YUV420;
392                                         hdmi_add_vic(vic, head);
393                                         break;
394                                 }
395                         }
396                 }
397         }
398 }
399
400 /* Parse CEA 861 Serial Extension. */
401 static int hdmi_edid_parse_extensions_cea(unsigned char *buf,
402                                           struct hdmi_edid *pedid)
403 {
404         unsigned int ddc_offset, native_dtd_num, cur_offset = 4;
405         unsigned int tag, IEEEOUI = 0, count, i;
406         struct fb_videomode *vmode;
407
408         if (!buf)
409                 return E_HDMI_EDID_PARAM;
410
411         /* Check ces extension version */
412         if (buf[1] != 3) {
413                 pr_err("[CEA] error version.\n");
414                 return E_HDMI_EDID_VERSION;
415         }
416
417         ddc_offset = buf[2];
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;
426                 switch (tag) {
427                 case 0x02:      /* Video Data Block */
428                         EDBG("[CEA] Video Data Block.\n");
429                         hdmi_edid_get_cea_svd(buf + cur_offset, pedid);
430                         break;
431                 case 0x01:      /* Audio Data Block */
432                         EDBG("[CEA] Audio Data Block.\n");
433                         hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);
434                         break;
435                 case 0x04:      /* Speaker Allocation Data Block */
436                         EDBG("[CEA] Speaker Allocatio Data Block.\n");
437                         break;
438                 case 0x03:      /* Vendor Specific Data Block */
439                         EDBG("[CEA] Vendor Specific Data Block.\n");
440
441                         IEEEOUI = buf[cur_offset + 3];
442                         IEEEOUI <<= 8;
443                         IEEEOUI += buf[cur_offset + 2];
444                         IEEEOUI <<= 8;
445                         IEEEOUI += buf[cur_offset + 1];
446                         EDBG("[CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);
447
448                         hdmi_edmi_parse_vsdb(buf, pedid,
449                                              cur_offset, IEEEOUI);
450                         break;
451                 case 0x05:      /* VESA DTC Data Block */
452                         EDBG("[CEA] VESA DTC Data Block.\n");
453                         break;
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]) {
458                         case 0x00:
459                                 EDBG("[CEA] Video Capability Data Block\n");
460                                 EDBG("value is %02x\n", buf[cur_offset + 2]);
461                                 break;
462                         case 0x05:
463                                 EDBG("[CEA] Colorimetry Data Block\n");
464                                 EDBG("value is %02x\n", buf[cur_offset + 2]);
465                                 pedid->colorimetry = buf[cur_offset + 2];
466                                 break;
467                         case 0x0e:
468                                 EDBG("[CEA] YCBCR 4:2:0 Video Data Block\n");
469                                 for (i = 0; i < count - 1; i++) {
470                                         EDBG("mode is %d\n",
471                                              buf[cur_offset + 2 + i]);
472                                         pedid->ycbcr420 = 1;
473                                         IEEEOUI = buf[cur_offset + 2 + i] |
474                                                   HDMI_VIDEO_YUV420;
475                                         hdmi_add_vic(IEEEOUI,
476                                                      &pedid->modelist);
477                                 }
478                                 break;
479                         case 0x0f:
480                                 EDBG("[CEA] YCBCR 4:2:0 Capability Map Data\n");
481                                 hdmi_edid_parse_yuv420cmdb(&buf[cur_offset + 2],
482                                                            count,
483                                                            &pedid->modelist);
484                                 pedid->ycbcr420 = 1;
485                                 break;
486                         }
487                         break;
488                 default:
489                         pr_err("[CEA] unkowned data block tag.\n");
490                         break;
491                 }
492                 cur_offset += (buf[cur_offset] & 0x1F) + 1;
493         }
494
495         /* Parse DTD */
496         vmode = kmalloc(sizeof(*vmode), GFP_KERNEL);
497
498         if (!vmode)
499                 return E_HDMI_EDID_SUCCESS;
500         while (ddc_offset < HDMI_EDID_BLOCK_SIZE - 2) {
501                 if (!buf[ddc_offset] && !buf[ddc_offset + 1])
502                         break;
503                 memset(vmode, 0, sizeof(struct fb_videomode));
504                 hdmi_edid_parse_dtd(buf + ddc_offset, vmode);
505                 hdmi_add_vic(hdmi_videomode_to_vic(vmode), &pedid->modelist);
506                 ddc_offset += 18;
507         }
508         kfree(vmode);
509
510         return E_HDMI_EDID_SUCCESS;
511 }
512
513 int hdmi_edid_parse_extensions(unsigned char *buf, struct hdmi_edid *pedid)
514 {
515         int rc;
516
517         if (!buf || !pedid)
518                 return E_HDMI_EDID_PARAM;
519
520         /* Checksum */
521         rc = hdmi_edid_checksum(buf);
522         if (rc != E_HDMI_EDID_SUCCESS) {
523                 pr_err("[EDID] extensions block checksum error\n");
524                 return E_HDMI_EDID_CHECKSUM;
525         }
526
527         switch (buf[0]) {
528         case 0xF0:
529                 EDBG("[EDID-EXTEND] Iextensions block map.\n");
530                 break;
531         case 0x02:
532                 EDBG("[EDID-EXTEND] CEA 861 Series Extension.\n");
533                 hdmi_edid_parse_extensions_cea(buf, pedid);
534                 break;
535         case 0x10:
536                 EDBG("[EDID-EXTEND] Video Timing Block Extension.\n");
537                 break;
538         case 0x40:
539                 EDBG("[EDID-EXTEND] Display Information Extension.\n");
540                 break;
541         case 0x50:
542                 EDBG("[EDID-EXTEND] Localized String Extension.\n");
543                 break;
544         case 0x60:
545                 EDBG("[EDID-EXTEND] Digital Packet Video Link Extension.\n");
546                 break;
547         default:
548                 pr_err("[EDID-EXTEND] Unkowned Extension.\n");
549                 return E_HDMI_EDID_UNKOWNDATA;
550         }
551
552         return E_HDMI_EDID_SUCCESS;
553 }