Rev 3120 | Rev 3480 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1123 | serge | 1 | /* |
2 | * Copyright (c) 2006 Luc Verhaegen (quirks list) |
||
3 | * Copyright (c) 2007-2008 Intel Corporation |
||
4 | * Jesse Barnes |
||
1963 | serge | 5 | * Copyright 2010 Red Hat, Inc. |
1123 | serge | 6 | * |
7 | * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from |
||
8 | * FB layer. |
||
9 | * Copyright (C) 2006 Dennis Munsie |
||
10 | * |
||
11 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
12 | * copy of this software and associated documentation files (the "Software"), |
||
13 | * to deal in the Software without restriction, including without limitation |
||
14 | * the rights to use, copy, modify, merge, publish, distribute, sub license, |
||
15 | * and/or sell copies of the Software, and to permit persons to whom the |
||
16 | * Software is furnished to do so, subject to the following conditions: |
||
17 | * |
||
18 | * The above copyright notice and this permission notice (including the |
||
19 | * next paragraph) shall be included in all copies or substantial portions |
||
20 | * of the Software. |
||
21 | * |
||
22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
24 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
25 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
28 | * DEALINGS IN THE SOFTWARE. |
||
29 | */ |
||
1221 | serge | 30 | #include |
1963 | serge | 31 | #include |
1125 | serge | 32 | #include |
3031 | serge | 33 | #include |
34 | #include |
||
35 | #include |
||
1963 | serge | 36 | #include "drm_edid_modes.h" |
1123 | serge | 37 | |
1963 | serge | 38 | #define version_greater(edid, maj, min) \ |
39 | (((edid)->version > (maj)) || \ |
||
40 | ((edid)->version == (maj) && (edid)->revision > (min))) |
||
1123 | serge | 41 | |
1963 | serge | 42 | #define EDID_EST_TIMINGS 16 |
43 | #define EDID_STD_TIMINGS 8 |
||
44 | #define EDID_DETAILED_TIMINGS 4 |
||
45 | |||
1123 | serge | 46 | /* |
47 | * EDID blocks out in the wild have a variety of bugs, try to collect |
||
48 | * them here (note that userspace may work around broken monitors first, |
||
49 | * but fixes should make their way here so that the kernel "just works" |
||
50 | * on as many displays as possible). |
||
51 | */ |
||
52 | |||
53 | /* First detailed mode wrong, use largest 60Hz mode */ |
||
54 | #define EDID_QUIRK_PREFER_LARGE_60 (1 << 0) |
||
55 | /* Reported 135MHz pixel clock is too high, needs adjustment */ |
||
56 | #define EDID_QUIRK_135_CLOCK_TOO_HIGH (1 << 1) |
||
57 | /* Prefer the largest mode at 75 Hz */ |
||
58 | #define EDID_QUIRK_PREFER_LARGE_75 (1 << 2) |
||
59 | /* Detail timing is in cm not mm */ |
||
60 | #define EDID_QUIRK_DETAILED_IN_CM (1 << 3) |
||
61 | /* Detailed timing descriptors have bogus size values, so just take the |
||
62 | * maximum size and use that. |
||
63 | */ |
||
64 | #define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4) |
||
65 | /* Monitor forgot to set the first detailed is preferred bit. */ |
||
66 | #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) |
||
67 | /* use +hsync +vsync for detailed mode */ |
||
68 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) |
||
3031 | serge | 69 | /* Force reduced-blanking timings for detailed modes */ |
70 | #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) |
||
1123 | serge | 71 | |
1963 | serge | 72 | struct detailed_mode_closure { |
73 | struct drm_connector *connector; |
||
74 | struct edid *edid; |
||
75 | bool preferred; |
||
76 | u32 quirks; |
||
77 | int modes; |
||
78 | }; |
||
1430 | serge | 79 | |
1179 | serge | 80 | #define LEVEL_DMT 0 |
81 | #define LEVEL_GTF 1 |
||
1963 | serge | 82 | #define LEVEL_GTF2 2 |
83 | #define LEVEL_CVT 3 |
||
1179 | serge | 84 | |
1123 | serge | 85 | static struct edid_quirk { |
3031 | serge | 86 | char vendor[4]; |
1123 | serge | 87 | int product_id; |
88 | u32 quirks; |
||
89 | } edid_quirk_list[] = { |
||
3031 | serge | 90 | /* ASUS VW222S */ |
91 | { "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING }, |
||
92 | |||
1123 | serge | 93 | /* Acer AL1706 */ |
94 | { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, |
||
95 | /* Acer F51 */ |
||
96 | { "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 }, |
||
97 | /* Unknown Acer */ |
||
98 | { "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, |
||
99 | |||
100 | /* Belinea 10 15 55 */ |
||
101 | { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, |
||
102 | { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, |
||
103 | |||
104 | /* Envision Peripherals, Inc. EN-7100e */ |
||
105 | { "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH }, |
||
1963 | serge | 106 | /* Envision EN2028 */ |
107 | { "EPI", 8232, EDID_QUIRK_PREFER_LARGE_60 }, |
||
1123 | serge | 108 | |
109 | /* Funai Electronics PM36B */ |
||
110 | { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | |
||
111 | EDID_QUIRK_DETAILED_IN_CM }, |
||
112 | |||
113 | /* LG Philips LCD LP154W01-A5 */ |
||
114 | { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, |
||
115 | { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, |
||
116 | |||
117 | /* Philips 107p5 CRT */ |
||
118 | { "PHL", 57364, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, |
||
119 | |||
120 | /* Proview AY765C */ |
||
121 | { "PTS", 765, EDID_QUIRK_FIRST_DETAILED_PREFERRED }, |
||
122 | |||
123 | /* Samsung SyncMaster 205BW. Note: irony */ |
||
124 | { "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP }, |
||
125 | /* Samsung SyncMaster 22[5-6]BW */ |
||
126 | { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, |
||
127 | { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, |
||
3031 | serge | 128 | |
129 | /* ViewSonic VA2026w */ |
||
130 | { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING }, |
||
1123 | serge | 131 | }; |
132 | |||
1963 | serge | 133 | /*** DDC fetch and block validation ***/ |
1123 | serge | 134 | |
1221 | serge | 135 | static const u8 edid_header[] = { |
136 | 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 |
||
137 | }; |
||
1123 | serge | 138 | |
2160 | serge | 139 | /* |
140 | * Sanity check the header of the base EDID block. Return 8 if the header |
||
141 | * is perfect, down to 0 if it's totally wrong. |
||
142 | */ |
||
143 | int drm_edid_header_is_valid(const u8 *raw_edid) |
||
144 | { |
||
145 | int i, score = 0; |
||
146 | |||
147 | for (i = 0; i < sizeof(edid_header); i++) |
||
148 | if (raw_edid[i] == edid_header[i]) |
||
149 | score++; |
||
150 | |||
151 | return score; |
||
152 | } |
||
153 | EXPORT_SYMBOL(drm_edid_header_is_valid); |
||
154 | |||
3031 | serge | 155 | static int edid_fixup __read_mostly = 6; |
156 | //module_param_named(edid_fixup, edid_fixup, int, 0400); |
||
157 | //MODULE_PARM_DESC(edid_fixup, |
||
158 | // "Minimum number of valid EDID header bytes (0-8, default 6)"); |
||
2160 | serge | 159 | |
1963 | serge | 160 | /* |
161 | * Sanity check the EDID block (base or extension). Return 0 if the block |
||
162 | * doesn't check out, or 1 if it's valid. |
||
1123 | serge | 163 | */ |
3031 | serge | 164 | bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid) |
1123 | serge | 165 | { |
1963 | serge | 166 | int i; |
1123 | serge | 167 | u8 csum = 0; |
1963 | serge | 168 | struct edid *edid = (struct edid *)raw_edid; |
1123 | serge | 169 | |
3031 | serge | 170 | if (edid_fixup > 8 || edid_fixup < 0) |
171 | edid_fixup = 6; |
||
172 | |||
173 | if (block == 0) { |
||
2160 | serge | 174 | int score = drm_edid_header_is_valid(raw_edid); |
1321 | serge | 175 | if (score == 8) ; |
3031 | serge | 176 | else if (score >= edid_fixup) { |
1321 | serge | 177 | DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); |
178 | memcpy(raw_edid, edid_header, sizeof(edid_header)); |
||
1963 | serge | 179 | } else { |
1123 | serge | 180 | goto bad; |
1963 | serge | 181 | } |
182 | } |
||
1123 | serge | 183 | |
184 | for (i = 0; i < EDID_LENGTH; i++) |
||
185 | csum += raw_edid[i]; |
||
186 | if (csum) { |
||
3120 | serge | 187 | if (print_bad_edid) { |
1123 | serge | 188 | DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); |
3120 | serge | 189 | } |
1963 | serge | 190 | |
191 | /* allow CEA to slide through, switches mangle this */ |
||
192 | if (raw_edid[0] != 0x02) |
||
1123 | serge | 193 | goto bad; |
194 | } |
||
195 | |||
1963 | serge | 196 | /* per-block-type checks */ |
197 | switch (raw_edid[0]) { |
||
198 | case 0: /* base */ |
||
1321 | serge | 199 | if (edid->version != 1) { |
200 | DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version); |
||
201 | goto bad; |
||
202 | } |
||
203 | |||
204 | if (edid->revision > 4) |
||
205 | DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n"); |
||
1963 | serge | 206 | break; |
1321 | serge | 207 | |
1963 | serge | 208 | default: |
209 | break; |
||
210 | } |
||
211 | |||
1123 | serge | 212 | return 1; |
213 | |||
214 | bad: |
||
3120 | serge | 215 | if (raw_edid && print_bad_edid) { |
2004 | serge | 216 | printk(KERN_ERR "Raw EDID:\n"); |
2160 | serge | 217 | // print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); |
1123 | serge | 218 | } |
219 | return 0; |
||
220 | } |
||
3031 | serge | 221 | EXPORT_SYMBOL(drm_edid_block_valid); |
1963 | serge | 222 | |
223 | /** |
||
224 | * drm_edid_is_valid - sanity check EDID data |
||
225 | * @edid: EDID data |
||
226 | * |
||
227 | * Sanity-check an entire EDID record (including extensions) |
||
228 | */ |
||
229 | bool drm_edid_is_valid(struct edid *edid) |
||
230 | { |
||
231 | int i; |
||
232 | u8 *raw = (u8 *)edid; |
||
233 | |||
234 | if (!edid) |
||
235 | return false; |
||
236 | |||
237 | for (i = 0; i <= edid->extensions; i++) |
||
3031 | serge | 238 | if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i, true)) |
1963 | serge | 239 | return false; |
240 | |||
241 | return true; |
||
242 | } |
||
1430 | serge | 243 | EXPORT_SYMBOL(drm_edid_is_valid); |
1123 | serge | 244 | |
1963 | serge | 245 | #define DDC_SEGMENT_ADDR 0x30 |
1123 | serge | 246 | /** |
1963 | serge | 247 | * Get EDID information via I2C. |
248 | * |
||
249 | * \param adapter : i2c device adaptor |
||
250 | * \param buf : EDID data buffer to be filled |
||
251 | * \param len : EDID data buffer length |
||
252 | * \return 0 on success or -1 on failure. |
||
253 | * |
||
254 | * Try to fetch EDID information by calling i2c driver function. |
||
255 | */ |
||
256 | static int |
||
257 | drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, |
||
258 | int block, int len) |
||
259 | { |
||
260 | unsigned char start = block * EDID_LENGTH; |
||
3031 | serge | 261 | unsigned char segment = block >> 1; |
262 | unsigned char xfers = segment ? 3 : 2; |
||
1963 | serge | 263 | int ret, retries = 5; |
264 | |||
265 | /* The core i2c driver will automatically retry the transfer if the |
||
266 | * adapter reports EAGAIN. However, we find that bit-banging transfers |
||
267 | * are susceptible to errors under a heavily loaded machine and |
||
268 | * generate spurious NAKs and timeouts. Retrying the transfer |
||
269 | * of the individual block a few times seems to overcome this. |
||
270 | */ |
||
271 | do { |
||
272 | struct i2c_msg msgs[] = { |
||
273 | { |
||
3031 | serge | 274 | .addr = DDC_SEGMENT_ADDR, |
275 | .flags = 0, |
||
276 | .len = 1, |
||
277 | .buf = &segment, |
||
278 | }, { |
||
1963 | serge | 279 | .addr = DDC_ADDR, |
280 | .flags = 0, |
||
281 | .len = 1, |
||
282 | .buf = &start, |
||
283 | }, { |
||
284 | .addr = DDC_ADDR, |
||
285 | .flags = I2C_M_RD, |
||
286 | .len = len, |
||
287 | .buf = buf, |
||
288 | } |
||
289 | }; |
||
290 | |||
3031 | serge | 291 | /* |
292 | * Avoid sending the segment addr to not upset non-compliant ddc |
||
293 | * monitors. |
||
294 | */ |
||
295 | ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers); |
||
296 | |||
297 | if (ret == -ENXIO) { |
||
298 | DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n", |
||
299 | adapter->name); |
||
300 | break; |
||
301 | } |
||
302 | } while (ret != xfers && --retries); |
||
303 | |||
304 | return ret == xfers ? 0 : -1; |
||
1963 | serge | 305 | } |
306 | |||
2004 | serge | 307 | static bool drm_edid_is_zero(u8 *in_edid, int length) |
308 | { |
||
309 | int i; |
||
310 | u32 *raw_edid = (u32 *)in_edid; |
||
311 | |||
312 | for (i = 0; i < length / 4; i++) |
||
313 | if (*(raw_edid + i) != 0) |
||
314 | return false; |
||
315 | return true; |
||
316 | } |
||
317 | |||
1963 | serge | 318 | static u8 * |
319 | drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) |
||
320 | { |
||
3031 | serge | 321 | size_t alloc_size; |
1963 | serge | 322 | int i, j = 0, valid_extensions = 0; |
323 | u8 *block, *new; |
||
3031 | serge | 324 | bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS); |
1963 | serge | 325 | |
326 | if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) |
||
327 | return NULL; |
||
328 | |||
329 | /* base block fetch */ |
||
330 | for (i = 0; i < 4; i++) { |
||
331 | if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) |
||
332 | goto out; |
||
3031 | serge | 333 | if (drm_edid_block_valid(block, 0, print_bad_edid)) |
1963 | serge | 334 | break; |
2004 | serge | 335 | if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { |
336 | connector->null_edid_counter++; |
||
337 | goto carp; |
||
338 | } |
||
1963 | serge | 339 | } |
340 | if (i == 4) |
||
341 | goto carp; |
||
342 | |||
343 | /* if there's no extensions, we're done */ |
||
344 | if (block[0x7e] == 0) |
||
345 | return block; |
||
346 | |||
347 | alloc_size = (block[0x7e] + 1) * EDID_LENGTH ; |
||
348 | |||
349 | new = kmalloc(alloc_size, GFP_KERNEL); |
||
350 | |||
351 | if (!new) |
||
352 | goto out; |
||
353 | |||
354 | memcpy(new, block, EDID_LENGTH); |
||
355 | kfree(block); |
||
356 | |||
357 | block = new; |
||
358 | |||
359 | for (j = 1; j <= block[0x7e]; j++) { |
||
360 | for (i = 0; i < 4; i++) { |
||
361 | if (drm_do_probe_ddc_edid(adapter, |
||
362 | block + (valid_extensions + 1) * EDID_LENGTH, |
||
363 | j, EDID_LENGTH)) |
||
364 | goto out; |
||
3031 | serge | 365 | if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid)) { |
1963 | serge | 366 | valid_extensions++; |
367 | break; |
||
368 | } |
||
369 | } |
||
370 | if (i == 4) |
||
371 | dev_warn(connector->dev->dev, |
||
372 | "%s: Ignoring invalid EDID block %d.\n", |
||
373 | drm_get_connector_name(connector), j); |
||
374 | } |
||
375 | |||
376 | if (valid_extensions != block[0x7e]) { |
||
377 | block[EDID_LENGTH-1] += block[0x7e] - valid_extensions; |
||
378 | block[0x7e] = valid_extensions; |
||
379 | new = kmalloc((valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); |
||
380 | if (!new) |
||
381 | goto out; |
||
382 | memcpy(new, block, alloc_size); |
||
383 | kfree(block); |
||
384 | block = new; |
||
385 | } |
||
386 | |||
387 | return block; |
||
388 | |||
389 | carp: |
||
3031 | serge | 390 | if (print_bad_edid) { |
1963 | serge | 391 | dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", |
392 | drm_get_connector_name(connector), j); |
||
3031 | serge | 393 | } |
394 | connector->bad_edid_counter++; |
||
1963 | serge | 395 | |
396 | out: |
||
397 | kfree(block); |
||
398 | return NULL; |
||
399 | } |
||
400 | |||
401 | /** |
||
402 | * Probe DDC presence. |
||
403 | * |
||
404 | * \param adapter : i2c device adaptor |
||
405 | * \return 1 on success |
||
406 | */ |
||
3031 | serge | 407 | bool |
1963 | serge | 408 | drm_probe_ddc(struct i2c_adapter *adapter) |
409 | { |
||
410 | unsigned char out; |
||
411 | |||
412 | return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0); |
||
413 | } |
||
3031 | serge | 414 | EXPORT_SYMBOL(drm_probe_ddc); |
1963 | serge | 415 | |
416 | /** |
||
417 | * drm_get_edid - get EDID data, if available |
||
418 | * @connector: connector we're probing |
||
419 | * @adapter: i2c adapter to use for DDC |
||
420 | * |
||
421 | * Poke the given i2c channel to grab EDID data if possible. If found, |
||
422 | * attach it to the connector. |
||
423 | * |
||
424 | * Return edid data or NULL if we couldn't find any. |
||
425 | */ |
||
426 | struct edid *drm_get_edid(struct drm_connector *connector, |
||
427 | struct i2c_adapter *adapter) |
||
428 | { |
||
429 | struct edid *edid = NULL; |
||
430 | |||
431 | if (drm_probe_ddc(adapter)) |
||
432 | edid = (struct edid *)drm_do_get_edid(connector, adapter); |
||
433 | |||
434 | return edid; |
||
435 | } |
||
436 | EXPORT_SYMBOL(drm_get_edid); |
||
437 | |||
438 | /*** EDID parsing ***/ |
||
439 | |||
440 | /** |
||
1123 | serge | 441 | * edid_vendor - match a string against EDID's obfuscated vendor field |
442 | * @edid: EDID to match |
||
443 | * @vendor: vendor string |
||
444 | * |
||
445 | * Returns true if @vendor is in @edid, false otherwise |
||
446 | */ |
||
447 | static bool edid_vendor(struct edid *edid, char *vendor) |
||
448 | { |
||
449 | char edid_vendor[3]; |
||
450 | |||
451 | edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@'; |
||
452 | edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) | |
||
453 | ((edid->mfg_id[1] & 0xe0) >> 5)) + '@'; |
||
454 | edid_vendor[2] = (edid->mfg_id[1] & 0x1f) + '@'; |
||
455 | |||
456 | return !strncmp(edid_vendor, vendor, 3); |
||
457 | } |
||
458 | |||
459 | /** |
||
460 | * edid_get_quirks - return quirk flags for a given EDID |
||
461 | * @edid: EDID to process |
||
462 | * |
||
463 | * This tells subsequent routines what fixes they need to apply. |
||
464 | */ |
||
465 | static u32 edid_get_quirks(struct edid *edid) |
||
466 | { |
||
467 | struct edid_quirk *quirk; |
||
468 | int i; |
||
469 | |||
470 | for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) { |
||
471 | quirk = &edid_quirk_list[i]; |
||
472 | |||
473 | if (edid_vendor(edid, quirk->vendor) && |
||
474 | (EDID_PRODUCT_ID(edid) == quirk->product_id)) |
||
475 | return quirk->quirks; |
||
476 | } |
||
477 | |||
478 | return 0; |
||
479 | } |
||
480 | |||
481 | #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) |
||
482 | #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) |
||
483 | |||
484 | /** |
||
485 | * edid_fixup_preferred - set preferred modes based on quirk list |
||
486 | * @connector: has mode list to fix up |
||
487 | * @quirks: quirks list |
||
488 | * |
||
489 | * Walk the mode list for @connector, clearing the preferred status |
||
490 | * on existing modes and setting it anew for the right mode ala @quirks. |
||
491 | */ |
||
492 | static void edid_fixup_preferred(struct drm_connector *connector, |
||
493 | u32 quirks) |
||
494 | { |
||
495 | struct drm_display_mode *t, *cur_mode, *preferred_mode; |
||
496 | int target_refresh = 0; |
||
497 | |||
498 | if (list_empty(&connector->probed_modes)) |
||
499 | return; |
||
500 | |||
501 | if (quirks & EDID_QUIRK_PREFER_LARGE_60) |
||
502 | target_refresh = 60; |
||
503 | if (quirks & EDID_QUIRK_PREFER_LARGE_75) |
||
504 | target_refresh = 75; |
||
505 | |||
506 | preferred_mode = list_first_entry(&connector->probed_modes, |
||
507 | struct drm_display_mode, head); |
||
508 | |||
509 | list_for_each_entry_safe(cur_mode, t, &connector->probed_modes, head) { |
||
510 | cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED; |
||
511 | |||
512 | if (cur_mode == preferred_mode) |
||
513 | continue; |
||
514 | |||
515 | /* Largest mode is preferred */ |
||
516 | if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode)) |
||
517 | preferred_mode = cur_mode; |
||
518 | |||
519 | /* At a given size, try to get closest to target refresh */ |
||
520 | if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) && |
||
521 | MODE_REFRESH_DIFF(cur_mode, target_refresh) < |
||
522 | MODE_REFRESH_DIFF(preferred_mode, target_refresh)) { |
||
523 | preferred_mode = cur_mode; |
||
524 | } |
||
525 | } |
||
526 | |||
527 | preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; |
||
528 | } |
||
529 | |||
3031 | serge | 530 | static bool |
531 | mode_is_rb(const struct drm_display_mode *mode) |
||
532 | { |
||
533 | return (mode->htotal - mode->hdisplay == 160) && |
||
534 | (mode->hsync_end - mode->hdisplay == 80) && |
||
535 | (mode->hsync_end - mode->hsync_start == 32) && |
||
536 | (mode->vsync_start - mode->vdisplay == 3); |
||
537 | } |
||
538 | |||
539 | /* |
||
540 | * drm_mode_find_dmt - Create a copy of a mode if present in DMT |
||
541 | * @dev: Device to duplicate against |
||
542 | * @hsize: Mode width |
||
543 | * @vsize: Mode height |
||
544 | * @fresh: Mode refresh rate |
||
545 | * @rb: Mode reduced-blanking-ness |
||
546 | * |
||
547 | * Walk the DMT mode list looking for a match for the given parameters. |
||
548 | * Return a newly allocated copy of the mode, or NULL if not found. |
||
549 | */ |
||
1963 | serge | 550 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, |
3031 | serge | 551 | int hsize, int vsize, int fresh, |
552 | bool rb) |
||
1179 | serge | 553 | { |
1321 | serge | 554 | int i; |
1179 | serge | 555 | |
1321 | serge | 556 | for (i = 0; i < drm_num_dmt_modes; i++) { |
1963 | serge | 557 | const struct drm_display_mode *ptr = &drm_dmt_modes[i]; |
3031 | serge | 558 | if (hsize != ptr->hdisplay) |
559 | continue; |
||
560 | if (vsize != ptr->vdisplay) |
||
561 | continue; |
||
562 | if (fresh != drm_mode_vrefresh(ptr)) |
||
563 | continue; |
||
564 | if (rb != mode_is_rb(ptr)) |
||
565 | continue; |
||
566 | |||
567 | return drm_mode_duplicate(dev, ptr); |
||
1179 | serge | 568 | } |
3031 | serge | 569 | |
570 | return NULL; |
||
1179 | serge | 571 | } |
1963 | serge | 572 | EXPORT_SYMBOL(drm_mode_find_dmt); |
1221 | serge | 573 | |
1963 | serge | 574 | typedef void detailed_cb(struct detailed_timing *timing, void *closure); |
575 | |||
576 | static void |
||
577 | cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) |
||
578 | { |
||
579 | int i, n = 0; |
||
3031 | serge | 580 | u8 d = ext[0x02]; |
1963 | serge | 581 | u8 *det_base = ext + d; |
582 | |||
3031 | serge | 583 | n = (127 - d) / 18; |
1963 | serge | 584 | for (i = 0; i < n; i++) |
585 | cb((struct detailed_timing *)(det_base + 18 * i), closure); |
||
586 | } |
||
587 | |||
588 | static void |
||
589 | vtb_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) |
||
590 | { |
||
591 | unsigned int i, n = min((int)ext[0x02], 6); |
||
592 | u8 *det_base = ext + 5; |
||
593 | |||
594 | if (ext[0x01] != 1) |
||
595 | return; /* unknown version */ |
||
596 | |||
597 | for (i = 0; i < n; i++) |
||
598 | cb((struct detailed_timing *)(det_base + 18 * i), closure); |
||
599 | } |
||
600 | |||
601 | static void |
||
602 | drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) |
||
603 | { |
||
604 | int i; |
||
605 | struct edid *edid = (struct edid *)raw_edid; |
||
606 | |||
607 | if (edid == NULL) |
||
608 | return; |
||
609 | |||
610 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) |
||
611 | cb(&(edid->detailed_timings[i]), closure); |
||
612 | |||
613 | for (i = 1; i <= raw_edid[0x7e]; i++) { |
||
614 | u8 *ext = raw_edid + (i * EDID_LENGTH); |
||
615 | switch (*ext) { |
||
616 | case CEA_EXT: |
||
617 | cea_for_each_detailed_block(ext, cb, closure); |
||
618 | break; |
||
619 | case VTB_EXT: |
||
620 | vtb_for_each_detailed_block(ext, cb, closure); |
||
621 | break; |
||
622 | default: |
||
623 | break; |
||
624 | } |
||
625 | } |
||
626 | } |
||
627 | |||
628 | static void |
||
629 | is_rb(struct detailed_timing *t, void *data) |
||
630 | { |
||
631 | u8 *r = (u8 *)t; |
||
632 | if (r[3] == EDID_DETAIL_MONITOR_RANGE) |
||
633 | if (r[15] & 0x10) |
||
634 | *(bool *)data = true; |
||
635 | } |
||
636 | |||
637 | /* EDID 1.4 defines this explicitly. For EDID 1.3, we guess, badly. */ |
||
638 | static bool |
||
639 | drm_monitor_supports_rb(struct edid *edid) |
||
640 | { |
||
641 | if (edid->revision >= 4) { |
||
3031 | serge | 642 | bool ret = false; |
1963 | serge | 643 | drm_for_each_detailed_block((u8 *)edid, is_rb, &ret); |
644 | return ret; |
||
645 | } |
||
646 | |||
647 | return ((edid->input & DRM_EDID_INPUT_DIGITAL) != 0); |
||
648 | } |
||
649 | |||
650 | static void |
||
651 | find_gtf2(struct detailed_timing *t, void *data) |
||
652 | { |
||
653 | u8 *r = (u8 *)t; |
||
654 | if (r[3] == EDID_DETAIL_MONITOR_RANGE && r[10] == 0x02) |
||
655 | *(u8 **)data = r; |
||
656 | } |
||
657 | |||
658 | /* Secondary GTF curve kicks in above some break frequency */ |
||
659 | static int |
||
660 | drm_gtf2_hbreak(struct edid *edid) |
||
661 | { |
||
662 | u8 *r = NULL; |
||
663 | drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); |
||
664 | return r ? (r[12] * 2) : 0; |
||
665 | } |
||
666 | |||
667 | static int |
||
668 | drm_gtf2_2c(struct edid *edid) |
||
669 | { |
||
670 | u8 *r = NULL; |
||
671 | drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); |
||
672 | return r ? r[13] : 0; |
||
673 | } |
||
674 | |||
675 | static int |
||
676 | drm_gtf2_m(struct edid *edid) |
||
677 | { |
||
678 | u8 *r = NULL; |
||
679 | drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); |
||
680 | return r ? (r[15] << 8) + r[14] : 0; |
||
681 | } |
||
682 | |||
683 | static int |
||
684 | drm_gtf2_k(struct edid *edid) |
||
685 | { |
||
686 | u8 *r = NULL; |
||
687 | drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); |
||
688 | return r ? r[16] : 0; |
||
689 | } |
||
690 | |||
691 | static int |
||
692 | drm_gtf2_2j(struct edid *edid) |
||
693 | { |
||
694 | u8 *r = NULL; |
||
695 | drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); |
||
696 | return r ? r[17] : 0; |
||
697 | } |
||
698 | |||
699 | /** |
||
700 | * standard_timing_level - get std. timing level(CVT/GTF/DMT) |
||
701 | * @edid: EDID block to scan |
||
702 | */ |
||
703 | static int standard_timing_level(struct edid *edid) |
||
704 | { |
||
705 | if (edid->revision >= 2) { |
||
706 | if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)) |
||
707 | return LEVEL_CVT; |
||
708 | if (drm_gtf2_hbreak(edid)) |
||
709 | return LEVEL_GTF2; |
||
710 | return LEVEL_GTF; |
||
711 | } |
||
712 | return LEVEL_DMT; |
||
713 | } |
||
714 | |||
1221 | serge | 715 | /* |
716 | * 0 is reserved. The spec says 0x01 fill for unused timings. Some old |
||
717 | * monitors fill with ascii space (0x20) instead. |
||
718 | */ |
||
719 | static int |
||
720 | bad_std_timing(u8 a, u8 b) |
||
721 | { |
||
722 | return (a == 0x00 && b == 0x00) || |
||
723 | (a == 0x01 && b == 0x01) || |
||
724 | (a == 0x20 && b == 0x20); |
||
725 | } |
||
726 | |||
1123 | serge | 727 | /** |
728 | * drm_mode_std - convert standard mode info (width, height, refresh) into mode |
||
729 | * @t: standard timing params |
||
1221 | serge | 730 | * @timing_level: standard timing level |
1123 | serge | 731 | * |
732 | * Take the standard timing params (in this case width, aspect, and refresh) |
||
1221 | serge | 733 | * and convert them into a real mode using CVT/GTF/DMT. |
1123 | serge | 734 | */ |
1963 | serge | 735 | static struct drm_display_mode * |
736 | drm_mode_std(struct drm_connector *connector, struct edid *edid, |
||
737 | struct std_timing *t, int revision) |
||
1123 | serge | 738 | { |
1963 | serge | 739 | struct drm_device *dev = connector->dev; |
740 | struct drm_display_mode *m, *mode = NULL; |
||
1179 | serge | 741 | int hsize, vsize; |
742 | int vrefresh_rate; |
||
1123 | serge | 743 | unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK) |
744 | >> EDID_TIMING_ASPECT_SHIFT; |
||
1179 | serge | 745 | unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK) |
746 | >> EDID_TIMING_VFREQ_SHIFT; |
||
1963 | serge | 747 | int timing_level = standard_timing_level(edid); |
1123 | serge | 748 | |
1221 | serge | 749 | if (bad_std_timing(t->hsize, t->vfreq_aspect)) |
750 | return NULL; |
||
751 | |||
1179 | serge | 752 | /* According to the EDID spec, the hdisplay = hsize * 8 + 248 */ |
753 | hsize = t->hsize * 8 + 248; |
||
754 | /* vrefresh_rate = vfreq + 60 */ |
||
755 | vrefresh_rate = vfreq + 60; |
||
756 | /* the vdisplay is calculated based on the aspect ratio */ |
||
1221 | serge | 757 | if (aspect_ratio == 0) { |
758 | if (revision < 3) |
||
759 | vsize = hsize; |
||
760 | else |
||
1123 | serge | 761 | vsize = (hsize * 10) / 16; |
1221 | serge | 762 | } else if (aspect_ratio == 1) |
1123 | serge | 763 | vsize = (hsize * 3) / 4; |
764 | else if (aspect_ratio == 2) |
||
765 | vsize = (hsize * 4) / 5; |
||
766 | else |
||
767 | vsize = (hsize * 9) / 16; |
||
1963 | serge | 768 | |
769 | /* HDTV hack, part 1 */ |
||
770 | if (vrefresh_rate == 60 && |
||
771 | ((hsize == 1360 && vsize == 765) || |
||
772 | (hsize == 1368 && vsize == 769))) { |
||
773 | hsize = 1366; |
||
774 | vsize = 768; |
||
775 | } |
||
776 | |||
777 | /* |
||
778 | * If this connector already has a mode for this size and refresh |
||
779 | * rate (because it came from detailed or CVT info), use that |
||
780 | * instead. This way we don't have to guess at interlace or |
||
781 | * reduced blanking. |
||
782 | */ |
||
783 | list_for_each_entry(m, &connector->probed_modes, head) |
||
784 | if (m->hdisplay == hsize && m->vdisplay == vsize && |
||
785 | drm_mode_vrefresh(m) == vrefresh_rate) |
||
786 | return NULL; |
||
787 | |||
788 | /* HDTV hack, part 2 */ |
||
789 | if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) { |
||
790 | mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0, |
||
1221 | serge | 791 | false); |
1179 | serge | 792 | mode->hdisplay = 1366; |
1963 | serge | 793 | mode->hsync_start = mode->hsync_start - 1; |
794 | mode->hsync_end = mode->hsync_end - 1; |
||
1179 | serge | 795 | return mode; |
796 | } |
||
1963 | serge | 797 | |
1179 | serge | 798 | /* check whether it can be found in default mode table */ |
3031 | serge | 799 | if (drm_monitor_supports_rb(edid)) { |
800 | mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate, |
||
801 | true); |
||
802 | if (mode) |
||
803 | return mode; |
||
804 | } |
||
805 | mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate, false); |
||
1179 | serge | 806 | if (mode) |
807 | return mode; |
||
1123 | serge | 808 | |
3031 | serge | 809 | /* okay, generate it */ |
1179 | serge | 810 | switch (timing_level) { |
811 | case LEVEL_DMT: |
||
812 | break; |
||
813 | case LEVEL_GTF: |
||
814 | mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); |
||
815 | break; |
||
1963 | serge | 816 | case LEVEL_GTF2: |
817 | /* |
||
818 | * This is potentially wrong if there's ever a monitor with |
||
819 | * more than one ranges section, each claiming a different |
||
820 | * secondary GTF curve. Please don't do that. |
||
821 | */ |
||
822 | mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); |
||
3031 | serge | 823 | if (!mode) |
824 | return NULL; |
||
1963 | serge | 825 | if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) { |
3031 | serge | 826 | drm_mode_destroy(dev, mode); |
1963 | serge | 827 | mode = drm_gtf_mode_complex(dev, hsize, vsize, |
828 | vrefresh_rate, 0, 0, |
||
829 | drm_gtf2_m(edid), |
||
830 | drm_gtf2_2c(edid), |
||
831 | drm_gtf2_k(edid), |
||
832 | drm_gtf2_2j(edid)); |
||
833 | } |
||
834 | break; |
||
1179 | serge | 835 | case LEVEL_CVT: |
1221 | serge | 836 | mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0, |
837 | false); |
||
1179 | serge | 838 | break; |
839 | } |
||
1123 | serge | 840 | return mode; |
841 | } |
||
842 | |||
1428 | serge | 843 | /* |
844 | * EDID is delightfully ambiguous about how interlaced modes are to be |
||
845 | * encoded. Our internal representation is of frame height, but some |
||
846 | * HDTV detailed timings are encoded as field height. |
||
847 | * |
||
848 | * The format list here is from CEA, in frame size. Technically we |
||
849 | * should be checking refresh rate too. Whatever. |
||
850 | */ |
||
851 | static void |
||
852 | drm_mode_do_interlace_quirk(struct drm_display_mode *mode, |
||
853 | struct detailed_pixel_timing *pt) |
||
854 | { |
||
855 | int i; |
||
856 | static const struct { |
||
857 | int w, h; |
||
858 | } cea_interlaced[] = { |
||
859 | { 1920, 1080 }, |
||
860 | { 720, 480 }, |
||
861 | { 1440, 480 }, |
||
862 | { 2880, 480 }, |
||
863 | { 720, 576 }, |
||
864 | { 1440, 576 }, |
||
865 | { 2880, 576 }, |
||
866 | }; |
||
867 | |||
868 | if (!(pt->misc & DRM_EDID_PT_INTERLACED)) |
||
869 | return; |
||
870 | |||
1963 | serge | 871 | for (i = 0; i < ARRAY_SIZE(cea_interlaced); i++) { |
1428 | serge | 872 | if ((mode->hdisplay == cea_interlaced[i].w) && |
873 | (mode->vdisplay == cea_interlaced[i].h / 2)) { |
||
874 | mode->vdisplay *= 2; |
||
875 | mode->vsync_start *= 2; |
||
876 | mode->vsync_end *= 2; |
||
877 | mode->vtotal *= 2; |
||
878 | mode->vtotal |= 1; |
||
879 | } |
||
880 | } |
||
881 | |||
882 | mode->flags |= DRM_MODE_FLAG_INTERLACE; |
||
883 | } |
||
884 | |||
1123 | serge | 885 | /** |
886 | * drm_mode_detailed - create a new mode from an EDID detailed timing section |
||
887 | * @dev: DRM device (needed to create new mode) |
||
888 | * @edid: EDID block |
||
889 | * @timing: EDID detailed timing info |
||
890 | * @quirks: quirks to apply |
||
891 | * |
||
892 | * An EDID detailed timing block contains enough info for us to create and |
||
893 | * return a new struct drm_display_mode. |
||
894 | */ |
||
895 | static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, |
||
896 | struct edid *edid, |
||
897 | struct detailed_timing *timing, |
||
898 | u32 quirks) |
||
899 | { |
||
900 | struct drm_display_mode *mode; |
||
901 | struct detailed_pixel_timing *pt = &timing->data.pixel_data; |
||
902 | unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo; |
||
903 | unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; |
||
904 | unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; |
||
905 | unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; |
||
906 | unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo; |
||
907 | unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo; |
||
908 | unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; |
||
909 | unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf); |
||
910 | |||
911 | /* ignore tiny modes */ |
||
912 | if (hactive < 64 || vactive < 64) |
||
913 | return NULL; |
||
914 | |||
915 | if (pt->misc & DRM_EDID_PT_STEREO) { |
||
916 | printk(KERN_WARNING "stereo mode not supported\n"); |
||
917 | return NULL; |
||
918 | } |
||
919 | if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { |
||
1404 | serge | 920 | printk(KERN_WARNING "composite sync not supported\n"); |
1123 | serge | 921 | } |
922 | |||
1246 | serge | 923 | /* it is incorrect if hsync/vsync width is zero */ |
924 | if (!hsync_pulse_width || !vsync_pulse_width) { |
||
925 | DRM_DEBUG_KMS("Incorrect Detailed timing. " |
||
926 | "Wrong Hsync/Vsync pulse width\n"); |
||
927 | return NULL; |
||
928 | } |
||
3031 | serge | 929 | |
930 | if (quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) { |
||
931 | mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false); |
||
932 | if (!mode) |
||
933 | return NULL; |
||
934 | |||
935 | goto set_size; |
||
936 | } |
||
937 | |||
1123 | serge | 938 | mode = drm_mode_create(dev); |
939 | if (!mode) |
||
940 | return NULL; |
||
941 | |||
942 | if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) |
||
943 | timing->pixel_clock = cpu_to_le16(1088); |
||
944 | |||
945 | mode->clock = le16_to_cpu(timing->pixel_clock) * 10; |
||
946 | |||
947 | mode->hdisplay = hactive; |
||
948 | mode->hsync_start = mode->hdisplay + hsync_offset; |
||
949 | mode->hsync_end = mode->hsync_start + hsync_pulse_width; |
||
950 | mode->htotal = mode->hdisplay + hblank; |
||
951 | |||
952 | mode->vdisplay = vactive; |
||
953 | mode->vsync_start = mode->vdisplay + vsync_offset; |
||
954 | mode->vsync_end = mode->vsync_start + vsync_pulse_width; |
||
955 | mode->vtotal = mode->vdisplay + vblank; |
||
956 | |||
1313 | serge | 957 | /* Some EDIDs have bogus h/vtotal values */ |
958 | if (mode->hsync_end > mode->htotal) |
||
959 | mode->htotal = mode->hsync_end + 1; |
||
960 | if (mode->vsync_end > mode->vtotal) |
||
961 | mode->vtotal = mode->vsync_end + 1; |
||
962 | |||
1963 | serge | 963 | drm_mode_do_interlace_quirk(mode, pt); |
964 | |||
1123 | serge | 965 | if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { |
966 | pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; |
||
967 | } |
||
968 | |||
969 | mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? |
||
970 | DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; |
||
971 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? |
||
972 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; |
||
973 | |||
3031 | serge | 974 | set_size: |
1123 | serge | 975 | mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; |
976 | mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; |
||
977 | |||
978 | if (quirks & EDID_QUIRK_DETAILED_IN_CM) { |
||
979 | mode->width_mm *= 10; |
||
980 | mode->height_mm *= 10; |
||
981 | } |
||
982 | |||
983 | if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { |
||
984 | mode->width_mm = edid->width_cm * 10; |
||
985 | mode->height_mm = edid->height_cm * 10; |
||
986 | } |
||
987 | |||
3031 | serge | 988 | mode->type = DRM_MODE_TYPE_DRIVER; |
989 | drm_mode_set_name(mode); |
||
990 | |||
1123 | serge | 991 | return mode; |
992 | } |
||
993 | |||
1963 | serge | 994 | static bool |
995 | mode_in_hsync_range(const struct drm_display_mode *mode, |
||
996 | struct edid *edid, u8 *t) |
||
997 | { |
||
998 | int hsync, hmin, hmax; |
||
999 | |||
1000 | hmin = t[7]; |
||
1001 | if (edid->revision >= 4) |
||
1002 | hmin += ((t[4] & 0x04) ? 255 : 0); |
||
1003 | hmax = t[8]; |
||
1004 | if (edid->revision >= 4) |
||
1005 | hmax += ((t[4] & 0x08) ? 255 : 0); |
||
1006 | hsync = drm_mode_hsync(mode); |
||
1007 | |||
1008 | return (hsync <= hmax && hsync >= hmin); |
||
1009 | } |
||
1010 | |||
1011 | static bool |
||
1012 | mode_in_vsync_range(const struct drm_display_mode *mode, |
||
1013 | struct edid *edid, u8 *t) |
||
1014 | { |
||
1015 | int vsync, vmin, vmax; |
||
1016 | |||
1017 | vmin = t[5]; |
||
1018 | if (edid->revision >= 4) |
||
1019 | vmin += ((t[4] & 0x01) ? 255 : 0); |
||
1020 | vmax = t[6]; |
||
1021 | if (edid->revision >= 4) |
||
1022 | vmax += ((t[4] & 0x02) ? 255 : 0); |
||
1023 | vsync = drm_mode_vrefresh(mode); |
||
1024 | |||
1025 | return (vsync <= vmax && vsync >= vmin); |
||
1026 | } |
||
1027 | |||
1028 | static u32 |
||
1029 | range_pixel_clock(struct edid *edid, u8 *t) |
||
1030 | { |
||
1031 | /* unspecified */ |
||
1032 | if (t[9] == 0 || t[9] == 255) |
||
1033 | return 0; |
||
1034 | |||
1035 | /* 1.4 with CVT support gives us real precision, yay */ |
||
1036 | if (edid->revision >= 4 && t[10] == 0x04) |
||
1037 | return (t[9] * 10000) - ((t[12] >> 2) * 250); |
||
1038 | |||
1039 | /* 1.3 is pathetic, so fuzz up a bit */ |
||
1040 | return t[9] * 10000 + 5001; |
||
1041 | } |
||
1042 | |||
1043 | static bool |
||
1044 | mode_in_range(const struct drm_display_mode *mode, struct edid *edid, |
||
1045 | struct detailed_timing *timing) |
||
1046 | { |
||
1047 | u32 max_clock; |
||
1048 | u8 *t = (u8 *)timing; |
||
1049 | |||
1050 | if (!mode_in_hsync_range(mode, edid, t)) |
||
1051 | return false; |
||
1052 | |||
1053 | if (!mode_in_vsync_range(mode, edid, t)) |
||
1054 | return false; |
||
1055 | |||
1056 | if ((max_clock = range_pixel_clock(edid, t))) |
||
1057 | if (mode->clock > max_clock) |
||
1058 | return false; |
||
1059 | |||
1060 | /* 1.4 max horizontal check */ |
||
1061 | if (edid->revision >= 4 && t[10] == 0x04) |
||
1062 | if (t[13] && mode->hdisplay > 8 * (t[13] + (256 * (t[12]&0x3)))) |
||
1063 | return false; |
||
1064 | |||
1065 | if (mode_is_rb(mode) && !drm_monitor_supports_rb(edid)) |
||
1066 | return false; |
||
1067 | |||
1068 | return true; |
||
1069 | } |
||
1070 | |||
3031 | serge | 1071 | static bool valid_inferred_mode(const struct drm_connector *connector, |
1072 | const struct drm_display_mode *mode) |
||
1073 | { |
||
1074 | struct drm_display_mode *m; |
||
1075 | bool ok = false; |
||
1076 | |||
1077 | list_for_each_entry(m, &connector->probed_modes, head) { |
||
1078 | if (mode->hdisplay == m->hdisplay && |
||
1079 | mode->vdisplay == m->vdisplay && |
||
1080 | drm_mode_vrefresh(mode) == drm_mode_vrefresh(m)) |
||
1081 | return false; /* duplicated */ |
||
1082 | if (mode->hdisplay <= m->hdisplay && |
||
1083 | mode->vdisplay <= m->vdisplay) |
||
1084 | ok = true; |
||
1085 | } |
||
1086 | return ok; |
||
1087 | } |
||
1088 | |||
1963 | serge | 1089 | static int |
3031 | serge | 1090 | drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid, |
1963 | serge | 1091 | struct detailed_timing *timing) |
1092 | { |
||
1093 | int i, modes = 0; |
||
1094 | struct drm_display_mode *newmode; |
||
1095 | struct drm_device *dev = connector->dev; |
||
1123 | serge | 1096 | |
1963 | serge | 1097 | for (i = 0; i < drm_num_dmt_modes; i++) { |
3031 | serge | 1098 | if (mode_in_range(drm_dmt_modes + i, edid, timing) && |
1099 | valid_inferred_mode(connector, drm_dmt_modes + i)) { |
||
1963 | serge | 1100 | newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]); |
1101 | if (newmode) { |
||
1102 | drm_mode_probed_add(connector, newmode); |
||
1103 | modes++; |
||
1104 | } |
||
1105 | } |
||
1106 | } |
||
1123 | serge | 1107 | |
1963 | serge | 1108 | return modes; |
1109 | } |
||
1110 | |||
3031 | serge | 1111 | /* fix up 1366x768 mode from 1368x768; |
1112 | * GFT/CVT can't express 1366 width which isn't dividable by 8 |
||
1113 | */ |
||
1114 | static void fixup_mode_1366x768(struct drm_display_mode *mode) |
||
1115 | { |
||
1116 | if (mode->hdisplay == 1368 && mode->vdisplay == 768) { |
||
1117 | mode->hdisplay = 1366; |
||
1118 | mode->hsync_start--; |
||
1119 | mode->hsync_end--; |
||
1120 | drm_mode_set_name(mode); |
||
1121 | } |
||
1122 | } |
||
1123 | |||
1124 | static int |
||
1125 | drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, |
||
1126 | struct detailed_timing *timing) |
||
1127 | { |
||
1128 | int i, modes = 0; |
||
1129 | struct drm_display_mode *newmode; |
||
1130 | struct drm_device *dev = connector->dev; |
||
1131 | |||
1132 | for (i = 0; i < num_extra_modes; i++) { |
||
1133 | const struct minimode *m = &extra_modes[i]; |
||
1134 | newmode = drm_gtf_mode(dev, m->w, m->h, m->r, 0, 0); |
||
1135 | if (!newmode) |
||
1136 | return modes; |
||
1137 | |||
1138 | fixup_mode_1366x768(newmode); |
||
1139 | if (!mode_in_range(newmode, edid, timing) || |
||
1140 | !valid_inferred_mode(connector, newmode)) { |
||
1141 | drm_mode_destroy(dev, newmode); |
||
1142 | continue; |
||
1143 | } |
||
1144 | |||
1145 | drm_mode_probed_add(connector, newmode); |
||
1146 | modes++; |
||
1147 | } |
||
1148 | |||
1149 | return modes; |
||
1150 | } |
||
1151 | |||
1152 | static int |
||
1153 | drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid, |
||
1154 | struct detailed_timing *timing) |
||
1155 | { |
||
1156 | int i, modes = 0; |
||
1157 | struct drm_display_mode *newmode; |
||
1158 | struct drm_device *dev = connector->dev; |
||
1159 | bool rb = drm_monitor_supports_rb(edid); |
||
1160 | |||
1161 | for (i = 0; i < num_extra_modes; i++) { |
||
1162 | const struct minimode *m = &extra_modes[i]; |
||
1163 | newmode = drm_cvt_mode(dev, m->w, m->h, m->r, rb, 0, 0); |
||
1164 | if (!newmode) |
||
1165 | return modes; |
||
1166 | |||
1167 | fixup_mode_1366x768(newmode); |
||
1168 | if (!mode_in_range(newmode, edid, timing) || |
||
1169 | !valid_inferred_mode(connector, newmode)) { |
||
1170 | drm_mode_destroy(dev, newmode); |
||
1171 | continue; |
||
1172 | } |
||
1173 | |||
1174 | drm_mode_probed_add(connector, newmode); |
||
1175 | modes++; |
||
1176 | } |
||
1177 | |||
1178 | return modes; |
||
1179 | } |
||
1180 | |||
1963 | serge | 1181 | static void |
1182 | do_inferred_modes(struct detailed_timing *timing, void *c) |
||
1183 | { |
||
1184 | struct detailed_mode_closure *closure = c; |
||
1185 | struct detailed_non_pixel *data = &timing->data.other_data; |
||
3031 | serge | 1186 | struct detailed_data_monitor_range *range = &data->data.range; |
1963 | serge | 1187 | |
3031 | serge | 1188 | if (data->type != EDID_DETAIL_MONITOR_RANGE) |
1189 | return; |
||
1190 | |||
1191 | closure->modes += drm_dmt_modes_for_range(closure->connector, |
||
1192 | closure->edid, |
||
1193 | timing); |
||
1194 | |||
1195 | if (!version_greater(closure->edid, 1, 1)) |
||
1196 | return; /* GTF not defined yet */ |
||
1197 | |||
1198 | switch (range->flags) { |
||
1199 | case 0x02: /* secondary gtf, XXX could do more */ |
||
1200 | case 0x00: /* default gtf */ |
||
1963 | serge | 1201 | closure->modes += drm_gtf_modes_for_range(closure->connector, |
1202 | closure->edid, |
||
1203 | timing); |
||
3031 | serge | 1204 | break; |
1205 | case 0x04: /* cvt, only in 1.4+ */ |
||
1206 | if (!version_greater(closure->edid, 1, 3)) |
||
1207 | break; |
||
1208 | |||
1209 | closure->modes += drm_cvt_modes_for_range(closure->connector, |
||
1210 | closure->edid, |
||
1211 | timing); |
||
1212 | break; |
||
1213 | case 0x01: /* just the ranges, no formula */ |
||
1214 | default: |
||
1215 | break; |
||
1216 | } |
||
1963 | serge | 1217 | } |
1218 | |||
1219 | static int |
||
1220 | add_inferred_modes(struct drm_connector *connector, struct edid *edid) |
||
1221 | { |
||
1222 | struct detailed_mode_closure closure = { |
||
1223 | connector, edid, 0, 0, 0 |
||
1224 | }; |
||
1225 | |||
1226 | if (version_greater(edid, 1, 0)) |
||
1227 | drm_for_each_detailed_block((u8 *)edid, do_inferred_modes, |
||
1228 | &closure); |
||
1229 | |||
1230 | return closure.modes; |
||
1231 | } |
||
1232 | |||
1233 | static int |
||
1234 | drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) |
||
1235 | { |
||
1236 | int i, j, m, modes = 0; |
||
1237 | struct drm_display_mode *mode; |
||
1238 | u8 *est = ((u8 *)timing) + 5; |
||
1239 | |||
1240 | for (i = 0; i < 6; i++) { |
||
1241 | for (j = 7; j > 0; j--) { |
||
1242 | m = (i * 8) + (7 - j); |
||
1243 | if (m >= ARRAY_SIZE(est3_modes)) |
||
1244 | break; |
||
1245 | if (est[i] & (1 << j)) { |
||
1246 | mode = drm_mode_find_dmt(connector->dev, |
||
1247 | est3_modes[m].w, |
||
1248 | est3_modes[m].h, |
||
3031 | serge | 1249 | est3_modes[m].r, |
1250 | est3_modes[m].rb); |
||
1963 | serge | 1251 | if (mode) { |
1252 | drm_mode_probed_add(connector, mode); |
||
1253 | modes++; |
||
1254 | } |
||
1255 | } |
||
1256 | } |
||
1257 | } |
||
1258 | |||
1259 | return modes; |
||
1260 | } |
||
1261 | |||
1262 | static void |
||
1263 | do_established_modes(struct detailed_timing *timing, void *c) |
||
1264 | { |
||
1265 | struct detailed_mode_closure *closure = c; |
||
1266 | struct detailed_non_pixel *data = &timing->data.other_data; |
||
1267 | |||
1268 | if (data->type == EDID_DETAIL_EST_TIMINGS) |
||
1269 | closure->modes += drm_est3_modes(closure->connector, timing); |
||
1270 | } |
||
1271 | |||
1123 | serge | 1272 | /** |
1273 | * add_established_modes - get est. modes from EDID and add them |
||
1274 | * @edid: EDID block to scan |
||
1275 | * |
||
1276 | * Each EDID block contains a bitmap of the supported "established modes" list |
||
1277 | * (defined above). Tease them out and add them to the global modes list. |
||
1278 | */ |
||
1963 | serge | 1279 | static int |
1280 | add_established_modes(struct drm_connector *connector, struct edid *edid) |
||
1123 | serge | 1281 | { |
1282 | struct drm_device *dev = connector->dev; |
||
1283 | unsigned long est_bits = edid->established_timings.t1 | |
||
1284 | (edid->established_timings.t2 << 8) | |
||
1285 | ((edid->established_timings.mfg_rsvd & 0x80) << 9); |
||
1286 | int i, modes = 0; |
||
1963 | serge | 1287 | struct detailed_mode_closure closure = { |
1288 | connector, edid, 0, 0, 0 |
||
1289 | }; |
||
1123 | serge | 1290 | |
1963 | serge | 1291 | for (i = 0; i <= EDID_EST_TIMINGS; i++) { |
1123 | serge | 1292 | if (est_bits & (1< |
1293 | struct drm_display_mode *newmode; |
||
1294 | newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); |
||
1295 | if (newmode) { |
||
1963 | serge | 1296 | drm_mode_probed_add(connector, newmode); |
1123 | serge | 1297 | modes++; |
1298 | } |
||
1299 | } |
||
1963 | serge | 1300 | } |
1123 | serge | 1301 | |
1963 | serge | 1302 | if (version_greater(edid, 1, 0)) |
1303 | drm_for_each_detailed_block((u8 *)edid, |
||
1304 | do_established_modes, &closure); |
||
1305 | |||
1306 | return modes + closure.modes; |
||
1123 | serge | 1307 | } |
1963 | serge | 1308 | |
1309 | static void |
||
1310 | do_standard_modes(struct detailed_timing *timing, void *c) |
||
1179 | serge | 1311 | { |
1963 | serge | 1312 | struct detailed_mode_closure *closure = c; |
1313 | struct detailed_non_pixel *data = &timing->data.other_data; |
||
1314 | struct drm_connector *connector = closure->connector; |
||
1315 | struct edid *edid = closure->edid; |
||
1316 | |||
1317 | if (data->type == EDID_DETAIL_STD_MODES) { |
||
1318 | int i; |
||
1319 | for (i = 0; i < 6; i++) { |
||
1320 | struct std_timing *std; |
||
1321 | struct drm_display_mode *newmode; |
||
1322 | |||
1323 | std = &data->data.timings[i]; |
||
1324 | newmode = drm_mode_std(connector, edid, std, |
||
1325 | edid->revision); |
||
1326 | if (newmode) { |
||
1327 | drm_mode_probed_add(connector, newmode); |
||
1328 | closure->modes++; |
||
1329 | } |
||
1330 | } |
||
1331 | } |
||
1179 | serge | 1332 | } |
1123 | serge | 1333 | |
1334 | /** |
||
1335 | * add_standard_modes - get std. modes from EDID and add them |
||
1336 | * @edid: EDID block to scan |
||
1337 | * |
||
1963 | serge | 1338 | * Standard modes can be calculated using the appropriate standard (DMT, |
1339 | * GTF or CVT. Grab them from @edid and add them to the list. |
||
1123 | serge | 1340 | */ |
1963 | serge | 1341 | static int |
1342 | add_standard_modes(struct drm_connector *connector, struct edid *edid) |
||
1123 | serge | 1343 | { |
1344 | int i, modes = 0; |
||
1963 | serge | 1345 | struct detailed_mode_closure closure = { |
1346 | connector, edid, 0, 0, 0 |
||
1347 | }; |
||
1123 | serge | 1348 | |
1349 | for (i = 0; i < EDID_STD_TIMINGS; i++) { |
||
1350 | struct drm_display_mode *newmode; |
||
1351 | |||
1963 | serge | 1352 | newmode = drm_mode_std(connector, edid, |
1353 | &edid->standard_timings[i], |
||
1354 | edid->revision); |
||
1123 | serge | 1355 | if (newmode) { |
1356 | drm_mode_probed_add(connector, newmode); |
||
1357 | modes++; |
||
1358 | } |
||
1359 | } |
||
1360 | |||
1963 | serge | 1361 | if (version_greater(edid, 1, 0)) |
1362 | drm_for_each_detailed_block((u8 *)edid, do_standard_modes, |
||
1363 | &closure); |
||
1123 | serge | 1364 | |
1963 | serge | 1365 | /* XXX should also look for standard codes in VTB blocks */ |
1321 | serge | 1366 | |
1963 | serge | 1367 | return modes + closure.modes; |
1321 | serge | 1368 | } |
1369 | |||
1370 | static int drm_cvt_modes(struct drm_connector *connector, |
||
1371 | struct detailed_timing *timing) |
||
1372 | { |
||
1123 | serge | 1373 | int i, j, modes = 0; |
1321 | serge | 1374 | struct drm_display_mode *newmode; |
1375 | struct drm_device *dev = connector->dev; |
||
1376 | struct cvt_timing *cvt; |
||
1377 | const int rates[] = { 60, 85, 75, 60, 50 }; |
||
1404 | serge | 1378 | const u8 empty[3] = { 0, 0, 0 }; |
1123 | serge | 1379 | |
1321 | serge | 1380 | for (i = 0; i < 4; i++) { |
1404 | serge | 1381 | int uninitialized_var(width), height; |
1321 | serge | 1382 | cvt = &(timing->data.other_data.data.cvt[i]); |
1179 | serge | 1383 | |
1404 | serge | 1384 | if (!memcmp(cvt->code, empty, 3)) |
1963 | serge | 1385 | continue; |
1404 | serge | 1386 | |
1387 | height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; |
||
1388 | switch (cvt->code[1] & 0x0c) { |
||
1321 | serge | 1389 | case 0x00: |
1390 | width = height * 4 / 3; |
||
1391 | break; |
||
1404 | serge | 1392 | case 0x04: |
1321 | serge | 1393 | width = height * 16 / 9; |
1394 | break; |
||
1404 | serge | 1395 | case 0x08: |
1321 | serge | 1396 | width = height * 16 / 10; |
1397 | break; |
||
1404 | serge | 1398 | case 0x0c: |
1321 | serge | 1399 | width = height * 15 / 9; |
1400 | break; |
||
1401 | } |
||
1402 | |||
1403 | for (j = 1; j < 5; j++) { |
||
1404 | if (cvt->code[2] & (1 << j)) { |
||
1405 | newmode = drm_cvt_mode(dev, width, height, |
||
1406 | rates[j], j == 0, |
||
1407 | false, false); |
||
1408 | if (newmode) { |
||
1409 | drm_mode_probed_add(connector, newmode); |
||
1410 | modes++; |
||
1411 | } |
||
1412 | } |
||
1413 | } |
||
1963 | serge | 1414 | } |
1321 | serge | 1415 | |
1416 | return modes; |
||
1417 | } |
||
1418 | |||
1963 | serge | 1419 | static void |
1420 | do_cvt_mode(struct detailed_timing *timing, void *c) |
||
1321 | serge | 1421 | { |
1963 | serge | 1422 | struct detailed_mode_closure *closure = c; |
1423 | struct detailed_non_pixel *data = &timing->data.other_data; |
||
1123 | serge | 1424 | |
1963 | serge | 1425 | if (data->type == EDID_DETAIL_CVT_3BYTE) |
1426 | closure->modes += drm_cvt_modes(closure->connector, timing); |
||
1427 | } |
||
1321 | serge | 1428 | |
1963 | serge | 1429 | static int |
1430 | add_cvt_modes(struct drm_connector *connector, struct edid *edid) |
||
1431 | { |
||
1432 | struct detailed_mode_closure closure = { |
||
1433 | connector, edid, 0, 0, 0 |
||
1434 | }; |
||
1321 | serge | 1435 | |
1963 | serge | 1436 | if (version_greater(edid, 1, 2)) |
1437 | drm_for_each_detailed_block((u8 *)edid, do_cvt_mode, &closure); |
||
1321 | serge | 1438 | |
1963 | serge | 1439 | /* XXX should also look for CVT codes in VTB blocks */ |
1123 | serge | 1440 | |
1963 | serge | 1441 | return closure.modes; |
1321 | serge | 1442 | } |
1443 | |||
1963 | serge | 1444 | static void |
1445 | do_detailed_mode(struct detailed_timing *timing, void *c) |
||
1321 | serge | 1446 | { |
1963 | serge | 1447 | struct detailed_mode_closure *closure = c; |
1448 | struct drm_display_mode *newmode; |
||
1321 | serge | 1449 | |
1963 | serge | 1450 | if (timing->pixel_clock) { |
1451 | newmode = drm_mode_detailed(closure->connector->dev, |
||
1452 | closure->edid, timing, |
||
1453 | closure->quirks); |
||
1454 | if (!newmode) |
||
1455 | return; |
||
1321 | serge | 1456 | |
1963 | serge | 1457 | if (closure->preferred) |
1458 | newmode->type |= DRM_MODE_TYPE_PREFERRED; |
||
1123 | serge | 1459 | |
1963 | serge | 1460 | drm_mode_probed_add(closure->connector, newmode); |
1461 | closure->modes++; |
||
1462 | closure->preferred = 0; |
||
1463 | } |
||
1179 | serge | 1464 | } |
1321 | serge | 1465 | |
1963 | serge | 1466 | /* |
1467 | * add_detailed_modes - Add modes from detailed timings |
||
1179 | serge | 1468 | * @connector: attached connector |
1963 | serge | 1469 | * @edid: EDID block to scan |
1179 | serge | 1470 | * @quirks: quirks to apply |
1471 | */ |
||
1963 | serge | 1472 | static int |
1473 | add_detailed_modes(struct drm_connector *connector, struct edid *edid, |
||
1474 | u32 quirks) |
||
1179 | serge | 1475 | { |
1963 | serge | 1476 | struct detailed_mode_closure closure = { |
1477 | connector, |
||
1478 | edid, |
||
1479 | 1, |
||
1480 | quirks, |
||
1481 | |||
1482 | }; |
||
1179 | serge | 1483 | |
1963 | serge | 1484 | if (closure.preferred && !version_greater(edid, 1, 3)) |
1485 | closure.preferred = |
||
1486 | (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); |
||
1179 | serge | 1487 | |
1963 | serge | 1488 | drm_for_each_detailed_block((u8 *)edid, do_detailed_mode, &closure); |
1179 | serge | 1489 | |
1963 | serge | 1490 | return closure.modes; |
1491 | } |
||
1179 | serge | 1492 | |
1963 | serge | 1493 | #define HDMI_IDENTIFIER 0x000C03 |
1494 | #define AUDIO_BLOCK 0x01 |
||
3031 | serge | 1495 | #define VIDEO_BLOCK 0x02 |
1963 | serge | 1496 | #define VENDOR_BLOCK 0x03 |
3031 | serge | 1497 | #define SPEAKER_BLOCK 0x04 |
1963 | serge | 1498 | #define EDID_BASIC_AUDIO (1 << 6) |
3031 | serge | 1499 | #define EDID_CEA_YCRCB444 (1 << 5) |
1500 | #define EDID_CEA_YCRCB422 (1 << 4) |
||
1179 | serge | 1501 | |
1123 | serge | 1502 | /** |
1963 | serge | 1503 | * Search EDID for CEA extension block. |
1123 | serge | 1504 | */ |
1963 | serge | 1505 | u8 *drm_find_cea_extension(struct edid *edid) |
1123 | serge | 1506 | { |
1963 | serge | 1507 | u8 *edid_ext = NULL; |
1321 | serge | 1508 | int i; |
1123 | serge | 1509 | |
1963 | serge | 1510 | /* No EDID or EDID extensions */ |
1511 | if (edid == NULL || edid->extensions == 0) |
||
1512 | return NULL; |
||
1321 | serge | 1513 | |
1963 | serge | 1514 | /* Find CEA extension */ |
1515 | for (i = 0; i < edid->extensions; i++) { |
||
1516 | edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1); |
||
1517 | if (edid_ext[0] == CEA_EXT) |
||
1518 | break; |
||
1123 | serge | 1519 | } |
1520 | |||
1963 | serge | 1521 | if (i == edid->extensions) |
1522 | return NULL; |
||
1123 | serge | 1523 | |
1963 | serge | 1524 | return edid_ext; |
1123 | serge | 1525 | } |
1963 | serge | 1526 | EXPORT_SYMBOL(drm_find_cea_extension); |
1123 | serge | 1527 | |
3192 | Serge | 1528 | /* |
1529 | * Looks for a CEA mode matching given drm_display_mode. |
||
1530 | * Returns its CEA Video ID code, or 0 if not found. |
||
1531 | */ |
||
1532 | u8 drm_match_cea_mode(struct drm_display_mode *to_match) |
||
1533 | { |
||
1534 | struct drm_display_mode *cea_mode; |
||
1535 | u8 mode; |
||
1536 | |||
1537 | for (mode = 0; mode < drm_num_cea_modes; mode++) { |
||
1538 | cea_mode = (struct drm_display_mode *)&edid_cea_modes[mode]; |
||
1539 | |||
1540 | if (drm_mode_equal(to_match, cea_mode)) |
||
1541 | return mode + 1; |
||
1542 | } |
||
1543 | return 0; |
||
1544 | } |
||
1545 | EXPORT_SYMBOL(drm_match_cea_mode); |
||
1546 | |||
1547 | |||
3031 | serge | 1548 | static int |
1549 | do_cea_modes (struct drm_connector *connector, u8 *db, u8 len) |
||
1550 | { |
||
1551 | struct drm_device *dev = connector->dev; |
||
1552 | u8 * mode, cea_mode; |
||
1553 | int modes = 0; |
||
1554 | |||
1555 | for (mode = db; mode < db + len; mode++) { |
||
1556 | cea_mode = (*mode & 127) - 1; /* CEA modes are numbered 1..127 */ |
||
1557 | if (cea_mode < drm_num_cea_modes) { |
||
1558 | struct drm_display_mode *newmode; |
||
1559 | newmode = drm_mode_duplicate(dev, |
||
1560 | &edid_cea_modes[cea_mode]); |
||
1561 | if (newmode) { |
||
1562 | drm_mode_probed_add(connector, newmode); |
||
1563 | modes++; |
||
1564 | } |
||
1565 | } |
||
1566 | } |
||
1567 | |||
1568 | return modes; |
||
1569 | } |
||
1570 | |||
1571 | static int |
||
1572 | cea_db_payload_len(const u8 *db) |
||
1573 | { |
||
1574 | return db[0] & 0x1f; |
||
1575 | } |
||
1576 | |||
1577 | static int |
||
1578 | cea_db_tag(const u8 *db) |
||
1579 | { |
||
1580 | return db[0] >> 5; |
||
1581 | } |
||
1582 | |||
1583 | static int |
||
1584 | cea_revision(const u8 *cea) |
||
1585 | { |
||
1586 | return cea[1]; |
||
1587 | } |
||
1588 | |||
1589 | static int |
||
1590 | cea_db_offsets(const u8 *cea, int *start, int *end) |
||
1591 | { |
||
1592 | /* Data block offset in CEA extension block */ |
||
1593 | *start = 4; |
||
1594 | *end = cea[2]; |
||
1595 | if (*end == 0) |
||
1596 | *end = 127; |
||
1597 | if (*end < 4 || *end > 127) |
||
1598 | return -ERANGE; |
||
1599 | return 0; |
||
1600 | } |
||
1601 | |||
1602 | #define for_each_cea_db(cea, i, start, end) \ |
||
1603 | for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1) |
||
1604 | |||
1605 | static int |
||
1606 | add_cea_modes(struct drm_connector *connector, struct edid *edid) |
||
1607 | { |
||
1608 | u8 * cea = drm_find_cea_extension(edid); |
||
1609 | u8 * db, dbl; |
||
1610 | int modes = 0; |
||
1611 | |||
1612 | if (cea && cea_revision(cea) >= 3) { |
||
1613 | int i, start, end; |
||
1614 | |||
1615 | if (cea_db_offsets(cea, &start, &end)) |
||
1616 | return 0; |
||
1617 | |||
1618 | for_each_cea_db(cea, i, start, end) { |
||
1619 | db = &cea[i]; |
||
1620 | dbl = cea_db_payload_len(db); |
||
1621 | |||
1622 | if (cea_db_tag(db) == VIDEO_BLOCK) |
||
1623 | modes += do_cea_modes (connector, db+1, dbl); |
||
1624 | } |
||
1625 | } |
||
1626 | |||
1627 | return modes; |
||
1628 | } |
||
1629 | |||
1630 | static void |
||
1631 | parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db) |
||
1632 | { |
||
1633 | u8 len = cea_db_payload_len(db); |
||
1634 | |||
1635 | if (len >= 6) { |
||
1636 | connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */ |
||
1637 | connector->dvi_dual = db[6] & 1; |
||
1638 | } |
||
1639 | if (len >= 7) |
||
1640 | connector->max_tmds_clock = db[7] * 5; |
||
1641 | if (len >= 8) { |
||
1642 | connector->latency_present[0] = db[8] >> 7; |
||
1643 | connector->latency_present[1] = (db[8] >> 6) & 1; |
||
1644 | } |
||
1645 | if (len >= 9) |
||
1646 | connector->video_latency[0] = db[9]; |
||
1647 | if (len >= 10) |
||
1648 | connector->audio_latency[0] = db[10]; |
||
1649 | if (len >= 11) |
||
1650 | connector->video_latency[1] = db[11]; |
||
1651 | if (len >= 12) |
||
1652 | connector->audio_latency[1] = db[12]; |
||
1653 | |||
3192 | Serge | 1654 | DRM_DEBUG_KMS("HDMI: DVI dual %d, " |
3031 | serge | 1655 | "max TMDS clock %d, " |
1656 | "latency present %d %d, " |
||
1657 | "video latency %d %d, " |
||
1658 | "audio latency %d %d\n", |
||
1659 | connector->dvi_dual, |
||
1660 | connector->max_tmds_clock, |
||
1661 | (int) connector->latency_present[0], |
||
1662 | (int) connector->latency_present[1], |
||
1663 | connector->video_latency[0], |
||
1664 | connector->video_latency[1], |
||
1665 | connector->audio_latency[0], |
||
1666 | connector->audio_latency[1]); |
||
1667 | } |
||
1668 | |||
1669 | static void |
||
1670 | monitor_name(struct detailed_timing *t, void *data) |
||
1671 | { |
||
1672 | if (t->data.other_data.type == EDID_DETAIL_MONITOR_NAME) |
||
1673 | *(u8 **)data = t->data.other_data.data.str.str; |
||
1674 | } |
||
1675 | |||
1676 | static bool cea_db_is_hdmi_vsdb(const u8 *db) |
||
1677 | { |
||
1678 | int hdmi_id; |
||
1679 | |||
1680 | if (cea_db_tag(db) != VENDOR_BLOCK) |
||
1681 | return false; |
||
1682 | |||
1683 | if (cea_db_payload_len(db) < 5) |
||
1684 | return false; |
||
1685 | |||
1686 | hdmi_id = db[1] | (db[2] << 8) | (db[3] << 16); |
||
1687 | |||
1688 | return hdmi_id == HDMI_IDENTIFIER; |
||
1689 | } |
||
1690 | |||
1123 | serge | 1691 | /** |
3031 | serge | 1692 | * drm_edid_to_eld - build ELD from EDID |
1693 | * @connector: connector corresponding to the HDMI/DP sink |
||
1694 | * @edid: EDID to parse |
||
1695 | * |
||
1696 | * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. |
||
1697 | * Some ELD fields are left to the graphics driver caller: |
||
1698 | * - Conn_Type |
||
1699 | * - HDCP |
||
1700 | * - Port_ID |
||
1701 | */ |
||
1702 | void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) |
||
1703 | { |
||
1704 | uint8_t *eld = connector->eld; |
||
1705 | u8 *cea; |
||
1706 | u8 *name; |
||
1707 | u8 *db; |
||
1708 | int sad_count = 0; |
||
1709 | int mnl; |
||
1710 | int dbl; |
||
1711 | |||
1712 | memset(eld, 0, sizeof(connector->eld)); |
||
1713 | |||
1714 | cea = drm_find_cea_extension(edid); |
||
1715 | if (!cea) { |
||
1716 | DRM_DEBUG_KMS("ELD: no CEA Extension found\n"); |
||
1717 | return; |
||
1718 | } |
||
1719 | |||
1720 | name = NULL; |
||
1721 | drm_for_each_detailed_block((u8 *)edid, monitor_name, &name); |
||
1722 | for (mnl = 0; name && mnl < 13; mnl++) { |
||
1723 | if (name[mnl] == 0x0a) |
||
1724 | break; |
||
1725 | eld[20 + mnl] = name[mnl]; |
||
1726 | } |
||
1727 | eld[4] = (cea[1] << 5) | mnl; |
||
1728 | DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20); |
||
1729 | |||
1730 | eld[0] = 2 << 3; /* ELD version: 2 */ |
||
1731 | |||
1732 | eld[16] = edid->mfg_id[0]; |
||
1733 | eld[17] = edid->mfg_id[1]; |
||
1734 | eld[18] = edid->prod_code[0]; |
||
1735 | eld[19] = edid->prod_code[1]; |
||
1736 | |||
1737 | if (cea_revision(cea) >= 3) { |
||
1738 | int i, start, end; |
||
1739 | |||
1740 | if (cea_db_offsets(cea, &start, &end)) { |
||
1741 | start = 0; |
||
1742 | end = 0; |
||
1743 | } |
||
1744 | |||
1745 | for_each_cea_db(cea, i, start, end) { |
||
1746 | db = &cea[i]; |
||
1747 | dbl = cea_db_payload_len(db); |
||
1748 | |||
1749 | switch (cea_db_tag(db)) { |
||
1750 | case AUDIO_BLOCK: |
||
1751 | /* Audio Data Block, contains SADs */ |
||
1752 | sad_count = dbl / 3; |
||
1753 | if (dbl >= 1) |
||
1754 | memcpy(eld + 20 + mnl, &db[1], dbl); |
||
1755 | break; |
||
1756 | case SPEAKER_BLOCK: |
||
1757 | /* Speaker Allocation Data Block */ |
||
1758 | if (dbl >= 1) |
||
1759 | eld[7] = db[1]; |
||
1760 | break; |
||
1761 | case VENDOR_BLOCK: |
||
1762 | /* HDMI Vendor-Specific Data Block */ |
||
1763 | if (cea_db_is_hdmi_vsdb(db)) |
||
1764 | parse_hdmi_vsdb(connector, db); |
||
1765 | break; |
||
1766 | default: |
||
1767 | break; |
||
1768 | } |
||
1769 | } |
||
1770 | } |
||
1771 | eld[5] |= sad_count << 4; |
||
1772 | eld[2] = (20 + mnl + sad_count * 3 + 3) / 4; |
||
1773 | |||
1774 | DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count); |
||
1775 | } |
||
1776 | EXPORT_SYMBOL(drm_edid_to_eld); |
||
1777 | |||
1778 | /** |
||
1779 | * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond |
||
1780 | * @connector: connector associated with the HDMI/DP sink |
||
1781 | * @mode: the display mode |
||
1782 | */ |
||
1783 | int drm_av_sync_delay(struct drm_connector *connector, |
||
1784 | struct drm_display_mode *mode) |
||
1785 | { |
||
1786 | int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); |
||
1787 | int a, v; |
||
1788 | |||
1789 | if (!connector->latency_present[0]) |
||
1790 | return 0; |
||
1791 | if (!connector->latency_present[1]) |
||
1792 | i = 0; |
||
1793 | |||
1794 | a = connector->audio_latency[i]; |
||
1795 | v = connector->video_latency[i]; |
||
1796 | |||
1797 | /* |
||
1798 | * HDMI/DP sink doesn't support audio or video? |
||
1799 | */ |
||
1800 | if (a == 255 || v == 255) |
||
1801 | return 0; |
||
1802 | |||
1803 | /* |
||
1804 | * Convert raw EDID values to millisecond. |
||
1805 | * Treat unknown latency as 0ms. |
||
1806 | */ |
||
1807 | if (a) |
||
1808 | a = min(2 * (a - 1), 500); |
||
1809 | if (v) |
||
1810 | v = min(2 * (v - 1), 500); |
||
1811 | |||
1812 | return max(v - a, 0); |
||
1813 | } |
||
1814 | EXPORT_SYMBOL(drm_av_sync_delay); |
||
1815 | |||
1816 | /** |
||
1817 | * drm_select_eld - select one ELD from multiple HDMI/DP sinks |
||
1818 | * @encoder: the encoder just changed display mode |
||
1819 | * @mode: the adjusted display mode |
||
1820 | * |
||
1821 | * It's possible for one encoder to be associated with multiple HDMI/DP sinks. |
||
1822 | * The policy is now hard coded to simply use the first HDMI/DP sink's ELD. |
||
1823 | */ |
||
1824 | struct drm_connector *drm_select_eld(struct drm_encoder *encoder, |
||
1825 | struct drm_display_mode *mode) |
||
1826 | { |
||
1827 | struct drm_connector *connector; |
||
1828 | struct drm_device *dev = encoder->dev; |
||
1829 | |||
1830 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
||
1831 | if (connector->encoder == encoder && connector->eld[0]) |
||
1832 | return connector; |
||
1833 | |||
1834 | return NULL; |
||
1835 | } |
||
1836 | EXPORT_SYMBOL(drm_select_eld); |
||
1837 | |||
1838 | /** |
||
1123 | serge | 1839 | * drm_detect_hdmi_monitor - detect whether monitor is hdmi. |
1840 | * @edid: monitor EDID information |
||
1841 | * |
||
1842 | * Parse the CEA extension according to CEA-861-B. |
||
1843 | * Return true if HDMI, false if not or unknown. |
||
1844 | */ |
||
1845 | bool drm_detect_hdmi_monitor(struct edid *edid) |
||
1846 | { |
||
1963 | serge | 1847 | u8 *edid_ext; |
3031 | serge | 1848 | int i; |
1123 | serge | 1849 | int start_offset, end_offset; |
1850 | |||
1963 | serge | 1851 | edid_ext = drm_find_cea_extension(edid); |
1852 | if (!edid_ext) |
||
3031 | serge | 1853 | return false; |
1123 | serge | 1854 | |
3031 | serge | 1855 | if (cea_db_offsets(edid_ext, &start_offset, &end_offset)) |
1856 | return false; |
||
1123 | serge | 1857 | |
1858 | /* |
||
1859 | * Because HDMI identifier is in Vendor Specific Block, |
||
1860 | * search it from all data blocks of CEA extension. |
||
1861 | */ |
||
3031 | serge | 1862 | for_each_cea_db(edid_ext, i, start_offset, end_offset) { |
1863 | if (cea_db_is_hdmi_vsdb(&edid_ext[i])) |
||
1864 | return true; |
||
1123 | serge | 1865 | } |
1866 | |||
3031 | serge | 1867 | return false; |
1123 | serge | 1868 | } |
1869 | EXPORT_SYMBOL(drm_detect_hdmi_monitor); |
||
1870 | |||
1871 | /** |
||
1963 | serge | 1872 | * drm_detect_monitor_audio - check monitor audio capability |
1873 | * |
||
1874 | * Monitor should have CEA extension block. |
||
1875 | * If monitor has 'basic audio', but no CEA audio blocks, it's 'basic |
||
1876 | * audio' only. If there is any audio extension block and supported |
||
1877 | * audio format, assume at least 'basic audio' support, even if 'basic |
||
1878 | * audio' is not defined in EDID. |
||
1879 | * |
||
1880 | */ |
||
1881 | bool drm_detect_monitor_audio(struct edid *edid) |
||
1882 | { |
||
1883 | u8 *edid_ext; |
||
1884 | int i, j; |
||
1885 | bool has_audio = false; |
||
1886 | int start_offset, end_offset; |
||
1887 | |||
1888 | edid_ext = drm_find_cea_extension(edid); |
||
1889 | if (!edid_ext) |
||
1890 | goto end; |
||
1891 | |||
1892 | has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0); |
||
1893 | |||
1894 | if (has_audio) { |
||
1895 | DRM_DEBUG_KMS("Monitor has basic audio support\n"); |
||
1896 | goto end; |
||
1897 | } |
||
1898 | |||
3031 | serge | 1899 | if (cea_db_offsets(edid_ext, &start_offset, &end_offset)) |
1900 | goto end; |
||
1963 | serge | 1901 | |
3031 | serge | 1902 | for_each_cea_db(edid_ext, i, start_offset, end_offset) { |
1903 | if (cea_db_tag(&edid_ext[i]) == AUDIO_BLOCK) { |
||
1963 | serge | 1904 | has_audio = true; |
3031 | serge | 1905 | for (j = 1; j < cea_db_payload_len(&edid_ext[i]) + 1; j += 3) |
1963 | serge | 1906 | DRM_DEBUG_KMS("CEA audio format %d\n", |
1907 | (edid_ext[i + j] >> 3) & 0xf); |
||
1908 | goto end; |
||
1909 | } |
||
1910 | } |
||
1911 | end: |
||
1912 | return has_audio; |
||
1913 | } |
||
1914 | EXPORT_SYMBOL(drm_detect_monitor_audio); |
||
1915 | |||
1916 | /** |
||
1917 | * drm_add_display_info - pull display info out if present |
||
1918 | * @edid: EDID data |
||
1919 | * @info: display info (attached to connector) |
||
1920 | * |
||
1921 | * Grab any available display info and stuff it into the drm_display_info |
||
1922 | * structure that's part of the connector. Useful for tracking bpp and |
||
1923 | * color spaces. |
||
1924 | */ |
||
1925 | static void drm_add_display_info(struct edid *edid, |
||
1926 | struct drm_display_info *info) |
||
1927 | { |
||
2160 | serge | 1928 | u8 *edid_ext; |
1929 | |||
1963 | serge | 1930 | info->width_mm = edid->width_cm * 10; |
1931 | info->height_mm = edid->height_cm * 10; |
||
1932 | |||
1933 | /* driver figures it out in this case */ |
||
1934 | info->bpc = 0; |
||
1935 | info->color_formats = 0; |
||
1936 | |||
3031 | serge | 1937 | if (edid->revision < 3) |
1963 | serge | 1938 | return; |
1939 | |||
1940 | if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) |
||
1941 | return; |
||
1942 | |||
3031 | serge | 1943 | /* Get data from CEA blocks if present */ |
1944 | edid_ext = drm_find_cea_extension(edid); |
||
1945 | if (edid_ext) { |
||
1946 | info->cea_rev = edid_ext[1]; |
||
1947 | |||
1948 | /* The existence of a CEA block should imply RGB support */ |
||
1949 | info->color_formats = DRM_COLOR_FORMAT_RGB444; |
||
1950 | if (edid_ext[3] & EDID_CEA_YCRCB444) |
||
1951 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; |
||
1952 | if (edid_ext[3] & EDID_CEA_YCRCB422) |
||
1953 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; |
||
1954 | } |
||
1955 | |||
1956 | /* Only defined for 1.4 with digital displays */ |
||
1957 | if (edid->revision < 4) |
||
1958 | return; |
||
1959 | |||
1963 | serge | 1960 | switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) { |
1961 | case DRM_EDID_DIGITAL_DEPTH_6: |
||
1962 | info->bpc = 6; |
||
1963 | break; |
||
1964 | case DRM_EDID_DIGITAL_DEPTH_8: |
||
1965 | info->bpc = 8; |
||
1966 | break; |
||
1967 | case DRM_EDID_DIGITAL_DEPTH_10: |
||
1968 | info->bpc = 10; |
||
1969 | break; |
||
1970 | case DRM_EDID_DIGITAL_DEPTH_12: |
||
1971 | info->bpc = 12; |
||
1972 | break; |
||
1973 | case DRM_EDID_DIGITAL_DEPTH_14: |
||
1974 | info->bpc = 14; |
||
1975 | break; |
||
1976 | case DRM_EDID_DIGITAL_DEPTH_16: |
||
1977 | info->bpc = 16; |
||
1978 | break; |
||
1979 | case DRM_EDID_DIGITAL_DEPTH_UNDEF: |
||
1980 | default: |
||
1981 | info->bpc = 0; |
||
1982 | break; |
||
1983 | } |
||
1984 | |||
3031 | serge | 1985 | info->color_formats |= DRM_COLOR_FORMAT_RGB444; |
1986 | if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) |
||
1987 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; |
||
1988 | if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) |
||
1989 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; |
||
1963 | serge | 1990 | } |
1991 | |||
1992 | /** |
||
1123 | serge | 1993 | * drm_add_edid_modes - add modes from EDID data, if available |
1994 | * @connector: connector we're probing |
||
1995 | * @edid: edid data |
||
1996 | * |
||
1997 | * Add the specified modes to the connector's mode list. |
||
1998 | * |
||
1999 | * Return number of modes added or 0 if we couldn't find any. |
||
2000 | */ |
||
2001 | int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) |
||
2002 | { |
||
2003 | int num_modes = 0; |
||
2004 | u32 quirks; |
||
2005 | |||
2006 | if (edid == NULL) { |
||
2007 | return 0; |
||
2008 | } |
||
1430 | serge | 2009 | if (!drm_edid_is_valid(edid)) { |
1963 | serge | 2010 | dev_warn(connector->dev->dev, "%s: EDID invalid.\n", |
1246 | serge | 2011 | drm_get_connector_name(connector)); |
1123 | serge | 2012 | return 0; |
2013 | } |
||
2014 | |||
2015 | quirks = edid_get_quirks(edid); |
||
2016 | |||
1963 | serge | 2017 | /* |
2018 | * EDID spec says modes should be preferred in this order: |
||
2019 | * - preferred detailed mode |
||
2020 | * - other detailed modes from base block |
||
2021 | * - detailed modes from extension blocks |
||
2022 | * - CVT 3-byte code modes |
||
2023 | * - standard timing codes |
||
2024 | * - established timing codes |
||
2025 | * - modes inferred from GTF or CVT range information |
||
2026 | * |
||
2027 | * We get this pretty much right. |
||
2028 | * |
||
2029 | * XXX order for additional mode types in extension blocks? |
||
2030 | */ |
||
2031 | num_modes += add_detailed_modes(connector, edid, quirks); |
||
2032 | num_modes += add_cvt_modes(connector, edid); |
||
2033 | num_modes += add_standard_modes(connector, edid); |
||
1123 | serge | 2034 | num_modes += add_established_modes(connector, edid); |
1963 | serge | 2035 | num_modes += add_inferred_modes(connector, edid); |
3031 | serge | 2036 | num_modes += add_cea_modes(connector, edid); |
1123 | serge | 2037 | |
2038 | if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) |
||
2039 | edid_fixup_preferred(connector, quirks); |
||
2040 | |||
1963 | serge | 2041 | drm_add_display_info(edid, &connector->display_info); |
1123 | serge | 2042 | |
2043 | return num_modes; |
||
2044 | } |
||
2045 | EXPORT_SYMBOL(drm_add_edid_modes); |
||
1179 | serge | 2046 | |
2047 | /** |
||
2048 | * drm_add_modes_noedid - add modes for the connectors without EDID |
||
2049 | * @connector: connector we're probing |
||
2050 | * @hdisplay: the horizontal display limit |
||
2051 | * @vdisplay: the vertical display limit |
||
2052 | * |
||
2053 | * Add the specified modes to the connector's mode list. Only when the |
||
2054 | * hdisplay/vdisplay is not beyond the given limit, it will be added. |
||
2055 | * |
||
2056 | * Return number of modes added or 0 if we couldn't find any. |
||
2057 | */ |
||
2058 | int drm_add_modes_noedid(struct drm_connector *connector, |
||
2059 | int hdisplay, int vdisplay) |
||
2060 | { |
||
2061 | int i, count, num_modes = 0; |
||
1963 | serge | 2062 | struct drm_display_mode *mode; |
1179 | serge | 2063 | struct drm_device *dev = connector->dev; |
2064 | |||
2065 | count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); |
||
2066 | if (hdisplay < 0) |
||
2067 | hdisplay = 0; |
||
2068 | if (vdisplay < 0) |
||
2069 | vdisplay = 0; |
||
2070 | |||
2071 | for (i = 0; i < count; i++) { |
||
1963 | serge | 2072 | const struct drm_display_mode *ptr = &drm_dmt_modes[i]; |
1179 | serge | 2073 | if (hdisplay && vdisplay) { |
2074 | /* |
||
2075 | * Only when two are valid, they will be used to check |
||
2076 | * whether the mode should be added to the mode list of |
||
2077 | * the connector. |
||
2078 | */ |
||
2079 | if (ptr->hdisplay > hdisplay || |
||
2080 | ptr->vdisplay > vdisplay) |
||
2081 | continue; |
||
2082 | } |
||
1321 | serge | 2083 | if (drm_mode_vrefresh(ptr) > 61) |
2084 | continue; |
||
1179 | serge | 2085 | mode = drm_mode_duplicate(dev, ptr); |
2086 | if (mode) { |
||
2087 | drm_mode_probed_add(connector, mode); |
||
2088 | num_modes++; |
||
2089 | } |
||
2090 | } |
||
2091 | return num_modes; |
||
2092 | } |
||
2093 | EXPORT_SYMBOL(drm_add_modes_noedid); |
||
3192 | Serge | 2094 | |
2095 | /** |
||
2096 | * drm_mode_cea_vic - return the CEA-861 VIC of a given mode |
||
2097 | * @mode: mode |
||
2098 | * |
||
2099 | * RETURNS: |
||
2100 | * The VIC number, 0 in case it's not a CEA-861 mode. |
||
2101 | */ |
||
2102 | uint8_t drm_mode_cea_vic(const struct drm_display_mode *mode) |
||
2103 | { |
||
2104 | uint8_t i; |
||
2105 | |||
2106 | for (i = 0; i < drm_num_cea_modes; i++) |
||
2107 | if (drm_mode_equal(mode, &edid_cea_modes[i])) |
||
2108 | return i + 1; |
||
2109 | |||
2110 | return 0; |
||
2111 | } |
||
2112 | EXPORT_SYMBOL(drm_mode_cea_vic);>>>>>>>><>><>><>>><>><>>><>>>>>>>>><>><>><>><>>><>>>>=>><>><>><>>>>>=>=>=>=>><>><>>>><>><>><>><>><>><>><>>>><>=>>>>> |