From d0a23476008384650b5d08111f456649bf425df3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:07:16 +0900 Subject: [PATCH 01/16] drm/vc4: hdmi: Use clk_set_min_rate instead The HSM clock needs to be running at 101% the pixel clock of the HDMI controller, however it's shared between the two HDMI controllers, which means that if the resolutions are different between the two HDMI controllers, and the lowest resolution is on the second (in enable order) controller, the first HDMI controller will end up with a smaller than expected clock rate. Since we don't really need an exact frequency there, we can simply change the minimum rate we expect instead. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/821992209cc0d7a83254bf26fe2bf507ef0994d2.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I5666bf89beb6bada919b279846e5c204fabd0ffc --- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 1c20561..61f6279 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -629,7 +629,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) * pixel clock, but HSM ends up being the limiting factor. */ hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); - ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate); + ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); return; -- 2.7.4 From b41b24ecdc754277251c07bacd03982651a70e7a Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:18:19 +0900 Subject: [PATCH 02/16] drm/vc4: hdmi: Remove register dumps in enable The current code has some logic, disabled by default, to dump the register setup in the HDMI controller. However, since we're going to split those functions in multiple, shorter, functions that only make sense where they are called in sequence, keeping the register dump makes little sense. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/c8c8d388f2d32fc3536336be36d003a862487eb7.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Remove hdmi reg dumps, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I8048f58783639cf790c8bb691007099943733a71 --- drivers/gpu/drm/vc4/vc4_hdmi.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 61f6279..7548431 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -589,7 +589,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - bool debug_dump_regs = false; unsigned long pixel_rate, hsm_rate; int ret; @@ -665,14 +664,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) if (vc4_hdmi->variant->phy_init) vc4_hdmi->variant->phy_init(vc4_hdmi, mode); - if (debug_dump_regs) { - struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); - - dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n"); - drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); - drm_print_regset32(&p, &vc4_hdmi->hd_regset); - } - HDMI_WRITE(HDMI_VID_CTL, 0); HDMI_WRITE(HDMI_SCHEDULER_CONTROL, @@ -698,14 +689,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); - if (debug_dump_regs) { - struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); - - dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n"); - drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); - drm_print_regset32(&p, &vc4_hdmi->hd_regset); - } - HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_ENABLE | -- 2.7.4 From e191c6f5f87b90c2044912afa9e70e5a35367fe5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:21:50 +0900 Subject: [PATCH 03/16] drm/vc4: hdmi: Always recenter the HDMI FIFO In order to avoid a pixel getting stuck in an unflushable FIFO, we need to recenter the FIFO every time we're doing a modeset and not only if we're connected to an HDMI monitor. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/b3faaf05ac6c4d3c364d28fa441571eb85903269.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: Ife295f612fb32ef2a02e1494c3a4b532735c989e --- drivers/gpu/drm/vc4/vc4_hdmi.c | 46 ++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 7548431..f8144aa 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -584,6 +584,30 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_CLOCK_STOP, 0); } +static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) +{ + u32 drift; + int ret; + + drift = HDMI_READ(HDMI_FIFO_CTL); + drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; + + HDMI_WRITE(HDMI_FIFO_CTL, + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); + usleep_range(1000, 1100); + HDMI_WRITE(HDMI_FIFO_CTL, + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); + + ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & + VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); + WARN_ONCE(ret, "Timeout waiting for " + "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); +} + static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; @@ -719,8 +743,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) } if (vc4_encoder->hdmi_monitor) { - u32 drift; - WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE)); HDMI_WRITE(HDMI_SCHEDULER_CONTROL, @@ -731,25 +753,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) VC4_HDMI_RAM_PACKET_ENABLE); vc4_hdmi_set_infoframes(encoder); - - drift = HDMI_READ(HDMI_FIFO_CTL); - drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; - - HDMI_WRITE(HDMI_FIFO_CTL, - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); - usleep_range(1000, 1100); - HDMI_WRITE(HDMI_FIFO_CTL, - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); - - ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & - VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); - WARN_ONCE(ret, "Timeout waiting for " - "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); } + + vc4_hdmi_recenter_fifo(vc4_hdmi); } static enum drm_mode_status -- 2.7.4 From 489ac6bc9de2adc1ff7a648ea18b6d8bcf081d7c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:26:58 +0900 Subject: [PATCH 04/16] drm/vc4: hdmi: Implement finer-grained hooks In order to prevent some pixels getting stuck in an unflushable FIFO on bcm2711, we need to enable the HVS, the pixelvalve (the CRTC) and the HDMI controller (the encoder) in an intertwined way, and with tight delays. However, the atomic callbacks don't really provide a way to work with either constraints, so we need to roll our own callbacks so that we can provide those guarantees. Since those callbacks have been implemented and called in the CRTC code, we can just implement them in the HDMI driver now. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/2e9226d971117065f3b97e597f04f7fe2f0c134c.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: Ice9a866f353d8e478e8f24c66b6e2e836e474817 --- drivers/gpu/drm/vc4/vc4_hdmi.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index f8144aa..188f2fb 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -387,12 +387,17 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) vc4_hdmi_set_audio_infoframe(encoder); } -static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) +static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - int ret; HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); +} + +static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder) +{ + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + int ret; if (vc4_hdmi->variant->phy_disable) vc4_hdmi->variant->phy_disable(vc4_hdmi); @@ -409,6 +414,10 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) DRM_ERROR("Failed to release power domain: %d\n", ret); } +static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) +{ +} + static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) { u32 csc_ctl; @@ -608,11 +617,10 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); } -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) +static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); unsigned long pixel_rate, hsm_rate; int ret; @@ -697,6 +705,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) if (vc4_hdmi->variant->set_timings) vc4_hdmi->variant->set_timings(vc4_hdmi, mode); +} + +static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder) +{ + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; + struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); if (vc4_encoder->hdmi_monitor && drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) { @@ -712,6 +727,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) } HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); +} + +static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) +{ + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + int ret; HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | @@ -758,6 +780,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) vc4_hdmi_recenter_fifo(vc4_hdmi); } +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) +{ +} + static enum drm_mode_status vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) @@ -1699,6 +1725,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) variant = of_device_get_match_data(dev); vc4_hdmi->variant = variant; vc4_hdmi->encoder.base.type = variant->id ? VC4_ENCODER_TYPE_HDMI1 : VC4_ENCODER_TYPE_HDMI0; + vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure; + vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable; + vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable; + vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable; + vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown; + encoder = &vc4_hdmi->encoder.base.base; ret = variant->init_resources(vc4_hdmi); -- 2.7.4 From 521cd5ed95e44648b8ae5d1e81f3af9bc6c0f3fd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:39:06 +0900 Subject: [PATCH 05/16] drm/vc4: hdmi: Do the VID_CTL configuration at once The VID_CTL setup is done in several places in the driver even though it's not really required. Let's simplify it a bit to do the configuration in one go. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/08e7ebb605a560fcc149b69b4af52753a7870b2f.1599120059.git-series.maxime@cerno.tech [cw00.choi: Apply it to both vc4_hdmi_set_timings and vc5_hdmi_set_timings, needed to troubleshoot page flip timed out issue.] Signed-off-by: Chanwoo Choi Signed-off-by: Hoegeun Kwon Change-Id: I3b12049c9bfb69d5d21c7186b677e8e32d756959 --- drivers/gpu/drm/vc4/vc4_hdmi.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 188f2fb..1084623 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -535,10 +535,6 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); - - HDMI_WRITE(HDMI_VID_CTL, - (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | - (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); } static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, @@ -586,10 +582,6 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); - HDMI_WRITE(HDMI_VID_CTL, - (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | - (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); - HDMI_WRITE(HDMI_CLOCK_STOP, 0); } @@ -696,8 +688,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) if (vc4_hdmi->variant->phy_init) vc4_hdmi->variant->phy_init(vc4_hdmi, mode); - HDMI_WRITE(HDMI_VID_CTL, 0); - HDMI_WRITE(HDMI_SCHEDULER_CONTROL, HDMI_READ(HDMI_SCHEDULER_CONTROL) | VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT | @@ -731,15 +721,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder) static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) { + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; + bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; int ret; HDMI_WRITE(HDMI_VID_CTL, - HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_ENABLE | VC4_HD_VID_CTL_UNDERFLOW_ENABLE | - VC4_HD_VID_CTL_FRAME_COUNTER_RESET); + VC4_HD_VID_CTL_FRAME_COUNTER_RESET | + (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | + (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); if (vc4_encoder->hdmi_monitor) { HDMI_WRITE(HDMI_SCHEDULER_CONTROL, -- 2.7.4 From 6a01bb354aecde44c192fed5475cac30542ae56f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:44:04 +0900 Subject: [PATCH 06/16] drm/vc4: hdmi: Switch to blank pixels when disabled In order to avoid pixels getting stuck in an unflushable FIFO, we need when we disable the HDMI controller to switch away from getting our pixels from the pixelvalve and instead use blank pixels, and switch back to the pixelvalve when we enable the HDMI controller. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/fde3efb1ad79f4476a73d310cbba3ec07dc6dabe.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I497f96e6d9b535d9d173d486fe1829c30093d88f --- drivers/gpu/drm/vc4/vc4_hdmi.c | 9 +++++++++ drivers/gpu/drm/vc4/vc4_regs.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 1084623..4c10427 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -392,6 +392,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder) struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); + + HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | + VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC); + + HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); } static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder) @@ -735,6 +741,9 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); + HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX); + if (vc4_encoder->hdmi_monitor) { HDMI_WRITE(HDMI_SCHEDULER_CONTROL, HDMI_READ(HDMI_SCHEDULER_CONTROL) | diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 4d01757..c14ee209 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -732,6 +732,9 @@ # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET BIT(29) # define VC4_HD_VID_CTL_VSYNC_LOW BIT(28) # define VC4_HD_VID_CTL_HSYNC_LOW BIT(27) +# define VC4_HD_VID_CTL_CLRSYNC BIT(24) +# define VC4_HD_VID_CTL_CLRRGB BIT(23) +# define VC4_HD_VID_CTL_BLANKPIX BIT(18) # define VC4_HD_CSC_CTL_ORDER_MASK VC4_MASK(7, 5) # define VC4_HD_CSC_CTL_ORDER_SHIFT 5 -- 2.7.4 From 8add429d6f035cb9e07937b94e6979b4bd5f40e3 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Fri, 11 Sep 2020 13:39:40 +0900 Subject: [PATCH 07/16] drm/vc4: hdmi: Fix to use clk_set_min_rate There is a problem that rpi_firmware_transaction fails while setting the clock rate. Add the missing code applied to the mainline. Change-Id: I56bcb00037fc85bb01f8a876ccd26798b4bddb39 Signed-off-by: Hoegeun Kwon Link: https://patchwork.freedesktop.org/patch/msgid/d757ddd6549da140f178563e5fd2bf1d129913fd.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 4c10427..bc6288d 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -671,7 +671,11 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) return; } - ret = clk_set_rate(vc4_hdmi->pixel_bvb_clock, + /* + * FIXME: When the pixel freq is 594MHz (4k60), this needs to be setup + * at 150MHz. + */ + ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, (hsm_rate > VC4_HSM_MID_CLOCK ? 150000000 : 75000000)); if (ret) { DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); -- 2.7.4 From 6b3581bbf037ce5d241a319249e5469f4cadfc6c Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Tue, 15 Sep 2020 09:32:49 +0900 Subject: [PATCH 08/16] drm/vc4: hvs: Boost the core clock during modeset In order to prevent timeouts and stalls in the pipeline, the core clock needs to be maxed at 500MHz during a modeset on the BCM2711. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/37ed9e0124c5cce005ddc8dafe821d8b0da036ff.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: A screen cracking problem occurs in FHD(1920x1080). The cause is that the clock should be kept at 500MHz, but it occurred when the clock fell to 200MHz, so apply a patch.] Signed-off-by: Hoegeun Kwon Change-Id: Ie0d4880966c1644bfdf56bb49dbb82559978538c --- drivers/gpu/drm/vc4/vc4_kms.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 7f857af..ae514d4 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -239,8 +239,8 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); } - if (!vc4->firmware_kms) - clk_set_rate(hvs->core_clk, 500000000); + if (vc4->hvs->hvs5) + clk_set_min_rate(hvs->core_clk, 500000000); drm_atomic_helper_wait_for_fences(dev, state, false); @@ -267,9 +267,6 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) drm_atomic_helper_commit_cleanup_done(state); - if (!vc4->firmware_kms) - clk_set_rate(hvs->core_clk, 200000000); - drm_atomic_state_put(state); up(&vc4->async_modeset); -- 2.7.4 From 779ecf8f6fe1428e2533edccfe550f6caabadde6 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Tue, 15 Sep 2020 18:48:22 +0900 Subject: [PATCH 09/16] scripts: mkbootimg_rpi4.sh: use compress image Use compressed image for less size. Change-Id: I9ec8b7e5e35bfa8ae6ac2832d52d4748e9a79668 Signed-off-by: Seung-Woo Kim --- scripts/mkbootimg_rpi4.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mkbootimg_rpi4.sh b/scripts/mkbootimg_rpi4.sh index 1127b94..babfd46 100755 --- a/scripts/mkbootimg_rpi4.sh +++ b/scripts/mkbootimg_rpi4.sh @@ -81,12 +81,12 @@ rm -rf tmp tmp_modules # Create boot tarball for the lthor flashing DATE=`date +%Y%m%d` if [ -n "$IS_64BIT" ]; then - BOOT_TARBALL=tizen-local-${DATE}-boot-arm64-rpi4.tar + BOOT_TARBALL=tizen-local-${DATE}-boot-arm64-rpi4.tar.gz else - BOOT_TARBALL=tizen-local-${DATE}-boot-armv7l-rpi4.tar + BOOT_TARBALL=tizen-local-${DATE}-boot-armv7l-rpi4.tar.gz fi -tar cf ${BOOT_TARBALL} boot.img modules.img +tar czf ${BOOT_TARBALL} boot.img modules.img if [ "$?" != "0" ]; then echo "Failed to create boot tarball" exit 1 -- 2.7.4 From 58dd253de9a7e210562f0d0576e1640279ef0f44 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Fri, 18 Sep 2020 15:54:43 +0900 Subject: [PATCH 10/16] drm/vc4: crtc: Add null pointer error handling Crash occurs when vc4_encoder is null. Add null error handling Unable to handle kernel NULL pointer dereference at virtual address 0000000000000090 Mem abort info: ESR = 0x96000005 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 Data abort info: ISV = 0, ISS = 0x00000005 CM = 0, WnR = 0 user pgtable: 4k pages, 39-bit VAs, pgdp=00000000f2a96000 [0000000000000090] pgd=0000000000000000, pud=0000000000000000 Internal error: Oops: 96000005 [#1] PREEMPT SMP Modules linked in: brcmfmac joydev brcmutil rpivid_mem CPU: 0 PID: 32 Comm: kworker/0:1 Not tainted 5.4.50-v8+ #414 Hardware name: Raspberry Pi 4 Model B (DT) Workqueue: events output_poll_execute pstate: 80000005 (Nzcv daif -PAN -UAO) pc : vc4_crtc_atomic_disable+0x150/0x2e8 lr : vc4_crtc_atomic_disable+0x50/0x2e8 ... Call trace: vc4_crtc_atomic_disable+0x150/0x2e8 drm_atomic_helper_commit_modeset_disables+0x344/0x410 vc4_atomic_complete_commit+0xd4/0x530 vc4_atomic_commit+0xf4/0x190 drm_atomic_commit+0x54/0x60 ... Change-Id: Ib3271bb3c8318079fe5815711f89a217e835adc6 Signed-off-by: Hoegeun Kwon --- drivers/gpu/drm/vc4/vc4_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 129cf90a..f8fa076 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -508,7 +508,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n"); - if (vc4_encoder->post_crtc_disable) + if (vc4_encoder && vc4_encoder->post_crtc_disable) vc4_encoder->post_crtc_disable(encoder); CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN); @@ -536,7 +536,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != SCALER_DISPSTATX_EMPTY); - if (vc4_encoder->post_crtc_powerdown) + if (vc4_encoder && vc4_encoder->post_crtc_powerdown) vc4_encoder->post_crtc_powerdown(encoder); /* -- 2.7.4 From 650aee597eeacf09ab51356fe341d36f74e82d1a Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 17 Sep 2020 14:16:23 +0200 Subject: [PATCH 11/16] drm/vc4: hvs: Pull the state of all the CRTCs prior to PV muxing The vc4 display engine has a first controller called the HVS that will perform the composition of the planes. That HVS has 3 FIFOs and can therefore compose planes for up to three outputs. The timings part is generated through a component called the Pixel Valve, and the BCM2711 has 6 of them. Thus, the HVS has some bits to control which FIFO gets output to which Pixel Valve. The current code supports that muxing by looking at all the CRTCs in a new DRM atomic state in atomic_check, and given the set of constraints that we have, assigns FIFOs to CRTCs or reject the mode entirely. The actual muxing will occur during atomic_commit. However, that doesn't work if only a fraction of the CRTCs' state is updated in that state, since it will ignore the CRTCs that are kept running unmodified, and will thus unassign its associated FIFO, and later disable it. In order to make the code work as expected, let's pull the CRTC state of all the enabled CRTC in our atomic_check so that we can operate on all the running CRTCs, no matter whether they are affected by the new state or not. Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically") Signed-off-by: Maxime Ripard Tested-by: Hoegeun Kwon Tested-by: Dave Stevenson Reviewed-by: Dave Stevenson Reviewed-by: Hoegeun Kwon Link: https://patchwork.freedesktop.org/patch/msgid/20200917121623.42023-1-maxime@cerno.tech [hoegeun.kwon: Fix dual hdmi issue] Signed-off-by: Hoegeun Kwon Change-Id: I750e253c7415b09e546beb2608445d581c441efe --- drivers/gpu/drm/vc4/vc4_kms.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index ae514d4..2502405 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -589,6 +589,23 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) struct drm_crtc *crtc; int i, ret; + /* + * Since the HVS FIFOs are shared across all the pixelvalves and + * the TXP (and thus all the CRTCs), we need to pull the current + * state of all the enabled CRTCs so that an update to a single + * CRTC still keeps the previous FIFOs enabled and assigned to + * the same CRTCs, instead of evaluating only the CRTC being + * modified. + */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (!crtc->state->enable) + continue; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + } + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc_state); -- 2.7.4 From 4453fe27ce2bb0db993870729a17919a35c74de7 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 5 Oct 2020 20:39:01 +0900 Subject: [PATCH 12/16] brcmfmac: change from brcmf_dbg to brcmf_info Change from brcmf_dbg to brcmf_info. This patch is workaround to check debug message on Testhub. Change-Id: I7fef8f64fc38e43b6544fab3e9474e7f1829cc60 Signed-off-by: Jaehoon Chung --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 8eb56d9..f59837c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -5392,19 +5392,19 @@ static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg, u32 status = e->status; if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) { - brcmf_dbg(CONN, "Processing Link %s & no network found\n", - e->flags & BRCMF_EVENT_MSG_LINK ? "up" : "down"); + brcmf_info("Processing Link %s & no network found %u\n", + e->flags & BRCMF_EVENT_MSG_LINK ? "up" : "down", status); return true; } if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) { - brcmf_dbg(CONN, "Processing connecting & no network found\n"); + brcmf_info("Processing connecting & no network found %u\n", status); return true; } if (event == BRCMF_E_PSK_SUP && status != BRCMF_E_STATUS_FWSUP_COMPLETED) { - brcmf_dbg(CONN, "Processing failed supplicant state: %u\n", + brcmf_info("Processing failed supplicant state: %u\n", status); return true; } @@ -5659,7 +5659,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, if (brcmf_is_apmode(ifp->vif)) { err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); } else if (brcmf_is_linkup(ifp->vif, e)) { - brcmf_dbg(CONN, "Linkup\n"); + brcmf_info("Linkup\n"); if (brcmf_is_ibssmode(ifp->vif)) { brcmf_inform_ibss(cfg, ndev, e->addr); chan = ieee80211_get_channel(cfg->wiphy, cfg->channel); @@ -5673,7 +5673,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, brcmf_bss_connect_done(cfg, ndev, e, true); brcmf_net_setcarrier(ifp, true); } else if (brcmf_is_linkdown(e)) { - brcmf_dbg(CONN, "Linkdown\n"); + brcmf_info("Linkdown\n"); if (!brcmf_is_ibssmode(ifp->vif)) { brcmf_bss_connect_done(cfg, ndev, e, false); brcmf_link_down(ifp->vif, @@ -5684,6 +5684,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, brcmf_net_setcarrier(ifp, false); } } else if (brcmf_is_nonetwork(cfg, e)) { + brcmf_info("No Network\n"); if (brcmf_is_ibssmode(ifp->vif)) clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); -- 2.7.4 From 1d6059916173b882b6755dfc6c05bf8027e4b4db Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 12 Oct 2020 13:26:40 +0900 Subject: [PATCH 13/16] drm/vc4: kms: Assign a FIFO to enabled CRTCs instead of active The HVS has three FIFOs that can be assigned to a number of PixelValves through a mux. However, changing that FIFO requires that we disable and then enable the pixelvalve, so we want to assign FIFOs to all the enabled CRTCs, and not just the active ones. Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically") Signed-off-by: Maxime Ripard [hoegeun.kwon: Needed to fix page flip issue of dual hdmi.] Signed-off-by: Hoegeun Kwon Change-Id: Id418d321e3cfc9b992bd1868e8084d9f8694a46e --- drivers/gpu/drm/vc4/vc4_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 2502405..96aadcb 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -613,7 +613,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) bool is_assigned = false; unsigned int channel; - if (!crtc_state->active || vc4->firmware_kms) + if (!crtc_state->enable || vc4->firmware_kms) continue; /* -- 2.7.4 From 704036c2a3e84a1d1a42d9511e3527e029c37e59 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 12 Oct 2020 16:44:43 +0900 Subject: [PATCH 14/16] drm/vc4: crtc: Keep the previously assigned HVS FIFO The HVS FIFOs are currently assigned each time we have an atomic_check for all the enabled CRTCs. However, if we are running multiple outputs in parallel and we happen to disable the first (by index) CRTC, we end up changing the assigned FIFO of the second CRTC without disabling and reenabling the pixelvalve which ends up in a stall and eventually a VBLANK timeout. In order to fix this, we can create a special value for our assigned channel to mark it as disabled, and if our CRTC already had an assigned channel in its previous state, we keep on using it. Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically") Signed-off-by: Maxime Ripard [hoegeun.kwon: Needed to fix page flip issue of dual hdmi.] Signed-off-by: Hoegeun Kwon Change-Id: I70e0d6b563d5c7f22a1a7e1527a401ac42395b78 --- drivers/gpu/drm/vc4/vc4_crtc.c | 12 +++++++++--- drivers/gpu/drm/vc4/vc4_drv.h | 1 + drivers/gpu/drm/vc4/vc4_kms.c | 21 +++++++++++++++------ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index f8fa076..2eabf02f 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1088,12 +1088,18 @@ static void vc4_crtc_destroy_state(struct drm_crtc *crtc, static void vc4_crtc_reset(struct drm_crtc *crtc) { + struct vc4_crtc_state *vc4_crtc_state; + if (crtc->state) vc4_crtc_destroy_state(crtc, crtc->state); - crtc->state = kzalloc(sizeof(struct vc4_crtc_state), GFP_KERNEL); - if (crtc->state) - crtc->state->crtc = crtc; + vc4_crtc_state = kzalloc(sizeof(*vc4_crtc_state), GFP_KERNEL); + if (!vc4_crtc_state) + return; + + vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; + crtc->state = &vc4_crtc_state->base; + crtc->state->crtc = crtc; } static const struct drm_crtc_funcs vc4_crtc_funcs = { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 9273595..457fd68 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -511,6 +511,7 @@ struct vc4_crtc_state { unsigned int bottom; } margins; }; +#define VC4_HVS_CHANNEL_DISABLED ((unsigned int) -1) static inline struct vc4_crtc_state * to_vc4_crtc_state(struct drm_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 96aadcb..77745ad 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -585,7 +585,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0); struct vc4_dev *vc4 = to_vc4_dev(state->dev); - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; int i, ret; @@ -598,6 +598,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) * modified. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct drm_crtc_state *crtc_state; if (!crtc->state->enable) continue; @@ -606,15 +607,23 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) return PTR_ERR(crtc_state); } - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { - struct vc4_crtc_state *vc4_crtc_state = - to_vc4_crtc_state(crtc_state); + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + struct vc4_crtc_state *new_vc4_crtc_state = + to_vc4_crtc_state(new_crtc_state); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); bool is_assigned = false; unsigned int channel; - if (!crtc_state->enable || vc4->firmware_kms) + if (old_crtc_state->enable && !new_crtc_state->enable) + new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; + + if (!new_crtc_state->enable) + continue; + + if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) { + unassigned_channels &= ~BIT(new_vc4_crtc_state->assigned_channel); continue; + } /* * The problem we have to solve here is that we have @@ -646,7 +655,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) if (!(BIT(channel) & vc4_crtc->data->hvs_available_channels)) continue; - vc4_crtc_state->assigned_channel = channel; + new_vc4_crtc_state->assigned_channel = channel; unassigned_channels &= ~BIT(channel); is_assigned = true; break; -- 2.7.4 From b6cf6945c8bb5da757776af2e4df8cebf6383368 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 12 Oct 2020 16:55:43 +0900 Subject: [PATCH 15/16] drm/vc4: kms: Split the HVS muxing check in a separate function The code that assigns HVS channels during atomic_check is starting to grow a bit big, let's move it into a separate function. Signed-off-by: Maxime Ripard [hoegeun.kwon: Needed to fix page flip issue of dual hdmi.] Signed-off-by: Hoegeun Kwon Change-Id: Icf636a846282981d21ad3e6652a3ec51f14993a4 --- drivers/gpu/drm/vc4/vc4_kms.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 77745ad..9a56596 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -580,14 +580,14 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = { #define NUM_OUTPUTS 6 #define NUM_CHANNELS 3 -static int -vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) +static int vc4_pv_muxing_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) { unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0); struct vc4_dev *vc4 = to_vc4_dev(state->dev); struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; - int i, ret; + unsigned int i; /* * Since the HVS FIFOs are shared across all the pixelvalves and @@ -665,6 +665,18 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) return -EINVAL; } + return 0; +} + +static int +vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) +{ + int ret; + + ret = vc4_pv_muxing_atomic_check(dev, state); + if (ret) + return ret; + ret = vc4_ctm_atomic_check(dev, state); if (ret < 0) return ret; -- 2.7.4 From 47951c47a46ca69c88001856f0e4236b2428fd32 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 8 Oct 2020 13:25:17 +0200 Subject: [PATCH 16/16] drm/vc4: kms: Document the muxing corner cases We've had a number of muxing corner-cases with specific ways to reproduce them, so let's document them to make sure they aren't lost and introduce regressions later on. Signed-off-by: Maxime Ripard [hoegeun.kwon: Needed to fix page flip issue of dual hdmi.] Signed-off-by: Hoegeun Kwon Change-Id: Icc4f82cd0c22f7b0b7e3c33be37d2e9d287638e4 --- drivers/gpu/drm/vc4/vc4_kms.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 9a56596..5beb875 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -580,6 +580,28 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = { #define NUM_OUTPUTS 6 #define NUM_CHANNELS 3 +/* + * The BCM2711 HVS has up to 7 output connected to the pixelvalves and + * the TXP (and therefore all the CRTCs found on that platform). + * + * The naive (and our initial) implementation would just iterate over + * all the active CRTCs, try to find a suitable FIFO, and then remove it + * from the available FIFOs pool. However, there's a few corner cases + * that need to be considered: + * + * - When running in a dual-display setup (so with two CRTCs involved), + * we can update the state of a single CRTC (for example by changing + * its mode using xrandr under X11) without affecting the other. In + * this case, the other CRTC wouldn't be in the state at all, so we + * need to consider all the running CRTCs in the DRM device to assign + * a FIFO, not just the one in the state. + * + * - Since we need the pixelvalve to be disabled and enabled back when + * the FIFO is changed, we should keep the FIFO assigned for as long + * as the CRTC is enabled, only considering it free again once that + * CRTC has been disabled. This can be tested by booting X11 on a + * single display, and changing the resolution down and then back up. + */ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { -- 2.7.4