From b6e19cb5c8d76278cfc5ee829dc1db19ab26e820 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Thu, 11 Sep 2025 18:31:14 +0800 Subject: [PATCH 01/21] ASoC: es7243e: Don't strip remove function when driver is builtin Fixes W=1 modpost warning: WARNING: modpost: sound/soc/codecs/es7243e.o: section mismatch in reference: es7243e_i2c_driver (section: .data) -> es7243e_i2c_remove (section: .exit.text) Signed-off-by: Tao Huang Change-Id: I5ce3f1f539e8f3e73277db40d97223bbaf38424a --- sound/soc/codecs/es7243e.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/es7243e.c b/sound/soc/codecs/es7243e.c index 6cd46c81f36e..f8ae1f680c25 100644 --- a/sound/soc/codecs/es7243e.c +++ b/sound/soc/codecs/es7243e.c @@ -2391,7 +2391,7 @@ es7243e_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *i2c_id) return ret; } -static void __exit es7243e_i2c_remove(struct i2c_client *i2c) +static void es7243e_i2c_remove(struct i2c_client *i2c) { sysfs_remove_group(&i2c->dev.kobj, &es7243e_debug_attr_group); } @@ -2613,7 +2613,7 @@ static struct i2c_driver es7243e_i2c_driver = { #endif }, .probe = es7243e_i2c_probe, - .remove = __exit_p(es7243e_i2c_remove), + .remove = es7243e_i2c_remove, .class = I2C_CLASS_HWMON, .id_table = es7243e_i2c_id, From d0e8f174dd01d809f1834b1d68d4ead30c53f368 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Wed, 19 Jun 2024 11:38:16 +0800 Subject: [PATCH 02/21] phy: rockchip: usbdp: use correct flag to init phy mode If the rockchip,dp-lane-mux property is config in dts, it mean DP function is used, but the USB function may not be used. It may be cause cmn ana lcpll lock timeout when initialize phy but USB function is not used. So just init the phy mode with USB function when u3-port node is enabled. If the rockchip,dp-lane-mux property is not in dts, it mean USB function is used, but the DP function is depend on DP Alt mode support by sink. If not sink device is disconnected and force to access DPTX controller register after initialize phy, The DP function should config, if not config the DPTX controller register can't be access. So if dp-port node is enabled, init the phy mode with DP function. Change-Id: I8aa7ab41d962a50dcdf6dffcf27070a6c6112efe Signed-off-by: Zhang Yubing --- drivers/phy/rockchip/phy-rockchip-usbdp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c index 89ddc07c5b78..0bb4b6a521e0 100644 --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c @@ -945,7 +945,6 @@ static int udphy_parse_lane_mux_data(struct rockchip_udphy *udphy, struct device udphy->mode = UDPHY_MODE_DP; udphy->dp_lanes = num_lanes; if (num_lanes == 1 || num_lanes == 2) { - udphy->mode |= UDPHY_MODE_USB; udphy->flip = udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP ? true : false; } @@ -1570,6 +1569,7 @@ static int rockchip_udphy_probe(struct platform_device *pdev) } if (device_property_present(dev, "svid")) { + udphy->mode |= UDPHY_MODE_DP; ret = udphy_setup_typec_mux(udphy); if (ret) return ret; @@ -1592,6 +1592,7 @@ static int rockchip_udphy_probe(struct platform_device *pdev) phy_set_bus_width(phy, udphy->dp_lanes); phy->attrs.max_link_rate = udphy_dp_get_max_link_rate(udphy, child_np); } else if (of_node_name_eq(child_np, "u3-port")) { + udphy->mode |= UDPHY_MODE_USB; phy = devm_phy_create(dev, child_np, &rockchip_u3phy_ops); if (IS_ERR(phy)) { dev_err(dev, "failed to create usb phy: %pOFn\n", child_np); From 9ce144742066e78dc3cdf9ec8c1c9cb00a64c97b Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Thu, 11 Sep 2025 11:13:57 +0800 Subject: [PATCH 03/21] arm64: config: rv1126b: disable unused RK_HEADSET and RK817 Signed-off-by: Weiwen Chen Change-Id: I23e19f14597246d7f3f5916853ffb692b4d728c9 --- arch/arm64/configs/rv1126b_defconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/configs/rv1126b_defconfig b/arch/arm64/configs/rv1126b_defconfig index c5fe46abb8c6..be98769335f1 100644 --- a/arch/arm64/configs/rv1126b_defconfig +++ b/arch/arm64/configs/rv1126b_defconfig @@ -178,8 +178,6 @@ CONFIG_SPI_ROCKCHIP_SFC=y CONFIG_PINCTRL_RK805=y CONFIG_GPIO_SYSFS=y CONFIG_SYSCON_REBOOT_MODE=y -CONFIG_BATTERY_RK817=y -CONFIG_CHARGER_RK817=y # CONFIG_HWMON is not set CONFIG_THERMAL=y CONFIG_THERMAL_WRITABLE_TRIPS=y @@ -336,7 +334,6 @@ CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y CONFIG_NVMEM_ROCKCHIP_OTP=y -CONFIG_RK_HEADSET=y CONFIG_ROCKCHIP_RKNPU=y CONFIG_EXT4_FS=y # CONFIG_DNOTIFY is not set From 9207016bfba54e0200d25580e17fd391e3c50d99 Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Thu, 11 Sep 2025 14:45:58 +0800 Subject: [PATCH 04/21] arm64: config: rv1126b: Add rv1126b-recovery.config Signed-off-by: Weiwen Chen Change-Id: I7cbd1c80607f79df3f1ed532c286b1baf904d397 --- arch/arm64/configs/rv1126b-recovery.config | 307 +++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 arch/arm64/configs/rv1126b-recovery.config diff --git a/arch/arm64/configs/rv1126b-recovery.config b/arch/arm64/configs/rv1126b-recovery.config new file mode 100644 index 000000000000..d6aa7bd6662a --- /dev/null +++ b/arch/arm64/configs/rv1126b-recovery.config @@ -0,0 +1,307 @@ +CONFIG_BLK_DEV_INITRD=y +# CONFIG_COREDUMP is not set +# CONFIG_CPU_FREQ is not set +CONFIG_CRC16=y +CONFIG_CRYPTO=y +# CONFIG_DMABUF_HEAPS_ROCKCHIP is not set +CONFIG_EXT4_FS=y +# CONFIG_I2C is not set +# CONFIG_IIO is not set +# CONFIG_KALLSYMS is not set +# CONFIG_MEDIA_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MSDOS_FS=y +CONFIG_MSDOS_PARTITION=y +CONFIG_MTD_BLOCK=y +CONFIG_NLS_CODEPAGE_936=y +# CONFIG_PM_DEVFREQ is not set +# CONFIG_PRINTK_TIME is not set +# CONFIG_PWM is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_SOUND is not set +CONFIG_SPI=y +# CONFIG_SQUASHFS is not set +# CONFIG_THERMAL is not set +CONFIG_VFAT_FS=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_CRYPTO_842 is not set +CONFIG_CRYPTO_ACOMP2=y +# CONFIG_CRYPTO_ADIANTUM is not set +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_AES_TI is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_ARIA is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_BLAKE2B is not set +# CONFIG_CRYPTO_BLAKE2S_ARM is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_CHACHA20_NEON is not set +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_CURVE25519 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +# CONFIG_CRYPTO_DEV_CCREE is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP is not set +# CONFIG_CRYPTO_DEV_SAFEXCEL is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECDSA is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_ECRDSA is not set +# CONFIG_CRYPTO_ESSIV is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_HCTR2 is not set +# CONFIG_CRYPTO_HMAC is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_JITTERENTROPY is not set +# CONFIG_CRYPTO_KEYWRAP is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_UTILS=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_MANAGER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_POLY1305 is not set +# CONFIG_CRYPTO_POLY1305_ARM is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA1_ARM is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA256_ARM is not set +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA512_ARM is not set +# CONFIG_CRYPTO_SM2 is not set +# CONFIG_CRYPTO_SM3_GENERIC is not set +# CONFIG_CRYPTO_SM4_GENERIC is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_VMAC is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_XXHASH is not set +# CONFIG_CRYPTO_ZSTD is not set +CONFIG_DECOMPRESS_XZ=y +# CONFIG_DM9051 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ENCX24J600 is not set +# CONFIG_EXT4_DEBUG is not set +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EZX_PCAP is not set +CONFIG_FAT_DEFAULT_CODEPAGE=936 +CONFIG_FAT_DEFAULT_IOCHARSET="cp936" +CONFIG_FAT_DEFAULT_UTF8=y +CONFIG_FAT_FS=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set +# CONFIG_INITRAMFS_FORCE is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +# CONFIG_KS8851 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_LMK04832 is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_OCELOT is not set +# CONFIG_MFD_RK806_SPI is not set +# CONFIG_MFD_RSMU_SPI is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +# CONFIG_MMC_CQHCI is not set +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_DW=y +# CONFIG_MMC_DW_BLUEFIELD is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +CONFIG_MMC_DW_PLTFM=y +CONFIG_MMC_DW_ROCKCHIP=y +# CONFIG_MMC_HSQ is not set +# CONFIG_MMC_MTK is not set +CONFIG_MMC_QUEUE_DEPTH=1 +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MOXTET is not set +# CONFIG_MSE102X is not set +CONFIG_MTD_BLKDEVS=y +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MCHP48L640 is not set +CONFIG_MTD_NAND_BBT_USING_FLASH=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_SPI_NAND=y +# CONFIG_MTD_SPI_NAND_ATO is not set +# CONFIG_MTD_SPI_NAND_BIWIN is not set +# CONFIG_MTD_SPI_NAND_DEVICE_AUTOSELECT is not set +# CONFIG_MTD_SPI_NAND_DOSILICON is not set +# CONFIG_MTD_SPI_NAND_ESMT is not set +# CONFIG_MTD_SPI_NAND_ETRON is not set +# CONFIG_MTD_SPI_NAND_FMSH is not set +# CONFIG_MTD_SPI_NAND_FORESEE is not set +CONFIG_MTD_SPI_NAND_GIGADEVICE=y +# CONFIG_MTD_SPI_NAND_GSTO is not set +# CONFIG_MTD_SPI_NAND_HIKSEMI is not set +# CONFIG_MTD_SPI_NAND_HYF is not set +# CONFIG_MTD_SPI_NAND_JSC is not set +CONFIG_MTD_SPI_NAND_MACRONIX=y +# CONFIG_MTD_SPI_NAND_MICRON is not set +# CONFIG_MTD_SPI_NAND_PARAGON is not set +# CONFIG_MTD_SPI_NAND_SILICONGO is not set +# CONFIG_MTD_SPI_NAND_SKYHIGH is not set +# CONFIG_MTD_SPI_NAND_TOSHIBA is not set +# CONFIG_MTD_SPI_NAND_UNIM is not set +CONFIG_MTD_SPI_NAND_WINBOND=y +# CONFIG_MTD_SPI_NAND_XINCUN is not set +# CONFIG_MTD_SPI_NAND_XTX is not set +# CONFIG_MTD_SPI_NAND_ZBIT is not set +CONFIG_MTD_SPI_NOR=y +# CONFIG_MTD_SPI_NOR_ATMEL is not set +# CONFIG_MTD_SPI_NOR_BOYA is not set +# CONFIG_MTD_SPI_NOR_CATALYST is not set +# CONFIG_MTD_SPI_NOR_DEVICE_AUTOSELECT is not set +# CONFIG_MTD_SPI_NOR_DOSILICON is not set +# CONFIG_MTD_SPI_NOR_EON is not set +# CONFIG_MTD_SPI_NOR_ESMT is not set +# CONFIG_MTD_SPI_NOR_EVERSPIN is not set +# CONFIG_MTD_SPI_NOR_FMSH is not set +# CONFIG_MTD_SPI_NOR_FUJITSU is not set +CONFIG_MTD_SPI_NOR_GIGADEVICE=y +# CONFIG_MTD_SPI_NOR_INTEL is not set +# CONFIG_MTD_SPI_NOR_ISSI is not set +CONFIG_MTD_SPI_NOR_MACRONIX=y +CONFIG_MTD_SPI_NOR_MISC=y +# CONFIG_MTD_SPI_NOR_NORMEM is not set +# CONFIG_MTD_SPI_NOR_PUYA is not set +# CONFIG_MTD_SPI_NOR_SPANSION is not set +# CONFIG_MTD_SPI_NOR_SST is not set +# CONFIG_MTD_SPI_NOR_STMICRO is not set +# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set +CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y +# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MTD_SPI_NOR_WINBOND=y +# CONFIG_MTD_SPI_NOR_XILINX is not set +# CONFIG_MTD_SPI_NOR_XMC is not set +# CONFIG_MTD_SPI_NOR_XTX is not set +# CONFIG_MTD_SST25L is not set +CONFIG_NET_VENDOR_ADI=y +# CONFIG_PI433 is not set +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y +# CONFIG_QCA7000_SPI is not set +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_GZIP is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +CONFIG_RD_XZ=y +# CONFIG_RD_ZSTD is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE is not set +# CONFIG_SDIO_UART is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SGL_ALLOC=y +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AMD is not set +# CONFIG_SPI_AX88796C is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_CADENCE_XSPI is not set +# CONFIG_SPI_DEBUG is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +# CONFIG_SPI_MICROCHIP_CORE is not set +# CONFIG_SPI_MICROCHIP_CORE_QSPI is not set +# CONFIG_SPI_MUX is not set +# CONFIG_SPI_MXIC is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_ROCKCHIP_FLEXBUS_FSPI is not set +# CONFIG_SPI_ROCKCHIP_FLEXBUS_SPI is not set +CONFIG_SPI_ROCKCHIP_SFC=y +# CONFIG_SPI_ROCKCHIP_SLAVE is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SLAVE is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y From b6672f6a2f7377dbab462380093932c7c8f213b8 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 10 Sep 2025 21:40:43 +0800 Subject: [PATCH 05/21] ARM: dts: rockchip: rk3506g-evb1-v10: add rk730 for evb1 And avoid to compiling error: rk3502g-evb1-v10.dtb: ERROR (phandle_references): /rk730-sound: Reference to non-existent node or label "sai_dais" Change-Id: I9ad829c7bc32cc6922ade9a3e3a66cdfa7d4e7fa Signed-off-by: Xing Zheng --- arch/arm/boot/dts/rk3502-evb1-v10.dtsi | 54 ++++++++++++++++++++++++++ arch/arm/boot/dts/rk3506g-evb1-v10.dts | 17 ++++---- 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/rk3502-evb1-v10.dtsi b/arch/arm/boot/dts/rk3502-evb1-v10.dtsi index 69124f896611..035ac72d2ca3 100644 --- a/arch/arm/boot/dts/rk3502-evb1-v10.dtsi +++ b/arch/arm/boot/dts/rk3502-evb1-v10.dtsi @@ -119,6 +119,15 @@ }; }; + sai_dais: sai-dais { + status = "disabled"; + compatible = "rockchip,multi-dais"; + dais = <&sai1>, <&sai4>; + capture,channel-mapping = <2 2>; + playback,channel-mapping = <2 0>; + mclk-fs-mapping = <256 1024>; + }; + es8388_sound: es8388-sound { status = "disabled"; compatible = "rockchip,multicodecs-card"; @@ -143,6 +152,32 @@ pinctrl-0 = <&spk_ctrl>; }; + rk730_sound: rk730-sound { + status = "disabled"; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-rk730"; + /* There is no hp-det and hp-con on evb1 */ + spk-con-gpio = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>; + rockchip,pre-power-on-delay-ms = <30>; + rockchip,post-power-down-delay-ms = <40>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,mclk-fs-mapping = <256 1024>; + rockchip,cpu = <&sai_dais>; + rockchip,codec = <&rk730>, <&audio_codec>; + rockchip,audio-routing = + "Headphone", "LOUT2", + "Headphone", "ROUT2", + "Speaker", "LOUT1", + "Speaker", "ROUT1", + "Headphone", "Headphone Power", + "Headphone", "Headphone Power", + "Speaker", "Speaker Power", + "Speaker", "Speaker Power", + "MIC2", "Main Mic", + "MIC1", "Headset Mic"; + }; + fiq_debugger: fiq-debugger { compatible = "rockchip,fiq-debugger"; rockchip,serial-id = <0>; @@ -318,6 +353,19 @@ pinctrl-names = "default"; pinctrl-0 = <&rm_io8_sai1_mclk>; }; + + rk730: rk730@17 { + status = "disabled"; + #sound-dai-cells = <0>; + compatible = "rockchip,rk730"; + reg = <0x17>; + clocks = <&mclkout_sai1>; + clock-names = "mclk"; + assigned-clocks = <&mclkout_sai1>; + assigned-clock-rates = <12288000>; + pinctrl-names = "default"; + pinctrl-0 = <&sai1_mclk_pins>; + }; }; &mmc { @@ -432,7 +480,12 @@ >; }; +&sai_dais { + status = "okay"; +}; + &sai1 { + rockchip,mclk-no-set; pinctrl-names = "default", "sleep"; pinctrl-0 = <&rm_io9_sai1_sclk &rm_io10_sai1_lrck @@ -446,6 +499,7 @@ &sai4 { status = "okay"; + rockchip,mclk-no-set; }; &saradc { diff --git a/arch/arm/boot/dts/rk3506g-evb1-v10.dts b/arch/arm/boot/dts/rk3506g-evb1-v10.dts index 16ed51342550..e8c309eb63c8 100644 --- a/arch/arm/boot/dts/rk3506g-evb1-v10.dts +++ b/arch/arm/boot/dts/rk3506g-evb1-v10.dts @@ -20,15 +20,6 @@ status = "okay"; }; - sai_dais: sai-dais { - status = "okay"; - compatible = "rockchip,multi-dais"; - dais = <&sai1>, <&sai4>; - capture,channel-mapping = <2 2>; - playback,channel-mapping = <2 0>; - mclk-fs-mapping = <256 1024>; - }; - vcc3v3_lcd_n: vcc3v3-lcd0-n { compatible = "regulator-fixed"; enable-active-high; @@ -123,6 +114,14 @@ }; }; +&rk730 { + status = "okay"; +}; + +&rk730_sound { + status = "okay"; +}; + &route_dsi { status = "okay"; }; From 2f434f8f1fad717ab07d3e0790b7e2f63d290709 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Thu, 11 Sep 2025 12:14:25 +0800 Subject: [PATCH 06/21] ASoC: codecs: rk730: Reduce the log output level to debug Change-Id: Idc8e09773100b9c1265ed4befd98b163fc854c3c Signed-off-by: Xing Zheng --- sound/soc/codecs/rk730.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rk730.c b/sound/soc/codecs/rk730.c index a1423bd196b9..0cc0b517e628 100644 --- a/sound/soc/codecs/rk730.c +++ b/sound/soc/codecs/rk730.c @@ -777,7 +777,7 @@ static int rk730_dai_hw_params(struct snd_pcm_substream *substream, params_rate(params)); return -EINVAL; } - dev_info(component->dev, "%s: Lookup mclk:%d for rate:%d\n", + dev_dbg(component->dev, "%s: Lookup mclk:%d for rate:%d\n", __func__, rk730->sysclk, params_rate(params)); if (clk_set_rate(rk730->mclk, rk730->sysclk) < 0) { @@ -798,7 +798,7 @@ static int rk730_dai_hw_params(struct snd_pcm_substream *substream, params_rate(params), rk730->sysclk); return coeff; } - dev_info(component->dev, "%s:index %d mclk=%d rate=%d\n", + dev_dbg(component->dev, "%s:index %d mclk=%d rate=%d\n", __func__, coeff, coeff_div[coeff].mclk, coeff_div[coeff].rate); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { From 904956c341db735c7d363f9c2d07814f4dcee5a9 Mon Sep 17 00:00:00 2001 From: Zitong Cai Date: Fri, 8 Aug 2025 09:23:20 +0800 Subject: [PATCH 07/21] mfd: display-serdes: Add max96789_select split mode link lock judgment Change-Id: I423c76f6371592d40b0b1d4cb9710d5a256fe3a6 Signed-off-by: Zitong Cai --- .../mfd/display-serdes/maxim/maxim-max96789.c | 43 +++++++++++++++---- .../mfd/display-serdes/maxim/maxim-max96789.h | 4 ++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96789.c b/drivers/mfd/display-serdes/maxim/maxim-max96789.c index a4e6801ebfd2..8d0929b79af3 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96789.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96789.c @@ -691,8 +691,9 @@ static struct serdes_chip_gpio_ops max96789_gpio_ops = { static int max96789_select(struct serdes *serdes, int chan) { - u32 link_cfg, val; - int ret; + int i; + int link_mode = LINKA; + u32 link_cfg, link_status; serdes_set_bits(serdes, 0x0001, DIS_REM_CC, FIELD_PREP(DIS_REM_CC, 0)); @@ -712,6 +713,7 @@ static int max96789_select(struct serdes *serdes, int chan) FIELD_PREP(RESET_ONESHOT, 1) | FIELD_PREP(AUTO_LINK, 0) | FIELD_PREP(LINK_CFG, DUAL_LINK)); + link_mode = DUAL_LINK; SERDES_DBG_CHIP("%s: change to use dual link\n", __func__); } else if (chan == 1 && (link_cfg & LINK_CFG) != LINKA) { serdes_set_bits(serdes, 0x0004, @@ -723,6 +725,7 @@ static int max96789_select(struct serdes *serdes, int chan) FIELD_PREP(RESET_ONESHOT, 1) | FIELD_PREP(AUTO_LINK, 0) | FIELD_PREP(LINK_CFG, LINKA)); + link_mode = LINKA; SERDES_DBG_CHIP("%s: change to use linkA\n", __func__); } else if (chan == 2 && (link_cfg & LINK_CFG) != LINKB) { serdes_set_bits(serdes, 0x0004, @@ -734,6 +737,7 @@ static int max96789_select(struct serdes *serdes, int chan) FIELD_PREP(RESET_ONESHOT, 1) | FIELD_PREP(AUTO_LINK, 0) | FIELD_PREP(LINK_CFG, LINKB)); + link_mode = LINKB; SERDES_DBG_CHIP("%s: change to use linkB\n", __func__); } else if (chan == 3 && (link_cfg & LINK_CFG) != SPLITTER_MODE) { serdes_set_bits(serdes, 0x0004, @@ -745,17 +749,40 @@ static int max96789_select(struct serdes *serdes, int chan) FIELD_PREP(RESET_ONESHOT, 1) | FIELD_PREP(AUTO_LINK, 0) | FIELD_PREP(LINK_CFG, SPLITTER_MODE)); + link_mode = SPLITTER_MODE; SERDES_DBG_CHIP("%s: change to use split mode\n", __func__); } - ret = regmap_read_poll_timeout(serdes->regmap, 0x0013, val, - val & LOCKED, 100, - 50 * USEC_PER_MSEC); - if (ret < 0) { - dev_err(serdes->dev, "GMSL2 link lock timeout\n"); - return ret; + for (i = 0; i < 50; i++) { + serdes_reg_read(serdes, 0x001f, &link_status); + switch (link_mode) { + case DUAL_LINK: + case SPLITTER_MODE: + if ((link_status & LINKA_LOCKED) && + (link_status & LINKB_LOCKED)) + goto out; + break; + case LINKA: + if (link_status & LINKA_LOCKED) + goto out; + break; + case LINKB: + if (link_status & LINKB_LOCKED) + goto out; + break; + } + + mdelay(5); } +out: + if (i > 49) + dev_info(serdes->dev, "link lock timeout, mode=%d val=0x%x\n", + link_mode, link_status); + else + dev_info(serdes->dev, "link locked, mode=%d, val=0x%x\n", + link_mode, link_status); + return 0; } diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96789.h b/drivers/mfd/display-serdes/maxim/maxim-max96789.h index e1bea119b0a7..b791fc46bd87 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96789.h +++ b/drivers/mfd/display-serdes/maxim/maxim-max96789.h @@ -72,6 +72,10 @@ #define LINK_MODE GENMASK(5, 4) #define LOCKED BIT(3) +/* 001fh */ +#define LINKA_LOCKED BIT(3) +#define LINKB_LOCKED BIT(4) + /* 0026h */ #define LF_1 GENMASK(6, 4) #define LF_0 GENMASK(2, 0) From 1a0a9f94511c89abf9f8f8f7753d28e393ccc62c Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Wed, 3 Sep 2025 14:40:05 +0800 Subject: [PATCH 08/21] clk: rockchip: rv1126b: fix aclk_core use div2 Change-Id: If920a41b4663a46ad6bd83c9c0fb07adb4972e74 Signed-off-by: Elaine Zhang --- drivers/clk/rockchip/clk-rv1126b.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/clk/rockchip/clk-rv1126b.c b/drivers/clk/rockchip/clk-rv1126b.c index f90b8963e127..ba3f74a76bcd 100644 --- a/drivers/clk/rockchip/clk-rv1126b.c +++ b/drivers/clk/rockchip/clk-rv1126b.c @@ -69,15 +69,17 @@ static struct rockchip_pll_rate_table rv1126b_pll_rates[] = { } static struct rockchip_cpuclk_rate_table rv1126b_cpuclk_rates[] __initdata = { - RV1126B_CPUCLK_RATE(1900000000, 5, 12), - RV1126B_CPUCLK_RATE(1850000000, 5, 12), - RV1126B_CPUCLK_RATE(1800000000, 5, 12), - RV1126B_CPUCLK_RATE(1608000000, 4, 10), - RV1126B_CPUCLK_RATE(1512000000, 4, 10), - RV1126B_CPUCLK_RATE(1416000000, 4, 10), - RV1126B_CPUCLK_RATE(1296000000, 3, 10), - RV1126B_CPUCLK_RATE(1200000000, 3, 10), - RV1126B_CPUCLK_RATE(1188000000, 3, 8), + RV1126B_CPUCLK_RATE(1900000000, 2, 12), + RV1126B_CPUCLK_RATE(1850000000, 2, 12), + RV1126B_CPUCLK_RATE(1800000000, 2, 12), + RV1126B_CPUCLK_RATE(1750000000, 2, 12), + RV1126B_CPUCLK_RATE(1700000000, 2, 12), + RV1126B_CPUCLK_RATE(1608000000, 2, 10), + RV1126B_CPUCLK_RATE(1512000000, 2, 10), + RV1126B_CPUCLK_RATE(1416000000, 2, 10), + RV1126B_CPUCLK_RATE(1296000000, 2, 10), + RV1126B_CPUCLK_RATE(1200000000, 2, 10), + RV1126B_CPUCLK_RATE(1188000000, 2, 8), RV1126B_CPUCLK_RATE(1104000000, 2, 8), RV1126B_CPUCLK_RATE(1008000000, 2, 8), RV1126B_CPUCLK_RATE(816000000, 2, 6), From 7c05575673ac43b2c3f241e06f5a0311a1b0a01c Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Mon, 25 Aug 2025 16:23:57 +0800 Subject: [PATCH 09/21] clk: rockchip: clk-pvtpll: rv1126bj: add pvtpll table for cpu/npu Change-Id: I958a938f919e7ccb3f01ccef331dff5325d26e9f Signed-off-by: Liang Chen --- drivers/clk/rockchip/clk-pvtpll.c | 36 ++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-pvtpll.c b/drivers/clk/rockchip/clk-pvtpll.c index 5850d7e60fc5..f0353ecaaabf 100644 --- a/drivers/clk/rockchip/clk-pvtpll.c +++ b/drivers/clk/rockchip/clk-pvtpll.c @@ -160,7 +160,8 @@ static struct pvtpll_table rv1126b_core_pvtpll_table[] = { ROCKCHIP_PVTPLL_VOLT_SEL(1900000000, 0, 30, 7), ROCKCHIP_PVTPLL_VOLT_SEL(1850000000, 0, 30, 7), ROCKCHIP_PVTPLL_VOLT_SEL(1800000000, 0, 30, 7), - ROCKCHIP_PVTPLL_VOLT_SEL(1700000000, 0, 30, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1750000000, 0, 30, 6), + ROCKCHIP_PVTPLL_VOLT_SEL(1700000000, 0, 30, 6), ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 30, 5), ROCKCHIP_PVTPLL_VOLT_SEL(1512000000, 0, 30, 3), ROCKCHIP_PVTPLL_VOLT_SEL(1416000000, 0, 34, 3), @@ -170,6 +171,22 @@ static struct pvtpll_table rv1126b_core_pvtpll_table[] = { ROCKCHIP_PVTPLL_VOLT_SEL(816000000, 0, 84, 3), }; +static struct pvtpll_table rv1126bj_core_pvtpll_table[] = { + /* rate_hz, ring_sel, length */ + ROCKCHIP_PVTPLL_VOLT_SEL(1900000000, 0, 30, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1850000000, 0, 30, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1800000000, 0, 30, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1750000000, 0, 30, 6), + ROCKCHIP_PVTPLL_VOLT_SEL(1700000000, 0, 30, 6), + ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 30, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(1512000000, 0, 30, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(1416000000, 0, 34, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(1296000000, 0, 38, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(1200000000, 0, 38, 3), + ROCKCHIP_PVTPLL_VOLT_SEL(1008000000, 0, 56, 1), + ROCKCHIP_PVTPLL_VOLT_SEL(816000000, 0, 92, 1), +}; + static struct pvtpll_table rv1126b_enc_pvtpll_table[] = { /* rate_hz, ring_se, length */ ROCKCHIP_PVTPLL(600000000, 0, 80), @@ -200,6 +217,19 @@ static struct pvtpll_table rv1126b_npu_pvtpll_table[] = { ROCKCHIP_PVTPLL_VOLT_SEL(510000000, 0, 108, 3), }; +static struct pvtpll_table rv1126bj_npu_pvtpll_table[] = { + /* rate_hz, ring_se, length, volt_sel_thr */ + ROCKCHIP_PVTPLL_VOLT_SEL(1100000000, 0, 12, 6), + ROCKCHIP_PVTPLL_VOLT_SEL(1050000000, 0, 12, 6), + ROCKCHIP_PVTPLL_VOLT_SEL(1000000000, 0, 12, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(950000000, 0, 12, 3), + ROCKCHIP_PVTPLL_VOLT_SEL(900000000, 0, 14, 2), + ROCKCHIP_PVTPLL_VOLT_SEL(800000000, 0, 18, 2), + ROCKCHIP_PVTPLL_VOLT_SEL(700000000, 0, 36, 1), + ROCKCHIP_PVTPLL_VOLT_SEL(600000000, 0, 68, 1), + ROCKCHIP_PVTPLL_VOLT_SEL(510000000, 0, 116, 1), +}; + static struct pvtpll_table rk3506_core_pvtpll_table[] = { /* rate_hz, ring_sel, length, volt_sel_thr */ ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 6, 7), @@ -734,6 +764,8 @@ static const struct rockchip_clock_pvtpll_info rv1126b_core_pvtpll_data = { .config = rv1126b_pvtpll_configs, .table_size = ARRAY_SIZE(rv1126b_core_pvtpll_table), .table = rv1126b_core_pvtpll_table, + .jm_table_size = ARRAY_SIZE(rv1126bj_core_pvtpll_table), + .jm_table = rv1126bj_core_pvtpll_table, .pvtpll_adjust_factor = 4, .pvtpll_volt_sel_adjust = pvtpll_volt_sel_adjust_linear, .mode_offset = 0x30300, @@ -767,6 +799,8 @@ static const struct rockchip_clock_pvtpll_info rv1126b_npu_pvtpll_data = { .config = rv1126b_pvtpll_configs, .table_size = ARRAY_SIZE(rv1126b_npu_pvtpll_table), .table = rv1126b_npu_pvtpll_table, + .jm_table_size = ARRAY_SIZE(rv1126bj_npu_pvtpll_table), + .jm_table = rv1126bj_npu_pvtpll_table, .pvtpll_adjust_factor = 6, .pvtpll_volt_sel_adjust = pvtpll_volt_sel_adjust_linear, .mode_offset = 0x90300, From 25910335e775564ca1cf88ec0c56d605b16142d6 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Mon, 25 Aug 2025 16:34:25 +0800 Subject: [PATCH 10/21] arm64: dts: rockchip: rv1126bj: add opp-table for cpu/npu Change-Id: I88861dc0c8a223026b9b480a5219c903c0044db4 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/rv1126b.dtsi | 155 ++++++++++++++++++++-- 1 file changed, 144 insertions(+), 11 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index 84b8db03c024..6b78afcd7d28 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -205,8 +205,8 @@ clock-output-names = "clk_core_pvtpll"; assigned-clocks = <&pvtpll_core>; assigned-clock-rates = <1200000000>; - nvmem-cells = <&cpu_opp_info>; - nvmem-cell-names = "opp-info"; + nvmem-cells = <&cpu_opp_info>, <&specification_serial_number>; + nvmem-cell-names = "opp-info", "specification_serial_number"; }; pvtpll_isp: pvtpll-isp@21c60000 { @@ -247,8 +247,8 @@ clock-output-names = "clk_npu_pvtpll"; assigned-clocks = <&pvtpll_npu>; assigned-clock-rates = <800000000>; - nvmem-cells = <&npu_opp_info>; - nvmem-cell-names = "opp-info"; + nvmem-cells = <&npu_opp_info>, <&specification_serial_number>; + nvmem-cell-names = "opp-info", "specification_serial_number"; }; }; @@ -317,6 +317,7 @@ nvmem-cell-names = "leakage", "opp-info", "mbist-vmin", "pvtm", "specification_serial_number"; + rockchip,supported-hw; rockchip,pvtm-voltage-sel = < 0 1669 0 1670 1714 1 @@ -342,6 +343,7 @@ rockchip,low-temp-min-volt = <950000>; opp-594000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <594000000>; opp-microvolt = <850000 850000 1100000>; opp-microvolt-L0 = <900000 900000 1100000>; @@ -351,6 +353,7 @@ }; opp-816000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <816000000>; opp-microvolt = <850000 850000 1100000>; opp-microvolt-L0 = <900000 900000 1100000>; @@ -358,6 +361,7 @@ clock-latency-ns = <40000>; }; opp-1008000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1008000000>; opp-microvolt = <850000 850000 1100000>; opp-microvolt-L0 = <900000 900000 1100000>; @@ -365,6 +369,7 @@ clock-latency-ns = <40000>; }; opp-1200000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1200000000>; opp-microvolt = <900000 900000 1100000>; opp-microvolt-L0 = <950000 950000 1100000>; @@ -372,6 +377,7 @@ clock-latency-ns = <40000>; }; opp-1296000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1296000000>; opp-microvolt = <950000 950000 1100000>; opp-microvolt-L0 = <1000000 1000000 1100000>; @@ -379,6 +385,7 @@ clock-latency-ns = <40000>; }; opp-1416000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1416000000>; opp-microvolt = <975000 975000 1100000>; opp-microvolt-L0 = <1025000 1025000 1100000>; @@ -386,6 +393,7 @@ clock-latency-ns = <40000>; }; opp-1512000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1512000000>; opp-microvolt = <1000000 1000000 1100000>; opp-microvolt-L0 = <1050000 1050000 1100000>; @@ -393,6 +401,7 @@ clock-latency-ns = <40000>; }; opp-1608000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1608000000>; opp-microvolt = <1000000 1000000 1100000>; opp-microvolt-L0 = <1100000 1100000 1100000>; @@ -401,6 +410,88 @@ opp-microvolt-L3 = <1025000 1025000 1100000>; clock-latency-ns = <40000>; }; + + /* RV1126BJ cpu OPPs */ + opp-j-594000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <594000000>; + opp-microvolt = <900000 900000 1100000>; + clock-latency-ns = <40000>; + opp-suspend; + }; + opp-j-816000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <816000000>; + opp-microvolt = <900000 900000 1100000>; + clock-latency-ns = <40000>; + }; + opp-j-1008000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1008000000>; + opp-microvolt = <900000 900000 1100000>; + clock-latency-ns = <40000>; + }; + opp-j-1200000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <900000 900000 1100000>; + clock-latency-ns = <40000>; + }; + opp-j-1296000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1296000000>; + opp-microvolt = <900000 900000 1100000>; + clock-latency-ns = <40000>; + }; + /* + * The Max frequency is 1296MHz in default normal mode. + * The Max frequency is 1750MHz in overdrive mode, + * but under the overdrive mode for a long time, + * the chipset may shorten the lifetime, especially in high + * temperature condition. Disable overdrive opps by default + * and you can enable them in dts file. + */ + cpu_opp_j_od_1416000000: opp-j-od-1416000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <925000 925000 1100000>; + opp-microvolt-L0 = <9750000 9750000 1100000>; + opp-microvolt-L1 = <950000 950000 1100000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; + cpu_opp_j_od_1512000000: opp-j-od-1512000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <950000 950000 1100000>; + opp-microvolt-L0 = <1000000 1000000 1100000>; + opp-microvolt-L1 = <975000 975000 1100000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; + cpu_opp_j_od_1608000000: opp-j-od-1608000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <1000000 1000000 1100000>; + opp-microvolt-L0 = <1100000 1100000 1100000>; + opp-microvolt-L1 = <1075000 1075000 1100000>; + opp-microvolt-L2 = <1050000 1050000 1100000>; + opp-microvolt-L3 = <1025000 1025000 1100000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; + cpu_opp_j_od_1750000000: opp-j-od-1750000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1750000000>; + opp-microvolt = <1100000 1100000 1100000>; + opp-microvolt-L4 = <1075000 1075000 1100000>; + opp-microvolt-L5 = <1050000 1050000 1100000>; + opp-microvolt-L6 = <1050000 1050000 1100000>; + opp-microvolt-L7 = <1050000 1050000 1100000>; + opp-microvolt-L8 = <1050000 1050000 1100000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; }; cpuinfo { @@ -3422,51 +3513,93 @@ rockchip,low-temp-min-volt = <950000>; opp-396000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <396000000>; opp-microvolt = <850000 850000 1050000>; opp-microvolt-L0 = <900000 900000 1050000>; opp-microvolt-L1 = <875000 875000 1050000>; }; opp-510000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <510000000>; opp-microvolt = <850000 850000 1050000>; opp-microvolt-L0 = <900000 900000 1050000>; opp-microvolt-L1 = <875000 875000 1050000>; }; opp-600000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <600000000>; opp-microvolt = <850000 850000 1050000>; opp-microvolt-L0 = <900000 900000 1050000>; opp-microvolt-L1 = <875000 875000 1050000>; }; opp-700000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <700000000>; opp-microvolt = <850000 850000 1050000>; opp-microvolt-L0 = <900000 900000 1050000>; opp-microvolt-L1 = <875000 875000 1050000>; }; opp-800000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <800000000>; opp-microvolt = <900000 900000 1050000>; }; opp-900000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <900000000>; opp-microvolt = <950000 950000 1050000>; opp-microvolt-L0 = <975000 975000 1050000>; }; opp-950000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <950000000>; opp-microvolt = <950000 950000 1050000>; opp-microvolt-L0 = <1000000 1000000 1050000>; opp-microvolt-L1 = <975000 975000 1050000>; }; + + /* RV1126BJ npu OPPs */ + opp-j-396000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <396000000>; + opp-microvolt = <900000 900000 1050000>; + }; + opp-j-510000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <510000000>; + opp-microvolt = <900000 900000 1050000>; + }; + opp-j-600000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <900000 900000 1050000>; + }; + opp-j-700000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <700000000>; + opp-microvolt = <900000 900000 1050000>; + }; + opp-j-800000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <900000 900000 1050000>; + }; + /* The Max frequency is 800MHz in default normal mode. + * The Max frequency is 950MHz in overdrive mode, + * but under the overdrive mode for a long time, + * the chipset may shorten the lifetime, especially in high + * temperature condition. Disable overdrive opps by default + * and you can enable them in dts file. + */ + npu_opp_j_od_950000000: opp-j-od-950000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <950000000>; + opp-microvolt = <950000 950000 1050000>; + opp-microvolt-L0 = <1000000 1000000 1050000>; + opp-microvolt-L1 = <975000 975000 1050000>; + status = "disabled"; + }; }; rknpu_mmu: iommu@22002000 { From d4f0968254a26161d396f3b451dc84347089f619 Mon Sep 17 00:00:00 2001 From: Zou Dengming Date: Tue, 3 Dec 2024 21:10:45 +0800 Subject: [PATCH 11/21] ASoC: rockchip: spdifrx: support 32bit Change-Id: I51fcef56456449c7e98a68b3aaa37823c8016ff3 Signed-off-by: Zou Dengming --- sound/soc/rockchip/rockchip_spdifrx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/rockchip/rockchip_spdifrx.c b/sound/soc/rockchip/rockchip_spdifrx.c index baa9df6dff7a..ba151cda97e7 100644 --- a/sound/soc/rockchip/rockchip_spdifrx.c +++ b/sound/soc/rockchip/rockchip_spdifrx.c @@ -156,7 +156,8 @@ static struct snd_soc_dai_driver rk_spdifrx_dai = { SNDRV_PCM_RATE_192000), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE), + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), }, .ops = &rk_spdifrx_dai_ops, }; From bb3fd4709b1f9a31de0d7c31856f6123c0471212 Mon Sep 17 00:00:00 2001 From: Zhong Shengquan Date: Fri, 27 Dec 2024 17:31:02 +0800 Subject: [PATCH 12/21] ASoC: rockchip: spdifrx: Add sample rate estimation feature Obtain the transmitter's sample rate through channel status bits, and use the CDRST register and MCLK to estimate the sample rate. Notify sync and sample rate information through controls.The control names are "RK SPDIFRX SYNC STATUS" and "RK SPDIFRX SAMPLE RATE". The application layer needs to monitor the controls and read the control values to obtain the information. For the sync control, 0 indicates an unlocked state, and 1 indicates a locked state. The sample rate control has two values, the first represents the sample rate obtained from the channel status, and the second represents the estimated sample rate. Change-Id: Ie3b4f009c55d326c4517996efa46e6e2e31c7d65 Signed-off-by: Zhong Shengquan --- sound/soc/rockchip/rockchip_spdifrx.c | 190 ++++++++++++++++++++++++-- sound/soc/rockchip/rockchip_spdifrx.h | 7 +- 2 files changed, 183 insertions(+), 14 deletions(-) diff --git a/sound/soc/rockchip/rockchip_spdifrx.c b/sound/soc/rockchip/rockchip_spdifrx.c index ba151cda97e7..e95e85243767 100644 --- a/sound/soc/rockchip/rockchip_spdifrx.c +++ b/sound/soc/rockchip/rockchip_spdifrx.c @@ -14,11 +14,18 @@ #include #include #include +#include #include #include #include "rockchip_spdifrx.h" +struct rk_spdifrx_info { + int sync; + unsigned int sample_rate_src; + unsigned int sample_rate_cal; +}; + struct rk_spdifrx_dev { struct device *dev; struct clk *mclk; @@ -26,7 +33,10 @@ struct rk_spdifrx_dev { struct snd_dmaengine_dai_dma_data capture_dma_data; struct regmap *regmap; struct reset_control *reset; + struct rk_spdifrx_info info; + struct snd_soc_dai *dai; int irq; + bool cdr_count_avg; }; static int rk_spdifrx_runtime_suspend(struct device *dev) @@ -67,14 +77,22 @@ static int rk_spdifrx_hw_params(struct snd_pcm_substream *substream, regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, SPDIFRX_INTEN_SYNCIE_MASK | - SPDIFRX_INTEN_NSYNCIE_MASK, + SPDIFRX_INTEN_NSYNCIE_MASK | + SPDIFRX_INTEN_BTEIE_MASK, SPDIFRX_INTEN_SYNCIE_EN | - SPDIFRX_INTEN_NSYNCIE_EN); + SPDIFRX_INTEN_NSYNCIE_EN | + SPDIFRX_INTEN_BTEIE_EN); regmap_update_bits(spdifrx->regmap, SPDIFRX_DMACR, SPDIFRX_DMACR_RDL_MASK, SPDIFRX_DMACR_RDL(8)); regmap_update_bits(spdifrx->regmap, SPDIFRX_CDR, SPDIFRX_CDR_AVGSEL_MASK | SPDIFRX_CDR_BYPASS_MASK, SPDIFRX_CDR_AVGSEL_MIN | SPDIFRX_CDR_BYPASS_DIS); + + if (params_rate(params) >= 32000) + spdifrx->cdr_count_avg = true; + else + spdifrx->cdr_count_avg = false; + return 0; } @@ -129,11 +147,76 @@ static int rk_spdifrx_trigger(struct snd_pcm_substream *substream, return ret; } +static int rk_spdifrx_sync_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct rk_spdifrx_dev *spdifrx = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.integer.value[0] = spdifrx->info.sync; + return 0; +} + +static int rk_spdifrx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct rk_spdifrx_dev *spdifrx = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.integer.value[0] = spdifrx->info.sample_rate_src; + ucontrol->value.integer.value[1] = spdifrx->info.sample_rate_cal; + return 0; +} + +static int rk_spdifrx_sync_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + + return 0; +} + +static int rk_spdifrx_sample_rate_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xffffffff; + + return 0; +} + +static struct snd_kcontrol_new rk_spdifrx_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "RK SPDIFRX SYNC STATUS", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = rk_spdifrx_sync_info, + .get = rk_spdifrx_sync_get, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "RK SPDIFRX SAMPLE RATE", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = rk_spdifrx_sample_rate_info, + .get = rk_spdifrx_sample_rate_get, + }, +}; + static int rk_spdifrx_dai_probe(struct snd_soc_dai *dai) { struct rk_spdifrx_dev *spdifrx = snd_soc_dai_get_drvdata(dai); dai->capture_dma_data = &spdifrx->capture_dma_data; + spdifrx->dai = dai; + snd_soc_add_dai_controls(dai, rk_spdifrx_controls, + ARRAY_SIZE(rk_spdifrx_controls)); return 0; } @@ -149,11 +232,7 @@ static struct snd_soc_dai_driver rk_spdifrx_dai = { .stream_name = "Capture", .channels_min = 2, .channels_max = 2, - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000), + .rates = SNDRV_PCM_RATE_8000_192000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -181,6 +260,7 @@ static bool rk_spdifrx_wr_reg(struct device *dev, unsigned int reg) case SPDIFRX_INTSR: case SPDIFRX_INTCLR: case SPDIFRX_SMPDR: + case SPDIFRX_CHNSR1: case SPDIFRX_BURSTINFO: return true; default: @@ -202,6 +282,7 @@ static bool rk_spdifrx_rd_reg(struct device *dev, unsigned int reg) case SPDIFRX_INTSR: case SPDIFRX_INTCLR: case SPDIFRX_SMPDR: + case SPDIFRX_CHNSR1: case SPDIFRX_BURSTINFO: return true; default: @@ -219,6 +300,7 @@ static bool rk_spdifrx_volatile_reg(struct device *dev, unsigned int reg) case SPDIFRX_INTSR: case SPDIFRX_INTCLR: case SPDIFRX_SMPDR: + case SPDIFRX_CHNSR1: case SPDIFRX_BURSTINFO: return true; default: @@ -248,23 +330,107 @@ static const struct regmap_config rk_spdifrx_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static unsigned int rk_spdifrx_get_sample_rate(unsigned int flag) +{ + unsigned int rate = 0; + + switch (flag) { + case IEC958_AES3_CON_FS_22050: + rate = 22050; + break; + case IEC958_AES3_CON_FS_24000: + rate = 24000; + break; + case IEC958_AES3_CON_FS_32000: + rate = 32000; + break; + case IEC958_AES3_CON_FS_44100: + rate = 44100; + break; + case IEC958_AES3_CON_FS_48000: + rate = 48000; + break; + case IEC958_AES3_CON_FS_88200: + rate = 88200; + break; + case IEC958_AES3_CON_FS_96000: + rate = 96000; + break; + case IEC958_AES3_CON_FS_176400: + rate = 176400; + break; + case IEC958_AES3_CON_FS_192000: + rate = 192000; + break; + case IEC958_AES3_CON_FS_768000: + rate = 768000; + break; + default: + return 0; + } + + return rate; +} + static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) { struct rk_spdifrx_dev *spdifrx = dev_id; + struct snd_soc_dai *dai = spdifrx->dai; + struct snd_kcontrol *sync_kctl = snd_soc_card_get_kcontrol(dai->component->card, + "RK SPDIFRX SYNC STATUS"); + struct snd_kcontrol *sample_kctl = snd_soc_card_get_kcontrol(dai->component->card, + "RK SPDIFRX SAMPLE RATE"); u32 intsr; + u32 val; + u32 count; + + if (pm_runtime_resume_and_get(spdifrx->dev) < 0) + return IRQ_NONE; regmap_read(spdifrx->regmap, SPDIFRX_INTSR, &intsr); - if (intsr & BIT(7)) { + if (intsr & SPDIFRX_INTSR_NSYNCISR_ACTIVE) { + spdifrx->info.sync = 0; + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &sync_kctl->id); dev_dbg(spdifrx->dev, "NSYNC\n"); - regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, BIT(7)); + regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_NSYNCICLR); } - if (intsr & BIT(9)) { - dev_dbg(spdifrx->dev, "SYNC\n"); - regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, BIT(9)); + if (intsr & SPDIFRX_INTSR_BTEISR_ACTIVE) { + regmap_read(spdifrx->regmap, SPDIFRX_CHNSR1, &val); + spdifrx->info.sample_rate_src = + rk_spdifrx_get_sample_rate((val & SPDIFRX_CHNSR1_SAMPLE_RATE_MASK) >> 8); + + regmap_read(spdifrx->regmap, SPDIFRX_CDRST, &val); + if (spdifrx->cdr_count_avg) + count = ((val & SPDIFRX_CDRST_MINCNT_MASK) + + ((val & SPDIFRX_CDRST_MAXCNT_MASK) >> 8)) / 4; + else + count = val & SPDIFRX_CDRST_MINCNT_MASK; + spdifrx->info.sample_rate_cal = clk_get_rate(spdifrx->mclk) / (count * 128); + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &sample_kctl->id); + + dev_dbg(spdifrx->dev, "src sample rate: %u Hz\n", spdifrx->info.sample_rate_src); + dev_dbg(spdifrx->dev, "cal sample rate: %u Hz\n", spdifrx->info.sample_rate_cal); + dev_dbg(spdifrx->dev, "BTEIE\n"); + + regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_BTECLR); + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, SPDIFRX_INTEN_BTEIE_MASK, + SPDIFRX_INTEN_BTEIE_DIS); } + if (intsr & SPDIFRX_INTSR_SYNCISR_ACTIVE) { + spdifrx->info.sync = 1; + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &sync_kctl->id); + dev_dbg(spdifrx->dev, "SYNC\n"); + regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_SYNCICLR); + } + + pm_runtime_put(spdifrx->dev); + return IRQ_HANDLED; } diff --git a/sound/soc/rockchip/rockchip_spdifrx.h b/sound/soc/rockchip/rockchip_spdifrx.h index e75b2d5afd04..ee9f4c78f040 100644 --- a/sound/soc/rockchip/rockchip_spdifrx.h +++ b/sound/soc/rockchip/rockchip_spdifrx.h @@ -81,10 +81,13 @@ #define SPDIFRX_INTCLR_SYNCICLR_MASK BIT(9) #define SPDIFRX_INTCLR_SYNCICLR BIT(9) #define SPDIFRX_INTCLR_BTECLR_MASK BIT(8) -#define SPDIFRX_INTCLR_BIECLR BIT(8) +#define SPDIFRX_INTCLR_BTECLR BIT(8) #define SPDIFRX_INTCLR_NSYNCICLR_MASK BIT(7) #define SPDIFRX_INTCLR_NSYNCICLR BIT(7) +/* SPDIFRX_CHNSRN */ +#define SPDIFRX_CHNSR1_SAMPLE_RATE_MASK GENMASK(11, 8) + /* BURSTINFO */ #define SPDIFRX_BURSTINFO_PD_MASK GENMASK(31, 16) #define SPDIFRX_BURSTINFO_BSNUM_MASK GENMASK(15, 13) @@ -107,7 +110,7 @@ #define SPDIFRX_INTCLR (0x0028) #define SPDIFRX_SMPDR (0x002C) #define SPDIFRX_USRDRN (0x0030) -#define SPDIFRX_CHNSRN (0x0060) +#define SPDIFRX_CHNSR1 (0x0064) #define SPDIFRX_BURSTINFO (0x0100) #endif /* _ROCKCHIP_SPDIFRX_H */ From eae70e5ad3cfbe074db7893b945091d3dea724b3 Mon Sep 17 00:00:00 2001 From: Zhong Shengquan Date: Tue, 18 Feb 2025 16:25:26 +0800 Subject: [PATCH 13/21] ASoC: rockchip: spdifrx: Update the dynamic detection feature Add a debounce timer to prevent continuous reporting of SYNC/NSYNC information during plug-in and unplug operations. Add the capability to detect non-linear pcm data and sample bit width, then notify the application layer of the results. Add a fifo timer to detect real-time data inflow in the rx fifo, supporting glitch-free sampling rate transitions. Add a configuration option for the always-on clock feature. Change-Id: Ifb7bd55e9eefb6e07d00e16de12abff43d7e4d4e Signed-off-by: Zhong Shengquan --- sound/soc/rockchip/rockchip_spdifrx.c | 506 ++++++++++++++++++++++++-- sound/soc/rockchip/rockchip_spdifrx.h | 44 ++- 2 files changed, 523 insertions(+), 27 deletions(-) diff --git a/sound/soc/rockchip/rockchip_spdifrx.c b/sound/soc/rockchip/rockchip_spdifrx.c index e95e85243767..066de3a388c0 100644 --- a/sound/soc/rockchip/rockchip_spdifrx.c +++ b/sound/soc/rockchip/rockchip_spdifrx.c @@ -6,24 +6,35 @@ * */ -#include -#include -#include #include -#include +#include +#include #include +#include +#include +#include #include #include +#include #include -#include #include +#include #include "rockchip_spdifrx.h" +#define QUIRK_ALWAYS_ON BIT(0) + struct rk_spdifrx_info { int sync; + int debounce_time_ms; + int liner_pcm; + int liner_pcm_last; unsigned int sample_rate_src; unsigned int sample_rate_cal; + unsigned int sample_rate_src_last; + unsigned int sample_rate_cal_last; + unsigned int sample_width; /* valid width */ + unsigned int sample_width_last; }; struct rk_spdifrx_dev { @@ -35,8 +46,23 @@ struct rk_spdifrx_dev { struct reset_control *reset; struct rk_spdifrx_info info; struct snd_soc_dai *dai; + struct timer_list debounce_timer; + struct timer_list non_liner_timer; + struct timer_list fifo_timer; + unsigned int mclk_rate; int irq; bool cdr_count_avg; + bool need_reset; +}; + +static const struct spdifrx_of_quirks { + char *quirk; + int id; +} of_quirks[] = { + { + .quirk = "rockchip,always-on", + .id = QUIRK_ALWAYS_ON, + }, }; static int rk_spdifrx_runtime_suspend(struct device *dev) @@ -78,17 +104,33 @@ static int rk_spdifrx_hw_params(struct snd_pcm_substream *substream, regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, SPDIFRX_INTEN_SYNCIE_MASK | SPDIFRX_INTEN_NSYNCIE_MASK | - SPDIFRX_INTEN_BTEIE_MASK, + SPDIFRX_INTEN_BTEIE_MASK | + SPDIFRX_INTEN_NPSPIE_MASK | + SPDIFRX_INTEN_BMDEIE_MASK | + SPDIFRX_INTEN_PEIE_MASK | + SPDIFRX_INTEN_CSCIE_MASK | + SPDIFRX_INTEN_NVLDIE_MASK, SPDIFRX_INTEN_SYNCIE_EN | SPDIFRX_INTEN_NSYNCIE_EN | - SPDIFRX_INTEN_BTEIE_EN); + SPDIFRX_INTEN_BTEIE_EN | + SPDIFRX_INTEN_NPSPIE_EN | + SPDIFRX_INTEN_BMDEIE_EN | + SPDIFRX_INTEN_PEIE_EN | + SPDIFRX_INTEN_CSCIE_EN | + SPDIFRX_INTEN_NVLDIE_EN); regmap_update_bits(spdifrx->regmap, SPDIFRX_DMACR, SPDIFRX_DMACR_RDL_MASK, SPDIFRX_DMACR_RDL(8)); regmap_update_bits(spdifrx->regmap, SPDIFRX_CDR, SPDIFRX_CDR_AVGSEL_MASK | SPDIFRX_CDR_BYPASS_MASK, - SPDIFRX_CDR_AVGSEL_MIN | SPDIFRX_CDR_BYPASS_DIS); + SPDIFRX_CDR_AVGSEL_MIN | SPDIFRX_CDR_BYPASS_EN); - if (params_rate(params) >= 32000) + spdifrx->need_reset = false; + spdifrx->info.sample_rate_cal_last = 0; + spdifrx->info.sample_rate_src_last = 0; + spdifrx->info.sample_width_last = 0; + spdifrx->info.liner_pcm_last = 1; + + if (params_rate(params) >= 44100) spdifrx->cdr_count_avg = true; else spdifrx->cdr_count_avg = false; @@ -147,6 +189,40 @@ static int rk_spdifrx_trigger(struct snd_pcm_substream *substream, return ret; } +static int rk_spdifrx_parse_quirks(struct rk_spdifrx_dev *spdifrx) +{ + int i = 0; + unsigned int quirks = 0; + + for (i = 0; i < ARRAY_SIZE(of_quirks); i++) + if (device_property_read_bool(spdifrx->dev, of_quirks[i].quirk)) + quirks |= of_quirks[i].id; + + if (quirks & QUIRK_ALWAYS_ON) { + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, + SPDIFRX_INTEN_SYNCIE_MASK | + SPDIFRX_INTEN_NSYNCIE_MASK | + SPDIFRX_INTEN_BTEIE_MASK | + SPDIFRX_INTEN_NPSPIE_MASK | + SPDIFRX_INTEN_BMDEIE_MASK | + SPDIFRX_INTEN_PEIE_MASK | + SPDIFRX_INTEN_CSCIE_MASK | + SPDIFRX_INTEN_NVLDIE_MASK, + SPDIFRX_INTEN_SYNCIE_EN | + SPDIFRX_INTEN_NSYNCIE_EN | + SPDIFRX_INTEN_BTEIE_EN | + SPDIFRX_INTEN_NPSPIE_EN | + SPDIFRX_INTEN_BMDEIE_EN | + SPDIFRX_INTEN_PEIE_EN | + SPDIFRX_INTEN_CSCIE_EN | + SPDIFRX_INTEN_NVLDIE_EN); + + pm_runtime_forbid(spdifrx->dev); + } + + return 0; +} + static int rk_spdifrx_sync_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -168,6 +244,46 @@ static int rk_spdifrx_sample_rate_get(struct snd_kcontrol *kcontrol, return 0; } +static int rk_spdifrx_debounce_time_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct rk_spdifrx_dev *spdifrx = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.integer.value[0] = spdifrx->info.debounce_time_ms; + return 0; +} + +static int rk_spdifrx_debounce_time_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct rk_spdifrx_dev *spdifrx = snd_soc_dai_get_drvdata(dai); + + spdifrx->info.debounce_time_ms = ucontrol->value.integer.value[0]; + return 0; +} + +static int rk_spdifrx_sample_width_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct rk_spdifrx_dev *spdifrx = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.integer.value[0] = spdifrx->info.sample_width; + return 0; +} + +static int rk_spdifrx_liner_pcm_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct rk_spdifrx_dev *spdifrx = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.integer.value[0] = spdifrx->info.liner_pcm; + return 0; +} + static int rk_spdifrx_sync_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -190,6 +306,39 @@ static int rk_spdifrx_sample_rate_info(struct snd_kcontrol *kcontrol, return 0; } +static int rk_spdifrx_debounce_time_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1000; + + return 0; +} + +static int rk_spdifrx_sample_width_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 64; + + return 0; +} + +static int rk_spdifrx_liner_pcm_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + + return 0; +} + static struct snd_kcontrol_new rk_spdifrx_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -207,6 +356,29 @@ static struct snd_kcontrol_new rk_spdifrx_controls[] = { .info = rk_spdifrx_sample_rate_info, .get = rk_spdifrx_sample_rate_get, }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "RK SPDIFRX DEBOUNCE TIME", + .info = rk_spdifrx_debounce_time_info, + .get = rk_spdifrx_debounce_time_get, + .put = rk_spdifrx_debounce_time_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "RK SPDIFRX SAMPLE WIDTH", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = rk_spdifrx_sample_width_info, + .get = rk_spdifrx_sample_width_get, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "RK SPDIFRX LINER PCM", + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = rk_spdifrx_liner_pcm_info, + .get = rk_spdifrx_liner_pcm_get, + }, }; static int rk_spdifrx_dai_probe(struct snd_soc_dai *dai) @@ -218,6 +390,8 @@ static int rk_spdifrx_dai_probe(struct snd_soc_dai *dai) snd_soc_add_dai_controls(dai, rk_spdifrx_controls, ARRAY_SIZE(rk_spdifrx_controls)); + rk_spdifrx_parse_quirks(spdifrx); + return 0; } @@ -261,6 +435,7 @@ static bool rk_spdifrx_wr_reg(struct device *dev, unsigned int reg) case SPDIFRX_INTCLR: case SPDIFRX_SMPDR: case SPDIFRX_CHNSR1: + case SPDIFRX_CHNSR2: case SPDIFRX_BURSTINFO: return true; default: @@ -283,6 +458,7 @@ static bool rk_spdifrx_rd_reg(struct device *dev, unsigned int reg) case SPDIFRX_INTCLR: case SPDIFRX_SMPDR: case SPDIFRX_CHNSR1: + case SPDIFRX_CHNSR2: case SPDIFRX_BURSTINFO: return true; default: @@ -301,6 +477,7 @@ static bool rk_spdifrx_volatile_reg(struct device *dev, unsigned int reg) case SPDIFRX_INTCLR: case SPDIFRX_SMPDR: case SPDIFRX_CHNSR1: + case SPDIFRX_CHNSR2: case SPDIFRX_BURSTINFO: return true; default: @@ -330,6 +507,30 @@ static const struct regmap_config rk_spdifrx_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static unsigned int rk_spdifrx_get_sample_width(unsigned int flag) +{ + unsigned int width = 0; + + switch (flag) { + case IEC958_AES4_CON_WORDLEN_20_16: + width = 16; + break; + case IEC958_AES4_CON_WORDLEN_22_18: + width = 18; + break; + case IEC958_AES4_CON_WORDLEN_20_16 | IEC958_AES4_CON_MAX_WORDLEN_24: + width = 20; + break; + case IEC958_AES4_CON_WORDLEN_24_20 | IEC958_AES4_CON_MAX_WORDLEN_24: + width = 24; + break; + default: + return 0; + } + + return width; +} + static unsigned int rk_spdifrx_get_sample_rate(unsigned int flag) { unsigned int rate = 0; @@ -372,14 +573,61 @@ static unsigned int rk_spdifrx_get_sample_rate(unsigned int flag) return rate; } +static unsigned int rk_spdifrx_convert_sample_rate(unsigned int mclk, unsigned int count) +{ + unsigned int rate; + + rate = mclk / (count * 128); + + if (rate >= (8000 + 16000) / 2 && rate < (16000 + 22050) / 2) + return 16000; + + if (rate >= (16000 + 22050) / 2 && rate < (22050 + 24000) / 2) + return 22050; + + if (rate >= (22050 + 24000) / 2 && rate < (24000 + 32000) / 2) + return 24000; + + if (rate >= (24000 + 32000) / 2 && rate < (32000 + 44100) / 2) + return 32000; + + if (rate >= (32000 + 44100) / 2 && rate < (44100 + 48000) / 2) + return 44100; + + if (rate >= (44100 + 48000) / 2 && rate < (48000 + 88200) / 2) + return 48000; + + if (rate >= (48000 + 88200) / 2 && rate < (88200 + 96000) / 2) + return 88200; + + if (rate >= (88200 + 96000) / 2 && rate < (96000 + 192000) / 2) + return 96000; + + if (rate >= (96000 + 176400) / 2 && rate < (176400 + 192000) / 2) + return 176400; + + if (rate >= (176400 + 192000) / 2 && rate < (192000 + 384000) / 2) + return 192000; + + if (rate >= (192000 + 384000) / 2 && rate < (384000 + 768000) / 2) + return 384000; + + if (rate >= (384000 + 768000) / 2) + return 768000; + + return 0; +} + static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) { struct rk_spdifrx_dev *spdifrx = dev_id; struct snd_soc_dai *dai = spdifrx->dai; - struct snd_kcontrol *sync_kctl = snd_soc_card_get_kcontrol(dai->component->card, - "RK SPDIFRX SYNC STATUS"); struct snd_kcontrol *sample_kctl = snd_soc_card_get_kcontrol(dai->component->card, "RK SPDIFRX SAMPLE RATE"); + struct snd_kcontrol *width_kctl = snd_soc_card_get_kcontrol(dai->component->card, + "RK SPDIFRX SAMPLE WIDTH"); + struct snd_kcontrol *liner_pcm_kctl = snd_soc_card_get_kcontrol(dai->component->card, + "RK SPDIFRX LINER PCM"); u32 intsr; u32 val; u32 count; @@ -389,12 +637,60 @@ static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) regmap_read(spdifrx->regmap, SPDIFRX_INTSR, &intsr); + if (intsr & SPDIFRX_INTSR_NVLDISR_ACTIVE) { + dev_dbg(spdifrx->dev, "No Valid Error\n"); + regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_NVLDICLR); + rk_spdifrx_reset(spdifrx); + spdifrx->need_reset = true; + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, + SPDIFRX_INTEN_NVLDIE_MASK, SPDIFRX_INTEN_NVLDIE_DIS); + } + + if (intsr & SPDIFRX_INTSR_CSCISR_ACTIVE) { + dev_dbg(spdifrx->dev, "CSC Changed\n"); + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, + SPDIFRX_INTEN_BTEIE_MASK, SPDIFRX_INTEN_BTEIE_EN); + regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_CSCICLR); + } + + if (intsr & SPDIFRX_INTSR_PEISR_ACTIVE) { + dev_dbg(spdifrx->dev, "Parity Error\n"); + regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_PEICLR); + rk_spdifrx_reset(spdifrx); + spdifrx->need_reset = true; + } + + if (intsr & SPDIFRX_INTSR_NPSPISR_ACTIVE) { + spdifrx->info.liner_pcm = 0; + if (spdifrx->info.liner_pcm != spdifrx->info.liner_pcm_last) { + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &liner_pcm_kctl->id); + spdifrx->info.liner_pcm_last = spdifrx->info.liner_pcm; + dev_dbg(spdifrx->dev, "non liner data\n"); + } + mod_timer(&spdifrx->non_liner_timer, jiffies + msecs_to_jiffies(100)); + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, + SPDIFRX_INTEN_NVLDIE_MASK, SPDIFRX_INTEN_NVLDIE_DIS); + regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_NPSPICLR); + } + + if (intsr & SPDIFRX_INTSR_BMDEISR_ACTIVE) { + dev_dbg(spdifrx->dev, "BMD Error\n"); + regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_BMDEICLR); + rk_spdifrx_reset(spdifrx); + spdifrx->need_reset = true; + } + if (intsr & SPDIFRX_INTSR_NSYNCISR_ACTIVE) { spdifrx->info.sync = 0; - snd_ctl_notify(dai->component->card->snd_card, - SNDRV_CTL_EVENT_MASK_VALUE, &sync_kctl->id); + spdifrx->need_reset = true; + mod_timer(&spdifrx->debounce_timer, jiffies + + msecs_to_jiffies(spdifrx->info.debounce_time_ms)); dev_dbg(spdifrx->dev, "NSYNC\n"); + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, SPDIFRX_INTEN_NSYNCIE_MASK, + SPDIFRX_INTEN_NSYNCIE_DIS); regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_NSYNCICLR); + regmap_write(spdifrx->regmap, SPDIFRX_CLR, 0x1); } if (intsr & SPDIFRX_INTSR_BTEISR_ACTIVE) { @@ -404,28 +700,58 @@ static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) regmap_read(spdifrx->regmap, SPDIFRX_CDRST, &val); if (spdifrx->cdr_count_avg) - count = ((val & SPDIFRX_CDRST_MINCNT_MASK) + - ((val & SPDIFRX_CDRST_MAXCNT_MASK) >> 8)) / 4; + count = ((val & SPDIFRX_CDRST_MINCNT_MASK) + 1 + + ((val & SPDIFRX_CDRST_MAXCNT_MASK) >> 8) + 1) / 4; else - count = val & SPDIFRX_CDRST_MINCNT_MASK; - spdifrx->info.sample_rate_cal = clk_get_rate(spdifrx->mclk) / (count * 128); - snd_ctl_notify(dai->component->card->snd_card, - SNDRV_CTL_EVENT_MASK_VALUE, &sample_kctl->id); + count = (val & SPDIFRX_CDRST_MINCNT_MASK) + 1; + + if (count > 0) + spdifrx->info.sample_rate_cal = + rk_spdifrx_convert_sample_rate(spdifrx->mclk_rate, count); + else + spdifrx->info.sample_rate_cal = 0; + + regmap_read(spdifrx->regmap, SPDIFRX_CHNSR2, &val); + spdifrx->info.sample_width = + rk_spdifrx_get_sample_width(val & SPDIFRX_CHNSR2_SAMPLE_WIDTH_MASK); + + if (spdifrx->info.sample_rate_src != spdifrx->info.sample_rate_src_last || + spdifrx->info.sample_rate_cal != spdifrx->info.sample_rate_cal_last) { + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &sample_kctl->id); + spdifrx->info.sample_rate_src_last = spdifrx->info.sample_rate_src; + spdifrx->info.sample_rate_cal_last = spdifrx->info.sample_rate_cal; + dev_dbg(spdifrx->dev, "src sample rate: %u Hz\n", + spdifrx->info.sample_rate_src); + dev_dbg(spdifrx->dev, "cal sample rate: %u Hz\n", + spdifrx->info.sample_rate_cal); + } + + if (spdifrx->info.sample_width != spdifrx->info.sample_width_last) { + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &width_kctl->id); + spdifrx->info.sample_width_last = spdifrx->info.sample_width; + dev_dbg(spdifrx->dev, "sample width: %u bit\n", spdifrx->info.sample_width); + } - dev_dbg(spdifrx->dev, "src sample rate: %u Hz\n", spdifrx->info.sample_rate_src); - dev_dbg(spdifrx->dev, "cal sample rate: %u Hz\n", spdifrx->info.sample_rate_cal); dev_dbg(spdifrx->dev, "BTEIE\n"); regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_BTECLR); - regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, SPDIFRX_INTEN_BTEIE_MASK, - SPDIFRX_INTEN_BTEIE_DIS); + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, + SPDIFRX_INTEN_BTEIE_MASK, SPDIFRX_INTEN_BTEIE_DIS); } if (intsr & SPDIFRX_INTSR_SYNCISR_ACTIVE) { spdifrx->info.sync = 1; - snd_ctl_notify(dai->component->card->snd_card, - SNDRV_CTL_EVENT_MASK_VALUE, &sync_kctl->id); + mod_timer(&spdifrx->debounce_timer, jiffies + + msecs_to_jiffies(spdifrx->info.debounce_time_ms)); + regmap_read(spdifrx->regmap, SPDIFRX_CDRST, &val); + dev_dbg(spdifrx->dev, "MINCNT = %lu, MAXCNT = %lu\n", + val & SPDIFRX_CDRST_MINCNT_MASK, (val & SPDIFRX_CDRST_MAXCNT_MASK) >> 8); dev_dbg(spdifrx->dev, "SYNC\n"); + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, + SPDIFRX_INTEN_BTEIE_MASK | SPDIFRX_INTEN_NSYNCIE_MASK, + SPDIFRX_INTEN_BTEIE_EN | SPDIFRX_INTEN_NSYNCIE_EN); regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_SYNCICLR); } @@ -434,6 +760,119 @@ static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) return IRQ_HANDLED; } +/* + * Check if data has been received into the rxfifo. + * + * Within the timeout_us interval, poll the SPDIFRX_FIFOCTRL + * register via regmap_read_poll_timeout_atomic to detect new + * data entries in the fifo + * + * The timeout_us parameter corresponds to the time required + * for a 32-bit data entry to be written into the fifo, which + * is inversely proportional to the sample rate, with a maximum + * value of 32μs (at 16kHz sample rate). + * + * If the actual polling duration exceeds the timeout_us by a + * predefined threshold, the current detection result is invalidated, + * and the system proceeds to the next scheduled timer interval. + */ +static void rk_spdifrx_fifo_timer_isr(struct timer_list *timer) +{ + struct rk_spdifrx_dev *spdifrx = from_timer(spdifrx, timer, fifo_timer); + unsigned int val, timeout_us; + unsigned int fifo_cnt; + ktime_t start, end; + int ret; + + if (spdifrx->info.sync == 0 || spdifrx->need_reset || spdifrx->info.sample_rate_src == 0) + return; + + timeout_us = DIV_ROUND_UP(500000, spdifrx->info.sample_rate_src); + + start = ktime_get(); + regmap_read(spdifrx->regmap, SPDIFRX_FIFOCTRL, &val); + fifo_cnt = (val & SPDIFRX_FIFOCTRL_RFL_MASK) >> 8; + + if (fifo_cnt < 8) { + ret = regmap_read_poll_timeout_atomic(spdifrx->regmap, SPDIFRX_FIFOCTRL, val, + ((val & SPDIFRX_FIFOCTRL_RFL_MASK) >> 8) != + fifo_cnt, 1, timeout_us); + end = ktime_get(); + if (ret == -ETIMEDOUT && ktime_us_delta(end, start) < 8 * timeout_us) { + dev_info(spdifrx->dev, "no data to fifo, reset\n"); + rk_spdifrx_reset(spdifrx); + spdifrx->need_reset = true; + return; + } + } + mod_timer(&spdifrx->fifo_timer, jiffies + msecs_to_jiffies(100)); +} + +static void rk_spdifrx_non_liner_timer_isr(struct timer_list *timer) +{ + struct rk_spdifrx_dev *spdifrx = from_timer(spdifrx, timer, non_liner_timer); + struct snd_soc_dai *dai = spdifrx->dai; + struct snd_kcontrol *liner_pcm_kctl = snd_soc_card_get_kcontrol(dai->component->card, + "RK SPDIFRX LINER PCM"); + + spdifrx->info.liner_pcm = 1; + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &liner_pcm_kctl->id); + spdifrx->info.liner_pcm_last = spdifrx->info.liner_pcm; + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, + SPDIFRX_INTEN_NVLDIE_MASK, SPDIFRX_INTEN_NVLDIE_EN); + dev_dbg(spdifrx->dev, "liner data\n"); +} + +static void rk_spdifrx_debounce_timer_isr(struct timer_list *timer) +{ + struct rk_spdifrx_dev *spdifrx = from_timer(spdifrx, timer, debounce_timer); + struct snd_soc_dai *dai = spdifrx->dai; + struct snd_kcontrol *sync_kctl = snd_soc_card_get_kcontrol(dai->component->card, + "RK SPDIFRX SYNC STATUS"); + struct snd_kcontrol *sample_kctl = snd_soc_card_get_kcontrol(dai->component->card, + "RK SPDIFRX SAMPLE RATE"); + u32 val; + u32 count; + + if (spdifrx->info.sync == 1) { + if (spdifrx->need_reset) { + rk_spdifrx_reset(spdifrx); + spdifrx->need_reset = false; + } else { + regmap_read(spdifrx->regmap, SPDIFRX_CDRST, &val); + if (spdifrx->cdr_count_avg) + count = ((val & SPDIFRX_CDRST_MINCNT_MASK) + 1 + + ((val & SPDIFRX_CDRST_MAXCNT_MASK) >> 8) + 1) / 4; + else + count = (val & SPDIFRX_CDRST_MINCNT_MASK) + 1; + + if (count > 0) + spdifrx->info.sample_rate_cal = + rk_spdifrx_convert_sample_rate(spdifrx->mclk_rate, count); + else + spdifrx->info.sample_rate_cal = 0; + + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &sample_kctl->id); + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &sync_kctl->id); + spdifrx->info.sample_rate_cal_last = spdifrx->info.sample_rate_cal; + mod_timer(&spdifrx->fifo_timer, jiffies + msecs_to_jiffies(1000)); + if (spdifrx->info.liner_pcm == 1) + regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, + SPDIFRX_INTEN_NVLDIE_MASK, + SPDIFRX_INTEN_NVLDIE_EN); + dev_dbg(spdifrx->dev, "notify sync and sample_rate_cal = %u hz\n", + spdifrx->info.sample_rate_cal); + } + } else if (spdifrx->info.sync == 0) { + snd_ctl_notify(dai->component->card->snd_card, + SNDRV_CTL_EVENT_MASK_VALUE, &sync_kctl->id); + dev_dbg(spdifrx->dev, "notify usync\n"); + } +} + static int rk_spdifrx_probe(struct platform_device *pdev) { struct rk_spdifrx_dev *spdifrx; @@ -460,10 +899,19 @@ static int rk_spdifrx_probe(struct platform_device *pdev) if (IS_ERR(spdifrx->mclk)) return PTR_ERR(spdifrx->mclk); + spdifrx->mclk_rate = clk_get_rate(spdifrx->mclk); + spdifrx->irq = platform_get_irq(pdev, 0); if (spdifrx->irq < 0) return spdifrx->irq; + spdifrx->info.debounce_time_ms = 100; + spdifrx->info.liner_pcm = 1; + spdifrx->info.liner_pcm_last = 1; + timer_setup(&spdifrx->debounce_timer, rk_spdifrx_debounce_timer_isr, 0); + timer_setup(&spdifrx->non_liner_timer, rk_spdifrx_non_liner_timer_isr, 0); + timer_setup(&spdifrx->fifo_timer, rk_spdifrx_fifo_timer_isr, 0); + ret = devm_request_threaded_irq(&pdev->dev, spdifrx->irq, NULL, rk_spdifrx_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, @@ -483,7 +931,7 @@ static int rk_spdifrx_probe(struct platform_device *pdev) spdifrx->capture_dma_data.addr = res->start + SPDIFRX_SMPDR; spdifrx->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - spdifrx->capture_dma_data.maxburst = 4; + spdifrx->capture_dma_data.maxburst = 8; spdifrx->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, spdifrx); @@ -522,6 +970,12 @@ err_pm_runtime: static int rk_spdifrx_remove(struct platform_device *pdev) { + struct rk_spdifrx_dev *spdifrx = dev_get_drvdata(&pdev->dev); + + del_timer_sync(&spdifrx->debounce_timer); + del_timer_sync(&spdifrx->non_liner_timer); + del_timer_sync(&spdifrx->fifo_timer); + pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) rk_spdifrx_runtime_suspend(&pdev->dev); diff --git a/sound/soc/rockchip/rockchip_spdifrx.h b/sound/soc/rockchip/rockchip_spdifrx.h index ee9f4c78f040..b72a68f95385 100644 --- a/sound/soc/rockchip/rockchip_spdifrx.h +++ b/sound/soc/rockchip/rockchip_spdifrx.h @@ -58,6 +58,21 @@ #define SPDIFRX_INTEN_NSYNCIE_MASK BIT(7) #define SPDIFRX_INTEN_NSYNCIE_EN BIT(7) #define SPDIFRX_INTEN_NSYNCIE_DIS (0 << 7) +#define SPDIFRX_INTEN_BMDEIE_MASK BIT(6) +#define SPDIFRX_INTEN_BMDEIE_EN BIT(6) +#define SPDIFRX_INTEN_BMDEIE_DIS (0 << 6) +#define SPDIFRX_INTEN_NPSPIE_MASK BIT(3) +#define SPDIFRX_INTEN_NPSPIE_EN BIT(3) +#define SPDIFRX_INTEN_NPSPIE_DIS (0 << 3) +#define SPDIFRX_INTEN_NVLDIE_MASK BIT(2) +#define SPDIFRX_INTEN_NVLDIE_EN BIT(2) +#define SPDIFRX_INTEN_NVLDIE_DIS (0 << 2) +#define SPDIFRX_INTEN_CSCIE_MASK BIT(1) +#define SPDIFRX_INTEN_CSCIE_EN BIT(1) +#define SPDIFRX_INTEN_CSCIE_DIS (0 << 1) +#define SPDIFRX_INTEN_PEIE_MASK BIT(0) +#define SPDIFRX_INTEN_PEIE_EN BIT(0) +#define SPDIFRX_INTEN_PEIE_DIS (0 << 0) /* INTMASK */ #define SPDIFRX_INTMASK_UBCIMSK BIT(10) @@ -68,12 +83,27 @@ #define SPDIFRX_INTMASK_BTEIUMSK (0 << 8) #define SPDIFRX_INTMASK_NSYNCIMSK BIT(7) #define SPDIFRX_INTMASK_NSYNCIUMSK (0 << 7) +#define SPDIFRX_INTMASK_BMDEIMSK BIT(6) +#define SPDIFRX_INTMASK_BMDEIUMSK (0 << 6) +#define SPDIFRX_INTMASK_NPSPIMSK BIT(3) +#define SPDIFRX_INTMASK_NPSPIUMSK (0 << 3) +#define SPDIFRX_INTMASK_NVLDIMSK BIT(2) +#define SPDIFRX_INTMASK_NVLDIUMSK (0 << 2) +#define SPDIFRX_INTMASK_CSCIMSK BIT(1) +#define SPDIFRX_INTMASK_CSCIUMSK (0 << 1) +#define SPDIFRX_INTMASK_PEIMSK BIT(0) +#define SPDIFRX_INTMASK_PEIUMSK (0 << 0) /* INTSR */ #define SPDIFRX_INTSR_UBCISR_ACTIVE BIT(10) #define SPDIFRX_INTSR_SYNCISR_ACTIVE BIT(9) #define SPDIFRX_INTSR_BTEISR_ACTIVE BIT(8) #define SPDIFRX_INTSR_NSYNCISR_ACTIVE BIT(7) +#define SPDIFRX_INTSR_BMDEISR_ACTIVE BIT(6) +#define SPDIFRX_INTSR_NPSPISR_ACTIVE BIT(3) +#define SPDIFRX_INTSR_NVLDISR_ACTIVE BIT(2) +#define SPDIFRX_INTSR_CSCISR_ACTIVE BIT(1) +#define SPDIFRX_INTSR_PEISR_ACTIVE BIT(0) /* INTCLR */ #define SPDIFRX_INTCLR_UBCICLR_MASK BIT(10) @@ -84,9 +114,20 @@ #define SPDIFRX_INTCLR_BTECLR BIT(8) #define SPDIFRX_INTCLR_NSYNCICLR_MASK BIT(7) #define SPDIFRX_INTCLR_NSYNCICLR BIT(7) +#define SPDIFRX_INTCLR_BMDEICLR_MASK BIT(6) +#define SPDIFRX_INTCLR_BMDEICLR BIT(6) +#define SPDIFRX_INTCLR_NPSPICLR_MASK BIT(3) +#define SPDIFRX_INTCLR_NPSPICLR BIT(3) +#define SPDIFRX_INTCLR_NVLDICLR_MASK BIT(2) +#define SPDIFRX_INTCLR_NVLDICLR BIT(2) +#define SPDIFRX_INTCLR_CSCICLR_MASK BIT(1) +#define SPDIFRX_INTCLR_CSCICLR BIT(1) +#define SPDIFRX_INTCLR_PEICLR_MASK BIT(0) +#define SPDIFRX_INTCLR_PEICLR BIT(0) /* SPDIFRX_CHNSRN */ -#define SPDIFRX_CHNSR1_SAMPLE_RATE_MASK GENMASK(11, 8) +#define SPDIFRX_CHNSR1_SAMPLE_RATE_MASK GENMASK(11, 8) +#define SPDIFRX_CHNSR2_SAMPLE_WIDTH_MASK GENMASK(3, 0) /* BURSTINFO */ #define SPDIFRX_BURSTINFO_PD_MASK GENMASK(31, 16) @@ -111,6 +152,7 @@ #define SPDIFRX_SMPDR (0x002C) #define SPDIFRX_USRDRN (0x0030) #define SPDIFRX_CHNSR1 (0x0064) +#define SPDIFRX_CHNSR2 (0x0068) #define SPDIFRX_BURSTINFO (0x0100) #endif /* _ROCKCHIP_SPDIFRX_H */ From 89360f8db226167d37f2f09129386842cf7afd0a Mon Sep 17 00:00:00 2001 From: Zhong Shengquan Date: Thu, 31 Jul 2025 15:11:04 +0800 Subject: [PATCH 14/21] ASoC: rockchip: spdifrx: fix issue where reset causes underrun in app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When sample rate changes, a reset operation is performed, and another reset occurs after debouncing. This results in less data being read by upper layer, thus triggering an underrun condition. Therefore, remove reset operation in rk_spdifrx_trigger. Meanwhile, when sample rate changes, ​​disable dma enable​​, and after debouncing completes, notify upper layer via stop_xrun to restart​​, then ​​enable dma to resume data transfer. ​​ Change-Id: Ie112ed83018722d069bd85d181f609c4bf865027 Signed-off-by: Zhong Shengquan --- sound/soc/rockchip/rockchip_spdifrx.c | 67 +++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_spdifrx.c b/sound/soc/rockchip/rockchip_spdifrx.c index 066de3a388c0..0a6137041ccc 100644 --- a/sound/soc/rockchip/rockchip_spdifrx.c +++ b/sound/soc/rockchip/rockchip_spdifrx.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -46,9 +47,11 @@ struct rk_spdifrx_dev { struct reset_control *reset; struct rk_spdifrx_info info; struct snd_soc_dai *dai; + struct snd_pcm_substream *substream; struct timer_list debounce_timer; struct timer_list non_liner_timer; struct timer_list fifo_timer; + struct work_struct xrun_work; unsigned int mclk_rate; int irq; bool cdr_count_avg; @@ -129,6 +132,7 @@ static int rk_spdifrx_hw_params(struct snd_pcm_substream *substream, spdifrx->info.sample_rate_src_last = 0; spdifrx->info.sample_width_last = 0; spdifrx->info.liner_pcm_last = 1; + spdifrx->substream = substream; if (params_rate(params) >= 44100) spdifrx->cdr_count_avg = true; @@ -155,7 +159,7 @@ static int rk_spdifrx_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - rk_spdifrx_reset(spdifrx); + regmap_write(spdifrx->regmap, SPDIFRX_CLR, SPDIFRX_CLR_RXSC); ret = regmap_update_bits(spdifrx->regmap, SPDIFRX_DMACR, SPDIFRX_DMACR_RDE_MASK, SPDIFRX_DMACR_RDE_ENABLE); @@ -166,6 +170,9 @@ static int rk_spdifrx_trigger(struct snd_pcm_substream *substream, ret = regmap_update_bits(spdifrx->regmap, SPDIFRX_CFGR, SPDIFRX_EN_MASK, SPDIFRX_EN); + + mod_timer(&spdifrx->fifo_timer, jiffies + msecs_to_jiffies(1000)); + dev_dbg(spdifrx->dev, "start fifo timer\n"); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: @@ -391,6 +398,7 @@ static int rk_spdifrx_dai_probe(struct snd_soc_dai *dai) ARRAY_SIZE(rk_spdifrx_controls)); rk_spdifrx_parse_quirks(spdifrx); + spdifrx->need_reset = true; return 0; } @@ -618,6 +626,24 @@ static unsigned int rk_spdifrx_convert_sample_rate(unsigned int mclk, unsigned i return 0; } +static int rk_spdifrx_disable_dma(struct rk_spdifrx_dev *spdifrx) +{ + int ret; + + ret = regmap_update_bits(spdifrx->regmap, SPDIFRX_DMACR, + SPDIFRX_DMACR_RDE_MASK, + SPDIFRX_DMACR_RDE_DISABLE); + + if (ret != 0) { + dev_err(spdifrx->dev, "Failed to disable rxdma\n"); + return ret; + } + + dev_dbg(spdifrx->dev, "rxdma disabled\n"); + + return ret; +} + static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) { struct rk_spdifrx_dev *spdifrx = dev_id; @@ -642,6 +668,7 @@ static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_NVLDICLR); rk_spdifrx_reset(spdifrx); spdifrx->need_reset = true; + rk_spdifrx_disable_dma(spdifrx); regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, SPDIFRX_INTEN_NVLDIE_MASK, SPDIFRX_INTEN_NVLDIE_DIS); } @@ -658,6 +685,7 @@ static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_PEICLR); rk_spdifrx_reset(spdifrx); spdifrx->need_reset = true; + rk_spdifrx_disable_dma(spdifrx); } if (intsr & SPDIFRX_INTSR_NPSPISR_ACTIVE) { @@ -679,6 +707,7 @@ static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_BMDEICLR); rk_spdifrx_reset(spdifrx); spdifrx->need_reset = true; + rk_spdifrx_disable_dma(spdifrx); } if (intsr & SPDIFRX_INTSR_NSYNCISR_ACTIVE) { @@ -690,7 +719,7 @@ static irqreturn_t rk_spdifrx_isr(int irq, void *dev_id) regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, SPDIFRX_INTEN_NSYNCIE_MASK, SPDIFRX_INTEN_NSYNCIE_DIS); regmap_write(spdifrx->regmap, SPDIFRX_INTCLR, SPDIFRX_INTCLR_NSYNCICLR); - regmap_write(spdifrx->regmap, SPDIFRX_CLR, 0x1); + regmap_write(spdifrx->regmap, SPDIFRX_CLR, SPDIFRX_CLR_RXSC); } if (intsr & SPDIFRX_INTSR_BTEISR_ACTIVE) { @@ -784,8 +813,18 @@ static void rk_spdifrx_fifo_timer_isr(struct timer_list *timer) ktime_t start, end; int ret; - if (spdifrx->info.sync == 0 || spdifrx->need_reset || spdifrx->info.sample_rate_src == 0) + if (spdifrx->info.sync == 0 || spdifrx->need_reset || spdifrx->info.sample_rate_src == 0) { + dev_dbg(spdifrx->dev, "exit fifo timer\n"); + dev_dbg(spdifrx->dev, "sync: %d, need_reset: %d, sample_rate_src: %u\n", + spdifrx->info.sync, spdifrx->need_reset, spdifrx->info.sample_rate_src); return; + } + + regmap_read(spdifrx->regmap, SPDIFRX_DMACR, &val); + if ((val & SPDIFRX_DMACR_RDE_MASK) == 0) { + dev_dbg(spdifrx->dev, "exit fifo timer: rxdma disabled\n"); + return; + } timeout_us = DIV_ROUND_UP(500000, spdifrx->info.sample_rate_src); @@ -802,6 +841,7 @@ static void rk_spdifrx_fifo_timer_isr(struct timer_list *timer) dev_info(spdifrx->dev, "no data to fifo, reset\n"); rk_spdifrx_reset(spdifrx); spdifrx->need_reset = true; + rk_spdifrx_disable_dma(spdifrx); return; } } @@ -839,6 +879,7 @@ static void rk_spdifrx_debounce_timer_isr(struct timer_list *timer) if (spdifrx->need_reset) { rk_spdifrx_reset(spdifrx); spdifrx->need_reset = false; + schedule_work(&spdifrx->xrun_work); } else { regmap_read(spdifrx->regmap, SPDIFRX_CDRST, &val); if (spdifrx->cdr_count_avg) @@ -858,7 +899,6 @@ static void rk_spdifrx_debounce_timer_isr(struct timer_list *timer) snd_ctl_notify(dai->component->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, &sync_kctl->id); spdifrx->info.sample_rate_cal_last = spdifrx->info.sample_rate_cal; - mod_timer(&spdifrx->fifo_timer, jiffies + msecs_to_jiffies(1000)); if (spdifrx->info.liner_pcm == 1) regmap_update_bits(spdifrx->regmap, SPDIFRX_INTEN, SPDIFRX_INTEN_NVLDIE_MASK, @@ -873,6 +913,24 @@ static void rk_spdifrx_debounce_timer_isr(struct timer_list *timer) } } +static void rk_spdifrx_xrun_work(struct work_struct *work) +{ + struct rk_spdifrx_dev *spdifrx = container_of(work, struct rk_spdifrx_dev, xrun_work); + int ret; + u32 val; + + ret = regmap_read_poll_timeout(spdifrx->regmap, SPDIFRX_CDR, val, + ((val & SPDIFRX_CDR_CS_MASK) >> 9) == 0x3, 300, 3000); + if (!ret) { + if (spdifrx->substream) { + snd_pcm_stop_xrun(spdifrx->substream); + dev_dbg(spdifrx->dev, "stop xrun\n"); + } + } else { + dev_dbg(spdifrx->dev, "reset enter sync failed\n"); + } +} + static int rk_spdifrx_probe(struct platform_device *pdev) { struct rk_spdifrx_dev *spdifrx; @@ -911,6 +969,7 @@ static int rk_spdifrx_probe(struct platform_device *pdev) timer_setup(&spdifrx->debounce_timer, rk_spdifrx_debounce_timer_isr, 0); timer_setup(&spdifrx->non_liner_timer, rk_spdifrx_non_liner_timer_isr, 0); timer_setup(&spdifrx->fifo_timer, rk_spdifrx_fifo_timer_isr, 0); + INIT_WORK(&spdifrx->xrun_work, rk_spdifrx_xrun_work); ret = devm_request_threaded_irq(&pdev->dev, spdifrx->irq, NULL, rk_spdifrx_isr, From 0aa0a5e9dc463a510c003484ff2a9d8581e0ef51 Mon Sep 17 00:00:00 2001 From: Xiao Yao Date: Thu, 11 Sep 2025 18:24:50 +0800 Subject: [PATCH 15/21] arm64: dts: rockchip: rv1126b-evb1: enable rtc-32k for sdiowifi Signed-off-by: Xiao Yao Change-Id: Ib10fc729d13f63929d266f33087d6f8e48b0ecd0 --- arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi index da82560304cd..971f67e0ccab 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi @@ -8,7 +8,11 @@ sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; pinctrl-names = "default"; - pinctrl-0 = <&wifi_enable_h>; + pinctrl-0 = <&wifi_enable_h &rtc_32k_pins>; + + //32.768k + clocks = <&xin32k>; + clock-names = "ext_clock"; /* * On the module itself this is one of these (depending From fd6109c5f85b79ce1bf6649067aaf2d99af16076 Mon Sep 17 00:00:00 2001 From: Chaoyi Chen Date: Wed, 7 May 2025 15:13:45 +0800 Subject: [PATCH 16/21] drm/rockchip: vop2: Change gt2/gt4 scale rate for rk3576 cluster win MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using the ZME algorithm for scaling, the scaling config needs to be adjusted to ensure performance: If plane height >= half of display height: - Use gt4 when down-scaling ratio > 8× - Use gt2 when down-scaling ratio > 4× Otherwise: - Use gt4 when down-scaling ratio > 6× - Use gt2 when down-scaling ratio > 3× Change-Id: I50ce653134dc697d64134ce7aa8f98a2d0e8262b Signed-off-by: Chaoyi Chen --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 49 +++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index ddb93a128f01..ccdee3ae6ef6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -3095,6 +3095,7 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win *win, struct vop2_video_port *vp = to_vop2_video_port(crtc); uint32_t pixel_format = fb->format->format; const struct drm_format_info *info = drm_format_info(pixel_format); + struct drm_display_mode *mode = &crtc->state->adjusted_mode; uint8_t hsub = info->hsub; uint8_t vsub = info->vsub; uint16_t cbcr_src_w = src_w / hsub; @@ -3144,12 +3145,22 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win *win, } } else { if (win_data->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) { - if (src_h >= (8 * dst_h)) { - ygt4 = 1; - src_h >>= 2; - } else if (src_h >= (4 * dst_h)) { - ygt2 = 1; - src_h >>= 1; + if (dst_h < mode->hdisplay >> 1) { + if (src_h >= (6 * dst_h)) { + ygt4 = 1; + src_h >>= 2; + } else if (src_h >= (3 * dst_h)) { + ygt2 = 1; + src_h >>= 1; + } + } else { + if (src_h >= (8 * dst_h)) { + ygt4 = 1; + src_h >>= 2; + } else if (src_h >= (4 * dst_h)) { + ygt2 = 1; + src_h >>= 1; + } } } else { if (src_h >= (4 * dst_h)) { @@ -3254,18 +3265,22 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win *win, ygt4 = 1; else if ((cbcr_src_h >= 100 * dst_h / 65) && (cbcr_src_h < 100 * dst_h / 35)) ygt2 = 1; + } else if (win_data->vsd_filter_mode == VOP2_SCALE_DOWN_ZME && + dst_h < mode->hdisplay >> 1) { + if (cbcr_src_h >= (6 * dst_h)) + ygt4 = 1; + else if (cbcr_src_h >= (3 * dst_h)) + ygt2 = 1; + } else if (win_data->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) { + if (cbcr_src_h >= (8 * dst_h)) + ygt4 = 1; + else if (cbcr_src_h >= (4 * dst_h)) + ygt2 = 1; } else { - if (win_data->vsd_filter_mode == VOP2_SCALE_DOWN_ZME) { - if (cbcr_src_h >= (8 * dst_h)) - ygt4 = 1; - else if (cbcr_src_h >= (4 * dst_h)) - ygt2 = 1; - } else { - if (cbcr_src_h >= (4 * dst_h)) - ygt4 = 1; - else if (cbcr_src_h >= (2 * dst_h)) - ygt2 = 1; - } + if (cbcr_src_h >= (4 * dst_h)) + ygt4 = 1; + else if (cbcr_src_h >= (2 * dst_h)) + ygt2 = 1; } if (ygt4) From f5281345b1826337aa182cefd3225246f8c0e913 Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Fri, 12 Sep 2025 11:10:10 +0800 Subject: [PATCH 17/21] phy: rockchip: inno-usb2: Fix the controller's failure to set host mode In USB Type-A ports with non-permanent VBUS power, switching mode from device to host via debugfs API would cause the controller to briefly enter host then revert to device. This happens because PHY sends an extcon message while EXTCON_USB_HOST remains false, so set EXTCON_USB_HOST to true during the mode-setting process to fix it. Serial logs show the following when debug is enabled in the PHY driver: [ 110.130678s][ T197]Workqueue: events rockchip_usb2phy_otg_sm_work [ 110.130682s][ T197]Call trace: [ 110.130688s][ T197] dump_backtrace+0x0/0x1dc [ 110.130693s][ T197] show_stack+0x18/0x24 [ 110.130698s][ T197] dump_stack_lvl+0xe4/0x12c [ 110.130701s][ T197] dump_stack+0x18/0x3c [ 110.130705s][ T197] rockchip_usb2phy_otg_sm_work+0x40/0x5ec [ 110.130709s][ T197] process_one_work+0x22c/0x510 [ 110.130712s][ T197] worker_thread+0x280/0x4ec [ 110.130716s][ T197] kthread+0x138/0x200 [ 110.130720s][ T197] ret_from_fork+0x10/0x18 [ 110.130727s][ T197]phy phy-fd5d0000.syscon:usb2-phy@0.0: b_peripheral otg sm work [ 110.130731s][ T197]phy phy-fd5d0000.syscon:usb2-phy@0.0: usb otg host connect [ 110.130736s][ T197]phy phy-fd5d0000.syscon:usb2-phy@0.0: extcon set cable(7) as 0 [ 110.130817s][ T197]phy phy-fd5d0000.syscon:usb2-phy@0.0: extcon set cable(1) as 0 [ 110.130834s][ T197]CPU: 6 PID: 197 Comm: kworker/6:3 VIP: 00 Tainted: G W 5.10.226 #1 [ 110.130837s][ T197]Hardware name: CDC710_SOCA_VA_BOM9_M_001_FACTORY (DT) [ 110.130841s][ T197]Workqueue: events rockchip_usb2phy_otg_sm_work [ 110.130845s][ T197]Call trace: [ 110.130848s][ T197] dump_backtrace+0x0/0x1dc [ 110.130853s][ T197] show_stack+0x18/0x24 [ 110.130856s][ T197] dump_stack_lvl+0xe4/0x12c [ 110.130859s][ T197] dump_stack+0x18/0x3c [ 110.130864s][ T197] dwc3_set_mode+0x20/0x7c [ 110.130869s][ T197] dwc3_drd_notifier+0x68/0x7c [ 110.130873s][ T197] raw_notifier_call_chain+0x40/0x6c [ 110.130878s][ T197] extcon_sync+0x124/0x2e0 [ 110.130882s][ T197] rockchip_usb2phy_otg_sm_work+0x480/0x5ec [ 110.130886s][ T197] process_one_work+0x22c/0x510 [ 110.130889s][ T197] worker_thread+0x280/0x4ec [ 110.130893s][ T197] kthread+0x138/0x200 [ 110.130896s][ T197] ret_from_fork+0x10/0x18 [ 110.130920s][ T197]CPU: 6 PID: 197 Comm: kworker/6:3 VIP: 00 Tainted: G W 5.10.226 #1 [ 110.130923s][ T197]Hardware name: CDC710_SOCA_VA_BOM9_M_001_FACTORY (DT) [ 110.130926s][ T197]Workqueue: events_freezable __dwc3_set_mode [ 110.130930s][ T197]Call trace: [ 110.130934s][ T197] dump_backtrace+0x0/0x1dc [ 110.130938s][ T197] show_stack+0x18/0x24 [ 110.130941s][ T197] dump_stack_lvl+0xe4/0x12c [ 110.130944s][ T197] dump_stack+0x18/0x3c [ 110.130947s][ T197] __dwc3_set_mode+0x2c/0xb54 [ 110.130951s][ T197] process_one_work+0x22c/0x510 [ 110.130954s][ T197] worker_thread+0x280/0x4ec [ 110.130958s][ T197] kthread+0x138/0x200 [ 110.130962s][ T197] ret_from_fork+0x10/0x18 [ 110.130971s][ T197]dwc->desired_role_sw_mode = 0 [ 110.130974s][ T197]dwc->current_role_sw_mode = 1 [ 110.131024s][ T197]xhci-hcd xhci-hcd.10.auto: remove, state 4 [ 110.131028s][ T197]xhci-hcd xhci-hcd.10.auto: roothub graceful disconnect [ 110.131035s][ T197]usb usb4: USB disconnect, device number 1 Change-Id: I7b0a2f8161eb52fd145f145f398586526ab1006b Signed-off-by: Frank Wang --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 20af74197466..2923de86c8ea 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -1091,6 +1091,7 @@ static int rockchip_usb2phy_set_mode(struct phy *phy, } extcon_set_state_sync(rphy->edev, EXTCON_USB_VBUS_EN, true); + extcon_set_state(rphy->edev, EXTCON_USB_HOST, true); /* For vbus always on, deinit EXTCON_USB to false. */ if (rport->vbus_always_on) extcon_set_state(rphy->edev, EXTCON_USB, false); From 87332bdb1a8274e33a1320e612a25e40aa78adf2 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Thu, 11 Sep 2025 14:40:38 +0800 Subject: [PATCH 18/21] drm/rockchip: dp_aux_client: remove unused debugfs.h Change-Id: I17898572d9782e5043fa00a74ab96723b50ad5c0 Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/rockchip_dp_mst_aux_client.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_dp_mst_aux_client.c b/drivers/gpu/drm/rockchip/rockchip_dp_mst_aux_client.c index d7bc91adc841..5dd426190ee9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_dp_mst_aux_client.c +++ b/drivers/gpu/drm/rockchip/rockchip_dp_mst_aux_client.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include From 9cb4d07e13d224c99cfac4eaf06ff3df74e2129d Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Fri, 12 Sep 2025 10:48:39 +0800 Subject: [PATCH 19/21] arm64: dts: rockchip: rk3568j: add overdrive opps for cpu/npu/gpu Disable overdrive opps by default, and enable them in board dts if use overdrive mode. Change-Id: I6db9bd54b727aa3723a2cf46e1b5bd40bdeca0d9 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/rk3568.dtsi | 68 ++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi index 7897f302b2e8..52ba325d0368 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi @@ -297,6 +297,38 @@ clock-latency-ns = <40000>; }; + /* + * The Max frequency is 1416MHz in default normal mode. + * The Max frequency is 1800MHz in overdrive mode, + * but under the overdrive mode for a long time, + * the chipset may shorten the lifetime, especially in high + * temperature condition. Disable overdrive opps by default + * and you can enable them in dts file. + */ + cpu_opp_j_od_1608000000: opp-j-od-1608000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <1100000 1100000 1150000>; + opp-microvolt-L0 = <1100000 1100000 1150000>; + opp-microvolt-L1 = <1050000 1050000 1150000>; + opp-microvolt-L2 = <1025000 1025000 1150000>; + opp-microvolt-L3 = <1000000 1000000 1150000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; + + cpu_opp_j_od_1800000000: opp-j-od-1800000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1150000 1150000 1150000>; + opp-microvolt-L0 = <1150000 1150000 1150000>; + opp-microvolt-L1 = <1100000 1100000 1150000>; + opp-microvolt-L2 = <1075000 1075000 1150000>; + opp-microvolt-L3 = <1050000 1050000 1150000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; + /* RK3568M cpu OPPs */ opp-m-1608000000 { opp-supported-hw = <0x02 0xffff>; @@ -323,6 +355,24 @@ opp-microvolt = <900000 900000 1000000>; }; + /* The Max frequency is 600MHz in default normal mode. + * The Max frequency is 800MHz in overdrive mode, + * but under the overdrive mode for a long time, + * the chipset may shorten the lifetime, especially in high + * temperature condition. Disable overdrive opps by default + * and you can enable them in dts file. + */ + gpu_opp_j_od_800000000: opp-j-od-800000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1000000 1000000 1000000>; + opp-microvolt-L0 = <1000000 1000000 1000000>; + opp-microvolt-L1 = <975000 975000 1000000>; + opp-microvolt-L2 = <950000 950000 1000000>; + opp-microvolt-L3 = <925000 925000 1000000>; + status = "disabled"; + }; + /* RK3568M gpu OPPs */ opp-m-800000000 { opp-supported-hw = <0x02 0xffff>; @@ -371,6 +421,24 @@ opp-microvolt = <900000 900000 1000000>; }; + /* The Max frequency is 600MHz in default normal mode. + * The Max frequency is 800MHz in overdrive mode, + * but under the overdrive mode for a long time, + * the chipset may shorten the lifetime, especially in high + * temperature condition. Disable overdrive opps by default + * and you can enable them in dts file. + */ + npu_opp_j_od_800000000: opp-j-od-800000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <925000 925000 1000000>; + opp-microvolt-L0 = <925000 925000 1000000>; + opp-microvolt-L1 = <900000 900000 1000000>; + opp-microvolt-L2 = <900000 900000 1000000>; + opp-microvolt-L3 = <900000 900000 1000000>; + status = "disabled"; + }; + /* RK3568M npu OPPs */ opp-m-900000000 { opp-supported-hw = <0x02 0xffff>; From 640c4f6115b23329bbae64b011dd6468994dd586 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Mon, 8 Sep 2025 10:27:48 +0800 Subject: [PATCH 20/21] ASoC: rockchip: spdif: Add support for non-pcm switch Signed-off-by: Sugar Zhang Change-Id: Iff38282013c02ba312ff5f8093fd762c358bdc37 --- sound/soc/rockchip/rockchip_spdif.c | 54 +++++++++++++++++++++++++++++ sound/soc/rockchip/rockchip_spdif.h | 4 +++ 2 files changed, 58 insertions(+) diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index f7191cc7ca5d..1bf56a052c08 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ struct rk_spdif_dev { struct snd_dmaengine_dai_dma_data playback_dma_data; struct regmap *regmap; + bool non_pcm; }; static const struct of_device_id rk_spdif_match[] __maybe_unused = { @@ -141,6 +143,20 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; + if (spdif->non_pcm) { + cs[0] |= IEC958_AES0_NONAUDIO; + for (i = 0; i < AES_IEC958_STATUS_SIZE / 2; i++) + regmap_write(spdif->regmap, SPDIF_VLDFRn(i), 0xffffffff); + regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_VFE_MASK, + SPDIF_CFGR_VFE_EN); + } else { + cs[0] &= ~IEC958_AES0_NONAUDIO; + for (i = 0; i < AES_IEC958_STATUS_SIZE / 2; i++) + regmap_write(spdif->regmap, SPDIF_VLDFRn(i), 0x0); + regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_VFE_MASK, + SPDIF_CFGR_VFE_DIS); + } + for (i = 0; i < CS_BYTE / 2; i++) regmap_write(spdif->regmap, SPDIF_CHNSRn(i), CS_FRAME(fc[i])); @@ -275,8 +291,46 @@ static struct snd_soc_dai_driver rk_spdif_dai = { .ops = &rk_spdif_dai_ops, }; +static const char * const non_pcm_text[] = { "pcm", "non pcm" }; +static const struct soc_enum __maybe_unused non_pcm_switch = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(non_pcm_text), non_pcm_text); + +static int rk_spdif_non_pcm_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_spdif_dev *spdif = snd_soc_component_get_drvdata(component); + + ucontrol->value.enumerated.item[0] = spdif->non_pcm; + + return 0; +} + +static int rk_spdif_non_pcm_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_spdif_dev *spdif = snd_soc_component_get_drvdata(component); + bool non_pcm; + + non_pcm = !!ucontrol->value.enumerated.item[0]; + if (non_pcm == spdif->non_pcm) + return 0; + + spdif->non_pcm = non_pcm; + + return 1; +} + +static const struct snd_kcontrol_new rk_spdif_controls[] = { + SOC_ENUM_EXT("AUDIO MODE", non_pcm_switch, + rk_spdif_non_pcm_get, rk_spdif_non_pcm_put), +}; + static const struct snd_soc_component_driver rk_spdif_component = { .name = "rockchip-spdif", + .controls = rk_spdif_controls, + .num_controls = ARRAY_SIZE(rk_spdif_controls), .legacy_dai_naming = 1, }; diff --git a/sound/soc/rockchip/rockchip_spdif.h b/sound/soc/rockchip/rockchip_spdif.h index 5c656bd8fd18..4f089006fdf6 100644 --- a/sound/soc/rockchip/rockchip_spdif.h +++ b/sound/soc/rockchip/rockchip_spdif.h @@ -25,6 +25,10 @@ #define SPDIF_CFGR_CSE_EN BIT(6) #define SPDIF_CFGR_CSE_DIS 0 +#define SPDIF_CFGR_VFE_MASK BIT(4) +#define SPDIF_CFGR_VFE_EN BIT(4) +#define SPDIF_CFGR_VFE_DIS 0 + #define SPDIF_CFGR_ADJ_MASK BIT(3) #define SPDIF_CFGR_ADJ_LEFT_J BIT(3) #define SPDIF_CFGR_ADJ_RIGHT_J 0 From 0db4dfdeff221d483deb1a03475d2de4c5bcbeb9 Mon Sep 17 00:00:00 2001 From: Haoran Han Date: Thu, 11 Sep 2025 10:37:41 +0800 Subject: [PATCH 21/21] media: i2c: max96756: Remove inappropriate function additions in kernel 5.10 version Change-Id: I48d18c8ed6833a86798f8e647fb5da735f3b18e0 Signed-off-by: Haoran Han --- drivers/media/i2c/max96756.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/drivers/media/i2c/max96756.c b/drivers/media/i2c/max96756.c index f890ec701f2a..42b18c9aaee6 100644 --- a/drivers/media/i2c/max96756.c +++ b/drivers/media/i2c/max96756.c @@ -1093,27 +1093,6 @@ static int max96756_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, return 0; } -#elif KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE -static int max96756_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, - struct v4l2_mbus_config *config) -{ - struct max96756 *max96756 = to_max96756(sd); - u32 val = 0; - const struct max96756_mode *mode = max96756->cur_mode; - u8 data_lanes = max96756->bus_cfg.bus.mipi_csi2.num_data_lanes; - int i = 0; - - val |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; - val |= (1 << (data_lanes - 1)); - - for (i = 0; i < PAD_MAX; i++) - val |= (mode->vc[i] & V4L2_MBUS_CSI2_CHANNELS); - - config->type = V4L2_MBUS_CSI2_DPHY; - config->flags = val; - - return 0; -} #else static int max96756_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_config *config)