Add memory bandwidth management to NVIDIA Tegra DRM driver
v14 cover Add memory bandwidth management to NVIDIA Tegra DRM driver
This series adds memory bandwidth management to the NVIDIA Tegra DRM driver, which is done using interconnect framework. It fixes display corruption that happens due to insufficient memory bandwidth.
Changelog:
v14: - Made improvements that were suggested by Michał Mirosław to v13:
- Changed 'unsigned int' to 'bool'.
- Renamed functions which calculate bandwidth state.
- Reworked comment in the code that explains why downscaled plane require higher bandwidth.
- Added round-up to bandwidth calculation.
- Added sanity checks of the plane index and fixed out-of-bounds access which happened on T124 due to the cursor plane index.
v13: - No code changes. Patches missed v5.12, re-sending them for v5.13.
Dmitry Osipenko (2):
drm/tegra: dc: Support memory bandwidth management drm/tegra: dc: Extend debug stats with total number of events
drivers/gpu/drm/tegra/Kconfig | 1 + drivers/gpu/drm/tegra/dc.c | 362 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tegra/dc.h | 19 ++ drivers/gpu/drm/tegra/drm.c | 14 ++ drivers/gpu/drm/tegra/hub.c | 3 + drivers/gpu/drm/tegra/plane.c | 127 ++++++++++++ drivers/gpu/drm/tegra/plane.h | 15 ++ 7 files changed, 541 insertions(+)
Signature · 6 lines
2.29.2 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v14 1/2 drm/tegra: dc: Support memory bandwidth management
Display controller (DC) performs isochronous memory transfers, and thus, has a requirement for a minimum memory bandwidth that shall be fulfilled, otherwise framebuffer data can't be fetched fast enough and this results in a DC's data-FIFO underflow that follows by a visual corruption.
The Memory Controller drivers provide facility for memory bandwidth management via interconnect API. Let's wire up the interconnect API support to the DC driver in order to fix the distorted display output on T30 Ouya, T124 TK1 and other Tegra devices.
--- drivers/gpu/drm/tegra/Kconfig | 1 + drivers/gpu/drm/tegra/dc.c | 352 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tegra/dc.h | 14 ++ drivers/gpu/drm/tegra/drm.c | 14 ++ drivers/gpu/drm/tegra/hub.c | 3 + drivers/gpu/drm/tegra/plane.c | 127 ++++++++++++ drivers/gpu/drm/tegra/plane.h | 15 ++ 7 files changed, 526 insertions(+)
drivers/gpu/drm/tegra/Kconfig +1 -0
@@ -9,6 +9,7 @@ config DRM_TEGRA select DRM_MIPI_DSI select DRM_PANEL select TEGRA_HOST1X + select INTERCONNECT select IOMMU_IOVA select CEC_CORE if CEC_NOTIFIER help
drivers/gpu/drm/tegra/dc.c +352 -0
469 lines not on this page · raw message
drivers/gpu/drm/tegra/dc.h +14 -0
@@ -15,6 +15,8 @@struct tegra_output ; +#define TEGRA_DC_LEGACY_PLANES_NUM 7 +struct tegra_dc_state {struct drm_crtc_state base;
@@ -23,6 +25,8 @@ struct tegra_dc_state {unsigned int div;u32 planes; + +unsigned long plane_peak_bw[TEGRA_DC_LEGACY_PLANES_NUM ]; };static inline struct tegra_dc_state *to_dc_state (struct drm_crtc_state *state)
@@ -33,6 +37,12 @@ static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state)return NULL ; } +static inline const struct tegra_dc_state * +to_const_dc_state (const struct drm_crtc_state *state) +{ +return to_dc_state ((struct drm_crtc_state *)state); +} +struct tegra_dc_stats {unsigned long frames;unsigned long vblank;
@@ -65,7 +75,9 @@ struct tegra_dc_soc_info {unsigned int num_overlay_formats;const u64 *modifiers;bool has_win_a_without_filters; +bool has_win_b_vfilter_mem_client;bool has_win_c_without_vert_filter; +bool plane_tiled_memory_bandwidth_x2; };struct tegra_dc {
@@ -151,6 +163,8 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,struct drm_crtc_state *crtc_state, struct clk *clk, unsigned long pclk, unsigned int div); +void tegra_crtc_atomic_post_commit (struct drm_crtc *crtc, +struct drm_atomic_state *state);/* from rgb.c */ int tegra_dc_rgb_probe (struct tegra_dc *dc);
drivers/gpu/drm/tegra/drm.c +14 -0
@@ -20,6 +20,7 @@#include <drm/drm_prime.h> #include <drm/drm_vblank.h> +#include "dc.h" #include "drm.h" #include "gem.h"
@@ -59,6 +60,17 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; +static void tegra_atomic_post_commit (struct drm_device *drm, +struct drm_atomic_state *old_state) +{ +struct drm_crtc_state *old_crtc_state__maybe_unused ; +struct drm_crtc *crtc; +unsigned int i; + +for_each_old_crtc_in_state (old_state, crtc, old_crtc_state, i) +tegra_crtc_atomic_post_commit (crtc, old_state); +} +static void tegra_atomic_commit_tail (struct drm_atomic_state *old_state) {struct drm_device *drm = old_state->dev;
@@ -75,6 +87,8 @@ static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state) }else {drm_atomic_helper_commit_tail_rpm (old_state); } + +tegra_atomic_post_commit (drm, old_state); } static const struct drm_mode_config_helper_funcs
drivers/gpu/drm/tegra/hub.c +3 -0
@@ -344,6 +344,9 @@ static int tegra_shared_plane_atomic_check(struct drm_plane *plane,struct tegra_dc *dc =to_tegra_dc (state->crtc);int err; + plane_state->peak_memory_bandwidth =0 ; + plane_state->avg_memory_bandwidth =0 ; +/* no need for further checks if the plane is being disabled */ if (!state->crtc || !state->fb)return 0 ;
drivers/gpu/drm/tegra/plane.c +127 -0
154 lines not on this page · raw message
drivers/gpu/drm/tegra/plane.h +15 -0
@@ -8,6 +8,7 @@#include <drm/drm_plane.h> +struct icc_path ;struct tegra_bo ;struct tegra_dc ;
@@ -16,6 +17,9 @@ struct tegra_plane {struct tegra_dc *dc;unsigned int offset;unsigned int index; + +struct icc_path *icc_mem; +struct icc_path *icc_mem_vfilter; };struct tegra_cursor {
@@ -52,6 +56,10 @@ struct tegra_plane_state {/* used for legacy blending support only */ struct tegra_plane_legacy_blending_state blending[2 ];bool opaque; + +/* bandwidths are in ICC units, i.e. kbytes/sec */ +u32 peak_memory_bandwidth; +u32 avg_memory_bandwidth; }; static inline struct tegra_plane_state *
@@ -63,6 +71,12 @@ to_tegra_plane_state(struct drm_plane_state *state)return NULL ; } +static inline const struct tegra_plane_state * +to_const_tegra_plane_state (const struct drm_plane_state *state) +{ +return to_tegra_plane_state ((struct drm_plane_state *)state); +} +extern const struct drm_plane_funcs tegra_plane_funcs; int tegra_plane_prepare_fb(struct drm_plane *plane,
@@ -77,5 +91,6 @@ int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap);bool tegra_plane_format_is_yuv (unsigned int format,bool *planar);int tegra_plane_setup_legacy_state (struct tegra_plane *tegra,struct tegra_plane_state *state); +int tegra_plane_interconnect_init (struct tegra_plane *plane);#endif /* TEGRA_PLANE_H */
Signature · 6 lines
2.29.2 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v14 1/2] drm/tegra: dc: Support memory bandwidth management
11.03.2021 20:06, Dmitry Osipenko пишет:
Quoted 4 lines
drivers/gpu/drm/tegra/plane.c +4
-0+static const char *const tegra_plane_icc_names[TEGRA_DC_LEGACY_PLANES_NUM ] = { +"wina" ,"winb" ,"winc" ,"" ,"" ,"" ,"cursor" , +}; +
drivers/gpu/drm/tegra/plane.c int tegra_plane_setup_legacy_state(struct tegra_plane *tegra, · line 702
Quoted 10 lines
drivers/gpu/drm/tegra/plane.c +10
-0+int tegra_plane_interconnect_init (struct tegra_plane *plane) +{ +const char *icc_name = tegra_plane_icc_names[plane->index]; +struct device *dev = plane->dc->dev; +struct tegra_dc *dc = plane->dc; +int err; + +if (WARN_ON (plane->index >=TEGRA_DC_LEGACY_PLANES_NUM ) || +WARN_ON (!tegra_plane_icc_names[plane->index])) +return -EINVAL ;
It just occurred to me that I added the NULL-check here, but missed to change "" to NULLs. I'll make a v15 shortly.
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v14 2/2 drm/tegra: dc: Extend debug stats with total number of events
In reply to Dmitry OsipenkoIt's useful to know the total number of underflow events and currently the debug stats are getting reset each time CRTC is being disabled. Let's account the overall number of events that doesn't get a reset.
--- drivers/gpu/drm/tegra/dc.c | 10 ++++++++++ drivers/gpu/drm/tegra/dc.h | 5 +++++ 2 files changed, 15 insertions(+)
drivers/gpu/drm/tegra/dc.c +10 -0
@@ -1539,6 +1539,11 @@ static int tegra_dc_show_stats(struct seq_file *s, void *data)seq_printf (s,"underflow: %lu\n" , dc->stats.underflow);seq_printf (s,"overflow: %lu\n" , dc->stats.overflow); +seq_printf (s,"frames total: %lu\n" , dc->stats.frames_total); +seq_printf (s,"vblank total: %lu\n" , dc->stats.vblank_total); +seq_printf (s,"underflow total: %lu\n" , dc->stats.underflow_total); +seq_printf (s,"overflow total: %lu\n" , dc->stats.overflow_total); +return 0 ; }
@@ -2313,6 +2318,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)/* dev_dbg(dc->dev, "%s(): frame end\n", __func__); */ + dc->stats.frames_total++; dc->stats.frames++; }
@@ -2321,6 +2327,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)dev_dbg(dc->dev, "%s(): vertical blank\n", __func__); */ drm_crtc_handle_vblank (&dc->base); + dc->stats.vblank_total++; dc->stats.vblank++; }
@@ -2328,6 +2335,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)/* dev_dbg(dc->dev, "%s(): underflow\n", __func__); */ + dc->stats.underflow_total++; dc->stats.underflow++; }
@@ -2335,11 +2343,13 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)/* dev_dbg(dc->dev, "%s(): overflow\n", __func__); */ + dc->stats.overflow_total++; dc->stats.overflow++; }if (status &HEAD_UF_INT ) {dev_dbg_ratelimited (dc->dev,"%s(): head underflow\n" , __func__); + dc->stats.underflow_total++; dc->stats.underflow++; }
drivers/gpu/drm/tegra/dc.h +5 -0
@@ -48,6 +48,11 @@ struct tegra_dc_stats {unsigned long vblank;unsigned long underflow;unsigned long overflow; + +unsigned long frames_total; +unsigned long vblank_total; +unsigned long underflow_total; +unsigned long overflow_total; };struct tegra_windowgroup_soc {
Signature · 6 lines
2.29.2 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
11.03.2021 20:06, Dmitry Osipenko пишет:
Quoted 22 lines
This series adds memory bandwidth management to the NVIDIA Tegra DRM driver, which is done using interconnect framework. It fixes display corruption that happens due to insufficient memory bandwidth.
Changelog:
v14: - Made improvements that were suggested by Michał Mirosław to v13:
- Changed 'unsigned int' to 'bool'.
- Renamed functions which calculate bandwidth state.
- Reworked comment in the code that explains why downscaled plane require higher bandwidth.
- Added round-up to bandwidth calculation.
- Added sanity checks of the plane index and fixed out-of-bounds access which happened on T124 due to the cursor plane index.v13: - No code changes. Patches missed v5.12, re-sending them for v5.13.
Dmitry Osipenko (2):
drm/tegra: dc: Support memory bandwidth management drm/tegra: dc: Extend debug stats with total number of events
Quoted 9 lines
drivers/gpu/drm/tegra/Kconfig | 1 + drivers/gpu/drm/tegra/dc.c | 362 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tegra/dc.h | 19 ++ drivers/gpu/drm/tegra/drm.c | 14 ++ drivers/gpu/drm/tegra/hub.c | 3 + drivers/gpu/drm/tegra/plane.c | 127 ++++++++++++ drivers/gpu/drm/tegra/plane.h | 15 ++ 7 files changed, 541 insertions(+)
Michał, please let me know if v14 looks good to you. I'll appreciate yours r-b, thanks in advance.
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel