From d9cbf6ebd428f00a5ca5655d6fdc03504bbceed0 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 10 Sep 2020 13:25:20 +0900 Subject: [PATCH 01/16] ARM: configs: tizen_bcm2711_defconfig: Enable VIDEO_CODEC_BCM2835 To support v4l2 codec device, enable VIDEO_CODEC_BCM2835. Change-Id: I7f7147901b77b3ff01afc1a7c3c7f0ab9cc20701 Signed-off-by: Seung-Woo Kim --- arch/arm/configs/tizen_bcm2711_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tizen_bcm2711_defconfig b/arch/arm/configs/tizen_bcm2711_defconfig index 565611b..167c914 100644 --- a/arch/arm/configs/tizen_bcm2711_defconfig +++ b/arch/arm/configs/tizen_bcm2711_defconfig @@ -419,6 +419,7 @@ CONFIG_STAGING_MEDIA=y CONFIG_ANDROID_LOGGER=y CONFIG_SND_BCM2835=y CONFIG_VIDEO_BCM2835=y +CONFIG_VIDEO_CODEC_BCM2835=y CONFIG_CLK_RASPBERRYPI=y CONFIG_MAILBOX=y CONFIG_BCM2835_MBOX=y -- 2.7.4 From 1f214bbbe0819ae7bb4e9ba4384ede5c974c985d Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 10 Sep 2020 13:28:11 +0900 Subject: [PATCH 02/16] ARM64: tizen_bcm2711_defconfig: Enable VIDEO_CODEC_BCM2835 To support v4l2 codec device, enable VIDEO_CODEC_BCM2835 and to meet dependency, enable MEDIA_CONTROLLER. Change-Id: Id473825163c409ceaab5d4b618cf8bddd6af0f68 Signed-off-by: Seung-Woo Kim --- arch/arm64/configs/tizen_bcm2711_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/tizen_bcm2711_defconfig b/arch/arm64/configs/tizen_bcm2711_defconfig index 3928257..de8a7cf 100644 --- a/arch/arm64/configs/tizen_bcm2711_defconfig +++ b/arch/arm64/configs/tizen_bcm2711_defconfig @@ -322,6 +322,7 @@ CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_ANALOG_TV_SUPPORT=y CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y CONFIG_USB_GSPCA_ZC3XX=m @@ -406,6 +407,7 @@ CONFIG_STAGING_MEDIA=y CONFIG_ANDROID_LOGGER=y CONFIG_SND_BCM2835=y CONFIG_VIDEO_BCM2835=y +CONFIG_VIDEO_CODEC_BCM2835=y CONFIG_CLK_RASPBERRYPI=y CONFIG_MAILBOX=y CONFIG_BCM2835_MBOX=y -- 2.7.4 From d2ead75e526d98aa4a838f2e9b66f8114eaca3fa Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 24 Aug 2020 19:56:15 +0900 Subject: [PATCH 03/16] drm/vc4: encoder: Add finer-grained encoder callbacks In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller requires very precise ordering and timing that the regular atomic callbacks don't provide. Let's add new callbacks on top of the regular ones to be able to split the configuration as needed. 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/1dd78efe8f29add73c97d0148cfd4ec8e34aaf22.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: For use encoder callback, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I16a1a59ad753d7c4e211c24a3563a607faa03a5c --- drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++ drivers/gpu/drm/vc4/vc4_drv.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 7925b7d..129cf90a 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -495,6 +495,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(old_state); u32 chan = vc4_crtc_state->assigned_channel; + struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); int ret; require_hvs_enabled(dev); @@ -506,6 +508,9 @@ 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) + vc4_encoder->post_crtc_disable(encoder); + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN); if (HVS_READ(SCALER_DISPCTRLX(chan)) & @@ -531,6 +536,9 @@ 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) + vc4_encoder->post_crtc_powerdown(encoder); + /* * Make sure we issue a vblank event after disabling the CRTC if * someone was waiting it. @@ -592,6 +600,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); struct drm_display_mode *mode = &crtc->state->adjusted_mode; u32 dispctrl; + struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); require_hvs_enabled(dev); @@ -627,14 +637,23 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, (vc4_state->feed_txp ? SCALER5_DISPCTRLX_ONESHOT : 0); + if (vc4_encoder->pre_crtc_configure) + vc4_encoder->pre_crtc_configure(encoder); + HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl); + if (vc4_encoder->pre_crtc_enable) + vc4_encoder->pre_crtc_enable(encoder); + /* When feeding the transposer block the pixelvalve is unneeded and * should not be enabled. */ if (!vc4_state->feed_txp) CRTC_WRITE(PV_V_CONTROL, CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); + + if (vc4_encoder->post_crtc_enable) + vc4_encoder->post_crtc_enable(encoder); } static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index afdf477..9273595 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -440,6 +440,13 @@ struct vc4_encoder { struct drm_encoder base; enum vc4_encoder_type type; u32 clock_select; + + void (*pre_crtc_configure)(struct drm_encoder *encoder); + void (*pre_crtc_enable)(struct drm_encoder *encoder); + void (*post_crtc_enable)(struct drm_encoder *encoder); + + void (*post_crtc_disable)(struct drm_encoder *encoder); + void (*post_crtc_powerdown)(struct drm_encoder *encoder); }; static inline struct vc4_encoder * -- 2.7.4 From fb91e38e8069c7b592767a33f436f0d4ea7a9d34 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 15:53:28 +0900 Subject: [PATCH 04/16] drm/vc4: hdmi: Add reset callback The BCM2711 and BCM283x HDMI controllers use a slightly different reset sequence, so let's add a callback to reset the 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/a34bcb493da07eae58ed704f65e72ce0748e8952.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Apply the missing code, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: If0383cb9b5f8ba5d3f309bfeab3e3c74272d8723 --- drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index da9fce5..77c05ae 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -97,6 +97,12 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) { + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); + udelay(1); + HDMI_WRITE(HDMI_M_CTL, 0); + + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE); + HDMI_WRITE(HDMI_SW_RESET_CONTROL, VC4_HDMI_SW_RESET_HDMI | VC4_HDMI_SW_RESET_FORMAT_DETECT); @@ -1757,14 +1763,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; } - /* HDMI core must be enabled. */ - if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) { - HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); - udelay(1); - HDMI_WRITE(HDMI_M_CTL, 0); - - HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE); - } pm_runtime_enable(dev); drm_encoder_init(drm, encoder, &vc4_hdmi_encoder_funcs, -- 2.7.4 From 11b503d4d3c574fd920243a5f35d8de1974bd96b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 17:31:56 +0900 Subject: [PATCH 05/16] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate The HSM clock needs to be setup at around 101% of the pixel rate. This was done previously by setting the clock rate to 163.7MHz at probe time and only check in mode_valid whether the mode pixel clock was under the pixel clock +1% or not. However, with 4k we need to change that frequency to a higher frequency than 163.7MHz, and yet want to have the lowest clock as possible to have a decent power saving. Let's change that logic a bit by setting the clock rate of the HSM clock to the pixel rate at encoder_enable time. This would work for the BCM2711 that support 4k resolutions and has a clock that can provide it, but we still have to take care of a 4k panel plugged on a BCM283x SoCs that wouldn't be able to use those modes, so let's define the limit in the variant. 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/7e692ddc231d33dd671e70ea04dd1dcf56c1ecb3.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Applied missing code, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I43328575d59a0bbccac8d4153ac5ed54f029550b --- drivers/gpu/drm/vc4/vc4_hdmi.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 77c05ae..1c20561 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -612,7 +612,23 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) return; } - hsm_rate = vc4_hdmi->variant->calc_hsm_clock(vc4_hdmi, pixel_rate); + /* + * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must + * be faster than pixel clock, infinitesimally faster, tested in + * simulation. Otherwise, exact value is unimportant for HDMI + * operation." This conflicts with bcm2835's vc4 documentation, which + * states HSM's clock has to be at least 108% of the pixel clock. + * + * Real life tests reveal that vc4's firmware statement holds up, and + * users are able to use pixel clocks closer to HSM's, namely for + * 1920x1200@60Hz. So it was decided to have leave a 1% margin between + * both clocks. Which, for RPi0-3 implies a maximum pixel clock of + * 162MHz. + * + * Additionally, the AXI clock needs to be at least 25% of + * 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); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); @@ -757,22 +773,6 @@ static enum drm_mode_status vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) { - /* - * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must - * be faster than pixel clock, infinitesimally faster, tested in - * simulation. Otherwise, exact value is unimportant for HDMI - * operation." This conflicts with bcm2835's vc4 documentation, which - * states HSM's clock has to be at least 108% of the pixel clock. - * - * Real life tests reveal that vc4's firmware statement holds up, and - * users are able to use pixel clocks closer to HSM's, namely for - * 1920x1200@60Hz. So it was decided to have leave a 1% margin between - * both clocks. Which, for RPi0-3 implies a maximum pixel clock of - * 162MHz. - * - * Additionally, the AXI clock needs to be at least 25% of - * pixel clock, but HSM ends up being the limiting factor. - */ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) @@ -794,7 +794,7 @@ static u32 vc4_hdmi_get_hsm_clock(struct vc4_hdmi *vc4_hdmi) static u32 vc5_hdmi_get_hsm_clock(struct vc4_hdmi *vc4_hdmi) { - return 108000000; + return 120000000; } static u32 vc4_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate) @@ -815,7 +815,7 @@ static u32 vc5_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixe * Use 101% as this is what the firmware uses. */ - return max_t(unsigned long, 108000000, (pixel_rate / 100) * 101); + return max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); } static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) -- 2.7.4 From d0a23476008384650b5d08111f456649bf425df3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:07:16 +0900 Subject: [PATCH 06/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 07/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 08/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 09/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 10/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 11/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 12/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 13/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 14/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 15/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 16/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