OSDN Git Service

various cleanups to EDID code:
[android-x86/external-libdrm.git] / linux-core / drm_edid.c
1 /*
2  * Copyright (c) 2007 Intel Corporation
3  *   Jesse Barnes <jesse.barnes@intel.com>
4  *
5  * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from
6  * FB layer.
7  */
8 #include <linux/i2c.h>
9 #include <linux/i2c-algo-bit.h>
10 #include "drmP.h"
11
12 #define EDID_LENGTH 128
13 #define DDC_ADDR 0x50
14
15 #ifdef BIG_ENDIAN
16 #error "EDID structure is little endian, need big endian versions"
17 #endif
18
19 struct est_timings {
20         u8 t1;
21         u8 t2;
22         u8 mfg_rsvd;
23 } __attribute__((packed));
24
25 struct std_timing {
26         u8 hsize; /* need to multiply by 8 then add 248 */
27         u8 vfreq:6; /* need to add 60 */
28         u8 aspect_ratio:2; /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
29 } __attribute__((packed));
30
31 /* If detailed data is pixel timing */
32 struct detailed_pixel_timing {
33         u8 hactive_lo;
34         u8 hblank_lo;
35         u8 hblank_hi:4;
36         u8 hactive_hi:4;
37         u8 vactive_lo;
38         u8 vblank_lo;
39         u8 vblank_hi:4;
40         u8 vactive_hi:4;
41         u8 hsync_offset_lo;
42         u8 hsync_pulse_width_lo;
43         u8 vsync_pulse_width_lo:4;
44         u8 vsync_offset_lo:4;
45         u8 hsync_pulse_width_hi:2;
46         u8 hsync_offset_hi:2;
47         u8 vsync_pulse_width_hi:2;
48         u8 vsync_offset_hi:2;
49         u8 width_mm_lo;
50         u8 height_mm_lo;
51         u8 height_mm_hi:4;
52         u8 width_mm_hi:4;
53         u8 hborder;
54         u8 vborder;
55         u8 unknown0:1;
56         u8 vsync_positive:1;
57         u8 hsync_positive:1;
58         u8 separate_sync:2;
59         u8 stereo:1;
60         u8 unknown6:1;
61         u8 interlaced:1;
62 } __attribute__((packed));
63
64 /* If it's not pixel timing, it'll be one of the below */
65 struct detailed_data_string {
66         u8 str[13];
67 } __attribute__((packed));
68
69 struct detailed_data_monitor_range {
70         u8 min_vfreq;
71         u8 max_vfreq;
72         u8 min_hfreq_khz;
73         u8 max_hfreq_khz;
74         u8 pixel_clock_mhz; /* need to multiply by 10 */
75         u16 sec_gtf_toggle; /* A000=use above, 20=use below */ /* FIXME: byte order */
76         u8 hfreq_start_khz; /* need to multiply by 2 */
77         u8 c; /* need to divide by 2 */
78         u16 m; /* FIXME: byte order */
79         u8 k;
80         u8 j; /* need to divide by 2 */
81 } __attribute__((packed));
82
83 struct detailed_data_wpindex {
84         u8 white_y_lo:2;
85         u8 white_x_lo:2;
86         u8 pad:4;
87         u8 white_x_hi;
88         u8 white_y_hi;
89         u8 gamma; /* need to divide by 100 then add 1 */
90 } __attribute__((packed));
91
92 struct detailed_data_color_point {
93         u8 windex1;
94         u8 wpindex1[3];
95         u8 windex2;
96         u8 wpindex2[3];
97 } __attribute__((packed));
98
99 struct detailed_non_pixel {
100         u8 pad1;
101         u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name
102                     fb=color point data, fa=standard timing data,
103                     f9=undefined, f8=mfg. reserved */
104         u8 pad2;
105         union {
106                 struct detailed_data_string str;
107                 struct detailed_data_monitor_range range;
108                 struct detailed_data_wpindex color;
109                 struct std_timing timings[5];
110         } data;
111 } __attribute__((packed));
112
113 #define EDID_DETAIL_STD_MODES 0xfa
114 #define EDID_DETAIL_MONITOR_CPDATA 0xfb
115 #define EDID_DETAIL_MONITOR_NAME 0xfc
116 #define EDID_DETAIL_MONITOR_RANGE 0xfd
117 #define EDID_DETAIL_MONITOR_STRING 0xfe
118 #define EDID_DETAIL_MONITOR_SERIAL 0xff
119
120 struct detailed_timing {
121         u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */
122         union {
123                 struct detailed_pixel_timing pixel_data;
124                 struct detailed_non_pixel other_data;
125         } data;
126 } __attribute__((packed));
127
128 struct edid {
129         u8 header[8];
130         /* Vendor & product info */
131         u16 mfg_id; /* FIXME: byte order */
132         u16 prod_code; /* FIXME: byte order */
133         u32 serial; /* FIXME: byte order */
134         u8 mfg_week;
135         u8 mfg_year;
136         /* EDID version */
137         u8 version;
138         u8 revision;
139         /* Display info: */
140         /*   input definition */
141         u8 serration_vsync:1;
142         u8 sync_on_green:1;
143         u8 composite_sync:1;
144         u8 separate_syncs:1;
145         u8 blank_to_black:1;
146         u8 video_level:2;
147         u8 digital:1; /* bits below must be zero if set */
148         u8 width_cm;
149         u8 height_cm;
150         u8 gamma;
151         /*   feature support */
152         u8 default_gtf:1;
153         u8 preferred_timing:1;
154         u8 standard_color:1;
155         u8 display_type:2; /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
156         u8 pm_active_off:1;
157         u8 pm_suspend:1;
158         u8 pm_standby:1;
159         /* Color characteristics */
160         u8 red_green_lo;
161         u8 black_white_lo;
162         u8 red_x;
163         u8 red_y;
164         u8 green_x;
165         u8 green_y;
166         u8 blue_x;
167         u8 blue_y;
168         u8 white_x;
169         u8 white_y;
170         /* Est. timings and mfg rsvd timings*/
171         struct est_timings established_timings;
172         /* Standard timings 1-8*/
173         struct std_timing standard_timings[8];
174         /* Detailing timings 1-4 */
175         struct detailed_timing detailed_timings[4];
176         /* Number of 128 byte ext. blocks */
177         u8 extensions;
178         /* Checksum */
179         u8 checksum;
180 } __attribute__((packed));
181
182 static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
183
184 /**
185  * edid_valid - sanity check EDID data
186  * @edid: EDID data
187  *
188  * Sanity check the EDID block by looking at the header, the version number
189  * and the checksum.  Return 0 if the EDID doesn't check out, or 1 if it's
190  * valid.
191  */
192 static bool edid_valid(struct edid *edid)
193 {
194         int i;
195         u8 csum = 0;
196         u8 *raw_edid = (u8 *)edid;
197
198         if (memcmp(edid->header, edid_header, sizeof(edid_header)))
199                 goto bad;
200         if (edid->version != 1)
201                 goto bad;
202         if (edid->revision <= 0 || edid->revision > 3)
203                 goto bad;
204
205         for (i = 0; i < EDID_LENGTH; i++)
206                 csum += raw_edid[i];
207         if (csum)
208                 goto bad;
209
210         return 1;
211
212 bad:
213         return 0;
214 }
215
216 /**
217  * drm_mode_std - convert standard mode info (width, height, refresh) into mode
218  * @t: standard timing params
219  *
220  * Take the standard timing params (in this case width, aspect, and refresh)
221  * and convert them into a real mode using CVT.
222  *
223  * Punts for now, but should eventually use the FB layer's CVT based mode
224  * generation code.
225  */
226 struct drm_display_mode *drm_mode_std(struct drm_device *dev,
227                                       struct std_timing *t)
228 {
229 //      struct fb_videomode mode;
230
231 //      fb_find_mode_cvt(&mode, 0, 0);
232         /* JJJ:  convert to drm_display_mode */
233         struct drm_display_mode *mode;
234         int hsize = t->hsize * 8 + 248, vsize;
235
236         mode = drm_crtc_mode_create(dev);
237         if (!mode)
238                 return NULL;
239
240         if (t->aspect_ratio == 0)
241                 vsize = (hsize * 10) / 16;
242         else if (t->aspect_ratio == 1)
243                 vsize = (hsize * 3) / 4;
244         else if (t->aspect_ratio == 2)
245                 vsize = (hsize * 4) / 5;
246         else
247                 vsize = (hsize * 9) / 16;
248
249         snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", hsize, vsize);
250
251         return mode;
252 }
253
254 /**
255  * drm_mode_detailed - create a new mode from an EDID detailed timing section
256  * @timing: EDID detailed timing info
257  * @preferred: is this a preferred mode?
258  *
259  * An EDID detailed timing block contains enough info for us to create and
260  * return a new struct drm_display_mode.  The @preferred flag will be set
261  * if this is the display's preferred timing, and we'll use it to indicate
262  * to the other layers that this mode is desired.
263  */
264 struct drm_display_mode *drm_mode_detailed(drm_device_t *dev,
265                                            struct detailed_timing *timing)
266 {
267         struct drm_display_mode *mode;
268         struct detailed_pixel_timing *pt = &timing->data.pixel_data;
269
270         if (pt->stereo) {
271                 printk(KERN_WARNING "stereo mode not supported\n");
272                 return NULL;
273         }
274         if (!pt->separate_sync) {
275                 printk(KERN_WARNING "integrated sync not supported\n");
276                 return NULL;
277         }
278
279         mode = drm_crtc_mode_create(dev);
280         if (!mode)
281                 return NULL;
282
283         mode->type = DRM_MODE_TYPE_DRIVER;
284         mode->clock = timing->pixel_clock / 100;
285
286         mode->hdisplay = (pt->hactive_hi << 8) | pt->hactive_lo;
287         mode->hsync_start = mode->hdisplay + ((pt->hsync_offset_hi << 8) |
288                                               pt->hsync_offset_lo);
289         mode->hsync_end = mode->hsync_start +
290                 ((pt->hsync_pulse_width_hi << 8) |
291                  pt->hsync_pulse_width_lo);
292         mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
293
294         mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
295         mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) |
296                                               pt->vsync_offset_lo);
297         mode->vsync_end = mode->vsync_start +
298                 ((pt->vsync_pulse_width_hi << 8) |
299                  pt->vsync_pulse_width_lo);
300         mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
301
302         snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay,
303                  mode->vdisplay);
304
305         if (pt->interlaced)
306                 mode->flags |= V_INTERLACE;
307
308         mode->flags |= pt->hsync_positive ? V_PHSYNC : V_NHSYNC;
309         mode->flags |= pt->vsync_positive ? V_PVSYNC : V_NVSYNC;
310
311         return mode;
312 }
313
314 /*
315  * Detailed mode info for the EDID "established modes" data to use.
316  */
317 static struct drm_display_mode edid_est_modes[] = {
318         { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
319                    968, 1056, 0, 600, 601, 605, 628, 0,
320                    V_PHSYNC | V_PVSYNC) }, /* 800x600@60Hz */
321         { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824,
322                    896, 1024, 0, 600, 601, 603,  625, 0,
323                    V_PHSYNC | V_PVSYNC) }, /* 800x600@56Hz */
324         { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656,
325                    720, 840, 0, 480, 481, 484, 500, 0,
326                    V_NHSYNC | V_NVSYNC) }, /* 640x480@75Hz */
327         { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
328                    704,  832, 0, 480, 489, 491, 520, 0,
329                    V_NHSYNC | V_NVSYNC) }, /* 640x480@72Hz */
330         { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704,
331                    768,  864, 0, 480, 483, 486, 525, 0,
332                    V_NHSYNC | V_NVSYNC) }, /* 640x480@67Hz */
333         { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656,
334                    752, 800, 0, 480, 490, 492, 525, 0,
335                    V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
336         { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738,
337                    846, 900, 0, 400, 421, 423,  449, 0,
338                    V_NHSYNC | V_NVSYNC) }, /* 720x400@88Hz */
339         { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738,
340                    846,  900, 0, 400, 412, 414, 449, 0,
341                    V_NHSYNC | V_PVSYNC) }, /* 720x400@70Hz */
342         { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
343                    1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
344                    V_PHSYNC | V_PVSYNC) }, /* 1280x1024@75Hz */
345         { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040,
346                    1136, 1312, 0,  768, 769, 772, 800, 0,
347                    V_PHSYNC | V_PVSYNC) }, /* 1024x768@75Hz */
348         { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
349                    1184, 1328, 0,  768, 771, 777, 806, 0,
350                    V_NHSYNC | V_NVSYNC) }, /* 1024x768@70Hz */
351         { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
352                    1184, 1344, 0,  768, 771, 777, 806, 0,
353                    V_NHSYNC | V_NVSYNC) }, /* 1024x768@60Hz */
354         { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032,
355                    1208, 1264, 0, 768, 768, 776, 817, 0,
356                    V_PHSYNC | V_PVSYNC | V_INTERLACE) }, /* 1024x768@43Hz */
357         { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864,
358                    928, 1152, 0, 624, 625, 628, 667, 0,
359                    V_NHSYNC | V_NVSYNC) }, /* 832x624@75Hz */
360         { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816,
361                    896, 1056, 0, 600, 601, 604,  625, 0,
362                    V_PHSYNC | V_PVSYNC) }, /* 800x600@75Hz */
363         { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856,
364                    976, 1040, 0, 600, 637, 643, 666, 0,
365                    V_PHSYNC | V_PVSYNC) }, /* 800x600@72Hz */
366         { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
367                    1344, 1600, 0,  864, 865, 868, 900, 0,
368                    V_PHSYNC | V_PVSYNC) }, /* 1152x864@75Hz */
369 };
370
371 #define EDID_EST_TIMINGS 16
372 #define EDID_STD_TIMINGS 8
373 #define EDID_DETAILED_TIMINGS 4
374
375 /**
376  * add_established_modes - get est. modes from EDID and add them
377  * @edid: EDID block to scan
378  *
379  * Each EDID block contains a bitmap of the supported "established modes" list
380  * (defined above).  Tease them out and add them to the global modes list.
381  */
382 static int add_established_modes(struct drm_output *output, struct edid *edid)
383 {
384         struct drm_device *dev = output->dev;
385         unsigned long est_bits = edid->established_timings.t1 |
386                 (edid->established_timings.t2 << 8) |
387                 ((edid->established_timings.mfg_rsvd & 0x80) << 9);
388         int i, modes = 0;
389
390         for (i = 0; i <= EDID_EST_TIMINGS; i++)
391                 if (est_bits & (1<<i)) {
392                         struct drm_display_mode *newmode;
393                         newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
394                         drm_mode_probed_add(output, newmode);
395                         modes++;
396                 }
397
398         return modes;
399 }
400
401 /**
402  * add_standard_modes - get std. modes from EDID and add them
403  * @edid: EDID block to scan
404  *
405  * Standard modes can be calculated using the CVT standard.  Grab them from
406  * @edid, calculate them, and add them to the list.
407  */
408 static int add_standard_modes(struct drm_output *output, struct edid *edid)
409 {
410         struct drm_device *dev = output->dev;
411         int i, modes = 0;
412
413         for (i = 0; i < EDID_STD_TIMINGS; i++) {
414                 struct std_timing *t = &edid->standard_timings[i];
415                 struct drm_display_mode *newmode;
416
417                 /* If std timings bytes are 1, 1 it's empty */
418                 if (t->hsize == 1 && (t->aspect_ratio | t->vfreq) == 1)
419                         continue;
420
421                 newmode = drm_mode_std(dev, &edid->standard_timings[i]);
422                 drm_mode_probed_add(output, newmode);
423                 modes++;
424         }
425
426         return modes;
427 }
428
429 /**
430  * add_detailed_modes - get detailed mode info from EDID data
431  * @edid: EDID block to scan
432  *
433  * Some of the detailed timing sections may contain mode information.  Grab
434  * it and add it to the list.
435  */
436 static int add_detailed_info(struct drm_output *output, struct edid *edid)
437 {
438         struct drm_device *dev = output->dev;
439         int i, j, modes = 0;
440
441         for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
442                 struct detailed_timing *timing = &edid->detailed_timings[i];
443                 struct detailed_non_pixel *data = &timing->data.other_data;
444                 struct drm_display_mode *newmode;
445
446                 /* EDID up to and including 1.2 may put monitor info here */
447                 if (edid->version == 1 && edid->revision < 3)
448                         continue;
449
450                 /* Detailed mode timing */
451                 if (timing->pixel_clock) {
452                         newmode = drm_mode_detailed(dev, timing);
453                         /* First detailed mode is preferred */
454                         if (i == 0 && edid->preferred_timing)
455                                 newmode->type |= DRM_MODE_TYPE_PREFERRED;
456                         drm_mode_probed_add(output, newmode);
457                                      
458                         modes++;
459                         continue;
460                 }
461
462                 /* Other timing or info */
463                 switch (data->type) {
464                 case EDID_DETAIL_MONITOR_SERIAL:
465                         break;
466                 case EDID_DETAIL_MONITOR_STRING:
467                         break;
468                 case EDID_DETAIL_MONITOR_RANGE:
469                         /* Get monitor range data */
470                         break;
471                 case EDID_DETAIL_MONITOR_NAME:
472                         break;
473                 case EDID_DETAIL_MONITOR_CPDATA:
474                         break;
475                 case EDID_DETAIL_STD_MODES:
476                         /* Five modes per detailed section */
477                         for (j = 0; j < 5; i++) {
478                                 struct std_timing *std;
479                                 struct drm_display_mode *newmode;
480
481                                 std = &data->data.timings[j];
482                                 newmode = drm_mode_std(dev, std);
483                                 drm_mode_probed_add(output, newmode);
484                                 modes++;
485                         }
486                         break;
487                 default:
488                         break;
489                 }
490         }
491
492         return modes;
493 }
494
495 #define DDC_ADDR 0x50
496
497 static unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter)
498 {
499         unsigned char start = 0x0;
500         unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
501         struct i2c_msg msgs[] = {
502                 {
503                         .addr   = DDC_ADDR,
504                         .flags  = 0,
505                         .len    = 1,
506                         .buf    = &start,
507                 }, {
508                         .addr   = DDC_ADDR,
509                         .flags  = I2C_M_RD,
510                         .len    = EDID_LENGTH,
511                         .buf    = buf,
512                 }
513         };
514
515         if (!buf) {
516                 dev_warn(&adapter->dev, "unable to allocate memory for EDID "
517                          "block.\n");
518                 return NULL;
519         }
520
521         if (i2c_transfer(adapter, msgs, 2) == 2)
522                 return buf;
523
524         dev_info(&adapter->dev, "unable to read EDID block.\n");
525         kfree(buf);
526         return NULL;
527 }
528
529 static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
530 {
531         struct i2c_algo_bit_data *algo_data = adapter->algo_data;
532         unsigned char *edid = NULL;
533         int i, j;
534
535         /*
536          * Startup the bus:
537          *   Set clock line high (but give it time to come up)
538          *   Then set clock & data low
539          */
540         algo_data->setscl(algo_data->data, 1);
541         udelay(550); /* startup delay */
542         algo_data->setscl(algo_data->data, 0);
543         algo_data->setsda(algo_data->data, 0);
544
545         for (i = 0; i < 3; i++) {
546                 /* For some old monitors we need the
547                  * following process to initialize/stop DDC
548                  */
549                 algo_data->setsda(algo_data->data, 0);
550                 msleep(13);
551
552                 algo_data->setscl(algo_data->data, 1);
553                 for (j = 0; j < 5; j++) {
554                         msleep(10);
555                         if (algo_data->getscl(algo_data->data))
556                                 break;
557                 }
558                 if (j == 5)
559                         continue;
560
561                 algo_data->setsda(algo_data->data, 0);
562                 msleep(15);
563                 algo_data->setscl(algo_data->data, 0);
564                 msleep(15);
565                 algo_data->setsda(algo_data->data, 1);
566                 msleep(15);
567
568                 /* Do the real work */
569                 edid = drm_do_probe_ddc_edid(adapter);
570                 algo_data->setsda(algo_data->data, 0);
571                 algo_data->setscl(algo_data->data, 0);
572                 msleep(15);
573
574                 algo_data->setscl(algo_data->data, 1);
575                 for (j = 0; j < 10; j++) {
576                         msleep(10);
577                         if (algo_data->getscl(algo_data->data))
578                                 break;
579                 }
580
581                 algo_data->setsda(algo_data->data, 1);
582                 msleep(15);
583                 algo_data->setscl(algo_data->data, 0);
584                 if (edid)
585                         break;
586         }
587         /* Release the DDC lines when done or the Apple Cinema HD display
588          * will switch off
589          */
590         algo_data->setsda(algo_data->data, 0);
591         algo_data->setscl(algo_data->data, 0);
592         algo_data->setscl(algo_data->data, 1);
593
594         return edid;
595 }
596
597 /**
598  * drm_add_edid_modes - add modes from EDID data, if available
599  * @output: output we're probing
600  * @adapter: i2c adapter to use for DDC
601  *
602  * Poke the given output's i2c channel to grab EDID data if possible.  If we
603  * get any, add the specified modes to the output's mode list.
604  *
605  * Return number of modes added or 0 if we couldn't find any.
606  */
607 int drm_add_edid_modes(struct drm_output *output, struct i2c_adapter *adapter)
608 {
609         struct edid *edid;
610         int num_modes = 0;
611
612         edid = (struct edid *)drm_ddc_read(adapter);
613         if (!edid) {
614                 dev_warn(&output->dev->pdev->dev, "%s: no EDID data\n",
615                          output->name);
616                 goto out_err;
617         }
618
619         if (!edid_valid(edid)) {
620                 dev_warn(&output->dev->pdev->dev, "%s: EDID invalid.\n",
621                          output->name);
622                 goto out_err;
623         }
624
625         num_modes += add_established_modes(output, edid);
626         num_modes += add_standard_modes(output, edid);
627         num_modes += add_detailed_info(output, edid);
628
629         return num_modes;
630
631 out_err:
632         kfree(edid);
633         return 0;
634 }
635 EXPORT_SYMBOL(drm_add_edid_modes);