diff options
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 37 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.h | 3 |
3 files changed, 45 insertions, 0 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index cc85c16cbc2a..ae2e16ed3874 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <drm/drm_crtc_helper.h> | 23 | #include <drm/drm_crtc_helper.h> |
| 24 | #include <drm/drm_mode.h> | 24 | #include <drm/drm_mode.h> |
| 25 | #include <drm/drm_plane_helper.h> | 25 | #include <drm/drm_plane_helper.h> |
| 26 | #include <linux/math64.h> | ||
| 26 | 27 | ||
| 27 | #include "omap_drv.h" | 28 | #include "omap_drv.h" |
| 28 | 29 | ||
| @@ -400,6 +401,41 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc, | |||
| 400 | drm_crtc_vblank_off(crtc); | 401 | drm_crtc_vblank_off(crtc); |
| 401 | } | 402 | } |
| 402 | 403 | ||
| 404 | static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc, | ||
| 405 | const struct drm_display_mode *mode) | ||
| 406 | { | ||
| 407 | struct omap_drm_private *priv = crtc->dev->dev_private; | ||
| 408 | |||
| 409 | /* Check for bandwidth limit */ | ||
| 410 | if (priv->max_bandwidth) { | ||
| 411 | /* | ||
| 412 | * Estimation for the bandwidth need of a given mode with one | ||
| 413 | * full screen plane: | ||
| 414 | * bandwidth = resolution * 32bpp * (pclk / (vtotal * htotal)) | ||
| 415 | * ^^ Refresh rate ^^ | ||
| 416 | * | ||
| 417 | * The interlaced mode is taken into account by using the | ||
| 418 | * pixelclock in the calculation. | ||
| 419 | * | ||
| 420 | * The equation is rearranged for 64bit arithmetic. | ||
| 421 | */ | ||
| 422 | uint64_t bandwidth = mode->clock * 1000; | ||
| 423 | unsigned int bpp = 4; | ||
| 424 | |||
| 425 | bandwidth = bandwidth * mode->hdisplay * mode->vdisplay * bpp; | ||
| 426 | bandwidth = div_u64(bandwidth, mode->htotal * mode->vtotal); | ||
| 427 | |||
| 428 | /* | ||
| 429 | * Reject modes which would need more bandwidth if used with one | ||
| 430 | * full resolution plane (most common use case). | ||
| 431 | */ | ||
| 432 | if (priv->max_bandwidth < bandwidth) | ||
| 433 | return MODE_BAD; | ||
| 434 | } | ||
| 435 | |||
| 436 | return MODE_OK; | ||
| 437 | } | ||
| 438 | |||
| 403 | static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) | 439 | static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) |
| 404 | { | 440 | { |
| 405 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 441 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| @@ -621,6 +657,7 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { | |||
| 621 | .atomic_flush = omap_crtc_atomic_flush, | 657 | .atomic_flush = omap_crtc_atomic_flush, |
| 622 | .atomic_enable = omap_crtc_atomic_enable, | 658 | .atomic_enable = omap_crtc_atomic_enable, |
| 623 | .atomic_disable = omap_crtc_atomic_disable, | 659 | .atomic_disable = omap_crtc_atomic_disable, |
| 660 | .mode_valid = omap_crtc_mode_valid, | ||
| 624 | }; | 661 | }; |
| 625 | 662 | ||
| 626 | /* ----------------------------------------------------------------------------- | 663 | /* ----------------------------------------------------------------------------- |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 96857c508ee0..c4bb261dfcd9 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
| @@ -563,6 +563,11 @@ static int pdev_probe(struct platform_device *pdev) | |||
| 563 | ddev->dev_private = priv; | 563 | ddev->dev_private = priv; |
| 564 | platform_set_drvdata(pdev, ddev); | 564 | platform_set_drvdata(pdev, ddev); |
| 565 | 565 | ||
| 566 | /* Get memory bandwidth limits */ | ||
| 567 | if (priv->dispc_ops->get_memory_bandwidth_limit) | ||
| 568 | priv->max_bandwidth = | ||
| 569 | priv->dispc_ops->get_memory_bandwidth_limit(); | ||
| 570 | |||
| 566 | omap_gem_init(ddev); | 571 | omap_gem_init(ddev); |
| 567 | 572 | ||
| 568 | ret = omap_modeset_init(ddev); | 573 | ret = omap_modeset_init(ddev); |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 4bd1e9070b31..d404e8c56b61 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
| @@ -83,6 +83,9 @@ struct omap_drm_private { | |||
| 83 | spinlock_t wait_lock; /* protects the wait_list */ | 83 | spinlock_t wait_lock; /* protects the wait_list */ |
| 84 | struct list_head wait_list; /* list of omap_irq_wait */ | 84 | struct list_head wait_list; /* list of omap_irq_wait */ |
| 85 | uint32_t irq_mask; /* enabled irqs in addition to wait_list */ | 85 | uint32_t irq_mask; /* enabled irqs in addition to wait_list */ |
| 86 | |||
| 87 | /* memory bandwidth limit if it is needed on the platform */ | ||
| 88 | unsigned int max_bandwidth; | ||
| 86 | }; | 89 | }; |
| 87 | 90 | ||
| 88 | 91 | ||
