Rev 2160 | Rev 3120 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2160 | Rev 3031 | ||
---|---|---|---|
Line 28... | Line 28... | ||
28 | * DEALINGS IN THE SOFTWARE. |
28 | * DEALINGS IN THE SOFTWARE. |
29 | */ |
29 | */ |
30 | #include |
30 | #include |
31 | #include |
31 | #include |
32 | #include |
32 | #include |
- | 33 | #include |
|
33 | #include "drmP.h" |
34 | #include |
34 | #include "drm_edid.h" |
35 | #include |
35 | #include "drm_edid_modes.h" |
36 | #include "drm_edid_modes.h" |
Line 36... | Line 37... | ||
36 | 37 | ||
37 | #define version_greater(edid, maj, min) \ |
38 | #define version_greater(edid, maj, min) \ |
38 | (((edid)->version > (maj)) || \ |
39 | (((edid)->version > (maj)) || \ |
Line 63... | Line 64... | ||
63 | #define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4) |
64 | #define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4) |
64 | /* Monitor forgot to set the first detailed is preferred bit. */ |
65 | /* Monitor forgot to set the first detailed is preferred bit. */ |
65 | #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) |
66 | #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) |
66 | /* use +hsync +vsync for detailed mode */ |
67 | /* use +hsync +vsync for detailed mode */ |
67 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) |
68 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) |
- | 69 | /* Force reduced-blanking timings for detailed modes */ |
|
- | 70 | #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) |
|
Line 68... | Line 71... | ||
68 | 71 | ||
69 | struct detailed_mode_closure { |
72 | struct detailed_mode_closure { |
70 | struct drm_connector *connector; |
73 | struct drm_connector *connector; |
71 | struct edid *edid; |
74 | struct edid *edid; |
Line 78... | Line 81... | ||
78 | #define LEVEL_GTF 1 |
81 | #define LEVEL_GTF 1 |
79 | #define LEVEL_GTF2 2 |
82 | #define LEVEL_GTF2 2 |
80 | #define LEVEL_CVT 3 |
83 | #define LEVEL_CVT 3 |
Line 81... | Line 84... | ||
81 | 84 | ||
82 | static struct edid_quirk { |
85 | static struct edid_quirk { |
83 | char *vendor; |
86 | char vendor[4]; |
84 | int product_id; |
87 | int product_id; |
85 | u32 quirks; |
88 | u32 quirks; |
- | 89 | } edid_quirk_list[] = { |
|
- | 90 | /* ASUS VW222S */ |
|
- | 91 | { "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING }, |
|
86 | } edid_quirk_list[] = { |
92 | |
87 | /* Acer AL1706 */ |
93 | /* Acer AL1706 */ |
88 | { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, |
94 | { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, |
89 | /* Acer F51 */ |
95 | /* Acer F51 */ |
90 | { "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 }, |
96 | { "API", 0x7602, EDID_QUIRK_PREFER_LARGE_60 }, |
Line 117... | Line 123... | ||
117 | /* Samsung SyncMaster 205BW. Note: irony */ |
123 | /* Samsung SyncMaster 205BW. Note: irony */ |
118 | { "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP }, |
124 | { "SAM", 541, EDID_QUIRK_DETAILED_SYNC_PP }, |
119 | /* Samsung SyncMaster 22[5-6]BW */ |
125 | /* Samsung SyncMaster 22[5-6]BW */ |
120 | { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, |
126 | { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, |
121 | { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, |
127 | { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, |
- | 128 | ||
- | 129 | /* ViewSonic VA2026w */ |
|
- | 130 | { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING }, |
|
122 | }; |
131 | }; |
Line 123... | Line 132... | ||
123 | 132 | ||
Line 124... | Line 133... | ||
124 | /*** DDC fetch and block validation ***/ |
133 | /*** DDC fetch and block validation ***/ |
Line 141... | Line 150... | ||
141 | 150 | ||
142 | return score; |
151 | return score; |
143 | } |
152 | } |
Line -... | Line 153... | ||
- | 153 | EXPORT_SYMBOL(drm_edid_header_is_valid); |
|
- | 154 | ||
- | 155 | static int edid_fixup __read_mostly = 6; |
|
- | 156 | //module_param_named(edid_fixup, edid_fixup, int, 0400); |
|
Line 144... | Line 157... | ||
144 | EXPORT_SYMBOL(drm_edid_header_is_valid); |
157 | //MODULE_PARM_DESC(edid_fixup, |
145 | 158 | // "Minimum number of valid EDID header bytes (0-8, default 6)"); |
|
146 | 159 | ||
147 | /* |
160 | /* |
148 | * Sanity check the EDID block (base or extension). Return 0 if the block |
- | |
149 | * doesn't check out, or 1 if it's valid. |
161 | * Sanity check the EDID block (base or extension). Return 0 if the block |
150 | */ |
162 | * doesn't check out, or 1 if it's valid. |
151 | static bool |
163 | */ |
152 | drm_edid_block_valid(u8 *raw_edid) |
164 | bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid) |
153 | { |
165 | { |
Line -... | Line 166... | ||
- | 166 | int i; |
|
- | 167 | u8 csum = 0; |
|
- | 168 | struct edid *edid = (struct edid *)raw_edid; |
|
154 | int i; |
169 | |
155 | u8 csum = 0; |
170 | if (edid_fixup > 8 || edid_fixup < 0) |
156 | struct edid *edid = (struct edid *)raw_edid; |
171 | edid_fixup = 6; |
157 | 172 | ||
158 | if (raw_edid[0] == 0x00) { |
173 | if (block == 0) { |
159 | int score = drm_edid_header_is_valid(raw_edid); |
174 | int score = drm_edid_header_is_valid(raw_edid); |
160 | if (score == 8) ; |
175 | if (score == 8) ; |
161 | else if (score >= 6) { |
176 | else if (score >= edid_fixup) { |
162 | DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); |
177 | DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); |
Line 199... | Line 214... | ||
199 | printk(KERN_ERR "Raw EDID:\n"); |
214 | printk(KERN_ERR "Raw EDID:\n"); |
200 | // print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); |
215 | // print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); |
201 | } |
216 | } |
202 | return 0; |
217 | return 0; |
203 | } |
218 | } |
- | 219 | EXPORT_SYMBOL(drm_edid_block_valid); |
|
Line 204... | Line 220... | ||
204 | 220 | ||
205 | /** |
221 | /** |
206 | * drm_edid_is_valid - sanity check EDID data |
222 | * drm_edid_is_valid - sanity check EDID data |
207 | * @edid: EDID data |
223 | * @edid: EDID data |
Line 215... | Line 231... | ||
215 | 231 | ||
216 | if (!edid) |
232 | if (!edid) |
Line 217... | Line 233... | ||
217 | return false; |
233 | return false; |
218 | 234 | ||
219 | for (i = 0; i <= edid->extensions; i++) |
235 | for (i = 0; i <= edid->extensions; i++) |
Line 220... | Line 236... | ||
220 | if (!drm_edid_block_valid(raw + i * EDID_LENGTH)) |
236 | if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i, true)) |
221 | return false; |
237 | return false; |
222 | 238 | ||
Line 223... | Line -... | ||
223 | return true; |
- | |
224 | } |
239 | return true; |
225 | EXPORT_SYMBOL(drm_edid_is_valid); |
240 | } |
226 | 241 | EXPORT_SYMBOL(drm_edid_is_valid); |
|
227 | #define DDC_ADDR 0x50 |
242 | |
228 | #define DDC_SEGMENT_ADDR 0x30 |
243 | #define DDC_SEGMENT_ADDR 0x30 |
Line 239... | Line 254... | ||
239 | static int |
254 | static int |
240 | drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, |
255 | drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, |
241 | int block, int len) |
256 | int block, int len) |
242 | { |
257 | { |
243 | unsigned char start = block * EDID_LENGTH; |
258 | unsigned char start = block * EDID_LENGTH; |
- | 259 | unsigned char segment = block >> 1; |
|
- | 260 | unsigned char xfers = segment ? 3 : 2; |
|
244 | int ret, retries = 5; |
261 | int ret, retries = 5; |
Line 245... | Line 262... | ||
245 | 262 | ||
246 | /* The core i2c driver will automatically retry the transfer if the |
263 | /* The core i2c driver will automatically retry the transfer if the |
247 | * adapter reports EAGAIN. However, we find that bit-banging transfers |
264 | * adapter reports EAGAIN. However, we find that bit-banging transfers |
Line 250... | Line 267... | ||
250 | * of the individual block a few times seems to overcome this. |
267 | * of the individual block a few times seems to overcome this. |
251 | */ |
268 | */ |
252 | do { |
269 | do { |
253 | struct i2c_msg msgs[] = { |
270 | struct i2c_msg msgs[] = { |
254 | { |
271 | { |
- | 272 | .addr = DDC_SEGMENT_ADDR, |
|
- | 273 | .flags = 0, |
|
- | 274 | .len = 1, |
|
- | 275 | .buf = &segment, |
|
- | 276 | }, { |
|
255 | .addr = DDC_ADDR, |
277 | .addr = DDC_ADDR, |
256 | .flags = 0, |
278 | .flags = 0, |
257 | .len = 1, |
279 | .len = 1, |
258 | .buf = &start, |
280 | .buf = &start, |
259 | }, { |
281 | }, { |
Line 261... | Line 283... | ||
261 | .flags = I2C_M_RD, |
283 | .flags = I2C_M_RD, |
262 | .len = len, |
284 | .len = len, |
263 | .buf = buf, |
285 | .buf = buf, |
264 | } |
286 | } |
265 | }; |
287 | }; |
266 | ret = i2c_transfer(adapter, msgs, 2); |
- | |
267 | } while (ret != 2 && --retries); |
- | |
Line -... | Line 288... | ||
- | 288 | ||
- | 289 | /* |
|
- | 290 | * Avoid sending the segment addr to not upset non-compliant ddc |
|
- | 291 | * monitors. |
|
- | 292 | */ |
|
- | 293 | ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers); |
|
- | 294 | ||
- | 295 | if (ret == -ENXIO) { |
|
- | 296 | DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n", |
|
- | 297 | adapter->name); |
|
- | 298 | break; |
|
- | 299 | } |
|
- | 300 | } while (ret != xfers && --retries); |
|
268 | 301 | ||
269 | return ret == 2 ? 0 : -1; |
302 | return ret == xfers ? 0 : -1; |
Line 270... | Line 303... | ||
270 | } |
303 | } |
271 | 304 | ||
272 | static bool drm_edid_is_zero(u8 *in_edid, int length) |
305 | static bool drm_edid_is_zero(u8 *in_edid, int length) |
Line 281... | Line 314... | ||
281 | } |
314 | } |
Line 282... | Line 315... | ||
282 | 315 | ||
283 | static u8 * |
316 | static u8 * |
284 | drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) |
317 | drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) |
- | 318 | { |
|
285 | { |
319 | size_t alloc_size; |
286 | int i, j = 0, valid_extensions = 0; |
320 | int i, j = 0, valid_extensions = 0; |
287 | u8 *block, *new; |
321 | u8 *block, *new; |
Line 288... | Line 322... | ||
288 | size_t alloc_size; |
322 | bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS); |
289 | 323 | ||
Line 290... | Line 324... | ||
290 | if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) |
324 | if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) |
291 | return NULL; |
325 | return NULL; |
292 | 326 | ||
293 | /* base block fetch */ |
327 | /* base block fetch */ |
294 | for (i = 0; i < 4; i++) { |
328 | for (i = 0; i < 4; i++) { |
295 | if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) |
329 | if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) |
296 | goto out; |
330 | goto out; |
297 | if (drm_edid_block_valid(block)) |
331 | if (drm_edid_block_valid(block, 0, print_bad_edid)) |
298 | break; |
332 | break; |
299 | if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { |
333 | if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { |
Line 324... | Line 358... | ||
324 | for (i = 0; i < 4; i++) { |
358 | for (i = 0; i < 4; i++) { |
325 | if (drm_do_probe_ddc_edid(adapter, |
359 | if (drm_do_probe_ddc_edid(adapter, |
326 | block + (valid_extensions + 1) * EDID_LENGTH, |
360 | block + (valid_extensions + 1) * EDID_LENGTH, |
327 | j, EDID_LENGTH)) |
361 | j, EDID_LENGTH)) |
328 | goto out; |
362 | goto out; |
329 | if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH)) { |
363 | if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid)) { |
330 | valid_extensions++; |
364 | valid_extensions++; |
331 | break; |
365 | break; |
332 | } |
366 | } |
333 | } |
367 | } |
334 | if (i == 4) |
368 | if (i == 4) |
Line 349... | Line 383... | ||
349 | } |
383 | } |
Line 350... | Line 384... | ||
350 | 384 | ||
Line 351... | Line 385... | ||
351 | return block; |
385 | return block; |
- | 386 | ||
352 | 387 | carp: |
|
353 | carp: |
388 | if (print_bad_edid) { |
- | 389 | dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", |
|
- | 390 | drm_get_connector_name(connector), j); |
|
Line 354... | Line 391... | ||
354 | dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", |
391 | } |
355 | drm_get_connector_name(connector), j); |
392 | connector->bad_edid_counter++; |
356 | 393 | ||
357 | out: |
394 | out: |
Line 363... | Line 400... | ||
363 | * Probe DDC presence. |
400 | * Probe DDC presence. |
364 | * |
401 | * |
365 | * \param adapter : i2c device adaptor |
402 | * \param adapter : i2c device adaptor |
366 | * \return 1 on success |
403 | * \return 1 on success |
367 | */ |
404 | */ |
368 | static bool |
405 | bool |
369 | drm_probe_ddc(struct i2c_adapter *adapter) |
406 | drm_probe_ddc(struct i2c_adapter *adapter) |
370 | { |
407 | { |
371 | unsigned char out; |
408 | unsigned char out; |
Line 372... | Line 409... | ||
372 | 409 | ||
373 | return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0); |
410 | return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0); |
- | 411 | } |
|
Line 374... | Line 412... | ||
374 | } |
412 | EXPORT_SYMBOL(drm_probe_ddc); |
375 | 413 | ||
376 | /** |
414 | /** |
377 | * drm_get_edid - get EDID data, if available |
415 | * drm_get_edid - get EDID data, if available |
Line 389... | Line 427... | ||
389 | struct edid *edid = NULL; |
427 | struct edid *edid = NULL; |
Line 390... | Line 428... | ||
390 | 428 | ||
391 | if (drm_probe_ddc(adapter)) |
429 | if (drm_probe_ddc(adapter)) |
Line 392... | Line -... | ||
392 | edid = (struct edid *)drm_do_get_edid(connector, adapter); |
- | |
393 | - | ||
394 | connector->display_info.raw_edid = (char *)edid; |
430 | edid = (struct edid *)drm_do_get_edid(connector, adapter); |
395 | - | ||
396 | return edid; |
431 | |
397 | 432 | return edid; |
|
Line 398... | Line 433... | ||
398 | } |
433 | } |
Line 488... | Line 523... | ||
488 | } |
523 | } |
Line 489... | Line 524... | ||
489 | 524 | ||
490 | preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; |
525 | preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; |
Line -... | Line 526... | ||
- | 526 | } |
|
- | 527 | ||
- | 528 | static bool |
|
- | 529 | mode_is_rb(const struct drm_display_mode *mode) |
|
- | 530 | { |
|
- | 531 | return (mode->htotal - mode->hdisplay == 160) && |
|
- | 532 | (mode->hsync_end - mode->hdisplay == 80) && |
|
- | 533 | (mode->hsync_end - mode->hsync_start == 32) && |
|
- | 534 | (mode->vsync_start - mode->vdisplay == 3); |
|
- | 535 | } |
|
- | 536 | ||
- | 537 | /* |
|
- | 538 | * drm_mode_find_dmt - Create a copy of a mode if present in DMT |
|
- | 539 | * @dev: Device to duplicate against |
|
- | 540 | * @hsize: Mode width |
|
- | 541 | * @vsize: Mode height |
|
- | 542 | * @fresh: Mode refresh rate |
|
- | 543 | * @rb: Mode reduced-blanking-ness |
|
- | 544 | * |
|
- | 545 | * Walk the DMT mode list looking for a match for the given parameters. |
|
491 | } |
546 | * Return a newly allocated copy of the mode, or NULL if not found. |
492 | 547 | */ |
|
- | 548 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, |
|
493 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, |
549 | int hsize, int vsize, int fresh, |
494 | int hsize, int vsize, int fresh) |
- | |
495 | { |
550 | bool rb) |
Line 496... | Line 551... | ||
496 | struct drm_display_mode *mode = NULL; |
551 | { |
497 | int i; |
552 | int i; |
498 | 553 | ||
- | 554 | for (i = 0; i < drm_num_dmt_modes; i++) { |
|
499 | for (i = 0; i < drm_num_dmt_modes; i++) { |
555 | const struct drm_display_mode *ptr = &drm_dmt_modes[i]; |
- | 556 | if (hsize != ptr->hdisplay) |
|
500 | const struct drm_display_mode *ptr = &drm_dmt_modes[i]; |
557 | continue; |
501 | if (hsize == ptr->hdisplay && |
558 | if (vsize != ptr->vdisplay) |
502 | vsize == ptr->vdisplay && |
559 | continue; |
503 | fresh == drm_mode_vrefresh(ptr)) { |
560 | if (fresh != drm_mode_vrefresh(ptr)) |
504 | /* get the expected default mode */ |
561 | continue; |
- | 562 | if (rb != mode_is_rb(ptr)) |
|
505 | mode = drm_mode_duplicate(dev, ptr); |
563 | continue; |
- | 564 | ||
506 | break; |
565 | return drm_mode_duplicate(dev, ptr); |
507 | } |
566 | } |
508 | } |
567 | |
Line 509... | Line 568... | ||
509 | return mode; |
568 | return NULL; |
Line 510... | Line 569... | ||
510 | } |
569 | } |
511 | EXPORT_SYMBOL(drm_mode_find_dmt); |
570 | EXPORT_SYMBOL(drm_mode_find_dmt); |
512 | 571 | ||
513 | typedef void detailed_cb(struct detailed_timing *timing, void *closure); |
572 | typedef void detailed_cb(struct detailed_timing *timing, void *closure); |
514 | 573 | ||
515 | static void |
574 | static void |
Line 516... | Line -... | ||
516 | cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) |
- | |
517 | { |
- | |
518 | int i, n = 0; |
- | |
519 | u8 rev = ext[0x01], d = ext[0x02]; |
- | |
520 | u8 *det_base = ext + d; |
- | |
521 | - | ||
522 | switch (rev) { |
575 | cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) |
523 | case 0: |
- | |
524 | /* can't happen */ |
- | |
525 | return; |
- | |
526 | case 1: |
- | |
527 | /* have to infer how many blocks we have, check pixel clock */ |
- | |
528 | for (i = 0; i < 6; i++) |
- | |
529 | if (det_base[18*i] || det_base[18*i+1]) |
- | |
530 | n++; |
- | |
531 | break; |
- | |
532 | default: |
576 | { |
533 | /* explicit count */ |
577 | int i, n = 0; |
534 | n = min(ext[0x03] & 0x0f, 6); |
578 | u8 d = ext[0x02]; |
Line 535... | Line 579... | ||
535 | break; |
579 | u8 *det_base = ext + d; |
Line 591... | Line 635... | ||
591 | /* EDID 1.4 defines this explicitly. For EDID 1.3, we guess, badly. */ |
635 | /* EDID 1.4 defines this explicitly. For EDID 1.3, we guess, badly. */ |
592 | static bool |
636 | static bool |
593 | drm_monitor_supports_rb(struct edid *edid) |
637 | drm_monitor_supports_rb(struct edid *edid) |
594 | { |
638 | { |
595 | if (edid->revision >= 4) { |
639 | if (edid->revision >= 4) { |
596 | bool ret; |
640 | bool ret = false; |
597 | drm_for_each_detailed_block((u8 *)edid, is_rb, &ret); |
641 | drm_for_each_detailed_block((u8 *)edid, is_rb, &ret); |
598 | return ret; |
642 | return ret; |
599 | } |
643 | } |
Line 600... | Line 644... | ||
600 | 644 | ||
Line 748... | Line 792... | ||
748 | mode->hsync_end = mode->hsync_end - 1; |
792 | mode->hsync_end = mode->hsync_end - 1; |
749 | return mode; |
793 | return mode; |
750 | } |
794 | } |
Line 751... | Line 795... | ||
751 | 795 | ||
- | 796 | /* check whether it can be found in default mode table */ |
|
752 | /* check whether it can be found in default mode table */ |
797 | if (drm_monitor_supports_rb(edid)) { |
- | 798 | mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate, |
|
- | 799 | true); |
|
- | 800 | if (mode) |
|
- | 801 | return mode; |
|
- | 802 | } |
|
753 | mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate); |
803 | mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate, false); |
754 | if (mode) |
804 | if (mode) |
Line -... | Line 805... | ||
- | 805 | return mode; |
|
755 | return mode; |
806 | |
756 | 807 | /* okay, generate it */ |
|
757 | switch (timing_level) { |
808 | switch (timing_level) { |
758 | case LEVEL_DMT: |
809 | case LEVEL_DMT: |
759 | break; |
810 | break; |
Line 765... | Line 816... | ||
765 | * This is potentially wrong if there's ever a monitor with |
816 | * This is potentially wrong if there's ever a monitor with |
766 | * more than one ranges section, each claiming a different |
817 | * more than one ranges section, each claiming a different |
767 | * secondary GTF curve. Please don't do that. |
818 | * secondary GTF curve. Please don't do that. |
768 | */ |
819 | */ |
769 | mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); |
820 | mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); |
- | 821 | if (!mode) |
|
- | 822 | return NULL; |
|
770 | if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) { |
823 | if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) { |
771 | kfree(mode); |
824 | drm_mode_destroy(dev, mode); |
772 | mode = drm_gtf_mode_complex(dev, hsize, vsize, |
825 | mode = drm_gtf_mode_complex(dev, hsize, vsize, |
773 | vrefresh_rate, 0, 0, |
826 | vrefresh_rate, 0, 0, |
774 | drm_gtf2_m(edid), |
827 | drm_gtf2_m(edid), |
775 | drm_gtf2_2c(edid), |
828 | drm_gtf2_2c(edid), |
776 | drm_gtf2_k(edid), |
829 | drm_gtf2_k(edid), |
Line 869... | Line 922... | ||
869 | if (!hsync_pulse_width || !vsync_pulse_width) { |
922 | if (!hsync_pulse_width || !vsync_pulse_width) { |
870 | DRM_DEBUG_KMS("Incorrect Detailed timing. " |
923 | DRM_DEBUG_KMS("Incorrect Detailed timing. " |
871 | "Wrong Hsync/Vsync pulse width\n"); |
924 | "Wrong Hsync/Vsync pulse width\n"); |
872 | return NULL; |
925 | return NULL; |
873 | } |
926 | } |
- | 927 | ||
- | 928 | if (quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) { |
|
874 | mode = drm_mode_create(dev); |
929 | mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false); |
875 | if (!mode) |
930 | if (!mode) |
876 | return NULL; |
931 | return NULL; |
Line -... | Line 932... | ||
- | 932 | ||
- | 933 | goto set_size; |
|
- | 934 | } |
|
877 | 935 | ||
- | 936 | mode = drm_mode_create(dev); |
|
- | 937 | if (!mode) |
|
Line 878... | Line 938... | ||
878 | mode->type = DRM_MODE_TYPE_DRIVER; |
938 | return NULL; |
879 | 939 | ||
Line 880... | Line 940... | ||
880 | if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) |
940 | if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) |
Line 898... | Line 958... | ||
898 | if (mode->vsync_end > mode->vtotal) |
958 | if (mode->vsync_end > mode->vtotal) |
899 | mode->vtotal = mode->vsync_end + 1; |
959 | mode->vtotal = mode->vsync_end + 1; |
Line 900... | Line 960... | ||
900 | 960 | ||
Line 901... | Line -... | ||
901 | drm_mode_do_interlace_quirk(mode, pt); |
- | |
902 | - | ||
903 | drm_mode_set_name(mode); |
961 | drm_mode_do_interlace_quirk(mode, pt); |
904 | 962 | ||
905 | if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { |
963 | if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { |
Line 906... | Line 964... | ||
906 | pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; |
964 | pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; |
907 | } |
965 | } |
908 | 966 | ||
909 | mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? |
967 | mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? |
Line -... | Line 968... | ||
- | 968 | DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; |
|
910 | DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; |
969 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? |
911 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? |
970 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; |
Line 912... | Line 971... | ||
912 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; |
971 | |
913 | 972 | set_size: |
|
Line 922... | Line 981... | ||
922 | if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { |
981 | if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { |
923 | mode->width_mm = edid->width_cm * 10; |
982 | mode->width_mm = edid->width_cm * 10; |
924 | mode->height_mm = edid->height_cm * 10; |
983 | mode->height_mm = edid->height_cm * 10; |
925 | } |
984 | } |
Line -... | Line 985... | ||
- | 985 | ||
926 | 986 | mode->type = DRM_MODE_TYPE_DRIVER; |
|
927 | return mode; |
- | |
Line 928... | Line 987... | ||
928 | } |
987 | drm_mode_set_name(mode); |
929 | - | ||
930 | static bool |
- | |
931 | mode_is_rb(const struct drm_display_mode *mode) |
- | |
932 | { |
- | |
933 | return (mode->htotal - mode->hdisplay == 160) && |
- | |
934 | (mode->hsync_end - mode->hdisplay == 80) && |
- | |
935 | (mode->hsync_end - mode->hsync_start == 32) && |
988 | |
Line 936... | Line 989... | ||
936 | (mode->vsync_start - mode->vdisplay == 3); |
989 | return mode; |
937 | } |
990 | } |
938 | 991 | ||
Line 1011... | Line 1064... | ||
1011 | return false; |
1064 | return false; |
Line 1012... | Line 1065... | ||
1012 | 1065 | ||
1013 | return true; |
1066 | return true; |
Line -... | Line 1067... | ||
- | 1067 | } |
|
- | 1068 | ||
1014 | } |
1069 | static bool valid_inferred_mode(const struct drm_connector *connector, |
- | 1070 | const struct drm_display_mode *mode) |
|
- | 1071 | { |
|
- | 1072 | struct drm_display_mode *m; |
|
- | 1073 | bool ok = false; |
|
- | 1074 | ||
- | 1075 | list_for_each_entry(m, &connector->probed_modes, head) { |
|
1015 | 1076 | if (mode->hdisplay == m->hdisplay && |
|
1016 | /* |
1077 | mode->vdisplay == m->vdisplay && |
- | 1078 | drm_mode_vrefresh(mode) == drm_mode_vrefresh(m)) |
|
- | 1079 | return false; /* duplicated */ |
|
- | 1080 | if (mode->hdisplay <= m->hdisplay && |
|
1017 | * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will |
1081 | mode->vdisplay <= m->vdisplay) |
- | 1082 | ok = true; |
|
- | 1083 | } |
|
- | 1084 | return ok; |
|
1018 | * need to account for them. |
1085 | } |
1019 | */ |
1086 | |
1020 | static int |
1087 | static int |
1021 | drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, |
1088 | drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid, |
1022 | struct detailed_timing *timing) |
1089 | struct detailed_timing *timing) |
1023 | { |
1090 | { |
1024 | int i, modes = 0; |
1091 | int i, modes = 0; |
Line 1025... | Line 1092... | ||
1025 | struct drm_display_mode *newmode; |
1092 | struct drm_display_mode *newmode; |
1026 | struct drm_device *dev = connector->dev; |
1093 | struct drm_device *dev = connector->dev; |
- | 1094 | ||
1027 | 1095 | for (i = 0; i < drm_num_dmt_modes; i++) { |
|
1028 | for (i = 0; i < drm_num_dmt_modes; i++) { |
1096 | if (mode_in_range(drm_dmt_modes + i, edid, timing) && |
1029 | if (mode_in_range(drm_dmt_modes + i, edid, timing)) { |
1097 | valid_inferred_mode(connector, drm_dmt_modes + i)) { |
1030 | newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]); |
1098 | newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]); |
1031 | if (newmode) { |
1099 | if (newmode) { |
Line 1036... | Line 1104... | ||
1036 | } |
1104 | } |
Line 1037... | Line 1105... | ||
1037 | 1105 | ||
1038 | return modes; |
1106 | return modes; |
Line -... | Line 1107... | ||
- | 1107 | } |
|
- | 1108 | ||
- | 1109 | /* fix up 1366x768 mode from 1368x768; |
|
- | 1110 | * GFT/CVT can't express 1366 width which isn't dividable by 8 |
|
- | 1111 | */ |
|
- | 1112 | static void fixup_mode_1366x768(struct drm_display_mode *mode) |
|
- | 1113 | { |
|
- | 1114 | if (mode->hdisplay == 1368 && mode->vdisplay == 768) { |
|
- | 1115 | mode->hdisplay = 1366; |
|
- | 1116 | mode->hsync_start--; |
|
- | 1117 | mode->hsync_end--; |
|
- | 1118 | drm_mode_set_name(mode); |
|
- | 1119 | } |
|
- | 1120 | } |
|
- | 1121 | ||
- | 1122 | static int |
|
- | 1123 | drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, |
|
- | 1124 | struct detailed_timing *timing) |
|
- | 1125 | { |
|
- | 1126 | int i, modes = 0; |
|
- | 1127 | struct drm_display_mode *newmode; |
|
- | 1128 | struct drm_device *dev = connector->dev; |
|
- | 1129 | ||
- | 1130 | for (i = 0; i < num_extra_modes; i++) { |
|
- | 1131 | const struct minimode *m = &extra_modes[i]; |
|
- | 1132 | newmode = drm_gtf_mode(dev, m->w, m->h, m->r, 0, 0); |
|
- | 1133 | if (!newmode) |
|
- | 1134 | return modes; |
|
- | 1135 | ||
- | 1136 | fixup_mode_1366x768(newmode); |
|
- | 1137 | if (!mode_in_range(newmode, edid, timing) || |
|
- | 1138 | !valid_inferred_mode(connector, newmode)) { |
|
- | 1139 | drm_mode_destroy(dev, newmode); |
|
- | 1140 | continue; |
|
- | 1141 | } |
|
- | 1142 | ||
- | 1143 | drm_mode_probed_add(connector, newmode); |
|
- | 1144 | modes++; |
|
- | 1145 | } |
|
- | 1146 | ||
- | 1147 | return modes; |
|
- | 1148 | } |
|
- | 1149 | ||
- | 1150 | static int |
|
- | 1151 | drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid, |
|
- | 1152 | struct detailed_timing *timing) |
|
- | 1153 | { |
|
- | 1154 | int i, modes = 0; |
|
- | 1155 | struct drm_display_mode *newmode; |
|
- | 1156 | struct drm_device *dev = connector->dev; |
|
- | 1157 | bool rb = drm_monitor_supports_rb(edid); |
|
- | 1158 | ||
- | 1159 | for (i = 0; i < num_extra_modes; i++) { |
|
- | 1160 | const struct minimode *m = &extra_modes[i]; |
|
- | 1161 | newmode = drm_cvt_mode(dev, m->w, m->h, m->r, rb, 0, 0); |
|
- | 1162 | if (!newmode) |
|
- | 1163 | return modes; |
|
- | 1164 | ||
- | 1165 | fixup_mode_1366x768(newmode); |
|
- | 1166 | if (!mode_in_range(newmode, edid, timing) || |
|
- | 1167 | !valid_inferred_mode(connector, newmode)) { |
|
- | 1168 | drm_mode_destroy(dev, newmode); |
|
- | 1169 | continue; |
|
- | 1170 | } |
|
- | 1171 | ||
- | 1172 | drm_mode_probed_add(connector, newmode); |
|
- | 1173 | modes++; |
|
- | 1174 | } |
|
- | 1175 | ||
- | 1176 | return modes; |
|
1039 | } |
1177 | } |
1040 | 1178 | ||
1041 | static void |
1179 | static void |
1042 | do_inferred_modes(struct detailed_timing *timing, void *c) |
1180 | do_inferred_modes(struct detailed_timing *timing, void *c) |
1043 | { |
1181 | { |
- | 1182 | struct detailed_mode_closure *closure = c; |
|
- | 1183 | struct detailed_non_pixel *data = &timing->data.other_data; |
|
1044 | struct detailed_mode_closure *closure = c; |
1184 | struct detailed_data_monitor_range *range = &data->data.range; |
- | 1185 | ||
Line -... | Line 1186... | ||
- | 1186 | if (data->type != EDID_DETAIL_MONITOR_RANGE) |
|
- | 1187 | return; |
|
- | 1188 | ||
- | 1189 | closure->modes += drm_dmt_modes_for_range(closure->connector, |
|
1045 | struct detailed_non_pixel *data = &timing->data.other_data; |
1190 | closure->edid, |
- | 1191 | timing); |
|
- | 1192 | ||
- | 1193 | if (!version_greater(closure->edid, 1, 1)) |
|
- | 1194 | return; /* GTF not defined yet */ |
|
- | 1195 | ||
1046 | int gtf = (closure->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); |
1196 | switch (range->flags) { |
1047 | 1197 | case 0x02: /* secondary gtf, XXX could do more */ |
|
1048 | if (gtf && data->type == EDID_DETAIL_MONITOR_RANGE) |
1198 | case 0x00: /* default gtf */ |
- | 1199 | closure->modes += drm_gtf_modes_for_range(closure->connector, |
|
- | 1200 | closure->edid, |
|
- | 1201 | timing); |
|
- | 1202 | break; |
|
- | 1203 | case 0x04: /* cvt, only in 1.4+ */ |
|
- | 1204 | if (!version_greater(closure->edid, 1, 3)) |
|
- | 1205 | break; |
|
- | 1206 | ||
- | 1207 | closure->modes += drm_cvt_modes_for_range(closure->connector, |
|
- | 1208 | closure->edid, |
|
- | 1209 | timing); |
|
- | 1210 | break; |
|
- | 1211 | case 0x01: /* just the ranges, no formula */ |
|
1049 | closure->modes += drm_gtf_modes_for_range(closure->connector, |
1212 | default: |
Line 1050... | Line 1213... | ||
1050 | closure->edid, |
1213 | break; |
1051 | timing); |
1214 | } |
1052 | } |
1215 | } |
Line 1079... | Line 1242... | ||
1079 | break; |
1242 | break; |
1080 | if (est[i] & (1 << j)) { |
1243 | if (est[i] & (1 << j)) { |
1081 | mode = drm_mode_find_dmt(connector->dev, |
1244 | mode = drm_mode_find_dmt(connector->dev, |
1082 | est3_modes[m].w, |
1245 | est3_modes[m].w, |
1083 | est3_modes[m].h, |
1246 | est3_modes[m].h, |
1084 | est3_modes[m].r |
1247 | est3_modes[m].r, |
1085 | /*, est3_modes[m].rb */); |
1248 | est3_modes[m].rb); |
1086 | if (mode) { |
1249 | if (mode) { |
1087 | drm_mode_probed_add(connector, mode); |
1250 | drm_mode_probed_add(connector, mode); |
1088 | modes++; |
1251 | modes++; |
1089 | } |
1252 | } |
1090 | } |
1253 | } |
Line 1325... | Line 1488... | ||
1325 | return closure.modes; |
1488 | return closure.modes; |
1326 | } |
1489 | } |
Line 1327... | Line 1490... | ||
1327 | 1490 | ||
1328 | #define HDMI_IDENTIFIER 0x000C03 |
1491 | #define HDMI_IDENTIFIER 0x000C03 |
- | 1492 | #define AUDIO_BLOCK 0x01 |
|
1329 | #define AUDIO_BLOCK 0x01 |
1493 | #define VIDEO_BLOCK 0x02 |
- | 1494 | #define VENDOR_BLOCK 0x03 |
|
1330 | #define VENDOR_BLOCK 0x03 |
1495 | #define SPEAKER_BLOCK 0x04 |
- | 1496 | #define EDID_BASIC_AUDIO (1 << 6) |
|
- | 1497 | #define EDID_CEA_YCRCB444 (1 << 5) |
|
Line 1331... | Line 1498... | ||
1331 | #define EDID_BASIC_AUDIO (1 << 6) |
1498 | #define EDID_CEA_YCRCB422 (1 << 4) |
1332 | 1499 | ||
1333 | /** |
1500 | /** |
1334 | * Search EDID for CEA extension block. |
1501 | * Search EDID for CEA extension block. |
Line 1354... | Line 1521... | ||
1354 | 1521 | ||
1355 | return edid_ext; |
1522 | return edid_ext; |
1356 | } |
1523 | } |
Line -... | Line 1524... | ||
- | 1524 | EXPORT_SYMBOL(drm_find_cea_extension); |
|
- | 1525 | ||
- | 1526 | static int |
|
- | 1527 | do_cea_modes (struct drm_connector *connector, u8 *db, u8 len) |
|
- | 1528 | { |
|
- | 1529 | struct drm_device *dev = connector->dev; |
|
- | 1530 | u8 * mode, cea_mode; |
|
- | 1531 | int modes = 0; |
|
- | 1532 | ||
- | 1533 | for (mode = db; mode < db + len; mode++) { |
|
- | 1534 | cea_mode = (*mode & 127) - 1; /* CEA modes are numbered 1..127 */ |
|
- | 1535 | if (cea_mode < drm_num_cea_modes) { |
|
- | 1536 | struct drm_display_mode *newmode; |
|
- | 1537 | newmode = drm_mode_duplicate(dev, |
|
- | 1538 | &edid_cea_modes[cea_mode]); |
|
- | 1539 | if (newmode) { |
|
- | 1540 | drm_mode_probed_add(connector, newmode); |
|
- | 1541 | modes++; |
|
- | 1542 | } |
|
- | 1543 | } |
|
- | 1544 | } |
|
- | 1545 | ||
- | 1546 | return modes; |
|
- | 1547 | } |
|
- | 1548 | ||
- | 1549 | static int |
|
- | 1550 | cea_db_payload_len(const u8 *db) |
|
- | 1551 | { |
|
- | 1552 | return db[0] & 0x1f; |
|
- | 1553 | } |
|
- | 1554 | ||
- | 1555 | static int |
|
- | 1556 | cea_db_tag(const u8 *db) |
|
- | 1557 | { |
|
- | 1558 | return db[0] >> 5; |
|
- | 1559 | } |
|
- | 1560 | ||
- | 1561 | static int |
|
- | 1562 | cea_revision(const u8 *cea) |
|
- | 1563 | { |
|
- | 1564 | return cea[1]; |
|
- | 1565 | } |
|
- | 1566 | ||
- | 1567 | static int |
|
- | 1568 | cea_db_offsets(const u8 *cea, int *start, int *end) |
|
- | 1569 | { |
|
- | 1570 | /* Data block offset in CEA extension block */ |
|
- | 1571 | *start = 4; |
|
- | 1572 | *end = cea[2]; |
|
- | 1573 | if (*end == 0) |
|
- | 1574 | *end = 127; |
|
- | 1575 | if (*end < 4 || *end > 127) |
|
- | 1576 | return -ERANGE; |
|
- | 1577 | return 0; |
|
- | 1578 | } |
|
- | 1579 | ||
- | 1580 | #define for_each_cea_db(cea, i, start, end) \ |
|
- | 1581 | for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1) |
|
- | 1582 | ||
- | 1583 | static int |
|
- | 1584 | add_cea_modes(struct drm_connector *connector, struct edid *edid) |
|
- | 1585 | { |
|
- | 1586 | u8 * cea = drm_find_cea_extension(edid); |
|
- | 1587 | u8 * db, dbl; |
|
- | 1588 | int modes = 0; |
|
- | 1589 | ||
- | 1590 | if (cea && cea_revision(cea) >= 3) { |
|
- | 1591 | int i, start, end; |
|
- | 1592 | ||
- | 1593 | if (cea_db_offsets(cea, &start, &end)) |
|
- | 1594 | return 0; |
|
- | 1595 | ||
- | 1596 | for_each_cea_db(cea, i, start, end) { |
|
- | 1597 | db = &cea[i]; |
|
- | 1598 | dbl = cea_db_payload_len(db); |
|
- | 1599 | ||
- | 1600 | if (cea_db_tag(db) == VIDEO_BLOCK) |
|
- | 1601 | modes += do_cea_modes (connector, db+1, dbl); |
|
- | 1602 | } |
|
- | 1603 | } |
|
- | 1604 | ||
- | 1605 | return modes; |
|
- | 1606 | } |
|
- | 1607 | ||
- | 1608 | static void |
|
- | 1609 | parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db) |
|
- | 1610 | { |
|
- | 1611 | u8 len = cea_db_payload_len(db); |
|
- | 1612 | ||
- | 1613 | if (len >= 6) { |
|
- | 1614 | connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */ |
|
- | 1615 | connector->dvi_dual = db[6] & 1; |
|
- | 1616 | } |
|
- | 1617 | if (len >= 7) |
|
- | 1618 | connector->max_tmds_clock = db[7] * 5; |
|
- | 1619 | if (len >= 8) { |
|
- | 1620 | connector->latency_present[0] = db[8] >> 7; |
|
- | 1621 | connector->latency_present[1] = (db[8] >> 6) & 1; |
|
- | 1622 | } |
|
- | 1623 | if (len >= 9) |
|
- | 1624 | connector->video_latency[0] = db[9]; |
|
- | 1625 | if (len >= 10) |
|
- | 1626 | connector->audio_latency[0] = db[10]; |
|
- | 1627 | if (len >= 11) |
|
- | 1628 | connector->video_latency[1] = db[11]; |
|
- | 1629 | if (len >= 12) |
|
- | 1630 | connector->audio_latency[1] = db[12]; |
|
- | 1631 | ||
- | 1632 | DRM_LOG_KMS("HDMI: DVI dual %d, " |
|
- | 1633 | "max TMDS clock %d, " |
|
- | 1634 | "latency present %d %d, " |
|
- | 1635 | "video latency %d %d, " |
|
- | 1636 | "audio latency %d %d\n", |
|
- | 1637 | connector->dvi_dual, |
|
- | 1638 | connector->max_tmds_clock, |
|
- | 1639 | (int) connector->latency_present[0], |
|
- | 1640 | (int) connector->latency_present[1], |
|
- | 1641 | connector->video_latency[0], |
|
- | 1642 | connector->video_latency[1], |
|
- | 1643 | connector->audio_latency[0], |
|
- | 1644 | connector->audio_latency[1]); |
|
- | 1645 | } |
|
- | 1646 | ||
- | 1647 | static void |
|
- | 1648 | monitor_name(struct detailed_timing *t, void *data) |
|
- | 1649 | { |
|
- | 1650 | if (t->data.other_data.type == EDID_DETAIL_MONITOR_NAME) |
|
- | 1651 | *(u8 **)data = t->data.other_data.data.str.str; |
|
- | 1652 | } |
|
- | 1653 | ||
- | 1654 | static bool cea_db_is_hdmi_vsdb(const u8 *db) |
|
- | 1655 | { |
|
- | 1656 | int hdmi_id; |
|
- | 1657 | ||
- | 1658 | if (cea_db_tag(db) != VENDOR_BLOCK) |
|
- | 1659 | return false; |
|
- | 1660 | ||
- | 1661 | if (cea_db_payload_len(db) < 5) |
|
- | 1662 | return false; |
|
- | 1663 | ||
- | 1664 | hdmi_id = db[1] | (db[2] << 8) | (db[3] << 16); |
|
- | 1665 | ||
- | 1666 | return hdmi_id == HDMI_IDENTIFIER; |
|
- | 1667 | } |
|
- | 1668 | ||
- | 1669 | /** |
|
- | 1670 | * drm_edid_to_eld - build ELD from EDID |
|
- | 1671 | * @connector: connector corresponding to the HDMI/DP sink |
|
- | 1672 | * @edid: EDID to parse |
|
- | 1673 | * |
|
- | 1674 | * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. |
|
- | 1675 | * Some ELD fields are left to the graphics driver caller: |
|
- | 1676 | * - Conn_Type |
|
- | 1677 | * - HDCP |
|
- | 1678 | * - Port_ID |
|
- | 1679 | */ |
|
- | 1680 | void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) |
|
- | 1681 | { |
|
- | 1682 | uint8_t *eld = connector->eld; |
|
- | 1683 | u8 *cea; |
|
- | 1684 | u8 *name; |
|
- | 1685 | u8 *db; |
|
- | 1686 | int sad_count = 0; |
|
- | 1687 | int mnl; |
|
- | 1688 | int dbl; |
|
- | 1689 | ||
- | 1690 | memset(eld, 0, sizeof(connector->eld)); |
|
- | 1691 | ||
- | 1692 | cea = drm_find_cea_extension(edid); |
|
- | 1693 | if (!cea) { |
|
- | 1694 | DRM_DEBUG_KMS("ELD: no CEA Extension found\n"); |
|
- | 1695 | return; |
|
- | 1696 | } |
|
- | 1697 | ||
- | 1698 | name = NULL; |
|
- | 1699 | drm_for_each_detailed_block((u8 *)edid, monitor_name, &name); |
|
- | 1700 | for (mnl = 0; name && mnl < 13; mnl++) { |
|
- | 1701 | if (name[mnl] == 0x0a) |
|
- | 1702 | break; |
|
- | 1703 | eld[20 + mnl] = name[mnl]; |
|
- | 1704 | } |
|
- | 1705 | eld[4] = (cea[1] << 5) | mnl; |
|
- | 1706 | DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20); |
|
- | 1707 | ||
- | 1708 | eld[0] = 2 << 3; /* ELD version: 2 */ |
|
- | 1709 | ||
- | 1710 | eld[16] = edid->mfg_id[0]; |
|
- | 1711 | eld[17] = edid->mfg_id[1]; |
|
- | 1712 | eld[18] = edid->prod_code[0]; |
|
- | 1713 | eld[19] = edid->prod_code[1]; |
|
- | 1714 | ||
- | 1715 | if (cea_revision(cea) >= 3) { |
|
- | 1716 | int i, start, end; |
|
- | 1717 | ||
- | 1718 | if (cea_db_offsets(cea, &start, &end)) { |
|
- | 1719 | start = 0; |
|
- | 1720 | end = 0; |
|
- | 1721 | } |
|
- | 1722 | ||
- | 1723 | for_each_cea_db(cea, i, start, end) { |
|
- | 1724 | db = &cea[i]; |
|
- | 1725 | dbl = cea_db_payload_len(db); |
|
- | 1726 | ||
- | 1727 | switch (cea_db_tag(db)) { |
|
- | 1728 | case AUDIO_BLOCK: |
|
- | 1729 | /* Audio Data Block, contains SADs */ |
|
- | 1730 | sad_count = dbl / 3; |
|
- | 1731 | if (dbl >= 1) |
|
- | 1732 | memcpy(eld + 20 + mnl, &db[1], dbl); |
|
- | 1733 | break; |
|
- | 1734 | case SPEAKER_BLOCK: |
|
- | 1735 | /* Speaker Allocation Data Block */ |
|
- | 1736 | if (dbl >= 1) |
|
- | 1737 | eld[7] = db[1]; |
|
- | 1738 | break; |
|
- | 1739 | case VENDOR_BLOCK: |
|
- | 1740 | /* HDMI Vendor-Specific Data Block */ |
|
- | 1741 | if (cea_db_is_hdmi_vsdb(db)) |
|
- | 1742 | parse_hdmi_vsdb(connector, db); |
|
- | 1743 | break; |
|
- | 1744 | default: |
|
- | 1745 | break; |
|
- | 1746 | } |
|
- | 1747 | } |
|
- | 1748 | } |
|
- | 1749 | eld[5] |= sad_count << 4; |
|
- | 1750 | eld[2] = (20 + mnl + sad_count * 3 + 3) / 4; |
|
- | 1751 | ||
- | 1752 | DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", (int)eld[2], sad_count); |
|
- | 1753 | } |
|
- | 1754 | EXPORT_SYMBOL(drm_edid_to_eld); |
|
- | 1755 | ||
- | 1756 | /** |
|
- | 1757 | * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond |
|
- | 1758 | * @connector: connector associated with the HDMI/DP sink |
|
- | 1759 | * @mode: the display mode |
|
- | 1760 | */ |
|
- | 1761 | int drm_av_sync_delay(struct drm_connector *connector, |
|
- | 1762 | struct drm_display_mode *mode) |
|
- | 1763 | { |
|
- | 1764 | int i = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); |
|
- | 1765 | int a, v; |
|
- | 1766 | ||
- | 1767 | if (!connector->latency_present[0]) |
|
- | 1768 | return 0; |
|
- | 1769 | if (!connector->latency_present[1]) |
|
- | 1770 | i = 0; |
|
- | 1771 | ||
- | 1772 | a = connector->audio_latency[i]; |
|
- | 1773 | v = connector->video_latency[i]; |
|
- | 1774 | ||
- | 1775 | /* |
|
- | 1776 | * HDMI/DP sink doesn't support audio or video? |
|
- | 1777 | */ |
|
- | 1778 | if (a == 255 || v == 255) |
|
- | 1779 | return 0; |
|
- | 1780 | ||
- | 1781 | /* |
|
- | 1782 | * Convert raw EDID values to millisecond. |
|
- | 1783 | * Treat unknown latency as 0ms. |
|
- | 1784 | */ |
|
- | 1785 | if (a) |
|
- | 1786 | a = min(2 * (a - 1), 500); |
|
- | 1787 | if (v) |
|
- | 1788 | v = min(2 * (v - 1), 500); |
|
- | 1789 | ||
- | 1790 | return max(v - a, 0); |
|
- | 1791 | } |
|
- | 1792 | EXPORT_SYMBOL(drm_av_sync_delay); |
|
- | 1793 | ||
- | 1794 | /** |
|
- | 1795 | * drm_select_eld - select one ELD from multiple HDMI/DP sinks |
|
- | 1796 | * @encoder: the encoder just changed display mode |
|
- | 1797 | * @mode: the adjusted display mode |
|
- | 1798 | * |
|
- | 1799 | * It's possible for one encoder to be associated with multiple HDMI/DP sinks. |
|
- | 1800 | * The policy is now hard coded to simply use the first HDMI/DP sink's ELD. |
|
- | 1801 | */ |
|
- | 1802 | struct drm_connector *drm_select_eld(struct drm_encoder *encoder, |
|
- | 1803 | struct drm_display_mode *mode) |
|
- | 1804 | { |
|
- | 1805 | struct drm_connector *connector; |
|
- | 1806 | struct drm_device *dev = encoder->dev; |
|
- | 1807 | ||
- | 1808 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
|
- | 1809 | if (connector->encoder == encoder && connector->eld[0]) |
|
- | 1810 | return connector; |
|
- | 1811 | ||
- | 1812 | return NULL; |
|
- | 1813 | } |
|
1357 | EXPORT_SYMBOL(drm_find_cea_extension); |
1814 | EXPORT_SYMBOL(drm_select_eld); |
1358 | 1815 | ||
1359 | /** |
1816 | /** |
1360 | * drm_detect_hdmi_monitor - detect whether monitor is hdmi. |
1817 | * drm_detect_hdmi_monitor - detect whether monitor is hdmi. |
1361 | * @edid: monitor EDID information |
1818 | * @edid: monitor EDID information |
1362 | * |
1819 | * |
1363 | * Parse the CEA extension according to CEA-861-B. |
1820 | * Parse the CEA extension according to CEA-861-B. |
1364 | * Return true if HDMI, false if not or unknown. |
1821 | * Return true if HDMI, false if not or unknown. |
1365 | */ |
1822 | */ |
1366 | bool drm_detect_hdmi_monitor(struct edid *edid) |
1823 | bool drm_detect_hdmi_monitor(struct edid *edid) |
1367 | { |
1824 | { |
1368 | u8 *edid_ext; |
1825 | u8 *edid_ext; |
1369 | int i, hdmi_id; |
- | |
Line 1370... | Line 1826... | ||
1370 | int start_offset, end_offset; |
1826 | int i; |
1371 | bool is_hdmi = false; |
1827 | int start_offset, end_offset; |
1372 | 1828 | ||
Line 1373... | Line 1829... | ||
1373 | edid_ext = drm_find_cea_extension(edid); |
1829 | edid_ext = drm_find_cea_extension(edid); |
1374 | if (!edid_ext) |
1830 | if (!edid_ext) |
1375 | goto end; |
- | |
Line 1376... | Line 1831... | ||
1376 | 1831 | return false; |
|
1377 | /* Data block offset in CEA extension block */ |
1832 | |
1378 | start_offset = 4; |
1833 | if (cea_db_offsets(edid_ext, &start_offset, &end_offset)) |
1379 | end_offset = edid_ext[2]; |
1834 | return false; |
1380 | 1835 | ||
1381 | /* |
- | |
1382 | * Because HDMI identifier is in Vendor Specific Block, |
- | |
1383 | * search it from all data blocks of CEA extension. |
- | |
1384 | */ |
- | |
1385 | for (i = start_offset; i < end_offset; |
1836 | /* |
1386 | /* Increased by data block len */ |
- | |
1387 | i += ((edid_ext[i] & 0x1f) + 1)) { |
- | |
1388 | /* Find vendor specific block */ |
- | |
1389 | if ((edid_ext[i] >> 5) == VENDOR_BLOCK) { |
1837 | * Because HDMI identifier is in Vendor Specific Block, |
1390 | hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) | |
- | |
1391 | edid_ext[i + 3] << 16; |
- | |
1392 | /* Find HDMI identifier */ |
1838 | * search it from all data blocks of CEA extension. |
Line 1393... | Line -... | ||
1393 | if (hdmi_id == HDMI_IDENTIFIER) |
- | |
1394 | is_hdmi = true; |
1839 | */ |
1395 | break; |
1840 | for_each_cea_db(edid_ext, i, start_offset, end_offset) { |
1396 | } |
1841 | if (cea_db_is_hdmi_vsdb(&edid_ext[i])) |
Line 1397... | Line 1842... | ||
1397 | } |
1842 | return true; |
1398 | 1843 | } |
|
Line 1427... | Line 1872... | ||
1427 | if (has_audio) { |
1872 | if (has_audio) { |
1428 | DRM_DEBUG_KMS("Monitor has basic audio support\n"); |
1873 | DRM_DEBUG_KMS("Monitor has basic audio support\n"); |
1429 | goto end; |
1874 | goto end; |
1430 | } |
1875 | } |
Line 1431... | Line 1876... | ||
1431 | 1876 | ||
1432 | /* Data block offset in CEA extension block */ |
1877 | if (cea_db_offsets(edid_ext, &start_offset, &end_offset)) |
1433 | start_offset = 4; |
- | |
Line 1434... | Line 1878... | ||
1434 | end_offset = edid_ext[2]; |
1878 | goto end; |
1435 | - | ||
1436 | for (i = start_offset; i < end_offset; |
1879 | |
1437 | i += ((edid_ext[i] & 0x1f) + 1)) { |
1880 | for_each_cea_db(edid_ext, i, start_offset, end_offset) { |
1438 | if ((edid_ext[i] >> 5) == AUDIO_BLOCK) { |
1881 | if (cea_db_tag(&edid_ext[i]) == AUDIO_BLOCK) { |
1439 | has_audio = true; |
1882 | has_audio = true; |
1440 | for (j = 1; j < (edid_ext[i] & 0x1f); j += 3) |
1883 | for (j = 1; j < cea_db_payload_len(&edid_ext[i]) + 1; j += 3) |
1441 | DRM_DEBUG_KMS("CEA audio format %d\n", |
1884 | DRM_DEBUG_KMS("CEA audio format %d\n", |
1442 | (edid_ext[i + j] >> 3) & 0xf); |
1885 | (edid_ext[i + j] >> 3) & 0xf); |
1443 | goto end; |
1886 | goto end; |
Line 1467... | Line 1910... | ||
1467 | 1910 | ||
1468 | /* driver figures it out in this case */ |
1911 | /* driver figures it out in this case */ |
1469 | info->bpc = 0; |
1912 | info->bpc = 0; |
Line 1470... | Line -... | ||
1470 | info->color_formats = 0; |
- | |
1471 | 1913 | info->color_formats = 0; |
|
1472 | /* Only defined for 1.4 with digital displays */ |
1914 | |
Line 1473... | Line 1915... | ||
1473 | if (edid->revision < 4) |
1915 | if (edid->revision < 3) |
1474 | return; |
1916 | return; |
Line -... | Line 1917... | ||
- | 1917 | ||
- | 1918 | if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) |
|
- | 1919 | return; |
|
- | 1920 | ||
- | 1921 | /* Get data from CEA blocks if present */ |
|
- | 1922 | edid_ext = drm_find_cea_extension(edid); |
|
- | 1923 | if (edid_ext) { |
|
- | 1924 | info->cea_rev = edid_ext[1]; |
|
- | 1925 | ||
- | 1926 | /* The existence of a CEA block should imply RGB support */ |
|
- | 1927 | info->color_formats = DRM_COLOR_FORMAT_RGB444; |
|
- | 1928 | if (edid_ext[3] & EDID_CEA_YCRCB444) |
|
- | 1929 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; |
|
- | 1930 | if (edid_ext[3] & EDID_CEA_YCRCB422) |
|
- | 1931 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; |
|
- | 1932 | } |
|
- | 1933 | ||
1475 | 1934 | /* Only defined for 1.4 with digital displays */ |
|
1476 | if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) |
1935 | if (edid->revision < 4) |
1477 | return; |
1936 | return; |
1478 | 1937 | ||
1479 | switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) { |
1938 | switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) { |
Line 1499... | Line 1958... | ||
1499 | default: |
1958 | default: |
1500 | info->bpc = 0; |
1959 | info->bpc = 0; |
1501 | break; |
1960 | break; |
1502 | } |
1961 | } |
Line 1503... | Line 1962... | ||
1503 | 1962 | ||
1504 | info->color_formats = DRM_COLOR_FORMAT_RGB444; |
1963 | info->color_formats |= DRM_COLOR_FORMAT_RGB444; |
1505 | if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB444) |
1964 | if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) |
1506 | info->color_formats = DRM_COLOR_FORMAT_YCRCB444; |
1965 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; |
1507 | if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB422) |
1966 | if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) |
1508 | info->color_formats = DRM_COLOR_FORMAT_YCRCB422; |
- | |
1509 | - | ||
1510 | /* Get data from CEA blocks if present */ |
- | |
1511 | edid_ext = drm_find_cea_extension(edid); |
- | |
1512 | if (!edid_ext) |
- | |
1513 | return; |
- | |
1514 | - | ||
1515 | info->cea_rev = edid_ext[1]; |
1967 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; |
Line 1516... | Line 1968... | ||
1516 | } |
1968 | } |
1517 | 1969 | ||
1518 | /** |
1970 | /** |
Line 1557... | Line 2009... | ||
1557 | num_modes += add_detailed_modes(connector, edid, quirks); |
2009 | num_modes += add_detailed_modes(connector, edid, quirks); |
1558 | num_modes += add_cvt_modes(connector, edid); |
2010 | num_modes += add_cvt_modes(connector, edid); |
1559 | num_modes += add_standard_modes(connector, edid); |
2011 | num_modes += add_standard_modes(connector, edid); |
1560 | num_modes += add_established_modes(connector, edid); |
2012 | num_modes += add_established_modes(connector, edid); |
1561 | num_modes += add_inferred_modes(connector, edid); |
2013 | num_modes += add_inferred_modes(connector, edid); |
- | 2014 | num_modes += add_cea_modes(connector, edid); |
|
Line 1562... | Line 2015... | ||
1562 | 2015 | ||
1563 | if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) |
2016 | if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) |
Line 1564... | Line 2017... | ||
1564 | edid_fixup_preferred(connector, quirks); |
2017 | edid_fixup_preferred(connector, quirks); |