From 6ce0551118c96967af02342d3701a0f03be9b18a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Mon, 31 Jan 2022 19:29:07 +0100 Subject: [PATCH] Remove some RPI patches --- ...2835-Remove-rounding-up-the-dividers.patch | 77 - ...-drm-vc4-hdmi-Set-a-default-HSM-rate.patch | 56 - ...e-the-HSM-clock-enable-to-runtime_pm.patch | 164 -- ...e-sure-the-controller-is-powered-in-.patch | 52 - ...e-sure-the-controller-is-powered-up-.patch | 72 - ...ork-the-pre_crtc_configure-error-han.patch | 81 - ...it-the-CEC-disable-enable-functions-.patch | 116 - ...e-sure-the-device-is-powered-with-CE.patch | 56 - ...n-if-we-access-the-controller-while-.patch | 54 - ...e-sure-the-HDMI-controller-is-powere.patch | 84 - ...rm-vc4-crtc-Drop-feed_txp-from-state.patch | 154 - ...blocking-commit-getting-stuck-foreve.patch | 144 - ...tc-Copy-assigned-channel-to-the-CRTC.patch | 114 - ...-a-spinlock-to-protect-register-acce.patch | 916 ------ ...-a-mutex-to-prevent-concurrent-frame.patch | 449 --- ...vent-access-to-crtc-state-outside-of.patch | 168 -- ...mi-Check-the-device-state-in-prepare.patch | 82 - ...dmi-Introduce-an-output_enabled-flag.patch | 85 - ...4-hdmi-Introduce-a-scdc_enabled-flag.patch | 108 - ...ove-the-DDC-probing-for-status-detec.patch | 50 - ...-drm-vc4-hdmi-Fix-HPD-GPIO-detection.patch | 43 - ...vc4-Make-vc4_crtc_get_encoder-public.patch | 52 - ...-encoder-to-vc4_crtc_config_pv-proto.patch | 48 - ...ork-the-encoder-retrieval-code-again.patch | 102 - .../0025-drm-vc4-crtc-Add-some-logging.patch | 43 - ...rage-the-load-tracker-on-the-BCM2711.patch | 134 - ...c4-hdmi-Raise-the-maximum-clock-rate.patch | 35 - ...Enable-the-scrambler-on-reconnection.patch | 43 - ...ase-the-core-clock-based-on-HVS-load.patch | 247 -- .../patches-5.15/0030-drm-vc4-select-PM.patch | 29 - ...ually-check-for-the-connector-status.patch | 65 - ...2835-Change-init-order-for-gpio-hogs.patch | 83 - ...e-dma-configuration-from-the-HVS-or-.patch | 59 - ...ort-for-DRM_FORMAT_P030-to-vc4-plane.patch | 168 -- ...ort-for-YUV-color-encodings-and-rang.patch | 146 - ...-as-an-acceptable-node-for-dma-range.patch | 32 - ...resent-but-empty-dmas-disables-audio.patch | 38 - ...gfs-node-that-dumps-the-current-disp.patch | 75 - ...the-HDMI-registers-into-the-debugfs-.patch | 102 - ...-the-2711-HVS-as-a-suitable-DMA-node.patch | 29 - ...nused-infoframe-packet-RAM-registers.patch | 50 - ...he-default-DPI-format-to-being-18bpp.patch | 39 - ...rm-Avoid-full-hdmi-audio-fifo-writes.patch | 37 - ...-source-offsets-with-DRM_FORMAT_P030.patch | 77 - ...ne-Remove-subpixel-positioning-check.patch | 67 - ...e-Support-2020-colourspace-for-yuv-p.patch | 112 - ...Convert-to-the-new-clock-request-API.patch | 47 - ...drm-vc4-Correct-pixel-order-for-DSI0.patch | 32 - ...-dsi0-as-the-correct-vc4-encoder-typ.patch | 34 - ...0-drm-vc4-Fix-dsi0-interrupt-support.patch | 193 -- ...ect-stop-condition-to-vc4_dsi_encode.patch | 35 - ...LCLK-modes-even-if-horz-timing-is-od.patch | 47 - ...ase-the-core-clock-based-on-HVS-load.patch | 65 - ...mplify-the-connector-state-retrieval.patch | 56 - ...vc4-Fix-timings-for-interlaced-modes.patch | 90 - ...in-calculations-for-the-right-bottom.patch | 43 - ...70-drm-vc4-Fix-timings-for-VEC-modes.patch | 155 - ...drm-vc4-Refactor-VEC-TV-mode-setting.patch | 172 -- ...drm-vc4-Fix-definition-of-PAL-M-mode.patch | 82 - ...support-for-more-analog-TV-standards.patch | 153 - ...tting-the-TV-norm-via-module-paramet.patch | 149 - ...drm-vc4-Refactor-mode-checking-logic.patch | 90 - ...onflicting-framebuffers-before-calli.patch | 42 - ...y-the-firmware-when-DRM-is-in-charge.patch | 61 - .../0478-drm-vc4-Add-firmware-kms-mode.patch | 2518 ----------------- ...mi-Unregister-codec-device-on-unbind.patch | 63 - ...vc4-fix-vc4_atomic_commit_tail-logic.patch | 134 - ...vc4-Reset-HDMI-MISC_CONTROL-register.patch | 76 - ...workaround-buffer-and-DMA-in-error-p.patch | 150 - ...vc4-Correct-DSI-divider-calculations.patch | 40 - ...0587-Add-missing-drm_crtc_commit_put.patch | 26 - ...-the-commit-before-starting-our-cloc.patch | 88 - ...vert-Add-missing-drm_crtc_commit_put.patch | 26 - ...vc4-Add-support-for-gamma-on-BCM2711.patch | 283 -- ...gfs-node-that-dumps-the-vc5-gamma-PW.patch | 119 - ...vs-Force-modeset-on-gamma-lut-change.patch | 114 - ...C-modeline-requirements-and-add-prog.patch | 163 -- ...-progressive-modes-readily-accessibl.patch | 171 -- ...-kms-Add-missing-drm_crtc_commit_put.patch | 35 - ...11-drm-vc4-kms-Fix-return-code-check.patch | 69 - ...r-the-HVS-FIFO-commit-pointer-once-d.patch | 40 - ...4-kms-Don-t-duplicate-pending-commit.patch | 42 - ...vc4-kms-Fix-previous-HVS-commit-wait.patch | 89 - ...-Move-clock-request-to-our-HVS-state.patch | 66 - ...nable-gamma-block-only-when-required.patch | 71 - ...m-vc4-Only-add-gamma-properties-once.patch | 31 - ...4-Validate-the-size-of-the-gamma_lut.patch | 37 - ...c4-Don-t-try-disabling-SCDC-on-Pi0-3.patch | 37 - ...fix-VIDIOC_DQEVENT-handling-on-non-x.patch | 136 - 89 files changed, 11207 deletions(-) delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0001-clk-bcm-2835-Remove-rounding-up-the-dividers.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0002-drm-vc4-hdmi-Set-a-default-HSM-rate.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0003-drm-vc4-hdmi-Move-the-HSM-clock-enable-to-runtime_pm.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0004-drm-vc4-hdmi-Make-sure-the-controller-is-powered-in-.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0005-drm-vc4-hdmi-Make-sure-the-controller-is-powered-up-.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0006-drm-vc4-hdmi-Rework-the-pre_crtc_configure-error-han.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0007-drm-vc4-hdmi-Split-the-CEC-disable-enable-functions-.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0008-drm-vc4-hdmi-Make-sure-the-device-is-powered-with-CE.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0009-drm-vc4-hdmi-Warn-if-we-access-the-controller-while-.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0010-drm-vc4-crtc-Make-sure-the-HDMI-controller-is-powere.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0011-drm-vc4-crtc-Drop-feed_txp-from-state.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0012-drm-vc4-Fix-non-blocking-commit-getting-stuck-foreve.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0013-drm-vc4-crtc-Copy-assigned-channel-to-the-CRTC.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0014-drm-vc4-hdmi-Add-a-spinlock-to-protect-register-acce.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0015-drm-vc4-hdmi-Use-a-mutex-to-prevent-concurrent-frame.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0016-drm-vc4-hdmi-Prevent-access-to-crtc-state-outside-of.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0017-drm-vc4-hdmi-Check-the-device-state-in-prepare.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0018-drm-vc4-hdmi-Introduce-an-output_enabled-flag.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0019-drm-vc4-hdmi-Introduce-a-scdc_enabled-flag.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0020-drm-vc4-hdmi-Remove-the-DDC-probing-for-status-detec.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0021-drm-vc4-hdmi-Fix-HPD-GPIO-detection.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0022-drm-vc4-Make-vc4_crtc_get_encoder-public.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0023-drm-vc4-crtc-Add-encoder-to-vc4_crtc_config_pv-proto.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0024-drm-vc4-crtc-Rework-the-encoder-retrieval-code-again.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0025-drm-vc4-crtc-Add-some-logging.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0026-drm-vc4-Leverage-the-load-tracker-on-the-BCM2711.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0027-drm-vc4-hdmi-Raise-the-maximum-clock-rate.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0028-drm-vc4-hdmi-Enable-the-scrambler-on-reconnection.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0029-drm-vc4-Increase-the-core-clock-based-on-HVS-load.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0030-drm-vc4-select-PM.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0032-drm-vc4-hdmi-Actually-check-for-the-connector-status.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0204-pinctrl-bcm2835-Change-init-order-for-gpio-hogs.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0441-drm-vc4-Adopt-the-dma-configuration-from-the-HVS-or-.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0443-drm-vc4-Add-support-for-DRM_FORMAT_P030-to-vc4-plane.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0444-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0445-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0446-drm-vc4-A-present-but-empty-dmas-disables-audio.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0447-drm-vc4-Add-debugfs-node-that-dumps-the-current-disp.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0448-drm-vc4-Add-all-the-HDMI-registers-into-the-debugfs-.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0449-drm-vc4-Add-the-2711-HVS-as-a-suitable-DMA-node.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0451-vc4-Clear-unused-infoframe-packet-RAM-registers.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0452-drm-vc4-Change-the-default-DPI-format-to-being-18bpp.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0453-vc4-drm-Avoid-full-hdmi-audio-fifo-writes.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0454-vc4-drm-Fix-source-offsets-with-DRM_FORMAT_P030.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0455-vc4-drm-vc4_plane-Remove-subpixel-positioning-check.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0456-vc4-kms-vc4_plane-Support-2020-colourspace-for-yuv-p.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0457-drm-vc4-hdmi-Convert-to-the-new-clock-request-API.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0458-drm-vc4-Correct-pixel-order-for-DSI0.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0459-drm-vc4-Register-dsi0-as-the-correct-vc4-encoder-typ.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0460-drm-vc4-Fix-dsi0-interrupt-support.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0461-drm-vc4-Add-correct-stop-condition-to-vc4_dsi_encode.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0463-drm-vc4-Allow-DBLCLK-modes-even-if-horz-timing-is-od.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0465-drm-vc4-Increase-the-core-clock-based-on-HVS-load.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0466-drm-vc4-hdmi-Simplify-the-connector-state-retrieval.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0467-drm-vc4-Fix-timings-for-interlaced-modes.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0469-drm-vc4-Fix-margin-calculations-for-the-right-bottom.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0470-drm-vc4-Fix-timings-for-VEC-modes.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0471-drm-vc4-Refactor-VEC-TV-mode-setting.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0472-drm-vc4-Fix-definition-of-PAL-M-mode.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0473-drm-vc4-Add-support-for-more-analog-TV-standards.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0474-drm-vc4-Allow-setting-the-TV-norm-via-module-paramet.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0475-drm-vc4-Refactor-mode-checking-logic.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0476-drm-vc4-Remove-conflicting-framebuffers-before-calli.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0477-drm-vc4-Notify-the-firmware-when-DRM-is-in-charge.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0478-drm-vc4-Add-firmware-kms-mode.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0484-drm-vc4-hdmi-Unregister-codec-device-on-unbind.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0485-drm-vc4-fix-vc4_atomic_commit_tail-logic.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0505-drm-vc4-Reset-HDMI-MISC_CONTROL-register.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0506-drm-vc4-Release-workaround-buffer-and-DMA-in-error-p.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0507-drm-vc4-Correct-DSI-divider-calculations.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0587-Add-missing-drm_crtc_commit_put.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0588-drm-vc4-Wait-for-the-commit-before-starting-our-cloc.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0589-Revert-Add-missing-drm_crtc_commit_put.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0594-drm-vc4-Add-support-for-gamma-on-BCM2711.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0595-drm-vc4-Add-debugfs-node-that-dumps-the-vc5-gamma-PW.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0596-drm-vc4-hvs-Force-modeset-on-gamma-lut-change.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0598-drm-vc4-Relax-VEC-modeline-requirements-and-add-prog.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0599-drm-vc4-Make-VEC-progressive-modes-readily-accessibl.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0610-drm-vc4-kms-Add-missing-drm_crtc_commit_put.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0611-drm-vc4-kms-Fix-return-code-check.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0612-drm-vc4-kms-Clear-the-HVS-FIFO-commit-pointer-once-d.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0613-drm-vc4-kms-Don-t-duplicate-pending-commit.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0614-drm-vc4-kms-Fix-previous-HVS-commit-wait.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0615-drm-vc4-kms-Move-clock-request-to-our-HVS-state.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0625-drm-vc4-Enable-gamma-block-only-when-required.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0626-drm-vc4-Only-add-gamma-properties-once.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0628-drm-vc4-Validate-the-size-of-the-gamma_lut.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0629-drm-vc4-Don-t-try-disabling-SCDC-on-Pi0-3.patch delete mode 100644 root/target/linux/bcm27xx/patches-5.15/0631-media-v4l2-core-fix-VIDIOC_DQEVENT-handling-on-non-x.patch diff --git a/root/target/linux/bcm27xx/patches-5.15/0001-clk-bcm-2835-Remove-rounding-up-the-dividers.patch b/root/target/linux/bcm27xx/patches-5.15/0001-clk-bcm-2835-Remove-rounding-up-the-dividers.patch deleted file mode 100644 index 1db49c4f..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0001-clk-bcm-2835-Remove-rounding-up-the-dividers.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 4b7a4389846c44ff6a3590027d25aefd796b50f4 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 22 Sep 2021 14:54:16 +0200 -Subject: [PATCH 001/634] clk: bcm-2835: Remove rounding up the dividers - -The driver, once it found a divider, tries to round it up by increasing -the least significant bit of the fractional part by one when the -round_up argument is set and there's a remainder. - -However, since it increases the divider it will actually reduce the -clock rate below what we were asking for, leading to issues with -clk_set_min_rate() that will complain that our rounded clock rate is -below the minimum of the rate. - -Since the dividers are fairly precise already, let's remove that part so -that we can have clk_set_min_rate() working. - -This is effectively a revert of 9c95b32ca093 ("clk: bcm2835: add a round -up ability to the clock divisor"). - -Fixes: 9c95b32ca093 ("clk: bcm2835: add a round up ability to the clock divisor") -Signed-off-by: Maxime Ripard -Acked-by: Stephen Boyd -Reviewed-by: Nicolas Saenz Julienne -Tested-by: Nicolas Saenz Julienne # boot and basic functionality -Tested-by: Michael Stapelberg -Link: https://patchwork.freedesktop.org/patch/msgid/20210922125419.4125779-3-maxime@cerno.tech ---- - drivers/clk/bcm/clk-bcm2835.c | 11 +++-------- - 1 file changed, 3 insertions(+), 8 deletions(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index bf97b2b2a63f..3667b4d731e7 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -932,8 +932,7 @@ static int bcm2835_clock_is_on(struct clk_hw *hw) - - static u32 bcm2835_clock_choose_div(struct clk_hw *hw, - unsigned long rate, -- unsigned long parent_rate, -- bool round_up) -+ unsigned long parent_rate) - { - struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); - const struct bcm2835_clock_data *data = clock->data; -@@ -945,10 +944,6 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, - - rem = do_div(temp, rate); - div = temp; -- -- /* Round up and mask off the unused bits */ -- if (round_up && ((div & unused_frac_mask) != 0 || rem != 0)) -- div += unused_frac_mask + 1; - div &= ~unused_frac_mask; - - /* different clamping limits apply for a mash clock */ -@@ -1079,7 +1074,7 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, - struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); - struct bcm2835_cprman *cprman = clock->cprman; - const struct bcm2835_clock_data *data = clock->data; -- u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false); -+ u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate); - u32 ctl; - - spin_lock(&cprman->regs_lock); -@@ -1130,7 +1125,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, - - if (!(BIT(parent_idx) & data->set_rate_parent)) { - *prate = clk_hw_get_rate(parent); -- *div = bcm2835_clock_choose_div(hw, rate, *prate, true); -+ *div = bcm2835_clock_choose_div(hw, rate, *prate); - - *avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div); - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0002-drm-vc4-hdmi-Set-a-default-HSM-rate.patch b/root/target/linux/bcm27xx/patches-5.15/0002-drm-vc4-hdmi-Set-a-default-HSM-rate.patch deleted file mode 100644 index 0f9efeb3..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0002-drm-vc4-hdmi-Set-a-default-HSM-rate.patch +++ /dev/null @@ -1,56 +0,0 @@ -From b6b62f912d8aa4bd47780b3de56dc35ee820aad9 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 22 Sep 2021 14:54:17 +0200 -Subject: [PATCH 002/634] drm/vc4: hdmi: Set a default HSM rate - -When the firmware doesn't setup the HSM rate (such as when booting -without an HDMI cable plugged in), its rate is 0 and thus any register -access results in a CPU stall, even though HSM is enabled. - -Let's enforce a minimum rate at boot to avoid this issue. - -Fixes: 4f6e3d66ac52 ("drm/vc4: Add runtime PM support to the HDMI encoder driver") -Signed-off-by: Maxime Ripard -Reviewed-by: Nicolas Saenz Julienne -Tested-by: Nicolas Saenz Julienne -Tested-by: Michael Stapelberg -Link: https://patchwork.freedesktop.org/patch/msgid/20210922125419.4125779-4-maxime@cerno.tech ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index ed8a4b7f8b6e..623a4699bd21 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -94,6 +94,7 @@ - # define VC4_HD_M_SW_RST BIT(2) - # define VC4_HD_M_ENABLE BIT(0) - -+#define HSM_MIN_CLOCK_FREQ 120000000 - #define CEC_CLOCK_FREQ 40000 - - #define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) -@@ -2161,6 +2162,19 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) - vc4_hdmi->disable_4kp60 = true; - } - -+ /* -+ * If we boot without any cable connected to the HDMI connector, -+ * the firmware will skip the HSM initialization and leave it -+ * with a rate of 0, resulting in a bus lockup when we're -+ * accessing the registers even if it's enabled. -+ * -+ * Let's put a sensible default at runtime_resume so that we -+ * don't end up in this situation. -+ */ -+ ret = clk_set_min_rate(vc4_hdmi->hsm_clock, HSM_MIN_CLOCK_FREQ); -+ if (ret) -+ goto err_put_ddc; -+ - if (vc4_hdmi->variant->reset) - vc4_hdmi->variant->reset(vc4_hdmi); - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0003-drm-vc4-hdmi-Move-the-HSM-clock-enable-to-runtime_pm.patch b/root/target/linux/bcm27xx/patches-5.15/0003-drm-vc4-hdmi-Move-the-HSM-clock-enable-to-runtime_pm.patch deleted file mode 100644 index 188a617b..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0003-drm-vc4-hdmi-Move-the-HSM-clock-enable-to-runtime_pm.patch +++ /dev/null @@ -1,164 +0,0 @@ -From bfb78996b5fb1fb937541a17f58afdcbf7e6a8a5 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 22 Sep 2021 14:54:18 +0200 -Subject: [PATCH 003/634] drm/vc4: hdmi: Move the HSM clock enable to - runtime_pm - -In order to access the HDMI controller, we need to make sure the HSM -clock is enabled. If we were to access it with the clock disabled, the -CPU would completely hang, resulting in an hard crash. - -Since we have different code path that would require it, let's move that -clock enable / disable to runtime_pm that will take care of the -reference counting for us. - -Since we also want to change the HSM clock rate and it's only valid -while the clock is disabled, we need to move the clk_set_min_rate() call -on the HSM clock above pm_runtime_get_and_sync(). - -Fixes: 4f6e3d66ac52 ("drm/vc4: Add runtime PM support to the HDMI encoder driver") -Signed-off-by: Maxime Ripard -Reviewed-by: Dave Stevenson -Reviewed-by: Nicolas Saenz Julienne -Tested-by: Nicolas Saenz Julienne -Tested-by: Michael Stapelberg -Link: https://patchwork.freedesktop.org/patch/msgid/20210922125419.4125779-5-maxime@cerno.tech -Link: https://lore.kernel.org/linux-arm-kernel/20210924152334.1342630-1-maxime@cerno.tech/ ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 70 +++++++++++++++++++++------------- - 1 file changed, 44 insertions(+), 26 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 623a4699bd21..6b0700d0b408 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -628,7 +628,6 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, - vc4_hdmi->variant->phy_disable(vc4_hdmi); - - clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); -- clk_disable_unprepare(vc4_hdmi->hsm_clock); - clk_disable_unprepare(vc4_hdmi->pixel_clock); - - ret = pm_runtime_put(&vc4_hdmi->pdev->dev); -@@ -894,28 +893,10 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - conn_state_to_vc4_hdmi_conn_state(conn_state); - struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -- unsigned long bvb_rate, pixel_rate, hsm_rate; -+ unsigned long pixel_rate = vc4_conn_state->pixel_rate; -+ unsigned long bvb_rate, hsm_rate; - int ret; - -- ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); -- if (ret < 0) { -- DRM_ERROR("Failed to retain power domain: %d\n", ret); -- return; -- } -- -- pixel_rate = vc4_conn_state->pixel_rate; -- ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate); -- if (ret) { -- DRM_ERROR("Failed to set pixel clock rate: %d\n", ret); -- return; -- } -- -- ret = clk_prepare_enable(vc4_hdmi->pixel_clock); -- if (ret) { -- DRM_ERROR("Failed to turn on pixel clock: %d\n", ret); -- return; -- } -- - /* - * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must - * be faster than pixel clock, infinitesimally faster, tested in -@@ -939,10 +920,21 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - return; - } - -- ret = clk_prepare_enable(vc4_hdmi->hsm_clock); -+ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); -+ if (ret < 0) { -+ DRM_ERROR("Failed to retain power domain: %d\n", ret); -+ return; -+ } -+ -+ ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate); - if (ret) { -- DRM_ERROR("Failed to turn on HSM clock: %d\n", ret); -- clk_disable_unprepare(vc4_hdmi->pixel_clock); -+ DRM_ERROR("Failed to set pixel clock rate: %d\n", ret); -+ return; -+ } -+ -+ ret = clk_prepare_enable(vc4_hdmi->pixel_clock); -+ if (ret) { -+ DRM_ERROR("Failed to turn on pixel clock: %d\n", ret); - return; - } - -@@ -958,7 +950,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate); - if (ret) { - DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); -- clk_disable_unprepare(vc4_hdmi->hsm_clock); - clk_disable_unprepare(vc4_hdmi->pixel_clock); - return; - } -@@ -966,7 +957,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); - if (ret) { - DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); -- clk_disable_unprepare(vc4_hdmi->hsm_clock); - clk_disable_unprepare(vc4_hdmi->pixel_clock); - return; - } -@@ -2099,6 +2089,27 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) - return 0; - } - -+static int __maybe_unused vc4_hdmi_runtime_suspend(struct device *dev) -+{ -+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); -+ -+ clk_disable_unprepare(vc4_hdmi->hsm_clock); -+ -+ return 0; -+} -+ -+static int vc4_hdmi_runtime_resume(struct device *dev) -+{ -+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = clk_prepare_enable(vc4_hdmi->hsm_clock); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ - static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) - { - const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); -@@ -2366,11 +2377,18 @@ static const struct of_device_id vc4_hdmi_dt_match[] = { - {} - }; - -+static const struct dev_pm_ops vc4_hdmi_pm_ops = { -+ SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend, -+ vc4_hdmi_runtime_resume, -+ NULL) -+}; -+ - struct platform_driver vc4_hdmi_driver = { - .probe = vc4_hdmi_dev_probe, - .remove = vc4_hdmi_dev_remove, - .driver = { - .name = "vc4_hdmi", - .of_match_table = vc4_hdmi_dt_match, -+ .pm = &vc4_hdmi_pm_ops, - }, - }; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0004-drm-vc4-hdmi-Make-sure-the-controller-is-powered-in-.patch b/root/target/linux/bcm27xx/patches-5.15/0004-drm-vc4-hdmi-Make-sure-the-controller-is-powered-in-.patch deleted file mode 100644 index 2a82dc92..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0004-drm-vc4-hdmi-Make-sure-the-controller-is-powered-in-.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 4bfb738710a3ea66e51eefbc8cd8e8673c84a5b3 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 22 Sep 2021 14:54:19 +0200 -Subject: [PATCH 004/634] drm/vc4: hdmi: Make sure the controller is powered in - detect - -If the HPD GPIO is not available and drm_probe_ddc fails, we end up -reading the HDMI_HOTPLUG register, but the controller might be powered -off resulting in a CPU hang. Make sure we have the power domain and the -HSM clock powered during the detect cycle to prevent the hang from -happening. - -Fixes: 4f6e3d66ac52 ("drm/vc4: Add runtime PM support to the HDMI encoder driver") -Signed-off-by: Maxime Ripard -Reviewed-by: Dave Stevenson -Reviewed-by: Nicolas Saenz Julienne -Tested-by: Nicolas Saenz Julienne -Tested-by: Michael Stapelberg -Link: https://patchwork.freedesktop.org/patch/msgid/20210922125419.4125779-6-maxime@cerno.tech ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 6b0700d0b408..21510ae31a9e 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -168,6 +168,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); - bool connected = false; - -+ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); -+ - if (vc4_hdmi->hpd_gpio && - gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) { - connected = true; -@@ -188,10 +190,12 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - } - } - -+ pm_runtime_put(&vc4_hdmi->pdev->dev); - return connector_status_connected; - } - - cec_phys_addr_invalidate(vc4_hdmi->cec_adap); -+ pm_runtime_put(&vc4_hdmi->pdev->dev); - return connector_status_disconnected; - } - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0005-drm-vc4-hdmi-Make-sure-the-controller-is-powered-up-.patch b/root/target/linux/bcm27xx/patches-5.15/0005-drm-vc4-hdmi-Make-sure-the-controller-is-powered-up-.patch deleted file mode 100644 index 581ff058..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0005-drm-vc4-hdmi-Make-sure-the-controller-is-powered-up-.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 977d70a849d52a89e8b9fd949b0339ff8e5c88f8 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 19 Aug 2021 15:59:27 +0200 -Subject: [PATCH 005/634] drm/vc4: hdmi: Make sure the controller is powered up - during bind - -In the bind hook, we actually need the device to have the HSM clock -running during the final part of the display initialisation where we -reset the controller and initialise the CEC component. - -Failing to do so will result in a complete, silent, hang of the CPU. - -Fixes: 411efa18e4b0 ("drm/vc4: hdmi: Move the HSM clock enable to runtime_pm") -Link: https://patchwork.freedesktop.org/patch/msgid/20210819135931.895976-3-maxime@cerno.tech -Reviewed-by: Dave Stevenson -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 17 +++++++++++++++-- - 1 file changed, 15 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 21510ae31a9e..2087717f1cce 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -2190,6 +2190,18 @@ 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); - -@@ -2201,8 +2213,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) - clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); - } - -- pm_runtime_enable(dev); -- - drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); - drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs); - -@@ -2226,6 +2236,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) - vc4_hdmi_debugfs_regs, - vc4_hdmi); - -+ pm_runtime_put_sync(dev); -+ - return 0; - - err_free_cec: -@@ -2236,6 +2248,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) - vc4_hdmi_connector_destroy(&vc4_hdmi->connector); - err_destroy_encoder: - drm_encoder_cleanup(encoder); -+ pm_runtime_put_sync(dev); - pm_runtime_disable(dev); - err_put_ddc: - put_device(&vc4_hdmi->ddc->dev); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0006-drm-vc4-hdmi-Rework-the-pre_crtc_configure-error-han.patch b/root/target/linux/bcm27xx/patches-5.15/0006-drm-vc4-hdmi-Rework-the-pre_crtc_configure-error-han.patch deleted file mode 100644 index 9516b7bc..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0006-drm-vc4-hdmi-Rework-the-pre_crtc_configure-error-han.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 98fa097e699cf1f9aeab523e109b06465b2e456a Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 19 Aug 2021 15:59:28 +0200 -Subject: [PATCH 006/634] drm/vc4: hdmi: Rework the pre_crtc_configure error - handling - -Since our pre_crtc_configure hook returned void, we didn't implement a -goto-based error path handling, leading to errors like failing to put -back the device in pm_runtime in all the error paths, but also failing -to disable the pixel clock if clk_set_min_rate on the HSM clock fails. - -Move to a goto-based implementation to have an easier consitency. - -Fixes: 4f6e3d66ac52 ("drm/vc4: Add runtime PM support to the HDMI encoder driver") -Link: https://patchwork.freedesktop.org/patch/msgid/20210819135931.895976-4-maxime@cerno.tech -Reviewed-by: Dave Stevenson -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 20 ++++++++++++++------ - 1 file changed, 14 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 2087717f1cce..49944644a9b3 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -933,15 +933,16 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate); - if (ret) { - DRM_ERROR("Failed to set pixel clock rate: %d\n", ret); -- return; -+ goto err_put_runtime_pm; - } - - ret = clk_prepare_enable(vc4_hdmi->pixel_clock); - if (ret) { - DRM_ERROR("Failed to turn on pixel clock: %d\n", ret); -- return; -+ goto err_put_runtime_pm; - } - -+ - vc4_hdmi_cec_update_clk_div(vc4_hdmi); - - if (pixel_rate > 297000000) -@@ -954,15 +955,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate); - if (ret) { - DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); -- clk_disable_unprepare(vc4_hdmi->pixel_clock); -- return; -+ goto err_disable_pixel_clock; - } - - ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); - if (ret) { - DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); -- clk_disable_unprepare(vc4_hdmi->pixel_clock); -- return; -+ goto err_disable_pixel_clock; - } - - if (vc4_hdmi->variant->phy_init) -@@ -975,6 +974,15 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - - if (vc4_hdmi->variant->set_timings) - vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode); -+ -+ return; -+ -+err_disable_pixel_clock: -+ clk_disable_unprepare(vc4_hdmi->pixel_clock); -+err_put_runtime_pm: -+ pm_runtime_put(&vc4_hdmi->pdev->dev); -+ -+ return; - } - - static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0007-drm-vc4-hdmi-Split-the-CEC-disable-enable-functions-.patch b/root/target/linux/bcm27xx/patches-5.15/0007-drm-vc4-hdmi-Split-the-CEC-disable-enable-functions-.patch deleted file mode 100644 index 3e6a873a..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0007-drm-vc4-hdmi-Split-the-CEC-disable-enable-functions-.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 9ae0103555f84dce8bf29859fb3f5820da07e34a Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 19 Aug 2021 15:59:29 +0200 -Subject: [PATCH 007/634] drm/vc4: hdmi: Split the CEC disable / enable - functions in two - -In order to ease further additions to the CEC enable and disable, let's -split the function into two functions, one to enable and the other to -disable. - -Reviewed-by: Dave Stevenson -Signed-off-by: Maxime Ripard -Link: https://patchwork.freedesktop.org/patch/msgid/20210819135931.895976-5-maxime@cerno.tech ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 75 ++++++++++++++++++++-------------- - 1 file changed, 45 insertions(+), 30 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 49944644a9b3..9b3c0009b2ed 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -1727,7 +1727,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) - return ret; - } - --static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) -+static int vc4_hdmi_cec_enable(struct cec_adapter *adap) - { - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - /* clock period in microseconds */ -@@ -1740,38 +1740,53 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) - val |= ((4700 / usecs) << VC4_HDMI_CEC_CNT_TO_4700_US_SHIFT) | - ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT); - -- if (enable) { -- HDMI_WRITE(HDMI_CEC_CNTRL_5, val | -- VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); -- HDMI_WRITE(HDMI_CEC_CNTRL_5, val); -- HDMI_WRITE(HDMI_CEC_CNTRL_2, -- ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) | -- ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) | -- ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) | -- ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) | -- ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT)); -- HDMI_WRITE(HDMI_CEC_CNTRL_3, -- ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) | -- ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) | -- ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) | -- ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT)); -- HDMI_WRITE(HDMI_CEC_CNTRL_4, -- ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) | -- ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) | -- ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) | -- ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT)); -- -- if (!vc4_hdmi->variant->external_irq_controller) -- HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC); -- } else { -- if (!vc4_hdmi->variant->external_irq_controller) -- HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC); -- HDMI_WRITE(HDMI_CEC_CNTRL_5, val | -- VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); -- } -+ HDMI_WRITE(HDMI_CEC_CNTRL_5, val | -+ VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); -+ HDMI_WRITE(HDMI_CEC_CNTRL_5, val); -+ HDMI_WRITE(HDMI_CEC_CNTRL_2, -+ ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) | -+ ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) | -+ ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) | -+ ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) | -+ ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT)); -+ HDMI_WRITE(HDMI_CEC_CNTRL_3, -+ ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) | -+ ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) | -+ ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) | -+ ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT)); -+ HDMI_WRITE(HDMI_CEC_CNTRL_4, -+ ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) | -+ ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) | -+ ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) | -+ ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT)); -+ -+ if (!vc4_hdmi->variant->external_irq_controller) -+ HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC); -+ -+ return 0; -+} -+ -+static int vc4_hdmi_cec_disable(struct cec_adapter *adap) -+{ -+ struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); -+ -+ if (!vc4_hdmi->variant->external_irq_controller) -+ HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC); -+ -+ HDMI_WRITE(HDMI_CEC_CNTRL_5, HDMI_READ(HDMI_CEC_CNTRL_5) | -+ VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); -+ - return 0; - } - -+static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) -+{ -+ if (enable) -+ return vc4_hdmi_cec_enable(adap); -+ else -+ return vc4_hdmi_cec_disable(adap); -+} -+ - static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) - { - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0008-drm-vc4-hdmi-Make-sure-the-device-is-powered-with-CE.patch b/root/target/linux/bcm27xx/patches-5.15/0008-drm-vc4-hdmi-Make-sure-the-device-is-powered-with-CE.patch deleted file mode 100644 index c1e42717..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0008-drm-vc4-hdmi-Make-sure-the-device-is-powered-with-CE.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 086555e0bcbdf8e2e6e9f9306323cb4bf84fb807 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 19 Aug 2021 15:59:30 +0200 -Subject: [PATCH 008/634] drm/vc4: hdmi: Make sure the device is powered with - CEC - -Similarly to what we encountered with the detect hook with DRM, nothing -actually prevents any of the CEC callback from being run while the HDMI -output is disabled. - -However, this is an issue since any register access to the controller -when it's powered down will result in a silent hang. - -Let's make sure we run the runtime_pm hooks when the CEC adapter is -opened and closed by the userspace to avoid that issue. - -Fixes: 15b4511a4af6 ("drm/vc4: add HDMI CEC support") -Reviewed-by: Dave Stevenson -Signed-off-by: Maxime Ripard -Link: https://patchwork.freedesktop.org/patch/msgid/20210819135931.895976-6-maxime@cerno.tech ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 9b3c0009b2ed..70101e09b245 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -1732,8 +1732,14 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - /* clock period in microseconds */ - const u32 usecs = 1000000 / CEC_CLOCK_FREQ; -- u32 val = HDMI_READ(HDMI_CEC_CNTRL_5); -+ u32 val; -+ int ret; -+ -+ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); -+ if (ret) -+ return ret; - -+ val = HDMI_READ(HDMI_CEC_CNTRL_5); - val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET | - VC4_HDMI_CEC_CNT_TO_4700_US_MASK | - VC4_HDMI_CEC_CNT_TO_4500_US_MASK); -@@ -1776,6 +1782,8 @@ static int vc4_hdmi_cec_disable(struct cec_adapter *adap) - HDMI_WRITE(HDMI_CEC_CNTRL_5, HDMI_READ(HDMI_CEC_CNTRL_5) | - VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); - -+ pm_runtime_put(&vc4_hdmi->pdev->dev); -+ - return 0; - } - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0009-drm-vc4-hdmi-Warn-if-we-access-the-controller-while-.patch b/root/target/linux/bcm27xx/patches-5.15/0009-drm-vc4-hdmi-Warn-if-we-access-the-controller-while-.patch deleted file mode 100644 index a1a1ddd9..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0009-drm-vc4-hdmi-Warn-if-we-access-the-controller-while-.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 54a0fd6b5fd8c0eeef7f3666ef1bbc2ce00cd779 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 19 Aug 2021 15:59:31 +0200 -Subject: [PATCH 009/634] drm/vc4: hdmi: Warn if we access the controller while - disabled - -We've had many silent hangs where the kernel would look like it just -stalled due to the access to one of the HDMI registers while the -controller was disabled. - -Add a warning if we're about to do that so that it's at least not silent -anymore. - -Reviewed-by: Dave Stevenson -Signed-off-by: Maxime Ripard -Link: https://patchwork.freedesktop.org/patch/msgid/20210819135931.895976-7-maxime@cerno.tech ---- - drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -index 19d2fdc446bc..99dde6e06a37 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -@@ -1,6 +1,8 @@ - #ifndef _VC4_HDMI_REGS_H_ - #define _VC4_HDMI_REGS_H_ - -+#include -+ - #include "vc4_hdmi.h" - - #define VC4_HDMI_PACKET_STRIDE 0x24 -@@ -412,6 +414,8 @@ 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)); -+ - if (reg >= variant->num_registers) { - dev_warn(&hdmi->pdev->dev, - "Invalid register ID %u\n", reg); -@@ -438,6 +442,8 @@ static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi, - const struct vc4_hdmi_variant *variant = hdmi->variant; - void __iomem *base; - -+ WARN_ON(!pm_runtime_active(&hdmi->pdev->dev)); -+ - if (reg >= variant->num_registers) { - dev_warn(&hdmi->pdev->dev, - "Invalid register ID %u\n", reg); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0010-drm-vc4-crtc-Make-sure-the-HDMI-controller-is-powere.patch b/root/target/linux/bcm27xx/patches-5.15/0010-drm-vc4-crtc-Make-sure-the-HDMI-controller-is-powere.patch deleted file mode 100644 index 98514154..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0010-drm-vc4-crtc-Make-sure-the-HDMI-controller-is-powere.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 7d9e3fd5588ff325e87844e3bcb0d167a9456e78 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 23 Sep 2021 20:50:13 +0200 -Subject: [PATCH 010/634] drm/vc4: crtc: Make sure the HDMI controller is - powered when disabling - -Since commit 875a4d536842 ("drm/vc4: drv: Disable the CRTC at boot -time"), during the initial setup of the driver we call into the VC4 HDMI -controller hooks to make sure the controller is properly disabled. - -However, we were never making sure that the device was properly powered -while doing so. This never resulted in any (reported) issue in practice, -but since the introduction of commit 4209f03fcb8e ("drm/vc4: hdmi: Warn -if we access the controller while disabled") we get a loud complaint -when we do that kind of access. - -Let's make sure we have the HDMI controller properly powered while -disabling it. - -Fixes: 875a4d536842 ("drm/vc4: drv: Disable the CRTC at boot time") -Signed-off-by: Maxime Ripard -Reviewed-by: Nicolas Saenz Julienne -Tested-by: Nicolas Saenz Julienne -Link: https://patchwork.freedesktop.org/patch/msgid/20210923185013.826679-1-maxime@cerno.tech ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 19 ++++++++++++++++++- - 1 file changed, 18 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 18f5009ce90e..c0df11e5fcf2 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -32,6 +32,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -42,6 +43,7 @@ - #include - - #include "vc4_drv.h" -+#include "vc4_hdmi.h" - #include "vc4_regs.h" - - #define HVS_FIFO_LATENCY_PIX 6 -@@ -496,8 +498,10 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc) - enum vc4_encoder_type encoder_type; - const struct vc4_pv_data *pv_data; - struct drm_encoder *encoder; -+ struct vc4_hdmi *vc4_hdmi; - unsigned encoder_sel; - int channel; -+ int ret; - - if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node, - "brcm,bcm2711-pixelvalve2") || -@@ -525,7 +529,20 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc) - if (WARN_ON(!encoder)) - return 0; - -- return vc4_crtc_disable(crtc, encoder, NULL, channel); -+ vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); -+ if (ret) -+ return ret; -+ -+ ret = vc4_crtc_disable(crtc, encoder, NULL, channel); -+ if (ret) -+ return ret; -+ -+ ret = pm_runtime_put(&vc4_hdmi->pdev->dev); -+ if (ret) -+ return ret; -+ -+ return 0; - } - - static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0011-drm-vc4-crtc-Drop-feed_txp-from-state.patch b/root/target/linux/bcm27xx/patches-5.15/0011-drm-vc4-crtc-Drop-feed_txp-from-state.patch deleted file mode 100644 index 9ebef506..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0011-drm-vc4-crtc-Drop-feed_txp-from-state.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 8dab6a99245dd443527dce15f99707b889c21248 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 18 Oct 2021 15:19:30 +0200 -Subject: [PATCH 011/634] drm/vc4: crtc: Drop feed_txp from state - -Accessing the crtc->state pointer from outside the modesetting context -is not allowed. We thus need to copy whatever we need from the KMS state -to our structure in order to access it. - -In VC4, a number of users of that pointers have crept in over the years, -the first one being whether or not the downstream controller of the -pixelvalve is our writeback controller. - -Fortunately for us, Since commit 39fcb2808376 ("drm/vc4: txp: Turn the -TXP into a CRTC of its own") this is no longer something that can change -from one commit to the other and is hardcoded. - -Let's set this flag in struct vc4_crtc if we happen to be the TXP, and -drop the flag from our private state structure. - -Link: https://lore.kernel.org/all/YWgteNaNeaS9uWDe@phenom.ffwll.local/ -Fixes: 008095e065a8 ("drm/vc4: Add support for the transposer block") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 3 +-- - drivers/gpu/drm/vc4/vc4_drv.h | 6 +++++- - drivers/gpu/drm/vc4/vc4_hvs.c | 7 +++---- - drivers/gpu/drm/vc4/vc4_kms.c | 3 ++- - drivers/gpu/drm/vc4/vc4_txp.c | 3 +-- - 5 files changed, 12 insertions(+), 10 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index c0df11e5fcf2..b90187d2c819 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -715,7 +715,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) - spin_lock_irqsave(&dev->event_lock, flags); - if (vc4_crtc->event && - (vc4_state->mm.start == HVS_READ(SCALER_DISPLACTX(chan)) || -- vc4_state->feed_txp)) { -+ vc4_crtc->feeds_txp)) { - drm_crtc_send_vblank_event(crtc, vc4_crtc->event); - vc4_crtc->event = NULL; - drm_crtc_vblank_put(crtc); -@@ -893,7 +893,6 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc) - return NULL; - - old_vc4_state = to_vc4_crtc_state(crtc->state); -- vc4_state->feed_txp = old_vc4_state->feed_txp; - vc4_state->margins = old_vc4_state->margins; - vc4_state->assigned_channel = old_vc4_state->assigned_channel; - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index ef73e0aaf726..3c69b89363cb 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -495,6 +495,11 @@ struct vc4_crtc { - struct drm_pending_vblank_event *event; - - struct debugfs_regset32 regset; -+ -+ /** -+ * @feeds_txp: True if the CRTC feeds our writeback controller. -+ */ -+ bool feeds_txp; - }; - - static inline struct vc4_crtc * -@@ -521,7 +526,6 @@ struct vc4_crtc_state { - struct drm_crtc_state base; - /* Dlist area for this CRTC configuration. */ - struct drm_mm_node mm; -- bool feed_txp; - bool txp_armed; - unsigned int assigned_channel; - -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index c239045e05d6..9ddaee6b368d 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -375,7 +375,7 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) - - spin_lock_irqsave(&dev->event_lock, flags); - -- if (!vc4_state->feed_txp || vc4_state->txp_armed) { -+ if (!vc4_crtc->feeds_txp || vc4_state->txp_armed) { - vc4_crtc->event = crtc->state->event; - crtc->state->event = NULL; - } -@@ -395,10 +395,9 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc, - { - struct drm_device *dev = crtc->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); -- struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); -- struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(new_crtc_state); - struct drm_display_mode *mode = &crtc->state->adjusted_mode; -- bool oneshot = vc4_state->feed_txp; -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ bool oneshot = vc4_crtc->feeds_txp; - - vc4_hvs_update_dlist(crtc); - vc4_hvs_init_channel(vc4, crtc, mode, oneshot); -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index f0b3e4cf5bce..028f19f7a5f8 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -233,6 +233,7 @@ static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, - unsigned int i; - - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); - u32 dispctrl; - u32 dsp3_mux; -@@ -253,7 +254,7 @@ static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, - * TXP IP, and we need to disable the FIFO2 -> pixelvalve1 - * route. - */ -- if (vc4_state->feed_txp) -+ if (vc4_crtc->feeds_txp) - dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX); - else - dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX); -diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c -index 2fc7f4b5fa09..26eda7542f74 100644 ---- a/drivers/gpu/drm/vc4/vc4_txp.c -+++ b/drivers/gpu/drm/vc4/vc4_txp.c -@@ -391,7 +391,6 @@ static int vc4_txp_atomic_check(struct drm_crtc *crtc, - { - struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, - crtc); -- struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); - int ret; - - ret = vc4_hvs_atomic_check(crtc, state); -@@ -399,7 +398,6 @@ static int vc4_txp_atomic_check(struct drm_crtc *crtc, - return ret; - - crtc_state->no_vblank = true; -- vc4_state->feed_txp = true; - - return 0; - } -@@ -482,6 +480,7 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) - - vc4_crtc->pdev = pdev; - vc4_crtc->data = &vc4_txp_crtc_data; -+ vc4_crtc->feeds_txp = true; - - txp->pdev = pdev; - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0012-drm-vc4-Fix-non-blocking-commit-getting-stuck-foreve.patch b/root/target/linux/bcm27xx/patches-5.15/0012-drm-vc4-Fix-non-blocking-commit-getting-stuck-foreve.patch deleted file mode 100644 index 371a4718..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0012-drm-vc4-Fix-non-blocking-commit-getting-stuck-foreve.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 7c65e42492d48ed03ce6b7e2346d5f969e30a62a Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 10 Jun 2021 17:48:28 +0200 -Subject: [PATCH 012/634] drm/vc4: Fix non-blocking commit getting stuck - forever - -In some situation, we can end up being stuck on a non-blocking that went -through properly. - -The situation that seems to trigger it reliably is to first start a -non-blocking commit, and then right after, and before we had any vblank -interrupt), start a blocking commit. - -This will lead to the first commit workqueue to be scheduled, setup the -display, while the second commit is waiting for the first one to be -completed. - -The vblank interrupt will then be raised, vc4_crtc_handle_vblank() will -run and will compare the active dlist in the HVS channel to the one -associated with the crtc->state. - -However, at that point, the second commit is waiting using -drm_atomic_helper_wait_for_dependencies that occurs after -drm_atomic_helper_swap_state has been called, so crtc->state points to -the second commit state. vc4_crtc_handle_vblank() will compare the two -dlist addresses and since they don't match will ignore the interrupt. - -The vblank event will never be reported, and the first and second commit -will wait for the first commit completion until they timeout. - -The underlying reason is that it was never safe to do so. Indeed, -accessing the ->state pointer access synchronization is based on -ownership guarantees that can only occur within the functions and hooks -defined as part of the KMS framework, and obviously the irq handler -isn't one of them. The rework to move to generic helpers only uncovered -the underlying issue. - -However, since the code path between -drm_atomic_helper_wait_for_dependencies() and -drm_atomic_helper_wait_for_vblanks() is serialised and we can't get two -commits in that path at the same time, we can work around this issue by -setting a variable associated to struct drm_crtc to the dlist we expect, -and then using it from the vc4_crtc_handle_vblank() function. - -Since that state is shared with the modesetting path, we also need to -introduce a spinlock to protect the code shared between the interrupt -handler and the modesetting path, protecting only our new variable for -now. - -Link: https://lore.kernel.org/all/YWgteNaNeaS9uWDe@phenom.ffwll.local/ -Fixes: 56d1fe0979dc ("drm/vc4: Make pageflip completion handling more robust.") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 5 ++++- - drivers/gpu/drm/vc4/vc4_drv.h | 14 ++++++++++++++ - drivers/gpu/drm/vc4/vc4_hvs.c | 7 +++++-- - 3 files changed, 23 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index b90187d2c819..98de8b265220 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -713,8 +713,9 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) - unsigned long flags; - - spin_lock_irqsave(&dev->event_lock, flags); -+ spin_lock(&vc4_crtc->irq_lock); - if (vc4_crtc->event && -- (vc4_state->mm.start == HVS_READ(SCALER_DISPLACTX(chan)) || -+ (vc4_crtc->current_dlist == HVS_READ(SCALER_DISPLACTX(chan)) || - vc4_crtc->feeds_txp)) { - drm_crtc_send_vblank_event(crtc, vc4_crtc->event); - vc4_crtc->event = NULL; -@@ -728,6 +729,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) - */ - vc4_hvs_unmask_underrun(dev, chan); - } -+ spin_unlock(&vc4_crtc->irq_lock); - spin_unlock_irqrestore(&dev->event_lock, flags); - } - -@@ -1127,6 +1129,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, - return PTR_ERR(primary_plane); - } - -+ spin_lock_init(&vc4_crtc->irq_lock); - drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, - crtc_funcs, NULL); - drm_crtc_helper_add(crtc, crtc_helper_funcs); -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 3c69b89363cb..6d2480abcf08 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -500,6 +500,20 @@ struct vc4_crtc { - * @feeds_txp: True if the CRTC feeds our writeback controller. - */ - bool feeds_txp; -+ -+ /** -+ * @irq_lock: Spinlock protecting the resources shared between -+ * the atomic code and our vblank handler. -+ */ -+ spinlock_t irq_lock; -+ -+ /** -+ * @current_dlist: Start offset of the display list currently -+ * set in the HVS for that CRTC. Protected by @irq_lock, and -+ * copied in vc4_hvs_update_dlist() for the CRTC interrupt -+ * handler to have access to that value. -+ */ -+ unsigned int current_dlist; - }; - - static inline struct vc4_crtc * -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index 9ddaee6b368d..f8ed0f6a57e0 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -365,10 +365,9 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); -+ unsigned long flags; - - if (crtc->state->event) { -- unsigned long flags; -- - crtc->state->event->pipe = drm_crtc_index(crtc); - - WARN_ON(drm_crtc_vblank_get(crtc) != 0); -@@ -388,6 +387,10 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) - HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), - vc4_state->mm.start); - } -+ -+ spin_lock_irqsave(&vc4_crtc->irq_lock, flags); -+ vc4_crtc->current_dlist = vc4_state->mm.start; -+ spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags); - } - - void vc4_hvs_atomic_enable(struct drm_crtc *crtc, --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0013-drm-vc4-crtc-Copy-assigned-channel-to-the-CRTC.patch b/root/target/linux/bcm27xx/patches-5.15/0013-drm-vc4-crtc-Copy-assigned-channel-to-the-CRTC.patch deleted file mode 100644 index f92ddf7c..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0013-drm-vc4-crtc-Copy-assigned-channel-to-the-CRTC.patch +++ /dev/null @@ -1,114 +0,0 @@ -From ed2955f9cdaf873fd2b470febe3da024e3aa3f11 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 18 Oct 2021 15:56:44 +0200 -Subject: [PATCH 013/634] drm/vc4: crtc: Copy assigned channel to the CRTC - -Accessing the crtc->state pointer from outside the modesetting context -is not allowed. We thus need to copy whatever we need from the KMS state -to our structure in order to access it. - -In VC4, a number of users of that pointers have crept in over the years, -and the previous commits removed them all but the HVS channel a CRTC has -been assigned. - -Let's move this channel in struct vc4_crtc at atomic_begin() time, drop -it from our private state structure, and remove our use of crtc->state -from our vblank handler entirely. - -Link: https://lore.kernel.org/all/YWgteNaNeaS9uWDe@phenom.ffwll.local/ -Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 4 ++-- - drivers/gpu/drm/vc4/vc4_drv.h | 9 +++++++++ - drivers/gpu/drm/vc4/vc4_hvs.c | 12 ++++++++++++ - drivers/gpu/drm/vc4/vc4_txp.c | 1 + - 4 files changed, 24 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 98de8b265220..e3ed52d96f42 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -708,8 +708,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) - struct drm_crtc *crtc = &vc4_crtc->base; - struct drm_device *dev = crtc->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); -- struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); -- u32 chan = vc4_state->assigned_channel; -+ u32 chan = vc4_crtc->current_hvs_channel; - unsigned long flags; - - spin_lock_irqsave(&dev->event_lock, flags); -@@ -955,6 +954,7 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { - static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { - .mode_valid = vc4_crtc_mode_valid, - .atomic_check = vc4_crtc_atomic_check, -+ .atomic_begin = vc4_hvs_atomic_begin, - .atomic_flush = vc4_hvs_atomic_flush, - .atomic_enable = vc4_crtc_atomic_enable, - .atomic_disable = vc4_crtc_atomic_disable, -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 6d2480abcf08..4b550ebd9572 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -514,6 +514,14 @@ struct vc4_crtc { - * handler to have access to that value. - */ - unsigned int current_dlist; -+ -+ /** -+ * @current_hvs_channel: HVS channel currently assigned to the -+ * CRTC. Protected by @irq_lock, and copied in -+ * vc4_hvs_atomic_begin() for the CRTC interrupt handler to have -+ * access to that value. -+ */ -+ unsigned int current_hvs_channel; - }; - - static inline struct vc4_crtc * -@@ -926,6 +934,7 @@ extern struct platform_driver vc4_hvs_driver; - void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output); - int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output); - int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state); -+void vc4_hvs_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state); - void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state); - void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state); - void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state); -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index f8ed0f6a57e0..604933e20e6a 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -393,6 +393,18 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) - spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags); - } - -+void vc4_hvs_atomic_begin(struct drm_crtc *crtc, -+ struct drm_atomic_state *state) -+{ -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_crtc->irq_lock, flags); -+ vc4_crtc->current_hvs_channel = vc4_state->assigned_channel; -+ spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags); -+} -+ - void vc4_hvs_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) - { -diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c -index 26eda7542f74..9809ca3e2945 100644 ---- a/drivers/gpu/drm/vc4/vc4_txp.c -+++ b/drivers/gpu/drm/vc4/vc4_txp.c -@@ -435,6 +435,7 @@ static void vc4_txp_atomic_disable(struct drm_crtc *crtc, - - static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = { - .atomic_check = vc4_txp_atomic_check, -+ .atomic_begin = vc4_hvs_atomic_begin, - .atomic_flush = vc4_hvs_atomic_flush, - .atomic_enable = vc4_txp_atomic_enable, - .atomic_disable = vc4_txp_atomic_disable, --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0014-drm-vc4-hdmi-Add-a-spinlock-to-protect-register-acce.patch b/root/target/linux/bcm27xx/patches-5.15/0014-drm-vc4-hdmi-Add-a-spinlock-to-protect-register-acce.patch deleted file mode 100644 index a6fa2fd8..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0014-drm-vc4-hdmi-Add-a-spinlock-to-protect-register-acce.patch +++ /dev/null @@ -1,916 +0,0 @@ -From a17ad9dc735724a186d8618c56e27467dbb1451b Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Tue, 19 Oct 2021 12:25:17 +0200 -Subject: [PATCH 014/634] drm/vc4: hdmi: Add a spinlock to protect register - access - -The vc4 HDMI driver has multiple path shared between the CEC, ALSA and -KMS frameworks, plus two interrupt handlers (CEC and hotplug) that will -read and modify a number of registers. - -Even though not bug has been reported so far, it's definitely unsafe, so -let's just add a spinlock to protect the register access of the HDMI -controller. - -Fixes: c8b75bca92cb ("drm/vc4: Add KMS support for Raspberry Pi.") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 202 ++++++++++++++++++++++++++-- - drivers/gpu/drm/vc4/vc4_hdmi.h | 5 + - drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 37 +++++ - drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 2 + - 4 files changed, 236 insertions(+), 10 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 70101e09b245..6a9d5d423cf8 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -118,6 +118,10 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) - - static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); - udelay(1); - HDMI_WRITE(HDMI_M_CTL, 0); -@@ -129,24 +133,36 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) - VC4_HDMI_SW_RESET_FORMAT_DETECT); - - HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long flags; -+ - reset_control_reset(vc4_hdmi->reset); - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - HDMI_WRITE(HDMI_DVP_CTL, 0); - - HDMI_WRITE(HDMI_CLOCK_STOP, - HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - #ifdef CONFIG_DRM_VC4_HDMI_CEC - static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long cec_rate = clk_get_rate(vc4_hdmi->cec_clock); -+ unsigned long flags; - u16 clk_cnt; - u32 value; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - value = HDMI_READ(HDMI_CEC_CNTRL_1); - value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK; - -@@ -154,9 +170,11 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) - * Set the clock divider: the hsm_clock rate and this divider - * setting will give a 40 kHz CEC clock. - */ -- clk_cnt = clk_get_rate(vc4_hdmi->cec_clock) / CEC_CLOCK_FREQ; -+ clk_cnt = cec_rate / CEC_CLOCK_FREQ; - value |= clk_cnt << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT; - HDMI_WRITE(HDMI_CEC_CNTRL_1, value); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - #else - static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} -@@ -175,8 +193,16 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - connected = true; - } else if (drm_probe_ddc(vc4_hdmi->ddc)) { - connected = true; -- } else if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) { -- connected = true; -+ } else { -+ unsigned long flags; -+ u32 hotplug; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ hotplug = HDMI_READ(HDMI_HOTPLUG); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ -+ if (hotplug & VC4_HDMI_HOTPLUG_CONNECTED) -+ connected = true; - } - - if (connected) { -@@ -369,9 +395,12 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, - { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - u32 packet_id = type - 0x80; -+ unsigned long flags; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, - HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id)); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - - if (!poll) - return 0; -@@ -391,6 +420,7 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, - void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi, - ram_packet_start->reg); - uint8_t buffer[VC4_HDMI_PACKET_STRIDE]; -+ unsigned long flags; - ssize_t len, i; - int ret; - -@@ -408,6 +438,8 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, - return; - } - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - for (i = 0; i < len; i += 7) { - writel(buffer[i + 0] << 0 | - buffer[i + 1] << 8 | -@@ -425,6 +457,9 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, - - HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, - HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id)); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) & - BIT(packet_id)), 100); - if (ret) -@@ -544,6 +579,7 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) - { - struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ unsigned long flags; - - if (!vc4_hdmi_supports_scrambling(encoder, mode)) - return; -@@ -554,8 +590,10 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) - drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); - drm_scdc_set_scrambling(vc4_hdmi->ddc, true); - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) | - VC5_HDMI_SCRAMBLER_CTL_ENABLE); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - - queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, - msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS)); -@@ -565,6 +603,7 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) - { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_crtc *crtc = encoder->crtc; -+ unsigned long flags; - - /* - * At boot, encoder->crtc will be NULL. Since we don't know the -@@ -580,8 +619,10 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) - if (delayed_work_pending(&vc4_hdmi->scrambling_work)) - cancel_delayed_work_sync(&vc4_hdmi->scrambling_work); - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) & - ~VC5_HDMI_SCRAMBLER_CTL_ENABLE); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - - drm_scdc_set_scrambling(vc4_hdmi->ddc, false); - drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false); -@@ -607,15 +648,23 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, - struct drm_atomic_state *state) - { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - - HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); - - HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_CLRRGB); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - mdelay(1); - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_VID_CTL, - HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - vc4_hdmi_disable_scrambling(encoder); - } - -@@ -623,10 +672,13 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, - struct drm_atomic_state *state) - { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ unsigned long flags; - int ret; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_VID_CTL, - HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - - if (vc4_hdmi->variant->phy_disable) - vc4_hdmi->variant->phy_disable(vc4_hdmi); -@@ -645,8 +697,11 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) - - static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) - { -+ unsigned long flags; - u32 csc_ctl; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, - VC4_HD_CSC_CTL_ORDER); - -@@ -676,14 +731,19 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) - - /* The RGB order applies even when CSC is disabled. */ - HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) - { -+ unsigned long flags; - u32 csc_ctl; - - csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */ - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - if (enable) { - /* CEA VICs other than #1 requre limited range RGB - * output unless overridden by an AVI infoframe. -@@ -715,6 +775,8 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) - } - - HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, -@@ -738,6 +800,9 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, - mode->crtc_vsync_end - - interlaced, - VC4_HDMI_VERTB_VBP)); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - - HDMI_WRITE(HDMI_HORZA, - (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | -@@ -761,6 +826,8 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, - - HDMI_WRITE(HDMI_VERTB0, vertb_even); - HDMI_WRITE(HDMI_VERTB1, vertb); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, -@@ -784,10 +851,13 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, - mode->crtc_vsync_end - - interlaced, - VC4_HDMI_VERTB_VBP)); -+ unsigned long flags; - unsigned char gcp; - bool gcp_en; - u32 reg; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021); - HDMI_WRITE(HDMI_HORZA, - (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) | -@@ -846,13 +916,18 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, - HDMI_WRITE(HDMI_GCP_CONFIG, reg); - - HDMI_WRITE(HDMI_CLOCK_STOP, 0); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long flags; - u32 drift; - int ret; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - drift = HDMI_READ(HDMI_FIFO_CTL); - drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; - -@@ -860,12 +935,20 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - usleep_range(1000, 1100); -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - HDMI_WRITE(HDMI_FIFO_CTL, - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & - VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); - WARN_ONCE(ret, "Timeout waiting for " -@@ -899,6 +982,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - unsigned long pixel_rate = vc4_conn_state->pixel_rate; - unsigned long bvb_rate, hsm_rate; -+ unsigned long flags; - int ret; - - /* -@@ -967,11 +1051,15 @@ 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, vc4_conn_state); - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - HDMI_WRITE(HDMI_SCHEDULER_CONTROL, - HDMI_READ(HDMI_SCHEDULER_CONTROL) | - VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT | - VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - if (vc4_hdmi->variant->set_timings) - vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode); - -@@ -991,6 +1079,7 @@ 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); -+ unsigned long flags; - - if (vc4_encoder->hdmi_monitor && - drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) { -@@ -1005,7 +1094,9 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, - vc4_encoder->limited_rgb_range = false; - } - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, -@@ -1016,8 +1107,11 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *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; -+ unsigned long flags; - int ret; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - HDMI_WRITE(HDMI_VID_CTL, - VC4_HD_VID_CTL_ENABLE | - VC4_HD_VID_CTL_CLRRGB | -@@ -1034,6 +1128,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, - HDMI_READ(HDMI_SCHEDULER_CONTROL) | - VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) & - VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000); - WARN_ONCE(ret, "Timeout waiting for " -@@ -1046,6 +1142,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, - HDMI_READ(HDMI_SCHEDULER_CONTROL) & - ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & - VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000); - WARN_ONCE(ret, "Timeout waiting for " -@@ -1053,6 +1151,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, - } - - if (vc4_encoder->hdmi_monitor) { -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & - VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE)); - HDMI_WRITE(HDMI_SCHEDULER_CONTROL, -@@ -1062,6 +1162,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, - HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, - VC4_HDMI_RAM_PACKET_ENABLE); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - vc4_hdmi_set_infoframes(encoder); - } - -@@ -1183,6 +1285,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi, - unsigned int samplerate) - { - u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock); -+ unsigned long flags; - unsigned long n, m; - - rational_best_approximation(hsm_clock, samplerate, -@@ -1192,9 +1295,11 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi, - VC4_HD_MAI_SMP_M_SHIFT) + 1, - &n, &m); - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_MAI_SMP, - VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) | - VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate) -@@ -1205,6 +1310,8 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerat - u32 n, cts; - u64 tmp; - -+ lockdep_assert_held(&vc4_hdmi->hw_lock); -+ - n = 128 * samplerate / 1000; - tmp = (u64)(mode->clock * 1000) * n; - do_div(tmp, 128 * samplerate); -@@ -1234,6 +1341,7 @@ static int vc4_hdmi_audio_startup(struct device *dev, void *data) - { - struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; -+ unsigned long flags; - - /* - * If the HDMI encoder hasn't probed, or the encoder is -@@ -1245,12 +1353,14 @@ static int vc4_hdmi_audio_startup(struct device *dev, void *data) - - vc4_hdmi->audio.streaming = true; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_MAI_CTL, - VC4_HD_MAI_CTL_RESET | - VC4_HD_MAI_CTL_FLUSH | - VC4_HD_MAI_CTL_DLATE | - VC4_HD_MAI_CTL_ERRORE | - VC4_HD_MAI_CTL_ERRORF); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - - if (vc4_hdmi->variant->phy_rng_enable) - vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); -@@ -1262,6 +1372,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) - { - struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - struct device *dev = &vc4_hdmi->pdev->dev; -+ unsigned long flags; - int ret; - - vc4_hdmi->audio.streaming = false; -@@ -1269,20 +1380,29 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) - if (ret) - dev_err(dev, "Failed to stop audio infoframe: %d\n", ret); - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET); - HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF); - HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - static void vc4_hdmi_audio_shutdown(struct device *dev, void *data) - { - struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - - HDMI_WRITE(HDMI_MAI_CTL, - VC4_HD_MAI_CTL_DLATE | - VC4_HD_MAI_CTL_ERRORE | - VC4_HD_MAI_CTL_ERRORF); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - if (vc4_hdmi->variant->phy_rng_disable) - vc4_hdmi->variant->phy_rng_disable(vc4_hdmi); - -@@ -1337,6 +1457,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, - struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - unsigned int sample_rate = params->sample_rate; - unsigned int channels = params->channels; -+ unsigned long flags; - u32 audio_packet_config, channel_mask; - u32 channel_map; - u32 mai_audio_format; -@@ -1345,14 +1466,15 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, - dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__, - sample_rate, params->sample_width, channels); - -+ vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate); -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_MAI_CTL, - VC4_SET_FIELD(channels, VC4_HD_MAI_CTL_CHNUM) | - VC4_HD_MAI_CTL_WHOLSMP | - VC4_HD_MAI_CTL_CHALIGN | - VC4_HD_MAI_CTL_ENABLE); - -- vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate); -- - mai_sample_rate = sample_rate_to_mai_fmt(sample_rate); - if (params->iec.status[0] & IEC958_AES0_NONAUDIO && - params->channels == 8) -@@ -1390,8 +1512,11 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, - channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask); - HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map); - HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config); -+ - vc4_hdmi_set_n_cts(vc4_hdmi, sample_rate); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea)); - vc4_hdmi_set_audio_infoframe(encoder); - -@@ -1658,6 +1783,8 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) - struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; - unsigned int i; - -+ lockdep_assert_held(&vc4_hdmi->hw_lock); -+ - msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> - VC4_HDMI_CEC_REC_WRD_CNT_SHIFT); - -@@ -1676,11 +1803,12 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) - } - } - --static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv) -+static irqreturn_t vc4_cec_irq_handler_tx_bare_locked(struct vc4_hdmi *vc4_hdmi) - { -- struct vc4_hdmi *vc4_hdmi = priv; - u32 cntrl1; - -+ lockdep_assert_held(&vc4_hdmi->hw_lock); -+ - cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); - vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; - cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN; -@@ -1689,11 +1817,24 @@ static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv) - return IRQ_WAKE_THREAD; - } - --static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv) -+static irqreturn_t vc4_cec_irq_handler_tx_bare(int irq, void *priv) - { - struct vc4_hdmi *vc4_hdmi = priv; -+ irqreturn_t ret; -+ -+ spin_lock(&vc4_hdmi->hw_lock); -+ ret = vc4_cec_irq_handler_tx_bare_locked(vc4_hdmi); -+ spin_unlock(&vc4_hdmi->hw_lock); -+ -+ return ret; -+} -+ -+static irqreturn_t vc4_cec_irq_handler_rx_bare_locked(struct vc4_hdmi *vc4_hdmi) -+{ - u32 cntrl1; - -+ lockdep_assert_held(&vc4_hdmi->hw_lock); -+ - vc4_hdmi->cec_rx_msg.len = 0; - cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); - vc4_cec_read_msg(vc4_hdmi, cntrl1); -@@ -1706,6 +1847,18 @@ static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv) - return IRQ_WAKE_THREAD; - } - -+static irqreturn_t vc4_cec_irq_handler_rx_bare(int irq, void *priv) -+{ -+ struct vc4_hdmi *vc4_hdmi = priv; -+ irqreturn_t ret; -+ -+ spin_lock(&vc4_hdmi->hw_lock); -+ ret = vc4_cec_irq_handler_rx_bare_locked(vc4_hdmi); -+ spin_unlock(&vc4_hdmi->hw_lock); -+ -+ return ret; -+} -+ - static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) - { - struct vc4_hdmi *vc4_hdmi = priv; -@@ -1716,14 +1869,17 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) - if (!(stat & VC4_HDMI_CPU_CEC)) - return IRQ_NONE; - -+ spin_lock(&vc4_hdmi->hw_lock); - cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5); - vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; - if (vc4_hdmi->cec_irq_was_rx) -- ret = vc4_cec_irq_handler_rx_bare(irq, priv); -+ ret = vc4_cec_irq_handler_rx_bare_locked(vc4_hdmi); - else -- ret = vc4_cec_irq_handler_tx_bare(irq, priv); -+ ret = vc4_cec_irq_handler_tx_bare_locked(vc4_hdmi); - - HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC); -+ spin_unlock(&vc4_hdmi->hw_lock); -+ - return ret; - } - -@@ -1732,6 +1888,7 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - /* clock period in microseconds */ - const u32 usecs = 1000000 / CEC_CLOCK_FREQ; -+ unsigned long flags; - u32 val; - int ret; - -@@ -1739,6 +1896,8 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) - if (ret) - return ret; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - val = HDMI_READ(HDMI_CEC_CNTRL_5); - val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET | - VC4_HDMI_CEC_CNT_TO_4700_US_MASK | -@@ -1769,12 +1928,17 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) - if (!vc4_hdmi->variant->external_irq_controller) - HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - return 0; - } - - static int vc4_hdmi_cec_disable(struct cec_adapter *adap) - { - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - - if (!vc4_hdmi->variant->external_irq_controller) - HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC); -@@ -1782,6 +1946,8 @@ static int vc4_hdmi_cec_disable(struct cec_adapter *adap) - HDMI_WRITE(HDMI_CEC_CNTRL_5, HDMI_READ(HDMI_CEC_CNTRL_5) | - VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); - -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - pm_runtime_put(&vc4_hdmi->pdev->dev); - - return 0; -@@ -1798,10 +1964,14 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) - static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) - { - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); -+ unsigned long flags; - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_CEC_CNTRL_1, - (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) | - (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - return 0; - } - -@@ -1810,6 +1980,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, - { - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - struct drm_device *dev = vc4_hdmi->connector.dev; -+ unsigned long flags; - u32 val; - unsigned int i; - -@@ -1818,6 +1989,8 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, - return -ENOMEM; - } - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - for (i = 0; i < msg->len; i += 4) - HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i >> 2), - (msg->msg[i]) | -@@ -1833,6 +2006,9 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, - val |= VC4_HDMI_CEC_START_XMIT_BEGIN; - - HDMI_WRITE(HDMI_CEC_CNTRL_1, val); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ - return 0; - } - -@@ -1847,6 +2023,7 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) - struct cec_connector_info conn_info; - struct platform_device *pdev = vc4_hdmi->pdev; - struct device *dev = &pdev->dev; -+ unsigned long flags; - u32 value; - int ret; - -@@ -1866,10 +2043,12 @@ 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); - -@@ -1888,7 +2067,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) - if (ret) - goto err_remove_cec_rx_handler; - } else { -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - - ret = request_threaded_irq(platform_get_irq(pdev, 0), - vc4_cec_irq_handler, -@@ -2158,6 +2339,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) - vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL); - if (!vc4_hdmi) - return -ENOMEM; -+ spin_lock_init(&vc4_hdmi->hw_lock); - INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq); - - dev_set_drvdata(dev, vc4_hdmi); -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h -index 33e9f665ab8e..006142fe8d4e 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h -@@ -178,6 +178,11 @@ struct vc4_hdmi { - - struct debugfs_regset32 hdmi_regset; - struct debugfs_regset32 hd_regset; -+ -+ /** -+ * @hw_lock: Spinlock protecting device register access. -+ */ -+ spinlock_t hw_lock; - }; - - static inline struct vc4_hdmi * -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c -index 36535480f8e2..62148f0dc284 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c -@@ -130,31 +130,49 @@ - void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - struct vc4_hdmi_connector_state *conn_state) - { -+ unsigned long flags; -+ - /* PHY should be in reset, like - * vc4_hdmi_encoder_disable() does. - */ - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); - HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_TX_PHY_CTL_0, - HDMI_READ(HDMI_TX_PHY_CTL_0) & - ~VC4_HDMI_TX_PHY_RNG_PWRDN); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_TX_PHY_CTL_0, - HDMI_READ(HDMI_TX_PHY_CTL_0) | - VC4_HDMI_TX_PHY_RNG_PWRDN); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - static unsigned long long -@@ -336,6 +354,8 @@ phy_get_channel_settings(enum vc4_hdmi_phy_channel chan, - - static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi) - { -+ lockdep_assert_held(&vc4_hdmi->hw_lock); -+ - HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f); - HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10)); - } -@@ -348,10 +368,13 @@ void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - unsigned long long pixel_freq = conn_state->pixel_rate; - unsigned long long vco_freq; - unsigned char word_sel; -+ unsigned long flags; - u8 vco_sel, vco_div; - - vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div); - -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -+ - vc5_hdmi_reset_phy(vc4_hdmi); - - HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, -@@ -501,23 +524,37 @@ void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, - HDMI_READ(HDMI_TX_PHY_RESET_CTL) | - VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB | - VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB); -+ -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - vc5_hdmi_reset_phy(vc4_hdmi); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, - HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) & - ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } - - void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi) - { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, - HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) | - VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); -+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - } -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -index 99dde6e06a37..fc971506bd4f 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -@@ -442,6 +442,8 @@ static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi, - const struct vc4_hdmi_variant *variant = hdmi->variant; - void __iomem *base; - -+ lockdep_assert_held(&hdmi->hw_lock); -+ - WARN_ON(!pm_runtime_active(&hdmi->pdev->dev)); - - if (reg >= variant->num_registers) { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0015-drm-vc4-hdmi-Use-a-mutex-to-prevent-concurrent-frame.patch b/root/target/linux/bcm27xx/patches-5.15/0015-drm-vc4-hdmi-Use-a-mutex-to-prevent-concurrent-frame.patch deleted file mode 100644 index 4a0def08..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0015-drm-vc4-hdmi-Use-a-mutex-to-prevent-concurrent-frame.patch +++ /dev/null @@ -1,449 +0,0 @@ -From a2cadb4575045b8503169302f3b18011c7e09c77 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Tue, 19 Oct 2021 14:19:04 +0200 -Subject: [PATCH 015/634] drm/vc4: hdmi: Use a mutex to prevent concurrent - framework access - -The vc4 HDMI controller registers into the KMS, CEC and ALSA -frameworks. - -However, no particular care is done to prevent the concurrent execution -of different framework hooks from happening at the same time. - -In order to protect against that scenario, let's introduce a mutex that -relevant ALSA and KMS hooks will need to take to prevent concurrent -execution. - -CEC is left out at the moment though, since the .get_modes and .detect -KMS hooks, when running cec_s_phys_addr_from_edid, can end up calling -CEC's .adap_enable hook. This introduces some reentrancy that isn't easy -to deal with properly. - -The CEC hooks also don't share much state with the rest of the driver: -the registers are entirely separate, we don't share any variable, the -only thing that can conflict is the CEC clock divider setup that can be -affected by a mode set. - -However, after discussing it, it looks like CEC should be able to -recover from this if it was to happen. - -Fixes: bb7d78568814 ("drm/vc4: Add HDMI audio support") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 118 +++++++++++++++++++++++++++++++-- - drivers/gpu/drm/vc4/vc4_hdmi.h | 14 ++++ - 2 files changed, 126 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 6a9d5d423cf8..a3f25efe60e9 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -186,6 +186,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); - bool connected = false; - -+ mutex_lock(&vc4_hdmi->mutex); -+ - WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); - - if (vc4_hdmi->hpd_gpio && -@@ -217,11 +219,13 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - } - - pm_runtime_put(&vc4_hdmi->pdev->dev); -+ mutex_unlock(&vc4_hdmi->mutex); - return connector_status_connected; - } - - cec_phys_addr_invalidate(vc4_hdmi->cec_adap); - pm_runtime_put(&vc4_hdmi->pdev->dev); -+ mutex_unlock(&vc4_hdmi->mutex); - return connector_status_disconnected; - } - -@@ -238,10 +242,14 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) - int ret = 0; - struct edid *edid; - -+ mutex_lock(&vc4_hdmi->mutex); -+ - edid = drm_get_edid(connector, vc4_hdmi->ddc); - cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); -- if (!edid) -- return -ENODEV; -+ if (!edid) { -+ ret = -ENODEV; -+ goto out; -+ } - - vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); - -@@ -261,6 +269,9 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) - } - } - -+out: -+ mutex_unlock(&vc4_hdmi->mutex); -+ - return ret; - } - -@@ -477,6 +488,8 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) - union hdmi_infoframe frame; - int ret; - -+ lockdep_assert_held(&vc4_hdmi->mutex); -+ - ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - connector, mode); - if (ret < 0) { -@@ -528,6 +541,8 @@ static void vc4_hdmi_set_hdr_infoframe(struct drm_encoder *encoder) - struct drm_connector_state *conn_state = connector->state; - union hdmi_infoframe frame; - -+ lockdep_assert_held(&vc4_hdmi->mutex); -+ - if (!vc4_hdmi->variant->supports_hdr) - return; - -@@ -544,6 +559,8 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) - { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - -+ lockdep_assert_held(&vc4_hdmi->mutex); -+ - vc4_hdmi_set_avi_infoframe(encoder); - vc4_hdmi_set_spd_infoframe(encoder); - /* -@@ -563,6 +580,8 @@ static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder, - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_display_info *display = &vc4_hdmi->connector.display_info; - -+ lockdep_assert_held(&vc4_hdmi->mutex); -+ - if (!vc4_encoder->hdmi_monitor) - return false; - -@@ -581,6 +600,8 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - unsigned long flags; - -+ lockdep_assert_held(&vc4_hdmi->mutex); -+ - if (!vc4_hdmi_supports_scrambling(encoder, mode)) - return; - -@@ -650,6 +671,8 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - unsigned long flags; - -+ mutex_lock(&vc4_hdmi->mutex); -+ - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - - HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); -@@ -666,6 +689,8 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, - spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - - vc4_hdmi_disable_scrambling(encoder); -+ -+ mutex_unlock(&vc4_hdmi->mutex); - } - - static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, -@@ -675,6 +700,8 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, - unsigned long flags; - int ret; - -+ mutex_lock(&vc4_hdmi->mutex); -+ - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_VID_CTL, - HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); -@@ -689,6 +716,8 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, - ret = pm_runtime_put(&vc4_hdmi->pdev->dev); - if (ret < 0) - DRM_ERROR("Failed to release power domain: %d\n", ret); -+ -+ mutex_unlock(&vc4_hdmi->mutex); - } - - static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) -@@ -985,6 +1014,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - unsigned long flags; - int ret; - -+ mutex_lock(&vc4_hdmi->mutex); -+ - /* - * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must - * be faster than pixel clock, infinitesimally faster, tested in -@@ -1005,13 +1036,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - 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; -+ goto out; - } - - ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); - if (ret < 0) { - DRM_ERROR("Failed to retain power domain: %d\n", ret); -- return; -+ goto out; - } - - ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate); -@@ -1063,13 +1094,16 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - if (vc4_hdmi->variant->set_timings) - vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode); - -+ mutex_unlock(&vc4_hdmi->mutex); -+ - return; - - err_disable_pixel_clock: - clk_disable_unprepare(vc4_hdmi->pixel_clock); - err_put_runtime_pm: - pm_runtime_put(&vc4_hdmi->pdev->dev); -- -+out: -+ mutex_unlock(&vc4_hdmi->mutex); - return; - } - -@@ -1081,6 +1115,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - unsigned long flags; - -+ mutex_lock(&vc4_hdmi->mutex); -+ - if (vc4_encoder->hdmi_monitor && - drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) { - if (vc4_hdmi->variant->csc_setup) -@@ -1097,6 +1133,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); - spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -+ -+ mutex_unlock(&vc4_hdmi->mutex); - } - - static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, -@@ -1110,6 +1148,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, - unsigned long flags; - int ret; - -+ mutex_lock(&vc4_hdmi->mutex); -+ - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - - HDMI_WRITE(HDMI_VID_CTL, -@@ -1169,6 +1209,8 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, - - vc4_hdmi_recenter_fifo(vc4_hdmi); - vc4_hdmi_enable_scrambling(encoder); -+ -+ mutex_unlock(&vc4_hdmi->mutex); - } - - static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) -@@ -1310,6 +1352,7 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerat - u32 n, cts; - u64 tmp; - -+ lockdep_assert_held(&vc4_hdmi->mutex); - lockdep_assert_held(&vc4_hdmi->hw_lock); - - n = 128 * samplerate / 1000; -@@ -1343,13 +1386,17 @@ static int vc4_hdmi_audio_startup(struct device *dev, void *data) - struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - unsigned long flags; - -+ mutex_lock(&vc4_hdmi->mutex); -+ - /* - * If the HDMI encoder hasn't probed, or the encoder is - * currently in DVI mode, treat the codec dai as missing. - */ - if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & -- VC4_HDMI_RAM_PACKET_ENABLE)) -+ VC4_HDMI_RAM_PACKET_ENABLE)) { -+ mutex_unlock(&vc4_hdmi->mutex); - return -ENODEV; -+ } - - vc4_hdmi->audio.streaming = true; - -@@ -1365,6 +1412,8 @@ static int vc4_hdmi_audio_startup(struct device *dev, void *data) - if (vc4_hdmi->variant->phy_rng_enable) - vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); - -+ mutex_unlock(&vc4_hdmi->mutex); -+ - return 0; - } - -@@ -1375,6 +1424,8 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) - unsigned long flags; - int ret; - -+ lockdep_assert_held(&vc4_hdmi->mutex); -+ - vc4_hdmi->audio.streaming = false; - ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO, false); - if (ret) -@@ -1394,6 +1445,8 @@ static void vc4_hdmi_audio_shutdown(struct device *dev, void *data) - struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - unsigned long flags; - -+ mutex_lock(&vc4_hdmi->mutex); -+ - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - - HDMI_WRITE(HDMI_MAI_CTL, -@@ -1408,6 +1461,8 @@ static void vc4_hdmi_audio_shutdown(struct device *dev, void *data) - - vc4_hdmi->audio.streaming = false; - vc4_hdmi_audio_reset(vc4_hdmi); -+ -+ mutex_unlock(&vc4_hdmi->mutex); - } - - static int sample_rate_to_mai_fmt(int samplerate) -@@ -1466,6 +1521,8 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, - dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__, - sample_rate, params->sample_width, channels); - -+ mutex_lock(&vc4_hdmi->mutex); -+ - vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate); - - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -@@ -1520,6 +1577,8 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, - memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea)); - vc4_hdmi_set_audio_infoframe(encoder); - -+ mutex_unlock(&vc4_hdmi->mutex); -+ - return 0; - } - -@@ -1562,7 +1621,9 @@ static int vc4_hdmi_audio_get_eld(struct device *dev, void *data, - struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - struct drm_connector *connector = &vc4_hdmi->connector; - -+ mutex_lock(&vc4_hdmi->mutex); - memcpy(buf, connector->eld, min(sizeof(connector->eld), len)); -+ mutex_unlock(&vc4_hdmi->mutex); - - return 0; - } -@@ -1892,6 +1953,17 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap) - u32 val; - int ret; - -+ /* -+ * NOTE: This function should really take vc4_hdmi->mutex, but doing so -+ * results in a reentrancy since cec_s_phys_addr_from_edid() called in -+ * .detect or .get_modes might call .adap_enable, which leads to this -+ * function being called with that mutex held. -+ * -+ * Concurrency is not an issue for the moment since we don't share any -+ * state with KMS, so we can ignore the lock for now, but we need to -+ * keep it in mind if we were to change that assumption. -+ */ -+ - ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); - if (ret) - return ret; -@@ -1938,6 +2010,17 @@ static int vc4_hdmi_cec_disable(struct cec_adapter *adap) - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - unsigned long flags; - -+ /* -+ * NOTE: This function should really take vc4_hdmi->mutex, but doing so -+ * results in a reentrancy since cec_s_phys_addr_from_edid() called in -+ * .detect or .get_modes might call .adap_enable, which leads to this -+ * function being called with that mutex held. -+ * -+ * Concurrency is not an issue for the moment since we don't share any -+ * state with KMS, so we can ignore the lock for now, but we need to -+ * keep it in mind if we were to change that assumption. -+ */ -+ - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - - if (!vc4_hdmi->variant->external_irq_controller) -@@ -1966,6 +2049,17 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) - struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - unsigned long flags; - -+ /* -+ * NOTE: This function should really take vc4_hdmi->mutex, but doing so -+ * results in a reentrancy since cec_s_phys_addr_from_edid() called in -+ * .detect or .get_modes might call .adap_enable, which leads to this -+ * function being called with that mutex held. -+ * -+ * Concurrency is not an issue for the moment since we don't share any -+ * state with KMS, so we can ignore the lock for now, but we need to -+ * keep it in mind if we were to change that assumption. -+ */ -+ - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_CEC_CNTRL_1, - (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) | -@@ -1984,6 +2078,17 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, - u32 val; - unsigned int i; - -+ /* -+ * NOTE: This function should really take vc4_hdmi->mutex, but doing so -+ * results in a reentrancy since cec_s_phys_addr_from_edid() called in -+ * .detect or .get_modes might call .adap_enable, which leads to this -+ * function being called with that mutex held. -+ * -+ * Concurrency is not an issue for the moment since we don't share any -+ * state with KMS, so we can ignore the lock for now, but we need to -+ * keep it in mind if we were to change that assumption. -+ */ -+ - if (msg->len > 16) { - drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len); - return -ENOMEM; -@@ -2339,6 +2444,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) - vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL); - if (!vc4_hdmi) - return -ENOMEM; -+ mutex_init(&vc4_hdmi->mutex); - spin_lock_init(&vc4_hdmi->hw_lock); - INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq); - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h -index 006142fe8d4e..cf9bb21a8ef7 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h -@@ -183,6 +183,20 @@ struct vc4_hdmi { - * @hw_lock: Spinlock protecting device register access. - */ - spinlock_t hw_lock; -+ -+ /** -+ * @mutex: Mutex protecting the driver access across multiple -+ * frameworks (KMS, ALSA). -+ * -+ * NOTE: While supported, CEC has been left out since -+ * cec_s_phys_addr_from_edid() might call .adap_enable and lead to a -+ * reentrancy issue between .get_modes (or .detect) and .adap_enable. -+ * Since we don't share any state between the CEC hooks and KMS', it's -+ * not a big deal. The only trouble might come from updating the CEC -+ * clock divider which might be affected by a modeset, but CEC should -+ * be resilient to that. -+ */ -+ struct mutex mutex; - }; - - static inline struct vc4_hdmi * --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0016-drm-vc4-hdmi-Prevent-access-to-crtc-state-outside-of.patch b/root/target/linux/bcm27xx/patches-5.15/0016-drm-vc4-hdmi-Prevent-access-to-crtc-state-outside-of.patch deleted file mode 100644 index c943250c..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0016-drm-vc4-hdmi-Prevent-access-to-crtc-state-outside-of.patch +++ /dev/null @@ -1,168 +0,0 @@ -From d51fcb1a3d1b478c76935b01a8788ff546727149 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Tue, 19 Oct 2021 14:19:29 +0200 -Subject: [PATCH 016/634] drm/vc4: hdmi: Prevent access to crtc->state outside - of KMS - -Accessing the crtc->state pointer from outside the modesetting context -is not allowed. We thus need to copy whatever we need from the KMS state -to our structure in order to access it. - -However, in the vc4 HDMI driver we do use that pointer in the ALSA code -path, and potentially in the hotplug interrupt handler path. - -These paths both need access to the CRTC adjusted mode in order for the -proper dividers to be set for ALSA, and the scrambler state to be -reinstated properly for hotplug. - -Let's copy this mode into our private encoder structure and reference it -from there when needed. Since that part is shared between KMS and other -paths, we need to protect it using our mutex. - -Link: https://lore.kernel.org/all/YWgteNaNeaS9uWDe@phenom.ffwll.local/ -Fixes: bb7d78568814 ("drm/vc4: Add HDMI audio support") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 38 +++++++++++++++++++++++----------- - drivers/gpu/drm/vc4/vc4_hdmi.h | 6 ++++++ - 2 files changed, 32 insertions(+), 12 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index a3f25efe60e9..355f85418862 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -483,8 +483,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) - struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - struct drm_connector *connector = &vc4_hdmi->connector; - struct drm_connector_state *cstate = connector->state; -- struct drm_crtc *crtc = encoder->crtc; -- const struct drm_display_mode *mode = &crtc->state->adjusted_mode; -+ const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - union hdmi_infoframe frame; - int ret; - -@@ -596,8 +595,8 @@ static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder, - - static void vc4_hdmi_enable_scrambling(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 drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - unsigned long flags; - - lockdep_assert_held(&vc4_hdmi->mutex); -@@ -623,18 +622,21 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) - static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) - { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - struct drm_crtc *crtc = encoder->crtc; - unsigned long flags; - -+ lockdep_assert_held(&vc4_hdmi->mutex); -+ - /* - * At boot, encoder->crtc will be NULL. Since we don't know the - * state of the scrambler and in order to avoid any - * inconsistency, let's disable it all the time. - */ -- if (crtc && !vc4_hdmi_supports_scrambling(encoder, &crtc->mode)) -+ if (crtc && !vc4_hdmi_supports_scrambling(encoder, mode)) - return; - -- if (crtc && !vc4_hdmi_mode_needs_scrambling(&crtc->mode)) -+ if (crtc && !vc4_hdmi_mode_needs_scrambling(mode)) - return; - - if (delayed_work_pending(&vc4_hdmi->scrambling_work)) -@@ -1007,8 +1009,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - vc4_hdmi_encoder_get_connector_state(encoder, state); - struct vc4_hdmi_connector_state *vc4_conn_state = - conn_state_to_vc4_hdmi_conn_state(conn_state); -- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - unsigned long pixel_rate = vc4_conn_state->pixel_rate; - unsigned long bvb_rate, hsm_rate; - unsigned long flags; -@@ -1110,9 +1112,9 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, - struct drm_atomic_state *state) - { -- 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); -+ struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; -+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - unsigned long flags; - - mutex_lock(&vc4_hdmi->mutex); -@@ -1140,8 +1142,8 @@ 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_atomic_state *state) - { -- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - 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; -@@ -1217,6 +1219,19 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) - { - } - -+static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) -+{ -+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ -+ mutex_lock(&vc4_hdmi->mutex); -+ memcpy(&vc4_hdmi->saved_adjusted_mode, -+ &crtc_state->adjusted_mode, -+ sizeof(vc4_hdmi->saved_adjusted_mode)); -+ mutex_unlock(&vc4_hdmi->mutex); -+} -+ - #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL - #define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL - -@@ -1293,6 +1308,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, - - static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { - .atomic_check = vc4_hdmi_encoder_atomic_check, -+ .atomic_mode_set = vc4_hdmi_encoder_atomic_mode_set, - .mode_valid = vc4_hdmi_encoder_mode_valid, - .disable = vc4_hdmi_encoder_disable, - .enable = vc4_hdmi_encoder_enable, -@@ -1346,9 +1362,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi, - - static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate) - { -- struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; -- struct drm_crtc *crtc = encoder->crtc; -- const struct drm_display_mode *mode = &crtc->state->adjusted_mode; -+ const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - u32 n, cts; - u64 tmp; - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h -index cf9bb21a8ef7..a43cc5614d19 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h -@@ -197,6 +197,12 @@ struct vc4_hdmi { - * be resilient to that. - */ - struct mutex mutex; -+ -+ /** -+ * @saved_adjusted_mode: Copy of @drm_crtc_state.adjusted_mode -+ * for use by ALSA hooks and interrupt handlers. Protected by @mutex. -+ */ -+ struct drm_display_mode saved_adjusted_mode; - }; - - static inline struct vc4_hdmi * --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0017-drm-vc4-hdmi-Check-the-device-state-in-prepare.patch b/root/target/linux/bcm27xx/patches-5.15/0017-drm-vc4-hdmi-Check-the-device-state-in-prepare.patch deleted file mode 100644 index d0eba951..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0017-drm-vc4-hdmi-Check-the-device-state-in-prepare.patch +++ /dev/null @@ -1,82 +0,0 @@ -From d78e135b703cd511621d2b396c03e8a8faa0b1a7 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 24 Sep 2021 14:27:38 +0200 -Subject: [PATCH 017/634] drm/vc4: hdmi: Check the device state in prepare() - -Even though we already check that the encoder->crtc pointer is there -during in startup(), which is part of the open() path in ASoC, nothing -guarantees that our encoder state won't change between the time when we -open the device and the time we prepare it. - -Move the sanity checks we do in startup() to a helper and call it from -prepare(). - -Fixes: 91e99e113929 ("drm/vc4: hdmi: Register HDMI codec") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 35 +++++++++++++++++++++++++++------- - 1 file changed, 28 insertions(+), 7 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 355f85418862..8ea2291fe784 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -1394,20 +1394,36 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai) - return snd_soc_card_get_drvdata(card); - } - -+static bool vc4_hdmi_audio_can_stream(struct vc4_hdmi *vc4_hdmi) -+{ -+ struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; -+ -+ lockdep_assert_held(&vc4_hdmi->mutex); -+ -+ /* -+ * The encoder doesn't have a CRTC until the first modeset. -+ */ -+ if (!encoder->crtc) -+ return false; -+ -+ /* -+ * If the encoder is currently in DVI mode, treat the codec DAI -+ * as missing. -+ */ -+ if (!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & VC4_HDMI_RAM_PACKET_ENABLE)) -+ return false; -+ -+ return true; -+} -+ - static int vc4_hdmi_audio_startup(struct device *dev, void *data) - { - struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); -- struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - unsigned long flags; - - mutex_lock(&vc4_hdmi->mutex); - -- /* -- * If the HDMI encoder hasn't probed, or the encoder is -- * currently in DVI mode, treat the codec dai as missing. -- */ -- if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & -- VC4_HDMI_RAM_PACKET_ENABLE)) { -+ if (!vc4_hdmi_audio_can_stream(vc4_hdmi)) { - mutex_unlock(&vc4_hdmi->mutex); - return -ENODEV; - } -@@ -1537,6 +1553,11 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, - - mutex_lock(&vc4_hdmi->mutex); - -+ if (!vc4_hdmi_audio_can_stream(vc4_hdmi)) { -+ mutex_unlock(&vc4_hdmi->mutex); -+ return -EINVAL; -+ } -+ - vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate); - - spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0018-drm-vc4-hdmi-Introduce-an-output_enabled-flag.patch b/root/target/linux/bcm27xx/patches-5.15/0018-drm-vc4-hdmi-Introduce-an-output_enabled-flag.patch deleted file mode 100644 index 2f9d0e8b..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0018-drm-vc4-hdmi-Introduce-an-output_enabled-flag.patch +++ /dev/null @@ -1,85 +0,0 @@ -From b3fa147e2b8ec4b9acf242a589e464ed49b54ffe Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Tue, 19 Oct 2021 17:31:58 +0200 -Subject: [PATCH 018/634] drm/vc4: hdmi: Introduce an output_enabled flag - -We currently poke at encoder->crtc in the ALSA code path to determine -whether the HDMI output is enabled or not, and thus whether we should -allow the audio output. - -However, that pointer is deprecated and shouldn't really be used by -atomic drivers anymore. Since we have the infrastructure in place now, -let's just create a flag that we toggle to report whether the controller -is currently enabled and use that instead of encoder->crtc in ALSA. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 16 ++++++++++++---- - drivers/gpu/drm/vc4/vc4_hdmi.h | 6 ++++++ - 2 files changed, 18 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 8ea2291fe784..d31fd7e1fb17 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -724,6 +724,11 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, - - static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) - { -+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ -+ mutex_lock(&vc4_hdmi->mutex); -+ vc4_hdmi->output_enabled = false; -+ mutex_unlock(&vc4_hdmi->mutex); - } - - static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) -@@ -1217,6 +1222,11 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder, - - static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) - { -+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ -+ mutex_lock(&vc4_hdmi->mutex); -+ vc4_hdmi->output_enabled = true; -+ mutex_unlock(&vc4_hdmi->mutex); - } - - static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, -@@ -1396,14 +1406,12 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai) - - static bool vc4_hdmi_audio_can_stream(struct vc4_hdmi *vc4_hdmi) - { -- struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; -- - lockdep_assert_held(&vc4_hdmi->mutex); - - /* -- * The encoder doesn't have a CRTC until the first modeset. -+ * If the controller is disabled, prevent any ALSA output. - */ -- if (!encoder->crtc) -+ if (!vc4_hdmi->output_enabled) - return false; - - /* -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h -index a43cc5614d19..5d3e97703e8d 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h -@@ -203,6 +203,12 @@ struct vc4_hdmi { - * for use by ALSA hooks and interrupt handlers. Protected by @mutex. - */ - struct drm_display_mode saved_adjusted_mode; -+ -+ /** -+ * @output_enabled: Is the HDMI controller currently active? -+ * Protected by @mutex. -+ */ -+ bool output_enabled; - }; - - static inline struct vc4_hdmi * --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0019-drm-vc4-hdmi-Introduce-a-scdc_enabled-flag.patch b/root/target/linux/bcm27xx/patches-5.15/0019-drm-vc4-hdmi-Introduce-a-scdc_enabled-flag.patch deleted file mode 100644 index f00e9b41..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0019-drm-vc4-hdmi-Introduce-a-scdc_enabled-flag.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 9aa26a91fcad0b72ff20dbc5dbce2a39eaf73d41 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Tue, 19 Oct 2021 19:13:46 +0200 -Subject: [PATCH 019/634] drm/vc4: hdmi: Introduce a scdc_enabled flag - -We currently rely on two functions, vc4_hdmi_supports_scrambling() and -vc4_hdmi_mode_needs_scrambling() to determine if we should enable and -disable the scrambler for any given mode. - -Since we might need to disable the controller at boot, we also always -run vc4_hdmi_disable_scrambling() and thus call those functions without -a mode yet, which in turns need to make some special casing in order for -it to work. - -Instead of duplicating the check for whether or not we need to take care -of the scrambler in both vc4_hdmi_enable_scrambling() and -vc4_hdmi_disable_scrambling(), we can do that check only when we enable -it and store whether or not it's been enabled in our private structure. - -We also need to initialize that flag at true to make sure we disable the -scrambler at boot since we can't really know its state yet. - -This allows to simplify a bit that part of the driver, and removes one -user of our copy of the CRTC adjusted mode outside of KMS (since -vc4_hdmi_disable_scrambling() might be called from the hotplug interrupt -handler). - -It also removes our last user of the legacy encoder->crtc pointer. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 22 ++++++++++++---------- - drivers/gpu/drm/vc4/vc4_hdmi.h | 6 ++++++ - 2 files changed, 18 insertions(+), 10 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index d31fd7e1fb17..5cca1dacc933 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -615,6 +615,8 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) - VC5_HDMI_SCRAMBLER_CTL_ENABLE); - spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - -+ vc4_hdmi->scdc_enabled = true; -+ - queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work, - msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS)); - } -@@ -622,22 +624,14 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) - static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) - { - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -- struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; -- struct drm_crtc *crtc = encoder->crtc; - unsigned long flags; - - lockdep_assert_held(&vc4_hdmi->mutex); - -- /* -- * At boot, encoder->crtc will be NULL. Since we don't know the -- * state of the scrambler and in order to avoid any -- * inconsistency, let's disable it all the time. -- */ -- if (crtc && !vc4_hdmi_supports_scrambling(encoder, mode)) -+ if (!vc4_hdmi->scdc_enabled) - return; - -- if (crtc && !vc4_hdmi_mode_needs_scrambling(mode)) -- return; -+ vc4_hdmi->scdc_enabled = false; - - if (delayed_work_pending(&vc4_hdmi->scrambling_work)) - cancel_delayed_work_sync(&vc4_hdmi->scrambling_work); -@@ -2502,6 +2496,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) - vc4_hdmi->pdev = pdev; - vc4_hdmi->variant = variant; - -+ /* -+ * Since we don't know the state of the controller and its -+ * display (if any), let's assume it's always enabled. -+ * vc4_hdmi_disable_scrambling() will thus run at boot, make -+ * sure it's disabled, and avoid any inconsistency. -+ */ -+ vc4_hdmi->scdc_enabled = true; -+ - ret = variant->init_resources(vc4_hdmi); - if (ret) - return ret; -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h -index 5d3e97703e8d..36c0b082a43b 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h -@@ -209,6 +209,12 @@ struct vc4_hdmi { - * Protected by @mutex. - */ - bool output_enabled; -+ -+ /** -+ * @scdc_enabled: Is the HDMI controller currently running with -+ * the scrambler on? Protected by @mutex. -+ */ -+ bool scdc_enabled; - }; - - static inline struct vc4_hdmi * --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0020-drm-vc4-hdmi-Remove-the-DDC-probing-for-status-detec.patch b/root/target/linux/bcm27xx/patches-5.15/0020-drm-vc4-hdmi-Remove-the-DDC-probing-for-status-detec.patch deleted file mode 100644 index e7fb13dc..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0020-drm-vc4-hdmi-Remove-the-DDC-probing-for-status-detec.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 46ea9d1cd67819a8ecdd75893290cbb259f7a71f Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Tue, 11 May 2021 17:05:11 +0200 -Subject: [PATCH 020/634] drm/vc4: hdmi: Remove the DDC probing for status - detection - -Commit 9d44abbbb8d5 ("drm/vc4: Fall back to using an EDID probe in the -absence of a GPIO.") added some code to read the EDID through DDC in the -HDMI driver detect hook since the Pi3 had no HPD GPIO back then. -However, commit b1b8f45b3130 ("ARM: dts: bcm2837: Add missing GPIOs of -Expander") changed that a couple of years later. - -This causes an issue though since some TV (like the LG 55C8) when it -comes out of standy will deassert the HPD line, but the EDID will -remain readable. - -It causes an issues nn platforms without an HPD GPIO, like the Pi4, -where the DDC probing will be our primary mean to detect a display, and -thus we will never detect the HPD pulse. This was fine before since the -pulse was small enough that we would never detect it, and we also didn't -have anything (like the scrambler) that needed to be set up in the -display. - -However, now that we have both, the display during the HPD pulse will -clear its scrambler status, and since we won't detect the -disconnect/reconnect cycle we will never enable the scrambler back. - -As our main reason for that DDC probing is gone, let's just remove it. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 5cca1dacc933..918941a2bc58 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -193,8 +193,6 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - if (vc4_hdmi->hpd_gpio && - gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) { - connected = true; -- } else if (drm_probe_ddc(vc4_hdmi->ddc)) { -- connected = true; - } else { - unsigned long flags; - u32 hotplug; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0021-drm-vc4-hdmi-Fix-HPD-GPIO-detection.patch b/root/target/linux/bcm27xx/patches-5.15/0021-drm-vc4-hdmi-Fix-HPD-GPIO-detection.patch deleted file mode 100644 index 7ff65dcc..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0021-drm-vc4-hdmi-Fix-HPD-GPIO-detection.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 84da606fe60662e046d6f7982d8a9281245b09f5 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 25 Jun 2021 17:16:51 +0200 -Subject: [PATCH 021/634] drm/vc4: hdmi: Fix HPD GPIO detection - -Prior to commit 6800234ceee0 ("drm/vc4: hdmi: Convert to gpiod"), in the -detect hook, if we had an HPD GPIO we would only rely on it and return -whatever state it was in. - -However, that commit changed that by mistake to only consider the case -where we have a GPIO and it returns a logical high, and would fall back -to the other methods otherwise. - -Since we can read the EDIDs when the HPD signal is low on some displays, -we changed the detection status from disconnected to connected, and we -would ignore an HPD pulse. - -Fixes: 6800234ceee0 ("drm/vc4: hdmi: Convert to gpiod") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 918941a2bc58..50e9e1f3ac47 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -190,9 +190,9 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - - WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); - -- if (vc4_hdmi->hpd_gpio && -- gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) { -- connected = true; -+ if (vc4_hdmi->hpd_gpio) { -+ if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) -+ connected = true; - } else { - unsigned long flags; - u32 hotplug; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0022-drm-vc4-Make-vc4_crtc_get_encoder-public.patch b/root/target/linux/bcm27xx/patches-5.15/0022-drm-vc4-Make-vc4_crtc_get_encoder-public.patch deleted file mode 100644 index c3a7a922..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0022-drm-vc4-Make-vc4_crtc_get_encoder-public.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 6ca024fdd37a7953f7f6ee301fef026cf9446272 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 26 May 2021 16:07:01 +0200 -Subject: [PATCH 022/634] drm/vc4: Make vc4_crtc_get_encoder public - -We'll need that function in vc4_kms to compute the core clock rate -requirements. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++---- - drivers/gpu/drm/vc4/vc4_drv.h | 5 +++++ - 2 files changed, 9 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index e3ed52d96f42..7cfd4a097847 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -281,10 +281,10 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc, - * allows drivers to push pixels to more than one encoder from the - * same CRTC. - */ --static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, -- struct drm_atomic_state *state, -- struct drm_connector_state *(*get_state)(struct drm_atomic_state *state, -- struct drm_connector *connector)) -+struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, -+ struct drm_atomic_state *state, -+ struct drm_connector_state *(*get_state)(struct drm_atomic_state *state, -+ struct drm_connector *connector)) - { - struct drm_connector *connector; - struct drm_connector_list_iter conn_iter; -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 4b550ebd9572..f5e678491502 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -544,6 +544,11 @@ vc4_crtc_to_vc4_pv_data(const struct vc4_crtc *crtc) - return container_of(data, struct vc4_pv_data, base); - } - -+struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, -+ struct drm_atomic_state *state, -+ struct drm_connector_state *(*get_state)(struct drm_atomic_state *state, -+ struct drm_connector *connector)); -+ - struct vc4_crtc_state { - struct drm_crtc_state base; - /* Dlist area for this CRTC configuration. */ --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0023-drm-vc4-crtc-Add-encoder-to-vc4_crtc_config_pv-proto.patch b/root/target/linux/bcm27xx/patches-5.15/0023-drm-vc4-crtc-Add-encoder-to-vc4_crtc_config_pv-proto.patch deleted file mode 100644 index d06dad4b..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0023-drm-vc4-crtc-Add-encoder-to-vc4_crtc_config_pv-proto.patch +++ /dev/null @@ -1,48 +0,0 @@ -From c2092ee4811081bab692db0ccf4893797df54b13 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 14 Jun 2021 15:27:24 +0200 -Subject: [PATCH 023/634] drm/vc4: crtc: Add encoder to vc4_crtc_config_pv - prototype - -vc4_crtc_config_pv() retrieves the encoder again, even though its only -caller, vc4_crtc_atomic_enable(), already did. - -Pass the encoder pointer as an argument instead of going through all the -connectors to retrieve it again. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 7cfd4a097847..e5c2e29a6f01 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -315,12 +315,11 @@ static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc) - CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_FIFO_CLR); - } - --static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_atomic_state *state) -+static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encoder, -+ struct drm_atomic_state *state) - { - struct drm_device *dev = crtc->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); -- struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, state, -- drm_atomic_get_new_connector_state); - struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc); -@@ -597,7 +596,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, - if (vc4_encoder->pre_crtc_configure) - vc4_encoder->pre_crtc_configure(encoder, state); - -- vc4_crtc_config_pv(crtc, state); -+ vc4_crtc_config_pv(crtc, encoder, state); - - CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN); - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0024-drm-vc4-crtc-Rework-the-encoder-retrieval-code-again.patch b/root/target/linux/bcm27xx/patches-5.15/0024-drm-vc4-crtc-Rework-the-encoder-retrieval-code-again.patch deleted file mode 100644 index 93df4c11..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0024-drm-vc4-crtc-Rework-the-encoder-retrieval-code-again.patch +++ /dev/null @@ -1,102 +0,0 @@ -From af2318d413f366931b7efaf179c326d67557e64b Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 21 Jun 2021 16:07:22 +0200 -Subject: [PATCH 024/634] drm/vc4: crtc: Rework the encoder retrieval code - (again) - -It turns out the encoder retrieval code, in addition to being -unnecessarily complicated, has a bug when only the planes and crtcs are -affected by a given atomic commit. - -Indeed, in such a case, either drm_atomic_get_old_connector_state or -drm_atomic_get_new_connector_state will return NULL and thus our encoder -retrieval code will not match on anything. - -We can however simplify the code by using drm_for_each_encoder_mask, the -drm_crtc_state storing the encoders a given CRTC is connected to -directly and without relying on any other state. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 30 +++++++++--------------------- - drivers/gpu/drm/vc4/vc4_drv.h | 4 +--- - 2 files changed, 10 insertions(+), 24 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index e5c2e29a6f01..fbc1d4638650 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -282,26 +282,14 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc, - * same CRTC. - */ - struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, -- struct drm_atomic_state *state, -- struct drm_connector_state *(*get_state)(struct drm_atomic_state *state, -- struct drm_connector *connector)) -+ struct drm_crtc_state *state) - { -- struct drm_connector *connector; -- struct drm_connector_list_iter conn_iter; -- -- drm_connector_list_iter_begin(crtc->dev, &conn_iter); -- drm_for_each_connector_iter(connector, &conn_iter) { -- struct drm_connector_state *conn_state = get_state(state, connector); -+ struct drm_encoder *encoder; - -- if (!conn_state) -- continue; -+ WARN_ON(hweight32(state->encoder_mask) > 1); - -- if (conn_state->crtc == crtc) { -- drm_connector_list_iter_end(&conn_iter); -- return connector->encoder; -- } -- } -- drm_connector_list_iter_end(&conn_iter); -+ drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) -+ return encoder; - - return NULL; - } -@@ -550,8 +538,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, - crtc); - struct vc4_crtc_state *old_vc4_state = to_vc4_crtc_state(old_state); -- struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, state, -- drm_atomic_get_old_connector_state); -+ struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, old_state); - struct drm_device *dev = crtc->dev; - - require_hvs_enabled(dev); -@@ -578,10 +565,11 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, - static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) - { -+ struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state, -+ crtc); - struct drm_device *dev = crtc->dev; - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -- struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, state, -- drm_atomic_get_new_connector_state); -+ struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, new_state); - struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); - - require_hvs_enabled(dev); -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index f5e678491502..60826aca9e5b 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -545,9 +545,7 @@ vc4_crtc_to_vc4_pv_data(const struct vc4_crtc *crtc) - } - - struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, -- struct drm_atomic_state *state, -- struct drm_connector_state *(*get_state)(struct drm_atomic_state *state, -- struct drm_connector *connector)); -+ struct drm_crtc_state *state); - - struct vc4_crtc_state { - struct drm_crtc_state base; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0025-drm-vc4-crtc-Add-some-logging.patch b/root/target/linux/bcm27xx/patches-5.15/0025-drm-vc4-crtc-Add-some-logging.patch deleted file mode 100644 index b70555fe..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0025-drm-vc4-crtc-Add-some-logging.patch +++ /dev/null @@ -1,43 +0,0 @@ -From f13f8a8233fdec553f3788edba1ebf5a6090b330 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 21 Jun 2021 16:13:02 +0200 -Subject: [PATCH 025/634] drm/vc4: crtc: Add some logging - -The encoder retrieval code has been a source of bugs and glitches in the -past and the crtc <-> encoder association been wrong in a number of -different ways. - -Add some logging to quickly spot issues if they occur. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index fbc1d4638650..6decaa12a078 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -541,6 +541,9 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, old_state); - struct drm_device *dev = crtc->dev; - -+ drm_dbg(dev, "Disabling CRTC %s (%u) connected to Encoder %s (%u)", -+ crtc->name, crtc->base.id, encoder->name, encoder->base.id); -+ - require_hvs_enabled(dev); - - /* Disable vblank irq handling before crtc is disabled. */ -@@ -572,6 +575,9 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, new_state); - struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); - -+ drm_dbg(dev, "Enabling CRTC %s (%u) connected to Encoder %s (%u)", -+ crtc->name, crtc->base.id, encoder->name, encoder->base.id); -+ - require_hvs_enabled(dev); - - /* Enable vblank irq handling before crtc is started otherwise --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0026-drm-vc4-Leverage-the-load-tracker-on-the-BCM2711.patch b/root/target/linux/bcm27xx/patches-5.15/0026-drm-vc4-Leverage-the-load-tracker-on-the-BCM2711.patch deleted file mode 100644 index 8aaa7925..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0026-drm-vc4-Leverage-the-load-tracker-on-the-BCM2711.patch +++ /dev/null @@ -1,134 +0,0 @@ -From b678d84ff877cf7f4264707f30f5e26c643f8414 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 21 Jun 2021 17:19:22 +0200 -Subject: [PATCH 026/634] drm/vc4: Leverage the load tracker on the BCM2711 - -The load tracker was initially designed to report and warn about a load -too high for the HVS. To do so, it computes for each plane the impact -it's going to have on the HVS, and will warn (if it's enabled) if we go -over what the hardware can process. - -While the limits being used are a bit irrelevant to the BCM2711, the -algorithm to compute the HVS load will be one component used in order to -compute the core clock rate on the BCM2711. - -Let's remove the hooks to prevent the load tracker to do its -computation, but since we don't have the same limits, don't check them -against them, and prevent the debugfs file to enable it from being -created. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_debugfs.c | 7 +++++-- - drivers/gpu/drm/vc4/vc4_drv.h | 3 --- - drivers/gpu/drm/vc4/vc4_kms.c | 16 +++++----------- - drivers/gpu/drm/vc4/vc4_plane.c | 5 ----- - 4 files changed, 10 insertions(+), 21 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c -index 6da22af4ee91..ba2d8ea562af 100644 ---- a/drivers/gpu/drm/vc4/vc4_debugfs.c -+++ b/drivers/gpu/drm/vc4/vc4_debugfs.c -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - - #include "vc4_drv.h" - #include "vc4_regs.h" -@@ -26,8 +27,10 @@ vc4_debugfs_init(struct drm_minor *minor) - struct vc4_dev *vc4 = to_vc4_dev(minor->dev); - struct vc4_debugfs_info_entry *entry; - -- debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR, -- minor->debugfs_root, &vc4->load_tracker_enabled); -+ if (!of_device_is_compatible(vc4->hvs->pdev->dev.of_node, -+ "brcm,bcm2711-vc5")) -+ debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR, -+ minor->debugfs_root, &vc4->load_tracker_enabled); - - list_for_each_entry(entry, &vc4->debugfs_list, link) { - drm_debugfs_create_files(&entry->info, 1, -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 60826aca9e5b..813c5d0ea98e 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -202,9 +202,6 @@ struct vc4_dev { - - int power_refcount; - -- /* Set to true when the load tracker is supported. */ -- bool load_tracker_available; -- - /* Set to true when the load tracker is active. */ - bool load_tracker_enabled; - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 028f19f7a5f8..41cb4869da50 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -552,9 +552,6 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state) - struct drm_plane *plane; - int i; - -- if (!vc4->load_tracker_available) -- return 0; -- - priv_state = drm_atomic_get_private_obj_state(state, - &vc4->load_tracker); - if (IS_ERR(priv_state)) -@@ -629,9 +626,6 @@ static void vc4_load_tracker_obj_fini(struct drm_device *dev, void *unused) - { - struct vc4_dev *vc4 = to_vc4_dev(dev); - -- if (!vc4->load_tracker_available) -- return; -- - drm_atomic_private_obj_fini(&vc4->load_tracker); - } - -@@ -639,9 +633,6 @@ static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) - { - struct vc4_load_tracker_state *load_state; - -- if (!vc4->load_tracker_available) -- return 0; -- - load_state = kzalloc(sizeof(*load_state), GFP_KERNEL); - if (!load_state) - return -ENOMEM; -@@ -869,9 +860,12 @@ int vc4_kms_load(struct drm_device *dev) - "brcm,bcm2711-vc5"); - int ret; - -+ /* -+ * The limits enforced by the load tracker aren't relevant for -+ * the BCM2711, but the load tracker computations are used for -+ * the core clock rate calculation. -+ */ - if (!is_vc5) { -- vc4->load_tracker_available = true; -- - /* Start with the load tracker enabled. Can be - * disabled through the debugfs load_tracker file. - */ -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index 19161b6ab27f..ac761c683663 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -529,11 +529,6 @@ static void vc4_plane_calc_load(struct drm_plane_state *state) - struct vc4_plane_state *vc4_state; - struct drm_crtc_state *crtc_state; - unsigned int vscale_factor; -- struct vc4_dev *vc4; -- -- vc4 = to_vc4_dev(state->plane->dev); -- if (!vc4->load_tracker_available) -- return; - - vc4_state = to_vc4_plane_state(state); - crtc_state = drm_atomic_get_existing_crtc_state(state->state, --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0027-drm-vc4-hdmi-Raise-the-maximum-clock-rate.patch b/root/target/linux/bcm27xx/patches-5.15/0027-drm-vc4-hdmi-Raise-the-maximum-clock-rate.patch deleted file mode 100644 index 5d4e4067..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0027-drm-vc4-hdmi-Raise-the-maximum-clock-rate.patch +++ /dev/null @@ -1,35 +0,0 @@ -From cd009dc7e47225c5736cae1d706adcb30b8d4ef5 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 8 Oct 2020 16:08:06 +0200 -Subject: [PATCH 027/634] drm/vc4: hdmi: Raise the maximum clock rate - -Now that we have the infrastructure in place, we can raise the maximum -pixel rate we can reach for HDMI0 on the BCM2711. - -HDMI1 is left untouched since its pixelvalve has a smaller FIFO and -would need a clock faster than what we can provide to support the same -modes. - -Acked-by: Thomas Zimmermann -Reviewed-by: Dave Stevenson -Signed-off-by: Maxime Ripard ---- - 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 50e9e1f3ac47..80ce69e0ead5 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -2697,7 +2697,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { - .encoder_type = VC4_ENCODER_TYPE_HDMI0, - .debugfs_name = "hdmi0_regs", - .card_name = "vc4-hdmi-0", -- .max_pixel_clock = HDMI_14_MAX_TMDS_CLK, -+ .max_pixel_clock = 600000000, - .registers = vc5_hdmi_hdmi0_fields, - .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi0_fields), - .phy_lane_mapping = { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0028-drm-vc4-hdmi-Enable-the-scrambler-on-reconnection.patch b/root/target/linux/bcm27xx/patches-5.15/0028-drm-vc4-hdmi-Enable-the-scrambler-on-reconnection.patch deleted file mode 100644 index b19a6360..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0028-drm-vc4-hdmi-Enable-the-scrambler-on-reconnection.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 4c78953fff281d78eabbd336a17bcded00d6316f Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 25 Jun 2021 16:22:39 +0200 -Subject: [PATCH 028/634] drm/vc4: hdmi: Enable the scrambler on reconnection - -If we have a state already and disconnect/reconnect the display, the -SCDC messages won't be sent again since we didn't go through a disable / -enable cycle. - -In order to fix this, let's call the vc4_hdmi_enable_scrambling function -in the detect callback if there is a mode and it needs the scrambler to -be enabled. - -Fixes: c85695a2016e ("drm/vc4: hdmi: Enable the scrambler") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 80ce69e0ead5..87870775471d 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -180,6 +180,8 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) - static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} - #endif - -+static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder); -+ - static enum drm_connector_status - vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - { -@@ -216,6 +218,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - } - } - -+ vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base.base); - pm_runtime_put(&vc4_hdmi->pdev->dev); - mutex_unlock(&vc4_hdmi->mutex); - return connector_status_connected; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0029-drm-vc4-Increase-the-core-clock-based-on-HVS-load.patch b/root/target/linux/bcm27xx/patches-5.15/0029-drm-vc4-Increase-the-core-clock-based-on-HVS-load.patch deleted file mode 100644 index 63db46c3..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0029-drm-vc4-Increase-the-core-clock-based-on-HVS-load.patch +++ /dev/null @@ -1,247 +0,0 @@ -From 32ab2dd5dc63120f1e006e4a3a6beaafbd5dd550 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 26 May 2021 16:13:02 +0200 -Subject: [PATCH 029/634] drm/vc4: Increase the core clock based on HVS load - -Depending on a given HVS output (HVS to PixelValves) and input (planes -attached to a channel) load, the HVS needs for the core clock to be -raised above its boot time default. - -Failing to do so will result in a vblank timeout and a stalled display -pipeline. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 15 +++++ - drivers/gpu/drm/vc4/vc4_drv.h | 2 + - drivers/gpu/drm/vc4/vc4_kms.c | 110 ++++++++++++++++++++++++++++++--- - 3 files changed, 118 insertions(+), 9 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 6decaa12a078..287dbc89ad64 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -659,12 +659,27 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc, - struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); - struct drm_connector *conn; - struct drm_connector_state *conn_state; -+ struct drm_encoder *encoder; - int ret, i; - - ret = vc4_hvs_atomic_check(crtc, state); - if (ret) - return ret; - -+ encoder = vc4_get_crtc_encoder(crtc, crtc_state); -+ if (encoder) { -+ const struct drm_display_mode *mode = &crtc_state->adjusted_mode; -+ struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); -+ -+ mode = &crtc_state->adjusted_mode; -+ if (vc4_encoder->type == VC4_ENCODER_TYPE_HDMI0) { -+ vc4_state->hvs_load = max(mode->clock * mode->hdisplay / mode->htotal + 1000, -+ mode->clock * 9 / 10) * 1000; -+ } else { -+ vc4_state->hvs_load = mode->clock * 1000; -+ } -+ } -+ - for_each_new_connector_in_state(state, conn, conn_state, - i) { - if (conn_state->crtc != crtc) -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 813c5d0ea98e..4329e09d357c 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -558,6 +558,8 @@ struct vc4_crtc_state { - unsigned int bottom; - } margins; - -+ unsigned long hvs_load; -+ - /* Transitional state below, only valid during atomic commits */ - bool update_muxing; - }; -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 41cb4869da50..79d4d9dd1394 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -39,9 +39,11 @@ static struct vc4_ctm_state *to_vc4_ctm_state(struct drm_private_state *priv) - - struct vc4_hvs_state { - struct drm_private_state base; -+ unsigned long core_clock_rate; - - struct { - unsigned in_use: 1; -+ unsigned long fifo_load; - struct drm_crtc_commit *pending_commit; - } fifo_state[HVS_NUM_CHANNELS]; - }; -@@ -340,10 +342,19 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - struct vc4_hvs *hvs = vc4->hvs; - struct drm_crtc_state *old_crtc_state; - struct drm_crtc_state *new_crtc_state; -+ struct vc4_hvs_state *new_hvs_state; - struct drm_crtc *crtc; - struct vc4_hvs_state *old_hvs_state; - int i; - -+ old_hvs_state = vc4_hvs_get_old_global_state(state); -+ if (WARN_ON(!old_hvs_state)) -+ return; -+ -+ new_hvs_state = vc4_hvs_get_new_global_state(state); -+ if (WARN_ON(!new_hvs_state)) -+ return; -+ - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - struct vc4_crtc_state *vc4_crtc_state; - -@@ -354,12 +365,13 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); - } - -- if (vc4->hvs->hvs5) -- clk_set_min_rate(hvs->core_clk, 500000000); -+ if (vc4->hvs->hvs5) { -+ unsigned long core_rate = max_t(unsigned long, -+ 500000000, -+ new_hvs_state->core_clock_rate); - -- old_hvs_state = vc4_hvs_get_old_global_state(state); -- if (!old_hvs_state) -- return; -+ clk_set_min_rate(hvs->core_clk, core_rate); -+ } - - for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { - struct vc4_crtc_state *vc4_crtc_state = -@@ -399,8 +411,12 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - - drm_atomic_helper_cleanup_planes(dev, state); - -- if (vc4->hvs->hvs5) -- clk_set_min_rate(hvs->core_clk, 0); -+ if (vc4->hvs->hvs5) { -+ drm_dbg(dev, "Running the core clock at %lu Hz\n", -+ new_hvs_state->core_clock_rate); -+ -+ clk_set_min_rate(hvs->core_clk, new_hvs_state->core_clock_rate); -+ } - } - - static int vc4_atomic_commit_setup(struct drm_atomic_state *state) -@@ -657,9 +673,9 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) - - __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); - -- - for (i = 0; i < HVS_NUM_CHANNELS; i++) { - state->fifo_state[i].in_use = old_state->fifo_state[i].in_use; -+ state->fifo_state[i].fifo_load = old_state->fifo_state[i].fifo_load; - - if (!old_state->fifo_state[i].pending_commit) - continue; -@@ -668,6 +684,8 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) - drm_crtc_commit_get(old_state->fifo_state[i].pending_commit); - } - -+ state->core_clock_rate = old_state->core_clock_rate; -+ - return &state->base; - } - -@@ -822,6 +840,76 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, - return 0; - } - -+static int -+vc4_core_clock_atomic_check(struct drm_atomic_state *state) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(state->dev); -+ struct drm_private_state *priv_state; -+ struct vc4_hvs_state *hvs_new_state; -+ struct vc4_load_tracker_state *load_state; -+ struct drm_crtc_state *old_crtc_state, *new_crtc_state; -+ struct drm_crtc *crtc; -+ unsigned int num_outputs; -+ unsigned long pixel_rate; -+ unsigned long cob_rate; -+ unsigned int i; -+ -+ priv_state = drm_atomic_get_private_obj_state(state, -+ &vc4->load_tracker); -+ if (IS_ERR(priv_state)) -+ return PTR_ERR(priv_state); -+ -+ load_state = to_vc4_load_tracker_state(priv_state); -+ -+ hvs_new_state = vc4_hvs_get_global_state(state); -+ if (!hvs_new_state) -+ return -EINVAL; -+ -+ for_each_oldnew_crtc_in_state(state, crtc, -+ old_crtc_state, -+ new_crtc_state, -+ i) { -+ if (old_crtc_state->active) { -+ struct vc4_crtc_state *old_vc4_state = -+ to_vc4_crtc_state(old_crtc_state); -+ unsigned int channel = old_vc4_state->assigned_channel; -+ -+ hvs_new_state->fifo_state[channel].fifo_load = 0; -+ } -+ -+ if (new_crtc_state->active) { -+ struct vc4_crtc_state *new_vc4_state = -+ to_vc4_crtc_state(new_crtc_state); -+ unsigned int channel = new_vc4_state->assigned_channel; -+ -+ hvs_new_state->fifo_state[channel].fifo_load = -+ new_vc4_state->hvs_load; -+ } -+ } -+ -+ cob_rate = 0; -+ num_outputs = 0; -+ for (i = 0; i < HVS_NUM_CHANNELS; i++) { -+ if (!hvs_new_state->fifo_state[i].in_use) -+ continue; -+ -+ num_outputs++; -+ cob_rate += hvs_new_state->fifo_state[i].fifo_load; -+ } -+ -+ pixel_rate = load_state->hvs_load; -+ if (num_outputs > 1) { -+ pixel_rate = (pixel_rate * 40) / 100; -+ } else { -+ pixel_rate = (pixel_rate * 60) / 100; -+ } -+ -+ hvs_new_state->core_clock_rate = max(cob_rate, pixel_rate); -+ -+ return 0; -+} -+ -+ - static int - vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) - { -@@ -839,7 +927,11 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) - if (ret) - return ret; - -- return vc4_load_tracker_atomic_check(state); -+ ret = vc4_load_tracker_atomic_check(state); -+ if (ret) -+ return ret; -+ -+ return vc4_core_clock_atomic_check(state); - } - - static struct drm_mode_config_helper_funcs vc4_mode_config_helpers = { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0030-drm-vc4-select-PM.patch b/root/target/linux/bcm27xx/patches-5.15/0030-drm-vc4-select-PM.patch deleted file mode 100644 index 31875644..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0030-drm-vc4-select-PM.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 13fd7f615657b8b300e1840a1ec393079126f53f Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 19 Aug 2021 15:53:03 +0200 -Subject: [PATCH 030/634] drm/vc4: select PM - -We already depend on runtime PM to get the power domains and clocks for -most of the devices supported by the vc4 driver, so let's just select it -to make sure it's there, and remove the ifdef. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/Kconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig -index 345a5570a3da..52a1c309cb4a 100644 ---- a/drivers/gpu/drm/vc4/Kconfig -+++ b/drivers/gpu/drm/vc4/Kconfig -@@ -9,6 +9,7 @@ config DRM_VC4 - select DRM_KMS_CMA_HELPER - select DRM_GEM_CMA_HELPER - select DRM_PANEL_BRIDGE -+ select PM - select SND_PCM - select SND_PCM_ELD - select SND_SOC_GENERIC_DMAENGINE_PCM --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0032-drm-vc4-hdmi-Actually-check-for-the-connector-status.patch b/root/target/linux/bcm27xx/patches-5.15/0032-drm-vc4-hdmi-Actually-check-for-the-connector-status.patch deleted file mode 100644 index d849e8cb..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0032-drm-vc4-hdmi-Actually-check-for-the-connector-status.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 9219926b71a1c16eb77ef9d96b14913b7f03757d Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 19 Aug 2021 13:50:12 +0200 -Subject: [PATCH 032/634] drm/vc4: hdmi: Actually check for the connector - status in hotplug - -The drm_helper_hpd_irq_event() documentation states that this function -is "useful for drivers which can't or don't track hotplug interrupts for -each connector." and that "Drivers which support hotplug interrupts for -each connector individually and which have a more fine-grained detect -logic should bypass this code and directly call -drm_kms_helper_hotplug_event()". This is thus what we ended-up doing. - -However, what this actually means, and is further explained in the -drm_kms_helper_hotplug_event() documentation, is that -drm_kms_helper_hotplug_event() should be called by drivers that can -track the connection status change, and if it has changed we should call -that function. - -This underlying expectation we failed to provide is that the caller of -drm_kms_helper_hotplug_event() should call drm_helper_probe_detect() to -probe the new status of the connector. - -Since we didn't do it, it meant that even though we were sending the -notification to user-space and the DRM clients that something changed we -never probed or updated our internal connector status ourselves. - -This went mostly unnoticed since the detect callback usually doesn't -have any side-effect. Also, if we were using the DRM fbdev emulation -(which is a DRM client), or any user-space application that can deal -with hotplug events, chances are they would react to the hotplug event -by probing the connector status eventually. - -However, now that we have to enable the scrambler in detect() if it was -enabled it has a side effect, and an application such as Kodi or -modetest doesn't deal with hotplug events. This resulted with a black -screen when Kodi or modetest was running when a screen was disconnected -and then reconnected, or switched off and on. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 87870775471d..053fbaf765ca 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -1783,10 +1783,11 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) - static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv) - { - struct vc4_hdmi *vc4_hdmi = priv; -- struct drm_device *dev = vc4_hdmi->connector.dev; -+ struct drm_connector *connector = &vc4_hdmi->connector; -+ struct drm_device *dev = connector->dev; - - if (dev && dev->registered) -- drm_kms_helper_hotplug_event(dev); -+ drm_connector_helper_hpd_irq_event(connector); - - return IRQ_HANDLED; - } --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0204-pinctrl-bcm2835-Change-init-order-for-gpio-hogs.patch b/root/target/linux/bcm27xx/patches-5.15/0204-pinctrl-bcm2835-Change-init-order-for-gpio-hogs.patch deleted file mode 100644 index 24335daf..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0204-pinctrl-bcm2835-Change-init-order-for-gpio-hogs.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 59a74cec84cf3d24346e378fd9b93df8ee593135 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 6 Jan 2020 14:05:42 +0000 -Subject: [PATCH 204/634] pinctrl: bcm2835: Change init order for gpio hogs - -pinctrl-bcm2835 is a combined pinctrl/gpio driver. Currently the gpio -side is registered first, but this breaks gpio hogs (which are -configured during gpiochip_add_data). Part of the hog initialisation -is a call to pinctrl_gpio_request, and since the pinctrl driver hasn't -yet been registered this results in an -EPROBE_DEFER from which it can -never recover. - -Change the initialisation sequence to register the pinctrl driver -first. - -See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=260600 - -Signed-off-by: Phil Elwell ---- - drivers/pinctrl/bcm/pinctrl-bcm2835.c | 29 +++++++++++++++------------ - 1 file changed, 16 insertions(+), 13 deletions(-) - -diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index 1fb103eb34a2..28ddc9f139a6 100644 ---- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c -+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -@@ -1243,6 +1243,18 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) - raw_spin_lock_init(&pc->irq_lock[i]); - } - -+ pc->pctl_desc = *pdata->pctl_desc; -+ pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); -+ if (IS_ERR(pc->pctl_dev)) { -+ gpiochip_remove(&pc->gpio_chip); -+ return PTR_ERR(pc->pctl_dev); -+ } -+ -+ pc->gpio_range = *pdata->gpio_range; -+ pc->gpio_range.base = pc->gpio_chip.base; -+ pc->gpio_range.gc = &pc->gpio_chip; -+ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); -+ - girq = &pc->gpio_chip.irq; - girq->chip = &bcm2835_gpio_irq_chip; - girq->parent_handler = bcm2835_gpio_irq_handler; -@@ -1250,8 +1262,10 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) - girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS, - sizeof(*girq->parents), - GFP_KERNEL); -- if (!girq->parents) -+ if (!girq->parents) { -+ pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); - return -ENOMEM; -+ } - - if (is_7211) { - pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS, -@@ -1306,21 +1320,10 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) - err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc); - if (err) { - dev_err(dev, "could not add GPIO chip\n"); -+ pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); - return err; - } - -- pc->pctl_desc = *pdata->pctl_desc; -- pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); -- if (IS_ERR(pc->pctl_dev)) { -- gpiochip_remove(&pc->gpio_chip); -- return PTR_ERR(pc->pctl_dev); -- } -- -- pc->gpio_range = *pdata->gpio_range; -- pc->gpio_range.base = pc->gpio_chip.base; -- pc->gpio_range.gc = &pc->gpio_chip; -- pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); -- - return 0; - } - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0441-drm-vc4-Adopt-the-dma-configuration-from-the-HVS-or-.patch b/root/target/linux/bcm27xx/patches-5.15/0441-drm-vc4-Adopt-the-dma-configuration-from-the-HVS-or-.patch deleted file mode 100644 index c523fbb7..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0441-drm-vc4-Adopt-the-dma-configuration-from-the-HVS-or-.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 78214f46d4903daf99263fdcc19ef2cb10d9030e Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Tue, 19 May 2020 14:54:28 +0100 -Subject: [PATCH 441/634] drm/vc4: Adopt the dma configuration from the HVS or - V3D component - -vc4_drv isn't necessarily under the /soc node in DT as it is a -virtual device, but it is the one that does the allocations. -The DMA addresses are consumed by primarily the HVS or V3D, and -those require VideoCore cache alias address mapping, and so will be -under /soc. - -During probe find the a suitable device node for HVS or V3D, -and adopt the DMA configuration of that node. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_drv.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index f6c16c5aee68..2a2e99873e40 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -214,6 +214,14 @@ static void vc4_match_add_drivers(struct device *dev, - } - } - -+const struct of_device_id vc4_dma_range_matches[] = { -+ { .compatible = "brcm,bcm2835-hvs" }, -+ { .compatible = "brcm,bcm2835-v3d" }, -+ { .compatible = "brcm,cygnus-v3d" }, -+ { .compatible = "brcm,vc4-v3d" }, -+ {} -+}; -+ - static int vc4_drm_bind(struct device *dev) - { - struct platform_device *pdev = to_platform_device(dev); -@@ -231,6 +239,16 @@ static int vc4_drm_bind(struct device *dev) - vc4_drm_driver.driver_features &= ~DRIVER_RENDER; - of_node_put(node); - -+ node = of_find_matching_node_and_match(NULL, vc4_dma_range_matches, -+ NULL); -+ if (node) { -+ ret = of_dma_configure(dev, node, true); -+ of_node_put(node); -+ -+ if (ret) -+ return ret; -+ } -+ - vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base); - if (IS_ERR(vc4)) - return PTR_ERR(vc4); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0443-drm-vc4-Add-support-for-DRM_FORMAT_P030-to-vc4-plane.patch b/root/target/linux/bcm27xx/patches-5.15/0443-drm-vc4-Add-support-for-DRM_FORMAT_P030-to-vc4-plane.patch deleted file mode 100644 index c45a1122..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0443-drm-vc4-Add-support-for-DRM_FORMAT_P030-to-vc4-plane.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 01281cef6f63e94e91a5eec62691b92d62451364 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Fri, 24 Jan 2020 14:25:41 +0000 -Subject: [PATCH 443/634] drm/vc4: Add support for DRM_FORMAT_P030 to vc4 - planes - -This currently doesn't handle non-zero source rectangles correctly, -but add support for DRM_FORMAT_P030 with DRM_FORMAT_MOD_BROADCOM_SAND128 -modifier to planes when running on HVS5. - -WIP still for source cropping SAND/P030 formats - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_plane.c | 79 ++++++++++++++++++++++++--------- - 1 file changed, 57 insertions(+), 22 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index ac761c683663..37a99ab9538c 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -33,6 +33,7 @@ static const struct hvs_format { - u32 hvs; /* HVS_FORMAT_* */ - u32 pixel_order; - u32 pixel_order_hvs5; -+ bool hvs5_only; - } hvs_formats[] = { - { - .drm = DRM_FORMAT_XRGB8888, -@@ -128,6 +129,12 @@ static const struct hvs_format { - .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE, - .pixel_order = HVS_PIXEL_ORDER_XYCRCB, - }, -+ { -+ .drm = DRM_FORMAT_P030, -+ .hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT, -+ .pixel_order = HVS_PIXEL_ORDER_XYCBCR, -+ .hvs5_only = true, -+ }, - }; - - static const struct hvs_format *vc4_get_hvs_format(u32 drm_format) -@@ -764,27 +771,33 @@ static int vc4_plane_mode_set(struct drm_plane *plane, - uint32_t param = fourcc_mod_broadcom_param(fb->modifier); - u32 tile_w, tile, x_off, pix_per_tile; - -- hvs_format = HVS_PIXEL_FORMAT_H264; -- -- switch (base_format_mod) { -- case DRM_FORMAT_MOD_BROADCOM_SAND64: -- tiling = SCALER_CTL0_TILING_64B; -- tile_w = 64; -- break; -- case DRM_FORMAT_MOD_BROADCOM_SAND128: -+ if (fb->format->format == DRM_FORMAT_P030) { -+ hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT; - tiling = SCALER_CTL0_TILING_128B; -- tile_w = 128; -- break; -- case DRM_FORMAT_MOD_BROADCOM_SAND256: -- tiling = SCALER_CTL0_TILING_256B_OR_T; -- tile_w = 256; -- break; -- default: -- break; -+ tile_w = 96; -+ } else { -+ hvs_format = HVS_PIXEL_FORMAT_H264; -+ -+ switch (base_format_mod) { -+ case DRM_FORMAT_MOD_BROADCOM_SAND64: -+ tiling = SCALER_CTL0_TILING_64B; -+ tile_w = 64; -+ break; -+ case DRM_FORMAT_MOD_BROADCOM_SAND128: -+ tiling = SCALER_CTL0_TILING_128B; -+ tile_w = 128; -+ break; -+ case DRM_FORMAT_MOD_BROADCOM_SAND256: -+ tiling = SCALER_CTL0_TILING_256B_OR_T; -+ tile_w = 256; -+ break; -+ default: -+ break; -+ } - } -- - if (param > SCALER_TILE_HEIGHT_MASK) { -- DRM_DEBUG_KMS("SAND height too large (%d)\n", param); -+ DRM_DEBUG_KMS("SAND height too large (%d)\n", -+ param); - return -EINVAL; - } - -@@ -794,6 +807,13 @@ static int vc4_plane_mode_set(struct drm_plane *plane, - - /* Adjust the base pointer to the first pixel to be scanned - * out. -+ * -+ * For P030, y_ptr [31:4] is the 128bit word for the start pixel -+ * y_ptr [3:0] is the pixel (0-11) contained within that 128bit -+ * word that should be taken as the first pixel. -+ * Ditto uv_ptr [31:4] vs [3:0], however [3:0] contains the -+ * element within the 128bit word, eg for pixel 3 the value -+ * should be 6. - */ - for (i = 0; i < num_planes; i++) { - vc4_state->offsets[i] += param * tile_w * tile; -@@ -955,7 +975,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, - - /* Pitch word 1/2 */ - for (i = 1; i < num_planes; i++) { -- if (hvs_format != HVS_PIXEL_FORMAT_H264) { -+ if (hvs_format != HVS_PIXEL_FORMAT_H264 && -+ hvs_format != HVS_PIXEL_FORMAT_YCBCR_10BIT) { - vc4_dlist_write(vc4_state, - VC4_SET_FIELD(fb->pitches[i], - SCALER_SRC_PITCH)); -@@ -1315,6 +1336,13 @@ static bool vc4_format_mod_supported(struct drm_plane *plane, - default: - return false; - } -+ case DRM_FORMAT_P030: -+ switch (fourcc_mod_broadcom_mod(modifier)) { -+ case DRM_FORMAT_MOD_BROADCOM_SAND128: -+ return true; -+ default: -+ return false; -+ } - case DRM_FORMAT_RGBX1010102: - case DRM_FORMAT_BGRX1010102: - case DRM_FORMAT_RGBA1010102: -@@ -1347,8 +1375,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, - struct drm_plane *plane = NULL; - struct vc4_plane *vc4_plane; - u32 formats[ARRAY_SIZE(hvs_formats)]; -+ int num_formats = 0; - int ret = 0; - unsigned i; -+ bool hvs5 = of_device_is_compatible(dev->dev->of_node, -+ "brcm,bcm2711-vc5"); - static const uint64_t modifiers[] = { - DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, - DRM_FORMAT_MOD_BROADCOM_SAND128, -@@ -1363,13 +1394,17 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, - if (!vc4_plane) - return ERR_PTR(-ENOMEM); - -- for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) -- formats[i] = hvs_formats[i].drm; -+ for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { -+ if (!hvs_formats[i].hvs5_only || hvs5) { -+ formats[num_formats] = hvs_formats[i].drm; -+ num_formats++; -+ } -+ } - - plane = &vc4_plane->base; - ret = drm_universal_plane_init(dev, plane, 0, - &vc4_plane_funcs, -- formats, ARRAY_SIZE(formats), -+ formats, num_formats, - modifiers, type, NULL); - if (ret) - return ERR_PTR(ret); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0444-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch b/root/target/linux/bcm27xx/patches-5.15/0444-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch deleted file mode 100644 index 428de92c..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0444-drm-vc4-Add-support-for-YUV-color-encodings-and-rang.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 6f0f000ac5988d07865104be6585fdb4a075aa4b Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Tue, 17 Sep 2019 18:28:17 +0100 -Subject: [PATCH 444/634] drm/vc4: Add support for YUV color encodings and - ranges - -The BT601/BT709 color encoding and limited vs full -range properties were not being exposed, defaulting -always to BT601 limited range. - -Expose the parameters and set the registers appropriately. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_plane.c | 72 +++++++++++++++++++++++++++++++-- - drivers/gpu/drm/vc4/vc4_regs.h | 3 ++ - 2 files changed, 72 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index 37a99ab9538c..9dd447ecd404 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -623,6 +623,53 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state) - return 0; - } - -+/* The colorspace conversion matrices are held in 3 entries in the dlist. -+ * Create an array of them, with entries for each full and limited mode, and -+ * each supported colorspace. -+ */ -+#define VC4_LIMITED_RANGE 0 -+#define VC4_FULL_RANGE 1 -+ -+static const u32 colorspace_coeffs[2][DRM_COLOR_ENCODING_MAX][3] = { -+ { -+ /* Limited range */ -+ { -+ /* BT601 */ -+ SCALER_CSC0_ITR_R_601_5, -+ SCALER_CSC1_ITR_R_601_5, -+ SCALER_CSC2_ITR_R_601_5, -+ }, { -+ /* BT709 */ -+ SCALER_CSC0_ITR_R_709_3, -+ SCALER_CSC1_ITR_R_709_3, -+ SCALER_CSC2_ITR_R_709_3, -+ }, { -+ /* BT2020. Not supported yet - copy 601 */ -+ SCALER_CSC0_ITR_R_601_5, -+ SCALER_CSC1_ITR_R_601_5, -+ SCALER_CSC2_ITR_R_601_5, -+ } -+ }, { -+ /* Full range */ -+ { -+ /* JFIF */ -+ SCALER_CSC0_JPEG_JFIF, -+ SCALER_CSC1_JPEG_JFIF, -+ SCALER_CSC2_JPEG_JFIF, -+ }, { -+ /* BT709 */ -+ SCALER_CSC0_ITR_R_709_3_FR, -+ SCALER_CSC1_ITR_R_709_3_FR, -+ SCALER_CSC2_ITR_R_709_3_FR, -+ }, { -+ /* BT2020. Not supported yet - copy JFIF */ -+ SCALER_CSC0_JPEG_JFIF, -+ SCALER_CSC1_JPEG_JFIF, -+ SCALER_CSC2_JPEG_JFIF, -+ } -+ } -+}; -+ - /* Writes out a full display list for an active plane to the plane's - * private dlist state. - */ -@@ -987,9 +1034,20 @@ static int vc4_plane_mode_set(struct drm_plane *plane, - - /* Colorspace conversion words */ - if (vc4_state->is_yuv) { -- vc4_dlist_write(vc4_state, SCALER_CSC0_ITR_R_601_5); -- vc4_dlist_write(vc4_state, SCALER_CSC1_ITR_R_601_5); -- vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5); -+ enum drm_color_encoding color_encoding = state->color_encoding; -+ enum drm_color_range color_range = state->color_range; -+ const u32 *ccm; -+ -+ if (color_encoding >= DRM_COLOR_ENCODING_MAX) -+ color_encoding = DRM_COLOR_YCBCR_BT601; -+ if (color_range >= DRM_COLOR_RANGE_MAX) -+ color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; -+ -+ ccm = colorspace_coeffs[color_range][color_encoding]; -+ -+ vc4_dlist_write(vc4_state, ccm[0]); -+ vc4_dlist_write(vc4_state, ccm[1]); -+ vc4_dlist_write(vc4_state, ccm[2]); - } - - vc4_state->lbm_offset = 0; -@@ -1418,6 +1476,14 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, - DRM_MODE_REFLECT_X | - DRM_MODE_REFLECT_Y); - -+ drm_plane_create_color_properties(plane, -+ BIT(DRM_COLOR_YCBCR_BT601) | -+ BIT(DRM_COLOR_YCBCR_BT709), -+ BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | -+ BIT(DRM_COLOR_YCBCR_FULL_RANGE), -+ DRM_COLOR_YCBCR_BT709, -+ DRM_COLOR_YCBCR_LIMITED_RANGE); -+ - return plane; - } - -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 489f921ef44d..78fd28599aeb 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -976,6 +976,7 @@ enum hvs_pixel_format { - #define SCALER_CSC0_ITR_R_601_5 0x00f00000 - #define SCALER_CSC0_ITR_R_709_3 0x00f00000 - #define SCALER_CSC0_JPEG_JFIF 0x00000000 -+#define SCALER_CSC0_ITR_R_709_3_FR 0x00000000 - - /* S2.8 contribution of Cb to Green */ - #define SCALER_CSC1_COEF_CB_GRN_MASK VC4_MASK(31, 22) -@@ -992,6 +993,7 @@ enum hvs_pixel_format { - #define SCALER_CSC1_ITR_R_601_5 0xe73304a8 - #define SCALER_CSC1_ITR_R_709_3 0xf2b784a8 - #define SCALER_CSC1_JPEG_JFIF 0xea34a400 -+#define SCALER_CSC1_ITR_R_709_3_FR 0xe23d0400 - - /* S2.8 contribution of Cb to Red */ - #define SCALER_CSC2_COEF_CB_RED_MASK VC4_MASK(29, 20) -@@ -1005,6 +1007,7 @@ enum hvs_pixel_format { - #define SCALER_CSC2_ITR_R_601_5 0x00066204 - #define SCALER_CSC2_ITR_R_709_3 0x00072a1c - #define SCALER_CSC2_JPEG_JFIF 0x000599c5 -+#define SCALER_CSC2_ITR_R_709_3_FR 0x00064ddb - - #define SCALER_TPZ0_VERT_RECALC BIT(31) - #define SCALER_TPZ0_SCALE_MASK VC4_MASK(28, 8) --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0445-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch b/root/target/linux/bcm27xx/patches-5.15/0445-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch deleted file mode 100644 index 93f0ddda..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0445-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 1480cb4fbbf4276df89c6a14d4d0fbfacbf982b2 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Tue, 19 May 2020 16:20:30 +0100 -Subject: [PATCH 445/634] drm/vc4: Add FKMS as an acceptable node for dma - ranges. - -Under FKMS, the firmware (via FKMS) also requires the VideoCore cache -aliases for image planes, as defined by the dma-ranges under /soc. - -Add rpi-firmware-kms to the list of acceptable nodes to look for -to copy dma config from. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_drv.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 2a2e99873e40..63d0d17537c1 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -216,6 +216,7 @@ static void vc4_match_add_drivers(struct device *dev, - - const struct of_device_id vc4_dma_range_matches[] = { - { .compatible = "brcm,bcm2835-hvs" }, -+ { .compatible = "raspberrypi,rpi-firmware-kms" }, - { .compatible = "brcm,bcm2835-v3d" }, - { .compatible = "brcm,cygnus-v3d" }, - { .compatible = "brcm,vc4-v3d" }, --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0446-drm-vc4-A-present-but-empty-dmas-disables-audio.patch b/root/target/linux/bcm27xx/patches-5.15/0446-drm-vc4-A-present-but-empty-dmas-disables-audio.patch deleted file mode 100644 index a83239b4..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0446-drm-vc4-A-present-but-empty-dmas-disables-audio.patch +++ /dev/null @@ -1,38 +0,0 @@ -From a023c47b56995ef66decfe1012efb51bf1fad38c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 31 Jul 2019 17:36:34 +0100 -Subject: [PATCH 446/634] drm/vc4: A present but empty dmas disables audio - -Overlays are unable to remove properties in the base DTB, but they -can overwrite them. Allow a present but empty 'dmas' property -to also disable the HDMI audio interface. - -See: https://github.com/raspberrypi/linux/issues/2489 - -Signed-off-by: Phil Elwell ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 053fbaf765ca..f5055657bf9b 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -1690,10 +1690,12 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) - const __be32 *addr; - int index; - int ret; -+ int len; - -- if (!of_find_property(dev->of_node, "dmas", NULL)) { -+ if (!of_find_property(dev->of_node, "dmas", &len) || -+ len == 0) { - dev_warn(dev, -- "'dmas' DT property is missing, no HDMI audio\n"); -+ "'dmas' DT property is missing or empty, no HDMI audio\n"); - return 0; - } - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0447-drm-vc4-Add-debugfs-node-that-dumps-the-current-disp.patch b/root/target/linux/bcm27xx/patches-5.15/0447-drm-vc4-Add-debugfs-node-that-dumps-the-current-disp.patch deleted file mode 100644 index ecb7da31..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0447-drm-vc4-Add-debugfs-node-that-dumps-the-current-disp.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 4db4f5f3401c7197e997d210d0d1f3fc3495cd1f Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Tue, 6 Oct 2020 18:44:42 +0100 -Subject: [PATCH 447/634] drm/vc4: Add debugfs node that dumps the current - display lists - -This allows easy analysis of display lists when debugging. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_hvs.c | 41 +++++++++++++++++++++++++++++++++++ - 1 file changed, 41 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index 604933e20e6a..ab79d0a82a19 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -95,6 +95,45 @@ static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data) - return 0; - } - -+static int vc4_hvs_debugfs_dlist(struct seq_file *m, void *data) -+{ -+ struct drm_info_node *node = m->private; -+ struct drm_device *dev = node->minor->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ struct drm_printer p = drm_seq_file_printer(m); -+ unsigned int next_entry_start = 0; -+ unsigned int i, j; -+ u32 dlist_word, dispstat; -+ -+ for (i = 0; i < SCALER_CHANNELS_COUNT; i++) { -+ dispstat = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(i)), -+ SCALER_DISPSTATX_MODE); -+ if (dispstat == SCALER_DISPSTATX_MODE_DISABLED || -+ dispstat == SCALER_DISPSTATX_MODE_EOF) { -+ drm_printf(&p, "HVS chan %u disabled\n", i); -+ continue; -+ } -+ -+ drm_printf(&p, "HVS chan %u:\n", i); -+ -+ for (j = HVS_READ(SCALER_DISPLISTX(i)); j < 256; j++) { -+ dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j); -+ drm_printf(&p, "dlist: %02d: 0x%08x\n", j, -+ dlist_word); -+ if (!next_entry_start || -+ next_entry_start == j) { -+ if (dlist_word & SCALER_CTL0_END) -+ break; -+ next_entry_start = j + -+ VC4_GET_FIELD(dlist_word, -+ SCALER_CTL0_SIZE); -+ } -+ } -+ } -+ -+ return 0; -+} -+ - /* The filter kernel is composed of dwords each containing 3 9-bit - * signed integers packed next to each other. - */ -@@ -689,6 +728,8 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) - vc4_debugfs_add_regset32(drm, "hvs_regs", &hvs->regset); - vc4_debugfs_add_file(drm, "hvs_underrun", vc4_hvs_debugfs_underrun, - NULL); -+ vc4_debugfs_add_file(drm, "hvs_dlists", vc4_hvs_debugfs_dlist, -+ NULL); - - return 0; - } --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0448-drm-vc4-Add-all-the-HDMI-registers-into-the-debugfs-.patch b/root/target/linux/bcm27xx/patches-5.15/0448-drm-vc4-Add-all-the-HDMI-registers-into-the-debugfs-.patch deleted file mode 100644 index f49d5db7..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0448-drm-vc4-Add-all-the-HDMI-registers-into-the-debugfs-.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 9b38bb5816dc9b004318743d8c10c6b96fdd71b2 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 21 Oct 2020 18:34:56 +0100 -Subject: [PATCH 448/634] drm/vc4: Add all the HDMI registers into the debugfs - dumps - -The vc5 HDMI registers hadn't been added into the debugfs -register sets, therefore weren't dumped on request. -Add them in. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 39 ++++++++++++++++++++++++++++++++++ - drivers/gpu/drm/vc4/vc4_hdmi.h | 8 +++++++ - 2 files changed, 47 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index f5055657bf9b..6826103aef37 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -112,6 +112,12 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) - - drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); - drm_print_regset32(&p, &vc4_hdmi->hd_regset); -+ drm_print_regset32(&p, &vc4_hdmi->cec_regset); -+ drm_print_regset32(&p, &vc4_hdmi->csc_regset); -+ drm_print_regset32(&p, &vc4_hdmi->dvp_regset); -+ drm_print_regset32(&p, &vc4_hdmi->phy_regset); -+ drm_print_regset32(&p, &vc4_hdmi->ram_regset); -+ drm_print_regset32(&p, &vc4_hdmi->rm_regset); - - return 0; - } -@@ -2352,6 +2358,7 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) - struct platform_device *pdev = vc4_hdmi->pdev; - struct device *dev = &pdev->dev; - struct resource *res; -+ int ret; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi"); - if (!res) -@@ -2448,6 +2455,38 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) - return PTR_ERR(vc4_hdmi->reset); - } - -+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); -+ if (ret) -+ return ret; -+ -+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); -+ if (ret) -+ return ret; -+ -+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->cec_regset, VC5_CEC); -+ if (ret) -+ return ret; -+ -+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->csc_regset, VC5_CSC); -+ if (ret) -+ return ret; -+ -+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->dvp_regset, VC5_DVP); -+ if (ret) -+ return ret; -+ -+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->phy_regset, VC5_PHY); -+ if (ret) -+ return ret; -+ -+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->ram_regset, VC5_RAM); -+ if (ret) -+ return ret; -+ -+ ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->rm_regset, VC5_RM); -+ if (ret) -+ return ret; -+ - return 0; - } - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h -index 36c0b082a43b..db53500a8435 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h -@@ -215,6 +215,14 @@ struct vc4_hdmi { - * the scrambler on? Protected by @mutex. - */ - bool scdc_enabled; -+ -+ /* VC5 debugfs regset */ -+ struct debugfs_regset32 cec_regset; -+ struct debugfs_regset32 csc_regset; -+ struct debugfs_regset32 dvp_regset; -+ struct debugfs_regset32 phy_regset; -+ struct debugfs_regset32 ram_regset; -+ struct debugfs_regset32 rm_regset; - }; - - static inline struct vc4_hdmi * --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0449-drm-vc4-Add-the-2711-HVS-as-a-suitable-DMA-node.patch b/root/target/linux/bcm27xx/patches-5.15/0449-drm-vc4-Add-the-2711-HVS-as-a-suitable-DMA-node.patch deleted file mode 100644 index 2bdd0287..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0449-drm-vc4-Add-the-2711-HVS-as-a-suitable-DMA-node.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 5d869c5244e794a6a606bea50fae5f4859a63b6b Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 26 Oct 2020 12:38:27 +0000 -Subject: [PATCH 449/634] drm/vc4: Add the 2711 HVS as a suitable DMA node - -With vc4-drv node not being under /soc on Pi4, we need to -adopt the correct DMA parameters from a suitable sub-component. -Add "brcm,bcm2711-hvs" to that list of components. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_drv.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 63d0d17537c1..baa419bc5199 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -216,6 +216,7 @@ static void vc4_match_add_drivers(struct device *dev, - - const struct of_device_id vc4_dma_range_matches[] = { - { .compatible = "brcm,bcm2835-hvs" }, -+ { .compatible = "brcm,bcm2711-hvs" }, - { .compatible = "raspberrypi,rpi-firmware-kms" }, - { .compatible = "brcm,bcm2835-v3d" }, - { .compatible = "brcm,cygnus-v3d" }, --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0451-vc4-Clear-unused-infoframe-packet-RAM-registers.patch b/root/target/linux/bcm27xx/patches-5.15/0451-vc4-Clear-unused-infoframe-packet-RAM-registers.patch deleted file mode 100644 index 5f25cb28..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0451-vc4-Clear-unused-infoframe-packet-RAM-registers.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0ac27b440a32561fff95203bbea64457c7ad4caa Mon Sep 17 00:00:00 2001 -From: Dom Cobley -Date: Tue, 10 Nov 2020 20:04:08 +0000 -Subject: [PATCH 451/634] vc4: Clear unused infoframe packet RAM registers - -Using a hdmi analyser the bytes in packet ram -registers beyond the length were visible in the -infoframes and it flagged the checksum as invalid. - -Zeroing unused words of packet RAM avoids this - -Signed-off-by: Dom Cobley ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 876833d25558..0d8735f6fed5 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -436,9 +436,11 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, - const struct vc4_hdmi_register *ram_packet_start = - &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; - u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id; -+ u32 packet_reg_next = ram_packet_start->offset + -+ VC4_HDMI_PACKET_STRIDE * (packet_id + 1); - void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi, - ram_packet_start->reg); -- uint8_t buffer[VC4_HDMI_PACKET_STRIDE]; -+ uint8_t buffer[VC4_HDMI_PACKET_STRIDE] = {}; - unsigned long flags; - ssize_t len, i; - int ret; -@@ -474,6 +476,13 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, - packet_reg += 4; - } - -+ /* -+ * clear remainder of packet ram as it's included in the -+ * infoframe and triggers a checksum error on hdmi analyser -+ */ -+ for (; packet_reg < packet_reg_next; packet_reg += 4) -+ writel(0, base + packet_reg); -+ - HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, - HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id)); - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0452-drm-vc4-Change-the-default-DPI-format-to-being-18bpp.patch b/root/target/linux/bcm27xx/patches-5.15/0452-drm-vc4-Change-the-default-DPI-format-to-being-18bpp.patch deleted file mode 100644 index 8c064b5a..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0452-drm-vc4-Change-the-default-DPI-format-to-being-18bpp.patch +++ /dev/null @@ -1,39 +0,0 @@ -From d6fb1d005219176d51f4705db8cfc1696f18e7d0 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Fri, 12 Feb 2021 17:31:37 +0000 -Subject: [PATCH 452/634] drm/vc4: Change the default DPI format to being - 18bpp, not 24. - -DPI hasn't really been used up until now, so the default has -been meaningless. -In theory we should be able to pass the desired format for the -adjacent bridge chip through, but framework seems to be missing -for that. - -As the main device to use DPI is the VGA666 or Adafruit Kippah, -both of which use RGB666, change the default to being RGB666 instead -of RGB888. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_dpi.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c -index afb446f49e9c..dde2c6014748 100644 ---- a/drivers/gpu/drm/vc4/vc4_dpi.c -+++ b/drivers/gpu/drm/vc4/vc4_dpi.c -@@ -188,8 +188,8 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) - break; - } - } else { -- /* Default to 24bit if no connector found. */ -- dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, DPI_FORMAT); -+ /* Default to 18bit if no connector found. */ -+ dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1, DPI_FORMAT); - } - - if (mode->flags & DRM_MODE_FLAG_NHSYNC) --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0453-vc4-drm-Avoid-full-hdmi-audio-fifo-writes.patch b/root/target/linux/bcm27xx/patches-5.15/0453-vc4-drm-Avoid-full-hdmi-audio-fifo-writes.patch deleted file mode 100644 index 80451686..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0453-vc4-drm-Avoid-full-hdmi-audio-fifo-writes.patch +++ /dev/null @@ -1,37 +0,0 @@ -From e9c41d0d371a0a53bcaff0c36ba53c74146b12ef Mon Sep 17 00:00:00 2001 -From: Dom Cobley -Date: Sun, 24 Jan 2021 15:44:10 +0000 -Subject: [PATCH 453/634] vc4/drm: Avoid full hdmi audio fifo writes - -We are getting occasional VC4_HD_MAI_CTL_ERRORF in -HDMI_MAI_CTL which seem to correspond with audio dropouts. - -Reduce the threshold where we deassert DREQ to avoid the fifo overfilling - -Signed-off-by: Dom Cobley ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 0d8735f6fed5..57683afda185 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -1610,10 +1610,10 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data, - - /* Set the MAI threshold */ - HDMI_WRITE(HDMI_MAI_THR, -- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) | -- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) | -- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) | -- VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW)); -+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICHIGH) | -+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_PANICLOW) | -+ VC4_SET_FIELD(0x06, VC4_HD_MAI_THR_DREQHIGH) | -+ VC4_SET_FIELD(0x08, VC4_HD_MAI_THR_DREQLOW)); - - HDMI_WRITE(HDMI_MAI_CONFIG, - VC4_HDMI_MAI_CONFIG_BIT_REVERSE | --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0454-vc4-drm-Fix-source-offsets-with-DRM_FORMAT_P030.patch b/root/target/linux/bcm27xx/patches-5.15/0454-vc4-drm-Fix-source-offsets-with-DRM_FORMAT_P030.patch deleted file mode 100644 index 187fedfb..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0454-vc4-drm-Fix-source-offsets-with-DRM_FORMAT_P030.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 1c048ce68d012aa65e942ac20b95e63dfc54eb84 Mon Sep 17 00:00:00 2001 -From: Dom Cobley -Date: Mon, 22 Mar 2021 19:43:48 +0000 -Subject: [PATCH 454/634] vc4/drm: Fix source offsets with DRM_FORMAT_P030 - -Spec says: bits [31:4] of the given address should point to -the 128-bit word containing the desired starting pixel, -and bits[3:0] should be between 0 and 11, indicating which -of the 12-pixels in that 128-bit word is the first pixel to be used - -Signed-off-by: Dom Cobley ---- - drivers/gpu/drm/vc4/vc4_plane.c | 25 +++++++++++++++++-------- - 1 file changed, 17 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index 9dd447ecd404..1a1a54fc3005 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -819,9 +819,21 @@ static int vc4_plane_mode_set(struct drm_plane *plane, - u32 tile_w, tile, x_off, pix_per_tile; - - if (fb->format->format == DRM_FORMAT_P030) { -+ /* -+ * Spec says: bits [31:4] of the given address should point to -+ * the 128-bit word containing the desired starting pixel, -+ * and bits[3:0] should be between 0 and 11, indicating which -+ * of the 12-pixels in that 128-bit word is the first pixel to be used -+ */ -+ u32 remaining_pixels = vc4_state->src_x % 96; -+ u32 aligned = remaining_pixels / 12; -+ u32 last_bits = remaining_pixels % 12; -+ -+ x_off = aligned * 16 + last_bits; - hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT; - tiling = SCALER_CTL0_TILING_128B; -- tile_w = 96; -+ tile_w = 128; -+ pix_per_tile = 96; - } else { - hvs_format = HVS_PIXEL_FORMAT_H264; - -@@ -841,17 +853,16 @@ static int vc4_plane_mode_set(struct drm_plane *plane, - default: - break; - } -+ pix_per_tile = tile_w / fb->format->cpp[0]; -+ x_off = (vc4_state->src_x % pix_per_tile) / -+ (i ? h_subsample : 1) * fb->format->cpp[i]; - } - if (param > SCALER_TILE_HEIGHT_MASK) { - DRM_DEBUG_KMS("SAND height too large (%d)\n", - param); - return -EINVAL; - } -- -- pix_per_tile = tile_w / fb->format->cpp[0]; - tile = vc4_state->src_x / pix_per_tile; -- x_off = vc4_state->src_x % pix_per_tile; -- - /* Adjust the base pointer to the first pixel to be scanned - * out. - * -@@ -867,9 +878,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, - vc4_state->offsets[i] += src_y / - (i ? v_subsample : 1) * - tile_w; -- vc4_state->offsets[i] += x_off / -- (i ? h_subsample : 1) * -- fb->format->cpp[i]; -+ vc4_state->offsets[i] += x_off & ~(i ? 1 : 0); - } - - pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0455-vc4-drm-vc4_plane-Remove-subpixel-positioning-check.patch b/root/target/linux/bcm27xx/patches-5.15/0455-vc4-drm-vc4_plane-Remove-subpixel-positioning-check.patch deleted file mode 100644 index 3904ebf3..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0455-vc4-drm-vc4_plane-Remove-subpixel-positioning-check.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 568920ba54a355561533ef94915d340eefe34a4b Mon Sep 17 00:00:00 2001 -From: Dom Cobley -Date: Mon, 15 Mar 2021 13:28:06 +0000 -Subject: [PATCH 455/634] vc4/drm: vc4_plane: Remove subpixel positioning check - -There is little harm in ignoring fractional coordinates -(they just get truncated). - -Without this: -modetest -M vc4 -F tiles,gradient -s 32:1920x1080-60 -P89@74:1920x1080*.1.1@XR24 - -is rejected. We have the same issue in Kodi when trying to -use zoom options on video. - -Note: even if all coordinates are fully integer. e.g. -src:[0,0,1920,1080] dest:[-10,-10,1940,1100] - -it will still get rejected as drm_atomic_helper_check_plane_state -uses drm_rect_clip_scaled which transforms this to fractional src coords - -Signed-off-by: Dom Cobley ---- - drivers/gpu/drm/vc4/vc4_plane.c | 21 ++++++++------------- - 1 file changed, 8 insertions(+), 13 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index 1a1a54fc3005..4ffd0730a130 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -339,7 +339,6 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) - struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); - struct drm_framebuffer *fb = state->fb; - struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); -- u32 subpixel_src_mask = (1 << 16) - 1; - int num_planes = fb->format->num_planes; - struct drm_crtc_state *crtc_state; - u32 h_subsample = fb->format->hsub; -@@ -361,18 +360,14 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) - for (i = 0; i < num_planes; i++) - vc4_state->offsets[i] = bo->paddr + fb->offsets[i]; - -- /* We don't support subpixel source positioning for scaling. */ -- if ((state->src.x1 & subpixel_src_mask) || -- (state->src.x2 & subpixel_src_mask) || -- (state->src.y1 & subpixel_src_mask) || -- (state->src.y2 & subpixel_src_mask)) { -- return -EINVAL; -- } -- -- vc4_state->src_x = state->src.x1 >> 16; -- vc4_state->src_y = state->src.y1 >> 16; -- vc4_state->src_w[0] = (state->src.x2 - state->src.x1) >> 16; -- vc4_state->src_h[0] = (state->src.y2 - state->src.y1) >> 16; -+ /* We don't support subpixel source positioning for scaling, -+ * but fractional coordinates can be generated by clipping -+ * so just round for now -+ */ -+ vc4_state->src_x = DIV_ROUND_CLOSEST(state->src.x1, 1<<16); -+ vc4_state->src_y = DIV_ROUND_CLOSEST(state->src.y1, 1<<16); -+ vc4_state->src_w[0] = DIV_ROUND_CLOSEST(state->src.x2, 1<<16) - vc4_state->src_x; -+ vc4_state->src_h[0] = DIV_ROUND_CLOSEST(state->src.y2, 1<<16) - vc4_state->src_y; - - vc4_state->crtc_x = state->dst.x1; - vc4_state->crtc_y = state->dst.y1; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0456-vc4-kms-vc4_plane-Support-2020-colourspace-for-yuv-p.patch b/root/target/linux/bcm27xx/patches-5.15/0456-vc4-kms-vc4_plane-Support-2020-colourspace-for-yuv-p.patch deleted file mode 100644 index 4327cdc4..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0456-vc4-kms-vc4_plane-Support-2020-colourspace-for-yuv-p.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 503f88ed418e0c73a7d880f73229d39232b2d7b7 Mon Sep 17 00:00:00 2001 -From: Dom Cobley -Date: Mon, 12 Apr 2021 17:27:43 +0100 -Subject: [PATCH 456/634] vc4/kms: vc4_plane: Support 2020 colourspace for yuv - planes - -https://gist.github.com/popcornmix/6b3e23103c60170b02b148e0ba5d6ed7 - -is the script used to generate the 601, 709 and 2020 colourspaces. -I've regenerated the existing ones using script so it is reproducible -but there are lsb differences compared to values here (copied from spec) -whose origin is now lost. - -Signed-off-by: Dom Cobley ---- - drivers/gpu/drm/vc4/vc4_plane.c | 19 ++++++++++--------- - drivers/gpu/drm/vc4/vc4_regs.h | 18 ++++++++++++------ - 2 files changed, 22 insertions(+), 15 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index 4ffd0730a130..c100eeddd5ad 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -639,10 +639,10 @@ static const u32 colorspace_coeffs[2][DRM_COLOR_ENCODING_MAX][3] = { - SCALER_CSC1_ITR_R_709_3, - SCALER_CSC2_ITR_R_709_3, - }, { -- /* BT2020. Not supported yet - copy 601 */ -- SCALER_CSC0_ITR_R_601_5, -- SCALER_CSC1_ITR_R_601_5, -- SCALER_CSC2_ITR_R_601_5, -+ /* BT2020 */ -+ SCALER_CSC0_ITR_R_2020, -+ SCALER_CSC1_ITR_R_2020, -+ SCALER_CSC2_ITR_R_2020, - } - }, { - /* Full range */ -@@ -657,10 +657,10 @@ static const u32 colorspace_coeffs[2][DRM_COLOR_ENCODING_MAX][3] = { - SCALER_CSC1_ITR_R_709_3_FR, - SCALER_CSC2_ITR_R_709_3_FR, - }, { -- /* BT2020. Not supported yet - copy JFIF */ -- SCALER_CSC0_JPEG_JFIF, -- SCALER_CSC1_JPEG_JFIF, -- SCALER_CSC2_JPEG_JFIF, -+ /* BT2020 */ -+ SCALER_CSC0_ITR_R_2020_FR, -+ SCALER_CSC1_ITR_R_2020_FR, -+ SCALER_CSC2_ITR_R_2020_FR, - } - } - }; -@@ -1482,7 +1482,8 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, - - drm_plane_create_color_properties(plane, - BIT(DRM_COLOR_YCBCR_BT601) | -- BIT(DRM_COLOR_YCBCR_BT709), -+ BIT(DRM_COLOR_YCBCR_BT709) | -+ BIT(DRM_COLOR_YCBCR_BT2020), - BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | - BIT(DRM_COLOR_YCBCR_FULL_RANGE), - DRM_COLOR_YCBCR_BT709, -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 78fd28599aeb..7538b84a6dca 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -975,8 +975,10 @@ enum hvs_pixel_format { - #define SCALER_CSC0_COEF_CR_OFS_SHIFT 0 - #define SCALER_CSC0_ITR_R_601_5 0x00f00000 - #define SCALER_CSC0_ITR_R_709_3 0x00f00000 -+#define SCALER_CSC0_ITR_R_2020 0x00f00000 - #define SCALER_CSC0_JPEG_JFIF 0x00000000 - #define SCALER_CSC0_ITR_R_709_3_FR 0x00000000 -+#define SCALER_CSC0_ITR_R_2020_FR 0x00000000 - - /* S2.8 contribution of Cb to Green */ - #define SCALER_CSC1_COEF_CB_GRN_MASK VC4_MASK(31, 22) -@@ -991,9 +993,11 @@ enum hvs_pixel_format { - #define SCALER_CSC1_COEF_CR_BLU_MASK VC4_MASK(1, 0) - #define SCALER_CSC1_COEF_CR_BLU_SHIFT 0 - #define SCALER_CSC1_ITR_R_601_5 0xe73304a8 --#define SCALER_CSC1_ITR_R_709_3 0xf2b784a8 --#define SCALER_CSC1_JPEG_JFIF 0xea34a400 --#define SCALER_CSC1_ITR_R_709_3_FR 0xe23d0400 -+#define SCALER_CSC1_ITR_R_709_3 0xf27784a8 -+#define SCALER_CSC1_ITR_R_2020 0xf43594a8 -+#define SCALER_CSC1_JPEG_JFIF 0xea349400 -+#define SCALER_CSC1_ITR_R_709_3_FR 0xf4388400 -+#define SCALER_CSC1_ITR_R_2020_FR 0xf5b6d400 - - /* S2.8 contribution of Cb to Red */ - #define SCALER_CSC2_COEF_CB_RED_MASK VC4_MASK(29, 20) -@@ -1004,10 +1008,12 @@ enum hvs_pixel_format { - /* S2.8 contribution of Cb to Blue */ - #define SCALER_CSC2_COEF_CB_BLU_MASK VC4_MASK(19, 10) - #define SCALER_CSC2_COEF_CB_BLU_SHIFT 10 --#define SCALER_CSC2_ITR_R_601_5 0x00066204 --#define SCALER_CSC2_ITR_R_709_3 0x00072a1c --#define SCALER_CSC2_JPEG_JFIF 0x000599c5 -+#define SCALER_CSC2_ITR_R_601_5 0x00066604 -+#define SCALER_CSC2_ITR_R_709_3 0x00072e1d -+#define SCALER_CSC2_ITR_R_2020 0x0006b624 -+#define SCALER_CSC2_JPEG_JFIF 0x00059dc6 - #define SCALER_CSC2_ITR_R_709_3_FR 0x00064ddb -+#define SCALER_CSC2_ITR_R_2020_FR 0x0005e5e2 - - #define SCALER_TPZ0_VERT_RECALC BIT(31) - #define SCALER_TPZ0_SCALE_MASK VC4_MASK(28, 8) --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0457-drm-vc4-hdmi-Convert-to-the-new-clock-request-API.patch b/root/target/linux/bcm27xx/patches-5.15/0457-drm-vc4-hdmi-Convert-to-the-new-clock-request-API.patch deleted file mode 100644 index b8a05557..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0457-drm-vc4-hdmi-Convert-to-the-new-clock-request-API.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 4a8efdb006a53021458e67535ac7023d254338f7 Mon Sep 17 00:00:00 2001 -From: Dom Cobley -Date: Tue, 13 Apr 2021 14:10:03 +0100 -Subject: [PATCH 457/634] drm/vc4: hdmi: Convert to the new clock request API - -The new clock request API allows us to increase the rate of the -core clock as required during mode set while decreasing it when -we're done, resulting in a better power-efficiency. - -Signed-off-by: Dom Cobley ---- - drivers/gpu/drm/vc4/vc4_kms.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 79d4d9dd1394..f9dce01c052f 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -345,6 +345,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - struct vc4_hvs_state *new_hvs_state; - struct drm_crtc *crtc; - struct vc4_hvs_state *old_hvs_state; -+ struct clk_request *core_req; - int i; - - old_hvs_state = vc4_hvs_get_old_global_state(state); -@@ -370,7 +371,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - 500000000, - new_hvs_state->core_clock_rate); - -- clk_set_min_rate(hvs->core_clk, core_rate); -+ core_req = clk_request_start(hvs->core_clk, core_rate); - } - - for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { -@@ -415,7 +416,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - drm_dbg(dev, "Running the core clock at %lu Hz\n", - new_hvs_state->core_clock_rate); - -- clk_set_min_rate(hvs->core_clk, new_hvs_state->core_clock_rate); -+ clk_request_done(core_req); - } - } - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0458-drm-vc4-Correct-pixel-order-for-DSI0.patch b/root/target/linux/bcm27xx/patches-5.15/0458-drm-vc4-Correct-pixel-order-for-DSI0.patch deleted file mode 100644 index ea310501..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0458-drm-vc4-Correct-pixel-order-for-DSI0.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 5ccb69c8e022a72ce37f7ba78fe5d676571c55d8 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Thu, 11 Feb 2021 18:37:04 +0000 -Subject: [PATCH 458/634] drm/vc4: Correct pixel order for DSI0 - -For slightly unknown reasons, dsi0 takes a different pixel format -to dsi1, and that has to be set in the pixel valve. - -Amend the setup accordingly. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 287dbc89ad64..5653476e8dcb 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -317,7 +317,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode - u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; - bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 || - vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); -- u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; -+ bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1; -+ u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; - u8 ppc = pv_data->pixels_per_clock; - bool debug_dump_regs = false; - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0459-drm-vc4-Register-dsi0-as-the-correct-vc4-encoder-typ.patch b/root/target/linux/bcm27xx/patches-5.15/0459-drm-vc4-Register-dsi0-as-the-correct-vc4-encoder-typ.patch deleted file mode 100644 index 096540be..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0459-drm-vc4-Register-dsi0-as-the-correct-vc4-encoder-typ.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0e0e02fcc1b341136276a4ffc45bfdb6c67c6898 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 8 Feb 2021 11:22:01 +0000 -Subject: [PATCH 459/634] drm/vc4: Register dsi0 as the correct vc4 encoder - type - -vc4_dsi was registering both dsi0 and dsi1 as VC4_ENCODER_TYPE_DSI1 -which seemed to work OK for a single DSI display, but fails -if there are two DSI displays connected. - -Update to register the correct type. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_dsi.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c -index a185027911ce..dfc68b2efd96 100644 ---- a/drivers/gpu/drm/vc4/vc4_dsi.c -+++ b/drivers/gpu/drm/vc4/vc4_dsi.c -@@ -1514,7 +1514,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - return -ENOMEM; - - INIT_LIST_HEAD(&dsi->bridge_chain); -- vc4_dsi_encoder->base.type = VC4_ENCODER_TYPE_DSI1; -+ vc4_dsi_encoder->base.type = dsi->variant->port ? -+ VC4_ENCODER_TYPE_DSI1 : VC4_ENCODER_TYPE_DSI0; - vc4_dsi_encoder->dsi = dsi; - dsi->encoder = &vc4_dsi_encoder->base.base; - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0460-drm-vc4-Fix-dsi0-interrupt-support.patch b/root/target/linux/bcm27xx/patches-5.15/0460-drm-vc4-Fix-dsi0-interrupt-support.patch deleted file mode 100644 index 67e2340c..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0460-drm-vc4-Fix-dsi0-interrupt-support.patch +++ /dev/null @@ -1,193 +0,0 @@ -From d9fc3b49dbca8f27ac5ca34a956a676109643d6a Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 10 Feb 2021 18:46:22 +0000 -Subject: [PATCH 460/634] drm/vc4: Fix dsi0 interrupt support. - -DSI0 seemingly had very little or no testing as a load of -the register mappings were incorrect/missing, so host -transfers always timed out due to enabling/checking incorrect -bits in the interrupt enable and status registers. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_dsi.c | 111 ++++++++++++++++++++++++++-------- - 1 file changed, 85 insertions(+), 26 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c -index dfc68b2efd96..b6bedc8da63f 100644 ---- a/drivers/gpu/drm/vc4/vc4_dsi.c -+++ b/drivers/gpu/drm/vc4/vc4_dsi.c -@@ -181,8 +181,50 @@ - - #define DSI0_TXPKT_PIX_FIFO 0x20 /* AKA PIX_FIFO */ - --#define DSI0_INT_STAT 0x24 --#define DSI0_INT_EN 0x28 -+#define DSI0_INT_STAT 0x24 -+#define DSI0_INT_EN 0x28 -+# define DSI0_INT_FIFO_ERR BIT(25) -+# define DSI0_INT_CMDC_DONE_MASK VC4_MASK(24, 23) -+# define DSI0_INT_CMDC_DONE_SHIFT 23 -+# define DSI0_INT_CMDC_DONE_NO_REPEAT 1 -+# define DSI0_INT_CMDC_DONE_REPEAT 3 -+# define DSI0_INT_PHY_DIR_RTF BIT(22) -+# define DSI0_INT_PHY_D1_ULPS BIT(21) -+# define DSI0_INT_PHY_D1_STOP BIT(20) -+# define DSI0_INT_PHY_RXLPDT BIT(19) -+# define DSI0_INT_PHY_RXTRIG BIT(18) -+# define DSI0_INT_PHY_D0_ULPS BIT(17) -+# define DSI0_INT_PHY_D0_LPDT BIT(16) -+# define DSI0_INT_PHY_D0_FTR BIT(15) -+# define DSI0_INT_PHY_D0_STOP BIT(14) -+/* Signaled when the clock lane enters the given state. */ -+# define DSI0_INT_PHY_CLK_ULPS BIT(13) -+# define DSI0_INT_PHY_CLK_HS BIT(12) -+# define DSI0_INT_PHY_CLK_FTR BIT(11) -+/* Signaled on timeouts */ -+# define DSI0_INT_PR_TO BIT(10) -+# define DSI0_INT_TA_TO BIT(9) -+# define DSI0_INT_LPRX_TO BIT(8) -+# define DSI0_INT_HSTX_TO BIT(7) -+/* Contention on a line when trying to drive the line low */ -+# define DSI0_INT_ERR_CONT_LP1 BIT(6) -+# define DSI0_INT_ERR_CONT_LP0 BIT(5) -+/* Control error: incorrect line state sequence on data lane 0. */ -+# define DSI0_INT_ERR_CONTROL BIT(4) -+# define DSI0_INT_ERR_SYNC_ESC BIT(3) -+# define DSI0_INT_RX2_PKT BIT(2) -+# define DSI0_INT_RX1_PKT BIT(1) -+# define DSI0_INT_CMD_PKT BIT(0) -+ -+#define DSI0_INTERRUPTS_ALWAYS_ENABLED (DSI0_INT_ERR_SYNC_ESC | \ -+ DSI0_INT_ERR_CONTROL | \ -+ DSI0_INT_ERR_CONT_LP0 | \ -+ DSI0_INT_ERR_CONT_LP1 | \ -+ DSI0_INT_HSTX_TO | \ -+ DSI0_INT_LPRX_TO | \ -+ DSI0_INT_TA_TO | \ -+ DSI0_INT_PR_TO) -+ - # define DSI1_INT_PHY_D3_ULPS BIT(30) - # define DSI1_INT_PHY_D3_STOP BIT(29) - # define DSI1_INT_PHY_D2_ULPS BIT(28) -@@ -894,6 +936,9 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) - - DSI_PORT_WRITE(PHY_AFEC0, afec0); - -+ /* AFEC reset hold time */ -+ mdelay(1); -+ - DSI_PORT_WRITE(PHY_AFEC1, - VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE1) | - VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE0) | -@@ -1060,12 +1105,9 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) - DSI_PORT_WRITE(CTRL, DSI_PORT_READ(CTRL) | DSI1_CTRL_EN); - - /* Bring AFE out of reset. */ -- if (dsi->variant->port == 0) { -- } else { -- DSI_PORT_WRITE(PHY_AFEC0, -- DSI_PORT_READ(PHY_AFEC0) & -- ~DSI1_PHY_AFEC0_RESET); -- } -+ DSI_PORT_WRITE(PHY_AFEC0, -+ DSI_PORT_READ(PHY_AFEC0) & -+ ~DSI_PORT_BIT(PHY_AFEC0_RESET)); - - vc4_dsi_ulps(dsi, false); - -@@ -1184,13 +1226,28 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, - /* Enable the appropriate interrupt for the transfer completion. */ - dsi->xfer_result = 0; - reinit_completion(&dsi->xfer_completion); -- DSI_PORT_WRITE(INT_STAT, DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF); -- if (msg->rx_len) { -- DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -- DSI1_INT_PHY_DIR_RTF)); -+ if (dsi->variant->port == 0) { -+ DSI_PORT_WRITE(INT_STAT, -+ DSI0_INT_CMDC_DONE_MASK | DSI1_INT_PHY_DIR_RTF); -+ if (msg->rx_len) { -+ DSI_PORT_WRITE(INT_EN, (DSI0_INTERRUPTS_ALWAYS_ENABLED | -+ DSI0_INT_PHY_DIR_RTF)); -+ } else { -+ DSI_PORT_WRITE(INT_EN, -+ (DSI0_INTERRUPTS_ALWAYS_ENABLED | -+ VC4_SET_FIELD(DSI0_INT_CMDC_DONE_NO_REPEAT, -+ DSI0_INT_CMDC_DONE))); -+ } - } else { -- DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -- DSI1_INT_TXPKT1_DONE)); -+ DSI_PORT_WRITE(INT_STAT, -+ DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF); -+ if (msg->rx_len) { -+ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -+ DSI1_INT_PHY_DIR_RTF)); -+ } else { -+ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -+ DSI1_INT_TXPKT1_DONE)); -+ } - } - - /* Send the packet. */ -@@ -1207,7 +1264,7 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, - ret = dsi->xfer_result; - } - -- DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); -+ DSI_PORT_WRITE(INT_EN, DSI_PORT_BIT(INTERRUPTS_ALWAYS_ENABLED)); - - if (ret) - goto reset_fifo_and_return; -@@ -1253,7 +1310,7 @@ static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, - DSI_PORT_BIT(CTRL_RESET_FIFOS)); - - DSI_PORT_WRITE(TXPKT1C, 0); -- DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); -+ DSI_PORT_WRITE(INT_EN, DSI_PORT_BIT(INTERRUPTS_ALWAYS_ENABLED)); - return ret; - } - -@@ -1394,26 +1451,28 @@ static irqreturn_t vc4_dsi_irq_handler(int irq, void *data) - DSI_PORT_WRITE(INT_STAT, stat); - - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_ERR_SYNC_ESC, "LPDT sync"); -+ DSI_PORT_BIT(INT_ERR_SYNC_ESC), "LPDT sync"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_ERR_CONTROL, "data lane 0 sequence"); -+ DSI_PORT_BIT(INT_ERR_CONTROL), "data lane 0 sequence"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_ERR_CONT_LP0, "LP0 contention"); -+ DSI_PORT_BIT(INT_ERR_CONT_LP0), "LP0 contention"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_ERR_CONT_LP1, "LP1 contention"); -+ DSI_PORT_BIT(INT_ERR_CONT_LP1), "LP1 contention"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_HSTX_TO, "HSTX timeout"); -+ DSI_PORT_BIT(INT_HSTX_TO), "HSTX timeout"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_LPRX_TO, "LPRX timeout"); -+ DSI_PORT_BIT(INT_LPRX_TO), "LPRX timeout"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_TA_TO, "turnaround timeout"); -+ DSI_PORT_BIT(INT_TA_TO), "turnaround timeout"); - dsi_handle_error(dsi, &ret, stat, -- DSI1_INT_PR_TO, "peripheral reset timeout"); -+ DSI_PORT_BIT(INT_PR_TO), "peripheral reset timeout"); - -- if (stat & (DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF)) { -+ if (stat & ((dsi->variant->port ? DSI1_INT_TXPKT1_DONE : -+ DSI0_INT_CMDC_DONE_MASK) | -+ DSI_PORT_BIT(INT_PHY_DIR_RTF))) { - complete(&dsi->xfer_completion); - ret = IRQ_HANDLED; -- } else if (stat & DSI1_INT_HSTX_TO) { -+ } else if (stat & DSI_PORT_BIT(INT_HSTX_TO)) { - complete(&dsi->xfer_completion); - dsi->xfer_result = -ETIMEDOUT; - ret = IRQ_HANDLED; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0461-drm-vc4-Add-correct-stop-condition-to-vc4_dsi_encode.patch b/root/target/linux/bcm27xx/patches-5.15/0461-drm-vc4-Add-correct-stop-condition-to-vc4_dsi_encode.patch deleted file mode 100644 index b6617c30..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0461-drm-vc4-Add-correct-stop-condition-to-vc4_dsi_encode.patch +++ /dev/null @@ -1,35 +0,0 @@ -From f90ecd85d1453fd60ff0156aec2e3b0fc22ea266 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Thu, 15 Apr 2021 16:18:16 +0100 -Subject: [PATCH 461/634] drm/vc4: Add correct stop condition to - vc4_dsi_encoder_disable iteration - -vc4_dsi_encoder_disable is partially an open coded version of -drm_bridge_chain_disable, but it missed a termination condition -in the loop for ->disable which meant that no post_disable -calls were made. - -Add in the termination clause. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_dsi.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c -index b6bedc8da63f..e433071bf797 100644 ---- a/drivers/gpu/drm/vc4/vc4_dsi.c -+++ b/drivers/gpu/drm/vc4/vc4_dsi.c -@@ -803,6 +803,9 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) - list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) { - if (iter->funcs->disable) - iter->funcs->disable(iter); -+ -+ if (iter == dsi->bridge) -+ break; - } - - vc4_dsi_ulps(dsi, true); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0463-drm-vc4-Allow-DBLCLK-modes-even-if-horz-timing-is-od.patch b/root/target/linux/bcm27xx/patches-5.15/0463-drm-vc4-Allow-DBLCLK-modes-even-if-horz-timing-is-od.patch deleted file mode 100644 index ab4cc2f9..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0463-drm-vc4-Allow-DBLCLK-modes-even-if-horz-timing-is-od.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 53bd65d8dc68d40a89026d5509013069cbc36a31 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 28 Apr 2021 16:14:21 +0100 -Subject: [PATCH 463/634] drm/vc4: Allow DBLCLK modes even if horz timing is - odd. - -The 2711 pixel valve can't produce odd horizontal timings, and -checks were added to vc4_hdmi_encoder_atomic_check and -vc4_hdmi_encoder_mode_valid to filter out/block selection of -such modes. - -Modes with DRM_MODE_FLAG_DBLCLK double all the horizontal timing -values before programming them into the PV. The PV values, -therefore, can not be odd, and so the modes can be supported. - -Amend the filtering appropriately. - -See https://github.com/raspberrypi/linux/issues/4307 - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 57683afda185..2c83252819e9 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -1267,6 +1267,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, - unsigned long long tmds_rate; - - if (vc4_hdmi->variant->unsupported_odd_h_timings && -+ !(mode->flags & DRM_MODE_FLAG_DBLCLK) && - ((mode->hdisplay % 2) || (mode->hsync_start % 2) || - (mode->hsync_end % 2) || (mode->htotal % 2))) - return -EINVAL; -@@ -1314,6 +1315,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - - if (vc4_hdmi->variant->unsupported_odd_h_timings && -+ !(mode->flags & DRM_MODE_FLAG_DBLCLK) && - ((mode->hdisplay % 2) || (mode->hsync_start % 2) || - (mode->hsync_end % 2) || (mode->htotal % 2))) - return MODE_H_ILLEGAL; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0465-drm-vc4-Increase-the-core-clock-based-on-HVS-load.patch b/root/target/linux/bcm27xx/patches-5.15/0465-drm-vc4-Increase-the-core-clock-based-on-HVS-load.patch deleted file mode 100644 index 7f028d8e..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0465-drm-vc4-Increase-the-core-clock-based-on-HVS-load.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 82eae7910c0537100d4b5a6bb697bb3e9996cd2a Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 26 May 2021 16:13:02 +0200 -Subject: [PATCH 465/634] drm/vc4: Increase the core clock based on HVS load - -Depending on a given HVS output (HVS to PixelValves) and input (planes -attached to a channel) load, the HVS needs for the core clock to be -raised above its boot time default. - -Failing to do so will result in a vblank timeout and a stalled display -pipeline. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_drv.h | 1 + - drivers/gpu/drm/vc4/vc4_kms.c | 14 ++++++++++++++ - 2 files changed, 15 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 4329e09d357c..3921959b4a5e 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -321,6 +321,7 @@ struct vc4_hvs { - u32 __iomem *dlist; - - struct clk *core_clk; -+ struct clk_request *core_req; - - /* Memory manager for CRTCs to allocate space in the display - * list. Units are dwords. -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index f9dce01c052f..a750b1e6c733 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -372,6 +372,12 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - new_hvs_state->core_clock_rate); - - core_req = clk_request_start(hvs->core_clk, core_rate); -+ -+ /* -+ * And remove the previous one based on the HVS -+ * requirements if any. -+ */ -+ clk_request_done(hvs->core_req); - } - - for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { -@@ -416,6 +422,14 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - drm_dbg(dev, "Running the core clock at %lu Hz\n", - new_hvs_state->core_clock_rate); - -+ /* -+ * Request a clock rate based on the current HVS -+ * requirements. -+ */ -+ hvs->core_req = clk_request_start(hvs->core_clk, -+ new_hvs_state->core_clock_rate); -+ -+ /* And drop the temporary request */ - clk_request_done(core_req); - } - } --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0466-drm-vc4-hdmi-Simplify-the-connector-state-retrieval.patch b/root/target/linux/bcm27xx/patches-5.15/0466-drm-vc4-hdmi-Simplify-the-connector-state-retrieval.patch deleted file mode 100644 index 3717e5dd..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0466-drm-vc4-hdmi-Simplify-the-connector-state-retrieval.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 74c8e5b794c36fa5dc152a42765499326853484c Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 27 Oct 2021 14:38:50 +0100 -Subject: [PATCH 466/634] drm/vc4: hdmi: Simplify the connector state retrieval - -When we have the entire DRM state, retrieving the connector state only -requires the drm_connector pointer. Fortunately for us, we have -allocated it as a part of the vc4_hdmi structure, so we can retrieve get -a pointer by simply accessing our field in that structure. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 21 +++------------------ - 1 file changed, 3 insertions(+), 18 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 2c83252819e9..efffe21d2e73 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -1002,30 +1002,15 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) - "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); - } - --static struct drm_connector_state * --vc4_hdmi_encoder_get_connector_state(struct drm_encoder *encoder, -- struct drm_atomic_state *state) --{ -- struct drm_connector_state *conn_state; -- struct drm_connector *connector; -- unsigned int i; -- -- for_each_new_connector_in_state(state, connector, conn_state, i) { -- if (conn_state->best_encoder == encoder) -- return conn_state; -- } -- -- return NULL; --} -- - static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, - struct drm_atomic_state *state) - { -+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -+ struct drm_connector *connector = &vc4_hdmi->connector; - struct drm_connector_state *conn_state = -- vc4_hdmi_encoder_get_connector_state(encoder, state); -+ drm_atomic_get_new_connector_state(state, connector); - struct vc4_hdmi_connector_state *vc4_conn_state = - conn_state_to_vc4_hdmi_conn_state(conn_state); -- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - unsigned long pixel_rate = vc4_conn_state->pixel_rate; - unsigned long bvb_rate, hsm_rate; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0467-drm-vc4-Fix-timings-for-interlaced-modes.patch b/root/target/linux/bcm27xx/patches-5.15/0467-drm-vc4-Fix-timings-for-interlaced-modes.patch deleted file mode 100644 index b641e748..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0467-drm-vc4-Fix-timings-for-interlaced-modes.patch +++ /dev/null @@ -1,90 +0,0 @@ -From f64d1bbe8a773f87ae1f4f68948b6935b64c8d75 Mon Sep 17 00:00:00 2001 -From: kFYatek <4499762+kFYatek@users.noreply.github.com> -Date: Wed, 23 Jun 2021 01:11:26 +0200 -Subject: [PATCH 467/634] drm/vc4: Fix timings for interlaced modes - -Increase the number of post-sync blanking lines on odd fields instead of -decreasing it on even fields. This makes the total number of lines -properly match the modelines. - -Additionally fix the value of PV_VCONTROL_ODD_DELAY, which did not take -pixels_per_clock into account, causing some displays to invert the -fields when driven by bcm2711. - -Signed-off-by: Mateusz Kwiatkowski ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 7 ++++--- - drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++------ - 2 files changed, 10 insertions(+), 9 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 5653476e8dcb..e21119f32552 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -344,7 +344,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode - PV_HORZB_HACTIVE)); - - CRTC_WRITE(PV_VERTA, -- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, -+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + -+ interlace, - PV_VERTA_VBP) | - VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, - PV_VERTA_VSYNC)); -@@ -356,7 +357,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode - if (interlace) { - CRTC_WRITE(PV_VERTA_EVEN, - VC4_SET_FIELD(mode->crtc_vtotal - -- mode->crtc_vsync_end - 1, -+ mode->crtc_vsync_end, - PV_VERTA_VBP) | - VC4_SET_FIELD(mode->crtc_vsync_end - - mode->crtc_vsync_start, -@@ -376,7 +377,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode - PV_VCONTROL_CONTINUOUS | - (is_dsi ? PV_VCONTROL_DSI : 0) | - PV_VCONTROL_INTERLACE | -- VC4_SET_FIELD(mode->htotal * pixel_rep / 2, -+ VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc), - PV_VCONTROL_ODD_DELAY)); - CRTC_WRITE(PV_VSYNCD_EVEN, 0); - } else { -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index efffe21d2e73..502d5bea5f61 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -840,12 +840,12 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, - VC4_HDMI_VERTA_VFP) | - VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); - u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | -- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, -+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + -+ interlaced, - VC4_HDMI_VERTB_VBP)); - u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | - VC4_SET_FIELD(mode->crtc_vtotal - -- mode->crtc_vsync_end - -- interlaced, -+ mode->crtc_vsync_end, - VC4_HDMI_VERTB_VBP)); - unsigned long flags; - -@@ -891,12 +891,12 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, - VC5_HDMI_VERTA_VFP) | - VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL)); - u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | -- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, -+ VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + -+ interlaced, - VC4_HDMI_VERTB_VBP)); - u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | - VC4_SET_FIELD(mode->crtc_vtotal - -- mode->crtc_vsync_end - -- interlaced, -+ mode->crtc_vsync_end, - VC4_HDMI_VERTB_VBP)); - unsigned long flags; - unsigned char gcp; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0469-drm-vc4-Fix-margin-calculations-for-the-right-bottom.patch b/root/target/linux/bcm27xx/patches-5.15/0469-drm-vc4-Fix-margin-calculations-for-the-right-bottom.patch deleted file mode 100644 index de70ae99..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0469-drm-vc4-Fix-margin-calculations-for-the-right-bottom.patch +++ /dev/null @@ -1,43 +0,0 @@ -From d7c52ab30d28898ea6df7cd0637c3e7ebc053b57 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 12 Jul 2021 12:27:59 +0100 -Subject: [PATCH 469/634] drm/vc4: Fix margin calculations for the right/bottom - edges - -The calculations clipped the right/bottom edge of the clipped -range based on the left/top margins. - -Fixes: 666e73587f90 ("drm/vc4: Take margin setup into account when updating planes") -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_plane.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index c100eeddd5ad..4d97d1747eef 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -310,16 +310,16 @@ static int vc4_plane_margins_adj(struct drm_plane_state *pstate) - adjhdisplay, - crtc_state->mode.hdisplay); - vc4_pstate->crtc_x += left; -- if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left) -- vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left; -+ if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - right) -+ vc4_pstate->crtc_x = crtc_state->mode.hdisplay - right; - - adjvdisplay = crtc_state->mode.vdisplay - (top + bottom); - vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y * - adjvdisplay, - crtc_state->mode.vdisplay); - vc4_pstate->crtc_y += top; -- if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top) -- vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top; -+ if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - bottom) -+ vc4_pstate->crtc_y = crtc_state->mode.vdisplay - bottom; - - vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w * - adjhdisplay, --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0470-drm-vc4-Fix-timings-for-VEC-modes.patch b/root/target/linux/bcm27xx/patches-5.15/0470-drm-vc4-Fix-timings-for-VEC-modes.patch deleted file mode 100644 index 641046ea..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0470-drm-vc4-Fix-timings-for-VEC-modes.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 4e4edf458c458663de9989d4c101842fbc05c9ae Mon Sep 17 00:00:00 2001 -From: Mateusz Kwiatkowski -Date: Thu, 15 Jul 2021 01:07:30 +0200 -Subject: [PATCH 470/634] drm/vc4: Fix timings for VEC modes - -This commit fixes vertical timings of the VEC (composite output) modes -to accurately represent the 525-line ("NTSC") and 625-line ("PAL") ITU-R -standards. - -Previous timings were actually defined as 502 and 601 lines, resulting -in non-standard 62.69 Hz and 52 Hz signals being generated, -respectively. - -Changes to vc4_crtc.c have also been made, to make the PixelValve -vertical timings accurately correspond to the DRM modeline in interlaced -modes. The resulting VERTA/VERTB register values have been verified -against the reference values set by the Raspberry Pi firmware. - -Signed-off-by: Mateusz Kwiatkowski ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 70 +++++++++++++++++++++------------- - drivers/gpu/drm/vc4/vc4_vec.c | 4 +- - 2 files changed, 45 insertions(+), 29 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index e21119f32552..23be68a8ecec 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -318,8 +318,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode - bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 || - vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); - bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1; -+ bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC; - u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; - u8 ppc = pv_data->pixels_per_clock; -+ -+ u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end; -+ u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start; -+ u16 vert_fp = mode->crtc_vsync_start - mode->crtc_vdisplay; -+ - bool debug_dump_regs = false; - - if (debug_dump_regs) { -@@ -343,49 +349,59 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode - VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc, - PV_HORZB_HACTIVE)); - -- CRTC_WRITE(PV_VERTA, -- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end + -- interlace, -- PV_VERTA_VBP) | -- VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, -- PV_VERTA_VSYNC)); -- CRTC_WRITE(PV_VERTB, -- VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, -- PV_VERTB_VFP) | -- VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); -- - if (interlace) { -+ bool odd_field_first = false; -+ u32 field_delay = mode->htotal * pixel_rep / (2 * ppc); -+ u16 vert_bp_even = vert_bp; -+ u16 vert_fp_even = vert_fp; -+ -+ if (is_vec) { -+ /* VEC (composite output) */ -+ ++field_delay; -+ if (mode->htotal == 858) { -+ /* 525-line mode (NTSC or PAL-M) */ -+ odd_field_first = true; -+ } -+ } -+ -+ if (odd_field_first) -+ ++vert_fp_even; -+ else -+ ++vert_bp; -+ - CRTC_WRITE(PV_VERTA_EVEN, -- VC4_SET_FIELD(mode->crtc_vtotal - -- mode->crtc_vsync_end, -- PV_VERTA_VBP) | -- VC4_SET_FIELD(mode->crtc_vsync_end - -- mode->crtc_vsync_start, -- PV_VERTA_VSYNC)); -+ VC4_SET_FIELD(vert_bp_even, PV_VERTA_VBP) | -+ VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC)); - CRTC_WRITE(PV_VERTB_EVEN, -- VC4_SET_FIELD(mode->crtc_vsync_start - -- mode->crtc_vdisplay, -- PV_VERTB_VFP) | -+ VC4_SET_FIELD(vert_fp_even, PV_VERTB_VFP) | - VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); - -- /* We set up first field even mode for HDMI. VEC's -- * NTSC mode would want first field odd instead, once -- * we support it (to do so, set ODD_FIRST and put the -- * delay in VSYNCD_EVEN instead). -+ /* We set up first field even mode for HDMI and VEC's PAL. -+ * For NTSC, we need first field odd. - */ - CRTC_WRITE(PV_V_CONTROL, - PV_VCONTROL_CONTINUOUS | - (is_dsi ? PV_VCONTROL_DSI : 0) | - PV_VCONTROL_INTERLACE | -- VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc), -- PV_VCONTROL_ODD_DELAY)); -- CRTC_WRITE(PV_VSYNCD_EVEN, 0); -+ (odd_field_first -+ ? PV_VCONTROL_ODD_FIRST -+ : VC4_SET_FIELD(field_delay, -+ PV_VCONTROL_ODD_DELAY))); -+ CRTC_WRITE(PV_VSYNCD_EVEN, -+ (odd_field_first ? field_delay : 0)); - } else { - CRTC_WRITE(PV_V_CONTROL, - PV_VCONTROL_CONTINUOUS | - (is_dsi ? PV_VCONTROL_DSI : 0)); - } - -+ CRTC_WRITE(PV_VERTA, -+ VC4_SET_FIELD(vert_bp, PV_VERTA_VBP) | -+ VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC)); -+ CRTC_WRITE(PV_VERTB, -+ VC4_SET_FIELD(vert_fp, PV_VERTB_VFP) | -+ VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); -+ - if (is_dsi) - CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); - -diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c -index 11fc3d6f66b1..4e2250b8fa23 100644 ---- a/drivers/gpu/drm/vc4/vc4_vec.c -+++ b/drivers/gpu/drm/vc4/vc4_vec.c -@@ -256,7 +256,7 @@ static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec) - static const struct drm_display_mode ntsc_mode = { - DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, -- 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0, -+ 480, 480 + 7, 480 + 7 + 6, 525, 0, - DRM_MODE_FLAG_INTERLACE) - }; - -@@ -278,7 +278,7 @@ static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec) - static const struct drm_display_mode pal_mode = { - DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, -- 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0, -+ 576, 576 + 4, 576 + 4 + 6, 625, 0, - DRM_MODE_FLAG_INTERLACE) - }; - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0471-drm-vc4-Refactor-VEC-TV-mode-setting.patch b/root/target/linux/bcm27xx/patches-5.15/0471-drm-vc4-Refactor-VEC-TV-mode-setting.patch deleted file mode 100644 index c19d68ed..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0471-drm-vc4-Refactor-VEC-TV-mode-setting.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 0050f48b39fe4864078ebd841f4264fa06424b88 Mon Sep 17 00:00:00 2001 -From: Mateusz Kwiatkowski -Date: Thu, 15 Jul 2021 01:07:49 +0200 -Subject: [PATCH 471/634] drm/vc4: Refactor VEC TV mode setting - -Change the mode_set function pointer logic to declarative config0, -config1 and custom_freq fields, to make TV mode setting logic more -concise and uniform. - -Additionally, remove the superfluous tv_mode field, which was redundant -with the mode field in struct drm_tv_connector_state. - -Signed-off-by: Mateusz Kwiatkowski ---- - drivers/gpu/drm/vc4/vc4_vec.c | 69 +++++++++++------------------------ - 1 file changed, 22 insertions(+), 47 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c -index 4e2250b8fa23..809690f2dd55 100644 ---- a/drivers/gpu/drm/vc4/vc4_vec.c -+++ b/drivers/gpu/drm/vc4/vc4_vec.c -@@ -170,8 +170,6 @@ struct vc4_vec { - - struct clk *clock; - -- const struct vc4_vec_tv_mode *tv_mode; -- - struct debugfs_regset32 regset; - }; - -@@ -211,7 +209,9 @@ enum vc4_vec_tv_mode_id { - - struct vc4_vec_tv_mode { - const struct drm_display_mode *mode; -- void (*mode_set)(struct vc4_vec *vec); -+ u32 config0; -+ u32 config1; -+ u32 custom_freq; - }; - - static const struct debugfs_reg32 vec_regs[] = { -@@ -241,18 +241,6 @@ static const struct debugfs_reg32 vec_regs[] = { - VC4_REG32(VEC_DAC_MISC), - }; - --static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec) --{ -- VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN); -- VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); --} -- --static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec) --{ -- VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD); -- VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); --} -- - static const struct drm_display_mode ntsc_mode = { - DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, -@@ -260,21 +248,6 @@ static const struct drm_display_mode ntsc_mode = { - DRM_MODE_FLAG_INTERLACE) - }; - --static void vc4_vec_pal_mode_set(struct vc4_vec *vec) --{ -- VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD); -- VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS); --} -- --static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec) --{ -- VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD); -- VEC_WRITE(VEC_CONFIG1, -- VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ); -- VEC_WRITE(VEC_FREQ3_2, 0x223b); -- VEC_WRITE(VEC_FREQ1_0, 0x61d1); --} -- - static const struct drm_display_mode pal_mode = { - DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, -@@ -285,19 +258,24 @@ static const struct drm_display_mode pal_mode = { - static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { - [VC4_VEC_TV_MODE_NTSC] = { - .mode = &ntsc_mode, -- .mode_set = vc4_vec_ntsc_mode_set, -+ .config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN, -+ .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_NTSC_J] = { - .mode = &ntsc_mode, -- .mode_set = vc4_vec_ntsc_j_mode_set, -+ .config0 = VEC_CONFIG0_NTSC_STD, -+ .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_PAL] = { - .mode = &pal_mode, -- .mode_set = vc4_vec_pal_mode_set, -+ .config0 = VEC_CONFIG0_PAL_BDGHI_STD, -+ .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_PAL_M] = { - .mode = &pal_mode, -- .mode_set = vc4_vec_pal_m_mode_set, -+ .config0 = VEC_CONFIG0_PAL_BDGHI_STD, -+ .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ, -+ .custom_freq = 0x223b61d1, - }, - }; - -@@ -367,7 +345,6 @@ static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev, - drm_object_attach_property(&connector->base, - dev->mode_config.tv_mode_property, - VC4_VEC_TV_MODE_NTSC); -- vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC]; - - drm_connector_attach_encoder(connector, vec->encoder); - -@@ -400,6 +377,7 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) - { - struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder); - struct vc4_vec *vec = vc4_vec_encoder->vec; -+ unsigned int tv_mode = vec->connector->state->tv.mode; - int ret; - - ret = pm_runtime_get_sync(&vec->pdev->dev); -@@ -455,7 +433,15 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) - /* Mask all interrupts. */ - VEC_WRITE(VEC_MASK0, 0); - -- vec->tv_mode->mode_set(vec); -+ VEC_WRITE(VEC_CONFIG0, vc4_vec_tv_modes[tv_mode].config0); -+ VEC_WRITE(VEC_CONFIG1, vc4_vec_tv_modes[tv_mode].config1); -+ if (vc4_vec_tv_modes[tv_mode].custom_freq != 0) { -+ VEC_WRITE(VEC_FREQ3_2, -+ (vc4_vec_tv_modes[tv_mode].custom_freq >> 16) & -+ 0xffff); -+ VEC_WRITE(VEC_FREQ1_0, -+ vc4_vec_tv_modes[tv_mode].custom_freq & 0xffff); -+ } - - VEC_WRITE(VEC_DAC_MISC, - VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N); -@@ -470,16 +456,6 @@ static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder, - return true; - } - --static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder, -- struct drm_crtc_state *crtc_state, -- struct drm_connector_state *conn_state) --{ -- struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder); -- struct vc4_vec *vec = vc4_vec_encoder->vec; -- -- vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode]; --} -- - static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -@@ -500,7 +476,6 @@ static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = { - .enable = vc4_vec_encoder_enable, - .mode_fixup = vc4_vec_encoder_mode_fixup, - .atomic_check = vc4_vec_encoder_atomic_check, -- .atomic_mode_set = vc4_vec_encoder_atomic_mode_set, - }; - - static const struct vc4_vec_variant bcm2835_vec_variant = { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0472-drm-vc4-Fix-definition-of-PAL-M-mode.patch b/root/target/linux/bcm27xx/patches-5.15/0472-drm-vc4-Fix-definition-of-PAL-M-mode.patch deleted file mode 100644 index d1edda34..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0472-drm-vc4-Fix-definition-of-PAL-M-mode.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 786d3424a7dd1ffb36ca211a1e4c23ac05320afd Mon Sep 17 00:00:00 2001 -From: Mateusz Kwiatkowski -Date: Thu, 15 Jul 2021 01:07:53 +0200 -Subject: [PATCH 472/634] drm/vc4: Fix definition of PAL-M mode - -PAL-M is a Brazilian analog TV standard that uses a PAL-style chroma -subcarrier at 3.575611[888111] MHz on top of 525-line (480i60) timings. -This commit makes the driver actually use the proper VEC preset for this -mode instead of just changing PAL subcarrier frequency. - -DRM mode constant names have also been changed, as they no longer -correspond to the "NTSC" or "PAL" terms. - -Signed-off-by: Mateusz Kwiatkowski ---- - drivers/gpu/drm/vc4/vc4_vec.c | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c -index 809690f2dd55..231ed492cb71 100644 ---- a/drivers/gpu/drm/vc4/vc4_vec.c -+++ b/drivers/gpu/drm/vc4/vc4_vec.c -@@ -68,6 +68,7 @@ - #define VEC_CONFIG0_STD_MASK GENMASK(1, 0) - #define VEC_CONFIG0_NTSC_STD 0 - #define VEC_CONFIG0_PAL_BDGHI_STD 1 -+#define VEC_CONFIG0_PAL_M_STD 2 - #define VEC_CONFIG0_PAL_N_STD 3 - - #define VEC_SCHPH 0x108 -@@ -241,14 +242,14 @@ static const struct debugfs_reg32 vec_regs[] = { - VC4_REG32(VEC_DAC_MISC), - }; - --static const struct drm_display_mode ntsc_mode = { -+static const struct drm_display_mode drm_mode_480i = { - DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, - 480, 480 + 7, 480 + 7 + 6, 525, 0, - DRM_MODE_FLAG_INTERLACE) - }; - --static const struct drm_display_mode pal_mode = { -+static const struct drm_display_mode drm_mode_576i = { - DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, - 576, 576 + 4, 576 + 4 + 6, 625, 0, -@@ -257,25 +258,24 @@ static const struct drm_display_mode pal_mode = { - - static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { - [VC4_VEC_TV_MODE_NTSC] = { -- .mode = &ntsc_mode, -+ .mode = &drm_mode_480i, - .config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_NTSC_J] = { -- .mode = &ntsc_mode, -+ .mode = &drm_mode_480i, - .config0 = VEC_CONFIG0_NTSC_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_PAL] = { -- .mode = &pal_mode, -+ .mode = &drm_mode_576i, - .config0 = VEC_CONFIG0_PAL_BDGHI_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_PAL_M] = { -- .mode = &pal_mode, -- .config0 = VEC_CONFIG0_PAL_BDGHI_STD, -- .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ, -- .custom_freq = 0x223b61d1, -+ .mode = &drm_mode_480i, -+ .config0 = VEC_CONFIG0_PAL_M_STD, -+ .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - }; - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0473-drm-vc4-Add-support-for-more-analog-TV-standards.patch b/root/target/linux/bcm27xx/patches-5.15/0473-drm-vc4-Add-support-for-more-analog-TV-standards.patch deleted file mode 100644 index fb2774e2..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0473-drm-vc4-Add-support-for-more-analog-TV-standards.patch +++ /dev/null @@ -1,153 +0,0 @@ -From d7adb28231c1e63db2752d6df2c13a95f900cdaf Mon Sep 17 00:00:00 2001 -From: Mateusz Kwiatkowski -Date: Thu, 15 Jul 2021 01:07:58 +0200 -Subject: [PATCH 473/634] drm/vc4: Add support for more analog TV standards - -Add support for the following composite output modes (all of them are -somewhat more obscure than the previously defined ones): - -- NTSC_443 - NTSC-style signal with the chroma subcarrier shifted to - 4.43361875 MHz (the PAL subcarrier frequency). Never used for - broadcasting, but sometimes used as a hack to play NTSC content in PAL - regions (e.g. on VCRs). -- PAL_N - PAL with alternative chroma subcarrier frequency, - 3.58205625 MHz. Used as a broadcast standard in Argentina, Paraguay - and Uruguay to fit 576i50 with colour in 6 MHz channel raster. -- PAL60 - 480i60 signal with PAL-style color at normal European PAL - frequency. Another non-standard, non-broadcast mode, used in similar - contexts as NTSC_443. Some displays support one but not the other. -- SECAM - French frequency-modulated analog color standard; also have - been broadcast in Eastern Europe and various parts of Africa and Asia. - Uses the same 576i50 timings as PAL. - -Also added some comments explaining color subcarrier frequency -registers. - -Signed-off-by: Mateusz Kwiatkowski ---- - drivers/gpu/drm/vc4/vc4_vec.c | 63 +++++++++++++++++++++++++++++++++++ - 1 file changed, 63 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c -index 231ed492cb71..e0bd484321d1 100644 ---- a/drivers/gpu/drm/vc4/vc4_vec.c -+++ b/drivers/gpu/drm/vc4/vc4_vec.c -@@ -45,6 +45,7 @@ - #define VEC_CONFIG0_YDEL(x) ((x) << 26) - #define VEC_CONFIG0_CDEL_MASK GENMASK(25, 24) - #define VEC_CONFIG0_CDEL(x) ((x) << 24) -+#define VEC_CONFIG0_SECAM_STD BIT(21) - #define VEC_CONFIG0_PBPR_FIL BIT(18) - #define VEC_CONFIG0_CHROMA_GAIN_MASK GENMASK(17, 16) - #define VEC_CONFIG0_CHROMA_GAIN_UNITY (0 << 16) -@@ -75,6 +76,27 @@ - #define VEC_SOFT_RESET 0x10c - #define VEC_CLMP0_START 0x144 - #define VEC_CLMP0_END 0x148 -+ -+/* -+ * These set the color subcarrier frequency -+ * if VEC_CONFIG1_CUSTOM_FREQ is enabled. -+ * -+ * VEC_FREQ1_0 contains the most significant 16-bit half-word, -+ * VEC_FREQ3_2 contains the least significant 16-bit half-word. -+ * 0x80000000 seems to be equivalent to the pixel clock -+ * (which itself is the VEC clock divided by 8). -+ * -+ * Reference values (with the default pixel clock of 13.5 MHz): -+ * -+ * NTSC (3579545.[45] Hz) - 0x21F07C1F -+ * PAL (4433618.75 Hz) - 0x2A098ACB -+ * PAL-M (3575611.[888111] Hz) - 0x21E6EFE3 -+ * PAL-N (3582056.25 Hz) - 0x21F69446 -+ * -+ * NOTE: For SECAM, it is used as the Dr center frequency, -+ * regardless of whether VEC_CONFIG1_CUSTOM_FREQ is enabled or not; -+ * that is specified as 4406250 Hz, which corresponds to 0x29C71C72. -+ */ - #define VEC_FREQ3_2 0x180 - #define VEC_FREQ1_0 0x184 - -@@ -117,6 +139,14 @@ - - #define VEC_INTERRUPT_CONTROL 0x190 - #define VEC_INTERRUPT_STATUS 0x194 -+ -+/* -+ * Db center frequency for SECAM; the clock for this is the same as for -+ * VEC_FREQ3_2/VEC_FREQ1_0, which is used for Dr center frequency. -+ * -+ * This is specified as 4250000 Hz, which corresponds to 0x284BDA13. -+ * That is also the default value, so no need to set it explicitly. -+ */ - #define VEC_FCW_SECAM_B 0x198 - #define VEC_SECAM_GAIN_VAL 0x19c - -@@ -204,8 +234,12 @@ struct vc4_vec_connector { - enum vc4_vec_tv_mode_id { - VC4_VEC_TV_MODE_NTSC, - VC4_VEC_TV_MODE_NTSC_J, -+ VC4_VEC_TV_MODE_NTSC_443, - VC4_VEC_TV_MODE_PAL, - VC4_VEC_TV_MODE_PAL_M, -+ VC4_VEC_TV_MODE_PAL_N, -+ VC4_VEC_TV_MODE_PAL60, -+ VC4_VEC_TV_MODE_SECAM, - }; - - struct vc4_vec_tv_mode { -@@ -267,6 +301,13 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { - .config0 = VEC_CONFIG0_NTSC_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, -+ [VC4_VEC_TV_MODE_NTSC_443] = { -+ /* NTSC with PAL chroma frequency */ -+ .mode = &drm_mode_480i, -+ .config0 = VEC_CONFIG0_NTSC_STD, -+ .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ, -+ .custom_freq = 0x2a098acb, -+ }, - [VC4_VEC_TV_MODE_PAL] = { - .mode = &drm_mode_576i, - .config0 = VEC_CONFIG0_PAL_BDGHI_STD, -@@ -277,6 +318,24 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { - .config0 = VEC_CONFIG0_PAL_M_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, -+ [VC4_VEC_TV_MODE_PAL_N] = { -+ .mode = &drm_mode_576i, -+ .config0 = VEC_CONFIG0_PAL_N_STD, -+ .config1 = VEC_CONFIG1_C_CVBS_CVBS, -+ }, -+ [VC4_VEC_TV_MODE_PAL60] = { -+ /* PAL-M with chroma frequency of regular PAL */ -+ .mode = &drm_mode_480i, -+ .config0 = VEC_CONFIG0_PAL_M_STD, -+ .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ, -+ .custom_freq = 0x2a098acb, -+ }, -+ [VC4_VEC_TV_MODE_SECAM] = { -+ .mode = &drm_mode_576i, -+ .config0 = VEC_CONFIG0_SECAM_STD, -+ .config1 = VEC_CONFIG1_C_CVBS_CVBS, -+ .custom_freq = 0x29c71c72, -+ }, - }; - - static enum drm_connector_status -@@ -499,8 +558,12 @@ static const struct of_device_id vc4_vec_dt_match[] = { - static const char * const tv_mode_names[] = { - [VC4_VEC_TV_MODE_NTSC] = "NTSC", - [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J", -+ [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443", - [VC4_VEC_TV_MODE_PAL] = "PAL", - [VC4_VEC_TV_MODE_PAL_M] = "PAL-M", -+ [VC4_VEC_TV_MODE_PAL_N] = "PAL-N", -+ [VC4_VEC_TV_MODE_PAL60] = "PAL60", -+ [VC4_VEC_TV_MODE_SECAM] = "SECAM", - }; - - static int vc4_vec_bind(struct device *dev, struct device *master, void *data) --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0474-drm-vc4-Allow-setting-the-TV-norm-via-module-paramet.patch b/root/target/linux/bcm27xx/patches-5.15/0474-drm-vc4-Allow-setting-the-TV-norm-via-module-paramet.patch deleted file mode 100644 index 31cffeaa..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0474-drm-vc4-Allow-setting-the-TV-norm-via-module-paramet.patch +++ /dev/null @@ -1,149 +0,0 @@ -From cb0f3c128dd03bae41ff68d04a2af324e8af0d2a Mon Sep 17 00:00:00 2001 -From: Mateusz Kwiatkowski -Date: Thu, 15 Jul 2021 01:08:01 +0200 -Subject: [PATCH 474/634] drm/vc4: Allow setting the TV norm via module - parameter - -Similar to the ch7006 and nouveau drivers, introduce a "tv_mode" module -parameter that allow setting the TV norm by specifying vc4.tv_norm= on -the kernel command line. - -If that is not specified, try inferring one of the most popular norms -(PAL or NTSC) from the video mode specified on the command line. On -Raspberry Pis, this causes the most common cases of the sdtv_mode -setting in config.txt to be respected. - -Signed-off-by: Mateusz Kwiatkowski ---- - drivers/gpu/drm/vc4/vc4_vec.c | 72 ++++++++++++++++++++++++++++------- - 1 file changed, 58 insertions(+), 14 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c -index e0bd484321d1..fb4360c0d9e3 100644 ---- a/drivers/gpu/drm/vc4/vc4_vec.c -+++ b/drivers/gpu/drm/vc4/vc4_vec.c -@@ -66,7 +66,7 @@ - #define VEC_CONFIG0_YCDELAY BIT(4) - #define VEC_CONFIG0_RAMPEN BIT(2) - #define VEC_CONFIG0_YCDIS BIT(2) --#define VEC_CONFIG0_STD_MASK GENMASK(1, 0) -+#define VEC_CONFIG0_STD_MASK (VEC_CONFIG0_SECAM_STD | GENMASK(1, 0)) - #define VEC_CONFIG0_NTSC_STD 0 - #define VEC_CONFIG0_PAL_BDGHI_STD 1 - #define VEC_CONFIG0_PAL_M_STD 2 -@@ -185,6 +185,8 @@ - #define VEC_DAC_MISC_DAC_RST_N BIT(0) - - -+static char *vc4_vec_tv_norm; -+ - struct vc4_vec_variant { - u32 dac_config; - }; -@@ -338,6 +340,44 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { - }, - }; - -+static const char * const tv_mode_names[] = { -+ [VC4_VEC_TV_MODE_NTSC] = "NTSC", -+ [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J", -+ [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443", -+ [VC4_VEC_TV_MODE_PAL] = "PAL", -+ [VC4_VEC_TV_MODE_PAL_M] = "PAL-M", -+ [VC4_VEC_TV_MODE_PAL_N] = "PAL-N", -+ [VC4_VEC_TV_MODE_PAL60] = "PAL60", -+ [VC4_VEC_TV_MODE_SECAM] = "SECAM", -+}; -+ -+enum vc4_vec_tv_mode_id -+vc4_vec_get_default_mode(struct drm_connector *connector) -+{ -+ int i; -+ -+ if (vc4_vec_tv_norm) { -+ for (i = 0; i < ARRAY_SIZE(tv_mode_names); i++) -+ if (strcmp(vc4_vec_tv_norm, tv_mode_names[i]) == 0) -+ return (enum vc4_vec_tv_mode_id) i; -+ } else if (connector->cmdline_mode.specified && -+ ((connector->cmdline_mode.refresh_specified && -+ (connector->cmdline_mode.refresh == 25 || -+ connector->cmdline_mode.refresh == 50)) || -+ (!connector->cmdline_mode.refresh_specified && -+ (connector->cmdline_mode.yres == 288 || -+ connector->cmdline_mode.yres == 576)))) { -+ /* -+ * no explicitly specified TV norm; use PAL if a mode that -+ * looks like PAL has been specified on the command line -+ */ -+ return VC4_VEC_TV_MODE_PAL; -+ } -+ -+ /* in all other cases, default to NTSC */ -+ return VC4_VEC_TV_MODE_NTSC; -+} -+ - static enum drm_connector_status - vc4_vec_connector_detect(struct drm_connector *connector, bool force) - { -@@ -367,11 +407,19 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector) - return 1; - } - -+static void vc4_vec_connector_reset(struct drm_connector *connector) -+{ -+ drm_atomic_helper_connector_reset(connector); -+ /* preserve TV standard */ -+ if (connector->state) -+ connector->state->tv.mode = vc4_vec_get_default_mode(connector); -+} -+ - static const struct drm_connector_funcs vc4_vec_connector_funcs = { - .detect = vc4_vec_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = vc4_vec_connector_destroy, -- .reset = drm_atomic_helper_connector_reset, -+ .reset = vc4_vec_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - }; -@@ -403,7 +451,7 @@ static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev, - - drm_object_attach_property(&connector->base, - dev->mode_config.tv_mode_property, -- VC4_VEC_TV_MODE_NTSC); -+ vc4_vec_get_default_mode(connector)); - - drm_connector_attach_encoder(connector, vec->encoder); - -@@ -555,17 +603,6 @@ static const struct of_device_id vc4_vec_dt_match[] = { - { /* sentinel */ }, - }; - --static const char * const tv_mode_names[] = { -- [VC4_VEC_TV_MODE_NTSC] = "NTSC", -- [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J", -- [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443", -- [VC4_VEC_TV_MODE_PAL] = "PAL", -- [VC4_VEC_TV_MODE_PAL_M] = "PAL-M", -- [VC4_VEC_TV_MODE_PAL_N] = "PAL-N", -- [VC4_VEC_TV_MODE_PAL60] = "PAL60", -- [VC4_VEC_TV_MODE_SECAM] = "SECAM", --}; -- - static int vc4_vec_bind(struct device *dev, struct device *master, void *data) - { - struct platform_device *pdev = to_platform_device(dev); -@@ -674,3 +711,10 @@ struct platform_driver vc4_vec_driver = { - .of_match_table = vc4_vec_dt_match, - }, - }; -+ -+module_param_named(tv_norm, vc4_vec_tv_norm, charp, 0600); -+MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" -+ "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n" -+ "\t\t\tPAL60, SECAM.\n" -+ "\t\tDefault: PAL if a 50 Hz mode has been set via video=,\n" -+ "\t\t\tNTSC otherwise"); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0475-drm-vc4-Refactor-mode-checking-logic.patch b/root/target/linux/bcm27xx/patches-5.15/0475-drm-vc4-Refactor-mode-checking-logic.patch deleted file mode 100644 index ca3edd0b..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0475-drm-vc4-Refactor-mode-checking-logic.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 435dc64038e7bbc027d5f4de1c8df7f13a411d29 Mon Sep 17 00:00:00 2001 -From: Mateusz Kwiatkowski -Date: Thu, 15 Jul 2021 01:08:05 +0200 -Subject: [PATCH 475/634] drm/vc4: Refactor mode checking logic - -Replace drm_encoder_helper_funcs::atomic_check with -drm_connector_helper_funcs::atomic_check - the former is not called -during drm_mode_obj_set_property_ioctl(). Set crtc_state->mode_changed -if TV norm changes even without explicit mode change. This makes things -like "xrandr --output Composite-1 --set mode PAL-M" work properly. - -Signed-off-by: Mateusz Kwiatkowski ---- - drivers/gpu/drm/vc4/vc4_vec.c | 42 ++++++++++++++++++++++------------- - 1 file changed, 26 insertions(+), 16 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c -index fb4360c0d9e3..b684595a5d0b 100644 ---- a/drivers/gpu/drm/vc4/vc4_vec.c -+++ b/drivers/gpu/drm/vc4/vc4_vec.c -@@ -415,6 +415,31 @@ static void vc4_vec_connector_reset(struct drm_connector *connector) - connector->state->tv.mode = vc4_vec_get_default_mode(connector); - } - -+static int vc4_vec_connector_atomic_check(struct drm_connector *conn, -+ struct drm_atomic_state *state) -+{ -+ struct drm_connector_state *old_state = -+ drm_atomic_get_old_connector_state(state, conn); -+ struct drm_connector_state *new_state = -+ drm_atomic_get_new_connector_state(state, conn); -+ -+ const struct vc4_vec_tv_mode *vec_mode = -+ &vc4_vec_tv_modes[new_state->tv.mode]; -+ -+ if (new_state->crtc) { -+ struct drm_crtc_state *crtc_state = -+ drm_atomic_get_new_crtc_state(state, new_state->crtc); -+ -+ if (!drm_mode_equal(vec_mode->mode, &crtc_state->mode)) -+ return -EINVAL; -+ -+ if (old_state->tv.mode != new_state->tv.mode) -+ crtc_state->mode_changed = true; -+ } -+ -+ return 0; -+} -+ - static const struct drm_connector_funcs vc4_vec_connector_funcs = { - .detect = vc4_vec_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, -@@ -426,6 +451,7 @@ static const struct drm_connector_funcs vc4_vec_connector_funcs = { - - static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = { - .get_modes = vc4_vec_connector_get_modes, -+ .atomic_check = vc4_vec_connector_atomic_check, - }; - - static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev, -@@ -563,26 +589,10 @@ static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder, - return true; - } - --static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, -- struct drm_crtc_state *crtc_state, -- struct drm_connector_state *conn_state) --{ -- const struct vc4_vec_tv_mode *vec_mode; -- -- vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode]; -- -- if (conn_state->crtc && -- !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode)) -- return -EINVAL; -- -- return 0; --} -- - static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = { - .disable = vc4_vec_encoder_disable, - .enable = vc4_vec_encoder_enable, - .mode_fixup = vc4_vec_encoder_mode_fixup, -- .atomic_check = vc4_vec_encoder_atomic_check, - }; - - static const struct vc4_vec_variant bcm2835_vec_variant = { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0476-drm-vc4-Remove-conflicting-framebuffers-before-calli.patch b/root/target/linux/bcm27xx/patches-5.15/0476-drm-vc4-Remove-conflicting-framebuffers-before-calli.patch deleted file mode 100644 index 162c25d6..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0476-drm-vc4-Remove-conflicting-framebuffers-before-calli.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 27c04928300510f13438df4a120f671df6b03321 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 25 Jun 2021 17:01:33 +0200 -Subject: [PATCH 476/634] drm/vc4: Remove conflicting framebuffers before - callind bind_all - -The bind hooks will modify their controller registers, so simplefb is -going to be unusable anyway. Let's avoid any transient state where it -could still be in the system but no longer functionnal. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_drv.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index baa419bc5199..556bf17a6573 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -273,15 +273,15 @@ static int vc4_drm_bind(struct device *dev) - if (ret) - return ret; - -- ret = component_bind_all(dev, drm); -+ ret = drm_aperture_remove_framebuffers(false, &vc4_drm_driver); - if (ret) - return ret; - -- ret = vc4_plane_create_additional_planes(drm); -+ ret = component_bind_all(dev, drm); - if (ret) -- goto unbind_all; -+ return ret; - -- ret = drm_aperture_remove_framebuffers(false, &vc4_drm_driver); -+ ret = vc4_plane_create_additional_planes(drm); - if (ret) - goto unbind_all; - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0477-drm-vc4-Notify-the-firmware-when-DRM-is-in-charge.patch b/root/target/linux/bcm27xx/patches-5.15/0477-drm-vc4-Notify-the-firmware-when-DRM-is-in-charge.patch deleted file mode 100644 index d193661b..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0477-drm-vc4-Notify-the-firmware-when-DRM-is-in-charge.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 69f5c55779c1953ead79e807ef8823478887dbec Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 23 Jun 2021 11:54:58 +0200 -Subject: [PATCH 477/634] drm/vc4: Notify the firmware when DRM is in charge - -Once the call to drm_fb_helper_remove_conflicting_framebuffers() has -been made, simplefb has been unregistered and the KMS driver is entirely -in charge of the display. - -Thus, we can notify the firmware it can free whatever resource it was -using to maintain simplefb functional. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_drv.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 556bf17a6573..88d6d2c6fa23 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -37,6 +37,8 @@ - #include - #include - -+#include -+ - #include "uapi/drm/vc4_drm.h" - - #include "vc4_drv.h" -@@ -273,10 +275,27 @@ static int vc4_drm_bind(struct device *dev) - if (ret) - return ret; - -+ node = of_parse_phandle(dev->of_node, "raspberrypi,firmware", 0); -+ if (node) { -+ vc4->firmware = rpi_firmware_get(node); -+ of_node_put(node); -+ -+ if (!vc4->firmware) -+ return -EPROBE_DEFER; -+ } -+ - ret = drm_aperture_remove_framebuffers(false, &vc4_drm_driver); - if (ret) - return ret; - -+ if (vc4->firmware) { -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_NOTIFY_DISPLAY_DONE, -+ NULL, 0); -+ if (ret) -+ drm_warn(drm, "Couldn't stop firmware display driver: %d\n", ret); -+ } -+ - ret = component_bind_all(dev, drm); - if (ret) - return ret; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0478-drm-vc4-Add-firmware-kms-mode.patch b/root/target/linux/bcm27xx/patches-5.15/0478-drm-vc4-Add-firmware-kms-mode.patch deleted file mode 100644 index 9e683cdb..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0478-drm-vc4-Add-firmware-kms-mode.patch +++ /dev/null @@ -1,2518 +0,0 @@ -From 8eed5dc92e35e091a373faf1891ef64d914e9bbd Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 7 Sep 2020 17:32:27 +0100 -Subject: [PATCH 478/634] drm/vc4: Add firmware-kms mode - -This is a squash of all firmware-kms related patches from previous -branches, up to and including -"drm/vc4: Set the possible crtcs mask correctly for planes with FKMS" -plus a couple of minor fixups for the 5.9 branch. -Please refer to earlier branches for full history. - -This patch includes work by Eric Anholt, James Hughes, Phil Elwell, -Dave Stevenson, Dom Cobley, and Jonathon Bell. - -Signed-off-by: Dave Stevenson - -drm/vc4: Fixup firmware-kms after "drm/atomic: Pass the full state to CRTC atomic enable/disable" - -Prototype for those calls changed, so amend fkms (which isn't -upstream) to match. - -Signed-off-by: Dave Stevenson - -drm/vc4: Fixup fkms for API change - -Atomic flush and check changed API, so fix up the downstream-only -FKMS driver. - -Signed-off-by: Dave Stevenson - -drm/vc4: Make normalize_zpos conditional on using fkms - -Eric's view was that there was no point in having zpos -support on vc4 as all the planes had the same functionality. - -Can be later squashed into (and fixes): -drm/vc4: Add firmware-kms mode - -Signed-off-by: Dom Cobley - -drm/vc4: FKMS: Change of Broadcast RGB mode needs a mode change - -The Broadcast RGB (aka HDMI limited/full range) property is only -notified to the firmware on mode change, so this needs to be -signalled when set. - -https://github.com/raspberrypi/firmware/issues/1580 - -Signed-off-by: Dave Stevenson - -vc4/drv: Only notify firmware of display done with kms - -fkms driver still wants firmware display to be active - -Signed-off-by: Dom Cobley - -ydrm/vc4: fkms: Fix margin calculations for the right/bottom edges - -The calculations clipped the right/bottom edge of the clipped -range based on the left/top margins. - -https://github.com/raspberrypi/linux/issues/4447 - -Signed-off-by: Dave Stevenson - -drm/vc4: fkms: Use new devm_rpi_firmware_get api - -drm/kms: Add allow_fb_modifiers - -Signed-off-by: Dom Cobley ---- - drivers/gpu/drm/vc4/Makefile | 1 + - drivers/gpu/drm/vc4/vc4_debugfs.c | 2 +- - drivers/gpu/drm/vc4/vc4_drv.c | 29 +- - drivers/gpu/drm/vc4/vc4_drv.h | 7 + - drivers/gpu/drm/vc4/vc4_firmware_kms.c | 1994 ++++++++++++++++++++ - drivers/gpu/drm/vc4/vc4_kms.c | 35 +- - drivers/gpu/drm/vc4/vc_image_types.h | 175 ++ - include/soc/bcm2835/raspberrypi-firmware.h | 6 + - 8 files changed, 2235 insertions(+), 14 deletions(-) - create mode 100644 drivers/gpu/drm/vc4/vc4_firmware_kms.c - create mode 100644 drivers/gpu/drm/vc4/vc_image_types.h - -diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile -index d0163e18e9ca..8281a044834f 100644 ---- a/drivers/gpu/drm/vc4/Makefile -+++ b/drivers/gpu/drm/vc4/Makefile -@@ -9,6 +9,7 @@ vc4-y := \ - vc4_dpi.o \ - vc4_dsi.o \ - vc4_fence.o \ -+ vc4_firmware_kms.o \ - vc4_kms.o \ - vc4_gem.o \ - vc4_hdmi.o \ -diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c -index ba2d8ea562af..2936a7e333a9 100644 ---- a/drivers/gpu/drm/vc4/vc4_debugfs.c -+++ b/drivers/gpu/drm/vc4/vc4_debugfs.c -@@ -27,7 +27,7 @@ vc4_debugfs_init(struct drm_minor *minor) - struct vc4_dev *vc4 = to_vc4_dev(minor->dev); - struct vc4_debugfs_info_entry *entry; - -- if (!of_device_is_compatible(vc4->hvs->pdev->dev.of_node, -+ if (vc4->hvs && !of_device_is_compatible(vc4->hvs->pdev->dev.of_node, - "brcm,bcm2711-vc5")) - debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR, - minor->debugfs_root, &vc4->load_tracker_enabled); -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 88d6d2c6fa23..a0fea4587a20 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -226,6 +226,18 @@ const struct of_device_id vc4_dma_range_matches[] = { - {} - }; - -+/* -+ * we need this helper function for determining presence of fkms -+ * before it's been bound -+ */ -+static bool firmware_kms(void) -+{ -+ return of_device_is_available(of_find_compatible_node(NULL, NULL, -+ "raspberrypi,rpi-firmware-kms")) || -+ of_device_is_available(of_find_compatible_node(NULL, NULL, -+ "raspberrypi,rpi-firmware-kms-2711")); -+} -+ - static int vc4_drm_bind(struct device *dev) - { - struct platform_device *pdev = to_platform_device(dev); -@@ -288,7 +300,7 @@ static int vc4_drm_bind(struct device *dev) - if (ret) - return ret; - -- if (vc4->firmware) { -+ if (vc4->firmware && !firmware_kms()) { - ret = rpi_firmware_property(vc4->firmware, - RPI_FIRMWARE_NOTIFY_DISPLAY_DONE, - NULL, 0); -@@ -300,16 +312,20 @@ static int vc4_drm_bind(struct device *dev) - if (ret) - return ret; - -- ret = vc4_plane_create_additional_planes(drm); -- if (ret) -- goto unbind_all; -+ if (!vc4->firmware_kms) { -+ ret = vc4_plane_create_additional_planes(drm); -+ if (ret) -+ goto unbind_all; -+ } - - ret = vc4_kms_load(drm); - if (ret < 0) - goto unbind_all; - -- drm_for_each_crtc(crtc, drm) -- vc4_crtc_disable_at_boot(crtc); -+ if (!vc4->firmware_kms) { -+ drm_for_each_crtc(crtc, drm) -+ vc4_crtc_disable_at_boot(crtc); -+ } - - ret = drm_dev_register(drm, 0); - if (ret < 0) -@@ -356,6 +372,7 @@ static struct platform_driver *const component_drivers[] = { - &vc4_dsi_driver, - &vc4_txp_driver, - &vc4_crtc_driver, -+ &vc4_firmware_kms_driver, - &vc4_v3d_driver, - }; - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 3921959b4a5e..48d5d13f38a3 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -76,11 +76,15 @@ struct vc4_dev { - - unsigned int irq; - -+ bool firmware_kms; -+ struct rpi_firmware *firmware; -+ - struct vc4_hvs *hvs; - struct vc4_v3d *v3d; - struct vc4_dpi *dpi; - struct vc4_vec *vec; - struct vc4_txp *txp; -+ struct vc4_fkms *fkms; - - struct vc4_hang_state *hang_state; - -@@ -896,6 +900,9 @@ extern struct platform_driver vc4_dsi_driver; - /* vc4_fence.c */ - extern const struct dma_fence_ops vc4_fence_ops; - -+/* vc4_firmware_kms.c */ -+extern struct platform_driver vc4_firmware_kms_driver; -+ - /* vc4_gem.c */ - int vc4_gem_init(struct drm_device *dev); - int vc4_submit_cl_ioctl(struct drm_device *dev, void *data, -diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -new file mode 100644 -index 000000000000..99e379c9812b ---- /dev/null -+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -@@ -0,0 +1,1994 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2016 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+/** -+ * DOC: VC4 firmware KMS module. -+ * -+ * As a hack to get us from the current closed source driver world -+ * toward a totally open stack, implement KMS on top of the Raspberry -+ * Pi's firmware display stack. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "vc4_drv.h" -+#include "vc4_regs.h" -+#include "vc_image_types.h" -+ -+int fkms_max_refresh_rate = 85; -+module_param(fkms_max_refresh_rate, int, 0644); -+MODULE_PARM_DESC(fkms_max_refresh_rate, "Max supported refresh rate"); -+ -+struct get_display_cfg { -+ u32 max_pixel_clock[2]; //Max pixel clock for each display -+}; -+ -+struct vc4_fkms { -+ struct get_display_cfg cfg; -+ bool bcm2711; -+}; -+ -+#define PLANES_PER_CRTC 8 -+ -+struct set_plane { -+ u8 display; -+ u8 plane_id; -+ u8 vc_image_type; -+ s8 layer; -+ -+ u16 width; -+ u16 height; -+ -+ u16 pitch; -+ u16 vpitch; -+ -+ u32 src_x; /* 16p16 */ -+ u32 src_y; /* 16p16 */ -+ -+ u32 src_w; /* 16p16 */ -+ u32 src_h; /* 16p16 */ -+ -+ s16 dst_x; -+ s16 dst_y; -+ -+ u16 dst_w; -+ u16 dst_h; -+ -+ u8 alpha; -+ u8 num_planes; -+ u8 is_vu; -+ u8 color_encoding; -+ -+ u32 planes[4]; /* DMA address of each plane */ -+ -+ u32 transform; -+}; -+ -+/* Values for the transform field */ -+#define TRANSFORM_NO_ROTATE 0 -+#define TRANSFORM_ROTATE_180 BIT(1) -+#define TRANSFORM_FLIP_HRIZ BIT(16) -+#define TRANSFORM_FLIP_VERT BIT(17) -+ -+struct mailbox_set_plane { -+ struct rpi_firmware_property_tag_header tag; -+ struct set_plane plane; -+}; -+ -+struct mailbox_blank_display { -+ struct rpi_firmware_property_tag_header tag1; -+ u32 display; -+ struct rpi_firmware_property_tag_header tag2; -+ u32 blank; -+}; -+ -+struct mailbox_display_pwr { -+ struct rpi_firmware_property_tag_header tag1; -+ u32 display; -+ u32 state; -+}; -+ -+struct mailbox_get_edid { -+ struct rpi_firmware_property_tag_header tag1; -+ u32 block; -+ u32 display_number; -+ u8 edid[128]; -+}; -+ -+struct set_timings { -+ u8 display; -+ u8 padding; -+ u16 video_id_code; -+ -+ u32 clock; /* in kHz */ -+ -+ u16 hdisplay; -+ u16 hsync_start; -+ -+ u16 hsync_end; -+ u16 htotal; -+ -+ u16 hskew; -+ u16 vdisplay; -+ -+ u16 vsync_start; -+ u16 vsync_end; -+ -+ u16 vtotal; -+ u16 vscan; -+ -+ u16 vrefresh; -+ u16 padding2; -+ -+ u32 flags; -+#define TIMINGS_FLAGS_H_SYNC_POS BIT(0) -+#define TIMINGS_FLAGS_H_SYNC_NEG 0 -+#define TIMINGS_FLAGS_V_SYNC_POS BIT(1) -+#define TIMINGS_FLAGS_V_SYNC_NEG 0 -+#define TIMINGS_FLAGS_INTERLACE BIT(2) -+ -+#define TIMINGS_FLAGS_ASPECT_MASK GENMASK(7, 4) -+#define TIMINGS_FLAGS_ASPECT_NONE (0 << 4) -+#define TIMINGS_FLAGS_ASPECT_4_3 (1 << 4) -+#define TIMINGS_FLAGS_ASPECT_16_9 (2 << 4) -+#define TIMINGS_FLAGS_ASPECT_64_27 (3 << 4) -+#define TIMINGS_FLAGS_ASPECT_256_135 (4 << 4) -+ -+/* Limited range RGB flag. Not set corresponds to full range. */ -+#define TIMINGS_FLAGS_RGB_LIMITED BIT(8) -+/* DVI monitor, therefore disable infoframes. Not set corresponds to HDMI. */ -+#define TIMINGS_FLAGS_DVI BIT(9) -+/* Double clock */ -+#define TIMINGS_FLAGS_DBL_CLK BIT(10) -+}; -+ -+struct mailbox_set_mode { -+ struct rpi_firmware_property_tag_header tag1; -+ struct set_timings timings; -+}; -+ -+static const struct vc_image_format { -+ u32 drm; /* DRM_FORMAT_* */ -+ u32 vc_image; /* VC_IMAGE_* */ -+ u32 is_vu; -+} vc_image_formats[] = { -+ { -+ .drm = DRM_FORMAT_XRGB8888, -+ .vc_image = VC_IMAGE_XRGB8888, -+ }, -+ { -+ .drm = DRM_FORMAT_ARGB8888, -+ .vc_image = VC_IMAGE_ARGB8888, -+ }, -+/* -+ * FIXME: Need to resolve which DRM format goes to which vc_image format -+ * for the remaining RGBA and RGBX formats. -+ * { -+ * .drm = DRM_FORMAT_ABGR8888, -+ * .vc_image = VC_IMAGE_RGBA8888, -+ * }, -+ * { -+ * .drm = DRM_FORMAT_XBGR8888, -+ * .vc_image = VC_IMAGE_RGBA8888, -+ * }, -+ */ -+ { -+ .drm = DRM_FORMAT_RGB565, -+ .vc_image = VC_IMAGE_RGB565, -+ }, -+ { -+ .drm = DRM_FORMAT_RGB888, -+ .vc_image = VC_IMAGE_BGR888, -+ }, -+ { -+ .drm = DRM_FORMAT_BGR888, -+ .vc_image = VC_IMAGE_RGB888, -+ }, -+ { -+ .drm = DRM_FORMAT_YUV422, -+ .vc_image = VC_IMAGE_YUV422PLANAR, -+ }, -+ { -+ .drm = DRM_FORMAT_YUV420, -+ .vc_image = VC_IMAGE_YUV420, -+ }, -+ { -+ .drm = DRM_FORMAT_YVU420, -+ .vc_image = VC_IMAGE_YUV420, -+ .is_vu = 1, -+ }, -+ { -+ .drm = DRM_FORMAT_NV12, -+ .vc_image = VC_IMAGE_YUV420SP, -+ }, -+ { -+ .drm = DRM_FORMAT_NV21, -+ .vc_image = VC_IMAGE_YUV420SP, -+ .is_vu = 1, -+ }, -+ { -+ .drm = DRM_FORMAT_P030, -+ .vc_image = VC_IMAGE_YUV10COL, -+ }, -+}; -+ -+static const struct vc_image_format *vc4_get_vc_image_fmt(u32 drm_format) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) { -+ if (vc_image_formats[i].drm == drm_format) -+ return &vc_image_formats[i]; -+ } -+ -+ return NULL; -+} -+ -+/* The firmware delivers a vblank interrupt to us through the SMI -+ * hardware, which has only this one register. -+ */ -+#define SMICS 0x0 -+#define SMIDSW0 0x14 -+#define SMIDSW1 0x1C -+#define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11)) -+ -+/* Flag to denote that the firmware is giving multiple display callbacks */ -+#define SMI_NEW 0xabcd0000 -+ -+#define vc4_crtc vc4_kms_crtc -+#define to_vc4_crtc to_vc4_kms_crtc -+struct vc4_crtc { -+ struct drm_crtc base; -+ struct drm_encoder *encoder; -+ struct drm_connector *connector; -+ void __iomem *regs; -+ -+ struct drm_pending_vblank_event *event; -+ bool vblank_enabled; -+ u32 display_number; -+ u32 display_type; -+}; -+ -+static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc) -+{ -+ return container_of(crtc, struct vc4_crtc, base); -+} -+ -+struct vc4_fkms_encoder { -+ struct drm_encoder base; -+ bool hdmi_monitor; -+ bool rgb_range_selectable; -+ int display_num; -+}; -+ -+static inline struct vc4_fkms_encoder * -+to_vc4_fkms_encoder(struct drm_encoder *encoder) -+{ -+ return container_of(encoder, struct vc4_fkms_encoder, base); -+} -+ -+/* "Broadcast RGB" property. -+ * Allows overriding of HDMI full or limited range RGB -+ */ -+#define VC4_BROADCAST_RGB_AUTO 0 -+#define VC4_BROADCAST_RGB_FULL 1 -+#define VC4_BROADCAST_RGB_LIMITED 2 -+ -+/* VC4 FKMS connector KMS struct */ -+struct vc4_fkms_connector { -+ struct drm_connector base; -+ -+ /* Since the connector is attached to just the one encoder, -+ * this is the reference to it so we can do the best_encoder() -+ * hook. -+ */ -+ struct drm_encoder *encoder; -+ struct vc4_dev *vc4_dev; -+ u32 display_number; -+ u32 display_type; -+ -+ struct drm_property *broadcast_rgb_property; -+}; -+ -+static inline struct vc4_fkms_connector * -+to_vc4_fkms_connector(struct drm_connector *connector) -+{ -+ return container_of(connector, struct vc4_fkms_connector, base); -+} -+ -+/* VC4 FKMS connector state */ -+struct vc4_fkms_connector_state { -+ struct drm_connector_state base; -+ -+ int broadcast_rgb; -+}; -+ -+#define to_vc4_fkms_connector_state(x) \ -+ container_of(x, struct vc4_fkms_connector_state, base) -+ -+static u32 vc4_get_display_type(u32 display_number) -+{ -+ const u32 display_types[] = { -+ /* The firmware display (DispmanX) IDs map to specific types in -+ * a fixed manner. -+ */ -+ DRM_MODE_ENCODER_DSI, /* MAIN_LCD - DSI or DPI */ -+ DRM_MODE_ENCODER_DSI, /* AUX_LCD */ -+ DRM_MODE_ENCODER_TMDS, /* HDMI0 */ -+ DRM_MODE_ENCODER_TVDAC, /* VEC */ -+ DRM_MODE_ENCODER_NONE, /* FORCE_LCD */ -+ DRM_MODE_ENCODER_NONE, /* FORCE_TV */ -+ DRM_MODE_ENCODER_NONE, /* FORCE_OTHER */ -+ DRM_MODE_ENCODER_TMDS, /* HDMI1 */ -+ DRM_MODE_ENCODER_NONE, /* FORCE_TV2 */ -+ }; -+ return display_number > ARRAY_SIZE(display_types) - 1 ? -+ DRM_MODE_ENCODER_NONE : display_types[display_number]; -+} -+ -+/* Firmware's structure for making an FB mbox call. */ -+struct fbinfo_s { -+ u32 xres, yres, xres_virtual, yres_virtual; -+ u32 pitch, bpp; -+ u32 xoffset, yoffset; -+ u32 base; -+ u32 screen_size; -+ u16 cmap[256]; -+}; -+ -+struct vc4_fkms_plane { -+ struct drm_plane base; -+ struct fbinfo_s *fbinfo; -+ dma_addr_t fbinfo_bus_addr; -+ u32 pitch; -+ struct mailbox_set_plane mb; -+}; -+ -+static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane) -+{ -+ return (struct vc4_fkms_plane *)plane; -+} -+ -+static int vc4_plane_set_blank(struct drm_plane *plane, bool blank) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); -+ struct mailbox_set_plane blank_mb = { -+ .tag = { RPI_FIRMWARE_SET_PLANE, sizeof(struct set_plane), 0 }, -+ .plane = { -+ .display = vc4_plane->mb.plane.display, -+ .plane_id = vc4_plane->mb.plane.plane_id, -+ } -+ }; -+ static const char * const plane_types[] = { -+ "overlay", -+ "primary", -+ "cursor" -+ }; -+ int ret; -+ -+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] %s plane %s", -+ plane->base.id, plane->name, plane_types[plane->type], -+ blank ? "blank" : "unblank"); -+ -+ if (blank) -+ ret = rpi_firmware_property_list(vc4->firmware, &blank_mb, -+ sizeof(blank_mb)); -+ else -+ ret = rpi_firmware_property_list(vc4->firmware, &vc4_plane->mb, -+ sizeof(vc4_plane->mb)); -+ -+ WARN_ONCE(ret, "%s: firmware call failed. Please update your firmware", -+ __func__); -+ return ret; -+} -+ -+static void vc4_fkms_crtc_get_margins(struct drm_crtc_state *state, -+ unsigned int *left, unsigned int *right, -+ unsigned int *top, unsigned int *bottom) -+{ -+ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state); -+ struct drm_connector_state *conn_state; -+ struct drm_connector *conn; -+ int i; -+ -+ *left = vc4_state->margins.left; -+ *right = vc4_state->margins.right; -+ *top = vc4_state->margins.top; -+ *bottom = vc4_state->margins.bottom; -+ -+ /* We have to interate over all new connector states because -+ * vc4_fkms_crtc_get_margins() might be called before -+ * vc4_fkms_crtc_atomic_check() which means margins info in -+ * vc4_crtc_state might be outdated. -+ */ -+ for_each_new_connector_in_state(state->state, conn, conn_state, i) { -+ if (conn_state->crtc != state->crtc) -+ continue; -+ -+ *left = conn_state->tv.margins.left; -+ *right = conn_state->tv.margins.right; -+ *top = conn_state->tv.margins.top; -+ *bottom = conn_state->tv.margins.bottom; -+ break; -+ } -+} -+ -+static int vc4_fkms_margins_adj(struct drm_plane_state *pstate, -+ struct set_plane *plane) -+{ -+ unsigned int left, right, top, bottom; -+ int adjhdisplay, adjvdisplay; -+ struct drm_crtc_state *crtc_state; -+ -+ crtc_state = drm_atomic_get_new_crtc_state(pstate->state, -+ pstate->crtc); -+ -+ vc4_fkms_crtc_get_margins(crtc_state, &left, &right, &top, &bottom); -+ -+ if (!left && !right && !top && !bottom) -+ return 0; -+ -+ if (left + right >= crtc_state->mode.hdisplay || -+ top + bottom >= crtc_state->mode.vdisplay) -+ return -EINVAL; -+ -+ adjhdisplay = crtc_state->mode.hdisplay - (left + right); -+ plane->dst_x = DIV_ROUND_CLOSEST(plane->dst_x * adjhdisplay, -+ (int)crtc_state->mode.hdisplay); -+ plane->dst_x += left; -+ if (plane->dst_x > (int)(crtc_state->mode.hdisplay - right)) -+ plane->dst_x = crtc_state->mode.hdisplay - right; -+ -+ adjvdisplay = crtc_state->mode.vdisplay - (top + bottom); -+ plane->dst_y = DIV_ROUND_CLOSEST(plane->dst_y * adjvdisplay, -+ (int)crtc_state->mode.vdisplay); -+ plane->dst_y += top; -+ if (plane->dst_y > (int)(crtc_state->mode.vdisplay - bottom)) -+ plane->dst_y = crtc_state->mode.vdisplay - bottom; -+ -+ plane->dst_w = DIV_ROUND_CLOSEST(plane->dst_w * adjhdisplay, -+ crtc_state->mode.hdisplay); -+ plane->dst_h = DIV_ROUND_CLOSEST(plane->dst_h * adjvdisplay, -+ crtc_state->mode.vdisplay); -+ -+ if (!plane->dst_w || !plane->dst_h) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static void vc4_plane_atomic_update(struct drm_plane *plane, -+ struct drm_atomic_state *old_state) -+{ -+ struct drm_plane_state *state = plane->state; -+ -+ /* -+ * Do NOT set now, as we haven't checked if the crtc is active or not. -+ * Set from vc4_plane_set_blank instead. -+ * -+ * If the CRTC is on (or going to be on) and we're enabled, -+ * then unblank. Otherwise, stay blank until CRTC enable. -+ */ -+ if (state->crtc->state->active) -+ vc4_plane_set_blank(plane, false); -+} -+ -+static void vc4_plane_atomic_disable(struct drm_plane *plane, -+ struct drm_atomic_state *old_state) -+{ -+ struct drm_plane_state *state = plane->state; -+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); -+ -+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane disable %dx%d@%d +%d,%d\n", -+ plane->base.id, plane->name, -+ state->crtc_w, -+ state->crtc_h, -+ vc4_plane->mb.plane.vc_image_type, -+ state->crtc_x, -+ state->crtc_y); -+ vc4_plane_set_blank(plane, true); -+} -+ -+static bool plane_enabled(struct drm_plane_state *state) -+{ -+ return state->fb && state->crtc; -+} -+ -+static int vc4_plane_to_mb(struct drm_plane *plane, -+ struct mailbox_set_plane *mb, -+ struct drm_plane_state *state) -+{ -+ struct drm_framebuffer *fb = state->fb; -+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); -+ const struct drm_format_info *drm_fmt = fb->format; -+ const struct vc_image_format *vc_fmt = -+ vc4_get_vc_image_fmt(drm_fmt->format); -+ int num_planes = fb->format->num_planes; -+ unsigned int rotation; -+ -+ mb->plane.vc_image_type = vc_fmt->vc_image; -+ mb->plane.width = fb->width; -+ mb->plane.height = fb->height; -+ mb->plane.pitch = fb->pitches[0]; -+ mb->plane.src_w = state->src_w; -+ mb->plane.src_h = state->src_h; -+ mb->plane.src_x = state->src_x; -+ mb->plane.src_y = state->src_y; -+ mb->plane.dst_w = state->crtc_w; -+ mb->plane.dst_h = state->crtc_h; -+ mb->plane.dst_x = state->crtc_x; -+ mb->plane.dst_y = state->crtc_y; -+ mb->plane.alpha = state->alpha >> 8; -+ mb->plane.layer = state->normalized_zpos ? -+ state->normalized_zpos : -127; -+ mb->plane.num_planes = num_planes; -+ mb->plane.is_vu = vc_fmt->is_vu; -+ mb->plane.planes[0] = bo->paddr + fb->offsets[0]; -+ -+ rotation = drm_rotation_simplify(state->rotation, -+ DRM_MODE_ROTATE_0 | -+ DRM_MODE_REFLECT_X | -+ DRM_MODE_REFLECT_Y); -+ -+ mb->plane.transform = TRANSFORM_NO_ROTATE; -+ if (rotation & DRM_MODE_REFLECT_X) -+ mb->plane.transform |= TRANSFORM_FLIP_HRIZ; -+ if (rotation & DRM_MODE_REFLECT_Y) -+ mb->plane.transform |= TRANSFORM_FLIP_VERT; -+ -+ vc4_fkms_margins_adj(state, &mb->plane); -+ -+ if (num_planes > 1) { -+ /* Assume this must be YUV */ -+ /* Makes assumptions on the stride for the chroma planes as we -+ * can't easily plumb in non-standard pitches. -+ */ -+ mb->plane.planes[1] = bo->paddr + fb->offsets[1]; -+ if (num_planes > 2) -+ mb->plane.planes[2] = bo->paddr + fb->offsets[2]; -+ else -+ mb->plane.planes[2] = 0; -+ -+ /* Special case the YUV420 with U and V as line interleaved -+ * planes as we have special handling for that case. -+ */ -+ if (num_planes == 3 && -+ (fb->offsets[2] - fb->offsets[1]) == fb->pitches[1]) -+ mb->plane.vc_image_type = VC_IMAGE_YUV420_S; -+ -+ switch (state->color_encoding) { -+ default: -+ case DRM_COLOR_YCBCR_BT601: -+ if (state->color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) -+ mb->plane.color_encoding = -+ VC_IMAGE_YUVINFO_CSC_ITUR_BT601; -+ else -+ mb->plane.color_encoding = -+ VC_IMAGE_YUVINFO_CSC_JPEG_JFIF; -+ break; -+ case DRM_COLOR_YCBCR_BT709: -+ /* Currently no support for a full range BT709 */ -+ mb->plane.color_encoding = -+ VC_IMAGE_YUVINFO_CSC_ITUR_BT709; -+ break; -+ case DRM_COLOR_YCBCR_BT2020: -+ /* Currently no support for a full range BT2020 */ -+ mb->plane.color_encoding = -+ VC_IMAGE_YUVINFO_CSC_REC_2020; -+ break; -+ } -+ } else { -+ mb->plane.planes[1] = 0; -+ mb->plane.planes[2] = 0; -+ } -+ mb->plane.planes[3] = 0; -+ -+ switch (fourcc_mod_broadcom_mod(fb->modifier)) { -+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: -+ switch (mb->plane.vc_image_type) { -+ case VC_IMAGE_XRGB8888: -+ mb->plane.vc_image_type = VC_IMAGE_TF_RGBX32; -+ break; -+ case VC_IMAGE_ARGB8888: -+ mb->plane.vc_image_type = VC_IMAGE_TF_RGBA32; -+ break; -+ case VC_IMAGE_RGB565: -+ mb->plane.vc_image_type = VC_IMAGE_TF_RGB565; -+ break; -+ } -+ break; -+ case DRM_FORMAT_MOD_BROADCOM_SAND128: -+ switch (mb->plane.vc_image_type) { -+ case VC_IMAGE_YUV420SP: -+ mb->plane.vc_image_type = VC_IMAGE_YUV_UV; -+ break; -+ /* VC_IMAGE_YUV10COL could be included in here, but it is only -+ * valid as a SAND128 format, so the table at the top will have -+ * already set the correct format. -+ */ -+ } -+ /* Note that the column pitch is passed across in lines, not -+ * bytes. -+ */ -+ mb->plane.pitch = fourcc_mod_broadcom_param(fb->modifier); -+ break; -+ } -+ -+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] plane update %dx%d@%d +dst(%d,%d, %d,%d) +src(%d,%d, %d,%d) 0x%08x/%08x/%08x/%d, alpha %u zpos %u\n", -+ plane->base.id, plane->name, -+ mb->plane.width, -+ mb->plane.height, -+ mb->plane.vc_image_type, -+ state->crtc_x, -+ state->crtc_y, -+ state->crtc_w, -+ state->crtc_h, -+ mb->plane.src_x, -+ mb->plane.src_y, -+ mb->plane.src_w, -+ mb->plane.src_h, -+ mb->plane.planes[0], -+ mb->plane.planes[1], -+ mb->plane.planes[2], -+ fb->pitches[0], -+ state->alpha, -+ state->normalized_zpos); -+ -+ return 0; -+} -+ -+static int vc4_plane_atomic_check(struct drm_plane *plane, -+ struct drm_atomic_state *state) -+{ -+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, -+ plane); -+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); -+ -+ if (!plane_enabled(new_plane_state)) -+ return 0; -+ -+ return vc4_plane_to_mb(plane, &vc4_plane->mb, new_plane_state); -+} -+ -+/* Called during init to allocate the plane's atomic state. */ -+static void vc4_plane_reset(struct drm_plane *plane) -+{ -+ struct vc4_plane_state *vc4_state; -+ -+ WARN_ON(plane->state); -+ -+ vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL); -+ if (!vc4_state) -+ return; -+ -+ __drm_atomic_helper_plane_reset(plane, &vc4_state->base); -+} -+ -+static void vc4_plane_destroy(struct drm_plane *plane) -+{ -+ drm_plane_cleanup(plane); -+} -+ -+static bool vc4_fkms_format_mod_supported(struct drm_plane *plane, -+ uint32_t format, -+ uint64_t modifier) -+{ -+ /* Support T_TILING for RGB formats only. */ -+ switch (format) { -+ case DRM_FORMAT_XRGB8888: -+ case DRM_FORMAT_ARGB8888: -+ case DRM_FORMAT_RGB565: -+ switch (modifier) { -+ case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: -+ case DRM_FORMAT_MOD_LINEAR: -+ return true; -+ default: -+ return false; -+ } -+ case DRM_FORMAT_NV12: -+ switch (fourcc_mod_broadcom_mod(modifier)) { -+ case DRM_FORMAT_MOD_LINEAR: -+ case DRM_FORMAT_MOD_BROADCOM_SAND128: -+ return true; -+ default: -+ return false; -+ } -+ case DRM_FORMAT_P030: -+ switch (fourcc_mod_broadcom_mod(modifier)) { -+ case DRM_FORMAT_MOD_BROADCOM_SAND128: -+ return true; -+ default: -+ return false; -+ } -+ case DRM_FORMAT_NV21: -+ case DRM_FORMAT_RGB888: -+ case DRM_FORMAT_BGR888: -+ case DRM_FORMAT_YUV422: -+ case DRM_FORMAT_YUV420: -+ case DRM_FORMAT_YVU420: -+ default: -+ return (modifier == DRM_FORMAT_MOD_LINEAR); -+ } -+} -+ -+static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) -+{ -+ struct vc4_plane_state *vc4_state; -+ -+ if (WARN_ON(!plane->state)) -+ return NULL; -+ -+ vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL); -+ if (!vc4_state) -+ return NULL; -+ -+ __drm_atomic_helper_plane_duplicate_state(plane, &vc4_state->base); -+ -+ return &vc4_state->base; -+} -+ -+static const struct drm_plane_funcs vc4_plane_funcs = { -+ .update_plane = drm_atomic_helper_update_plane, -+ .disable_plane = drm_atomic_helper_disable_plane, -+ .destroy = vc4_plane_destroy, -+ .set_property = NULL, -+ .reset = vc4_plane_reset, -+ .atomic_duplicate_state = vc4_plane_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, -+ .format_mod_supported = vc4_fkms_format_mod_supported, -+}; -+ -+static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { -+ .prepare_fb = drm_gem_plane_helper_prepare_fb, -+ .cleanup_fb = NULL, -+ .atomic_check = vc4_plane_atomic_check, -+ .atomic_update = vc4_plane_atomic_update, -+ .atomic_disable = vc4_plane_atomic_disable, -+}; -+ -+static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev, -+ enum drm_plane_type type, -+ u8 display_num, -+ u8 plane_id) -+{ -+ struct drm_plane *plane = NULL; -+ struct vc4_fkms_plane *vc4_plane; -+ u32 formats[ARRAY_SIZE(vc_image_formats)]; -+ unsigned int default_zpos = 0; -+ u32 num_formats = 0; -+ int ret = 0; -+ static const uint64_t modifiers[] = { -+ DRM_FORMAT_MOD_LINEAR, -+ /* VC4_T_TILED should come after linear, because we -+ * would prefer to scan out linear (less bus traffic). -+ */ -+ DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, -+ DRM_FORMAT_MOD_BROADCOM_SAND128, -+ DRM_FORMAT_MOD_INVALID, -+ }; -+ int i; -+ -+ vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane), -+ GFP_KERNEL); -+ if (!vc4_plane) { -+ ret = -ENOMEM; -+ goto fail; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(vc_image_formats); i++) -+ formats[num_formats++] = vc_image_formats[i].drm; -+ -+ plane = &vc4_plane->base; -+ ret = drm_universal_plane_init(dev, plane, 0, -+ &vc4_plane_funcs, -+ formats, num_formats, modifiers, -+ type, NULL); -+ -+ /* FIXME: Do we need to be checking return values from all these calls? -+ */ -+ drm_plane_helper_add(plane, &vc4_plane_helper_funcs); -+ -+ drm_plane_create_alpha_property(plane); -+ drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, -+ DRM_MODE_ROTATE_0 | -+ DRM_MODE_ROTATE_180 | -+ DRM_MODE_REFLECT_X | -+ DRM_MODE_REFLECT_Y); -+ drm_plane_create_color_properties(plane, -+ BIT(DRM_COLOR_YCBCR_BT601) | -+ BIT(DRM_COLOR_YCBCR_BT709) | -+ BIT(DRM_COLOR_YCBCR_BT2020), -+ BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | -+ BIT(DRM_COLOR_YCBCR_FULL_RANGE), -+ DRM_COLOR_YCBCR_BT709, -+ DRM_COLOR_YCBCR_LIMITED_RANGE); -+ -+ /* -+ * Default frame buffer setup is with FB on -127, and raspistill etc -+ * tend to drop overlays on layer 2. Cursor plane was on layer +127. -+ * -+ * For F-KMS the mailbox call allows for a s8. -+ * Remap zpos 0 to -127 for the background layer, but leave all the -+ * other layers as requested by KMS. -+ */ -+ switch (type) { -+ default: -+ case DRM_PLANE_TYPE_PRIMARY: -+ default_zpos = 0; -+ break; -+ case DRM_PLANE_TYPE_OVERLAY: -+ default_zpos = 1; -+ break; -+ case DRM_PLANE_TYPE_CURSOR: -+ default_zpos = 2; -+ break; -+ } -+ drm_plane_create_zpos_property(plane, default_zpos, 0, 127); -+ -+ /* Prepare the static elements of the mailbox structure */ -+ vc4_plane->mb.tag.tag = RPI_FIRMWARE_SET_PLANE; -+ vc4_plane->mb.tag.buf_size = sizeof(struct set_plane); -+ vc4_plane->mb.tag.req_resp_size = 0; -+ vc4_plane->mb.plane.display = display_num; -+ vc4_plane->mb.plane.plane_id = plane_id; -+ vc4_plane->mb.plane.layer = default_zpos ? default_zpos : -127; -+ -+ return plane; -+fail: -+ if (plane) -+ vc4_plane_destroy(plane); -+ -+ return ERR_PTR(ret); -+} -+ -+static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ struct drm_display_mode *mode = &crtc->state->adjusted_mode; -+ struct vc4_fkms_encoder *vc4_encoder = -+ to_vc4_fkms_encoder(vc4_crtc->encoder); -+ struct mailbox_set_mode mb = { -+ .tag1 = { RPI_FIRMWARE_SET_TIMING, -+ sizeof(struct set_timings), 0}, -+ }; -+ union hdmi_infoframe frame; -+ int ret; -+ -+ ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, vc4_crtc->connector, mode); -+ if (ret < 0) { -+ DRM_ERROR("couldn't fill AVI infoframe\n"); -+ return; -+ } -+ -+ DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u, flags 0x%04x\n", -+ vc4_crtc->display_number, mode->name, mode->clock, -+ mode->hdisplay, mode->hsync_start, mode->hsync_end, -+ mode->htotal, mode->hskew, mode->vdisplay, -+ mode->vsync_start, mode->vsync_end, mode->vtotal, -+ mode->vscan, drm_mode_vrefresh(mode), -+ mode->picture_aspect_ratio, mode->flags); -+ mb.timings.display = vc4_crtc->display_number; -+ -+ mb.timings.clock = mode->clock; -+ mb.timings.hdisplay = mode->hdisplay; -+ mb.timings.hsync_start = mode->hsync_start; -+ mb.timings.hsync_end = mode->hsync_end; -+ mb.timings.htotal = mode->htotal; -+ mb.timings.hskew = mode->hskew; -+ mb.timings.vdisplay = mode->vdisplay; -+ mb.timings.vsync_start = mode->vsync_start; -+ mb.timings.vsync_end = mode->vsync_end; -+ mb.timings.vtotal = mode->vtotal; -+ mb.timings.vscan = mode->vscan; -+ mb.timings.vrefresh = drm_mode_vrefresh(mode); -+ mb.timings.flags = 0; -+ if (mode->flags & DRM_MODE_FLAG_PHSYNC) -+ mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS; -+ if (mode->flags & DRM_MODE_FLAG_PVSYNC) -+ mb.timings.flags |= TIMINGS_FLAGS_V_SYNC_POS; -+ -+ switch (frame.avi.picture_aspect) { -+ default: -+ case HDMI_PICTURE_ASPECT_NONE: -+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_NONE; -+ break; -+ case HDMI_PICTURE_ASPECT_4_3: -+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_4_3; -+ break; -+ case HDMI_PICTURE_ASPECT_16_9: -+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_16_9; -+ break; -+ case HDMI_PICTURE_ASPECT_64_27: -+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_64_27; -+ break; -+ case HDMI_PICTURE_ASPECT_256_135: -+ mb.timings.flags |= TIMINGS_FLAGS_ASPECT_256_135; -+ break; -+ } -+ -+ if (mode->flags & DRM_MODE_FLAG_INTERLACE) -+ mb.timings.flags |= TIMINGS_FLAGS_INTERLACE; -+ if (mode->flags & DRM_MODE_FLAG_DBLCLK) -+ mb.timings.flags |= TIMINGS_FLAGS_DBL_CLK; -+ -+ mb.timings.video_id_code = frame.avi.video_code; -+ -+ if (!vc4_encoder->hdmi_monitor) { -+ mb.timings.flags |= TIMINGS_FLAGS_DVI; -+ } else { -+ struct vc4_fkms_connector_state *conn_state = -+ to_vc4_fkms_connector_state(vc4_crtc->connector->state); -+ -+ if (conn_state->broadcast_rgb == VC4_BROADCAST_RGB_AUTO) { -+ /* See CEA-861-E - 5.1 Default Encoding Parameters */ -+ if (drm_default_rgb_quant_range(mode) == -+ HDMI_QUANTIZATION_RANGE_LIMITED) -+ mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED; -+ } else { -+ if (conn_state->broadcast_rgb == -+ VC4_BROADCAST_RGB_LIMITED) -+ mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED; -+ -+ /* If not using the default range, then do not provide -+ * a VIC as the HDMI spec requires that we do not -+ * signal the opposite of the defined range in the AVI -+ * infoframe. -+ */ -+ if (!!(mb.timings.flags & TIMINGS_FLAGS_RGB_LIMITED) != -+ (drm_default_rgb_quant_range(mode) == -+ HDMI_QUANTIZATION_RANGE_LIMITED)) -+ mb.timings.video_id_code = 0; -+ } -+ } -+ -+ /* -+ * FIXME: To implement -+ * switch(mode->flag & DRM_MODE_FLAG_3D_MASK) { -+ * case DRM_MODE_FLAG_3D_NONE: -+ * case DRM_MODE_FLAG_3D_FRAME_PACKING: -+ * case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE: -+ * case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE: -+ * case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL: -+ * case DRM_MODE_FLAG_3D_L_DEPTH: -+ * case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH: -+ * case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM: -+ * case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF: -+ * } -+ */ -+ -+ ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb)); -+} -+ -+static void vc4_crtc_disable(struct drm_crtc *crtc, -+ struct drm_atomic_state *state) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct drm_plane *plane; -+ -+ DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n", -+ crtc->base.id); -+ drm_crtc_vblank_off(crtc); -+ -+ /* Always turn the planes off on CRTC disable. In DRM, planes -+ * are enabled/disabled through the update/disable hooks -+ * above, and the CRTC enable/disable independently controls -+ * whether anything scans out at all, but the firmware doesn't -+ * give us a CRTC-level control for that. -+ */ -+ -+ drm_atomic_crtc_for_each_plane(plane, crtc) -+ vc4_plane_atomic_disable(plane, state); -+ -+ /* -+ * Make sure we issue a vblank event after disabling the CRTC if -+ * someone was waiting it. -+ */ -+ if (crtc->state->event) { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ drm_crtc_send_vblank_event(crtc, crtc->state->event); -+ crtc->state->event = NULL; -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ } -+} -+ -+static void vc4_crtc_consume_event(struct drm_crtc *crtc) -+{ -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ struct drm_device *dev = crtc->dev; -+ unsigned long flags; -+ -+ if (!crtc->state->event) -+ return; -+ -+ crtc->state->event->pipe = drm_crtc_index(crtc); -+ -+ WARN_ON(drm_crtc_vblank_get(crtc) != 0); -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ vc4_crtc->event = crtc->state->event; -+ crtc->state->event = NULL; -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+} -+ -+static void vc4_crtc_enable(struct drm_crtc *crtc, -+ struct drm_atomic_state *state) -+{ -+ struct drm_plane *plane; -+ -+ DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n", -+ crtc->base.id); -+ drm_crtc_vblank_on(crtc); -+ vc4_crtc_consume_event(crtc); -+ -+ /* Unblank the planes (if they're supposed to be displayed). */ -+ drm_atomic_crtc_for_each_plane(plane, crtc) -+ if (plane->state->fb) -+ vc4_plane_set_blank(plane, plane->state->visible); -+} -+ -+static enum drm_mode_status -+vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) -+{ -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ struct drm_device *dev = crtc->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ struct vc4_fkms *fkms = vc4->fkms; -+ -+ /* Do not allow doublescan modes from user space */ -+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { -+ DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n", -+ crtc->base.id); -+ return MODE_NO_DBLESCAN; -+ } -+ -+ /* Disable refresh rates > defined threshold (default 85Hz) as limited -+ * gain from them -+ */ -+ if (drm_mode_vrefresh(mode) > fkms_max_refresh_rate) -+ return MODE_BAD_VVALUE; -+ -+ /* Limit the pixel clock based on the HDMI clock limits from the -+ * firmware -+ */ -+ switch (vc4_crtc->display_number) { -+ case 2: /* HDMI0 */ -+ if (fkms->cfg.max_pixel_clock[0] && -+ mode->clock > fkms->cfg.max_pixel_clock[0]) -+ return MODE_CLOCK_HIGH; -+ break; -+ case 7: /* HDMI1 */ -+ if (fkms->cfg.max_pixel_clock[1] && -+ mode->clock > fkms->cfg.max_pixel_clock[1]) -+ return MODE_CLOCK_HIGH; -+ break; -+ } -+ -+ /* Pi4 can't generate odd horizontal timings on HDMI, so reject modes -+ * that would set them. -+ */ -+ if (fkms->bcm2711 && -+ (vc4_crtc->display_number == 2 || vc4_crtc->display_number == 7) && -+ !(mode->flags & DRM_MODE_FLAG_DBLCLK) && -+ ((mode->hdisplay | /* active */ -+ (mode->hsync_start - mode->hdisplay) | /* front porch */ -+ (mode->hsync_end - mode->hsync_start) | /* sync pulse */ -+ (mode->htotal - mode->hsync_end)) & 1)) /* back porch */ { -+ DRM_DEBUG_KMS("[CRTC:%d] Odd timing rejected %u %u %u %u.\n", -+ crtc->base.id, mode->hdisplay, mode->hsync_start, -+ mode->hsync_end, mode->htotal); -+ return MODE_H_ILLEGAL; -+ } -+ -+ return MODE_OK; -+} -+ -+static int vc4_crtc_atomic_check(struct drm_crtc *crtc, -+ struct drm_atomic_state *state) -+{ -+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, -+ crtc); -+ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); -+ struct drm_connector *conn; -+ struct drm_connector_state *conn_state; -+ int i; -+ -+ DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n", crtc->base.id); -+ -+ for_each_new_connector_in_state(crtc_state->state, conn, conn_state, i) { -+ if (conn_state->crtc != crtc) -+ continue; -+ -+ vc4_state->margins.left = conn_state->tv.margins.left; -+ vc4_state->margins.right = conn_state->tv.margins.right; -+ vc4_state->margins.top = conn_state->tv.margins.top; -+ vc4_state->margins.bottom = conn_state->tv.margins.bottom; -+ break; -+ } -+ return 0; -+} -+ -+static void vc4_crtc_atomic_flush(struct drm_crtc *crtc, -+ struct drm_atomic_state *state) -+{ -+ struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, -+ crtc); -+ -+ DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n", -+ crtc->base.id); -+ if (crtc->state->active && old_state->active && crtc->state->event) -+ vc4_crtc_consume_event(crtc); -+} -+ -+static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) -+{ -+ struct drm_crtc *crtc = &vc4_crtc->base; -+ struct drm_device *dev = crtc->dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ if (vc4_crtc->event) { -+ drm_crtc_send_vblank_event(crtc, vc4_crtc->event); -+ vc4_crtc->event = NULL; -+ drm_crtc_vblank_put(crtc); -+ } -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+} -+ -+static irqreturn_t vc4_crtc_irq_handler(int irq, void *data) -+{ -+ struct vc4_crtc **crtc_list = data; -+ int i; -+ u32 stat = readl(crtc_list[0]->regs + SMICS); -+ irqreturn_t ret = IRQ_NONE; -+ u32 chan; -+ -+ if (stat & SMICS_INTERRUPTS) { -+ writel(0, crtc_list[0]->regs + SMICS); -+ -+ chan = readl(crtc_list[0]->regs + SMIDSW0); -+ -+ if ((chan & 0xFFFF0000) != SMI_NEW) { -+ /* Older firmware. Treat the one interrupt as vblank/ -+ * complete for all crtcs. -+ */ -+ for (i = 0; crtc_list[i]; i++) { -+ if (crtc_list[i]->vblank_enabled) -+ drm_crtc_handle_vblank(&crtc_list[i]->base); -+ vc4_crtc_handle_page_flip(crtc_list[i]); -+ } -+ } else { -+ if (chan & 1) { -+ writel(SMI_NEW, crtc_list[0]->regs + SMIDSW0); -+ if (crtc_list[0]->vblank_enabled) -+ drm_crtc_handle_vblank(&crtc_list[0]->base); -+ vc4_crtc_handle_page_flip(crtc_list[0]); -+ } -+ -+ if (crtc_list[1]) { -+ /* Check for the secondary display too */ -+ chan = readl(crtc_list[0]->regs + SMIDSW1); -+ -+ if (chan & 1) { -+ writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1); -+ -+ if (crtc_list[1]->vblank_enabled) -+ drm_crtc_handle_vblank(&crtc_list[1]->base); -+ vc4_crtc_handle_page_flip(crtc_list[1]); -+ } -+ } -+ } -+ -+ ret = IRQ_HANDLED; -+ } -+ -+ return ret; -+} -+ -+static int vc4_fkms_page_flip(struct drm_crtc *crtc, -+ struct drm_framebuffer *fb, -+ struct drm_pending_vblank_event *event, -+ uint32_t flags, -+ struct drm_modeset_acquire_ctx *ctx) -+{ -+ if (flags & DRM_MODE_PAGE_FLIP_ASYNC) { -+ DRM_ERROR("Async flips aren't allowed\n"); -+ return -EINVAL; -+ } -+ -+ return drm_atomic_helper_page_flip(crtc, fb, event, flags, ctx); -+} -+ -+static struct drm_crtc_state * -+vc4_fkms_crtc_duplicate_state(struct drm_crtc *crtc) -+{ -+ struct vc4_crtc_state *vc4_state, *old_vc4_state; -+ -+ vc4_state = kzalloc(sizeof(*vc4_state), GFP_KERNEL); -+ if (!vc4_state) -+ return NULL; -+ -+ old_vc4_state = to_vc4_crtc_state(crtc->state); -+ vc4_state->margins = old_vc4_state->margins; -+ -+ __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base); -+ return &vc4_state->base; -+} -+ -+static void -+vc4_fkms_crtc_reset(struct drm_crtc *crtc) -+{ -+ if (crtc->state) -+ __drm_atomic_helper_crtc_destroy_state(crtc->state); -+ -+ crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); -+ if (crtc->state) -+ crtc->state->crtc = crtc; -+} -+ -+static int vc4_fkms_enable_vblank(struct drm_crtc *crtc) -+{ -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ -+ DRM_DEBUG_KMS("[CRTC:%d] enable_vblank.\n", -+ crtc->base.id); -+ vc4_crtc->vblank_enabled = true; -+ -+ return 0; -+} -+ -+static void vc4_fkms_disable_vblank(struct drm_crtc *crtc) -+{ -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ -+ DRM_DEBUG_KMS("[CRTC:%d] disable_vblank.\n", -+ crtc->base.id); -+ vc4_crtc->vblank_enabled = false; -+} -+ -+static const struct drm_crtc_funcs vc4_crtc_funcs = { -+ .set_config = drm_atomic_helper_set_config, -+ .destroy = drm_crtc_cleanup, -+ .page_flip = vc4_fkms_page_flip, -+ .set_property = NULL, -+ .cursor_set = NULL, /* handled by drm_mode_cursor_universal */ -+ .cursor_move = NULL, /* handled by drm_mode_cursor_universal */ -+ .reset = vc4_fkms_crtc_reset, -+ .atomic_duplicate_state = vc4_fkms_crtc_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, -+ .enable_vblank = vc4_fkms_enable_vblank, -+ .disable_vblank = vc4_fkms_disable_vblank, -+}; -+ -+static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { -+ .mode_set_nofb = vc4_crtc_mode_set_nofb, -+ .mode_valid = vc4_crtc_mode_valid, -+ .atomic_check = vc4_crtc_atomic_check, -+ .atomic_flush = vc4_crtc_atomic_flush, -+ .atomic_enable = vc4_crtc_enable, -+ .atomic_disable = vc4_crtc_disable, -+}; -+ -+static const struct of_device_id vc4_firmware_kms_dt_match[] = { -+ { .compatible = "raspberrypi,rpi-firmware-kms" }, -+ { .compatible = "raspberrypi,rpi-firmware-kms-2711", -+ .data = (void *)1 }, -+ {} -+}; -+ -+static enum drm_connector_status -+vc4_fkms_connector_detect(struct drm_connector *connector, bool force) -+{ -+ DRM_DEBUG_KMS("connector detect.\n"); -+ return connector_status_connected; -+} -+ -+/* Queries the firmware to populate a drm_mode structure for this display */ -+static int vc4_fkms_get_fw_mode(struct vc4_fkms_connector *fkms_connector, -+ struct drm_display_mode *mode) -+{ -+ struct vc4_dev *vc4 = fkms_connector->vc4_dev; -+ struct set_timings timings = { 0 }; -+ int ret; -+ -+ timings.display = fkms_connector->display_number; -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_GET_DISPLAY_TIMING, &timings, -+ sizeof(timings)); -+ if (ret || !timings.clock) -+ /* No mode returned - abort */ -+ return -1; -+ -+ /* Equivalent to DRM_MODE macro. */ -+ memset(mode, 0, sizeof(*mode)); -+ strncpy(mode->name, "FIXED_MODE", sizeof(mode->name)); -+ mode->status = 0; -+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; -+ mode->clock = timings.clock; -+ mode->hdisplay = timings.hdisplay; -+ mode->hsync_start = timings.hsync_start; -+ mode->hsync_end = timings.hsync_end; -+ mode->htotal = timings.htotal; -+ mode->hskew = 0; -+ mode->vdisplay = timings.vdisplay; -+ mode->vsync_start = timings.vsync_start; -+ mode->vsync_end = timings.vsync_end; -+ mode->vtotal = timings.vtotal; -+ mode->vscan = timings.vscan; -+ -+ if (timings.flags & TIMINGS_FLAGS_H_SYNC_POS) -+ mode->flags |= DRM_MODE_FLAG_PHSYNC; -+ else -+ mode->flags |= DRM_MODE_FLAG_NHSYNC; -+ -+ if (timings.flags & TIMINGS_FLAGS_V_SYNC_POS) -+ mode->flags |= DRM_MODE_FLAG_PVSYNC; -+ else -+ mode->flags |= DRM_MODE_FLAG_NVSYNC; -+ -+ if (timings.flags & TIMINGS_FLAGS_INTERLACE) -+ mode->flags |= DRM_MODE_FLAG_INTERLACE; -+ -+ return 0; -+} -+ -+static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block, -+ size_t len) -+{ -+ struct vc4_fkms_connector *fkms_connector = -+ (struct vc4_fkms_connector *)data; -+ struct vc4_dev *vc4 = fkms_connector->vc4_dev; -+ struct mailbox_get_edid mb = { -+ .tag1 = { RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY, -+ 128 + 8, 0 }, -+ .block = block, -+ .display_number = fkms_connector->display_number, -+ }; -+ int ret = 0; -+ -+ ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb)); -+ -+ if (!ret) -+ memcpy(buf, mb.edid, len); -+ -+ return ret; -+} -+ -+static int vc4_fkms_connector_get_modes(struct drm_connector *connector) -+{ -+ struct vc4_fkms_connector *fkms_connector = -+ to_vc4_fkms_connector(connector); -+ struct drm_encoder *encoder = fkms_connector->encoder; -+ struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder); -+ struct drm_display_mode fw_mode; -+ struct drm_display_mode *mode; -+ struct edid *edid; -+ int num_modes; -+ -+ if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode)) { -+ drm_mode_debug_printmodeline(&fw_mode); -+ mode = drm_mode_duplicate(connector->dev, -+ &fw_mode); -+ drm_mode_probed_add(connector, mode); -+ num_modes = 1; /* 1 mode */ -+ } else { -+ edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block, -+ fkms_connector); -+ -+ /* FIXME: Can we do CEC? -+ * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid); -+ * if (!edid) -+ * return -ENODEV; -+ */ -+ -+ vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); -+ -+ drm_connector_update_edid_property(connector, edid); -+ num_modes = drm_add_edid_modes(connector, edid); -+ kfree(edid); -+ } -+ -+ return num_modes; -+} -+ -+/* This is the DSI panel resolution. Use this as a default should the firmware -+ * not respond to our request for the timings. -+ */ -+static const struct drm_display_mode lcd_mode = { -+ DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, -+ 25979400 / 1000, -+ 800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0, -+ 480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0, -+ 0) -+}; -+ -+static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector) -+{ -+ struct vc4_fkms_connector *fkms_connector = -+ to_vc4_fkms_connector(connector); -+ struct drm_display_mode *mode; -+ struct drm_display_mode fw_mode; -+ -+ if (!vc4_fkms_get_fw_mode(fkms_connector, &fw_mode) && fw_mode.clock) -+ mode = drm_mode_duplicate(connector->dev, -+ &fw_mode); -+ else -+ mode = drm_mode_duplicate(connector->dev, -+ &lcd_mode); -+ -+ if (!mode) { -+ DRM_ERROR("Failed to create a new display mode\n"); -+ return -ENOMEM; -+ } -+ -+ drm_mode_probed_add(connector, mode); -+ -+ /* We have one mode */ -+ return 1; -+} -+ -+static struct drm_encoder * -+vc4_fkms_connector_best_encoder(struct drm_connector *connector) -+{ -+ struct vc4_fkms_connector *fkms_connector = -+ to_vc4_fkms_connector(connector); -+ DRM_DEBUG_KMS("best_connector.\n"); -+ return fkms_connector->encoder; -+} -+ -+static void vc4_fkms_connector_destroy(struct drm_connector *connector) -+{ -+ DRM_DEBUG_KMS("[CONNECTOR:%d] destroy.\n", -+ connector->base.id); -+ drm_connector_unregister(connector); -+ drm_connector_cleanup(connector); -+} -+ -+/** -+ * vc4_connector_duplicate_state - duplicate connector state -+ * @connector: digital connector -+ * -+ * Allocates and returns a copy of the connector state (both common and -+ * digital connector specific) for the specified connector. -+ * -+ * Returns: The newly allocated connector state, or NULL on failure. -+ */ -+struct drm_connector_state * -+vc4_connector_duplicate_state(struct drm_connector *connector) -+{ -+ struct vc4_fkms_connector_state *state; -+ -+ state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ -+ __drm_atomic_helper_connector_duplicate_state(connector, &state->base); -+ return &state->base; -+} -+ -+/** -+ * vc4_connector_atomic_get_property - hook for connector->atomic_get_property. -+ * @connector: Connector to get the property for. -+ * @state: Connector state to retrieve the property from. -+ * @property: Property to retrieve. -+ * @val: Return value for the property. -+ * -+ * Returns the atomic property value for a digital connector. -+ */ -+int vc4_connector_atomic_get_property(struct drm_connector *connector, -+ const struct drm_connector_state *state, -+ struct drm_property *property, -+ uint64_t *val) -+{ -+ struct vc4_fkms_connector *fkms_connector = -+ to_vc4_fkms_connector(connector); -+ struct vc4_fkms_connector_state *vc4_conn_state = -+ to_vc4_fkms_connector_state(state); -+ -+ if (property == fkms_connector->broadcast_rgb_property) { -+ *val = vc4_conn_state->broadcast_rgb; -+ } else { -+ DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n", -+ property->base.id, property->name); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * vc4_connector_atomic_set_property - hook for connector->atomic_set_property. -+ * @connector: Connector to set the property for. -+ * @state: Connector state to set the property on. -+ * @property: Property to set. -+ * @val: New value for the property. -+ * -+ * Sets the atomic property value for a digital connector. -+ */ -+int vc4_connector_atomic_set_property(struct drm_connector *connector, -+ struct drm_connector_state *state, -+ struct drm_property *property, -+ uint64_t val) -+{ -+ struct vc4_fkms_connector *fkms_connector = -+ to_vc4_fkms_connector(connector); -+ struct vc4_fkms_connector_state *vc4_conn_state = -+ to_vc4_fkms_connector_state(state); -+ -+ if (property == fkms_connector->broadcast_rgb_property) { -+ vc4_conn_state->broadcast_rgb = val; -+ return 0; -+ } -+ -+ DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n", -+ property->base.id, property->name); -+ return -EINVAL; -+} -+ -+int vc4_connector_atomic_check(struct drm_connector *connector, -+ struct drm_atomic_state *state) -+{ -+ struct drm_connector_state *old_state = -+ drm_atomic_get_old_connector_state(state, connector); -+ struct vc4_fkms_connector_state *vc4_old_state = -+ to_vc4_fkms_connector_state(old_state); -+ struct drm_connector_state *new_state = -+ drm_atomic_get_new_connector_state(state, connector); -+ struct vc4_fkms_connector_state *vc4_new_state = -+ to_vc4_fkms_connector_state(new_state); -+ struct drm_crtc *crtc = new_state->crtc; -+ -+ if (!crtc) -+ return 0; -+ -+ if (vc4_old_state->broadcast_rgb != vc4_new_state->broadcast_rgb) { -+ struct drm_crtc_state *crtc_state; -+ -+ crtc_state = drm_atomic_get_crtc_state(state, crtc); -+ if (IS_ERR(crtc_state)) -+ return PTR_ERR(crtc_state); -+ -+ crtc_state->mode_changed = true; -+ } -+ return 0; -+} -+ -+static void vc4_hdmi_connector_reset(struct drm_connector *connector) -+{ -+ drm_atomic_helper_connector_reset(connector); -+ drm_atomic_helper_connector_tv_reset(connector); -+} -+ -+static const struct drm_connector_funcs vc4_fkms_connector_funcs = { -+ .detect = vc4_fkms_connector_detect, -+ .fill_modes = drm_helper_probe_single_connector_modes, -+ .destroy = vc4_fkms_connector_destroy, -+ .reset = vc4_hdmi_connector_reset, -+ .atomic_duplicate_state = vc4_connector_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -+ .atomic_get_property = vc4_connector_atomic_get_property, -+ .atomic_set_property = vc4_connector_atomic_set_property, -+}; -+ -+static const struct drm_connector_helper_funcs vc4_fkms_connector_helper_funcs = { -+ .get_modes = vc4_fkms_connector_get_modes, -+ .best_encoder = vc4_fkms_connector_best_encoder, -+ .atomic_check = vc4_connector_atomic_check, -+}; -+ -+static const struct drm_connector_helper_funcs vc4_fkms_lcd_conn_helper_funcs = { -+ .get_modes = vc4_fkms_lcd_connector_get_modes, -+ .best_encoder = vc4_fkms_connector_best_encoder, -+}; -+ -+static const struct drm_prop_enum_list broadcast_rgb_names[] = { -+ { VC4_BROADCAST_RGB_AUTO, "Automatic" }, -+ { VC4_BROADCAST_RGB_FULL, "Full" }, -+ { VC4_BROADCAST_RGB_LIMITED, "Limited 16:235" }, -+}; -+ -+static void -+vc4_attach_broadcast_rgb_property(struct vc4_fkms_connector *fkms_connector) -+{ -+ struct drm_device *dev = fkms_connector->base.dev; -+ struct drm_property *prop; -+ -+ prop = fkms_connector->broadcast_rgb_property; -+ if (!prop) { -+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, -+ "Broadcast RGB", -+ broadcast_rgb_names, -+ ARRAY_SIZE(broadcast_rgb_names)); -+ if (!prop) -+ return; -+ -+ fkms_connector->broadcast_rgb_property = prop; -+ } -+ -+ drm_object_attach_property(&fkms_connector->base.base, prop, 0); -+} -+ -+static struct drm_connector * -+vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder, -+ u32 display_num) -+{ -+ struct drm_connector *connector = NULL; -+ struct vc4_fkms_connector *fkms_connector; -+ struct vc4_fkms_connector_state *conn_state = NULL; -+ struct vc4_dev *vc4_dev = to_vc4_dev(dev); -+ int ret = 0; -+ -+ DRM_DEBUG_KMS("connector_init, display_num %u\n", display_num); -+ -+ fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector), -+ GFP_KERNEL); -+ if (!fkms_connector) -+ return ERR_PTR(-ENOMEM); -+ -+ /* -+ * Allocate enough memory to hold vc4_fkms_connector_state, -+ */ -+ conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL); -+ if (!conn_state) { -+ kfree(fkms_connector); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ connector = &fkms_connector->base; -+ -+ fkms_connector->encoder = encoder; -+ fkms_connector->display_number = display_num; -+ fkms_connector->display_type = vc4_get_display_type(display_num); -+ fkms_connector->vc4_dev = vc4_dev; -+ -+ __drm_atomic_helper_connector_reset(connector, -+ &conn_state->base); -+ -+ if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) { -+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs, -+ DRM_MODE_CONNECTOR_DSI); -+ drm_connector_helper_add(connector, -+ &vc4_fkms_lcd_conn_helper_funcs); -+ connector->interlace_allowed = 0; -+ } else if (fkms_connector->display_type == DRM_MODE_ENCODER_TVDAC) { -+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs, -+ DRM_MODE_CONNECTOR_Composite); -+ drm_connector_helper_add(connector, -+ &vc4_fkms_lcd_conn_helper_funcs); -+ connector->interlace_allowed = 1; -+ } else { -+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs, -+ DRM_MODE_CONNECTOR_HDMIA); -+ drm_connector_helper_add(connector, -+ &vc4_fkms_connector_helper_funcs); -+ connector->interlace_allowed = 1; -+ } -+ -+ ret = drm_mode_create_tv_margin_properties(dev); -+ if (ret) -+ goto fail; -+ -+ drm_connector_attach_tv_margin_properties(connector); -+ -+ connector->polled = (DRM_CONNECTOR_POLL_CONNECT | -+ DRM_CONNECTOR_POLL_DISCONNECT); -+ -+ connector->doublescan_allowed = 0; -+ -+ vc4_attach_broadcast_rgb_property(fkms_connector); -+ -+ drm_connector_attach_encoder(connector, encoder); -+ -+ return connector; -+ -+ fail: -+ if (connector) -+ vc4_fkms_connector_destroy(connector); -+ -+ return ERR_PTR(ret); -+} -+ -+static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder) -+{ -+ DRM_DEBUG_KMS("Encoder_destroy\n"); -+ drm_encoder_cleanup(encoder); -+} -+ -+static const struct drm_encoder_funcs vc4_fkms_encoder_funcs = { -+ .destroy = vc4_fkms_encoder_destroy, -+}; -+ -+static void vc4_fkms_display_power(struct drm_encoder *encoder, bool power) -+{ -+ struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder); -+ struct vc4_dev *vc4 = to_vc4_dev(encoder->dev); -+ -+ struct mailbox_display_pwr pwr = { -+ .tag1 = {RPI_FIRMWARE_SET_DISPLAY_POWER, 8, 0, }, -+ .display = vc4_encoder->display_num, -+ .state = power ? 1 : 0, -+ }; -+ -+ rpi_firmware_property_list(vc4->firmware, &pwr, sizeof(pwr)); -+} -+ -+static void vc4_fkms_encoder_enable(struct drm_encoder *encoder) -+{ -+ vc4_fkms_display_power(encoder, true); -+ DRM_DEBUG_KMS("Encoder_enable\n"); -+} -+ -+static void vc4_fkms_encoder_disable(struct drm_encoder *encoder) -+{ -+ vc4_fkms_display_power(encoder, false); -+ DRM_DEBUG_KMS("Encoder_disable\n"); -+} -+ -+static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = { -+ .enable = vc4_fkms_encoder_enable, -+ .disable = vc4_fkms_encoder_disable, -+}; -+ -+static int vc4_fkms_create_screen(struct device *dev, struct drm_device *drm, -+ int display_idx, int display_ref, -+ struct vc4_crtc **ret_crtc) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(drm); -+ struct vc4_crtc *vc4_crtc; -+ struct vc4_fkms_encoder *vc4_encoder; -+ struct drm_crtc *crtc; -+ struct drm_plane *destroy_plane, *temp; -+ struct mailbox_blank_display blank = { -+ .tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, }, -+ .display = display_idx, -+ .tag2 = { RPI_FIRMWARE_FRAMEBUFFER_BLANK, 4, 0, }, -+ .blank = 1, -+ }; -+ struct drm_plane *planes[PLANES_PER_CRTC]; -+ int ret, i; -+ -+ vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL); -+ if (!vc4_crtc) -+ return -ENOMEM; -+ crtc = &vc4_crtc->base; -+ -+ vc4_crtc->display_number = display_ref; -+ vc4_crtc->display_type = vc4_get_display_type(display_ref); -+ -+ /* Blank the firmware provided framebuffer */ -+ rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank)); -+ -+ for (i = 0; i < PLANES_PER_CRTC; i++) { -+ planes[i] = vc4_fkms_plane_init(drm, -+ (i == 0) ? -+ DRM_PLANE_TYPE_PRIMARY : -+ (i == PLANES_PER_CRTC - 1) ? -+ DRM_PLANE_TYPE_CURSOR : -+ DRM_PLANE_TYPE_OVERLAY, -+ display_ref, -+ i + (display_idx * PLANES_PER_CRTC) -+ ); -+ if (IS_ERR(planes[i])) { -+ dev_err(dev, "failed to construct plane %u\n", i); -+ ret = PTR_ERR(planes[i]); -+ goto err; -+ } -+ } -+ -+ drm_crtc_init_with_planes(drm, crtc, planes[0], -+ planes[PLANES_PER_CRTC - 1], &vc4_crtc_funcs, -+ NULL); -+ drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs); -+ -+ /* Update the possible_crtcs mask for the overlay plane(s) */ -+ for (i = 1; i < (PLANES_PER_CRTC - 1); i++) -+ planes[i]->possible_crtcs = drm_crtc_mask(crtc); -+ -+ vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL); -+ if (!vc4_encoder) -+ return -ENOMEM; -+ vc4_crtc->encoder = &vc4_encoder->base; -+ -+ vc4_encoder->display_num = display_ref; -+ vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc); -+ -+ drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs, -+ vc4_crtc->display_type, NULL); -+ drm_encoder_helper_add(&vc4_encoder->base, -+ &vc4_fkms_encoder_helper_funcs); -+ -+ vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base, -+ display_ref); -+ if (IS_ERR(vc4_crtc->connector)) { -+ ret = PTR_ERR(vc4_crtc->connector); -+ goto err_destroy_encoder; -+ } -+ -+ *ret_crtc = vc4_crtc; -+ -+ return 0; -+ -+err_destroy_encoder: -+ vc4_fkms_encoder_destroy(vc4_crtc->encoder); -+ list_for_each_entry_safe(destroy_plane, temp, -+ &drm->mode_config.plane_list, head) { -+ if (destroy_plane->possible_crtcs == 1 << drm_crtc_index(crtc)) -+ destroy_plane->funcs->destroy(destroy_plane); -+ } -+err: -+ return ret; -+} -+ -+static int vc4_fkms_bind(struct device *dev, struct device *master, void *data) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct drm_device *drm = dev_get_drvdata(master); -+ struct vc4_dev *vc4 = to_vc4_dev(drm); -+ struct device_node *firmware_node; -+ const struct of_device_id *match; -+ struct vc4_crtc **crtc_list; -+ u32 num_displays, display_num; -+ struct vc4_fkms *fkms; -+ int ret; -+ u32 display_id; -+ -+ vc4->firmware_kms = true; -+ -+ fkms = devm_kzalloc(dev, sizeof(*fkms), GFP_KERNEL); -+ if (!fkms) -+ return -ENOMEM; -+ -+ match = of_match_device(vc4_firmware_kms_dt_match, dev); -+ if (!match) -+ return -ENODEV; -+ if (match->data) -+ fkms->bcm2711 = true; -+ -+ firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0); -+ vc4->firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node); -+ if (!vc4->firmware) { -+ DRM_DEBUG("Failed to get Raspberry Pi firmware reference.\n"); -+ return -EPROBE_DEFER; -+ } -+ of_node_put(firmware_node); -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS, -+ &num_displays, sizeof(u32)); -+ -+ /* If we fail to get the number of displays, then -+ * assume old firmware that doesn't have the mailbox call, so just -+ * set one display -+ */ -+ if (ret) { -+ num_displays = 1; -+ DRM_WARN("Unable to determine number of displays - assuming 1\n"); -+ ret = 0; -+ } -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_GET_DISPLAY_CFG, -+ &fkms->cfg, sizeof(fkms->cfg)); -+ -+ if (ret) -+ return -EINVAL; -+ /* The firmware works in Hz. This will be compared against kHz, so div -+ * 1000 now rather than multiple times later. -+ */ -+ fkms->cfg.max_pixel_clock[0] /= 1000; -+ fkms->cfg.max_pixel_clock[1] /= 1000; -+ -+ /* Allocate a list, with space for a NULL on the end */ -+ crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1), -+ GFP_KERNEL); -+ if (!crtc_list) -+ return -ENOMEM; -+ -+ for (display_num = 0; display_num < num_displays; display_num++) { -+ display_id = display_num; -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID, -+ &display_id, sizeof(display_id)); -+ /* FIXME: Determine the correct error handling here. -+ * Should we fail to create the one "screen" but keep the -+ * others, or fail the whole thing? -+ */ -+ if (ret) -+ DRM_ERROR("Failed to get display id %u\n", display_num); -+ -+ ret = vc4_fkms_create_screen(dev, drm, display_num, display_id, -+ &crtc_list[display_num]); -+ if (ret) -+ DRM_ERROR("Oh dear, failed to create display %u\n", -+ display_num); -+ } -+ -+ if (num_displays > 0) { -+ /* Map the SMI interrupt reg */ -+ crtc_list[0]->regs = vc4_ioremap_regs(pdev, 0); -+ if (IS_ERR(crtc_list[0]->regs)) -+ DRM_ERROR("Oh dear, failed to map registers\n"); -+ -+ writel(0, crtc_list[0]->regs + SMICS); -+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), -+ vc4_crtc_irq_handler, 0, -+ "vc4 firmware kms", crtc_list); -+ if (ret) -+ DRM_ERROR("Oh dear, failed to register IRQ\n"); -+ } else { -+ DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n"); -+ } -+ -+ vc4->fkms = fkms; -+ -+ platform_set_drvdata(pdev, crtc_list); -+ -+ return 0; -+} -+ -+static void vc4_fkms_unbind(struct device *dev, struct device *master, -+ void *data) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct vc4_crtc **crtc_list = dev_get_drvdata(dev); -+ int i; -+ -+ for (i = 0; crtc_list[i]; i++) { -+ vc4_fkms_connector_destroy(crtc_list[i]->connector); -+ vc4_fkms_encoder_destroy(crtc_list[i]->encoder); -+ drm_crtc_cleanup(&crtc_list[i]->base); -+ } -+ -+ platform_set_drvdata(pdev, NULL); -+} -+ -+static const struct component_ops vc4_fkms_ops = { -+ .bind = vc4_fkms_bind, -+ .unbind = vc4_fkms_unbind, -+}; -+ -+static int vc4_fkms_probe(struct platform_device *pdev) -+{ -+ return component_add(&pdev->dev, &vc4_fkms_ops); -+} -+ -+static int vc4_fkms_remove(struct platform_device *pdev) -+{ -+ component_del(&pdev->dev, &vc4_fkms_ops); -+ return 0; -+} -+ -+struct platform_driver vc4_firmware_kms_driver = { -+ .probe = vc4_fkms_probe, -+ .remove = vc4_fkms_remove, -+ .driver = { -+ .name = "vc4_firmware_kms", -+ .of_match_table = vc4_firmware_kms_dt_match, -+ }, -+}; -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index a750b1e6c733..26a31bd97a5d 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -160,6 +160,9 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state) - struct vc4_ctm_state *ctm_state = to_vc4_ctm_state(vc4->ctm_manager.state); - struct drm_color_ctm *ctm = ctm_state->ctm; - -+ if (vc4->firmware_kms) -+ return; -+ - if (ctm_state->fifo) { - HVS_WRITE(SCALER_OLEDCOEF2, - VC4_SET_FIELD(vc4_ctm_s31_32_to_s0_9(ctm->matrix[0]), -@@ -359,14 +362,14 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - struct vc4_crtc_state *vc4_crtc_state; - -- if (!new_crtc_state->commit) -+ if (!new_crtc_state->commit || vc4->firmware_kms) - continue; - - vc4_crtc_state = to_vc4_crtc_state(new_crtc_state); - vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); - } - -- if (vc4->hvs->hvs5) { -+ if (vc4->hvs && vc4->hvs->hvs5) { - unsigned long core_rate = max_t(unsigned long, - 500000000, - new_hvs_state->core_clock_rate); -@@ -401,10 +404,12 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - - vc4_ctm_commit(vc4, state); - -- if (vc4->hvs->hvs5) -- vc5_hvs_pv_muxing_commit(vc4, state); -- else -- vc4_hvs_pv_muxing_commit(vc4, state); -+ if (!vc4->firmware_kms) { -+ if (vc4->hvs && vc4->hvs->hvs5) -+ vc5_hvs_pv_muxing_commit(vc4, state); -+ else -+ vc4_hvs_pv_muxing_commit(vc4, state); -+ } - - drm_atomic_helper_commit_planes(dev, state, 0); - -@@ -418,7 +423,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - - drm_atomic_helper_cleanup_planes(dev, state); - -- if (vc4->hvs->hvs5) { -+ if (vc4->hvs && vc4->hvs->hvs5) { - drm_dbg(dev, "Running the core clock at %lu Hz\n", - new_hvs_state->core_clock_rate); - -@@ -436,11 +441,21 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - - static int vc4_atomic_commit_setup(struct drm_atomic_state *state) - { -+ struct drm_device *dev = state->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); - struct drm_crtc_state *crtc_state; - struct vc4_hvs_state *hvs_state; - struct drm_crtc *crtc; - unsigned int i; - -+ /* We know for sure we don't want an async update here. Set -+ * state->legacy_cursor_update to false to prevent -+ * drm_atomic_helper_setup_commit() from auto-completing -+ * commit->flip_done. -+ */ -+ if (!vc4->firmware_kms) -+ state->legacy_cursor_update = false; -+ - hvs_state = vc4_hvs_get_new_global_state(state); - if (!hvs_state) - return -EINVAL; -@@ -780,6 +795,7 @@ static int vc4_hvs_channels_obj_init(struct vc4_dev *vc4) - static int vc4_pv_muxing_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) - { -+ struct vc4_dev *vc4 = to_vc4_dev(state->dev); - struct vc4_hvs_state *hvs_new_state; - struct drm_crtc_state *old_crtc_state, *new_crtc_state; - struct drm_crtc *crtc; -@@ -803,6 +819,9 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, - unsigned int matching_channels; - unsigned int channel; - -+ if (vc4->firmware_kms) -+ continue; -+ - /* Nothing to do here, let's skip it */ - if (old_crtc_state->enable == new_crtc_state->enable) - continue; -@@ -1000,6 +1019,8 @@ int vc4_kms_load(struct drm_device *dev) - dev->mode_config.helper_private = &vc4_mode_config_helpers; - dev->mode_config.preferred_depth = 24; - dev->mode_config.async_page_flip = true; -+ if (vc4->firmware_kms) -+ dev->mode_config.normalize_zpos = true; - - ret = vc4_ctm_obj_init(vc4); - if (ret) -diff --git a/drivers/gpu/drm/vc4/vc_image_types.h b/drivers/gpu/drm/vc4/vc_image_types.h -new file mode 100644 -index 000000000000..e8d2b4b162f7 ---- /dev/null -+++ b/drivers/gpu/drm/vc4/vc_image_types.h -@@ -0,0 +1,175 @@ -+ -+/* -+ * Copyright (c) 2012, Broadcom Europe Ltd -+ * -+ * Values taken from vc_image_types.h released by Broadcom at -+ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h -+ * and vc_image_structs.h at -+ * https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_structs.h -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+enum { -+ VC_IMAGE_MIN = 0, //bounds for error checking -+ -+ VC_IMAGE_RGB565 = 1, -+ VC_IMAGE_1BPP, -+ VC_IMAGE_YUV420, -+ VC_IMAGE_48BPP, -+ VC_IMAGE_RGB888, -+ VC_IMAGE_8BPP, -+ /* 4bpp palettised image */ -+ VC_IMAGE_4BPP, -+ /* A separated format of 16 colour/light shorts followed by 16 z -+ * values -+ */ -+ VC_IMAGE_3D32, -+ /* 16 colours followed by 16 z values */ -+ VC_IMAGE_3D32B, -+ /* A separated format of 16 material/colour/light shorts followed by -+ * 16 z values -+ */ -+ VC_IMAGE_3D32MAT, -+ /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */ -+ VC_IMAGE_RGB2X9, -+ /* 32-bit format holding 18 bits of 6.6.6 RGB */ -+ VC_IMAGE_RGB666, -+ /* 4bpp palettised image with embedded palette */ -+ VC_IMAGE_PAL4_OBSOLETE, -+ /* 8bpp palettised image with embedded palette */ -+ VC_IMAGE_PAL8_OBSOLETE, -+ /* RGB888 with an alpha byte after each pixel */ -+ VC_IMAGE_RGBA32, -+ /* a line of Y (32-byte padded), a line of U (16-byte padded), and a -+ * line of V (16-byte padded) -+ */ -+ VC_IMAGE_YUV422, -+ /* RGB565 with a transparent patch */ -+ VC_IMAGE_RGBA565, -+ /* Compressed (4444) version of RGBA32 */ -+ VC_IMAGE_RGBA16, -+ /* VCIII codec format */ -+ VC_IMAGE_YUV_UV, -+ /* VCIII T-format RGBA8888 */ -+ VC_IMAGE_TF_RGBA32, -+ /* VCIII T-format RGBx8888 */ -+ VC_IMAGE_TF_RGBX32, -+ /* VCIII T-format float */ -+ VC_IMAGE_TF_FLOAT, -+ /* VCIII T-format RGBA4444 */ -+ VC_IMAGE_TF_RGBA16, -+ /* VCIII T-format RGB5551 */ -+ VC_IMAGE_TF_RGBA5551, -+ /* VCIII T-format RGB565 */ -+ VC_IMAGE_TF_RGB565, -+ /* VCIII T-format 8-bit luma and 8-bit alpha */ -+ VC_IMAGE_TF_YA88, -+ /* VCIII T-format 8 bit generic sample */ -+ VC_IMAGE_TF_BYTE, -+ /* VCIII T-format 8-bit palette */ -+ VC_IMAGE_TF_PAL8, -+ /* VCIII T-format 4-bit palette */ -+ VC_IMAGE_TF_PAL4, -+ /* VCIII T-format Ericsson Texture Compressed */ -+ VC_IMAGE_TF_ETC1, -+ /* RGB888 with R & B swapped */ -+ VC_IMAGE_BGR888, -+ /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after -+ * each row of pixels -+ */ -+ VC_IMAGE_BGR888_NP, -+ /* Bayer image, extra defines which variant is being used */ -+ VC_IMAGE_BAYER, -+ /* General wrapper for codec images e.g. JPEG from camera */ -+ VC_IMAGE_CODEC, -+ /* VCIII codec format */ -+ VC_IMAGE_YUV_UV32, -+ /* VCIII T-format 8-bit luma */ -+ VC_IMAGE_TF_Y8, -+ /* VCIII T-format 8-bit alpha */ -+ VC_IMAGE_TF_A8, -+ /* VCIII T-format 16-bit generic sample */ -+ VC_IMAGE_TF_SHORT, -+ /* VCIII T-format 1bpp black/white */ -+ VC_IMAGE_TF_1BPP, -+ VC_IMAGE_OPENGL, -+ /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */ -+ VC_IMAGE_YUV444I, -+ /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on -+ * a per line basis) -+ */ -+ VC_IMAGE_YUV422PLANAR, -+ /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */ -+ VC_IMAGE_ARGB8888, -+ /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */ -+ VC_IMAGE_XRGB8888, -+ -+ /* interleaved 8 bit samples of Y, U, Y, V (4 flavours) */ -+ VC_IMAGE_YUV422YUYV, -+ VC_IMAGE_YUV422YVYU, -+ VC_IMAGE_YUV422UYVY, -+ VC_IMAGE_YUV422VYUY, -+ -+ /* 32bpp like RGBA32 but with unused alpha */ -+ VC_IMAGE_RGBX32, -+ /* 32bpp, corresponding to RGBA with unused alpha */ -+ VC_IMAGE_RGBX8888, -+ /* 32bpp, corresponding to BGRA with unused alpha */ -+ VC_IMAGE_BGRX8888, -+ -+ /* Y as a plane, then UV byte interleaved in plane with same pitch, -+ * half height -+ */ -+ VC_IMAGE_YUV420SP, -+ -+ /* Y, U, & V planes separately 4:4:4 */ -+ VC_IMAGE_YUV444PLANAR, -+ -+ /* T-format 8-bit U - same as TF_Y8 buf from U plane */ -+ VC_IMAGE_TF_U8, -+ /* T-format 8-bit U - same as TF_Y8 buf from V plane */ -+ VC_IMAGE_TF_V8, -+ -+ /* YUV4:2:0 planar, 16bit values */ -+ VC_IMAGE_YUV420_16, -+ /* YUV4:2:0 codec format, 16bit values */ -+ VC_IMAGE_YUV_UV_16, -+ /* YUV4:2:0 with U,V in side-by-side format */ -+ VC_IMAGE_YUV420_S, -+ /* 10-bit YUV 420 column image format */ -+ VC_IMAGE_YUV10COL, -+ /* 32-bpp, 10-bit R/G/B, 2-bit Alpha */ -+ VC_IMAGE_RGBA1010102, -+ -+ VC_IMAGE_MAX, /* bounds for error checking */ -+ VC_IMAGE_FORCE_ENUM_16BIT = 0xffff, -+}; -+ -+enum { -+ /* Unknown or unset - defaults to BT601 interstitial */ -+ VC_IMAGE_YUVINFO_UNSPECIFIED = 0, -+ -+ /* colour-space conversions data [4 bits] */ -+ -+ /* ITU-R BT.601-5 [SDTV] (compatible with VideoCore-II) */ -+ VC_IMAGE_YUVINFO_CSC_ITUR_BT601 = 1, -+ /* ITU-R BT.709-3 [HDTV] */ -+ VC_IMAGE_YUVINFO_CSC_ITUR_BT709 = 2, -+ /* JPEG JFIF */ -+ VC_IMAGE_YUVINFO_CSC_JPEG_JFIF = 3, -+ /* Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */ -+ VC_IMAGE_YUVINFO_CSC_FCC = 4, -+ /* Society of Motion Picture and Television Engineers 240M (1999) */ -+ VC_IMAGE_YUVINFO_CSC_SMPTE_240M = 5, -+ /* ITU-R BT.470-2 System M */ -+ VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_M = 6, -+ /* ITU-R BT.470-2 System B,G */ -+ VC_IMAGE_YUVINFO_CSC_ITUR_BT470_2_BG = 7, -+ /* JPEG JFIF, but with 16..255 luma */ -+ VC_IMAGE_YUVINFO_CSC_JPEG_JFIF_Y16_255 = 8, -+ /* Rec 2020 */ -+ VC_IMAGE_YUVINFO_CSC_REC_2020 = 9, -+}; -diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index ee361b90eb29..7fdce4033b46 100644 ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -73,6 +73,7 @@ enum rpi_firmware_property_tag { - RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, - RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, - RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, -+ RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY = 0x00030023, - RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, - RPI_FIRMWARE_GET_THROTTLED = 0x00030046, - RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047, -@@ -149,6 +150,11 @@ enum rpi_firmware_property_tag { - - RPI_FIRMWARE_VCHIQ_INIT = 0x00048010, - -+ RPI_FIRMWARE_SET_PLANE = 0x00048015, -+ RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017, -+ RPI_FIRMWARE_SET_TIMING = 0x00048017, -+ RPI_FIRMWARE_GET_DISPLAY_CFG = 0x00040018, -+ RPI_FIRMWARE_SET_DISPLAY_POWER = 0x00048019, - RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, - RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, - }; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0484-drm-vc4-hdmi-Unregister-codec-device-on-unbind.patch b/root/target/linux/bcm27xx/patches-5.15/0484-drm-vc4-hdmi-Unregister-codec-device-on-unbind.patch deleted file mode 100644 index f071cf1f..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0484-drm-vc4-hdmi-Unregister-codec-device-on-unbind.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 59dca213da407638874caf97b0e9c15f886df890 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 23 Jul 2021 15:45:54 +0200 -Subject: [PATCH 484/634] drm/vc4: hdmi: Unregister codec device on unbind - -On bind we will register the HDMI codec device but we don't unregister -it on unbind, leading to a device leakage. Unregister our device at -unbind. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 8 ++++++++ - drivers/gpu/drm/vc4/vc4_hdmi.h | 1 + - 2 files changed, 9 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 502d5bea5f61..395a9e9c1e5a 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -1746,6 +1746,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) - dev_err(dev, "Couldn't register the HDMI codec: %ld\n", PTR_ERR(codec_pdev)); - return PTR_ERR(codec_pdev); - } -+ vc4_hdmi->audio.codec_pdev = codec_pdev; - - dai_link->cpus = &vc4_hdmi->audio.cpu; - dai_link->codecs = &vc4_hdmi->audio.codec; -@@ -1785,6 +1786,12 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) - - } - -+static void vc4_hdmi_audio_exit(struct vc4_hdmi *vc4_hdmi) -+{ -+ platform_device_unregister(vc4_hdmi->audio.codec_pdev); -+ vc4_hdmi->audio.codec_pdev = NULL; -+} -+ - static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv) - { - struct vc4_hdmi *vc4_hdmi = priv; -@@ -2689,6 +2696,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, - kfree(vc4_hdmi->hdmi_regset.regs); - kfree(vc4_hdmi->hd_regset.regs); - -+ vc4_hdmi_audio_exit(vc4_hdmi); - vc4_hdmi_cec_exit(vc4_hdmi); - vc4_hdmi_hotplug_exit(vc4_hdmi); - vc4_hdmi_connector_destroy(&vc4_hdmi->connector); -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h -index db53500a8435..275c4674d50f 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h -@@ -113,6 +113,7 @@ struct vc4_hdmi_audio { - struct snd_soc_dai_link_component platform; - struct snd_dmaengine_dai_dma_data dma_data; - struct hdmi_audio_infoframe infoframe; -+ struct platform_device *codec_pdev; - bool streaming; - }; - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0485-drm-vc4-fix-vc4_atomic_commit_tail-logic.patch b/root/target/linux/bcm27xx/patches-5.15/0485-drm-vc4-fix-vc4_atomic_commit_tail-logic.patch deleted file mode 100644 index cb9f8c80..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0485-drm-vc4-fix-vc4_atomic_commit_tail-logic.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 214b5251ae7f2559119f4fe202e2d83fe27ea970 Mon Sep 17 00:00:00 2001 -From: Mark Rutland -Date: Tue, 8 Jun 2021 09:55:12 +0100 -Subject: [PATCH 485/634] drm/vc4: fix vc4_atomic_commit_tail() logic - -In vc4_atomic_commit_tail() we iterate of the set of old CRTCs, and -attempt to wait on any channels which are still in use. When we iterate -over the CRTCs, we have: - -* `i` - the index of the CRTC -* `channel` - the channel a CRTC is using - -When we check the channel state, we consult: - - old_hvs_state->fifo_state[channel].in_use - -... but when we wait for the channel, we erroneously wait on: - - old_hvs_state->fifo_state[i].pending_commit - -... rather than: - - old_hvs_state->fifo_state[channel].pending_commit - -... and this bogus access has been observed to result in boot-time hangs -on some arm64 configurations, and can be detected using KASAN. FIx this -by using the correct index. - -I've tested this on a Raspberry Pi 3 model B v1.2 with KASAN. - -Trimmed KASAN splat: - -| ================================================================== -| BUG: KASAN: slab-out-of-bounds in vc4_atomic_commit_tail+0x1cc/0x910 -| Read of size 8 at addr ffff000007360440 by task kworker/u8:0/7 -| CPU: 2 PID: 7 Comm: kworker/u8:0 Not tainted 5.13.0-rc3-00009-g694c523e7267 #3 -| -| Hardware name: Raspberry Pi 3 Model B (DT) -| Workqueue: events_unbound deferred_probe_work_func -| Call trace: -| dump_backtrace+0x0/0x2b4 -| show_stack+0x1c/0x30 -| dump_stack+0xfc/0x168 -| print_address_description.constprop.0+0x2c/0x2c0 -| kasan_report+0x1dc/0x240 -| __asan_load8+0x98/0xd4 -| vc4_atomic_commit_tail+0x1cc/0x910 -| commit_tail+0x100/0x210 -| ... -| -| Allocated by task 7: -| kasan_save_stack+0x2c/0x60 -| __kasan_kmalloc+0x90/0xb4 -| vc4_hvs_channels_duplicate_state+0x60/0x1a0 -| drm_atomic_get_private_obj_state+0x144/0x230 -| vc4_atomic_check+0x40/0x73c -| drm_atomic_check_only+0x998/0xe60 -| drm_atomic_commit+0x34/0x94 -| drm_client_modeset_commit_atomic+0x2f4/0x3a0 -| drm_client_modeset_commit_locked+0x8c/0x230 -| drm_client_modeset_commit+0x38/0x60 -| drm_fb_helper_set_par+0x104/0x17c -| fbcon_init+0x43c/0x970 -| visual_init+0x14c/0x1e4 -| ... -| -| The buggy address belongs to the object at ffff000007360400 -| which belongs to the cache kmalloc-128 of size 128 -| The buggy address is located 64 bytes inside of -| 128-byte region [ffff000007360400, ffff000007360480) -| The buggy address belongs to the page: -| page:(____ptrval____) refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x7360 -| flags: 0x3fffc0000000200(slab|node=0|zone=0|lastcpupid=0xffff) -| raw: 03fffc0000000200 dead000000000100 dead000000000122 ffff000004c02300 -| raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000 -| page dumped because: kasan: bad access detected -| -| Memory state around the buggy address: -| ffff000007360300: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb -| ffff000007360380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc -| >ffff000007360400: 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc fc -| ^ -| ffff000007360480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc -| ffff000007360500: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb -| ================================================================== - -Link: https://lore.kernel.org/r/4d0c8318-bad8-2be7-e292-fc8f70c198de@samsung.com -Link: https://lore.kernel.org/linux-arm-kernel/20210607151740.moncryl5zv3ahq4s@gilmour -Signed-off-by: Mark Rutland -Reported-by: Marek Szyprowski -Cc: Arnd Bergmann -Cc: Catalin Marinas -Cc: Daniel Vetter -Cc: David Airlie -Cc: Emma Anholt -Cc: Maxime Ripard -Cc: Will Deacon -Cc: dri-devel@lists.freedesktop.org -Acked-by: Arnd Bergmann -Tested-by: Marek Szyprowski -Signed-off-by: Maxime Ripard -Link: https://patchwork.freedesktop.org/patch/msgid/20210608085513.2069-1-mark.rutland@arm.com ---- - drivers/gpu/drm/vc4/vc4_kms.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 26a31bd97a5d..8a8476f7df08 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -386,6 +386,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { - struct vc4_crtc_state *vc4_crtc_state = - to_vc4_crtc_state(old_crtc_state); -+ struct drm_crtc_commit *commit; - unsigned int channel = vc4_crtc_state->assigned_channel; - int ret; - -@@ -395,7 +396,11 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - if (!old_hvs_state->fifo_state[channel].in_use) - continue; - -- ret = drm_crtc_commit_wait(old_hvs_state->fifo_state[channel].pending_commit); -+ commit = old_hvs_state->fifo_state[channel].pending_commit; -+ if (!commit) -+ continue; -+ -+ ret = drm_crtc_commit_wait(commit); - if (ret) - drm_err(dev, "Timed out waiting for commit\n"); - } --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0505-drm-vc4-Reset-HDMI-MISC_CONTROL-register.patch b/root/target/linux/bcm27xx/patches-5.15/0505-drm-vc4-Reset-HDMI-MISC_CONTROL-register.patch deleted file mode 100644 index 2c01fe19..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0505-drm-vc4-Reset-HDMI-MISC_CONTROL-register.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 362e013b4a3f887c718a5808c8825e98a0e3511e Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 13 Sep 2021 17:30:18 +0100 -Subject: [PATCH 505/634] drm/vc4: Reset HDMI MISC_CONTROL register. - -The HDMI block can repeat pixels for double clocked modes, -and the firmware is now configuring the block to do this as -the PV is doing it incorrectly when at 2pixels/clock. -If the kernel doesn't reset it then we end up with strange -modes. - -Reset MISC_CONTROL. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 8 ++++++++ - drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 3 +++ - 2 files changed, 11 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index 395a9e9c1e5a..a6afd7d7f21c 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -78,6 +78,9 @@ - #define VC5_HDMI_VERTB_VSPO_SHIFT 16 - #define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16) - -+#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_SHIFT 0 -+#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK VC4_MASK(3, 0) -+ - #define VC5_HDMI_SCRAMBLER_CTL_ENABLE BIT(0) - - #define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_SHIFT 8 -@@ -962,6 +965,11 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, - reg |= gcp_en ? VC5_HDMI_GCP_CONFIG_GCP_ENABLE : 0; - HDMI_WRITE(HDMI_GCP_CONFIG, reg); - -+ reg = HDMI_READ(HDMI_MISC_CONTROL); -+ reg &= ~VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK; -+ reg |= VC4_SET_FIELD(0, VC5_HDMI_MISC_CONTROL_PIXEL_REP); -+ HDMI_WRITE(HDMI_MISC_CONTROL, reg); -+ - HDMI_WRITE(HDMI_CLOCK_STOP, 0); - - spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -index fc971506bd4f..24056441a4bb 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h -@@ -125,6 +125,7 @@ enum vc4_hdmi_field { - HDMI_VERTB0, - HDMI_VERTB1, - HDMI_VID_CTL, -+ HDMI_MISC_CONTROL, - }; - - struct vc4_hdmi_register { -@@ -235,6 +236,7 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi0_fields[] = { - VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), - VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), - VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), -+ VC4_HDMI_REG(HDMI_MISC_CONTROL, 0x100), - VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c), - VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0), - VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170), -@@ -315,6 +317,7 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi1_fields[] = { - VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), - VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), - VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), -+ VC4_HDMI_REG(HDMI_MISC_CONTROL, 0x100), - VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c), - VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0), - VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170), --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0506-drm-vc4-Release-workaround-buffer-and-DMA-in-error-p.patch b/root/target/linux/bcm27xx/patches-5.15/0506-drm-vc4-Release-workaround-buffer-and-DMA-in-error-p.patch deleted file mode 100644 index 29e98522..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0506-drm-vc4-Release-workaround-buffer-and-DMA-in-error-p.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 8fe39ec43ba5d59b6f88d6a17477a2a1a206483d Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Tue, 6 Jul 2021 18:53:28 +0100 -Subject: [PATCH 506/634] drm/vc4: Release workaround buffer and DMA in error - paths and unbind - -On Pi0-3 the driver allocates a buffer and requests a DMA channel -because the ARM can't write to DSI1's registers directly. -However unbind and the error paths in bind don't release the buffer or -the DMA channel. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_dsi.c | 51 ++++++++++++++++++++++++++--------- - 1 file changed, 39 insertions(+), 12 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c -index e433071bf797..abfa19cc9b45 100644 ---- a/drivers/gpu/drm/vc4/vc4_dsi.c -+++ b/drivers/gpu/drm/vc4/vc4_dsi.c -@@ -1616,7 +1616,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - if (ret != -EPROBE_DEFER) - DRM_ERROR("Failed to get DMA channel: %d\n", - ret); -- return ret; -+ goto err_free_dma_mem; - } - - /* Get the physical address of the device's registers. The -@@ -1645,7 +1645,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get interrupt: %d\n", ret); -- return ret; -+ goto err_free_dma; - } - - dsi->escape_clock = devm_clk_get(dev, "escape"); -@@ -1653,7 +1653,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - ret = PTR_ERR(dsi->escape_clock); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get escape clock: %d\n", ret); -- return ret; -+ goto err_free_dma; - } - - dsi->pll_phy_clock = devm_clk_get(dev, "phy"); -@@ -1661,7 +1661,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - ret = PTR_ERR(dsi->pll_phy_clock); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get phy clock: %d\n", ret); -- return ret; -+ goto err_free_dma; - } - - dsi->pixel_clock = devm_clk_get(dev, "pixel"); -@@ -1669,7 +1669,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - ret = PTR_ERR(dsi->pixel_clock); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get pixel clock: %d\n", ret); -- return ret; -+ goto err_free_dma; - } - - ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, -@@ -1684,33 +1684,37 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - if (ret == -ENODEV) - return 0; - -- return ret; -+ goto err_free_dma; - } - - if (panel) { - dsi->bridge = devm_drm_panel_bridge_add_typed(dev, panel, - DRM_MODE_CONNECTOR_DSI); -- if (IS_ERR(dsi->bridge)) -- return PTR_ERR(dsi->bridge); -+ if (IS_ERR(dsi->bridge)) { -+ ret = PTR_ERR(dsi->bridge); -+ goto err_free_dma; -+ } - } - - /* The esc clock rate is supposed to always be 100Mhz. */ - ret = clk_set_rate(dsi->escape_clock, 100 * 1000000); - if (ret) { - dev_err(dev, "Failed to set esc clock: %d\n", ret); -- return ret; -+ goto err_free_dma; - } - - ret = vc4_dsi_init_phy_clocks(dsi); - if (ret) -- return ret; -+ goto err_free_dma; - - drm_simple_encoder_init(drm, dsi->encoder, DRM_MODE_ENCODER_DSI); - drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); - - ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0); -- if (ret) -- return ret; -+ if (ret) { -+ dev_err(dev, "bridge attach failed: %d\n", ret); -+ goto err_free_dma; -+ } - /* Disable the atomic helper calls into the bridge. We - * manually call the bridge pre_enable / enable / etc. calls - * from our driver, since we need to sequence them within the -@@ -1723,6 +1727,19 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) - pm_runtime_enable(dev); - - return 0; -+ -+err_free_dma: -+ if (dsi->reg_dma_chan) { -+ dma_release_channel(dsi->reg_dma_chan); -+ dsi->reg_dma_chan = NULL; -+ } -+err_free_dma_mem: -+ if (dsi->reg_dma_mem) { -+ dma_free_coherent(dev, 4, dsi->reg_dma_mem, dsi->reg_dma_paddr); -+ dsi->reg_dma_mem = NULL; -+ } -+ -+ return ret; - } - - static void vc4_dsi_unbind(struct device *dev, struct device *master, -@@ -1739,6 +1756,16 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, - */ - list_splice_init(&dsi->bridge_chain, &dsi->encoder->bridge_chain); - drm_encoder_cleanup(dsi->encoder); -+ -+ if (dsi->reg_dma_chan) { -+ dma_release_channel(dsi->reg_dma_chan); -+ dsi->reg_dma_chan = NULL; -+ } -+ -+ if (dsi->reg_dma_mem) { -+ dma_free_coherent(dev, 4, dsi->reg_dma_mem, dsi->reg_dma_paddr); -+ dsi->reg_dma_mem = NULL; -+ } - } - - static const struct component_ops vc4_dsi_ops = { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0507-drm-vc4-Correct-DSI-divider-calculations.patch b/root/target/linux/bcm27xx/patches-5.15/0507-drm-vc4-Correct-DSI-divider-calculations.patch deleted file mode 100644 index 5bd483d3..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0507-drm-vc4-Correct-DSI-divider-calculations.patch +++ /dev/null @@ -1,40 +0,0 @@ -From c5819b09ed426ed64570bc11c4f0ca9622a32889 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Fri, 18 Jun 2021 21:52:28 +0100 -Subject: [PATCH 507/634] drm/vc4: Correct DSI divider calculations - -The divider calculations tried to find the divider -just faster than the clock requested. However if -it required a divider of 7 then the for loop -aborted without handling the "error" case, and could -end up with a clock lower than requested. - -Correct the loop so that we always have a clock greater -than requested. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_dsi.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c -index abfa19cc9b45..270e26e56e51 100644 ---- a/drivers/gpu/drm/vc4/vc4_dsi.c -+++ b/drivers/gpu/drm/vc4/vc4_dsi.c -@@ -850,11 +850,9 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder, - /* Find what divider gets us a faster clock than the requested - * pixel clock. - */ -- for (divider = 1; divider < 8; divider++) { -- if (parent_rate / divider < pll_clock) { -- divider--; -+ for (divider = 1; divider < 7; divider++) { -+ if (parent_rate / (divider + 1) < pll_clock) - break; -- } - } - - /* Now that we've picked a PLL divider, calculate back to its --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0587-Add-missing-drm_crtc_commit_put.patch b/root/target/linux/bcm27xx/patches-5.15/0587-Add-missing-drm_crtc_commit_put.patch deleted file mode 100644 index 69360070..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0587-Add-missing-drm_crtc_commit_put.patch +++ /dev/null @@ -1,26 +0,0 @@ -From dfededf17d005d8f5f6a86247f1cb7ba019fbc5c Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 27 Aug 2021 18:20:25 +0200 -Subject: [PATCH 587/634] Add missing drm_crtc_commit_put - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_kms.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 8a8476f7df08..cc905b8c3282 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -403,6 +403,8 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - ret = drm_crtc_commit_wait(commit); - if (ret) - drm_err(dev, "Timed out waiting for commit\n"); -+ -+ drm_crtc_commit_put(commit); - } - - drm_atomic_helper_commit_modeset_disables(dev, state); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0588-drm-vc4-Wait-for-the-commit-before-starting-our-cloc.patch b/root/target/linux/bcm27xx/patches-5.15/0588-drm-vc4-Wait-for-the-commit-before-starting-our-cloc.patch deleted file mode 100644 index 5453a5fd..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0588-drm-vc4-Wait-for-the-commit-before-starting-our-cloc.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 8c994de768f64b6697798c7b08f25b05485195c9 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 30 Aug 2021 15:30:41 +0200 -Subject: [PATCH 588/634] drm/vc4: Wait for the commit before starting our - clock request - -Several DRM/KMS atomic commits can run in parallel if they affect -different CRTC. These commits share the global HVS state, so we have -some code to make sure we run commits in sequence. This synchronization -code is one of the first thing that runs in vc4_atomic_commit_tail(). - -Another constraints we have is that we need to make sure the HVS clock -gets a boost during the commit. That code relies on clk_requests and -will remove the old requests and start a new one. We also need another, -temporary, request for the duration of the commit. - -The algorithm is thus to start a temporary request, drop the previous -one, do the commit, start a new request for the current mode, and -finally drop the temporary request. - -However, the part that takes a temporary request and drops the older one -runs before the commit synchronization code. - -Thus, under the proper conditions, we can end up dropping twice the old -request, resulting in an use-after-free. - -To avoid it, let's move the clock setup in the protected section. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_kms.c | 34 ++++++++++++++++++++-------------- - 1 file changed, 20 insertions(+), 14 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index cc905b8c3282..8c63b962b2e6 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -369,20 +369,6 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); - } - -- if (vc4->hvs && vc4->hvs->hvs5) { -- unsigned long core_rate = max_t(unsigned long, -- 500000000, -- new_hvs_state->core_clock_rate); -- -- core_req = clk_request_start(hvs->core_clk, core_rate); -- -- /* -- * And remove the previous one based on the HVS -- * requirements if any. -- */ -- clk_request_done(hvs->core_req); -- } -- - for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { - struct vc4_crtc_state *vc4_crtc_state = - to_vc4_crtc_state(old_crtc_state); -@@ -407,6 +393,26 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - drm_crtc_commit_put(commit); - } - -+ if (vc4->hvs && vc4->hvs->hvs5) { -+ unsigned long core_rate = max_t(unsigned long, -+ 500000000, -+ new_hvs_state->core_clock_rate); -+ -+ drm_dbg(dev, "Raising the core clock at %lu Hz\n", core_rate); -+ -+ /* -+ * Do a temporary request on the core clock during the -+ * modeset. -+ */ -+ core_req = clk_request_start(hvs->core_clk, core_rate); -+ -+ /* -+ * And remove the previous one based on the HVS -+ * requirements if any. -+ */ -+ clk_request_done(hvs->core_req); -+ } -+ - drm_atomic_helper_commit_modeset_disables(dev, state); - - vc4_ctm_commit(vc4, state); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0589-Revert-Add-missing-drm_crtc_commit_put.patch b/root/target/linux/bcm27xx/patches-5.15/0589-Revert-Add-missing-drm_crtc_commit_put.patch deleted file mode 100644 index 9e6af225..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0589-Revert-Add-missing-drm_crtc_commit_put.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 4b11270886ebe8019e079040638ed0766d505ae5 Mon Sep 17 00:00:00 2001 -From: Dom Cobley -Date: Wed, 27 Oct 2021 16:22:41 +0100 -Subject: [PATCH 589/634] Revert "Add missing drm_crtc_commit_put" - -This reverts commit c3ca5d8eccbb8a380e784ba01421dd484618d0d1. ---- - drivers/gpu/drm/vc4/vc4_kms.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 8c63b962b2e6..2511113a6f82 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -389,8 +389,6 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - ret = drm_crtc_commit_wait(commit); - if (ret) - drm_err(dev, "Timed out waiting for commit\n"); -- -- drm_crtc_commit_put(commit); - } - - if (vc4->hvs && vc4->hvs->hvs5) { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0594-drm-vc4-Add-support-for-gamma-on-BCM2711.patch b/root/target/linux/bcm27xx/patches-5.15/0594-drm-vc4-Add-support-for-gamma-on-BCM2711.patch deleted file mode 100644 index 51b8cd07..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0594-drm-vc4-Add-support-for-gamma-on-BCM2711.patch +++ /dev/null @@ -1,283 +0,0 @@ -From b522484f4b813a26b597934fbb61573eb7f17f00 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Tue, 27 Apr 2021 14:24:21 +0200 -Subject: [PATCH 594/634] drm/vc4: Add support for gamma on BCM2711 - -BCM2711 changes from a 256 entry lookup table to a 16 point -piecewise linear function as the pipeline bitdepth has increased -to make a LUT unwieldy. - -Implement a simple conversion from a 256 entry LUT that userspace -is likely to expect to 16 evenly spread points in the PWL. This -could be improved with curve fitting at a later date. - -Co-developed-by: Juerg Haefliger -Signed-off-by: Juerg Haefliger -Signed-off-by: Dave Stevenson -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 35 +++++++++++--- - drivers/gpu/drm/vc4/vc4_drv.h | 28 +++++++++-- - drivers/gpu/drm/vc4/vc4_hvs.c | 87 ++++++++++++++++++++++++++++++++-- - drivers/gpu/drm/vc4/vc4_regs.h | 22 +++++++++ - 4 files changed, 159 insertions(+), 13 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 23be68a8ecec..e06801557cec 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -1162,19 +1162,42 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, - - if (!vc4->hvs->hvs5) { - drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); -+ } else { -+ /* This is a lie for hvs5 which uses a 16 point PWL, but it -+ * allows for something smarter than just 16 linearly spaced -+ * segments. Conversion is done in vc5_hvs_update_gamma_lut. -+ */ -+ drm_mode_crtc_set_gamma_size(crtc, 256); -+ } - -- drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); -+ drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); - -+ if (!vc4->hvs->hvs5) { - /* We support CTM, but only for one CRTC at a time. It's therefore - * implemented as private driver state in vc4_kms, not here. - */ - drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size); -- } - -- for (i = 0; i < crtc->gamma_size; i++) { -- vc4_crtc->lut_r[i] = i; -- vc4_crtc->lut_g[i] = i; -- vc4_crtc->lut_b[i] = i; -+ /* Initialize the VC4 gamma LUTs */ -+ for (i = 0; i < crtc->gamma_size; i++) { -+ vc4_crtc->lut_r[i] = i; -+ vc4_crtc->lut_g[i] = i; -+ vc4_crtc->lut_b[i] = i; -+ } -+ } else { -+ /* Initialize the VC5 gamma PWL entries. Assume 12-bit pipeline, -+ * evenly spread over full range. -+ */ -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++) { -+ vc4_crtc->pwl_r[i] = -+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8); -+ vc4_crtc->pwl_g[i] = -+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8); -+ vc4_crtc->pwl_b[i] = -+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8); -+ vc4_crtc->pwl_a[i] = -+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, i << 12, 1 << 8); -+ } - } - - return 0; -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 48d5d13f38a3..56d014b91e4e 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -19,6 +19,7 @@ - #include - - #include "uapi/drm/vc4_drm.h" -+#include "vc4_regs.h" - - struct drm_device; - struct drm_gem_object; -@@ -481,6 +482,17 @@ struct vc4_pv_data { - - }; - -+struct vc5_gamma_entry { -+ u32 x_c_terms; -+ u32 grad_term; -+}; -+ -+#define VC5_HVS_SET_GAMMA_ENTRY(x, c, g) (struct vc5_gamma_entry){ \ -+ .x_c_terms = VC4_SET_FIELD((x), SCALER5_DSPGAMMA_OFF_X) | \ -+ VC4_SET_FIELD((c), SCALER5_DSPGAMMA_OFF_C), \ -+ .grad_term = (g) \ -+} -+ - struct vc4_crtc { - struct drm_crtc base; - struct platform_device *pdev; -@@ -490,9 +502,19 @@ struct vc4_crtc { - /* Timestamp at start of vblank irq - unaffected by lock delays. */ - ktime_t t_vblank; - -- u8 lut_r[256]; -- u8 lut_g[256]; -- u8 lut_b[256]; -+ union { -+ struct { /* VC4 gamma LUT */ -+ u8 lut_r[256]; -+ u8 lut_g[256]; -+ u8 lut_b[256]; -+ }; -+ struct { /* VC5 gamma PWL entries */ -+ struct vc5_gamma_entry pwl_r[SCALER5_DSPGAMMA_NUM_POINTS]; -+ struct vc5_gamma_entry pwl_g[SCALER5_DSPGAMMA_NUM_POINTS]; -+ struct vc5_gamma_entry pwl_b[SCALER5_DSPGAMMA_NUM_POINTS]; -+ struct vc5_gamma_entry pwl_a[SCALER5_DSPGAMMA_NUM_POINTS]; -+ }; -+ }; - - struct drm_pending_vblank_event *event; - -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index ab79d0a82a19..73751bd6775a 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -236,6 +236,80 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc) - vc4_hvs_lut_load(crtc); - } - -+static void vc5_hvs_write_gamma_entry(struct vc4_dev *vc4, -+ u32 offset, -+ struct vc5_gamma_entry *gamma) -+{ -+ HVS_WRITE(offset, gamma->x_c_terms); -+ HVS_WRITE(offset + 4, gamma->grad_term); -+} -+ -+static void vc5_hvs_lut_load(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); -+ u32 i; -+ u32 offset = SCALER5_DSPGAMMA_START + -+ vc4_state->assigned_channel * SCALER5_DSPGAMMA_CHAN_OFFSET; -+ -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) -+ vc5_hvs_write_gamma_entry(vc4, offset, &vc4_crtc->pwl_r[i]); -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) -+ vc5_hvs_write_gamma_entry(vc4, offset, &vc4_crtc->pwl_g[i]); -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) -+ vc5_hvs_write_gamma_entry(vc4, offset, &vc4_crtc->pwl_b[i]); -+ -+ if (vc4_state->assigned_channel == 2) { -+ /* Alpha only valid on channel 2 */ -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) -+ vc5_hvs_write_gamma_entry(vc4, offset, &vc4_crtc->pwl_a[i]); -+ } -+} -+ -+static void vc5_hvs_update_gamma_lut(struct drm_crtc *crtc) -+{ -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ struct drm_color_lut *lut = crtc->state->gamma_lut->data; -+ unsigned int step, i; -+ u32 start, end; -+ -+#define VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl, chan) \ -+ start = drm_color_lut_extract(lut[i * step].chan, 12); \ -+ end = drm_color_lut_extract(lut[(i + 1) * step - 1].chan, 12); \ -+ \ -+ /* Negative gradients not permitted by the hardware, so \ -+ * flatten such points out. \ -+ */ \ -+ if (end < start) \ -+ end = start; \ -+ \ -+ /* Assume 12bit pipeline. \ -+ * X evenly spread over full range (12 bit). \ -+ * C as U12.4 format. \ -+ * Gradient as U4.8 format. \ -+ */ \ -+ vc4_crtc->pwl[i] = \ -+ VC5_HVS_SET_GAMMA_ENTRY(i << 8, start << 4, \ -+ ((end - start) << 4) / (step - 1)) -+ -+ /* HVS5 has a 16 point piecewise linear function for each colour -+ * channel (including alpha on channel 2) on each display channel. -+ * -+ * Currently take a crude subsample of the gamma LUT, but this could -+ * be improved to implement curve fitting. -+ */ -+ step = crtc->gamma_size / SCALER5_DSPGAMMA_NUM_POINTS; -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++) { -+ VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl_r, red); -+ VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl_g, green); -+ VC5_HVS_UPDATE_GAMMA_ENTRY_FROM_LUT(pwl_b, blue); -+ } -+ -+ vc5_hvs_lut_load(crtc); -+} -+ - int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output) - { - struct vc4_dev *vc4 = to_vc4_dev(dev); -@@ -329,14 +403,16 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc, - dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE; - - HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx | -- SCALER_DISPBKGND_AUTOHS | -- ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) | -+ SCALER_DISPBKGND_AUTOHS | SCALER_DISPBKGND_GAMMA | - (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); - - /* Reload the LUT, since the SRAMs would have been disabled if - * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once. - */ -- vc4_hvs_lut_load(crtc); -+ if (!vc4->hvs->hvs5) -+ vc4_hvs_lut_load(crtc); -+ else -+ vc5_hvs_lut_load(crtc); - - return 0; - } -@@ -534,7 +610,10 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, - u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)); - - if (crtc->state->gamma_lut) { -- vc4_hvs_update_gamma_lut(crtc); -+ if (!vc4->hvs->hvs5) -+ vc4_hvs_update_gamma_lut(crtc); -+ else -+ vc5_hvs_update_gamma_lut(crtc); - dispbkgndx |= SCALER_DISPBKGND_GAMMA; - } else { - /* Unsetting DISPBKGND_GAMMA skips the gamma lut step -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 7538b84a6dca..5989b2ff28c7 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -491,6 +491,28 @@ - #define SCALER_DLIST_START 0x00002000 - #define SCALER_DLIST_SIZE 0x00004000 - -+/* Gamma PWL for each channel. 16 points for each of 4 colour channels (alpha -+ * only on channel 2). 8 bytes per entry, offsets first, then gradient: -+ * Y = GRAD * X + C -+ * -+ * Values for X and C are left justified, and vary depending on the width of -+ * the HVS channel: -+ * 8-bit pipeline: X uses [31:24], C is U8.8 format, and GRAD is U4.8. -+ * 12-bit pipeline: X uses [31:20], C is U12.4 format, and GRAD is U4.8. -+ * -+ * The 3 HVS channels start at 0x400 offsets (ie chan 1 starts at 0x2400, and -+ * chan 2 at 0x2800). -+ */ -+#define SCALER5_DSPGAMMA_NUM_POINTS 16 -+#define SCALER5_DSPGAMMA_START 0x00002000 -+#define SCALER5_DSPGAMMA_CHAN_OFFSET 0x400 -+# define SCALER5_DSPGAMMA_OFF_X_MASK VC4_MASK(31, 20) -+# define SCALER5_DSPGAMMA_OFF_X_SHIFT 20 -+# define SCALER5_DSPGAMMA_OFF_C_MASK VC4_MASK(15, 0) -+# define SCALER5_DSPGAMMA_OFF_C_SHIFT 0 -+# define SCALER5_DSPGAMMA_GRAD_MASK VC4_MASK(11, 0) -+# define SCALER5_DSPGAMMA_GRAD_SHIFT 0 -+ - #define SCALER5_DLIST_START 0x00004000 - - # define VC4_HDMI_SW_RESET_FORMAT_DETECT BIT(1) --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0595-drm-vc4-Add-debugfs-node-that-dumps-the-vc5-gamma-PW.patch b/root/target/linux/bcm27xx/patches-5.15/0595-drm-vc4-Add-debugfs-node-that-dumps-the-vc5-gamma-PW.patch deleted file mode 100644 index 459b594e..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0595-drm-vc4-Add-debugfs-node-that-dumps-the-vc5-gamma-PW.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 07731742ce0c5d4f90d87a475df32165f6dcdfbf Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 28 Apr 2021 12:32:10 +0200 -Subject: [PATCH 595/634] drm/vc4: Add debugfs node that dumps the vc5 gamma - PWL entries - -This helps with debugging the conversion from a 256 point gamma LUT to -16 point PWL entries as used by the BCM2711. - -Co-developed-by: Juerg Haefliger -Signed-off-by: Juerg Haefliger -Signed-off-by: Dave Stevenson -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_hvs.c | 81 +++++++++++++++++++++++++++++++++++ - 1 file changed, 81 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index 73751bd6775a..6fbf26e9f113 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -134,6 +134,84 @@ static int vc4_hvs_debugfs_dlist(struct seq_file *m, void *data) - return 0; - } - -+static int vc5_hvs_debugfs_gamma(struct seq_file *m, void *data) -+{ -+ struct drm_info_node *node = m->private; -+ struct drm_device *dev = node->minor->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ struct drm_printer p = drm_seq_file_printer(m); -+ unsigned int i, chan; -+ u32 dispstat, dispbkgndx; -+ -+ for (chan = 0; chan < SCALER_CHANNELS_COUNT; chan++) { -+ u32 x_c, grad; -+ u32 offset = SCALER5_DSPGAMMA_START + -+ chan * SCALER5_DSPGAMMA_CHAN_OFFSET; -+ -+ dispstat = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)), -+ SCALER_DISPSTATX_MODE); -+ if (dispstat == SCALER_DISPSTATX_MODE_DISABLED || -+ dispstat == SCALER_DISPSTATX_MODE_EOF) { -+ drm_printf(&p, "HVS channel %u: Channel disabled\n", chan); -+ continue; -+ } -+ -+ dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan)); -+ if (!(dispbkgndx & SCALER_DISPBKGND_GAMMA)) { -+ drm_printf(&p, "HVS channel %u: Gamma disabled\n", chan); -+ continue; -+ } -+ -+ drm_printf(&p, "HVS channel %u:\n", chan); -+ drm_printf(&p, " red:\n"); -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) { -+ x_c = HVS_READ(offset); -+ grad = HVS_READ(offset + 4); -+ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n", -+ x_c, grad, -+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X), -+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C), -+ grad); -+ } -+ drm_printf(&p, " green:\n"); -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) { -+ x_c = HVS_READ(offset); -+ grad = HVS_READ(offset + 4); -+ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n", -+ x_c, grad, -+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X), -+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C), -+ grad); -+ } -+ drm_printf(&p, " blue:\n"); -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) { -+ x_c = HVS_READ(offset); -+ grad = HVS_READ(offset + 4); -+ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n", -+ x_c, grad, -+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X), -+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C), -+ grad); -+ } -+ -+ /* Alpha only valid on channel 2 */ -+ if (chan != 2) -+ continue; -+ -+ drm_printf(&p, " alpha:\n"); -+ for (i = 0; i < SCALER5_DSPGAMMA_NUM_POINTS; i++, offset += 8) { -+ x_c = HVS_READ(offset); -+ grad = HVS_READ(offset + 4); -+ drm_printf(&p, " %08x %08x - x %u, c %u, grad %u\n", -+ x_c, grad, -+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_X), -+ VC4_GET_FIELD(x_c, SCALER5_DSPGAMMA_OFF_C), -+ grad); -+ } -+ } -+ return 0; -+} -+ - /* The filter kernel is composed of dwords each containing 3 9-bit - * signed integers packed next to each other. - */ -@@ -809,6 +887,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) - NULL); - vc4_debugfs_add_file(drm, "hvs_dlists", vc4_hvs_debugfs_dlist, - NULL); -+ if (hvs->hvs5) -+ vc4_debugfs_add_file(drm, "hvs_gamma", vc5_hvs_debugfs_gamma, -+ NULL); - - return 0; - } --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0596-drm-vc4-hvs-Force-modeset-on-gamma-lut-change.patch b/root/target/linux/bcm27xx/patches-5.15/0596-drm-vc4-hvs-Force-modeset-on-gamma-lut-change.patch deleted file mode 100644 index 53054aeb..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0596-drm-vc4-hvs-Force-modeset-on-gamma-lut-change.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 6c2da4ae666989c7a534115287b8a587230fea02 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 14 Jun 2021 15:28:30 +0200 -Subject: [PATCH 596/634] drm/vc4: hvs: Force modeset on gamma lut change - -The HVS Gamma block can only be updated when idle, so we need to disable -the HVS channel when the gamma property is set in an atomic commit. - -Since the pixelvalve cannot have its assigned channel halted without -stalling unless it's disabled as well, in our case that means forcing a -full disable / enable cycle on the pipeline. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 17 +++++++++++++++++ - drivers/gpu/drm/vc4/vc4_drv.h | 3 +++ - drivers/gpu/drm/vc4/vc4_hvs.c | 32 +++++++++++++++++++++++++++++++- - 3 files changed, 51 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index e06801557cec..8a081fa0c366 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -294,6 +294,23 @@ struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, - return NULL; - } - -+#define drm_for_each_connector_mask(connector, dev, connector_mask) \ -+ list_for_each_entry((connector), &(dev)->mode_config.connector_list, head) \ -+ for_each_if ((connector_mask) & drm_connector_mask(connector)) -+ -+struct drm_connector *vc4_get_crtc_connector(struct drm_crtc *crtc, -+ struct drm_crtc_state *state) -+{ -+ struct drm_connector *connector; -+ -+ WARN_ON(hweight32(state->connector_mask) > 1); -+ -+ drm_for_each_connector_mask(connector, crtc->dev, state->connector_mask) -+ return connector; -+ -+ return NULL; -+} -+ - static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc) - { - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 56d014b91e4e..67a70d38e22e 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -568,6 +568,9 @@ vc4_crtc_to_vc4_pv_data(const struct vc4_crtc *crtc) - return container_of(data, struct vc4_pv_data, base); - } - -+struct drm_connector *vc4_get_crtc_connector(struct drm_crtc *crtc, -+ struct drm_crtc_state *state); -+ - struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc, - struct drm_crtc_state *state); - -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index 6fbf26e9f113..6372c48097d5 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -519,6 +519,36 @@ void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan) - SCALER_DISPSTATX_EMPTY); - } - -+static int vc4_hvs_gamma_check(struct drm_crtc *crtc, -+ struct drm_atomic_state *state) -+{ -+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); -+ struct drm_connector_state *conn_state; -+ struct drm_connector *connector; -+ struct drm_device *dev = crtc->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ -+ if (!vc4->hvs->hvs5) -+ return 0; -+ -+ if (!crtc_state->color_mgmt_changed) -+ return 0; -+ -+ connector = vc4_get_crtc_connector(crtc, crtc_state); -+ if (!connector) -+ return -EINVAL; -+ -+ if (!(connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)) -+ return 0; -+ -+ conn_state = drm_atomic_get_connector_state(state, connector); -+ if (!conn_state) -+ return -EINVAL; -+ -+ crtc_state->mode_changed = true; -+ return 0; -+} -+ - int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) - { - struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); -@@ -549,7 +579,7 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) - if (ret) - return ret; - -- return 0; -+ return vc4_hvs_gamma_check(crtc, state); - } - - static void vc4_hvs_update_dlist(struct drm_crtc *crtc) --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0598-drm-vc4-Relax-VEC-modeline-requirements-and-add-prog.patch b/root/target/linux/bcm27xx/patches-5.15/0598-drm-vc4-Relax-VEC-modeline-requirements-and-add-prog.patch deleted file mode 100644 index 51a4aa07..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0598-drm-vc4-Relax-VEC-modeline-requirements-and-add-prog.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 017a412bded3979956f20d530db0128b772b925d Mon Sep 17 00:00:00 2001 -From: Mateusz Kwiatkowski -Date: Thu, 15 Jul 2021 01:08:08 +0200 -Subject: [PATCH 598/634] drm/vc4: Relax VEC modeline requirements and add - progressive mode support - -Make vc4_vec_encoder_atomic_check() accept arbitrary modelines, as long -as they result in somewhat sane output from the VEC. The bounds have -been determined empirically. Additionally, add support for the -progressive 262-line and 312-line modes. - -Signed-off-by: Mateusz Kwiatkowski ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 1 + - drivers/gpu/drm/vc4/vc4_vec.c | 97 ++++++++++++++++++++++++++++------ - 2 files changed, 83 insertions(+), 15 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 8a081fa0c366..65c53a10ed6d 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -410,6 +410,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode - CRTC_WRITE(PV_V_CONTROL, - PV_VCONTROL_CONTINUOUS | - (is_dsi ? PV_VCONTROL_DSI : 0)); -+ CRTC_WRITE(PV_VSYNCD_EVEN, 0); - } - - CRTC_WRITE(PV_VERTA, -diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c -index b684595a5d0b..661fac65b8a8 100644 ---- a/drivers/gpu/drm/vc4/vc4_vec.c -+++ b/drivers/gpu/drm/vc4/vc4_vec.c -@@ -423,18 +423,11 @@ static int vc4_vec_connector_atomic_check(struct drm_connector *conn, - struct drm_connector_state *new_state = - drm_atomic_get_new_connector_state(state, conn); - -- const struct vc4_vec_tv_mode *vec_mode = -- &vc4_vec_tv_modes[new_state->tv.mode]; -- -- if (new_state->crtc) { -+ if (new_state->crtc && old_state->tv.mode != new_state->tv.mode) { - struct drm_crtc_state *crtc_state = - drm_atomic_get_new_crtc_state(state, new_state->crtc); - -- if (!drm_mode_equal(vec_mode->mode, &crtc_state->mode)) -- return -EINVAL; -- -- if (old_state->tv.mode != new_state->tv.mode) -- crtc_state->mode_changed = true; -+ crtc_state->mode_changed = true; - } - - return 0; -@@ -559,7 +552,10 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) - VEC_WRITE(VEC_CLMP0_START, 0xac); - VEC_WRITE(VEC_CLMP0_END, 0xec); - VEC_WRITE(VEC_CONFIG2, -- VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS); -+ VEC_CONFIG2_UV_DIG_DIS | -+ VEC_CONFIG2_RGB_DIG_DIS | -+ ((encoder->crtc->state->adjusted_mode.flags & -+ DRM_MODE_FLAG_INTERLACE) ? 0 : VEC_CONFIG2_PROG_SCAN)); - VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD); - VEC_WRITE(VEC_DAC_CONFIG, vec->variant->dac_config); - -@@ -582,17 +578,88 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder) - } - - --static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder, -- const struct drm_display_mode *mode, -- struct drm_display_mode *adjusted_mode) -+static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) - { -- return true; -+ const struct drm_display_mode *reference_mode = -+ vc4_vec_tv_modes[conn_state->tv.mode].mode; -+ -+ if (crtc_state->adjusted_mode.crtc_clock != reference_mode->clock || -+ crtc_state->adjusted_mode.crtc_htotal != reference_mode->htotal || -+ crtc_state->adjusted_mode.crtc_hdisplay % 4 != 0 || -+ crtc_state->adjusted_mode.crtc_hsync_end - -+ crtc_state->adjusted_mode.crtc_hsync_start < 1) -+ return -EINVAL; -+ -+ switch (reference_mode->vtotal) { -+ case 525: -+ if (crtc_state->adjusted_mode.crtc_vdisplay < 1 || -+ crtc_state->adjusted_mode.crtc_vdisplay > 253 || -+ crtc_state->adjusted_mode.crtc_vsync_start - -+ crtc_state->adjusted_mode.crtc_vdisplay < 1 || -+ crtc_state->adjusted_mode.crtc_vsync_end - -+ crtc_state->adjusted_mode.crtc_vsync_start != 3 || -+ crtc_state->adjusted_mode.crtc_vtotal - -+ crtc_state->adjusted_mode.crtc_vsync_end < 4 || -+ crtc_state->adjusted_mode.crtc_vtotal > 262) -+ return -EINVAL; -+ -+ if ((crtc_state->adjusted_mode.flags & -+ DRM_MODE_FLAG_INTERLACE) && -+ (crtc_state->adjusted_mode.vdisplay % 2 != 0 || -+ crtc_state->adjusted_mode.vsync_start % 2 != 1 || -+ crtc_state->adjusted_mode.vsync_end % 2 != 1 || -+ crtc_state->adjusted_mode.vtotal % 2 != 1)) -+ return -EINVAL; -+ -+ /* progressive mode is hard-wired to 262 total lines */ -+ if (!(crtc_state->adjusted_mode.flags & -+ DRM_MODE_FLAG_INTERLACE) && -+ crtc_state->adjusted_mode.crtc_vtotal != 262) -+ return -EINVAL; -+ -+ break; -+ -+ case 625: -+ if (crtc_state->adjusted_mode.crtc_vdisplay < 1 || -+ crtc_state->adjusted_mode.crtc_vdisplay > 305 || -+ crtc_state->adjusted_mode.crtc_vsync_start - -+ crtc_state->adjusted_mode.crtc_vdisplay < 1 || -+ crtc_state->adjusted_mode.crtc_vsync_end - -+ crtc_state->adjusted_mode.crtc_vsync_start != 3 || -+ crtc_state->adjusted_mode.crtc_vtotal - -+ crtc_state->adjusted_mode.crtc_vsync_end < 2 || -+ crtc_state->adjusted_mode.crtc_vtotal > 312) -+ return -EINVAL; -+ -+ if ((crtc_state->adjusted_mode.flags & -+ DRM_MODE_FLAG_INTERLACE) && -+ (crtc_state->adjusted_mode.vdisplay % 2 != 0 || -+ crtc_state->adjusted_mode.vsync_start % 2 != 0 || -+ crtc_state->adjusted_mode.vsync_end % 2 != 0 || -+ crtc_state->adjusted_mode.vtotal % 2 != 1)) -+ return -EINVAL; -+ -+ /* progressive mode is hard-wired to 312 total lines */ -+ if (!(crtc_state->adjusted_mode.flags & -+ DRM_MODE_FLAG_INTERLACE) && -+ crtc_state->adjusted_mode.crtc_vtotal != 312) -+ return -EINVAL; -+ -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; - } - - static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = { - .disable = vc4_vec_encoder_disable, - .enable = vc4_vec_encoder_enable, -- .mode_fixup = vc4_vec_encoder_mode_fixup, -+ .atomic_check = vc4_vec_encoder_atomic_check, - }; - - static const struct vc4_vec_variant bcm2835_vec_variant = { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0599-drm-vc4-Make-VEC-progressive-modes-readily-accessibl.patch b/root/target/linux/bcm27xx/patches-5.15/0599-drm-vc4-Make-VEC-progressive-modes-readily-accessibl.patch deleted file mode 100644 index 79214693..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0599-drm-vc4-Make-VEC-progressive-modes-readily-accessibl.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 4bcf5e8ac14bf77216868a165cac0a414d0d5687 Mon Sep 17 00:00:00 2001 -From: Mateusz Kwiatkowski -Date: Thu, 15 Jul 2021 01:08:11 +0200 -Subject: [PATCH 599/634] drm/vc4: Make VEC progressive modes readily - accessible - -Add predefined modelines for the 240p (NTSC) and 288p (PAL) progressive -modes, and report them through vc4_vec_connector_get_modes(). - -Signed-off-by: Mateusz Kwiatkowski ---- - drivers/gpu/drm/vc4/vc4_vec.c | 73 ++++++++++++++++++++++++++--------- - 1 file changed, 55 insertions(+), 18 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c -index 661fac65b8a8..d263fdaa1ee8 100644 ---- a/drivers/gpu/drm/vc4/vc4_vec.c -+++ b/drivers/gpu/drm/vc4/vc4_vec.c -@@ -245,7 +245,8 @@ enum vc4_vec_tv_mode_id { - }; - - struct vc4_vec_tv_mode { -- const struct drm_display_mode *mode; -+ const struct drm_display_mode *interlaced_mode; -+ const struct drm_display_mode *progressive_mode; - u32 config0; - u32 config1; - u32 custom_freq; -@@ -279,61 +280,81 @@ static const struct debugfs_reg32 vec_regs[] = { - }; - - static const struct drm_display_mode drm_mode_480i = { -- DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, -+ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, - 480, 480 + 7, 480 + 7 + 6, 525, 0, - DRM_MODE_FLAG_INTERLACE) - }; - -+static const struct drm_display_mode drm_mode_240p = { -+ DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 13500, -+ 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, -+ 240, 240 + 3, 240 + 3 + 3, 262, 0, 0) -+}; -+ - static const struct drm_display_mode drm_mode_576i = { -- DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, -+ DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, - 576, 576 + 4, 576 + 4 + 6, 625, 0, - DRM_MODE_FLAG_INTERLACE) - }; - -+static const struct drm_display_mode drm_mode_288p = { -+ DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 13500, -+ 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, -+ 288, 288 + 2, 288 + 2 + 3, 312, 0, 0) -+}; -+ - static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { - [VC4_VEC_TV_MODE_NTSC] = { -- .mode = &drm_mode_480i, -+ .interlaced_mode = &drm_mode_480i, -+ .progressive_mode = &drm_mode_240p, - .config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_NTSC_J] = { -- .mode = &drm_mode_480i, -+ .interlaced_mode = &drm_mode_480i, -+ .progressive_mode = &drm_mode_240p, - .config0 = VEC_CONFIG0_NTSC_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_NTSC_443] = { - /* NTSC with PAL chroma frequency */ -- .mode = &drm_mode_480i, -+ .interlaced_mode = &drm_mode_480i, -+ .progressive_mode = &drm_mode_240p, - .config0 = VEC_CONFIG0_NTSC_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ, - .custom_freq = 0x2a098acb, - }, - [VC4_VEC_TV_MODE_PAL] = { -- .mode = &drm_mode_576i, -+ .interlaced_mode = &drm_mode_576i, -+ .progressive_mode = &drm_mode_288p, - .config0 = VEC_CONFIG0_PAL_BDGHI_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_PAL_M] = { -- .mode = &drm_mode_480i, -+ .interlaced_mode = &drm_mode_480i, -+ .progressive_mode = &drm_mode_240p, - .config0 = VEC_CONFIG0_PAL_M_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_PAL_N] = { -- .mode = &drm_mode_576i, -+ .interlaced_mode = &drm_mode_576i, -+ .progressive_mode = &drm_mode_288p, - .config0 = VEC_CONFIG0_PAL_N_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - }, - [VC4_VEC_TV_MODE_PAL60] = { - /* PAL-M with chroma frequency of regular PAL */ -- .mode = &drm_mode_480i, -+ .interlaced_mode = &drm_mode_480i, -+ .progressive_mode = &drm_mode_240p, - .config0 = VEC_CONFIG0_PAL_M_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ, - .custom_freq = 0x2a098acb, - }, - [VC4_VEC_TV_MODE_SECAM] = { -- .mode = &drm_mode_576i, -+ .interlaced_mode = &drm_mode_576i, -+ .progressive_mode = &drm_mode_288p, - .config0 = VEC_CONFIG0_SECAM_STD, - .config1 = VEC_CONFIG1_C_CVBS_CVBS, - .custom_freq = 0x29c71c72, -@@ -393,16 +414,32 @@ static void vc4_vec_connector_destroy(struct drm_connector *connector) - static int vc4_vec_connector_get_modes(struct drm_connector *connector) - { - struct drm_connector_state *state = connector->state; -- struct drm_display_mode *mode; -- -- mode = drm_mode_duplicate(connector->dev, -- vc4_vec_tv_modes[state->tv.mode].mode); -- if (!mode) { -+ struct drm_display_mode *interlaced_mode, *progressive_mode; -+ -+ interlaced_mode = -+ drm_mode_duplicate(connector->dev, -+ vc4_vec_tv_modes[state->tv.mode].interlaced_mode); -+ progressive_mode = -+ drm_mode_duplicate(connector->dev, -+ vc4_vec_tv_modes[state->tv.mode].progressive_mode); -+ if (!interlaced_mode || !progressive_mode) { - DRM_ERROR("Failed to create a new display mode\n"); -+ drm_mode_destroy(connector->dev, interlaced_mode); -+ drm_mode_destroy(connector->dev, progressive_mode); - return -ENOMEM; - } - -- drm_mode_probed_add(connector, mode); -+ if (connector->cmdline_mode.specified && -+ connector->cmdline_mode.refresh_specified && -+ !connector->cmdline_mode.interlace) -+ /* progressive mode set at boot, let's make it preferred */ -+ progressive_mode->type |= DRM_MODE_TYPE_PREFERRED; -+ else -+ /* otherwise, interlaced mode is preferred */ -+ interlaced_mode->type |= DRM_MODE_TYPE_PREFERRED; -+ -+ drm_mode_probed_add(connector, interlaced_mode); -+ drm_mode_probed_add(connector, progressive_mode); - - return 1; - } -@@ -583,7 +620,7 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, - struct drm_connector_state *conn_state) - { - const struct drm_display_mode *reference_mode = -- vc4_vec_tv_modes[conn_state->tv.mode].mode; -+ vc4_vec_tv_modes[conn_state->tv.mode].interlaced_mode; - - if (crtc_state->adjusted_mode.crtc_clock != reference_mode->clock || - crtc_state->adjusted_mode.crtc_htotal != reference_mode->htotal || --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0610-drm-vc4-kms-Add-missing-drm_crtc_commit_put.patch b/root/target/linux/bcm27xx/patches-5.15/0610-drm-vc4-kms-Add-missing-drm_crtc_commit_put.patch deleted file mode 100644 index e60e6615..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0610-drm-vc4-kms-Add-missing-drm_crtc_commit_put.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 34b3c67f34338cbdf08d927dbbedbb9074bb072d Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 27 Aug 2021 18:20:25 +0200 -Subject: [PATCH 610/634] drm/vc4: kms: Add missing drm_crtc_commit_put - -Commit 9ec03d7f1ed3 ("drm/vc4: kms: Wait on previous FIFO users before a -commit") introduced a global state for the HVS, with each FIFO storing -the current CRTC commit so that we can properly synchronize commits. - -However, the refcounting was off and we thus ended up leaking the -drm_crtc_commit structure every commit. Add a drm_crtc_commit_put to -prevent the leakage. - -Fixes: 9ec03d7f1ed3 ("drm/vc4: kms: Wait on previous FIFO users before a commit") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_kms.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 2511113a6f82..8c63b962b2e6 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -389,6 +389,8 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - ret = drm_crtc_commit_wait(commit); - if (ret) - drm_err(dev, "Timed out waiting for commit\n"); -+ -+ drm_crtc_commit_put(commit); - } - - if (vc4->hvs && vc4->hvs->hvs5) { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0611-drm-vc4-kms-Fix-return-code-check.patch b/root/target/linux/bcm27xx/patches-5.15/0611-drm-vc4-kms-Fix-return-code-check.patch deleted file mode 100644 index 8da2332a..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0611-drm-vc4-kms-Fix-return-code-check.patch +++ /dev/null @@ -1,69 +0,0 @@ -From e77ab08dffd64552b5f22ec0ba2d9cf371475883 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 20 Oct 2021 13:31:22 +0200 -Subject: [PATCH 611/634] drm/vc4: kms: Fix return code check - -The HVS global state functions return an error pointer, but in most -cases we check if it's NULL, possibly resulting in an invalid pointer -dereference. - -Fixes: 9ec03d7f1ed3 ("drm/vc4: kms: Wait on previous FIFO users before a commit") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_kms.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 8c63b962b2e6..82462d4c4853 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -352,11 +352,11 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - int i; - - old_hvs_state = vc4_hvs_get_old_global_state(state); -- if (WARN_ON(!old_hvs_state)) -+ if (WARN_ON(IS_ERR(old_hvs_state))) - return; - - new_hvs_state = vc4_hvs_get_new_global_state(state); -- if (WARN_ON(!new_hvs_state)) -+ if (WARN_ON(IS_ERR(new_hvs_state))) - return; - - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { -@@ -470,8 +470,8 @@ static int vc4_atomic_commit_setup(struct drm_atomic_state *state) - state->legacy_cursor_update = false; - - hvs_state = vc4_hvs_get_new_global_state(state); -- if (!hvs_state) -- return -EINVAL; -+ if (WARN_ON(IS_ERR(hvs_state))) -+ return PTR_ERR(hvs_state); - - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { - struct vc4_crtc_state *vc4_crtc_state = -@@ -816,8 +816,8 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, - unsigned int i; - - hvs_new_state = vc4_hvs_get_global_state(state); -- if (!hvs_new_state) -- return -EINVAL; -+ if (IS_ERR(hvs_new_state)) -+ return PTR_ERR(hvs_new_state); - - for (i = 0; i < ARRAY_SIZE(hvs_new_state->fifo_state); i++) - if (!hvs_new_state->fifo_state[i].in_use) -@@ -909,8 +909,8 @@ vc4_core_clock_atomic_check(struct drm_atomic_state *state) - load_state = to_vc4_load_tracker_state(priv_state); - - hvs_new_state = vc4_hvs_get_global_state(state); -- if (!hvs_new_state) -- return -EINVAL; -+ if (IS_ERR(hvs_new_state)) -+ return PTR_ERR(hvs_new_state); - - for_each_oldnew_crtc_in_state(state, crtc, - old_crtc_state, --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0612-drm-vc4-kms-Clear-the-HVS-FIFO-commit-pointer-once-d.patch b/root/target/linux/bcm27xx/patches-5.15/0612-drm-vc4-kms-Clear-the-HVS-FIFO-commit-pointer-once-d.patch deleted file mode 100644 index 4522a50f..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0612-drm-vc4-kms-Clear-the-HVS-FIFO-commit-pointer-once-d.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 1adf064f5c8a44ae56bc609a7648f384363a3df4 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 21 Oct 2021 13:57:25 +0200 -Subject: [PATCH 612/634] drm/vc4: kms: Clear the HVS FIFO commit pointer once - done - -Commit 9ec03d7f1ed3 ("drm/vc4: kms: Wait on previous FIFO users before a -commit") introduced a wait on the previous commit done on a given HVS -FIFO. - -However, we never cleared that pointer once done. Since -drm_crtc_commit_put can free the drm_crtc_commit structure directly if -we were the last user, this means that it can lead to a use-after free -if we were to duplicate the state, and that stale pointer would even be -copied to the new state. - -Set the pointer to NULL once we're done with the wait so that we don't -carry over a pointer to a free'd structure. - -Fixes: 9ec03d7f1ed3 ("drm/vc4: kms: Wait on previous FIFO users before a commit") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_kms.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 82462d4c4853..59f10c4d76ae 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -391,6 +391,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - drm_err(dev, "Timed out waiting for commit\n"); - - drm_crtc_commit_put(commit); -+ old_hvs_state->fifo_state[channel].pending_commit = NULL; - } - - if (vc4->hvs && vc4->hvs->hvs5) { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0613-drm-vc4-kms-Don-t-duplicate-pending-commit.patch b/root/target/linux/bcm27xx/patches-5.15/0613-drm-vc4-kms-Don-t-duplicate-pending-commit.patch deleted file mode 100644 index de0f170b..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0613-drm-vc4-kms-Don-t-duplicate-pending-commit.patch +++ /dev/null @@ -1,42 +0,0 @@ -From ff06c5211fc9921c45ed2fe23f43ff2e8656c402 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 21 Oct 2021 13:57:44 +0200 -Subject: [PATCH 613/634] drm/vc4: kms: Don't duplicate pending commit - -Our HVS global state, when duplicated, will also copy the pointer to the -drm_crtc_commit (and increase the reference count) for each FIFO if the -pointer is not NULL. - -However, our atomic_setup function will overwrite that pointer without -putting the reference back leading to a memory leak. - -Since the commit is only relevant during the atomic commit process, it -doesn't make sense to duplicate the reference to the commit anyway. -Let's remove it. - -Fixes: 9ec03d7f1ed3 ("drm/vc4: kms: Wait on previous FIFO users before a commit") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_kms.c | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 59f10c4d76ae..2ac6c7c66fc2 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -720,12 +720,6 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) - for (i = 0; i < HVS_NUM_CHANNELS; i++) { - state->fifo_state[i].in_use = old_state->fifo_state[i].in_use; - state->fifo_state[i].fifo_load = old_state->fifo_state[i].fifo_load; -- -- if (!old_state->fifo_state[i].pending_commit) -- continue; -- -- state->fifo_state[i].pending_commit = -- drm_crtc_commit_get(old_state->fifo_state[i].pending_commit); - } - - state->core_clock_rate = old_state->core_clock_rate; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0614-drm-vc4-kms-Fix-previous-HVS-commit-wait.patch b/root/target/linux/bcm27xx/patches-5.15/0614-drm-vc4-kms-Fix-previous-HVS-commit-wait.patch deleted file mode 100644 index 6b183e65..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0614-drm-vc4-kms-Fix-previous-HVS-commit-wait.patch +++ /dev/null @@ -1,89 +0,0 @@ -From dd7d827b5466f4820a477484c25a28a309d43b20 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 5 Nov 2021 10:51:25 +0100 -Subject: [PATCH 614/634] drm/vc4: kms: Fix previous HVS commit wait - -Our current code is supposed to serialise the commits by waiting for all -the drm_crtc_commits associated to the previous HVS state. - -However, assuming we have two CRTCs running and being configured and we -configure each one alternatively, we end up in a situation where we're -not waiting at all. - -Indeed, starting with a state (state 0) where both CRTCs are running, -and doing a commit (state 1) on the first CRTC (CRTC 0), we'll associate -its commit to its assigned FIFO in vc4_hvs_state. - -If we get a new commit (state 2), this time affecting the second CRTC -(CRTC 1), the DRM core will allow both commits to execute in parallel -(assuming they don't have any share resources). - -Our code in vc4_atomic_commit_tail is supposed to make sure we only get -one commit at a time and serialised by order of submission. It does so -by using for_each_old_crtc_in_state, making sure that the CRTC has a -FIFO assigned, is used, and has a commit pending. If it does, then we'll -wait for the commit before going forward. - -During the transition from state 0 to state 1, as our old CRTC state we -get the CRTC 0 state 0, its commit, we wait for it, everything works fine. - -During the transition from state 1 to state 2 though, the use of -for_each_old_crtc_in_state is wrong. Indeed, while the code assumes it's -returning the state of the CRTC in the old state (so CRTC 0 state 1), it -actually returns the old state of the CRTC affected by the current -commit, so CRTC 0 state 0 since it wasn't part of state 1. - -Due to this, if we alternate between the configuration of CRTC 0 and -CRTC 1, we never actually wait for anything since we should be waiting -on the other every time, but it never is affected by the previous -commit. - -Change the logic to, at every commit, look at every FIFO in the previous -HVS state, and if it's in use and has a commit associated to it, wait -for that commit. - -Fixes: 9ec03d7f1ed3 ("drm/vc4: kms: Wait on previous FIFO users before a commit") -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_kms.c | 10 ++-------- - 1 file changed, 2 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 2ac6c7c66fc2..2721a0f61dc0 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -343,12 +343,12 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - struct drm_device *dev = state->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hvs *hvs = vc4->hvs; -- struct drm_crtc_state *old_crtc_state; - struct drm_crtc_state *new_crtc_state; - struct vc4_hvs_state *new_hvs_state; - struct drm_crtc *crtc; - struct vc4_hvs_state *old_hvs_state; - struct clk_request *core_req; -+ unsigned int channel; - int i; - - old_hvs_state = vc4_hvs_get_old_global_state(state); -@@ -369,16 +369,10 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); - } - -- for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { -- struct vc4_crtc_state *vc4_crtc_state = -- to_vc4_crtc_state(old_crtc_state); -+ for (channel = 0; channel < HVS_NUM_CHANNELS; channel++) { - struct drm_crtc_commit *commit; -- unsigned int channel = vc4_crtc_state->assigned_channel; - int ret; - -- if (channel == VC4_HVS_CHANNEL_DISABLED) -- continue; -- - if (!old_hvs_state->fifo_state[channel].in_use) - continue; - --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0615-drm-vc4-kms-Move-clock-request-to-our-HVS-state.patch b/root/target/linux/bcm27xx/patches-5.15/0615-drm-vc4-kms-Move-clock-request-to-our-HVS-state.patch deleted file mode 100644 index e1bfc152..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0615-drm-vc4-kms-Move-clock-request-to-our-HVS-state.patch +++ /dev/null @@ -1,66 +0,0 @@ -From fec8348360a6326272064885cfe94b2695f94864 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 4 Nov 2021 14:04:37 +0100 -Subject: [PATCH 615/634] drm/vc4: kms: Move clock request to our HVS state - -Our current clock request has been stored so far on the main HVS -structure, but even though we shouldn't have two commits in parallel and -it shouldn't cause any functional change, the request itself is linked -to a given HVS state. - -Move the request there to make a bit more sense. - -Signed-off-by: Maxime Ripard ---- - drivers/gpu/drm/vc4/vc4_drv.h | 1 - - drivers/gpu/drm/vc4/vc4_kms.c | 8 +++++--- - 2 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 67a70d38e22e..81bca15b31e2 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -326,7 +326,6 @@ struct vc4_hvs { - u32 __iomem *dlist; - - struct clk *core_clk; -- struct clk_request *core_req; - - /* Memory manager for CRTCs to allocate space in the display - * list. Units are dwords. -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index 2721a0f61dc0..77c2a7ce5ef6 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -40,6 +40,7 @@ static struct vc4_ctm_state *to_vc4_ctm_state(struct drm_private_state *priv) - struct vc4_hvs_state { - struct drm_private_state base; - unsigned long core_clock_rate; -+ struct clk_request *core_req; - - struct { - unsigned in_use: 1; -@@ -405,7 +406,8 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - * And remove the previous one based on the HVS - * requirements if any. - */ -- clk_request_done(hvs->core_req); -+ clk_request_done(old_hvs_state->core_req); -+ old_hvs_state->core_req = NULL; - } - - drm_atomic_helper_commit_modeset_disables(dev, state); -@@ -439,8 +441,8 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - * Request a clock rate based on the current HVS - * requirements. - */ -- hvs->core_req = clk_request_start(hvs->core_clk, -- new_hvs_state->core_clock_rate); -+ new_hvs_state->core_req = clk_request_start(hvs->core_clk, -+ new_hvs_state->core_clock_rate); - - /* And drop the temporary request */ - clk_request_done(core_req); --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0625-drm-vc4-Enable-gamma-block-only-when-required.patch b/root/target/linux/bcm27xx/patches-5.15/0625-drm-vc4-Enable-gamma-block-only-when-required.patch deleted file mode 100644 index a57775c0..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0625-drm-vc4-Enable-gamma-block-only-when-required.patch +++ /dev/null @@ -1,71 +0,0 @@ -From cc93e4c6e01d1274e1e241d45265bb88405697c1 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 8 Nov 2021 17:32:45 +0000 -Subject: [PATCH 625/634] drm/vc4: Enable gamma block only when required. - -With HVS5 the gamma block is now only reprogrammed with -a disable/enable. Loading the table from vc4_hvs_init_channel -(called from vc4_hvs_atomic_enable) appears to be at an -invalid point in time and so isn't applied. - -Switch to enabling and disabling the gamma table instead. This -isn't safe if the pipeline is running, but it isn't now. -For HVS4 it is safe to enable and disable dynamically, so -adopt that approach there too. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_hvs.c | 22 +++++++++++++++++----- - 1 file changed, 17 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index 6372c48097d5..1302260d7d87 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -480,8 +480,12 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc, - dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; - dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE; - -+ if (crtc->state->gamma_lut) -+ /* Enable gamma on if required */ -+ dispbkgndx |= SCALER_DISPBKGND_GAMMA; -+ - HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx | -- SCALER_DISPBKGND_AUTOHS | SCALER_DISPBKGND_GAMMA | -+ SCALER_DISPBKGND_AUTOHS | - (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); - - /* Reload the LUT, since the SRAMs would have been disabled if -@@ -718,17 +722,25 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, - u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)); - - if (crtc->state->gamma_lut) { -- if (!vc4->hvs->hvs5) -+ if (!vc4->hvs->hvs5) { - vc4_hvs_update_gamma_lut(crtc); -- else -+ dispbkgndx |= SCALER_DISPBKGND_GAMMA; -+ } else { - vc5_hvs_update_gamma_lut(crtc); -- dispbkgndx |= SCALER_DISPBKGND_GAMMA; -+ } - } else { - /* Unsetting DISPBKGND_GAMMA skips the gamma lut step - * in hardware, which is the same as a linear lut that - * DRM expects us to use in absence of a user lut. -+ * -+ * Do NOT change state dynamically for hvs5 as it -+ * inserts a delay in the pipeline that will cause -+ * stalls if enabled/disabled whilst running. The other -+ * should already be disabling/enabling the pipeline -+ * when gamma changes. - */ -- dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; -+ if (!vc4->hvs->hvs5) -+ dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; - } - HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx); - } --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0626-drm-vc4-Only-add-gamma-properties-once.patch b/root/target/linux/bcm27xx/patches-5.15/0626-drm-vc4-Only-add-gamma-properties-once.patch deleted file mode 100644 index 3336adaf..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0626-drm-vc4-Only-add-gamma-properties-once.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 35b77f70d93442750a907586fd1cf7b28331061a Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 8 Nov 2021 18:25:49 +0000 -Subject: [PATCH 626/634] drm/vc4: Only add gamma properties once. - -Two calls were made to drm_crtc_enable_color_mgmt to add gamma -and CTM, however they were both set to add the gamma properties, -so they ended up added twice. - -Fixes: 766cc6b1f7fc "drm/vc4: Add CTM support" -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index 65c53a10ed6d..cf4dcf8ef433 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -1194,7 +1194,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, - /* We support CTM, but only for one CRTC at a time. It's therefore - * implemented as private driver state in vc4_kms, not here. - */ -- drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size); -+ drm_crtc_enable_color_mgmt(crtc, 0, true, 0); - - /* Initialize the VC4 gamma LUTs */ - for (i = 0; i < crtc->gamma_size; i++) { --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0628-drm-vc4-Validate-the-size-of-the-gamma_lut.patch b/root/target/linux/bcm27xx/patches-5.15/0628-drm-vc4-Validate-the-size-of-the-gamma_lut.patch deleted file mode 100644 index 00851c6b..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0628-drm-vc4-Validate-the-size-of-the-gamma_lut.patch +++ /dev/null @@ -1,37 +0,0 @@ -From a528d57967f93fb0ae67e5e6a57074805d926928 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 10 Nov 2021 16:36:12 +0000 -Subject: [PATCH 628/634] drm/vc4: Validate the size of the gamma_lut - -Add a check to vc4_hvs_gamma_check to ensure a new non-empty -gamma LUT is of the correct length before accepting it. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_hvs.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index 1302260d7d87..a873d9d8fd58 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -538,6 +538,16 @@ static int vc4_hvs_gamma_check(struct drm_crtc *crtc, - if (!crtc_state->color_mgmt_changed) - return 0; - -+ if (crtc_state->gamma_lut) { -+ unsigned int len = drm_color_lut_size(crtc_state->gamma_lut); -+ -+ if (len != crtc->gamma_size) { -+ DRM_DEBUG_KMS("Invalid LUT size; got %u, expected %u\n", -+ len, crtc->gamma_size); -+ return -EINVAL; -+ } -+ } -+ - connector = vc4_get_crtc_connector(crtc, crtc_state); - if (!connector) - return -EINVAL; --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0629-drm-vc4-Don-t-try-disabling-SCDC-on-Pi0-3.patch b/root/target/linux/bcm27xx/patches-5.15/0629-drm-vc4-Don-t-try-disabling-SCDC-on-Pi0-3.patch deleted file mode 100644 index a560a567..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0629-drm-vc4-Don-t-try-disabling-SCDC-on-Pi0-3.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 7de6460aef7e0122b110b5ef38513fdea630c18c Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Tue, 16 Nov 2021 10:34:34 +0000 -Subject: [PATCH 629/634] drm/vc4: Don't try disabling SCDC on Pi0-3. - -The code that set the scdc_enabled flag to ensure it was -disabled at boot time also ran on Pi0-3 where there is no -SCDC support. This lead to a warning in vc4_hdmi_encoder_post_crtc_disable -due to vc4_hdmi_disable_scrambling being called and trying to -read (and write) register HDMI_SCRAMBLER_CTL which doesn't -exist on those platforms. - -Only set the flag should the interface be configured to support -more than HDMI 1.4. - -Signed-off-by: Dave Stevenson ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index a6afd7d7f21c..70a1beb67dda 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -2557,7 +2557,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) - * vc4_hdmi_disable_scrambling() will thus run at boot, make - * sure it's disabled, and avoid any inconsistency. - */ -- vc4_hdmi->scdc_enabled = true; -+ if (variant->max_pixel_clock > HDMI_14_MAX_TMDS_CLK) -+ vc4_hdmi->scdc_enabled = true; - - ret = variant->init_resources(vc4_hdmi); - if (ret) --- -2.33.1 - diff --git a/root/target/linux/bcm27xx/patches-5.15/0631-media-v4l2-core-fix-VIDIOC_DQEVENT-handling-on-non-x.patch b/root/target/linux/bcm27xx/patches-5.15/0631-media-v4l2-core-fix-VIDIOC_DQEVENT-handling-on-non-x.patch deleted file mode 100644 index f9491616..00000000 --- a/root/target/linux/bcm27xx/patches-5.15/0631-media-v4l2-core-fix-VIDIOC_DQEVENT-handling-on-non-x.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 58b75a603967b8de888949220993bafd65fcca60 Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Tue, 26 Oct 2021 06:49:54 +0100 -Subject: [PATCH 631/634] media: v4l2-core: fix VIDIOC_DQEVENT handling on - non-x86 - -My previous bugfix addressed an API inconsistency found by syzbot, -and it correctly fixed the issue on x86-64 machines, which now behave -correctly for both native and compat tasks. - -Unfortunately, John found that the patch broke compat mode on all other -architectures, as they can no longer rely on the VIDIOC_DQEVENT_TIME32 -code from the native handler as a fallback in the compat code. - -The best way I can see for addressing this is to generalize the -VIDIOC_DQEVENT32_TIME32 code from x86 and use that for all architectures, -leaving only the VIDIOC_DQEVENT32 variant as x86 specific. The original -code was trying to be clever and use the same conversion helper for native -32-bit code and compat mode, but that turned out to be too obscure so -even I missed that bit I had introduced myself when I made the fix. - -Fixes: c344f07aa1b4 ("media: v4l2-core: ignore native time32 ioctls on 64-bit") -Reported-by: John Stultz -Signed-off-by: Arnd Bergmann -Tested-by: John Stultz -Signed-off-by: Hans Verkuil -Signed-off-by: Mauro Carvalho Chehab ---- - drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 41 ++++++++----------- - 1 file changed, 17 insertions(+), 24 deletions(-) - -diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c -index 47aff3b19742..80aaf07b16f2 100644 ---- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c -+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c -@@ -744,10 +744,6 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64, - /* - * x86 is the only compat architecture with different struct alignment - * between 32-bit and 64-bit tasks. -- * -- * On all other architectures, v4l2_event32 and v4l2_event32_time32 are -- * the same as v4l2_event and v4l2_event_time32, so we can use the native -- * handlers, converting v4l2_event to v4l2_event_time32 if necessary. - */ - struct v4l2_event32 { - __u32 type; -@@ -765,21 +761,6 @@ struct v4l2_event32 { - __u32 reserved[8]; - }; - --#ifdef CONFIG_COMPAT_32BIT_TIME --struct v4l2_event32_time32 { -- __u32 type; -- union { -- compat_s64 value64; -- __u8 data[64]; -- } u; -- __u32 pending; -- __u32 sequence; -- struct old_timespec32 timestamp; -- __u32 id; -- __u32 reserved[8]; --}; --#endif -- - static int put_v4l2_event32(struct v4l2_event *p64, - struct v4l2_event32 __user *p32) - { -@@ -795,7 +776,22 @@ static int put_v4l2_event32(struct v4l2_event *p64, - return 0; - } - -+#endif -+ - #ifdef CONFIG_COMPAT_32BIT_TIME -+struct v4l2_event32_time32 { -+ __u32 type; -+ union { -+ compat_s64 value64; -+ __u8 data[64]; -+ } u; -+ __u32 pending; -+ __u32 sequence; -+ struct old_timespec32 timestamp; -+ __u32 id; -+ __u32 reserved[8]; -+}; -+ - static int put_v4l2_event32_time32(struct v4l2_event *p64, - struct v4l2_event32_time32 __user *p32) - { -@@ -811,7 +807,6 @@ static int put_v4l2_event32_time32(struct v4l2_event *p64, - return 0; - } - #endif --#endif - - struct v4l2_edid32 { - __u32 pad; -@@ -873,9 +868,7 @@ static int put_v4l2_edid32(struct v4l2_edid *p64, - #define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32) - #define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32) - #define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32) --#ifdef CONFIG_X86_64 - #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32) --#endif - #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32) - #endif - -@@ -929,10 +922,10 @@ unsigned int v4l2_compat_translate_cmd(unsigned int cmd) - #ifdef CONFIG_X86_64 - case VIDIOC_DQEVENT32: - return VIDIOC_DQEVENT; -+#endif - #ifdef CONFIG_COMPAT_32BIT_TIME - case VIDIOC_DQEVENT32_TIME32: - return VIDIOC_DQEVENT; --#endif - #endif - } - return cmd; -@@ -1025,10 +1018,10 @@ int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd) - #ifdef CONFIG_X86_64 - case VIDIOC_DQEVENT32: - return put_v4l2_event32(parg, arg); -+#endif - #ifdef CONFIG_COMPAT_32BIT_TIME - case VIDIOC_DQEVENT32_TIME32: - return put_v4l2_event32_time32(parg, arg); --#endif - #endif - } - return 0; --- -2.33.1 -