From 40cac8ff38eccad624d5d6a5135660fb8fae1bad Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 25 Nov 2021 14:46:55 +0000 Subject: [PATCH 1/4] drm/vc4: Move HDMI reset to pm_resume Pi0-3 have power domains attached to the pm_runtime hooks for the HDMI block. Initialisation done in the reset called from bind is therefore lost if all users of the domain are suspended. The VEC shares the same lowest level clock/power gating as the HDMI block, so whilst that is enabled the block is never actually powered down, but if it isn't enabled then we lose the state. Reset and initialise the HDMI block from pm_resume. Signed-off-by: Dave Stevenson --- drivers/gpu/drm/vc4/vc4_hdmi.c | 61 ++++++++++++++++++----------- drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 +- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 807cf15e213029..702101b3fdf1c9 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2242,7 +2242,6 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) struct platform_device *pdev = vc4_hdmi->pdev; struct device *dev = &pdev->dev; unsigned long flags; - u32 value; int ret; if (!of_find_property(dev->of_node, "interrupts", NULL)) { @@ -2261,15 +2260,6 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - value = HDMI_READ(HDMI_CEC_CNTRL_1); - /* Set the logical address to Unregistered */ - value |= VC4_HDMI_CEC_ADDR_MASK; - HDMI_WRITE(HDMI_CEC_CNTRL_1, value); - spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - - vc4_hdmi_cec_update_clk_div(vc4_hdmi); - if (vc4_hdmi->variant->external_irq_controller) { ret = request_threaded_irq(platform_get_irq_byname(pdev, "cec-rx"), vc4_cec_irq_handler_rx_bare, @@ -2332,6 +2322,29 @@ static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) cec_unregister_adapter(vc4_hdmi->cec_adap); } + +static int vc4_hdmi_cec_resume(struct vc4_hdmi *vc4_hdmi) +{ + unsigned long flags; + u32 value; + + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + value = HDMI_READ(HDMI_CEC_CNTRL_1); + /* Set the logical address to Unregistered */ + value |= VC4_HDMI_CEC_ADDR_MASK; + HDMI_WRITE(HDMI_CEC_CNTRL_1, value); + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + vc4_hdmi_cec_update_clk_div(vc4_hdmi); + + if (!vc4_hdmi->variant->external_irq_controller) { + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff); + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + + return 0; +} #else static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) { @@ -2340,6 +2353,10 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {}; +static void vc4_hdmi_cec_resume(struct vc4_hdmi *vc4_hdmi) +{ + return 0; +} #endif static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi, @@ -2575,6 +2592,15 @@ static int vc4_hdmi_runtime_resume(struct device *dev) if (ret) return ret; + if (vc4_hdmi->variant->reset) + vc4_hdmi->variant->reset(vc4_hdmi); + + ret = vc4_hdmi_cec_resume(vc4_hdmi); + if (ret) { + clk_disable_unprepare(vc4_hdmi->hsm_clock); + return ret; + } + return 0; } #endif @@ -2688,20 +2714,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (ret) goto err_put_ddc; - /* - * We need to have the device powered up at this point to call - * our reset hook and for the CEC init. - */ - ret = vc4_hdmi_runtime_resume(dev); - if (ret) - goto err_put_ddc; - - pm_runtime_get_noresume(dev); - pm_runtime_set_active(dev); pm_runtime_enable(dev); - if (vc4_hdmi->variant->reset) - vc4_hdmi->variant->reset(vc4_hdmi); + ret = pm_runtime_resume_and_get(dev); + if (ret) + goto err_put_ddc; if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h index 24056441a4bb64..72b76941248294 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h @@ -417,7 +417,7 @@ static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi, const struct vc4_hdmi_variant *variant = hdmi->variant; void __iomem *base; - WARN_ON(!pm_runtime_active(&hdmi->pdev->dev)); + WARN_ON(pm_runtime_status_suspended(&hdmi->pdev->dev)); if (reg >= variant->num_registers) { dev_warn(&hdmi->pdev->dev, @@ -447,7 +447,7 @@ static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi, lockdep_assert_held(&hdmi->hw_lock); - WARN_ON(!pm_runtime_active(&hdmi->pdev->dev)); + WARN_ON(pm_runtime_status_suspended(&hdmi->pdev->dev)); if (reg >= variant->num_registers) { dev_warn(&hdmi->pdev->dev, From 3bf50b14bd49fd12cb1590f39de824da70c5da8b Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 2 Dec 2021 13:53:36 +0000 Subject: [PATCH 2/4] clk: bcm: rpi: Add the BCM283x pixel clock. The clk-bcm2835 handling of the pixel clock does not function correctly when the HDMI power domain is disabled. The firmware supports it correctly, so add it to the firmware clock driver. Signed-off-by: Dave Stevenson --- drivers/clk/bcm/clk-raspberrypi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 0e3be5ec61ca35..c307e054f805b1 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -276,6 +276,7 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi, case RPI_FIRMWARE_HEVC_CLK_ID: case RPI_FIRMWARE_PIXEL_BVB_CLK_ID: case RPI_FIRMWARE_VEC_CLK_ID: + case RPI_FIRMWARE_PIXEL_CLK_ID: hw = raspberrypi_clk_register(rpi, clks->parent, clks->id); if (IS_ERR(hw)) From 58eebb7a3dfd35084798d0ebb64d0628aacd55b0 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 2 Dec 2021 14:11:09 +0000 Subject: [PATCH 3/4] dt: bcm283x: Change BCM283x HDMI to use firmware clock driver The clk-bcm2835 handling of the pixel clock does not function correctly when the HDMI power domain is disabled. The firmware supports it correctly, and the firmware clock driver now supports it, so switch the vc4-hdmi driver to use the firmware clock driver. Signed-off-by: Dave Stevenson --- arch/arm/boot/dts/bcm2835-common.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm2835-common.dtsi b/arch/arm/boot/dts/bcm2835-common.dtsi index 15f3975f1ca183..7f46a6ec512c1b 100644 --- a/arch/arm/boot/dts/bcm2835-common.dtsi +++ b/arch/arm/boot/dts/bcm2835-common.dtsi @@ -128,7 +128,7 @@ "hd"; interrupts = <2 8>, <2 9>; ddc = <&i2c2>; - clocks = <&clocks BCM2835_PLLH_PIX>, + clocks = <&firmware_clocks 9>, <&clocks BCM2835_CLOCK_HSM>; clock-names = "pixel", "hdmi"; dmas = <&dma (17|(1<<27)|(1<<24))>; From f2e8c8a3ab4e9beb2bca92aa0a6c9f0d329f0db1 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 26 Nov 2021 17:59:07 +0000 Subject: [PATCH 4/4] Revert "Revert "overlays: vc4-kms-v3d: Change composite handling"" Reinstates the new handling. This reverts commit 46c99e3d7cf38446491b3c2a826fc05dcebc588d. Signed-off-by: Dave Stevenson --- arch/arm/boot/dts/overlays/README | 4 ++-- arch/arm/boot/dts/overlays/upstream-overlay.dts | 2 +- arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index 8e4939377c40f4..bedb501b3ce528 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -3620,8 +3620,8 @@ Params: cma-512 CMA is 512MB (needs 1GB) cma-default Use upstream's default value audio Enable or disable audio over HDMI (default "on") noaudio Disable all HDMI audio (default "off") - nocomposite Disable the composite video output (default - "off") + composite Enable the composite output (default "off") + N.B. Disables all other outputs on a Pi 4. Name: vc4-kms-v3d-pi4 diff --git a/arch/arm/boot/dts/overlays/upstream-overlay.dts b/arch/arm/boot/dts/overlays/upstream-overlay.dts index 7c4071a7cb2702..2852bea52309bd 100644 --- a/arch/arm/boot/dts/overlays/upstream-overlay.dts +++ b/arch/arm/boot/dts/overlays/upstream-overlay.dts @@ -1,4 +1,4 @@ -// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-default dwc2-overlay.dts,dr_mode=otg +// redo: ovmerge -c vc4-kms-v3d-overlay.dts,cma-default,composite dwc2-overlay.dts,dr_mode=otg /dts-v1/; /plugin/; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts index 62e1d77a8182cf..351fc160e8030d 100644 --- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts +++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts @@ -89,7 +89,7 @@ fragment@11 { target = <&vec>; - __overlay__ { + __dormant__ { status = "okay"; }; }; @@ -118,6 +118,6 @@ __overrides__ { audio = <0>,"!13"; noaudio = <0>,"=13"; - nocomposite = <0>, "!11"; + composite = <0>, "=11"; }; };