Hi Sylwester,
On 5/30/20 1:32 AM, Sylwester Nawrocki wrote:
From: Marek Szyprowski m.szyprowski@samsung.com
This patch adds interconnect support to exynos-mixer. The mixer works the same as before when CONFIG_INTERCONNECT is 'n'.
For proper operation of the video mixer block we need to ensure the interconnect busses like DMC or LEFTBUS provide enough bandwidth so as to avoid DMA buffer underruns in the mixer block. i.e we need to prevent those busses from operating in low perfomance OPPs when the mixer is running. In this patch the bus bandwidth request is done through the interconnect API, the bandiwidth value is calculated from selected DRM mode, i.e. video plane width, height, refresh rate and pixel format.
Co-developed-by: Artur Świgoń a.swigon@samsung.com Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com [s.nawrocki: renamed soc_path variable to icc_path, edited commit desc.] Signed-off-by: Sylwester Nawrocki s.nawrocki@samsung.com
Changes for v5:
- renamed soc_path variable to icc_path
drivers/gpu/drm/exynos/exynos_mixer.c | 73 ++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 21b726b..bdae683 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -13,6 +13,7 @@ #include <linux/component.h> #include <linux/delay.h> #include <linux/i2c.h> +#include <linux/interconnect.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/kernel.h> @@ -98,6 +99,7 @@ struct mixer_context { struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR]; unsigned long flags;
struct icc_path *icc_path;
int irq; void __iomem *mixer_regs;
@@ -934,6 +936,42 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) mixer_reg_writemask(mixer_ctx, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); }
+static void mixer_set_memory_bandwidth(struct exynos_drm_crtc *crtc) +{
- struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
- struct mixer_context *ctx = crtc->ctx;
- unsigned long bw, bandwidth = 0;
- u32 avg_bw, peak_bw;
- int i, j, sub;
- if (!ctx->icc_path)
return;
- for (i = 0; i < MIXER_WIN_NR; i++) {
struct drm_plane *plane = &ctx->planes[i].base;
const struct drm_format_info *format;
if (plane->state && plane->state->crtc && plane->state->fb) {
format = plane->state->fb->format;
bw = mode->hdisplay * mode->vdisplay *
drm_mode_vrefresh(mode);
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
bw /= 2;
for (j = 0; j < format->num_planes; j++) {
sub = j ? (format->vsub * format->hsub) : 1;
bandwidth += format->cpp[j] * bw / sub;
First of all, I agree this approach.
Could you please add more detailed comments for understadning about this calculation? As you commented, it seems that the final bandwidth contains the width/height/refresh rate and pixel format. If you add one real example, it will be very helpful.
(snip)