diff options
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index d8da30e90db5..04fa6f1808d1 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #include <linux/export.h> | 35 | #include <linux/export.h> |
36 | #include <drm/drmP.h> | 36 | #include <drm/drmP.h> |
37 | #include <drm/drm_crtc.h> | 37 | #include <drm/drm_crtc.h> |
38 | #include <video/of_videomode.h> | ||
39 | #include <video/videomode.h> | ||
38 | 40 | ||
39 | /** | 41 | /** |
40 | * drm_mode_debug_printmodeline - debug print a mode | 42 | * drm_mode_debug_printmodeline - debug print a mode |
@@ -504,6 +506,74 @@ drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, | |||
504 | } | 506 | } |
505 | EXPORT_SYMBOL(drm_gtf_mode); | 507 | EXPORT_SYMBOL(drm_gtf_mode); |
506 | 508 | ||
509 | #if IS_ENABLED(CONFIG_VIDEOMODE) | ||
510 | int drm_display_mode_from_videomode(const struct videomode *vm, | ||
511 | struct drm_display_mode *dmode) | ||
512 | { | ||
513 | dmode->hdisplay = vm->hactive; | ||
514 | dmode->hsync_start = dmode->hdisplay + vm->hfront_porch; | ||
515 | dmode->hsync_end = dmode->hsync_start + vm->hsync_len; | ||
516 | dmode->htotal = dmode->hsync_end + vm->hback_porch; | ||
517 | |||
518 | dmode->vdisplay = vm->vactive; | ||
519 | dmode->vsync_start = dmode->vdisplay + vm->vfront_porch; | ||
520 | dmode->vsync_end = dmode->vsync_start + vm->vsync_len; | ||
521 | dmode->vtotal = dmode->vsync_end + vm->vback_porch; | ||
522 | |||
523 | dmode->clock = vm->pixelclock / 1000; | ||
524 | |||
525 | dmode->flags = 0; | ||
526 | if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH) | ||
527 | dmode->flags |= DRM_MODE_FLAG_PHSYNC; | ||
528 | else if (vm->dmt_flags & VESA_DMT_HSYNC_LOW) | ||
529 | dmode->flags |= DRM_MODE_FLAG_NHSYNC; | ||
530 | if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH) | ||
531 | dmode->flags |= DRM_MODE_FLAG_PVSYNC; | ||
532 | else if (vm->dmt_flags & VESA_DMT_VSYNC_LOW) | ||
533 | dmode->flags |= DRM_MODE_FLAG_NVSYNC; | ||
534 | if (vm->data_flags & DISPLAY_FLAGS_INTERLACED) | ||
535 | dmode->flags |= DRM_MODE_FLAG_INTERLACE; | ||
536 | if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN) | ||
537 | dmode->flags |= DRM_MODE_FLAG_DBLSCAN; | ||
538 | drm_mode_set_name(dmode); | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode); | ||
543 | #endif | ||
544 | |||
545 | #if IS_ENABLED(CONFIG_OF_VIDEOMODE) | ||
546 | /** | ||
547 | * of_get_drm_display_mode - get a drm_display_mode from devicetree | ||
548 | * @np: device_node with the timing specification | ||
549 | * @dmode: will be set to the return value | ||
550 | * @index: index into the list of display timings in devicetree | ||
551 | * | ||
552 | * This function is expensive and should only be used, if only one mode is to be | ||
553 | * read from DT. To get multiple modes start with of_get_display_timings and | ||
554 | * work with that instead. | ||
555 | */ | ||
556 | int of_get_drm_display_mode(struct device_node *np, | ||
557 | struct drm_display_mode *dmode, int index) | ||
558 | { | ||
559 | struct videomode vm; | ||
560 | int ret; | ||
561 | |||
562 | ret = of_get_videomode(np, &vm, index); | ||
563 | if (ret) | ||
564 | return ret; | ||
565 | |||
566 | drm_display_mode_from_videomode(&vm, dmode); | ||
567 | |||
568 | pr_debug("%s: got %dx%d display mode from %s\n", | ||
569 | of_node_full_name(np), vm.hactive, vm.vactive, np->name); | ||
570 | drm_mode_debug_printmodeline(dmode); | ||
571 | |||
572 | return 0; | ||
573 | } | ||
574 | EXPORT_SYMBOL_GPL(of_get_drm_display_mode); | ||
575 | #endif | ||
576 | |||
507 | /** | 577 | /** |
508 | * drm_mode_set_name - set the name on a mode | 578 | * drm_mode_set_name - set the name on a mode |
509 | * @mode: name will be set in this mode | 579 | * @mode: name will be set in this mode |