Hi,
Changes since v2: - Rebased on drm-next (v2 was based on drm-next and my 'drm/omap: Module parameter for display order configuration' series, thus it was not applying cleanly. - Added Acked-by from Rob to the dt-binding changes
Changes since v1: - Use the crtc->mode_valid and not connector->mode_valid as the limit is really posed by the 'crtc' (DISPC) - Bandwidth calculation changed: do the calculation in place + extended comment - looked for better place to document the max-memory-bandwidth, but can not find any suitable document. Creating a new txt file for only one property did not seemed feasable.
This series will add simple memory bandwidth limit support to reject modes which, if used with one plane in full size would fail the limit.
Regards, Peter --- Peter Ujfalusi (3): dt-bindings: display/ti: Add optional property to set memory bandwidth limit drm/omap: dss: Add support for reporting memory bandwidth limitation drm/omap: Filter displays mode based on bandwidth limit
.../devicetree/bindings/display/ti/ti,dra7-dss.txt | 5 +++ .../bindings/display/ti/ti,omap2-dss.txt | 4 +++ .../bindings/display/ti/ti,omap3-dss.txt | 4 +++ .../bindings/display/ti/ti,omap4-dss.txt | 4 +++ .../bindings/display/ti/ti,omap5-dss.txt | 4 +++ drivers/gpu/drm/omapdrm/dss/dispc.c | 13 ++++++++ drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 ++ drivers/gpu/drm/omapdrm/omap_crtc.c | 37 ++++++++++++++++++++++ drivers/gpu/drm/omapdrm/omap_drv.c | 5 +++ drivers/gpu/drm/omapdrm/omap_drv.h | 3 ++ 10 files changed, 81 insertions(+)
max-memory-bandwidth can be used to specify the maximum bandwidth dispc can use when reading display data from main memory.
In some SoC (am437x for example) we have memory bandwidth limitation which causes underflow in the display subsystem.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Acked-by: Rob Herring robh@kernel.org --- Documentation/devicetree/bindings/display/ti/ti,dra7-dss.txt | 5 +++++ Documentation/devicetree/bindings/display/ti/ti,omap2-dss.txt | 4 ++++ Documentation/devicetree/bindings/display/ti/ti,omap3-dss.txt | 4 ++++ Documentation/devicetree/bindings/display/ti/ti,omap4-dss.txt | 4 ++++ Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt | 4 ++++ 5 files changed, 21 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/ti/ti,dra7-dss.txt b/Documentation/devicetree/bindings/display/ti/ti,dra7-dss.txt index c30f9ec189ed..91279f1060fe 100644 --- a/Documentation/devicetree/bindings/display/ti/ti,dra7-dss.txt +++ b/Documentation/devicetree/bindings/display/ti/ti,dra7-dss.txt @@ -47,6 +47,11 @@ Required properties: - clocks: handle to fclk - clock-names: "fck"
+Optional properties: +- max-memory-bandwidth: Input memory (from main memory to dispc) bandwidth limit + in bytes per second + + HDMI ----
diff --git a/Documentation/devicetree/bindings/display/ti/ti,omap2-dss.txt b/Documentation/devicetree/bindings/display/ti/ti,omap2-dss.txt index afcd5a86c6a4..ee867c4d1152 100644 --- a/Documentation/devicetree/bindings/display/ti/ti,omap2-dss.txt +++ b/Documentation/devicetree/bindings/display/ti/ti,omap2-dss.txt @@ -28,6 +28,10 @@ Required properties: - ti,hwmods: "dss_dispc" - interrupts: the DISPC interrupt
+Optional properties: +- max-memory-bandwidth: Input memory (from main memory to dispc) bandwidth limit + in bytes per second +
RFBI ---- diff --git a/Documentation/devicetree/bindings/display/ti/ti,omap3-dss.txt b/Documentation/devicetree/bindings/display/ti/ti,omap3-dss.txt index dc66e1447c31..cd02516a40b6 100644 --- a/Documentation/devicetree/bindings/display/ti/ti,omap3-dss.txt +++ b/Documentation/devicetree/bindings/display/ti/ti,omap3-dss.txt @@ -37,6 +37,10 @@ Required properties: - clocks: handle to fclk - clock-names: "fck"
+Optional properties: +- max-memory-bandwidth: Input memory (from main memory to dispc) bandwidth limit + in bytes per second +
RFBI ---- diff --git a/Documentation/devicetree/bindings/display/ti/ti,omap4-dss.txt b/Documentation/devicetree/bindings/display/ti/ti,omap4-dss.txt index bc624db8888d..0f85f6b3a5a8 100644 --- a/Documentation/devicetree/bindings/display/ti/ti,omap4-dss.txt +++ b/Documentation/devicetree/bindings/display/ti/ti,omap4-dss.txt @@ -36,6 +36,10 @@ Required properties: - clocks: handle to fclk - clock-names: "fck"
+Optional properties: +- max-memory-bandwidth: Input memory (from main memory to dispc) bandwidth limit + in bytes per second +
RFBI ---- diff --git a/Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt b/Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt index 118a486c47bb..20861218649f 100644 --- a/Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt +++ b/Documentation/devicetree/bindings/display/ti/ti,omap5-dss.txt @@ -36,6 +36,10 @@ Required properties: - clocks: handle to fclk - clock-names: "fck"
+Optional properties: +- max-memory-bandwidth: Input memory (from main memory to dispc) bandwidth limit + in bytes per second +
RFBI ----
The get_memory_bandwidth_limit() in dispc_ops can be used to query the memory bandwidth limit of dispc by upper layers.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 13 +++++++++++++ drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 ++ 2 files changed, 15 insertions(+)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 0f4fdb221498..90f9ad89af0d 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -4325,6 +4325,17 @@ static void dispc_free_irq(void *dev_id) dispc.user_data = NULL; }
+static u32 dispc_get_memory_bandwidth_limit(void) +{ + u32 limit = 0; + + /* Optional maximum memory bandwidth */ + of_property_read_u32(dispc.pdev->dev.of_node, "max-memory-bandwidth", + &limit); + + return limit; +} + /* * Workaround for errata i734 in DSS dispc * - LCD1 Gamma Correction Is Not Working When GFX Pipe Is Disabled @@ -4497,6 +4508,8 @@ static const struct dispc_ops dispc_ops = { .get_num_ovls = dispc_get_num_ovls, .get_num_mgrs = dispc_get_num_mgrs,
+ .get_memory_bandwidth_limit = dispc_get_memory_bandwidth_limit, + .mgr_enable = dispc_mgr_enable, .mgr_is_enabled = dispc_mgr_is_enabled, .mgr_get_vsync_irq = dispc_mgr_get_vsync_irq, diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 990422b35784..c2166d2d3f29 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -695,6 +695,8 @@ struct dispc_ops { int (*get_num_ovls)(void); int (*get_num_mgrs)(void);
+ u32 (*get_memory_bandwidth_limit)(void); + void (*mgr_enable)(enum omap_channel channel, bool enable); bool (*mgr_is_enabled)(enum omap_channel channel); u32 (*mgr_get_vsync_irq)(enum omap_channel channel);
If we have memory bandwidth limit configured, reject the modes which would require more bandwidth than the limit if it is used with one full resolution plane (most common use case).
This filtering is not providing full protection as it is possible that application would pick smaller crtc resolution with high resolution planes and down scaling, or can enable more smaller planes where the sum of their bandwidth need would be higher than the limit.
This patch only allows us to filter out modes which would need more bandwidth if they were used with one full screen plane.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- drivers/gpu/drm/omapdrm/omap_crtc.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/omapdrm/omap_drv.c | 5 +++++ drivers/gpu/drm/omapdrm/omap_drv.h | 3 +++ 3 files changed, 45 insertions(+)
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 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_mode.h> #include <drm/drm_plane_helper.h> +#include <linux/math64.h>
#include "omap_drv.h"
@@ -400,6 +401,41 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc, drm_crtc_vblank_off(crtc); }
+static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) +{ + struct omap_drm_private *priv = crtc->dev->dev_private; + + /* Check for bandwidth limit */ + if (priv->max_bandwidth) { + /* + * Estimation for the bandwidth need of a given mode with one + * full screen plane: + * bandwidth = resolution * 32bpp * (pclk / (vtotal * htotal)) + * ^^ Refresh rate ^^ + * + * The interlaced mode is taken into account by using the + * pixelclock in the calculation. + * + * The equation is rearranged for 64bit arithmetic. + */ + uint64_t bandwidth = mode->clock * 1000; + unsigned int bpp = 4; + + bandwidth = bandwidth * mode->hdisplay * mode->vdisplay * bpp; + bandwidth = div_u64(bandwidth, mode->htotal * mode->vtotal); + + /* + * Reject modes which would need more bandwidth if used with one + * full resolution plane (most common use case). + */ + if (priv->max_bandwidth < bandwidth) + return MODE_BAD; + } + + return MODE_OK; +} + static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); @@ -621,6 +657,7 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { .atomic_flush = omap_crtc_atomic_flush, .atomic_enable = omap_crtc_atomic_enable, .atomic_disable = omap_crtc_atomic_disable, + .mode_valid = omap_crtc_mode_valid, };
/* ----------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index cdf5b0601eba..ba3d22fae55b 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -593,6 +593,11 @@ static int pdev_probe(struct platform_device *pdev) ddev->dev_private = priv; platform_set_drvdata(pdev, ddev);
+ /* Get memory bandwidth limits */ + if (priv->dispc_ops->get_memory_bandwidth_limit) + priv->max_bandwidth = + priv->dispc_ops->get_memory_bandwidth_limit(); + omap_gem_init(ddev);
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 { spinlock_t wait_lock; /* protects the wait_list */ struct list_head wait_list; /* list of omap_irq_wait */ uint32_t irq_mask; /* enabled irqs in addition to wait_list */ + + /* memory bandwidth limit if it is needed on the platform */ + unsigned int max_bandwidth; };
On 30/11/17 14:12, Peter Ujfalusi wrote:
Hi,
Changes since v2:
- Rebased on drm-next (v2 was based on drm-next and my 'drm/omap: Module parameter for display order configuration' series, thus it was not applying cleanly.
- Added Acked-by from Rob to the dt-binding changes
Changes since v1:
- Use the crtc->mode_valid and not connector->mode_valid as the limit is really posed by the 'crtc' (DISPC)
- Bandwidth calculation changed: do the calculation in place + extended comment
- looked for better place to document the max-memory-bandwidth, but can not find any suitable document. Creating a new txt file for only one property did not seemed feasable.
This series will add simple memory bandwidth limit support to reject modes which, if used with one plane in full size would fail the limit.
Regards, Peter
Peter Ujfalusi (3): dt-bindings: display/ti: Add optional property to set memory bandwidth limit drm/omap: dss: Add support for reporting memory bandwidth limitation drm/omap: Filter displays mode based on bandwidth limit
.../devicetree/bindings/display/ti/ti,dra7-dss.txt | 5 +++ .../bindings/display/ti/ti,omap2-dss.txt | 4 +++ .../bindings/display/ti/ti,omap3-dss.txt | 4 +++ .../bindings/display/ti/ti,omap4-dss.txt | 4 +++ .../bindings/display/ti/ti,omap5-dss.txt | 4 +++ drivers/gpu/drm/omapdrm/dss/dispc.c | 13 ++++++++ drivers/gpu/drm/omapdrm/dss/omapdss.h | 2 ++ drivers/gpu/drm/omapdrm/omap_crtc.c | 37 ++++++++++++++++++++++ drivers/gpu/drm/omapdrm/omap_drv.c | 5 +++ drivers/gpu/drm/omapdrm/omap_drv.h | 3 ++ 10 files changed, 81 insertions(+)
Thanks, I have applied this series.
Tomi
dri-devel@lists.freedesktop.org