From 245cf523bfd83696e47bee61cf29ba7db6170cc6 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 9 Oct 2023 21:01:09 +0200 Subject: [PATCH 1/7] Allwinner: linux: remove hack, since it doesn't help --- ...or-lower-power-off-delay-to-1-second.patch | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 projects/Allwinner/patches/linux/0046-HACK-regulator-lower-power-off-delay-to-1-second.patch diff --git a/projects/Allwinner/patches/linux/0046-HACK-regulator-lower-power-off-delay-to-1-second.patch b/projects/Allwinner/patches/linux/0046-HACK-regulator-lower-power-off-delay-to-1-second.patch deleted file mode 100644 index ebe66405bc..0000000000 --- a/projects/Allwinner/patches/linux/0046-HACK-regulator-lower-power-off-delay-to-1-second.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Sun, 10 Sep 2023 12:08:31 +0200 -Subject: [PATCH] HACK: regulator: lower power off delay to 1 second - -Signed-off-by: Jernej Skrabec ---- - drivers/regulator/core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c -index d8e1caaf207e..b8d9409b77b8 100644 ---- a/drivers/regulator/core.c -+++ b/drivers/regulator/core.c -@@ -6285,7 +6285,7 @@ static int __init regulator_init_complete(void) - * command line option might be useful. - */ - schedule_delayed_work(®ulator_init_complete_work, -- msecs_to_jiffies(30000)); -+ msecs_to_jiffies(1000)); - - return 0; - } From 6718a19956dbfd841edee7affa83bbd5b0b63e1b Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 9 Oct 2023 21:01:30 +0200 Subject: [PATCH 2/7] Revert "Allwinner: atf: remove unneeded patch" This reverts commit 5002048ede2ae0805b2a87387d72b21619a96da0. --- ...i-Don-t-enable-referenced-regulators.patch | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 projects/Allwinner/patches/atf/0003-sunxi-Don-t-enable-referenced-regulators.patch diff --git a/projects/Allwinner/patches/atf/0003-sunxi-Don-t-enable-referenced-regulators.patch b/projects/Allwinner/patches/atf/0003-sunxi-Don-t-enable-referenced-regulators.patch new file mode 100644 index 0000000000..2de0cda61c --- /dev/null +++ b/projects/Allwinner/patches/atf/0003-sunxi-Don-t-enable-referenced-regulators.patch @@ -0,0 +1,22 @@ +From 89a2da7c8bae95cf9225015489736e2fc434f4d9 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 2 Jan 2021 16:35:31 +0100 +Subject: [PATCH] sunxi: Don't enable referenced regulators + +This break certain devices which need appropriate power on sequence. +--- + drivers/allwinner/axp/common.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/allwinner/axp/common.c ++++ b/drivers/allwinner/axp/common.c +@@ -112,9 +112,6 @@ static bool should_enable_regulator(const void *fdt, + if (is_node_disabled(fdt, node)) { + return false; + } +- if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) { +- return true; +- } + if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) { + return true; + } From 3855985fae06c89988389d752b3a24157ab687e1 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 9 Oct 2023 21:12:59 +0200 Subject: [PATCH 3/7] Allwinner: linux: reorganize patches --- ...08-firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch} | 0 ...col.patch => 0009-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch} | 0 ...patch => 0010-arm64-dts-allwinner-a64-Add-SCPI-protocol.patch} | 0 ....patch => 0011-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch} | 0 ...on.patch => 0012-ASoC-hdmi-codec-fix-channel-allocation.patch} | 0 ...=> 0013-drm_call_drm_atomic_helper_shutdown_at_shutdown.patch} | 0 ...rror.patch => 0014-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch} | 0 ...pport.patch => 0015-drm-sun4i-mixer-Add-caching-support.patch} | 0 ...pport-for-AC200.patch => 0016-mfd-Add-support-for-AC200.patch} | 0 ...0-EPHY.patch => 0017-net-phy-Add-support-for-AC200-EPHY.patch} | 0 ...030-wip-H6-deinterlace.patch => 0018-wip-H6-deinterlace.patch} | 0 ...s-h6-deinterlace.patch => 0019-arm64-dts-h6-deinterlace.patch} | 0 ...P-I2S-multi-channel.patch => 0020-WIP-I2S-multi-channel.patch} | 0 ...sound-card.patch => 0021-HACK-h3-h5-Add-HDMI-sound-card.patch} | 0 ...I-sound-card.patch => 0022-HACK-a64-Add-HDMI-sound-card.patch} | 0 ...bpi-m2u-analog-codec.patch => 0023-bpi-m2u-analog-codec.patch} | 0 ...042-r40-hdmi-audio-wip.patch => 0024-r40-hdmi-audio-wip.patch} | 0 ...MI-sound-card.patch => 0025-HACK-h6-Add-HDMI-sound-card.patch} | 0 ...PHY.patch => 0026-phy-handle-optional-regulator-for-PHY.patch} | 0 ...=> 0027-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch} | 0 ...028-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch} | 0 ...029-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch} | 0 ...> 0030-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch} | 0 ... 0031-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch} | 0 ...32-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch} | 0 ...2cs.patch => 0033-bluetooth-btrtl-add-hci-ver-rtl8822cs.patch} | 0 ...on.patch => 0034-HACK-Disable-MBUS-due-to-fw_devlink-on.patch} | 0 ...{0058-WIP-OPi3-DT-fixes.patch => 0035-WIP-OPi3-DT-fixes.patch} | 0 ...WIP-drm-bridge-synopsys-Fix-CEC-not-working-after-power.patch} | 0 ...tch => 0037-media--cedrus--Don-t-CPU-map-source-buffers.patch} | 0 .../{0065-wip-fix-H6-4k-60.patch => 0038-wip-fix-H6-4k-60.patch} | 0 ...h => 0039-arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch} | 0 ... => 0040-iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch} | 0 ...gePi-3-LTS-support.patch => 0041-OrangePi-3-LTS-support.patch} | 0 ...end.patch => 0042-tanix-mmc-rtw88-keep-power-in-suspend.patch} | 0 ...patch => 0043-Bluetooth-btrtl-Add-support-for-RTL8822BS.patch} | 0 ... 0044-ARM-dts-sun8i-r40-Add-interconnect-to-video-codec.patch} | 0 .../{0036-wip-h3-h5-cvbs.patch => 0045-wip-h3-h5-cvbs.patch} | 0 ...-for-H3.patch => 0046-HACK-SW-CEC-implementation-for-H3.patch} | 0 ...47-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch} | 0 40 files changed, 0 insertions(+), 0 deletions(-) rename projects/Allwinner/patches/linux/{0009-firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch => 0008-firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch} (100%) rename projects/Allwinner/patches/linux/{0010-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch => 0009-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch} (100%) rename projects/Allwinner/patches/linux/{0011-arm64-dts-allwinner-a64-Add-SCPI-protocol.patch => 0010-arm64-dts-allwinner-a64-Add-SCPI-protocol.patch} (100%) rename projects/Allwinner/patches/linux/{0012-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch => 0011-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch} (100%) rename projects/Allwinner/patches/linux/{0013-ASoC-hdmi-codec-fix-channel-allocation.patch => 0012-ASoC-hdmi-codec-fix-channel-allocation.patch} (100%) rename projects/Allwinner/patches/linux/{0014-drm_call_drm_atomic_helper_shutdown_at_shutdown.patch => 0013-drm_call_drm_atomic_helper_shutdown_at_shutdown.patch} (100%) rename projects/Allwinner/patches/linux/{0024-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch => 0014-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch} (100%) rename projects/Allwinner/patches/linux/{0027-drm-sun4i-mixer-Add-caching-support.patch => 0015-drm-sun4i-mixer-Add-caching-support.patch} (100%) rename projects/Allwinner/patches/linux/{0028-mfd-Add-support-for-AC200.patch => 0016-mfd-Add-support-for-AC200.patch} (100%) rename projects/Allwinner/patches/linux/{0029-net-phy-Add-support-for-AC200-EPHY.patch => 0017-net-phy-Add-support-for-AC200-EPHY.patch} (100%) rename projects/Allwinner/patches/linux/{0030-wip-H6-deinterlace.patch => 0018-wip-H6-deinterlace.patch} (100%) rename projects/Allwinner/patches/linux/{0031-arm64-dts-h6-deinterlace.patch => 0019-arm64-dts-h6-deinterlace.patch} (100%) rename projects/Allwinner/patches/linux/{0033-WIP-I2S-multi-channel.patch => 0020-WIP-I2S-multi-channel.patch} (100%) rename projects/Allwinner/patches/linux/{0034-HACK-h3-h5-Add-HDMI-sound-card.patch => 0021-HACK-h3-h5-Add-HDMI-sound-card.patch} (100%) rename projects/Allwinner/patches/linux/{0039-HACK-a64-Add-HDMI-sound-card.patch => 0022-HACK-a64-Add-HDMI-sound-card.patch} (100%) rename projects/Allwinner/patches/linux/{0041-bpi-m2u-analog-codec.patch => 0023-bpi-m2u-analog-codec.patch} (100%) rename projects/Allwinner/patches/linux/{0042-r40-hdmi-audio-wip.patch => 0024-r40-hdmi-audio-wip.patch} (100%) rename projects/Allwinner/patches/linux/{0043-HACK-h6-Add-HDMI-sound-card.patch => 0025-HACK-h6-Add-HDMI-sound-card.patch} (100%) rename projects/Allwinner/patches/linux/{0044-phy-handle-optional-regulator-for-PHY.patch => 0026-phy-handle-optional-regulator-for-PHY.patch} (100%) rename projects/Allwinner/patches/linux/{0045-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch => 0027-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch} (100%) rename projects/Allwinner/patches/linux/{0048-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch => 0028-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch} (100%) rename projects/Allwinner/patches/linux/{0049-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch => 0029-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch} (100%) rename projects/Allwinner/patches/linux/{0051-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch => 0030-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch} (100%) rename projects/Allwinner/patches/linux/{0052-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch => 0031-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch} (100%) rename projects/Allwinner/patches/linux/{0053-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch => 0032-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch} (100%) rename projects/Allwinner/patches/linux/{0056-bluetooth-btrtl-add-hci-ver-rtl8822cs.patch => 0033-bluetooth-btrtl-add-hci-ver-rtl8822cs.patch} (100%) rename projects/Allwinner/patches/linux/{0057-HACK-Disable-MBUS-due-to-fw_devlink-on.patch => 0034-HACK-Disable-MBUS-due-to-fw_devlink-on.patch} (100%) rename projects/Allwinner/patches/linux/{0058-WIP-OPi3-DT-fixes.patch => 0035-WIP-OPi3-DT-fixes.patch} (100%) rename projects/Allwinner/patches/linux/{0060-WIP-drm-bridge-synopsys-Fix-CEC-not-working-after-power.patch => 0036-WIP-drm-bridge-synopsys-Fix-CEC-not-working-after-power.patch} (100%) rename projects/Allwinner/patches/linux/{0061-media--cedrus--Don-t-CPU-map-source-buffers.patch => 0037-media--cedrus--Don-t-CPU-map-source-buffers.patch} (100%) rename projects/Allwinner/patches/linux/{0065-wip-fix-H6-4k-60.patch => 0038-wip-fix-H6-4k-60.patch} (100%) rename projects/Allwinner/patches/linux/{0066-arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch => 0039-arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch} (100%) rename projects/Allwinner/patches/linux/{0073-iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch => 0040-iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch} (100%) rename projects/Allwinner/patches/linux/{0077-OrangePi-3-LTS-support.patch => 0041-OrangePi-3-LTS-support.patch} (100%) rename projects/Allwinner/patches/linux/{0100-tanix-mmc-rtw88-keep-power-in-suspend.patch => 0042-tanix-mmc-rtw88-keep-power-in-suspend.patch} (100%) rename projects/Allwinner/patches/linux/{0101-Bluetooth-btrtl-Add-support-for-RTL8822BS.patch => 0043-Bluetooth-btrtl-Add-support-for-RTL8822BS.patch} (100%) rename projects/Allwinner/patches/linux/{0105-ARM-dts-sun8i-r40-Add-interconnect-to-video-codec.patch => 0044-ARM-dts-sun8i-r40-Add-interconnect-to-video-codec.patch} (100%) rename projects/Allwinner/patches/linux/{0036-wip-h3-h5-cvbs.patch => 0045-wip-h3-h5-cvbs.patch} (100%) rename projects/Allwinner/patches/linux/{0063-HACK-SW-CEC-implementation-for-H3.patch => 0046-HACK-SW-CEC-implementation-for-H3.patch} (100%) rename projects/Allwinner/patches/linux/{0075-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch => 0047-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch} (100%) diff --git a/projects/Allwinner/patches/linux/0009-firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch b/projects/Allwinner/patches/linux/0008-firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch similarity index 100% rename from projects/Allwinner/patches/linux/0009-firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch rename to projects/Allwinner/patches/linux/0008-firmware-arm_scpi-Support-unidirectional-mailbox-cha.patch diff --git a/projects/Allwinner/patches/linux/0010-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch b/projects/Allwinner/patches/linux/0009-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch similarity index 100% rename from projects/Allwinner/patches/linux/0010-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch rename to projects/Allwinner/patches/linux/0009-ARM-dts-sunxi-h3-h5-Add-SCPI-protocol.patch diff --git a/projects/Allwinner/patches/linux/0011-arm64-dts-allwinner-a64-Add-SCPI-protocol.patch b/projects/Allwinner/patches/linux/0010-arm64-dts-allwinner-a64-Add-SCPI-protocol.patch similarity index 100% rename from projects/Allwinner/patches/linux/0011-arm64-dts-allwinner-a64-Add-SCPI-protocol.patch rename to projects/Allwinner/patches/linux/0010-arm64-dts-allwinner-a64-Add-SCPI-protocol.patch diff --git a/projects/Allwinner/patches/linux/0012-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch b/projects/Allwinner/patches/linux/0011-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch similarity index 100% rename from projects/Allwinner/patches/linux/0012-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch rename to projects/Allwinner/patches/linux/0011-arm64-dts-allwinner-h6-Add-SCPI-protocol.patch diff --git a/projects/Allwinner/patches/linux/0013-ASoC-hdmi-codec-fix-channel-allocation.patch b/projects/Allwinner/patches/linux/0012-ASoC-hdmi-codec-fix-channel-allocation.patch similarity index 100% rename from projects/Allwinner/patches/linux/0013-ASoC-hdmi-codec-fix-channel-allocation.patch rename to projects/Allwinner/patches/linux/0012-ASoC-hdmi-codec-fix-channel-allocation.patch diff --git a/projects/Allwinner/patches/linux/0014-drm_call_drm_atomic_helper_shutdown_at_shutdown.patch b/projects/Allwinner/patches/linux/0013-drm_call_drm_atomic_helper_shutdown_at_shutdown.patch similarity index 100% rename from projects/Allwinner/patches/linux/0014-drm_call_drm_atomic_helper_shutdown_at_shutdown.patch rename to projects/Allwinner/patches/linux/0013-drm_call_drm_atomic_helper_shutdown_at_shutdown.patch diff --git a/projects/Allwinner/patches/linux/0024-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch b/projects/Allwinner/patches/linux/0014-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch similarity index 100% rename from projects/Allwinner/patches/linux/0024-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch rename to projects/Allwinner/patches/linux/0014-WIP-dw-hdmi-cec-sleep-100ms-on-error.patch diff --git a/projects/Allwinner/patches/linux/0027-drm-sun4i-mixer-Add-caching-support.patch b/projects/Allwinner/patches/linux/0015-drm-sun4i-mixer-Add-caching-support.patch similarity index 100% rename from projects/Allwinner/patches/linux/0027-drm-sun4i-mixer-Add-caching-support.patch rename to projects/Allwinner/patches/linux/0015-drm-sun4i-mixer-Add-caching-support.patch diff --git a/projects/Allwinner/patches/linux/0028-mfd-Add-support-for-AC200.patch b/projects/Allwinner/patches/linux/0016-mfd-Add-support-for-AC200.patch similarity index 100% rename from projects/Allwinner/patches/linux/0028-mfd-Add-support-for-AC200.patch rename to projects/Allwinner/patches/linux/0016-mfd-Add-support-for-AC200.patch diff --git a/projects/Allwinner/patches/linux/0029-net-phy-Add-support-for-AC200-EPHY.patch b/projects/Allwinner/patches/linux/0017-net-phy-Add-support-for-AC200-EPHY.patch similarity index 100% rename from projects/Allwinner/patches/linux/0029-net-phy-Add-support-for-AC200-EPHY.patch rename to projects/Allwinner/patches/linux/0017-net-phy-Add-support-for-AC200-EPHY.patch diff --git a/projects/Allwinner/patches/linux/0030-wip-H6-deinterlace.patch b/projects/Allwinner/patches/linux/0018-wip-H6-deinterlace.patch similarity index 100% rename from projects/Allwinner/patches/linux/0030-wip-H6-deinterlace.patch rename to projects/Allwinner/patches/linux/0018-wip-H6-deinterlace.patch diff --git a/projects/Allwinner/patches/linux/0031-arm64-dts-h6-deinterlace.patch b/projects/Allwinner/patches/linux/0019-arm64-dts-h6-deinterlace.patch similarity index 100% rename from projects/Allwinner/patches/linux/0031-arm64-dts-h6-deinterlace.patch rename to projects/Allwinner/patches/linux/0019-arm64-dts-h6-deinterlace.patch diff --git a/projects/Allwinner/patches/linux/0033-WIP-I2S-multi-channel.patch b/projects/Allwinner/patches/linux/0020-WIP-I2S-multi-channel.patch similarity index 100% rename from projects/Allwinner/patches/linux/0033-WIP-I2S-multi-channel.patch rename to projects/Allwinner/patches/linux/0020-WIP-I2S-multi-channel.patch diff --git a/projects/Allwinner/patches/linux/0034-HACK-h3-h5-Add-HDMI-sound-card.patch b/projects/Allwinner/patches/linux/0021-HACK-h3-h5-Add-HDMI-sound-card.patch similarity index 100% rename from projects/Allwinner/patches/linux/0034-HACK-h3-h5-Add-HDMI-sound-card.patch rename to projects/Allwinner/patches/linux/0021-HACK-h3-h5-Add-HDMI-sound-card.patch diff --git a/projects/Allwinner/patches/linux/0039-HACK-a64-Add-HDMI-sound-card.patch b/projects/Allwinner/patches/linux/0022-HACK-a64-Add-HDMI-sound-card.patch similarity index 100% rename from projects/Allwinner/patches/linux/0039-HACK-a64-Add-HDMI-sound-card.patch rename to projects/Allwinner/patches/linux/0022-HACK-a64-Add-HDMI-sound-card.patch diff --git a/projects/Allwinner/patches/linux/0041-bpi-m2u-analog-codec.patch b/projects/Allwinner/patches/linux/0023-bpi-m2u-analog-codec.patch similarity index 100% rename from projects/Allwinner/patches/linux/0041-bpi-m2u-analog-codec.patch rename to projects/Allwinner/patches/linux/0023-bpi-m2u-analog-codec.patch diff --git a/projects/Allwinner/patches/linux/0042-r40-hdmi-audio-wip.patch b/projects/Allwinner/patches/linux/0024-r40-hdmi-audio-wip.patch similarity index 100% rename from projects/Allwinner/patches/linux/0042-r40-hdmi-audio-wip.patch rename to projects/Allwinner/patches/linux/0024-r40-hdmi-audio-wip.patch diff --git a/projects/Allwinner/patches/linux/0043-HACK-h6-Add-HDMI-sound-card.patch b/projects/Allwinner/patches/linux/0025-HACK-h6-Add-HDMI-sound-card.patch similarity index 100% rename from projects/Allwinner/patches/linux/0043-HACK-h6-Add-HDMI-sound-card.patch rename to projects/Allwinner/patches/linux/0025-HACK-h6-Add-HDMI-sound-card.patch diff --git a/projects/Allwinner/patches/linux/0044-phy-handle-optional-regulator-for-PHY.patch b/projects/Allwinner/patches/linux/0026-phy-handle-optional-regulator-for-PHY.patch similarity index 100% rename from projects/Allwinner/patches/linux/0044-phy-handle-optional-regulator-for-PHY.patch rename to projects/Allwinner/patches/linux/0026-phy-handle-optional-regulator-for-PHY.patch diff --git a/projects/Allwinner/patches/linux/0045-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch b/projects/Allwinner/patches/linux/0027-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch similarity index 100% rename from projects/Allwinner/patches/linux/0045-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch rename to projects/Allwinner/patches/linux/0027-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch diff --git a/projects/Allwinner/patches/linux/0048-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch b/projects/Allwinner/patches/linux/0028-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch similarity index 100% rename from projects/Allwinner/patches/linux/0048-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch rename to projects/Allwinner/patches/linux/0028-arm64-allwinner-dts-h6-enable-USB3-port-on-Pine-H64.patch diff --git a/projects/Allwinner/patches/linux/0049-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch b/projects/Allwinner/patches/linux/0029-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch similarity index 100% rename from projects/Allwinner/patches/linux/0049-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch rename to projects/Allwinner/patches/linux/0029-arm64-dts-allwinner-h6-Add-AC200-EPHY-related-nodes.patch diff --git a/projects/Allwinner/patches/linux/0051-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch b/projects/Allwinner/patches/linux/0030-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch similarity index 100% rename from projects/Allwinner/patches/linux/0051-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch rename to projects/Allwinner/patches/linux/0030-arm64-dts-allwinner-h6-tanix-tx6-enable-ethernet.patch diff --git a/projects/Allwinner/patches/linux/0052-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch b/projects/Allwinner/patches/linux/0031-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch similarity index 100% rename from projects/Allwinner/patches/linux/0052-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch rename to projects/Allwinner/patches/linux/0031-arm64-allwinner-h6-Enable-USB3-for-OrangePi-Lite2.patch diff --git a/projects/Allwinner/patches/linux/0053-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch b/projects/Allwinner/patches/linux/0032-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch similarity index 100% rename from projects/Allwinner/patches/linux/0053-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch rename to projects/Allwinner/patches/linux/0032-mmc-sunxi-fix-unusuable-eMMC-on-some-H6-boards-by-di.patch diff --git a/projects/Allwinner/patches/linux/0056-bluetooth-btrtl-add-hci-ver-rtl8822cs.patch b/projects/Allwinner/patches/linux/0033-bluetooth-btrtl-add-hci-ver-rtl8822cs.patch similarity index 100% rename from projects/Allwinner/patches/linux/0056-bluetooth-btrtl-add-hci-ver-rtl8822cs.patch rename to projects/Allwinner/patches/linux/0033-bluetooth-btrtl-add-hci-ver-rtl8822cs.patch diff --git a/projects/Allwinner/patches/linux/0057-HACK-Disable-MBUS-due-to-fw_devlink-on.patch b/projects/Allwinner/patches/linux/0034-HACK-Disable-MBUS-due-to-fw_devlink-on.patch similarity index 100% rename from projects/Allwinner/patches/linux/0057-HACK-Disable-MBUS-due-to-fw_devlink-on.patch rename to projects/Allwinner/patches/linux/0034-HACK-Disable-MBUS-due-to-fw_devlink-on.patch diff --git a/projects/Allwinner/patches/linux/0058-WIP-OPi3-DT-fixes.patch b/projects/Allwinner/patches/linux/0035-WIP-OPi3-DT-fixes.patch similarity index 100% rename from projects/Allwinner/patches/linux/0058-WIP-OPi3-DT-fixes.patch rename to projects/Allwinner/patches/linux/0035-WIP-OPi3-DT-fixes.patch diff --git a/projects/Allwinner/patches/linux/0060-WIP-drm-bridge-synopsys-Fix-CEC-not-working-after-power.patch b/projects/Allwinner/patches/linux/0036-WIP-drm-bridge-synopsys-Fix-CEC-not-working-after-power.patch similarity index 100% rename from projects/Allwinner/patches/linux/0060-WIP-drm-bridge-synopsys-Fix-CEC-not-working-after-power.patch rename to projects/Allwinner/patches/linux/0036-WIP-drm-bridge-synopsys-Fix-CEC-not-working-after-power.patch diff --git a/projects/Allwinner/patches/linux/0061-media--cedrus--Don-t-CPU-map-source-buffers.patch b/projects/Allwinner/patches/linux/0037-media--cedrus--Don-t-CPU-map-source-buffers.patch similarity index 100% rename from projects/Allwinner/patches/linux/0061-media--cedrus--Don-t-CPU-map-source-buffers.patch rename to projects/Allwinner/patches/linux/0037-media--cedrus--Don-t-CPU-map-source-buffers.patch diff --git a/projects/Allwinner/patches/linux/0065-wip-fix-H6-4k-60.patch b/projects/Allwinner/patches/linux/0038-wip-fix-H6-4k-60.patch similarity index 100% rename from projects/Allwinner/patches/linux/0065-wip-fix-H6-4k-60.patch rename to projects/Allwinner/patches/linux/0038-wip-fix-H6-4k-60.patch diff --git a/projects/Allwinner/patches/linux/0066-arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch b/projects/Allwinner/patches/linux/0039-arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch similarity index 100% rename from projects/Allwinner/patches/linux/0066-arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch rename to projects/Allwinner/patches/linux/0039-arm64-dts-allwinner-h6-Fix-Cedrus-IOMMU-again.patch diff --git a/projects/Allwinner/patches/linux/0073-iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch b/projects/Allwinner/patches/linux/0040-iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch similarity index 100% rename from projects/Allwinner/patches/linux/0073-iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch rename to projects/Allwinner/patches/linux/0040-iommu-sun50i-Allow-page-sizes-multiple-of-4096.patch diff --git a/projects/Allwinner/patches/linux/0077-OrangePi-3-LTS-support.patch b/projects/Allwinner/patches/linux/0041-OrangePi-3-LTS-support.patch similarity index 100% rename from projects/Allwinner/patches/linux/0077-OrangePi-3-LTS-support.patch rename to projects/Allwinner/patches/linux/0041-OrangePi-3-LTS-support.patch diff --git a/projects/Allwinner/patches/linux/0100-tanix-mmc-rtw88-keep-power-in-suspend.patch b/projects/Allwinner/patches/linux/0042-tanix-mmc-rtw88-keep-power-in-suspend.patch similarity index 100% rename from projects/Allwinner/patches/linux/0100-tanix-mmc-rtw88-keep-power-in-suspend.patch rename to projects/Allwinner/patches/linux/0042-tanix-mmc-rtw88-keep-power-in-suspend.patch diff --git a/projects/Allwinner/patches/linux/0101-Bluetooth-btrtl-Add-support-for-RTL8822BS.patch b/projects/Allwinner/patches/linux/0043-Bluetooth-btrtl-Add-support-for-RTL8822BS.patch similarity index 100% rename from projects/Allwinner/patches/linux/0101-Bluetooth-btrtl-Add-support-for-RTL8822BS.patch rename to projects/Allwinner/patches/linux/0043-Bluetooth-btrtl-Add-support-for-RTL8822BS.patch diff --git a/projects/Allwinner/patches/linux/0105-ARM-dts-sun8i-r40-Add-interconnect-to-video-codec.patch b/projects/Allwinner/patches/linux/0044-ARM-dts-sun8i-r40-Add-interconnect-to-video-codec.patch similarity index 100% rename from projects/Allwinner/patches/linux/0105-ARM-dts-sun8i-r40-Add-interconnect-to-video-codec.patch rename to projects/Allwinner/patches/linux/0044-ARM-dts-sun8i-r40-Add-interconnect-to-video-codec.patch diff --git a/projects/Allwinner/patches/linux/0036-wip-h3-h5-cvbs.patch b/projects/Allwinner/patches/linux/0045-wip-h3-h5-cvbs.patch similarity index 100% rename from projects/Allwinner/patches/linux/0036-wip-h3-h5-cvbs.patch rename to projects/Allwinner/patches/linux/0045-wip-h3-h5-cvbs.patch diff --git a/projects/Allwinner/patches/linux/0063-HACK-SW-CEC-implementation-for-H3.patch b/projects/Allwinner/patches/linux/0046-HACK-SW-CEC-implementation-for-H3.patch similarity index 100% rename from projects/Allwinner/patches/linux/0063-HACK-SW-CEC-implementation-for-H3.patch rename to projects/Allwinner/patches/linux/0046-HACK-SW-CEC-implementation-for-H3.patch diff --git a/projects/Allwinner/patches/linux/0075-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch b/projects/Allwinner/patches/linux/0047-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch similarity index 100% rename from projects/Allwinner/patches/linux/0075-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch rename to projects/Allwinner/patches/linux/0047-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch From 6cddae6deeeb7a29ddb690c9c285680053482041 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 9 Oct 2023 22:11:20 +0200 Subject: [PATCH 4/7] Allwinner: linux: Add 10-bit HDMI and Cedrus support --- projects/Allwinner/linux/linux.aarch64.conf | 2 +- projects/Allwinner/linux/linux.arm.conf | 2 +- .../linux/0041-OrangePi-3-LTS-support.patch | 3 +- ...codec-Add-capture-format-to-support-.patch | 75 ++ ...codec-Add-capture-format-to-support-.patch | 74 ++ ...-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch | 131 --- ...un4i-dw-hdmi-Deinit-PHY-in-fail-path.patch | 31 + ...w-hdmi-Remove-double-encoder-cleanup.patch | 80 ++ ...i-dw-hdmi-Switch-to-bridge-functions.patch | 213 +++++ ...Don-t-show-error-for-deferred-probes.patch | 30 + ...i-Make-sun8i_hdmi_phy_get-more-intui.patch | 85 ++ ...i-dw-hdmi-check-for-phy-device-first.patch | 97 ++ ...rm-sun4i-de2-de3-Change-CSC-argument.patch | 176 ++++ ...de2-de3-Merge-CSC-functions-into-one.patch | 220 +++++ ...de3-call-csc-setup-also-for-UI-layer.patch | 63 ++ ...mi-add-mtmdsclock-parameter-to-phy-c.patch | 80 ++ ...mi-support-configuring-phy-for-deep-.patch | 63 ++ ...w-hdmi-limit-mode-and-bus-format-to-.patch | 211 +++++ ...4i-de3-Add-support-for-YUV420-output.patch | 886 ++++++++++++++++++ ...-h265-Fix-configuring-bitstream-size.patch | 65 ++ ...V12-and-P010-AFBC-compressed-formats.patch | 45 + ...-format-filtering-based-on-depth-and.patch | 51 + ...plement-AFBC-YUV420-formats-for-H265.patch | 169 ++++ ...-de2-Initialize-layer-fields-earlier.patch | 68 ++ ...drm-sun4i-de3-Implement-AFBC-support.patch | 571 +++++++++++ ...-media-cedrus-Increase-H6-clock-rate.patch | 29 + ...lwinner-h6-Add-GPU-OPP-to-all-boards.patch | 67 ++ ...5-cvbs.patch => 0068-wip-h3-h5-cvbs.patch} | 84 +- ...9-HACK-SW-CEC-implementation-for-H3.patch} | 122 ++- 29 files changed, 3567 insertions(+), 226 deletions(-) create mode 100644 projects/Allwinner/patches/linux/0045-media-mediatek-vcodec-Add-capture-format-to-support-.patch create mode 100644 projects/Allwinner/patches/linux/0046-media-mediatek-vcodec-Add-capture-format-to-support-.patch delete mode 100644 projects/Allwinner/patches/linux/0047-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch create mode 100644 projects/Allwinner/patches/linux/0047-drm-sun4i-dw-hdmi-Deinit-PHY-in-fail-path.patch create mode 100644 projects/Allwinner/patches/linux/0048-drm-sun4i-dw-hdmi-Remove-double-encoder-cleanup.patch create mode 100644 projects/Allwinner/patches/linux/0049-drm-sun4i-dw-hdmi-Switch-to-bridge-functions.patch create mode 100644 projects/Allwinner/patches/linux/0050-drm-sun4i-Don-t-show-error-for-deferred-probes.patch create mode 100644 projects/Allwinner/patches/linux/0051-drm-sun4i-dw-hdmi-Make-sun8i_hdmi_phy_get-more-intui.patch create mode 100644 projects/Allwinner/patches/linux/0052-drm-sun4i-dw-hdmi-check-for-phy-device-first.patch create mode 100644 projects/Allwinner/patches/linux/0053-drm-sun4i-de2-de3-Change-CSC-argument.patch create mode 100644 projects/Allwinner/patches/linux/0054-drm-sun4i-de2-de3-Merge-CSC-functions-into-one.patch create mode 100644 projects/Allwinner/patches/linux/0055-drm-sun4i-de2-de3-call-csc-setup-also-for-UI-layer.patch create mode 100644 projects/Allwinner/patches/linux/0056-drm-bridge-dw-hdmi-add-mtmdsclock-parameter-to-phy-c.patch create mode 100644 projects/Allwinner/patches/linux/0057-drm-bridge-dw-hdmi-support-configuring-phy-for-deep-.patch create mode 100644 projects/Allwinner/patches/linux/0058-WIP-drm-bridge-dw-hdmi-limit-mode-and-bus-format-to-.patch create mode 100644 projects/Allwinner/patches/linux/0059-WIP-drm-sun4i-de3-Add-support-for-YUV420-output.patch create mode 100644 projects/Allwinner/patches/linux/0060-media-cedrus-h265-Fix-configuring-bitstream-size.patch create mode 100644 projects/Allwinner/patches/linux/0061-media-Add-NV12-and-P010-AFBC-compressed-formats.patch create mode 100644 projects/Allwinner/patches/linux/0062-media-cedrus-add-format-filtering-based-on-depth-and.patch create mode 100644 projects/Allwinner/patches/linux/0063-media-cedrus-Implement-AFBC-YUV420-formats-for-H265.patch create mode 100644 projects/Allwinner/patches/linux/0064-drm-sun4i-de2-Initialize-layer-fields-earlier.patch create mode 100644 projects/Allwinner/patches/linux/0065-drm-sun4i-de3-Implement-AFBC-support.patch create mode 100644 projects/Allwinner/patches/linux/0066-media-cedrus-Increase-H6-clock-rate.patch create mode 100644 projects/Allwinner/patches/linux/0067-arm64-dts-allwinner-h6-Add-GPU-OPP-to-all-boards.patch rename projects/Allwinner/patches/linux/{0045-wip-h3-h5-cvbs.patch => 0068-wip-h3-h5-cvbs.patch} (84%) rename projects/Allwinner/patches/linux/{0046-HACK-SW-CEC-implementation-for-H3.patch => 0069-HACK-SW-CEC-implementation-for-H3.patch} (66%) diff --git a/projects/Allwinner/linux/linux.aarch64.conf b/projects/Allwinner/linux/linux.aarch64.conf index 784cdfe69e..7687dfc691 100644 --- a/projects/Allwinner/linux/linux.aarch64.conf +++ b/projects/Allwinner/linux/linux.aarch64.conf @@ -4202,7 +4202,7 @@ CONFIG_DRM_PANEL_BRIDGE=y # # CONFIG_DRM_CHIPONE_ICN6211 is not set # CONFIG_DRM_CHRONTEL_CH7033 is not set -# CONFIG_DRM_DISPLAY_CONNECTOR is not set +CONFIG_DRM_DISPLAY_CONNECTOR=y # CONFIG_DRM_ITE_IT6505 is not set # CONFIG_DRM_LONTIUM_LT8912B is not set # CONFIG_DRM_LONTIUM_LT9211 is not set diff --git a/projects/Allwinner/linux/linux.arm.conf b/projects/Allwinner/linux/linux.arm.conf index 14fa1dec08..76c5229fe3 100644 --- a/projects/Allwinner/linux/linux.arm.conf +++ b/projects/Allwinner/linux/linux.arm.conf @@ -3928,7 +3928,7 @@ CONFIG_DRM_PANEL_BRIDGE=y # # CONFIG_DRM_CHIPONE_ICN6211 is not set # CONFIG_DRM_CHRONTEL_CH7033 is not set -CONFIG_DRM_DISPLAY_CONNECTOR=m +CONFIG_DRM_DISPLAY_CONNECTOR=y # CONFIG_DRM_ITE_IT6505 is not set # CONFIG_DRM_LONTIUM_LT8912B is not set # CONFIG_DRM_LONTIUM_LT9211 is not set diff --git a/projects/Allwinner/patches/linux/0041-OrangePi-3-LTS-support.patch b/projects/Allwinner/patches/linux/0041-OrangePi-3-LTS-support.patch index 06c1d6e0bd..93d9c33ad8 100644 --- a/projects/Allwinner/patches/linux/0041-OrangePi-3-LTS-support.patch +++ b/projects/Allwinner/patches/linux/0041-OrangePi-3-LTS-support.patch @@ -27,7 +27,7 @@ new file mode 100644 index 000000000000..6a5df1103a90 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3-lts.dts -@@ -0,0 +1,315 @@ +@@ -0,0 +1,316 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2023 Jernej Skrabec +// Based on sun50i-h6-orangepi-3.dts, which is: @@ -37,6 +37,7 @@ index 000000000000..6a5df1103a90 + +#include "sun50i-h6.dtsi" +#include "sun50i-h6-cpu-opp.dtsi" ++#include "sun50i-h6-gpu-opp.dtsi" + +#include + diff --git a/projects/Allwinner/patches/linux/0045-media-mediatek-vcodec-Add-capture-format-to-support-.patch b/projects/Allwinner/patches/linux/0045-media-mediatek-vcodec-Add-capture-format-to-support-.patch new file mode 100644 index 0000000000..ec37ca59c7 --- /dev/null +++ b/projects/Allwinner/patches/linux/0045-media-mediatek-vcodec-Add-capture-format-to-support-.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mingjia Zhang +Date: Sat, 29 Jul 2023 11:41:10 +0800 +Subject: [PATCH] media: mediatek: vcodec: Add capture format to support 10bit + tile mode + +Define one uncompressed capture format V4L2_PIX_FMT_MT2110T in order to +support 10bit for AV1/VP9/HEVC in mt8195. + +Signed-off-by: Mingjia Zhang +Co-developed-by: Yunfei Dong +Signed-off-by: Yunfei Dong +Signed-off-by: Hans Verkuil +--- + Documentation/userspace-api/media/v4l/pixfmt-reserved.rst | 7 +++++++ + drivers/media/v4l2-core/v4l2-common.c | 2 ++ + drivers/media/v4l2-core/v4l2-ioctl.c | 1 + + include/uapi/linux/videodev2.h | 1 + + 4 files changed, 11 insertions(+) + +diff --git a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst +index 58f6ae25b2e7..0bc69639baaa 100644 +--- a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst ++++ b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst +@@ -275,6 +275,13 @@ please make a proposal on the linux-media mailing list. + + Decoder's implementation can be found here, + `aspeed_codec `__ ++ * .. _V4L2-PIX-FMT-MT2110T: ++ ++ - ``V4L2_PIX_FMT_MT2110T`` ++ - 'MT2110T' ++ - This format is two-planar 10-Bit tile mode and having similitude with ++ ``V4L2_PIX_FMT_MM21`` in term of alignment and tiling. Used for VP9, AV1 ++ and HEVC. + .. raw:: latex + + \normalsize +diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c +index bee1535b04d3..869fc09a210b 100644 +--- a/drivers/media/v4l2-core/v4l2-common.c ++++ b/drivers/media/v4l2-core/v4l2-common.c +@@ -262,6 +262,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) + { .format = V4L2_PIX_FMT_VYUY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, ++ { .format = V4L2_PIX_FMT_MT2110T, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2, ++ .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }}, + + /* YUV planar formats */ + { .format = V4L2_PIX_FMT_NV12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 01ba27f2ef87..f465c0e3d6e3 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1508,6 +1508,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_QC10C: descr = "QCOM Compressed 10-bit Format"; break; + case V4L2_PIX_FMT_AJPG: descr = "Aspeed JPEG"; break; + case V4L2_PIX_FMT_AV1_FRAME: descr = "AV1 Frame"; break; ++ case V4L2_PIX_FMT_MT2110T: descr = "Mediatek 10bit Tile Mode"; break; + default: + if (fmt->description[0]) + return; +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index 3af6a82d0cad..8c7d71afbdc7 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -796,6 +796,7 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_Z16 v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */ + #define V4L2_PIX_FMT_MT21C v4l2_fourcc('M', 'T', '2', '1') /* Mediatek compressed block mode */ + #define V4L2_PIX_FMT_MM21 v4l2_fourcc('M', 'M', '2', '1') /* Mediatek 8-bit block mode, two non-contiguous planes */ ++#define V4L2_PIX_FMT_MT2110T v4l2_fourcc('M', 'T', '2', 'T') /* Mediatek 10-bit block tile mode */ + #define V4L2_PIX_FMT_INZI v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar Greyscale 10-bit and Depth 16-bit */ + #define V4L2_PIX_FMT_CNF4 v4l2_fourcc('C', 'N', 'F', '4') /* Intel 4-bit packed depth confidence information */ + #define V4L2_PIX_FMT_HI240 v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */ diff --git a/projects/Allwinner/patches/linux/0046-media-mediatek-vcodec-Add-capture-format-to-support-.patch b/projects/Allwinner/patches/linux/0046-media-mediatek-vcodec-Add-capture-format-to-support-.patch new file mode 100644 index 0000000000..babb247667 --- /dev/null +++ b/projects/Allwinner/patches/linux/0046-media-mediatek-vcodec-Add-capture-format-to-support-.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mingjia Zhang +Date: Sat, 29 Jul 2023 11:41:11 +0800 +Subject: [PATCH] media: mediatek: vcodec: Add capture format to support 10bit + raster mode + +Define one uncompressed capture format V4L2_PIX_FMT_MT2110R in order to +support 10bit for H264 in mt8195. + +Signed-off-by: Mingjia Zhang +Co-developed-by: Yunfei Dong +Signed-off-by: Yunfei Dong +Signed-off-by: Hans Verkuil +--- + Documentation/userspace-api/media/v4l/pixfmt-reserved.rst | 6 ++++++ + drivers/media/v4l2-core/v4l2-common.c | 2 ++ + drivers/media/v4l2-core/v4l2-ioctl.c | 1 + + include/uapi/linux/videodev2.h | 1 + + 4 files changed, 10 insertions(+) + +diff --git a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst +index 0bc69639baaa..296ad2025e8d 100644 +--- a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst ++++ b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst +@@ -282,6 +282,12 @@ please make a proposal on the linux-media mailing list. + - This format is two-planar 10-Bit tile mode and having similitude with + ``V4L2_PIX_FMT_MM21`` in term of alignment and tiling. Used for VP9, AV1 + and HEVC. ++ * .. _V4L2-PIX-FMT-MT2110R: ++ ++ - ``V4L2_PIX_FMT_MT2110R`` ++ - 'MT2110R' ++ - This format is two-planar 10-Bit raster mode and having similitude with ++ ``V4L2_PIX_FMT_MM21`` in term of alignment and tiling. Used for AVC. + .. raw:: latex + + \normalsize +diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c +index 869fc09a210b..3a4b15a98e02 100644 +--- a/drivers/media/v4l2-core/v4l2-common.c ++++ b/drivers/media/v4l2-core/v4l2-common.c +@@ -264,6 +264,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) + { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_MT2110T, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2, + .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }}, ++ { .format = V4L2_PIX_FMT_MT2110R, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2, ++ .block_w = { 16, 8, 0, 0 }, .block_h = { 32, 16, 0, 0 }}, + + /* YUV planar formats */ + { .format = V4L2_PIX_FMT_NV12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index f465c0e3d6e3..f4d9d6279094 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1509,6 +1509,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_AJPG: descr = "Aspeed JPEG"; break; + case V4L2_PIX_FMT_AV1_FRAME: descr = "AV1 Frame"; break; + case V4L2_PIX_FMT_MT2110T: descr = "Mediatek 10bit Tile Mode"; break; ++ case V4L2_PIX_FMT_MT2110R: descr = "Mediatek 10bit Raster Mode"; break; + default: + if (fmt->description[0]) + return; +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index 8c7d71afbdc7..78260e5d9985 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -797,6 +797,7 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_MT21C v4l2_fourcc('M', 'T', '2', '1') /* Mediatek compressed block mode */ + #define V4L2_PIX_FMT_MM21 v4l2_fourcc('M', 'M', '2', '1') /* Mediatek 8-bit block mode, two non-contiguous planes */ + #define V4L2_PIX_FMT_MT2110T v4l2_fourcc('M', 'T', '2', 'T') /* Mediatek 10-bit block tile mode */ ++#define V4L2_PIX_FMT_MT2110R v4l2_fourcc('M', 'T', '2', 'R') /* Mediatek 10-bit block raster mode */ + #define V4L2_PIX_FMT_INZI v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar Greyscale 10-bit and Depth 16-bit */ + #define V4L2_PIX_FMT_CNF4 v4l2_fourcc('C', 'N', 'F', '4') /* Intel 4-bit packed depth confidence information */ + #define V4L2_PIX_FMT_HI240 v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */ diff --git a/projects/Allwinner/patches/linux/0047-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch b/projects/Allwinner/patches/linux/0047-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch deleted file mode 100644 index 00cb2d4f14..0000000000 --- a/projects/Allwinner/patches/linux/0047-Revert-drm-sun4i-dw-hdmi-Fix-ddc-en-GPIO-consumer-co.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jernej Skrabec -Date: Fri, 14 Oct 2022 23:35:13 +0200 -Subject: [PATCH] Revert "drm/sun4i: dw-hdmi: Fix ddc-en GPIO consumer - conflict" - -This reverts commit 920169041baa0a7497ed702aa97d6a2d6285efd3. ---- - drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 54 +++++++++++++++++++++++++-- - drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 + - 2 files changed, 52 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c -index 477cb6985b4d..a8d75fd7e9f4 100644 ---- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c -+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c -@@ -93,10 +93,34 @@ static u32 sun8i_dw_hdmi_find_possible_crtcs(struct drm_device *drm, - return crtcs; - } - -+static int sun8i_dw_hdmi_find_connector_pdev(struct device *dev, -+ struct platform_device **pdev_out) -+{ -+ struct platform_device *pdev; -+ struct device_node *remote; -+ -+ remote = of_graph_get_remote_node(dev->of_node, 1, -1); -+ if (!remote) -+ return -ENODEV; -+ -+ if (!of_device_is_compatible(remote, "hdmi-connector")) { -+ of_node_put(remote); -+ return -ENODEV; -+ } -+ -+ pdev = of_find_device_by_node(remote); -+ of_node_put(remote); -+ if (!pdev) -+ return -ENODEV; -+ -+ *pdev_out = pdev; -+ return 0; -+} -+ - static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, - void *data) - { -- struct platform_device *pdev = to_platform_device(dev); -+ struct platform_device *pdev = to_platform_device(dev), *connector_pdev; - struct dw_hdmi_plat_data *plat_data; - struct drm_device *drm = data; - struct device_node *phy_node; -@@ -143,16 +167,30 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, - return dev_err_probe(dev, PTR_ERR(hdmi->regulator), - "Couldn't get regulator\n"); - -+ ret = sun8i_dw_hdmi_find_connector_pdev(dev, &connector_pdev); -+ if (!ret) { -+ hdmi->ddc_en = gpiod_get_optional(&connector_pdev->dev, -+ "ddc-en", GPIOD_OUT_HIGH); -+ platform_device_put(connector_pdev); -+ -+ if (IS_ERR(hdmi->ddc_en)) { -+ dev_err(dev, "Couldn't get ddc-en gpio\n"); -+ return PTR_ERR(hdmi->ddc_en); -+ } -+ } -+ - ret = regulator_enable(hdmi->regulator); - if (ret) { - dev_err(dev, "Failed to enable regulator\n"); -- return ret; -+ goto err_unref_ddc_en; - } - -+ gpiod_set_value(hdmi->ddc_en, 1); -+ - ret = reset_control_deassert(hdmi->rst_ctrl); - if (ret) { - dev_err(dev, "Could not deassert ctrl reset control\n"); -- goto err_disable_regulator; -+ goto err_disable_ddc_en; - } - - ret = clk_prepare_enable(hdmi->clk_tmds); -@@ -207,8 +245,12 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, - clk_disable_unprepare(hdmi->clk_tmds); - err_assert_ctrl_reset: - reset_control_assert(hdmi->rst_ctrl); --err_disable_regulator: -+err_disable_ddc_en: -+ gpiod_set_value(hdmi->ddc_en, 0); - regulator_disable(hdmi->regulator); -+err_unref_ddc_en: -+ if (hdmi->ddc_en) -+ gpiod_put(hdmi->ddc_en); - - return ret; - } -@@ -222,7 +264,11 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master, - sun8i_hdmi_phy_deinit(hdmi->phy); - clk_disable_unprepare(hdmi->clk_tmds); - reset_control_assert(hdmi->rst_ctrl); -+ gpiod_set_value(hdmi->ddc_en, 0); - regulator_disable(hdmi->regulator); -+ -+ if (hdmi->ddc_en) -+ gpiod_put(hdmi->ddc_en); - } - - static const struct component_ops sun8i_dw_hdmi_ops = { -diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h -index ab80d52a70bb..f082b8ecfe2c 100644 ---- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h -+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -187,6 +188,7 @@ struct sun8i_dw_hdmi { - struct regulator *regulator; - const struct sun8i_dw_hdmi_quirks *quirks; - struct reset_control *rst_ctrl; -+ struct gpio_desc *ddc_en; - }; - - extern struct platform_driver sun8i_hdmi_phy_driver; diff --git a/projects/Allwinner/patches/linux/0047-drm-sun4i-dw-hdmi-Deinit-PHY-in-fail-path.patch b/projects/Allwinner/patches/linux/0047-drm-sun4i-dw-hdmi-Deinit-PHY-in-fail-path.patch new file mode 100644 index 0000000000..0b3999ba21 --- /dev/null +++ b/projects/Allwinner/patches/linux/0047-drm-sun4i-dw-hdmi-Deinit-PHY-in-fail-path.patch @@ -0,0 +1,31 @@ +From 519b9e72303cabcb87f4d5b8792069ca20b7f13b Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 23 Sep 2023 10:23:45 +0200 +Subject: [PATCH 01/23] drm/sun4i: dw-hdmi: Deinit PHY in fail path + +Commit 9bf3797796f5 ("drm/sun4i: dw-hdmi: Make HDMI PHY into a platform +device") removed code for PHY deinitialization in fail path. + +Add it back. + +Fixes: 9bf3797796f5 ("drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device") +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 4727dfaa8fb9..0b647b030b15 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -203,6 +203,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + + cleanup_encoder: + drm_encoder_cleanup(encoder); ++ sun8i_hdmi_phy_deinit(hdmi->phy); + err_disable_clk_tmds: + clk_disable_unprepare(hdmi->clk_tmds); + err_assert_ctrl_reset: +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0048-drm-sun4i-dw-hdmi-Remove-double-encoder-cleanup.patch b/projects/Allwinner/patches/linux/0048-drm-sun4i-dw-hdmi-Remove-double-encoder-cleanup.patch new file mode 100644 index 0000000000..4d28597ac8 --- /dev/null +++ b/projects/Allwinner/patches/linux/0048-drm-sun4i-dw-hdmi-Remove-double-encoder-cleanup.patch @@ -0,0 +1,80 @@ +From 9047008f1c8cebcc33cb068d9961fcfb8ff0eea7 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 11 Dec 2021 18:17:49 +0100 +Subject: [PATCH 02/23] drm/sun4i: dw-hdmi: Remove double encoder cleanup + +It turns out that comment is wrong - dw hdmi driver never does any +encoder cleanup. In fact, cleanup is done automatically, in destroy +callback of encoder. Even more, encoder memory will be freed when hdmi +device is destroyed. However, encoder will be cleaned up after that, in +drm_mode_config_cleanup(), which is called later. This will cause use +after free bug. + +Remove redundant encoder cleanup, switch memory allocation to live as +long as drm object and while at it, check return code of encoder +initialization. + +Fixes: b7c7436a5ff0 ("drm/sun4i: Implement A83T HDMI driver") +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 17 +++++++---------- + 1 file changed, 7 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 0b647b030b15..8f8d3bdba5ce 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -8,6 +8,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -107,7 +108,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + if (!pdev->dev.of_node) + return -ENODEV; + +- hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); ++ hdmi = drmm_kzalloc(drm, sizeof(*hdmi), GFP_KERNEL); + if (!hdmi) + return -ENOMEM; + +@@ -180,7 +181,9 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + goto err_disable_clk_tmds; + + drm_encoder_helper_add(encoder, &sun8i_dw_hdmi_encoder_helper_funcs); +- drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); ++ ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); ++ if (ret) ++ goto err_deinit_phy; + + plat_data->mode_valid = hdmi->quirks->mode_valid; + plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe; +@@ -189,20 +192,14 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + platform_set_drvdata(pdev, hdmi); + + hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); +- +- /* +- * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), +- * which would have called the encoder cleanup. Do it manually. +- */ + if (IS_ERR(hdmi->hdmi)) { + ret = PTR_ERR(hdmi->hdmi); +- goto cleanup_encoder; ++ goto err_deinit_phy; + } + + return 0; + +-cleanup_encoder: +- drm_encoder_cleanup(encoder); ++err_deinit_phy: + sun8i_hdmi_phy_deinit(hdmi->phy); + err_disable_clk_tmds: + clk_disable_unprepare(hdmi->clk_tmds); +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0049-drm-sun4i-dw-hdmi-Switch-to-bridge-functions.patch b/projects/Allwinner/patches/linux/0049-drm-sun4i-dw-hdmi-Switch-to-bridge-functions.patch new file mode 100644 index 0000000000..2d4a7396ef --- /dev/null +++ b/projects/Allwinner/patches/linux/0049-drm-sun4i-dw-hdmi-Switch-to-bridge-functions.patch @@ -0,0 +1,213 @@ +From 8d284097c6b9e7513e2946e17567aa490e19b779 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 23 Sep 2023 12:55:32 +0200 +Subject: [PATCH 03/23] drm/sun4i: dw-hdmi: Switch to bridge functions + +Since ddc-en property handling was moved from sun8i dw-hdmi driver to +display connector driver, probe order of drivers determines if EDID is +properly read at boot time or not. + +In order to fix this, let's switch to bridge functions which allows us +to build proper chain and defer execution until all drivers are probed. + +Fixes: 920169041baa ("drm/sun4i: dw-hdmi: Fix ddc-en GPIO consumer conflict") +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 114 +++++++++++++++++++++++++- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 5 ++ + 2 files changed, 117 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 8f8d3bdba5ce..93831cdf1917 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -8,14 +8,82 @@ + #include + #include + ++#include ++#include + #include + #include + #include + #include + ++#include ++ + #include "sun8i_dw_hdmi.h" + #include "sun8i_tcon_top.h" + ++#define bridge_to_sun8i_dw_hdmi(x) \ ++ container_of(x, struct sun8i_dw_hdmi, enc_bridge) ++ ++static int sun8i_hdmi_enc_attach(struct drm_bridge *bridge, ++ enum drm_bridge_attach_flags flags) ++{ ++ struct sun8i_dw_hdmi *hdmi = bridge_to_sun8i_dw_hdmi(bridge); ++ ++ return drm_bridge_attach(&hdmi->encoder, hdmi->hdmi_bridge, ++ &hdmi->enc_bridge, flags); ++} ++ ++static void sun8i_hdmi_enc_detach(struct drm_bridge *bridge) ++{ ++ struct sun8i_dw_hdmi *hdmi = bridge_to_sun8i_dw_hdmi(bridge); ++ ++ cec_notifier_conn_unregister(hdmi->cec_notifier); ++ hdmi->cec_notifier = NULL; ++} ++ ++static void sun8i_hdmi_enc_hpd_notify(struct drm_bridge *bridge, ++ enum drm_connector_status status) ++{ ++ struct sun8i_dw_hdmi *hdmi = bridge_to_sun8i_dw_hdmi(bridge); ++ struct edid *edid; ++ ++ if (!hdmi->cec_notifier) ++ return; ++ ++ if (status == connector_status_connected) { ++ edid = drm_bridge_get_edid(hdmi->hdmi_bridge, hdmi->connector); ++ if (edid) ++ cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, ++ edid); ++ } else { ++ cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); ++ } ++} ++ ++static int sun8i_hdmi_enc_atomic_check(struct drm_bridge *bridge, ++ struct drm_bridge_state *bridge_state, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state) ++{ ++ struct drm_connector_state *old_conn_state = ++ drm_atomic_get_old_connector_state(conn_state->state, ++ conn_state->connector); ++ ++ if (!drm_connector_atomic_hdr_metadata_equal(old_conn_state, conn_state)) ++ crtc_state->mode_changed = true; ++ ++ return 0; ++} ++ ++static const struct drm_bridge_funcs sun8i_hdmi_enc_bridge_funcs = { ++ .attach = sun8i_hdmi_enc_attach, ++ .detach = sun8i_hdmi_enc_detach, ++ .hpd_notify = sun8i_hdmi_enc_hpd_notify, ++ .atomic_check = sun8i_hdmi_enc_atomic_check, ++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_reset = drm_atomic_helper_bridge_reset, ++}; ++ + static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) +@@ -99,6 +167,8 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + { + struct platform_device *pdev = to_platform_device(dev); + struct dw_hdmi_plat_data *plat_data; ++ struct cec_connector_info conn_info; ++ struct drm_connector *connector; + struct drm_device *drm = data; + struct device_node *phy_node; + struct drm_encoder *encoder; +@@ -187,18 +257,57 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + + plat_data->mode_valid = hdmi->quirks->mode_valid; + plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe; ++ plat_data->output_port = 1; + sun8i_hdmi_phy_set_ops(hdmi->phy, plat_data); + + platform_set_drvdata(pdev, hdmi); + +- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); ++ hdmi->hdmi = dw_hdmi_probe(pdev, plat_data); + if (IS_ERR(hdmi->hdmi)) { + ret = PTR_ERR(hdmi->hdmi); + goto err_deinit_phy; + } + ++ hdmi->hdmi_bridge = of_drm_find_bridge(dev->of_node); ++ ++ hdmi->enc_bridge.funcs = &sun8i_hdmi_enc_bridge_funcs; ++ hdmi->enc_bridge.type = DRM_MODE_CONNECTOR_HDMIA; ++ hdmi->enc_bridge.interlace_allowed = true; ++ ++ drm_bridge_add(&hdmi->enc_bridge); ++ ++ ret = drm_bridge_attach(encoder, &hdmi->enc_bridge, NULL, ++ DRM_BRIDGE_ATTACH_NO_CONNECTOR); ++ if (ret) ++ goto err_remove_dw_hdmi; ++ ++ connector = drm_bridge_connector_init(drm, encoder); ++ if (IS_ERR(connector)) { ++ dev_err(dev, "Unable to create HDMI bridge connector\n"); ++ ret = PTR_ERR(connector); ++ goto err_remove_dw_hdmi; ++ } ++ ++ hdmi->connector = connector; ++ drm_connector_attach_encoder(connector, encoder); ++ ++ if (hdmi->quirks->use_drm_infoframe) ++ drm_connector_attach_hdr_output_metadata_property(connector); ++ ++ cec_fill_conn_info_from_drm(&conn_info, connector); ++ ++ hdmi->cec_notifier = cec_notifier_conn_register(&pdev->dev, NULL, ++ &conn_info); ++ if (!hdmi->cec_notifier) { ++ ret = -ENOMEM; ++ goto err_remove_dw_hdmi; ++ } ++ + return 0; + ++err_remove_dw_hdmi: ++ drm_bridge_remove(&hdmi->enc_bridge); ++ dw_hdmi_remove(hdmi->hdmi); + err_deinit_phy: + sun8i_hdmi_phy_deinit(hdmi->phy); + err_disable_clk_tmds: +@@ -216,7 +325,8 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master, + { + struct sun8i_dw_hdmi *hdmi = dev_get_drvdata(dev); + +- dw_hdmi_unbind(hdmi->hdmi); ++ drm_bridge_remove(&hdmi->enc_bridge); ++ dw_hdmi_remove(hdmi->hdmi); + sun8i_hdmi_phy_deinit(hdmi->phy); + clk_disable_unprepare(hdmi->clk_tmds); + reset_control_assert(hdmi->rst_ctrl); +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +index ab80d52a70bb..18ffc1b4841f 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +@@ -7,6 +7,7 @@ + #define _SUN8I_DW_HDMI_H_ + + #include ++#include + #include + #include + #include +@@ -178,9 +179,13 @@ struct sun8i_dw_hdmi_quirks { + }; + + struct sun8i_dw_hdmi { ++ struct cec_notifier *cec_notifier; + struct clk *clk_tmds; ++ struct drm_connector *connector; + struct device *dev; ++ struct drm_bridge enc_bridge; + struct dw_hdmi *hdmi; ++ struct drm_bridge *hdmi_bridge; + struct drm_encoder encoder; + struct sun8i_hdmi_phy *phy; + struct dw_hdmi_plat_data plat_data; +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0050-drm-sun4i-Don-t-show-error-for-deferred-probes.patch b/projects/Allwinner/patches/linux/0050-drm-sun4i-Don-t-show-error-for-deferred-probes.patch new file mode 100644 index 0000000000..e5ba5b7efd --- /dev/null +++ b/projects/Allwinner/patches/linux/0050-drm-sun4i-Don-t-show-error-for-deferred-probes.patch @@ -0,0 +1,30 @@ +From 5cd81f7bbbd50529e8534986e3ea40276c4a26cc Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 23 Sep 2023 13:31:23 +0200 +Subject: [PATCH 04/23] drm/sun4i: Don't show error for deferred probes. + +Drivers probing in display pipeline can be deferred for many reasons. +Don't print error for such cases. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun4i_drv.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c +index 6a8dfc022d3c..b4816a1b0be3 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_drv.c ++++ b/drivers/gpu/drm/sun4i/sun4i_drv.c +@@ -88,7 +88,8 @@ static int sun4i_drv_bind(struct device *dev) + + ret = component_bind_all(drm->dev, drm); + if (ret) { +- dev_err(drm->dev, "Couldn't bind all pipelines components\n"); ++ dev_err_probe(drm->dev, ret, ++ "Couldn't bind all pipelines components\n"); + goto cleanup_mode_config; + } + +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0051-drm-sun4i-dw-hdmi-Make-sun8i_hdmi_phy_get-more-intui.patch b/projects/Allwinner/patches/linux/0051-drm-sun4i-dw-hdmi-Make-sun8i_hdmi_phy_get-more-intui.patch new file mode 100644 index 0000000000..980cdedba7 --- /dev/null +++ b/projects/Allwinner/patches/linux/0051-drm-sun4i-dw-hdmi-Make-sun8i_hdmi_phy_get-more-intui.patch @@ -0,0 +1,85 @@ +From 873d6afcf4f64ac7380e7f18cd3604d47bea7570 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 23 Sep 2023 17:52:08 +0200 +Subject: [PATCH 05/23] drm/sun4i: dw-hdmi: Make sun8i_hdmi_phy_get() more + intuitive + +Let's make sun8i_hdmi_phy_get() to behave more like other kernel +functions and return phy pointer instead of setting field in struct. +This also makes function more universal. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 5 +++-- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 +- + drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 10 ++++------ + 3 files changed, 8 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 93831cdf1917..50cffdbc4b5c 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -239,10 +239,11 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + goto err_disable_clk_tmds; + } + +- ret = sun8i_hdmi_phy_get(hdmi, phy_node); ++ hdmi->phy = sun8i_hdmi_phy_get(phy_node); + of_node_put(phy_node); +- if (ret) { ++ if (IS_ERR(hdmi->phy)) { + dev_err(dev, "Couldn't get the HDMI PHY\n"); ++ ret = PTR_ERR(hdmi->phy); + goto err_disable_clk_tmds; + } + +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +index 18ffc1b4841f..5383d9267a4d 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +@@ -202,7 +202,7 @@ encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder) + return container_of(encoder, struct sun8i_dw_hdmi, encoder); + } + +-int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node); ++struct sun8i_hdmi_phy *sun8i_hdmi_phy_get(struct device_node *node); + + int sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy); + void sun8i_hdmi_phy_deinit(struct sun8i_hdmi_phy *phy); +diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +index 489ea94693ff..581233d6eaf2 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c ++++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +@@ -650,25 +650,23 @@ static const struct of_device_id sun8i_hdmi_phy_of_table[] = { + { /* sentinel */ } + }; + +-int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node) ++struct sun8i_hdmi_phy *sun8i_hdmi_phy_get(struct device_node *node) + { + struct platform_device *pdev = of_find_device_by_node(node); + struct sun8i_hdmi_phy *phy; + + if (!pdev) +- return -EPROBE_DEFER; ++ return ERR_PTR(-EPROBE_DEFER); + + phy = platform_get_drvdata(pdev); + if (!phy) { + put_device(&pdev->dev); +- return -EPROBE_DEFER; ++ return ERR_PTR(-EPROBE_DEFER); + } + +- hdmi->phy = phy; +- + put_device(&pdev->dev); + +- return 0; ++ return phy; + } + + static int sun8i_hdmi_phy_probe(struct platform_device *pdev) +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0052-drm-sun4i-dw-hdmi-check-for-phy-device-first.patch b/projects/Allwinner/patches/linux/0052-drm-sun4i-dw-hdmi-check-for-phy-device-first.patch new file mode 100644 index 0000000000..98ea3aaf4b --- /dev/null +++ b/projects/Allwinner/patches/linux/0052-drm-sun4i-dw-hdmi-check-for-phy-device-first.patch @@ -0,0 +1,97 @@ +From c3f41c49cd55dbb6fa23472e35673875a09e2cb7 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 23 Sep 2023 18:07:07 +0200 +Subject: [PATCH 06/23] drm/sun4i: dw-hdmi: check for phy device first + +Let's check for phy device first. Since it uses much of the same clocks +and resets it also lowers amount of possible deferred probes. + +While at it, don't report error for deferred phy probe. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 35 +++++++++++++-------------- + 1 file changed, 17 insertions(+), 18 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 50cffdbc4b5c..22e084989ee6 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -173,11 +173,24 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + struct device_node *phy_node; + struct drm_encoder *encoder; + struct sun8i_dw_hdmi *hdmi; ++ struct sun8i_hdmi_phy *phy; + int ret; + + if (!pdev->dev.of_node) + return -ENODEV; + ++ phy_node = of_parse_phandle(dev->of_node, "phys", 0); ++ if (!phy_node) { ++ dev_err(dev, "Can't find PHY phandle\n"); ++ return -EINVAL; ++ } ++ ++ phy = sun8i_hdmi_phy_get(phy_node); ++ of_node_put(phy_node); ++ if (IS_ERR(phy)) ++ return dev_err_probe(dev, PTR_ERR(phy), ++ "Couldn't get the HDMI PHY\n"); ++ + hdmi = drmm_kzalloc(drm, sizeof(*hdmi), GFP_KERNEL); + if (!hdmi) + return -ENOMEM; +@@ -185,6 +198,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + plat_data = &hdmi->plat_data; + hdmi->dev = &pdev->dev; + encoder = &hdmi->encoder; ++ hdmi->phy = phy; + + hdmi->quirks = of_device_get_match_data(dev); + +@@ -232,22 +246,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + goto err_assert_ctrl_reset; + } + +- phy_node = of_parse_phandle(dev->of_node, "phys", 0); +- if (!phy_node) { +- dev_err(dev, "Can't found PHY phandle\n"); +- ret = -EINVAL; +- goto err_disable_clk_tmds; +- } +- +- hdmi->phy = sun8i_hdmi_phy_get(phy_node); +- of_node_put(phy_node); +- if (IS_ERR(hdmi->phy)) { +- dev_err(dev, "Couldn't get the HDMI PHY\n"); +- ret = PTR_ERR(hdmi->phy); +- goto err_disable_clk_tmds; +- } +- +- ret = sun8i_hdmi_phy_init(hdmi->phy); ++ ret = sun8i_hdmi_phy_init(phy); + if (ret) + goto err_disable_clk_tmds; + +@@ -259,7 +258,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + plat_data->mode_valid = hdmi->quirks->mode_valid; + plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe; + plat_data->output_port = 1; +- sun8i_hdmi_phy_set_ops(hdmi->phy, plat_data); ++ sun8i_hdmi_phy_set_ops(phy, plat_data); + + platform_set_drvdata(pdev, hdmi); + +@@ -310,7 +309,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + drm_bridge_remove(&hdmi->enc_bridge); + dw_hdmi_remove(hdmi->hdmi); + err_deinit_phy: +- sun8i_hdmi_phy_deinit(hdmi->phy); ++ sun8i_hdmi_phy_deinit(phy); + err_disable_clk_tmds: + clk_disable_unprepare(hdmi->clk_tmds); + err_assert_ctrl_reset: +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0053-drm-sun4i-de2-de3-Change-CSC-argument.patch b/projects/Allwinner/patches/linux/0053-drm-sun4i-de2-de3-Change-CSC-argument.patch new file mode 100644 index 0000000000..2bcc0e6376 --- /dev/null +++ b/projects/Allwinner/patches/linux/0053-drm-sun4i-de2-de3-Change-CSC-argument.patch @@ -0,0 +1,176 @@ +From 846aad8037db9e4503f89007c0d9a8e79d7fc816 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 18 Feb 2020 22:07:37 +0100 +Subject: [PATCH 07/23] drm/sun4i: de2/de3: Change CSC argument + +Currently, CSC module takes care only for converting YUV to RGB. +However, DE3 is more suited to work in YUV color space. Change CSC mode +argument to format type to be more neutral. New argument only tells +layer format type and doesn't imply output type. + +This commit doesn't make any functional change. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_csc.c | 22 +++++++++++----------- + drivers/gpu/drm/sun4i/sun8i_csc.h | 10 +++++----- + drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 16 ++++++++-------- + 3 files changed, 24 insertions(+), 24 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c +index 58480d8e4f70..6ebd1c3aa3ab 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_csc.c ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.c +@@ -108,7 +108,7 @@ static const u32 yuv2rgb_de3[2][3][12] = { + }; + + static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, +- enum sun8i_csc_mode mode, ++ enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range) + { +@@ -118,12 +118,12 @@ static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, + + table = yuv2rgb[range][encoding]; + +- switch (mode) { +- case SUN8I_CSC_MODE_YUV2RGB: ++ switch (fmt_type) { ++ case FORMAT_TYPE_YUV: + base_reg = SUN8I_CSC_COEFF(base, 0); + regmap_bulk_write(map, base_reg, table, 12); + break; +- case SUN8I_CSC_MODE_YVU2RGB: ++ case FORMAT_TYPE_YVU: + for (i = 0; i < 12; i++) { + if ((i & 3) == 1) + base_reg = SUN8I_CSC_COEFF(base, i + 1); +@@ -141,7 +141,7 @@ static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, + } + + static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, +- enum sun8i_csc_mode mode, ++ enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range) + { +@@ -151,12 +151,12 @@ static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, + + table = yuv2rgb_de3[range][encoding]; + +- switch (mode) { +- case SUN8I_CSC_MODE_YUV2RGB: ++ switch (fmt_type) { ++ case FORMAT_TYPE_YUV: + addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); + regmap_bulk_write(map, addr, table, 12); + break; +- case SUN8I_CSC_MODE_YVU2RGB: ++ case FORMAT_TYPE_YVU: + for (i = 0; i < 12; i++) { + if ((i & 3) == 1) + addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, +@@ -206,7 +206,7 @@ static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable) + } + + void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, +- enum sun8i_csc_mode mode, ++ enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range) + { +@@ -214,14 +214,14 @@ void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, + + if (mixer->cfg->is_de3) { + sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer, +- mode, encoding, range); ++ fmt_type, encoding, range); + return; + } + + base = ccsc_base[mixer->cfg->ccsc][layer]; + + sun8i_csc_set_coefficients(mixer->engine.regs, base, +- mode, encoding, range); ++ fmt_type, encoding, range); + } + + void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable) +diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h +index 828b86fd0cab..7322770f39f0 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_csc.h ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.h +@@ -22,14 +22,14 @@ struct sun8i_mixer; + + #define SUN8I_CSC_CTRL_EN BIT(0) + +-enum sun8i_csc_mode { +- SUN8I_CSC_MODE_OFF, +- SUN8I_CSC_MODE_YUV2RGB, +- SUN8I_CSC_MODE_YVU2RGB, ++enum format_type { ++ FORMAT_TYPE_RGB, ++ FORMAT_TYPE_YUV, ++ FORMAT_TYPE_YVU, + }; + + void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, +- enum sun8i_csc_mode mode, ++ enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range); + void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable); +diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +index f9c0a56d3a14..76e2d3ec0a78 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +@@ -242,19 +242,19 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, + return 0; + } + +-static u32 sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format) ++static u32 sun8i_vi_layer_get_format_type(const struct drm_format_info *format) + { + if (!format->is_yuv) +- return SUN8I_CSC_MODE_OFF; ++ return FORMAT_TYPE_RGB; + + switch (format->format) { + case DRM_FORMAT_YVU411: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YVU444: +- return SUN8I_CSC_MODE_YVU2RGB; ++ return FORMAT_TYPE_YVU; + default: +- return SUN8I_CSC_MODE_YUV2RGB; ++ return FORMAT_TYPE_YUV; + } + } + +@@ -262,7 +262,7 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, + int overlay, struct drm_plane *plane) + { + struct drm_plane_state *state = plane->state; +- u32 val, ch_base, csc_mode, hw_fmt; ++ u32 val, ch_base, fmt_type, hw_fmt; + const struct drm_format_info *fmt; + int ret; + +@@ -280,9 +280,9 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, + SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay), + SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val); + +- csc_mode = sun8i_vi_layer_get_csc_mode(fmt); +- if (csc_mode != SUN8I_CSC_MODE_OFF) { +- sun8i_csc_set_ccsc_coefficients(mixer, channel, csc_mode, ++ fmt_type = sun8i_vi_layer_get_format_type(fmt); ++ if (fmt_type != FORMAT_TYPE_RGB) { ++ sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_type, + state->color_encoding, + state->color_range); + sun8i_csc_enable_ccsc(mixer, channel, true); +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0054-drm-sun4i-de2-de3-Merge-CSC-functions-into-one.patch b/projects/Allwinner/patches/linux/0054-drm-sun4i-de2-de3-Merge-CSC-functions-into-one.patch new file mode 100644 index 0000000000..6b4512d810 --- /dev/null +++ b/projects/Allwinner/patches/linux/0054-drm-sun4i-de2-de3-Merge-CSC-functions-into-one.patch @@ -0,0 +1,220 @@ +From 9a4784752427c56839353f09446c5344a3b84641 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 18 Feb 2020 23:19:48 +0100 +Subject: [PATCH 08/23] drm/sun4i: de2/de3: Merge CSC functions into one + +Merging both function into one lets this one decide on it's own if CSC +should be enabled or not. Currently heuristics for that is pretty simple +- enable it for YUV formats and disable for RGB. However, DE3 can have +whole pipeline in RGB or YUV format. YUV pipeline will be supported in +later commits. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_csc.c | 89 ++++++++++---------------- + drivers/gpu/drm/sun4i/sun8i_csc.h | 9 ++- + drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 11 +--- + 3 files changed, 40 insertions(+), 69 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c +index 6ebd1c3aa3ab..0dcbc0866ae8 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_csc.c ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.c +@@ -107,23 +107,28 @@ static const u32 yuv2rgb_de3[2][3][12] = { + }, + }; + +-static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, +- enum format_type fmt_type, +- enum drm_color_encoding encoding, +- enum drm_color_range range) ++static void sun8i_csc_setup(struct regmap *map, u32 base, ++ enum format_type fmt_type, ++ enum drm_color_encoding encoding, ++ enum drm_color_range range) + { ++ u32 base_reg, val; + const u32 *table; +- u32 base_reg; + int i; + + table = yuv2rgb[range][encoding]; + + switch (fmt_type) { ++ case FORMAT_TYPE_RGB: ++ val = 0; ++ break; + case FORMAT_TYPE_YUV: ++ val = SUN8I_CSC_CTRL_EN; + base_reg = SUN8I_CSC_COEFF(base, 0); + regmap_bulk_write(map, base_reg, table, 12); + break; + case FORMAT_TYPE_YVU: ++ val = SUN8I_CSC_CTRL_EN; + for (i = 0; i < 12; i++) { + if ((i & 3) == 1) + base_reg = SUN8I_CSC_COEFF(base, i + 1); +@@ -135,28 +140,37 @@ static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, + } + break; + default: ++ val = 0; + DRM_WARN("Wrong CSC mode specified.\n"); + return; + } ++ ++ regmap_write(map, SUN8I_CSC_CTRL(base), val); + } + +-static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, +- enum format_type fmt_type, +- enum drm_color_encoding encoding, +- enum drm_color_range range) ++static void sun8i_de3_ccsc_setup(struct regmap *map, int layer, ++ enum format_type fmt_type, ++ enum drm_color_encoding encoding, ++ enum drm_color_range range) + { ++ u32 addr, val, mask; + const u32 *table; +- u32 addr; + int i; + ++ mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer); + table = yuv2rgb_de3[range][encoding]; + + switch (fmt_type) { ++ case FORMAT_TYPE_RGB: ++ val = 0; ++ break; + case FORMAT_TYPE_YUV: ++ val = mask; + addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); + regmap_bulk_write(map, addr, table, 12); + break; + case FORMAT_TYPE_YVU: ++ val = mask; + for (i = 0; i < 12; i++) { + if ((i & 3) == 1) + addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, +@@ -173,67 +187,30 @@ static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, + } + break; + default: ++ val = 0; + DRM_WARN("Wrong CSC mode specified.\n"); + return; + } +-} +- +-static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable) +-{ +- u32 val; +- +- if (enable) +- val = SUN8I_CSC_CTRL_EN; +- else +- val = 0; +- +- regmap_update_bits(map, SUN8I_CSC_CTRL(base), SUN8I_CSC_CTRL_EN, val); +-} +- +-static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable) +-{ +- u32 val, mask; +- +- mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer); +- +- if (enable) +- val = mask; +- else +- val = 0; + + regmap_update_bits(map, SUN50I_MIXER_BLEND_CSC_CTL(DE3_BLD_BASE), + mask, val); + } + +-void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, +- enum format_type fmt_type, +- enum drm_color_encoding encoding, +- enum drm_color_range range) ++void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, ++ enum format_type fmt_type, ++ enum drm_color_encoding encoding, ++ enum drm_color_range range) + { + u32 base; + + if (mixer->cfg->is_de3) { +- sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer, +- fmt_type, encoding, range); ++ sun8i_de3_ccsc_setup(mixer->engine.regs, layer, ++ fmt_type, encoding, range); + return; + } + + base = ccsc_base[mixer->cfg->ccsc][layer]; + +- sun8i_csc_set_coefficients(mixer->engine.regs, base, +- fmt_type, encoding, range); +-} +- +-void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable) +-{ +- u32 base; +- +- if (mixer->cfg->is_de3) { +- sun8i_de3_ccsc_enable(mixer->engine.regs, layer, enable); +- return; +- } +- +- base = ccsc_base[mixer->cfg->ccsc][layer]; +- +- sun8i_csc_enable(mixer->engine.regs, base, enable); ++ sun8i_csc_setup(mixer->engine.regs, base, ++ fmt_type, encoding, range); + } +diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h +index 7322770f39f0..b7546e06e315 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_csc.h ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.h +@@ -28,10 +28,9 @@ enum format_type { + FORMAT_TYPE_YVU, + }; + +-void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, +- enum format_type fmt_type, +- enum drm_color_encoding encoding, +- enum drm_color_range range); +-void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable); ++void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, ++ enum format_type fmt_type, ++ enum drm_color_encoding encoding, ++ enum drm_color_range range); + + #endif +diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +index 76e2d3ec0a78..6ee3790a2a81 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +@@ -281,14 +281,9 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, + SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val); + + fmt_type = sun8i_vi_layer_get_format_type(fmt); +- if (fmt_type != FORMAT_TYPE_RGB) { +- sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_type, +- state->color_encoding, +- state->color_range); +- sun8i_csc_enable_ccsc(mixer, channel, true); +- } else { +- sun8i_csc_enable_ccsc(mixer, channel, false); +- } ++ sun8i_csc_set_ccsc(mixer, channel, fmt_type, ++ state->color_encoding, ++ state->color_range); + + if (!fmt->is_yuv) + val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE; +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0055-drm-sun4i-de2-de3-call-csc-setup-also-for-UI-layer.patch b/projects/Allwinner/patches/linux/0055-drm-sun4i-de2-de3-call-csc-setup-also-for-UI-layer.patch new file mode 100644 index 0000000000..39c367a38b --- /dev/null +++ b/projects/Allwinner/patches/linux/0055-drm-sun4i-de2-de3-call-csc-setup-also-for-UI-layer.patch @@ -0,0 +1,63 @@ +From f2a3b64aec5e23c89f5ae5a5121a4226b8ad2ee9 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 19 Feb 2020 20:59:27 +0100 +Subject: [PATCH 09/23] drm/sun4i: de2/de3: call csc setup also for UI layer + +Currently, only VI layer calls CSC setup function. This comes from DE2 +limitation, which doesn't have CSC unit for UI layers. However, DE3 has +separate CSC units for each layer. This allows display pipeline to make +output signal in different color spaces. To support both use cases, add +a call to CSC setup function also in UI layer code. For DE2, this will +be a no-op, but it will allow DE3 to output signal in multiple formats. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_csc.c | 8 +++++--- + drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 6 ++++++ + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c +index 0dcbc0866ae8..68d955c63b05 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_csc.c ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.c +@@ -209,8 +209,10 @@ void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, + return; + } + +- base = ccsc_base[mixer->cfg->ccsc][layer]; ++ if (layer < mixer->cfg->vi_num) { ++ base = ccsc_base[mixer->cfg->ccsc][layer]; + +- sun8i_csc_setup(mixer->engine.regs, base, +- fmt_type, encoding, range); ++ sun8i_csc_setup(mixer->engine.regs, base, ++ fmt_type, encoding, range); ++ } + } +diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +index ca75ca0835a6..884abe3cf773 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +@@ -20,6 +20,7 @@ + #include + #include + ++#include "sun8i_csc.h" + #include "sun8i_mixer.h" + #include "sun8i_ui_layer.h" + #include "sun8i_ui_scaler.h" +@@ -184,6 +185,11 @@ static int sun8i_ui_layer_update_formats(struct sun8i_mixer *mixer, int channel, + SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay), + SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val); + ++ /* Note: encoding and range arguments are ignored for RGB */ ++ sun8i_csc_set_ccsc(mixer, channel, FORMAT_TYPE_RGB, ++ DRM_COLOR_YCBCR_BT601, ++ DRM_COLOR_YCBCR_FULL_RANGE); ++ + return 0; + } + +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0056-drm-bridge-dw-hdmi-add-mtmdsclock-parameter-to-phy-c.patch b/projects/Allwinner/patches/linux/0056-drm-bridge-dw-hdmi-add-mtmdsclock-parameter-to-phy-c.patch new file mode 100644 index 0000000000..da8555a2ee --- /dev/null +++ b/projects/Allwinner/patches/linux/0056-drm-bridge-dw-hdmi-add-mtmdsclock-parameter-to-phy-c.patch @@ -0,0 +1,80 @@ +From c792bfdebef49c299a2043f7aecf4b44e376c332 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 18:00:44 +0000 +Subject: [PATCH 10/23] drm/bridge: dw-hdmi: add mtmdsclock parameter to phy + configure ops + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 10 ++++++---- + drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c | 3 ++- + include/drm/bridge/dw_hdmi.h | 3 ++- + 3 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 9721bdc2b7a3..c00fb616b587 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -124,7 +124,8 @@ struct dw_hdmi_phy_data { + bool has_svsret; + int (*configure)(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *pdata, +- unsigned long mpixelclock); ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock); + }; + + struct dw_hdmi { +@@ -1571,7 +1572,8 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) + */ + static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *pdata, +- unsigned long mpixelclock) ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock) + { + const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; + const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; +@@ -1648,9 +1650,9 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, + + /* Write to the PHY as configured by the platform */ + if (pdata->configure_phy) +- ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock); ++ ret = pdata->configure_phy(hdmi, pdata->priv_data, mpixelclock, mtmdsclock); + else +- ret = phy->configure(hdmi, pdata, mpixelclock); ++ ret = phy->configure(hdmi, pdata, mpixelclock, mtmdsclock); + if (ret) { + dev_err(hdmi->dev, "PHY configuration failed (clock %lu)\n", + mpixelclock); +diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c +index 119d69d20b23..3d0e7f94ed77 100644 +--- a/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c ++++ b/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c +@@ -53,7 +53,8 @@ rcar_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data, + } + + static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data, +- unsigned long mpixelclock) ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock) + { + const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params; + +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 6a46baa0737c..4c0f850ce3c7 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -159,7 +159,8 @@ struct dw_hdmi_plat_data { + const struct dw_hdmi_curr_ctrl *cur_ctr; + const struct dw_hdmi_phy_config *phy_config; + int (*configure_phy)(struct dw_hdmi *hdmi, void *data, +- unsigned long mpixelclock); ++ unsigned long mpixelclock, ++ unsigned long mtmdsclock); + + unsigned int disable_cec : 1; + }; +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0057-drm-bridge-dw-hdmi-support-configuring-phy-for-deep-.patch b/projects/Allwinner/patches/linux/0057-drm-bridge-dw-hdmi-support-configuring-phy-for-deep-.patch new file mode 100644 index 0000000000..25f4653c39 --- /dev/null +++ b/projects/Allwinner/patches/linux/0057-drm-bridge-dw-hdmi-support-configuring-phy-for-deep-.patch @@ -0,0 +1,63 @@ +From 760dd4bfec9f57bb1260f7b3219054a2ad28ceb3 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 20 Jul 2020 21:34:48 +0000 +Subject: [PATCH 11/23] drm/bridge: dw-hdmi: support configuring phy for deep + color + +Q: Should we rename dw_hdmi_curr_ctrl and dw_hdmi_phy_config mpixelclock to mtmdsclock ? + +Signed-off-by: Jonas Karlman +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index c00fb616b587..da2641a65e75 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1578,6 +1578,7 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; + const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; + const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; ++ int depth; + + /* TOFIX Will need 420 specific PHY configuration tables */ + +@@ -1587,11 +1588,11 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + break; + + for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) +- if (mpixelclock <= curr_ctrl->mpixelclock) ++ if (mtmdsclock <= curr_ctrl->mpixelclock) + break; + + for (; phy_config->mpixelclock != ~0UL; phy_config++) +- if (mpixelclock <= phy_config->mpixelclock) ++ if (mtmdsclock <= phy_config->mpixelclock) + break; + + if (mpll_config->mpixelclock == ~0UL || +@@ -1599,11 +1600,17 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi, + phy_config->mpixelclock == ~0UL) + return -EINVAL; + +- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, ++ depth = hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); ++ if (depth > 8 && mpixelclock != mtmdsclock) ++ depth = fls(depth - 8) - 1; ++ else ++ depth = 0; ++ ++ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].cpce, + HDMI_3D_TX_PHY_CPCE_CTRL); +- dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, ++ dw_hdmi_phy_i2c_write(hdmi, mpll_config->res[depth].gmp, + HDMI_3D_TX_PHY_GMPCTRL); +- dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], ++ dw_hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[depth], + HDMI_3D_TX_PHY_CURRCTRL); + + dw_hdmi_phy_i2c_write(hdmi, 0, HDMI_3D_TX_PHY_PLLPHBYCTRL); +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0058-WIP-drm-bridge-dw-hdmi-limit-mode-and-bus-format-to-.patch b/projects/Allwinner/patches/linux/0058-WIP-drm-bridge-dw-hdmi-limit-mode-and-bus-format-to-.patch new file mode 100644 index 0000000000..3a100d143f --- /dev/null +++ b/projects/Allwinner/patches/linux/0058-WIP-drm-bridge-dw-hdmi-limit-mode-and-bus-format-to-.patch @@ -0,0 +1,211 @@ +From e9a6924289b7ba7ca604272cbe52756f385d26df Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 20 Dec 2019 08:12:43 +0000 +Subject: [PATCH 12/23] WIP: drm/bridge: dw-hdmi: limit mode and bus format to + max_tmds_clock + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 113 ++++++++++++++-------- + 1 file changed, 73 insertions(+), 40 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index da2641a65e75..9c8c17827956 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1989,6 +1989,21 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi, + HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN); + } + ++static unsigned int ++hdmi_get_tmdsclock(unsigned int bus_format, unsigned int pixelclock) ++{ ++ int color_depth = hdmi_bus_fmt_color_depth(bus_format); ++ unsigned int tmdsclock = pixelclock; ++ ++ if (!hdmi_bus_fmt_is_yuv422(bus_format) && color_depth > 8) ++ tmdsclock = (u64)pixelclock * color_depth / 8; ++ ++ if (hdmi_bus_fmt_is_yuv420(bus_format)) ++ tmdsclock /= 2; ++ ++ return tmdsclock; ++} ++ + static void hdmi_av_composer(struct dw_hdmi *hdmi, + const struct drm_display_info *display, + const struct drm_display_mode *mode) +@@ -2000,29 +2015,11 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, + unsigned int vdisplay, hdisplay; + + vmode->mpixelclock = mode->clock * 1000; ++ vmode->mtmdsclock = ++ hdmi_get_tmdsclock(hdmi->hdmi_data.enc_out_bus_format, ++ vmode->mpixelclock); + + dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); +- +- vmode->mtmdsclock = vmode->mpixelclock; +- +- if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { +- switch (hdmi_bus_fmt_color_depth( +- hdmi->hdmi_data.enc_out_bus_format)) { +- case 16: +- vmode->mtmdsclock = vmode->mpixelclock * 2; +- break; +- case 12: +- vmode->mtmdsclock = vmode->mpixelclock * 3 / 2; +- break; +- case 10: +- vmode->mtmdsclock = vmode->mpixelclock * 5 / 4; +- break; +- } +- } +- +- if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) +- vmode->mtmdsclock /= 2; +- + dev_dbg(hdmi->dev, "final tmdsclock = %d\n", vmode->mtmdsclock); + + /* Set up HDMI_FC_INVIDCONF */ +@@ -2646,8 +2643,21 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) + * - MEDIA_BUS_FMT_RGB888_1X24, + */ + +-/* Can return a maximum of 11 possible output formats for a mode/connector */ +-#define MAX_OUTPUT_SEL_FORMATS 11 ++/* Can return a maximum of 15 possible output formats for a mode/connector */ ++#define MAX_OUTPUT_SEL_FORMATS 15 ++ ++static bool is_tmds_allowed(struct drm_display_info *info, ++ struct drm_display_mode *mode, ++ u32 bus_format) ++{ ++ unsigned long tmdsclock = hdmi_get_tmdsclock(bus_format, mode->clock); ++ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; ++ ++ if (max_tmds_clock >= tmdsclock) ++ return true; ++ ++ return false; ++} + + static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, +@@ -2690,19 +2700,23 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + + /* Order bus formats from 16bit to 8bit if supported */ + if (max_bpc >= 16 && info->bpc == 16 && +- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)) ++ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY16_0_5X48)) + output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY16_0_5X48; + + if (max_bpc >= 12 && info->bpc >= 12 && +- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)) ++ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY12_0_5X36)) + output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36; + + if (max_bpc >= 10 && info->bpc >= 10 && +- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)) ++ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY10_0_5X30)) + output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; + + /* Default 8bit fallback */ +- output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY8_0_5X24)) ++ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; + + if (drm_mode_is_420_only(info, mode)) { + *num_output_fmts = i; +@@ -2715,42 +2729,52 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, + * if supported. In any case the default RGB888 format is added + */ + +- /* Default 8bit RGB fallback */ +- output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; +- + if (max_bpc >= 16 && info->bpc == 16) { +- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV16_1X48)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; + +- output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB161616_1X48)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; + } + + if (max_bpc >= 12 && info->bpc >= 12) { +- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR422) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY12_1X24)) + output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; + +- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV12_1X36)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; + +- output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB121212_1X36)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; + } + + if (max_bpc >= 10 && info->bpc >= 10) { +- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR422) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY10_1X20)) + output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; + +- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV10_1X30)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; + +- output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; ++ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB101010_1X30)) ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; + } + +- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR422) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY8_1X16)) + output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; + +- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) ++ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR444) && ++ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV8_1X24)) + output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; + ++ /* Default 8bit RGB fallback */ ++ output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; ++ + *num_output_fmts = i; + + return output_fmts; +@@ -2930,11 +2954,20 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + struct dw_hdmi *hdmi = bridge->driver_private; + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; + enum drm_mode_status mode_status = MODE_OK; ++ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; ++ int clock = mode->clock; + + /* We don't support double-clocked modes */ + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + return MODE_BAD; + ++ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && ++ (info->color_formats & DRM_COLOR_FORMAT_YCBCR420)) ++ clock /= 2; ++ ++ if (clock > max_tmds_clock) ++ return MODE_CLOCK_HIGH; ++ + if (pdata->mode_valid) + mode_status = pdata->mode_valid(hdmi, pdata->priv_data, info, + mode); +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0059-WIP-drm-sun4i-de3-Add-support-for-YUV420-output.patch b/projects/Allwinner/patches/linux/0059-WIP-drm-sun4i-de3-Add-support-for-YUV420-output.patch new file mode 100644 index 0000000000..d4e317c308 --- /dev/null +++ b/projects/Allwinner/patches/linux/0059-WIP-drm-sun4i-de3-Add-support-for-YUV420-output.patch @@ -0,0 +1,886 @@ +From d8126b4e7ec771a5be4ab9513aed390461a70d3d Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 24 Sep 2023 13:20:12 +0200 +Subject: [PATCH 13/23] WIP: drm/sun4i: de3: Add support for YUV420 output + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 24 ++- + drivers/gpu/drm/drm_atomic_state_helper.c | 7 + + drivers/gpu/drm/sun4i/Makefile | 3 +- + drivers/gpu/drm/sun4i/sun4i_tcon.c | 26 +++- + drivers/gpu/drm/sun4i/sun50i_fmt.c | 74 ++++++++++ + drivers/gpu/drm/sun4i/sun50i_fmt.h | 30 ++++ + drivers/gpu/drm/sun4i/sun8i_csc.c | 172 +++++++++++++++++++++- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 97 +++++++++++- + drivers/gpu/drm/sun4i/sun8i_mixer.c | 51 ++++++- + drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 + + drivers/gpu/drm/sun4i/sunxi_engine.h | 48 ++++++ + 11 files changed, 509 insertions(+), 25 deletions(-) + create mode 100644 drivers/gpu/drm/sun4i/sun50i_fmt.c + create mode 100644 drivers/gpu/drm/sun4i/sun50i_fmt.h + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 9c8c17827956..8b4b4d45c1c9 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1019,19 +1019,15 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi) + color_format = 0x07; + break; + +- case MEDIA_BUS_FMT_YUV8_1X24: + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: + color_format = 0x09; + break; +- case MEDIA_BUS_FMT_YUV10_1X30: + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + color_format = 0x0B; + break; +- case MEDIA_BUS_FMT_YUV12_1X36: + case MEDIA_BUS_FMT_UYYVYY12_0_5X36: + color_format = 0x0D; + break; +- case MEDIA_BUS_FMT_YUV16_1X48: + case MEDIA_BUS_FMT_UYYVYY16_0_5X48: + color_format = 0x0F; + break; +@@ -1046,6 +1042,19 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi) + color_format = 0x12; + break; + ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ color_format = 0x17; ++ break; ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ color_format = 0x19; ++ break; ++ case MEDIA_BUS_FMT_YUV12_1X36: ++ color_format = 0x1B; ++ break; ++ case MEDIA_BUS_FMT_YUV16_1X48: ++ color_format = 0x1D; ++ break; ++ + default: + return; + } +@@ -1165,7 +1174,7 @@ static void hdmi_video_csc(struct dw_hdmi *hdmi) + if (is_color_space_interpolation(hdmi)) + interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1; + else if (is_color_space_decimation(hdmi)) +- decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3; ++ decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1; + + switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) { + case 8: +@@ -1207,7 +1216,6 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi) + u8 val, vp_conf; + u8 clear_gcp_auto = 0; + +- + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) || + hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format) || + hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) { +@@ -1803,7 +1811,9 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, + frame.colorspace = HDMI_COLORSPACE_RGB; + + /* Set up colorimetry */ +- if (!hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { ++ if (connector->colorspace_property) { ++ drm_hdmi_avi_infoframe_colorimetry(&frame, connector->state); ++ } else if (!hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { + switch (hdmi->hdmi_data.enc_out_encoding) { + case V4L2_YCBCR_ENC_601: + if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601) +diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c +index 784e63d70a42..1f9cf2bc6445 100644 +--- a/drivers/gpu/drm/drm_atomic_state_helper.c ++++ b/drivers/gpu/drm/drm_atomic_state_helper.c +@@ -415,7 +415,14 @@ void + __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state, + struct drm_connector *connector) + { ++ struct drm_property *prop; ++ + conn_state->connector = connector; ++ prop = connector->max_bpc_property; ++ if (prop) { ++ conn_state->max_bpc = prop->values[1]; ++ conn_state->max_requested_bpc = prop->values[1]; ++ } + } + EXPORT_SYMBOL(__drm_atomic_helper_connector_state_reset); + +diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile +index bad7497a0d11..3f516329f51e 100644 +--- a/drivers/gpu/drm/sun4i/Makefile ++++ b/drivers/gpu/drm/sun4i/Makefile +@@ -16,7 +16,8 @@ sun8i-drm-hdmi-y += sun8i_hdmi_phy_clk.o + + sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ + sun8i_vi_layer.o sun8i_ui_scaler.o \ +- sun8i_vi_scaler.o sun8i_csc.o ++ sun8i_vi_scaler.o sun8i_csc.o \ ++ sun50i_fmt.o + + sun4i-tcon-y += sun4i_crtc.o + sun4i-tcon-y += sun4i_tcon_dclk.o +diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c +index a1a2c845ade0..e39926e9f0b5 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c ++++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c +@@ -598,14 +598,26 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, + static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, + const struct drm_display_mode *mode) + { +- unsigned int bp, hsync, vsync, vtotal; ++ unsigned int bp, hsync, vsync, vtotal, div; ++ struct sun4i_crtc *scrtc = tcon->crtc; ++ struct sunxi_engine *engine = scrtc->engine; + u8 clk_delay; + u32 val; + + WARN_ON(!tcon->quirks->has_channel_1); + ++ switch (engine->format) { ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ div = 2; ++ break; ++ default: ++ div = 1; ++ break; ++ } ++ + /* Configure the dot clock */ +- clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); ++ clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000 / div); + + /* Adjust clock delay */ + clk_delay = sun4i_tcon_get_clk_delay(mode, 1); +@@ -624,17 +636,17 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, + + /* Set the input resolution */ + regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG, +- SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) | ++ SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay / div) | + SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay)); + + /* Set the upscaling resolution */ + regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG, +- SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) | ++ SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay / div) | + SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay)); + + /* Set the output resolution */ + regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG, +- SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) | ++ SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay / div) | + SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay)); + + /* Set horizontal display timings */ +@@ -642,8 +654,8 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, + DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", + mode->htotal, bp); + regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG, +- SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) | +- SUN4I_TCON1_BASIC3_H_BACKPORCH(bp)); ++ SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal / div) | ++ SUN4I_TCON1_BASIC3_H_BACKPORCH(bp / div)); + + bp = mode->crtc_vtotal - mode->crtc_vsync_start; + DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", +diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.c b/drivers/gpu/drm/sun4i/sun50i_fmt.c +new file mode 100644 +index 000000000000..18a8d5032ddc +--- /dev/null ++++ b/drivers/gpu/drm/sun4i/sun50i_fmt.c +@@ -0,0 +1,74 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (C) Jernej Skrabec ++ */ ++ ++#include ++ ++#include "sun50i_fmt.h" ++ ++static bool sun50i_fmt_is_10bit(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ case MEDIA_BUS_FMT_UYVY10_1X20: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static u32 sun50i_fmt_get_colorspace(u32 format) ++{ ++ switch (format) { ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ return SUN50I_FMT_CS_YUV420; ++ case MEDIA_BUS_FMT_UYVY8_1X16: ++ case MEDIA_BUS_FMT_UYVY10_1X20: ++ return SUN50I_FMT_CS_YUV422; ++ default: ++ return SUN50I_FMT_CS_YUV444RGB; ++ } ++} ++ ++void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width, ++ u16 height, u32 format) ++{ ++ u32 colorspace, limit[3]; ++ bool bit10; ++ ++ colorspace = sun50i_fmt_get_colorspace(format); ++ bit10 = sun50i_fmt_is_10bit(format); ++ ++ regmap_write(mixer->engine.regs, SUN50I_FMT_CTRL, 0); ++ ++ regmap_write(mixer->engine.regs, SUN50I_FMT_SIZE, ++ SUN8I_MIXER_SIZE(width, height)); ++ regmap_write(mixer->engine.regs, SUN50I_FMT_SWAP, 0); ++ regmap_write(mixer->engine.regs, SUN50I_FMT_DEPTH, bit10); ++ regmap_write(mixer->engine.regs, SUN50I_FMT_FORMAT, colorspace); ++ regmap_write(mixer->engine.regs, SUN50I_FMT_COEF, 0); ++ ++ if (colorspace != SUN50I_FMT_CS_YUV444RGB) { ++ limit[0] = SUN50I_FMT_LIMIT(64, 940); ++ limit[1] = SUN50I_FMT_LIMIT(64, 960); ++ limit[2] = SUN50I_FMT_LIMIT(64, 960); ++ } else if (bit10) { ++ limit[0] = SUN50I_FMT_LIMIT(0, 1023); ++ limit[1] = SUN50I_FMT_LIMIT(0, 1023); ++ limit[2] = SUN50I_FMT_LIMIT(0, 1023); ++ } else { ++ limit[0] = SUN50I_FMT_LIMIT(0, 1021); ++ limit[1] = SUN50I_FMT_LIMIT(0, 1021); ++ limit[2] = SUN50I_FMT_LIMIT(0, 1021); ++ } ++ ++ regmap_write(mixer->engine.regs, SUN50I_FMT_LMT_Y, limit[0]); ++ regmap_write(mixer->engine.regs, SUN50I_FMT_LMT_C0, limit[1]); ++ regmap_write(mixer->engine.regs, SUN50I_FMT_LMT_C1, limit[2]); ++ ++ regmap_write(mixer->engine.regs, SUN50I_FMT_CTRL, 1); ++} +diff --git a/drivers/gpu/drm/sun4i/sun50i_fmt.h b/drivers/gpu/drm/sun4i/sun50i_fmt.h +new file mode 100644 +index 000000000000..0fa1d2d22e59 +--- /dev/null ++++ b/drivers/gpu/drm/sun4i/sun50i_fmt.h +@@ -0,0 +1,30 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Copyright (C) Jernej Skrabec ++ */ ++ ++#ifndef _SUN50I_FMT_H_ ++#define _SUN50I_FMT_H_ ++ ++#include "sun8i_mixer.h" ++ ++#define SUN50I_FMT_CTRL 0xa8000 ++#define SUN50I_FMT_SIZE 0xa8004 ++#define SUN50I_FMT_SWAP 0xa8008 ++#define SUN50I_FMT_DEPTH 0xa800c ++#define SUN50I_FMT_FORMAT 0xa8010 ++#define SUN50I_FMT_COEF 0xa8014 ++#define SUN50I_FMT_LMT_Y 0xa8020 ++#define SUN50I_FMT_LMT_C0 0xa8024 ++#define SUN50I_FMT_LMT_C1 0xa8028 ++ ++#define SUN50I_FMT_LIMIT(low, high) (((high) << 16) | (low)) ++ ++#define SUN50I_FMT_CS_YUV444RGB 0 ++#define SUN50I_FMT_CS_YUV422 1 ++#define SUN50I_FMT_CS_YUV420 2 ++ ++void sun50i_fmt_setup(struct sun8i_mixer *mixer, u16 width, ++ u16 height, u32 format); ++ ++#endif +diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c +index 68d955c63b05..3b022bfb85ad 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_csc.c ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.c +@@ -5,6 +5,8 @@ + + #include + ++#include ++ + #include "sun8i_csc.h" + #include "sun8i_mixer.h" + +@@ -107,12 +109,141 @@ static const u32 yuv2rgb_de3[2][3][12] = { + }, + }; + ++/* always convert to limited mode */ ++static const u32 rgb2yuv_de3[3][12] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ 0x0000837A, 0x0001021D, 0x00003221, 0x00000040, ++ 0xFFFFB41C, 0xFFFF6B03, 0x0000E0E1, 0x00000200, ++ 0x0000E0E1, 0xFFFF43B1, 0xFFFFDB6E, 0x00000200, ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ 0x00005D7C, 0x00013A7C, 0x00001FBF, 0x00000040, ++ 0xFFFFCC78, 0xFFFF52A7, 0x0000E0E1, 0x00000200, ++ 0x0000E0E1, 0xFFFF33BE, 0xFFFFEB61, 0x00000200, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ 0x00007384, 0x00012A21, 0x00001A13, 0x00000040, ++ 0xFFFFC133, 0xFFFF5DEC, 0x0000E0E1, 0x00000200, ++ 0x0000E0E1, 0xFFFF3135, 0xFFFFEDEA, 0x00000200, ++ }, ++}; ++ ++/* always convert to limited mode */ ++static const u32 yuv2yuv_de3[2][3][3][12] = { ++ [DRM_COLOR_YCBCR_LIMITED_RANGE] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ 0x00020000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00020000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00020000, 0x00000000, ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ 0x00020000, 0xFFFFC4D7, 0xFFFF9589, 0xFFC00040, ++ 0x00000000, 0x0002098B, 0x00003AAF, 0xFE000200, ++ 0x00000000, 0x0000266D, 0x00020CF8, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ 0x00020000, 0xFFFFBFCE, 0xFFFFC5FF, 0xFFC00040, ++ 0x00000000, 0x00020521, 0x00001F89, 0xFE000200, ++ 0x00000000, 0x00002C87, 0x00020F07, 0xFE000200, ++ }, ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ 0x00020000, 0x000032D9, 0x00006226, 0xFFC00040, ++ 0x00000000, 0x0001FACE, 0xFFFFC759, 0xFE000200, ++ 0x00000000, 0xFFFFDAE7, 0x0001F780, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ 0x00020000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00020000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00020000, 0x00000000, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ 0x00020000, 0xFFFFF782, 0x00003036, 0xFFC00040, ++ 0x00000000, 0x0001FD99, 0xFFFFE5CA, 0xFE000200, ++ 0x00000000, 0x000005E4, 0x0002015A, 0xFE000200, ++ }, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ 0x00020000, 0x00003B03, 0x000034D2, 0xFFC00040, ++ 0x00000000, 0x0001FD8C, 0xFFFFE183, 0xFE000200, ++ 0x00000000, 0xFFFFD4F3, 0x0001F3FA, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ 0x00020000, 0x00000916, 0xFFFFD061, 0xFFC00040, ++ 0x00000000, 0x0002021C, 0x00001A40, 0xFE000200, ++ 0x00000000, 0xFFFFFA19, 0x0001FE5A, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ 0x00020000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00020000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00020000, 0x00000000, ++ }, ++ }, ++ }, ++ [DRM_COLOR_YCBCR_FULL_RANGE] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040, ++ 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200, ++ 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ 0x0001B7B8, 0xFFFFCC08, 0xFFFFA27B, 0x00000040, ++ 0x00000000, 0x0001CA24, 0x0000338D, 0xFE000200, ++ 0x00000000, 0x000021C1, 0x0001CD26, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ 0x0001B7B8, 0xFFFFC79C, 0xFFFFCD0C, 0x00000040, ++ 0x00000000, 0x0001C643, 0x00001BB4, 0xFE000200, ++ 0x00000000, 0x0000271D, 0x0001CEF5, 0xFE000200, ++ }, ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ 0x0001B7B8, 0x00002CAB, 0x00005638, 0x00000040, ++ 0x00000000, 0x0001BD32, 0xFFFFCE3C, 0xFE000200, ++ 0x00000000, 0xFFFFDF6A, 0x0001BA4A, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040, ++ 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200, ++ 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ 0x0001B7B8, 0xFFFFF88A, 0x00002A5A, 0x00000040, ++ 0x00000000, 0x0001BFA5, 0xFFFFE8FA, 0xFE000200, ++ 0x00000000, 0x0000052D, 0x0001C2F1, 0xFE000200, ++ }, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ 0x0001B7B8, 0x000033D6, 0x00002E66, 0x00000040, ++ 0x00000000, 0x0001BF9A, 0xFFFFE538, 0xFE000200, ++ 0x00000000, 0xFFFFDA2F, 0x0001B732, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ 0x0001B7B8, 0x000007FB, 0xFFFFD62B, 0x00000040, ++ 0x00000000, 0x0001C39D, 0x0000170F, 0xFE000200, ++ 0x00000000, 0xFFFFFAD1, 0x0001C04F, 0xFE000200, ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040, ++ 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200, ++ 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200, ++ }, ++ }, ++ }, ++}; ++ + static void sun8i_csc_setup(struct regmap *map, u32 base, + enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range) + { +- u32 base_reg, val; ++ u32 base_reg, val = 0; + const u32 *table; + int i; + +@@ -148,28 +279,59 @@ static void sun8i_csc_setup(struct regmap *map, u32 base, + regmap_write(map, SUN8I_CSC_CTRL(base), val); + } + +-static void sun8i_de3_ccsc_setup(struct regmap *map, int layer, ++static const u32 *sun8i_csc_get_de3_yuv_table(enum drm_color_encoding in_enc, ++ enum drm_color_range in_range, ++ u32 out_format, ++ enum drm_color_encoding out_enc) ++{ ++ if (out_format == MEDIA_BUS_FMT_RGB888_1X24) ++ return yuv2rgb_de3[in_range][in_enc]; ++ ++ /* check for identity transformation */ ++ if (in_range == DRM_COLOR_YCBCR_LIMITED_RANGE && out_enc == in_enc) ++ return NULL; ++ ++ return yuv2yuv_de3[in_range][in_enc][out_enc]; ++} ++ ++static void sun8i_de3_ccsc_setup(struct sunxi_engine *engine, int layer, + enum format_type fmt_type, + enum drm_color_encoding encoding, + enum drm_color_range range) + { +- u32 addr, val, mask; ++ u32 addr, val = 0, mask; ++ struct regmap *map; + const u32 *table; + int i; + + mask = SUN50I_MIXER_BLEND_CSC_CTL_EN(layer); + table = yuv2rgb_de3[range][encoding]; ++ map = engine->regs; + + switch (fmt_type) { + case FORMAT_TYPE_RGB: +- val = 0; ++ if (engine->format == MEDIA_BUS_FMT_RGB888_1X24) ++ break; ++ val = mask; ++ addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); ++ regmap_bulk_write(map, addr, rgb2yuv_de3[engine->encoding], 12); + break; + case FORMAT_TYPE_YUV: ++ table = sun8i_csc_get_de3_yuv_table(encoding, range, ++ engine->format, ++ engine->encoding); ++ if (!table) ++ break; + val = mask; + addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0); + regmap_bulk_write(map, addr, table, 12); + break; + case FORMAT_TYPE_YVU: ++ table = sun8i_csc_get_de3_yuv_table(encoding, range, ++ engine->format, ++ engine->encoding); ++ if (!table) ++ table = yuv2yuv_de3[range][encoding][encoding]; + val = mask; + for (i = 0; i < 12; i++) { + if ((i & 3) == 1) +@@ -204,7 +366,7 @@ void sun8i_csc_set_ccsc(struct sun8i_mixer *mixer, int layer, + u32 base; + + if (mixer->cfg->is_de3) { +- sun8i_de3_ccsc_setup(mixer->engine.regs, layer, ++ sun8i_de3_ccsc_setup(&mixer->engine, layer, + fmt_type, encoding, range); + return; + } +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 22e084989ee6..7309590feb56 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -17,8 +18,10 @@ + + #include + ++#include "sun4i_crtc.h" + #include "sun8i_dw_hdmi.h" + #include "sun8i_tcon_top.h" ++#include "sunxi_engine.h" + + #define bridge_to_sun8i_dw_hdmi(x) \ + container_of(x, struct sun8i_dw_hdmi, enc_bridge) +@@ -64,16 +67,89 @@ static int sun8i_hdmi_enc_atomic_check(struct drm_bridge *bridge, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) + { +- struct drm_connector_state *old_conn_state = ++ struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(crtc_state->crtc); ++ struct sunxi_engine *engine = crtc->engine; ++ struct drm_connector_state *old_conn_state; ++ enum drm_color_encoding encoding; ++ ++ old_conn_state = + drm_atomic_get_old_connector_state(conn_state->state, + conn_state->connector); + ++ switch (conn_state->colorspace) { ++ case DRM_MODE_COLORIMETRY_SMPTE_170M_YCC: ++ case DRM_MODE_COLORIMETRY_XVYCC_601: ++ case DRM_MODE_COLORIMETRY_SYCC_601: ++ case DRM_MODE_COLORIMETRY_OPYCC_601: ++ case DRM_MODE_COLORIMETRY_BT601_YCC: ++ encoding = DRM_COLOR_YCBCR_BT601; ++ break; ++ ++ default: ++ case DRM_MODE_COLORIMETRY_NO_DATA: ++ case DRM_MODE_COLORIMETRY_BT709_YCC: ++ case DRM_MODE_COLORIMETRY_XVYCC_709: ++ case DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED: ++ case DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT: ++ encoding = DRM_COLOR_YCBCR_BT709; ++ break; ++ ++ case DRM_MODE_COLORIMETRY_BT2020_CYCC: ++ case DRM_MODE_COLORIMETRY_BT2020_YCC: ++ case DRM_MODE_COLORIMETRY_BT2020_RGB: ++ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65: ++ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER: ++ encoding = DRM_COLOR_YCBCR_BT2020; ++ break; ++ } ++ ++ if (crtc->engine->format != bridge_state->output_bus_cfg.format) ++ crtc_state->mode_changed = true; ++ ++ sunxi_engine_set_format(engine, bridge_state->output_bus_cfg.format, ++ encoding); ++ + if (!drm_connector_atomic_hdr_metadata_equal(old_conn_state, conn_state)) + crtc_state->mode_changed = true; + + return 0; + } + ++static u32 * ++sun8i_hdmi_enc_get_input_bus_fmts(struct drm_bridge *bridge, ++ struct drm_bridge_state *bridge_state, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state, ++ u32 output_fmt, ++ unsigned int *num_input_fmts) ++{ ++ struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(crtc_state->crtc); ++ u32 *input_fmt, *supported, count, i; ++ ++ *num_input_fmts = 0; ++ input_fmt = NULL; ++ ++ supported = sunxi_engine_get_supported_formats(crtc->engine, &count); ++ if (count == 0 || !supported) ++ return NULL; ++ ++ for (i = 0; i < count; i++) ++ if (output_fmt == supported[i]) { ++ input_fmt = kzalloc(sizeof(*input_fmt), GFP_KERNEL); ++ if (!input_fmt) ++ break; ++ ++ *num_input_fmts = 1; ++ *input_fmt = output_fmt; ++ ++ break; ++ } ++ ++ kfree(supported); ++ ++ return input_fmt; ++} ++ + static const struct drm_bridge_funcs sun8i_hdmi_enc_bridge_funcs = { + .attach = sun8i_hdmi_enc_attach, + .detach = sun8i_hdmi_enc_detach, +@@ -81,6 +157,7 @@ static const struct drm_bridge_funcs sun8i_hdmi_enc_bridge_funcs = { + .atomic_check = sun8i_hdmi_enc_atomic_check, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_get_input_bus_fmts = sun8i_hdmi_enc_get_input_bus_fmts, + .atomic_reset = drm_atomic_helper_bridge_reset, + }; + +@@ -114,6 +191,11 @@ sun8i_dw_hdmi_mode_valid_h6(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *info, + const struct drm_display_mode *mode) + { ++ unsigned long clock = mode->crtc_clock * 1000; ++ ++ if (drm_mode_is_420(info, mode)) ++ clock /= 2; ++ + /* + * Controller support maximum of 594 MHz, which correlates to + * 4K@60Hz 4:4:4 or RGB. +@@ -257,6 +339,8 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + + plat_data->mode_valid = hdmi->quirks->mode_valid; + plat_data->use_drm_infoframe = hdmi->quirks->use_drm_infoframe; ++ plat_data->ycbcr_420_allowed = hdmi->quirks->use_drm_infoframe; ++ plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709; + plat_data->output_port = 1; + sun8i_hdmi_phy_set_ops(phy, plat_data); + +@@ -291,8 +375,17 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + hdmi->connector = connector; + drm_connector_attach_encoder(connector, encoder); + +- if (hdmi->quirks->use_drm_infoframe) ++ drm_atomic_helper_connector_reset(connector); ++ ++ drm_mode_create_hdmi_colorspace_property(connector, 0); ++ ++ if (hdmi->quirks->use_drm_infoframe) { + drm_connector_attach_hdr_output_metadata_property(connector); ++ drm_connector_attach_max_bpc_property(connector, 8, 12); ++ drm_connector_attach_colorspace_property(connector); ++ } ++ ++ connector->ycbcr_420_allowed = hdmi->quirks->use_drm_infoframe; + + cec_fill_conn_info_from_drm(&conn_info, connector); + +diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c +index 01382860aaee..8e32d0b24ac9 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c +@@ -22,7 +22,10 @@ + #include + #include + ++#include ++ + #include "sun4i_drv.h" ++#include "sun50i_fmt.h" + #include "sun8i_mixer.h" + #include "sun8i_ui_layer.h" + #include "sun8i_vi_layer.h" +@@ -326,12 +329,51 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine, + + DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n", + interlaced ? "on" : "off"); ++ ++ if (engine->format == MEDIA_BUS_FMT_RGB888_1X24) ++ val = SUN8I_MIXER_BLEND_COLOR_BLACK; ++ else ++ val = 0xff108080; ++ ++ regmap_write(mixer->engine.regs, ++ SUN8I_MIXER_BLEND_BKCOLOR(bld_base), val); ++ regmap_write(mixer->engine.regs, ++ SUN8I_MIXER_BLEND_ATTR_FCOLOR(bld_base, 0), val); ++ ++ if (mixer->cfg->has_formatter) ++ sun50i_fmt_setup(mixer, mode->hdisplay, ++ mode->vdisplay, mixer->engine.format); ++} ++ ++static u32 *sun8i_mixer_get_supported_fmts(struct sunxi_engine *engine, u32 *num) ++{ ++ struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); ++ u32 *formats, count; ++ ++ count = 0; ++ ++ formats = kcalloc(8, sizeof(*formats), GFP_KERNEL); ++ if (!formats) ++ return NULL; ++ ++ if (mixer->cfg->has_formatter) { ++ formats[count++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; ++ formats[count++] = MEDIA_BUS_FMT_YUV8_1X24; ++ formats[count++] = MEDIA_BUS_FMT_UYVY8_1X16; ++ } ++ ++ formats[count++] = MEDIA_BUS_FMT_RGB888_1X24; ++ ++ *num = count; ++ ++ return formats; + } + + static const struct sunxi_engine_ops sun8i_engine_ops = { +- .commit = sun8i_mixer_commit, +- .layers_init = sun8i_layers_init, +- .mode_set = sun8i_mixer_mode_set, ++ .commit = sun8i_mixer_commit, ++ .layers_init = sun8i_layers_init, ++ .mode_set = sun8i_mixer_mode_set, ++ .get_supported_fmts = sun8i_mixer_get_supported_fmts, + }; + + static const struct regmap_config sun8i_mixer_regmap_config = { +@@ -392,6 +434,8 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master, + dev_set_drvdata(dev, mixer); + mixer->engine.ops = &sun8i_engine_ops; + mixer->engine.node = dev->of_node; ++ /* default output format, supported by all mixers */ ++ mixer->engine.format = MEDIA_BUS_FMT_RGB888_1X24; + + if (of_property_present(dev->of_node, "iommus")) { + /* +@@ -653,6 +697,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = { + static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = { + .ccsc = CCSC_MIXER0_LAYOUT, + .is_de3 = true, ++ .has_formatter = 1, + .mod_rate = 600000000, + .scaler_mask = 0xf, + .scanline_yuv = 4096, +diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h +index 85c94884fb9a..13401643c7bf 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h ++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h +@@ -162,6 +162,7 @@ enum { + * @mod_rate: module clock rate that needs to be set in order to have + * a functional block. + * @is_de3: true, if this is next gen display engine 3.0, false otherwise. ++ * @has_formatter: true, if mixer has formatter core, for 10-bit and YUV handling + * @scaline_yuv: size of a scanline for VI scaler for YUV formats. + */ + struct sun8i_mixer_cfg { +@@ -171,6 +172,7 @@ struct sun8i_mixer_cfg { + int ccsc; + unsigned long mod_rate; + unsigned int is_de3 : 1; ++ unsigned int has_formatter : 1; + unsigned int scanline_yuv; + }; + +diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h +index ec8cf9b2bda4..5e64cda5675a 100644 +--- a/drivers/gpu/drm/sun4i/sunxi_engine.h ++++ b/drivers/gpu/drm/sun4i/sunxi_engine.h +@@ -6,6 +6,8 @@ + #ifndef _SUNXI_ENGINE_H_ + #define _SUNXI_ENGINE_H_ + ++#include ++ + struct drm_plane; + struct drm_device; + struct drm_crtc_state; +@@ -120,6 +122,20 @@ struct sunxi_engine_ops { + */ + void (*mode_set)(struct sunxi_engine *engine, + const struct drm_display_mode *mode); ++ ++ /** ++ * @get_supported_fmts ++ * ++ * This callback is used to enumerate all supported output ++ * formats by the engine. They are used for bridge format ++ * negotiation. ++ * ++ * This function is optional. ++ */ ++ u32 *(*get_supported_fmts)(struct sunxi_engine *engine, u32 *num); ++ ++ void (*set_format)(struct sunxi_engine *engine, u32 format, ++ enum drm_color_encoding encoding); + }; + + /** +@@ -137,6 +153,9 @@ struct sunxi_engine { + + int id; + ++ u32 format; ++ enum drm_color_encoding encoding; ++ + /* Engine list management */ + struct list_head list; + }; +@@ -208,4 +227,33 @@ sunxi_engine_mode_set(struct sunxi_engine *engine, + if (engine->ops && engine->ops->mode_set) + engine->ops->mode_set(engine, mode); + } ++ ++/** ++ * sunxi_engine_get_supported_formats - Provide array of supported formats ++ * @engine: pointer to the engine ++ * @num: pointer to variable, which will hold number of formats ++ * ++ * This list can be used for format negotiation by bridge. ++ */ ++static inline u32 * ++sunxi_engine_get_supported_formats(struct sunxi_engine *engine, u32 *num) ++{ ++ if (engine->ops && engine->ops->get_supported_fmts) ++ return engine->ops->get_supported_fmts(engine, num); ++ ++ *num = 0; ++ ++ return NULL; ++} ++ ++static inline void ++sunxi_engine_set_format(struct sunxi_engine *engine, u32 format, ++ enum drm_color_encoding encoding) ++{ ++ if (engine->ops && engine->ops->set_format) ++ return engine->ops->set_format(engine, format, encoding); ++ ++ engine->format = format; ++ engine->encoding = encoding; ++} + #endif /* _SUNXI_ENGINE_H_ */ +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0060-media-cedrus-h265-Fix-configuring-bitstream-size.patch b/projects/Allwinner/patches/linux/0060-media-cedrus-h265-Fix-configuring-bitstream-size.patch new file mode 100644 index 0000000000..e7dd7f0d23 --- /dev/null +++ b/projects/Allwinner/patches/linux/0060-media-cedrus-h265-Fix-configuring-bitstream-size.patch @@ -0,0 +1,65 @@ +From 6fba61d436ed9d610e1001860e2fcdf2ccf96803 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 7 Oct 2023 08:36:47 +0200 +Subject: [PATCH 14/23] media: cedrus: h265: Fix configuring bitstream size + +bit_size field holds size of slice, not slice + header. Because of HW +quirks, driver can't program in just slice, but also preceeding header. +But that means that currently used bit_size is wrong (too small). +Instead, just use size of whole buffer. There is no harm in doing this. + +Fixes: 86caab29da78 ("media: cedrus: Add HEVC/H.265 decoding support") +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index fc9297232456..16c822637dc6 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -427,11 +427,11 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + unsigned int ctb_addr_x, ctb_addr_y; + struct cedrus_buffer *cedrus_buf; + dma_addr_t src_buf_addr; +- dma_addr_t src_buf_end_addr; + u32 chroma_log2_weight_denom; + u32 num_entry_point_offsets; + u32 output_pic_list_index; + u32 pic_order_cnt[2]; ++ size_t slice_bytes; + u8 padding; + int count; + u32 reg; +@@ -443,6 +443,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + pred_weight_table = &slice_params->pred_weight_table; + num_entry_point_offsets = slice_params->num_entry_point_offsets; + cedrus_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf); ++ slice_bytes = vb2_get_plane_payload(&run->src->vb2_buf, 0); + + /* + * If entry points offsets are present, we should get them +@@ -490,7 +491,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + + cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0); + +- reg = slice_params->bit_size; ++ reg = slice_bytes * 8; + cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg); + + /* Source beginning and end addresses. */ +@@ -504,10 +505,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + + cedrus_write(dev, VE_DEC_H265_BITS_ADDR, reg); + +- src_buf_end_addr = src_buf_addr + +- DIV_ROUND_UP(slice_params->bit_size, 8); +- +- reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr); ++ reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_addr + slice_bytes); + cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); + + /* Coding tree block address */ +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0061-media-Add-NV12-and-P010-AFBC-compressed-formats.patch b/projects/Allwinner/patches/linux/0061-media-Add-NV12-and-P010-AFBC-compressed-formats.patch new file mode 100644 index 0000000000..353c738920 --- /dev/null +++ b/projects/Allwinner/patches/linux/0061-media-Add-NV12-and-P010-AFBC-compressed-formats.patch @@ -0,0 +1,45 @@ +From b60d442e96407bf90126e455b6466465438a5381 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 7 Oct 2023 09:43:35 +0200 +Subject: [PATCH 15/23] media: Add NV12 and P010 AFBC compressed formats + +Cedrus supports AFBC compressed NV12 and P010 formats, which +considerably speed up H265 decoding. Add them. + +Signed-off-by: Jernej Skrabec +--- + drivers/media/v4l2-core/v4l2-ioctl.c | 2 ++ + include/uapi/linux/videodev2.h | 4 ++++ + 2 files changed, 6 insertions(+) + +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index f4d9d6279094..1e07066fa129 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1510,6 +1510,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) + case V4L2_PIX_FMT_AV1_FRAME: descr = "AV1 Frame"; break; + case V4L2_PIX_FMT_MT2110T: descr = "Mediatek 10bit Tile Mode"; break; + case V4L2_PIX_FMT_MT2110R: descr = "Mediatek 10bit Raster Mode"; break; ++ case V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT: descr = "YUV 4:2:0 (AFBC 16x16)"; break; ++ case V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT: descr = "10-bit YUV 4:2:0 (AFBC 16x16)"; break; + default: + if (fmt->description[0]) + return; +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index 78260e5d9985..968cdb3d0306 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -683,6 +683,10 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_NV12M_8L128 v4l2_fourcc('N', 'A', '1', '2') /* Y/CbCr 4:2:0 8x128 tiles */ + #define V4L2_PIX_FMT_NV12M_10BE_8L128 v4l2_fourcc_be('N', 'T', '1', '2') /* Y/CbCr 4:2:0 10-bit 8x128 tiles */ + ++/* AFBC YUV formats */ ++#define V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT v4l2_fourcc('A', 'S', '1', '2') /* YUV420 AFBC compressed, 16x16 macroblocks, split */ ++#define V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT v4l2_fourcc('A', 'S', '0', '1') /* YUV420 10-bit AFBC compressed, 16x16 macroblocks, split */ ++ + /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */ + #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ + #define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0062-media-cedrus-add-format-filtering-based-on-depth-and.patch b/projects/Allwinner/patches/linux/0062-media-cedrus-add-format-filtering-based-on-depth-and.patch new file mode 100644 index 0000000000..3baad4e0a4 --- /dev/null +++ b/projects/Allwinner/patches/linux/0062-media-cedrus-add-format-filtering-based-on-depth-and.patch @@ -0,0 +1,51 @@ +From ef817a8f5bfd38d91f9250b138a90edafb7b21a0 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 7 Oct 2023 09:45:25 +0200 +Subject: [PATCH 16/23] media: cedrus: add format filtering based on depth and + src format + +Some Cedrus variant, like that found in H6, support special output +formats only with specific codecs, like H265. + +Add extra filtering fields based on bit depth and source format. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus_video.c | 7 +++++++ + drivers/staging/media/sunxi/cedrus/cedrus_video.h | 2 ++ + 2 files changed, 9 insertions(+) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index b00feaf4072c..75b6f2e85a5f 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -87,6 +87,13 @@ static struct cedrus_format *cedrus_find_format(struct cedrus_ctx *ctx, + !(fmt->directions & directions)) + continue; + ++ if (fmt->depth && fmt->depth != ctx->bit_depth) ++ continue; ++ ++ if (fmt->src_format && ++ fmt->src_format != ctx->src_fmt.pixelformat) ++ continue; ++ + if (fmt->pixelformat == pixelformat) + break; + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.h b/drivers/staging/media/sunxi/cedrus/cedrus_video.h +index 8e1afc16a6a1..c8e9909ecdee 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.h +@@ -20,6 +20,8 @@ struct cedrus_format { + u32 pixelformat; + u32 directions; + unsigned int capabilities; ++ unsigned int depth; ++ u32 src_format; + }; + + extern const struct v4l2_ioctl_ops cedrus_ioctl_ops; +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0063-media-cedrus-Implement-AFBC-YUV420-formats-for-H265.patch b/projects/Allwinner/patches/linux/0063-media-cedrus-Implement-AFBC-YUV420-formats-for-H265.patch new file mode 100644 index 0000000000..07b40e5a6b --- /dev/null +++ b/projects/Allwinner/patches/linux/0063-media-cedrus-Implement-AFBC-YUV420-formats-for-H265.patch @@ -0,0 +1,169 @@ +From eaa6dd41f9c4c9a12d7f81a6ead80cc5d7146afa Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 8 Oct 2023 12:44:59 +0200 +Subject: [PATCH 17/23] media: cedrus: Implement AFBC YUV420 formats for H265 + +AFBC output formats are more performant, since they are optimized for +more efficient memory operations and transfers. + +Add support for them. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.h | 11 ++++++ + .../staging/media/sunxi/cedrus/cedrus_h265.c | 3 +- + .../staging/media/sunxi/cedrus/cedrus_hw.c | 16 +++++++++ + .../staging/media/sunxi/cedrus/cedrus_regs.h | 6 ++++ + .../staging/media/sunxi/cedrus/cedrus_video.c | 36 +++++++++++++++++++ + 5 files changed, 71 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h +index 522c184e2afc..c7ec4dee8630 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -268,6 +268,17 @@ cedrus_is_capable(struct cedrus_ctx *ctx, unsigned int capabilities) + return (ctx->dev->capabilities & capabilities) == capabilities; + } + ++static inline bool is_afbc_format(u32 format) ++{ ++ switch (format) { ++ case V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT: ++ case V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT: ++ return true; ++ default: ++ return false; ++ } ++} ++ + void *cedrus_find_control_data(struct cedrus_ctx *ctx, u32 id); + u32 cedrus_get_num_of_controls(struct cedrus_ctx *ctx, u32 id); + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index 16c822637dc6..2372fafab475 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -120,7 +120,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, + { + struct cedrus_dev *dev = ctx->dev; + dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buf, 0); +- dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buf, 1); ++ dma_addr_t dst_chroma_addr = is_afbc_format(ctx->dst_fmt.pixelformat) ? ++ 0 : cedrus_dst_buf_addr(ctx, buf, 1); + dma_addr_t mv_col_buf_addr[2] = { + cedrus_h265_frame_info_mv_col_buf_addr(buf, 0), + cedrus_h265_frame_info_mv_col_buf_addr(buf, field_pic ? 1 : 0) +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +index b696bf884cbd..ac0a88d47e10 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +@@ -65,6 +65,18 @@ int cedrus_engine_enable(struct cedrus_ctx *ctx) + reg |= VE_MODE_PIC_WIDTH_IS_4096; + if (ctx->src_fmt.width > 2048) + reg |= VE_MODE_PIC_WIDTH_MORE_2048; ++ /* ++ * NOTE: Not sure if RGB default color feature is part of official ++ * AFBC standard or not and if it is, which feature that is. However, ++ * in order to render it properly with display engine, default color ++ * has to be set to white there. ++ */ ++ if (is_afbc_format(ctx->dst_fmt.pixelformat)) ++ reg |= VE_MODE_COMPRESS_EN | ++ VE_MODE_MIN_VAL_WRAP_EN | ++ VE_MODE_RGB_DEF_COLOR_EN | ++ VE_MODE_BODYBUF_1K_ALIGNED | ++ VE_MODE_COMPRESS_MODE_AFBC; + + cedrus_write(ctx->dev, VE_MODE, reg); + +@@ -85,6 +97,10 @@ void cedrus_dst_format_set(struct cedrus_dev *dev, + u32 reg; + + switch (fmt->pixelformat) { ++ case V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT: ++ case V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT: ++ /* format is already set in cedrus_engine_enable() */ ++ break; + case V4L2_PIX_FMT_NV12: + chroma_size = ALIGN(width, 16) * ALIGN(height, 16) / 2; + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +index 05e6cbc548ab..c3dcd93a29eb 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_regs.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_regs.h +@@ -35,12 +35,18 @@ + + #define VE_MODE 0x00 + ++#define VE_MODE_COMPRESS_EN BIT(29) ++#define VE_MODE_MIN_VAL_WRAP_EN BIT(27) ++#define VE_MODE_RGB_DEF_COLOR_EN BIT(26) + #define VE_MODE_PIC_WIDTH_IS_4096 BIT(22) + #define VE_MODE_PIC_WIDTH_MORE_2048 BIT(21) + #define VE_MODE_REC_WR_MODE_2MB (0x01 << 20) + #define VE_MODE_REC_WR_MODE_1MB (0x00 << 20) + #define VE_MODE_DDR_MODE_BW_128 (0x03 << 16) + #define VE_MODE_DDR_MODE_BW_256 (0x02 << 16) ++#define VE_MODE_BODYBUF_1K_ALIGNED BIT(12) ++#define VE_MODE_COMPRESS_MODE_LOSSLESS (0x00 << 4) ++#define VE_MODE_COMPRESS_MODE_AFBC (0x01 << 4) + #define VE_MODE_DISABLED (0x07 << 0) + #define VE_MODE_DEC_H265 (0x04 << 0) + #define VE_MODE_DEC_H264 (0x01 << 0) +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +index 75b6f2e85a5f..a61b30946204 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c +@@ -55,6 +55,22 @@ static struct cedrus_format cedrus_formats[] = { + .directions = CEDRUS_DECODE_SRC, + .capabilities = CEDRUS_CAPABILITY_VP8_DEC, + }, ++ { ++ .pixelformat = V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT, ++ .directions = CEDRUS_DECODE_DST, ++ .capabilities = CEDRUS_CAPABILITY_UNTILED | ++ CEDRUS_CAPABILITY_H265_10_DEC, ++ .depth = 10, ++ .src_format = V4L2_PIX_FMT_HEVC_SLICE, ++ }, ++ { ++ .pixelformat = V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT, ++ .directions = CEDRUS_DECODE_DST, ++ .capabilities = CEDRUS_CAPABILITY_UNTILED | ++ CEDRUS_CAPABILITY_H265_10_DEC, ++ .depth = 8, ++ .src_format = V4L2_PIX_FMT_HEVC_SLICE, ++ }, + { + .pixelformat = V4L2_PIX_FMT_NV12, + .directions = CEDRUS_DECODE_DST, +@@ -160,6 +176,26 @@ void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) + sizeimage += bytesperline * height / 2; + + break; ++ ++ case V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT: ++ /* Zero bytes per line for compressed destination. */ ++ bytesperline = 0; ++ ++ sizeimage = DIV_ROUND_UP(width, 16) * ++ DIV_ROUND_UP(height + 4, 16) * (512 + 16) + ++ 32 + SZ_1K; ++ ++ break; ++ ++ case V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT: ++ /* Zero bytes per line for compressed destination. */ ++ bytesperline = 0; ++ ++ sizeimage = DIV_ROUND_UP(width, 16) * ++ DIV_ROUND_UP(height + 4, 16) * (384 + 16) + ++ 32 + SZ_1K; ++ ++ break; + } + + pix_fmt->width = width; +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0064-drm-sun4i-de2-Initialize-layer-fields-earlier.patch b/projects/Allwinner/patches/linux/0064-drm-sun4i-de2-Initialize-layer-fields-earlier.patch new file mode 100644 index 0000000000..b3ac0a7bef --- /dev/null +++ b/projects/Allwinner/patches/linux/0064-drm-sun4i-de2-Initialize-layer-fields-earlier.patch @@ -0,0 +1,68 @@ +From 678c304daf5a489a781179b25fe72e4e856d0c6c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 8 Oct 2023 12:48:12 +0200 +Subject: [PATCH 18/23] drm/sun4i: de2: Initialize layer fields earlier + +drm_universal_plane_init() can already call some callbacks, like +format_mod_supported, during initialization. Because of that, fields +should be initialized beforehand. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 7 ++++--- + drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 7 ++++--- + 2 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +index 884abe3cf773..91781b5bbbbc 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +@@ -365,6 +365,10 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm, + if (!layer) + return ERR_PTR(-ENOMEM); + ++ layer->mixer = mixer; ++ layer->channel = channel; ++ layer->overlay = 0; ++ + if (index == 0) + type = DRM_PLANE_TYPE_PRIMARY; + +@@ -395,9 +399,6 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm, + } + + drm_plane_helper_add(&layer->plane, &sun8i_ui_layer_helper_funcs); +- layer->mixer = mixer; +- layer->channel = channel; +- layer->overlay = 0; + + return layer; + } +diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +index 6ee3790a2a81..329e8bf8cd20 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +@@ -549,6 +549,10 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, + if (!layer) + return ERR_PTR(-ENOMEM); + ++ layer->mixer = mixer; ++ layer->channel = index; ++ layer->overlay = 0; ++ + if (mixer->cfg->is_de3) { + formats = sun8i_vi_layer_de3_formats; + format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats); +@@ -607,9 +611,6 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, + } + + drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs); +- layer->mixer = mixer; +- layer->channel = index; +- layer->overlay = 0; + + return layer; + } +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0065-drm-sun4i-de3-Implement-AFBC-support.patch b/projects/Allwinner/patches/linux/0065-drm-sun4i-de3-Implement-AFBC-support.patch new file mode 100644 index 0000000000..d8cc547d85 --- /dev/null +++ b/projects/Allwinner/patches/linux/0065-drm-sun4i-de3-Implement-AFBC-support.patch @@ -0,0 +1,571 @@ +From 75f9a78d91a37c0eadf952e97e93d3f51bfda1b6 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 8 Oct 2023 13:01:01 +0200 +Subject: [PATCH 19/23] drm/sun4i: de3: Implement AFBC support + +Buffers, compressed with AFBC, are generally more efficient for memory +transfers. Add support for them. + +Currently it's implemented only for VI layers, but vendor code and +documentation suggest UI layers can have them too. However, I haven't +observed any SoC with such feature. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/Makefile | 2 +- + drivers/gpu/drm/sun4i/sun50i_afbc.c | 240 +++++++++++++++++++++++++ + drivers/gpu/drm/sun4i/sun50i_afbc.h | 87 +++++++++ + drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 81 +++++++-- + 4 files changed, 397 insertions(+), 13 deletions(-) + create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.c + create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.h + +diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile +index 3f516329f51e..78290f1660fb 100644 +--- a/drivers/gpu/drm/sun4i/Makefile ++++ b/drivers/gpu/drm/sun4i/Makefile +@@ -17,7 +17,7 @@ sun8i-drm-hdmi-y += sun8i_hdmi_phy_clk.o + sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ + sun8i_vi_layer.o sun8i_ui_scaler.o \ + sun8i_vi_scaler.o sun8i_csc.o \ +- sun50i_fmt.o ++ sun50i_fmt.o sun50i_afbc.o + + sun4i-tcon-y += sun4i_crtc.o + sun4i-tcon-y += sun4i_tcon_dclk.o +diff --git a/drivers/gpu/drm/sun4i/sun50i_afbc.c b/drivers/gpu/drm/sun4i/sun50i_afbc.c +new file mode 100644 +index 000000000000..27a771608eef +--- /dev/null ++++ b/drivers/gpu/drm/sun4i/sun50i_afbc.c +@@ -0,0 +1,240 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (C) Jernej Skrabec ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "sun50i_afbc.h" ++#include "sun8i_mixer.h" ++ ++bool sun50i_afbc_format_mod_supported(struct sun8i_mixer *mixer, ++ u32 format, u64 modifier) ++{ ++ u64 mode; ++ ++ if (modifier == DRM_FORMAT_MOD_INVALID) ++ return false; ++ ++ if (modifier == DRM_FORMAT_MOD_LINEAR) { ++ if (format == DRM_FORMAT_YUV420_8BIT || ++ format == DRM_FORMAT_YUV420_10BIT || ++ format == DRM_FORMAT_Y210) ++ return false; ++ return true; ++ } ++ ++ if (!mixer->cfg->is_de3) ++ return false; ++ ++ mode = AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_SPARSE | ++ AFBC_FORMAT_MOD_SPLIT; ++ ++ switch (format) { ++ case DRM_FORMAT_RGBA8888: ++ case DRM_FORMAT_RGB888: ++ case DRM_FORMAT_RGB565: ++ case DRM_FORMAT_RGBA4444: ++ case DRM_FORMAT_RGBA5551: ++ case DRM_FORMAT_RGBA1010102: ++ mode |= AFBC_FORMAT_MOD_YTR; ++ break; ++ case DRM_FORMAT_YUYV: ++ case DRM_FORMAT_Y210: ++ case DRM_FORMAT_YUV420_8BIT: ++ case DRM_FORMAT_YUV420_10BIT: ++ break; ++ default: ++ return false; ++ } ++ ++ return modifier == DRM_FORMAT_MOD_ARM_AFBC(mode); ++} ++ ++void sun50i_afbc_atomic_update(struct sun8i_mixer *mixer, unsigned int channel, ++ struct drm_plane *plane) ++{ ++ struct drm_plane_state *state = plane->state; ++ struct drm_framebuffer *fb = state->fb; ++ const struct drm_format_info *format = fb->format; ++ struct drm_gem_dma_object *gem; ++ u32 base, val, src_w, src_h; ++ u32 def_color0, def_color1; ++ struct regmap *regs; ++ dma_addr_t dma_addr; ++ ++ base = sun8i_channel_base(mixer, channel) + SUN50I_AFBC_CH_OFFSET; ++ regs = mixer->engine.regs; ++ ++ src_w = drm_rect_width(&state->src) >> 16; ++ src_h = drm_rect_height(&state->src) >> 16; ++ ++ val = SUN50I_FBD_SIZE_HEIGHT(src_h); ++ val |= SUN50I_FBD_SIZE_WIDTH(src_w); ++ regmap_write(regs, SUN50I_FBD_SIZE(base), val); ++ ++ val = SUN50I_FBD_BLK_SIZE_HEIGHT(DIV_ROUND_UP(src_h, 16)); ++ val = SUN50I_FBD_BLK_SIZE_WIDTH(DIV_ROUND_UP(src_w, 16)); ++ regmap_write(regs, SUN50I_FBD_BLK_SIZE(base), val); ++ ++ val = SUN50I_FBD_SRC_CROP_TOP(0); ++ val |= SUN50I_FBD_SRC_CROP_LEFT(0); ++ regmap_write(regs, SUN50I_FBD_SRC_CROP(base), val); ++ ++ val = SUN50I_FBD_LAY_CROP_TOP(state->src.y1 >> 16); ++ val |= SUN50I_FBD_LAY_CROP_LEFT(state->src.x1 >> 16); ++ regmap_write(regs, SUN50I_FBD_LAY_CROP(base), val); ++ ++ /* ++ * Default color is always set to white, in colorspace and bitness ++ * that coresponds to used format. If it is actually used or not ++ * depends on AFBC buffer. At least in Cedrus it can be turned on ++ * or off. ++ * NOTE: G and B channels are off by 1 (up). It's unclear if this ++ * is because HW need such value or it is due to good enough code ++ * in vendor driver and HW clips the value anyway. ++ */ ++ def_color0 = 0; ++ def_color1 = 0; ++ ++ val = 0; ++ switch (format->format) { ++ case DRM_FORMAT_YUYV: ++ case DRM_FORMAT_YUV420_10BIT: ++ val |= SUN50I_FBD_FMT_SBS1(2); ++ val |= SUN50I_FBD_FMT_SBS0(1); ++ break; ++ case DRM_FORMAT_Y210: ++ val |= SUN50I_FBD_FMT_SBS1(3); ++ val |= SUN50I_FBD_FMT_SBS0(2); ++ break; ++ default: ++ val |= SUN50I_FBD_FMT_SBS1(1); ++ val |= SUN50I_FBD_FMT_SBS0(1); ++ break; ++ } ++ switch (format->format) { ++ case DRM_FORMAT_RGBA8888: ++ val |= SUN50I_FBD_FMT_YUV_TRAN; ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA_8888); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(255) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(255); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(256) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(256); ++ break; ++ case DRM_FORMAT_RGB888: ++ val |= SUN50I_FBD_FMT_YUV_TRAN; ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGB_888); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(255); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(256) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(256); ++ break; ++ case DRM_FORMAT_RGB565: ++ val |= SUN50I_FBD_FMT_YUV_TRAN; ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGB_565); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(31); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(64) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(32); ++ break; ++ case DRM_FORMAT_RGBA4444: ++ val |= SUN50I_FBD_FMT_YUV_TRAN; ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA_4444); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(15) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(15); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(16) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(16); ++ break; ++ case DRM_FORMAT_RGBA5551: ++ val |= SUN50I_FBD_FMT_YUV_TRAN; ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA_5551); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(1) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(31); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(32) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(32); ++ break; ++ case DRM_FORMAT_RGBA1010102: ++ val |= SUN50I_FBD_FMT_YUV_TRAN; ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_RGBA1010102); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(3) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(1023); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(1024) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(1024); ++ break; ++ case DRM_FORMAT_YUV420_8BIT: ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_YUV420); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(255); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(128) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(128); ++ break; ++ case DRM_FORMAT_YUYV: ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_YUV422); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(255); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(128) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(128); ++ break; ++ case DRM_FORMAT_YUV420_10BIT: ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_P010); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(1023); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(512) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(512); ++ break; ++ case DRM_FORMAT_Y210: ++ val |= SUN50I_FBD_FMT_IN_FMT(SUN50I_AFBC_P210); ++ def_color0 = SUN50I_FBD_DEFAULT_COLOR0_ALPHA(0) | ++ SUN50I_FBD_DEFAULT_COLOR0_YR(1023); ++ def_color1 = SUN50I_FBD_DEFAULT_COLOR1_UG(512) | ++ SUN50I_FBD_DEFAULT_COLOR1_VB(512); ++ break; ++ } ++ regmap_write(regs, SUN50I_FBD_FMT(base), val); ++ ++ /* Get the physical address of the buffer in memory */ ++ gem = drm_fb_dma_get_gem_obj(fb, 0); ++ ++ DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr); ++ ++ /* Compute the start of the displayed memory */ ++ dma_addr = gem->dma_addr + fb->offsets[0]; ++ ++ regmap_write(regs, SUN50I_FBD_LADDR(base), lower_32_bits(dma_addr)); ++ regmap_write(regs, SUN50I_FBD_HADDR(base), upper_32_bits(dma_addr)); ++ ++ val = SUN50I_FBD_OVL_SIZE_HEIGHT(src_h); ++ val |= SUN50I_FBD_OVL_SIZE_WIDTH(src_w); ++ regmap_write(regs, SUN50I_FBD_OVL_SIZE(base), val); ++ ++ val = SUN50I_FBD_OVL_COOR_Y(0); ++ val |= SUN50I_FBD_OVL_COOR_X(0); ++ regmap_write(regs, SUN50I_FBD_OVL_COOR(base), val); ++ ++ regmap_write(regs, SUN50I_FBD_OVL_BG_COLOR(base), ++ SUN8I_MIXER_BLEND_COLOR_BLACK); ++ regmap_write(regs, SUN50I_FBD_DEFAULT_COLOR0(base), def_color0); ++ regmap_write(regs, SUN50I_FBD_DEFAULT_COLOR1(base), def_color1); ++ ++ val = SUN50I_FBD_CTL_GLB_ALPHA(state->alpha >> 16); ++ val |= SUN50I_FBD_CTL_CLK_GATE; ++ val |= (state->alpha == DRM_BLEND_ALPHA_OPAQUE) ? ++ SUN50I_FBD_CTL_ALPHA_MODE_PIXEL : ++ SUN50I_FBD_CTL_ALPHA_MODE_COMBINED; ++ val |= SUN50I_FBD_CTL_FBD_EN; ++ regmap_write(regs, SUN50I_FBD_CTL(base), val); ++} ++ ++void sun50i_afbc_disable(struct sun8i_mixer *mixer, unsigned int channel) ++{ ++ u32 base = sun8i_channel_base(mixer, channel) + SUN50I_AFBC_CH_OFFSET; ++ ++ regmap_write(mixer->engine.regs, SUN50I_FBD_CTL(base), 0); ++} +diff --git a/drivers/gpu/drm/sun4i/sun50i_afbc.h b/drivers/gpu/drm/sun4i/sun50i_afbc.h +new file mode 100644 +index 000000000000..cea685c86855 +--- /dev/null ++++ b/drivers/gpu/drm/sun4i/sun50i_afbc.h +@@ -0,0 +1,87 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Copyright (C) Jernej Skrabec ++ */ ++ ++#ifndef _SUN50I_AFBC_H_ ++#define _SUN50I_AFBC_H_ ++ ++#include ++ ++#define SUN50I_AFBC_CH_OFFSET 0x300 ++ ++#define SUN50I_AFBC_RGBA_8888 0x02 ++#define SUN50I_AFBC_RGB_888 0x08 ++#define SUN50I_AFBC_RGB_565 0x0a ++#define SUN50I_AFBC_RGBA_4444 0x0e ++#define SUN50I_AFBC_RGBA_5551 0x12 ++#define SUN50I_AFBC_RGBA1010102 0x16 ++#define SUN50I_AFBC_YUV422 0x26 ++#define SUN50I_AFBC_YUV420 0x2a ++#define SUN50I_AFBC_P010 0x30 ++#define SUN50I_AFBC_P210 0x32 ++ ++#define SUN50I_FBD_CTL(base) ((base) + 0x00) ++#define SUN50I_FBD_CTL_GLB_ALPHA(v) ((v) << 24) ++#define SUN50I_FBD_CTL_CLK_GATE BIT(4) ++#define SUN50I_FBD_CTL_ALPHA_MODE_PIXEL ((0) << 2) ++#define SUN50I_FBD_CTL_ALPHA_MODE_LAYER ((1) << 2) ++#define SUN50I_FBD_CTL_ALPHA_MODE_COMBINED ((2) << 2) ++#define SUN50I_FBD_CTL_FBD_FCEN BIT(1) ++#define SUN50I_FBD_CTL_FBD_EN BIT(0) ++ ++#define SUN50I_FBD_SIZE(base) ((base) + 0x08) ++#define SUN50I_FBD_SIZE_HEIGHT(v) (((v) - 1) << 16) ++#define SUN50I_FBD_SIZE_WIDTH(v) (((v) - 1) << 0) ++ ++#define SUN50I_FBD_BLK_SIZE(base) ((base) + 0x0c) ++#define SUN50I_FBD_BLK_SIZE_HEIGHT(v) ((v) << 16) ++#define SUN50I_FBD_BLK_SIZE_WIDTH(v) ((v) << 0) ++ ++#define SUN50I_FBD_SRC_CROP(base) ((base) + 0x10) ++#define SUN50I_FBD_SRC_CROP_TOP(v) ((v) << 16) ++#define SUN50I_FBD_SRC_CROP_LEFT(v) ((v) << 0) ++ ++#define SUN50I_FBD_LAY_CROP(base) ((base) + 0x14) ++#define SUN50I_FBD_LAY_CROP_TOP(v) ((v) << 16) ++#define SUN50I_FBD_LAY_CROP_LEFT(v) ((v) << 0) ++ ++#define SUN50I_FBD_FMT(base) ((base) + 0x18) ++#define SUN50I_FBD_FMT_SBS1(v) ((v) << 18) ++#define SUN50I_FBD_FMT_SBS0(v) ((v) << 16) ++#define SUN50I_FBD_FMT_YUV_TRAN BIT(7) ++#define SUN50I_FBD_FMT_IN_FMT(v) ((v) << 0) ++ ++#define SUN50I_FBD_LADDR(base) ((base) + 0x20) ++#define SUN50I_FBD_HADDR(base) ((base) + 0x24) ++ ++#define SUN50I_FBD_OVL_SIZE(base) ((base) + 0x30) ++#define SUN50I_FBD_OVL_SIZE_HEIGHT(v) (((v) - 1) << 16) ++#define SUN50I_FBD_OVL_SIZE_WIDTH(v) (((v) - 1) << 0) ++ ++#define SUN50I_FBD_OVL_COOR(base) ((base) + 0x34) ++#define SUN50I_FBD_OVL_COOR_Y(v) ((v) << 16) ++#define SUN50I_FBD_OVL_COOR_X(v) ((v) << 0) ++ ++#define SUN50I_FBD_OVL_BG_COLOR(base) ((base) + 0x38) ++#define SUN50I_FBD_OVL_FILL_COLOR(base) ((base) + 0x3c) ++ ++#define SUN50I_FBD_DEFAULT_COLOR0(base) ((base) + 0x50) ++#define SUN50I_FBD_DEFAULT_COLOR0_ALPHA(v) ((v) << 16) ++#define SUN50I_FBD_DEFAULT_COLOR0_YR(v) ((v) << 0) ++ ++#define SUN50I_FBD_DEFAULT_COLOR1(base) ((base) + 0x54) ++#define SUN50I_FBD_DEFAULT_COLOR1_VB(v) ((v) << 16) ++#define SUN50I_FBD_DEFAULT_COLOR1_UG(v) ((v) << 0) ++ ++struct sun8i_mixer; ++struct drm_plane; ++ ++bool sun50i_afbc_format_mod_supported(struct sun8i_mixer *mixer, ++ u32 format, u64 modifier); ++ ++void sun50i_afbc_atomic_update(struct sun8i_mixer *mixer, unsigned int channel, ++ struct drm_plane *plane); ++void sun50i_afbc_disable(struct sun8i_mixer *mixer, unsigned int channel); ++ ++#endif +diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +index 329e8bf8cd20..28a2c44843e6 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +@@ -11,8 +11,10 @@ + #include + #include + #include ++#include + #include + ++#include "sun50i_afbc.h" + #include "sun8i_csc.h" + #include "sun8i_mixer.h" + #include "sun8i_vi_layer.h" +@@ -99,7 +101,7 @@ static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel, + + static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, + int overlay, struct drm_plane *plane, +- unsigned int zpos) ++ unsigned int zpos, bool afbc) + { + struct drm_plane_state *state = plane->state; + const struct drm_format_info *format = state->fb->format; +@@ -182,7 +184,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, + + required = src_h * 100 / dst_h; + +- if (ability < required) { ++ if (!afbc && ability < required) { + DRM_DEBUG_DRIVER("Using vertical coarse scaling\n"); + vm = src_h; + vn = (u32)ability * dst_h / 100; +@@ -192,7 +194,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, + /* it seems that every RGB scaler has buffer for 2048 pixels */ + scanline = subsampled ? mixer->cfg->scanline_yuv : 2048; + +- if (src_w > scanline) { ++ if (!afbc && src_w > scanline) { + DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n"); + hm = src_w; + hn = scanline; +@@ -356,6 +358,15 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, + return 0; + } + ++static void sun8i_vi_layer_prepare_non_linear(struct sun8i_mixer *mixer, ++ int channel, int overlay) ++{ ++ u32 base = sun8i_channel_base(mixer, channel); ++ ++ regmap_write(mixer->engine.regs, ++ SUN8I_MIXER_CHAN_VI_LAYER_ATTR(base, overlay), 0); ++} ++ + static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *state) + { +@@ -399,6 +410,7 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane, + + sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0, + old_zpos); ++ sun50i_afbc_disable(mixer, layer->channel); + } + + static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, +@@ -411,26 +423,51 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, + struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); + unsigned int zpos = new_state->normalized_zpos; + unsigned int old_zpos = old_state->normalized_zpos; ++ struct drm_framebuffer *fb = plane->state->fb; + struct sun8i_mixer *mixer = layer->mixer; ++ bool afbc = drm_is_afbc(fb->modifier); + + if (!new_state->visible) { + sun8i_vi_layer_enable(mixer, layer->channel, + layer->overlay, false, 0, old_zpos); ++ sun50i_afbc_disable(mixer, layer->channel); + return; + } + ++ if (afbc) { ++ u32 fmt_type; ++ ++ sun8i_vi_layer_prepare_non_linear(mixer, layer->channel, ++ layer->overlay); ++ sun50i_afbc_atomic_update(mixer, layer->channel, plane); ++ ++ fmt_type = sun8i_vi_layer_get_format_type(fb->format); ++ sun8i_csc_set_ccsc(mixer, layer->channel, fmt_type, ++ plane->state->color_encoding, ++ plane->state->color_range); ++ } else { ++ sun50i_afbc_disable(mixer, layer->channel); ++ sun8i_vi_layer_update_alpha(mixer, layer->channel, ++ layer->overlay, plane); ++ sun8i_vi_layer_update_formats(mixer, layer->channel, ++ layer->overlay, plane); ++ sun8i_vi_layer_update_buffer(mixer, layer->channel, ++ layer->overlay, plane); ++ } + sun8i_vi_layer_update_coord(mixer, layer->channel, +- layer->overlay, plane, zpos); +- sun8i_vi_layer_update_alpha(mixer, layer->channel, +- layer->overlay, plane); +- sun8i_vi_layer_update_formats(mixer, layer->channel, +- layer->overlay, plane); +- sun8i_vi_layer_update_buffer(mixer, layer->channel, +- layer->overlay, plane); ++ layer->overlay, plane, zpos, afbc); + sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, + true, zpos, old_zpos); + } + ++static bool sun8i_vi_layer_format_mod_supported(struct drm_plane *plane, ++ u32 format, u64 modifier) ++{ ++ struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); ++ ++ return sun50i_afbc_format_mod_supported(layer->mixer, format, modifier); ++} ++ + static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { + .atomic_check = sun8i_vi_layer_atomic_check, + .atomic_disable = sun8i_vi_layer_atomic_disable, +@@ -444,6 +481,7 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs = { + .disable_plane = drm_atomic_helper_disable_plane, + .reset = drm_atomic_helper_plane_reset, + .update_plane = drm_atomic_helper_update_plane, ++ .format_mod_supported = sun8i_vi_layer_format_mod_supported, + }; + + /* +@@ -527,6 +565,11 @@ static const u32 sun8i_vi_layer_de3_formats[] = { + DRM_FORMAT_YVU411, + DRM_FORMAT_YVU420, + DRM_FORMAT_YVU422, ++ ++ /* AFBC only formats */ ++ DRM_FORMAT_YUV420_8BIT, ++ DRM_FORMAT_YUV420_10BIT, ++ DRM_FORMAT_Y210, + }; + + static const uint64_t sun8i_layer_modifiers[] = { +@@ -534,6 +577,18 @@ static const uint64_t sun8i_layer_modifiers[] = { + DRM_FORMAT_MOD_INVALID + }; + ++static const uint64_t sun50i_layer_de3_modifiers[] = { ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_SPARSE | ++ AFBC_FORMAT_MOD_SPLIT), ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_YTR | ++ AFBC_FORMAT_MOD_SPARSE | ++ AFBC_FORMAT_MOD_SPLIT), ++ DRM_FORMAT_MOD_LINEAR, ++ DRM_FORMAT_MOD_INVALID ++}; ++ + struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, + struct sun8i_mixer *mixer, + int index) +@@ -542,6 +597,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, + u32 supported_encodings, supported_ranges; + unsigned int plane_cnt, format_count; + struct sun8i_vi_layer *layer; ++ const uint64_t *modifiers; + const u32 *formats; + int ret; + +@@ -556,9 +612,11 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, + if (mixer->cfg->is_de3) { + formats = sun8i_vi_layer_de3_formats; + format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats); ++ modifiers = sun50i_layer_de3_modifiers; + } else { + formats = sun8i_vi_layer_formats; + format_count = ARRAY_SIZE(sun8i_vi_layer_formats); ++ modifiers = sun8i_layer_modifiers; + } + + if (!mixer->cfg->ui_num && index == 0) +@@ -568,8 +626,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, + ret = drm_universal_plane_init(drm, &layer->plane, 0, + &sun8i_vi_layer_funcs, + formats, format_count, +- sun8i_layer_modifiers, +- type, NULL); ++ modifiers, type, NULL); + if (ret) { + dev_err(drm->dev, "Couldn't initialize layer\n"); + return ERR_PTR(ret); +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0066-media-cedrus-Increase-H6-clock-rate.patch b/projects/Allwinner/patches/linux/0066-media-cedrus-Increase-H6-clock-rate.patch new file mode 100644 index 0000000000..4a1edd6b13 --- /dev/null +++ b/projects/Allwinner/patches/linux/0066-media-cedrus-Increase-H6-clock-rate.patch @@ -0,0 +1,29 @@ +From c7999f0a3a7f275756a10a87849bb8fa47d315d3 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Mon, 9 Oct 2023 20:16:27 +0200 +Subject: [PATCH 20/23] media: cedrus: Increase H6 clock rate + +Vendor driver runs Cedrus at 648 MHz, supposedly to be able to decode +4k HEVC at 60 fps. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c +index 8e248d4a0aec..8d1ad841f66f 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -646,7 +646,7 @@ static const struct cedrus_variant sun50i_h6_cedrus_variant = { + CEDRUS_CAPABILITY_H265_DEC | + CEDRUS_CAPABILITY_H265_10_DEC | + CEDRUS_CAPABILITY_VP8_DEC, +- .mod_rate = 600000000, ++ .mod_rate = 648000000, + }; + + static const struct of_device_id cedrus_dt_match[] = { +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0067-arm64-dts-allwinner-h6-Add-GPU-OPP-to-all-boards.patch b/projects/Allwinner/patches/linux/0067-arm64-dts-allwinner-h6-Add-GPU-OPP-to-all-boards.patch new file mode 100644 index 0000000000..55e88aff4f --- /dev/null +++ b/projects/Allwinner/patches/linux/0067-arm64-dts-allwinner-h6-Add-GPU-OPP-to-all-boards.patch @@ -0,0 +1,67 @@ +From c0652e260579791f38bc1d7c9c634135a1065c82 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Mon, 9 Oct 2023 20:55:25 +0200 +Subject: [PATCH 21/23] arm64: dts: allwinner: h6: Add GPU OPP to all boards + +All H6 boards have GPU. Let's enable OPP table for it on all boards. +That allows either better performance or lower power consumption. + +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts | 1 + + arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi | 1 + + arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 1 + + arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi | 1 + + 4 files changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +index 6fc65e8db220..817976ba20f3 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +@@ -5,6 +5,7 @@ + + #include "sun50i-h6.dtsi" + #include "sun50i-h6-cpu-opp.dtsi" ++#include "sun50i-h6-gpu-opp.dtsi" + + #include + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi +index 92745128fcfe..6a0e3bf9bdb7 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi +@@ -5,6 +5,7 @@ + /dts-v1/; + + #include "sun50i-h6.dtsi" ++#include "sun50i-h6-gpu-opp.dtsi" + + #include + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +index 1ffd68f43f87..ee31303dc886 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +@@ -5,6 +5,7 @@ + + #include "sun50i-h6.dtsi" + #include "sun50i-h6-cpu-opp.dtsi" ++#include "sun50i-h6-gpu-opp.dtsi" + + #include + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi +index c3faefa651d9..531c8f2b423d 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi +@@ -5,6 +5,7 @@ + + #include "sun50i-h6.dtsi" + #include "sun50i-h6-cpu-opp.dtsi" ++#include "sun50i-h6-gpu-opp.dtsi" + + #include + +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0045-wip-h3-h5-cvbs.patch b/projects/Allwinner/patches/linux/0068-wip-h3-h5-cvbs.patch similarity index 84% rename from projects/Allwinner/patches/linux/0045-wip-h3-h5-cvbs.patch rename to projects/Allwinner/patches/linux/0068-wip-h3-h5-cvbs.patch index de3e468fa6..2fac2c6416 100644 --- a/projects/Allwinner/patches/linux/0045-wip-h3-h5-cvbs.patch +++ b/projects/Allwinner/patches/linux/0068-wip-h3-h5-cvbs.patch @@ -1,23 +1,23 @@ -From 24545292c40900c0871381b8697ade70aa9e3bdf Mon Sep 17 00:00:00 2001 +From d7b2340cd84ba5ce3494e8acbf52191e1d85bbe8 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Wed, 20 Jan 2021 22:15:36 +0100 -Subject: [PATCH] wip h3/h5 cvbs +Subject: [PATCH 22/23] wip h3/h5 cvbs --- - arch/arm/boot/dts/allwinner/sun8i-h3.dtsi | 22 +++++ - arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi | 95 +++++++++++++++++++- + arch/arm/boot/dts/allwinner/sun8i-h3.dtsi | 22 +++++ + arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi | 95 +++++++++++++++++++- arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 22 +++++ drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 14 ++- drivers/gpu/drm/sun4i/sun4i_tv.c | 35 +++++++- - drivers/gpu/drm/sun4i/sun8i_mixer.c | 44 ++++++++- + drivers/gpu/drm/sun4i/sun8i_mixer.c | 38 ++++++++ drivers/gpu/drm/sun4i/sun8i_mixer.h | 5 +- - 7 files changed, 226 insertions(+), 11 deletions(-) + 7 files changed, 223 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/allwinner/sun8i-h3.dtsi b/arch/arm/boot/dts/allwinner/sun8i-h3.dtsi -index 448dd325f8c3..d896dc5502f5 100644 +index eac2349a2380..411640fca509 100644 --- a/arch/arm/boot/dts/allwinner/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/allwinner/sun8i-h3.dtsi -@@ -252,6 +252,20 @@ ths: thermal-sensor@1c25000 { +@@ -239,6 +239,20 @@ ths: thermal-sensor@1c25000 { nvmem-cell-names = "calibration"; #thermal-sensor-cells = <0>; }; @@ -38,7 +38,7 @@ index 448dd325f8c3..d896dc5502f5 100644 }; thermal-zones { -@@ -299,6 +313,10 @@ &mbus { +@@ -286,6 +300,10 @@ &mbus { compatible = "allwinner,sun8i-h3-mbus"; }; @@ -49,7 +49,7 @@ index 448dd325f8c3..d896dc5502f5 100644 &mmc0 { compatible = "allwinner,sun7i-a20-mmc"; clocks = <&ccu CLK_BUS_MMC0>, -@@ -346,3 +364,7 @@ &rtc { +@@ -333,3 +351,7 @@ &rtc { &sid { compatible = "allwinner,sun8i-h3-sid"; }; @@ -58,10 +58,10 @@ index 448dd325f8c3..d896dc5502f5 100644 + remote-endpoint = <&tve_in_tcon1>; +}; diff --git a/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi -index 3d37a6a586b6..152029413784 100644 +index ade1cd50e445..dc2ae4270347 100644 --- a/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/allwinner/sunxi-h3-h5.dtsi -@@ -119,7 +119,7 @@ osc32k: osc32k_clk { +@@ -102,7 +102,7 @@ osc32k: osc32k_clk { de: display-engine { compatible = "allwinner,sun8i-h3-display-engine"; @@ -70,7 +70,7 @@ index 3d37a6a586b6..152029413784 100644 status = "disabled"; }; -@@ -163,11 +163,50 @@ ports { +@@ -139,11 +139,50 @@ ports { #size-cells = <0>; mixer0_out: port@1 { @@ -122,7 +122,7 @@ index 3d37a6a586b6..152029413784 100644 }; }; }; -@@ -196,11 +235,19 @@ ports { +@@ -172,11 +211,19 @@ ports { #size-cells = <0>; tcon0_in: port@0 { @@ -143,7 +143,7 @@ index 3d37a6a586b6..152029413784 100644 }; tcon0_out: port@1 { -@@ -216,6 +263,48 @@ tcon0_out_hdmi: endpoint@1 { +@@ -192,6 +239,48 @@ tcon0_out_hdmi: endpoint@1 { }; }; @@ -193,10 +193,10 @@ index 3d37a6a586b6..152029413784 100644 /* compatible and clocks are in per SoC .dtsi file */ reg = <0x01c0f000 0x1000>; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -index 4f00ae227cce..d30c85948ac5 100644 +index d3caf27b6a55..31e67b91e4fa 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -@@ -197,6 +197,20 @@ ths: thermal-sensor@1c25000 { +@@ -184,6 +184,20 @@ ths: thermal-sensor@1c25000 { nvmem-cell-names = "calibration"; #thermal-sensor-cells = <1>; }; @@ -217,7 +217,7 @@ index 4f00ae227cce..d30c85948ac5 100644 }; thermal-zones { -@@ -250,6 +264,10 @@ &mbus { +@@ -237,6 +251,10 @@ &mbus { compatible = "allwinner,sun50i-h5-mbus"; }; @@ -228,7 +228,7 @@ index 4f00ae227cce..d30c85948ac5 100644 &mmc0 { compatible = "allwinner,sun50i-h5-mmc", "allwinner,sun50i-a64-mmc"; -@@ -285,3 +303,7 @@ &rtc { +@@ -272,3 +290,7 @@ &rtc { &sid { compatible = "allwinner,sun50i-h5-sid"; }; @@ -237,10 +237,10 @@ index 4f00ae227cce..d30c85948ac5 100644 + remote-endpoint = <&tve_in_tcon1>; +}; diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c -index e058cf691aea..0b0df6d6bc9c 100644 +index 74274c17efb3..c4f4ba836408 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c -@@ -458,8 +458,18 @@ static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents, +@@ -463,8 +463,18 @@ static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents, CLK_SET_RATE_PARENT); static const char * const tve_parents[] = { "pll-de", "pll-periph1" }; @@ -262,7 +262,7 @@ index e058cf691aea..0b0df6d6bc9c 100644 static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" }; static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents, diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c -index 94883abe0dfd..9c7090a0d52a 100644 +index ec65d9d59de7..d2235d5a7416 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -10,6 +10,7 @@ @@ -273,7 +273,7 @@ index 94883abe0dfd..9c7090a0d52a 100644 #include #include #include -@@ -167,6 +168,11 @@ struct tv_mode { +@@ -159,6 +160,11 @@ struct tv_mode { const struct resync_parameters *resync_params; }; @@ -285,7 +285,7 @@ index 94883abe0dfd..9c7090a0d52a 100644 struct sun4i_tv { struct drm_connector connector; struct drm_encoder encoder; -@@ -527,7 +533,7 @@ static const struct regmap_config sun4i_tv_regmap_config = { +@@ -419,7 +425,7 @@ static const struct regmap_config sun4i_tv_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, @@ -294,7 +294,7 @@ index 94883abe0dfd..9c7090a0d52a 100644 .name = "tv-encoder", }; -@@ -537,13 +543,19 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, +@@ -429,13 +435,19 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = data; struct sun4i_drv *drv = drm->dev_private; @@ -314,7 +314,7 @@ index 94883abe0dfd..9c7090a0d52a 100644 tv->drv = drv; dev_set_drvdata(dev, tv); -@@ -580,6 +592,11 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, +@@ -472,6 +484,11 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, } clk_prepare_enable(tv->clk); @@ -326,8 +326,8 @@ index 94883abe0dfd..9c7090a0d52a 100644 drm_encoder_helper_add(&tv->encoder, &sun4i_tv_helper_funcs); ret = drm_simple_encoder_init(drm, &tv->encoder, -@@ -648,8 +665,22 @@ static int sun4i_tv_remove(struct platform_device *pdev) - return 0; +@@ -551,8 +568,22 @@ static void sun4i_tv_remove(struct platform_device *pdev) + component_del(&pdev->dev, &sun4i_tv_ops); } +static const struct sun4i_tv_quirks a10_quirks = { @@ -351,10 +351,10 @@ index 94883abe0dfd..9c7090a0d52a 100644 }; MODULE_DEVICE_TABLE(of, sun4i_tv_of_table); diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c -index f5291170bf5e..490e8e74450f 100644 +index 8e32d0b24ac9..854f5ab76463 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c -@@ -32,6 +32,12 @@ struct de2_fmt_info { +@@ -36,6 +36,12 @@ struct de2_fmt_info { u32 de2_fmt; }; @@ -367,8 +367,8 @@ index f5291170bf5e..490e8e74450f 100644 static const struct de2_fmt_info de2_formats[] = { { .drm_fmt = DRM_FORMAT_ARGB8888, -@@ -327,10 +333,29 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine, - interlaced ? "on" : "off"); +@@ -369,11 +375,30 @@ static u32 *sun8i_mixer_get_supported_fmts(struct sunxi_engine *engine, u32 *num + return formats; } +static void sun8i_mixer_apply_color_correction(struct sunxi_engine *engine) @@ -389,18 +389,16 @@ index f5291170bf5e..490e8e74450f 100644 +} + static const struct sunxi_engine_ops sun8i_engine_ops = { -- .commit = sun8i_mixer_commit, -- .layers_init = sun8i_layers_init, -- .mode_set = sun8i_mixer_mode_set, -+ .commit = sun8i_mixer_commit, -+ .layers_init = sun8i_layers_init, -+ .mode_set = sun8i_mixer_mode_set, + .commit = sun8i_mixer_commit, + .layers_init = sun8i_layers_init, + .mode_set = sun8i_mixer_mode_set, + .get_supported_fmts = sun8i_mixer_get_supported_fmts, + .apply_color_correction = sun8i_mixer_apply_color_correction, + .disable_color_correction = sun8i_mixer_disable_color_correction, }; - static bool sun8i_mixer_volatile_reg(struct device *dev, unsigned int reg) -@@ -600,6 +625,15 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = { + static const struct regmap_config sun8i_mixer_regmap_config = { +@@ -631,6 +656,15 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = { .vi_num = 1, }; @@ -416,7 +414,7 @@ index f5291170bf5e..490e8e74450f 100644 static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 297000000, -@@ -686,6 +720,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = { +@@ -718,6 +752,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = { .compatible = "allwinner,sun8i-h3-de2-mixer-0", .data = &sun8i_h3_mixer0_cfg, }, @@ -428,7 +426,7 @@ index f5291170bf5e..490e8e74450f 100644 .compatible = "allwinner,sun8i-r40-de2-mixer-0", .data = &sun8i_r40_mixer0_cfg, diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h -index 85c94884fb9a..28cdaf0044d9 100644 +index 13401643c7bf..5951adb66e69 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -118,6 +118,10 @@ @@ -451,5 +449,5 @@ index 85c94884fb9a..28cdaf0044d9 100644 #define SUN50I_MIXER_FCE_EN 0x70000 #define SUN50I_MIXER_PEAK_EN 0x70800 -- -2.37.3 +2.42.0 diff --git a/projects/Allwinner/patches/linux/0046-HACK-SW-CEC-implementation-for-H3.patch b/projects/Allwinner/patches/linux/0069-HACK-SW-CEC-implementation-for-H3.patch similarity index 66% rename from projects/Allwinner/patches/linux/0046-HACK-SW-CEC-implementation-for-H3.patch rename to projects/Allwinner/patches/linux/0069-HACK-SW-CEC-implementation-for-H3.patch index 1c0185c807..d82e27f5a4 100644 --- a/projects/Allwinner/patches/linux/0046-HACK-SW-CEC-implementation-for-H3.patch +++ b/projects/Allwinner/patches/linux/0069-HACK-SW-CEC-implementation-for-H3.patch @@ -1,7 +1,7 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 24edf1dbd1ea0935d425333ab1e1041de2b4874c Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 11 Oct 2021 20:13:41 +0200 -Subject: [PATCH] HACK: SW CEC implementation for H3 +Subject: [PATCH 23/23] HACK: SW CEC implementation for H3 Many H3 boards lack 32768 Hz external oscillator, so internal RC is used instead. However, it's too unstable for CEC. Use SW implementation @@ -10,25 +10,41 @@ instead. That makes it usable, albeit sensitive to cpufreq changes. Signed-off-by: Jernej Skrabec --- drivers/gpu/drm/sun4i/Kconfig | 2 + - drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 13 ++++ - drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 83 +++++++++++++++++++++++++- - 3 files changed, 96 insertions(+), 2 deletions(-) + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 4 ++ + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 14 ++++ + drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 98 +++++++++++++++++++++++++- + 4 files changed, 116 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig -index 5755f0432e77..b93eb2fb52ce 100644 +index 4741d9f6544c..4dac2dddf707 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig -@@ -56,6 +56,8 @@ config DRM_SUN8I_DW_HDMI - tristate "Support for Allwinner version of DesignWare HDMI" +@@ -59,6 +59,8 @@ config DRM_SUN8I_DW_HDMI depends on DRM_SUN4I + default DRM_SUN4I select DRM_DW_HDMI + select CEC_CORE + select CEC_PIN help Choose this option if you have an Allwinner SoC with the - DesignWare HDMI controller with custom HDMI PHY. If M is + DesignWare HDMI controller. SoCs that support HDMI and +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 7309590feb56..bde6b81def55 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -273,6 +273,10 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + return dev_err_probe(dev, PTR_ERR(phy), + "Couldn't get the HDMI PHY\n"); + ++ ret = sun8i_hdmi_phy_register_cec(phy, dev); ++ if (ret) ++ return ret; ++ + hdmi = drmm_kzalloc(drm, sizeof(*hdmi), GFP_KERNEL); + if (!hdmi) + return -ENOMEM; diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h -index bffe1b9cd3dc..61c97619cba1 100644 +index 5383d9267a4d..9d1158f24ddb 100644 --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h @@ -13,6 +13,8 @@ @@ -54,7 +70,7 @@ index bffe1b9cd3dc..61c97619cba1 100644 struct sun8i_hdmi_phy; -@@ -164,6 +173,8 @@ struct sun8i_hdmi_phy_variant { +@@ -159,6 +168,8 @@ struct sun8i_hdmi_phy_variant { }; struct sun8i_hdmi_phy { @@ -63,7 +79,7 @@ index bffe1b9cd3dc..61c97619cba1 100644 struct clk *clk_bus; struct clk *clk_mod; struct clk *clk_phy; -@@ -174,6 +185,8 @@ struct sun8i_hdmi_phy { +@@ -169,6 +180,8 @@ struct sun8i_hdmi_phy { struct regmap *regs; struct reset_control *rst_phy; const struct sun8i_hdmi_phy_variant *variant; @@ -72,11 +88,18 @@ index bffe1b9cd3dc..61c97619cba1 100644 }; struct sun8i_dw_hdmi_quirks { +@@ -211,5 +224,6 @@ void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy, + + int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev, + bool second_parent); ++int sun8i_hdmi_phy_register_cec(struct sun8i_hdmi_phy *phy, struct device *dev); + + #endif /* _SUN8I_DW_HDMI_H_ */ diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c -index b64d93da651d..e2936e7745b8 100644 +index 581233d6eaf2..a5771b5d9b67 100644 --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c -@@ -506,8 +506,9 @@ +@@ -507,8 +507,9 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy) regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, 0); @@ -88,7 +111,7 @@ index b64d93da651d..e2936e7745b8 100644 /* read calibration data */ regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val); -@@ -584,8 +585,47 @@ +@@ -585,8 +586,47 @@ void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy, plat_data->cur_ctr = variant->cur_ctr; plat_data->phy_config = variant->phy_cfg; } @@ -136,40 +159,36 @@ index b64d93da651d..e2936e7745b8 100644 static const struct regmap_config sun8i_hdmi_phy_regmap_config = { .reg_bits = 32, .val_bits = 32, -@@ -653,6 +693,7 @@ - { - struct platform_device *pdev = of_find_device_by_node(node); - struct sun8i_hdmi_phy *phy; +@@ -669,6 +709,41 @@ struct sun8i_hdmi_phy *sun8i_hdmi_phy_get(struct device_node *node) + return phy; + } + ++int sun8i_hdmi_phy_register_cec(struct sun8i_hdmi_phy *phy, struct device *dev) ++{ + int ret; - - if (!pdev) - return -EPROBE_DEFER; -@@ -666,8 +707,35 @@ - hdmi->phy = phy; - - put_device(&pdev->dev); -+ -+ if (phy->bit_bang_cec) { -+ phy->cec_adapter = -+ cec_pin_allocate_adapter(&sun8i_hdmi_phy_cec_pin_ops, -+ phy, "sun8i-cec", -+ CEC_CAP_DEFAULTS); -+ ret = PTR_ERR_OR_ZERO(phy->cec_adapter); -+ if (ret < 0) -+ return 0; + -+ phy->cec_notifier = cec_notifier_cec_adap_register(hdmi->dev, NULL, phy->cec_adapter); -+ if (!phy->cec_notifier) { -+ ret = -ENOMEM; -+ goto err_delete_cec_adapter; -+ } ++ if (!phy->bit_bang_cec) ++ return 0; + -+ ret = cec_register_adapter(phy->cec_adapter, hdmi->dev); -+ if (ret < 0) -+ goto err_put_cec_notifier; ++ phy->cec_adapter = ++ cec_pin_allocate_adapter(&sun8i_hdmi_phy_cec_pin_ops, ++ phy, "sun8i-cec", ++ CEC_CAP_DEFAULTS); ++ if (IS_ERR(phy->cec_adapter)) ++ return PTR_ERR(phy->cec_adapter); ++ ++ phy->cec_notifier = cec_notifier_cec_adap_register(dev, NULL, ++ phy->cec_adapter); ++ if (!phy->cec_notifier) { ++ ret = -ENOMEM; ++ goto err_delete_cec_adapter; + } - - return 0; ++ ++ ret = cec_register_adapter(phy->cec_adapter, dev); ++ if (ret < 0) ++ goto err_put_cec_notifier; ++ ++ return 0; + +err_put_cec_notifier: + cec_notifier_cec_adap_unregister(phy->cec_notifier, phy->cec_adapter); @@ -177,10 +196,12 @@ index b64d93da651d..e2936e7745b8 100644 + cec_delete_adapter(phy->cec_adapter); + + return ret; - } - ++} ++ static int sun8i_hdmi_phy_probe(struct platform_device *pdev) -@@ -682,6 +750,14 @@ + { + struct device *dev = &pdev->dev; +@@ -681,6 +756,14 @@ static int sun8i_hdmi_phy_probe(struct platform_device *pdev) phy->variant = of_device_get_match_data(dev); phy->dev = dev; @@ -195,7 +216,7 @@ index b64d93da651d..e2936e7745b8 100644 regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) -@@ -728,8 +804,19 @@ +@@ -727,8 +810,19 @@ static int sun8i_hdmi_phy_probe(struct platform_device *pdev) return 0; } @@ -215,3 +236,6 @@ index b64d93da651d..e2936e7745b8 100644 .driver = { .name = "sun8i-hdmi-phy", .of_match_table = sun8i_hdmi_phy_of_table, +-- +2.42.0 + From 86074bd1a23382ef13aa9b648e78abfdf086d1ac Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 9 Oct 2023 22:16:25 +0200 Subject: [PATCH 5/7] Allwinner: u-boot: Fix DRAM size detection for H6 --- ...am-size-detection-for-some-H6-boards.patch | 46 +++++++++++++++++++ .../patches/u-boot/0014-unreliable-dram.patch | 40 ---------------- 2 files changed, 46 insertions(+), 40 deletions(-) create mode 100644 projects/Allwinner/patches/u-boot/0014-sunxi-dram-Fix-incorrect-ram-size-detection-for-some-H6-boards.patch delete mode 100644 projects/Allwinner/patches/u-boot/0014-unreliable-dram.patch diff --git a/projects/Allwinner/patches/u-boot/0014-sunxi-dram-Fix-incorrect-ram-size-detection-for-some-H6-boards.patch b/projects/Allwinner/patches/u-boot/0014-sunxi-dram-Fix-incorrect-ram-size-detection-for-some-H6-boards.patch new file mode 100644 index 0000000000..ac90fa5eab --- /dev/null +++ b/projects/Allwinner/patches/u-boot/0014-sunxi-dram-Fix-incorrect-ram-size-detection-for-some-H6-boards.patch @@ -0,0 +1,46 @@ +From: Gunjan Gupta +Subject: [PATCH 1/1] sunxi: dram: Fix incorrect ram size detection for some H6 + boards +Date: Sun, 1 Oct 2023 21:43:32 +0530 + +On some H6 boards like Orange Pi 3 LTS, some times U-Boot fails to detect +ram size correctly. Instead of 2GB thats available, it detects 4GB of ram +and then SPL just hangs there making board not to boot further. + +On debugging, I found that the rows value were being determined correctly, +but columns were sometimes off by one value. I found that adding some +delay after the mctl_core_init call along with making use of dsb in the +start of the mctl_mem_matches solves the issue. + +Signed-off-by: Gunjan Gupta +--- + + arch/arm/mach-sunxi/dram_helpers.c | 1 + + arch/arm/mach-sunxi/dram_sun50i_h6.c | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c +index cdf2750f1c..5758c58e07 100644 +--- a/arch/arm/mach-sunxi/dram_helpers.c ++++ b/arch/arm/mach-sunxi/dram_helpers.c +@@ -32,6 +32,7 @@ void mctl_await_completion(u32 *reg, u32 mask, u32 val) + #ifndef CONFIG_MACH_SUNIV + bool mctl_mem_matches(u32 offset) + { ++ dsb(); + /* Try to write different values to RAM at two addresses */ + writel(0, CFG_SYS_SDRAM_BASE); + writel(0xaa55aa55, (ulong)CFG_SYS_SDRAM_BASE + offset); +diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c +index bff2e42513..a031a845f5 100644 +--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c ++++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c +@@ -623,6 +623,8 @@ static void mctl_auto_detect_dram_size(struct dram_para *para) + para->cols = 11; + mctl_core_init(para); + ++ udelay(50); ++ + for (para->cols = 8; para->cols < 11; para->cols++) { + /* 8 bits per byte and 16/32 bit width */ + if (mctl_mem_matches(1 << (para->cols + 1 + diff --git a/projects/Allwinner/patches/u-boot/0014-unreliable-dram.patch b/projects/Allwinner/patches/u-boot/0014-unreliable-dram.patch deleted file mode 100644 index 222c60b429..0000000000 --- a/projects/Allwinner/patches/u-boot/0014-unreliable-dram.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: megous@megous.com -Date: Mon, 29 Jul 2019 01:39:42 +0200 -Subject: [U-Boot] [PATCH] Fix unreliable detection of DRAM size on Orange Pi 3 - -From: Ondrej Jirman - -Orange Pi 3 has 2 GiB of DRAM, that sometime get misdetected -as 4 GiB, due to false negative result from mctl_mem_matches() -when detecting number of column address bits. This leads to -u-boot detecting more address bits than there are and the -boot process hangs shortly after. - -In mctl_mem_matches() we need to wait for each write to finish, -separately. Without this, the check is not reliable for some -unknown reason, probably having to do with unpredictable memory -access ordering. - -Patch was made with help from AndrĂ© Przywara, who noticed that -my original idea about detection failing due to read-back from -cache without involving DRAM was false, because data cache is -still of at the time of the DRAM size autodetection. - -Signed-off-by: Ondrej Jirman -Cc: AndrĂ© Przywara ---- - arch/arm/mach-sunxi/dram_helpers.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c -index 239ab421a8..6dba448638 100644 ---- a/arch/arm/mach-sunxi/dram_helpers.c -+++ b/arch/arm/mach-sunxi/dram_helpers.c -@@ -30,6 +30,7 @@ bool mctl_mem_matches(u32 offset) - { - /* Try to write different values to RAM at two addresses */ - writel(0, CONFIG_SYS_SDRAM_BASE); -+ dsb(); - writel(0xaa55aa55, (ulong)CONFIG_SYS_SDRAM_BASE + offset); - dsb(); - /* Check if the same value is actually observed when reading back */ From 34391fb3442f16e9f986607c287ff741b1130a26 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 9 Oct 2023 22:18:21 +0200 Subject: [PATCH 6/7] Allwinner: kodi: Fix detection of compressed buffers --- projects/Allwinner/patches/kodi/PR23889.patch | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 projects/Allwinner/patches/kodi/PR23889.patch diff --git a/projects/Allwinner/patches/kodi/PR23889.patch b/projects/Allwinner/patches/kodi/PR23889.patch new file mode 100644 index 0000000000..adca389c5b --- /dev/null +++ b/projects/Allwinner/patches/kodi/PR23889.patch @@ -0,0 +1,27 @@ +From bc62215d60a1b956474cd821e9bd08b4b48dafab Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 8 Oct 2023 16:18:18 +0200 +Subject: [PATCH] VideoLayerBridgeDRMPRIME: Remove pitch check + +With some formats, like single plane and/or compressed ones, pitch can +be 0, since it has no meaning there. + +In any case, drmModeAddFB2WithModifiers() will verify arguments, +including pitch (if applicable), and reject invalid combinations. +--- + .../VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp +index 233e6310bb823..34d1ab6235591 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/VideoLayerBridgeDRMPRIME.cpp +@@ -105,7 +105,7 @@ bool CVideoLayerBridgeDRMPRIME::Map(CVideoBufferDRMPRIME* buffer) + { + int object = layer->planes[plane].object_index; + uint32_t handle = buffer->m_handles[object]; +- if (handle && layer->planes[plane].pitch) ++ if (handle) + { + handles[plane] = handle; + pitches[plane] = layer->planes[plane].pitch; From 8431ea07b4c45b90a454029c7d5a97bfa7f1b4e4 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 9 Oct 2023 22:20:36 +0200 Subject: [PATCH 7/7] Allwinner: ffmpeg: Add support for new formats --- ...0001-v4l2-request-api-add-new-codecs.patch | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 projects/Allwinner/patches/ffmpeg/0001-v4l2-request-api-add-new-codecs.patch diff --git a/projects/Allwinner/patches/ffmpeg/0001-v4l2-request-api-add-new-codecs.patch b/projects/Allwinner/patches/ffmpeg/0001-v4l2-request-api-add-new-codecs.patch new file mode 100644 index 0000000000..cbd290cbcd --- /dev/null +++ b/projects/Allwinner/patches/ffmpeg/0001-v4l2-request-api-add-new-codecs.patch @@ -0,0 +1,115 @@ +From d748cee3aa69b12056fc53c2c48bb866c110f53f Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Mon, 9 Oct 2023 22:19:18 +0200 +Subject: [PATCH] v4l2 request api: add new codecs + +--- + libavcodec/v4l2_request.c | 43 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 38 insertions(+), 5 deletions(-) + +diff --git a/libavcodec/v4l2_request.c b/libavcodec/v4l2_request.c +index 8777834c539f..ceca298956f7 100644 +--- a/libavcodec/v4l2_request.c ++++ b/libavcodec/v4l2_request.c +@@ -38,6 +38,14 @@ + #define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') + #endif + ++#ifndef V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT ++#define V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT fourcc_code('A', 'S', '1', '2') ++#endif ++ ++#ifndef V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT ++#define V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT fourcc_code('A', 'S', '0', '1') ++#endif ++ + uint64_t ff_v4l2_request_get_capture_timestamp(AVFrame *frame) + { + V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)frame->data[0]; +@@ -190,6 +198,9 @@ static int v4l2_request_dequeue_buffer(V4L2RequestContext *ctx, V4L2RequestBuffe + } + + const uint32_t v4l2_request_capture_pixelformats[] = { ++ V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT, ++ V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT, ++ V4L2_PIX_FMT_P010, + V4L2_PIX_FMT_NV12, + #ifdef DRM_FORMAT_MOD_ALLWINNER_TILED + V4L2_PIX_FMT_SUNXI_TILED_NV12, +@@ -210,6 +221,10 @@ static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4 + uint32_t pixelformat = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.pixelformat : format->fmt.pix.pixelformat; + + switch (pixelformat) { ++ case V4L2_PIX_FMT_P010: ++ layer->format = DRM_FORMAT_P010; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; ++ break; + case V4L2_PIX_FMT_NV12: + layer->format = DRM_FORMAT_NV12; + desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; +@@ -236,6 +251,18 @@ static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4 + desc->objects[0].format_modifier = DRM_FORMAT_MOD_LINEAR; + break; + #endif ++ case V4L2_PIX_FMT_YUV420_10_AFBC_16X16_SPLIT: ++ layer->format = DRM_FORMAT_YUV420_10BIT; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_SPARSE | ++ AFBC_FORMAT_MOD_SPLIT); ++ break; ++ case V4L2_PIX_FMT_YUV420_8_AFBC_16X16_SPLIT: ++ layer->format = DRM_FORMAT_YUV420_8BIT; ++ desc->objects[0].format_modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_SPARSE | ++ AFBC_FORMAT_MOD_SPLIT); ++ break; + default: + return -1; + } +@@ -245,15 +272,18 @@ static int v4l2_request_set_drm_descriptor(V4L2RequestDescriptor *req, struct v4 + desc->objects[0].size = req->capture.size; + + desc->nb_layers = 1; +- layer->nb_planes = 2; ++ layer->nb_planes = 1; + + layer->planes[0].object_index = 0; + layer->planes[0].offset = 0; + layer->planes[0].pitch = V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.plane_fmt[0].bytesperline : format->fmt.pix.bytesperline; + +- layer->planes[1].object_index = 0; +- layer->planes[1].offset = layer->planes[0].pitch * (V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.height : format->fmt.pix.height); +- layer->planes[1].pitch = layer->planes[0].pitch; ++ if (desc->objects[0].format_modifier == DRM_FORMAT_MOD_LINEAR) { ++ layer->nb_planes = 2; ++ layer->planes[1].object_index = 0; ++ layer->planes[1].offset = layer->planes[0].pitch * (V4L2_TYPE_IS_MULTIPLANAR(format->type) ? format->fmt.pix_mp.height : format->fmt.pix.height); ++ layer->planes[1].pitch = layer->planes[0].pitch; ++ } + + return 0; + } +@@ -1019,16 +1049,19 @@ int ff_v4l2_request_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_c + { + V4L2RequestContext *ctx = avctx->internal->hwaccel_priv_data; + AVHWFramesContext *hwfc = (AVHWFramesContext*)hw_frames_ctx->data; ++ uint32_t pixelformat; + + hwfc->format = AV_PIX_FMT_DRM_PRIME; +- hwfc->sw_format = AV_PIX_FMT_NV12; + if (V4L2_TYPE_IS_MULTIPLANAR(ctx->format.type)) { + hwfc->width = ctx->format.fmt.pix_mp.width; + hwfc->height = ctx->format.fmt.pix_mp.height; ++ pixelformat = ctx->format.fmt.pix_mp.pixelformat; + } else { + hwfc->width = ctx->format.fmt.pix.width; + hwfc->height = ctx->format.fmt.pix.height; ++ pixelformat = ctx->format.fmt.pix.pixelformat; + } ++ hwfc->sw_format = pixelformat == V4L2_PIX_FMT_P010 ? AV_PIX_FMT_P010LE : AV_PIX_FMT_NV12; + + hwfc->pool = av_buffer_pool_init2(sizeof(V4L2RequestDescriptor), avctx, v4l2_request_frame_alloc, v4l2_request_pool_free); + if (!hwfc->pool) +-- +2.42.0 +