diff --git a/config/kernel/linux-rockchip-rk3588-6.11.config b/config/kernel/linux-rockchip-rk3588-6.11.config index d866c1ad5..347500e39 100644 --- a/config/kernel/linux-rockchip-rk3588-6.11.config +++ b/config/kernel/linux-rockchip-rk3588-6.11.config @@ -4404,6 +4404,7 @@ CONFIG_HW_RANDOM_VIRTIO=m CONFIG_HW_RANDOM_OPTEE=m # CONFIG_HW_RANDOM_CCTRNG is not set # CONFIG_HW_RANDOM_XIPHERA is not set +CONFIG_HW_RANDOM_ROCKCHIP=m CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=m CONFIG_HW_RANDOM_CN10K=y # CONFIG_APPLICOM is not set @@ -5909,6 +5910,8 @@ CONFIG_VIDEO_ROCKCHIP_ISP1=m # # Sunxi media platform drivers # +CONFIG_VIDEO_SYNOPSYS_HDMIRX=m +CONFIG_HDMIRX_LOAD_DEFAULT_EDID=y # # Texas Instruments drivers @@ -6490,6 +6493,7 @@ CONFIG_ROCKCHIP_VOP2=y CONFIG_ROCKCHIP_ANALOGIX_DP=y CONFIG_ROCKCHIP_CDN_DP=y CONFIG_ROCKCHIP_DW_HDMI=y +CONFIG_ROCKCHIP_DW_HDMI_QP=y CONFIG_ROCKCHIP_DW_MIPI_DSI=y CONFIG_ROCKCHIP_INNO_HDMI=y CONFIG_ROCKCHIP_LVDS=y @@ -6660,6 +6664,7 @@ CONFIG_DRM_DW_HDMI_AHB_AUDIO=m CONFIG_DRM_DW_HDMI_I2S_AUDIO=m # CONFIG_DRM_DW_HDMI_GP_AUDIO is not set CONFIG_DRM_DW_HDMI_CEC=m +CONFIG_DRM_DW_HDMI_QP=m CONFIG_DRM_DW_MIPI_DSI=m # end of Display Interface Bridges @@ -8472,6 +8477,7 @@ CONFIG_DVB_AV7110_OSD=y CONFIG_DVB_SP8870=m # CONFIG_VIDEO_MAX96712 is not set CONFIG_VIDEO_ROCKCHIP_VDEC=m +CONFIG_VIDEO_ROCKCHIP_VDEC2=m # # StarFive media platform drivers @@ -10443,6 +10449,8 @@ CONFIG_CRYPTO_DEV_NITROX_CNN55XX=m CONFIG_CRYPTO_DEV_CAVIUM_ZIP=m CONFIG_CRYPTO_DEV_ROCKCHIP=m # CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG is not set +CONFIG_CRYPTO_DEV_ROCKCHIP2=m +# CONFIG_CRYPTO_DEV_ROCKCHIP2_DEBUG is not set CONFIG_CRYPTO_DEV_VIRTIO=m CONFIG_CRYPTO_DEV_SAFEXCEL=m CONFIG_CRYPTO_DEV_CCREE=m diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0024-RK3588-Add-Crypto-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0024-RK3588-Add-Crypto-Support.patch index 9262b1dd7..eacd9fcf9 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0024-RK3588-Add-Crypto-Support.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0024-RK3588-Add-Crypto-Support.patch @@ -1,19 +1,21 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From a0ba8a456c62483e2b8fbbf021fd5ca4ffa07fe8 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Tue, 7 Nov 2023 15:55:27 +0000 -Subject: dt-bindings: crypto: add support for rockchip,crypto-rk3588 +Subject: [PATCH 1/4] dt-bindings: crypto: add support for + rockchip,crypto-rk3588 Add device tree binding documentation for the Rockchip cryptographic offloader V2. Signed-off-by: Corentin Labbe --- - Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml | 65 ++++++++++ + .../crypto/rockchip,rk3588-crypto.yaml | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) + create mode 100644 Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml diff --git a/Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml b/Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml new file mode 100644 -index 000000000000..111111111111 +index 000000000000..c01963413260 --- /dev/null +++ b/Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml @@ -0,0 +1,65 @@ @@ -83,12 +85,13 @@ index 000000000000..111111111111 + reset-names = "core"; + }; -- -Armbian +2.45.2 -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 + +From b9c55c60a732b7d05b6344289091218f7dcb9208 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Tue, 7 Nov 2023 15:55:30 +0000 -Subject: ARM64: dts: rk356x: add crypto node +Subject: [PATCH 2/4] ARM64: dts: rk356x: add crypto node Both RK3566 and RK3568 have a crypto IP handled by the rk3588 crypto driver so adds a node for it. @@ -96,11 +99,11 @@ node for it. Tested-by: Ricardo Pardini Signed-off-by: Corentin Labbe --- - arch/arm64/boot/dts/rockchip/rk356x.dtsi | 12 ++++++++++ + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi -index 111111111111..222222222222 100644 +index 4690be841a1c..50d1c42b6740 100644 --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi @@ -1113,6 +1113,18 @@ sdhci: mmc@fe310000 { @@ -123,12 +126,13 @@ index 111111111111..222222222222 100644 compatible = "rockchip,rk3568-i2s-tdm"; reg = <0x0 0xfe400000 0x0 0x1000>; -- -Armbian +2.45.2 -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 + +From 9e082adac7e03d2ffe78b49f92e556a4a70e0ee8 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Tue, 7 Nov 2023 15:55:31 +0000 -Subject: reset: rockchip: secure reset must be used by SCMI +Subject: [PATCH 3/4] reset: rockchip: secure reset must be used by SCMI While working on the rk3588 crypto driver, I loose lot of time understanding why resetting the IP failed. @@ -138,12 +142,12 @@ All resets in this block must be handled via SCMI call. Signed-off-by: Corentin Labbe --- - drivers/clk/rockchip/rst-rk3588.c | 42 ------ - include/dt-bindings/reset/rockchip,rk3588-cru.h | 68 +++++----- + drivers/clk/rockchip/rst-rk3588.c | 42 ------------ + .../dt-bindings/reset/rockchip,rk3588-cru.h | 68 +++++++++---------- 2 files changed, 34 insertions(+), 76 deletions(-) diff --git a/drivers/clk/rockchip/rst-rk3588.c b/drivers/clk/rockchip/rst-rk3588.c -index 111111111111..222222222222 100644 +index c4ebc01f1c9c..7a856de64d9e 100644 --- a/drivers/clk/rockchip/rst-rk3588.c +++ b/drivers/clk/rockchip/rst-rk3588.c @@ -16,9 +16,6 @@ @@ -203,7 +207,7 @@ index 111111111111..222222222222 100644 void rk3588_rst_init(struct device_node *np, void __iomem *reg_base) diff --git a/include/dt-bindings/reset/rockchip,rk3588-cru.h b/include/dt-bindings/reset/rockchip,rk3588-cru.h -index 111111111111..222222222222 100644 +index e2fe4bd5f7f0..b74f1046f5a5 100644 --- a/include/dt-bindings/reset/rockchip,rk3588-cru.h +++ b/include/dt-bindings/reset/rockchip,rk3588-cru.h @@ -716,40 +716,40 @@ @@ -282,12 +286,13 @@ index 111111111111..222222222222 100644 #define SRST_A_HDMIRX_BIU 660 -- -Armbian +2.45.2 -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 + +From 8e6f2d80ad933db9d542a9d08a9f733341e65b90 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Tue, 7 Nov 2023 15:55:32 +0000 -Subject: crypto: rockchip: add rk3588 driver +Subject: [PATCH 4/4] crypto: rockchip: add rk3588 driver RK3588 have a new crypto IP, this patch adds basic support for it. Only hashes and cipher are handled for the moment. @@ -296,14 +301,18 @@ Signed-off-by: Corentin Labbe --- drivers/crypto/Kconfig | 29 + drivers/crypto/rockchip/Makefile | 5 + - drivers/crypto/rockchip/rk2_crypto.c | 739 ++++++++++ - drivers/crypto/rockchip/rk2_crypto.h | 246 +++ - drivers/crypto/rockchip/rk2_crypto_ahash.c | 344 +++++ - drivers/crypto/rockchip/rk2_crypto_skcipher.c | 576 ++++++++ - 6 files changed, 1939 insertions(+) + drivers/crypto/rockchip/rk2_crypto.c | 738 ++++++++++++++++++ + drivers/crypto/rockchip/rk2_crypto.h | 246 ++++++ + drivers/crypto/rockchip/rk2_crypto_ahash.c | 344 ++++++++ + drivers/crypto/rockchip/rk2_crypto_skcipher.c | 576 ++++++++++++++ + 6 files changed, 1938 insertions(+) + create mode 100644 drivers/crypto/rockchip/rk2_crypto.c + create mode 100644 drivers/crypto/rockchip/rk2_crypto.h + create mode 100644 drivers/crypto/rockchip/rk2_crypto_ahash.c + create mode 100644 drivers/crypto/rockchip/rk2_crypto_skcipher.c diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig -index 111111111111..222222222222 100644 +index 94f23c6fc93b..95d700c88161 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -653,6 +653,35 @@ config CRYPTO_DEV_TEGRA @@ -343,7 +352,7 @@ index 111111111111..222222222222 100644 tristate "Support for Xilinx ZynqMP AES hw accelerator" depends on ZYNQMP_FIRMWARE || COMPILE_TEST diff --git a/drivers/crypto/rockchip/Makefile b/drivers/crypto/rockchip/Makefile -index 111111111111..222222222222 100644 +index 785277aca71e..452a12ff6538 100644 --- a/drivers/crypto/rockchip/Makefile +++ b/drivers/crypto/rockchip/Makefile @@ -3,3 +3,8 @@ obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rk_crypto.o @@ -357,10 +366,10 @@ index 111111111111..222222222222 100644 + rk2_crypto_ahash.o diff --git a/drivers/crypto/rockchip/rk2_crypto.c b/drivers/crypto/rockchip/rk2_crypto.c new file mode 100644 -index 000000000000..111111111111 +index 000000000000..bac7cc39c403 --- /dev/null +++ b/drivers/crypto/rockchip/rk2_crypto.c -@@ -0,0 +1,739 @@ +@@ -0,0 +1,738 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * hardware cryptographic offloader for RK3568/RK3588 SoC @@ -1063,7 +1072,7 @@ index 000000000000..111111111111 + return err; +} + -+static int rk2_crypto_remove(struct platform_device *pdev) ++static void rk2_crypto_remove(struct platform_device *pdev) +{ + struct rk2_crypto_dev *rkc = platform_get_drvdata(pdev); + struct rk2_crypto_dev *first; @@ -1082,7 +1091,6 @@ index 000000000000..111111111111 + } + rk2_crypto_pm_exit(rkc); + crypto_engine_exit(rkc->engine); -+ return 0; +} + +static struct platform_driver crypto_driver = { @@ -1102,7 +1110,7 @@ index 000000000000..111111111111 +MODULE_AUTHOR("Corentin Labbe "); diff --git a/drivers/crypto/rockchip/rk2_crypto.h b/drivers/crypto/rockchip/rk2_crypto.h new file mode 100644 -index 000000000000..111111111111 +index 000000000000..59cd8be59f70 --- /dev/null +++ b/drivers/crypto/rockchip/rk2_crypto.h @@ -0,0 +1,246 @@ @@ -1354,7 +1362,7 @@ index 000000000000..111111111111 +void rk2_hash_exit_tfm(struct crypto_ahash *tfm); diff --git a/drivers/crypto/rockchip/rk2_crypto_ahash.c b/drivers/crypto/rockchip/rk2_crypto_ahash.c new file mode 100644 -index 000000000000..111111111111 +index 000000000000..75b8d9893447 --- /dev/null +++ b/drivers/crypto/rockchip/rk2_crypto_ahash.c @@ -0,0 +1,344 @@ @@ -1704,7 +1712,7 @@ index 000000000000..111111111111 +} diff --git a/drivers/crypto/rockchip/rk2_crypto_skcipher.c b/drivers/crypto/rockchip/rk2_crypto_skcipher.c new file mode 100644 -index 000000000000..111111111111 +index 000000000000..3e8e44d84b47 --- /dev/null +++ b/drivers/crypto/rockchip/rk2_crypto_skcipher.c @@ -0,0 +1,576 @@ @@ -2285,5 +2293,5 @@ index 000000000000..111111111111 + crypto_free_skcipher(ctx->fallback_tfm); +} -- -Armbian +2.45.2 diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0026-RK3588-Add-VPU121-H.264-Decoder-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0026-RK3588-Add-VPU121-H.264-Decoder-Support.patch index a82128b41..e82613093 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0026-RK3588-Add-VPU121-H.264-Decoder-Support.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0026-RK3588-Add-VPU121-H.264-Decoder-Support.patch @@ -1,9 +1,7 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Thu, 13 Jun 2024 15:48:42 +0200 -Subject: media: dt-bindings: rk3568-vepu: Add RK3588 VEPU121 - +From 74ffd5840cdacdb030246e79a2485016296d73f5 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot +Date: Thu, 18 Apr 2024 16:15:05 +0200 +Subject: [PATCH 1/7] media: dt-bindings: rk3568-vepu: Add RK3588 VEPU121 This encoder-only device is present four times on this SoC, and should support everything the rk3568 vepu supports (so JPEG, H.264 and VP8 @@ -12,13 +10,14 @@ systems might already support RK3568 VEPU and want to avoid registering four of them separately considering they can be used as a cluster. Signed-off-by: Emmanuel Gil Peyrot +Acked-by: Conor Dooley Signed-off-by: Sebastian Reichel --- - Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml | 1 + + .../devicetree/bindings/media/rockchip,rk3568-vepu.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml b/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml -index 111111111111..222222222222 100644 +index 9d90d8d0565a..947ad699cc5e 100644 --- a/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml +++ b/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml @@ -17,6 +17,7 @@ properties: @@ -30,12 +29,49 @@ index 111111111111..222222222222 100644 reg: maxItems: 1 -- -Armbian +2.46.0 -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 + +From 936c9b832deddee07a229c3ad19d0e284d2b7d4a Mon Sep 17 00:00:00 2001 +From: Jianfeng Liu +Date: Tue, 30 Apr 2024 10:40:01 +0800 +Subject: [PATCH 2/7] media: dt-bindings: rockchip-vpu: Add RK3588 VPU121 + +RK3588 has four Hantro H1 VEPUs (encoder-only) modules and one combined +Hantro H1/G1 VPU (decoder and encoder). These are not described as +separate IP, since they are sharing an internal cache. This adds the +RK3588 specific compatible string for the combined VPU, which seems to +be identical to the version found in the RK3568. + +Signed-off-by: Jianfeng Liu +Acked-by: Conor Dooley +Signed-off-by: Sebastian Reichel +--- + Documentation/devicetree/bindings/media/rockchip-vpu.yaml | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +index c57e1f488895..2710bb2fb0d1 100644 +--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +@@ -31,6 +31,9 @@ properties: + - items: + - const: rockchip,rk3228-vpu + - const: rockchip,rk3399-vpu ++ - items: ++ - const: rockchip,rk3588-vpu121 ++ - const: rockchip,rk3568-vpu + + reg: + maxItems: 1 +-- +2.46.0 + + +From 5199fc492e1d0d8ce04ffd251cdf0af87f02fbf3 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel -Date: Thu, 13 Jun 2024 15:48:44 +0200 -Subject: media: hantro: Disable multicore support +Date: Thu, 13 Jun 2024 14:29:55 +0200 +Subject: [PATCH 3/7] media: hantro: Disable multicore support Avoid exposing equal Hantro video codecs to userspace. Equal video codecs allow scheduling work between the cores. For that kernel support @@ -48,14 +84,14 @@ cores), but applies to all SoCs. Signed-off-by: Sebastian Reichel --- - drivers/media/platform/verisilicon/hantro_drv.c | 37 ++++++++++ - 1 file changed, 37 insertions(+) + .../media/platform/verisilicon/hantro_drv.c | 47 +++++++++++++++++++ + 1 file changed, 47 insertions(+) diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c -index 111111111111..222222222222 100644 +index 34b123dafd89..748187623990 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c -@@ -992,6 +992,39 @@ static const struct media_device_ops hantro_m2m_media_ops = { +@@ -992,6 +992,49 @@ static const struct media_device_ops hantro_m2m_media_ops = { .req_queue = v4l2_m2m_request_queue, }; @@ -70,8 +106,9 @@ index 111111111111..222222222222 100644 + */ +static int hantro_disable_multicore(struct hantro_dev *vpu) +{ ++ struct device_node *node = NULL; + const char *compatible; -+ struct device_node *node; ++ bool is_main_core; + int ret; + + /* Intentionally ignores the fallback strings */ @@ -79,12 +116,21 @@ index 111111111111..222222222222 100644 + if (ret) + return ret; + -+ /* first compatible node found from the root node is considered the main core */ -+ node = of_find_compatible_node(NULL, NULL, compatible); -+ if (!node) -+ return -EINVAL; /* broken DT? */ ++ /* The first compatible and available node found is considered the main core */ ++ do { ++ node = of_find_compatible_node(node, NULL, compatible); ++ if (of_device_is_available(node)) ++ break; ++ } while (node); + -+ if (vpu->dev->of_node != node) { ++ if (!node) ++ return -EINVAL; ++ ++ is_main_core = (vpu->dev->of_node == node); ++ ++ of_node_put(node); ++ ++ if (!is_main_core) { + dev_info(vpu->dev, "missing multi-core support, ignoring this instance\n"); + return -ENODEV; + } @@ -95,7 +141,7 @@ index 111111111111..222222222222 100644 static int hantro_probe(struct platform_device *pdev) { const struct of_device_id *match; -@@ -1011,6 +1044,10 @@ static int hantro_probe(struct platform_device *pdev) +@@ -1011,6 +1054,10 @@ static int hantro_probe(struct platform_device *pdev) match = of_match_node(of_hantro_match, pdev->dev.of_node); vpu->variant = match->data; @@ -107,12 +153,13 @@ index 111111111111..222222222222 100644 * Support for nxp,imx8mq-vpu is kept for backwards compatibility * but it's deprecated. Please update your DTS file to use -- -Armbian +2.46.0 -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 + +From bb294970b29147116b8d6699c05e1c51f9b3a746 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel -Date: Thu, 13 Jun 2024 15:48:45 +0200 -Subject: media: hantro: Add RK3588 VEPU121 +Date: Thu, 13 Jun 2024 14:48:43 +0200 +Subject: [PATCH 4/7] media: hantro: Add RK3588 VEPU121 RK3588 handling is exactly the same as RK3568. This is not handled using fallback compatibles to avoid exposing multiple @@ -125,7 +172,7 @@ Signed-off-by: Sebastian Reichel 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c -index 111111111111..222222222222 100644 +index 748187623990..05bbac853c4f 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -722,6 +722,7 @@ static const struct of_device_id of_hantro_match[] = { @@ -137,5 +184,219 @@ index 111111111111..222222222222 100644 #endif #ifdef CONFIG_VIDEO_HANTRO_IMX8M -- -Armbian +2.46.0 + + +From 9820579abb632ea927e6e693ea8f9ea9fc2a90c5 Mon Sep 17 00:00:00 2001 +From: Emmanuel Gil Peyrot +Date: Wed, 5 Jun 2024 15:28:33 +0200 +Subject: [PATCH 5/7] arm64: dts: rockchip: Add VEPU121 to RK3588 + +RK3588 has 4 Hantro G1 encoder-only cores. They are all independent IP, +but can be used as a cluster (i.e. sharing work between the cores). +These cores are called VEPU121 in the TRM. The TRM describes one more +VEPU121, but that is combined with a Hantro H1. That one will be handled +using the VPU binding instead. + +Signed-off-by: Emmanuel Gil Peyrot +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 80 +++++++++++++++++++ + 1 file changed, 80 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +index b6e4df180f0b..595f129a2d8c 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +@@ -1122,6 +1122,86 @@ power-domain@RK3588_PD_SDMMC { + }; + }; + ++ vepu121_0: video-codec@fdba0000 { ++ compatible = "rockchip,rk3588-vepu121"; ++ reg = <0x0 0xfdba0000 0x0 0x800>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER0>, <&cru HCLK_JPEG_ENCODER0>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vepu121_0_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vepu121_0_mmu: iommu@fdba0800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdba0800 0x0 0x40>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER0>, <&cru HCLK_JPEG_ENCODER0>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ ++ vepu121_1: video-codec@fdba4000 { ++ compatible = "rockchip,rk3588-vepu121"; ++ reg = <0x0 0xfdba4000 0x0 0x800>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER1>, <&cru HCLK_JPEG_ENCODER1>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vepu121_1_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vepu121_1_mmu: iommu@fdba4800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdba4800 0x0 0x40>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER1>, <&cru HCLK_JPEG_ENCODER1>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ ++ vepu121_2: video-codec@fdba8000 { ++ compatible = "rockchip,rk3588-vepu121"; ++ reg = <0x0 0xfdba8000 0x0 0x800>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER2>, <&cru HCLK_JPEG_ENCODER2>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vepu121_2_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vepu121_2_mmu: iommu@fdba8800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdba8800 0x0 0x40>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER2>, <&cru HCLK_JPEG_ENCODER2>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ ++ vepu121_3: video-codec@fdbac000 { ++ compatible = "rockchip,rk3588-vepu121"; ++ reg = <0x0 0xfdbac000 0x0 0x800>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER3>, <&cru HCLK_JPEG_ENCODER3>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vepu121_3_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vepu121_3_mmu: iommu@fdbac800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdbac800 0x0 0x40>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER3>, <&cru HCLK_JPEG_ENCODER3>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ + av1d: video-codec@fdc70000 { + compatible = "rockchip,rk3588-av1-vpu"; + reg = <0x0 0xfdc70000 0x0 0x800>; +-- +2.46.0 + + +From 9abdf23677ceaf0f2b2984ba4adf8105dbd2df25 Mon Sep 17 00:00:00 2001 +From: Jianfeng Liu +Date: Tue, 30 Apr 2024 10:40:02 +0800 +Subject: [PATCH 6/7] arm64: dts: rockchip: Add VPU121 support for RK3588 + +Enable Hantro G1 video decoder in RK3588's devicetree. + +Tested with FFmpeg v4l2_request code taken from [1] +with MPEG2, H.264 and VP8 samples. + +[1] https://github.com/LibreELEC/LibreELEC.tv/blob/master/packages/multimedia/ffmpeg/patches/v4l2-request/ffmpeg-001-v4l2-request.patch + +Signed-off-by: Jianfeng Liu +Tested-by: Hugh Cole-Baker +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 21 +++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +index 595f129a2d8c..14b8d8691255 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +@@ -1122,6 +1122,27 @@ power-domain@RK3588_PD_SDMMC { + }; + }; + ++ vpu121: video-codec@fdb50000 { ++ compatible = "rockchip,rk3588-vpu121", "rockchip,rk3568-vpu"; ++ reg = <0x0 0xfdb50000 0x0 0x800>; ++ interrupts = ; ++ interrupt-names = "vdpu"; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vpu121_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vpu121_mmu: iommu@fdb50800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdb50800 0x0 0x40>; ++ interrupts = ; ++ clock-names = "aclk", "iface"; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ + vepu121_0: video-codec@fdba0000 { + compatible = "rockchip,rk3588-vepu121"; + reg = <0x0 0xfdba0000 0x0 0x800>; +-- +2.46.0 + + +From 64cf83f3ee9ac0a7987e2354d6b4a6875be6b7dc Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Mon, 29 Jul 2024 23:21:19 +0300 +Subject: [PATCH 7/7] arm64: dts: rockchip: rk3588: disable H264 decoding on + Hantro decoder + +--- + Documentation/devicetree/bindings/media/rockchip-vpu.yaml | 2 +- + arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 7 ++++--- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +index 2710bb2fb0d1..1da7700e4a55 100644 +--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +@@ -33,7 +33,7 @@ properties: + - const: rockchip,rk3399-vpu + - items: + - const: rockchip,rk3588-vpu121 +- - const: rockchip,rk3568-vpu ++ - const: rockchip,rk3399-vpu + + reg: + maxItems: 1 +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +index 14b8d8691255..ee5e6c45f601 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +@@ -1123,10 +1123,11 @@ power-domain@RK3588_PD_SDMMC { + }; + + vpu121: video-codec@fdb50000 { +- compatible = "rockchip,rk3588-vpu121", "rockchip,rk3568-vpu"; ++ compatible = "rockchip,rk3588-vpu121", "rockchip,rk3399-vpu"; + reg = <0x0 0xfdb50000 0x0 0x800>; +- interrupts = ; +- interrupt-names = "vdpu"; ++ interrupts = , ++ ; ++ interrupt-names = "vepu", "vdpu"; + clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; + clock-names = "aclk", "hclk"; + iommus = <&vpu121_mmu>; +-- +2.46.0 diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0027-RK3588-Add-rkvdec2-Support-v3.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0027-RK3588-Add-rkvdec2-Support-v3.patch index 83106c591..1ac1c5c19 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0027-RK3588-Add-rkvdec2-Support-v3.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0027-RK3588-Add-rkvdec2-Support-v3.patch @@ -1,21 +1,546 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From b2e319e38dac42c3ca0d4bf18adb5a9fa02a4b72 Mon Sep 17 00:00:00 2001 From: Detlev Casanova -Date: Thu, 20 Jun 2024 10:19:43 -0400 -Subject: media: rockchip: Move H264 CABAC table to header file +Date: Tue, 18 Jun 2024 12:41:51 -0400 +Subject: [PATCH 1/4] media: rockchip: Move H264 CABAC table to header file The table will be shared with the rkvdec2 driver in following commits. +As HW formatted CABAC tables can be shared between drivers, it makes sense +to group them in an include folder. + +Each driver can include the tables they need so that all tables are not +built in the kernel, but rather in each driver, if the driver is enabled. + Signed-off-by: Detlev Casanova --- - drivers/staging/media/rkvdec/rkvdec-h264-cabac.h | 509 ++++++++++ - drivers/staging/media/rkvdec/rkvdec-h264.c | 500 +-------- + drivers/staging/media/rkvdec/rkvdec-h264.c | 500 +------------------- + include/media/v4l2-cabac/rkvdec-cabac.h | 509 +++++++++++++++++++++ 2 files changed, 510 insertions(+), 499 deletions(-) + create mode 100644 include/media/v4l2-cabac/rkvdec-cabac.h -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264-cabac.h b/drivers/staging/media/rkvdec/rkvdec-h264-cabac.h +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 4fc167b42cf0..ce63b6fbaa33 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -11,6 +11,7 @@ + + #include + #include ++#include + + #include "rkvdec.h" + #include "rkvdec-regs.h" +@@ -117,505 +118,6 @@ struct rkvdec_h264_ctx { + struct rkvdec_h264_reflists reflists; + }; + +-#define CABAC_ENTRY(ctxidx, idc0_m, idc0_n, idc1_m, idc1_n, \ +- idc2_m, idc2_n, intra_m, intra_n) \ +- [0][(ctxidx)] = {idc0_m, idc0_n}, \ +- [1][(ctxidx)] = {idc1_m, idc1_n}, \ +- [2][(ctxidx)] = {idc2_m, idc2_n}, \ +- [3][(ctxidx)] = {intra_m, intra_n} +- +-/* +- * Constant CABAC table. +- * Built from the tables described in section '9.3.1.1 Initialisation process +- * for context variables' of the H264 spec. +- */ +-static const s8 rkvdec_h264_cabac_table[4][464][2] = { +- /* Table 9-12 – Values of variables m and n for ctxIdx from 0 to 10 */ +- CABAC_ENTRY(0, 20, -15, 20, -15, 20, -15, 20, -15), +- CABAC_ENTRY(1, 2, 54, 2, 54, 2, 54, 2, 54), +- CABAC_ENTRY(2, 3, 74, 3, 74, 3, 74, 3, 74), +- CABAC_ENTRY(3, 20, -15, 20, -15, 20, -15, 20, -15), +- CABAC_ENTRY(4, 2, 54, 2, 54, 2, 54, 2, 54), +- CABAC_ENTRY(5, 3, 74, 3, 74, 3, 74, 3, 74), +- CABAC_ENTRY(6, -28, 127, -28, 127, -28, 127, -28, 127), +- CABAC_ENTRY(7, -23, 104, -23, 104, -23, 104, -23, 104), +- CABAC_ENTRY(8, -6, 53, -6, 53, -6, 53, -6, 53), +- CABAC_ENTRY(9, -1, 54, -1, 54, -1, 54, -1, 54), +- CABAC_ENTRY(10, 7, 51, 7, 51, 7, 51, 7, 51), +- +- /* Table 9-13 – Values of variables m and n for ctxIdx from 11 to 23 */ +- CABAC_ENTRY(11, 23, 33, 22, 25, 29, 16, 0, 0), +- CABAC_ENTRY(12, 23, 2, 34, 0, 25, 0, 0, 0), +- CABAC_ENTRY(13, 21, 0, 16, 0, 14, 0, 0, 0), +- CABAC_ENTRY(14, 1, 9, -2, 9, -10, 51, 0, 0), +- CABAC_ENTRY(15, 0, 49, 4, 41, -3, 62, 0, 0), +- CABAC_ENTRY(16, -37, 118, -29, 118, -27, 99, 0, 0), +- CABAC_ENTRY(17, 5, 57, 2, 65, 26, 16, 0, 0), +- CABAC_ENTRY(18, -13, 78, -6, 71, -4, 85, 0, 0), +- CABAC_ENTRY(19, -11, 65, -13, 79, -24, 102, 0, 0), +- CABAC_ENTRY(20, 1, 62, 5, 52, 5, 57, 0, 0), +- CABAC_ENTRY(21, 12, 49, 9, 50, 6, 57, 0, 0), +- CABAC_ENTRY(22, -4, 73, -3, 70, -17, 73, 0, 0), +- CABAC_ENTRY(23, 17, 50, 10, 54, 14, 57, 0, 0), +- +- /* Table 9-14 – Values of variables m and n for ctxIdx from 24 to 39 */ +- CABAC_ENTRY(24, 18, 64, 26, 34, 20, 40, 0, 0), +- CABAC_ENTRY(25, 9, 43, 19, 22, 20, 10, 0, 0), +- CABAC_ENTRY(26, 29, 0, 40, 0, 29, 0, 0, 0), +- CABAC_ENTRY(27, 26, 67, 57, 2, 54, 0, 0, 0), +- CABAC_ENTRY(28, 16, 90, 41, 36, 37, 42, 0, 0), +- CABAC_ENTRY(29, 9, 104, 26, 69, 12, 97, 0, 0), +- CABAC_ENTRY(30, -46, 127, -45, 127, -32, 127, 0, 0), +- CABAC_ENTRY(31, -20, 104, -15, 101, -22, 117, 0, 0), +- CABAC_ENTRY(32, 1, 67, -4, 76, -2, 74, 0, 0), +- CABAC_ENTRY(33, -13, 78, -6, 71, -4, 85, 0, 0), +- CABAC_ENTRY(34, -11, 65, -13, 79, -24, 102, 0, 0), +- CABAC_ENTRY(35, 1, 62, 5, 52, 5, 57, 0, 0), +- CABAC_ENTRY(36, -6, 86, 6, 69, -6, 93, 0, 0), +- CABAC_ENTRY(37, -17, 95, -13, 90, -14, 88, 0, 0), +- CABAC_ENTRY(38, -6, 61, 0, 52, -6, 44, 0, 0), +- CABAC_ENTRY(39, 9, 45, 8, 43, 4, 55, 0, 0), +- +- /* Table 9-15 – Values of variables m and n for ctxIdx from 40 to 53 */ +- CABAC_ENTRY(40, -3, 69, -2, 69, -11, 89, 0, 0), +- CABAC_ENTRY(41, -6, 81, -5, 82, -15, 103, 0, 0), +- CABAC_ENTRY(42, -11, 96, -10, 96, -21, 116, 0, 0), +- CABAC_ENTRY(43, 6, 55, 2, 59, 19, 57, 0, 0), +- CABAC_ENTRY(44, 7, 67, 2, 75, 20, 58, 0, 0), +- CABAC_ENTRY(45, -5, 86, -3, 87, 4, 84, 0, 0), +- CABAC_ENTRY(46, 2, 88, -3, 100, 6, 96, 0, 0), +- CABAC_ENTRY(47, 0, 58, 1, 56, 1, 63, 0, 0), +- CABAC_ENTRY(48, -3, 76, -3, 74, -5, 85, 0, 0), +- CABAC_ENTRY(49, -10, 94, -6, 85, -13, 106, 0, 0), +- CABAC_ENTRY(50, 5, 54, 0, 59, 5, 63, 0, 0), +- CABAC_ENTRY(51, 4, 69, -3, 81, 6, 75, 0, 0), +- CABAC_ENTRY(52, -3, 81, -7, 86, -3, 90, 0, 0), +- CABAC_ENTRY(53, 0, 88, -5, 95, -1, 101, 0, 0), +- +- /* Table 9-16 – Values of variables m and n for ctxIdx from 54 to 59 */ +- CABAC_ENTRY(54, -7, 67, -1, 66, 3, 55, 0, 0), +- CABAC_ENTRY(55, -5, 74, -1, 77, -4, 79, 0, 0), +- CABAC_ENTRY(56, -4, 74, 1, 70, -2, 75, 0, 0), +- CABAC_ENTRY(57, -5, 80, -2, 86, -12, 97, 0, 0), +- CABAC_ENTRY(58, -7, 72, -5, 72, -7, 50, 0, 0), +- CABAC_ENTRY(59, 1, 58, 0, 61, 1, 60, 0, 0), +- +- /* Table 9-17 – Values of variables m and n for ctxIdx from 60 to 69 */ +- CABAC_ENTRY(60, 0, 41, 0, 41, 0, 41, 0, 41), +- CABAC_ENTRY(61, 0, 63, 0, 63, 0, 63, 0, 63), +- CABAC_ENTRY(62, 0, 63, 0, 63, 0, 63, 0, 63), +- CABAC_ENTRY(63, 0, 63, 0, 63, 0, 63, 0, 63), +- CABAC_ENTRY(64, -9, 83, -9, 83, -9, 83, -9, 83), +- CABAC_ENTRY(65, 4, 86, 4, 86, 4, 86, 4, 86), +- CABAC_ENTRY(66, 0, 97, 0, 97, 0, 97, 0, 97), +- CABAC_ENTRY(67, -7, 72, -7, 72, -7, 72, -7, 72), +- CABAC_ENTRY(68, 13, 41, 13, 41, 13, 41, 13, 41), +- CABAC_ENTRY(69, 3, 62, 3, 62, 3, 62, 3, 62), +- +- /* Table 9-18 – Values of variables m and n for ctxIdx from 70 to 104 */ +- CABAC_ENTRY(70, 0, 45, 13, 15, 7, 34, 0, 11), +- CABAC_ENTRY(71, -4, 78, 7, 51, -9, 88, 1, 55), +- CABAC_ENTRY(72, -3, 96, 2, 80, -20, 127, 0, 69), +- CABAC_ENTRY(73, -27, 126, -39, 127, -36, 127, -17, 127), +- CABAC_ENTRY(74, -28, 98, -18, 91, -17, 91, -13, 102), +- CABAC_ENTRY(75, -25, 101, -17, 96, -14, 95, 0, 82), +- CABAC_ENTRY(76, -23, 67, -26, 81, -25, 84, -7, 74), +- CABAC_ENTRY(77, -28, 82, -35, 98, -25, 86, -21, 107), +- CABAC_ENTRY(78, -20, 94, -24, 102, -12, 89, -27, 127), +- CABAC_ENTRY(79, -16, 83, -23, 97, -17, 91, -31, 127), +- CABAC_ENTRY(80, -22, 110, -27, 119, -31, 127, -24, 127), +- CABAC_ENTRY(81, -21, 91, -24, 99, -14, 76, -18, 95), +- CABAC_ENTRY(82, -18, 102, -21, 110, -18, 103, -27, 127), +- CABAC_ENTRY(83, -13, 93, -18, 102, -13, 90, -21, 114), +- CABAC_ENTRY(84, -29, 127, -36, 127, -37, 127, -30, 127), +- CABAC_ENTRY(85, -7, 92, 0, 80, 11, 80, -17, 123), +- CABAC_ENTRY(86, -5, 89, -5, 89, 5, 76, -12, 115), +- CABAC_ENTRY(87, -7, 96, -7, 94, 2, 84, -16, 122), +- CABAC_ENTRY(88, -13, 108, -4, 92, 5, 78, -11, 115), +- CABAC_ENTRY(89, -3, 46, 0, 39, -6, 55, -12, 63), +- CABAC_ENTRY(90, -1, 65, 0, 65, 4, 61, -2, 68), +- CABAC_ENTRY(91, -1, 57, -15, 84, -14, 83, -15, 84), +- CABAC_ENTRY(92, -9, 93, -35, 127, -37, 127, -13, 104), +- CABAC_ENTRY(93, -3, 74, -2, 73, -5, 79, -3, 70), +- CABAC_ENTRY(94, -9, 92, -12, 104, -11, 104, -8, 93), +- CABAC_ENTRY(95, -8, 87, -9, 91, -11, 91, -10, 90), +- CABAC_ENTRY(96, -23, 126, -31, 127, -30, 127, -30, 127), +- CABAC_ENTRY(97, 5, 54, 3, 55, 0, 65, -1, 74), +- CABAC_ENTRY(98, 6, 60, 7, 56, -2, 79, -6, 97), +- CABAC_ENTRY(99, 6, 59, 7, 55, 0, 72, -7, 91), +- CABAC_ENTRY(100, 6, 69, 8, 61, -4, 92, -20, 127), +- CABAC_ENTRY(101, -1, 48, -3, 53, -6, 56, -4, 56), +- CABAC_ENTRY(102, 0, 68, 0, 68, 3, 68, -5, 82), +- CABAC_ENTRY(103, -4, 69, -7, 74, -8, 71, -7, 76), +- CABAC_ENTRY(104, -8, 88, -9, 88, -13, 98, -22, 125), +- +- /* Table 9-19 – Values of variables m and n for ctxIdx from 105 to 165 */ +- CABAC_ENTRY(105, -2, 85, -13, 103, -4, 86, -7, 93), +- CABAC_ENTRY(106, -6, 78, -13, 91, -12, 88, -11, 87), +- CABAC_ENTRY(107, -1, 75, -9, 89, -5, 82, -3, 77), +- CABAC_ENTRY(108, -7, 77, -14, 92, -3, 72, -5, 71), +- CABAC_ENTRY(109, 2, 54, -8, 76, -4, 67, -4, 63), +- CABAC_ENTRY(110, 5, 50, -12, 87, -8, 72, -4, 68), +- CABAC_ENTRY(111, -3, 68, -23, 110, -16, 89, -12, 84), +- CABAC_ENTRY(112, 1, 50, -24, 105, -9, 69, -7, 62), +- CABAC_ENTRY(113, 6, 42, -10, 78, -1, 59, -7, 65), +- CABAC_ENTRY(114, -4, 81, -20, 112, 5, 66, 8, 61), +- CABAC_ENTRY(115, 1, 63, -17, 99, 4, 57, 5, 56), +- CABAC_ENTRY(116, -4, 70, -78, 127, -4, 71, -2, 66), +- CABAC_ENTRY(117, 0, 67, -70, 127, -2, 71, 1, 64), +- CABAC_ENTRY(118, 2, 57, -50, 127, 2, 58, 0, 61), +- CABAC_ENTRY(119, -2, 76, -46, 127, -1, 74, -2, 78), +- CABAC_ENTRY(120, 11, 35, -4, 66, -4, 44, 1, 50), +- CABAC_ENTRY(121, 4, 64, -5, 78, -1, 69, 7, 52), +- CABAC_ENTRY(122, 1, 61, -4, 71, 0, 62, 10, 35), +- CABAC_ENTRY(123, 11, 35, -8, 72, -7, 51, 0, 44), +- CABAC_ENTRY(124, 18, 25, 2, 59, -4, 47, 11, 38), +- CABAC_ENTRY(125, 12, 24, -1, 55, -6, 42, 1, 45), +- CABAC_ENTRY(126, 13, 29, -7, 70, -3, 41, 0, 46), +- CABAC_ENTRY(127, 13, 36, -6, 75, -6, 53, 5, 44), +- CABAC_ENTRY(128, -10, 93, -8, 89, 8, 76, 31, 17), +- CABAC_ENTRY(129, -7, 73, -34, 119, -9, 78, 1, 51), +- CABAC_ENTRY(130, -2, 73, -3, 75, -11, 83, 7, 50), +- CABAC_ENTRY(131, 13, 46, 32, 20, 9, 52, 28, 19), +- CABAC_ENTRY(132, 9, 49, 30, 22, 0, 67, 16, 33), +- CABAC_ENTRY(133, -7, 100, -44, 127, -5, 90, 14, 62), +- CABAC_ENTRY(134, 9, 53, 0, 54, 1, 67, -13, 108), +- CABAC_ENTRY(135, 2, 53, -5, 61, -15, 72, -15, 100), +- CABAC_ENTRY(136, 5, 53, 0, 58, -5, 75, -13, 101), +- CABAC_ENTRY(137, -2, 61, -1, 60, -8, 80, -13, 91), +- CABAC_ENTRY(138, 0, 56, -3, 61, -21, 83, -12, 94), +- CABAC_ENTRY(139, 0, 56, -8, 67, -21, 64, -10, 88), +- CABAC_ENTRY(140, -13, 63, -25, 84, -13, 31, -16, 84), +- CABAC_ENTRY(141, -5, 60, -14, 74, -25, 64, -10, 86), +- CABAC_ENTRY(142, -1, 62, -5, 65, -29, 94, -7, 83), +- CABAC_ENTRY(143, 4, 57, 5, 52, 9, 75, -13, 87), +- CABAC_ENTRY(144, -6, 69, 2, 57, 17, 63, -19, 94), +- CABAC_ENTRY(145, 4, 57, 0, 61, -8, 74, 1, 70), +- CABAC_ENTRY(146, 14, 39, -9, 69, -5, 35, 0, 72), +- CABAC_ENTRY(147, 4, 51, -11, 70, -2, 27, -5, 74), +- CABAC_ENTRY(148, 13, 68, 18, 55, 13, 91, 18, 59), +- CABAC_ENTRY(149, 3, 64, -4, 71, 3, 65, -8, 102), +- CABAC_ENTRY(150, 1, 61, 0, 58, -7, 69, -15, 100), +- CABAC_ENTRY(151, 9, 63, 7, 61, 8, 77, 0, 95), +- CABAC_ENTRY(152, 7, 50, 9, 41, -10, 66, -4, 75), +- CABAC_ENTRY(153, 16, 39, 18, 25, 3, 62, 2, 72), +- CABAC_ENTRY(154, 5, 44, 9, 32, -3, 68, -11, 75), +- CABAC_ENTRY(155, 4, 52, 5, 43, -20, 81, -3, 71), +- CABAC_ENTRY(156, 11, 48, 9, 47, 0, 30, 15, 46), +- CABAC_ENTRY(157, -5, 60, 0, 44, 1, 7, -13, 69), +- CABAC_ENTRY(158, -1, 59, 0, 51, -3, 23, 0, 62), +- CABAC_ENTRY(159, 0, 59, 2, 46, -21, 74, 0, 65), +- CABAC_ENTRY(160, 22, 33, 19, 38, 16, 66, 21, 37), +- CABAC_ENTRY(161, 5, 44, -4, 66, -23, 124, -15, 72), +- CABAC_ENTRY(162, 14, 43, 15, 38, 17, 37, 9, 57), +- CABAC_ENTRY(163, -1, 78, 12, 42, 44, -18, 16, 54), +- CABAC_ENTRY(164, 0, 60, 9, 34, 50, -34, 0, 62), +- CABAC_ENTRY(165, 9, 69, 0, 89, -22, 127, 12, 72), +- +- /* Table 9-20 – Values of variables m and n for ctxIdx from 166 to 226 */ +- CABAC_ENTRY(166, 11, 28, 4, 45, 4, 39, 24, 0), +- CABAC_ENTRY(167, 2, 40, 10, 28, 0, 42, 15, 9), +- CABAC_ENTRY(168, 3, 44, 10, 31, 7, 34, 8, 25), +- CABAC_ENTRY(169, 0, 49, 33, -11, 11, 29, 13, 18), +- CABAC_ENTRY(170, 0, 46, 52, -43, 8, 31, 15, 9), +- CABAC_ENTRY(171, 2, 44, 18, 15, 6, 37, 13, 19), +- CABAC_ENTRY(172, 2, 51, 28, 0, 7, 42, 10, 37), +- CABAC_ENTRY(173, 0, 47, 35, -22, 3, 40, 12, 18), +- CABAC_ENTRY(174, 4, 39, 38, -25, 8, 33, 6, 29), +- CABAC_ENTRY(175, 2, 62, 34, 0, 13, 43, 20, 33), +- CABAC_ENTRY(176, 6, 46, 39, -18, 13, 36, 15, 30), +- CABAC_ENTRY(177, 0, 54, 32, -12, 4, 47, 4, 45), +- CABAC_ENTRY(178, 3, 54, 102, -94, 3, 55, 1, 58), +- CABAC_ENTRY(179, 2, 58, 0, 0, 2, 58, 0, 62), +- CABAC_ENTRY(180, 4, 63, 56, -15, 6, 60, 7, 61), +- CABAC_ENTRY(181, 6, 51, 33, -4, 8, 44, 12, 38), +- CABAC_ENTRY(182, 6, 57, 29, 10, 11, 44, 11, 45), +- CABAC_ENTRY(183, 7, 53, 37, -5, 14, 42, 15, 39), +- CABAC_ENTRY(184, 6, 52, 51, -29, 7, 48, 11, 42), +- CABAC_ENTRY(185, 6, 55, 39, -9, 4, 56, 13, 44), +- CABAC_ENTRY(186, 11, 45, 52, -34, 4, 52, 16, 45), +- CABAC_ENTRY(187, 14, 36, 69, -58, 13, 37, 12, 41), +- CABAC_ENTRY(188, 8, 53, 67, -63, 9, 49, 10, 49), +- CABAC_ENTRY(189, -1, 82, 44, -5, 19, 58, 30, 34), +- CABAC_ENTRY(190, 7, 55, 32, 7, 10, 48, 18, 42), +- CABAC_ENTRY(191, -3, 78, 55, -29, 12, 45, 10, 55), +- CABAC_ENTRY(192, 15, 46, 32, 1, 0, 69, 17, 51), +- CABAC_ENTRY(193, 22, 31, 0, 0, 20, 33, 17, 46), +- CABAC_ENTRY(194, -1, 84, 27, 36, 8, 63, 0, 89), +- CABAC_ENTRY(195, 25, 7, 33, -25, 35, -18, 26, -19), +- CABAC_ENTRY(196, 30, -7, 34, -30, 33, -25, 22, -17), +- CABAC_ENTRY(197, 28, 3, 36, -28, 28, -3, 26, -17), +- CABAC_ENTRY(198, 28, 4, 38, -28, 24, 10, 30, -25), +- CABAC_ENTRY(199, 32, 0, 38, -27, 27, 0, 28, -20), +- CABAC_ENTRY(200, 34, -1, 34, -18, 34, -14, 33, -23), +- CABAC_ENTRY(201, 30, 6, 35, -16, 52, -44, 37, -27), +- CABAC_ENTRY(202, 30, 6, 34, -14, 39, -24, 33, -23), +- CABAC_ENTRY(203, 32, 9, 32, -8, 19, 17, 40, -28), +- CABAC_ENTRY(204, 31, 19, 37, -6, 31, 25, 38, -17), +- CABAC_ENTRY(205, 26, 27, 35, 0, 36, 29, 33, -11), +- CABAC_ENTRY(206, 26, 30, 30, 10, 24, 33, 40, -15), +- CABAC_ENTRY(207, 37, 20, 28, 18, 34, 15, 41, -6), +- CABAC_ENTRY(208, 28, 34, 26, 25, 30, 20, 38, 1), +- CABAC_ENTRY(209, 17, 70, 29, 41, 22, 73, 41, 17), +- CABAC_ENTRY(210, 1, 67, 0, 75, 20, 34, 30, -6), +- CABAC_ENTRY(211, 5, 59, 2, 72, 19, 31, 27, 3), +- CABAC_ENTRY(212, 9, 67, 8, 77, 27, 44, 26, 22), +- CABAC_ENTRY(213, 16, 30, 14, 35, 19, 16, 37, -16), +- CABAC_ENTRY(214, 18, 32, 18, 31, 15, 36, 35, -4), +- CABAC_ENTRY(215, 18, 35, 17, 35, 15, 36, 38, -8), +- CABAC_ENTRY(216, 22, 29, 21, 30, 21, 28, 38, -3), +- CABAC_ENTRY(217, 24, 31, 17, 45, 25, 21, 37, 3), +- CABAC_ENTRY(218, 23, 38, 20, 42, 30, 20, 38, 5), +- CABAC_ENTRY(219, 18, 43, 18, 45, 31, 12, 42, 0), +- CABAC_ENTRY(220, 20, 41, 27, 26, 27, 16, 35, 16), +- CABAC_ENTRY(221, 11, 63, 16, 54, 24, 42, 39, 22), +- CABAC_ENTRY(222, 9, 59, 7, 66, 0, 93, 14, 48), +- CABAC_ENTRY(223, 9, 64, 16, 56, 14, 56, 27, 37), +- CABAC_ENTRY(224, -1, 94, 11, 73, 15, 57, 21, 60), +- CABAC_ENTRY(225, -2, 89, 10, 67, 26, 38, 12, 68), +- CABAC_ENTRY(226, -9, 108, -10, 116, -24, 127, 2, 97), +- +- /* Table 9-21 – Values of variables m and n for ctxIdx from 227 to 275 */ +- CABAC_ENTRY(227, -6, 76, -23, 112, -24, 115, -3, 71), +- CABAC_ENTRY(228, -2, 44, -15, 71, -22, 82, -6, 42), +- CABAC_ENTRY(229, 0, 45, -7, 61, -9, 62, -5, 50), +- CABAC_ENTRY(230, 0, 52, 0, 53, 0, 53, -3, 54), +- CABAC_ENTRY(231, -3, 64, -5, 66, 0, 59, -2, 62), +- CABAC_ENTRY(232, -2, 59, -11, 77, -14, 85, 0, 58), +- CABAC_ENTRY(233, -4, 70, -9, 80, -13, 89, 1, 63), +- CABAC_ENTRY(234, -4, 75, -9, 84, -13, 94, -2, 72), +- CABAC_ENTRY(235, -8, 82, -10, 87, -11, 92, -1, 74), +- CABAC_ENTRY(236, -17, 102, -34, 127, -29, 127, -9, 91), +- CABAC_ENTRY(237, -9, 77, -21, 101, -21, 100, -5, 67), +- CABAC_ENTRY(238, 3, 24, -3, 39, -14, 57, -5, 27), +- CABAC_ENTRY(239, 0, 42, -5, 53, -12, 67, -3, 39), +- CABAC_ENTRY(240, 0, 48, -7, 61, -11, 71, -2, 44), +- CABAC_ENTRY(241, 0, 55, -11, 75, -10, 77, 0, 46), +- CABAC_ENTRY(242, -6, 59, -15, 77, -21, 85, -16, 64), +- CABAC_ENTRY(243, -7, 71, -17, 91, -16, 88, -8, 68), +- CABAC_ENTRY(244, -12, 83, -25, 107, -23, 104, -10, 78), +- CABAC_ENTRY(245, -11, 87, -25, 111, -15, 98, -6, 77), +- CABAC_ENTRY(246, -30, 119, -28, 122, -37, 127, -10, 86), +- CABAC_ENTRY(247, 1, 58, -11, 76, -10, 82, -12, 92), +- CABAC_ENTRY(248, -3, 29, -10, 44, -8, 48, -15, 55), +- CABAC_ENTRY(249, -1, 36, -10, 52, -8, 61, -10, 60), +- CABAC_ENTRY(250, 1, 38, -10, 57, -8, 66, -6, 62), +- CABAC_ENTRY(251, 2, 43, -9, 58, -7, 70, -4, 65), +- CABAC_ENTRY(252, -6, 55, -16, 72, -14, 75, -12, 73), +- CABAC_ENTRY(253, 0, 58, -7, 69, -10, 79, -8, 76), +- CABAC_ENTRY(254, 0, 64, -4, 69, -9, 83, -7, 80), +- CABAC_ENTRY(255, -3, 74, -5, 74, -12, 92, -9, 88), +- CABAC_ENTRY(256, -10, 90, -9, 86, -18, 108, -17, 110), +- CABAC_ENTRY(257, 0, 70, 2, 66, -4, 79, -11, 97), +- CABAC_ENTRY(258, -4, 29, -9, 34, -22, 69, -20, 84), +- CABAC_ENTRY(259, 5, 31, 1, 32, -16, 75, -11, 79), +- CABAC_ENTRY(260, 7, 42, 11, 31, -2, 58, -6, 73), +- CABAC_ENTRY(261, 1, 59, 5, 52, 1, 58, -4, 74), +- CABAC_ENTRY(262, -2, 58, -2, 55, -13, 78, -13, 86), +- CABAC_ENTRY(263, -3, 72, -2, 67, -9, 83, -13, 96), +- CABAC_ENTRY(264, -3, 81, 0, 73, -4, 81, -11, 97), +- CABAC_ENTRY(265, -11, 97, -8, 89, -13, 99, -19, 117), +- CABAC_ENTRY(266, 0, 58, 3, 52, -13, 81, -8, 78), +- CABAC_ENTRY(267, 8, 5, 7, 4, -6, 38, -5, 33), +- CABAC_ENTRY(268, 10, 14, 10, 8, -13, 62, -4, 48), +- CABAC_ENTRY(269, 14, 18, 17, 8, -6, 58, -2, 53), +- CABAC_ENTRY(270, 13, 27, 16, 19, -2, 59, -3, 62), +- CABAC_ENTRY(271, 2, 40, 3, 37, -16, 73, -13, 71), +- CABAC_ENTRY(272, 0, 58, -1, 61, -10, 76, -10, 79), +- CABAC_ENTRY(273, -3, 70, -5, 73, -13, 86, -12, 86), +- CABAC_ENTRY(274, -6, 79, -1, 70, -9, 83, -13, 90), +- CABAC_ENTRY(275, -8, 85, -4, 78, -10, 87, -14, 97), +- +- /* Table 9-22 – Values of variables m and n for ctxIdx from 277 to 337 */ +- CABAC_ENTRY(277, -13, 106, -21, 126, -22, 127, -6, 93), +- CABAC_ENTRY(278, -16, 106, -23, 124, -25, 127, -6, 84), +- CABAC_ENTRY(279, -10, 87, -20, 110, -25, 120, -8, 79), +- CABAC_ENTRY(280, -21, 114, -26, 126, -27, 127, 0, 66), +- CABAC_ENTRY(281, -18, 110, -25, 124, -19, 114, -1, 71), +- CABAC_ENTRY(282, -14, 98, -17, 105, -23, 117, 0, 62), +- CABAC_ENTRY(283, -22, 110, -27, 121, -25, 118, -2, 60), +- CABAC_ENTRY(284, -21, 106, -27, 117, -26, 117, -2, 59), +- CABAC_ENTRY(285, -18, 103, -17, 102, -24, 113, -5, 75), +- CABAC_ENTRY(286, -21, 107, -26, 117, -28, 118, -3, 62), +- CABAC_ENTRY(287, -23, 108, -27, 116, -31, 120, -4, 58), +- CABAC_ENTRY(288, -26, 112, -33, 122, -37, 124, -9, 66), +- CABAC_ENTRY(289, -10, 96, -10, 95, -10, 94, -1, 79), +- CABAC_ENTRY(290, -12, 95, -14, 100, -15, 102, 0, 71), +- CABAC_ENTRY(291, -5, 91, -8, 95, -10, 99, 3, 68), +- CABAC_ENTRY(292, -9, 93, -17, 111, -13, 106, 10, 44), +- CABAC_ENTRY(293, -22, 94, -28, 114, -50, 127, -7, 62), +- CABAC_ENTRY(294, -5, 86, -6, 89, -5, 92, 15, 36), +- CABAC_ENTRY(295, 9, 67, -2, 80, 17, 57, 14, 40), +- CABAC_ENTRY(296, -4, 80, -4, 82, -5, 86, 16, 27), +- CABAC_ENTRY(297, -10, 85, -9, 85, -13, 94, 12, 29), +- CABAC_ENTRY(298, -1, 70, -8, 81, -12, 91, 1, 44), +- CABAC_ENTRY(299, 7, 60, -1, 72, -2, 77, 20, 36), +- CABAC_ENTRY(300, 9, 58, 5, 64, 0, 71, 18, 32), +- CABAC_ENTRY(301, 5, 61, 1, 67, -1, 73, 5, 42), +- CABAC_ENTRY(302, 12, 50, 9, 56, 4, 64, 1, 48), +- CABAC_ENTRY(303, 15, 50, 0, 69, -7, 81, 10, 62), +- CABAC_ENTRY(304, 18, 49, 1, 69, 5, 64, 17, 46), +- CABAC_ENTRY(305, 17, 54, 7, 69, 15, 57, 9, 64), +- CABAC_ENTRY(306, 10, 41, -7, 69, 1, 67, -12, 104), +- CABAC_ENTRY(307, 7, 46, -6, 67, 0, 68, -11, 97), +- CABAC_ENTRY(308, -1, 51, -16, 77, -10, 67, -16, 96), +- CABAC_ENTRY(309, 7, 49, -2, 64, 1, 68, -7, 88), +- CABAC_ENTRY(310, 8, 52, 2, 61, 0, 77, -8, 85), +- CABAC_ENTRY(311, 9, 41, -6, 67, 2, 64, -7, 85), +- CABAC_ENTRY(312, 6, 47, -3, 64, 0, 68, -9, 85), +- CABAC_ENTRY(313, 2, 55, 2, 57, -5, 78, -13, 88), +- CABAC_ENTRY(314, 13, 41, -3, 65, 7, 55, 4, 66), +- CABAC_ENTRY(315, 10, 44, -3, 66, 5, 59, -3, 77), +- CABAC_ENTRY(316, 6, 50, 0, 62, 2, 65, -3, 76), +- CABAC_ENTRY(317, 5, 53, 9, 51, 14, 54, -6, 76), +- CABAC_ENTRY(318, 13, 49, -1, 66, 15, 44, 10, 58), +- CABAC_ENTRY(319, 4, 63, -2, 71, 5, 60, -1, 76), +- CABAC_ENTRY(320, 6, 64, -2, 75, 2, 70, -1, 83), +- CABAC_ENTRY(321, -2, 69, -1, 70, -2, 76, -7, 99), +- CABAC_ENTRY(322, -2, 59, -9, 72, -18, 86, -14, 95), +- CABAC_ENTRY(323, 6, 70, 14, 60, 12, 70, 2, 95), +- CABAC_ENTRY(324, 10, 44, 16, 37, 5, 64, 0, 76), +- CABAC_ENTRY(325, 9, 31, 0, 47, -12, 70, -5, 74), +- CABAC_ENTRY(326, 12, 43, 18, 35, 11, 55, 0, 70), +- CABAC_ENTRY(327, 3, 53, 11, 37, 5, 56, -11, 75), +- CABAC_ENTRY(328, 14, 34, 12, 41, 0, 69, 1, 68), +- CABAC_ENTRY(329, 10, 38, 10, 41, 2, 65, 0, 65), +- CABAC_ENTRY(330, -3, 52, 2, 48, -6, 74, -14, 73), +- CABAC_ENTRY(331, 13, 40, 12, 41, 5, 54, 3, 62), +- CABAC_ENTRY(332, 17, 32, 13, 41, 7, 54, 4, 62), +- CABAC_ENTRY(333, 7, 44, 0, 59, -6, 76, -1, 68), +- CABAC_ENTRY(334, 7, 38, 3, 50, -11, 82, -13, 75), +- CABAC_ENTRY(335, 13, 50, 19, 40, -2, 77, 11, 55), +- CABAC_ENTRY(336, 10, 57, 3, 66, -2, 77, 5, 64), +- CABAC_ENTRY(337, 26, 43, 18, 50, 25, 42, 12, 70), +- +- /* Table 9-23 – Values of variables m and n for ctxIdx from 338 to 398 */ +- CABAC_ENTRY(338, 14, 11, 19, -6, 17, -13, 15, 6), +- CABAC_ENTRY(339, 11, 14, 18, -6, 16, -9, 6, 19), +- CABAC_ENTRY(340, 9, 11, 14, 0, 17, -12, 7, 16), +- CABAC_ENTRY(341, 18, 11, 26, -12, 27, -21, 12, 14), +- CABAC_ENTRY(342, 21, 9, 31, -16, 37, -30, 18, 13), +- CABAC_ENTRY(343, 23, -2, 33, -25, 41, -40, 13, 11), +- CABAC_ENTRY(344, 32, -15, 33, -22, 42, -41, 13, 15), +- CABAC_ENTRY(345, 32, -15, 37, -28, 48, -47, 15, 16), +- CABAC_ENTRY(346, 34, -21, 39, -30, 39, -32, 12, 23), +- CABAC_ENTRY(347, 39, -23, 42, -30, 46, -40, 13, 23), +- CABAC_ENTRY(348, 42, -33, 47, -42, 52, -51, 15, 20), +- CABAC_ENTRY(349, 41, -31, 45, -36, 46, -41, 14, 26), +- CABAC_ENTRY(350, 46, -28, 49, -34, 52, -39, 14, 44), +- CABAC_ENTRY(351, 38, -12, 41, -17, 43, -19, 17, 40), +- CABAC_ENTRY(352, 21, 29, 32, 9, 32, 11, 17, 47), +- CABAC_ENTRY(353, 45, -24, 69, -71, 61, -55, 24, 17), +- CABAC_ENTRY(354, 53, -45, 63, -63, 56, -46, 21, 21), +- CABAC_ENTRY(355, 48, -26, 66, -64, 62, -50, 25, 22), +- CABAC_ENTRY(356, 65, -43, 77, -74, 81, -67, 31, 27), +- CABAC_ENTRY(357, 43, -19, 54, -39, 45, -20, 22, 29), +- CABAC_ENTRY(358, 39, -10, 52, -35, 35, -2, 19, 35), +- CABAC_ENTRY(359, 30, 9, 41, -10, 28, 15, 14, 50), +- CABAC_ENTRY(360, 18, 26, 36, 0, 34, 1, 10, 57), +- CABAC_ENTRY(361, 20, 27, 40, -1, 39, 1, 7, 63), +- CABAC_ENTRY(362, 0, 57, 30, 14, 30, 17, -2, 77), +- CABAC_ENTRY(363, -14, 82, 28, 26, 20, 38, -4, 82), +- CABAC_ENTRY(364, -5, 75, 23, 37, 18, 45, -3, 94), +- CABAC_ENTRY(365, -19, 97, 12, 55, 15, 54, 9, 69), +- CABAC_ENTRY(366, -35, 125, 11, 65, 0, 79, -12, 109), +- CABAC_ENTRY(367, 27, 0, 37, -33, 36, -16, 36, -35), +- CABAC_ENTRY(368, 28, 0, 39, -36, 37, -14, 36, -34), +- CABAC_ENTRY(369, 31, -4, 40, -37, 37, -17, 32, -26), +- CABAC_ENTRY(370, 27, 6, 38, -30, 32, 1, 37, -30), +- CABAC_ENTRY(371, 34, 8, 46, -33, 34, 15, 44, -32), +- CABAC_ENTRY(372, 30, 10, 42, -30, 29, 15, 34, -18), +- CABAC_ENTRY(373, 24, 22, 40, -24, 24, 25, 34, -15), +- CABAC_ENTRY(374, 33, 19, 49, -29, 34, 22, 40, -15), +- CABAC_ENTRY(375, 22, 32, 38, -12, 31, 16, 33, -7), +- CABAC_ENTRY(376, 26, 31, 40, -10, 35, 18, 35, -5), +- CABAC_ENTRY(377, 21, 41, 38, -3, 31, 28, 33, 0), +- CABAC_ENTRY(378, 26, 44, 46, -5, 33, 41, 38, 2), +- CABAC_ENTRY(379, 23, 47, 31, 20, 36, 28, 33, 13), +- CABAC_ENTRY(380, 16, 65, 29, 30, 27, 47, 23, 35), +- CABAC_ENTRY(381, 14, 71, 25, 44, 21, 62, 13, 58), +- CABAC_ENTRY(382, 8, 60, 12, 48, 18, 31, 29, -3), +- CABAC_ENTRY(383, 6, 63, 11, 49, 19, 26, 26, 0), +- CABAC_ENTRY(384, 17, 65, 26, 45, 36, 24, 22, 30), +- CABAC_ENTRY(385, 21, 24, 22, 22, 24, 23, 31, -7), +- CABAC_ENTRY(386, 23, 20, 23, 22, 27, 16, 35, -15), +- CABAC_ENTRY(387, 26, 23, 27, 21, 24, 30, 34, -3), +- CABAC_ENTRY(388, 27, 32, 33, 20, 31, 29, 34, 3), +- CABAC_ENTRY(389, 28, 23, 26, 28, 22, 41, 36, -1), +- CABAC_ENTRY(390, 28, 24, 30, 24, 22, 42, 34, 5), +- CABAC_ENTRY(391, 23, 40, 27, 34, 16, 60, 32, 11), +- CABAC_ENTRY(392, 24, 32, 18, 42, 15, 52, 35, 5), +- CABAC_ENTRY(393, 28, 29, 25, 39, 14, 60, 34, 12), +- CABAC_ENTRY(394, 23, 42, 18, 50, 3, 78, 39, 11), +- CABAC_ENTRY(395, 19, 57, 12, 70, -16, 123, 30, 29), +- CABAC_ENTRY(396, 22, 53, 21, 54, 21, 53, 34, 26), +- CABAC_ENTRY(397, 22, 61, 14, 71, 22, 56, 29, 39), +- CABAC_ENTRY(398, 11, 86, 11, 83, 25, 61, 19, 66), +- +- /* Values of variables m and n for ctxIdx from 399 to 463 (not documented) */ +- CABAC_ENTRY(399, 12, 40, 25, 32, 21, 33, 31, 21), +- CABAC_ENTRY(400, 11, 51, 21, 49, 19, 50, 31, 31), +- CABAC_ENTRY(401, 14, 59, 21, 54, 17, 61, 25, 50), +- CABAC_ENTRY(402, -4, 79, -5, 85, -3, 78, -17, 120), +- CABAC_ENTRY(403, -7, 71, -6, 81, -8, 74, -20, 112), +- CABAC_ENTRY(404, -5, 69, -10, 77, -9, 72, -18, 114), +- CABAC_ENTRY(405, -9, 70, -7, 81, -10, 72, -11, 85), +- CABAC_ENTRY(406, -8, 66, -17, 80, -18, 75, -15, 92), +- CABAC_ENTRY(407, -10, 68, -18, 73, -12, 71, -14, 89), +- CABAC_ENTRY(408, -19, 73, -4, 74, -11, 63, -26, 71), +- CABAC_ENTRY(409, -12, 69, -10, 83, -5, 70, -15, 81), +- CABAC_ENTRY(410, -16, 70, -9, 71, -17, 75, -14, 80), +- CABAC_ENTRY(411, -15, 67, -9, 67, -14, 72, 0, 68), +- CABAC_ENTRY(412, -20, 62, -1, 61, -16, 67, -14, 70), +- CABAC_ENTRY(413, -19, 70, -8, 66, -8, 53, -24, 56), +- CABAC_ENTRY(414, -16, 66, -14, 66, -14, 59, -23, 68), +- CABAC_ENTRY(415, -22, 65, 0, 59, -9, 52, -24, 50), +- CABAC_ENTRY(416, -20, 63, 2, 59, -11, 68, -11, 74), +- CABAC_ENTRY(417, 9, -2, 17, -10, 9, -2, 23, -13), +- CABAC_ENTRY(418, 26, -9, 32, -13, 30, -10, 26, -13), +- CABAC_ENTRY(419, 33, -9, 42, -9, 31, -4, 40, -15), +- CABAC_ENTRY(420, 39, -7, 49, -5, 33, -1, 49, -14), +- CABAC_ENTRY(421, 41, -2, 53, 0, 33, 7, 44, 3), +- CABAC_ENTRY(422, 45, 3, 64, 3, 31, 12, 45, 6), +- CABAC_ENTRY(423, 49, 9, 68, 10, 37, 23, 44, 34), +- CABAC_ENTRY(424, 45, 27, 66, 27, 31, 38, 33, 54), +- CABAC_ENTRY(425, 36, 59, 47, 57, 20, 64, 19, 82), +- CABAC_ENTRY(426, -6, 66, -5, 71, -9, 71, -3, 75), +- CABAC_ENTRY(427, -7, 35, 0, 24, -7, 37, -1, 23), +- CABAC_ENTRY(428, -7, 42, -1, 36, -8, 44, 1, 34), +- CABAC_ENTRY(429, -8, 45, -2, 42, -11, 49, 1, 43), +- CABAC_ENTRY(430, -5, 48, -2, 52, -10, 56, 0, 54), +- CABAC_ENTRY(431, -12, 56, -9, 57, -12, 59, -2, 55), +- CABAC_ENTRY(432, -6, 60, -6, 63, -8, 63, 0, 61), +- CABAC_ENTRY(433, -5, 62, -4, 65, -9, 67, 1, 64), +- CABAC_ENTRY(434, -8, 66, -4, 67, -6, 68, 0, 68), +- CABAC_ENTRY(435, -8, 76, -7, 82, -10, 79, -9, 92), +- CABAC_ENTRY(436, -5, 85, -3, 81, -3, 78, -14, 106), +- CABAC_ENTRY(437, -6, 81, -3, 76, -8, 74, -13, 97), +- CABAC_ENTRY(438, -10, 77, -7, 72, -9, 72, -15, 90), +- CABAC_ENTRY(439, -7, 81, -6, 78, -10, 72, -12, 90), +- CABAC_ENTRY(440, -17, 80, -12, 72, -18, 75, -18, 88), +- CABAC_ENTRY(441, -18, 73, -14, 68, -12, 71, -10, 73), +- CABAC_ENTRY(442, -4, 74, -3, 70, -11, 63, -9, 79), +- CABAC_ENTRY(443, -10, 83, -6, 76, -5, 70, -14, 86), +- CABAC_ENTRY(444, -9, 71, -5, 66, -17, 75, -10, 73), +- CABAC_ENTRY(445, -9, 67, -5, 62, -14, 72, -10, 70), +- CABAC_ENTRY(446, -1, 61, 0, 57, -16, 67, -10, 69), +- CABAC_ENTRY(447, -8, 66, -4, 61, -8, 53, -5, 66), +- CABAC_ENTRY(448, -14, 66, -9, 60, -14, 59, -9, 64), +- CABAC_ENTRY(449, 0, 59, 1, 54, -9, 52, -5, 58), +- CABAC_ENTRY(450, 2, 59, 2, 58, -11, 68, 2, 59), +- CABAC_ENTRY(451, 21, -13, 17, -10, 9, -2, 21, -10), +- CABAC_ENTRY(452, 33, -14, 32, -13, 30, -10, 24, -11), +- CABAC_ENTRY(453, 39, -7, 42, -9, 31, -4, 28, -8), +- CABAC_ENTRY(454, 46, -2, 49, -5, 33, -1, 28, -1), +- CABAC_ENTRY(455, 51, 2, 53, 0, 33, 7, 29, 3), +- CABAC_ENTRY(456, 60, 6, 64, 3, 31, 12, 29, 9), +- CABAC_ENTRY(457, 61, 17, 68, 10, 37, 23, 35, 20), +- CABAC_ENTRY(458, 55, 34, 66, 27, 31, 38, 29, 36), +- CABAC_ENTRY(459, 42, 62, 47, 57, 20, 64, 14, 67), +-}; +- + static void set_ps_field(u32 *buf, struct rkvdec_ps_field field, u32 value) + { + u8 bit = field.offset % 32, word = field.offset / 32; +diff --git a/include/media/v4l2-cabac/rkvdec-cabac.h b/include/media/v4l2-cabac/rkvdec-cabac.h new file mode 100644 -index 000000000000..111111111111 +index 000000000000..3324c4cb6130 --- /dev/null -+++ b/drivers/staging/media/rkvdec/rkvdec-h264-cabac.h ++++ b/include/media/v4l2-cabac/rkvdec-cabac.h @@ -0,0 +1,509 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + @@ -526,531 +1051,14 @@ index 000000000000..111111111111 +}; + +#endif /* RKVDEC_H264_CABAC_H_ */ -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index 111111111111..222222222222 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -14,6 +14,7 @@ - - #include "rkvdec.h" - #include "rkvdec-regs.h" -+#include "rkvdec-h264-cabac.h" - - /* Size with u32 units. */ - #define RKV_CABAC_INIT_BUFFER_SIZE (3680 + 128) -@@ -117,505 +118,6 @@ struct rkvdec_h264_ctx { - struct rkvdec_h264_reflists reflists; - }; - --#define CABAC_ENTRY(ctxidx, idc0_m, idc0_n, idc1_m, idc1_n, \ -- idc2_m, idc2_n, intra_m, intra_n) \ -- [0][(ctxidx)] = {idc0_m, idc0_n}, \ -- [1][(ctxidx)] = {idc1_m, idc1_n}, \ -- [2][(ctxidx)] = {idc2_m, idc2_n}, \ -- [3][(ctxidx)] = {intra_m, intra_n} -- --/* -- * Constant CABAC table. -- * Built from the tables described in section '9.3.1.1 Initialisation process -- * for context variables' of the H264 spec. -- */ --static const s8 rkvdec_h264_cabac_table[4][464][2] = { -- /* Table 9-12 – Values of variables m and n for ctxIdx from 0 to 10 */ -- CABAC_ENTRY(0, 20, -15, 20, -15, 20, -15, 20, -15), -- CABAC_ENTRY(1, 2, 54, 2, 54, 2, 54, 2, 54), -- CABAC_ENTRY(2, 3, 74, 3, 74, 3, 74, 3, 74), -- CABAC_ENTRY(3, 20, -15, 20, -15, 20, -15, 20, -15), -- CABAC_ENTRY(4, 2, 54, 2, 54, 2, 54, 2, 54), -- CABAC_ENTRY(5, 3, 74, 3, 74, 3, 74, 3, 74), -- CABAC_ENTRY(6, -28, 127, -28, 127, -28, 127, -28, 127), -- CABAC_ENTRY(7, -23, 104, -23, 104, -23, 104, -23, 104), -- CABAC_ENTRY(8, -6, 53, -6, 53, -6, 53, -6, 53), -- CABAC_ENTRY(9, -1, 54, -1, 54, -1, 54, -1, 54), -- CABAC_ENTRY(10, 7, 51, 7, 51, 7, 51, 7, 51), -- -- /* Table 9-13 – Values of variables m and n for ctxIdx from 11 to 23 */ -- CABAC_ENTRY(11, 23, 33, 22, 25, 29, 16, 0, 0), -- CABAC_ENTRY(12, 23, 2, 34, 0, 25, 0, 0, 0), -- CABAC_ENTRY(13, 21, 0, 16, 0, 14, 0, 0, 0), -- CABAC_ENTRY(14, 1, 9, -2, 9, -10, 51, 0, 0), -- CABAC_ENTRY(15, 0, 49, 4, 41, -3, 62, 0, 0), -- CABAC_ENTRY(16, -37, 118, -29, 118, -27, 99, 0, 0), -- CABAC_ENTRY(17, 5, 57, 2, 65, 26, 16, 0, 0), -- CABAC_ENTRY(18, -13, 78, -6, 71, -4, 85, 0, 0), -- CABAC_ENTRY(19, -11, 65, -13, 79, -24, 102, 0, 0), -- CABAC_ENTRY(20, 1, 62, 5, 52, 5, 57, 0, 0), -- CABAC_ENTRY(21, 12, 49, 9, 50, 6, 57, 0, 0), -- CABAC_ENTRY(22, -4, 73, -3, 70, -17, 73, 0, 0), -- CABAC_ENTRY(23, 17, 50, 10, 54, 14, 57, 0, 0), -- -- /* Table 9-14 – Values of variables m and n for ctxIdx from 24 to 39 */ -- CABAC_ENTRY(24, 18, 64, 26, 34, 20, 40, 0, 0), -- CABAC_ENTRY(25, 9, 43, 19, 22, 20, 10, 0, 0), -- CABAC_ENTRY(26, 29, 0, 40, 0, 29, 0, 0, 0), -- CABAC_ENTRY(27, 26, 67, 57, 2, 54, 0, 0, 0), -- CABAC_ENTRY(28, 16, 90, 41, 36, 37, 42, 0, 0), -- CABAC_ENTRY(29, 9, 104, 26, 69, 12, 97, 0, 0), -- CABAC_ENTRY(30, -46, 127, -45, 127, -32, 127, 0, 0), -- CABAC_ENTRY(31, -20, 104, -15, 101, -22, 117, 0, 0), -- CABAC_ENTRY(32, 1, 67, -4, 76, -2, 74, 0, 0), -- CABAC_ENTRY(33, -13, 78, -6, 71, -4, 85, 0, 0), -- CABAC_ENTRY(34, -11, 65, -13, 79, -24, 102, 0, 0), -- CABAC_ENTRY(35, 1, 62, 5, 52, 5, 57, 0, 0), -- CABAC_ENTRY(36, -6, 86, 6, 69, -6, 93, 0, 0), -- CABAC_ENTRY(37, -17, 95, -13, 90, -14, 88, 0, 0), -- CABAC_ENTRY(38, -6, 61, 0, 52, -6, 44, 0, 0), -- CABAC_ENTRY(39, 9, 45, 8, 43, 4, 55, 0, 0), -- -- /* Table 9-15 – Values of variables m and n for ctxIdx from 40 to 53 */ -- CABAC_ENTRY(40, -3, 69, -2, 69, -11, 89, 0, 0), -- CABAC_ENTRY(41, -6, 81, -5, 82, -15, 103, 0, 0), -- CABAC_ENTRY(42, -11, 96, -10, 96, -21, 116, 0, 0), -- CABAC_ENTRY(43, 6, 55, 2, 59, 19, 57, 0, 0), -- CABAC_ENTRY(44, 7, 67, 2, 75, 20, 58, 0, 0), -- CABAC_ENTRY(45, -5, 86, -3, 87, 4, 84, 0, 0), -- CABAC_ENTRY(46, 2, 88, -3, 100, 6, 96, 0, 0), -- CABAC_ENTRY(47, 0, 58, 1, 56, 1, 63, 0, 0), -- CABAC_ENTRY(48, -3, 76, -3, 74, -5, 85, 0, 0), -- CABAC_ENTRY(49, -10, 94, -6, 85, -13, 106, 0, 0), -- CABAC_ENTRY(50, 5, 54, 0, 59, 5, 63, 0, 0), -- CABAC_ENTRY(51, 4, 69, -3, 81, 6, 75, 0, 0), -- CABAC_ENTRY(52, -3, 81, -7, 86, -3, 90, 0, 0), -- CABAC_ENTRY(53, 0, 88, -5, 95, -1, 101, 0, 0), -- -- /* Table 9-16 – Values of variables m and n for ctxIdx from 54 to 59 */ -- CABAC_ENTRY(54, -7, 67, -1, 66, 3, 55, 0, 0), -- CABAC_ENTRY(55, -5, 74, -1, 77, -4, 79, 0, 0), -- CABAC_ENTRY(56, -4, 74, 1, 70, -2, 75, 0, 0), -- CABAC_ENTRY(57, -5, 80, -2, 86, -12, 97, 0, 0), -- CABAC_ENTRY(58, -7, 72, -5, 72, -7, 50, 0, 0), -- CABAC_ENTRY(59, 1, 58, 0, 61, 1, 60, 0, 0), -- -- /* Table 9-17 – Values of variables m and n for ctxIdx from 60 to 69 */ -- CABAC_ENTRY(60, 0, 41, 0, 41, 0, 41, 0, 41), -- CABAC_ENTRY(61, 0, 63, 0, 63, 0, 63, 0, 63), -- CABAC_ENTRY(62, 0, 63, 0, 63, 0, 63, 0, 63), -- CABAC_ENTRY(63, 0, 63, 0, 63, 0, 63, 0, 63), -- CABAC_ENTRY(64, -9, 83, -9, 83, -9, 83, -9, 83), -- CABAC_ENTRY(65, 4, 86, 4, 86, 4, 86, 4, 86), -- CABAC_ENTRY(66, 0, 97, 0, 97, 0, 97, 0, 97), -- CABAC_ENTRY(67, -7, 72, -7, 72, -7, 72, -7, 72), -- CABAC_ENTRY(68, 13, 41, 13, 41, 13, 41, 13, 41), -- CABAC_ENTRY(69, 3, 62, 3, 62, 3, 62, 3, 62), -- -- /* Table 9-18 – Values of variables m and n for ctxIdx from 70 to 104 */ -- CABAC_ENTRY(70, 0, 45, 13, 15, 7, 34, 0, 11), -- CABAC_ENTRY(71, -4, 78, 7, 51, -9, 88, 1, 55), -- CABAC_ENTRY(72, -3, 96, 2, 80, -20, 127, 0, 69), -- CABAC_ENTRY(73, -27, 126, -39, 127, -36, 127, -17, 127), -- CABAC_ENTRY(74, -28, 98, -18, 91, -17, 91, -13, 102), -- CABAC_ENTRY(75, -25, 101, -17, 96, -14, 95, 0, 82), -- CABAC_ENTRY(76, -23, 67, -26, 81, -25, 84, -7, 74), -- CABAC_ENTRY(77, -28, 82, -35, 98, -25, 86, -21, 107), -- CABAC_ENTRY(78, -20, 94, -24, 102, -12, 89, -27, 127), -- CABAC_ENTRY(79, -16, 83, -23, 97, -17, 91, -31, 127), -- CABAC_ENTRY(80, -22, 110, -27, 119, -31, 127, -24, 127), -- CABAC_ENTRY(81, -21, 91, -24, 99, -14, 76, -18, 95), -- CABAC_ENTRY(82, -18, 102, -21, 110, -18, 103, -27, 127), -- CABAC_ENTRY(83, -13, 93, -18, 102, -13, 90, -21, 114), -- CABAC_ENTRY(84, -29, 127, -36, 127, -37, 127, -30, 127), -- CABAC_ENTRY(85, -7, 92, 0, 80, 11, 80, -17, 123), -- CABAC_ENTRY(86, -5, 89, -5, 89, 5, 76, -12, 115), -- CABAC_ENTRY(87, -7, 96, -7, 94, 2, 84, -16, 122), -- CABAC_ENTRY(88, -13, 108, -4, 92, 5, 78, -11, 115), -- CABAC_ENTRY(89, -3, 46, 0, 39, -6, 55, -12, 63), -- CABAC_ENTRY(90, -1, 65, 0, 65, 4, 61, -2, 68), -- CABAC_ENTRY(91, -1, 57, -15, 84, -14, 83, -15, 84), -- CABAC_ENTRY(92, -9, 93, -35, 127, -37, 127, -13, 104), -- CABAC_ENTRY(93, -3, 74, -2, 73, -5, 79, -3, 70), -- CABAC_ENTRY(94, -9, 92, -12, 104, -11, 104, -8, 93), -- CABAC_ENTRY(95, -8, 87, -9, 91, -11, 91, -10, 90), -- CABAC_ENTRY(96, -23, 126, -31, 127, -30, 127, -30, 127), -- CABAC_ENTRY(97, 5, 54, 3, 55, 0, 65, -1, 74), -- CABAC_ENTRY(98, 6, 60, 7, 56, -2, 79, -6, 97), -- CABAC_ENTRY(99, 6, 59, 7, 55, 0, 72, -7, 91), -- CABAC_ENTRY(100, 6, 69, 8, 61, -4, 92, -20, 127), -- CABAC_ENTRY(101, -1, 48, -3, 53, -6, 56, -4, 56), -- CABAC_ENTRY(102, 0, 68, 0, 68, 3, 68, -5, 82), -- CABAC_ENTRY(103, -4, 69, -7, 74, -8, 71, -7, 76), -- CABAC_ENTRY(104, -8, 88, -9, 88, -13, 98, -22, 125), -- -- /* Table 9-19 – Values of variables m and n for ctxIdx from 105 to 165 */ -- CABAC_ENTRY(105, -2, 85, -13, 103, -4, 86, -7, 93), -- CABAC_ENTRY(106, -6, 78, -13, 91, -12, 88, -11, 87), -- CABAC_ENTRY(107, -1, 75, -9, 89, -5, 82, -3, 77), -- CABAC_ENTRY(108, -7, 77, -14, 92, -3, 72, -5, 71), -- CABAC_ENTRY(109, 2, 54, -8, 76, -4, 67, -4, 63), -- CABAC_ENTRY(110, 5, 50, -12, 87, -8, 72, -4, 68), -- CABAC_ENTRY(111, -3, 68, -23, 110, -16, 89, -12, 84), -- CABAC_ENTRY(112, 1, 50, -24, 105, -9, 69, -7, 62), -- CABAC_ENTRY(113, 6, 42, -10, 78, -1, 59, -7, 65), -- CABAC_ENTRY(114, -4, 81, -20, 112, 5, 66, 8, 61), -- CABAC_ENTRY(115, 1, 63, -17, 99, 4, 57, 5, 56), -- CABAC_ENTRY(116, -4, 70, -78, 127, -4, 71, -2, 66), -- CABAC_ENTRY(117, 0, 67, -70, 127, -2, 71, 1, 64), -- CABAC_ENTRY(118, 2, 57, -50, 127, 2, 58, 0, 61), -- CABAC_ENTRY(119, -2, 76, -46, 127, -1, 74, -2, 78), -- CABAC_ENTRY(120, 11, 35, -4, 66, -4, 44, 1, 50), -- CABAC_ENTRY(121, 4, 64, -5, 78, -1, 69, 7, 52), -- CABAC_ENTRY(122, 1, 61, -4, 71, 0, 62, 10, 35), -- CABAC_ENTRY(123, 11, 35, -8, 72, -7, 51, 0, 44), -- CABAC_ENTRY(124, 18, 25, 2, 59, -4, 47, 11, 38), -- CABAC_ENTRY(125, 12, 24, -1, 55, -6, 42, 1, 45), -- CABAC_ENTRY(126, 13, 29, -7, 70, -3, 41, 0, 46), -- CABAC_ENTRY(127, 13, 36, -6, 75, -6, 53, 5, 44), -- CABAC_ENTRY(128, -10, 93, -8, 89, 8, 76, 31, 17), -- CABAC_ENTRY(129, -7, 73, -34, 119, -9, 78, 1, 51), -- CABAC_ENTRY(130, -2, 73, -3, 75, -11, 83, 7, 50), -- CABAC_ENTRY(131, 13, 46, 32, 20, 9, 52, 28, 19), -- CABAC_ENTRY(132, 9, 49, 30, 22, 0, 67, 16, 33), -- CABAC_ENTRY(133, -7, 100, -44, 127, -5, 90, 14, 62), -- CABAC_ENTRY(134, 9, 53, 0, 54, 1, 67, -13, 108), -- CABAC_ENTRY(135, 2, 53, -5, 61, -15, 72, -15, 100), -- CABAC_ENTRY(136, 5, 53, 0, 58, -5, 75, -13, 101), -- CABAC_ENTRY(137, -2, 61, -1, 60, -8, 80, -13, 91), -- CABAC_ENTRY(138, 0, 56, -3, 61, -21, 83, -12, 94), -- CABAC_ENTRY(139, 0, 56, -8, 67, -21, 64, -10, 88), -- CABAC_ENTRY(140, -13, 63, -25, 84, -13, 31, -16, 84), -- CABAC_ENTRY(141, -5, 60, -14, 74, -25, 64, -10, 86), -- CABAC_ENTRY(142, -1, 62, -5, 65, -29, 94, -7, 83), -- CABAC_ENTRY(143, 4, 57, 5, 52, 9, 75, -13, 87), -- CABAC_ENTRY(144, -6, 69, 2, 57, 17, 63, -19, 94), -- CABAC_ENTRY(145, 4, 57, 0, 61, -8, 74, 1, 70), -- CABAC_ENTRY(146, 14, 39, -9, 69, -5, 35, 0, 72), -- CABAC_ENTRY(147, 4, 51, -11, 70, -2, 27, -5, 74), -- CABAC_ENTRY(148, 13, 68, 18, 55, 13, 91, 18, 59), -- CABAC_ENTRY(149, 3, 64, -4, 71, 3, 65, -8, 102), -- CABAC_ENTRY(150, 1, 61, 0, 58, -7, 69, -15, 100), -- CABAC_ENTRY(151, 9, 63, 7, 61, 8, 77, 0, 95), -- CABAC_ENTRY(152, 7, 50, 9, 41, -10, 66, -4, 75), -- CABAC_ENTRY(153, 16, 39, 18, 25, 3, 62, 2, 72), -- CABAC_ENTRY(154, 5, 44, 9, 32, -3, 68, -11, 75), -- CABAC_ENTRY(155, 4, 52, 5, 43, -20, 81, -3, 71), -- CABAC_ENTRY(156, 11, 48, 9, 47, 0, 30, 15, 46), -- CABAC_ENTRY(157, -5, 60, 0, 44, 1, 7, -13, 69), -- CABAC_ENTRY(158, -1, 59, 0, 51, -3, 23, 0, 62), -- CABAC_ENTRY(159, 0, 59, 2, 46, -21, 74, 0, 65), -- CABAC_ENTRY(160, 22, 33, 19, 38, 16, 66, 21, 37), -- CABAC_ENTRY(161, 5, 44, -4, 66, -23, 124, -15, 72), -- CABAC_ENTRY(162, 14, 43, 15, 38, 17, 37, 9, 57), -- CABAC_ENTRY(163, -1, 78, 12, 42, 44, -18, 16, 54), -- CABAC_ENTRY(164, 0, 60, 9, 34, 50, -34, 0, 62), -- CABAC_ENTRY(165, 9, 69, 0, 89, -22, 127, 12, 72), -- -- /* Table 9-20 – Values of variables m and n for ctxIdx from 166 to 226 */ -- CABAC_ENTRY(166, 11, 28, 4, 45, 4, 39, 24, 0), -- CABAC_ENTRY(167, 2, 40, 10, 28, 0, 42, 15, 9), -- CABAC_ENTRY(168, 3, 44, 10, 31, 7, 34, 8, 25), -- CABAC_ENTRY(169, 0, 49, 33, -11, 11, 29, 13, 18), -- CABAC_ENTRY(170, 0, 46, 52, -43, 8, 31, 15, 9), -- CABAC_ENTRY(171, 2, 44, 18, 15, 6, 37, 13, 19), -- CABAC_ENTRY(172, 2, 51, 28, 0, 7, 42, 10, 37), -- CABAC_ENTRY(173, 0, 47, 35, -22, 3, 40, 12, 18), -- CABAC_ENTRY(174, 4, 39, 38, -25, 8, 33, 6, 29), -- CABAC_ENTRY(175, 2, 62, 34, 0, 13, 43, 20, 33), -- CABAC_ENTRY(176, 6, 46, 39, -18, 13, 36, 15, 30), -- CABAC_ENTRY(177, 0, 54, 32, -12, 4, 47, 4, 45), -- CABAC_ENTRY(178, 3, 54, 102, -94, 3, 55, 1, 58), -- CABAC_ENTRY(179, 2, 58, 0, 0, 2, 58, 0, 62), -- CABAC_ENTRY(180, 4, 63, 56, -15, 6, 60, 7, 61), -- CABAC_ENTRY(181, 6, 51, 33, -4, 8, 44, 12, 38), -- CABAC_ENTRY(182, 6, 57, 29, 10, 11, 44, 11, 45), -- CABAC_ENTRY(183, 7, 53, 37, -5, 14, 42, 15, 39), -- CABAC_ENTRY(184, 6, 52, 51, -29, 7, 48, 11, 42), -- CABAC_ENTRY(185, 6, 55, 39, -9, 4, 56, 13, 44), -- CABAC_ENTRY(186, 11, 45, 52, -34, 4, 52, 16, 45), -- CABAC_ENTRY(187, 14, 36, 69, -58, 13, 37, 12, 41), -- CABAC_ENTRY(188, 8, 53, 67, -63, 9, 49, 10, 49), -- CABAC_ENTRY(189, -1, 82, 44, -5, 19, 58, 30, 34), -- CABAC_ENTRY(190, 7, 55, 32, 7, 10, 48, 18, 42), -- CABAC_ENTRY(191, -3, 78, 55, -29, 12, 45, 10, 55), -- CABAC_ENTRY(192, 15, 46, 32, 1, 0, 69, 17, 51), -- CABAC_ENTRY(193, 22, 31, 0, 0, 20, 33, 17, 46), -- CABAC_ENTRY(194, -1, 84, 27, 36, 8, 63, 0, 89), -- CABAC_ENTRY(195, 25, 7, 33, -25, 35, -18, 26, -19), -- CABAC_ENTRY(196, 30, -7, 34, -30, 33, -25, 22, -17), -- CABAC_ENTRY(197, 28, 3, 36, -28, 28, -3, 26, -17), -- CABAC_ENTRY(198, 28, 4, 38, -28, 24, 10, 30, -25), -- CABAC_ENTRY(199, 32, 0, 38, -27, 27, 0, 28, -20), -- CABAC_ENTRY(200, 34, -1, 34, -18, 34, -14, 33, -23), -- CABAC_ENTRY(201, 30, 6, 35, -16, 52, -44, 37, -27), -- CABAC_ENTRY(202, 30, 6, 34, -14, 39, -24, 33, -23), -- CABAC_ENTRY(203, 32, 9, 32, -8, 19, 17, 40, -28), -- CABAC_ENTRY(204, 31, 19, 37, -6, 31, 25, 38, -17), -- CABAC_ENTRY(205, 26, 27, 35, 0, 36, 29, 33, -11), -- CABAC_ENTRY(206, 26, 30, 30, 10, 24, 33, 40, -15), -- CABAC_ENTRY(207, 37, 20, 28, 18, 34, 15, 41, -6), -- CABAC_ENTRY(208, 28, 34, 26, 25, 30, 20, 38, 1), -- CABAC_ENTRY(209, 17, 70, 29, 41, 22, 73, 41, 17), -- CABAC_ENTRY(210, 1, 67, 0, 75, 20, 34, 30, -6), -- CABAC_ENTRY(211, 5, 59, 2, 72, 19, 31, 27, 3), -- CABAC_ENTRY(212, 9, 67, 8, 77, 27, 44, 26, 22), -- CABAC_ENTRY(213, 16, 30, 14, 35, 19, 16, 37, -16), -- CABAC_ENTRY(214, 18, 32, 18, 31, 15, 36, 35, -4), -- CABAC_ENTRY(215, 18, 35, 17, 35, 15, 36, 38, -8), -- CABAC_ENTRY(216, 22, 29, 21, 30, 21, 28, 38, -3), -- CABAC_ENTRY(217, 24, 31, 17, 45, 25, 21, 37, 3), -- CABAC_ENTRY(218, 23, 38, 20, 42, 30, 20, 38, 5), -- CABAC_ENTRY(219, 18, 43, 18, 45, 31, 12, 42, 0), -- CABAC_ENTRY(220, 20, 41, 27, 26, 27, 16, 35, 16), -- CABAC_ENTRY(221, 11, 63, 16, 54, 24, 42, 39, 22), -- CABAC_ENTRY(222, 9, 59, 7, 66, 0, 93, 14, 48), -- CABAC_ENTRY(223, 9, 64, 16, 56, 14, 56, 27, 37), -- CABAC_ENTRY(224, -1, 94, 11, 73, 15, 57, 21, 60), -- CABAC_ENTRY(225, -2, 89, 10, 67, 26, 38, 12, 68), -- CABAC_ENTRY(226, -9, 108, -10, 116, -24, 127, 2, 97), -- -- /* Table 9-21 – Values of variables m and n for ctxIdx from 227 to 275 */ -- CABAC_ENTRY(227, -6, 76, -23, 112, -24, 115, -3, 71), -- CABAC_ENTRY(228, -2, 44, -15, 71, -22, 82, -6, 42), -- CABAC_ENTRY(229, 0, 45, -7, 61, -9, 62, -5, 50), -- CABAC_ENTRY(230, 0, 52, 0, 53, 0, 53, -3, 54), -- CABAC_ENTRY(231, -3, 64, -5, 66, 0, 59, -2, 62), -- CABAC_ENTRY(232, -2, 59, -11, 77, -14, 85, 0, 58), -- CABAC_ENTRY(233, -4, 70, -9, 80, -13, 89, 1, 63), -- CABAC_ENTRY(234, -4, 75, -9, 84, -13, 94, -2, 72), -- CABAC_ENTRY(235, -8, 82, -10, 87, -11, 92, -1, 74), -- CABAC_ENTRY(236, -17, 102, -34, 127, -29, 127, -9, 91), -- CABAC_ENTRY(237, -9, 77, -21, 101, -21, 100, -5, 67), -- CABAC_ENTRY(238, 3, 24, -3, 39, -14, 57, -5, 27), -- CABAC_ENTRY(239, 0, 42, -5, 53, -12, 67, -3, 39), -- CABAC_ENTRY(240, 0, 48, -7, 61, -11, 71, -2, 44), -- CABAC_ENTRY(241, 0, 55, -11, 75, -10, 77, 0, 46), -- CABAC_ENTRY(242, -6, 59, -15, 77, -21, 85, -16, 64), -- CABAC_ENTRY(243, -7, 71, -17, 91, -16, 88, -8, 68), -- CABAC_ENTRY(244, -12, 83, -25, 107, -23, 104, -10, 78), -- CABAC_ENTRY(245, -11, 87, -25, 111, -15, 98, -6, 77), -- CABAC_ENTRY(246, -30, 119, -28, 122, -37, 127, -10, 86), -- CABAC_ENTRY(247, 1, 58, -11, 76, -10, 82, -12, 92), -- CABAC_ENTRY(248, -3, 29, -10, 44, -8, 48, -15, 55), -- CABAC_ENTRY(249, -1, 36, -10, 52, -8, 61, -10, 60), -- CABAC_ENTRY(250, 1, 38, -10, 57, -8, 66, -6, 62), -- CABAC_ENTRY(251, 2, 43, -9, 58, -7, 70, -4, 65), -- CABAC_ENTRY(252, -6, 55, -16, 72, -14, 75, -12, 73), -- CABAC_ENTRY(253, 0, 58, -7, 69, -10, 79, -8, 76), -- CABAC_ENTRY(254, 0, 64, -4, 69, -9, 83, -7, 80), -- CABAC_ENTRY(255, -3, 74, -5, 74, -12, 92, -9, 88), -- CABAC_ENTRY(256, -10, 90, -9, 86, -18, 108, -17, 110), -- CABAC_ENTRY(257, 0, 70, 2, 66, -4, 79, -11, 97), -- CABAC_ENTRY(258, -4, 29, -9, 34, -22, 69, -20, 84), -- CABAC_ENTRY(259, 5, 31, 1, 32, -16, 75, -11, 79), -- CABAC_ENTRY(260, 7, 42, 11, 31, -2, 58, -6, 73), -- CABAC_ENTRY(261, 1, 59, 5, 52, 1, 58, -4, 74), -- CABAC_ENTRY(262, -2, 58, -2, 55, -13, 78, -13, 86), -- CABAC_ENTRY(263, -3, 72, -2, 67, -9, 83, -13, 96), -- CABAC_ENTRY(264, -3, 81, 0, 73, -4, 81, -11, 97), -- CABAC_ENTRY(265, -11, 97, -8, 89, -13, 99, -19, 117), -- CABAC_ENTRY(266, 0, 58, 3, 52, -13, 81, -8, 78), -- CABAC_ENTRY(267, 8, 5, 7, 4, -6, 38, -5, 33), -- CABAC_ENTRY(268, 10, 14, 10, 8, -13, 62, -4, 48), -- CABAC_ENTRY(269, 14, 18, 17, 8, -6, 58, -2, 53), -- CABAC_ENTRY(270, 13, 27, 16, 19, -2, 59, -3, 62), -- CABAC_ENTRY(271, 2, 40, 3, 37, -16, 73, -13, 71), -- CABAC_ENTRY(272, 0, 58, -1, 61, -10, 76, -10, 79), -- CABAC_ENTRY(273, -3, 70, -5, 73, -13, 86, -12, 86), -- CABAC_ENTRY(274, -6, 79, -1, 70, -9, 83, -13, 90), -- CABAC_ENTRY(275, -8, 85, -4, 78, -10, 87, -14, 97), -- -- /* Table 9-22 – Values of variables m and n for ctxIdx from 277 to 337 */ -- CABAC_ENTRY(277, -13, 106, -21, 126, -22, 127, -6, 93), -- CABAC_ENTRY(278, -16, 106, -23, 124, -25, 127, -6, 84), -- CABAC_ENTRY(279, -10, 87, -20, 110, -25, 120, -8, 79), -- CABAC_ENTRY(280, -21, 114, -26, 126, -27, 127, 0, 66), -- CABAC_ENTRY(281, -18, 110, -25, 124, -19, 114, -1, 71), -- CABAC_ENTRY(282, -14, 98, -17, 105, -23, 117, 0, 62), -- CABAC_ENTRY(283, -22, 110, -27, 121, -25, 118, -2, 60), -- CABAC_ENTRY(284, -21, 106, -27, 117, -26, 117, -2, 59), -- CABAC_ENTRY(285, -18, 103, -17, 102, -24, 113, -5, 75), -- CABAC_ENTRY(286, -21, 107, -26, 117, -28, 118, -3, 62), -- CABAC_ENTRY(287, -23, 108, -27, 116, -31, 120, -4, 58), -- CABAC_ENTRY(288, -26, 112, -33, 122, -37, 124, -9, 66), -- CABAC_ENTRY(289, -10, 96, -10, 95, -10, 94, -1, 79), -- CABAC_ENTRY(290, -12, 95, -14, 100, -15, 102, 0, 71), -- CABAC_ENTRY(291, -5, 91, -8, 95, -10, 99, 3, 68), -- CABAC_ENTRY(292, -9, 93, -17, 111, -13, 106, 10, 44), -- CABAC_ENTRY(293, -22, 94, -28, 114, -50, 127, -7, 62), -- CABAC_ENTRY(294, -5, 86, -6, 89, -5, 92, 15, 36), -- CABAC_ENTRY(295, 9, 67, -2, 80, 17, 57, 14, 40), -- CABAC_ENTRY(296, -4, 80, -4, 82, -5, 86, 16, 27), -- CABAC_ENTRY(297, -10, 85, -9, 85, -13, 94, 12, 29), -- CABAC_ENTRY(298, -1, 70, -8, 81, -12, 91, 1, 44), -- CABAC_ENTRY(299, 7, 60, -1, 72, -2, 77, 20, 36), -- CABAC_ENTRY(300, 9, 58, 5, 64, 0, 71, 18, 32), -- CABAC_ENTRY(301, 5, 61, 1, 67, -1, 73, 5, 42), -- CABAC_ENTRY(302, 12, 50, 9, 56, 4, 64, 1, 48), -- CABAC_ENTRY(303, 15, 50, 0, 69, -7, 81, 10, 62), -- CABAC_ENTRY(304, 18, 49, 1, 69, 5, 64, 17, 46), -- CABAC_ENTRY(305, 17, 54, 7, 69, 15, 57, 9, 64), -- CABAC_ENTRY(306, 10, 41, -7, 69, 1, 67, -12, 104), -- CABAC_ENTRY(307, 7, 46, -6, 67, 0, 68, -11, 97), -- CABAC_ENTRY(308, -1, 51, -16, 77, -10, 67, -16, 96), -- CABAC_ENTRY(309, 7, 49, -2, 64, 1, 68, -7, 88), -- CABAC_ENTRY(310, 8, 52, 2, 61, 0, 77, -8, 85), -- CABAC_ENTRY(311, 9, 41, -6, 67, 2, 64, -7, 85), -- CABAC_ENTRY(312, 6, 47, -3, 64, 0, 68, -9, 85), -- CABAC_ENTRY(313, 2, 55, 2, 57, -5, 78, -13, 88), -- CABAC_ENTRY(314, 13, 41, -3, 65, 7, 55, 4, 66), -- CABAC_ENTRY(315, 10, 44, -3, 66, 5, 59, -3, 77), -- CABAC_ENTRY(316, 6, 50, 0, 62, 2, 65, -3, 76), -- CABAC_ENTRY(317, 5, 53, 9, 51, 14, 54, -6, 76), -- CABAC_ENTRY(318, 13, 49, -1, 66, 15, 44, 10, 58), -- CABAC_ENTRY(319, 4, 63, -2, 71, 5, 60, -1, 76), -- CABAC_ENTRY(320, 6, 64, -2, 75, 2, 70, -1, 83), -- CABAC_ENTRY(321, -2, 69, -1, 70, -2, 76, -7, 99), -- CABAC_ENTRY(322, -2, 59, -9, 72, -18, 86, -14, 95), -- CABAC_ENTRY(323, 6, 70, 14, 60, 12, 70, 2, 95), -- CABAC_ENTRY(324, 10, 44, 16, 37, 5, 64, 0, 76), -- CABAC_ENTRY(325, 9, 31, 0, 47, -12, 70, -5, 74), -- CABAC_ENTRY(326, 12, 43, 18, 35, 11, 55, 0, 70), -- CABAC_ENTRY(327, 3, 53, 11, 37, 5, 56, -11, 75), -- CABAC_ENTRY(328, 14, 34, 12, 41, 0, 69, 1, 68), -- CABAC_ENTRY(329, 10, 38, 10, 41, 2, 65, 0, 65), -- CABAC_ENTRY(330, -3, 52, 2, 48, -6, 74, -14, 73), -- CABAC_ENTRY(331, 13, 40, 12, 41, 5, 54, 3, 62), -- CABAC_ENTRY(332, 17, 32, 13, 41, 7, 54, 4, 62), -- CABAC_ENTRY(333, 7, 44, 0, 59, -6, 76, -1, 68), -- CABAC_ENTRY(334, 7, 38, 3, 50, -11, 82, -13, 75), -- CABAC_ENTRY(335, 13, 50, 19, 40, -2, 77, 11, 55), -- CABAC_ENTRY(336, 10, 57, 3, 66, -2, 77, 5, 64), -- CABAC_ENTRY(337, 26, 43, 18, 50, 25, 42, 12, 70), -- -- /* Table 9-23 – Values of variables m and n for ctxIdx from 338 to 398 */ -- CABAC_ENTRY(338, 14, 11, 19, -6, 17, -13, 15, 6), -- CABAC_ENTRY(339, 11, 14, 18, -6, 16, -9, 6, 19), -- CABAC_ENTRY(340, 9, 11, 14, 0, 17, -12, 7, 16), -- CABAC_ENTRY(341, 18, 11, 26, -12, 27, -21, 12, 14), -- CABAC_ENTRY(342, 21, 9, 31, -16, 37, -30, 18, 13), -- CABAC_ENTRY(343, 23, -2, 33, -25, 41, -40, 13, 11), -- CABAC_ENTRY(344, 32, -15, 33, -22, 42, -41, 13, 15), -- CABAC_ENTRY(345, 32, -15, 37, -28, 48, -47, 15, 16), -- CABAC_ENTRY(346, 34, -21, 39, -30, 39, -32, 12, 23), -- CABAC_ENTRY(347, 39, -23, 42, -30, 46, -40, 13, 23), -- CABAC_ENTRY(348, 42, -33, 47, -42, 52, -51, 15, 20), -- CABAC_ENTRY(349, 41, -31, 45, -36, 46, -41, 14, 26), -- CABAC_ENTRY(350, 46, -28, 49, -34, 52, -39, 14, 44), -- CABAC_ENTRY(351, 38, -12, 41, -17, 43, -19, 17, 40), -- CABAC_ENTRY(352, 21, 29, 32, 9, 32, 11, 17, 47), -- CABAC_ENTRY(353, 45, -24, 69, -71, 61, -55, 24, 17), -- CABAC_ENTRY(354, 53, -45, 63, -63, 56, -46, 21, 21), -- CABAC_ENTRY(355, 48, -26, 66, -64, 62, -50, 25, 22), -- CABAC_ENTRY(356, 65, -43, 77, -74, 81, -67, 31, 27), -- CABAC_ENTRY(357, 43, -19, 54, -39, 45, -20, 22, 29), -- CABAC_ENTRY(358, 39, -10, 52, -35, 35, -2, 19, 35), -- CABAC_ENTRY(359, 30, 9, 41, -10, 28, 15, 14, 50), -- CABAC_ENTRY(360, 18, 26, 36, 0, 34, 1, 10, 57), -- CABAC_ENTRY(361, 20, 27, 40, -1, 39, 1, 7, 63), -- CABAC_ENTRY(362, 0, 57, 30, 14, 30, 17, -2, 77), -- CABAC_ENTRY(363, -14, 82, 28, 26, 20, 38, -4, 82), -- CABAC_ENTRY(364, -5, 75, 23, 37, 18, 45, -3, 94), -- CABAC_ENTRY(365, -19, 97, 12, 55, 15, 54, 9, 69), -- CABAC_ENTRY(366, -35, 125, 11, 65, 0, 79, -12, 109), -- CABAC_ENTRY(367, 27, 0, 37, -33, 36, -16, 36, -35), -- CABAC_ENTRY(368, 28, 0, 39, -36, 37, -14, 36, -34), -- CABAC_ENTRY(369, 31, -4, 40, -37, 37, -17, 32, -26), -- CABAC_ENTRY(370, 27, 6, 38, -30, 32, 1, 37, -30), -- CABAC_ENTRY(371, 34, 8, 46, -33, 34, 15, 44, -32), -- CABAC_ENTRY(372, 30, 10, 42, -30, 29, 15, 34, -18), -- CABAC_ENTRY(373, 24, 22, 40, -24, 24, 25, 34, -15), -- CABAC_ENTRY(374, 33, 19, 49, -29, 34, 22, 40, -15), -- CABAC_ENTRY(375, 22, 32, 38, -12, 31, 16, 33, -7), -- CABAC_ENTRY(376, 26, 31, 40, -10, 35, 18, 35, -5), -- CABAC_ENTRY(377, 21, 41, 38, -3, 31, 28, 33, 0), -- CABAC_ENTRY(378, 26, 44, 46, -5, 33, 41, 38, 2), -- CABAC_ENTRY(379, 23, 47, 31, 20, 36, 28, 33, 13), -- CABAC_ENTRY(380, 16, 65, 29, 30, 27, 47, 23, 35), -- CABAC_ENTRY(381, 14, 71, 25, 44, 21, 62, 13, 58), -- CABAC_ENTRY(382, 8, 60, 12, 48, 18, 31, 29, -3), -- CABAC_ENTRY(383, 6, 63, 11, 49, 19, 26, 26, 0), -- CABAC_ENTRY(384, 17, 65, 26, 45, 36, 24, 22, 30), -- CABAC_ENTRY(385, 21, 24, 22, 22, 24, 23, 31, -7), -- CABAC_ENTRY(386, 23, 20, 23, 22, 27, 16, 35, -15), -- CABAC_ENTRY(387, 26, 23, 27, 21, 24, 30, 34, -3), -- CABAC_ENTRY(388, 27, 32, 33, 20, 31, 29, 34, 3), -- CABAC_ENTRY(389, 28, 23, 26, 28, 22, 41, 36, -1), -- CABAC_ENTRY(390, 28, 24, 30, 24, 22, 42, 34, 5), -- CABAC_ENTRY(391, 23, 40, 27, 34, 16, 60, 32, 11), -- CABAC_ENTRY(392, 24, 32, 18, 42, 15, 52, 35, 5), -- CABAC_ENTRY(393, 28, 29, 25, 39, 14, 60, 34, 12), -- CABAC_ENTRY(394, 23, 42, 18, 50, 3, 78, 39, 11), -- CABAC_ENTRY(395, 19, 57, 12, 70, -16, 123, 30, 29), -- CABAC_ENTRY(396, 22, 53, 21, 54, 21, 53, 34, 26), -- CABAC_ENTRY(397, 22, 61, 14, 71, 22, 56, 29, 39), -- CABAC_ENTRY(398, 11, 86, 11, 83, 25, 61, 19, 66), -- -- /* Values of variables m and n for ctxIdx from 399 to 463 (not documented) */ -- CABAC_ENTRY(399, 12, 40, 25, 32, 21, 33, 31, 21), -- CABAC_ENTRY(400, 11, 51, 21, 49, 19, 50, 31, 31), -- CABAC_ENTRY(401, 14, 59, 21, 54, 17, 61, 25, 50), -- CABAC_ENTRY(402, -4, 79, -5, 85, -3, 78, -17, 120), -- CABAC_ENTRY(403, -7, 71, -6, 81, -8, 74, -20, 112), -- CABAC_ENTRY(404, -5, 69, -10, 77, -9, 72, -18, 114), -- CABAC_ENTRY(405, -9, 70, -7, 81, -10, 72, -11, 85), -- CABAC_ENTRY(406, -8, 66, -17, 80, -18, 75, -15, 92), -- CABAC_ENTRY(407, -10, 68, -18, 73, -12, 71, -14, 89), -- CABAC_ENTRY(408, -19, 73, -4, 74, -11, 63, -26, 71), -- CABAC_ENTRY(409, -12, 69, -10, 83, -5, 70, -15, 81), -- CABAC_ENTRY(410, -16, 70, -9, 71, -17, 75, -14, 80), -- CABAC_ENTRY(411, -15, 67, -9, 67, -14, 72, 0, 68), -- CABAC_ENTRY(412, -20, 62, -1, 61, -16, 67, -14, 70), -- CABAC_ENTRY(413, -19, 70, -8, 66, -8, 53, -24, 56), -- CABAC_ENTRY(414, -16, 66, -14, 66, -14, 59, -23, 68), -- CABAC_ENTRY(415, -22, 65, 0, 59, -9, 52, -24, 50), -- CABAC_ENTRY(416, -20, 63, 2, 59, -11, 68, -11, 74), -- CABAC_ENTRY(417, 9, -2, 17, -10, 9, -2, 23, -13), -- CABAC_ENTRY(418, 26, -9, 32, -13, 30, -10, 26, -13), -- CABAC_ENTRY(419, 33, -9, 42, -9, 31, -4, 40, -15), -- CABAC_ENTRY(420, 39, -7, 49, -5, 33, -1, 49, -14), -- CABAC_ENTRY(421, 41, -2, 53, 0, 33, 7, 44, 3), -- CABAC_ENTRY(422, 45, 3, 64, 3, 31, 12, 45, 6), -- CABAC_ENTRY(423, 49, 9, 68, 10, 37, 23, 44, 34), -- CABAC_ENTRY(424, 45, 27, 66, 27, 31, 38, 33, 54), -- CABAC_ENTRY(425, 36, 59, 47, 57, 20, 64, 19, 82), -- CABAC_ENTRY(426, -6, 66, -5, 71, -9, 71, -3, 75), -- CABAC_ENTRY(427, -7, 35, 0, 24, -7, 37, -1, 23), -- CABAC_ENTRY(428, -7, 42, -1, 36, -8, 44, 1, 34), -- CABAC_ENTRY(429, -8, 45, -2, 42, -11, 49, 1, 43), -- CABAC_ENTRY(430, -5, 48, -2, 52, -10, 56, 0, 54), -- CABAC_ENTRY(431, -12, 56, -9, 57, -12, 59, -2, 55), -- CABAC_ENTRY(432, -6, 60, -6, 63, -8, 63, 0, 61), -- CABAC_ENTRY(433, -5, 62, -4, 65, -9, 67, 1, 64), -- CABAC_ENTRY(434, -8, 66, -4, 67, -6, 68, 0, 68), -- CABAC_ENTRY(435, -8, 76, -7, 82, -10, 79, -9, 92), -- CABAC_ENTRY(436, -5, 85, -3, 81, -3, 78, -14, 106), -- CABAC_ENTRY(437, -6, 81, -3, 76, -8, 74, -13, 97), -- CABAC_ENTRY(438, -10, 77, -7, 72, -9, 72, -15, 90), -- CABAC_ENTRY(439, -7, 81, -6, 78, -10, 72, -12, 90), -- CABAC_ENTRY(440, -17, 80, -12, 72, -18, 75, -18, 88), -- CABAC_ENTRY(441, -18, 73, -14, 68, -12, 71, -10, 73), -- CABAC_ENTRY(442, -4, 74, -3, 70, -11, 63, -9, 79), -- CABAC_ENTRY(443, -10, 83, -6, 76, -5, 70, -14, 86), -- CABAC_ENTRY(444, -9, 71, -5, 66, -17, 75, -10, 73), -- CABAC_ENTRY(445, -9, 67, -5, 62, -14, 72, -10, 70), -- CABAC_ENTRY(446, -1, 61, 0, 57, -16, 67, -10, 69), -- CABAC_ENTRY(447, -8, 66, -4, 61, -8, 53, -5, 66), -- CABAC_ENTRY(448, -14, 66, -9, 60, -14, 59, -9, 64), -- CABAC_ENTRY(449, 0, 59, 1, 54, -9, 52, -5, 58), -- CABAC_ENTRY(450, 2, 59, 2, 58, -11, 68, 2, 59), -- CABAC_ENTRY(451, 21, -13, 17, -10, 9, -2, 21, -10), -- CABAC_ENTRY(452, 33, -14, 32, -13, 30, -10, 24, -11), -- CABAC_ENTRY(453, 39, -7, 42, -9, 31, -4, 28, -8), -- CABAC_ENTRY(454, 46, -2, 49, -5, 33, -1, 28, -1), -- CABAC_ENTRY(455, 51, 2, 53, 0, 33, 7, 29, 3), -- CABAC_ENTRY(456, 60, 6, 64, 3, 31, 12, 29, 9), -- CABAC_ENTRY(457, 61, 17, 68, 10, 37, 23, 35, 20), -- CABAC_ENTRY(458, 55, 34, 66, 27, 31, 38, 29, 36), -- CABAC_ENTRY(459, 42, 62, 47, 57, 20, 64, 14, 67), --}; -- - static void set_ps_field(u32 *buf, struct rkvdec_ps_field field, u32 value) - { - u8 bit = field.offset % 32, word = field.offset / 32; -- -Armbian +2.45.2 -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 + +From ad4ef790fc671da994ad3c2691034fe954e95ff4 Mon Sep 17 00:00:00 2001 From: Detlev Casanova -Date: Thu, 20 Jun 2024 10:19:44 -0400 -Subject: media: rockchip: Introduce the rkvdec2 driver +Date: Fri, 14 Jun 2024 19:52:12 -0400 +Subject: [PATCH 2/4] media: rockchip: Introduce the rkvdec2 driver This driver supports the second generation of the Rockchip Video decoder, also known as vdpu34x. @@ -1089,46 +1097,45 @@ in future features. Signed-off-by: Detlev Casanova --- - drivers/staging/media/Kconfig | 1 + - drivers/staging/media/Makefile | 1 + - drivers/staging/media/rkvdec2/Kconfig | 15 + - drivers/staging/media/rkvdec2/Makefile | 3 + - drivers/staging/media/rkvdec2/TODO | 9 + - drivers/staging/media/rkvdec2/rkvdec2-h264.c | 739 ++++++ - drivers/staging/media/rkvdec2/rkvdec2-regs.h | 345 +++ - drivers/staging/media/rkvdec2/rkvdec2.c | 1253 ++++++++++ - drivers/staging/media/rkvdec2/rkvdec2.h | 130 + - 9 files changed, 2496 insertions(+) + drivers/media/platform/rockchip/Kconfig | 1 + + drivers/media/platform/rockchip/Makefile | 1 + + .../media/platform/rockchip/rkvdec2/Kconfig | 15 + + .../media/platform/rockchip/rkvdec2/Makefile | 3 + + .../platform/rockchip/rkvdec2/rkvdec2-h264.c | 744 ++++++++++ + .../platform/rockchip/rkvdec2/rkvdec2-regs.h | 346 +++++ + .../media/platform/rockchip/rkvdec2/rkvdec2.c | 1263 +++++++++++++++++ + .../media/platform/rockchip/rkvdec2/rkvdec2.h | 130 ++ + 8 files changed, 2503 insertions(+) + create mode 100644 drivers/media/platform/rockchip/rkvdec2/Kconfig + create mode 100644 drivers/media/platform/rockchip/rkvdec2/Makefile + create mode 100644 drivers/media/platform/rockchip/rkvdec2/rkvdec2-h264.c + create mode 100644 drivers/media/platform/rockchip/rkvdec2/rkvdec2-regs.h + create mode 100644 drivers/media/platform/rockchip/rkvdec2/rkvdec2.c + create mode 100644 drivers/media/platform/rockchip/rkvdec2/rkvdec2.h -diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig -index 111111111111..222222222222 100644 ---- a/drivers/staging/media/Kconfig -+++ b/drivers/staging/media/Kconfig -@@ -35,6 +35,7 @@ source "drivers/staging/media/meson/vdec/Kconfig" - source "drivers/staging/media/omap4iss/Kconfig" +diff --git a/drivers/media/platform/rockchip/Kconfig b/drivers/media/platform/rockchip/Kconfig +index b41d3960c1b4..36987ef24014 100644 +--- a/drivers/media/platform/rockchip/Kconfig ++++ b/drivers/media/platform/rockchip/Kconfig +@@ -4,3 +4,4 @@ comment "Rockchip media platform drivers" - source "drivers/staging/media/rkvdec/Kconfig" -+source "drivers/staging/media/rkvdec2/Kconfig" - - source "drivers/staging/media/starfive/Kconfig" - -diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile -index 111111111111..222222222222 100644 ---- a/drivers/staging/media/Makefile -+++ b/drivers/staging/media/Makefile -@@ -6,6 +6,7 @@ obj-$(CONFIG_VIDEO_MAX96712) += max96712/ - obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/ - obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ - obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/ + source "drivers/media/platform/rockchip/rga/Kconfig" + source "drivers/media/platform/rockchip/rkisp1/Kconfig" ++source "drivers/media/platform/rockchip/rkvdec2/Kconfig" +diff --git a/drivers/media/platform/rockchip/Makefile b/drivers/media/platform/rockchip/Makefile +index 4f782b876ac9..8c108d91d13e 100644 +--- a/drivers/media/platform/rockchip/Makefile ++++ b/drivers/media/platform/rockchip/Makefile +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-y += rga/ + obj-y += rkisp1/ +obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC2) += rkvdec2/ - obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/ - obj-$(CONFIG_VIDEO_SUNXI) += sunxi/ - obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/ -diff --git a/drivers/staging/media/rkvdec2/Kconfig b/drivers/staging/media/rkvdec2/Kconfig +diff --git a/drivers/media/platform/rockchip/rkvdec2/Kconfig b/drivers/media/platform/rockchip/rkvdec2/Kconfig new file mode 100644 -index 000000000000..111111111111 +index 000000000000..fd505cb7aff9 --- /dev/null -+++ b/drivers/staging/media/rkvdec2/Kconfig ++++ b/drivers/media/platform/rockchip/rkvdec2/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +config VIDEO_ROCKCHIP_VDEC2 @@ -1145,36 +1152,21 @@ index 000000000000..111111111111 + which accelerates video decoding. + To compile this driver as a module, choose M here: the module + will be called rockchip-vdec2. -diff --git a/drivers/staging/media/rkvdec2/Makefile b/drivers/staging/media/rkvdec2/Makefile +diff --git a/drivers/media/platform/rockchip/rkvdec2/Makefile b/drivers/media/platform/rockchip/rkvdec2/Makefile new file mode 100644 -index 000000000000..111111111111 +index 000000000000..b5a6ac701970 --- /dev/null -+++ b/drivers/staging/media/rkvdec2/Makefile ++++ b/drivers/media/platform/rockchip/rkvdec2/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC2) += rockchip-vdec2.o + +rockchip-vdec2-y += rkvdec2.o rkvdec2-h264.o -diff --git a/drivers/staging/media/rkvdec2/TODO b/drivers/staging/media/rkvdec2/TODO +diff --git a/drivers/media/platform/rockchip/rkvdec2/rkvdec2-h264.c b/drivers/media/platform/rockchip/rkvdec2/rkvdec2-h264.c new file mode 100644 -index 000000000000..111111111111 +index 000000000000..2e991c85d90e --- /dev/null -+++ b/drivers/staging/media/rkvdec2/TODO -@@ -0,0 +1,9 @@ -+* Support for 4:2:2 and 10 bits -+* Support for rockchip IOMMU -+* Support for HEVC and VP9 are planned for this driver. -+ -+ First, the h264 backend needs to be stabilized. -+ -+* Evaluate sharing code with rkvdec -+ -+ As rkvdec is still in staging, this driver stays there as well. -diff --git a/drivers/staging/media/rkvdec2/rkvdec2-h264.c b/drivers/staging/media/rkvdec2/rkvdec2-h264.c -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/drivers/staging/media/rkvdec2/rkvdec2-h264.c -@@ -0,0 +1,739 @@ ++++ b/drivers/media/platform/rockchip/rkvdec2/rkvdec2-h264.c +@@ -0,0 +1,744 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip Video Decoder 2 H264 backend @@ -1187,11 +1179,10 @@ index 000000000000..111111111111 + +#include +#include ++#include + +#include "rkvdec2.h" +#include "rkvdec2-regs.h" -+/* This header will move to a rockchip/common folder when de-staging */ -+#include "../rkvdec/rkvdec-h264-cabac.h" + +#define RKVDEC_NUM_REFLIST 3 + @@ -1291,7 +1282,7 @@ index 000000000000..111111111111 + +/* Data structure describing auxiliary buffer format. */ +struct rkvdec2_h264_priv_tbl { -+ u32 cabac_table[928]; ++ u32 cabac_table[4][464][2]; + struct rkvdec2_h264_scaling_list scaling_list; + struct rkvdec2_sps_pps param_set[256]; + struct rkvdec2_rps rps; @@ -1304,18 +1295,18 @@ index 000000000000..111111111111 +}; + +struct rkvdec2_h264_run { -+ struct rkvdec2_run base; -+ const struct v4l2_ctrl_h264_decode_params *decode_params; -+ const struct v4l2_ctrl_h264_sps *sps; -+ const struct v4l2_ctrl_h264_pps *pps; -+ const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; ++ struct rkvdec2_run base; ++ const struct v4l2_ctrl_h264_decode_params *decode_params; ++ const struct v4l2_ctrl_h264_sps *sps; ++ const struct v4l2_ctrl_h264_pps *pps; ++ const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; + struct vb2_buffer *ref_buf[V4L2_H264_NUM_DPB_ENTRIES]; +}; + +struct rkvdec2_h264_ctx { -+ struct rkvdec2_aux_buf priv_tbl; -+ struct rkvdec2_h264_reflists reflists; -+ struct rkvdec2_regs_h264 regs; ++ struct rkvdec2_aux_buf priv_tbl; ++ struct rkvdec2_h264_reflists reflists; ++ struct rkvdec2_regs_h264 regs; +}; + +static void assemble_hw_pps(struct rkvdec2_ctx *ctx, @@ -1342,13 +1333,13 @@ index 000000000000..111111111111 + memset(hw_ps, 0, sizeof(*hw_ps)); + + /* write sps */ -+ hw_ps->sps.seq_parameter_set_id = 0xf; -+ hw_ps->sps.profile_idc = 0xff; -+ hw_ps->sps.constraint_set3_flag = 1; ++ hw_ps->sps.seq_parameter_set_id = sps->seq_parameter_set_id; ++ hw_ps->sps.profile_idc = sps->profile_idc; ++ hw_ps->sps.constraint_set3_flag = !!(sps->constraint_set_flags & (1 << 3)); + hw_ps->sps.chroma_format_idc = sps->chroma_format_idc; + hw_ps->sps.bit_depth_luma = sps->bit_depth_luma_minus8; + hw_ps->sps.bit_depth_chroma = sps->bit_depth_chroma_minus8; -+ hw_ps->sps.qpprime_y_zero_transform_bypass_flag = 0; ++ hw_ps->sps.qpprime_y_zero_transform_bypass_flag = !!(sps->flags & V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS); + hw_ps->sps.log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; + hw_ps->sps.max_num_ref_frames = sps->max_num_ref_frames; + hw_ps->sps.pic_order_cnt_type = sps->pic_order_cnt_type; @@ -1376,8 +1367,8 @@ index 000000000000..111111111111 + !!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE); + + /* write pps */ -+ hw_ps->pps.pic_parameter_set_id = 0xff; -+ hw_ps->pps.pps_seq_parameter_set_id = 0x1f; ++ hw_ps->pps.pic_parameter_set_id = pps->pic_parameter_set_id; ++ hw_ps->pps.pps_seq_parameter_set_id = pps->seq_parameter_set_id; + hw_ps->pps.entropy_coding_mode_flag = + !!(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE); + hw_ps->pps.bottom_field_pic_order_in_frame_present_flag = @@ -1575,7 +1566,7 @@ index 000000000000..111111111111 +{ +#ifdef CONFIG_ARM64 + __iowrite32_copy(dst, src, len); -+#elif defined(CONFIG_ARM) ++#else + memcpy_toio(dst, src, len); +#endif +} @@ -1668,6 +1659,8 @@ index 000000000000..111111111111 + regs->common.timeout_threshold = RKVDEC2_TIMEOUT_4K; + else if (pixels < RKVDEC2_8K_PIXELS) + regs->common.timeout_threshold = RKVDEC2_TIMEOUT_8K; ++ else ++ regs->common.timeout_threshold = RKVDEC2_TIMEOUT_MAX; + + /* Set TOP and BOTTOM POCs */ + regs->h264_param.cur_top_poc = dec_params->top_field_order_cnt; @@ -1872,6 +1865,7 @@ index 000000000000..111111111111 + struct rkvdec2_dev *rkvdec = ctx->dev; + struct rkvdec2_h264_ctx *h264_ctx = ctx->priv; + struct rkvdec2_h264_run run; ++ uint32_t watchdog_time; + + rkvdec2_h264_run_preamble(ctx, &run); + @@ -1891,7 +1885,10 @@ index 000000000000..111111111111 + + rkvdec2_run_postamble(ctx, &run.base); + -+ schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000)); ++ /* Set watchdog at 2 times the hardware timeout threshold */ ++ u64 timeout_threshold = h264_ctx->regs.common.timeout_threshold; ++ watchdog_time = 2 * (1000 * timeout_threshold) / clk_get_rate(rkvdec->clocks[0].clk); ++ schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(watchdog_time)); + + /* Start decoding! */ + writel(RKVDEC2_REG_DEC_E_BIT, rkvdec->regs + RKVDEC2_REG_DEC_E); @@ -1914,12 +1911,12 @@ index 000000000000..111111111111 + .run = rkvdec2_h264_run, + .try_ctrl = rkvdec2_h264_try_ctrl, +}; -diff --git a/drivers/staging/media/rkvdec2/rkvdec2-regs.h b/drivers/staging/media/rkvdec2/rkvdec2-regs.h +diff --git a/drivers/media/platform/rockchip/rkvdec2/rkvdec2-regs.h b/drivers/media/platform/rockchip/rkvdec2/rkvdec2-regs.h new file mode 100644 -index 000000000000..111111111111 +index 000000000000..2a432fc0bf52 --- /dev/null -+++ b/drivers/staging/media/rkvdec2/rkvdec2-regs.h -@@ -0,0 +1,345 @@ ++++ b/drivers/media/platform/rockchip/rkvdec2/rkvdec2-regs.h +@@ -0,0 +1,346 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Rockchip Video Decoder 2 driver registers description @@ -1950,6 +1947,7 @@ index 000000000000..111111111111 +#define RKVDEC2_TIMEOUT_1080p (0xefffff) +#define RKVDEC2_TIMEOUT_4K (0x2cfffff) +#define RKVDEC2_TIMEOUT_8K (0x4ffffff) ++#define RKVDEC2_TIMEOUT_MAX (0xffffffff) + +#define RKVDEC2_REG_DEC_E 0x028 +#define RKVDEC2_REG_DEC_E_BIT 1 @@ -2265,12 +2263,12 @@ index 000000000000..111111111111 +} __packed; + +#endif /* __RKVDEC_REGS_H__ */ -diff --git a/drivers/staging/media/rkvdec2/rkvdec2.c b/drivers/staging/media/rkvdec2/rkvdec2.c +diff --git a/drivers/media/platform/rockchip/rkvdec2/rkvdec2.c b/drivers/media/platform/rockchip/rkvdec2/rkvdec2.c new file mode 100644 -index 000000000000..111111111111 +index 000000000000..852e88fc0ea1 --- /dev/null -+++ b/drivers/staging/media/rkvdec2/rkvdec2.c -@@ -0,0 +1,1253 @@ ++++ b/drivers/media/platform/rockchip/rkvdec2/rkvdec2.c +@@ -0,0 +1,1263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rockchip Video Decoder 2 driver @@ -2284,6 +2282,7 @@ index 000000000000..111111111111 +#include +#include +#include ++#include +#include +#include +#include @@ -2342,7 +2341,7 @@ index 000000000000..111111111111 + }, + { + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, -+ .cfg.min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, ++ .cfg.min = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, + .cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, + .cfg.menu_skip_mask = + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED), @@ -2406,7 +2405,7 @@ index 000000000000..111111111111 + {67, PIC_HEIGHT}, // filtc col +}; + -+#define RCB_SIZE(n) (rcb_sizes[(n)].multiplier * (rcb_sizes[(n)].axis ? height : width)) ++#define RCB_SIZE(n,w,h) (rcb_sizes[(n)].multiplier * (rcb_sizes[(n)].axis ? (h) : (w))) + +static const struct rkvdec2_coded_fmt_desc * +rkvdec2_find_coded_fmt_desc(u32 fourcc) @@ -2469,17 +2468,24 @@ index 000000000000..111111111111 +static int rkvdec2_enum_framesizes(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ -+ const struct rkvdec2_coded_fmt_desc *fmt; ++ const struct rkvdec2_coded_fmt_desc *desc; + + if (fsize->index != 0) + return -EINVAL; + -+ fmt = rkvdec2_find_coded_fmt_desc(fsize->pixel_format); -+ if (!fmt) ++ desc = rkvdec2_find_coded_fmt_desc(fsize->pixel_format); ++ if (!desc) + return -EINVAL; + -+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; -+ fsize->stepwise = fmt->frmsize; ++ fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; ++ ++ fsize->stepwise.min_height = 1; ++ fsize->stepwise.min_width = 1; ++ fsize->stepwise.step_height = 1; ++ fsize->stepwise.step_width = 1; ++ fsize->stepwise.max_height = desc->frmsize.max_height; ++ fsize->stepwise.max_width = desc->frmsize.max_width; ++ + return 0; +} + @@ -2825,6 +2831,8 @@ index 000000000000..111111111111 + height = ctx->decoded_fmt.fmt.pix_mp.height; + + for (i = 0; i < RKVDEC2_RCB_COUNT; i++) { ++ size_t rcb_size = RCB_SIZE(i, width, height); ++ + if (!ctx->rcb_bufs[i].cpu) + continue; + @@ -2832,11 +2840,11 @@ index 000000000000..111111111111 + case RKVDEC2_ALLOC_SRAM: + gen_pool_free(ctx->dev->sram_pool, + (unsigned long)ctx->rcb_bufs[i].cpu, -+ RCB_SIZE(i)); ++ rcb_size); + break; + case RKVDEC2_ALLOC_DMA: + dma_free_coherent(ctx->dev->dev, -+ RCB_SIZE(i), ++ rcb_size, + ctx->rcb_bufs[i].cpu, + ctx->rcb_bufs[i].dma); + break; @@ -2857,7 +2865,7 @@ index 000000000000..111111111111 + for (i = 0; i < RKVDEC2_RCB_COUNT; i++) { + void *cpu = NULL; + dma_addr_t dma; -+ size_t rcb_size = RCB_SIZE(i); ++ size_t rcb_size = RCB_SIZE(i, width, height); + enum rkvdec2_alloc_type alloc_type = RKVDEC2_ALLOC_SRAM; + + if (ctx->dev->sram_pool) { @@ -3420,7 +3428,7 @@ index 000000000000..111111111111 + if (ret) + return ret; + -+ rkvdec->regs = devm_platform_ioremap_resource(pdev, 0); ++ rkvdec->regs = devm_platform_ioremap_resource_byname(pdev, "function"); + if (IS_ERR(rkvdec->regs)) + return PTR_ERR(rkvdec->regs); + @@ -3524,11 +3532,11 @@ index 000000000000..111111111111 +MODULE_AUTHOR("Detlev Casanova "); +MODULE_DESCRIPTION("Rockchip Video Decoder 2 driver"); +MODULE_LICENSE("GPL"); -diff --git a/drivers/staging/media/rkvdec2/rkvdec2.h b/drivers/staging/media/rkvdec2/rkvdec2.h +diff --git a/drivers/media/platform/rockchip/rkvdec2/rkvdec2.h b/drivers/media/platform/rockchip/rkvdec2/rkvdec2.h new file mode 100644 -index 000000000000..111111111111 +index 000000000000..8613051775e9 --- /dev/null -+++ b/drivers/staging/media/rkvdec2/rkvdec2.h ++++ b/drivers/media/platform/rockchip/rkvdec2/rkvdec2.h @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* @@ -3661,5 +3669,231 @@ index 000000000000..111111111111 + +#endif /* RKVDEC_H_ */ -- -Armbian +2.45.2 + + +From 26a9741268ff1f11d1d573c1cecd5f2ce5f4ba79 Mon Sep 17 00:00:00 2001 +From: Detlev Casanova +Date: Fri, 14 Jun 2024 19:53:40 -0400 +Subject: [PATCH 3/4] media: dt-bindings: rockchip: Document RK3588 Video + Decoder bindings + +Document the Rockchip RK3588 Video Decoder bindings. + +Signed-off-by: Detlev Casanova +--- + .../bindings/media/rockchip,vdec.yaml | 73 ++++++++++++++++++- + 1 file changed, 72 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml +index 08b02ec16755..bb79499bebb0 100644 +--- a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml +@@ -17,6 +17,7 @@ properties: + compatible: + oneOf: + - const: rockchip,rk3399-vdec ++ - const: rockchip,rk3588-vdec + - items: + - enum: + - rockchip,rk3228-vdec +@@ -24,35 +25,72 @@ properties: + - const: rockchip,rk3399-vdec + + reg: +- maxItems: 1 ++ minItems: 1 ++ items: ++ - description: The link table configuration registers base ++ - description: The function configuration registers base ++ - description: The cache configuration registers base ++ ++ reg-names: ++ items: ++ - const: link ++ - const: function ++ - const: cache + + interrupts: + maxItems: 1 + + clocks: ++ minItems: 4 + items: + - description: The Video Decoder AXI interface clock + - description: The Video Decoder AHB interface clock + - description: The Video Decoded CABAC clock + - description: The Video Decoder core clock ++ - description: The Video decoder HEVC CABAC clock + + clock-names: ++ minItems: 4 + items: + - const: axi + - const: ahb + - const: cabac + - const: core ++ - const: hevc_cabac + + assigned-clocks: true + + assigned-clock-rates: true + ++ resets: ++ items: ++ - description: The Video Decoder AXI interface reset ++ - description: The Video Decoder AHB interface reset ++ - description: The Video Decoded CABAC reset ++ - description: The Video Decoder core reset ++ - description: The Video decoder HEVC CABAC reset ++ ++ reset-names: ++ items: ++ - const: axi ++ - const: ahb ++ - const: cabac ++ - const: core ++ - const: hevc_cabac ++ + power-domains: + maxItems: 1 + + iommus: + maxItems: 1 + ++ sram: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: | ++ phandle to a reserved on-chip SRAM regions. ++ Some SoCs, like rk3588 provide on-chip SRAM to store temporary ++ buffers during decoding. ++ + required: + - compatible + - reg +@@ -61,6 +99,39 @@ required: + - clock-names + - power-domains + ++allOf: ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: rockchip,rk3588-vdec ++ then: ++ properties: ++ reg: ++ minItems: 3 ++ reg-names: ++ minItems: 3 ++ clocks: ++ minItems: 5 ++ clock-names: ++ minItems: 5 ++ resets: ++ minItems: 5 ++ reset-names: ++ minItems: 5 ++ else: ++ properties: ++ reg: ++ maxItems: 1 ++ reg-names: false ++ clocks: ++ maxItems: 4 ++ clock-names: ++ maxItems: 4 ++ resets: false ++ reset-names: false ++ sram: false ++ + additionalProperties: false + + examples: +-- +2.45.2 + + +From 3acffd4e3409070f92fbf2defdbcf46fc818f529 Mon Sep 17 00:00:00 2001 +From: Detlev Casanova +Date: Fri, 14 Jun 2024 19:56:19 -0400 +Subject: [PATCH 4/4] arm64: dts: rockchip: Add rkvdec2 Video Decoder on + rk3588(s) + +Add the rkvdec2 Video Decoder to the RK3588s devicetree. + +Signed-off-by: Detlev Casanova +--- + arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 48 +++++++++++++++++++ + 1 file changed, 48 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +index b6e4df180f0b..2307e496dde8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +@@ -1122,6 +1122,44 @@ power-domain@RK3588_PD_SDMMC { + }; + }; + ++ vdec0: video-decoder@fdc38000 { ++ compatible = "rockchip,rk3588-vdec"; ++ reg = <0x0 0xfdc38000 0x0 0x100>, <0x0 0xfdc38100 0x0 0x500>, <0x0 0xfdc38600 0x0 0x100>; ++ reg-names = "link", "function", "cache"; ++ interrupts = ; ++ clocks = <&cru ACLK_RKVDEC0>, <&cru HCLK_RKVDEC0>, <&cru CLK_RKVDEC0_CA>, ++ <&cru CLK_RKVDEC0_CORE>, <&cru CLK_RKVDEC0_HEVC_CA>; ++ clock-names = "axi", "ahb", "cabac", "core", "hevc_cabac"; ++ assigned-clocks = <&cru ACLK_RKVDEC0>, <&cru CLK_RKVDEC0_CORE>, ++ <&cru CLK_RKVDEC0_CA>, <&cru CLK_RKVDEC0_HEVC_CA>; ++ assigned-clock-rates = <800000000>, <600000000>, ++ <600000000>, <1000000000>; ++ resets = <&cru SRST_A_RKVDEC0>, <&cru SRST_H_RKVDEC0>, <&cru SRST_RKVDEC0_CA>, ++ <&cru SRST_RKVDEC0_CORE>, <&cru SRST_RKVDEC0_HEVC_CA>; ++ reset-names = "axi", "ahb", "cabac", "core", "hevc_cabac"; ++ power-domains = <&power RK3588_PD_RKVDEC0>; ++ sram = <&vdec0_sram>; ++ }; ++ ++ vdec1: video-decoder@fdc40000 { ++ compatible = "rockchip,rk3588-vdec"; ++ reg = <0x0 0xfdc40000 0x0 0x100>, <0x0 0xfdc40100 0x0 0x500>, <0x0 0xfdc40600 0x0 0x100>; ++ reg-names = "link", "function", "cache"; ++ interrupts = ; ++ clocks = <&cru ACLK_RKVDEC1>, <&cru HCLK_RKVDEC1>, <&cru CLK_RKVDEC1_CA>, ++ <&cru CLK_RKVDEC1_CORE>, <&cru CLK_RKVDEC1_HEVC_CA>; ++ clock-names = "axi", "ahb", "cabac", "core", "hevc_cabac"; ++ assigned-clocks = <&cru ACLK_RKVDEC1>, <&cru CLK_RKVDEC1_CORE>, ++ <&cru CLK_RKVDEC1_CA>, <&cru CLK_RKVDEC1_HEVC_CA>; ++ assigned-clock-rates = <800000000>, <600000000>, ++ <600000000>, <1000000000>; ++ resets = <&cru SRST_A_RKVDEC1>, <&cru SRST_H_RKVDEC1>, <&cru SRST_RKVDEC1_CA>, ++ <&cru SRST_RKVDEC1_CORE>, <&cru SRST_RKVDEC1_HEVC_CA>; ++ reset-names = "axi", "ahb", "cabac", "core", "hevc_cabac"; ++ power-domains = <&power RK3588_PD_RKVDEC1>; ++ sram = <&vdec1_sram>; ++ }; ++ + av1d: video-codec@fdc70000 { + compatible = "rockchip,rk3588-av1-vpu"; + reg = <0x0 0xfdc70000 0x0 0x800>; +@@ -2725,6 +2763,16 @@ system_sram2: sram@ff001000 { + ranges = <0x0 0x0 0xff001000 0xef000>; + #address-cells = <1>; + #size-cells = <1>; ++ ++ vdec0_sram: codec-sram@0 { ++ reg = <0x0 0x78000>; ++ pool; ++ }; ++ ++ vdec1_sram: codec-sram@78000 { ++ reg = <0x78000 0x77000>; ++ pool; ++ }; + }; + + pinctrl: pinctrl { +-- +2.45.2 diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0147-arm64-dts-rockchip-rk3588-add-RGA2-node.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0029-arm64-dts-rockchip-rk3588-add-RGA2-node.patch similarity index 100% rename from patch/kernel/archive/rockchip-rk3588-6.11/0147-arm64-dts-rockchip-rk3588-add-RGA2-node.patch rename to patch/kernel/archive/rockchip-rk3588-6.11/0029-arm64-dts-rockchip-rk3588-add-RGA2-node.patch diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0113-add-synopsys-designware-hdmi-rx-controller.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0113-add-synopsys-designware-hdmi-rx-controller.patch index 50d858175..18ec03814 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0113-add-synopsys-designware-hdmi-rx-controller.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0113-add-synopsys-designware-hdmi-rx-controller.patch @@ -1,33 +1,236 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 3dbcda0077c859d0dd08aab8e488b940506573ef Mon Sep 17 00:00:00 2001 From: Shreeya Patel -Date: Mon, 29 Jul 2024 14:41:14 +0300 -Subject: arm64: dts: rockchip: Add device tree support for HDMI RX Controller +Date: Fri, 19 Jul 2024 18:10:29 +0530 +Subject: [PATCH 1/5] MAINTAINERS: Add entry for Synopsys DesignWare HDMI RX + Driver +Add an entry for Synopsys DesignWare HDMI Receiver Controller +Driver. + +Signed-off-by: Shreeya Patel +Reviewed-by: Christopher Obbard +Link: https://lore.kernel.org/r/20240719124032.26852-2-shreeya.patel@collabora.com +Signed-off-by: Sebastian Reichel --- - arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi | 42 + - arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi | 56 + - drivers/media/platform/Kconfig | 1 + - drivers/media/platform/Makefile | 1 + - drivers/media/platform/synopsys/Kconfig | 3 + - drivers/media/platform/synopsys/Makefile | 2 + - drivers/media/platform/synopsys/hdmirx/Kconfig | 27 + - drivers/media/platform/synopsys/hdmirx/Makefile | 4 + - drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c | 2763 ++++++++++ - drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h | 394 ++ - drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.c | 285 + - drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.h | 44 + - 12 files changed, 3622 insertions(+) + MAINTAINERS | 8 ++++++++ + 1 file changed, 8 insertions(+) -diff --git a/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi -index 111111111111..222222222222 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi -@@ -169,6 +169,48 @@ hdmim0_tx1_sda: hdmim0-tx1-sda { - /* hdmim0_tx1_sda */ - <2 RK_PB4 4 &pcfg_pull_none>; +diff --git a/MAINTAINERS b/MAINTAINERS +index 42decde38320..9a83c9cec932 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -22142,6 +22142,14 @@ F: drivers/net/pcs/pcs-xpcs.c + F: drivers/net/pcs/pcs-xpcs.h + F: include/linux/pcs/pcs-xpcs.h + ++SYNOPSYS DESIGNWARE HDMI RX CONTROLLER DRIVER ++M: Shreeya Patel + R: Andy Shevchenko +-- +2.45.2 + + +From 0b2d3a37d013f1115cd12d60fe2d9b768fb08002 Mon Sep 17 00:00:00 2001 +From: Shreeya Patel +Date: Fri, 19 Jul 2024 18:10:30 +0530 +Subject: [PATCH 2/5] dt-bindings: media: Document bindings for HDMI RX + Controller + +Document bindings for the Synopsys DesignWare HDMI RX Controller. + +Reviewed-by: Rob Herring +Reviewed-by: Dmitry Osipenko +Signed-off-by: Shreeya Patel +Reviewed-by: Sebastian Reichel +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20240719124032.26852-3-shreeya.patel@collabora.com +Signed-off-by: Sebastian Reichel +--- + .../bindings/media/snps,dw-hdmi-rx.yaml | 132 ++++++++++++++++++ + 1 file changed, 132 insertions(+) + create mode 100644 Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml + +diff --git a/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml +new file mode 100644 +index 000000000000..96ae1e2d2816 +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/snps,dw-hdmi-rx.yaml +@@ -0,0 +1,132 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++# Device Tree bindings for Synopsys DesignWare HDMI RX Controller ++ ++--- ++$id: http://devicetree.org/schemas/media/snps,dw-hdmi-rx.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Synopsys DesignWare HDMI RX Controller ++ ++maintainers: ++ - Shreeya Patel ++ ++description: ++ Synopsys DesignWare HDMI Input Controller preset on RK3588 SoCs ++ allowing devices to receive and decode high-resolution video streams ++ from external sources like media players, cameras, laptops, etc. ++ ++properties: ++ compatible: ++ items: ++ - const: rockchip,rk3588-hdmirx-ctrler ++ - const: snps,dw-hdmi-rx ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 3 ++ ++ interrupt-names: ++ items: ++ - const: cec ++ - const: hdmi ++ - const: dma ++ ++ clocks: ++ maxItems: 7 ++ ++ clock-names: ++ items: ++ - const: aclk ++ - const: audio ++ - const: cr_para ++ - const: pclk ++ - const: ref ++ - const: hclk_s_hdmirx ++ - const: hclk_vo1 ++ ++ power-domains: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 4 ++ ++ reset-names: ++ items: ++ - const: axi ++ - const: apb ++ - const: ref ++ - const: biu ++ ++ memory-region: ++ maxItems: 1 ++ ++ hpd-gpios: ++ description: GPIO specifier for HPD. ++ maxItems: 1 ++ ++ rockchip,grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ The phandle of the syscon node for the general register file ++ containing HDMIRX PHY status bits. ++ ++ rockchip,vo1-grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ The phandle of the syscon node for the Video Output GRF register ++ to enable EDID transfer through SDAIN and SCLIN. ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - interrupt-names ++ - clocks ++ - clock-names ++ - power-domains ++ - resets ++ - pinctrl-0 ++ - hpd-gpios ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ hdmi_receiver: hdmi-receiver@fdee0000 { ++ compatible = "rockchip,rk3588-hdmirx-ctrler", "snps,dw-hdmi-rx"; ++ reg = <0xfdee0000 0x6000>; ++ interrupts = , ++ , ++ ; ++ interrupt-names = "cec", "hdmi", "dma"; ++ clocks = <&cru ACLK_HDMIRX>, ++ <&cru CLK_HDMIRX_AUD>, ++ <&cru CLK_CR_PARA>, ++ <&cru PCLK_HDMIRX>, ++ <&cru CLK_HDMIRX_REF>, ++ <&cru PCLK_S_HDMIRX>, ++ <&cru HCLK_VO1>; ++ clock-names = "aclk", ++ "audio", ++ "cr_para", ++ "pclk", ++ "ref", ++ "hclk_s_hdmirx", ++ "hclk_vo1"; ++ power-domains = <&power RK3588_PD_VO1>; ++ resets = <&cru SRST_A_HDMIRX>, <&cru SRST_P_HDMIRX>, ++ <&cru SRST_HDMIRX_REF>, <&cru SRST_A_HDMIRX_BIU>; ++ reset-names = "axi", "apb", "ref", "biu"; ++ memory-region = <&hdmi_receiver_cma>; ++ pinctrl-0 = <&hdmim1_rx_cec &hdmim1_rx_hpdin &hdmim1_rx_scl &hdmim1_rx_sda &hdmirx_5v_detection>; ++ pinctrl-names = "default"; ++ hpd-gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; ++ }; +-- +2.45.2 + + +From a0de6ca89f167df7a2c491cb24bb191a6ced8bed Mon Sep 17 00:00:00 2001 +From: Shreeya Patel +Date: Fri, 19 Jul 2024 18:10:31 +0530 +Subject: [PATCH 3/5] arm64: dts: rockchip: Add device tree support for HDMI RX + Controller + +Add device tree support for Synopsys DesignWare HDMI RX +Controller. + +Reviewed-by: Dmitry Osipenko +Tested-by: Dmitry Osipenko +Co-developed-by: Dingxian Wen +Signed-off-by: Dingxian Wen +Signed-off-by: Shreeya Patel +Link: https://lore.kernel.org/r/20240719124032.26852-4-shreeya.patel@collabora.com +Signed-off-by: Sebastian Reichel +--- + .../dts/rockchip/rk3588-base-pinctrl.dtsi | 14 +++++ + .../arm64/boot/dts/rockchip/rk3588-extra.dtsi | 56 +++++++++++++++++++ + 2 files changed, 70 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi +index 30db12c4fc82..ca006f5a4c90 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi +@@ -594,6 +594,20 @@ hdmim0_tx1_hpd: hdmim0-tx1-hpd { + /* hdmim0_tx1_hpd */ + <1 RK_PA6 5 &pcfg_pull_none>; }; + -+ /omit-if-no-ref/ ++ /omit-if-no-ref/ + hdmim1_rx: hdmim1-rx { + rockchip,pins = + /* hdmim1_rx_cec */ @@ -40,39 +243,11 @@ index 111111111111..222222222222 100644 + <3 RK_PD4 5 &pcfg_pull_none>; + }; + -+ /omit-if-no-ref/ -+ hdmim1_rx_cec: hdmim1-rx-cec { -+ rockchip,pins = -+ /* hdmim1_rx_cec */ -+ <3 RK_PD1 5 &pcfg_pull_none>; -+ }; -+ -+ /omit-if-no-ref/ -+ hdmim1_rx_hpdin: hdmim1-rx-hpdin { -+ rockchip,pins = -+ /* hdmim1_rx_hpdin */ -+ <3 RK_PD4 5 &pcfg_pull_none>; -+ }; -+ -+ /omit-if-no-ref/ -+ hdmim1_rx_scl: hdmim1-rx-scl { -+ rockchip,pins = -+ /* hdmim1_rx_scl */ -+ <3 RK_PD2 5 &pcfg_pull_none>; -+ }; -+ -+ /omit-if-no-ref/ -+ hdmim1_rx_sda: hdmim1-rx-sda { -+ rockchip,pins = -+ /* hdmim1_rx_sda */ -+ <3 RK_PD3 5 &pcfg_pull_none>; -+ }; -+ - }; - - i2c0 { + /omit-if-no-ref/ + hdmim1_rx_cec: hdmim1-rx-cec { + rockchip,pins = diff --git a/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi -index 111111111111..222222222222 100644 +index 0ce0934ec6b7..96f8ce91eaf4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi @@ -7,6 +7,29 @@ @@ -83,7 +258,7 @@ index 111111111111..222222222222 100644 + #address-cells = <2>; + #size-cells = <2>; + ranges; -+ ++ + /* + * The 4k HDMI capture controller works only with 32bit + * phys addresses and doesn't support IOMMU. HDMI RX CMA @@ -94,18 +269,18 @@ index 111111111111..222222222222 100644 + * we doubled the 66MB value. + */ + hdmi_receiver_cma: hdmi-receiver-cma { -+ compatible = "shared-dma-pool"; -+ alloc-ranges = <0x0 0x0 0x0 0xffffffff>; -+ size = <0x0 (160 * 0x100000)>; /* 160MiB */ -+ no-map; -+ status = "disabled"; ++ compatible = "shared-dma-pool"; ++ alloc-ranges = <0x0 0x0 0x0 0xffffffff>; ++ size = <0x0 (160 * 0x100000)>; /* 160MiB */ ++ no-map; ++ status = "disabled"; + }; + }; + usb_host1_xhci: usb@fc400000 { compatible = "rockchip,rk3588-dwc3", "snps,dwc3"; reg = <0x0 0xfc400000 0x0 0x400000>; -@@ -433,6 +456,39 @@ combphy1_ps: phy@fee10000 { +@@ -135,6 +158,39 @@ i2s10_8ch: i2s@fde00000 { status = "disabled"; }; @@ -116,37 +291,86 @@ index 111111111111..222222222222 100644 + rockchip,grf = <&sys_grf>; + rockchip,vo1-grf = <&vo1_grf>; + interrupts = , -+ , -+ ; ++ , ++ ; + interrupt-names = "cec", "hdmi", "dma"; + clocks = <&cru ACLK_HDMIRX>, -+ <&cru CLK_HDMIRX_AUD>, -+ <&cru CLK_CR_PARA>, -+ <&cru PCLK_HDMIRX>, -+ <&cru CLK_HDMIRX_REF>, -+ <&cru PCLK_S_HDMIRX>, -+ <&cru HCLK_VO1>; ++ <&cru CLK_HDMIRX_AUD>, ++ <&cru CLK_CR_PARA>, ++ <&cru PCLK_HDMIRX>, ++ <&cru CLK_HDMIRX_REF>, ++ <&cru PCLK_S_HDMIRX>, ++ <&cru HCLK_VO1>; + clock-names = "aclk", -+ "audio", -+ "cr_para", -+ "pclk", -+ "ref", -+ "hclk_s_hdmirx", -+ "hclk_vo1"; ++ "audio", ++ "cr_para", ++ "pclk", ++ "ref", ++ "hclk_s_hdmirx", ++ "hclk_vo1"; + resets = <&cru SRST_A_HDMIRX>, <&cru SRST_P_HDMIRX>, -+ <&cru SRST_HDMIRX_REF>, <&cru SRST_A_HDMIRX_BIU>; ++ <&cru SRST_HDMIRX_REF>, <&cru SRST_A_HDMIRX_BIU>; + reset-names = "axi", "apb", "ref", "biu"; + memory-region = <&hdmi_receiver_cma>; -+ pinctrl-0 = <&hdmim1_rx>; -+ pinctrl-names = "default"; -+ status = "disabled"; ++ pinctrl-0 = <&hdmim1_rx>; ++ pinctrl-names = "default"; ++ status = "disabled"; + }; + - pcie30phy: phy@fee80000 { - compatible = "rockchip,rk3588-pcie3-phy"; - reg = <0x0 0xfee80000 0x0 0x20000>; + pcie3x4: pcie@fe150000 { + compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie"; + #address-cells = <3>; +-- +2.45.2 + + +From 4412f5bba1c8b964439064bd5d03e75d3ed58653 Mon Sep 17 00:00:00 2001 +From: Shreeya Patel +Date: Fri, 19 Jul 2024 18:10:32 +0530 +Subject: [PATCH 4/5] media: platform: synopsys: Add support for hdmi input + driver + +Add initial support for the Synopsys DesignWare HDMI RX +Controller Driver used by Rockchip RK3588. The driver +supports: + - HDMI 1.4b and 2.0 modes (HDMI 4k@60Hz) + - RGB888, YUV422, YUV444 and YCC420 pixel formats + - CEC + - EDID configuration + +The hardware also has Audio and HDCP capabilities, but these are +not yet supported by the driver. + +Reviewed-by: Dmitry Osipenko +Tested-by: Dmitry Osipenko +Co-developed-by: Dingxian Wen +Signed-off-by: Dingxian Wen +Signed-off-by: Shreeya Patel +Link: https://lore.kernel.org/r/20240719124032.26852-5-shreeya.patel@collabora.com +Signed-off-by: Sebastian Reichel +--- + drivers/media/platform/Kconfig | 1 + + drivers/media/platform/Makefile | 1 + + drivers/media/platform/synopsys/Kconfig | 3 + + drivers/media/platform/synopsys/Makefile | 2 + + .../media/platform/synopsys/hdmirx/Kconfig | 27 + + .../media/platform/synopsys/hdmirx/Makefile | 4 + + .../platform/synopsys/hdmirx/snps_hdmirx.c | 2763 +++++++++++++++++ + .../platform/synopsys/hdmirx/snps_hdmirx.h | 394 +++ + .../synopsys/hdmirx/snps_hdmirx_cec.c | 285 ++ + .../synopsys/hdmirx/snps_hdmirx_cec.h | 44 + + 10 files changed, 3524 insertions(+) + create mode 100644 drivers/media/platform/synopsys/Kconfig + create mode 100644 drivers/media/platform/synopsys/Makefile + create mode 100644 drivers/media/platform/synopsys/hdmirx/Kconfig + create mode 100644 drivers/media/platform/synopsys/hdmirx/Makefile + create mode 100644 drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c + create mode 100644 drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h + create mode 100644 drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.c + create mode 100644 drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.h + diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index 111111111111..222222222222 100644 +index 85d2627776b6..9287faafdce5 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -85,6 +85,7 @@ source "drivers/media/platform/rockchip/Kconfig" @@ -158,7 +382,7 @@ index 111111111111..222222222222 100644 source "drivers/media/platform/verisilicon/Kconfig" source "drivers/media/platform/via/Kconfig" diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile -index 111111111111..222222222222 100644 +index ace4e34483dd..6fd7db0541c7 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -28,6 +28,7 @@ obj-y += rockchip/ @@ -171,7 +395,7 @@ index 111111111111..222222222222 100644 obj-y += via/ diff --git a/drivers/media/platform/synopsys/Kconfig b/drivers/media/platform/synopsys/Kconfig new file mode 100644 -index 000000000000..111111111111 +index 000000000000..4fd521f78425 --- /dev/null +++ b/drivers/media/platform/synopsys/Kconfig @@ -0,0 +1,3 @@ @@ -180,7 +404,7 @@ index 000000000000..111111111111 +source "drivers/media/platform/synopsys/hdmirx/Kconfig" diff --git a/drivers/media/platform/synopsys/Makefile b/drivers/media/platform/synopsys/Makefile new file mode 100644 -index 000000000000..111111111111 +index 000000000000..3b12c574dd67 --- /dev/null +++ b/drivers/media/platform/synopsys/Makefile @@ -0,0 +1,2 @@ @@ -188,7 +412,7 @@ index 000000000000..111111111111 +obj-y += hdmirx/ diff --git a/drivers/media/platform/synopsys/hdmirx/Kconfig b/drivers/media/platform/synopsys/hdmirx/Kconfig new file mode 100644 -index 000000000000..111111111111 +index 000000000000..ab569e59300f --- /dev/null +++ b/drivers/media/platform/synopsys/hdmirx/Kconfig @@ -0,0 +1,27 @@ @@ -221,7 +445,7 @@ index 000000000000..111111111111 + such as supported resolutions, refresh rates, and audio formats. diff --git a/drivers/media/platform/synopsys/hdmirx/Makefile b/drivers/media/platform/synopsys/hdmirx/Makefile new file mode 100644 -index 000000000000..111111111111 +index 000000000000..2fa2d9e25300 --- /dev/null +++ b/drivers/media/platform/synopsys/hdmirx/Makefile @@ -0,0 +1,4 @@ @@ -231,7 +455,7 @@ index 000000000000..111111111111 +obj-$(CONFIG_VIDEO_SYNOPSYS_HDMIRX) += synopsys-hdmirx.o diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c new file mode 100644 -index 000000000000..111111111111 +index 000000000000..1dfecf256393 --- /dev/null +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.c @@ -0,0 +1,2763 @@ @@ -2985,7 +3209,7 @@ index 000000000000..111111111111 + +static struct platform_driver hdmirx_driver = { + .probe = hdmirx_probe, -+ .remove_new = hdmirx_remove, ++ .remove = hdmirx_remove, + .driver = { + .name = "snps_hdmirx", + .of_match_table = hdmirx_id, @@ -3000,7 +3224,7 @@ index 000000000000..111111111111 +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h new file mode 100644 -index 000000000000..111111111111 +index 000000000000..220ab99ca611 --- /dev/null +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h @@ -0,0 +1,394 @@ @@ -3400,7 +3624,7 @@ index 000000000000..111111111111 +#endif diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.c b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.c new file mode 100644 -index 000000000000..111111111111 +index 000000000000..9f67e2080bb6 --- /dev/null +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.c @@ -0,0 +1,285 @@ @@ -3691,7 +3915,7 @@ index 000000000000..111111111111 +} diff --git a/drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.h b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.h new file mode 100644 -index 000000000000..111111111111 +index 000000000000..c55c403cdb9f --- /dev/null +++ b/drivers/media/platform/synopsys/hdmirx/snps_hdmirx_cec.h @@ -0,0 +1,44 @@ @@ -3740,5 +3964,34 @@ index 000000000000..111111111111 + +#endif /* DW_HDMI_RX_CEC_H */ -- -Armbian +2.45.2 + + +From b7723aa090a4826f623b434b15a14bc6cf6fe538 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Mon, 29 Jul 2024 17:29:46 +0200 +Subject: [PATCH 5/5] arm64: defconfig: Enable Synopsys HDMI receiver + +The Rockchip RK3588 has a built-in HDMI receiver block from +Synopsys. Let's enable the driver for it. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/configs/defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig +index 23139a36ec0d..10b088434625 100644 +--- a/arch/arm64/configs/defconfig ++++ b/arch/arm64/configs/defconfig +@@ -841,6 +841,7 @@ CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m + CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m + CONFIG_VIDEO_SAMSUNG_S5P_MFC=m + CONFIG_VIDEO_SUN6I_CSI=m ++CONFIG_VIDEO_SYNOPSYS_HDMIRX=m + CONFIG_VIDEO_TI_J721E_CSI2RX=m + CONFIG_VIDEO_HANTRO=m + CONFIG_VIDEO_IMX219=m +-- +2.45.2 diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0130-phy-phy-rockchip-samsung-hdptx-Enable-runtime-PM.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0130-phy-phy-rockchip-samsung-hdptx-Enable-runtime-PM.patch new file mode 100644 index 000000000..6f65233b2 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0130-phy-phy-rockchip-samsung-hdptx-Enable-runtime-PM.patch @@ -0,0 +1,126 @@ +From 851c498258fab10b2176df6f237e147b3aa18556 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Tue, 11 Jun 2024 02:06:10 +0300 +Subject: [PATCH 1/2] phy: phy-rockchip-samsung-hdptx: Explicitly include + pm_runtime.h + +Driver makes use of helpers from pm_runtime.h, but relies on the header +file being implicitly included. + +Explicitly pull the header in to avoid potential build failures in some +configurations. + +Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver") +Signed-off-by: Cristian Ciocaltea +--- + drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +index 946c01210ac8..3bd9b62b23dc 100644 +--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +-- +2.45.2 + + +From 4cff4539ae49d68bdbf005b9b66c62cf0174df13 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Tue, 11 Jun 2024 02:28:26 +0300 +Subject: [PATCH 2/2] phy: phy-rockchip-samsung-hdptx: Enable runtime PM at PHY + core level + +When a new PHY is created via [devm_]phy_create(), the runtime PM for it +is not enabled unless the parent device (which creates the PHY) has its +own runtime PM already enabled. + +Move the call to devm_pm_runtime_enable() before devm_phy_create() to +enable runtime PM at PHY core level. + +With this change the ->power_on() and ->power_off() callbacks do not +require explicit runtime PM management anymore, since the PHY core +handles that via phy_pm_runtime_{get,put}_sync() when phy_power_on() and +phy_power_off() are invoked. + +Hence drop the now unnecessary calls to pm_runtime_resume_and_get() and +pm_runtime_put() helpers. + +Signed-off-by: Cristian Ciocaltea +--- + .../phy/rockchip/phy-rockchip-samsung-hdptx.c | 24 +++++-------------- + 1 file changed, 6 insertions(+), 18 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +index 3bd9b62b23dc..72de287282eb 100644 +--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -860,7 +860,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, + static int rk_hdptx_phy_power_on(struct phy *phy) + { + struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); +- int ret, bus_width = phy_get_bus_width(hdptx->phy); ++ int bus_width = phy_get_bus_width(hdptx->phy); + /* + * FIXME: Temporary workaround to pass pixel_clk_rate + * from the HDMI bridge driver until phy_configure_opts_hdmi +@@ -871,17 +871,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy) + dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n", + __func__, bus_width, rate); + +- ret = pm_runtime_resume_and_get(hdptx->dev); +- if (ret) { +- dev_err(hdptx->dev, "Failed to resume phy: %d\n", ret); +- return ret; +- } +- +- ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); +- if (ret) +- pm_runtime_put(hdptx->dev); +- +- return ret; ++ return rk_hdptx_ropll_tmds_mode_config(hdptx, rate); + } + + static int rk_hdptx_phy_power_off(struct phy *phy) +@@ -894,8 +884,6 @@ static int rk_hdptx_phy_power_off(struct phy *phy) + if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) + rk_hdptx_phy_disable(hdptx); + +- pm_runtime_put(hdptx->dev); +- + return ret; + } + +@@ -977,6 +965,10 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) + return dev_err_probe(dev, PTR_ERR(hdptx->grf), + "Could not get GRF syscon\n"); + ++ ret = devm_pm_runtime_enable(dev); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); ++ + hdptx->phy = devm_phy_create(dev, NULL, &rk_hdptx_phy_ops); + if (IS_ERR(hdptx->phy)) + return dev_err_probe(dev, PTR_ERR(hdptx->phy), +@@ -986,10 +978,6 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) + phy_set_drvdata(hdptx->phy, hdptx); + phy_set_bus_width(hdptx->phy, 8); + +- ret = devm_pm_runtime_enable(dev); +- if (ret) +- return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); +- + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return dev_err_probe(dev, PTR_ERR(phy_provider), +-- +2.45.2 + diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0131-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0131-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch new file mode 100644 index 000000000..4ccac6c6e --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0131-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch @@ -0,0 +1,326 @@ +From 2ed8602d4c0c5d211163ad1727fd2d76e20407af Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Mon, 19 Feb 2024 21:53:24 +0200 +Subject: [PATCH 1/2] dt-bindings: phy: rockchip,rk3588-hdptx-phy: Add + #clock-cells + +The HDMI PHY can be used as a clock provider on RK3588 SoC, hence add +the necessary '#clock-cells' property. + +Signed-off-by: Cristian Ciocaltea +--- + .../devicetree/bindings/phy/rockchip,rk3588-hdptx-phy.yaml | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Documentation/devicetree/bindings/phy/rockchip,rk3588-hdptx-phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,rk3588-hdptx-phy.yaml +index 54e822c715f3..84fe59dbcf48 100644 +--- a/Documentation/devicetree/bindings/phy/rockchip,rk3588-hdptx-phy.yaml ++++ b/Documentation/devicetree/bindings/phy/rockchip,rk3588-hdptx-phy.yaml +@@ -27,6 +27,9 @@ properties: + - const: ref + - const: apb + ++ "#clock-cells": ++ const: 0 ++ + "#phy-cells": + const: 0 + +-- +2.45.2 + + +From 50108aebe8997fcb0c61e81363024ca8f2ae1fcd Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Tue, 16 Jan 2024 19:27:40 +0200 +Subject: [PATCH 2/2] phy: phy-rockchip-samsung-hdptx: Add clock provider + support + +The HDMI PHY PLL can be used as an alternative dclk source to RK3588 SoC +CRU. It provides more accurate clock rates required by VOP2 to improve +existing support for display modes handling, which is known to be +problematic when dealing with non-integer refresh rates, among others. + +It is worth noting this only works for HDMI 2.0 or below, e.g. cannot be +used to support HDMI 2.1 4K@120Hz mode. + +Signed-off-by: Cristian Ciocaltea +--- + .../phy/rockchip/phy-rockchip-samsung-hdptx.c | 195 ++++++++++++++++-- + 1 file changed, 173 insertions(+), 22 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +index 72de287282eb..9f084697dd05 100644 +--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -8,6 +8,7 @@ + */ + #include + #include ++#include + #include + #include + #include +@@ -191,6 +192,8 @@ + #define LN3_TX_SER_RATE_SEL_HBR2 BIT(3) + #define LN3_TX_SER_RATE_SEL_HBR3 BIT(2) + ++#define HDMI20_MAX_RATE 600000000 ++ + struct lcpll_config { + u32 bit_rate; + u8 lcvco_mode_en; +@@ -273,6 +276,12 @@ struct rk_hdptx_phy { + struct clk_bulk_data *clks; + int nr_clks; + struct reset_control_bulk_data rsts[RST_MAX]; ++ ++ /* clk provider */ ++ struct clk_hw hw; ++ unsigned long rate; ++ ++ atomic_t usage_count; + }; + + static const struct ropll_config ropll_tmds_cfg[] = { +@@ -760,6 +769,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, + struct ropll_config rc = {0}; + int i; + ++ hdptx->rate = rate * 100; ++ + for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) + if (rate == ropll_tmds_cfg[i].bit_rate) { + cfg = &ropll_tmds_cfg[i]; +@@ -823,19 +834,6 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, + static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, + unsigned int rate) + { +- u32 val; +- int ret; +- +- ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); +- if (ret) +- return ret; +- +- if (!(val & HDPTX_O_PLL_LOCK_DONE)) { +- ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate); +- if (ret) +- return ret; +- } +- + rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq); + + regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06); +@@ -857,10 +855,68 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, + return rk_hdptx_post_enable_lane(hdptx); + } + ++static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx, ++ unsigned int rate) ++{ ++ u32 status; ++ int ret; ++ ++ if (atomic_inc_return(&hdptx->usage_count) > 1) ++ return 0; ++ ++ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status); ++ if (ret) ++ goto dec_usage; ++ ++ if (status & HDPTX_O_PLL_LOCK_DONE) ++ dev_warn(hdptx->dev, "PLL locked by unknown consumer!\n"); ++ ++ if (rate) { ++ ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate); ++ if (ret) ++ goto dec_usage; ++ } ++ ++ return 0; ++ ++dec_usage: ++ atomic_dec(&hdptx->usage_count); ++ return ret; ++} ++ ++static int rk_hdptx_phy_consumer_put(struct rk_hdptx_phy *hdptx, bool force) ++{ ++ u32 status; ++ int ret; ++ ++ ret = atomic_dec_return(&hdptx->usage_count); ++ if (ret > 0) ++ return 0; ++ ++ if (ret < 0) { ++ dev_warn(hdptx->dev, "Usage count underflow!\n"); ++ ret = -EINVAL; ++ } else { ++ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status); ++ if (!ret) { ++ if (status & HDPTX_O_PLL_LOCK_DONE) ++ rk_hdptx_phy_disable(hdptx); ++ return 0; ++ } else if (force) { ++ return 0; ++ } ++ } ++ ++ atomic_inc(&hdptx->usage_count); ++ return ret; ++} ++ + static int rk_hdptx_phy_power_on(struct phy *phy) + { + struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); + int bus_width = phy_get_bus_width(hdptx->phy); ++ int ret; ++ + /* + * FIXME: Temporary workaround to pass pixel_clk_rate + * from the HDMI bridge driver until phy_configure_opts_hdmi +@@ -871,20 +927,22 @@ static int rk_hdptx_phy_power_on(struct phy *phy) + dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n", + __func__, bus_width, rate); + +- return rk_hdptx_ropll_tmds_mode_config(hdptx, rate); ++ ret = rk_hdptx_phy_consumer_get(hdptx, rate); ++ if (ret) ++ return ret; ++ ++ ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); ++ if (ret) ++ rk_hdptx_phy_consumer_put(hdptx, true); ++ ++ return ret; + } + + static int rk_hdptx_phy_power_off(struct phy *phy) + { + struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); +- u32 val; +- int ret; + +- ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); +- if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) +- rk_hdptx_phy_disable(hdptx); +- +- return ret; ++ return rk_hdptx_phy_consumer_put(hdptx, false); + } + + static const struct phy_ops rk_hdptx_phy_ops = { +@@ -893,6 +951,99 @@ static const struct phy_ops rk_hdptx_phy_ops = { + .owner = THIS_MODULE, + }; + ++static struct rk_hdptx_phy *to_rk_hdptx_phy(struct clk_hw *hw) ++{ ++ return container_of(hw, struct rk_hdptx_phy, hw); ++} ++ ++static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw) ++{ ++ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); ++ ++ return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate / 100); ++} ++ ++static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw) ++{ ++ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); ++ ++ rk_hdptx_phy_consumer_put(hdptx, true); ++} ++ ++static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); ++ ++ return hdptx->rate; ++} ++ ++static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ u32 bit_rate = rate / 100; ++ int i; ++ ++ if (rate > HDMI20_MAX_RATE) ++ return rate; ++ ++ for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) ++ if (bit_rate == ropll_tmds_cfg[i].bit_rate) ++ break; ++ ++ if (i == ARRAY_SIZE(ropll_tmds_cfg) && ++ !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL)) ++ return -EINVAL; ++ ++ return rate; ++} ++ ++static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); ++ ++ return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100); ++} ++ ++static const struct clk_ops hdptx_phy_clk_ops = { ++ .prepare = rk_hdptx_phy_clk_prepare, ++ .unprepare = rk_hdptx_phy_clk_unprepare, ++ .recalc_rate = rk_hdptx_phy_clk_recalc_rate, ++ .round_rate = rk_hdptx_phy_clk_round_rate, ++ .set_rate = rk_hdptx_phy_clk_set_rate, ++}; ++ ++static int rk_hdptx_phy_clk_register(struct rk_hdptx_phy *hdptx) ++{ ++ struct device *dev = hdptx->dev; ++ const char *name, *pname; ++ struct clk *refclk; ++ int ret, id; ++ ++ refclk = devm_clk_get(dev, "ref"); ++ if (IS_ERR(refclk)) ++ return dev_err_probe(dev, PTR_ERR(refclk), ++ "Failed to get ref clock\n"); ++ ++ id = of_alias_get_id(dev->of_node, "hdptxphy"); ++ name = id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; ++ pname = __clk_get_name(refclk); ++ ++ hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops, ++ CLK_GET_RATE_NOCACHE); ++ ++ ret = devm_clk_hw_register(dev, &hdptx->hw); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to register clock\n"); ++ ++ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &hdptx->hw); ++ if (ret) ++ return dev_err_probe(dev, ret, ++ "Failed to register clk provider\n"); ++ return 0; ++} ++ + static int rk_hdptx_phy_runtime_suspend(struct device *dev) + { + struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev); +@@ -987,7 +1138,7 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) + reset_control_deassert(hdptx->rsts[RST_CMN].rstc); + reset_control_deassert(hdptx->rsts[RST_INIT].rstc); + +- return 0; ++ return rk_hdptx_phy_clk_register(hdptx); + } + + static const struct dev_pm_ops rk_hdptx_phy_pm_ops = { +-- +2.45.2 + diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0132-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch similarity index 91% rename from patch/kernel/archive/rockchip-rk3588-6.11/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch rename to patch/kernel/archive/rockchip-rk3588-6.11/0132-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch index edcf535b2..29d720837 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0132-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch @@ -1,7 +1,8 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 07fd1529770701e8c18d9030cd70344b8e2472a5 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Mon, 5 Feb 2024 01:38:48 +0200 -Subject: phy: phy-rockchip-samsung-hdptx: Add FRL & EARC support +Subject: [PATCH 2/2] [WIP] phy: phy-rockchip-samsung-hdptx: Add FRL & EARC + support For upstreaming, this requires extending the standard PHY API to support HDMI configuration options [1]. @@ -10,37 +11,40 @@ Currently, the bus_width PHY attribute is used to pass clock rate and flags for 10-bit color depth, FRL and EARC. This is done by the HDMI bridge driver via phy_set_bus_width(). -[1]: https://lore.kernel.org/all/59d5595a24bbcca897e814440179fa2caf3dff38.1707040881.git.Sandor.yu@nxp.com/ +[1]: https://lore.kernel.org/all/20240306101625.795732-3-alexander.stein@ew.tq-group.com/ Signed-off-by: Cristian Ciocaltea --- - drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 434 +++++++++- - 1 file changed, 431 insertions(+), 3 deletions(-) + .../phy/rockchip/phy-rockchip-samsung-hdptx.c | 428 +++++++++++++++++- + 1 file changed, 426 insertions(+), 2 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c -index 111111111111..222222222222 100644 +index 9f084697dd05..45db96be3f64 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c -@@ -190,6 +190,12 @@ - #define LN3_TX_SER_RATE_SEL_HBR2 BIT(3) +@@ -193,6 +193,10 @@ #define LN3_TX_SER_RATE_SEL_HBR3 BIT(2) -+#define HDMI20_MAX_RATE 600000000 + #define HDMI20_MAX_RATE 600000000 +#define DATA_RATE_MASK 0xFFFFFFF +#define COLOR_DEPTH_MASK BIT(31) +#define HDMI_MODE_MASK BIT(30) +#define HDMI_EARC_MASK BIT(29) -+ + struct lcpll_config { u32 bit_rate; - u8 lcvco_mode_en; -@@ -272,6 +278,25 @@ struct rk_hdptx_phy { +@@ -276,6 +280,7 @@ struct rk_hdptx_phy { struct clk_bulk_data *clks; int nr_clks; struct reset_control_bulk_data rsts[RST_MAX]; + bool earc_en; -+}; -+ + + /* clk provider */ + struct clk_hw hw; +@@ -284,6 +289,24 @@ struct rk_hdptx_phy { + atomic_t usage_count; + }; + +static const struct lcpll_config lcpll_cfg[] = { + { 48000000, 1, 0, 0, 0x7d, 0x7d, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, + 0, 0x13, 0x18, 1, 0, 0x20, 0x0c, 1, 0, }, @@ -57,10 +61,12 @@ index 111111111111..222222222222 100644 + 0, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, + { 9000000, 0x7d, 0x7d, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, + 0, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, - }; - ++}; ++ static const struct ropll_config ropll_tmds_cfg[] = { -@@ -449,6 +474,73 @@ static const struct reg_sequence rk_hdtpx_tmds_cmn_init_seq[] = { + { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, + 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, +@@ -459,6 +482,73 @@ static const struct reg_sequence rk_hdtpx_tmds_cmn_init_seq[] = { REG_SEQ0(CMN_REG(009b), 0x00), }; @@ -134,7 +140,7 @@ index 111111111111..222222222222 100644 static const struct reg_sequence rk_hdtpx_common_sb_init_seq[] = { REG_SEQ0(SB_REG(0114), 0x00), REG_SEQ0(SB_REG(0115), 0x00), -@@ -472,6 +564,17 @@ static const struct reg_sequence rk_hdtpx_tmds_lntop_lowbr_seq[] = { +@@ -482,6 +572,17 @@ static const struct reg_sequence rk_hdtpx_tmds_lntop_lowbr_seq[] = { REG_SEQ0(LNTOP_REG(0205), 0x1f), }; @@ -152,7 +158,7 @@ index 111111111111..222222222222 100644 static const struct reg_sequence rk_hdtpx_common_lane_init_seq[] = { REG_SEQ0(LANE_REG(0303), 0x0c), REG_SEQ0(LANE_REG(0307), 0x20), -@@ -550,6 +653,40 @@ static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = { +@@ -560,6 +661,40 @@ static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = { REG_SEQ0(LANE_REG(0606), 0x1c), }; @@ -193,7 +199,7 @@ index 111111111111..222222222222 100644 static bool rk_hdptx_phy_is_rw_reg(struct device *dev, unsigned int reg) { switch (reg) { -@@ -651,6 +788,47 @@ static int rk_hdptx_post_enable_pll(struct rk_hdptx_phy *hdptx) +@@ -661,6 +796,47 @@ static int rk_hdptx_post_enable_pll(struct rk_hdptx_phy *hdptx) return 0; } @@ -241,7 +247,7 @@ index 111111111111..222222222222 100644 static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx) { u32 val; -@@ -680,6 +858,99 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx) +@@ -690,6 +866,99 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx) regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); } @@ -341,7 +347,7 @@ index 111111111111..222222222222 100644 static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate, struct ropll_config *cfg) { -@@ -755,9 +1026,13 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate, +@@ -765,9 +1034,13 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate, static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, unsigned int rate) { @@ -354,9 +360,9 @@ index 111111111111..222222222222 100644 + if (color_depth) + rate = rate * 10 / 8; - for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) - if (rate == ropll_tmds_cfg[i].bit_rate) { -@@ -813,6 +1088,9 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, + hdptx->rate = rate * 100; + +@@ -825,6 +1098,9 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK, FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv)); @@ -366,7 +372,7 @@ index 111111111111..222222222222 100644 regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN, PLL_PCG_CLK_EN); -@@ -853,9 +1131,146 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, +@@ -852,9 +1128,146 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq); rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lane_init_seq); @@ -510,10 +516,10 @@ index 111111111111..222222222222 100644 + return rk_hdptx_post_power_up(hdptx); +} + - static int rk_hdptx_phy_power_on(struct phy *phy) + static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx, + unsigned int rate) { - struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); -@@ -865,7 +1280,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy) +@@ -922,11 +1335,22 @@ static int rk_hdptx_phy_power_on(struct phy *phy) * from the HDMI bridge driver until phy_configure_opts_hdmi * becomes available in the PHY API. */ @@ -522,11 +528,7 @@ index 111111111111..222222222222 100644 dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n", __func__, bus_width, rate); -@@ -876,7 +1291,20 @@ static int rk_hdptx_phy_power_on(struct phy *phy) - return ret; - } -- ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); + if (bus_width & HDMI_EARC_MASK) + hdptx->earc_en = true; + else @@ -534,16 +536,13 @@ index 111111111111..222222222222 100644 + + if (bus_width & HDMI_MODE_MASK) { + if (rate > 24000000) -+ ret = rk_hdptx_lcpll_frl_mode_config(hdptx, bus_width); -+ else -+ ret = rk_hdptx_ropll_frl_mode_config(hdptx, bus_width); -+ } else { -+ ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); ++ return rk_hdptx_lcpll_frl_mode_config(hdptx, bus_width); ++ return rk_hdptx_ropll_frl_mode_config(hdptx, bus_width); + } + + ret = rk_hdptx_phy_consumer_get(hdptx, rate); if (ret) - pm_runtime_put(hdptx->dev); - + return ret; -- -Armbian +2.45.2 diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0133-drm-rockchip-vop2-Improve-display-modes-handling.patch similarity index 93% rename from patch/kernel/archive/rockchip-rk3588-6.11/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch rename to patch/kernel/archive/rockchip-rk3588-6.11/0133-drm-rockchip-vop2-Improve-display-modes-handling.patch index ca6f5d4b6..f7fb7fb51 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0133-drm-rockchip-vop2-Improve-display-modes-handling.patch @@ -1,7 +1,45 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 511586733f05f9d62c86a7f077d0a8104a9e1e01 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Wed, 27 Mar 2024 20:36:15 +0200 +Subject: [PATCH 1/2] [WIP] dt-bindings: display: rockchip-drm: Add optional + clocks property + +Allow using the clock provided by HDMI0 PHY PLL to improve HDMI output +support on RK3588 SoC. + +Signed-off-by: Cristian Ciocaltea +--- + .../bindings/display/rockchip/rockchip-drm.yaml | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-drm.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-drm.yaml +index a8d18a37cb23..9d000760dd6e 100644 +--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-drm.yaml ++++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-drm.yaml +@@ -28,6 +28,14 @@ properties: + of vop devices. vop definitions as defined in + Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml + ++ clocks: ++ maxItems: 1 ++ description: Optional clock provided by HDMI0 PLL ++ ++ clock-names: ++ items: ++ - const: hdmi0_phy_pll ++ + required: + - compatible + - ports +-- +2.45.2 + + +From de09dc535799458e6be99ab62e86fd02525bbfe4 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Fri, 3 Nov 2023 19:58:02 +0200 -Subject: drm/rockchip: vop2: Improve display modes handling on rk3588 +Subject: [PATCH 2/2] [WIP] drm/rockchip: vop2: Improve display modes handling + on rk3588 The initial vop2 support for rk3588 in mainline is not able to handle all display modes supported by connected displays, e.g. @@ -15,11 +53,11 @@ Improve HDMI0 clocking in order to support the additional display modes. Fixes: 5a028e8f062f ("drm/rockchip: vop2: Add support for rk3588") Signed-off-by: Cristian Ciocaltea --- - drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 553 +++++++++- + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 553 ++++++++++++++++++- 1 file changed, 552 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c -index 111111111111..222222222222 100644 +index 9873172e3fd3..629f60184f66 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -5,6 +5,8 @@ @@ -675,5 +713,5 @@ index 111111111111..222222222222 100644 if (ret >= 0) { vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc, -- -Armbian +2.45.2 diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0134-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0134-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch new file mode 100644 index 000000000..d48e58fcb --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0134-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch @@ -0,0 +1,2665 @@ +From ae26670c06f61c28cb7c276274404e2897f73634 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Thu, 11 Jul 2024 13:57:34 +0300 +Subject: [PATCH 1/7] drm/bridge-connector: Fix double free in error handling + paths + +The recent switch to drmm allocation in drm_bridge_connector_init() may +cause double free on bridge_connector in some of the error handling +paths. + +Drop the explicit kfree() calls on bridge_connector. + +Fixes: c12907be57b1 ("drm/bridge-connector: switch to using drmm allocations") +Signed-off-by: Cristian Ciocaltea +--- + drivers/gpu/drm/drm_bridge_connector.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c +index 0869b663f17e..a4fbf1eb7ac5 100644 +--- a/drivers/gpu/drm/drm_bridge_connector.c ++++ b/drivers/gpu/drm/drm_bridge_connector.c +@@ -443,10 +443,8 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, + panel_bridge = bridge; + } + +- if (connector_type == DRM_MODE_CONNECTOR_Unknown) { +- kfree(bridge_connector); ++ if (connector_type == DRM_MODE_CONNECTOR_Unknown) + return ERR_PTR(-EINVAL); +- } + + if (bridge_connector->bridge_hdmi) + ret = drmm_connector_hdmi_init(drm, connector, +@@ -461,10 +459,8 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, + ret = drmm_connector_init(drm, connector, + &drm_bridge_connector_funcs, + connector_type, ddc); +- if (ret) { +- kfree(bridge_connector); ++ if (ret) + return ERR_PTR(ret); +- } + + drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs); + +-- +2.45.2 + + +From 10b2bc0b5dd7ea1224f04567022dedc3a1830ca0 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Fri, 26 Jul 2024 02:54:52 +0300 +Subject: [PATCH 2/7] dt-bindings: display: bridge: Add schema for Synopsys DW + HDMI QP TX IP + +Add dt-binding schema containing the common properties for the Synopsys +DesignWare HDMI QP TX controller. + +Note this is not a full dt-binding specification, but is meant to be +referenced by platform-specific bindings for this IP core. + +Signed-off-by: Cristian Ciocaltea +--- + .../display/bridge/synopsys,dw-hdmi-qp.yaml | 66 +++++++++++++++++++ + 1 file changed, 66 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi-qp.yaml + +diff --git a/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi-qp.yaml b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi-qp.yaml +new file mode 100644 +index 000000000000..d8aee12b121d +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/bridge/synopsys,dw-hdmi-qp.yaml +@@ -0,0 +1,66 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/display/bridge/synopsys,dw-hdmi-qp.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Common Properties for Synopsys DesignWare HDMI QP TX Controller IP ++ ++maintainers: ++ - Cristian Ciocaltea ++ ++description: | ++ This document defines device tree properties for the Synopsys DesignWare ++ HDMI 2.1 Quad-Pixel (QP) TX controller IP core. ++ It doesn't constitute a device tree binding specification by itself, but ++ is meant to be referenced by platform-specific device tree bindings. ++ ++ When referenced from platform device tree bindings, the properties defined ++ in this document are defined as follows. The platform device tree bindings ++ are responsible for defining whether each property is required or optional. ++ ++properties: ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ minItems: 4 ++ maxItems: 6 ++ items: ++ - description: Peripheral/APB bus clock ++ - description: EARC RX biphase clock ++ - description: Reference clock ++ - description: Audio interface clock ++ additionalItems: true ++ ++ clock-names: ++ minItems: 4 ++ maxItems: 6 ++ items: ++ - const: pclk ++ - const: earc ++ - const: ref ++ - const: aud ++ additionalItems: true ++ ++ interrupts: ++ minItems: 4 ++ maxItems: 5 ++ items: ++ - description: AVP Unit interrupt ++ - description: CEC interrupt ++ - description: eARC RX interrupt ++ - description: Main Unit interrupt ++ additionalItems: true ++ ++ interrupt-names: ++ minItems: 4 ++ maxItems: 5 ++ items: ++ - const: avp ++ - const: cec ++ - const: earc ++ - const: main ++ additionalItems: true ++ ++additionalProperties: true +-- +2.45.2 + + +From 61b5f6860e545fb8b76c4d011af8674122d13a49 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Mon, 20 May 2024 14:49:50 +0300 +Subject: [PATCH 3/7] drm/bridge: synopsys: Add DW HDMI QP TX Controller driver + +The Synopsys DesignWare HDMI 2.1 Quad-Pixel (QP) TX Controller supports +the following features, among others: + +* Fixed Rate Link (FRL) +* Display Stream Compression (DSC) +* 4K@120Hz and 8K@60Hz video modes +* Variable Refresh Rate (VRR) including Quick Media Switching (QMS), aka + Cinema VRR +* Fast Vactive (FVA), aka Quick Frame Transport (QFT) +* SCDC I2C DDC access +* TMDS Scrambler enabling 2160p@60Hz with RGB/YCbCr4:4:4 +* YCbCr4:2:0 enabling 2160p@60Hz at lower HDMI link speeds +* Multi-stream audio +* Enhanced Audio Return Channel (EARC) + +Add driver to enable basic support, i.e. RGB output up to 4K@60Hz, +without audio, CEC or any HDMI 2.1 specific features. + +Co-developed-by: Algea Cao +Signed-off-by: Algea Cao +Signed-off-by: Cristian Ciocaltea +--- + drivers/gpu/drm/bridge/synopsys/Kconfig | 8 + + drivers/gpu/drm/bridge/synopsys/Makefile | 2 + + drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 748 +++++++++++++++++ + drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h | 834 +++++++++++++++++++ + include/drm/bridge/dw_hdmi_qp.h | 37 + + 5 files changed, 1629 insertions(+) + create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c + create mode 100644 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h + create mode 100644 include/drm/bridge/dw_hdmi_qp.h + +diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig +index 15fc182d05ef..ca416dab156d 100644 +--- a/drivers/gpu/drm/bridge/synopsys/Kconfig ++++ b/drivers/gpu/drm/bridge/synopsys/Kconfig +@@ -46,6 +46,14 @@ config DRM_DW_HDMI_CEC + Support the CE interface which is part of the Synopsys + Designware HDMI block. + ++config DRM_DW_HDMI_QP ++ tristate ++ select DRM_DISPLAY_HDMI_HELPER ++ select DRM_DISPLAY_HDMI_STATE_HELPER ++ select DRM_DISPLAY_HELPER ++ select DRM_KMS_HELPER ++ select REGMAP_MMIO ++ + config DRM_DW_MIPI_DSI + tristate + select DRM_KMS_HELPER +diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile +index ce715562e9e5..9869d9651ed1 100644 +--- a/drivers/gpu/drm/bridge/synopsys/Makefile ++++ b/drivers/gpu/drm/bridge/synopsys/Makefile +@@ -5,4 +5,6 @@ obj-$(CONFIG_DRM_DW_HDMI_GP_AUDIO) += dw-hdmi-gp-audio.o + obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o + obj-$(CONFIG_DRM_DW_HDMI_CEC) += dw-hdmi-cec.o + ++obj-$(CONFIG_DRM_DW_HDMI_QP) += dw-hdmi-qp.o ++ + obj-$(CONFIG_DRM_DW_MIPI_DSI) += dw-mipi-dsi.o +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +new file mode 100644 +index 000000000000..6c144249e610 +--- /dev/null ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +@@ -0,0 +1,748 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd. ++ * Copyright (c) 2024 Collabora Ltd. ++ * ++ * Author: Algea Cao ++ * Author: Cristian Ciocaltea ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "dw-hdmi-qp.h" ++ ++#define DDC_CI_ADDR 0x37 ++#define DDC_SEGMENT_ADDR 0x30 ++ ++#define SCDC_MIN_SOURCE_VERSION 0x1 ++ ++#define HDMI14_MAX_TMDSCLK 340000000 ++ ++struct dw_hdmi_qp_i2c { ++ struct i2c_adapter adap; ++ ++ struct mutex lock; /* used to serialize data transfers */ ++ struct completion cmp; ++ u8 stat; ++ ++ u8 slave_reg; ++ bool is_regaddr; ++ bool is_segment; ++}; ++ ++struct dw_hdmi_qp { ++ struct drm_bridge bridge; ++ ++ struct device *dev; ++ struct dw_hdmi_qp_i2c *i2c; ++ ++ struct { ++ const struct dw_hdmi_qp_phy_ops *ops; ++ void *data; ++ } phy; ++ ++ struct clk *ref_clk; ++ ++ struct drm_connector *curr_conn; ++ unsigned long long pix_clock; ++ ++ struct regmap *regm; ++}; ++ ++/* Filter out invalid setups to avoid configuring SCDC and scrambling */ ++static bool dw_hdmi_qp_support_scdc(struct dw_hdmi_qp *hdmi, ++ const struct drm_display_info *display) ++{ ++ /* Disable if no DDC bus */ ++ if (!hdmi->bridge.ddc) ++ return false; ++ ++ /* Disable if SCDC is not supported, or if an HF-VSDB block is absent */ ++ if (!display->hdmi.scdc.supported || ++ !display->hdmi.scdc.scrambling.supported) ++ return false; ++ ++ /* ++ * Disable if display only support low TMDS rates and scrambling ++ * for low rates is not supported either ++ */ ++ if (!display->hdmi.scdc.scrambling.low_rates && ++ display->max_tmds_clock <= 340000) ++ return false; ++ ++ return true; ++} ++ ++int dw_hdmi_qp_set_refclk_rate(struct dw_hdmi_qp *hdmi, unsigned long rate) ++{ ++ return clk_set_rate(hdmi->ref_clk, rate); ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_qp_set_refclk_rate); ++ ++/* ++ * HDMI2.0 Specifies the following procedure for High TMDS Bit Rates: ++ * - The Source shall suspend transmission of the TMDS clock and data ++ * ++ * - The Source shall write to the TMDS_Bit_Clock_Ratio bit to change it ++ * from a 0 to a 1 or from a 1 to a 0 ++ * ++ * - The Source shall allow a minimum of 1 ms and a maximum of 100 ms from ++ * the time the TMDS_Bit_Clock_Ratio bit is written until resuming ++ * transmission of TMDS clock and data ++ * ++ * To respect the 100ms max delay, the dw_hdmi_qp_set_high_tmds_clock_ratio() ++ * helper should be called right before enabling the TMDS Clock and Data in ++ * the PHY configuration callback. ++ */ ++void dw_hdmi_qp_set_high_tmds_clock_ratio(struct dw_hdmi_qp *hdmi, ++ const struct drm_display_info *display) ++{ ++ bool set; ++ ++ if (hdmi->curr_conn && dw_hdmi_qp_support_scdc(hdmi, display)) { ++ set = (hdmi->pix_clock > HDMI14_MAX_TMDSCLK); ++ drm_scdc_set_high_tmds_clock_ratio(hdmi->curr_conn, set); ++ } ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_qp_set_high_tmds_clock_ratio); ++ ++static void dw_hdmi_qp_write(struct dw_hdmi_qp *hdmi, unsigned int val, ++ int offset) ++{ ++ regmap_write(hdmi->regm, offset, val); ++} ++ ++static unsigned int dw_hdmi_qp_read(struct dw_hdmi_qp *hdmi, int offset) ++{ ++ unsigned int val = 0; ++ ++ regmap_read(hdmi->regm, offset, &val); ++ ++ return val; ++} ++ ++static void dw_hdmi_qp_mod(struct dw_hdmi_qp *hdmi, unsigned int data, ++ unsigned int mask, unsigned int reg) ++{ ++ regmap_update_bits(hdmi->regm, reg, mask, data); ++} ++ ++static int dw_hdmi_qp_i2c_read(struct dw_hdmi_qp *hdmi, ++ unsigned char *buf, unsigned int length) ++{ ++ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; ++ int stat; ++ ++ if (!i2c->is_regaddr) { ++ dev_dbg(hdmi->dev, "set read register address to 0\n"); ++ i2c->slave_reg = 0x00; ++ i2c->is_regaddr = true; ++ } ++ ++ while (length--) { ++ reinit_completion(&i2c->cmp); ++ ++ dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, ++ I2CM_INTERFACE_CONTROL0); ++ ++ if (i2c->is_segment) ++ dw_hdmi_qp_mod(hdmi, I2CM_EXT_READ, I2CM_WR_MASK, ++ I2CM_INTERFACE_CONTROL0); ++ else ++ dw_hdmi_qp_mod(hdmi, I2CM_FM_READ, I2CM_WR_MASK, ++ I2CM_INTERFACE_CONTROL0); ++ ++ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); ++ if (!stat) { ++ dev_err(hdmi->dev, "i2c read timed out\n"); ++ dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); ++ return -EAGAIN; ++ } ++ ++ /* Check for error condition on the bus */ ++ if (i2c->stat & I2CM_NACK_RCVD_IRQ) { ++ dev_err(hdmi->dev, "i2c read error\n"); ++ dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); ++ return -EIO; ++ } ++ ++ *buf++ = dw_hdmi_qp_read(hdmi, I2CM_INTERFACE_RDDATA_0_3) & 0xff; ++ dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0); ++ } ++ ++ i2c->is_segment = false; ++ ++ return 0; ++} ++ ++static int dw_hdmi_qp_i2c_write(struct dw_hdmi_qp *hdmi, ++ unsigned char *buf, unsigned int length) ++{ ++ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; ++ int stat; ++ ++ if (!i2c->is_regaddr) { ++ /* Use the first write byte as register address */ ++ i2c->slave_reg = buf[0]; ++ length--; ++ buf++; ++ i2c->is_regaddr = true; ++ } ++ ++ while (length--) { ++ reinit_completion(&i2c->cmp); ++ ++ dw_hdmi_qp_write(hdmi, *buf++, I2CM_INTERFACE_WRDATA_0_3); ++ dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, ++ I2CM_INTERFACE_CONTROL0); ++ dw_hdmi_qp_mod(hdmi, I2CM_FM_WRITE, I2CM_WR_MASK, ++ I2CM_INTERFACE_CONTROL0); ++ ++ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); ++ if (!stat) { ++ dev_err(hdmi->dev, "i2c write time out!\n"); ++ dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); ++ return -EAGAIN; ++ } ++ ++ /* Check for error condition on the bus */ ++ if (i2c->stat & I2CM_NACK_RCVD_IRQ) { ++ dev_err(hdmi->dev, "i2c write nack!\n"); ++ dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); ++ return -EIO; ++ } ++ ++ dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0); ++ } ++ ++ return 0; ++} ++ ++static int dw_hdmi_qp_i2c_xfer(struct i2c_adapter *adap, ++ struct i2c_msg *msgs, int num) ++{ ++ struct dw_hdmi_qp *hdmi = i2c_get_adapdata(adap); ++ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; ++ u8 addr = msgs[0].addr; ++ int i, ret = 0; ++ ++ if (addr == DDC_CI_ADDR) ++ /* ++ * The internal I2C controller does not support the multi-byte ++ * read and write operations needed for DDC/CI. ++ * FIXME: Blacklist the DDC/CI address until we filter out ++ * unsupported I2C operations. ++ */ ++ return -EOPNOTSUPP; ++ ++ for (i = 0; i < num; i++) { ++ if (msgs[i].len == 0) { ++ dev_err(hdmi->dev, ++ "unsupported transfer %d/%d, no data\n", ++ i + 1, num); ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ mutex_lock(&i2c->lock); ++ ++ /* Unmute DONE and ERROR interrupts */ ++ dw_hdmi_qp_mod(hdmi, I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N, ++ I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N, ++ MAINUNIT_1_INT_MASK_N); ++ ++ /* Set slave device address taken from the first I2C message */ ++ if (addr == DDC_SEGMENT_ADDR && msgs[0].len == 1) ++ addr = DDC_ADDR; ++ ++ dw_hdmi_qp_mod(hdmi, addr << 5, I2CM_SLVADDR, I2CM_INTERFACE_CONTROL0); ++ ++ /* Set slave device register address on transfer */ ++ i2c->is_regaddr = false; ++ ++ /* Set segment pointer for I2C extended read mode operation */ ++ i2c->is_segment = false; ++ ++ for (i = 0; i < num; i++) { ++ if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) { ++ i2c->is_segment = true; ++ dw_hdmi_qp_mod(hdmi, DDC_SEGMENT_ADDR, I2CM_SEG_ADDR, ++ I2CM_INTERFACE_CONTROL1); ++ dw_hdmi_qp_mod(hdmi, *msgs[i].buf << 7, I2CM_SEG_PTR, ++ I2CM_INTERFACE_CONTROL1); ++ } else { ++ if (msgs[i].flags & I2C_M_RD) ++ ret = dw_hdmi_qp_i2c_read(hdmi, msgs[i].buf, ++ msgs[i].len); ++ else ++ ret = dw_hdmi_qp_i2c_write(hdmi, msgs[i].buf, ++ msgs[i].len); ++ } ++ if (ret < 0) ++ break; ++ } ++ ++ if (!ret) ++ ret = num; ++ ++ /* Mute DONE and ERROR interrupts */ ++ dw_hdmi_qp_mod(hdmi, 0, I2CM_OP_DONE_MASK_N | I2CM_NACK_RCVD_MASK_N, ++ MAINUNIT_1_INT_MASK_N); ++ ++ mutex_unlock(&i2c->lock); ++ ++ return ret; ++} ++ ++static u32 dw_hdmi_qp_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm dw_hdmi_qp_algorithm = { ++ .master_xfer = dw_hdmi_qp_i2c_xfer, ++ .functionality = dw_hdmi_qp_i2c_func, ++}; ++ ++static struct i2c_adapter *dw_hdmi_qp_i2c_adapter(struct dw_hdmi_qp *hdmi) ++{ ++ struct dw_hdmi_qp_i2c *i2c; ++ struct i2c_adapter *adap; ++ int ret; ++ ++ i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL); ++ if (!i2c) ++ return ERR_PTR(-ENOMEM); ++ ++ mutex_init(&i2c->lock); ++ init_completion(&i2c->cmp); ++ ++ adap = &i2c->adap; ++ adap->owner = THIS_MODULE; ++ adap->dev.parent = hdmi->dev; ++ adap->algo = &dw_hdmi_qp_algorithm; ++ strscpy(adap->name, "DesignWare HDMI QP", sizeof(adap->name)); ++ ++ i2c_set_adapdata(adap, hdmi); ++ ++ ret = devm_i2c_add_adapter(hdmi->dev, adap); ++ if (ret) { ++ dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name); ++ devm_kfree(hdmi->dev, i2c); ++ return ERR_PTR(ret); ++ } ++ ++ hdmi->i2c = i2c; ++ dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); ++ ++ return adap; ++} ++ ++static int dw_hdmi_qp_config_avi_infoframe(struct dw_hdmi_qp *hdmi, ++ const u8 *buffer, size_t len) ++{ ++ u32 val, i, j; ++ ++ if (len != HDMI_INFOFRAME_SIZE(AVI)) { ++ dev_err(hdmi->dev, "failed to configure avi infoframe\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * DW HDMI QP IP uses a different byte format from standard AVI info ++ * frames, though generally the bits are in the correct bytes. ++ */ ++ val = buffer[1] << 8 | buffer[2] << 16; ++ dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS0); ++ ++ for (i = 0; i < 4; i++) { ++ for (j = 0; j < 4; j++) { ++ if (i * 4 + j >= 14) ++ break; ++ if (!j) ++ val = buffer[i * 4 + j + 3]; ++ val |= buffer[i * 4 + j + 3] << (8 * j); ++ } ++ ++ dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS1 + i * 4); ++ } ++ ++ dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_FIELDRATE, PKTSCHED_PKT_CONFIG1); ++ ++ dw_hdmi_qp_mod(hdmi, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, ++ PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, PKTSCHED_PKT_EN); ++ ++ return 0; ++} ++ ++static int dw_hdmi_qp_config_drm_infoframe(struct dw_hdmi_qp *hdmi, ++ const u8 *buffer, size_t len) ++{ ++ u32 val, i; ++ ++ if (len != HDMI_INFOFRAME_SIZE(DRM)) { ++ dev_err(hdmi->dev, "failed to configure drm infoframe\n"); ++ return -EINVAL; ++ } ++ ++ dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN); ++ ++ val = buffer[1] << 8 | buffer[2] << 16; ++ dw_hdmi_qp_write(hdmi, val, PKT_DRMI_CONTENTS0); ++ ++ for (i = 0; i <= buffer[2]; i++) { ++ if (i % 4 == 0) ++ val = buffer[3 + i]; ++ val |= buffer[3 + i] << ((i % 4) * 8); ++ ++ if ((i % 4 == 3) || i == buffer[2]) ++ dw_hdmi_qp_write(hdmi, val, ++ PKT_DRMI_CONTENTS1 + ((i / 4) * 4)); ++ } ++ ++ dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_FIELDRATE, PKTSCHED_PKT_CONFIG1); ++ dw_hdmi_qp_mod(hdmi, PKTSCHED_DRMI_TX_EN, PKTSCHED_DRMI_TX_EN, ++ PKTSCHED_PKT_EN); ++ ++ return 0; ++} ++ ++static void dw_hdmi_qp_setup(struct dw_hdmi_qp *hdmi, ++ struct drm_connector *connector) ++{ ++ bool scramb; ++ u8 ver; ++ ++ if (!connector->display_info.is_hdmi) { ++ dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); ++ ++ dw_hdmi_qp_mod(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, ++ HDCP2LOGIC_CONFIG0); ++ dw_hdmi_qp_mod(hdmi, OPMODE_DVI, OPMODE_DVI, LINK_CONFIG0); ++ ++ return; ++ } ++ ++ dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); ++ ++ dw_hdmi_qp_mod(hdmi, 0, OPMODE_DVI, LINK_CONFIG0); ++ dw_hdmi_qp_mod(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0); ++ ++ scramb = (hdmi->pix_clock > HDMI14_MAX_TMDSCLK); ++ ++ if (dw_hdmi_qp_support_scdc(hdmi, &connector->display_info)) { ++ if (scramb) { ++ drm_scdc_readb(hdmi->bridge.ddc, SCDC_SINK_VERSION, &ver); ++ drm_scdc_writeb(hdmi->bridge.ddc, SCDC_SOURCE_VERSION, ++ min_t(u8, ver, SCDC_MIN_SOURCE_VERSION)); ++ } ++ ++ drm_scdc_set_high_tmds_clock_ratio(connector, scramb); ++ drm_scdc_set_scrambling(connector, scramb); ++ } ++ ++ dw_hdmi_qp_write(hdmi, scramb, SCRAMB_CONFIG0); ++} ++ ++static int dw_hdmi_qp_bridge_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 dw_hdmi_qp *hdmi = bridge->driver_private; ++ int ret; ++ ++ ret = drm_atomic_helper_connector_hdmi_check(conn_state->connector, ++ conn_state->state); ++ if (ret) ++ dev_dbg(hdmi->dev, "%s failed: %d\n", __func__, ret); ++ ++ return ret; ++} ++ ++static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ struct drm_atomic_state *state = old_state->base.state; ++ struct drm_connector *connector; ++ struct drm_connector_state *conn_state; ++ ++ connector = drm_atomic_get_new_connector_for_encoder(state, ++ bridge->encoder); ++ conn_state = drm_atomic_get_new_connector_state(state, connector); ++ ++ hdmi->pix_clock = conn_state->hdmi.tmds_char_rate; ++ hdmi->curr_conn = connector; ++ ++ hdmi->phy.ops->init(hdmi, hdmi->phy.data, &connector->display_info); ++ ++ dw_hdmi_qp_setup(hdmi, connector); ++ ++ drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); ++} ++ ++static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ ++ hdmi->curr_conn = NULL; ++ hdmi->phy.ops->disable(hdmi, hdmi->phy.data); ++} ++ ++static enum drm_connector_status ++dw_hdmi_qp_bridge_detect(struct drm_bridge *bridge) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ ++ return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); ++} ++ ++static const struct drm_edid * ++dw_hdmi_qp_bridge_edid_read(struct drm_bridge *bridge, ++ struct drm_connector *connector) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ const struct drm_edid *drm_edid; ++ ++ if (!bridge->ddc) ++ return NULL; ++ ++ drm_edid = drm_edid_read_ddc(connector, bridge->ddc); ++ if (!drm_edid) ++ dev_dbg(hdmi->dev, "failed to get edid\n"); ++ ++ return drm_edid; ++} ++ ++static int dw_hdmi_qp_bridge_clear_infoframe(struct drm_bridge *bridge, ++ enum hdmi_infoframe_type type) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ ++ switch (type) { ++ case HDMI_INFOFRAME_TYPE_AVI: ++ dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, ++ PKTSCHED_PKT_EN); ++ break; ++ ++ case HDMI_INFOFRAME_TYPE_DRM: ++ dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN); ++ break; ++ ++ default: ++ dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type); ++ } ++ ++ return 0; ++} ++ ++static int dw_hdmi_qp_bridge_write_infoframe(struct drm_bridge *bridge, ++ enum hdmi_infoframe_type type, ++ const u8 *buffer, size_t len) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ ++ dw_hdmi_qp_bridge_clear_infoframe(bridge, type); ++ ++ switch (type) { ++ case HDMI_INFOFRAME_TYPE_AVI: ++ return dw_hdmi_qp_config_avi_infoframe(hdmi, buffer, len); ++ ++ case HDMI_INFOFRAME_TYPE_DRM: ++ return dw_hdmi_qp_config_drm_infoframe(hdmi, buffer, len); ++ ++ default: ++ dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type); ++ return 0; ++ } ++} ++ ++static const struct drm_bridge_funcs dw_hdmi_qp_bridge_funcs = { ++ .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, ++ .atomic_check = dw_hdmi_qp_bridge_atomic_check, ++ .atomic_enable = dw_hdmi_qp_bridge_atomic_enable, ++ .atomic_disable = dw_hdmi_qp_bridge_atomic_disable, ++ .detect = dw_hdmi_qp_bridge_detect, ++ .edid_read = dw_hdmi_qp_bridge_edid_read, ++ .hdmi_clear_infoframe = dw_hdmi_qp_bridge_clear_infoframe, ++ .hdmi_write_infoframe = dw_hdmi_qp_bridge_write_infoframe, ++}; ++ ++static irqreturn_t dw_hdmi_qp_main_hardirq(int irq, void *dev_id) ++{ ++ struct dw_hdmi_qp *hdmi = dev_id; ++ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; ++ u32 stat; ++ ++ stat = dw_hdmi_qp_read(hdmi, MAINUNIT_1_INT_STATUS); ++ ++ i2c->stat = stat & (I2CM_OP_DONE_IRQ | I2CM_READ_REQUEST_IRQ | ++ I2CM_NACK_RCVD_IRQ); ++ ++ if (i2c->stat) { ++ dw_hdmi_qp_write(hdmi, i2c->stat, MAINUNIT_1_INT_CLEAR); ++ complete(&i2c->cmp); ++ } ++ ++ if (stat) ++ return IRQ_HANDLED; ++ ++ return IRQ_NONE; ++} ++ ++static const struct regmap_config dw_hdmi_qp_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = EARCRX_1_INT_FORCE, ++}; ++ ++static void dw_hdmi_qp_init_hw(struct dw_hdmi_qp *hdmi) ++{ ++ dw_hdmi_qp_write(hdmi, 0, MAINUNIT_0_INT_MASK_N); ++ dw_hdmi_qp_write(hdmi, 0, MAINUNIT_1_INT_MASK_N); ++ dw_hdmi_qp_write(hdmi, 428571429, TIMER_BASE_CONFIG0); ++ ++ /* Software reset */ ++ dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0); ++ ++ dw_hdmi_qp_write(hdmi, 0x085c085c, I2CM_FM_SCL_CONFIG0); ++ ++ dw_hdmi_qp_mod(hdmi, 0, I2CM_FM_EN, I2CM_INTERFACE_CONTROL0); ++ ++ /* Clear DONE and ERROR interrupts */ ++ dw_hdmi_qp_write(hdmi, I2CM_OP_DONE_CLEAR | I2CM_NACK_RCVD_CLEAR, ++ MAINUNIT_1_INT_CLEAR); ++ ++ if (hdmi->phy.ops->setup_hpd) ++ hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); ++} ++ ++struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, ++ struct drm_encoder *encoder, ++ const struct dw_hdmi_qp_plat_data *plat_data) ++{ ++ static const char * const clk_names[] = { ++ "pclk", "earc", "aud", "ref" /* keep "ref" last */ ++ }; ++ struct device *dev = &pdev->dev; ++ struct dw_hdmi_qp *hdmi; ++ void __iomem *regs; ++ struct clk *clk; ++ int irq, ret, i; ++ ++ if (!plat_data->phy_ops || !plat_data->phy_ops->init || ++ !plat_data->phy_ops->disable || !plat_data->phy_ops->read_hpd) { ++ dev_err(dev, "Missing platform PHY ops\n"); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); ++ if (!hdmi) ++ return ERR_PTR(-ENOMEM); ++ ++ hdmi->dev = dev; ++ ++ regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(regs)) ++ return regs; ++ ++ hdmi->regm = devm_regmap_init_mmio(dev, regs, &dw_hdmi_qp_regmap_config); ++ if (IS_ERR(hdmi->regm)) { ++ dev_err(dev, "Failed to configure regmap\n"); ++ return ERR_CAST(hdmi->regm); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(clk_names); i++) { ++ clk = devm_clk_get_enabled(hdmi->dev, clk_names[i]); ++ ++ if (IS_ERR(clk)) { ++ if (PTR_ERR(clk) != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get %s clock\n", ++ clk_names[i]); ++ return ERR_CAST(clk); ++ } ++ } ++ hdmi->ref_clk = clk; ++ ++ hdmi->phy.ops = plat_data->phy_ops; ++ hdmi->phy.data = plat_data->phy_data; ++ ++ dw_hdmi_qp_init_hw(hdmi); ++ ++ irq = platform_get_irq_byname(pdev, "main"); ++ if (irq < 0) ++ return ERR_PTR(irq); ++ ++ ret = devm_request_threaded_irq(dev, irq, ++ dw_hdmi_qp_main_hardirq, NULL, ++ IRQF_SHARED, dev_name(dev), hdmi); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ hdmi->bridge.driver_private = hdmi; ++ hdmi->bridge.funcs = &dw_hdmi_qp_bridge_funcs; ++ hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | ++ DRM_BRIDGE_OP_EDID | ++ DRM_BRIDGE_OP_HDMI | ++ DRM_BRIDGE_OP_HPD; ++ hdmi->bridge.of_node = pdev->dev.of_node; ++ hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; ++ hdmi->bridge.vendor = "Synopsys"; ++ hdmi->bridge.product = "DW HDMI QP TX"; ++ ++ hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi); ++ if (IS_ERR(hdmi->bridge.ddc)) ++ hdmi->bridge.ddc = NULL; ++ ++ ret = devm_drm_bridge_add(dev, &hdmi->bridge); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, ++ DRM_BRIDGE_ATTACH_NO_CONNECTOR); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ return hdmi; ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind); ++ ++void dw_hdmi_qp_unbind(struct dw_hdmi_qp *hdmi) ++{ ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_qp_unbind); ++ ++void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi) ++{ ++ dw_hdmi_qp_init_hw(hdmi); ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume); ++ ++MODULE_AUTHOR("Algea Cao "); ++MODULE_AUTHOR("Cristian Ciocaltea "); ++MODULE_DESCRIPTION("DW HDMI QP transmitter driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:dw-hdmi-qp"); +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h +new file mode 100644 +index 000000000000..2115b8ef0bd6 +--- /dev/null ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h +@@ -0,0 +1,834 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) Rockchip Electronics Co.Ltd ++ * Author: ++ * Algea Cao ++ */ ++#ifndef __DW_HDMI_QP_H__ ++#define __DW_HDMI_QP_H__ ++ ++#include ++ ++/* Main Unit Registers */ ++#define CORE_ID 0x0 ++#define VER_NUMBER 0x4 ++#define VER_TYPE 0x8 ++#define CONFIG_REG 0xc ++#define CONFIG_CEC BIT(28) ++#define CONFIG_AUD_UD BIT(23) ++#define CORE_TIMESTAMP_HHMM 0x14 ++#define CORE_TIMESTAMP_MMDD 0x18 ++#define CORE_TIMESTAMP_YYYY 0x1c ++/* Reset Manager Registers */ ++#define GLOBAL_SWRESET_REQUEST 0x40 ++#define EARCRX_CMDC_SWINIT_P BIT(27) ++#define AVP_DATAPATH_PACKET_AUDIO_SWINIT_P BIT(10) ++#define GLOBAL_SWDISABLE 0x44 ++#define CEC_SWDISABLE BIT(17) ++#define AVP_DATAPATH_PACKET_AUDIO_SWDISABLE BIT(10) ++#define AVP_DATAPATH_VIDEO_SWDISABLE BIT(6) ++#define RESET_MANAGER_CONFIG0 0x48 ++#define RESET_MANAGER_STATUS0 0x50 ++#define RESET_MANAGER_STATUS1 0x54 ++#define RESET_MANAGER_STATUS2 0x58 ++/* Timer Base Registers */ ++#define TIMER_BASE_CONFIG0 0x80 ++#define TIMER_BASE_STATUS0 0x84 ++/* CMU Registers */ ++#define CMU_CONFIG0 0xa0 ++#define CMU_CONFIG1 0xa4 ++#define CMU_CONFIG2 0xa8 ++#define CMU_CONFIG3 0xac ++#define CMU_STATUS 0xb0 ++#define DISPLAY_CLK_MONITOR 0x3f ++#define DISPLAY_CLK_LOCKED 0X15 ++#define EARC_BPCLK_OFF BIT(9) ++#define AUDCLK_OFF BIT(7) ++#define LINKQPCLK_OFF BIT(5) ++#define VIDQPCLK_OFF BIT(3) ++#define IPI_CLK_OFF BIT(1) ++#define CMU_IPI_CLK_FREQ 0xb4 ++#define CMU_VIDQPCLK_FREQ 0xb8 ++#define CMU_LINKQPCLK_FREQ 0xbc ++#define CMU_AUDQPCLK_FREQ 0xc0 ++#define CMU_EARC_BPCLK_FREQ 0xc4 ++/* I2CM Registers */ ++#define I2CM_SM_SCL_CONFIG0 0xe0 ++#define I2CM_FM_SCL_CONFIG0 0xe4 ++#define I2CM_CONFIG0 0xe8 ++#define I2CM_CONTROL0 0xec ++#define I2CM_STATUS0 0xf0 ++#define I2CM_INTERFACE_CONTROL0 0xf4 ++#define I2CM_ADDR 0xff000 ++#define I2CM_SLVADDR 0xfe0 ++#define I2CM_WR_MASK 0x1e ++#define I2CM_EXT_READ BIT(4) ++#define I2CM_SHORT_READ BIT(3) ++#define I2CM_FM_READ BIT(2) ++#define I2CM_FM_WRITE BIT(1) ++#define I2CM_FM_EN BIT(0) ++#define I2CM_INTERFACE_CONTROL1 0xf8 ++#define I2CM_SEG_PTR 0x7f80 ++#define I2CM_SEG_ADDR 0x7f ++#define I2CM_INTERFACE_WRDATA_0_3 0xfc ++#define I2CM_INTERFACE_WRDATA_4_7 0x100 ++#define I2CM_INTERFACE_WRDATA_8_11 0x104 ++#define I2CM_INTERFACE_WRDATA_12_15 0x108 ++#define I2CM_INTERFACE_RDDATA_0_3 0x10c ++#define I2CM_INTERFACE_RDDATA_4_7 0x110 ++#define I2CM_INTERFACE_RDDATA_8_11 0x114 ++#define I2CM_INTERFACE_RDDATA_12_15 0x118 ++/* SCDC Registers */ ++#define SCDC_CONFIG0 0x140 ++#define SCDC_I2C_FM_EN BIT(12) ++#define SCDC_UPD_FLAGS_AUTO_CLR BIT(6) ++#define SCDC_UPD_FLAGS_POLL_EN BIT(4) ++#define SCDC_CONTROL0 0x148 ++#define SCDC_STATUS0 0x150 ++#define STATUS_UPDATE BIT(0) ++#define FRL_START BIT(4) ++#define FLT_UPDATE BIT(5) ++/* FLT Registers */ ++#define FLT_CONFIG0 0x160 ++#define FLT_CONFIG1 0x164 ++#define FLT_CONFIG2 0x168 ++#define FLT_CONTROL0 0x170 ++/* Main Unit 2 Registers */ ++#define MAINUNIT_STATUS0 0x180 ++/* Video Interface Registers */ ++#define VIDEO_INTERFACE_CONFIG0 0x800 ++#define VIDEO_INTERFACE_CONFIG1 0x804 ++#define VIDEO_INTERFACE_CONFIG2 0x808 ++#define VIDEO_INTERFACE_CONTROL0 0x80c ++#define VIDEO_INTERFACE_STATUS0 0x814 ++/* Video Packing Registers */ ++#define VIDEO_PACKING_CONFIG0 0x81c ++/* Audio Interface Registers */ ++#define AUDIO_INTERFACE_CONFIG0 0x820 ++#define AUD_IF_SEL_MSK 0x3 ++#define AUD_IF_SPDIF 0x2 ++#define AUD_IF_I2S 0x1 ++#define AUD_IF_PAI 0x0 ++#define AUD_FIFO_INIT_ON_OVF_MSK BIT(2) ++#define AUD_FIFO_INIT_ON_OVF_EN BIT(2) ++#define I2S_LINES_EN_MSK GENMASK(7, 4) ++#define I2S_LINES_EN(x) BIT((x) + 4) ++#define I2S_BPCUV_RCV_MSK BIT(12) ++#define I2S_BPCUV_RCV_EN BIT(12) ++#define I2S_BPCUV_RCV_DIS 0 ++#define SPDIF_LINES_EN GENMASK(19, 16) ++#define AUD_FORMAT_MSK GENMASK(26, 24) ++#define AUD_3DOBA (0x7 << 24) ++#define AUD_3DASP (0x6 << 24) ++#define AUD_MSOBA (0x5 << 24) ++#define AUD_MSASP (0x4 << 24) ++#define AUD_HBR (0x3 << 24) ++#define AUD_DST (0x2 << 24) ++#define AUD_OBA (0x1 << 24) ++#define AUD_ASP (0x0 << 24) ++#define AUDIO_INTERFACE_CONFIG1 0x824 ++#define AUDIO_INTERFACE_CONTROL0 0x82c ++#define AUDIO_FIFO_CLR_P BIT(0) ++#define AUDIO_INTERFACE_STATUS0 0x834 ++/* Frame Composer Registers */ ++#define FRAME_COMPOSER_CONFIG0 0x840 ++#define FRAME_COMPOSER_CONFIG1 0x844 ++#define FRAME_COMPOSER_CONFIG2 0x848 ++#define FRAME_COMPOSER_CONFIG3 0x84c ++#define FRAME_COMPOSER_CONFIG4 0x850 ++#define FRAME_COMPOSER_CONFIG5 0x854 ++#define FRAME_COMPOSER_CONFIG6 0x858 ++#define FRAME_COMPOSER_CONFIG7 0x85c ++#define FRAME_COMPOSER_CONFIG8 0x860 ++#define FRAME_COMPOSER_CONFIG9 0x864 ++#define FRAME_COMPOSER_CONTROL0 0x86c ++/* Video Monitor Registers */ ++#define VIDEO_MONITOR_CONFIG0 0x880 ++#define VIDEO_MONITOR_STATUS0 0x884 ++#define VIDEO_MONITOR_STATUS1 0x888 ++#define VIDEO_MONITOR_STATUS2 0x88c ++#define VIDEO_MONITOR_STATUS3 0x890 ++#define VIDEO_MONITOR_STATUS4 0x894 ++#define VIDEO_MONITOR_STATUS5 0x898 ++#define VIDEO_MONITOR_STATUS6 0x89c ++/* HDCP2 Logic Registers */ ++#define HDCP2LOGIC_CONFIG0 0x8e0 ++#define HDCP2_BYPASS BIT(0) ++#define HDCP2LOGIC_ESM_GPIO_IN 0x8e4 ++#define HDCP2LOGIC_ESM_GPIO_OUT 0x8e8 ++/* HDCP14 Registers */ ++#define HDCP14_CONFIG0 0x900 ++#define HDCP14_CONFIG1 0x904 ++#define HDCP14_CONFIG2 0x908 ++#define HDCP14_CONFIG3 0x90c ++#define HDCP14_KEY_SEED 0x914 ++#define HDCP14_KEY_H 0x918 ++#define HDCP14_KEY_L 0x91c ++#define HDCP14_KEY_STATUS 0x920 ++#define HDCP14_AKSV_H 0x924 ++#define HDCP14_AKSV_L 0x928 ++#define HDCP14_AN_H 0x92c ++#define HDCP14_AN_L 0x930 ++#define HDCP14_STATUS0 0x934 ++#define HDCP14_STATUS1 0x938 ++/* Scrambler Registers */ ++#define SCRAMB_CONFIG0 0x960 ++/* Video Configuration Registers */ ++#define LINK_CONFIG0 0x968 ++#define OPMODE_FRL_4LANES BIT(8) ++#define OPMODE_DVI BIT(4) ++#define OPMODE_FRL BIT(0) ++/* TMDS FIFO Registers */ ++#define TMDS_FIFO_CONFIG0 0x970 ++#define TMDS_FIFO_CONTROL0 0x974 ++/* FRL RSFEC Registers */ ++#define FRL_RSFEC_CONFIG0 0xa20 ++#define FRL_RSFEC_STATUS0 0xa30 ++/* FRL Packetizer Registers */ ++#define FRL_PKTZ_CONFIG0 0xa40 ++#define FRL_PKTZ_CONTROL0 0xa44 ++#define FRL_PKTZ_CONTROL1 0xa50 ++#define FRL_PKTZ_STATUS1 0xa54 ++/* Packet Scheduler Registers */ ++#define PKTSCHED_CONFIG0 0xa80 ++#define PKTSCHED_PRQUEUE0_CONFIG0 0xa84 ++#define PKTSCHED_PRQUEUE1_CONFIG0 0xa88 ++#define PKTSCHED_PRQUEUE2_CONFIG0 0xa8c ++#define PKTSCHED_PRQUEUE2_CONFIG1 0xa90 ++#define PKTSCHED_PRQUEUE2_CONFIG2 0xa94 ++#define PKTSCHED_PKT_CONFIG0 0xa98 ++#define PKTSCHED_PKT_CONFIG1 0xa9c ++#define PKTSCHED_DRMI_FIELDRATE BIT(13) ++#define PKTSCHED_AVI_FIELDRATE BIT(12) ++#define PKTSCHED_PKT_CONFIG2 0xaa0 ++#define PKTSCHED_PKT_CONFIG3 0xaa4 ++#define PKTSCHED_PKT_EN 0xaa8 ++#define PKTSCHED_DRMI_TX_EN BIT(17) ++#define PKTSCHED_AUDI_TX_EN BIT(15) ++#define PKTSCHED_AVI_TX_EN BIT(13) ++#define PKTSCHED_EMP_CVTEM_TX_EN BIT(10) ++#define PKTSCHED_AMD_TX_EN BIT(8) ++#define PKTSCHED_GCP_TX_EN BIT(3) ++#define PKTSCHED_AUDS_TX_EN BIT(2) ++#define PKTSCHED_ACR_TX_EN BIT(1) ++#define PKTSCHED_NULL_TX_EN BIT(0) ++#define PKTSCHED_PKT_CONTROL0 0xaac ++#define PKTSCHED_PKT_SEND 0xab0 ++#define PKTSCHED_PKT_STATUS0 0xab4 ++#define PKTSCHED_PKT_STATUS1 0xab8 ++#define PKT_NULL_CONTENTS0 0xb00 ++#define PKT_NULL_CONTENTS1 0xb04 ++#define PKT_NULL_CONTENTS2 0xb08 ++#define PKT_NULL_CONTENTS3 0xb0c ++#define PKT_NULL_CONTENTS4 0xb10 ++#define PKT_NULL_CONTENTS5 0xb14 ++#define PKT_NULL_CONTENTS6 0xb18 ++#define PKT_NULL_CONTENTS7 0xb1c ++#define PKT_ACP_CONTENTS0 0xb20 ++#define PKT_ACP_CONTENTS1 0xb24 ++#define PKT_ACP_CONTENTS2 0xb28 ++#define PKT_ACP_CONTENTS3 0xb2c ++#define PKT_ACP_CONTENTS4 0xb30 ++#define PKT_ACP_CONTENTS5 0xb34 ++#define PKT_ACP_CONTENTS6 0xb38 ++#define PKT_ACP_CONTENTS7 0xb3c ++#define PKT_ISRC1_CONTENTS0 0xb40 ++#define PKT_ISRC1_CONTENTS1 0xb44 ++#define PKT_ISRC1_CONTENTS2 0xb48 ++#define PKT_ISRC1_CONTENTS3 0xb4c ++#define PKT_ISRC1_CONTENTS4 0xb50 ++#define PKT_ISRC1_CONTENTS5 0xb54 ++#define PKT_ISRC1_CONTENTS6 0xb58 ++#define PKT_ISRC1_CONTENTS7 0xb5c ++#define PKT_ISRC2_CONTENTS0 0xb60 ++#define PKT_ISRC2_CONTENTS1 0xb64 ++#define PKT_ISRC2_CONTENTS2 0xb68 ++#define PKT_ISRC2_CONTENTS3 0xb6c ++#define PKT_ISRC2_CONTENTS4 0xb70 ++#define PKT_ISRC2_CONTENTS5 0xb74 ++#define PKT_ISRC2_CONTENTS6 0xb78 ++#define PKT_ISRC2_CONTENTS7 0xb7c ++#define PKT_GMD_CONTENTS0 0xb80 ++#define PKT_GMD_CONTENTS1 0xb84 ++#define PKT_GMD_CONTENTS2 0xb88 ++#define PKT_GMD_CONTENTS3 0xb8c ++#define PKT_GMD_CONTENTS4 0xb90 ++#define PKT_GMD_CONTENTS5 0xb94 ++#define PKT_GMD_CONTENTS6 0xb98 ++#define PKT_GMD_CONTENTS7 0xb9c ++#define PKT_AMD_CONTENTS0 0xba0 ++#define PKT_AMD_CONTENTS1 0xba4 ++#define PKT_AMD_CONTENTS2 0xba8 ++#define PKT_AMD_CONTENTS3 0xbac ++#define PKT_AMD_CONTENTS4 0xbb0 ++#define PKT_AMD_CONTENTS5 0xbb4 ++#define PKT_AMD_CONTENTS6 0xbb8 ++#define PKT_AMD_CONTENTS7 0xbbc ++#define PKT_VSI_CONTENTS0 0xbc0 ++#define PKT_VSI_CONTENTS1 0xbc4 ++#define PKT_VSI_CONTENTS2 0xbc8 ++#define PKT_VSI_CONTENTS3 0xbcc ++#define PKT_VSI_CONTENTS4 0xbd0 ++#define PKT_VSI_CONTENTS5 0xbd4 ++#define PKT_VSI_CONTENTS6 0xbd8 ++#define PKT_VSI_CONTENTS7 0xbdc ++#define PKT_AVI_CONTENTS0 0xbe0 ++#define HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT BIT(4) ++#define HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR 0x04 ++#define HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR 0x08 ++#define HDMI_FC_AVICONF2_IT_CONTENT_VALID 0x80 ++#define PKT_AVI_CONTENTS1 0xbe4 ++#define PKT_AVI_CONTENTS2 0xbe8 ++#define PKT_AVI_CONTENTS3 0xbec ++#define PKT_AVI_CONTENTS4 0xbf0 ++#define PKT_AVI_CONTENTS5 0xbf4 ++#define PKT_AVI_CONTENTS6 0xbf8 ++#define PKT_AVI_CONTENTS7 0xbfc ++#define PKT_SPDI_CONTENTS0 0xc00 ++#define PKT_SPDI_CONTENTS1 0xc04 ++#define PKT_SPDI_CONTENTS2 0xc08 ++#define PKT_SPDI_CONTENTS3 0xc0c ++#define PKT_SPDI_CONTENTS4 0xc10 ++#define PKT_SPDI_CONTENTS5 0xc14 ++#define PKT_SPDI_CONTENTS6 0xc18 ++#define PKT_SPDI_CONTENTS7 0xc1c ++#define PKT_AUDI_CONTENTS0 0xc20 ++#define PKT_AUDI_CONTENTS1 0xc24 ++#define PKT_AUDI_CONTENTS2 0xc28 ++#define PKT_AUDI_CONTENTS3 0xc2c ++#define PKT_AUDI_CONTENTS4 0xc30 ++#define PKT_AUDI_CONTENTS5 0xc34 ++#define PKT_AUDI_CONTENTS6 0xc38 ++#define PKT_AUDI_CONTENTS7 0xc3c ++#define PKT_NVI_CONTENTS0 0xc40 ++#define PKT_NVI_CONTENTS1 0xc44 ++#define PKT_NVI_CONTENTS2 0xc48 ++#define PKT_NVI_CONTENTS3 0xc4c ++#define PKT_NVI_CONTENTS4 0xc50 ++#define PKT_NVI_CONTENTS5 0xc54 ++#define PKT_NVI_CONTENTS6 0xc58 ++#define PKT_NVI_CONTENTS7 0xc5c ++#define PKT_DRMI_CONTENTS0 0xc60 ++#define PKT_DRMI_CONTENTS1 0xc64 ++#define PKT_DRMI_CONTENTS2 0xc68 ++#define PKT_DRMI_CONTENTS3 0xc6c ++#define PKT_DRMI_CONTENTS4 0xc70 ++#define PKT_DRMI_CONTENTS5 0xc74 ++#define PKT_DRMI_CONTENTS6 0xc78 ++#define PKT_DRMI_CONTENTS7 0xc7c ++#define PKT_GHDMI1_CONTENTS0 0xc80 ++#define PKT_GHDMI1_CONTENTS1 0xc84 ++#define PKT_GHDMI1_CONTENTS2 0xc88 ++#define PKT_GHDMI1_CONTENTS3 0xc8c ++#define PKT_GHDMI1_CONTENTS4 0xc90 ++#define PKT_GHDMI1_CONTENTS5 0xc94 ++#define PKT_GHDMI1_CONTENTS6 0xc98 ++#define PKT_GHDMI1_CONTENTS7 0xc9c ++#define PKT_GHDMI2_CONTENTS0 0xca0 ++#define PKT_GHDMI2_CONTENTS1 0xca4 ++#define PKT_GHDMI2_CONTENTS2 0xca8 ++#define PKT_GHDMI2_CONTENTS3 0xcac ++#define PKT_GHDMI2_CONTENTS4 0xcb0 ++#define PKT_GHDMI2_CONTENTS5 0xcb4 ++#define PKT_GHDMI2_CONTENTS6 0xcb8 ++#define PKT_GHDMI2_CONTENTS7 0xcbc ++/* EMP Packetizer Registers */ ++#define PKT_EMP_CONFIG0 0xce0 ++#define PKT_EMP_CONTROL0 0xcec ++#define PKT_EMP_CONTROL1 0xcf0 ++#define PKT_EMP_CONTROL2 0xcf4 ++#define PKT_EMP_VTEM_CONTENTS0 0xd00 ++#define PKT_EMP_VTEM_CONTENTS1 0xd04 ++#define PKT_EMP_VTEM_CONTENTS2 0xd08 ++#define PKT_EMP_VTEM_CONTENTS3 0xd0c ++#define PKT_EMP_VTEM_CONTENTS4 0xd10 ++#define PKT_EMP_VTEM_CONTENTS5 0xd14 ++#define PKT_EMP_VTEM_CONTENTS6 0xd18 ++#define PKT_EMP_VTEM_CONTENTS7 0xd1c ++#define PKT0_EMP_CVTEM_CONTENTS0 0xd20 ++#define PKT0_EMP_CVTEM_CONTENTS1 0xd24 ++#define PKT0_EMP_CVTEM_CONTENTS2 0xd28 ++#define PKT0_EMP_CVTEM_CONTENTS3 0xd2c ++#define PKT0_EMP_CVTEM_CONTENTS4 0xd30 ++#define PKT0_EMP_CVTEM_CONTENTS5 0xd34 ++#define PKT0_EMP_CVTEM_CONTENTS6 0xd38 ++#define PKT0_EMP_CVTEM_CONTENTS7 0xd3c ++#define PKT1_EMP_CVTEM_CONTENTS0 0xd40 ++#define PKT1_EMP_CVTEM_CONTENTS1 0xd44 ++#define PKT1_EMP_CVTEM_CONTENTS2 0xd48 ++#define PKT1_EMP_CVTEM_CONTENTS3 0xd4c ++#define PKT1_EMP_CVTEM_CONTENTS4 0xd50 ++#define PKT1_EMP_CVTEM_CONTENTS5 0xd54 ++#define PKT1_EMP_CVTEM_CONTENTS6 0xd58 ++#define PKT1_EMP_CVTEM_CONTENTS7 0xd5c ++#define PKT2_EMP_CVTEM_CONTENTS0 0xd60 ++#define PKT2_EMP_CVTEM_CONTENTS1 0xd64 ++#define PKT2_EMP_CVTEM_CONTENTS2 0xd68 ++#define PKT2_EMP_CVTEM_CONTENTS3 0xd6c ++#define PKT2_EMP_CVTEM_CONTENTS4 0xd70 ++#define PKT2_EMP_CVTEM_CONTENTS5 0xd74 ++#define PKT2_EMP_CVTEM_CONTENTS6 0xd78 ++#define PKT2_EMP_CVTEM_CONTENTS7 0xd7c ++#define PKT3_EMP_CVTEM_CONTENTS0 0xd80 ++#define PKT3_EMP_CVTEM_CONTENTS1 0xd84 ++#define PKT3_EMP_CVTEM_CONTENTS2 0xd88 ++#define PKT3_EMP_CVTEM_CONTENTS3 0xd8c ++#define PKT3_EMP_CVTEM_CONTENTS4 0xd90 ++#define PKT3_EMP_CVTEM_CONTENTS5 0xd94 ++#define PKT3_EMP_CVTEM_CONTENTS6 0xd98 ++#define PKT3_EMP_CVTEM_CONTENTS7 0xd9c ++#define PKT4_EMP_CVTEM_CONTENTS0 0xda0 ++#define PKT4_EMP_CVTEM_CONTENTS1 0xda4 ++#define PKT4_EMP_CVTEM_CONTENTS2 0xda8 ++#define PKT4_EMP_CVTEM_CONTENTS3 0xdac ++#define PKT4_EMP_CVTEM_CONTENTS4 0xdb0 ++#define PKT4_EMP_CVTEM_CONTENTS5 0xdb4 ++#define PKT4_EMP_CVTEM_CONTENTS6 0xdb8 ++#define PKT4_EMP_CVTEM_CONTENTS7 0xdbc ++#define PKT5_EMP_CVTEM_CONTENTS0 0xdc0 ++#define PKT5_EMP_CVTEM_CONTENTS1 0xdc4 ++#define PKT5_EMP_CVTEM_CONTENTS2 0xdc8 ++#define PKT5_EMP_CVTEM_CONTENTS3 0xdcc ++#define PKT5_EMP_CVTEM_CONTENTS4 0xdd0 ++#define PKT5_EMP_CVTEM_CONTENTS5 0xdd4 ++#define PKT5_EMP_CVTEM_CONTENTS6 0xdd8 ++#define PKT5_EMP_CVTEM_CONTENTS7 0xddc ++/* Audio Packetizer Registers */ ++#define AUDPKT_CONTROL0 0xe20 ++#define AUDPKT_PBIT_FORCE_EN_MASK BIT(12) ++#define AUDPKT_PBIT_FORCE_EN BIT(12) ++#define AUDPKT_CHSTATUS_OVR_EN_MASK BIT(0) ++#define AUDPKT_CHSTATUS_OVR_EN BIT(0) ++#define AUDPKT_CONTROL1 0xe24 ++#define AUDPKT_ACR_CONTROL0 0xe40 ++#define AUDPKT_ACR_N_VALUE 0xfffff ++#define AUDPKT_ACR_CONTROL1 0xe44 ++#define AUDPKT_ACR_CTS_OVR_VAL_MSK GENMASK(23, 4) ++#define AUDPKT_ACR_CTS_OVR_VAL(x) ((x) << 4) ++#define AUDPKT_ACR_CTS_OVR_EN_MSK BIT(1) ++#define AUDPKT_ACR_CTS_OVR_EN BIT(1) ++#define AUDPKT_ACR_STATUS0 0xe4c ++#define AUDPKT_CHSTATUS_OVR0 0xe60 ++#define AUDPKT_CHSTATUS_OVR1 0xe64 ++/* IEC60958 Byte 3: Sampleing frenuency Bits 24 to 27 */ ++#define AUDPKT_CHSTATUS_SR_MASK GENMASK(3, 0) ++#define AUDPKT_CHSTATUS_SR_22050 0x4 ++#define AUDPKT_CHSTATUS_SR_24000 0x6 ++#define AUDPKT_CHSTATUS_SR_32000 0x3 ++#define AUDPKT_CHSTATUS_SR_44100 0x0 ++#define AUDPKT_CHSTATUS_SR_48000 0x2 ++#define AUDPKT_CHSTATUS_SR_88200 0x8 ++#define AUDPKT_CHSTATUS_SR_96000 0xa ++#define AUDPKT_CHSTATUS_SR_176400 0xc ++#define AUDPKT_CHSTATUS_SR_192000 0xe ++#define AUDPKT_CHSTATUS_SR_768000 0x9 ++#define AUDPKT_CHSTATUS_SR_NOT_INDICATED 0x1 ++/* IEC60958 Byte 4: Original Sampleing frenuency Bits 36 to 39 */ ++#define AUDPKT_CHSTATUS_0SR_MASK GENMASK(15, 12) ++#define AUDPKT_CHSTATUS_OSR_8000 0x6 ++#define AUDPKT_CHSTATUS_OSR_11025 0xa ++#define AUDPKT_CHSTATUS_OSR_12000 0x2 ++#define AUDPKT_CHSTATUS_OSR_16000 0x8 ++#define AUDPKT_CHSTATUS_OSR_22050 0xb ++#define AUDPKT_CHSTATUS_OSR_24000 0x9 ++#define AUDPKT_CHSTATUS_OSR_32000 0xc ++#define AUDPKT_CHSTATUS_OSR_44100 0xf ++#define AUDPKT_CHSTATUS_OSR_48000 0xd ++#define AUDPKT_CHSTATUS_OSR_88200 0x7 ++#define AUDPKT_CHSTATUS_OSR_96000 0x5 ++#define AUDPKT_CHSTATUS_OSR_176400 0x3 ++#define AUDPKT_CHSTATUS_OSR_192000 0x1 ++#define AUDPKT_CHSTATUS_OSR_NOT_INDICATED 0x0 ++#define AUDPKT_CHSTATUS_OVR2 0xe68 ++#define AUDPKT_CHSTATUS_OVR3 0xe6c ++#define AUDPKT_CHSTATUS_OVR4 0xe70 ++#define AUDPKT_CHSTATUS_OVR5 0xe74 ++#define AUDPKT_CHSTATUS_OVR6 0xe78 ++#define AUDPKT_CHSTATUS_OVR7 0xe7c ++#define AUDPKT_CHSTATUS_OVR8 0xe80 ++#define AUDPKT_CHSTATUS_OVR9 0xe84 ++#define AUDPKT_CHSTATUS_OVR10 0xe88 ++#define AUDPKT_CHSTATUS_OVR11 0xe8c ++#define AUDPKT_CHSTATUS_OVR12 0xe90 ++#define AUDPKT_CHSTATUS_OVR13 0xe94 ++#define AUDPKT_CHSTATUS_OVR14 0xe98 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC0 0xea0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC1 0xea4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC2 0xea8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC3 0xeac ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC4 0xeb0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC5 0xeb4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC6 0xeb8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC7 0xebc ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC8 0xec0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC9 0xec4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC10 0xec8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC11 0xecc ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC12 0xed0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC13 0xed4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC14 0xed8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC15 0xedc ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC16 0xee0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC17 0xee4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC18 0xee8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC19 0xeec ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC20 0xef0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC21 0xef4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC22 0xef8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC23 0xefc ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC24 0xf00 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC25 0xf04 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC26 0xf08 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC27 0xf0c ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC28 0xf10 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC29 0xf14 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC30 0xf18 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC31 0xf1c ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC32 0xf20 ++#define AUDPKT_VBIT_OVR0 0xf24 ++/* CEC Registers */ ++#define CEC_TX_CONTROL 0x1000 ++#define CEC_STATUS 0x1004 ++#define CEC_CONFIG 0x1008 ++#define CEC_ADDR 0x100c ++#define CEC_TX_COUNT 0x1020 ++#define CEC_TX_DATA3_0 0x1024 ++#define CEC_TX_DATA7_4 0x1028 ++#define CEC_TX_DATA11_8 0x102c ++#define CEC_TX_DATA15_12 0x1030 ++#define CEC_RX_COUNT_STATUS 0x1040 ++#define CEC_RX_DATA3_0 0x1044 ++#define CEC_RX_DATA7_4 0x1048 ++#define CEC_RX_DATA11_8 0x104c ++#define CEC_RX_DATA15_12 0x1050 ++#define CEC_LOCK_CONTROL 0x1054 ++#define CEC_RXQUAL_BITTIME_CONFIG 0x1060 ++#define CEC_RX_BITTIME_CONFIG 0x1064 ++#define CEC_TX_BITTIME_CONFIG 0x1068 ++/* eARC RX CMDC Registers */ ++#define EARCRX_CMDC_CONFIG0 0x1800 ++#define EARCRX_XACTREAD_STOP_CFG BIT(26) ++#define EARCRX_XACTREAD_RETRY_CFG BIT(25) ++#define EARCRX_CMDC_DSCVR_EARCVALID0_TO_DISC1 BIT(24) ++#define EARCRX_CMDC_XACT_RESTART_EN BIT(18) ++#define EARCRX_CMDC_CONFIG1 0x1804 ++#define EARCRX_CMDC_CONTROL 0x1808 ++#define EARCRX_CMDC_HEARTBEAT_LOSS_EN BIT(4) ++#define EARCRX_CMDC_DISCOVERY_EN BIT(3) ++#define EARCRX_CONNECTOR_HPD BIT(1) ++#define EARCRX_CMDC_WHITELIST0_CONFIG 0x180c ++#define EARCRX_CMDC_WHITELIST1_CONFIG 0x1810 ++#define EARCRX_CMDC_WHITELIST2_CONFIG 0x1814 ++#define EARCRX_CMDC_WHITELIST3_CONFIG 0x1818 ++#define EARCRX_CMDC_STATUS 0x181c ++#define EARCRX_CMDC_XACT_INFO 0x1820 ++#define EARCRX_CMDC_XACT_ACTION 0x1824 ++#define EARCRX_CMDC_HEARTBEAT_RXSTAT_SE 0x1828 ++#define EARCRX_CMDC_HEARTBEAT_STATUS 0x182c ++#define EARCRX_CMDC_XACT_WR0 0x1840 ++#define EARCRX_CMDC_XACT_WR1 0x1844 ++#define EARCRX_CMDC_XACT_WR2 0x1848 ++#define EARCRX_CMDC_XACT_WR3 0x184c ++#define EARCRX_CMDC_XACT_WR4 0x1850 ++#define EARCRX_CMDC_XACT_WR5 0x1854 ++#define EARCRX_CMDC_XACT_WR6 0x1858 ++#define EARCRX_CMDC_XACT_WR7 0x185c ++#define EARCRX_CMDC_XACT_WR8 0x1860 ++#define EARCRX_CMDC_XACT_WR9 0x1864 ++#define EARCRX_CMDC_XACT_WR10 0x1868 ++#define EARCRX_CMDC_XACT_WR11 0x186c ++#define EARCRX_CMDC_XACT_WR12 0x1870 ++#define EARCRX_CMDC_XACT_WR13 0x1874 ++#define EARCRX_CMDC_XACT_WR14 0x1878 ++#define EARCRX_CMDC_XACT_WR15 0x187c ++#define EARCRX_CMDC_XACT_WR16 0x1880 ++#define EARCRX_CMDC_XACT_WR17 0x1884 ++#define EARCRX_CMDC_XACT_WR18 0x1888 ++#define EARCRX_CMDC_XACT_WR19 0x188c ++#define EARCRX_CMDC_XACT_WR20 0x1890 ++#define EARCRX_CMDC_XACT_WR21 0x1894 ++#define EARCRX_CMDC_XACT_WR22 0x1898 ++#define EARCRX_CMDC_XACT_WR23 0x189c ++#define EARCRX_CMDC_XACT_WR24 0x18a0 ++#define EARCRX_CMDC_XACT_WR25 0x18a4 ++#define EARCRX_CMDC_XACT_WR26 0x18a8 ++#define EARCRX_CMDC_XACT_WR27 0x18ac ++#define EARCRX_CMDC_XACT_WR28 0x18b0 ++#define EARCRX_CMDC_XACT_WR29 0x18b4 ++#define EARCRX_CMDC_XACT_WR30 0x18b8 ++#define EARCRX_CMDC_XACT_WR31 0x18bc ++#define EARCRX_CMDC_XACT_WR32 0x18c0 ++#define EARCRX_CMDC_XACT_WR33 0x18c4 ++#define EARCRX_CMDC_XACT_WR34 0x18c8 ++#define EARCRX_CMDC_XACT_WR35 0x18cc ++#define EARCRX_CMDC_XACT_WR36 0x18d0 ++#define EARCRX_CMDC_XACT_WR37 0x18d4 ++#define EARCRX_CMDC_XACT_WR38 0x18d8 ++#define EARCRX_CMDC_XACT_WR39 0x18dc ++#define EARCRX_CMDC_XACT_WR40 0x18e0 ++#define EARCRX_CMDC_XACT_WR41 0x18e4 ++#define EARCRX_CMDC_XACT_WR42 0x18e8 ++#define EARCRX_CMDC_XACT_WR43 0x18ec ++#define EARCRX_CMDC_XACT_WR44 0x18f0 ++#define EARCRX_CMDC_XACT_WR45 0x18f4 ++#define EARCRX_CMDC_XACT_WR46 0x18f8 ++#define EARCRX_CMDC_XACT_WR47 0x18fc ++#define EARCRX_CMDC_XACT_WR48 0x1900 ++#define EARCRX_CMDC_XACT_WR49 0x1904 ++#define EARCRX_CMDC_XACT_WR50 0x1908 ++#define EARCRX_CMDC_XACT_WR51 0x190c ++#define EARCRX_CMDC_XACT_WR52 0x1910 ++#define EARCRX_CMDC_XACT_WR53 0x1914 ++#define EARCRX_CMDC_XACT_WR54 0x1918 ++#define EARCRX_CMDC_XACT_WR55 0x191c ++#define EARCRX_CMDC_XACT_WR56 0x1920 ++#define EARCRX_CMDC_XACT_WR57 0x1924 ++#define EARCRX_CMDC_XACT_WR58 0x1928 ++#define EARCRX_CMDC_XACT_WR59 0x192c ++#define EARCRX_CMDC_XACT_WR60 0x1930 ++#define EARCRX_CMDC_XACT_WR61 0x1934 ++#define EARCRX_CMDC_XACT_WR62 0x1938 ++#define EARCRX_CMDC_XACT_WR63 0x193c ++#define EARCRX_CMDC_XACT_WR64 0x1940 ++#define EARCRX_CMDC_XACT_RD0 0x1960 ++#define EARCRX_CMDC_XACT_RD1 0x1964 ++#define EARCRX_CMDC_XACT_RD2 0x1968 ++#define EARCRX_CMDC_XACT_RD3 0x196c ++#define EARCRX_CMDC_XACT_RD4 0x1970 ++#define EARCRX_CMDC_XACT_RD5 0x1974 ++#define EARCRX_CMDC_XACT_RD6 0x1978 ++#define EARCRX_CMDC_XACT_RD7 0x197c ++#define EARCRX_CMDC_XACT_RD8 0x1980 ++#define EARCRX_CMDC_XACT_RD9 0x1984 ++#define EARCRX_CMDC_XACT_RD10 0x1988 ++#define EARCRX_CMDC_XACT_RD11 0x198c ++#define EARCRX_CMDC_XACT_RD12 0x1990 ++#define EARCRX_CMDC_XACT_RD13 0x1994 ++#define EARCRX_CMDC_XACT_RD14 0x1998 ++#define EARCRX_CMDC_XACT_RD15 0x199c ++#define EARCRX_CMDC_XACT_RD16 0x19a0 ++#define EARCRX_CMDC_XACT_RD17 0x19a4 ++#define EARCRX_CMDC_XACT_RD18 0x19a8 ++#define EARCRX_CMDC_XACT_RD19 0x19ac ++#define EARCRX_CMDC_XACT_RD20 0x19b0 ++#define EARCRX_CMDC_XACT_RD21 0x19b4 ++#define EARCRX_CMDC_XACT_RD22 0x19b8 ++#define EARCRX_CMDC_XACT_RD23 0x19bc ++#define EARCRX_CMDC_XACT_RD24 0x19c0 ++#define EARCRX_CMDC_XACT_RD25 0x19c4 ++#define EARCRX_CMDC_XACT_RD26 0x19c8 ++#define EARCRX_CMDC_XACT_RD27 0x19cc ++#define EARCRX_CMDC_XACT_RD28 0x19d0 ++#define EARCRX_CMDC_XACT_RD29 0x19d4 ++#define EARCRX_CMDC_XACT_RD30 0x19d8 ++#define EARCRX_CMDC_XACT_RD31 0x19dc ++#define EARCRX_CMDC_XACT_RD32 0x19e0 ++#define EARCRX_CMDC_XACT_RD33 0x19e4 ++#define EARCRX_CMDC_XACT_RD34 0x19e8 ++#define EARCRX_CMDC_XACT_RD35 0x19ec ++#define EARCRX_CMDC_XACT_RD36 0x19f0 ++#define EARCRX_CMDC_XACT_RD37 0x19f4 ++#define EARCRX_CMDC_XACT_RD38 0x19f8 ++#define EARCRX_CMDC_XACT_RD39 0x19fc ++#define EARCRX_CMDC_XACT_RD40 0x1a00 ++#define EARCRX_CMDC_XACT_RD41 0x1a04 ++#define EARCRX_CMDC_XACT_RD42 0x1a08 ++#define EARCRX_CMDC_XACT_RD43 0x1a0c ++#define EARCRX_CMDC_XACT_RD44 0x1a10 ++#define EARCRX_CMDC_XACT_RD45 0x1a14 ++#define EARCRX_CMDC_XACT_RD46 0x1a18 ++#define EARCRX_CMDC_XACT_RD47 0x1a1c ++#define EARCRX_CMDC_XACT_RD48 0x1a20 ++#define EARCRX_CMDC_XACT_RD49 0x1a24 ++#define EARCRX_CMDC_XACT_RD50 0x1a28 ++#define EARCRX_CMDC_XACT_RD51 0x1a2c ++#define EARCRX_CMDC_XACT_RD52 0x1a30 ++#define EARCRX_CMDC_XACT_RD53 0x1a34 ++#define EARCRX_CMDC_XACT_RD54 0x1a38 ++#define EARCRX_CMDC_XACT_RD55 0x1a3c ++#define EARCRX_CMDC_XACT_RD56 0x1a40 ++#define EARCRX_CMDC_XACT_RD57 0x1a44 ++#define EARCRX_CMDC_XACT_RD58 0x1a48 ++#define EARCRX_CMDC_XACT_RD59 0x1a4c ++#define EARCRX_CMDC_XACT_RD60 0x1a50 ++#define EARCRX_CMDC_XACT_RD61 0x1a54 ++#define EARCRX_CMDC_XACT_RD62 0x1a58 ++#define EARCRX_CMDC_XACT_RD63 0x1a5c ++#define EARCRX_CMDC_XACT_RD64 0x1a60 ++#define EARCRX_CMDC_SYNC_CONFIG 0x1b00 ++/* eARC RX DMAC Registers */ ++#define EARCRX_DMAC_PHY_CONTROL 0x1c00 ++#define EARCRX_DMAC_CONFIG 0x1c08 ++#define EARCRX_DMAC_CONTROL0 0x1c0c ++#define EARCRX_DMAC_AUDIO_EN BIT(1) ++#define EARCRX_DMAC_EN BIT(0) ++#define EARCRX_DMAC_CONTROL1 0x1c10 ++#define EARCRX_DMAC_STATUS 0x1c14 ++#define EARCRX_DMAC_CHSTATUS0 0x1c18 ++#define EARCRX_DMAC_CHSTATUS1 0x1c1c ++#define EARCRX_DMAC_CHSTATUS2 0x1c20 ++#define EARCRX_DMAC_CHSTATUS3 0x1c24 ++#define EARCRX_DMAC_CHSTATUS4 0x1c28 ++#define EARCRX_DMAC_CHSTATUS5 0x1c2c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC0 0x1c30 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC1 0x1c34 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC2 0x1c38 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC3 0x1c3c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC4 0x1c40 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC5 0x1c44 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC6 0x1c48 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC7 0x1c4c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC8 0x1c50 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC9 0x1c54 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC10 0x1c58 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC11 0x1c5c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT0 0x1c60 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT1 0x1c64 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT2 0x1c68 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT3 0x1c6c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT4 0x1c70 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT5 0x1c74 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT6 0x1c78 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT7 0x1c7c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT8 0x1c80 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT9 0x1c84 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT10 0x1c88 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT11 0x1c8c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT0 0x1c90 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT1 0x1c94 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT2 0x1c98 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT3 0x1c9c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT4 0x1ca0 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT5 0x1ca4 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT6 0x1ca8 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT7 0x1cac ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT8 0x1cb0 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT9 0x1cb4 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT10 0x1cb8 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT11 0x1cbc ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC0 0x1cc0 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC1 0x1cc4 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC2 0x1cc8 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC3 0x1ccc ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC4 0x1cd0 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC5 0x1cd4 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC6 0x1cd8 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC7 0x1cdc ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC8 0x1ce0 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC9 0x1ce4 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC10 0x1ce8 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC11 0x1cec ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC12 0x1cf0 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC13 0x1cf4 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC14 0x1cf8 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC15 0x1cfc ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC16 0x1d00 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC17 0x1d04 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC18 0x1d08 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC19 0x1d0c ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC20 0x1d10 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC21 0x1d14 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC22 0x1d18 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC23 0x1d1c ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC24 0x1d20 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC25 0x1d24 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC26 0x1d28 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC27 0x1d2c ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC28 0x1d30 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC29 0x1d34 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC30 0x1d38 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC31 0x1d3c ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC32 0x1d40 ++#define EARCRX_DMAC_CHSTATUS_STREAMER0 0x1d44 ++#define EARCRX_DMAC_CHSTATUS_STREAMER1 0x1d48 ++#define EARCRX_DMAC_CHSTATUS_STREAMER2 0x1d4c ++#define EARCRX_DMAC_CHSTATUS_STREAMER3 0x1d50 ++#define EARCRX_DMAC_CHSTATUS_STREAMER4 0x1d54 ++#define EARCRX_DMAC_CHSTATUS_STREAMER5 0x1d58 ++#define EARCRX_DMAC_CHSTATUS_STREAMER6 0x1d5c ++#define EARCRX_DMAC_CHSTATUS_STREAMER7 0x1d60 ++#define EARCRX_DMAC_CHSTATUS_STREAMER8 0x1d64 ++#define EARCRX_DMAC_CHSTATUS_STREAMER9 0x1d68 ++#define EARCRX_DMAC_CHSTATUS_STREAMER10 0x1d6c ++#define EARCRX_DMAC_CHSTATUS_STREAMER11 0x1d70 ++#define EARCRX_DMAC_CHSTATUS_STREAMER12 0x1d74 ++#define EARCRX_DMAC_CHSTATUS_STREAMER13 0x1d78 ++#define EARCRX_DMAC_CHSTATUS_STREAMER14 0x1d7c ++#define EARCRX_DMAC_USRDATA_STREAMER0 0x1d80 ++/* Main Unit Interrupt Registers */ ++#define MAIN_INTVEC_INDEX 0x3000 ++#define MAINUNIT_0_INT_STATUS 0x3010 ++#define MAINUNIT_0_INT_MASK_N 0x3014 ++#define MAINUNIT_0_INT_CLEAR 0x3018 ++#define MAINUNIT_0_INT_FORCE 0x301c ++#define MAINUNIT_1_INT_STATUS 0x3020 ++#define FLT_EXIT_TO_LTSL_IRQ BIT(22) ++#define FLT_EXIT_TO_LTS4_IRQ BIT(21) ++#define FLT_EXIT_TO_LTSP_IRQ BIT(20) ++#define SCDC_NACK_RCVD_IRQ BIT(12) ++#define SCDC_RR_REPLY_STOP_IRQ BIT(11) ++#define SCDC_UPD_FLAGS_CLR_IRQ BIT(10) ++#define SCDC_UPD_FLAGS_CHG_IRQ BIT(9) ++#define SCDC_UPD_FLAGS_RD_IRQ BIT(8) ++#define I2CM_NACK_RCVD_IRQ BIT(2) ++#define I2CM_READ_REQUEST_IRQ BIT(1) ++#define I2CM_OP_DONE_IRQ BIT(0) ++#define MAINUNIT_1_INT_MASK_N 0x3024 ++#define I2CM_NACK_RCVD_MASK_N BIT(2) ++#define I2CM_READ_REQUEST_MASK_N BIT(1) ++#define I2CM_OP_DONE_MASK_N BIT(0) ++#define MAINUNIT_1_INT_CLEAR 0x3028 ++#define I2CM_NACK_RCVD_CLEAR BIT(2) ++#define I2CM_READ_REQUEST_CLEAR BIT(1) ++#define I2CM_OP_DONE_CLEAR BIT(0) ++#define MAINUNIT_1_INT_FORCE 0x302c ++/* AVPUNIT Interrupt Registers */ ++#define AVP_INTVEC_INDEX 0x3800 ++#define AVP_0_INT_STATUS 0x3810 ++#define AVP_0_INT_MASK_N 0x3814 ++#define AVP_0_INT_CLEAR 0x3818 ++#define AVP_0_INT_FORCE 0x381c ++#define AVP_1_INT_STATUS 0x3820 ++#define AVP_1_INT_MASK_N 0x3824 ++#define HDCP14_AUTH_CHG_MASK_N BIT(6) ++#define AVP_1_INT_CLEAR 0x3828 ++#define AVP_1_INT_FORCE 0x382c ++#define AVP_2_INT_STATUS 0x3830 ++#define AVP_2_INT_MASK_N 0x3834 ++#define AVP_2_INT_CLEAR 0x3838 ++#define AVP_2_INT_FORCE 0x383c ++#define AVP_3_INT_STATUS 0x3840 ++#define AVP_3_INT_MASK_N 0x3844 ++#define AVP_3_INT_CLEAR 0x3848 ++#define AVP_3_INT_FORCE 0x384c ++#define AVP_4_INT_STATUS 0x3850 ++#define AVP_4_INT_MASK_N 0x3854 ++#define AVP_4_INT_CLEAR 0x3858 ++#define AVP_4_INT_FORCE 0x385c ++#define AVP_5_INT_STATUS 0x3860 ++#define AVP_5_INT_MASK_N 0x3864 ++#define AVP_5_INT_CLEAR 0x3868 ++#define AVP_5_INT_FORCE 0x386c ++#define AVP_6_INT_STATUS 0x3870 ++#define AVP_6_INT_MASK_N 0x3874 ++#define AVP_6_INT_CLEAR 0x3878 ++#define AVP_6_INT_FORCE 0x387c ++/* CEC Interrupt Registers */ ++#define CEC_INT_STATUS 0x4000 ++#define CEC_INT_MASK_N 0x4004 ++#define CEC_INT_CLEAR 0x4008 ++#define CEC_INT_FORCE 0x400c ++/* eARC RX Interrupt Registers */ ++#define EARCRX_INTVEC_INDEX 0x4800 ++#define EARCRX_0_INT_STATUS 0x4810 ++#define EARCRX_CMDC_DISCOVERY_TIMEOUT_IRQ BIT(9) ++#define EARCRX_CMDC_DISCOVERY_DONE_IRQ BIT(8) ++#define EARCRX_0_INT_MASK_N 0x4814 ++#define EARCRX_0_INT_CLEAR 0x4818 ++#define EARCRX_0_INT_FORCE 0x481c ++#define EARCRX_1_INT_STATUS 0x4820 ++#define EARCRX_1_INT_MASK_N 0x4824 ++#define EARCRX_1_INT_CLEAR 0x4828 ++#define EARCRX_1_INT_FORCE 0x482c ++ ++#endif /* __DW_HDMI_QP_H__ */ +diff --git a/include/drm/bridge/dw_hdmi_qp.h b/include/drm/bridge/dw_hdmi_qp.h +new file mode 100644 +index 000000000000..7ec18d8091d6 +--- /dev/null ++++ b/include/drm/bridge/dw_hdmi_qp.h +@@ -0,0 +1,37 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd. ++ * Copyright (c) 2024 Collabora Ltd. ++ */ ++ ++#ifndef __DW_HDMI_QP__ ++#define __DW_HDMI_QP__ ++ ++struct device; ++struct drm_display_info; ++struct drm_encoder; ++struct dw_hdmi_qp; ++struct platform_device; ++ ++struct dw_hdmi_qp_phy_ops { ++ int (*init)(struct dw_hdmi_qp *hdmi, void *data, ++ const struct drm_display_info *display); ++ void (*disable)(struct dw_hdmi_qp *hdmi, void *data); ++ enum drm_connector_status (*read_hpd)(struct dw_hdmi_qp *hdmi, void *data); ++ void (*setup_hpd)(struct dw_hdmi_qp *hdmi, void *data); ++}; ++ ++struct dw_hdmi_qp_plat_data { ++ const struct dw_hdmi_qp_phy_ops *phy_ops; ++ void *phy_data; ++}; ++ ++int dw_hdmi_qp_set_refclk_rate(struct dw_hdmi_qp *hdmi, unsigned long rate); ++void dw_hdmi_qp_set_high_tmds_clock_ratio(struct dw_hdmi_qp *hdmi, ++ const struct drm_display_info *display); ++void dw_hdmi_qp_unbind(struct dw_hdmi_qp *hdmi); ++struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, ++ struct drm_encoder *encoder, ++ const struct dw_hdmi_qp_plat_data *plat_data); ++void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi); ++#endif /* __DW_HDMI_QP__ */ +-- +2.45.2 + + +From c6f1df902a1877210008527b568ffd37c772ce13 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Fri, 26 Jul 2024 03:07:04 +0300 +Subject: [PATCH 4/7] dt-bindings: display: rockchip: Add schema for RK3588 + HDMI TX Controller + +Rockchip RK3588 SoC integrates the Synopsys DesignWare HDMI 2.1 +Quad-Pixel (QP) TX controller IP. + +Since this is a new IP block, quite different from those used in the +previous generations of Rockchip SoCs, add a dedicated binding file. + +Signed-off-by: Cristian Ciocaltea +--- + .../display/rockchip/rockchip,dw-hdmi-qp.yaml | 188 ++++++++++++++++++ + 1 file changed, 188 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi-qp.yaml + +diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi-qp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi-qp.yaml +new file mode 100644 +index 000000000000..33572c88a589 +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi-qp.yaml +@@ -0,0 +1,188 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/display/rockchip/rockchip,dw-hdmi-qp.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Rockchip DW HDMI QP TX Encoder ++ ++maintainers: ++ - Cristian Ciocaltea ++ ++description: ++ Rockchip RK3588 SoC integrates the Synopsys DesignWare HDMI QP TX controller ++ IP and a HDMI/eDP TX Combo PHY based on a Samsung IP block. ++ ++allOf: ++ - $ref: ../bridge/synopsys,dw-hdmi-qp.yaml# ++ - $ref: /schemas/sound/dai-common.yaml# ++ ++properties: ++ compatible: ++ enum: ++ - rockchip,rk3588-dw-hdmi-qp ++ ++ clocks: ++ minItems: 4 ++ items: ++ - {} ++ - {} ++ - {} ++ - {} ++ # The next clocks are optional, but shall be specified in this ++ # order when present. ++ - description: TMDS/FRL link clock ++ - description: Video datapath clock ++ ++ clock-names: ++ minItems: 4 ++ items: ++ - {} ++ - {} ++ - {} ++ - {} ++ - enum: [hdp, hclk_vo1] ++ - const: hclk_vo1 ++ ++ interrupts: ++ items: ++ - {} ++ - {} ++ - {} ++ - {} ++ - description: HPD interrupt ++ ++ interrupt-names: ++ items: ++ - {} ++ - {} ++ - {} ++ - {} ++ - const: hpd ++ ++ phys: ++ maxItems: 1 ++ description: The HDMI/eDP PHY. ++ ++ phy-names: ++ const: hdmi ++ ++ ports: ++ $ref: /schemas/graph.yaml#/properties/ports ++ ++ properties: ++ port@0: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Port node with one endpoint connected to a vop node. ++ ++ port@1: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Port node with one endpoint connected to a hdmi-connector node. ++ ++ required: ++ - port@0 ++ - port@1 ++ ++ power-domains: ++ maxItems: 1 ++ ++ resets: ++ minItems: 2 ++ maxItems: 2 ++ ++ reset-names: ++ items: ++ - const: ref ++ - const: hdp ++ ++ "#sound-dai-cells": ++ const: 0 ++ ++ rockchip,grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Most HDMI QP related data is accessed through SYS GRF regs. ++ ++ rockchip,vo1_grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Additional HDMI QP related data is accessed through VO1 GRF regs. ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - interrupts ++ - interrupt-names ++ - phys ++ - phy-names ++ - ports ++ - resets ++ - reset-names ++ - rockchip,grf ++ - rockchip,vo1_grf ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ #include ++ #include ++ ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ hdmi@fde80000 { ++ compatible = "rockchip,rk3588-dw-hdmi-qp"; ++ reg = <0x0 0xfde80000 0x0 0x20000>; ++ clocks = <&cru PCLK_HDMITX0>, ++ <&cru CLK_HDMITX0_EARC>, ++ <&cru CLK_HDMITX0_REF>, ++ <&cru MCLK_I2S5_8CH_TX>, ++ <&cru CLK_HDMIHDP0>, ++ <&cru HCLK_VO1>; ++ clock-names = "pclk", "earc", "ref", "aud", "hdp", "hclk_vo1"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "avp", "cec", "earc", "main", "hpd"; ++ phys = <&hdptxphy_hdmi0>; ++ phy-names = "hdmi"; ++ power-domains = <&power RK3588_PD_VO1>; ++ resets = <&cru SRST_HDMITX0_REF>, <&cru SRST_HDMIHDP0>; ++ reset-names = "ref", "hdp"; ++ rockchip,grf = <&sys_grf>; ++ rockchip,vo1_grf = <&vo1_grf>; ++ #sound-dai-cells = <0>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ hdmi0_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi0>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ hdmi0_out_con0: endpoint { ++ remote-endpoint = <&hdmi_con0_in>; ++ }; ++ }; ++ }; ++ }; ++ }; +-- +2.45.2 + + +From 625148b9625da7ad7a3623b8057010a7ae05952d Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Wed, 17 Jul 2024 03:34:36 +0300 +Subject: [PATCH 5/7] drm/rockchip: Explicitly include bits header + +Driver makes use of the BIT() macro, but relies on the bits header being +implicitly included. + +Explicitly pull the header in to avoid potential build failures in some +configurations. + +While at it, reorder include directives alphabetically. + +Fixes: 8c8546546f25 ("drm/rockchip: move output interface related definition to rockchip_drm_drv.h") +Signed-off-by: Cristian Ciocaltea +--- + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +index bbb9e0bf6804..8d566fcd80a2 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +@@ -12,9 +12,10 @@ + #include + #include + ++#include ++#include + #include + #include +-#include + + #define ROCKCHIP_MAX_FB_BUFFER 3 + #define ROCKCHIP_MAX_CONNECTOR 2 +-- +2.45.2 + + +From b70f862d9c5273f785e9c81e0c53db8c4b09faab Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Sat, 6 Jul 2024 03:22:35 +0300 +Subject: [PATCH 6/7] drm/rockchip: Add basic RK3588 HDMI output support + +The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1 +Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a +Samsung IP block. + +Add just the basic support for now, i.e. RGB output up to 4K@60Hz, +without audio, CEC or any of the HDMI 2.1 specific features. + +Co-developed-by: Algea Cao +Signed-off-by: Algea Cao +Signed-off-by: Cristian Ciocaltea +--- + drivers/gpu/drm/rockchip/Kconfig | 8 + + drivers/gpu/drm/rockchip/Makefile | 1 + + .../gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 430 ++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 + + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + + 5 files changed, 442 insertions(+) + create mode 100644 drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c + +diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig +index 7df875e38517..4da7cef24f57 100644 +--- a/drivers/gpu/drm/rockchip/Kconfig ++++ b/drivers/gpu/drm/rockchip/Kconfig +@@ -8,6 +8,7 @@ config DRM_ROCKCHIP + select VIDEOMODE_HELPERS + select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP + select DRM_DW_HDMI if ROCKCHIP_DW_HDMI ++ select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP + select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI + select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI + select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI +@@ -63,6 +64,13 @@ config ROCKCHIP_DW_HDMI + enable HDMI on RK3288 or RK3399 based SoC, you should select + this option. + ++config ROCKCHIP_DW_HDMI_QP ++ bool "Rockchip specific extensions for Synopsys DW HDMI QP" ++ help ++ This selects support for Rockchip SoC specific extensions ++ for the Synopsys DesignWare HDMI QP driver. If you want to ++ enable HDMI on RK3588 based SoC, you should select this option. ++ + config ROCKCHIP_DW_MIPI_DSI + bool "Rockchip specific extensions for Synopsys DW MIPI DSI" + select GENERIC_PHY_MIPI_DPHY +diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile +index 3ff7b21c0414..3eab662a5a1d 100644 +--- a/drivers/gpu/drm/rockchip/Makefile ++++ b/drivers/gpu/drm/rockchip/Makefile +@@ -11,6 +11,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o + rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o + rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o + rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o ++rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI_QP) += dw_hdmi_qp-rockchip.o + rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi-rockchip.o + rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o + rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c +new file mode 100644 +index 000000000000..e04417940573 +--- /dev/null ++++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c +@@ -0,0 +1,430 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd. ++ * Copyright (c) 2024 Collabora Ltd. ++ * ++ * Author: Algea Cao ++ * Author: Cristian Ciocaltea ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "rockchip_drm_drv.h" ++ ++#define RK3588_GRF_SOC_CON2 0x0308 ++#define RK3588_HDMI0_HPD_INT_MSK BIT(13) ++#define RK3588_HDMI0_HPD_INT_CLR BIT(12) ++#define RK3588_GRF_SOC_CON7 0x031c ++#define RK3588_SET_HPD_PATH_MASK GENMASK(13, 12) ++#define RK3588_GRF_SOC_STATUS1 0x0384 ++#define RK3588_HDMI0_LEVEL_INT BIT(16) ++#define RK3588_GRF_VO1_CON3 0x000c ++#define RK3588_SCLIN_MASK BIT(9) ++#define RK3588_SDAIN_MASK BIT(10) ++#define RK3588_MODE_MASK BIT(11) ++#define RK3588_I2S_SEL_MASK BIT(13) ++#define RK3588_GRF_VO1_CON9 0x0024 ++#define RK3588_HDMI0_GRANT_SEL BIT(10) ++ ++#define HIWORD_UPDATE(val, mask) ((val) | (mask) << 16) ++ ++struct rockchip_hdmi_qp { ++ struct device *dev; ++ struct regmap *regmap; ++ struct regmap *vo1_regmap; ++ struct rockchip_encoder encoder; ++ struct dw_hdmi_qp *hdmi; ++ struct phy *phy; ++ struct gpio_desc *enable_gpio; ++ struct delayed_work hpd_work; ++}; ++ ++static struct rockchip_hdmi_qp *to_rockchip_hdmi_qp(struct drm_encoder *encoder) ++{ ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ return container_of(rkencoder, struct rockchip_hdmi_qp, encoder); ++} ++ ++static void ++dw_hdmi_qp_rockchip_encoder_mode_set(struct drm_encoder *encoder, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adj_mode) ++{ ++ struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder); ++ ++ dw_hdmi_qp_set_refclk_rate(hdmi->hdmi, adj_mode->clock * 1000); ++} ++ ++static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder) ++{ ++ struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder); ++ struct drm_crtc *crtc = encoder->crtc; ++ int rate; ++ ++ /* Unconditionally switch to TMDS as FRL is not yet supported */ ++ gpiod_set_value(hdmi->enable_gpio, 1); ++ ++ if (crtc && crtc->state) { ++ dw_hdmi_qp_set_refclk_rate(hdmi->hdmi, ++ crtc->state->adjusted_mode.crtc_clock * 1000); ++ /* ++ * FIXME: Temporary workaround to pass pixel clock rate ++ * to the PHY driver until phy_configure_opts_hdmi ++ * becomes available in the PHY API. See also the related ++ * comment in rk_hdptx_phy_power_on() from ++ * drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++ */ ++ rate = crtc->state->mode.clock * 10; ++ phy_set_bus_width(hdmi->phy, rate); ++ drm_dbg(hdmi, "%s set bus_width=%u\n", __func__, rate); ++ } ++} ++ ++static int ++dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state) ++{ ++ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); ++ ++ s->output_mode = ROCKCHIP_OUT_MODE_AAAA; ++ s->output_type = DRM_MODE_CONNECTOR_HDMIA; ++ ++ return 0; ++} ++ ++static const struct ++drm_encoder_helper_funcs dw_hdmi_qp_rockchip_encoder_helper_funcs = { ++ .mode_set = dw_hdmi_qp_rockchip_encoder_mode_set, ++ .enable = dw_hdmi_qp_rockchip_encoder_enable, ++ .atomic_check = dw_hdmi_qp_rockchip_encoder_atomic_check, ++}; ++ ++static int dw_hdmi_qp_rk3588_phy_init(struct dw_hdmi_qp *dw_hdmi, void *data, ++ const struct drm_display_info *display) ++{ ++ struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; ++ ++ dw_hdmi_qp_set_high_tmds_clock_ratio(dw_hdmi, display); ++ ++ return phy_power_on(hdmi->phy); ++} ++ ++static void dw_hdmi_qp_rk3588_phy_disable(struct dw_hdmi_qp *dw_hdmi, ++ void *data) ++{ ++ struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; ++ ++ phy_power_off(hdmi->phy); ++} ++ ++static enum drm_connector_status ++dw_hdmi_qp_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) ++{ ++ struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; ++ u32 val; ++ ++ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val); ++ ++ return val & RK3588_HDMI0_LEVEL_INT ? ++ connector_status_connected : connector_status_disconnected; ++} ++ ++static void dw_hdmi_qp_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) ++{ ++ struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; ++ ++ regmap_write(hdmi->regmap, ++ RK3588_GRF_SOC_CON2, ++ HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, ++ RK3588_HDMI0_HPD_INT_CLR | ++ RK3588_HDMI0_HPD_INT_MSK)); ++} ++ ++static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = { ++ .init = dw_hdmi_qp_rk3588_phy_init, ++ .disable = dw_hdmi_qp_rk3588_phy_disable, ++ .read_hpd = dw_hdmi_qp_rk3588_read_hpd, ++ .setup_hpd = dw_hdmi_qp_rk3588_setup_hpd, ++}; ++ ++static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work) ++{ ++ struct rockchip_hdmi_qp *hdmi = container_of(work, ++ struct rockchip_hdmi_qp, ++ hpd_work.work); ++ struct drm_device *drm = hdmi->encoder.encoder.dev; ++ bool changed; ++ ++ if (drm) { ++ changed = drm_helper_hpd_irq_event(drm); ++ if (changed) ++ drm_dbg(hdmi, "connector status changed\n"); ++ } ++} ++ ++static irqreturn_t dw_hdmi_qp_rk3588_hardirq(int irq, void *dev_id) ++{ ++ struct rockchip_hdmi_qp *hdmi = dev_id; ++ u32 intr_stat, val; ++ ++ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat); ++ ++ if (intr_stat) { ++ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, ++ RK3588_HDMI0_HPD_INT_MSK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); ++ return IRQ_WAKE_THREAD; ++ } ++ ++ return IRQ_NONE; ++} ++ ++static irqreturn_t dw_hdmi_qp_rk3588_irq(int irq, void *dev_id) ++{ ++ struct rockchip_hdmi_qp *hdmi = dev_id; ++ u32 intr_stat, val; ++ int debounce_ms; ++ ++ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat); ++ if (!intr_stat) ++ return IRQ_NONE; ++ ++ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, ++ RK3588_HDMI0_HPD_INT_CLR); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); ++ ++ debounce_ms = intr_stat & RK3588_HDMI0_LEVEL_INT ? 150 : 20; ++ mod_delayed_work(system_wq, &hdmi->hpd_work, ++ msecs_to_jiffies(debounce_ms)); ++ ++ val |= HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); ++ ++ return IRQ_HANDLED; ++} ++ ++static const struct of_device_id dw_hdmi_qp_rockchip_dt_ids[] = { ++ { .compatible = "rockchip,rk3588-dw-hdmi-qp", ++ .data = &rk3588_hdmi_phy_ops }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dw_hdmi_qp_rockchip_dt_ids); ++ ++static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master, ++ void *data) ++{ ++ static const char * const clk_names[] = { "hdp", "hclk_vo1" }; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct dw_hdmi_qp_plat_data plat_data; ++ struct drm_device *drm = data; ++ struct drm_connector *connector; ++ struct drm_encoder *encoder; ++ struct rockchip_hdmi_qp *hdmi; ++ struct clk *clk; ++ int ret, irq, i; ++ u32 val; ++ ++ if (!pdev->dev.of_node) ++ return -ENODEV; ++ ++ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); ++ if (!hdmi) ++ return -ENOMEM; ++ ++ plat_data.phy_ops = of_device_get_match_data(dev); ++ if (!plat_data.phy_ops) ++ return -ENODEV; ++ ++ plat_data.phy_data = hdmi; ++ hdmi->dev = &pdev->dev; ++ ++ encoder = &hdmi->encoder.encoder; ++ encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); ++ ++ rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder, ++ dev->of_node, 0, 0); ++ /* ++ * If we failed to find the CRTC(s) which this encoder is ++ * supposed to be connected to, it's because the CRTC has ++ * not been registered yet. Defer probing, and hope that ++ * the required CRTC is added later. ++ */ ++ if (encoder->possible_crtcs == 0) ++ return -EPROBE_DEFER; ++ ++ hdmi->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "rockchip,grf"); ++ if (IS_ERR(hdmi->regmap)) { ++ drm_err(hdmi, "Unable to get rockchip,grf\n"); ++ return PTR_ERR(hdmi->regmap); ++ } ++ ++ hdmi->vo1_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "rockchip,vo1_grf"); ++ if (IS_ERR(hdmi->vo1_regmap)) { ++ drm_err(hdmi, "Unable to get rockchip,vo1_grf\n"); ++ return PTR_ERR(hdmi->vo1_regmap); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(clk_names); i++) { ++ clk = devm_clk_get_optional_enabled(hdmi->dev, clk_names[i]); ++ ++ if (IS_ERR(clk)) { ++ ret = PTR_ERR(clk); ++ if (ret != -EPROBE_DEFER) ++ drm_err(hdmi, "Failed to get %s clock: %d\n", ++ clk_names[i], ret); ++ return ret; ++ } ++ } ++ ++ hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable", ++ GPIOD_OUT_HIGH); ++ if (IS_ERR(hdmi->enable_gpio)) { ++ ret = PTR_ERR(hdmi->enable_gpio); ++ drm_err(hdmi, "Failed to request enable GPIO: %d\n", ret); ++ return ret; ++ } ++ ++ hdmi->phy = devm_phy_get(dev, "hdmi"); ++ if (IS_ERR(hdmi->phy)) { ++ ret = PTR_ERR(hdmi->phy); ++ if (ret != -EPROBE_DEFER) ++ drm_err(hdmi, "failed to get phy: %d\n", ret); ++ return ret; ++ } ++ ++ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | ++ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | ++ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | ++ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); ++ ++ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, ++ RK3588_SET_HPD_PATH_MASK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); ++ ++ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, ++ RK3588_HDMI0_GRANT_SEL); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); ++ ++ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); ++ ++ INIT_DELAYED_WORK(&hdmi->hpd_work, dw_hdmi_qp_rk3588_hpd_work); ++ ++ irq = platform_get_irq_byname(pdev, "hpd"); ++ if (irq < 0) ++ return irq; ++ ++ ret = devm_request_threaded_irq(hdmi->dev, irq, ++ dw_hdmi_qp_rk3588_hardirq, ++ dw_hdmi_qp_rk3588_irq, ++ IRQF_SHARED, "dw-hdmi-qp-hpd", ++ hdmi); ++ if (ret) ++ return ret; ++ ++ drm_encoder_helper_add(encoder, &dw_hdmi_qp_rockchip_encoder_helper_funcs); ++ drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); ++ ++ platform_set_drvdata(pdev, hdmi); ++ ++ hdmi->hdmi = dw_hdmi_qp_bind(pdev, encoder, &plat_data); ++ if (IS_ERR(hdmi->hdmi)) { ++ ret = PTR_ERR(hdmi->hdmi); ++ drm_encoder_cleanup(encoder); ++ return ret; ++ } ++ ++ connector = drm_bridge_connector_init(drm, encoder); ++ if (IS_ERR(connector)) { ++ ret = PTR_ERR(connector); ++ drm_err(hdmi, "failed to init bridge connector: %d\n", ret); ++ return ret; ++ } ++ ++ return drm_connector_attach_encoder(connector, encoder); ++} ++ ++static void dw_hdmi_qp_rockchip_unbind(struct device *dev, ++ struct device *master, ++ void *data) ++{ ++ struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev); ++ ++ cancel_delayed_work_sync(&hdmi->hpd_work); ++ dw_hdmi_qp_unbind(hdmi->hdmi); ++ ++ drm_encoder_cleanup(&hdmi->encoder.encoder); ++} ++ ++static const struct component_ops dw_hdmi_qp_rockchip_ops = { ++ .bind = dw_hdmi_qp_rockchip_bind, ++ .unbind = dw_hdmi_qp_rockchip_unbind, ++}; ++ ++static int dw_hdmi_qp_rockchip_probe(struct platform_device *pdev) ++{ ++ return component_add(&pdev->dev, &dw_hdmi_qp_rockchip_ops); ++} ++ ++static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev) ++{ ++ component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops); ++} ++ ++static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev) ++{ ++ struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev); ++ u32 val; ++ ++ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | ++ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | ++ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | ++ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); ++ ++ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, ++ RK3588_SET_HPD_PATH_MASK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); ++ ++ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, ++ RK3588_HDMI0_GRANT_SEL); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); ++ ++ dw_hdmi_qp_resume(dev, hdmi->hdmi); ++ ++ if (hdmi->encoder.encoder.dev) ++ drm_helper_hpd_irq_event(hdmi->encoder.encoder.dev); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = { ++ SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_qp_rockchip_resume) ++}; ++ ++struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = { ++ .probe = dw_hdmi_qp_rockchip_probe, ++ .remove_new = dw_hdmi_qp_rockchip_remove, ++ .driver = { ++ .name = "dwhdmiqp-rockchip", ++ .pm = &dw_hdmi_qp_rockchip_pm, ++ .of_match_table = dw_hdmi_qp_rockchip_dt_ids, ++ }, ++}; +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +index 44d769d9234d..04ef7a2c3833 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +@@ -503,6 +503,8 @@ static int __init rockchip_drm_init(void) + ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP); + ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver, + CONFIG_ROCKCHIP_DW_HDMI); ++ ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_qp_rockchip_pltfm_driver, ++ CONFIG_ROCKCHIP_DW_HDMI_QP); + ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_rockchip_driver, + CONFIG_ROCKCHIP_DW_MIPI_DSI); + ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI); +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +index 8d566fcd80a2..24b4ce5ceaf1 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +@@ -88,6 +88,7 @@ int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rencoder, + int rockchip_drm_endpoint_is_subdriver(struct device_node *ep); + extern struct platform_driver cdn_dp_driver; + extern struct platform_driver dw_hdmi_rockchip_pltfm_driver; ++extern struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver; + extern struct platform_driver dw_mipi_dsi_rockchip_driver; + extern struct platform_driver inno_hdmi_driver; + extern struct platform_driver rockchip_dp_driver; +-- +2.45.2 + + +From e7fc4fbd45f0b18442e94ab60a29a71f435d6103 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Thu, 11 Jul 2024 14:48:43 +0300 +Subject: [PATCH 7/7] arm64: defconfig: Enable Rockchip extensions for Synopsys + DW HDMI QP + +Enable Rockchip specific extensions for the Synopsys DesignWare HDMI QP +driver. + +This is needed for the HDMI output support on RK3588 SoC based boards. + +Signed-off-by: Cristian Ciocaltea +--- + arch/arm64/configs/defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig +index 7d32fca64996..d8b6419d9724 100644 +--- a/arch/arm64/configs/defconfig ++++ b/arch/arm64/configs/defconfig +@@ -864,6 +864,7 @@ CONFIG_ROCKCHIP_VOP2=y + CONFIG_ROCKCHIP_ANALOGIX_DP=y + CONFIG_ROCKCHIP_CDN_DP=y + CONFIG_ROCKCHIP_DW_HDMI=y ++CONFIG_ROCKCHIP_DW_HDMI_QP=y + CONFIG_ROCKCHIP_DW_MIPI_DSI=y + CONFIG_ROCKCHIP_INNO_HDMI=y + CONFIG_ROCKCHIP_LVDS=y +-- +2.45.2 + diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0135-arm64-dts-rockchip-Add-HDMI0-bridge-CLK-to-rk3588.patch similarity index 51% rename from patch/kernel/archive/rockchip-rk3588-6.11/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch rename to patch/kernel/archive/rockchip-rk3588-6.11/0135-arm64-dts-rockchip-Add-HDMI0-bridge-CLK-to-rk3588.patch index d87dbea11..8fdf4863e 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.11/0135-arm64-dts-rockchip-Add-HDMI0-bridge-CLK-to-rk3588.patch @@ -1,68 +1,55 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 719faa1ed1fbe8b998cd3c2d3f846503767bbf8c Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Mon, 15 Jan 2024 22:47:41 +0200 -Subject: arm64: dts: rockchip: Add HDMI0 bridge to rk3588 +Subject: [PATCH 1/6] arm64: dts: rockchip: Add HDMI0 bridge to rk3588 Add DT node for the HDMI0 bridge found on RK3588 SoC. Signed-off-by: Cristian Ciocaltea --- - arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 55 ++++++++++ - 1 file changed, 55 insertions(+) + arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 42 +++++++++++++++++++ + 1 file changed, 42 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi -index 111111111111..222222222222 100644 +index b6e4df180f0b..c24c042818d9 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi -@@ -1254,6 +1254,61 @@ i2s9_8ch: i2s@fddfc000 { +@@ -1254,6 +1254,48 @@ i2s9_8ch: i2s@fddfc000 { status = "disabled"; }; + hdmi0: hdmi@fde80000 { -+ compatible = "rockchip,rk3588-dw-hdmi"; ++ compatible = "rockchip,rk3588-dw-hdmi-qp"; + reg = <0x0 0xfde80000 0x0 0x20000>; ++ clocks = <&cru PCLK_HDMITX0>, ++ <&cru CLK_HDMITX0_EARC>, ++ <&cru CLK_HDMITX0_REF>, ++ <&cru MCLK_I2S5_8CH_TX>, ++ <&cru CLK_HDMIHDP0>, ++ <&cru HCLK_VO1>; ++ clock-names = "pclk", "earc", "ref", "aud", "hdp", "hclk_vo1"; + interrupts = , + , + , + , + ; -+ clocks = <&cru PCLK_HDMITX0>, -+ <&cru CLK_HDMIHDP0>, -+ <&cru CLK_HDMITX0_EARC>, -+ <&cru CLK_HDMITX0_REF>, -+ <&cru MCLK_I2S5_8CH_TX>, -+ <&cru DCLK_VOP0>, -+ <&cru DCLK_VOP1>, -+ <&cru DCLK_VOP2>, -+ <&cru DCLK_VOP3>, -+ <&cru HCLK_VO1>; -+ clock-names = "pclk", -+ "hpd", -+ "earc", -+ "hdmitx_ref", -+ "aud", -+ "dclk_vp0", -+ "dclk_vp1", -+ "dclk_vp2", -+ "dclk_vp3", -+ "hclk_vo1"; -+ resets = <&cru SRST_HDMITX0_REF>, <&cru SRST_HDMIHDP0>; -+ reset-names = "ref", "hdp"; -+ power-domains = <&power RK3588_PD_VO1>; ++ interrupt-names = "avp", "cec", "earc", "main", "hpd"; ++ phys = <&hdptxphy_hdmi0>; ++ phy-names = "hdmi"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmim0_tx0_cec &hdmim0_tx0_hpd + &hdmim0_tx0_scl &hdmim0_tx0_sda>; -+ reg-io-width = <4>; ++ power-domains = <&power RK3588_PD_VO1>; ++ resets = <&cru SRST_HDMITX0_REF>, <&cru SRST_HDMIHDP0>; ++ reset-names = "ref", "hdp"; + rockchip,grf = <&sys_grf>; + rockchip,vo1_grf = <&vo1_grf>; -+ phys = <&hdptxphy_hdmi0>; -+ phy-names = "hdmi"; + status = "disabled"; -+ ++ + ports { + #address-cells = <1>; + #size-cells = <0>; -+ ++ + hdmi0_in: port@0 { + reg = <0>; + }; @@ -77,5 +64,32 @@ index 111111111111..222222222222 100644 compatible = "rockchip,rk3588-qos", "syscon"; reg = <0x0 0xfdf35000 0x0 0x20>; -- -Armbian +2.45.2 + +From fe5d3825918416dce3c060d0d8397a425e87d6f8 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Tue, 16 Jan 2024 03:13:38 +0200 +Subject: [PATCH 4/6] [WIP] arm64: dts: rockchip: Enable HDMI0 PHY clk provider + on rk3588 + +The HDMI0 PHY can be used as a clock provider on RK3588, hence add the +missing #clock-cells property. +--- + arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +index c24c042818d9..90b4aa04ce1e 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +@@ -2696,6 +2696,7 @@ hdptxphy_hdmi0: phy@fed60000 { + reg = <0x0 0xfed60000 0x0 0x2000>; + clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>; + clock-names = "ref", "apb"; ++ #clock-cells = <0>; + #phy-cells = <0>; + resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>, + <&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>, +-- +2.45.2 diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch deleted file mode 100644 index 874158217..000000000 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Tue, 16 Jan 2024 03:13:38 +0200 -Subject: arm64: dts: rockchip: Enable HDMI0 PHY clk provider on rk3588 - -The HDMI0 PHY can be used as a clock provider on RK3588, hence add the -missing #clock-cells property. ---- - arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi -index 111111111111..222222222222 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi -@@ -2709,6 +2709,7 @@ hdptxphy_hdmi0: phy@fed60000 { - reg = <0x0 0xfed60000 0x0 0x2000>; - clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>; - clock-names = "ref", "apb"; -+ #clock-cells = <0>; - #phy-cells = <0>; - resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>, - <&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>, --- -Armbian - diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch deleted file mode 100644 index 43173de65..000000000 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Tue, 16 Jan 2024 19:27:40 +0200 -Subject: phy: phy-rockchip-samsung-hdptx: Add clock provider - -The HDMI PHY PLL can be used as an alternative dclk source to SoC CRU. -It provides more accurate clock rates required to properly support -various display modes, e.g. those relying on non-integer refresh rates. - -Also note this only works for HDMI 2.0 or bellow, e.g. cannot be used to -support HDMI 2.1 4K@120Hz mode. - -Signed-off-by: Cristian Ciocaltea ---- - drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 148 +++++++++- - 1 file changed, 143 insertions(+), 5 deletions(-) - -diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c -index 111111111111..222222222222 100644 ---- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c -+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c -@@ -8,6 +8,7 @@ - */ - #include - #include -+#include - #include - #include - #include -@@ -279,6 +280,12 @@ struct rk_hdptx_phy { - int nr_clks; - struct reset_control_bulk_data rsts[RST_MAX]; - bool earc_en; -+ -+ /* clk provider */ -+ struct clk_hw hw; -+ unsigned long rate; -+ int id; -+ int count; - }; - - static const struct lcpll_config lcpll_cfg[] = { -@@ -1031,6 +1038,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, - const struct ropll_config *cfg = NULL; - struct ropll_config rc = {0}; - -+ hdptx->rate = rate * 100; -+ - if (color_depth) - rate = rate * 10 / 8; - -@@ -1315,11 +1324,13 @@ static int rk_hdptx_phy_power_off(struct phy *phy) - { - struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); - u32 val; -- int ret; -+ int ret = 0; - -- ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); -- if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) -- rk_hdptx_phy_disable(hdptx); -+ if (hdptx->count == 0) { -+ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); -+ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) -+ rk_hdptx_phy_disable(hdptx); -+ } - - pm_runtime_put(hdptx->dev); - -@@ -1332,6 +1343,129 @@ static const struct phy_ops rk_hdptx_phy_ops = { - .owner = THIS_MODULE, - }; - -+static struct rk_hdptx_phy *to_rk_hdptx_phy(struct clk_hw *hw) -+{ -+ return container_of(hw, struct rk_hdptx_phy, hw); -+} -+ -+static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw) -+{ -+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); -+ int ret; -+ -+ ret = pm_runtime_resume_and_get(hdptx->dev); -+ if (ret) { -+ dev_err(hdptx->dev, "Failed to resume phy clk: %d\n", ret); -+ return ret; -+ } -+ -+ if (!hdptx->count && hdptx->rate) { -+ ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, hdptx->rate / 100); -+ if (ret < 0) { -+ dev_err(hdptx->dev, "Failed to init PHY PLL: %d\n", ret); -+ pm_runtime_put(hdptx->dev); -+ return ret; -+ } -+ } -+ -+ hdptx->count++; -+ -+ return 0; -+} -+ -+static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw) -+{ -+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); -+ -+ if (hdptx->count == 1) { -+ u32 val; -+ int ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); -+ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) -+ rk_hdptx_phy_disable(hdptx); -+ } -+ -+ hdptx->count--; -+ pm_runtime_put(hdptx->dev); -+} -+ -+static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); -+ -+ return hdptx->rate; -+} -+ -+static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *parent_rate) -+{ -+ const struct ropll_config *cfg = NULL; -+ u32 bit_rate = rate / 100; -+ int i; -+ -+ if (rate > HDMI20_MAX_RATE) -+ return rate; -+ -+ for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) -+ if (bit_rate == ropll_tmds_cfg[i].bit_rate) { -+ cfg = &ropll_tmds_cfg[i]; -+ break; -+ } -+ -+ if (!cfg && !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL)) -+ return -EINVAL; -+ -+ return rate; -+} -+ -+static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); -+ u32 val; -+ int ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); -+ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) -+ rk_hdptx_phy_disable(hdptx); -+ -+ return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100); -+} -+ -+static const struct clk_ops hdptx_phy_clk_ops = { -+ .prepare = rk_hdptx_phy_clk_prepare, -+ .unprepare = rk_hdptx_phy_clk_unprepare, -+ .recalc_rate = rk_hdptx_phy_clk_recalc_rate, -+ .round_rate = rk_hdptx_phy_clk_round_rate, -+ .set_rate = rk_hdptx_phy_clk_set_rate, -+}; -+ -+static int rk_hdptx_phy_clk_register(struct rk_hdptx_phy *hdptx) -+{ -+ struct device *dev = hdptx->dev; -+ const char *name, *pname; -+ struct clk *refclk; -+ int ret; -+ -+ refclk = devm_clk_get(dev, "ref"); -+ if (IS_ERR(refclk)) -+ return dev_err_probe(dev, PTR_ERR(refclk), -+ "Failed to get ref clock\n"); -+ -+ pname = __clk_get_name(refclk); -+ name = hdptx->id ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; -+ hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops, -+ CLK_GET_RATE_NOCACHE); -+ -+ ret = devm_clk_hw_register(dev, &hdptx->hw); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to register clock\n"); -+ -+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &hdptx->hw); -+ if (ret) -+ return dev_err_probe(dev, ret, -+ "Failed to register clk provider\n"); -+ return 0; -+} -+ - static int rk_hdptx_phy_runtime_suspend(struct device *dev) - { - struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev); -@@ -1367,6 +1501,10 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) - - hdptx->dev = dev; - -+ hdptx->id = of_alias_get_id(dev->of_node, "hdptxphy"); -+ if (hdptx->id < 0) -+ hdptx->id = 0; -+ - regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(regs)) - return dev_err_probe(dev, PTR_ERR(regs), -@@ -1426,7 +1564,7 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) - reset_control_deassert(hdptx->rsts[RST_CMN].rstc); - reset_control_deassert(hdptx->rsts[RST_INIT].rstc); - -- return 0; -+ return rk_hdptx_phy_clk_register(hdptx); - } - - static const struct dev_pm_ops rk_hdptx_phy_pm_ops = { --- -Armbian - diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch deleted file mode 100644 index c4994f7d9..000000000 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch +++ /dev/null @@ -1,6616 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Wed, 1 Nov 2023 18:50:38 +0200 -Subject: [WIP] drm/bridge: synopsys: Add initial support for DW HDMI QP TX - Controller - -Co-developed-by: Algea Cao -Signed-off-by: Algea Cao -Signed-off-by: Cristian Ciocaltea ---- - drivers/gpu/drm/bridge/synopsys/Makefile | 2 +- - drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 2401 ++++++++ - drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h | 831 +++ - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 89 + - drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 4 + - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2740 +++++++++- - include/drm/bridge/dw_hdmi.h | 101 + - 7 files changed, 6102 insertions(+), 66 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile -index 111111111111..222222222222 100644 ---- a/drivers/gpu/drm/bridge/synopsys/Makefile -+++ b/drivers/gpu/drm/bridge/synopsys/Makefile -@@ -1,5 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0-only --obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o -+obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o dw-hdmi-qp.o - obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o - obj-$(CONFIG_DRM_DW_HDMI_GP_AUDIO) += dw-hdmi-gp-audio.o - obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c -@@ -0,0 +1,2401 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright (C) Rockchip Electronics Co.Ltd -+ * Author: -+ * Algea Cao -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "dw-hdmi-qp.h" -+ -+#define DDC_CI_ADDR 0x37 -+#define DDC_SEGMENT_ADDR 0x30 -+ -+#define HDMI_EDID_LEN 512 -+ -+/* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */ -+#define SCDC_MIN_SOURCE_VERSION 0x1 -+ -+#define HDMI14_MAX_TMDSCLK 340000000 -+#define HDMI20_MAX_TMDSCLK_KHZ 600000 -+ -+static const unsigned int dw_hdmi_cable[] = { -+ EXTCON_DISP_HDMI, -+ EXTCON_NONE, -+}; -+ -+static const struct drm_display_mode dw_hdmi_default_modes[] = { -+ /* 16 - 1920x1080@60Hz 16:9 */ -+ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008, -+ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, -+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), -+ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, -+ /* 2 - 720x480@60Hz 4:3 */ -+ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736, -+ 798, 858, 0, 480, 489, 495, 525, 0, -+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), -+ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, -+ /* 4 - 1280x720@60Hz 16:9 */ -+ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390, -+ 1430, 1650, 0, 720, 725, 730, 750, 0, -+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), -+ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, -+ /* 31 - 1920x1080@50Hz 16:9 */ -+ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448, -+ 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, -+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), -+ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, -+ /* 19 - 1280x720@50Hz 16:9 */ -+ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720, -+ 1760, 1980, 0, 720, 725, 730, 750, 0, -+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), -+ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, -+ /* 17 - 720x576@50Hz 4:3 */ -+ { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732, -+ 796, 864, 0, 576, 581, 586, 625, 0, -+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), -+ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, -+ /* 2 - 720x480@60Hz 4:3 */ -+ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736, -+ 798, 858, 0, 480, 489, 495, 525, 0, -+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), -+ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, -+}; -+ -+enum frl_mask { -+ FRL_3GBPS_3LANE = 1, -+ FRL_6GBPS_3LANE, -+ FRL_6GBPS_4LANE, -+ FRL_8GBPS_4LANE, -+ FRL_10GBPS_4LANE, -+ FRL_12GBPS_4LANE, -+}; -+ -+struct hdmi_vmode_qp { -+ bool mdataenablepolarity; -+ -+ unsigned int previous_pixelclock; -+ unsigned long mpixelclock; -+ unsigned int mpixelrepetitioninput; -+ unsigned int mpixelrepetitionoutput; -+ unsigned long previous_tmdsclock; -+ unsigned int mtmdsclock; -+}; -+ -+struct hdmi_qp_data_info { -+ unsigned int enc_in_bus_format; -+ unsigned int enc_out_bus_format; -+ unsigned int enc_in_encoding; -+ unsigned int enc_out_encoding; -+ unsigned int quant_range; -+ unsigned int pix_repet_factor; -+ struct hdmi_vmode_qp video_mode; -+ bool update; -+}; -+ -+struct dw_hdmi_qp_i2c { -+ struct i2c_adapter adap; -+ -+ struct mutex lock; /* used to serialize data transfers */ -+ struct completion cmp; -+ u32 stat; -+ -+ u8 slave_reg; -+ bool is_regaddr; -+ bool is_segment; -+ -+ unsigned int scl_high_ns; -+ unsigned int scl_low_ns; -+}; -+ -+struct dw_hdmi_qp { -+ struct drm_connector connector; -+ struct drm_bridge bridge; -+ struct platform_device *hdcp_dev; -+ struct platform_device *audio; -+ struct platform_device *cec; -+ struct device *dev; -+ struct dw_hdmi_qp_i2c *i2c; -+ -+ struct hdmi_qp_data_info hdmi_data; -+ const struct dw_hdmi_plat_data *plat_data; -+ -+ int vic; -+ int main_irq; -+ int avp_irq; -+ int earc_irq; -+ -+ u8 edid[HDMI_EDID_LEN]; -+ -+ struct { -+ const struct dw_hdmi_qp_phy_ops *ops; -+ const char *name; -+ void *data; -+ bool enabled; -+ } phy; -+ -+ struct drm_display_mode previous_mode; -+ -+ struct i2c_adapter *ddc; -+ void __iomem *regs; -+ bool sink_is_hdmi; -+ -+ struct mutex mutex; /* for state below and previous_mode */ -+ //[CC:] curr_conn should be removed -+ struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */ -+ enum drm_connector_force force; /* mutex-protected force state */ -+ bool disabled; /* DRM has disabled our bridge */ -+ bool bridge_is_on; /* indicates the bridge is on */ -+ bool rxsense; /* rxsense state */ -+ u8 phy_mask; /* desired phy int mask settings */ -+ u8 mc_clkdis; /* clock disable register */ -+ -+ u32 scdc_intr; -+ u32 flt_intr; -+ //[CC:] remove earc -+ u32 earc_intr; -+ -+ struct dentry *debugfs_dir; -+ bool scramble_low_rates; -+ -+ struct extcon_dev *extcon; -+ -+ struct regmap *regm; -+ -+ bool initialized; /* hdmi is enabled before bind */ -+ struct completion flt_cmp; -+ struct completion earc_cmp; -+ -+ hdmi_codec_plugged_cb plugged_cb; -+ struct device *codec_dev; -+ enum drm_connector_status last_connector_result; -+}; -+ -+static inline void hdmi_writel(struct dw_hdmi_qp *hdmi, u32 val, int offset) -+{ -+ regmap_write(hdmi->regm, offset, val); -+} -+ -+static inline u32 hdmi_readl(struct dw_hdmi_qp *hdmi, int offset) -+{ -+ unsigned int val = 0; -+ -+ regmap_read(hdmi->regm, offset, &val); -+ -+ return val; -+} -+ -+static void handle_plugged_change(struct dw_hdmi_qp *hdmi, bool plugged) -+{ -+ if (hdmi->plugged_cb && hdmi->codec_dev) -+ hdmi->plugged_cb(hdmi->codec_dev, plugged); -+} -+ -+static void hdmi_modb(struct dw_hdmi_qp *hdmi, u32 data, u32 mask, u32 reg) -+{ -+ regmap_update_bits(hdmi->regm, reg, mask, data); -+} -+ -+static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ case MEDIA_BUS_FMT_RGB121212_1X36: -+ case MEDIA_BUS_FMT_RGB161616_1X48: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_YUV12_1X36: -+ case MEDIA_BUS_FMT_YUV16_1X48: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ case MEDIA_BUS_FMT_UYVY10_1X20: -+ case MEDIA_BUS_FMT_UYVY12_1X24: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36: -+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+static int hdmi_bus_fmt_color_depth(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ return 8; -+ -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_UYVY10_1X20: -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ return 10; -+ -+ case MEDIA_BUS_FMT_RGB121212_1X36: -+ case MEDIA_BUS_FMT_YUV12_1X36: -+ case MEDIA_BUS_FMT_UYVY12_1X24: -+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36: -+ return 12; -+ -+ case MEDIA_BUS_FMT_RGB161616_1X48: -+ case MEDIA_BUS_FMT_YUV16_1X48: -+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48: -+ return 16; -+ -+ default: -+ return 0; -+ } -+} -+ -+static void dw_hdmi_i2c_init(struct dw_hdmi_qp *hdmi) -+{ -+ /* Software reset */ -+ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); -+ -+ hdmi_writel(hdmi, 0x085c085c, I2CM_FM_SCL_CONFIG0); -+ -+ hdmi_modb(hdmi, 0, I2CM_FM_EN, I2CM_INTERFACE_CONTROL0); -+ -+ /* Clear DONE and ERROR interrupts */ -+ hdmi_writel(hdmi, I2CM_OP_DONE_CLEAR | I2CM_NACK_RCVD_CLEAR, -+ MAINUNIT_1_INT_CLEAR); -+} -+ -+static int dw_hdmi_i2c_read(struct dw_hdmi_qp *hdmi, -+ unsigned char *buf, unsigned int length) -+{ -+ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; -+ int stat; -+ -+ if (!i2c->is_regaddr) { -+ dev_dbg(hdmi->dev, "set read register address to 0\n"); -+ i2c->slave_reg = 0x00; -+ i2c->is_regaddr = true; -+ } -+ -+ while (length--) { -+ reinit_completion(&i2c->cmp); -+ -+ hdmi_modb(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, -+ I2CM_INTERFACE_CONTROL0); -+ -+ hdmi_modb(hdmi, I2CM_FM_READ, I2CM_WR_MASK, -+ I2CM_INTERFACE_CONTROL0); -+ -+ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); -+ if (!stat) { -+ dev_err(hdmi->dev, "i2c read time out!\n"); -+ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); -+ return -EAGAIN; -+ } -+ -+ /* Check for error condition on the bus */ -+ if (i2c->stat & I2CM_NACK_RCVD_IRQ) { -+ dev_err(hdmi->dev, "i2c read err!\n"); -+ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); -+ return -EIO; -+ } -+ -+ *buf++ = hdmi_readl(hdmi, I2CM_INTERFACE_RDDATA_0_3) & 0xff; -+ hdmi_modb(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0); -+ } -+ i2c->is_segment = false; -+ -+ return 0; -+} -+ -+static int dw_hdmi_i2c_write(struct dw_hdmi_qp *hdmi, -+ unsigned char *buf, unsigned int length) -+{ -+ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; -+ int stat; -+ -+ if (!i2c->is_regaddr) { -+ /* Use the first write byte as register address */ -+ i2c->slave_reg = buf[0]; -+ length--; -+ buf++; -+ i2c->is_regaddr = true; -+ } -+ -+ while (length--) { -+ reinit_completion(&i2c->cmp); -+ -+ hdmi_writel(hdmi, *buf++, I2CM_INTERFACE_WRDATA_0_3); -+ hdmi_modb(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, -+ I2CM_INTERFACE_CONTROL0); -+ hdmi_modb(hdmi, I2CM_FM_WRITE, I2CM_WR_MASK, -+ I2CM_INTERFACE_CONTROL0); -+ -+ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); -+ if (!stat) { -+ dev_err(hdmi->dev, "i2c write time out!\n"); -+ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); -+ return -EAGAIN; -+ } -+ -+ /* Check for error condition on the bus */ -+ if (i2c->stat & I2CM_NACK_RCVD_IRQ) { -+ dev_err(hdmi->dev, "i2c write nack!\n"); -+ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); -+ return -EIO; -+ } -+ hdmi_modb(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0); -+ } -+ -+ return 0; -+} -+ -+static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap, -+ struct i2c_msg *msgs, int num) -+{ -+ struct dw_hdmi_qp *hdmi = i2c_get_adapdata(adap); -+ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; -+ u8 addr = msgs[0].addr; -+ int i, ret = 0; -+ -+ if (addr == DDC_CI_ADDR) -+ /* -+ * The internal I2C controller does not support the multi-byte -+ * read and write operations needed for DDC/CI. -+ * TOFIX: Blacklist the DDC/CI address until we filter out -+ * unsupported I2C operations. -+ */ -+ return -EOPNOTSUPP; -+ -+ for (i = 0; i < num; i++) { -+ if (msgs[i].len == 0) { -+ dev_err(hdmi->dev, -+ "unsupported transfer %d/%d, no data\n", -+ i + 1, num); -+ return -EOPNOTSUPP; -+ } -+ } -+ -+ mutex_lock(&i2c->lock); -+ -+ /* Unmute DONE and ERROR interrupts */ -+ hdmi_modb(hdmi, I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N, -+ I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N, -+ MAINUNIT_1_INT_MASK_N); -+ -+ /* Set slave device address taken from the first I2C message */ -+ if (addr == DDC_SEGMENT_ADDR && msgs[0].len == 1) -+ addr = DDC_ADDR; -+ -+ hdmi_modb(hdmi, addr << 5, I2CM_SLVADDR, I2CM_INTERFACE_CONTROL0); -+ -+ /* Set slave device register address on transfer */ -+ i2c->is_regaddr = false; -+ -+ /* Set segment pointer for I2C extended read mode operation */ -+ i2c->is_segment = false; -+ -+ for (i = 0; i < num; i++) { -+ if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) { -+ i2c->is_segment = true; -+ hdmi_modb(hdmi, DDC_SEGMENT_ADDR, I2CM_SEG_ADDR, -+ I2CM_INTERFACE_CONTROL1); -+ hdmi_modb(hdmi, *msgs[i].buf, I2CM_SEG_PTR, -+ I2CM_INTERFACE_CONTROL1); -+ } else { -+ if (msgs[i].flags & I2C_M_RD) -+ ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, -+ msgs[i].len); -+ else -+ ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, -+ msgs[i].len); -+ } -+ if (ret < 0) -+ break; -+ } -+ -+ if (!ret) -+ ret = num; -+ -+ /* Mute DONE and ERROR interrupts */ -+ hdmi_modb(hdmi, 0, I2CM_OP_DONE_MASK_N | I2CM_NACK_RCVD_MASK_N, -+ MAINUNIT_1_INT_MASK_N); -+ -+ mutex_unlock(&i2c->lock); -+ -+ return ret; -+} -+ -+static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -+} -+ -+static const struct i2c_algorithm dw_hdmi_algorithm = { -+ .master_xfer = dw_hdmi_i2c_xfer, -+ .functionality = dw_hdmi_i2c_func, -+}; -+ -+static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi_qp *hdmi) -+{ -+ struct i2c_adapter *adap; -+ struct dw_hdmi_qp_i2c *i2c; -+ int ret; -+ -+ i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL); -+ if (!i2c) -+ return ERR_PTR(-ENOMEM); -+ -+ mutex_init(&i2c->lock); -+ init_completion(&i2c->cmp); -+ -+ adap = &i2c->adap; -+ adap->owner = THIS_MODULE; -+ adap->dev.parent = hdmi->dev; -+ adap->algo = &dw_hdmi_algorithm; -+ strscpy(adap->name, "ddc", sizeof(adap->name)); -+ i2c_set_adapdata(adap, hdmi); -+ -+ ret = i2c_add_adapter(adap); -+ if (ret) { -+ dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name); -+ devm_kfree(hdmi->dev, i2c); -+ return ERR_PTR(ret); -+ } -+ -+ hdmi->i2c = i2c; -+ -+ dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); -+ -+ return adap; -+} -+ -+#define HDMI_PHY_EARC_MASK BIT(29) -+ -+/* ----------------------------------------------------------------------------- -+ * HDMI TX Setup -+ */ -+ -+static void hdmi_infoframe_set_checksum(u8 *ptr, int size) -+{ -+ u8 csum = 0; -+ int i; -+ -+ ptr[3] = 0; -+ /* compute checksum */ -+ for (i = 0; i < size; i++) -+ csum += ptr[i]; -+ -+ ptr[3] = 256 - csum; -+} -+ -+static void hdmi_config_AVI(struct dw_hdmi_qp *hdmi, -+ const struct drm_connector *connector, -+ const struct drm_display_mode *mode) -+{ -+ struct hdmi_avi_infoframe frame; -+ u32 val, i, j; -+ u8 buff[17]; -+ enum hdmi_quantization_range rgb_quant_range = -+ hdmi->hdmi_data.quant_range; -+ -+ /* Initialise info frame from DRM mode */ -+ drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode); -+ -+ /* -+ * Ignore monitor selectable quantization, use quantization set -+ * by the user -+ */ -+ drm_hdmi_avi_infoframe_quant_range(&frame, connector, mode, rgb_quant_range); -+ if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) -+ frame.colorspace = HDMI_COLORSPACE_YUV444; -+ else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) -+ frame.colorspace = HDMI_COLORSPACE_YUV422; -+ else if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) -+ frame.colorspace = HDMI_COLORSPACE_YUV420; -+ else -+ frame.colorspace = HDMI_COLORSPACE_RGB; -+ -+ /* Set up colorimetry */ -+ 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) -+ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; -+ else -+ frame.colorimetry = HDMI_COLORIMETRY_ITU_601; -+ frame.extended_colorimetry = -+ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; -+ break; -+ case V4L2_YCBCR_ENC_709: -+ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709) -+ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; -+ else -+ frame.colorimetry = HDMI_COLORIMETRY_ITU_709; -+ frame.extended_colorimetry = -+ HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; -+ break; -+ case V4L2_YCBCR_ENC_BT2020: -+ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_BT2020) -+ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; -+ else -+ frame.colorimetry = HDMI_COLORIMETRY_ITU_709; -+ frame.extended_colorimetry = -+ HDMI_EXTENDED_COLORIMETRY_BT2020; -+ break; -+ default: /* Carries no data */ -+ frame.colorimetry = HDMI_COLORIMETRY_ITU_601; -+ frame.extended_colorimetry = -+ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; -+ break; -+ } -+ } else { -+ if (hdmi->hdmi_data.enc_out_encoding == V4L2_YCBCR_ENC_BT2020) { -+ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; -+ frame.extended_colorimetry = -+ HDMI_EXTENDED_COLORIMETRY_BT2020; -+ } else { -+ frame.colorimetry = HDMI_COLORIMETRY_NONE; -+ frame.extended_colorimetry = -+ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; -+ } -+ } -+ -+ frame.scan_mode = HDMI_SCAN_MODE_NONE; -+ frame.video_code = hdmi->vic; -+ -+ hdmi_avi_infoframe_pack_only(&frame, buff, 17); -+ -+ /* mode which vic >= 128 must use avi version 3 */ -+ if (hdmi->vic >= 128) { -+ frame.version = 3; -+ buff[1] = frame.version; -+ buff[4] &= 0x1f; -+ buff[4] |= ((frame.colorspace & 0x7) << 5); -+ buff[7] = frame.video_code; -+ hdmi_infoframe_set_checksum(buff, 17); -+ } -+ -+ /* -+ * The Designware IP uses a different byte format from standard -+ * AVI info frames, though generally the bits are in the correct -+ * bytes. -+ */ -+ -+ val = (frame.version << 8) | (frame.length << 16); -+ hdmi_writel(hdmi, val, PKT_AVI_CONTENTS0); -+ -+ for (i = 0; i < 4; i++) { -+ for (j = 0; j < 4; j++) { -+ if (i * 4 + j >= 14) -+ break; -+ if (!j) -+ val = buff[i * 4 + j + 3]; -+ val |= buff[i * 4 + j + 3] << (8 * j); -+ } -+ -+ hdmi_writel(hdmi, val, PKT_AVI_CONTENTS1 + i * 4); -+ } -+ -+ hdmi_modb(hdmi, 0, PKTSCHED_AVI_FIELDRATE, PKTSCHED_PKT_CONFIG1); -+ -+ hdmi_modb(hdmi, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, -+ PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, -+ PKTSCHED_PKT_EN); -+} -+ -+static void hdmi_config_CVTEM(struct dw_hdmi_qp *hdmi) -+{ -+ u8 ds_type = 0; -+ u8 sync = 1; -+ u8 vfr = 1; -+ u8 afr = 0; -+ u8 new = 1; -+ u8 end = 0; -+ u8 data_set_length = 136; -+ u8 hb1[6] = { 0x80, 0, 0, 0, 0, 0x40 }; -+ u8 *pps_body; -+ u32 val, i, reg; -+ struct drm_display_mode *mode = &hdmi->previous_mode; -+ int hsync, hfront, hback; -+ struct dw_hdmi_link_config *link_cfg; -+ void *data = hdmi->plat_data->phy_data; -+ -+ hdmi_modb(hdmi, 0, PKTSCHED_EMP_CVTEM_TX_EN, PKTSCHED_PKT_EN); -+ -+ if (hdmi->plat_data->get_link_cfg) { -+ link_cfg = hdmi->plat_data->get_link_cfg(data); -+ } else { -+ dev_err(hdmi->dev, "can't get frl link cfg\n"); -+ return; -+ } -+ -+ if (!link_cfg->dsc_mode) { -+ dev_info(hdmi->dev, "don't use dsc mode\n"); -+ return; -+ } -+ -+ pps_body = link_cfg->pps_payload; -+ -+ hsync = mode->hsync_end - mode->hsync_start; -+ hback = mode->htotal - mode->hsync_end; -+ hfront = mode->hsync_start - mode->hdisplay; -+ -+ for (i = 0; i < 6; i++) { -+ val = i << 16 | hb1[i] << 8; -+ hdmi_writel(hdmi, val, PKT0_EMP_CVTEM_CONTENTS0 + i * 0x20); -+ } -+ -+ val = new << 7 | end << 6 | ds_type << 4 | afr << 3 | -+ vfr << 2 | sync << 1; -+ hdmi_writel(hdmi, val, PKT0_EMP_CVTEM_CONTENTS1); -+ -+ val = data_set_length << 16 | pps_body[0] << 24; -+ hdmi_writel(hdmi, val, PKT0_EMP_CVTEM_CONTENTS2); -+ -+ reg = PKT0_EMP_CVTEM_CONTENTS3; -+ for (i = 1; i < 125; i++) { -+ if (reg == PKT1_EMP_CVTEM_CONTENTS0 || -+ reg == PKT2_EMP_CVTEM_CONTENTS0 || -+ reg == PKT3_EMP_CVTEM_CONTENTS0 || -+ reg == PKT4_EMP_CVTEM_CONTENTS0 || -+ reg == PKT5_EMP_CVTEM_CONTENTS0) { -+ reg += 4; -+ i--; -+ continue; -+ } -+ if (i % 4 == 1) -+ val = pps_body[i]; -+ if (i % 4 == 2) -+ val |= pps_body[i] << 8; -+ if (i % 4 == 3) -+ val |= pps_body[i] << 16; -+ if (!(i % 4)) { -+ val |= pps_body[i] << 24; -+ hdmi_writel(hdmi, val, reg); -+ reg += 4; -+ } -+ } -+ -+ val = (hfront & 0xff) << 24 | pps_body[127] << 16 | -+ pps_body[126] << 8 | pps_body[125]; -+ hdmi_writel(hdmi, val, PKT4_EMP_CVTEM_CONTENTS6); -+ -+ val = (hback & 0xff) << 24 | ((hsync >> 8) & 0xff) << 16 | -+ (hsync & 0xff) << 8 | ((hfront >> 8) & 0xff); -+ hdmi_writel(hdmi, val, PKT4_EMP_CVTEM_CONTENTS7); -+ -+ val = link_cfg->hcactive << 8 | ((hback >> 8) & 0xff); -+ hdmi_writel(hdmi, val, PKT5_EMP_CVTEM_CONTENTS1); -+ -+ for (i = PKT5_EMP_CVTEM_CONTENTS2; i <= PKT5_EMP_CVTEM_CONTENTS7; i += 4) -+ hdmi_writel(hdmi, 0, i); -+ -+ hdmi_modb(hdmi, PKTSCHED_EMP_CVTEM_TX_EN, PKTSCHED_EMP_CVTEM_TX_EN, -+ PKTSCHED_PKT_EN); -+} -+ -+static void hdmi_config_drm_infoframe(struct dw_hdmi_qp *hdmi, -+ const struct drm_connector *connector) -+{ -+ const struct drm_connector_state *conn_state = connector->state; -+ struct hdr_output_metadata *hdr_metadata; -+ struct hdmi_drm_infoframe frame; -+ u8 buffer[30]; -+ ssize_t err; -+ int i; -+ u32 val; -+ -+ if (!hdmi->plat_data->use_drm_infoframe) -+ return; -+ -+ hdmi_modb(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN); -+ -+ if (!hdmi->connector.hdr_sink_metadata.hdmi_type1.eotf) { -+ DRM_DEBUG("No need to set HDR metadata in infoframe\n"); -+ return; -+ } -+ -+ if (!conn_state->hdr_output_metadata) { -+ DRM_DEBUG("source metadata not set yet\n"); -+ return; -+ } -+ -+ hdr_metadata = (struct hdr_output_metadata *) -+ conn_state->hdr_output_metadata->data; -+ -+ if (!(hdmi->connector.hdr_sink_metadata.hdmi_type1.eotf & -+ BIT(hdr_metadata->hdmi_metadata_type1.eotf))) { -+ DRM_ERROR("Not support EOTF %d\n", -+ hdr_metadata->hdmi_metadata_type1.eotf); -+ return; -+ } -+ -+ err = drm_hdmi_infoframe_set_hdr_metadata(&frame, conn_state); -+ if (err < 0) -+ return; -+ -+ err = hdmi_drm_infoframe_pack(&frame, buffer, sizeof(buffer)); -+ if (err < 0) { -+ dev_err(hdmi->dev, "Failed to pack drm infoframe: %zd\n", err); -+ return; -+ } -+ -+ val = (frame.version << 8) | (frame.length << 16); -+ hdmi_writel(hdmi, val, PKT_DRMI_CONTENTS0); -+ -+ for (i = 0; i <= frame.length; i++) { -+ if (i % 4 == 0) -+ val = buffer[3 + i]; -+ val |= buffer[3 + i] << ((i % 4) * 8); -+ -+ if (i % 4 == 3 || (i == (frame.length))) -+ hdmi_writel(hdmi, val, PKT_DRMI_CONTENTS1 + ((i / 4) * 4)); -+ } -+ -+ hdmi_modb(hdmi, 0, PKTSCHED_DRMI_FIELDRATE, PKTSCHED_PKT_CONFIG1); -+ -+ hdmi_modb(hdmi, PKTSCHED_DRMI_TX_EN, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN); -+ -+ DRM_DEBUG("%s eotf %d end\n", __func__, -+ hdr_metadata->hdmi_metadata_type1.eotf); -+} -+ -+/* Filter out invalid setups to avoid configuring SCDC and scrambling */ -+static bool dw_hdmi_support_scdc(struct dw_hdmi_qp *hdmi, -+ const struct drm_display_info *display) -+{ -+ /* Disable if no DDC bus */ -+ if (!hdmi->ddc) -+ return false; -+ -+ /* Disable if SCDC is not supported, or if an HF-VSDB block is absent */ -+ if (!display->hdmi.scdc.supported || -+ !display->hdmi.scdc.scrambling.supported) -+ return false; -+ -+ /* -+ * Disable if display only support low TMDS rates and scrambling -+ * for low rates is not supported either -+ */ -+ if (!display->hdmi.scdc.scrambling.low_rates && -+ display->max_tmds_clock <= 340000) -+ return false; -+ -+ return true; -+} -+ -+static int hdmi_set_frl_mask(int frl_rate) -+{ -+ switch (frl_rate) { -+ case 48: -+ return FRL_12GBPS_4LANE; -+ case 40: -+ return FRL_10GBPS_4LANE; -+ case 32: -+ return FRL_8GBPS_4LANE; -+ case 24: -+ return FRL_6GBPS_4LANE; -+ case 18: -+ return FRL_6GBPS_3LANE; -+ case 9: -+ return FRL_3GBPS_3LANE; -+ } -+ -+ return 0; -+} -+ -+static int hdmi_start_flt(struct dw_hdmi_qp *hdmi, u8 rate) -+{ -+ u8 val; -+ u8 ffe_lv = 0; -+ int i = 0, stat; -+ -+ /* FLT_READY & FFE_LEVELS read */ -+ for (i = 0; i < 20; i++) { -+ drm_scdc_readb(hdmi->ddc, SCDC_STATUS_FLAGS_0, &val); -+ if (val & BIT(6)) -+ break; -+ msleep(20); -+ } -+ -+ if (i == 20) { -+ dev_err(hdmi->dev, "sink flt isn't ready\n"); -+ return -EINVAL; -+ } -+ -+ hdmi_modb(hdmi, SCDC_UPD_FLAGS_RD_IRQ, SCDC_UPD_FLAGS_RD_IRQ, -+ MAINUNIT_1_INT_MASK_N); -+ hdmi_modb(hdmi, SCDC_UPD_FLAGS_POLL_EN | SCDC_UPD_FLAGS_AUTO_CLR, -+ SCDC_UPD_FLAGS_POLL_EN | SCDC_UPD_FLAGS_AUTO_CLR, -+ SCDC_CONFIG0); -+ -+ /* max ffe level 3 */ -+ val = 3 << 4 | hdmi_set_frl_mask(rate); -+ drm_scdc_writeb(hdmi->ddc, 0x31, val); -+ -+ /* select FRL_RATE & FFE_LEVELS */ -+ hdmi_writel(hdmi, ffe_lv, FLT_CONFIG0); -+ -+ /* Start LTS_3 state in source DUT */ -+ reinit_completion(&hdmi->flt_cmp); -+ hdmi_modb(hdmi, FLT_EXIT_TO_LTSP_IRQ, FLT_EXIT_TO_LTSP_IRQ, -+ MAINUNIT_1_INT_MASK_N); -+ hdmi_writel(hdmi, 1, FLT_CONTROL0); -+ -+ /* wait for completed link training at source side */ -+ stat = wait_for_completion_timeout(&hdmi->flt_cmp, HZ * 2); -+ if (!stat) { -+ dev_err(hdmi->dev, "wait lts3 finish time out\n"); -+ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_POLL_EN | -+ SCDC_UPD_FLAGS_AUTO_CLR, SCDC_CONFIG0); -+ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_RD_IRQ, -+ MAINUNIT_1_INT_MASK_N); -+ return -EAGAIN; -+ } -+ -+ if (!(hdmi->flt_intr & FLT_EXIT_TO_LTSP_IRQ)) { -+ dev_err(hdmi->dev, "not to ltsp\n"); -+ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_POLL_EN | -+ SCDC_UPD_FLAGS_AUTO_CLR, SCDC_CONFIG0); -+ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_RD_IRQ, -+ MAINUNIT_1_INT_MASK_N); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+#define HDMI_MODE_FRL_MASK BIT(30) -+ -+static void hdmi_set_op_mode(struct dw_hdmi_qp *hdmi, -+ struct dw_hdmi_link_config *link_cfg, -+ const struct drm_connector *connector) -+{ -+ int frl_rate; -+ int i; -+ -+ /* set sink frl mode disable and wait sink ready */ -+ hdmi_writel(hdmi, 0, FLT_CONFIG0); -+ if (dw_hdmi_support_scdc(hdmi, &connector->display_info)) -+ drm_scdc_writeb(hdmi->ddc, 0x31, 0); -+ /* -+ * some TVs must wait a while before switching frl mode resolution, -+ * or the signal may not be recognized. -+ */ -+ msleep(200); -+ -+ if (!link_cfg->frl_mode) { -+ dev_info(hdmi->dev, "dw hdmi qp use tmds mode\n"); -+ hdmi_modb(hdmi, 0, OPMODE_FRL, LINK_CONFIG0); -+ hdmi_modb(hdmi, 0, OPMODE_FRL_4LANES, LINK_CONFIG0); -+ return; -+ } -+ -+ if (link_cfg->frl_lanes == 4) -+ hdmi_modb(hdmi, OPMODE_FRL_4LANES, OPMODE_FRL_4LANES, -+ LINK_CONFIG0); -+ else -+ hdmi_modb(hdmi, 0, OPMODE_FRL_4LANES, LINK_CONFIG0); -+ -+ hdmi_modb(hdmi, 1, OPMODE_FRL, LINK_CONFIG0); -+ -+ frl_rate = link_cfg->frl_lanes * link_cfg->rate_per_lane; -+ hdmi_start_flt(hdmi, frl_rate); -+ -+ for (i = 0; i < 50; i++) { -+ hdmi_modb(hdmi, PKTSCHED_NULL_TX_EN, PKTSCHED_NULL_TX_EN, PKTSCHED_PKT_EN); -+ mdelay(1); -+ hdmi_modb(hdmi, 0, PKTSCHED_NULL_TX_EN, PKTSCHED_PKT_EN); -+ } -+} -+ -+static unsigned long -+hdmi_get_tmdsclock(struct dw_hdmi_qp *hdmi, unsigned long mpixelclock) -+{ -+ unsigned long tmdsclock = mpixelclock; -+ unsigned int depth = -+ hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); -+ -+ if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { -+ switch (depth) { -+ case 16: -+ tmdsclock = mpixelclock * 2; -+ break; -+ case 12: -+ tmdsclock = mpixelclock * 3 / 2; -+ break; -+ case 10: -+ tmdsclock = mpixelclock * 5 / 4; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ return tmdsclock; -+} -+ -+//[CC:] is connector param different from hdmi->connector? -+//[CC:] probably it possible to hook the whole implementation into dw-hdmi.c -+static int dw_hdmi_qp_setup(struct dw_hdmi_qp *hdmi, -+ struct drm_connector *connector, -+ struct drm_display_mode *mode) -+{ -+ int ret; -+ void *data = hdmi->plat_data->phy_data; -+ struct hdmi_vmode_qp *vmode = &hdmi->hdmi_data.video_mode; -+ struct dw_hdmi_link_config *link_cfg; -+ u8 bytes = 0; -+ -+ hdmi->vic = drm_match_cea_mode(mode); -+ if (!hdmi->vic) -+ dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n"); -+ else -+ dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic); -+ -+ if (hdmi->plat_data->get_enc_out_encoding) -+ hdmi->hdmi_data.enc_out_encoding = -+ hdmi->plat_data->get_enc_out_encoding(data); -+ else if ((hdmi->vic == 6) || (hdmi->vic == 7) || -+ (hdmi->vic == 21) || (hdmi->vic == 22) || -+ (hdmi->vic == 2) || (hdmi->vic == 3) || -+ (hdmi->vic == 17) || (hdmi->vic == 18)) -+ hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601; -+ else -+ hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709; -+ -+ if (mode->flags & DRM_MODE_FLAG_DBLCLK) { -+ hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1; -+ hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 1; -+ } else { -+ hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; -+ hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; -+ } -+ /* Get input format from plat data or fallback to RGB888 */ -+ if (hdmi->plat_data->get_input_bus_format) -+ hdmi->hdmi_data.enc_in_bus_format = -+ hdmi->plat_data->get_input_bus_format(data); -+ else if (hdmi->plat_data->input_bus_format) -+ hdmi->hdmi_data.enc_in_bus_format = -+ hdmi->plat_data->input_bus_format; -+ else -+ hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24; -+ -+ /* Default to RGB888 output format */ -+ if (hdmi->plat_data->get_output_bus_format) -+ hdmi->hdmi_data.enc_out_bus_format = -+ hdmi->plat_data->get_output_bus_format(data); -+ else -+ hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24; -+ -+ /* Get input encoding from plat data or fallback to none */ -+ if (hdmi->plat_data->get_enc_in_encoding) -+ hdmi->hdmi_data.enc_in_encoding = -+ hdmi->plat_data->get_enc_in_encoding(data); -+ else if (hdmi->plat_data->input_bus_encoding) -+ hdmi->hdmi_data.enc_in_encoding = -+ hdmi->plat_data->input_bus_encoding; -+ else -+ hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT; -+ -+ if (hdmi->plat_data->get_quant_range) -+ hdmi->hdmi_data.quant_range = -+ hdmi->plat_data->get_quant_range(data); -+ else -+ hdmi->hdmi_data.quant_range = HDMI_QUANTIZATION_RANGE_DEFAULT; -+ -+ if (hdmi->plat_data->get_link_cfg) -+ link_cfg = hdmi->plat_data->get_link_cfg(data); -+ else -+ return -EINVAL; -+ -+ hdmi->phy.ops->set_mode(hdmi, hdmi->phy.data, HDMI_MODE_FRL_MASK, -+ link_cfg->frl_mode); -+ -+ /* -+ * According to the dw-hdmi specification 6.4.2 -+ * vp_pr_cd[3:0]: -+ * 0000b: No pixel repetition (pixel sent only once) -+ * 0001b: Pixel sent two times (pixel repeated once) -+ */ -+ hdmi->hdmi_data.pix_repet_factor = -+ (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 1 : 0; -+ hdmi->hdmi_data.video_mode.mdataenablepolarity = true; -+ -+ vmode->previous_pixelclock = vmode->mpixelclock; -+ //[CC:] no split mode -+ // if (hdmi->plat_data->split_mode) -+ // mode->crtc_clock /= 2; -+ vmode->mpixelclock = mode->crtc_clock * 1000; -+ if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING) -+ vmode->mpixelclock *= 2; -+ dev_dbg(hdmi->dev, "final pixclk = %ld\n", vmode->mpixelclock); -+ vmode->previous_tmdsclock = vmode->mtmdsclock; -+ vmode->mtmdsclock = hdmi_get_tmdsclock(hdmi, vmode->mpixelclock); -+ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) -+ vmode->mtmdsclock /= 2; -+ dev_info(hdmi->dev, "final tmdsclk = %d\n", vmode->mtmdsclock); -+ -+ ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode); -+ if (ret) -+ return ret; -+ -+ if (hdmi->plat_data->set_grf_cfg) -+ hdmi->plat_data->set_grf_cfg(data); -+ -+ /* not for DVI mode */ -+ if (hdmi->sink_is_hdmi) { -+ dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); -+ hdmi_modb(hdmi, 0, OPMODE_DVI, LINK_CONFIG0); -+ hdmi_modb(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0); -+ if (!link_cfg->frl_mode) { -+ if (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK) { -+ drm_scdc_readb(hdmi->ddc, SCDC_SINK_VERSION, &bytes); -+ drm_scdc_writeb(hdmi->ddc, SCDC_SOURCE_VERSION, -+ min_t(u8, bytes, SCDC_MIN_SOURCE_VERSION)); -+ //[CC:] use dw_hdmi_set_high_tmds_clock_ratio() -+ drm_scdc_set_high_tmds_clock_ratio(connector, 1); -+ drm_scdc_set_scrambling(connector, 1); -+ hdmi_writel(hdmi, 1, SCRAMB_CONFIG0); -+ } else { -+ if (dw_hdmi_support_scdc(hdmi, &connector->display_info)) { -+ drm_scdc_set_high_tmds_clock_ratio(connector, 0); -+ drm_scdc_set_scrambling(connector, 0); -+ } -+ hdmi_writel(hdmi, 0, SCRAMB_CONFIG0); -+ } -+ } -+ /* HDMI Initialization Step F - Configure AVI InfoFrame */ -+ hdmi_config_AVI(hdmi, connector, mode); -+ hdmi_config_CVTEM(hdmi); -+ hdmi_config_drm_infoframe(hdmi, connector); -+ hdmi_set_op_mode(hdmi, link_cfg, connector); -+ } else { -+ hdmi_modb(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0); -+ hdmi_modb(hdmi, OPMODE_DVI, OPMODE_DVI, LINK_CONFIG0); -+ dev_info(hdmi->dev, "%s DVI mode\n", __func__); -+ } -+ -+ return 0; -+} -+ -+static enum drm_connector_status -+dw_hdmi_connector_detect(struct drm_connector *connector, bool force) -+{ -+ struct dw_hdmi_qp *hdmi = -+ container_of(connector, struct dw_hdmi_qp, connector); -+ struct dw_hdmi_qp *secondary = NULL; -+ enum drm_connector_status result, result_secondary; -+ -+ mutex_lock(&hdmi->mutex); -+ hdmi->force = DRM_FORCE_UNSPECIFIED; -+ mutex_unlock(&hdmi->mutex); -+ -+ if (hdmi->plat_data->left) -+ secondary = hdmi->plat_data->left; -+ else if (hdmi->plat_data->right) -+ secondary = hdmi->plat_data->right; -+ -+ result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); -+ -+ if (secondary) { -+ result_secondary = secondary->phy.ops->read_hpd(secondary, secondary->phy.data); -+ if (result == connector_status_connected && -+ result_secondary == connector_status_connected) -+ result = connector_status_connected; -+ else -+ result = connector_status_disconnected; -+ } -+ -+ mutex_lock(&hdmi->mutex); -+ if (result != hdmi->last_connector_result) { -+ dev_dbg(hdmi->dev, "read_hpd result: %d", result); -+ handle_plugged_change(hdmi, -+ result == connector_status_connected); -+ hdmi->last_connector_result = result; -+ } -+ mutex_unlock(&hdmi->mutex); -+ -+ return result; -+} -+ -+static int -+dw_hdmi_update_hdr_property(struct drm_connector *connector) -+{ -+ struct drm_device *dev = connector->dev; -+ struct dw_hdmi_qp *hdmi = container_of(connector, struct dw_hdmi_qp, -+ connector); -+ void *data = hdmi->plat_data->phy_data; -+ const struct hdr_static_metadata *metadata = -+ &connector->hdr_sink_metadata.hdmi_type1; -+ size_t size = sizeof(*metadata); -+ struct drm_property *property = NULL; -+ struct drm_property_blob *blob; -+ int ret; -+ -+ if (hdmi->plat_data->get_hdr_property) -+ property = hdmi->plat_data->get_hdr_property(data); -+ -+ if (!property) -+ return -EINVAL; -+ -+ if (hdmi->plat_data->get_hdr_blob) -+ blob = hdmi->plat_data->get_hdr_blob(data); -+ else -+ return -EINVAL; -+ -+ ret = drm_property_replace_global_blob(dev, &blob, size, metadata, -+ &connector->base, property); -+ return ret; -+} -+ -+static int dw_hdmi_connector_get_modes(struct drm_connector *connector) -+{ -+ struct dw_hdmi_qp *hdmi = -+ container_of(connector, struct dw_hdmi_qp, connector); -+ struct hdr_static_metadata *metedata = -+ &connector->hdr_sink_metadata.hdmi_type1; -+ struct edid *edid; -+ struct drm_display_mode *mode; -+ struct drm_display_info *info = &connector->display_info; -+ // void *data = hdmi->plat_data->phy_data; -+ int i, ret = 0; -+ -+ if (!hdmi->ddc) -+ return 0; -+ -+ memset(metedata, 0, sizeof(*metedata)); -+ edid = drm_get_edid(connector, hdmi->ddc); -+ if (edid) { -+ dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", -+ edid->width_cm, edid->height_cm); -+ -+ hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); -+ drm_connector_update_edid_property(connector, edid); -+ // if (hdmi->plat_data->get_edid_dsc_info) -+ // hdmi->plat_data->get_edid_dsc_info(data, edid); -+ ret = drm_add_edid_modes(connector, edid); -+ dw_hdmi_update_hdr_property(connector); -+ // if (ret > 0 && hdmi->plat_data->split_mode) { -+ // struct dw_hdmi_qp *secondary = NULL; -+ // void *secondary_data; -+ // -+ // if (hdmi->plat_data->left) -+ // secondary = hdmi->plat_data->left; -+ // else if (hdmi->plat_data->right) -+ // secondary = hdmi->plat_data->right; -+ // -+ // if (!secondary) -+ // return -ENOMEM; -+ // secondary_data = secondary->plat_data->phy_data; -+ // -+ // list_for_each_entry(mode, &connector->probed_modes, head) -+ // hdmi->plat_data->convert_to_split_mode(mode); -+ // -+ // secondary->sink_is_hdmi = drm_detect_hdmi_monitor(edid); -+ // if (secondary->plat_data->get_edid_dsc_info) -+ // secondary->plat_data->get_edid_dsc_info(secondary_data, edid); -+ // } -+ kfree(edid); -+ } else { -+ hdmi->sink_is_hdmi = true; -+ -+ if (hdmi->plat_data->split_mode) { -+ if (hdmi->plat_data->left) { -+ hdmi->plat_data->left->sink_is_hdmi = true; -+ } else if (hdmi->plat_data->right) { -+ hdmi->plat_data->right->sink_is_hdmi = true; -+ } -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(dw_hdmi_default_modes); i++) { -+ const struct drm_display_mode *ptr = -+ &dw_hdmi_default_modes[i]; -+ -+ mode = drm_mode_duplicate(connector->dev, ptr); -+ if (mode) { -+ if (!i) -+ mode->type = DRM_MODE_TYPE_PREFERRED; -+ drm_mode_probed_add(connector, mode); -+ ret++; -+ } -+ } -+ if (ret > 0 && hdmi->plat_data->split_mode) { -+ struct drm_display_mode *mode; -+ -+ list_for_each_entry(mode, &connector->probed_modes, head) -+ hdmi->plat_data->convert_to_split_mode(mode); -+ } -+ info->edid_hdmi_rgb444_dc_modes = 0; -+ info->hdmi.y420_dc_modes = 0; -+ info->color_formats = 0; -+ -+ dev_info(hdmi->dev, "failed to get edid\n"); -+ } -+ -+ return ret; -+} -+ -+static int -+dw_hdmi_atomic_connector_set_property(struct drm_connector *connector, -+ struct drm_connector_state *state, -+ struct drm_property *property, -+ uint64_t val) -+{ -+ struct dw_hdmi_qp *hdmi = -+ container_of(connector, struct dw_hdmi_qp, connector); -+ const struct dw_hdmi_property_ops *ops = hdmi->plat_data->property_ops; -+ -+ if (ops && ops->set_property) -+ return ops->set_property(connector, state, property, -+ val, hdmi->plat_data->phy_data); -+ else -+ return -EINVAL; -+} -+ -+static int -+dw_hdmi_atomic_connector_get_property(struct drm_connector *connector, -+ const struct drm_connector_state *state, -+ struct drm_property *property, -+ uint64_t *val) -+{ -+ struct dw_hdmi_qp *hdmi = -+ container_of(connector, struct dw_hdmi_qp, connector); -+ const struct dw_hdmi_property_ops *ops = hdmi->plat_data->property_ops; -+ -+ if (ops && ops->get_property) -+ return ops->get_property(connector, state, property, -+ val, hdmi->plat_data->phy_data); -+ else -+ return -EINVAL; -+} -+ -+static int -+dw_hdmi_connector_set_property(struct drm_connector *connector, -+ struct drm_property *property, uint64_t val) -+{ -+ return dw_hdmi_atomic_connector_set_property(connector, NULL, -+ property, val); -+} -+ -+static void dw_hdmi_attach_properties(struct dw_hdmi_qp *hdmi) -+{ -+ unsigned int color = MEDIA_BUS_FMT_RGB888_1X24; -+ const struct dw_hdmi_property_ops *ops = -+ hdmi->plat_data->property_ops; -+ -+ if (ops && ops->attach_properties) -+ return ops->attach_properties(&hdmi->connector, color, 0, -+ hdmi->plat_data->phy_data); -+} -+ -+static void dw_hdmi_destroy_properties(struct dw_hdmi_qp *hdmi) -+{ -+ const struct dw_hdmi_property_ops *ops = -+ hdmi->plat_data->property_ops; -+ -+ if (ops && ops->destroy_properties) -+ return ops->destroy_properties(&hdmi->connector, -+ hdmi->plat_data->phy_data); -+} -+ -+static struct drm_encoder * -+dw_hdmi_connector_best_encoder(struct drm_connector *connector) -+{ -+ struct dw_hdmi_qp *hdmi = -+ container_of(connector, struct dw_hdmi_qp, connector); -+ -+ return hdmi->bridge.encoder; -+} -+ -+static bool dw_hdmi_color_changed(struct drm_connector *connector, -+ struct drm_atomic_state *state) -+{ -+ struct dw_hdmi_qp *hdmi = -+ container_of(connector, struct dw_hdmi_qp, connector); -+ void *data = hdmi->plat_data->phy_data; -+ struct drm_connector_state *old_state = -+ drm_atomic_get_old_connector_state(state, connector); -+ struct drm_connector_state *new_state = -+ drm_atomic_get_new_connector_state(state, connector); -+ bool ret = false; -+ -+ if (hdmi->plat_data->get_color_changed) -+ ret = hdmi->plat_data->get_color_changed(data); -+ -+ if (new_state->colorspace != old_state->colorspace) -+ ret = true; -+ -+ return ret; -+} -+ -+static bool hdr_metadata_equal(const struct drm_connector_state *old_state, -+ const struct drm_connector_state *new_state) -+{ -+ struct drm_property_blob *old_blob = old_state->hdr_output_metadata; -+ struct drm_property_blob *new_blob = new_state->hdr_output_metadata; -+ -+ if (!old_blob || !new_blob) -+ return old_blob == new_blob; -+ -+ if (old_blob->length != new_blob->length) -+ return false; -+ -+ return !memcmp(old_blob->data, new_blob->data, old_blob->length); -+} -+ -+static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, -+ struct drm_atomic_state *state) -+{ -+ struct drm_connector_state *old_state = -+ drm_atomic_get_old_connector_state(state, connector); -+ struct drm_connector_state *new_state = -+ drm_atomic_get_new_connector_state(state, connector); -+ struct drm_crtc *crtc = new_state->crtc; -+ struct drm_crtc_state *crtc_state; -+ struct dw_hdmi_qp *hdmi = -+ container_of(connector, struct dw_hdmi_qp, connector); -+ struct drm_display_mode *mode = NULL; -+ void *data = hdmi->plat_data->phy_data; -+ struct hdmi_vmode_qp *vmode = &hdmi->hdmi_data.video_mode; -+ -+ if (!crtc) -+ return 0; -+ -+ crtc_state = drm_atomic_get_crtc_state(state, crtc); -+ if (IS_ERR(crtc_state)) -+ return PTR_ERR(crtc_state); -+ -+ /* -+ * If HDMI is enabled in uboot, it's need to record -+ * drm_display_mode and set phy status to enabled. -+ */ -+ if (!vmode->mpixelclock) { -+ crtc_state = drm_atomic_get_crtc_state(state, crtc); -+ if (hdmi->plat_data->get_enc_in_encoding) -+ hdmi->hdmi_data.enc_in_encoding = -+ hdmi->plat_data->get_enc_in_encoding(data); -+ if (hdmi->plat_data->get_enc_out_encoding) -+ hdmi->hdmi_data.enc_out_encoding = -+ hdmi->plat_data->get_enc_out_encoding(data); -+ if (hdmi->plat_data->get_input_bus_format) -+ hdmi->hdmi_data.enc_in_bus_format = -+ hdmi->plat_data->get_input_bus_format(data); -+ if (hdmi->plat_data->get_output_bus_format) -+ hdmi->hdmi_data.enc_out_bus_format = -+ hdmi->plat_data->get_output_bus_format(data); -+ -+ mode = &crtc_state->mode; -+ if (hdmi->plat_data->split_mode) { -+ hdmi->plat_data->convert_to_origin_mode(mode); -+ mode->crtc_clock /= 2; -+ } -+ memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); -+ vmode->mpixelclock = mode->crtc_clock * 1000; -+ vmode->previous_pixelclock = mode->clock; -+ vmode->previous_tmdsclock = mode->clock; -+ vmode->mtmdsclock = hdmi_get_tmdsclock(hdmi, -+ vmode->mpixelclock); -+ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) -+ vmode->mtmdsclock /= 2; -+ } -+ -+ if (!hdr_metadata_equal(old_state, new_state) || -+ dw_hdmi_color_changed(connector, state)) { -+ crtc_state = drm_atomic_get_crtc_state(state, crtc); -+ if (IS_ERR(crtc_state)) -+ return PTR_ERR(crtc_state); -+ -+ crtc_state->mode_changed = true; -+ } -+ -+ return 0; -+} -+ -+static void dw_hdmi_connector_force(struct drm_connector *connector) -+{ -+ struct dw_hdmi_qp *hdmi = -+ container_of(connector, struct dw_hdmi_qp, connector); -+ -+ mutex_lock(&hdmi->mutex); -+ -+ if (hdmi->force != connector->force) { -+ if (!hdmi->disabled && connector->force == DRM_FORCE_OFF) -+ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, -+ false); -+ else if (hdmi->disabled && connector->force == DRM_FORCE_ON) -+ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, -+ true); -+ } -+ -+ hdmi->force = connector->force; -+ mutex_unlock(&hdmi->mutex); -+} -+ -+static int dw_hdmi_qp_fill_modes(struct drm_connector *connector, u32 max_x, -+ u32 max_y) -+{ -+ return drm_helper_probe_single_connector_modes(connector, 9000, 9000); -+} -+ -+static const struct drm_connector_funcs dw_hdmi_connector_funcs = { -+ .fill_modes = dw_hdmi_qp_fill_modes, -+ .detect = dw_hdmi_connector_detect, -+ .destroy = drm_connector_cleanup, -+ .force = dw_hdmi_connector_force, -+ .reset = drm_atomic_helper_connector_reset, -+ .set_property = dw_hdmi_connector_set_property, -+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -+ .atomic_set_property = dw_hdmi_atomic_connector_set_property, -+ .atomic_get_property = dw_hdmi_atomic_connector_get_property, -+}; -+ -+static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = { -+ .get_modes = dw_hdmi_connector_get_modes, -+ .best_encoder = dw_hdmi_connector_best_encoder, -+ .atomic_check = dw_hdmi_connector_atomic_check, -+}; -+ -+static int dw_hdmi_qp_bridge_attach(struct drm_bridge *bridge, -+ enum drm_bridge_attach_flags flags) -+{ -+ struct dw_hdmi_qp *hdmi = bridge->driver_private; -+ struct drm_encoder *encoder = bridge->encoder; -+ struct drm_connector *connector = &hdmi->connector; -+ -+ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) -+ return 0; -+ -+ connector->interlace_allowed = 1; -+ connector->polled = DRM_CONNECTOR_POLL_HPD; -+ -+ drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); -+ -+ // [CC:] use drm_connector_init_with_ddc or drmm_connector_init -+ // to provide ddc reference -+ drm_connector_init_with_ddc(bridge->dev, connector, -+ &dw_hdmi_connector_funcs, -+ DRM_MODE_CONNECTOR_HDMIA, -+ hdmi->ddc); -+ -+ drm_connector_attach_encoder(connector, encoder); -+ dw_hdmi_attach_properties(hdmi); -+ -+ return 0; -+} -+ -+static void dw_hdmi_qp_bridge_mode_set(struct drm_bridge *bridge, -+ const struct drm_display_mode *orig_mode, -+ const struct drm_display_mode *mode) -+{ -+ struct dw_hdmi_qp *hdmi = bridge->driver_private; -+ -+ mutex_lock(&hdmi->mutex); -+ -+ /* Store the display mode for plugin/DKMS poweron events */ -+ memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); -+ if (hdmi->plat_data->split_mode) -+ hdmi->plat_data->convert_to_origin_mode(&hdmi->previous_mode); -+ -+ mutex_unlock(&hdmi->mutex); -+} -+ -+static enum drm_mode_status -+dw_hdmi_qp_bridge_mode_valid(struct drm_bridge *bridge, -+ const struct drm_display_info *info, -+ const struct drm_display_mode *mode) -+{ -+ return MODE_OK; -+} -+ -+static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, -+ struct drm_bridge_state *old_state) -+{ -+ struct dw_hdmi_qp *hdmi = bridge->driver_private; -+ struct drm_atomic_state *state = old_state->base.state; -+ struct drm_connector *connector; -+ -+ connector = drm_atomic_get_new_connector_for_encoder(state, -+ bridge->encoder); -+ -+ mutex_lock(&hdmi->mutex); -+ hdmi->curr_conn = connector; -+ dw_hdmi_qp_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); -+ hdmi->disabled = false; -+ mutex_unlock(&hdmi->mutex); -+ -+ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, true); -+ handle_plugged_change(hdmi, true); -+} -+ -+static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, -+ struct drm_bridge_state *old_state) -+{ -+ struct dw_hdmi_qp *hdmi = bridge->driver_private; -+ -+ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, false); -+ handle_plugged_change(hdmi, false); -+ mutex_lock(&hdmi->mutex); -+ -+ hdmi->curr_conn = NULL; -+ -+ if (hdmi->phy.ops->disable) -+ hdmi->phy.ops->disable(hdmi, hdmi->phy.data); -+ hdmi->disabled = true; -+ mutex_unlock(&hdmi->mutex); -+} -+ -+static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { -+ .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, -+ .attach = dw_hdmi_qp_bridge_attach, -+ .mode_set = dw_hdmi_qp_bridge_mode_set, -+ .mode_valid = dw_hdmi_qp_bridge_mode_valid, -+ .atomic_enable = dw_hdmi_qp_bridge_atomic_enable, -+ .atomic_disable = dw_hdmi_qp_bridge_atomic_disable, -+}; -+ -+static irqreturn_t dw_hdmi_qp_main_hardirq(int irq, void *dev_id) -+{ -+ struct dw_hdmi_qp *hdmi = dev_id; -+ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; -+ u32 stat; -+ -+ stat = hdmi_readl(hdmi, MAINUNIT_1_INT_STATUS); -+ -+ i2c->stat = stat & (I2CM_OP_DONE_IRQ | I2CM_READ_REQUEST_IRQ | -+ I2CM_NACK_RCVD_IRQ); -+ hdmi->scdc_intr = stat & (SCDC_UPD_FLAGS_RD_IRQ | -+ SCDC_UPD_FLAGS_CHG_IRQ | -+ SCDC_UPD_FLAGS_CLR_IRQ | -+ SCDC_RR_REPLY_STOP_IRQ | -+ SCDC_NACK_RCVD_IRQ); -+ hdmi->flt_intr = stat & (FLT_EXIT_TO_LTSP_IRQ | -+ FLT_EXIT_TO_LTS4_IRQ | -+ FLT_EXIT_TO_LTSL_IRQ); -+ -+ if (i2c->stat) { -+ hdmi_writel(hdmi, i2c->stat, MAINUNIT_1_INT_CLEAR); -+ complete(&i2c->cmp); -+ } -+ -+ if (hdmi->flt_intr) { -+ dev_dbg(hdmi->dev, "i2c flt irq:%#x\n", hdmi->flt_intr); -+ hdmi_writel(hdmi, hdmi->flt_intr, MAINUNIT_1_INT_CLEAR); -+ complete(&hdmi->flt_cmp); -+ } -+ -+ if (hdmi->scdc_intr) { -+ u8 val; -+ -+ dev_dbg(hdmi->dev, "i2c scdc irq:%#x\n", hdmi->scdc_intr); -+ hdmi_writel(hdmi, hdmi->scdc_intr, MAINUNIT_1_INT_CLEAR); -+ val = hdmi_readl(hdmi, SCDC_STATUS0); -+ -+ /* frl start */ -+ if (val & BIT(4)) { -+ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_POLL_EN | -+ SCDC_UPD_FLAGS_AUTO_CLR, SCDC_CONFIG0); -+ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_RD_IRQ, -+ MAINUNIT_1_INT_MASK_N); -+ dev_info(hdmi->dev, "frl start\n"); -+ } -+ -+ } -+ -+ if (stat) -+ return IRQ_HANDLED; -+ -+ return IRQ_NONE; -+} -+ -+static irqreturn_t dw_hdmi_qp_avp_hardirq(int irq, void *dev_id) -+{ -+ struct dw_hdmi_qp *hdmi = dev_id; -+ u32 stat; -+ -+ stat = hdmi_readl(hdmi, AVP_1_INT_STATUS); -+ if (stat) { -+ dev_dbg(hdmi->dev, "HDCP irq %#x\n", stat); -+ stat &= ~stat; -+ hdmi_writel(hdmi, stat, AVP_1_INT_MASK_N); -+ return IRQ_WAKE_THREAD; -+ } -+ -+ return IRQ_NONE; -+} -+ -+static irqreturn_t dw_hdmi_qp_earc_hardirq(int irq, void *dev_id) -+{ -+ struct dw_hdmi_qp *hdmi = dev_id; -+ u32 stat; -+ -+ stat = hdmi_readl(hdmi, EARCRX_0_INT_STATUS); -+ if (stat) { -+ dev_dbg(hdmi->dev, "earc irq %#x\n", stat); -+ stat &= ~stat; -+ hdmi_writel(hdmi, stat, EARCRX_0_INT_MASK_N); -+ return IRQ_WAKE_THREAD; -+ } -+ -+ return IRQ_NONE; -+} -+ -+static irqreturn_t dw_hdmi_qp_avp_irq(int irq, void *dev_id) -+{ -+ struct dw_hdmi_qp *hdmi = dev_id; -+ u32 stat; -+ -+ stat = hdmi_readl(hdmi, AVP_1_INT_STATUS); -+ -+ if (!stat) -+ return IRQ_NONE; -+ -+ hdmi_writel(hdmi, stat, AVP_1_INT_CLEAR); -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t dw_hdmi_qp_earc_irq(int irq, void *dev_id) -+{ -+ struct dw_hdmi_qp *hdmi = dev_id; -+ u32 stat; -+ -+ stat = hdmi_readl(hdmi, EARCRX_0_INT_STATUS); -+ -+ if (!stat) -+ return IRQ_NONE; -+ -+ hdmi_writel(hdmi, stat, EARCRX_0_INT_CLEAR); -+ -+ hdmi->earc_intr = stat; -+ complete(&hdmi->earc_cmp); -+ -+ return IRQ_HANDLED; -+} -+ -+static int dw_hdmi_detect_phy(struct dw_hdmi_qp *hdmi) -+{ -+ u8 phy_type; -+ -+ phy_type = hdmi->plat_data->phy_force_vendor ? -+ DW_HDMI_PHY_VENDOR_PHY : 0; -+ -+ if (phy_type == DW_HDMI_PHY_VENDOR_PHY) { -+ /* Vendor PHYs require support from the glue layer. */ -+ if (!hdmi->plat_data->qp_phy_ops || !hdmi->plat_data->phy_name) { -+ dev_err(hdmi->dev, -+ "Vendor HDMI PHY not supported by glue layer\n"); -+ return -ENODEV; -+ } -+ -+ hdmi->phy.ops = hdmi->plat_data->qp_phy_ops; -+ hdmi->phy.data = hdmi->plat_data->phy_data; -+ hdmi->phy.name = hdmi->plat_data->phy_name; -+ } -+ -+ return 0; -+} -+ -+static const struct regmap_config hdmi_regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ .max_register = EARCRX_1_INT_FORCE, -+}; -+ -+struct dw_hdmi_qp_reg_table { -+ int reg_base; -+ int reg_end; -+}; -+ -+static const struct dw_hdmi_qp_reg_table hdmi_reg_table[] = { -+ {0x0, 0xc}, -+ {0x14, 0x1c}, -+ {0x44, 0x48}, -+ {0x50, 0x58}, -+ {0x80, 0x84}, -+ {0xa0, 0xc4}, -+ {0xe0, 0xe8}, -+ {0xf0, 0x118}, -+ {0x140, 0x140}, -+ {0x150, 0x150}, -+ {0x160, 0x168}, -+ {0x180, 0x180}, -+ {0x800, 0x800}, -+ {0x808, 0x808}, -+ {0x814, 0x814}, -+ {0x81c, 0x824}, -+ {0x834, 0x834}, -+ {0x840, 0x864}, -+ {0x86c, 0x86c}, -+ {0x880, 0x89c}, -+ {0x8e0, 0x8e8}, -+ {0x900, 0x900}, -+ {0x908, 0x90c}, -+ {0x920, 0x938}, -+ {0x920, 0x938}, -+ {0x960, 0x960}, -+ {0x968, 0x968}, -+ {0xa20, 0xa20}, -+ {0xa30, 0xa30}, -+ {0xa40, 0xa40}, -+ {0xa54, 0xa54}, -+ {0xa80, 0xaac}, -+ {0xab4, 0xab8}, -+ {0xb00, 0xcbc}, -+ {0xce0, 0xce0}, -+ {0xd00, 0xddc}, -+ {0xe20, 0xe24}, -+ {0xe40, 0xe44}, -+ {0xe4c, 0xe4c}, -+ {0xe60, 0xe80}, -+ {0xea0, 0xf24}, -+ {0x1004, 0x100c}, -+ {0x1020, 0x1030}, -+ {0x1040, 0x1050}, -+ {0x1060, 0x1068}, -+ {0x1800, 0x1820}, -+ {0x182c, 0x182c}, -+ {0x1840, 0x1940}, -+ {0x1960, 0x1a60}, -+ {0x1b00, 0x1b00}, -+ {0x1c00, 0x1c00}, -+ {0x3000, 0x3000}, -+ {0x3010, 0x3014}, -+ {0x3020, 0x3024}, -+ {0x3800, 0x3800}, -+ {0x3810, 0x3814}, -+ {0x3820, 0x3824}, -+ {0x3830, 0x3834}, -+ {0x3840, 0x3844}, -+ {0x3850, 0x3854}, -+ {0x3860, 0x3864}, -+ {0x3870, 0x3874}, -+ {0x4000, 0x4004}, -+ {0x4800, 0x4800}, -+ {0x4810, 0x4814}, -+}; -+ -+static int dw_hdmi_ctrl_show(struct seq_file *s, void *v) -+{ -+ struct dw_hdmi_qp *hdmi = s->private; -+ u32 i = 0, j = 0, val = 0; -+ -+ seq_puts(s, "\n---------------------------------------------------"); -+ -+ for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) { -+ for (j = hdmi_reg_table[i].reg_base; -+ j <= hdmi_reg_table[i].reg_end; j += 4) { -+ val = hdmi_readl(hdmi, j); -+ -+ if ((j - hdmi_reg_table[i].reg_base) % 16 == 0) -+ seq_printf(s, "\n>>>hdmi_ctl %04x:", j); -+ seq_printf(s, " %08x", val); -+ } -+ } -+ seq_puts(s, "\n---------------------------------------------------\n"); -+ -+ return 0; -+} -+ -+static int dw_hdmi_ctrl_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, dw_hdmi_ctrl_show, inode->i_private); -+} -+ -+static ssize_t -+dw_hdmi_ctrl_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dw_hdmi_qp *hdmi = -+ ((struct seq_file *)file->private_data)->private; -+ u32 reg, val; -+ char kbuf[25]; -+ -+ if (count > 24) { -+ dev_err(hdmi->dev, "out of buf range\n"); -+ return count; -+ } -+ -+ if (copy_from_user(kbuf, buf, count)) -+ return -EFAULT; -+ kbuf[count - 1] = '\0'; -+ -+ if (sscanf(kbuf, "%x %x", ®, &val) == -1) -+ return -EFAULT; -+ if (reg > EARCRX_1_INT_FORCE) { -+ dev_err(hdmi->dev, "it is no a hdmi register\n"); -+ return count; -+ } -+ dev_info(hdmi->dev, "/**********hdmi register config******/"); -+ dev_info(hdmi->dev, "\n reg=%x val=%x\n", reg, val); -+ hdmi_writel(hdmi, val, reg); -+ return count; -+} -+ -+static const struct file_operations dw_hdmi_ctrl_fops = { -+ .owner = THIS_MODULE, -+ .open = dw_hdmi_ctrl_open, -+ .read = seq_read, -+ .write = dw_hdmi_ctrl_write, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static int dw_hdmi_status_show(struct seq_file *s, void *v) -+{ -+ struct dw_hdmi_qp *hdmi = s->private; -+ u32 val; -+ -+ seq_puts(s, "PHY: "); -+ if (hdmi->disabled) { -+ seq_puts(s, "disabled\n"); -+ return 0; -+ } -+ seq_puts(s, "enabled\t\t\tMode: "); -+ if (hdmi->sink_is_hdmi) -+ seq_puts(s, "HDMI\n"); -+ else -+ seq_puts(s, "DVI\n"); -+ -+ if (hdmi->hdmi_data.video_mode.mpixelclock > 600000000) { -+ seq_printf(s, "FRL Mode Pixel Clk: %luHz\n", -+ hdmi->hdmi_data.video_mode.mpixelclock); -+ } else { -+ if (hdmi->hdmi_data.video_mode.mtmdsclock > 340000000) -+ val = hdmi->hdmi_data.video_mode.mtmdsclock / 4; -+ else -+ val = hdmi->hdmi_data.video_mode.mtmdsclock; -+ seq_printf(s, "TMDS Mode Pixel Clk: %luHz\t\tTMDS Clk: %uHz\n", -+ hdmi->hdmi_data.video_mode.mpixelclock, val); -+ } -+ -+ seq_puts(s, "Color Format: "); -+ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) -+ seq_puts(s, "RGB"); -+ else if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) -+ seq_puts(s, "YUV444"); -+ else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) -+ seq_puts(s, "YUV422"); -+ else if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) -+ seq_puts(s, "YUV420"); -+ else -+ seq_puts(s, "UNKNOWN"); -+ val = hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); -+ seq_printf(s, "\t\tColor Depth: %d bit\n", val); -+ seq_puts(s, "Colorimetry: "); -+ switch (hdmi->hdmi_data.enc_out_encoding) { -+ case V4L2_YCBCR_ENC_601: -+ seq_puts(s, "ITU.BT601"); -+ break; -+ case V4L2_YCBCR_ENC_709: -+ seq_puts(s, "ITU.BT709"); -+ break; -+ case V4L2_YCBCR_ENC_BT2020: -+ seq_puts(s, "ITU.BT2020"); -+ break; -+ default: /* Carries no data */ -+ seq_puts(s, "ITU.BT601"); -+ break; -+ } -+ -+ seq_puts(s, "\t\tEOTF: "); -+ -+ val = hdmi_readl(hdmi, PKTSCHED_PKT_EN); -+ if (!(val & PKTSCHED_DRMI_TX_EN)) { -+ seq_puts(s, "Off\n"); -+ return 0; -+ } -+ -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS1); -+ val = (val >> 8) & 0x7; -+ switch (val) { -+ case HDMI_EOTF_TRADITIONAL_GAMMA_SDR: -+ seq_puts(s, "SDR"); -+ break; -+ case HDMI_EOTF_TRADITIONAL_GAMMA_HDR: -+ seq_puts(s, "HDR"); -+ break; -+ case HDMI_EOTF_SMPTE_ST2084: -+ seq_puts(s, "ST2084"); -+ break; -+ case HDMI_EOTF_BT_2100_HLG: -+ seq_puts(s, "HLG"); -+ break; -+ default: -+ seq_puts(s, "Not Defined\n"); -+ return 0; -+ } -+ -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS1); -+ val = (val >> 16) & 0xffff; -+ seq_printf(s, "\nx0: %d", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS2); -+ val = val & 0xffff; -+ seq_printf(s, "\t\t\t\ty0: %d\n", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS2); -+ val = (val >> 16) & 0xffff; -+ seq_printf(s, "x1: %d", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS3); -+ val = val & 0xffff; -+ seq_printf(s, "\t\t\t\ty1: %d\n", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS3); -+ val = (val >> 16) & 0xffff; -+ seq_printf(s, "x2: %d", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS4); -+ val = val & 0xffff; -+ seq_printf(s, "\t\t\t\ty2: %d\n", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS4); -+ val = (val >> 16) & 0xffff; -+ seq_printf(s, "white x: %d", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS5); -+ val = val & 0xffff; -+ seq_printf(s, "\t\t\twhite y: %d\n", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS5); -+ val = (val >> 16) & 0xffff; -+ seq_printf(s, "max lum: %d", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS6); -+ val = val & 0xffff; -+ seq_printf(s, "\t\t\tmin lum: %d\n", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS6); -+ val = (val >> 16) & 0xffff; -+ seq_printf(s, "max cll: %d", val); -+ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS7); -+ val = val & 0xffff; -+ seq_printf(s, "\t\t\tmax fall: %d\n", val); -+ return 0; -+} -+ -+static int dw_hdmi_status_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, dw_hdmi_status_show, inode->i_private); -+} -+ -+static const struct file_operations dw_hdmi_status_fops = { -+ .owner = THIS_MODULE, -+ .open = dw_hdmi_status_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static void dw_hdmi_register_debugfs(struct device *dev, struct dw_hdmi_qp *hdmi) -+{ -+ u8 buf[11]; -+ -+ snprintf(buf, sizeof(buf), "dw-hdmi%d", hdmi->plat_data->id); -+ hdmi->debugfs_dir = debugfs_create_dir(buf, NULL); -+ if (IS_ERR(hdmi->debugfs_dir)) { -+ dev_err(dev, "failed to create debugfs dir!\n"); -+ return; -+ } -+ -+ debugfs_create_file("status", 0400, hdmi->debugfs_dir, -+ hdmi, &dw_hdmi_status_fops); -+ debugfs_create_file("ctrl", 0600, hdmi->debugfs_dir, -+ hdmi, &dw_hdmi_ctrl_fops); -+} -+ -+static struct dw_hdmi_qp * -+__dw_hdmi_probe(struct platform_device *pdev, -+ const struct dw_hdmi_plat_data *plat_data) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct device_node *ddc_node; -+ struct dw_hdmi_qp *hdmi; -+ struct resource *iores = NULL; -+ int irq; -+ int ret; -+ -+ hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); -+ if (!hdmi) -+ return ERR_PTR(-ENOMEM); -+ -+ hdmi->connector.stereo_allowed = 1; -+ hdmi->plat_data = plat_data; -+ hdmi->dev = dev; -+ hdmi->disabled = true; -+ -+ mutex_init(&hdmi->mutex); -+ -+ ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); -+ if (ddc_node) { -+ hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); -+ of_node_put(ddc_node); -+ if (!hdmi->ddc) { -+ dev_dbg(hdmi->dev, "failed to read ddc node\n"); -+ return ERR_PTR(-EPROBE_DEFER); -+ } -+ -+ } else { -+ dev_dbg(hdmi->dev, "no ddc property found\n"); -+ } -+ -+ if (!plat_data->regm) { -+ const struct regmap_config *reg_config; -+ -+ reg_config = &hdmi_regmap_config; -+ -+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ hdmi->regs = devm_ioremap_resource(dev, iores); -+ if (IS_ERR(hdmi->regs)) { -+ ret = PTR_ERR(hdmi->regs); -+ goto err_res; -+ } -+ -+ hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config); -+ if (IS_ERR(hdmi->regm)) { -+ dev_err(dev, "Failed to configure regmap\n"); -+ ret = PTR_ERR(hdmi->regm); -+ goto err_res; -+ } -+ } else { -+ hdmi->regm = plat_data->regm; -+ } -+ -+ ret = dw_hdmi_detect_phy(hdmi); -+ if (ret < 0) -+ goto err_res; -+ -+ hdmi_writel(hdmi, 0, MAINUNIT_0_INT_MASK_N); -+ hdmi_writel(hdmi, 0, MAINUNIT_1_INT_MASK_N); -+ hdmi_writel(hdmi, 428571429, TIMER_BASE_CONFIG0); -+ if ((hdmi_readl(hdmi, CMU_STATUS) & DISPLAY_CLK_MONITOR) == DISPLAY_CLK_LOCKED) { -+ hdmi->initialized = true; -+ hdmi->disabled = false; -+ } -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ ret = irq; -+ goto err_res; -+ } -+ -+ hdmi->avp_irq = irq; -+ ret = devm_request_threaded_irq(dev, hdmi->avp_irq, -+ dw_hdmi_qp_avp_hardirq, -+ dw_hdmi_qp_avp_irq, IRQF_SHARED, -+ dev_name(dev), hdmi); -+ if (ret) -+ goto err_res; -+ -+ irq = platform_get_irq(pdev, 1); -+ if (irq < 0) { -+ ret = irq; -+ goto err_res; -+ } -+ -+ irq = platform_get_irq(pdev, 2); -+ if (irq < 0) { -+ ret = irq; -+ goto err_res; -+ } -+ -+ hdmi->earc_irq = irq; -+ ret = devm_request_threaded_irq(dev, hdmi->earc_irq, -+ dw_hdmi_qp_earc_hardirq, -+ dw_hdmi_qp_earc_irq, IRQF_SHARED, -+ dev_name(dev), hdmi); -+ if (ret) -+ goto err_res; -+ -+ irq = platform_get_irq(pdev, 3); -+ if (irq < 0) { -+ ret = irq; -+ goto err_res; -+ } -+ -+ hdmi->main_irq = irq; -+ ret = devm_request_threaded_irq(dev, hdmi->main_irq, -+ dw_hdmi_qp_main_hardirq, NULL, -+ IRQF_SHARED, dev_name(dev), hdmi); -+ if (ret) -+ goto err_res; -+ -+ /* If DDC bus is not specified, try to register HDMI I2C bus */ -+ if (!hdmi->ddc) { -+ hdmi->ddc = dw_hdmi_i2c_adapter(hdmi); -+ if (IS_ERR(hdmi->ddc)) -+ hdmi->ddc = NULL; -+ /* -+ * Read high and low time from device tree. If not available use -+ * the default timing scl clock rate is about 99.6KHz. -+ */ -+ if (of_property_read_u32(np, "ddc-i2c-scl-high-time-ns", -+ &hdmi->i2c->scl_high_ns)) -+ hdmi->i2c->scl_high_ns = 4708; -+ if (of_property_read_u32(np, "ddc-i2c-scl-low-time-ns", -+ &hdmi->i2c->scl_low_ns)) -+ hdmi->i2c->scl_low_ns = 4916; -+ } -+ -+ hdmi->bridge.driver_private = hdmi; -+ hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; -+#ifdef CONFIG_OF -+ hdmi->bridge.of_node = pdev->dev.of_node; -+#endif -+ -+ if (hdmi->phy.ops->setup_hpd) -+ hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); -+ -+ hdmi->connector.ycbcr_420_allowed = hdmi->plat_data->ycbcr_420_allowed; -+ -+ hdmi->extcon = devm_extcon_dev_allocate(hdmi->dev, dw_hdmi_cable); -+ if (IS_ERR(hdmi->extcon)) { -+ dev_err(hdmi->dev, "allocate extcon failed\n"); -+ ret = PTR_ERR(hdmi->extcon); -+ goto err_res; -+ } -+ -+ ret = devm_extcon_dev_register(hdmi->dev, hdmi->extcon); -+ if (ret) { -+ dev_err(hdmi->dev, "failed to register extcon: %d\n", ret); -+ goto err_res; -+ } -+ -+ ret = extcon_set_property_capability(hdmi->extcon, EXTCON_DISP_HDMI, -+ EXTCON_PROP_DISP_HPD); -+ if (ret) { -+ dev_err(hdmi->dev, -+ "failed to set USB property capability: %d\n", ret); -+ goto err_res; -+ } -+ -+ /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */ -+ if (hdmi->i2c) -+ dw_hdmi_i2c_init(hdmi); -+ -+ init_completion(&hdmi->flt_cmp); -+ init_completion(&hdmi->earc_cmp); -+ -+ if (of_property_read_bool(np, "scramble-low-rates")) -+ hdmi->scramble_low_rates = true; -+ -+ dw_hdmi_register_debugfs(dev, hdmi); -+ -+ return hdmi; -+ -+err_res: -+ if (hdmi->i2c) -+ i2c_del_adapter(&hdmi->i2c->adap); -+ else -+ i2c_put_adapter(hdmi->ddc); -+ -+ return ERR_PTR(ret); -+} -+ -+static void __dw_hdmi_remove(struct dw_hdmi_qp *hdmi) -+{ -+ if (hdmi->avp_irq) -+ disable_irq(hdmi->avp_irq); -+ -+ if (hdmi->main_irq) -+ disable_irq(hdmi->main_irq); -+ -+ if (hdmi->earc_irq) -+ disable_irq(hdmi->earc_irq); -+ -+ debugfs_remove_recursive(hdmi->debugfs_dir); -+ -+ if (!hdmi->plat_data->first_screen) { -+ dw_hdmi_destroy_properties(hdmi); -+ hdmi->connector.funcs->destroy(&hdmi->connector); -+ } -+ -+ if (hdmi->audio && !IS_ERR(hdmi->audio)) -+ platform_device_unregister(hdmi->audio); -+ -+ // [CC:] dw_hdmi_rockchip_unbind() also calls drm_encoder_cleanup() -+ // and causes a seg fault due to NULL ptr dererence -+ // if (hdmi->bridge.encoder && !hdmi->plat_data->first_screen) -+ // hdmi->bridge.encoder->funcs->destroy(hdmi->bridge.encoder); -+ // -+ if (!IS_ERR(hdmi->cec)) -+ platform_device_unregister(hdmi->cec); -+ if (hdmi->i2c) -+ i2c_del_adapter(&hdmi->i2c->adap); -+ else -+ i2c_put_adapter(hdmi->ddc); -+} -+ -+/* ----------------------------------------------------------------------------- -+ * Bind/unbind API, used from platforms based on the component framework. -+ */ -+struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, -+ struct drm_encoder *encoder, -+ struct dw_hdmi_plat_data *plat_data) -+{ -+ struct dw_hdmi_qp *hdmi; -+ int ret; -+ -+ hdmi = __dw_hdmi_probe(pdev, plat_data); -+ if (IS_ERR(hdmi)) -+ return hdmi; -+ -+ if (!plat_data->first_screen) { -+ ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0); -+ if (ret) { -+ __dw_hdmi_remove(hdmi); -+ dev_err(hdmi->dev, "Failed to initialize bridge with drm\n"); -+ return ERR_PTR(ret); -+ } -+ -+ plat_data->connector = &hdmi->connector; -+ } -+ -+ if (plat_data->split_mode && !hdmi->plat_data->first_screen) { -+ struct dw_hdmi_qp *secondary = NULL; -+ -+ if (hdmi->plat_data->left) -+ secondary = hdmi->plat_data->left; -+ else if (hdmi->plat_data->right) -+ secondary = hdmi->plat_data->right; -+ -+ if (!secondary) -+ return ERR_PTR(-ENOMEM); -+ ret = drm_bridge_attach(encoder, &secondary->bridge, &hdmi->bridge, -+ DRM_BRIDGE_ATTACH_NO_CONNECTOR); -+ if (ret) -+ return ERR_PTR(ret); -+ } -+ -+ return hdmi; -+} -+EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind); -+ -+void dw_hdmi_qp_unbind(struct dw_hdmi_qp *hdmi) -+{ -+ __dw_hdmi_remove(hdmi); -+} -+EXPORT_SYMBOL_GPL(dw_hdmi_qp_unbind); -+ -+void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi) -+{ -+ if (!hdmi) { -+ dev_warn(dev, "Hdmi has not been initialized\n"); -+ return; -+ } -+ -+ mutex_lock(&hdmi->mutex); -+ -+ /* -+ * When system shutdown, hdmi should be disabled. -+ * When system suspend, dw_hdmi_qp_bridge_disable will disable hdmi first. -+ * To prevent duplicate operation, we should determine whether hdmi -+ * has been disabled. -+ */ -+ if (!hdmi->disabled) -+ hdmi->disabled = true; -+ mutex_unlock(&hdmi->mutex); -+ -+ if (hdmi->avp_irq) -+ disable_irq(hdmi->avp_irq); -+ -+ if (hdmi->main_irq) -+ disable_irq(hdmi->main_irq); -+ -+ if (hdmi->earc_irq) -+ disable_irq(hdmi->earc_irq); -+ -+ pinctrl_pm_select_sleep_state(dev); -+} -+EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend); -+ -+void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi) -+{ -+ if (!hdmi) { -+ dev_warn(dev, "Hdmi has not been initialized\n"); -+ return; -+ } -+ -+ hdmi_writel(hdmi, 0, MAINUNIT_0_INT_MASK_N); -+ hdmi_writel(hdmi, 0, MAINUNIT_1_INT_MASK_N); -+ hdmi_writel(hdmi, 428571429, TIMER_BASE_CONFIG0); -+ -+ pinctrl_pm_select_default_state(dev); -+ -+ mutex_lock(&hdmi->mutex); -+ if (hdmi->i2c) -+ dw_hdmi_i2c_init(hdmi); -+ if (hdmi->avp_irq) -+ enable_irq(hdmi->avp_irq); -+ -+ if (hdmi->main_irq) -+ enable_irq(hdmi->main_irq); -+ -+ if (hdmi->earc_irq) -+ enable_irq(hdmi->earc_irq); -+ -+ mutex_unlock(&hdmi->mutex); -+} -+EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume); -+ -+MODULE_AUTHOR("Algea Cao "); -+MODULE_DESCRIPTION("DW HDMI QP transmitter driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:dw-hdmi-qp"); -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h -new file mode 100644 -index 000000000000..111111111111 ---- /dev/null -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h -@@ -0,0 +1,831 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Copyright (C) Rockchip Electronics Co.Ltd -+ * Author: -+ * Algea Cao -+ */ -+#ifndef __DW_HDMI_QP_H__ -+#define __DW_HDMI_QP_H__ -+/* Main Unit Registers */ -+#define CORE_ID 0x0 -+#define VER_NUMBER 0x4 -+#define VER_TYPE 0x8 -+#define CONFIG_REG 0xc -+#define CONFIG_CEC BIT(28) -+#define CONFIG_AUD_UD BIT(23) -+#define CORE_TIMESTAMP_HHMM 0x14 -+#define CORE_TIMESTAMP_MMDD 0x18 -+#define CORE_TIMESTAMP_YYYY 0x1c -+/* Reset Manager Registers */ -+#define GLOBAL_SWRESET_REQUEST 0x40 -+#define EARCRX_CMDC_SWINIT_P BIT(27) -+#define AVP_DATAPATH_PACKET_AUDIO_SWINIT_P BIT(10) -+#define GLOBAL_SWDISABLE 0x44 -+#define CEC_SWDISABLE BIT(17) -+#define AVP_DATAPATH_PACKET_AUDIO_SWDISABLE BIT(10) -+#define AVP_DATAPATH_VIDEO_SWDISABLE BIT(6) -+#define RESET_MANAGER_CONFIG0 0x48 -+#define RESET_MANAGER_STATUS0 0x50 -+#define RESET_MANAGER_STATUS1 0x54 -+#define RESET_MANAGER_STATUS2 0x58 -+/* Timer Base Registers */ -+#define TIMER_BASE_CONFIG0 0x80 -+#define TIMER_BASE_STATUS0 0x84 -+/* CMU Registers */ -+#define CMU_CONFIG0 0xa0 -+#define CMU_CONFIG1 0xa4 -+#define CMU_CONFIG2 0xa8 -+#define CMU_CONFIG3 0xac -+#define CMU_STATUS 0xb0 -+#define DISPLAY_CLK_MONITOR 0x3f -+#define DISPLAY_CLK_LOCKED 0X15 -+#define EARC_BPCLK_OFF BIT(9) -+#define AUDCLK_OFF BIT(7) -+#define LINKQPCLK_OFF BIT(5) -+#define VIDQPCLK_OFF BIT(3) -+#define IPI_CLK_OFF BIT(1) -+#define CMU_IPI_CLK_FREQ 0xb4 -+#define CMU_VIDQPCLK_FREQ 0xb8 -+#define CMU_LINKQPCLK_FREQ 0xbc -+#define CMU_AUDQPCLK_FREQ 0xc0 -+#define CMU_EARC_BPCLK_FREQ 0xc4 -+/* I2CM Registers */ -+#define I2CM_SM_SCL_CONFIG0 0xe0 -+#define I2CM_FM_SCL_CONFIG0 0xe4 -+#define I2CM_CONFIG0 0xe8 -+#define I2CM_CONTROL0 0xec -+#define I2CM_STATUS0 0xf0 -+#define I2CM_INTERFACE_CONTROL0 0xf4 -+#define I2CM_ADDR 0xff000 -+#define I2CM_SLVADDR 0xfe0 -+#define I2CM_WR_MASK 0x1e -+#define I2CM_EXT_READ BIT(4) -+#define I2CM_SHORT_READ BIT(3) -+#define I2CM_FM_READ BIT(2) -+#define I2CM_FM_WRITE BIT(1) -+#define I2CM_FM_EN BIT(0) -+#define I2CM_INTERFACE_CONTROL1 0xf8 -+#define I2CM_SEG_PTR 0x7f80 -+#define I2CM_SEG_ADDR 0x7f -+#define I2CM_INTERFACE_WRDATA_0_3 0xfc -+#define I2CM_INTERFACE_WRDATA_4_7 0x100 -+#define I2CM_INTERFACE_WRDATA_8_11 0x104 -+#define I2CM_INTERFACE_WRDATA_12_15 0x108 -+#define I2CM_INTERFACE_RDDATA_0_3 0x10c -+#define I2CM_INTERFACE_RDDATA_4_7 0x110 -+#define I2CM_INTERFACE_RDDATA_8_11 0x114 -+#define I2CM_INTERFACE_RDDATA_12_15 0x118 -+/* SCDC Registers */ -+#define SCDC_CONFIG0 0x140 -+#define SCDC_I2C_FM_EN BIT(12) -+#define SCDC_UPD_FLAGS_AUTO_CLR BIT(6) -+#define SCDC_UPD_FLAGS_POLL_EN BIT(4) -+#define SCDC_CONTROL0 0x148 -+#define SCDC_STATUS0 0x150 -+#define STATUS_UPDATE BIT(0) -+#define FRL_START BIT(4) -+#define FLT_UPDATE BIT(5) -+/* FLT Registers */ -+#define FLT_CONFIG0 0x160 -+#define FLT_CONFIG1 0x164 -+#define FLT_CONFIG2 0x168 -+#define FLT_CONTROL0 0x170 -+/* Main Unit 2 Registers */ -+#define MAINUNIT_STATUS0 0x180 -+/* Video Interface Registers */ -+#define VIDEO_INTERFACE_CONFIG0 0x800 -+#define VIDEO_INTERFACE_CONFIG1 0x804 -+#define VIDEO_INTERFACE_CONFIG2 0x808 -+#define VIDEO_INTERFACE_CONTROL0 0x80c -+#define VIDEO_INTERFACE_STATUS0 0x814 -+/* Video Packing Registers */ -+#define VIDEO_PACKING_CONFIG0 0x81c -+/* Audio Interface Registers */ -+#define AUDIO_INTERFACE_CONFIG0 0x820 -+#define AUD_IF_SEL_MSK 0x3 -+#define AUD_IF_SPDIF 0x2 -+#define AUD_IF_I2S 0x1 -+#define AUD_IF_PAI 0x0 -+#define AUD_FIFO_INIT_ON_OVF_MSK BIT(2) -+#define AUD_FIFO_INIT_ON_OVF_EN BIT(2) -+#define I2S_LINES_EN_MSK GENMASK(7, 4) -+#define I2S_LINES_EN(x) BIT(x + 4) -+#define I2S_BPCUV_RCV_MSK BIT(12) -+#define I2S_BPCUV_RCV_EN BIT(12) -+#define I2S_BPCUV_RCV_DIS 0 -+#define SPDIF_LINES_EN GENMASK(19, 16) -+#define AUD_FORMAT_MSK GENMASK(26, 24) -+#define AUD_3DOBA (0x7 << 24) -+#define AUD_3DASP (0x6 << 24) -+#define AUD_MSOBA (0x5 << 24) -+#define AUD_MSASP (0x4 << 24) -+#define AUD_HBR (0x3 << 24) -+#define AUD_DST (0x2 << 24) -+#define AUD_OBA (0x1 << 24) -+#define AUD_ASP (0x0 << 24) -+#define AUDIO_INTERFACE_CONFIG1 0x824 -+#define AUDIO_INTERFACE_CONTROL0 0x82c -+#define AUDIO_FIFO_CLR_P BIT(0) -+#define AUDIO_INTERFACE_STATUS0 0x834 -+/* Frame Composer Registers */ -+#define FRAME_COMPOSER_CONFIG0 0x840 -+#define FRAME_COMPOSER_CONFIG1 0x844 -+#define FRAME_COMPOSER_CONFIG2 0x848 -+#define FRAME_COMPOSER_CONFIG3 0x84c -+#define FRAME_COMPOSER_CONFIG4 0x850 -+#define FRAME_COMPOSER_CONFIG5 0x854 -+#define FRAME_COMPOSER_CONFIG6 0x858 -+#define FRAME_COMPOSER_CONFIG7 0x85c -+#define FRAME_COMPOSER_CONFIG8 0x860 -+#define FRAME_COMPOSER_CONFIG9 0x864 -+#define FRAME_COMPOSER_CONTROL0 0x86c -+/* Video Monitor Registers */ -+#define VIDEO_MONITOR_CONFIG0 0x880 -+#define VIDEO_MONITOR_STATUS0 0x884 -+#define VIDEO_MONITOR_STATUS1 0x888 -+#define VIDEO_MONITOR_STATUS2 0x88c -+#define VIDEO_MONITOR_STATUS3 0x890 -+#define VIDEO_MONITOR_STATUS4 0x894 -+#define VIDEO_MONITOR_STATUS5 0x898 -+#define VIDEO_MONITOR_STATUS6 0x89c -+/* HDCP2 Logic Registers */ -+#define HDCP2LOGIC_CONFIG0 0x8e0 -+#define HDCP2_BYPASS BIT(0) -+#define HDCP2LOGIC_ESM_GPIO_IN 0x8e4 -+#define HDCP2LOGIC_ESM_GPIO_OUT 0x8e8 -+/* HDCP14 Registers */ -+#define HDCP14_CONFIG0 0x900 -+#define HDCP14_CONFIG1 0x904 -+#define HDCP14_CONFIG2 0x908 -+#define HDCP14_CONFIG3 0x90c -+#define HDCP14_KEY_SEED 0x914 -+#define HDCP14_KEY_H 0x918 -+#define HDCP14_KEY_L 0x91c -+#define HDCP14_KEY_STATUS 0x920 -+#define HDCP14_AKSV_H 0x924 -+#define HDCP14_AKSV_L 0x928 -+#define HDCP14_AN_H 0x92c -+#define HDCP14_AN_L 0x930 -+#define HDCP14_STATUS0 0x934 -+#define HDCP14_STATUS1 0x938 -+/* Scrambler Registers */ -+#define SCRAMB_CONFIG0 0x960 -+/* Video Configuration Registers */ -+#define LINK_CONFIG0 0x968 -+#define OPMODE_FRL_4LANES BIT(8) -+#define OPMODE_DVI BIT(4) -+#define OPMODE_FRL BIT(0) -+/* TMDS FIFO Registers */ -+#define TMDS_FIFO_CONFIG0 0x970 -+#define TMDS_FIFO_CONTROL0 0x974 -+/* FRL RSFEC Registers */ -+#define FRL_RSFEC_CONFIG0 0xa20 -+#define FRL_RSFEC_STATUS0 0xa30 -+/* FRL Packetizer Registers */ -+#define FRL_PKTZ_CONFIG0 0xa40 -+#define FRL_PKTZ_CONTROL0 0xa44 -+#define FRL_PKTZ_CONTROL1 0xa50 -+#define FRL_PKTZ_STATUS1 0xa54 -+/* Packet Scheduler Registers */ -+#define PKTSCHED_CONFIG0 0xa80 -+#define PKTSCHED_PRQUEUE0_CONFIG0 0xa84 -+#define PKTSCHED_PRQUEUE1_CONFIG0 0xa88 -+#define PKTSCHED_PRQUEUE2_CONFIG0 0xa8c -+#define PKTSCHED_PRQUEUE2_CONFIG1 0xa90 -+#define PKTSCHED_PRQUEUE2_CONFIG2 0xa94 -+#define PKTSCHED_PKT_CONFIG0 0xa98 -+#define PKTSCHED_PKT_CONFIG1 0xa9c -+#define PKTSCHED_DRMI_FIELDRATE BIT(13) -+#define PKTSCHED_AVI_FIELDRATE BIT(12) -+#define PKTSCHED_PKT_CONFIG2 0xaa0 -+#define PKTSCHED_PKT_CONFIG3 0xaa4 -+#define PKTSCHED_PKT_EN 0xaa8 -+#define PKTSCHED_DRMI_TX_EN BIT(17) -+#define PKTSCHED_AUDI_TX_EN BIT(15) -+#define PKTSCHED_AVI_TX_EN BIT(13) -+#define PKTSCHED_EMP_CVTEM_TX_EN BIT(10) -+#define PKTSCHED_AMD_TX_EN BIT(8) -+#define PKTSCHED_GCP_TX_EN BIT(3) -+#define PKTSCHED_AUDS_TX_EN BIT(2) -+#define PKTSCHED_ACR_TX_EN BIT(1) -+#define PKTSCHED_NULL_TX_EN BIT(0) -+#define PKTSCHED_PKT_CONTROL0 0xaac -+#define PKTSCHED_PKT_SEND 0xab0 -+#define PKTSCHED_PKT_STATUS0 0xab4 -+#define PKTSCHED_PKT_STATUS1 0xab8 -+#define PKT_NULL_CONTENTS0 0xb00 -+#define PKT_NULL_CONTENTS1 0xb04 -+#define PKT_NULL_CONTENTS2 0xb08 -+#define PKT_NULL_CONTENTS3 0xb0c -+#define PKT_NULL_CONTENTS4 0xb10 -+#define PKT_NULL_CONTENTS5 0xb14 -+#define PKT_NULL_CONTENTS6 0xb18 -+#define PKT_NULL_CONTENTS7 0xb1c -+#define PKT_ACP_CONTENTS0 0xb20 -+#define PKT_ACP_CONTENTS1 0xb24 -+#define PKT_ACP_CONTENTS2 0xb28 -+#define PKT_ACP_CONTENTS3 0xb2c -+#define PKT_ACP_CONTENTS4 0xb30 -+#define PKT_ACP_CONTENTS5 0xb34 -+#define PKT_ACP_CONTENTS6 0xb38 -+#define PKT_ACP_CONTENTS7 0xb3c -+#define PKT_ISRC1_CONTENTS0 0xb40 -+#define PKT_ISRC1_CONTENTS1 0xb44 -+#define PKT_ISRC1_CONTENTS2 0xb48 -+#define PKT_ISRC1_CONTENTS3 0xb4c -+#define PKT_ISRC1_CONTENTS4 0xb50 -+#define PKT_ISRC1_CONTENTS5 0xb54 -+#define PKT_ISRC1_CONTENTS6 0xb58 -+#define PKT_ISRC1_CONTENTS7 0xb5c -+#define PKT_ISRC2_CONTENTS0 0xb60 -+#define PKT_ISRC2_CONTENTS1 0xb64 -+#define PKT_ISRC2_CONTENTS2 0xb68 -+#define PKT_ISRC2_CONTENTS3 0xb6c -+#define PKT_ISRC2_CONTENTS4 0xb70 -+#define PKT_ISRC2_CONTENTS5 0xb74 -+#define PKT_ISRC2_CONTENTS6 0xb78 -+#define PKT_ISRC2_CONTENTS7 0xb7c -+#define PKT_GMD_CONTENTS0 0xb80 -+#define PKT_GMD_CONTENTS1 0xb84 -+#define PKT_GMD_CONTENTS2 0xb88 -+#define PKT_GMD_CONTENTS3 0xb8c -+#define PKT_GMD_CONTENTS4 0xb90 -+#define PKT_GMD_CONTENTS5 0xb94 -+#define PKT_GMD_CONTENTS6 0xb98 -+#define PKT_GMD_CONTENTS7 0xb9c -+#define PKT_AMD_CONTENTS0 0xba0 -+#define PKT_AMD_CONTENTS1 0xba4 -+#define PKT_AMD_CONTENTS2 0xba8 -+#define PKT_AMD_CONTENTS3 0xbac -+#define PKT_AMD_CONTENTS4 0xbb0 -+#define PKT_AMD_CONTENTS5 0xbb4 -+#define PKT_AMD_CONTENTS6 0xbb8 -+#define PKT_AMD_CONTENTS7 0xbbc -+#define PKT_VSI_CONTENTS0 0xbc0 -+#define PKT_VSI_CONTENTS1 0xbc4 -+#define PKT_VSI_CONTENTS2 0xbc8 -+#define PKT_VSI_CONTENTS3 0xbcc -+#define PKT_VSI_CONTENTS4 0xbd0 -+#define PKT_VSI_CONTENTS5 0xbd4 -+#define PKT_VSI_CONTENTS6 0xbd8 -+#define PKT_VSI_CONTENTS7 0xbdc -+#define PKT_AVI_CONTENTS0 0xbe0 -+#define HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT BIT(4) -+#define HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR 0x04 -+#define HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR 0x08 -+#define HDMI_FC_AVICONF2_IT_CONTENT_VALID 0x80 -+#define PKT_AVI_CONTENTS1 0xbe4 -+#define PKT_AVI_CONTENTS2 0xbe8 -+#define PKT_AVI_CONTENTS3 0xbec -+#define PKT_AVI_CONTENTS4 0xbf0 -+#define PKT_AVI_CONTENTS5 0xbf4 -+#define PKT_AVI_CONTENTS6 0xbf8 -+#define PKT_AVI_CONTENTS7 0xbfc -+#define PKT_SPDI_CONTENTS0 0xc00 -+#define PKT_SPDI_CONTENTS1 0xc04 -+#define PKT_SPDI_CONTENTS2 0xc08 -+#define PKT_SPDI_CONTENTS3 0xc0c -+#define PKT_SPDI_CONTENTS4 0xc10 -+#define PKT_SPDI_CONTENTS5 0xc14 -+#define PKT_SPDI_CONTENTS6 0xc18 -+#define PKT_SPDI_CONTENTS7 0xc1c -+#define PKT_AUDI_CONTENTS0 0xc20 -+#define PKT_AUDI_CONTENTS1 0xc24 -+#define PKT_AUDI_CONTENTS2 0xc28 -+#define PKT_AUDI_CONTENTS3 0xc2c -+#define PKT_AUDI_CONTENTS4 0xc30 -+#define PKT_AUDI_CONTENTS5 0xc34 -+#define PKT_AUDI_CONTENTS6 0xc38 -+#define PKT_AUDI_CONTENTS7 0xc3c -+#define PKT_NVI_CONTENTS0 0xc40 -+#define PKT_NVI_CONTENTS1 0xc44 -+#define PKT_NVI_CONTENTS2 0xc48 -+#define PKT_NVI_CONTENTS3 0xc4c -+#define PKT_NVI_CONTENTS4 0xc50 -+#define PKT_NVI_CONTENTS5 0xc54 -+#define PKT_NVI_CONTENTS6 0xc58 -+#define PKT_NVI_CONTENTS7 0xc5c -+#define PKT_DRMI_CONTENTS0 0xc60 -+#define PKT_DRMI_CONTENTS1 0xc64 -+#define PKT_DRMI_CONTENTS2 0xc68 -+#define PKT_DRMI_CONTENTS3 0xc6c -+#define PKT_DRMI_CONTENTS4 0xc70 -+#define PKT_DRMI_CONTENTS5 0xc74 -+#define PKT_DRMI_CONTENTS6 0xc78 -+#define PKT_DRMI_CONTENTS7 0xc7c -+#define PKT_GHDMI1_CONTENTS0 0xc80 -+#define PKT_GHDMI1_CONTENTS1 0xc84 -+#define PKT_GHDMI1_CONTENTS2 0xc88 -+#define PKT_GHDMI1_CONTENTS3 0xc8c -+#define PKT_GHDMI1_CONTENTS4 0xc90 -+#define PKT_GHDMI1_CONTENTS5 0xc94 -+#define PKT_GHDMI1_CONTENTS6 0xc98 -+#define PKT_GHDMI1_CONTENTS7 0xc9c -+#define PKT_GHDMI2_CONTENTS0 0xca0 -+#define PKT_GHDMI2_CONTENTS1 0xca4 -+#define PKT_GHDMI2_CONTENTS2 0xca8 -+#define PKT_GHDMI2_CONTENTS3 0xcac -+#define PKT_GHDMI2_CONTENTS4 0xcb0 -+#define PKT_GHDMI2_CONTENTS5 0xcb4 -+#define PKT_GHDMI2_CONTENTS6 0xcb8 -+#define PKT_GHDMI2_CONTENTS7 0xcbc -+/* EMP Packetizer Registers */ -+#define PKT_EMP_CONFIG0 0xce0 -+#define PKT_EMP_CONTROL0 0xcec -+#define PKT_EMP_CONTROL1 0xcf0 -+#define PKT_EMP_CONTROL2 0xcf4 -+#define PKT_EMP_VTEM_CONTENTS0 0xd00 -+#define PKT_EMP_VTEM_CONTENTS1 0xd04 -+#define PKT_EMP_VTEM_CONTENTS2 0xd08 -+#define PKT_EMP_VTEM_CONTENTS3 0xd0c -+#define PKT_EMP_VTEM_CONTENTS4 0xd10 -+#define PKT_EMP_VTEM_CONTENTS5 0xd14 -+#define PKT_EMP_VTEM_CONTENTS6 0xd18 -+#define PKT_EMP_VTEM_CONTENTS7 0xd1c -+#define PKT0_EMP_CVTEM_CONTENTS0 0xd20 -+#define PKT0_EMP_CVTEM_CONTENTS1 0xd24 -+#define PKT0_EMP_CVTEM_CONTENTS2 0xd28 -+#define PKT0_EMP_CVTEM_CONTENTS3 0xd2c -+#define PKT0_EMP_CVTEM_CONTENTS4 0xd30 -+#define PKT0_EMP_CVTEM_CONTENTS5 0xd34 -+#define PKT0_EMP_CVTEM_CONTENTS6 0xd38 -+#define PKT0_EMP_CVTEM_CONTENTS7 0xd3c -+#define PKT1_EMP_CVTEM_CONTENTS0 0xd40 -+#define PKT1_EMP_CVTEM_CONTENTS1 0xd44 -+#define PKT1_EMP_CVTEM_CONTENTS2 0xd48 -+#define PKT1_EMP_CVTEM_CONTENTS3 0xd4c -+#define PKT1_EMP_CVTEM_CONTENTS4 0xd50 -+#define PKT1_EMP_CVTEM_CONTENTS5 0xd54 -+#define PKT1_EMP_CVTEM_CONTENTS6 0xd58 -+#define PKT1_EMP_CVTEM_CONTENTS7 0xd5c -+#define PKT2_EMP_CVTEM_CONTENTS0 0xd60 -+#define PKT2_EMP_CVTEM_CONTENTS1 0xd64 -+#define PKT2_EMP_CVTEM_CONTENTS2 0xd68 -+#define PKT2_EMP_CVTEM_CONTENTS3 0xd6c -+#define PKT2_EMP_CVTEM_CONTENTS4 0xd70 -+#define PKT2_EMP_CVTEM_CONTENTS5 0xd74 -+#define PKT2_EMP_CVTEM_CONTENTS6 0xd78 -+#define PKT2_EMP_CVTEM_CONTENTS7 0xd7c -+#define PKT3_EMP_CVTEM_CONTENTS0 0xd80 -+#define PKT3_EMP_CVTEM_CONTENTS1 0xd84 -+#define PKT3_EMP_CVTEM_CONTENTS2 0xd88 -+#define PKT3_EMP_CVTEM_CONTENTS3 0xd8c -+#define PKT3_EMP_CVTEM_CONTENTS4 0xd90 -+#define PKT3_EMP_CVTEM_CONTENTS5 0xd94 -+#define PKT3_EMP_CVTEM_CONTENTS6 0xd98 -+#define PKT3_EMP_CVTEM_CONTENTS7 0xd9c -+#define PKT4_EMP_CVTEM_CONTENTS0 0xda0 -+#define PKT4_EMP_CVTEM_CONTENTS1 0xda4 -+#define PKT4_EMP_CVTEM_CONTENTS2 0xda8 -+#define PKT4_EMP_CVTEM_CONTENTS3 0xdac -+#define PKT4_EMP_CVTEM_CONTENTS4 0xdb0 -+#define PKT4_EMP_CVTEM_CONTENTS5 0xdb4 -+#define PKT4_EMP_CVTEM_CONTENTS6 0xdb8 -+#define PKT4_EMP_CVTEM_CONTENTS7 0xdbc -+#define PKT5_EMP_CVTEM_CONTENTS0 0xdc0 -+#define PKT5_EMP_CVTEM_CONTENTS1 0xdc4 -+#define PKT5_EMP_CVTEM_CONTENTS2 0xdc8 -+#define PKT5_EMP_CVTEM_CONTENTS3 0xdcc -+#define PKT5_EMP_CVTEM_CONTENTS4 0xdd0 -+#define PKT5_EMP_CVTEM_CONTENTS5 0xdd4 -+#define PKT5_EMP_CVTEM_CONTENTS6 0xdd8 -+#define PKT5_EMP_CVTEM_CONTENTS7 0xddc -+/* Audio Packetizer Registers */ -+#define AUDPKT_CONTROL0 0xe20 -+#define AUDPKT_PBIT_FORCE_EN_MASK BIT(12) -+#define AUDPKT_PBIT_FORCE_EN BIT(12) -+#define AUDPKT_CHSTATUS_OVR_EN_MASK BIT(0) -+#define AUDPKT_CHSTATUS_OVR_EN BIT(0) -+#define AUDPKT_CONTROL1 0xe24 -+#define AUDPKT_ACR_CONTROL0 0xe40 -+#define AUDPKT_ACR_N_VALUE 0xfffff -+#define AUDPKT_ACR_CONTROL1 0xe44 -+#define AUDPKT_ACR_CTS_OVR_VAL_MSK GENMASK(23, 4) -+#define AUDPKT_ACR_CTS_OVR_VAL(x) ((x) << 4) -+#define AUDPKT_ACR_CTS_OVR_EN_MSK BIT(1) -+#define AUDPKT_ACR_CTS_OVR_EN BIT(1) -+#define AUDPKT_ACR_STATUS0 0xe4c -+#define AUDPKT_CHSTATUS_OVR0 0xe60 -+#define AUDPKT_CHSTATUS_OVR1 0xe64 -+/* IEC60958 Byte 3: Sampleing frenuency Bits 24 to 27 */ -+#define AUDPKT_CHSTATUS_SR_MASK GENMASK(3, 0) -+#define AUDPKT_CHSTATUS_SR_22050 0x4 -+#define AUDPKT_CHSTATUS_SR_24000 0x6 -+#define AUDPKT_CHSTATUS_SR_32000 0x3 -+#define AUDPKT_CHSTATUS_SR_44100 0x0 -+#define AUDPKT_CHSTATUS_SR_48000 0x2 -+#define AUDPKT_CHSTATUS_SR_88200 0x8 -+#define AUDPKT_CHSTATUS_SR_96000 0xa -+#define AUDPKT_CHSTATUS_SR_176400 0xc -+#define AUDPKT_CHSTATUS_SR_192000 0xe -+#define AUDPKT_CHSTATUS_SR_768000 0x9 -+#define AUDPKT_CHSTATUS_SR_NOT_INDICATED 0x1 -+/* IEC60958 Byte 4: Original Sampleing frenuency Bits 36 to 39 */ -+#define AUDPKT_CHSTATUS_0SR_MASK GENMASK(15, 12) -+#define AUDPKT_CHSTATUS_OSR_8000 0x6 -+#define AUDPKT_CHSTATUS_OSR_11025 0xa -+#define AUDPKT_CHSTATUS_OSR_12000 0x2 -+#define AUDPKT_CHSTATUS_OSR_16000 0x8 -+#define AUDPKT_CHSTATUS_OSR_22050 0xb -+#define AUDPKT_CHSTATUS_OSR_24000 0x9 -+#define AUDPKT_CHSTATUS_OSR_32000 0xc -+#define AUDPKT_CHSTATUS_OSR_44100 0xf -+#define AUDPKT_CHSTATUS_OSR_48000 0xd -+#define AUDPKT_CHSTATUS_OSR_88200 0x7 -+#define AUDPKT_CHSTATUS_OSR_96000 0x5 -+#define AUDPKT_CHSTATUS_OSR_176400 0x3 -+#define AUDPKT_CHSTATUS_OSR_192000 0x1 -+#define AUDPKT_CHSTATUS_OSR_NOT_INDICATED 0x0 -+#define AUDPKT_CHSTATUS_OVR2 0xe68 -+#define AUDPKT_CHSTATUS_OVR3 0xe6c -+#define AUDPKT_CHSTATUS_OVR4 0xe70 -+#define AUDPKT_CHSTATUS_OVR5 0xe74 -+#define AUDPKT_CHSTATUS_OVR6 0xe78 -+#define AUDPKT_CHSTATUS_OVR7 0xe7c -+#define AUDPKT_CHSTATUS_OVR8 0xe80 -+#define AUDPKT_CHSTATUS_OVR9 0xe84 -+#define AUDPKT_CHSTATUS_OVR10 0xe88 -+#define AUDPKT_CHSTATUS_OVR11 0xe8c -+#define AUDPKT_CHSTATUS_OVR12 0xe90 -+#define AUDPKT_CHSTATUS_OVR13 0xe94 -+#define AUDPKT_CHSTATUS_OVR14 0xe98 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC0 0xea0 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC1 0xea4 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC2 0xea8 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC3 0xeac -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC4 0xeb0 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC5 0xeb4 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC6 0xeb8 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC7 0xebc -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC8 0xec0 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC9 0xec4 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC10 0xec8 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC11 0xecc -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC12 0xed0 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC13 0xed4 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC14 0xed8 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC15 0xedc -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC16 0xee0 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC17 0xee4 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC18 0xee8 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC19 0xeec -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC20 0xef0 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC21 0xef4 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC22 0xef8 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC23 0xefc -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC24 0xf00 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC25 0xf04 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC26 0xf08 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC27 0xf0c -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC28 0xf10 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC29 0xf14 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC30 0xf18 -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC31 0xf1c -+#define AUDPKT_USRDATA_OVR_MSG_GENERIC32 0xf20 -+#define AUDPKT_VBIT_OVR0 0xf24 -+/* CEC Registers */ -+#define CEC_TX_CONTROL 0x1000 -+#define CEC_STATUS 0x1004 -+#define CEC_CONFIG 0x1008 -+#define CEC_ADDR 0x100c -+#define CEC_TX_COUNT 0x1020 -+#define CEC_TX_DATA3_0 0x1024 -+#define CEC_TX_DATA7_4 0x1028 -+#define CEC_TX_DATA11_8 0x102c -+#define CEC_TX_DATA15_12 0x1030 -+#define CEC_RX_COUNT_STATUS 0x1040 -+#define CEC_RX_DATA3_0 0x1044 -+#define CEC_RX_DATA7_4 0x1048 -+#define CEC_RX_DATA11_8 0x104c -+#define CEC_RX_DATA15_12 0x1050 -+#define CEC_LOCK_CONTROL 0x1054 -+#define CEC_RXQUAL_BITTIME_CONFIG 0x1060 -+#define CEC_RX_BITTIME_CONFIG 0x1064 -+#define CEC_TX_BITTIME_CONFIG 0x1068 -+/* eARC RX CMDC Registers */ -+#define EARCRX_CMDC_CONFIG0 0x1800 -+#define EARCRX_XACTREAD_STOP_CFG BIT(26) -+#define EARCRX_XACTREAD_RETRY_CFG BIT(25) -+#define EARCRX_CMDC_DSCVR_EARCVALID0_TO_DISC1 BIT(24) -+#define EARCRX_CMDC_XACT_RESTART_EN BIT(18) -+#define EARCRX_CMDC_CONFIG1 0x1804 -+#define EARCRX_CMDC_CONTROL 0x1808 -+#define EARCRX_CMDC_HEARTBEAT_LOSS_EN BIT(4) -+#define EARCRX_CMDC_DISCOVERY_EN BIT(3) -+#define EARCRX_CONNECTOR_HPD BIT(1) -+#define EARCRX_CMDC_WHITELIST0_CONFIG 0x180c -+#define EARCRX_CMDC_WHITELIST1_CONFIG 0x1810 -+#define EARCRX_CMDC_WHITELIST2_CONFIG 0x1814 -+#define EARCRX_CMDC_WHITELIST3_CONFIG 0x1818 -+#define EARCRX_CMDC_STATUS 0x181c -+#define EARCRX_CMDC_XACT_INFO 0x1820 -+#define EARCRX_CMDC_XACT_ACTION 0x1824 -+#define EARCRX_CMDC_HEARTBEAT_RXSTAT_SE 0x1828 -+#define EARCRX_CMDC_HEARTBEAT_STATUS 0x182c -+#define EARCRX_CMDC_XACT_WR0 0x1840 -+#define EARCRX_CMDC_XACT_WR1 0x1844 -+#define EARCRX_CMDC_XACT_WR2 0x1848 -+#define EARCRX_CMDC_XACT_WR3 0x184c -+#define EARCRX_CMDC_XACT_WR4 0x1850 -+#define EARCRX_CMDC_XACT_WR5 0x1854 -+#define EARCRX_CMDC_XACT_WR6 0x1858 -+#define EARCRX_CMDC_XACT_WR7 0x185c -+#define EARCRX_CMDC_XACT_WR8 0x1860 -+#define EARCRX_CMDC_XACT_WR9 0x1864 -+#define EARCRX_CMDC_XACT_WR10 0x1868 -+#define EARCRX_CMDC_XACT_WR11 0x186c -+#define EARCRX_CMDC_XACT_WR12 0x1870 -+#define EARCRX_CMDC_XACT_WR13 0x1874 -+#define EARCRX_CMDC_XACT_WR14 0x1878 -+#define EARCRX_CMDC_XACT_WR15 0x187c -+#define EARCRX_CMDC_XACT_WR16 0x1880 -+#define EARCRX_CMDC_XACT_WR17 0x1884 -+#define EARCRX_CMDC_XACT_WR18 0x1888 -+#define EARCRX_CMDC_XACT_WR19 0x188c -+#define EARCRX_CMDC_XACT_WR20 0x1890 -+#define EARCRX_CMDC_XACT_WR21 0x1894 -+#define EARCRX_CMDC_XACT_WR22 0x1898 -+#define EARCRX_CMDC_XACT_WR23 0x189c -+#define EARCRX_CMDC_XACT_WR24 0x18a0 -+#define EARCRX_CMDC_XACT_WR25 0x18a4 -+#define EARCRX_CMDC_XACT_WR26 0x18a8 -+#define EARCRX_CMDC_XACT_WR27 0x18ac -+#define EARCRX_CMDC_XACT_WR28 0x18b0 -+#define EARCRX_CMDC_XACT_WR29 0x18b4 -+#define EARCRX_CMDC_XACT_WR30 0x18b8 -+#define EARCRX_CMDC_XACT_WR31 0x18bc -+#define EARCRX_CMDC_XACT_WR32 0x18c0 -+#define EARCRX_CMDC_XACT_WR33 0x18c4 -+#define EARCRX_CMDC_XACT_WR34 0x18c8 -+#define EARCRX_CMDC_XACT_WR35 0x18cc -+#define EARCRX_CMDC_XACT_WR36 0x18d0 -+#define EARCRX_CMDC_XACT_WR37 0x18d4 -+#define EARCRX_CMDC_XACT_WR38 0x18d8 -+#define EARCRX_CMDC_XACT_WR39 0x18dc -+#define EARCRX_CMDC_XACT_WR40 0x18e0 -+#define EARCRX_CMDC_XACT_WR41 0x18e4 -+#define EARCRX_CMDC_XACT_WR42 0x18e8 -+#define EARCRX_CMDC_XACT_WR43 0x18ec -+#define EARCRX_CMDC_XACT_WR44 0x18f0 -+#define EARCRX_CMDC_XACT_WR45 0x18f4 -+#define EARCRX_CMDC_XACT_WR46 0x18f8 -+#define EARCRX_CMDC_XACT_WR47 0x18fc -+#define EARCRX_CMDC_XACT_WR48 0x1900 -+#define EARCRX_CMDC_XACT_WR49 0x1904 -+#define EARCRX_CMDC_XACT_WR50 0x1908 -+#define EARCRX_CMDC_XACT_WR51 0x190c -+#define EARCRX_CMDC_XACT_WR52 0x1910 -+#define EARCRX_CMDC_XACT_WR53 0x1914 -+#define EARCRX_CMDC_XACT_WR54 0x1918 -+#define EARCRX_CMDC_XACT_WR55 0x191c -+#define EARCRX_CMDC_XACT_WR56 0x1920 -+#define EARCRX_CMDC_XACT_WR57 0x1924 -+#define EARCRX_CMDC_XACT_WR58 0x1928 -+#define EARCRX_CMDC_XACT_WR59 0x192c -+#define EARCRX_CMDC_XACT_WR60 0x1930 -+#define EARCRX_CMDC_XACT_WR61 0x1934 -+#define EARCRX_CMDC_XACT_WR62 0x1938 -+#define EARCRX_CMDC_XACT_WR63 0x193c -+#define EARCRX_CMDC_XACT_WR64 0x1940 -+#define EARCRX_CMDC_XACT_RD0 0x1960 -+#define EARCRX_CMDC_XACT_RD1 0x1964 -+#define EARCRX_CMDC_XACT_RD2 0x1968 -+#define EARCRX_CMDC_XACT_RD3 0x196c -+#define EARCRX_CMDC_XACT_RD4 0x1970 -+#define EARCRX_CMDC_XACT_RD5 0x1974 -+#define EARCRX_CMDC_XACT_RD6 0x1978 -+#define EARCRX_CMDC_XACT_RD7 0x197c -+#define EARCRX_CMDC_XACT_RD8 0x1980 -+#define EARCRX_CMDC_XACT_RD9 0x1984 -+#define EARCRX_CMDC_XACT_RD10 0x1988 -+#define EARCRX_CMDC_XACT_RD11 0x198c -+#define EARCRX_CMDC_XACT_RD12 0x1990 -+#define EARCRX_CMDC_XACT_RD13 0x1994 -+#define EARCRX_CMDC_XACT_RD14 0x1998 -+#define EARCRX_CMDC_XACT_RD15 0x199c -+#define EARCRX_CMDC_XACT_RD16 0x19a0 -+#define EARCRX_CMDC_XACT_RD17 0x19a4 -+#define EARCRX_CMDC_XACT_RD18 0x19a8 -+#define EARCRX_CMDC_XACT_RD19 0x19ac -+#define EARCRX_CMDC_XACT_RD20 0x19b0 -+#define EARCRX_CMDC_XACT_RD21 0x19b4 -+#define EARCRX_CMDC_XACT_RD22 0x19b8 -+#define EARCRX_CMDC_XACT_RD23 0x19bc -+#define EARCRX_CMDC_XACT_RD24 0x19c0 -+#define EARCRX_CMDC_XACT_RD25 0x19c4 -+#define EARCRX_CMDC_XACT_RD26 0x19c8 -+#define EARCRX_CMDC_XACT_RD27 0x19cc -+#define EARCRX_CMDC_XACT_RD28 0x19d0 -+#define EARCRX_CMDC_XACT_RD29 0x19d4 -+#define EARCRX_CMDC_XACT_RD30 0x19d8 -+#define EARCRX_CMDC_XACT_RD31 0x19dc -+#define EARCRX_CMDC_XACT_RD32 0x19e0 -+#define EARCRX_CMDC_XACT_RD33 0x19e4 -+#define EARCRX_CMDC_XACT_RD34 0x19e8 -+#define EARCRX_CMDC_XACT_RD35 0x19ec -+#define EARCRX_CMDC_XACT_RD36 0x19f0 -+#define EARCRX_CMDC_XACT_RD37 0x19f4 -+#define EARCRX_CMDC_XACT_RD38 0x19f8 -+#define EARCRX_CMDC_XACT_RD39 0x19fc -+#define EARCRX_CMDC_XACT_RD40 0x1a00 -+#define EARCRX_CMDC_XACT_RD41 0x1a04 -+#define EARCRX_CMDC_XACT_RD42 0x1a08 -+#define EARCRX_CMDC_XACT_RD43 0x1a0c -+#define EARCRX_CMDC_XACT_RD44 0x1a10 -+#define EARCRX_CMDC_XACT_RD45 0x1a14 -+#define EARCRX_CMDC_XACT_RD46 0x1a18 -+#define EARCRX_CMDC_XACT_RD47 0x1a1c -+#define EARCRX_CMDC_XACT_RD48 0x1a20 -+#define EARCRX_CMDC_XACT_RD49 0x1a24 -+#define EARCRX_CMDC_XACT_RD50 0x1a28 -+#define EARCRX_CMDC_XACT_RD51 0x1a2c -+#define EARCRX_CMDC_XACT_RD52 0x1a30 -+#define EARCRX_CMDC_XACT_RD53 0x1a34 -+#define EARCRX_CMDC_XACT_RD54 0x1a38 -+#define EARCRX_CMDC_XACT_RD55 0x1a3c -+#define EARCRX_CMDC_XACT_RD56 0x1a40 -+#define EARCRX_CMDC_XACT_RD57 0x1a44 -+#define EARCRX_CMDC_XACT_RD58 0x1a48 -+#define EARCRX_CMDC_XACT_RD59 0x1a4c -+#define EARCRX_CMDC_XACT_RD60 0x1a50 -+#define EARCRX_CMDC_XACT_RD61 0x1a54 -+#define EARCRX_CMDC_XACT_RD62 0x1a58 -+#define EARCRX_CMDC_XACT_RD63 0x1a5c -+#define EARCRX_CMDC_XACT_RD64 0x1a60 -+#define EARCRX_CMDC_SYNC_CONFIG 0x1b00 -+/* eARC RX DMAC Registers */ -+#define EARCRX_DMAC_PHY_CONTROL 0x1c00 -+#define EARCRX_DMAC_CONFIG 0x1c08 -+#define EARCRX_DMAC_CONTROL0 0x1c0c -+#define EARCRX_DMAC_AUDIO_EN BIT(1) -+#define EARCRX_DMAC_EN BIT(0) -+#define EARCRX_DMAC_CONTROL1 0x1c10 -+#define EARCRX_DMAC_STATUS 0x1c14 -+#define EARCRX_DMAC_CHSTATUS0 0x1c18 -+#define EARCRX_DMAC_CHSTATUS1 0x1c1c -+#define EARCRX_DMAC_CHSTATUS2 0x1c20 -+#define EARCRX_DMAC_CHSTATUS3 0x1c24 -+#define EARCRX_DMAC_CHSTATUS4 0x1c28 -+#define EARCRX_DMAC_CHSTATUS5 0x1c2c -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC0 0x1c30 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC1 0x1c34 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC2 0x1c38 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC3 0x1c3c -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC4 0x1c40 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC5 0x1c44 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC6 0x1c48 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC7 0x1c4c -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC8 0x1c50 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC9 0x1c54 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC10 0x1c58 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC11 0x1c5c -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT0 0x1c60 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT1 0x1c64 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT2 0x1c68 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT3 0x1c6c -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT4 0x1c70 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT5 0x1c74 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT6 0x1c78 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT7 0x1c7c -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT8 0x1c80 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT9 0x1c84 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT10 0x1c88 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT11 0x1c8c -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT0 0x1c90 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT1 0x1c94 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT2 0x1c98 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT3 0x1c9c -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT4 0x1ca0 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT5 0x1ca4 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT6 0x1ca8 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT7 0x1cac -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT8 0x1cb0 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT9 0x1cb4 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT10 0x1cb8 -+#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT11 0x1cbc -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC0 0x1cc0 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC1 0x1cc4 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC2 0x1cc8 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC3 0x1ccc -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC4 0x1cd0 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC5 0x1cd4 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC6 0x1cd8 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC7 0x1cdc -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC8 0x1ce0 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC9 0x1ce4 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC10 0x1ce8 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC11 0x1cec -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC12 0x1cf0 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC13 0x1cf4 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC14 0x1cf8 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC15 0x1cfc -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC16 0x1d00 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC17 0x1d04 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC18 0x1d08 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC19 0x1d0c -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC20 0x1d10 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC21 0x1d14 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC22 0x1d18 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC23 0x1d1c -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC24 0x1d20 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC25 0x1d24 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC26 0x1d28 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC27 0x1d2c -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC28 0x1d30 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC29 0x1d34 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC30 0x1d38 -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC31 0x1d3c -+#define EARCRX_DMAC_USRDATA_MSG_GENERIC32 0x1d40 -+#define EARCRX_DMAC_CHSTATUS_STREAMER0 0x1d44 -+#define EARCRX_DMAC_CHSTATUS_STREAMER1 0x1d48 -+#define EARCRX_DMAC_CHSTATUS_STREAMER2 0x1d4c -+#define EARCRX_DMAC_CHSTATUS_STREAMER3 0x1d50 -+#define EARCRX_DMAC_CHSTATUS_STREAMER4 0x1d54 -+#define EARCRX_DMAC_CHSTATUS_STREAMER5 0x1d58 -+#define EARCRX_DMAC_CHSTATUS_STREAMER6 0x1d5c -+#define EARCRX_DMAC_CHSTATUS_STREAMER7 0x1d60 -+#define EARCRX_DMAC_CHSTATUS_STREAMER8 0x1d64 -+#define EARCRX_DMAC_CHSTATUS_STREAMER9 0x1d68 -+#define EARCRX_DMAC_CHSTATUS_STREAMER10 0x1d6c -+#define EARCRX_DMAC_CHSTATUS_STREAMER11 0x1d70 -+#define EARCRX_DMAC_CHSTATUS_STREAMER12 0x1d74 -+#define EARCRX_DMAC_CHSTATUS_STREAMER13 0x1d78 -+#define EARCRX_DMAC_CHSTATUS_STREAMER14 0x1d7c -+#define EARCRX_DMAC_USRDATA_STREAMER0 0x1d80 -+/* Main Unit Interrupt Registers */ -+#define MAIN_INTVEC_INDEX 0x3000 -+#define MAINUNIT_0_INT_STATUS 0x3010 -+#define MAINUNIT_0_INT_MASK_N 0x3014 -+#define MAINUNIT_0_INT_CLEAR 0x3018 -+#define MAINUNIT_0_INT_FORCE 0x301c -+#define MAINUNIT_1_INT_STATUS 0x3020 -+#define FLT_EXIT_TO_LTSL_IRQ BIT(22) -+#define FLT_EXIT_TO_LTS4_IRQ BIT(21) -+#define FLT_EXIT_TO_LTSP_IRQ BIT(20) -+#define SCDC_NACK_RCVD_IRQ BIT(12) -+#define SCDC_RR_REPLY_STOP_IRQ BIT(11) -+#define SCDC_UPD_FLAGS_CLR_IRQ BIT(10) -+#define SCDC_UPD_FLAGS_CHG_IRQ BIT(9) -+#define SCDC_UPD_FLAGS_RD_IRQ BIT(8) -+#define I2CM_NACK_RCVD_IRQ BIT(2) -+#define I2CM_READ_REQUEST_IRQ BIT(1) -+#define I2CM_OP_DONE_IRQ BIT(0) -+#define MAINUNIT_1_INT_MASK_N 0x3024 -+#define I2CM_NACK_RCVD_MASK_N BIT(2) -+#define I2CM_READ_REQUEST_MASK_N BIT(1) -+#define I2CM_OP_DONE_MASK_N BIT(0) -+#define MAINUNIT_1_INT_CLEAR 0x3028 -+#define I2CM_NACK_RCVD_CLEAR BIT(2) -+#define I2CM_READ_REQUEST_CLEAR BIT(1) -+#define I2CM_OP_DONE_CLEAR BIT(0) -+#define MAINUNIT_1_INT_FORCE 0x302c -+/* AVPUNIT Interrupt Registers */ -+#define AVP_INTVEC_INDEX 0x3800 -+#define AVP_0_INT_STATUS 0x3810 -+#define AVP_0_INT_MASK_N 0x3814 -+#define AVP_0_INT_CLEAR 0x3818 -+#define AVP_0_INT_FORCE 0x381c -+#define AVP_1_INT_STATUS 0x3820 -+#define AVP_1_INT_MASK_N 0x3824 -+#define HDCP14_AUTH_CHG_MASK_N BIT(6) -+#define AVP_1_INT_CLEAR 0x3828 -+#define AVP_1_INT_FORCE 0x382c -+#define AVP_2_INT_STATUS 0x3830 -+#define AVP_2_INT_MASK_N 0x3834 -+#define AVP_2_INT_CLEAR 0x3838 -+#define AVP_2_INT_FORCE 0x383c -+#define AVP_3_INT_STATUS 0x3840 -+#define AVP_3_INT_MASK_N 0x3844 -+#define AVP_3_INT_CLEAR 0x3848 -+#define AVP_3_INT_FORCE 0x384c -+#define AVP_4_INT_STATUS 0x3850 -+#define AVP_4_INT_MASK_N 0x3854 -+#define AVP_4_INT_CLEAR 0x3858 -+#define AVP_4_INT_FORCE 0x385c -+#define AVP_5_INT_STATUS 0x3860 -+#define AVP_5_INT_MASK_N 0x3864 -+#define AVP_5_INT_CLEAR 0x3868 -+#define AVP_5_INT_FORCE 0x386c -+#define AVP_6_INT_STATUS 0x3870 -+#define AVP_6_INT_MASK_N 0x3874 -+#define AVP_6_INT_CLEAR 0x3878 -+#define AVP_6_INT_FORCE 0x387c -+/* CEC Interrupt Registers */ -+#define CEC_INT_STATUS 0x4000 -+#define CEC_INT_MASK_N 0x4004 -+#define CEC_INT_CLEAR 0x4008 -+#define CEC_INT_FORCE 0x400c -+/* eARC RX Interrupt Registers */ -+#define EARCRX_INTVEC_INDEX 0x4800 -+#define EARCRX_0_INT_STATUS 0x4810 -+#define EARCRX_CMDC_DISCOVERY_TIMEOUT_IRQ BIT(9) -+#define EARCRX_CMDC_DISCOVERY_DONE_IRQ BIT(8) -+#define EARCRX_0_INT_MASK_N 0x4814 -+#define EARCRX_0_INT_CLEAR 0x4818 -+#define EARCRX_0_INT_FORCE 0x481c -+#define EARCRX_1_INT_STATUS 0x4820 -+#define EARCRX_1_INT_MASK_N 0x4824 -+#define EARCRX_1_INT_CLEAR 0x4828 -+#define EARCRX_1_INT_FORCE 0x482c -+ -+#endif /* __DW_HDMI_QP_H__ */ -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index 111111111111..222222222222 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -163,6 +163,8 @@ struct dw_hdmi { - void __iomem *regs; - bool sink_is_hdmi; - bool sink_has_audio; -+ bool support_hdmi; -+ int force_output; - - struct pinctrl *pinctrl; - struct pinctrl_state *default_state; -@@ -255,6 +257,25 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, - hdmi_modb(hdmi, data << shift, mask, reg); - } - -+static bool dw_hdmi_check_output_type_changed(struct dw_hdmi *hdmi) -+{ -+ bool sink_hdmi; -+ -+ sink_hdmi = hdmi->sink_is_hdmi; -+ -+ if (hdmi->force_output == 1) -+ hdmi->sink_is_hdmi = true; -+ else if (hdmi->force_output == 2) -+ hdmi->sink_is_hdmi = false; -+ else -+ hdmi->sink_is_hdmi = hdmi->support_hdmi; -+ -+ if (sink_hdmi != hdmi->sink_is_hdmi) -+ return true; -+ -+ return false; -+} -+ - static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi) - { - hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, -@@ -2539,6 +2560,45 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, - return 0; - } - -+void dw_hdmi_set_quant_range(struct dw_hdmi *hdmi) -+{ -+ if (!hdmi->bridge_is_on) -+ return; -+ -+ hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP); -+ dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); -+ hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP); -+} -+EXPORT_SYMBOL_GPL(dw_hdmi_set_quant_range); -+ -+void dw_hdmi_set_output_type(struct dw_hdmi *hdmi, u64 val) -+{ -+ hdmi->force_output = val; -+ -+ if (!dw_hdmi_check_output_type_changed(hdmi)) -+ return; -+ -+ if (!hdmi->bridge_is_on) -+ return; -+ -+ hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP); -+ dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); -+ hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP); -+} -+EXPORT_SYMBOL_GPL(dw_hdmi_set_output_type); -+ -+bool dw_hdmi_get_output_whether_hdmi(struct dw_hdmi *hdmi) -+{ -+ return hdmi->sink_is_hdmi; -+} -+EXPORT_SYMBOL_GPL(dw_hdmi_get_output_whether_hdmi); -+ -+int dw_hdmi_get_output_type_cap(struct dw_hdmi *hdmi) -+{ -+ return hdmi->support_hdmi; -+} -+EXPORT_SYMBOL_GPL(dw_hdmi_get_output_type_cap); -+ - static void dw_hdmi_connector_force(struct drm_connector *connector) - { - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, -@@ -3668,6 +3728,35 @@ void dw_hdmi_unbind(struct dw_hdmi *hdmi) - } - EXPORT_SYMBOL_GPL(dw_hdmi_unbind); - -+void dw_hdmi_suspend(struct dw_hdmi *hdmi) -+{ -+ if (!hdmi) -+ return; -+ -+ mutex_lock(&hdmi->mutex); -+ -+ /* -+ * When system shutdown, hdmi should be disabled. -+ * When system suspend, dw_hdmi_bridge_disable will disable hdmi first. -+ * To prevent duplicate operation, we should determine whether hdmi -+ * has been disabled. -+ */ -+ if (!hdmi->disabled) { -+ hdmi->disabled = true; -+ dw_hdmi_update_power(hdmi); -+ dw_hdmi_update_phy_mask(hdmi); -+ } -+ mutex_unlock(&hdmi->mutex); -+ -+ //[CC: needed?] -+ // if (hdmi->irq) -+ // disable_irq(hdmi->irq); -+ // cancel_delayed_work(&hdmi->work); -+ // flush_workqueue(hdmi->workqueue); -+ pinctrl_pm_select_sleep_state(hdmi->dev); -+} -+EXPORT_SYMBOL_GPL(dw_hdmi_suspend); -+ - void dw_hdmi_resume(struct dw_hdmi *hdmi) - { - dw_hdmi_init_hw(hdmi); -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -index 111111111111..222222222222 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -@@ -851,6 +851,10 @@ enum { - HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00, - HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04, - -+/* HDMI_FC_GCP */ -+ HDMI_FC_GCP_SET_AVMUTE = 0x2, -+ HDMI_FC_GCP_CLEAR_AVMUTE = 0x1, -+ - /* FC_DBGFORCE field values */ - HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10, - HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1, -diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 111111111111..222222222222 100644 ---- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -4,21 +4,32 @@ - */ - - #include -+#include -+#include - #include - #include - #include - #include -+#include - #include - #include - -+#include -+#include -+#include -+#include - #include - #include - #include - #include - #include - -+#include -+ - #include "rockchip_drm_drv.h" - -+#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) -+ - #define RK3228_GRF_SOC_CON2 0x0408 - #define RK3228_HDMI_SDAIN_MSK BIT(14) - #define RK3228_HDMI_SCLIN_MSK BIT(13) -@@ -29,8 +40,11 @@ - - #define RK3288_GRF_SOC_CON6 0x025C - #define RK3288_HDMI_LCDC_SEL BIT(4) --#define RK3328_GRF_SOC_CON2 0x0408 -+#define RK3288_GRF_SOC_CON16 0x03a8 -+#define RK3288_HDMI_LCDC0_YUV420 BIT(2) -+#define RK3288_HDMI_LCDC1_YUV420 BIT(3) - -+#define RK3328_GRF_SOC_CON2 0x0408 - #define RK3328_HDMI_SDAIN_MSK BIT(11) - #define RK3328_HDMI_SCLIN_MSK BIT(10) - #define RK3328_HDMI_HPD_IOE BIT(2) -@@ -54,32 +68,177 @@ - #define RK3568_HDMI_SDAIN_MSK BIT(15) - #define RK3568_HDMI_SCLIN_MSK BIT(14) - --#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) -+#define RK3588_GRF_SOC_CON2 0x0308 -+#define RK3588_HDMI1_HPD_INT_MSK BIT(15) -+#define RK3588_HDMI1_HPD_INT_CLR BIT(14) -+#define RK3588_HDMI0_HPD_INT_MSK BIT(13) -+#define RK3588_HDMI0_HPD_INT_CLR BIT(12) -+#define RK3588_GRF_SOC_CON7 0x031c -+#define RK3588_SET_HPD_PATH_MASK (0x3 << 12) -+#define RK3588_GRF_SOC_STATUS1 0x0384 -+#define RK3588_HDMI0_LOW_MORETHAN100MS BIT(20) -+#define RK3588_HDMI0_HPD_PORT_LEVEL BIT(19) -+#define RK3588_HDMI0_IHPD_PORT BIT(18) -+#define RK3588_HDMI0_OHPD_INT BIT(17) -+#define RK3588_HDMI0_LEVEL_INT BIT(16) -+#define RK3588_HDMI0_INTR_CHANGE_CNT (0x7 << 13) -+#define RK3588_HDMI1_LOW_MORETHAN100MS BIT(28) -+#define RK3588_HDMI1_HPD_PORT_LEVEL BIT(27) -+#define RK3588_HDMI1_IHPD_PORT BIT(26) -+#define RK3588_HDMI1_OHPD_INT BIT(25) -+#define RK3588_HDMI1_LEVEL_INT BIT(24) -+#define RK3588_HDMI1_INTR_CHANGE_CNT (0x7 << 21) -+ -+#define RK3588_GRF_VO1_CON3 0x000c -+#define RK3588_COLOR_FORMAT_MASK 0xf -+#define RK3588_YUV444 0x2 -+#define RK3588_YUV420 0x3 -+#define RK3588_COMPRESSED_DATA 0xb -+#define RK3588_COLOR_DEPTH_MASK (0xf << 4) -+#define RK3588_8BPC (0x5 << 4) -+#define RK3588_10BPC (0x6 << 4) -+#define RK3588_CECIN_MASK BIT(8) -+#define RK3588_SCLIN_MASK BIT(9) -+#define RK3588_SDAIN_MASK BIT(10) -+#define RK3588_MODE_MASK BIT(11) -+#define RK3588_COMPRESS_MODE_MASK BIT(12) -+#define RK3588_I2S_SEL_MASK BIT(13) -+#define RK3588_SPDIF_SEL_MASK BIT(14) -+#define RK3588_GRF_VO1_CON4 0x0010 -+#define RK3588_HDMI21_MASK BIT(0) -+#define RK3588_GRF_VO1_CON9 0x0024 -+#define RK3588_HDMI0_GRANT_SEL BIT(10) -+#define RK3588_HDMI0_GRANT_SW BIT(11) -+#define RK3588_HDMI1_GRANT_SEL BIT(12) -+#define RK3588_HDMI1_GRANT_SW BIT(13) -+#define RK3588_GRF_VO1_CON6 0x0018 -+#define RK3588_GRF_VO1_CON7 0x001c -+ -+#define COLOR_DEPTH_10BIT BIT(31) -+#define HDMI_FRL_MODE BIT(30) -+#define HDMI_EARC_MODE BIT(29) -+ -+#define HDMI20_MAX_RATE 600000 -+#define HDMI_8K60_RATE 2376000 - - /** - * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips - * @lcdsel_grf_reg: grf register offset of lcdc select -+ * @ddc_en_reg: grf register offset of hdmi ddc enable - * @lcdsel_big: reg value of selecting vop big for HDMI - * @lcdsel_lit: reg value of selecting vop little for HDMI -+ * @split_mode: flag indicating split mode capability - */ - struct rockchip_hdmi_chip_data { - int lcdsel_grf_reg; -+ int ddc_en_reg; - u32 lcdsel_big; - u32 lcdsel_lit; -+ bool split_mode; -+}; -+ -+enum hdmi_frl_rate_per_lane { -+ FRL_12G_PER_LANE = 12, -+ FRL_10G_PER_LANE = 10, -+ FRL_8G_PER_LANE = 8, -+ FRL_6G_PER_LANE = 6, -+ FRL_3G_PER_LANE = 3, -+}; -+ -+enum rk_if_color_depth { -+ RK_IF_DEPTH_8, -+ RK_IF_DEPTH_10, -+ RK_IF_DEPTH_12, -+ RK_IF_DEPTH_16, -+ RK_IF_DEPTH_420_10, -+ RK_IF_DEPTH_420_12, -+ RK_IF_DEPTH_420_16, -+ RK_IF_DEPTH_6, -+ RK_IF_DEPTH_MAX, -+}; -+ -+enum rk_if_color_format { -+ RK_IF_FORMAT_RGB, /* default RGB */ -+ RK_IF_FORMAT_YCBCR444, /* YCBCR 444 */ -+ RK_IF_FORMAT_YCBCR422, /* YCBCR 422 */ -+ RK_IF_FORMAT_YCBCR420, /* YCBCR 420 */ -+ RK_IF_FORMAT_YCBCR_HQ, /* Highest subsampled YUV */ -+ RK_IF_FORMAT_YCBCR_LQ, /* Lowest subsampled YUV */ -+ RK_IF_FORMAT_MAX, - }; - - struct rockchip_hdmi { - struct device *dev; - struct regmap *regmap; -+ struct regmap *vo1_regmap; - struct rockchip_encoder encoder; -+ struct drm_device *drm_dev; - const struct rockchip_hdmi_chip_data *chip_data; -- const struct dw_hdmi_plat_data *plat_data; -+ struct dw_hdmi_plat_data *plat_data; -+ struct clk *aud_clk; - struct clk *ref_clk; - struct clk *grf_clk; -+ struct clk *hclk_vio; -+ struct clk *hclk_vo1; -+ struct clk *hclk_vop; -+ struct clk *hpd_clk; -+ struct clk *pclk; -+ struct clk *earc_clk; -+ struct clk *hdmitx_ref; - struct dw_hdmi *hdmi; -+ struct dw_hdmi_qp *hdmi_qp; -+ - struct regulator *avdd_0v9; - struct regulator *avdd_1v8; - struct phy *phy; -+ -+ u32 max_tmdsclk; -+ bool unsupported_yuv_input; -+ bool unsupported_deep_color; -+ bool skip_check_420_mode; -+ u8 force_output; -+ u8 id; -+ bool hpd_stat; -+ bool is_hdmi_qp; -+ bool user_split_mode; -+ -+ unsigned long bus_format; -+ unsigned long output_bus_format; -+ unsigned long enc_out_encoding; -+ int color_changed; -+ int hpd_irq; -+ int vp_id; -+ -+ struct drm_property *color_depth_property; -+ struct drm_property *hdmi_output_property; -+ struct drm_property *colordepth_capacity; -+ struct drm_property *outputmode_capacity; -+ struct drm_property *quant_range; -+ struct drm_property *hdr_panel_metadata_property; -+ struct drm_property *next_hdr_sink_data_property; -+ struct drm_property *output_hdmi_dvi; -+ struct drm_property *output_type_capacity; -+ struct drm_property *user_split_mode_prop; -+ -+ struct drm_property_blob *hdr_panel_blob_ptr; -+ struct drm_property_blob *next_hdr_data_ptr; -+ -+ unsigned int colordepth; -+ unsigned int colorimetry; -+ unsigned int hdmi_quant_range; -+ unsigned int phy_bus_width; -+ enum rk_if_color_format hdmi_output; -+ // struct rockchip_drm_sub_dev sub_dev; -+ -+ u8 max_frl_rate_per_lane; -+ u8 max_lanes; -+ // struct rockchip_drm_dsc_cap dsc_cap; -+ // struct next_hdr_sink_data next_hdr_data; -+ struct dw_hdmi_link_config link_cfg; -+ struct gpio_desc *enable_gpio; -+ -+ struct delayed_work work; -+ struct workqueue_struct *workqueue; - }; - - static struct rockchip_hdmi *to_rockchip_hdmi(struct drm_encoder *encoder) -@@ -202,13 +361,830 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { - /*pixelclk symbol term vlev*/ - { 74250000, 0x8009, 0x0004, 0x0272}, - { 148500000, 0x802b, 0x0004, 0x028d}, -+ { 165000000, 0x802b, 0x0004, 0x0209}, - { 297000000, 0x8039, 0x0005, 0x028d}, -+ { 594000000, 0x8039, 0x0000, 0x019d}, - { ~0UL, 0x0000, 0x0000, 0x0000} - }; - -+enum ROW_INDEX_BPP { -+ ROW_INDEX_6BPP = 0, -+ ROW_INDEX_8BPP, -+ ROW_INDEX_10BPP, -+ ROW_INDEX_12BPP, -+ ROW_INDEX_23BPP, -+ MAX_ROW_INDEX -+}; -+ -+enum COLUMN_INDEX_BPC { -+ COLUMN_INDEX_8BPC = 0, -+ COLUMN_INDEX_10BPC, -+ COLUMN_INDEX_12BPC, -+ COLUMN_INDEX_14BPC, -+ COLUMN_INDEX_16BPC, -+ MAX_COLUMN_INDEX -+}; -+ -+#define PPS_TABLE_LEN 8 -+#define PPS_BPP_LEN 4 -+#define PPS_BPC_LEN 2 -+ -+struct pps_data { -+ u32 pic_width; -+ u32 pic_height; -+ u32 slice_width; -+ u32 slice_height; -+ bool convert_rgb; -+ u8 bpc; -+ u8 bpp; -+ u8 raw_pps[128]; -+}; -+ -+#if 0 -+/* -+ * Selected Rate Control Related Parameter Recommended Values -+ * from DSC_v1.11 spec & C Model release: DSC_model_20161212 -+ */ -+static struct pps_data pps_datas[PPS_TABLE_LEN] = { -+ { -+ /* 7680x4320/960X96 rgb 8bpc 12bpp */ -+ 7680, 4320, 960, 96, 1, 8, 192, -+ { -+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xc0, 0x10, 0xe0, -+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0, -+ 0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9, -+ 0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa, -+ 0x08, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00, -+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, -+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, -+ 0x7d, 0x7e, 0x00, 0x82, 0x00, 0xc0, 0x09, 0x00, -+ 0x09, 0x7e, 0x19, 0xbc, 0x19, 0xba, 0x19, 0xf8, -+ 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76, -+ 0x2a, 0x76, 0x2a, 0x74, 0x3a, 0xb4, 0x52, 0xf4, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -+ }, -+ }, -+ { -+ /* 7680x4320/960X96 rgb 8bpc 11bpp */ -+ 7680, 4320, 960, 96, 1, 8, 176, -+ { -+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xb0, 0x10, 0xe0, -+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28, -+ 0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0, -+ 0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33, -+ 0x0f, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00, -+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, -+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, -+ 0x7d, 0x7e, 0x00, 0x82, 0x01, 0x00, 0x09, 0x40, -+ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8, -+ 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76, -+ 0x2a, 0x76, 0x2a, 0xb4, 0x3a, 0xb4, 0x52, 0xf4, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -+ }, -+ }, -+ { -+ /* 7680x4320/960X96 rgb 8bpc 10bpp */ -+ 7680, 4320, 960, 96, 1, 8, 160, -+ { -+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xa0, 0x10, 0xe0, -+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0, -+ 0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0, -+ 0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb, -+ 0x16, 0x00, 0x10, 0xec, 0x03, 0x0c, 0x20, 0x00, -+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, -+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, -+ 0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40, -+ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8, -+ 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6, -+ 0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x5b, 0x34, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -+ }, -+ }, -+ { -+ /* 7680x4320/960X96 rgb 8bpc 9bpp */ -+ 7680, 4320, 960, 96, 1, 8, 144, -+ { -+ 0x12, 0x00, 0x00, 0x8d, 0x30, 0x90, 0x10, 0xe0, -+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38, -+ 0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7, -+ 0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa, -+ 0x17, 0x00, 0x10, 0xf1, 0x03, 0x0c, 0x20, 0x00, -+ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, -+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, -+ 0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40, -+ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8, -+ 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6, -+ 0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x63, 0x74, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -+ }, -+ }, -+ { -+ /* 7680x4320/960X96 rgb 10bpc 12bpp */ -+ 7680, 4320, 960, 96, 1, 10, 192, -+ { -+ 0x12, 0x00, 0x00, 0xad, 0x30, 0xc0, 0x10, 0xe0, -+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0, -+ 0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9, -+ 0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa, -+ 0x08, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00, -+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38, -+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, -+ 0x7d, 0x7e, 0x01, 0x02, 0x11, 0x80, 0x22, 0x00, -+ 0x22, 0x7e, 0x32, 0xbc, 0x32, 0xba, 0x3a, 0xf8, -+ 0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76, -+ 0x4b, 0x76, 0x4b, 0x74, 0x5b, 0xb4, 0x73, 0xf4, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -+ }, -+ }, -+ { -+ /* 7680x4320/960X96 rgb 10bpc 11bpp */ -+ 7680, 4320, 960, 96, 1, 10, 176, -+ { -+ 0x12, 0x00, 0x00, 0xad, 0x30, 0xb0, 0x10, 0xe0, -+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28, -+ 0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0, -+ 0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33, -+ 0x0f, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00, -+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38, -+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, -+ 0x7d, 0x7e, 0x01, 0x42, 0x19, 0xc0, 0x2a, 0x40, -+ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8, -+ 0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76, -+ 0x4b, 0x76, 0x4b, 0xb4, 0x5b, 0xb4, 0x73, 0xf4, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -+ }, -+ }, -+ { -+ /* 7680x4320/960X96 rgb 10bpc 10bpp */ -+ 7680, 4320, 960, 96, 1, 10, 160, -+ { -+ 0x12, 0x00, 0x00, 0xad, 0x30, 0xa0, 0x10, 0xe0, -+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0, -+ 0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0, -+ 0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb, -+ 0x16, 0x00, 0x10, 0xec, 0x07, 0x10, 0x20, 0x00, -+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38, -+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, -+ 0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40, -+ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8, -+ 0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6, -+ 0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x7c, 0x34, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -+ }, -+ }, -+ { -+ /* 7680x4320/960X96 rgb 10bpc 9bpp */ -+ 7680, 4320, 960, 96, 1, 10, 144, -+ { -+ 0x12, 0x00, 0x00, 0xad, 0x30, 0x90, 0x10, 0xe0, -+ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38, -+ 0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7, -+ 0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa, -+ 0x17, 0x00, 0x10, 0xf1, 0x07, 0x10, 0x20, 0x00, -+ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38, -+ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, -+ 0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40, -+ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8, -+ 0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6, -+ 0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x84, 0x74, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -+ }, -+ }, -+}; -+ -+static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ case MEDIA_BUS_FMT_RGB121212_1X36: -+ case MEDIA_BUS_FMT_RGB161616_1X48: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_YUV12_1X36: -+ case MEDIA_BUS_FMT_YUV16_1X48: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+#endif -+ -+static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ case MEDIA_BUS_FMT_UYVY10_1X20: -+ case MEDIA_BUS_FMT_UYVY12_1X24: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36: -+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+static int hdmi_bus_fmt_color_depth(unsigned int bus_format) -+{ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ return 8; -+ -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ case MEDIA_BUS_FMT_UYVY10_1X20: -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ return 10; -+ -+ case MEDIA_BUS_FMT_RGB121212_1X36: -+ case MEDIA_BUS_FMT_YUV12_1X36: -+ case MEDIA_BUS_FMT_UYVY12_1X24: -+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36: -+ return 12; -+ -+ case MEDIA_BUS_FMT_RGB161616_1X48: -+ case MEDIA_BUS_FMT_YUV16_1X48: -+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48: -+ return 16; -+ -+ default: -+ return 0; -+ } -+} -+ -+static unsigned int -+hdmi_get_tmdsclock(struct rockchip_hdmi *hdmi, unsigned long pixelclock) -+{ -+ unsigned int tmdsclock = pixelclock; -+ unsigned int depth = -+ hdmi_bus_fmt_color_depth(hdmi->output_bus_format); -+ -+ if (!hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format)) { -+ switch (depth) { -+ case 16: -+ tmdsclock = pixelclock * 2; -+ break; -+ case 12: -+ tmdsclock = pixelclock * 3 / 2; -+ break; -+ case 10: -+ tmdsclock = pixelclock * 5 / 4; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ return tmdsclock; -+} -+ -+static int rockchip_hdmi_match_by_id(struct device *dev, const void *data) -+{ -+ struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); -+ const unsigned int *id = data; -+ -+ return hdmi->id == *id; -+} -+ -+static struct rockchip_hdmi * -+rockchip_hdmi_find_by_id(struct device_driver *drv, unsigned int id) -+{ -+ struct device *dev; -+ -+ dev = driver_find_device(drv, NULL, &id, rockchip_hdmi_match_by_id); -+ if (!dev) -+ return NULL; -+ -+ return dev_get_drvdata(dev); -+} -+ -+static void hdmi_select_link_config(struct rockchip_hdmi *hdmi, -+ struct drm_crtc_state *crtc_state, -+ unsigned int tmdsclk) -+{ -+ struct drm_display_mode mode; -+ int max_lanes, max_rate_per_lane; -+ // int max_dsc_lanes, max_dsc_rate_per_lane; -+ unsigned long max_frl_rate; -+ -+ drm_mode_copy(&mode, &crtc_state->mode); -+ -+ max_lanes = hdmi->max_lanes; -+ max_rate_per_lane = hdmi->max_frl_rate_per_lane; -+ max_frl_rate = max_lanes * max_rate_per_lane * 1000000; -+ -+ hdmi->link_cfg.dsc_mode = false; -+ hdmi->link_cfg.frl_lanes = max_lanes; -+ hdmi->link_cfg.rate_per_lane = max_rate_per_lane; -+ -+ if (!max_frl_rate || (tmdsclk < HDMI20_MAX_RATE && mode.clock < HDMI20_MAX_RATE)) { -+ hdmi->link_cfg.frl_mode = false; -+ return; -+ } -+ -+ hdmi->link_cfg.frl_mode = true; -+ dev_warn(hdmi->dev, "use unsupported frl hdmi mode\n"); -+ -+ // if (!hdmi->dsc_cap.v_1p2) -+ // return; -+ // -+ // max_dsc_lanes = hdmi->dsc_cap.max_lanes; -+ // max_dsc_rate_per_lane = -+ // hdmi->dsc_cap.max_frl_rate_per_lane; -+ // -+ // if (mode.clock >= HDMI_8K60_RATE && -+ // !hdmi_bus_fmt_is_yuv420(hdmi->bus_format) && -+ // !hdmi_bus_fmt_is_yuv422(hdmi->bus_format)) { -+ // hdmi->link_cfg.dsc_mode = true; -+ // hdmi->link_cfg.frl_lanes = max_dsc_lanes; -+ // hdmi->link_cfg.rate_per_lane = max_dsc_rate_per_lane; -+ // } else { -+ // hdmi->link_cfg.dsc_mode = false; -+ // hdmi->link_cfg.frl_lanes = max_lanes; -+ // hdmi->link_cfg.rate_per_lane = max_rate_per_lane; -+ // } -+} -+ -+///////////////////////////////////////////////////////////////////////////////////// -+/* CC: disable DSC */ -+#if 0 -+static int hdmi_dsc_get_slice_height(int vactive) -+{ -+ int slice_height; -+ -+ /* -+ * Slice Height determination : HDMI2.1 Section 7.7.5.2 -+ * Select smallest slice height >=96, that results in a valid PPS and -+ * requires minimum padding lines required for final slice. -+ * -+ * Assumption : Vactive is even. -+ */ -+ for (slice_height = 96; slice_height <= vactive; slice_height += 2) -+ if (vactive % slice_height == 0) -+ return slice_height; -+ -+ return 0; -+} -+ -+static int hdmi_dsc_get_num_slices(struct rockchip_hdmi *hdmi, -+ struct drm_crtc_state *crtc_state, -+ int src_max_slices, int src_max_slice_width, -+ int hdmi_max_slices, int hdmi_throughput) -+{ -+/* Pixel rates in KPixels/sec */ -+#define HDMI_DSC_PEAK_PIXEL_RATE 2720000 -+/* -+ * Rates at which the source and sink are required to process pixels in each -+ * slice, can be two levels: either at least 340000KHz or at least 40000KHz. -+ */ -+#define HDMI_DSC_MAX_ENC_THROUGHPUT_0 340000 -+#define HDMI_DSC_MAX_ENC_THROUGHPUT_1 400000 -+ -+/* Spec limits the slice width to 2720 pixels */ -+#define MAX_HDMI_SLICE_WIDTH 2720 -+ int kslice_adjust; -+ int adjusted_clk_khz; -+ int min_slices; -+ int target_slices; -+ int max_throughput; /* max clock freq. in khz per slice */ -+ int max_slice_width; -+ int slice_width; -+ int pixel_clock = crtc_state->mode.clock; -+ -+ if (!hdmi_throughput) -+ return 0; -+ -+ /* -+ * Slice Width determination : HDMI2.1 Section 7.7.5.1 -+ * kslice_adjust factor for 4:2:0, and 4:2:2 formats is 0.5, where as -+ * for 4:4:4 is 1.0. Multiplying these factors by 10 and later -+ * dividing adjusted clock value by 10. -+ */ -+ if (hdmi_bus_fmt_is_yuv444(hdmi->output_bus_format) || -+ hdmi_bus_fmt_is_rgb(hdmi->output_bus_format)) -+ kslice_adjust = 10; -+ else -+ kslice_adjust = 5; -+ -+ /* -+ * As per spec, the rate at which the source and the sink process -+ * the pixels per slice are at two levels: at least 340Mhz or 400Mhz. -+ * This depends upon the pixel clock rate and output formats -+ * (kslice adjust). -+ * If pixel clock * kslice adjust >= 2720MHz slices can be processed -+ * at max 340MHz, otherwise they can be processed at max 400MHz. -+ */ -+ -+ adjusted_clk_khz = DIV_ROUND_UP(kslice_adjust * pixel_clock, 10); -+ -+ if (adjusted_clk_khz <= HDMI_DSC_PEAK_PIXEL_RATE) -+ max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_0; -+ else -+ max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_1; -+ -+ /* -+ * Taking into account the sink's capability for maximum -+ * clock per slice (in MHz) as read from HF-VSDB. -+ */ -+ max_throughput = min(max_throughput, hdmi_throughput * 1000); -+ -+ min_slices = DIV_ROUND_UP(adjusted_clk_khz, max_throughput); -+ max_slice_width = min(MAX_HDMI_SLICE_WIDTH, src_max_slice_width); -+ -+ /* -+ * Keep on increasing the num of slices/line, starting from min_slices -+ * per line till we get such a number, for which the slice_width is -+ * just less than max_slice_width. The slices/line selected should be -+ * less than or equal to the max horizontal slices that the combination -+ * of PCON encoder and HDMI decoder can support. -+ */ -+ do { -+ if (min_slices <= 1 && src_max_slices >= 1 && hdmi_max_slices >= 1) -+ target_slices = 1; -+ else if (min_slices <= 2 && src_max_slices >= 2 && hdmi_max_slices >= 2) -+ target_slices = 2; -+ else if (min_slices <= 4 && src_max_slices >= 4 && hdmi_max_slices >= 4) -+ target_slices = 4; -+ else if (min_slices <= 8 && src_max_slices >= 8 && hdmi_max_slices >= 8) -+ target_slices = 8; -+ else if (min_slices <= 12 && src_max_slices >= 12 && hdmi_max_slices >= 12) -+ target_slices = 12; -+ else if (min_slices <= 16 && src_max_slices >= 16 && hdmi_max_slices >= 16) -+ target_slices = 16; -+ else -+ return 0; -+ -+ slice_width = DIV_ROUND_UP(crtc_state->mode.hdisplay, target_slices); -+ if (slice_width > max_slice_width) -+ min_slices = target_slices + 1; -+ } while (slice_width > max_slice_width); -+ -+ return target_slices; -+} -+ -+static int hdmi_dsc_slices(struct rockchip_hdmi *hdmi, -+ struct drm_crtc_state *crtc_state) -+{ -+ int hdmi_throughput = hdmi->dsc_cap.clk_per_slice; -+ int hdmi_max_slices = hdmi->dsc_cap.max_slices; -+ int rk_max_slices = 8; -+ int rk_max_slice_width = 2048; -+ -+ return hdmi_dsc_get_num_slices(hdmi, crtc_state, rk_max_slices, -+ rk_max_slice_width, -+ hdmi_max_slices, hdmi_throughput); -+} -+ -+static int -+hdmi_dsc_get_bpp(struct rockchip_hdmi *hdmi, int src_fractional_bpp, -+ int slice_width, int num_slices, bool hdmi_all_bpp, -+ int hdmi_max_chunk_bytes) -+{ -+ int max_dsc_bpp, min_dsc_bpp; -+ int target_bytes; -+ bool bpp_found = false; -+ int bpp_decrement_x16; -+ int bpp_target; -+ int bpp_target_x16; -+ -+ /* -+ * Get min bpp and max bpp as per Table 7.23, in HDMI2.1 spec -+ * Start with the max bpp and keep on decrementing with -+ * fractional bpp, if supported by PCON DSC encoder -+ * -+ * for each bpp we check if no of bytes can be supported by HDMI sink -+ */ -+ -+ /* only 9\10\12 bpp was tested */ -+ min_dsc_bpp = 9; -+ max_dsc_bpp = 12; -+ -+ /* -+ * Taking into account if all dsc_all_bpp supported by HDMI2.1 sink -+ * Section 7.7.34 : Source shall not enable compressed Video -+ * Transport with bpp_target settings above 12 bpp unless -+ * DSC_all_bpp is set to 1. -+ */ -+ if (!hdmi_all_bpp) -+ max_dsc_bpp = min(max_dsc_bpp, 12); -+ -+ /* -+ * The Sink has a limit of compressed data in bytes for a scanline, -+ * as described in max_chunk_bytes field in HFVSDB block of edid. -+ * The no. of bytes depend on the target bits per pixel that the -+ * source configures. So we start with the max_bpp and calculate -+ * the target_chunk_bytes. We keep on decrementing the target_bpp, -+ * till we get the target_chunk_bytes just less than what the sink's -+ * max_chunk_bytes, or else till we reach the min_dsc_bpp. -+ * -+ * The decrement is according to the fractional support from PCON DSC -+ * encoder. For fractional BPP we use bpp_target as a multiple of 16. -+ * -+ * bpp_target_x16 = bpp_target * 16 -+ * So we need to decrement by {1, 2, 4, 8, 16} for fractional bpps -+ * {1/16, 1/8, 1/4, 1/2, 1} respectively. -+ */ -+ -+ bpp_target = max_dsc_bpp; -+ -+ /* src does not support fractional bpp implies decrement by 16 for bppx16 */ -+ if (!src_fractional_bpp) -+ src_fractional_bpp = 1; -+ bpp_decrement_x16 = DIV_ROUND_UP(16, src_fractional_bpp); -+ bpp_target_x16 = bpp_target * 16; -+ -+ while (bpp_target_x16 > (min_dsc_bpp * 16)) { -+ int bpp; -+ -+ bpp = DIV_ROUND_UP(bpp_target_x16, 16); -+ target_bytes = DIV_ROUND_UP((num_slices * slice_width * bpp), 8); -+ if (target_bytes <= hdmi_max_chunk_bytes) { -+ bpp_found = true; -+ break; -+ } -+ bpp_target_x16 -= bpp_decrement_x16; -+ } -+ if (bpp_found) -+ return bpp_target_x16; -+ -+ return 0; -+} -+ -+static int -+dw_hdmi_dsc_bpp(struct rockchip_hdmi *hdmi, -+ int num_slices, int slice_width) -+{ -+ bool hdmi_all_bpp = hdmi->dsc_cap.all_bpp; -+ int fractional_bpp = 0; -+ int hdmi_max_chunk_bytes = hdmi->dsc_cap.total_chunk_kbytes * 1024; -+ -+ return hdmi_dsc_get_bpp(hdmi, fractional_bpp, slice_width, -+ num_slices, hdmi_all_bpp, -+ hdmi_max_chunk_bytes); -+} -+ -+static int dw_hdmi_qp_set_link_cfg(struct rockchip_hdmi *hdmi, -+ u16 pic_width, u16 pic_height, -+ u16 slice_width, u16 slice_height, -+ u16 bits_per_pixel, u8 bits_per_component) -+{ -+ int i; -+ -+ for (i = 0; i < PPS_TABLE_LEN; i++) -+ if (pic_width == pps_datas[i].pic_width && -+ pic_height == pps_datas[i].pic_height && -+ slice_width == pps_datas[i].slice_width && -+ slice_height == pps_datas[i].slice_height && -+ bits_per_component == pps_datas[i].bpc && -+ bits_per_pixel == pps_datas[i].bpp && -+ hdmi_bus_fmt_is_rgb(hdmi->output_bus_format) == pps_datas[i].convert_rgb) -+ break; -+ -+ if (i == PPS_TABLE_LEN) { -+ dev_err(hdmi->dev, "can't find pps cfg!\n"); -+ return -EINVAL; -+ } -+ -+ memcpy(hdmi->link_cfg.pps_payload, pps_datas[i].raw_pps, 128); -+ hdmi->link_cfg.hcactive = DIV_ROUND_UP(slice_width * (bits_per_pixel / 16), 8) * -+ (pic_width / slice_width); -+ -+ return 0; -+} -+ -+static void dw_hdmi_qp_dsc_configure(struct rockchip_hdmi *hdmi, -+ struct rockchip_crtc_state *s, -+ struct drm_crtc_state *crtc_state) -+{ -+ int ret; -+ int slice_height; -+ int slice_width; -+ int bits_per_pixel; -+ int slice_count; -+ bool hdmi_is_dsc_1_2; -+ unsigned int depth = hdmi_bus_fmt_color_depth(hdmi->output_bus_format); -+ -+ if (!crtc_state) -+ return; -+ -+ hdmi_is_dsc_1_2 = hdmi->dsc_cap.v_1p2; -+ -+ if (!hdmi_is_dsc_1_2) -+ return; -+ -+ slice_height = hdmi_dsc_get_slice_height(crtc_state->mode.vdisplay); -+ if (!slice_height) -+ return; -+ -+ slice_count = hdmi_dsc_slices(hdmi, crtc_state); -+ if (!slice_count) -+ return; -+ -+ slice_width = DIV_ROUND_UP(crtc_state->mode.hdisplay, slice_count); -+ -+ bits_per_pixel = dw_hdmi_dsc_bpp(hdmi, slice_count, slice_width); -+ if (!bits_per_pixel) -+ return; -+ -+ ret = dw_hdmi_qp_set_link_cfg(hdmi, crtc_state->mode.hdisplay, -+ crtc_state->mode.vdisplay, slice_width, -+ slice_height, bits_per_pixel, depth); -+ -+ if (ret) { -+ dev_err(hdmi->dev, "set vdsc cfg failed\n"); -+ return; -+ } -+ dev_info(hdmi->dev, "dsc_enable\n"); -+ s->dsc_enable = 1; -+ s->dsc_sink_cap.version_major = 1; -+ s->dsc_sink_cap.version_minor = 2; -+ s->dsc_sink_cap.slice_width = slice_width; -+ s->dsc_sink_cap.slice_height = slice_height; -+ s->dsc_sink_cap.target_bits_per_pixel_x16 = bits_per_pixel; -+ s->dsc_sink_cap.block_pred = 1; -+ s->dsc_sink_cap.native_420 = 0; -+ -+ memcpy(&s->pps, hdmi->link_cfg.pps_payload, 128); -+} -+#endif -+///////////////////////////////////////////////////////////////////////////////////////// -+ -+// static int rockchip_hdmi_update_phy_table(struct rockchip_hdmi *hdmi, -+// u32 *config, -+// int phy_table_size) -+// { -+// int i; -+// -+// if (phy_table_size > ARRAY_SIZE(rockchip_phy_config)) { -+// dev_err(hdmi->dev, "phy table array number is out of range\n"); -+// return -E2BIG; -+// } -+// -+// for (i = 0; i < phy_table_size; i++) { -+// if (config[i * 4] != 0) -+// rockchip_phy_config[i].mpixelclock = (u64)config[i * 4]; -+// else -+// rockchip_phy_config[i].mpixelclock = ~0UL; -+// rockchip_phy_config[i].sym_ctr = (u16)config[i * 4 + 1]; -+// rockchip_phy_config[i].term = (u16)config[i * 4 + 2]; -+// rockchip_phy_config[i].vlev_ctr = (u16)config[i * 4 + 3]; -+// } -+// -+// return 0; -+// } -+ -+static void repo_hpd_event(struct work_struct *p_work) -+{ -+ struct rockchip_hdmi *hdmi = container_of(p_work, struct rockchip_hdmi, work.work); -+ bool change; -+ -+ change = drm_helper_hpd_irq_event(hdmi->drm_dev); -+ if (change) { -+ dev_dbg(hdmi->dev, "hpd stat changed:%d\n", hdmi->hpd_stat); -+ // dw_hdmi_qp_cec_set_hpd(hdmi->hdmi_qp, hdmi->hpd_stat, change); -+ } -+} -+ -+static irqreturn_t rockchip_hdmi_hardirq(int irq, void *dev_id) -+{ -+ struct rockchip_hdmi *hdmi = dev_id; -+ u32 intr_stat, val; -+ -+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat); -+ -+ if (intr_stat) { -+ dev_dbg(hdmi->dev, "hpd irq %#x\n", intr_stat); -+ -+ if (!hdmi->id) -+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, -+ RK3588_HDMI0_HPD_INT_MSK); -+ else -+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, -+ RK3588_HDMI1_HPD_INT_MSK); -+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); -+ return IRQ_WAKE_THREAD; -+ } -+ -+ return IRQ_NONE; -+} -+ -+static irqreturn_t rockchip_hdmi_irq(int irq, void *dev_id) -+{ -+ struct rockchip_hdmi *hdmi = dev_id; -+ u32 intr_stat, val; -+ int msecs; -+ bool stat; -+ -+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat); -+ -+ if (!intr_stat) -+ return IRQ_NONE; -+ -+ if (!hdmi->id) { -+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, -+ RK3588_HDMI0_HPD_INT_CLR); -+ if (intr_stat & RK3588_HDMI0_LEVEL_INT) -+ stat = true; -+ else -+ stat = false; -+ } else { -+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR, -+ RK3588_HDMI1_HPD_INT_CLR); -+ if (intr_stat & RK3588_HDMI1_LEVEL_INT) -+ stat = true; -+ else -+ stat = false; -+ } -+ -+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); -+ -+ if (stat) { -+ hdmi->hpd_stat = true; -+ msecs = 150; -+ } else { -+ hdmi->hpd_stat = false; -+ msecs = 20; -+ } -+ mod_delayed_work(hdmi->workqueue, &hdmi->work, msecs_to_jiffies(msecs)); -+ -+ if (!hdmi->id) { -+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, -+ RK3588_HDMI0_HPD_INT_CLR) | -+ HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK); -+ } else { -+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR, -+ RK3588_HDMI1_HPD_INT_CLR) | -+ HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK); -+ } -+ -+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); -+ -+ return IRQ_HANDLED; -+} -+ - static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) - { - struct device_node *np = hdmi->dev->of_node; -+ int ret; - - hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); - if (IS_ERR(hdmi->regmap)) { -@@ -216,6 +1192,14 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) - return PTR_ERR(hdmi->regmap); - } - -+ if (hdmi->is_hdmi_qp) { -+ hdmi->vo1_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,vo1_grf"); -+ if (IS_ERR(hdmi->vo1_regmap)) { -+ DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,vo1_grf\n"); -+ return PTR_ERR(hdmi->vo1_regmap); -+ } -+ } -+ - hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "ref"); - if (!hdmi->ref_clk) - hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "vpll"); -@@ -245,6 +1229,79 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) - if (IS_ERR(hdmi->avdd_1v8)) - return PTR_ERR(hdmi->avdd_1v8); - -+ hdmi->hclk_vio = devm_clk_get(hdmi->dev, "hclk_vio"); -+ if (PTR_ERR(hdmi->hclk_vio) == -ENOENT) { -+ hdmi->hclk_vio = NULL; -+ } else if (PTR_ERR(hdmi->hclk_vio) == -EPROBE_DEFER) { -+ return -EPROBE_DEFER; -+ } else if (IS_ERR(hdmi->hclk_vio)) { -+ dev_err(hdmi->dev, "failed to get hclk_vio clock\n"); -+ return PTR_ERR(hdmi->hclk_vio); -+ } -+ -+ hdmi->hclk_vop = devm_clk_get(hdmi->dev, "hclk"); -+ if (PTR_ERR(hdmi->hclk_vop) == -ENOENT) { -+ hdmi->hclk_vop = NULL; -+ } else if (PTR_ERR(hdmi->hclk_vop) == -EPROBE_DEFER) { -+ return -EPROBE_DEFER; -+ } else if (IS_ERR(hdmi->hclk_vop)) { -+ dev_err(hdmi->dev, "failed to get hclk_vop clock\n"); -+ return PTR_ERR(hdmi->hclk_vop); -+ } -+ -+ hdmi->aud_clk = devm_clk_get_optional(hdmi->dev, "aud"); -+ if (IS_ERR(hdmi->aud_clk)) { -+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->aud_clk), -+ "failed to get aud_clk clock\n"); -+ return PTR_ERR(hdmi->aud_clk); -+ } -+ -+ hdmi->hpd_clk = devm_clk_get_optional(hdmi->dev, "hpd"); -+ if (IS_ERR(hdmi->hpd_clk)) { -+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hpd_clk), -+ "failed to get hpd_clk clock\n"); -+ return PTR_ERR(hdmi->hpd_clk); -+ } -+ -+ hdmi->hclk_vo1 = devm_clk_get_optional(hdmi->dev, "hclk_vo1"); -+ if (IS_ERR(hdmi->hclk_vo1)) { -+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hclk_vo1), -+ "failed to get hclk_vo1 clock\n"); -+ return PTR_ERR(hdmi->hclk_vo1); -+ } -+ -+ hdmi->earc_clk = devm_clk_get_optional(hdmi->dev, "earc"); -+ if (IS_ERR(hdmi->earc_clk)) { -+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->earc_clk), -+ "failed to get earc_clk clock\n"); -+ return PTR_ERR(hdmi->earc_clk); -+ } -+ -+ hdmi->hdmitx_ref = devm_clk_get_optional(hdmi->dev, "hdmitx_ref"); -+ if (IS_ERR(hdmi->hdmitx_ref)) { -+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hdmitx_ref), -+ "failed to get hdmitx_ref clock\n"); -+ return PTR_ERR(hdmi->hdmitx_ref); -+ } -+ -+ hdmi->pclk = devm_clk_get_optional(hdmi->dev, "pclk"); -+ if (IS_ERR(hdmi->pclk)) { -+ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->pclk), -+ "failed to get pclk clock\n"); -+ return PTR_ERR(hdmi->pclk); -+ } -+ -+ hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable", -+ GPIOD_OUT_HIGH); -+ if (IS_ERR(hdmi->enable_gpio)) { -+ ret = PTR_ERR(hdmi->enable_gpio); -+ dev_err(hdmi->dev, "failed to request enable GPIO: %d\n", ret); -+ return ret; -+ } -+ -+ hdmi->skip_check_420_mode = -+ of_property_read_bool(np, "skip-check-420-mode"); -+ - return 0; - } - -@@ -283,9 +1340,114 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data, - - return MODE_BAD; - } -+/* [CC:] enable downstream mode_valid() */ -+// static enum drm_mode_status -+// dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, void *data, -+// const struct drm_display_info *info, -+// const struct drm_display_mode *mode) -+// { -+// struct drm_encoder *encoder = connector->encoder; -+// enum drm_mode_status status = MODE_OK; -+// struct drm_device *dev = connector->dev; -+// struct rockchip_drm_private *priv = dev->dev_private; -+// struct drm_crtc *crtc; -+// struct rockchip_hdmi *hdmi; -+// -+// /* -+// * Pixel clocks we support are always < 2GHz and so fit in an -+// * int. We should make sure source rate does too so we don't get -+// * overflow when we multiply by 1000. -+// */ -+// if (mode->clock > INT_MAX / 1000) -+// return MODE_BAD; -+// -+// if (!encoder) { -+// const struct drm_connector_helper_funcs *funcs; -+// -+// funcs = connector->helper_private; -+// if (funcs->atomic_best_encoder) -+// encoder = funcs->atomic_best_encoder(connector, -+// connector->state); -+// else -+// encoder = funcs->best_encoder(connector); -+// } -+// -+// if (!encoder || !encoder->possible_crtcs) -+// return MODE_BAD; -+// -+// hdmi = to_rockchip_hdmi(encoder); -+// -+// /* -+// * If sink max TMDS clock < 340MHz, we should check the mode pixel -+// * clock > 340MHz is YCbCr420 or not and whether the platform supports -+// * YCbCr420. -+// */ -+// if (!hdmi->skip_check_420_mode) { -+// if (mode->clock > 340000 && -+// connector->display_info.max_tmds_clock < 340000 && -+// (!drm_mode_is_420(&connector->display_info, mode) || -+// !connector->ycbcr_420_allowed)) -+// return MODE_BAD; -+// -+// if (hdmi->max_tmdsclk <= 340000 && mode->clock > 340000 && -+// !drm_mode_is_420(&connector->display_info, mode)) -+// return MODE_BAD; -+// }; -+// -+// if (hdmi->phy) { -+// if (hdmi->is_hdmi_qp) -+// phy_set_bus_width(hdmi->phy, mode->clock * 10); -+// else -+// phy_set_bus_width(hdmi->phy, 8); -+// } -+// -+// /* -+// * ensure all drm display mode can work, if someone want support more -+// * resolutions, please limit the possible_crtc, only connect to -+// * needed crtc. -+// */ -+// drm_for_each_crtc(crtc, connector->dev) { -+// int pipe = drm_crtc_index(crtc); -+// const struct rockchip_crtc_funcs *funcs = -+// priv->crtc_funcs[pipe]; -+// -+// if (!(encoder->possible_crtcs & drm_crtc_mask(crtc))) -+// continue; -+// if (!funcs || !funcs->mode_valid) -+// continue; -+// -+// status = funcs->mode_valid(crtc, mode, -+// DRM_MODE_CONNECTOR_HDMIA); -+// if (status != MODE_OK) -+// return status; -+// } -+// -+// return status; -+// } -+// - - static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) - { -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ // struct drm_crtc *crtc = encoder->crtc; -+ // struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); -+ // -+ // if (crtc->state->active_changed) { -+ // if (hdmi->plat_data->split_mode) { -+ // s->output_if &= ~(VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1); -+ // } else { -+ // if (!hdmi->id) -+ // s->output_if &= ~VOP_OUTPUT_IF_HDMI1; -+ // else -+ // s->output_if &= ~VOP_OUTPUT_IF_HDMI0; -+ // } -+ // } -+ /* -+ * when plug out hdmi it will be switch cvbs and then phy bus width -+ * must be set as 8 -+ */ -+ if (hdmi->phy) -+ phy_set_bus_width(hdmi->phy, 8); - } - - static bool -@@ -301,6 +1463,27 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *adj_mode) - { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ struct drm_crtc *crtc; -+ struct rockchip_crtc_state *s; -+ -+ if (!encoder->crtc) -+ return; -+ crtc = encoder->crtc; -+ -+ if (!crtc->state) -+ return; -+ s = to_rockchip_crtc_state(crtc->state); -+ -+ if (!s) -+ return; -+ -+ if (hdmi->is_hdmi_qp) { -+ // s->dsc_enable = 0; -+ // if (hdmi->link_cfg.dsc_mode) -+ // dw_hdmi_qp_dsc_configure(hdmi, s, crtc->state); -+ -+ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width); -+ } - - clk_set_rate(hdmi->ref_clk, adj_mode->clock * 1000); - } -@@ -308,14 +1491,25 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, - static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) - { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ struct drm_crtc *crtc = encoder->crtc; - u32 val; -+ int mux; - int ret; - -+ if (WARN_ON(!crtc || !crtc->state)) -+ return; -+ -+ if (hdmi->phy) -+ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width); -+ -+ clk_set_rate(hdmi->ref_clk, -+ crtc->state->adjusted_mode.crtc_clock * 1000); -+ - if (hdmi->chip_data->lcdsel_grf_reg < 0) - return; - -- ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); -- if (ret) -+ mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); -+ if (mux) - val = hdmi->chip_data->lcdsel_lit; - else - val = hdmi->chip_data->lcdsel_big; -@@ -330,24 +1524,992 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) - if (ret != 0) - DRM_DEV_ERROR(hdmi->dev, "Could not write to GRF: %d\n", ret); - -+ if (hdmi->chip_data->lcdsel_grf_reg == RK3288_GRF_SOC_CON6) { -+ struct rockchip_crtc_state *s = -+ to_rockchip_crtc_state(crtc->state); -+ u32 mode_mask = mux ? RK3288_HDMI_LCDC1_YUV420 : -+ RK3288_HDMI_LCDC0_YUV420; -+ -+ if (s->output_mode == ROCKCHIP_OUT_MODE_YUV420) -+ val = HIWORD_UPDATE(mode_mask, mode_mask); -+ else -+ val = HIWORD_UPDATE(0, mode_mask); -+ -+ regmap_write(hdmi->regmap, RK3288_GRF_SOC_CON16, val); -+ } -+ - clk_disable_unprepare(hdmi->grf_clk); - DRM_DEV_DEBUG(hdmi->dev, "vop %s output to hdmi\n", - ret ? "LIT" : "BIG"); - } - --static int --dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, -- struct drm_crtc_state *crtc_state, -- struct drm_connector_state *conn_state) -+static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi) - { -- struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); -+ int val; -+ bool is_hdmi0; - -- s->output_mode = ROCKCHIP_OUT_MODE_AAAA; -- s->output_type = DRM_MODE_CONNECTOR_HDMIA; -+ if (!hdmi->id) -+ is_hdmi0 = true; -+ else -+ is_hdmi0 = false; -+ -+ if (!hdmi->link_cfg.frl_mode) { -+ val = HIWORD_UPDATE(0, RK3588_HDMI21_MASK); -+ if (is_hdmi0) -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val); -+ else -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val); -+ -+ val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK); -+ if (is_hdmi0) -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); -+ else -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); -+ -+ return; -+ } -+ -+ val = HIWORD_UPDATE(RK3588_HDMI21_MASK, RK3588_HDMI21_MASK); -+ if (is_hdmi0) -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val); -+ else -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val); -+ -+ if (hdmi->link_cfg.dsc_mode) { -+ val = HIWORD_UPDATE(RK3588_COMPRESS_MODE_MASK | RK3588_COMPRESSED_DATA, -+ RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK); -+ if (is_hdmi0) -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); -+ else -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); -+ } else { -+ val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK); -+ if (is_hdmi0) -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); -+ else -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); -+ } -+} -+ -+static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format, -+ u32 depth) -+{ -+ u32 val = 0; -+ -+ switch (bus_format) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ val = HIWORD_UPDATE(0, RK3588_COLOR_FORMAT_MASK); -+ break; -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ val = HIWORD_UPDATE(RK3588_YUV420, RK3588_COLOR_FORMAT_MASK); -+ break; -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ val = HIWORD_UPDATE(RK3588_YUV444, RK3588_COLOR_FORMAT_MASK); -+ break; -+ default: -+ dev_err(hdmi->dev, "can't set correct color format\n"); -+ return; -+ } -+ -+ if (hdmi->link_cfg.dsc_mode) -+ val = HIWORD_UPDATE(RK3588_COMPRESSED_DATA, RK3588_COLOR_FORMAT_MASK); -+ -+ if (depth == 8) -+ val |= HIWORD_UPDATE(RK3588_8BPC, RK3588_COLOR_DEPTH_MASK); -+ else -+ val |= HIWORD_UPDATE(RK3588_10BPC, RK3588_COLOR_DEPTH_MASK); -+ -+ if (!hdmi->id) -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); -+ else -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); -+} -+ -+static void rk3588_set_grf_cfg(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ int color_depth; -+ -+ rk3588_set_link_mode(hdmi); -+ color_depth = hdmi_bus_fmt_color_depth(hdmi->bus_format); -+ rk3588_set_color_format(hdmi, hdmi->bus_format, color_depth); -+} -+ -+static void -+dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state, -+ struct drm_crtc_state *crtc_state, -+ struct rockchip_hdmi *hdmi, -+ unsigned int *color_format, -+ unsigned int *output_mode, -+ unsigned long *bus_format, -+ unsigned int *bus_width, -+ unsigned long *enc_out_encoding, -+ unsigned int *eotf) -+{ -+ struct drm_display_info *info = &conn_state->connector->display_info; -+ struct drm_display_mode mode; -+ struct hdr_output_metadata *hdr_metadata; -+ u32 vic; -+ unsigned long tmdsclock, pixclock; -+ unsigned int color_depth; -+ bool support_dc = false; -+ bool sink_is_hdmi = true; -+ u32 max_tmds_clock = info->max_tmds_clock; -+ int output_eotf; -+ -+ drm_mode_copy(&mode, &crtc_state->mode); -+ pixclock = mode.crtc_clock; -+ // if (hdmi->plat_data->split_mode) { -+ // drm_mode_convert_to_origin_mode(&mode); -+ // pixclock /= 2; -+ // } -+ -+ vic = drm_match_cea_mode(&mode); -+ -+ if (!hdmi->is_hdmi_qp) -+ sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi); -+ -+ *color_format = RK_IF_FORMAT_RGB; -+ -+ switch (hdmi->hdmi_output) { -+ case RK_IF_FORMAT_YCBCR_HQ: -+ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) -+ *color_format = RK_IF_FORMAT_YCBCR444; -+ else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) -+ *color_format = RK_IF_FORMAT_YCBCR422; -+ else if (conn_state->connector->ycbcr_420_allowed && -+ drm_mode_is_420(info, &mode) && -+ (pixclock >= 594000 && !hdmi->is_hdmi_qp)) -+ *color_format = RK_IF_FORMAT_YCBCR420; -+ break; -+ case RK_IF_FORMAT_YCBCR_LQ: -+ if (conn_state->connector->ycbcr_420_allowed && -+ drm_mode_is_420(info, &mode) && pixclock >= 594000) -+ *color_format = RK_IF_FORMAT_YCBCR420; -+ else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) -+ *color_format = RK_IF_FORMAT_YCBCR422; -+ else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) -+ *color_format = RK_IF_FORMAT_YCBCR444; -+ break; -+ case RK_IF_FORMAT_YCBCR420: -+ if (conn_state->connector->ycbcr_420_allowed && -+ drm_mode_is_420(info, &mode) && pixclock >= 594000) -+ *color_format = RK_IF_FORMAT_YCBCR420; -+ break; -+ case RK_IF_FORMAT_YCBCR422: -+ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) -+ *color_format = RK_IF_FORMAT_YCBCR422; -+ break; -+ case RK_IF_FORMAT_YCBCR444: -+ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) -+ *color_format = RK_IF_FORMAT_YCBCR444; -+ break; -+ case RK_IF_FORMAT_RGB: -+ default: -+ break; -+ } -+ -+ if (*color_format == RK_IF_FORMAT_RGB && -+ info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) -+ support_dc = true; -+ if (*color_format == RK_IF_FORMAT_YCBCR444 && -+ info->edid_hdmi_rgb444_dc_modes & -+ (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30)) -+ support_dc = true; -+ if (*color_format == RK_IF_FORMAT_YCBCR422) -+ support_dc = true; -+ if (*color_format == RK_IF_FORMAT_YCBCR420 && -+ info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) -+ support_dc = true; -+ -+ if (hdmi->colordepth > 8 && support_dc) -+ color_depth = 10; -+ else -+ color_depth = 8; -+ -+ if (!sink_is_hdmi) { -+ *color_format = RK_IF_FORMAT_RGB; -+ color_depth = 8; -+ } -+ -+ *eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR; -+ if (conn_state->hdr_output_metadata) { -+ hdr_metadata = (struct hdr_output_metadata *) -+ conn_state->hdr_output_metadata->data; -+ output_eotf = hdr_metadata->hdmi_metadata_type1.eotf; -+ if (output_eotf > HDMI_EOTF_TRADITIONAL_GAMMA_SDR && -+ output_eotf <= HDMI_EOTF_BT_2100_HLG) -+ *eotf = output_eotf; -+ } -+ -+ hdmi->colorimetry = conn_state->colorspace; -+ -+ if ((*eotf > HDMI_EOTF_TRADITIONAL_GAMMA_SDR && -+ conn_state->connector->hdr_sink_metadata.hdmi_type1.eotf & -+ BIT(*eotf)) || ((hdmi->colorimetry >= DRM_MODE_COLORIMETRY_BT2020_CYCC) && -+ (hdmi->colorimetry <= DRM_MODE_COLORIMETRY_BT2020_YCC))) -+ *enc_out_encoding = V4L2_YCBCR_ENC_BT2020; -+ else if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) || -+ (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18)) -+ *enc_out_encoding = V4L2_YCBCR_ENC_601; -+ else -+ *enc_out_encoding = V4L2_YCBCR_ENC_709; -+ -+ if (*enc_out_encoding == V4L2_YCBCR_ENC_BT2020) { -+ /* BT2020 require color depth at lest 10bit */ -+ color_depth = 10; -+ /* We prefer use YCbCr422 to send 10bit */ -+ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) -+ *color_format = RK_IF_FORMAT_YCBCR422; -+ if (hdmi->is_hdmi_qp) { -+ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420) { -+ if (mode.clock >= 340000) -+ *color_format = RK_IF_FORMAT_YCBCR420; -+ else -+ *color_format = RK_IF_FORMAT_RGB; -+ } else { -+ *color_format = RK_IF_FORMAT_RGB; -+ } -+ } -+ } -+ -+ if (mode.flags & DRM_MODE_FLAG_DBLCLK) -+ pixclock *= 2; -+ if ((mode.flags & DRM_MODE_FLAG_3D_MASK) == -+ DRM_MODE_FLAG_3D_FRAME_PACKING) -+ pixclock *= 2; -+ -+ if (*color_format == RK_IF_FORMAT_YCBCR422 || color_depth == 8) -+ tmdsclock = pixclock; -+ else -+ tmdsclock = pixclock * (color_depth) / 8; -+ -+ if (*color_format == RK_IF_FORMAT_YCBCR420) -+ tmdsclock /= 2; -+ -+ /* XXX: max_tmds_clock of some sink is 0, we think it is 340MHz. */ -+ if (!max_tmds_clock) -+ max_tmds_clock = 340000; -+ -+ max_tmds_clock = min(max_tmds_clock, hdmi->max_tmdsclk); -+ -+ if ((tmdsclock > max_tmds_clock) && !hdmi->is_hdmi_qp) { -+ if (max_tmds_clock >= 594000) { -+ color_depth = 8; -+ } else if (max_tmds_clock > 340000) { -+ if (drm_mode_is_420(info, &mode) || tmdsclock >= 594000) -+ *color_format = RK_IF_FORMAT_YCBCR420; -+ } else { -+ color_depth = 8; -+ if (drm_mode_is_420(info, &mode) || tmdsclock >= 594000) -+ *color_format = RK_IF_FORMAT_YCBCR420; -+ } -+ } -+ -+ if (hdmi->is_hdmi_qp) { -+ if (mode.clock >= 340000) { -+ if (drm_mode_is_420(info, &mode)) -+ *color_format = RK_IF_FORMAT_YCBCR420; -+ else -+ *color_format = RK_IF_FORMAT_RGB; -+ } else if (tmdsclock > max_tmds_clock) { -+ color_depth = 8; -+ if (drm_mode_is_420(info, &mode)) -+ *color_format = RK_IF_FORMAT_YCBCR420; -+ } -+ } -+ -+ if (*color_format == RK_IF_FORMAT_YCBCR420) { -+ *output_mode = ROCKCHIP_OUT_MODE_YUV420; -+ if (color_depth > 8) -+ *bus_format = MEDIA_BUS_FMT_UYYVYY10_0_5X30; -+ else -+ *bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24; -+ *bus_width = color_depth / 2; -+ } else { -+ *output_mode = ROCKCHIP_OUT_MODE_AAAA; -+ if (color_depth > 8) { -+ if (*color_format != RK_IF_FORMAT_RGB && -+ !hdmi->unsupported_yuv_input) -+ *bus_format = MEDIA_BUS_FMT_YUV10_1X30; -+ else -+ *bus_format = MEDIA_BUS_FMT_RGB101010_1X30; -+ } else { -+ if (*color_format != RK_IF_FORMAT_RGB && -+ !hdmi->unsupported_yuv_input) -+ *bus_format = MEDIA_BUS_FMT_YUV8_1X24; -+ else -+ *bus_format = MEDIA_BUS_FMT_RGB888_1X24; -+ } -+ if (*color_format == RK_IF_FORMAT_YCBCR422) -+ *bus_width = 8; -+ else -+ *bus_width = color_depth; -+ } -+ -+ hdmi->bus_format = *bus_format; -+ -+ if (*color_format == RK_IF_FORMAT_YCBCR422) { -+ if (color_depth == 12) -+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24; -+ else if (color_depth == 10) -+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20; -+ else -+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16; -+ } else { -+ hdmi->output_bus_format = *bus_format; -+ } -+} -+ -+static bool -+dw_hdmi_rockchip_check_color(struct drm_connector_state *conn_state, -+ struct rockchip_hdmi *hdmi) -+{ -+ struct drm_crtc_state *crtc_state = conn_state->crtc->state; -+ unsigned int colorformat; -+ unsigned long bus_format; -+ unsigned long output_bus_format = hdmi->output_bus_format; -+ unsigned long enc_out_encoding = hdmi->enc_out_encoding; -+ unsigned int eotf, bus_width; -+ unsigned int output_mode; -+ -+ dw_hdmi_rockchip_select_output(conn_state, crtc_state, hdmi, -+ &colorformat, -+ &output_mode, &bus_format, &bus_width, -+ &hdmi->enc_out_encoding, &eotf); -+ -+ if (output_bus_format != hdmi->output_bus_format || -+ enc_out_encoding != hdmi->enc_out_encoding) -+ return true; -+ else -+ return false; -+} -+ -+static int -+dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) -+{ -+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); -+ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); -+ unsigned int colorformat, bus_width, tmdsclk; -+ struct drm_display_mode mode; -+ unsigned int output_mode; -+ unsigned long bus_format; -+ int color_depth; -+ bool secondary = false; -+ -+ /* -+ * There are two hdmi but only one encoder in split mode, -+ * so we need to check twice. -+ */ -+secondary: -+ drm_mode_copy(&mode, &crtc_state->mode); -+ -+ hdmi->vp_id = 0; -+ // hdmi->vp_id = s->vp_id; -+ // if (hdmi->plat_data->split_mode) -+ // drm_mode_convert_to_origin_mode(&mode); -+ -+ int eotf; -+ dw_hdmi_rockchip_select_output(conn_state, crtc_state, hdmi, -+ &colorformat, -+ &output_mode, &bus_format, &bus_width, -+ // &hdmi->enc_out_encoding, &s->eotf); -+ &hdmi->enc_out_encoding, &eotf); -+ -+ s->bus_format = bus_format; -+ if (hdmi->is_hdmi_qp) { -+ color_depth = hdmi_bus_fmt_color_depth(bus_format); -+ tmdsclk = hdmi_get_tmdsclock(hdmi, crtc_state->mode.clock); -+ if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format)) -+ tmdsclk /= 2; -+ hdmi_select_link_config(hdmi, crtc_state, tmdsclk); -+ -+ if (hdmi->link_cfg.frl_mode) { -+ gpiod_set_value(hdmi->enable_gpio, 0); -+ /* in the current version, support max 40G frl */ -+ if (hdmi->link_cfg.rate_per_lane >= 10) { -+ hdmi->link_cfg.frl_lanes = 4; -+ hdmi->link_cfg.rate_per_lane = 10; -+ } -+ bus_width = hdmi->link_cfg.frl_lanes * -+ hdmi->link_cfg.rate_per_lane * 1000000; -+ /* 10 bit color depth and frl mode */ -+ if (color_depth == 10) -+ bus_width |= -+ COLOR_DEPTH_10BIT | HDMI_FRL_MODE; -+ else -+ bus_width |= HDMI_FRL_MODE; -+ } else { -+ gpiod_set_value(hdmi->enable_gpio, 1); -+ bus_width = hdmi_get_tmdsclock(hdmi, mode.clock * 10); -+ if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format)) -+ bus_width /= 2; -+ -+ if (color_depth == 10) -+ bus_width |= COLOR_DEPTH_10BIT; -+ } -+ } -+ -+ hdmi->phy_bus_width = bus_width; -+ -+ if (hdmi->phy) -+ phy_set_bus_width(hdmi->phy, bus_width); -+ -+ s->output_type = DRM_MODE_CONNECTOR_HDMIA; -+ // s->tv_state = &conn_state->tv; -+ // -+ // if (hdmi->plat_data->split_mode) { -+ // s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE; -+ // if (hdmi->plat_data->right && hdmi->id) -+ // s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP; -+ // s->output_if |= VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1; -+ // } else { -+ // if (!hdmi->id) -+ // s->output_if |= VOP_OUTPUT_IF_HDMI0; -+ // else -+ // s->output_if |= VOP_OUTPUT_IF_HDMI1; -+ // } -+ -+ s->output_mode = output_mode; -+ hdmi->bus_format = s->bus_format; -+ -+ if (hdmi->enc_out_encoding == V4L2_YCBCR_ENC_BT2020) -+ s->color_space = V4L2_COLORSPACE_BT2020; -+ else if (colorformat == RK_IF_FORMAT_RGB) -+ s->color_space = V4L2_COLORSPACE_DEFAULT; -+ else if (hdmi->enc_out_encoding == V4L2_YCBCR_ENC_709) -+ s->color_space = V4L2_COLORSPACE_REC709; -+ else -+ s->color_space = V4L2_COLORSPACE_SMPTE170M; -+ -+ if (hdmi->plat_data->split_mode && !secondary) { -+ hdmi = rockchip_hdmi_find_by_id(hdmi->dev->driver, !hdmi->id); -+ secondary = true; -+ goto secondary; -+ } - - return 0; - } - -+static unsigned long -+dw_hdmi_rockchip_get_input_bus_format(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ return hdmi->bus_format; -+} -+ -+static unsigned long -+dw_hdmi_rockchip_get_output_bus_format(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ return hdmi->output_bus_format; -+} -+ -+static unsigned long -+dw_hdmi_rockchip_get_enc_in_encoding(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ return hdmi->enc_out_encoding; -+} -+ -+static unsigned long -+dw_hdmi_rockchip_get_enc_out_encoding(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ return hdmi->enc_out_encoding; -+} -+ -+static unsigned long -+dw_hdmi_rockchip_get_quant_range(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ return hdmi->hdmi_quant_range; -+} -+ -+static struct drm_property * -+dw_hdmi_rockchip_get_hdr_property(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ return hdmi->hdr_panel_metadata_property; -+} -+ -+static struct drm_property_blob * -+dw_hdmi_rockchip_get_hdr_blob(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ return hdmi->hdr_panel_blob_ptr; -+} -+ -+static bool -+dw_hdmi_rockchip_get_color_changed(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ bool ret = false; -+ -+ if (hdmi->color_changed) -+ ret = true; -+ hdmi->color_changed = 0; -+ -+ return ret; -+} -+ -+#if 0 -+static int -+dw_hdmi_rockchip_get_edid_dsc_info(void *data, struct edid *edid) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ if (!edid) -+ return -EINVAL; -+ -+ return rockchip_drm_parse_cea_ext(&hdmi->dsc_cap, -+ &hdmi->max_frl_rate_per_lane, -+ &hdmi->max_lanes, edid); -+} -+ -+static int -+dw_hdmi_rockchip_get_next_hdr_data(void *data, struct edid *edid, -+ struct drm_connector *connector) -+{ -+ int ret; -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ struct next_hdr_sink_data *sink_data = &hdmi->next_hdr_data; -+ size_t size = sizeof(*sink_data); -+ struct drm_property *property = hdmi->next_hdr_sink_data_property; -+ struct drm_property_blob *blob = hdmi->hdr_panel_blob_ptr; -+ -+ if (!edid) -+ return -EINVAL; -+ -+ rockchip_drm_parse_next_hdr(sink_data, edid); -+ -+ ret = drm_property_replace_global_blob(connector->dev, &blob, size, sink_data, -+ &connector->base, property); -+ -+ return ret; -+}; -+#endif -+ -+static -+struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ return &hdmi->link_cfg; -+} -+ -+#if 0 -+static const struct drm_prop_enum_list color_depth_enum_list[] = { -+ { 0, "Automatic" }, /* Prefer highest color depth */ -+ { 8, "24bit" }, -+ { 10, "30bit" }, -+}; -+ -+static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = { -+ { RK_IF_FORMAT_RGB, "rgb" }, -+ { RK_IF_FORMAT_YCBCR444, "ycbcr444" }, -+ { RK_IF_FORMAT_YCBCR422, "ycbcr422" }, -+ { RK_IF_FORMAT_YCBCR420, "ycbcr420" }, -+ { RK_IF_FORMAT_YCBCR_HQ, "ycbcr_high_subsampling" }, -+ { RK_IF_FORMAT_YCBCR_LQ, "ycbcr_low_subsampling" }, -+ { RK_IF_FORMAT_MAX, "invalid_output" }, -+}; -+ -+static const struct drm_prop_enum_list quant_range_enum_list[] = { -+ { HDMI_QUANTIZATION_RANGE_DEFAULT, "default" }, -+ { HDMI_QUANTIZATION_RANGE_LIMITED, "limit" }, -+ { HDMI_QUANTIZATION_RANGE_FULL, "full" }, -+}; -+ -+static const struct drm_prop_enum_list output_hdmi_dvi_enum_list[] = { -+ { 0, "auto" }, -+ { 1, "force_hdmi" }, -+ { 2, "force_dvi" }, -+}; -+ -+static const struct drm_prop_enum_list output_type_cap_list[] = { -+ { 0, "DVI" }, -+ { 1, "HDMI" }, -+}; -+#endif -+ -+static void -+dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, -+ unsigned int color, int version, -+ void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ struct drm_property *prop; -+ // struct rockchip_drm_private *private = connector->dev->dev_private; -+ -+ switch (color) { -+ case MEDIA_BUS_FMT_RGB101010_1X30: -+ hdmi->hdmi_output = RK_IF_FORMAT_RGB; -+ hdmi->colordepth = 10; -+ break; -+ case MEDIA_BUS_FMT_YUV8_1X24: -+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR444; -+ hdmi->colordepth = 8; -+ break; -+ case MEDIA_BUS_FMT_YUV10_1X30: -+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR444; -+ hdmi->colordepth = 10; -+ break; -+ case MEDIA_BUS_FMT_UYVY10_1X20: -+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR422; -+ hdmi->colordepth = 10; -+ break; -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR422; -+ hdmi->colordepth = 8; -+ break; -+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: -+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR420; -+ hdmi->colordepth = 8; -+ break; -+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: -+ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR420; -+ hdmi->colordepth = 10; -+ break; -+ default: -+ hdmi->hdmi_output = RK_IF_FORMAT_RGB; -+ hdmi->colordepth = 8; -+ } -+ -+ hdmi->bus_format = color; -+ -+ if (hdmi->hdmi_output == RK_IF_FORMAT_YCBCR422) { -+ if (hdmi->colordepth == 12) -+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24; -+ else if (hdmi->colordepth == 10) -+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20; -+ else -+ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16; -+ } else { -+ hdmi->output_bus_format = hdmi->bus_format; -+ } -+ -+#if 0 -+ /* RK3368 does not support deep color mode */ -+ if (!hdmi->color_depth_property && !hdmi->unsupported_deep_color) { -+ prop = drm_property_create_enum(connector->dev, 0, -+ RK_IF_PROP_COLOR_DEPTH, -+ color_depth_enum_list, -+ ARRAY_SIZE(color_depth_enum_list)); -+ if (prop) { -+ hdmi->color_depth_property = prop; -+ drm_object_attach_property(&connector->base, prop, 0); -+ } -+ } -+ -+ prop = drm_property_create_enum(connector->dev, 0, RK_IF_PROP_COLOR_FORMAT, -+ drm_hdmi_output_enum_list, -+ ARRAY_SIZE(drm_hdmi_output_enum_list)); -+ if (prop) { -+ hdmi->hdmi_output_property = prop; -+ drm_object_attach_property(&connector->base, prop, 0); -+ } -+ -+ prop = drm_property_create_range(connector->dev, 0, -+ RK_IF_PROP_COLOR_DEPTH_CAPS, -+ 0, 0xff); -+ if (prop) { -+ hdmi->colordepth_capacity = prop; -+ drm_object_attach_property(&connector->base, prop, 0); -+ } -+ -+ prop = drm_property_create_range(connector->dev, 0, -+ RK_IF_PROP_COLOR_FORMAT_CAPS, -+ 0, 0xf); -+ if (prop) { -+ hdmi->outputmode_capacity = prop; -+ drm_object_attach_property(&connector->base, prop, 0); -+ } -+ -+ prop = drm_property_create(connector->dev, -+ DRM_MODE_PROP_BLOB | -+ DRM_MODE_PROP_IMMUTABLE, -+ "HDR_PANEL_METADATA", 0); -+ if (prop) { -+ hdmi->hdr_panel_metadata_property = prop; -+ drm_object_attach_property(&connector->base, prop, 0); -+ } -+ -+ prop = drm_property_create(connector->dev, -+ DRM_MODE_PROP_BLOB | -+ DRM_MODE_PROP_IMMUTABLE, -+ "NEXT_HDR_SINK_DATA", 0); -+ if (prop) { -+ hdmi->next_hdr_sink_data_property = prop; -+ drm_object_attach_property(&connector->base, prop, 0); -+ } -+ -+ prop = drm_property_create_bool(connector->dev, DRM_MODE_PROP_IMMUTABLE, -+ "USER_SPLIT_MODE"); -+ if (prop) { -+ hdmi->user_split_mode_prop = prop; -+ drm_object_attach_property(&connector->base, prop, -+ hdmi->user_split_mode ? 1 : 0); -+ } -+ -+ if (!hdmi->is_hdmi_qp) { -+ prop = drm_property_create_enum(connector->dev, 0, -+ "output_hdmi_dvi", -+ output_hdmi_dvi_enum_list, -+ ARRAY_SIZE(output_hdmi_dvi_enum_list)); -+ if (prop) { -+ hdmi->output_hdmi_dvi = prop; -+ drm_object_attach_property(&connector->base, prop, 0); -+ } -+ -+ prop = drm_property_create_enum(connector->dev, 0, -+ "output_type_capacity", -+ output_type_cap_list, -+ ARRAY_SIZE(output_type_cap_list)); -+ if (prop) { -+ hdmi->output_type_capacity = prop; -+ drm_object_attach_property(&connector->base, prop, 0); -+ } -+ -+ prop = drm_property_create_enum(connector->dev, 0, -+ "hdmi_quant_range", -+ quant_range_enum_list, -+ ARRAY_SIZE(quant_range_enum_list)); -+ if (prop) { -+ hdmi->quant_range = prop; -+ drm_object_attach_property(&connector->base, prop, 0); -+ } -+ } -+#endif -+ -+ prop = connector->dev->mode_config.hdr_output_metadata_property; -+ if (version >= 0x211a || hdmi->is_hdmi_qp) -+ drm_object_attach_property(&connector->base, prop, 0); -+ -+ if (!drm_mode_create_hdmi_colorspace_property(connector, 0)) -+ drm_object_attach_property(&connector->base, -+ connector->colorspace_property, 0); -+ -+#if 0 -+ // [CC:] if this is not needed, also drop connector_id_prop -+ if (!private->connector_id_prop) -+ private->connector_id_prop = drm_property_create_range(connector->dev, -+ DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_IMMUTABLE, -+ "CONNECTOR_ID", 0, 0xf); -+ if (private->connector_id_prop) -+ drm_object_attach_property(&connector->base, private->connector_id_prop, hdmi->id); -+#endif -+} -+ -+static void -+dw_hdmi_rockchip_destroy_properties(struct drm_connector *connector, -+ void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ if (hdmi->color_depth_property) { -+ drm_property_destroy(connector->dev, -+ hdmi->color_depth_property); -+ hdmi->color_depth_property = NULL; -+ } -+ -+ if (hdmi->hdmi_output_property) { -+ drm_property_destroy(connector->dev, -+ hdmi->hdmi_output_property); -+ hdmi->hdmi_output_property = NULL; -+ } -+ -+ if (hdmi->colordepth_capacity) { -+ drm_property_destroy(connector->dev, -+ hdmi->colordepth_capacity); -+ hdmi->colordepth_capacity = NULL; -+ } -+ -+ if (hdmi->outputmode_capacity) { -+ drm_property_destroy(connector->dev, -+ hdmi->outputmode_capacity); -+ hdmi->outputmode_capacity = NULL; -+ } -+ -+ if (hdmi->quant_range) { -+ drm_property_destroy(connector->dev, -+ hdmi->quant_range); -+ hdmi->quant_range = NULL; -+ } -+ -+ if (hdmi->hdr_panel_metadata_property) { -+ drm_property_destroy(connector->dev, -+ hdmi->hdr_panel_metadata_property); -+ hdmi->hdr_panel_metadata_property = NULL; -+ } -+ -+ if (hdmi->next_hdr_sink_data_property) { -+ drm_property_destroy(connector->dev, -+ hdmi->next_hdr_sink_data_property); -+ hdmi->next_hdr_sink_data_property = NULL; -+ } -+ -+ if (hdmi->output_hdmi_dvi) { -+ drm_property_destroy(connector->dev, -+ hdmi->output_hdmi_dvi); -+ hdmi->output_hdmi_dvi = NULL; -+ } -+ -+ if (hdmi->output_type_capacity) { -+ drm_property_destroy(connector->dev, -+ hdmi->output_type_capacity); -+ hdmi->output_type_capacity = NULL; -+ } -+ -+ if (hdmi->user_split_mode_prop) { -+ drm_property_destroy(connector->dev, -+ hdmi->user_split_mode_prop); -+ hdmi->user_split_mode_prop = NULL; -+ } -+} -+ -+static int -+dw_hdmi_rockchip_set_property(struct drm_connector *connector, -+ struct drm_connector_state *state, -+ struct drm_property *property, -+ u64 val, -+ void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ struct drm_mode_config *config = &connector->dev->mode_config; -+ -+ if (property == hdmi->color_depth_property) { -+ hdmi->colordepth = val; -+ /* If hdmi is disconnected, state->crtc is null */ -+ if (!state->crtc) -+ return 0; -+ if (dw_hdmi_rockchip_check_color(state, hdmi)) -+ hdmi->color_changed++; -+ return 0; -+ } else if (property == hdmi->hdmi_output_property) { -+ hdmi->hdmi_output = val; -+ if (!state->crtc) -+ return 0; -+ if (dw_hdmi_rockchip_check_color(state, hdmi)) -+ hdmi->color_changed++; -+ return 0; -+ } else if (property == hdmi->quant_range) { -+ u64 quant_range = hdmi->hdmi_quant_range; -+ -+ hdmi->hdmi_quant_range = val; -+ if (quant_range != hdmi->hdmi_quant_range) -+ dw_hdmi_set_quant_range(hdmi->hdmi); -+ return 0; -+ } else if (property == config->hdr_output_metadata_property) { -+ return 0; -+ } else if (property == hdmi->output_hdmi_dvi) { -+ if (hdmi->force_output != val) -+ hdmi->color_changed++; -+ hdmi->force_output = val; -+ dw_hdmi_set_output_type(hdmi->hdmi, val); -+ return 0; -+ } else if (property == hdmi->colordepth_capacity) { -+ return 0; -+ } else if (property == hdmi->outputmode_capacity) { -+ return 0; -+ } else if (property == hdmi->output_type_capacity) { -+ return 0; -+ } -+ -+ DRM_ERROR("Unknown property [PROP:%d:%s]\n", -+ property->base.id, property->name); -+ -+ return -EINVAL; -+} -+ -+static int -+dw_hdmi_rockchip_get_property(struct drm_connector *connector, -+ const struct drm_connector_state *state, -+ struct drm_property *property, -+ u64 *val, -+ void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ struct drm_display_info *info = &connector->display_info; -+ struct drm_mode_config *config = &connector->dev->mode_config; -+ -+ if (property == hdmi->color_depth_property) { -+ *val = hdmi->colordepth; -+ return 0; -+ } else if (property == hdmi->hdmi_output_property) { -+ *val = hdmi->hdmi_output; -+ return 0; -+ } else if (property == hdmi->colordepth_capacity) { -+ *val = BIT(RK_IF_DEPTH_8); -+ /* RK3368 only support 8bit */ -+ if (hdmi->unsupported_deep_color) -+ return 0; -+ if (info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) -+ *val |= BIT(RK_IF_DEPTH_10); -+ if (info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36) -+ *val |= BIT(RK_IF_DEPTH_12); -+ if (info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_48) -+ *val |= BIT(RK_IF_DEPTH_16); -+ if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) -+ *val |= BIT(RK_IF_DEPTH_420_10); -+ if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) -+ *val |= BIT(RK_IF_DEPTH_420_12); -+ if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48) -+ *val |= BIT(RK_IF_DEPTH_420_16); -+ return 0; -+ } else if (property == hdmi->outputmode_capacity) { -+ *val = BIT(RK_IF_FORMAT_RGB); -+ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) -+ *val |= BIT(RK_IF_FORMAT_YCBCR444); -+ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) -+ *val |= BIT(RK_IF_FORMAT_YCBCR422); -+ if (connector->ycbcr_420_allowed && -+ info->color_formats & DRM_COLOR_FORMAT_YCBCR420) -+ *val |= BIT(RK_IF_FORMAT_YCBCR420); -+ return 0; -+ } else if (property == hdmi->quant_range) { -+ *val = hdmi->hdmi_quant_range; -+ return 0; -+ } else if (property == config->hdr_output_metadata_property) { -+ *val = state->hdr_output_metadata ? -+ state->hdr_output_metadata->base.id : 0; -+ return 0; -+ } else if (property == hdmi->output_hdmi_dvi) { -+ *val = hdmi->force_output; -+ return 0; -+ } else if (property == hdmi->output_type_capacity) { -+ *val = dw_hdmi_get_output_type_cap(hdmi->hdmi); -+ return 0; -+ } else if (property == hdmi->user_split_mode_prop) { -+ *val = hdmi->user_split_mode; -+ return 0; -+ } -+ -+ DRM_ERROR("Unknown property [PROP:%d:%s]\n", -+ property->base.id, property->name); -+ -+ return -EINVAL; -+} -+ -+static const struct dw_hdmi_property_ops dw_hdmi_rockchip_property_ops = { -+ .attach_properties = dw_hdmi_rockchip_attach_properties, -+ .destroy_properties = dw_hdmi_rockchip_destroy_properties, -+ .set_property = dw_hdmi_rockchip_set_property, -+ .get_property = dw_hdmi_rockchip_get_property, -+}; -+ - static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { - .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, - .mode_set = dw_hdmi_rockchip_encoder_mode_set, -@@ -356,20 +2518,24 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun - .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, - }; - --static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, -- const struct drm_display_info *display, -- const struct drm_display_mode *mode) -+static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data) - { - struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; - -- return phy_power_on(hdmi->phy); -+ while (hdmi->phy->power_count > 0) -+ phy_power_off(hdmi->phy); - } - --static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data) -+static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, -+ const struct drm_display_info *display, -+ const struct drm_display_mode *mode) - { - struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; - -- phy_power_off(hdmi->phy); -+ dw_hdmi_rockchip_genphy_disable(dw_hdmi, data); -+ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display); -+ -+ return phy_power_on(hdmi->phy); - } - - static void dw_hdmi_rk3228_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) -@@ -436,6 +2602,90 @@ static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) - RK3328_HDMI_HPD_IOE)); - } - -+static void dw_hdmi_qp_rockchip_phy_disable(struct dw_hdmi_qp *dw_hdmi, -+ void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ while (hdmi->phy->power_count > 0) -+ phy_power_off(hdmi->phy); -+} -+ -+static int dw_hdmi_qp_rockchip_genphy_init(struct dw_hdmi_qp *dw_hdmi, void *data, -+ struct drm_display_mode *mode) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ dw_hdmi_qp_rockchip_phy_disable(dw_hdmi, data); -+ -+ return phy_power_on(hdmi->phy); -+} -+ -+static enum drm_connector_status -+dw_hdmi_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) -+{ -+ u32 val; -+ int ret; -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val); -+ -+ if (!hdmi->id) { -+ if (val & RK3588_HDMI0_LEVEL_INT) { -+ hdmi->hpd_stat = true; -+ ret = connector_status_connected; -+ } else { -+ hdmi->hpd_stat = false; -+ ret = connector_status_disconnected; -+ } -+ } else { -+ if (val & RK3588_HDMI1_LEVEL_INT) { -+ hdmi->hpd_stat = true; -+ ret = connector_status_connected; -+ } else { -+ hdmi->hpd_stat = false; -+ ret = connector_status_disconnected; -+ } -+ } -+ -+ return ret; -+} -+ -+static void dw_hdmi_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ u32 val; -+ -+ if (!hdmi->id) { -+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, -+ RK3588_HDMI0_HPD_INT_CLR) | -+ HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK); -+ } else { -+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR, -+ RK3588_HDMI1_HPD_INT_CLR) | -+ HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK); -+ } -+ -+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); -+} -+ -+static void dw_hdmi_rk3588_phy_set_mode(struct dw_hdmi_qp *dw_hdmi, void *data, -+ u32 mode_mask, bool enable) -+{ -+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; -+ -+ if (!hdmi->phy) -+ return; -+ -+ /* set phy earc/frl mode */ -+ if (enable) -+ hdmi->phy_bus_width |= mode_mask; -+ else -+ hdmi->phy_bus_width &= ~mode_mask; -+ -+ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width); -+} -+ - static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { - .init = dw_hdmi_rockchip_genphy_init, - .disable = dw_hdmi_rockchip_genphy_disable, -@@ -525,6 +2775,30 @@ static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = { - .use_drm_infoframe = true, - }; - -+static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = { -+ .init = dw_hdmi_qp_rockchip_genphy_init, -+ .disable = dw_hdmi_qp_rockchip_phy_disable, -+ .read_hpd = dw_hdmi_rk3588_read_hpd, -+ .setup_hpd = dw_hdmi_rk3588_setup_hpd, -+ .set_mode = dw_hdmi_rk3588_phy_set_mode, -+}; -+ -+struct rockchip_hdmi_chip_data rk3588_hdmi_chip_data = { -+ .lcdsel_grf_reg = -1, -+ .ddc_en_reg = RK3588_GRF_VO1_CON3, -+ .split_mode = true, -+}; -+ -+static const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = { -+ .phy_data = &rk3588_hdmi_chip_data, -+ .qp_phy_ops = &rk3588_hdmi_phy_ops, -+ .phy_name = "samsung_hdptx_phy", -+ .phy_force_vendor = true, -+ .ycbcr_420_allowed = true, -+ .is_hdmi_qp = true, -+ .use_drm_infoframe = true, -+}; -+ - static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { - { .compatible = "rockchip,rk3228-dw-hdmi", - .data = &rk3228_hdmi_drv_data -@@ -541,6 +2815,9 @@ static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { - { .compatible = "rockchip,rk3568-dw-hdmi", - .data = &rk3568_hdmi_drv_data - }, -+ { .compatible = "rockchip,rk3588-dw-hdmi", -+ .data = &rk3588_hdmi_drv_data -+ }, - {}, - }; - MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids); -@@ -550,44 +2827,103 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - { - struct platform_device *pdev = to_platform_device(dev); - struct dw_hdmi_plat_data *plat_data; -- const struct of_device_id *match; - struct drm_device *drm = data; - struct drm_encoder *encoder; - struct rockchip_hdmi *hdmi; -+ struct rockchip_hdmi *secondary; - int ret; -+ u32 val; - - if (!pdev->dev.of_node) - return -ENODEV; - -- hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); -+ hdmi = platform_get_drvdata(pdev); - if (!hdmi) - return -ENOMEM; - -- match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); -- plat_data = devm_kmemdup(&pdev->dev, match->data, -- sizeof(*plat_data), GFP_KERNEL); -- if (!plat_data) -- return -ENOMEM; -+ plat_data = hdmi->plat_data; -+ hdmi->drm_dev = drm; - -- hdmi->dev = &pdev->dev; -- hdmi->plat_data = plat_data; -- hdmi->chip_data = plat_data->phy_data; - plat_data->phy_data = hdmi; -- plat_data->priv_data = hdmi; -- encoder = &hdmi->encoder.encoder; -+ plat_data->get_input_bus_format = -+ dw_hdmi_rockchip_get_input_bus_format; -+ plat_data->get_output_bus_format = -+ dw_hdmi_rockchip_get_output_bus_format; -+ plat_data->get_enc_in_encoding = -+ dw_hdmi_rockchip_get_enc_in_encoding; -+ plat_data->get_enc_out_encoding = -+ dw_hdmi_rockchip_get_enc_out_encoding; -+ plat_data->get_quant_range = -+ dw_hdmi_rockchip_get_quant_range; -+ plat_data->get_hdr_property = -+ dw_hdmi_rockchip_get_hdr_property; -+ plat_data->get_hdr_blob = -+ dw_hdmi_rockchip_get_hdr_blob; -+ plat_data->get_color_changed = -+ dw_hdmi_rockchip_get_color_changed; -+ // plat_data->get_edid_dsc_info = -+ // dw_hdmi_rockchip_get_edid_dsc_info; -+ // plat_data->get_next_hdr_data = -+ // dw_hdmi_rockchip_get_next_hdr_data; -+ plat_data->get_link_cfg = dw_hdmi_rockchip_get_link_cfg; -+ plat_data->set_grf_cfg = rk3588_set_grf_cfg; -+ // plat_data->convert_to_split_mode = drm_mode_convert_to_split_mode; -+ // plat_data->convert_to_origin_mode = drm_mode_convert_to_origin_mode; -+ -+ plat_data->property_ops = &dw_hdmi_rockchip_property_ops; -+ -+ secondary = rockchip_hdmi_find_by_id(dev->driver, !hdmi->id); -+ /* If don't enable hdmi0 and hdmi1, we don't enable split mode */ -+ if (hdmi->chip_data->split_mode && secondary) { - -- encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); -- rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder, -- dev->of_node, 0, 0); -+ /* -+ * hdmi can only attach bridge and init encoder/connector in the -+ * last bind hdmi in split mode, or hdmi->hdmi_qp will not be initialized -+ * and plat_data->left/right will be null pointer. we must check if split -+ * mode is on and determine the sequence of hdmi bind. -+ */ -+ if (device_property_read_bool(dev, "split-mode") || -+ device_property_read_bool(secondary->dev, "split-mode")) { -+ plat_data->split_mode = true; -+ secondary->plat_data->split_mode = true; -+ if (!secondary->plat_data->first_screen) -+ plat_data->first_screen = true; -+ } -+ -+ if (device_property_read_bool(dev, "user-split-mode") || -+ device_property_read_bool(secondary->dev, "user-split-mode")) { -+ hdmi->user_split_mode = true; -+ secondary->user_split_mode = true; -+ } -+ } -+ -+ if (!plat_data->first_screen) { -+ encoder = &hdmi->encoder.encoder; -+ encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); -+ rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder, -+ dev->of_node, 0, 0); -+ /* -+ * If we failed to find the CRTC(s) which this encoder is -+ * supposed to be connected to, it's because the CRTC has -+ * not been registered yet. Defer probing, and hope that -+ * the required CRTC is added later. -+ */ -+ if (encoder->possible_crtcs == 0) -+ return -EPROBE_DEFER; -+ -+ drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); -+ // [CC:] consider using drmm_simple_encoder_alloc() -+ drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); -+ } -+ -+ if (!plat_data->max_tmdsclk) -+ hdmi->max_tmdsclk = 594000; -+ else -+ hdmi->max_tmdsclk = plat_data->max_tmdsclk; - -- /* -- * If we failed to find the CRTC(s) which this encoder is -- * supposed to be connected to, it's because the CRTC has -- * not been registered yet. Defer probing, and hope that -- * the required CRTC is added later. -- */ -- if (encoder->possible_crtcs == 0) -- return -EPROBE_DEFER; -+ -+ hdmi->unsupported_yuv_input = plat_data->unsupported_yuv_input; -+ hdmi->unsupported_deep_color = plat_data->unsupported_deep_color; - - ret = rockchip_hdmi_parse_dt(hdmi); - if (ret) { -@@ -596,34 +2932,44 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - return ret; - } - -- hdmi->phy = devm_phy_optional_get(dev, "hdmi"); -- if (IS_ERR(hdmi->phy)) { -- ret = PTR_ERR(hdmi->phy); -- if (ret != -EPROBE_DEFER) -- DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); -+ ret = clk_prepare_enable(hdmi->aud_clk); -+ if (ret) { -+ dev_err(hdmi->dev, "Failed to enable HDMI aud_clk: %d\n", ret); - return ret; - } - -- ret = regulator_enable(hdmi->avdd_0v9); -+ ret = clk_prepare_enable(hdmi->hpd_clk); - if (ret) { -- DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret); -- goto err_avdd_0v9; -+ dev_err(hdmi->dev, "Failed to enable HDMI hpd_clk: %d\n", ret); -+ return ret; - } - -- ret = regulator_enable(hdmi->avdd_1v8); -+ ret = clk_prepare_enable(hdmi->hclk_vo1); - if (ret) { -- DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret); -- goto err_avdd_1v8; -+ dev_err(hdmi->dev, "Failed to enable HDMI hclk_vo1: %d\n", ret); -+ return ret; - } - -- ret = clk_prepare_enable(hdmi->ref_clk); -+ ret = clk_prepare_enable(hdmi->earc_clk); - if (ret) { -- DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI reference clock: %d\n", -- ret); -- goto err_clk; -+ dev_err(hdmi->dev, "Failed to enable HDMI earc_clk: %d\n", ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(hdmi->hdmitx_ref); -+ if (ret) { -+ dev_err(hdmi->dev, "Failed to enable HDMI hdmitx_ref: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(hdmi->pclk); -+ if (ret) { -+ dev_err(hdmi->dev, "Failed to enable HDMI pclk: %d\n", ret); -+ return ret; - } - -- if (hdmi->chip_data == &rk3568_chip_data) { -+ if (hdmi->chip_data->ddc_en_reg == RK3568_GRF_VO_CON1) { - regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1, - HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK | - RK3568_HDMI_SCLIN_MSK, -@@ -631,12 +2977,131 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - RK3568_HDMI_SCLIN_MSK)); - } - -- drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); -- drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); -+ if (hdmi->is_hdmi_qp) { -+ if (!hdmi->id) { -+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | -+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | -+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | -+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); -+ -+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, -+ RK3588_SET_HPD_PATH_MASK); -+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); -+ -+ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, -+ RK3588_HDMI0_GRANT_SEL); -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); -+ } else { -+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | -+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | -+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | -+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); -+ -+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, -+ RK3588_SET_HPD_PATH_MASK); -+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); -+ -+ val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL, -+ RK3588_HDMI1_GRANT_SEL); -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); -+ } -+ } - -- platform_set_drvdata(pdev, hdmi); -+ ret = clk_prepare_enable(hdmi->hclk_vio); -+ if (ret) { -+ dev_err(hdmi->dev, "Failed to enable HDMI hclk_vio: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(hdmi->hclk_vop); -+ if (ret) { -+ dev_err(hdmi->dev, "Failed to enable HDMI hclk_vop: %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(hdmi->ref_clk); -+ if (ret) { -+ DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI reference clock: %d\n", -+ ret); -+ goto err_clk; -+ } -+ -+ ret = regulator_enable(hdmi->avdd_0v9); -+ if (ret) { -+ DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret); -+ goto err_avdd_0v9; -+ } -+ -+ ret = regulator_enable(hdmi->avdd_1v8); -+ if (ret) { -+ DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret); -+ goto err_avdd_1v8; -+ } -+ -+ if (!hdmi->id) -+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK); -+ else -+ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, RK3588_HDMI1_HPD_INT_MSK); -+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); -+ -+ if (hdmi->is_hdmi_qp) { -+ hdmi->hpd_irq = platform_get_irq(pdev, 4); -+ if (hdmi->hpd_irq < 0) -+ return hdmi->hpd_irq; -+ -+ ret = devm_request_threaded_irq(hdmi->dev, hdmi->hpd_irq, -+ rockchip_hdmi_hardirq, -+ rockchip_hdmi_irq, -+ IRQF_SHARED, "dw-hdmi-qp-hpd", -+ hdmi); -+ if (ret) -+ return ret; -+ } -+ -+ hdmi->phy = devm_phy_optional_get(dev, "hdmi"); -+ if (IS_ERR(hdmi->phy)) { -+ hdmi->phy = devm_phy_optional_get(dev, "hdmi_phy"); -+ if (IS_ERR(hdmi->phy)) { -+ ret = PTR_ERR(hdmi->phy); -+ if (ret != -EPROBE_DEFER) -+ DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); -+ return ret; -+ } -+ } -+ -+ if (hdmi->is_hdmi_qp) { -+ // [CC:] do proper error handling, e.g. clk_disable_unprepare -+ hdmi->hdmi_qp = dw_hdmi_qp_bind(pdev, &hdmi->encoder.encoder, plat_data); -+ -+ if (IS_ERR(hdmi->hdmi_qp)) { -+ ret = PTR_ERR(hdmi->hdmi_qp); -+ drm_encoder_cleanup(&hdmi->encoder.encoder); -+ } -+ -+ // if (plat_data->connector) { -+ // hdmi->sub_dev.connector = plat_data->connector; -+ // hdmi->sub_dev.of_node = dev->of_node; -+ // rockchip_drm_register_sub_dev(&hdmi->sub_dev); -+ // } -+ -+ if (plat_data->split_mode && secondary) { -+ if (device_property_read_bool(dev, "split-mode")) { -+ plat_data->right = secondary->hdmi_qp; -+ secondary->plat_data->left = hdmi->hdmi_qp; -+ } else { -+ plat_data->left = secondary->hdmi_qp; -+ secondary->plat_data->right = hdmi->hdmi_qp; -+ } -+ } -+ -+ return ret; -+ } - -- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); -+ hdmi->hdmi = dw_hdmi_bind(pdev, &hdmi->encoder.encoder, plat_data); - - /* - * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), -@@ -647,11 +3112,24 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, - goto err_bind; - } - -+ // if (plat_data->connector) { -+ // hdmi->sub_dev.connector = plat_data->connector; -+ // hdmi->sub_dev.of_node = dev->of_node; -+ // rockchip_drm_register_sub_dev(&hdmi->sub_dev); -+ // } -+ - return 0; - - err_bind: -- drm_encoder_cleanup(encoder); -+ drm_encoder_cleanup(&hdmi->encoder.encoder); -+ clk_disable_unprepare(hdmi->aud_clk); - clk_disable_unprepare(hdmi->ref_clk); -+ clk_disable_unprepare(hdmi->hclk_vop); -+ clk_disable_unprepare(hdmi->hpd_clk); -+ clk_disable_unprepare(hdmi->hclk_vo1); -+ clk_disable_unprepare(hdmi->earc_clk); -+ clk_disable_unprepare(hdmi->hdmitx_ref); -+ clk_disable_unprepare(hdmi->pclk); - err_clk: - regulator_disable(hdmi->avdd_1v8); - err_avdd_1v8: -@@ -665,9 +3143,29 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, - { - struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); - -- dw_hdmi_unbind(hdmi->hdmi); -+ if (hdmi->is_hdmi_qp) { -+ cancel_delayed_work(&hdmi->work); -+ flush_workqueue(hdmi->workqueue); -+ } -+ -+ // if (hdmi->sub_dev.connector) -+ // rockchip_drm_unregister_sub_dev(&hdmi->sub_dev); -+ // -+ if (hdmi->is_hdmi_qp) -+ dw_hdmi_qp_unbind(hdmi->hdmi_qp); -+ else -+ dw_hdmi_unbind(hdmi->hdmi); -+ - drm_encoder_cleanup(&hdmi->encoder.encoder); -+ -+ clk_disable_unprepare(hdmi->aud_clk); - clk_disable_unprepare(hdmi->ref_clk); -+ clk_disable_unprepare(hdmi->hclk_vop); -+ clk_disable_unprepare(hdmi->hpd_clk); -+ clk_disable_unprepare(hdmi->hclk_vo1); -+ clk_disable_unprepare(hdmi->earc_clk); -+ clk_disable_unprepare(hdmi->hdmitx_ref); -+ clk_disable_unprepare(hdmi->pclk); - - regulator_disable(hdmi->avdd_1v8); - regulator_disable(hdmi->avdd_0v9); -@@ -680,30 +3178,142 @@ static const struct component_ops dw_hdmi_rockchip_ops = { - - static int dw_hdmi_rockchip_probe(struct platform_device *pdev) - { -+ struct rockchip_hdmi *hdmi; -+ const struct of_device_id *match; -+ struct dw_hdmi_plat_data *plat_data; -+ int id; -+ -+ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); -+ if (!hdmi) -+ return -ENOMEM; -+ -+ id = of_alias_get_id(pdev->dev.of_node, "hdmi"); -+ if (id < 0) -+ id = 0; -+ -+ hdmi->id = id; -+ hdmi->dev = &pdev->dev; -+ -+ match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); -+ plat_data = devm_kmemdup(&pdev->dev, match->data, -+ sizeof(*plat_data), GFP_KERNEL); -+ if (!plat_data) -+ return -ENOMEM; -+ -+ plat_data->id = hdmi->id; -+ hdmi->plat_data = plat_data; -+ hdmi->chip_data = plat_data->phy_data; -+ hdmi->is_hdmi_qp = plat_data->is_hdmi_qp; -+ -+ if (hdmi->is_hdmi_qp) { -+ hdmi->workqueue = create_workqueue("hpd_queue"); -+ INIT_DELAYED_WORK(&hdmi->work, repo_hpd_event); -+ } -+ -+ platform_set_drvdata(pdev, hdmi); -+ pm_runtime_enable(&pdev->dev); -+ pm_runtime_get_sync(&pdev->dev); -+ - return component_add(&pdev->dev, &dw_hdmi_rockchip_ops); - } - -+static void dw_hdmi_rockchip_shutdown(struct platform_device *pdev) -+{ -+ struct rockchip_hdmi *hdmi = dev_get_drvdata(&pdev->dev); -+ -+ if (!hdmi) -+ return; -+ -+ if (hdmi->is_hdmi_qp) { -+ cancel_delayed_work(&hdmi->work); -+ flush_workqueue(hdmi->workqueue); -+ dw_hdmi_qp_suspend(hdmi->dev, hdmi->hdmi_qp); -+ } else { -+ dw_hdmi_suspend(hdmi->hdmi); -+ } -+ pm_runtime_put_sync(&pdev->dev); -+} -+ - static void dw_hdmi_rockchip_remove(struct platform_device *pdev) - { -+ struct rockchip_hdmi *hdmi = dev_get_drvdata(&pdev->dev); -+ - component_del(&pdev->dev, &dw_hdmi_rockchip_ops); -+ pm_runtime_disable(&pdev->dev); -+ -+ if (hdmi->is_hdmi_qp) -+ destroy_workqueue(hdmi->workqueue); -+} -+ -+static int __maybe_unused dw_hdmi_rockchip_suspend(struct device *dev) -+{ -+ struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); -+ -+ if (hdmi->is_hdmi_qp) -+ dw_hdmi_qp_suspend(dev, hdmi->hdmi_qp); -+ else -+ dw_hdmi_suspend(hdmi->hdmi); -+ -+ pm_runtime_put_sync(dev); -+ -+ return 0; - } - - static int __maybe_unused dw_hdmi_rockchip_resume(struct device *dev) - { - struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); -+ u32 val; - -- dw_hdmi_resume(hdmi->hdmi); -+ if (hdmi->is_hdmi_qp) { -+ if (!hdmi->id) { -+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | -+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | -+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | -+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); -+ -+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, -+ RK3588_SET_HPD_PATH_MASK); -+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); -+ -+ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, -+ RK3588_HDMI0_GRANT_SEL); -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); -+ } else { -+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | -+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | -+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | -+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); -+ -+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, -+ RK3588_SET_HPD_PATH_MASK); -+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); -+ -+ val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL, -+ RK3588_HDMI1_GRANT_SEL); -+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); -+ } -+ -+ dw_hdmi_qp_resume(dev, hdmi->hdmi_qp); -+ drm_helper_hpd_irq_event(hdmi->drm_dev); -+ } else { -+ dw_hdmi_resume(hdmi->hdmi); -+ } -+ pm_runtime_get_sync(dev); - - return 0; - } - - static const struct dev_pm_ops dw_hdmi_rockchip_pm = { -- SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_rockchip_resume) -+ SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_rockchip_suspend, -+ dw_hdmi_rockchip_resume) - }; - - struct platform_driver dw_hdmi_rockchip_pltfm_driver = { - .probe = dw_hdmi_rockchip_probe, - .remove_new = dw_hdmi_rockchip_remove, -+ .shutdown = dw_hdmi_rockchip_shutdown, - .driver = { - .name = "dwhdmi-rockchip", - .pm = &dw_hdmi_rockchip_pm, -diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h -index 111111111111..222222222222 100644 ---- a/include/drm/bridge/dw_hdmi.h -+++ b/include/drm/bridge/dw_hdmi.h -@@ -6,12 +6,14 @@ - #ifndef __DW_HDMI__ - #define __DW_HDMI__ - -+#include - #include - - struct drm_display_info; - struct drm_display_mode; - struct drm_encoder; - struct dw_hdmi; -+struct dw_hdmi_qp; - struct platform_device; - - /** -@@ -92,6 +94,13 @@ enum dw_hdmi_phy_type { - DW_HDMI_PHY_VENDOR_PHY = 0xfe, - }; - -+struct dw_hdmi_audio_tmds_n { -+ unsigned long tmds; -+ unsigned int n_32k; -+ unsigned int n_44k1; -+ unsigned int n_48k; -+}; -+ - struct dw_hdmi_mpll_config { - unsigned long mpixelclock; - struct { -@@ -112,6 +121,15 @@ struct dw_hdmi_phy_config { - u16 vlev_ctr; /* voltage level control */ - }; - -+struct dw_hdmi_link_config { -+ bool dsc_mode; -+ bool frl_mode; -+ int frl_lanes; -+ int rate_per_lane; -+ int hcactive; -+ u8 pps_payload[128]; -+}; -+ - struct dw_hdmi_phy_ops { - int (*init)(struct dw_hdmi *hdmi, void *data, - const struct drm_display_info *display, -@@ -123,14 +141,52 @@ struct dw_hdmi_phy_ops { - void (*setup_hpd)(struct dw_hdmi *hdmi, void *data); - }; - -+struct dw_hdmi_qp_phy_ops { -+ int (*init)(struct dw_hdmi_qp *hdmi, void *data, -+ struct drm_display_mode *mode); -+ void (*disable)(struct dw_hdmi_qp *hdmi, void *data); -+ enum drm_connector_status (*read_hpd)(struct dw_hdmi_qp *hdmi, -+ void *data); -+ void (*update_hpd)(struct dw_hdmi_qp *hdmi, void *data, -+ bool force, bool disabled, bool rxsense); -+ void (*setup_hpd)(struct dw_hdmi_qp *hdmi, void *data); -+ void (*set_mode)(struct dw_hdmi_qp *dw_hdmi, void *data, -+ u32 mode_mask, bool enable); -+}; -+ -+struct dw_hdmi_property_ops { -+ void (*attach_properties)(struct drm_connector *connector, -+ unsigned int color, int version, -+ void *data); -+ void (*destroy_properties)(struct drm_connector *connector, -+ void *data); -+ int (*set_property)(struct drm_connector *connector, -+ struct drm_connector_state *state, -+ struct drm_property *property, -+ u64 val, -+ void *data); -+ int (*get_property)(struct drm_connector *connector, -+ const struct drm_connector_state *state, -+ struct drm_property *property, -+ u64 *val, -+ void *data); -+}; -+ - struct dw_hdmi_plat_data { - struct regmap *regm; - -+ //[CC:] not in dowstream - unsigned int output_port; - -+ unsigned long input_bus_format; - unsigned long input_bus_encoding; -+ unsigned int max_tmdsclk; -+ int id; - bool use_drm_infoframe; - bool ycbcr_420_allowed; -+ bool unsupported_yuv_input; -+ bool unsupported_deep_color; -+ bool is_hdmi_qp; - - /* - * Private data passed to all the .mode_valid() and .configure_phy() -@@ -139,6 +195,7 @@ struct dw_hdmi_plat_data { - void *priv_data; - - /* Platform-specific mode validation (optional). */ -+ //[CC:] downstream changed "struct dw_hdmi *hdmi" to "struct drm_connector *connector" - enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, - const struct drm_display_info *info, - const struct drm_display_mode *mode); -@@ -150,18 +207,50 @@ struct dw_hdmi_plat_data { - - /* Vendor PHY support */ - const struct dw_hdmi_phy_ops *phy_ops; -+ const struct dw_hdmi_qp_phy_ops *qp_phy_ops; - const char *phy_name; - void *phy_data; - unsigned int phy_force_vendor; - -+ /* split mode */ -+ bool split_mode; -+ bool first_screen; -+ struct dw_hdmi_qp *left; -+ struct dw_hdmi_qp *right; -+ - /* Synopsys PHY support */ - const struct dw_hdmi_mpll_config *mpll_cfg; -+ const struct dw_hdmi_mpll_config *mpll_cfg_420; - 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 int disable_cec : 1; -+ -+ //[CC:] 7b29b5f29585 ("drm/rockchip: dw_hdmi: Support HDMI 2.0 YCbCr 4:2:0") -+ unsigned long (*get_input_bus_format)(void *data); -+ unsigned long (*get_output_bus_format)(void *data); -+ unsigned long (*get_enc_in_encoding)(void *data); -+ unsigned long (*get_enc_out_encoding)(void *data); -+ -+ unsigned long (*get_quant_range)(void *data); -+ struct drm_property *(*get_hdr_property)(void *data); -+ struct drm_property_blob *(*get_hdr_blob)(void *data); -+ bool (*get_color_changed)(void *data); -+ int (*get_yuv422_format)(struct drm_connector *connector, -+ struct edid *edid); -+ int (*get_edid_dsc_info)(void *data, struct edid *edid); -+ int (*get_next_hdr_data)(void *data, struct edid *edid, -+ struct drm_connector *connector); -+ struct dw_hdmi_link_config *(*get_link_cfg)(void *data); -+ void (*set_grf_cfg)(void *data); -+ void (*convert_to_split_mode)(struct drm_display_mode *mode); -+ void (*convert_to_origin_mode)(struct drm_display_mode *mode); -+ -+ /* Vendor Property support */ -+ const struct dw_hdmi_property_ops *property_ops; -+ struct drm_connector *connector; - }; - - struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, -@@ -172,6 +261,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, - struct drm_encoder *encoder, - const struct dw_hdmi_plat_data *plat_data); - -+void dw_hdmi_suspend(struct dw_hdmi *hdmi); - void dw_hdmi_resume(struct dw_hdmi *hdmi); - - void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense); -@@ -205,6 +295,17 @@ enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, - void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, - bool force, bool disabled, bool rxsense); - void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data); -+void dw_hdmi_set_quant_range(struct dw_hdmi *hdmi); -+void dw_hdmi_set_output_type(struct dw_hdmi *hdmi, u64 val); -+bool dw_hdmi_get_output_whether_hdmi(struct dw_hdmi *hdmi); -+int dw_hdmi_get_output_type_cap(struct dw_hdmi *hdmi); -+ -+void dw_hdmi_qp_unbind(struct dw_hdmi_qp *hdmi); -+struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, -+ struct drm_encoder *encoder, -+ struct dw_hdmi_plat_data *plat_data); -+void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi); -+void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi); - - bool dw_hdmi_bus_fmt_is_420(struct dw_hdmi *hdmi); - --- -Armbian - diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch b/patch/kernel/archive/rockchip-rk3588-6.11/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch deleted file mode 100644 index 4c0ad9def..000000000 --- a/patch/kernel/archive/rockchip-rk3588-6.11/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ColorfulRhino -Date: Wed, 12 Jun 2024 12:17:18 +0200 -Subject: Fix HDMI controller patch at - drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c -index 111111111111..222222222222 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c -@@ -5,6 +5,7 @@ - * Algea Cao - */ - #include -+#include - #include - #include - #include --- -Armbian - diff --git a/patch/kernel/archive/rockchip-rk3588-6.11/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch b/patch/kernel/archive/rockchip-rk3588-6.11/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch index f9fd65eeb..c3e053410 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.11/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.11/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch @@ -1,14 +1,14 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From 9e44204e18695761c90996a5031e50afa61420d3 Mon Sep 17 00:00:00 2001 From: Muhammed Efe Cetin Date: Thu, 16 Nov 2023 18:15:09 +0300 -Subject: arm64: dts: Add missing nodes to Orange Pi 5 Plus +Subject: [PATCH] arm64: dts: Add missing nodes to Orange Pi 5 Plus --- - arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts | 203 +++++++++- - 1 file changed, 202 insertions(+), 1 deletion(-) + .../dts/rockchip/rk3588-orangepi-5-plus.dts | 217 +++++++++++++++++- + 1 file changed, 216 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts -index 111111111111..222222222222 100644 +index e74871491ef5..72eb082732c6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts @@ -10,6 +10,7 @@ @@ -19,7 +19,25 @@ index 111111111111..222222222222 100644 #include "rk3588.dtsi" / { -@@ -158,6 +159,20 @@ daicodec: simple-audio-card,codec { +@@ -85,6 +86,17 @@ led { + }; + }; + ++ hdmi0-con { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi0_con_in: endpoint { ++ remote-endpoint = <&hdmi0_out_con>; ++ }; ++ }; ++ }; ++ + fan: pwm-fan { + compatible = "pwm-fan"; + cooling-levels = <0 70 75 80 100>; +@@ -158,6 +170,20 @@ daicodec: simple-audio-card,codec { }; }; @@ -40,7 +58,7 @@ index 111111111111..222222222222 100644 vcc3v3_pcie30: vcc3v3-pcie30-regulator { compatible = "regulator-fixed"; enable-active-high; -@@ -199,6 +214,18 @@ vcc5v0_sys: vcc5v0-sys-regulator { +@@ -199,6 +225,18 @@ vcc5v0_sys: vcc5v0-sys-regulator { regulator-max-microvolt = <5000000>; }; @@ -59,7 +77,7 @@ index 111111111111..222222222222 100644 vcc5v0_usb20: vcc5v0-usb20-regulator { compatible = "regulator-fixed"; enable-active-high; -@@ -311,6 +338,53 @@ hym8563: rtc@51 { +@@ -311,6 +349,53 @@ hym8563: rtc@51 { pinctrl-0 = <&hym8563_int>; wakeup-source; }; @@ -113,13 +131,13 @@ index 111111111111..222222222222 100644 }; &i2c7 { -@@ -383,9 +457,15 @@ &pcie3x4 { +@@ -383,9 +468,15 @@ &pcie3x4 { }; &pinctrl { + hdmirx { + hdmirx_5v_detection: hdmirx-5v-detection { -+ rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; ++ rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + @@ -130,7 +148,7 @@ index 111111111111..222222222222 100644 }; }; -@@ -408,6 +488,14 @@ hp_detect: hp-detect { +@@ -408,6 +499,14 @@ hp_detect: hp-detect { }; usb { @@ -145,7 +163,7 @@ index 111111111111..222222222222 100644 vcc5v0_usb20_en: vcc5v0-usb20-en { rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; }; -@@ -803,6 +891,22 @@ &tsadc { +@@ -803,6 +902,22 @@ &tsadc { status = "okay"; }; @@ -168,7 +186,7 @@ index 111111111111..222222222222 100644 &u2phy2 { status = "okay"; }; -@@ -831,6 +935,35 @@ &uart9 { +@@ -831,6 +946,35 @@ &uart9 { status = "okay"; }; @@ -204,12 +222,12 @@ index 111111111111..222222222222 100644 &usb_host0_ehci { status = "okay"; }; -@@ -839,6 +972,20 @@ &usb_host0_ohci { +@@ -839,6 +983,20 @@ &usb_host0_ohci { status = "okay"; }; +&usb_host0_xhci { -+ dr_mode = "otg"; ++ dr_mode = "host"; + usb-role-switch; + status = "okay"; + @@ -225,7 +243,7 @@ index 111111111111..222222222222 100644 &usb_host1_ehci { status = "okay"; }; -@@ -846,3 +993,57 @@ &usb_host1_ehci { +@@ -846,3 +1004,60 @@ &usb_host1_ehci { &usb_host1_ohci { status = "okay"; }; @@ -240,30 +258,12 @@ index 111111111111..222222222222 100644 + status = "okay"; +}; + -+&hdmi0 { -+ status = "okay"; -+ enable-gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_HIGH>; -+ cec-enable = "true"; -+}; -+ +&hdptxphy_hdmi0 { + status = "okay"; +}; + -+&hdmi_receiver { -+ status = "okay"; -+ hpd-gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_LOW>; -+ pinctrl-0 = <&hdmim1_rx_cec &hdmim1_rx_hpdin &hdmim1_rx_scl -+ &hdmim1_rx_sda &hdmirx_5v_detection>; -+ pinctrl-names = "default"; -+}; -+ -+&hdmi_receiver_cma { -+ status = "okay"; -+}; -+ -+ -+&vop_mmu { ++&hdmi0 { ++ enable-gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + @@ -273,10 +273,31 @@ index 111111111111..222222222222 100644 + }; +}; + ++&hdmi0_out { ++ hdmi0_out_con: endpoint { ++ remote-endpoint = <&hdmi0_con_in>; ++ }; ++}; ++ ++&hdmi_receiver { ++ hpd = <&gpio1 RK_PC6 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&hdmim1_rx_cec &hdmim1_rx_hpdin &hdmim1_rx_scl &hdmim1_rx_sda &hdmirx_5v_detection>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&hdmi_receiver_cma { ++ status = "okay"; ++}; ++ +&vop { + status = "okay"; +}; + ++&vop_mmu { ++ status = "okay"; ++}; ++ +&vp0 { + vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; @@ -284,5 +305,5 @@ index 111111111111..222222222222 100644 + }; +}; -- -Armbian +2.45.2