Rev 4560 | Rev 5271 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4560 | Rev 5060 | ||
---|---|---|---|
Line 33... | Line 33... | ||
33 | #include |
33 | #include |
34 | #include |
34 | #include |
35 | #include |
35 | #include |
36 | #include |
36 | #include |
37 | #include |
37 | #include |
- | 38 | #include |
|
- | 39 | ||
- | 40 | #include "drm_crtc_internal.h" |
|
Line 38... | Line 41... | ||
38 | 41 | ||
39 | /** |
42 | /** |
40 | * drm_mode_debug_printmodeline - debug print a mode |
- | |
41 | * @dev: DRM device |
43 | * drm_mode_debug_printmodeline - print a mode to dmesg |
42 | * @mode: mode to print |
44 | * @mode: mode to print |
43 | * |
- | |
44 | * LOCKING: |
- | |
45 | * None. |
- | |
46 | * |
45 | * |
47 | * Describe @mode using DRM_DEBUG. |
46 | * Describe @mode using DRM_DEBUG. |
48 | */ |
47 | */ |
49 | void drm_mode_debug_printmodeline(const struct drm_display_mode *mode) |
48 | void drm_mode_debug_printmodeline(const struct drm_display_mode *mode) |
50 | { |
49 | { |
Line 57... | Line 56... | ||
57 | mode->vsync_end, mode->vtotal, mode->type, mode->flags); |
56 | mode->vsync_end, mode->vtotal, mode->type, mode->flags); |
58 | } |
57 | } |
59 | EXPORT_SYMBOL(drm_mode_debug_printmodeline); |
58 | EXPORT_SYMBOL(drm_mode_debug_printmodeline); |
Line 60... | Line 59... | ||
60 | 59 | ||
61 | /** |
60 | /** |
62 | * drm_cvt_mode -create a modeline based on CVT algorithm |
61 | * drm_mode_create - create a new display mode |
- | 62 | * @dev: DRM device |
|
- | 63 | * |
|
- | 64 | * Create a new, cleared drm_display_mode with kzalloc, allocate an ID for it |
|
- | 65 | * and return it. |
|
- | 66 | * |
|
- | 67 | * Returns: |
|
- | 68 | * Pointer to new mode on success, NULL on error. |
|
- | 69 | */ |
|
- | 70 | struct drm_display_mode *drm_mode_create(struct drm_device *dev) |
|
- | 71 | { |
|
- | 72 | struct drm_display_mode *nmode; |
|
- | 73 | ||
- | 74 | nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); |
|
- | 75 | if (!nmode) |
|
- | 76 | return NULL; |
|
- | 77 | ||
- | 78 | if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) { |
|
- | 79 | kfree(nmode); |
|
- | 80 | return NULL; |
|
- | 81 | } |
|
- | 82 | ||
- | 83 | return nmode; |
|
- | 84 | } |
|
- | 85 | EXPORT_SYMBOL(drm_mode_create); |
|
- | 86 | ||
- | 87 | /** |
|
- | 88 | * drm_mode_destroy - remove a mode |
|
- | 89 | * @dev: DRM device |
|
- | 90 | * @mode: mode to remove |
|
- | 91 | * |
|
- | 92 | * Release @mode's unique ID, then free it @mode structure itself using kfree. |
|
- | 93 | */ |
|
- | 94 | void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) |
|
- | 95 | { |
|
- | 96 | if (!mode) |
|
- | 97 | return; |
|
- | 98 | ||
- | 99 | drm_mode_object_put(dev, &mode->base); |
|
- | 100 | ||
- | 101 | kfree(mode); |
|
- | 102 | } |
|
- | 103 | EXPORT_SYMBOL(drm_mode_destroy); |
|
- | 104 | ||
- | 105 | /** |
|
- | 106 | * drm_mode_probed_add - add a mode to a connector's probed_mode list |
|
- | 107 | * @connector: connector the new mode |
|
- | 108 | * @mode: mode data |
|
- | 109 | * |
|
- | 110 | * Add @mode to @connector's probed_mode list for later use. This list should |
|
- | 111 | * then in a second step get filtered and all the modes actually supported by |
|
- | 112 | * the hardware moved to the @connector's modes list. |
|
- | 113 | */ |
|
- | 114 | void drm_mode_probed_add(struct drm_connector *connector, |
|
- | 115 | struct drm_display_mode *mode) |
|
- | 116 | { |
|
- | 117 | WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex)); |
|
- | 118 | ||
- | 119 | list_add_tail(&mode->head, &connector->probed_modes); |
|
- | 120 | } |
|
- | 121 | EXPORT_SYMBOL(drm_mode_probed_add); |
|
- | 122 | ||
- | 123 | /** |
|
- | 124 | * drm_cvt_mode -create a modeline based on the CVT algorithm |
|
63 | * @dev: DRM device |
125 | * @dev: drm device |
64 | * @hdisplay: hdisplay size |
126 | * @hdisplay: hdisplay size |
65 | * @vdisplay: vdisplay size |
127 | * @vdisplay: vdisplay size |
66 | * @vrefresh : vrefresh rate |
128 | * @vrefresh: vrefresh rate |
67 | * @reduced : Whether the GTF calculation is simplified |
129 | * @reduced: whether to use reduced blanking |
68 | * @interlaced:Whether the interlace is supported |
- | |
69 | * |
- | |
70 | * LOCKING: |
- | |
71 | * none. |
- | |
72 | * |
130 | * @interlaced: whether to compute an interlaced mode |
73 | * return the modeline based on CVT algorithm |
131 | * @margins: whether to add margins (borders) |
74 | * |
132 | * |
75 | * This function is called to generate the modeline based on CVT algorithm |
133 | * This function is called to generate the modeline based on CVT algorithm |
76 | * according to the hdisplay, vdisplay, vrefresh. |
134 | * according to the hdisplay, vdisplay, vrefresh. |
77 | * It is based from the VESA(TM) Coordinated Video Timing Generator by |
135 | * It is based from the VESA(TM) Coordinated Video Timing Generator by |
78 | * Graham Loveridge April 9, 2003 available at |
136 | * Graham Loveridge April 9, 2003 available at |
79 | * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls |
137 | * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls |
80 | * |
138 | * |
81 | * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c. |
139 | * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c. |
- | 140 | * What I have done is to translate it by using integer calculation. |
|
- | 141 | * |
|
- | 142 | * Returns: |
|
- | 143 | * The modeline based on the CVT algorithm stored in a drm_display_mode object. |
|
- | 144 | * The display mode object is allocated with drm_mode_create(). Returns NULL |
|
82 | * What I have done is to translate it by using integer calculation. |
145 | * when no mode could be allocated. |
83 | */ |
- | |
84 | #define HV_FACTOR 1000 |
146 | */ |
85 | struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, |
147 | struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, |
86 | int vdisplay, int vrefresh, |
148 | int vdisplay, int vrefresh, |
87 | bool reduced, bool interlaced, bool margins) |
149 | bool reduced, bool interlaced, bool margins) |
- | 150 | { |
|
88 | { |
151 | #define HV_FACTOR 1000 |
89 | /* 1) top/bottom margin size (% of height) - default: 1.8, */ |
152 | /* 1) top/bottom margin size (% of height) - default: 1.8, */ |
90 | #define CVT_MARGIN_PERCENTAGE 18 |
153 | #define CVT_MARGIN_PERCENTAGE 18 |
91 | /* 2) character cell horizontal granularity (pixels) - default 8 */ |
154 | /* 2) character cell horizontal granularity (pixels) - default 8 */ |
92 | #define CVT_H_GRANULARITY 8 |
155 | #define CVT_H_GRANULARITY 8 |
Line 277... | Line 340... | ||
277 | return drm_mode; |
340 | return drm_mode; |
278 | } |
341 | } |
279 | EXPORT_SYMBOL(drm_cvt_mode); |
342 | EXPORT_SYMBOL(drm_cvt_mode); |
Line 280... | Line 343... | ||
280 | 343 | ||
281 | /** |
344 | /** |
282 | * drm_gtf_mode_complex - create the modeline based on full GTF algorithm |
- | |
283 | * |
345 | * drm_gtf_mode_complex - create the modeline based on the full GTF algorithm |
284 | * @dev :drm device |
346 | * @dev: drm device |
285 | * @hdisplay :hdisplay size |
347 | * @hdisplay: hdisplay size |
286 | * @vdisplay :vdisplay size |
348 | * @vdisplay: vdisplay size |
287 | * @vrefresh :vrefresh rate. |
349 | * @vrefresh: vrefresh rate. |
288 | * @interlaced :whether the interlace is supported |
350 | * @interlaced: whether to compute an interlaced mode |
289 | * @margins :desired margin size |
351 | * @margins: desired margin (borders) size |
290 | * @GTF_[MCKJ] :extended GTF formula parameters |
- | |
291 | * |
352 | * @GTF_M: extended GTF formula parameters |
292 | * LOCKING. |
353 | * @GTF_2C: extended GTF formula parameters |
293 | * none. |
- | |
294 | * |
354 | * @GTF_K: extended GTF formula parameters |
295 | * return the modeline based on full GTF algorithm. |
355 | * @GTF_2J: extended GTF formula parameters |
296 | * |
356 | * |
297 | * GTF feature blocks specify C and J in multiples of 0.5, so we pass them |
357 | * GTF feature blocks specify C and J in multiples of 0.5, so we pass them |
- | 358 | * in here multiplied by two. For a C of 40, pass in 80. |
|
- | 359 | * |
|
- | 360 | * Returns: |
|
- | 361 | * The modeline based on the full GTF algorithm stored in a drm_display_mode object. |
|
- | 362 | * The display mode object is allocated with drm_mode_create(). Returns NULL |
|
298 | * in here multiplied by two. For a C of 40, pass in 80. |
363 | * when no mode could be allocated. |
299 | */ |
364 | */ |
300 | struct drm_display_mode * |
365 | struct drm_display_mode * |
301 | drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay, |
366 | drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay, |
302 | int vrefresh, bool interlaced, int margins, |
367 | int vrefresh, bool interlaced, int margins, |
Line 463... | Line 528... | ||
463 | return drm_mode; |
528 | return drm_mode; |
464 | } |
529 | } |
465 | EXPORT_SYMBOL(drm_gtf_mode_complex); |
530 | EXPORT_SYMBOL(drm_gtf_mode_complex); |
Line 466... | Line 531... | ||
466 | 531 | ||
467 | /** |
532 | /** |
468 | * drm_gtf_mode - create the modeline based on GTF algorithm |
- | |
469 | * |
533 | * drm_gtf_mode - create the modeline based on the GTF algorithm |
470 | * @dev :drm device |
534 | * @dev: drm device |
471 | * @hdisplay :hdisplay size |
535 | * @hdisplay: hdisplay size |
472 | * @vdisplay :vdisplay size |
536 | * @vdisplay: vdisplay size |
473 | * @vrefresh :vrefresh rate. |
537 | * @vrefresh: vrefresh rate. |
474 | * @interlaced :whether the interlace is supported |
538 | * @interlaced: whether to compute an interlaced mode |
475 | * @margins :whether the margin is supported |
- | |
476 | * |
- | |
477 | * LOCKING. |
- | |
478 | * none. |
539 | * @margins: desired margin (borders) size |
479 | * |
540 | * |
480 | * return the modeline based on GTF algorithm |
541 | * return the modeline based on GTF algorithm |
481 | * |
542 | * |
482 | * This function is to create the modeline based on the GTF algorithm. |
543 | * This function is to create the modeline based on the GTF algorithm. |
Line 492... | Line 553... | ||
492 | * Standard GTF parameters: |
553 | * Standard GTF parameters: |
493 | * M = 600 |
554 | * M = 600 |
494 | * C = 40 |
555 | * C = 40 |
495 | * K = 128 |
556 | * K = 128 |
496 | * J = 20 |
557 | * J = 20 |
- | 558 | * |
|
- | 559 | * Returns: |
|
- | 560 | * The modeline based on the GTF algorithm stored in a drm_display_mode object. |
|
- | 561 | * The display mode object is allocated with drm_mode_create(). Returns NULL |
|
- | 562 | * when no mode could be allocated. |
|
497 | */ |
563 | */ |
498 | struct drm_display_mode * |
564 | struct drm_display_mode * |
499 | drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, |
565 | drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, |
500 | bool lace, int margins) |
566 | bool interlaced, int margins) |
501 | { |
567 | { |
502 | return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh, lace, |
568 | return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh, |
- | 569 | interlaced, margins, |
|
503 | margins, 600, 40 * 2, 128, 20 * 2); |
570 | 600, 40 * 2, 128, 20 * 2); |
504 | } |
571 | } |
505 | EXPORT_SYMBOL(drm_gtf_mode); |
572 | EXPORT_SYMBOL(drm_gtf_mode); |
Line 506... | Line 573... | ||
506 | 573 | ||
- | 574 | #ifdef CONFIG_VIDEOMODE_HELPERS |
|
- | 575 | /** |
|
- | 576 | * drm_display_mode_from_videomode - fill in @dmode using @vm, |
|
- | 577 | * @vm: videomode structure to use as source |
|
- | 578 | * @dmode: drm_display_mode structure to use as destination |
|
- | 579 | * |
|
- | 580 | * Fills out @dmode using the display mode specified in @vm. |
|
507 | #ifdef CONFIG_VIDEOMODE_HELPERS |
581 | */ |
508 | int drm_display_mode_from_videomode(const struct videomode *vm, |
582 | void drm_display_mode_from_videomode(const struct videomode *vm, |
509 | struct drm_display_mode *dmode) |
583 | struct drm_display_mode *dmode) |
510 | { |
584 | { |
511 | dmode->hdisplay = vm->hactive; |
585 | dmode->hdisplay = vm->hactive; |
512 | dmode->hsync_start = dmode->hdisplay + vm->hfront_porch; |
586 | dmode->hsync_start = dmode->hdisplay + vm->hfront_porch; |
Line 534... | Line 608... | ||
534 | if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN) |
608 | if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN) |
535 | dmode->flags |= DRM_MODE_FLAG_DBLSCAN; |
609 | dmode->flags |= DRM_MODE_FLAG_DBLSCAN; |
536 | if (vm->flags & DISPLAY_FLAGS_DOUBLECLK) |
610 | if (vm->flags & DISPLAY_FLAGS_DOUBLECLK) |
537 | dmode->flags |= DRM_MODE_FLAG_DBLCLK; |
611 | dmode->flags |= DRM_MODE_FLAG_DBLCLK; |
538 | drm_mode_set_name(dmode); |
612 | drm_mode_set_name(dmode); |
539 | - | ||
540 | return 0; |
- | |
541 | } |
613 | } |
542 | EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode); |
614 | EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode); |
Line 543... | Line 615... | ||
543 | 615 | ||
544 | #ifdef CONFIG_OF |
616 | #ifdef CONFIG_OF |
Line 549... | Line 621... | ||
549 | * @index: index into the list of display timings in devicetree |
621 | * @index: index into the list of display timings in devicetree |
550 | * |
622 | * |
551 | * This function is expensive and should only be used, if only one mode is to be |
623 | * This function is expensive and should only be used, if only one mode is to be |
552 | * read from DT. To get multiple modes start with of_get_display_timings and |
624 | * read from DT. To get multiple modes start with of_get_display_timings and |
553 | * work with that instead. |
625 | * work with that instead. |
- | 626 | * |
|
- | 627 | * Returns: |
|
- | 628 | * 0 on success, a negative errno code when no of videomode node was found. |
|
554 | */ |
629 | */ |
555 | int of_get_drm_display_mode(struct device_node *np, |
630 | int of_get_drm_display_mode(struct device_node *np, |
556 | struct drm_display_mode *dmode, int index) |
631 | struct drm_display_mode *dmode, int index) |
557 | { |
632 | { |
558 | struct videomode vm; |
633 | struct videomode vm; |
Line 576... | Line 651... | ||
576 | 651 | ||
577 | /** |
652 | /** |
578 | * drm_mode_set_name - set the name on a mode |
653 | * drm_mode_set_name - set the name on a mode |
579 | * @mode: name will be set in this mode |
654 | * @mode: name will be set in this mode |
580 | * |
- | |
581 | * LOCKING: |
- | |
582 | * None. |
- | |
583 | * |
655 | * |
- | 656 | * Set the name of @mode to a standard format which is |
|
584 | * Set the name of @mode to a standard format. |
657 | * with an optional 'i' suffix for interlaced modes. |
585 | */ |
658 | */ |
586 | void drm_mode_set_name(struct drm_display_mode *mode) |
659 | void drm_mode_set_name(struct drm_display_mode *mode) |
587 | { |
660 | { |
Line 591... | Line 664... | ||
591 | mode->hdisplay, mode->vdisplay, |
664 | mode->hdisplay, mode->vdisplay, |
592 | interlaced ? "i" : ""); |
665 | interlaced ? "i" : ""); |
593 | } |
666 | } |
594 | EXPORT_SYMBOL(drm_mode_set_name); |
667 | EXPORT_SYMBOL(drm_mode_set_name); |
Line 595... | Line -... | ||
595 | - | ||
596 | /** |
- | |
597 | * drm_mode_width - get the width of a mode |
- | |
598 | * @mode: mode |
- | |
599 | * |
- | |
600 | * LOCKING: |
- | |
601 | * None. |
- | |
602 | * |
- | |
603 | * Return @mode's width (hdisplay) value. |
- | |
604 | * |
- | |
605 | * FIXME: is this needed? |
- | |
606 | * |
- | |
607 | * RETURNS: |
- | |
608 | * @mode->hdisplay |
- | |
609 | */ |
- | |
610 | int drm_mode_width(const struct drm_display_mode *mode) |
- | |
611 | { |
- | |
612 | return mode->hdisplay; |
- | |
613 | - | ||
614 | } |
- | |
615 | EXPORT_SYMBOL(drm_mode_width); |
- | |
616 | - | ||
617 | /** |
- | |
618 | * drm_mode_height - get the height of a mode |
- | |
619 | * @mode: mode |
- | |
620 | * |
- | |
621 | * LOCKING: |
- | |
622 | * None. |
- | |
623 | * |
- | |
624 | * Return @mode's height (vdisplay) value. |
- | |
625 | * |
- | |
626 | * FIXME: is this needed? |
- | |
627 | * |
- | |
628 | * RETURNS: |
- | |
629 | * @mode->vdisplay |
- | |
630 | */ |
- | |
631 | int drm_mode_height(const struct drm_display_mode *mode) |
- | |
632 | { |
- | |
633 | return mode->vdisplay; |
- | |
634 | } |
- | |
635 | EXPORT_SYMBOL(drm_mode_height); |
- | |
636 | 668 | ||
637 | /** drm_mode_hsync - get the hsync of a mode |
669 | /** drm_mode_hsync - get the hsync of a mode |
638 | * @mode: mode |
670 | * @mode: mode |
639 | * |
671 | * |
640 | * LOCKING: |
- | |
641 | * None. |
- | |
642 | * |
672 | * Returns: |
- | 673 | * @modes's hsync rate in kHz, rounded to the nearest integer. Calculates the |
|
643 | * Return @modes's hsync rate in kHz, rounded to the nearest int. |
674 | * value first if it is not yet set. |
644 | */ |
675 | */ |
645 | int drm_mode_hsync(const struct drm_display_mode *mode) |
676 | int drm_mode_hsync(const struct drm_display_mode *mode) |
646 | { |
677 | { |
Line 662... | Line 693... | ||
662 | 693 | ||
663 | /** |
694 | /** |
664 | * drm_mode_vrefresh - get the vrefresh of a mode |
695 | * drm_mode_vrefresh - get the vrefresh of a mode |
665 | * @mode: mode |
696 | * @mode: mode |
666 | * |
- | |
667 | * LOCKING: |
- | |
668 | * None. |
- | |
669 | * |
- | |
670 | * Return @mode's vrefresh rate in Hz or calculate it if necessary. |
- | |
671 | * |
- | |
672 | * FIXME: why is this needed? shouldn't vrefresh be set already? |
- | |
673 | * |
697 | * |
674 | * RETURNS: |
698 | * Returns: |
675 | * Vertical refresh rate. It will be the result of actual value plus 0.5. |
- | |
676 | * If it is 70.288, it will return 70Hz. |
699 | * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the |
677 | * If it is 59.6, it will return 60Hz. |
700 | * value first if it is not yet set. |
678 | */ |
701 | */ |
679 | int drm_mode_vrefresh(const struct drm_display_mode *mode) |
702 | int drm_mode_vrefresh(const struct drm_display_mode *mode) |
680 | { |
703 | { |
681 | int refresh = 0; |
704 | int refresh = 0; |
Line 701... | Line 724... | ||
701 | return refresh; |
724 | return refresh; |
702 | } |
725 | } |
703 | EXPORT_SYMBOL(drm_mode_vrefresh); |
726 | EXPORT_SYMBOL(drm_mode_vrefresh); |
Line 704... | Line 727... | ||
704 | 727 | ||
705 | /** |
728 | /** |
706 | * drm_mode_set_crtcinfo - set CRTC modesetting parameters |
729 | * drm_mode_set_crtcinfo - set CRTC modesetting timing parameters |
707 | * @p: mode |
730 | * @p: mode |
708 | * @adjust_flags: a combination of adjustment flags |
731 | * @adjust_flags: a combination of adjustment flags |
709 | * |
- | |
710 | * LOCKING: |
- | |
711 | * None. |
- | |
712 | * |
732 | * |
713 | * Setup the CRTC modesetting parameters for @p, adjusting if necessary. |
733 | * Setup the CRTC modesetting timing parameters for @p, adjusting if necessary. |
714 | * |
734 | * |
715 | * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of |
735 | * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of |
716 | * interlaced modes. |
736 | * interlaced modes. |
717 | * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for |
737 | * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for |
Line 776... | Line 796... | ||
776 | p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay); |
796 | p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay); |
777 | p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal); |
797 | p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal); |
778 | } |
798 | } |
779 | EXPORT_SYMBOL(drm_mode_set_crtcinfo); |
799 | EXPORT_SYMBOL(drm_mode_set_crtcinfo); |
Line 780... | Line -... | ||
780 | - | ||
781 | 800 | ||
782 | /** |
801 | /** |
783 | * drm_mode_copy - copy the mode |
802 | * drm_mode_copy - copy the mode |
784 | * @dst: mode to overwrite |
803 | * @dst: mode to overwrite |
785 | * @src: mode to copy |
804 | * @src: mode to copy |
786 | * |
- | |
787 | * LOCKING: |
- | |
788 | * None. |
- | |
789 | * |
805 | * |
790 | * Copy an existing mode into another mode, preserving the object id and |
806 | * Copy an existing mode into another mode, preserving the object id and |
791 | * list head of the destination mode. |
807 | * list head of the destination mode. |
792 | */ |
808 | */ |
793 | void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src) |
809 | void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src) |
Line 801... | Line 817... | ||
801 | } |
817 | } |
802 | EXPORT_SYMBOL(drm_mode_copy); |
818 | EXPORT_SYMBOL(drm_mode_copy); |
Line 803... | Line 819... | ||
803 | 819 | ||
804 | /** |
820 | /** |
- | 821 | * drm_mode_duplicate - allocate and duplicate an existing mode |
|
805 | * drm_mode_duplicate - allocate and duplicate an existing mode |
822 | * @dev: drm_device to allocate the duplicated mode for |
806 | * @m: mode to duplicate |
- | |
807 | * |
- | |
808 | * LOCKING: |
- | |
809 | * None. |
823 | * @mode: mode to duplicate |
810 | * |
824 | * |
811 | * Just allocate a new mode, copy the existing mode into it, and return |
825 | * Just allocate a new mode, copy the existing mode into it, and return |
- | 826 | * a pointer to it. Used to create new instances of established modes. |
|
- | 827 | * |
|
- | 828 | * Returns: |
|
812 | * a pointer to it. Used to create new instances of established modes. |
829 | * Pointer to duplicated mode on success, NULL on error. |
813 | */ |
830 | */ |
814 | struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, |
831 | struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, |
815 | const struct drm_display_mode *mode) |
832 | const struct drm_display_mode *mode) |
816 | { |
833 | { |
Line 829... | Line 846... | ||
829 | /** |
846 | /** |
830 | * drm_mode_equal - test modes for equality |
847 | * drm_mode_equal - test modes for equality |
831 | * @mode1: first mode |
848 | * @mode1: first mode |
832 | * @mode2: second mode |
849 | * @mode2: second mode |
833 | * |
850 | * |
834 | * LOCKING: |
- | |
835 | * None. |
- | |
836 | * |
- | |
837 | * Check to see if @mode1 and @mode2 are equivalent. |
851 | * Check to see if @mode1 and @mode2 are equivalent. |
838 | * |
852 | * |
839 | * RETURNS: |
853 | * Returns: |
840 | * True if the modes are equal, false otherwise. |
854 | * True if the modes are equal, false otherwise. |
841 | */ |
855 | */ |
842 | bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2) |
856 | bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2) |
843 | { |
857 | { |
844 | /* do clock check convert to PICOS so fb modes get matched |
858 | /* do clock check convert to PICOS so fb modes get matched |
Line 860... | Line 874... | ||
860 | /** |
874 | /** |
861 | * drm_mode_equal_no_clocks_no_stereo - test modes for equality |
875 | * drm_mode_equal_no_clocks_no_stereo - test modes for equality |
862 | * @mode1: first mode |
876 | * @mode1: first mode |
863 | * @mode2: second mode |
877 | * @mode2: second mode |
864 | * |
878 | * |
865 | * LOCKING: |
- | |
866 | * None. |
- | |
867 | * |
- | |
868 | * Check to see if @mode1 and @mode2 are equivalent, but |
879 | * Check to see if @mode1 and @mode2 are equivalent, but |
869 | * don't check the pixel clocks nor the stereo layout. |
880 | * don't check the pixel clocks nor the stereo layout. |
870 | * |
881 | * |
871 | * RETURNS: |
882 | * Returns: |
872 | * True if the modes are equal, false otherwise. |
883 | * True if the modes are equal, false otherwise. |
873 | */ |
884 | */ |
874 | bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, |
885 | bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, |
875 | const struct drm_display_mode *mode2) |
886 | const struct drm_display_mode *mode2) |
876 | { |
887 | { |
Line 896... | Line 907... | ||
896 | * drm_mode_validate_size - make sure modes adhere to size constraints |
907 | * drm_mode_validate_size - make sure modes adhere to size constraints |
897 | * @dev: DRM device |
908 | * @dev: DRM device |
898 | * @mode_list: list of modes to check |
909 | * @mode_list: list of modes to check |
899 | * @maxX: maximum width |
910 | * @maxX: maximum width |
900 | * @maxY: maximum height |
911 | * @maxY: maximum height |
901 | * @maxPitch: max pitch |
- | |
902 | * |
912 | * |
903 | * LOCKING: |
- | |
904 | * Caller must hold a lock protecting @mode_list. |
913 | * This function is a helper which can be used to validate modes against size |
905 | * |
- | |
906 | * The DRM device (@dev) has size and pitch limits. Here we validate the |
914 | * limitations of the DRM device/connector. If a mode is too big its status |
907 | * modes we probed for @dev against those limits and set their status as |
915 | * memeber is updated with the appropriate validation failure code. The list |
908 | * necessary. |
916 | * itself is not changed. |
909 | */ |
917 | */ |
910 | void drm_mode_validate_size(struct drm_device *dev, |
918 | void drm_mode_validate_size(struct drm_device *dev, |
911 | struct list_head *mode_list, |
919 | struct list_head *mode_list, |
912 | int maxX, int maxY, int maxPitch) |
920 | int maxX, int maxY) |
913 | { |
921 | { |
914 | struct drm_display_mode *mode; |
922 | struct drm_display_mode *mode; |
Line 915... | Line 923... | ||
915 | 923 | ||
916 | list_for_each_entry(mode, mode_list, head) { |
- | |
917 | if (maxPitch > 0 && mode->hdisplay > maxPitch) |
- | |
918 | mode->status = MODE_BAD_WIDTH; |
- | |
919 | 924 | list_for_each_entry(mode, mode_list, head) { |
|
920 | if (maxX > 0 && mode->hdisplay > maxX) |
925 | if (maxX > 0 && mode->hdisplay > maxX) |
Line 921... | Line 926... | ||
921 | mode->status = MODE_VIRTUAL_X; |
926 | mode->status = MODE_VIRTUAL_X; |
922 | 927 | ||
Line 930... | Line 935... | ||
930 | * drm_mode_prune_invalid - remove invalid modes from mode list |
935 | * drm_mode_prune_invalid - remove invalid modes from mode list |
931 | * @dev: DRM device |
936 | * @dev: DRM device |
932 | * @mode_list: list of modes to check |
937 | * @mode_list: list of modes to check |
933 | * @verbose: be verbose about it |
938 | * @verbose: be verbose about it |
934 | * |
939 | * |
935 | * LOCKING: |
- | |
936 | * Caller must hold a lock protecting @mode_list. |
940 | * This helper function can be used to prune a display mode list after |
937 | * |
- | |
938 | * Once mode list generation is complete, a caller can use this routine to |
941 | * validation has been completed. All modes who's status is not MODE_OK will be |
939 | * remove invalid modes from a mode list. If any of the modes have a |
942 | * removed from the list, and if @verbose the status code and mode name is also |
940 | * status other than %MODE_OK, they are removed from @mode_list and freed. |
943 | * printed to dmesg. |
941 | */ |
944 | */ |
942 | void drm_mode_prune_invalid(struct drm_device *dev, |
945 | void drm_mode_prune_invalid(struct drm_device *dev, |
943 | struct list_head *mode_list, bool verbose) |
946 | struct list_head *mode_list, bool verbose) |
944 | { |
947 | { |
945 | struct drm_display_mode *mode, *t; |
948 | struct drm_display_mode *mode, *t; |
Line 962... | Line 965... | ||
962 | * drm_mode_compare - compare modes for favorability |
965 | * drm_mode_compare - compare modes for favorability |
963 | * @priv: unused |
966 | * @priv: unused |
964 | * @lh_a: list_head for first mode |
967 | * @lh_a: list_head for first mode |
965 | * @lh_b: list_head for second mode |
968 | * @lh_b: list_head for second mode |
966 | * |
969 | * |
967 | * LOCKING: |
- | |
968 | * None. |
- | |
969 | * |
- | |
970 | * Compare two modes, given by @lh_a and @lh_b, returning a value indicating |
970 | * Compare two modes, given by @lh_a and @lh_b, returning a value indicating |
971 | * which is better. |
971 | * which is better. |
972 | * |
972 | * |
973 | * RETURNS: |
973 | * Returns: |
974 | * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or |
974 | * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or |
975 | * positive if @lh_b is better than @lh_a. |
975 | * positive if @lh_b is better than @lh_a. |
976 | */ |
976 | */ |
977 | static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head *lh_b) |
977 | static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head *lh_b) |
978 | { |
978 | { |
Line 996... | Line 996... | ||
996 | return diff; |
996 | return diff; |
997 | } |
997 | } |
Line 998... | Line 998... | ||
998 | 998 | ||
999 | /** |
999 | /** |
1000 | * drm_mode_sort - sort mode list |
1000 | * drm_mode_sort - sort mode list |
1001 | * @mode_list: list to sort |
- | |
1002 | * |
- | |
1003 | * LOCKING: |
- | |
1004 | * Caller must hold a lock protecting @mode_list. |
1001 | * @mode_list: list of drm_display_mode structures to sort |
1005 | * |
1002 | * |
1006 | * Sort @mode_list by favorability, putting good modes first. |
1003 | * Sort @mode_list by favorability, moving good modes to the head of the list. |
1007 | */ |
1004 | */ |
1008 | void drm_mode_sort(struct list_head *mode_list) |
1005 | void drm_mode_sort(struct list_head *mode_list) |
1009 | { |
1006 | { |
1010 | list_sort(NULL, mode_list, drm_mode_compare); |
1007 | list_sort(NULL, mode_list, drm_mode_compare); |
1011 | } |
1008 | } |
Line 1012... | Line 1009... | ||
1012 | EXPORT_SYMBOL(drm_mode_sort); |
1009 | EXPORT_SYMBOL(drm_mode_sort); |
1013 | 1010 | ||
1014 | /** |
1011 | /** |
1015 | * drm_mode_connector_list_update - update the mode list for the connector |
- | |
1016 | * @connector: the connector to update |
- | |
1017 | * |
1012 | * drm_mode_connector_list_update - update the mode list for the connector |
1018 | * LOCKING: |
1013 | * @connector: the connector to update |
1019 | * Caller must hold a lock protecting @mode_list. |
1014 | * @merge_type_bits: whether to merge or overright type bits. |
1020 | * |
1015 | * |
1021 | * This moves the modes from the @connector probed_modes list |
1016 | * This moves the modes from the @connector probed_modes list |
- | 1017 | * to the actual mode list. It compares the probed mode against the current |
|
- | 1018 | * list and only adds different/new modes. |
|
1022 | * to the actual mode list. It compares the probed mode against the current |
1019 | * |
1023 | * list and only adds different modes. All modes unverified after this point |
1020 | * This is just a helper functions doesn't validate any modes itself and also |
1024 | * will be removed by the prune invalid modes. |
1021 | * doesn't prune any invalid modes. Callers need to do that themselves. |
- | 1022 | */ |
|
1025 | */ |
1023 | void drm_mode_connector_list_update(struct drm_connector *connector, |
1026 | void drm_mode_connector_list_update(struct drm_connector *connector) |
1024 | bool merge_type_bits) |
1027 | { |
1025 | { |
1028 | struct drm_display_mode *mode; |
1026 | struct drm_display_mode *mode; |
Line -... | Line 1027... | ||
- | 1027 | struct drm_display_mode *pmode, *pt; |
|
- | 1028 | int found_it; |
|
1029 | struct drm_display_mode *pmode, *pt; |
1029 | |
1030 | int found_it; |
1030 | WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex)); |
1031 | 1031 | ||
1032 | list_for_each_entry_safe(pmode, pt, &connector->probed_modes, |
1032 | list_for_each_entry_safe(pmode, pt, &connector->probed_modes, |
1033 | head) { |
1033 | head) { |
1034 | found_it = 0; |
1034 | found_it = 0; |
1035 | /* go through current modes checking for the new probed mode */ |
1035 | /* go through current modes checking for the new probed mode */ |
1036 | list_for_each_entry(mode, &connector->modes, head) { |
1036 | list_for_each_entry(mode, &connector->modes, head) { |
1037 | if (drm_mode_equal(pmode, mode)) { |
1037 | if (drm_mode_equal(pmode, mode)) { |
1038 | found_it = 1; |
1038 | found_it = 1; |
- | 1039 | /* if equal delete the probed mode */ |
|
1039 | /* if equal delete the probed mode */ |
1040 | mode->status = pmode->status; |
- | 1041 | /* Merge type bits together */ |
|
- | 1042 | if (merge_type_bits) |
|
1040 | mode->status = pmode->status; |
1043 | mode->type |= pmode->type; |
1041 | /* Merge type bits together */ |
1044 | else |
1042 | mode->type |= pmode->type; |
1045 | mode->type = pmode->type; |
1043 | list_del(&pmode->head); |
1046 | list_del(&pmode->head); |
1044 | drm_mode_destroy(connector->dev, pmode); |
1047 | drm_mode_destroy(connector->dev, pmode); |