From 58a858b3e88ee007d26988eef84dd22b5da07e11 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sun, 11 Feb 2018 23:00:03 +0100 Subject: [PATCH] linux: update rockchip-4.4 to 7b43537e --- packages/linux/package.mk | 4 +- .../linux/rockchip-4.4/linux.aarch64.conf | 25 +- .../linux/rockchip-4.4/linux.arm.conf | 24 +- .../rockchip-4.4/linux-0001-miniarm.patch | 36 +- .../linux/rockchip-4.4/linux.aarch64.conf | 33 +- .../linux/rockchip-4.4/linux.arm.conf | 30 +- .../rockchip-4.4/linux-0001-rockchip.patch | 4321 +--------------- .../linux/rockchip-4.4/linux-0002-ir.patch | 156 +- .../linux/rockchip-4.4/linux-0003-cec.patch | 2832 ++-------- .../linux/rockchip-4.4/linux-0004-audio.patch | 1533 +++++- .../rockchip-4.4/linux-0005-legacy.patch | 19 +- .../linux/rockchip-4.4/linux-0006-dts.patch | 4600 +++++++++++++++++ .../rockchip-4.4/linux-0007-rtl8211f.patch | 870 ++++ .../linux-0008-dtoverlay-configfs.patch | 1120 ++++ .../rockchip-4.4/linux-0009-mmc-pwrseq.patch | 949 ++++ .../linux/rockchip-4.4/linux-1000-pl330.patch | 612 ++- 16 files changed, 10289 insertions(+), 6875 deletions(-) create mode 100644 projects/Rockchip/patches/linux/rockchip-4.4/linux-0006-dts.patch create mode 100644 projects/Rockchip/patches/linux/rockchip-4.4/linux-0007-rtl8211f.patch create mode 100644 projects/Rockchip/patches/linux/rockchip-4.4/linux-0008-dtoverlay-configfs.patch create mode 100644 projects/Rockchip/patches/linux/rockchip-4.4/linux-0009-mmc-pwrseq.patch diff --git a/packages/linux/package.mk b/packages/linux/package.mk index e9e58d24cd..65f8c78cbd 100644 --- a/packages/linux/package.mk +++ b/packages/linux/package.mk @@ -47,8 +47,8 @@ case "$LINUX" in PKG_DEPENDS_TARGET="$PKG_DEPENDS_TARGET aml-dtbtools:host" ;; rockchip-4.4) - PKG_VERSION="28018092" - PKG_SHA256="944b59f3b8fd9c1e37ea717e600651f9e49f3f01e2e9290d00386dec1789bf83" + PKG_VERSION="7b43537e" + PKG_SHA256="f934e8364308388868edd8d89f6fa71af8516a9b25bfaa1451bdc1b473735fdc" PKG_URL="https://github.com/rockchip-linux/kernel/archive/$PKG_VERSION.tar.gz" PKG_SOURCE_DIR="kernel-$PKG_VERSION*" PKG_PATCH_DIRS="rockchip-4.4" diff --git a/projects/Rockchip/devices/RockBox/linux/rockchip-4.4/linux.aarch64.conf b/projects/Rockchip/devices/RockBox/linux/rockchip-4.4/linux.aarch64.conf index 5cf8620cbd..a348ca2e17 100644 --- a/projects/Rockchip/devices/RockBox/linux/rockchip-4.4/linux.aarch64.conf +++ b/projects/Rockchip/devices/RockBox/linux/rockchip-4.4/linux.aarch64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.103 Kernel Configuration +# Linux/arm64 4.4.112 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -458,6 +458,7 @@ CONFIG_SECCOMP=y # CONFIG_CRASH_DUMP is not set # CONFIG_XEN is not set CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_UNMAP_KERNEL_AT_EL0=y # CONFIG_ARMV8_DEPRECATED is not set # CONFIG_ARM64_SW_TTBR0_PAN is not set @@ -1686,6 +1687,7 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y # CONFIG_TOUCHSCREEN_GSLX680_VR is not set # CONFIG_TOUCHSCREEN_GSLX680_FIREFLY is not set # CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_GSL3673_800X1280 is not set # CONFIG_TOUCHSCREEN_GT9XX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_GUNZE is not set @@ -1736,6 +1738,7 @@ CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y # CONFIG_TOUCHSCREEN_ZFORCE is not set # CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set # CONFIG_TOUCHSCREEN_VTL_CT36X is not set +# CONFIG_TOUCHSCREEN_GT1X is not set # CONFIG_ROCKCHIP_REMOTECTL is not set # @@ -2376,6 +2379,7 @@ CONFIG_MFD_CROS_EC_SPI=y # CONFIG_MFD_RT5033 is not set # CONFIG_MFD_RTSX_USB is not set # CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK618 is not set CONFIG_MFD_RK808=y # CONFIG_MFD_RN5T618 is not set # CONFIG_MFD_SEC_CORE is not set @@ -2598,14 +2602,15 @@ CONFIG_DRM_BRIDGE=y # # Display Interface Bridges # +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_RK1000 is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +CONFIG_DRM_ANALOGIX_DP=y CONFIG_DRM_DW_HDMI=y # CONFIG_DRM_DW_HDMI_AHB_AUDIO is not set CONFIG_DRM_DW_HDMI_I2S_AUDIO=y CONFIG_DRM_DW_HDMI_CEC=y -# CONFIG_DRM_NXP_PTN3460 is not set -# CONFIG_DRM_PARADE_PS8622 is not set -# CONFIG_DRM_RK1000 is not set -CONFIG_DRM_ANALOGIX_DP=y # CONFIG_POWERVR_ROGUE_M is not set CONFIG_MALI400=m CONFIG_MALI450=y @@ -2873,6 +2878,7 @@ CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_CS42XX8_I2C is not set # CONFIG_SND_SOC_CS4349 is not set # CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_CX20810 is not set # CONFIG_SND_SOC_BT_SCO is not set CONFIG_SND_SOC_ES8316=y # CONFIG_SND_SOC_ES8323 is not set @@ -3323,6 +3329,8 @@ CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_EMBEDDED_SDIO is not set # CONFIG_MMC_PARANOID_SD_INIT is not set +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y # # MMC/SD/SDIO Card Drivers @@ -3721,6 +3729,7 @@ CONFIG_CLKSRC_PROBE=y CONFIG_ROCKCHIP_TIMER=y CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set # CONFIG_ARM_TIMER_SP804 is not set # CONFIG_ATMEL_PIT is not set # CONFIG_SH_TIMER_CMT is not set @@ -3783,10 +3792,10 @@ CONFIG_DEVFREQ_GOV_USERSPACE=y # # DEVFREQ Drivers # -# CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ is not set +CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y CONFIG_PM_DEVFREQ_EVENT=y -# CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI is not set -# CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP is not set +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP=y CONFIG_EXTCON=y # diff --git a/projects/Rockchip/devices/TinkerBoard/linux/rockchip-4.4/linux.arm.conf b/projects/Rockchip/devices/TinkerBoard/linux/rockchip-4.4/linux.arm.conf index 8bee659376..50e38b9864 100644 --- a/projects/Rockchip/devices/TinkerBoard/linux/rockchip-4.4/linux.arm.conf +++ b/projects/Rockchip/devices/TinkerBoard/linux/rockchip-4.4/linux.arm.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.4.103 Kernel Configuration +# Linux/arm 4.4.112 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -1582,6 +1582,7 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y # CONFIG_TOUCHSCREEN_GSLX680_VR is not set # CONFIG_TOUCHSCREEN_GSLX680_FIREFLY is not set # CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_GSL3673_800X1280 is not set # CONFIG_TOUCHSCREEN_GT9XX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_GUNZE is not set @@ -1632,6 +1633,7 @@ CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y # CONFIG_TOUCHSCREEN_ZFORCE is not set # CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set # CONFIG_TOUCHSCREEN_VTL_CT36X is not set +# CONFIG_TOUCHSCREEN_GT1X is not set # CONFIG_ROCKCHIP_REMOTECTL is not set # @@ -2221,6 +2223,7 @@ CONFIG_MFD_CROS_EC_SPI=y # CONFIG_MFD_RT5033 is not set # CONFIG_MFD_RTSX_USB is not set # CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK618 is not set CONFIG_MFD_RK808=y # CONFIG_MFD_RN5T618 is not set # CONFIG_MFD_SEC_CORE is not set @@ -2434,14 +2437,15 @@ CONFIG_DRM_BRIDGE=y # # Display Interface Bridges # +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_RK1000 is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +CONFIG_DRM_ANALOGIX_DP=y CONFIG_DRM_DW_HDMI=y # CONFIG_DRM_DW_HDMI_AHB_AUDIO is not set CONFIG_DRM_DW_HDMI_I2S_AUDIO=y # CONFIG_DRM_DW_HDMI_CEC is not set -# CONFIG_DRM_NXP_PTN3460 is not set -# CONFIG_DRM_PARADE_PS8622 is not set -# CONFIG_DRM_RK1000 is not set -CONFIG_DRM_ANALOGIX_DP=y # CONFIG_DRM_STI is not set # CONFIG_POWERVR_ROGUE_M is not set # CONFIG_MALI400 is not set @@ -2688,6 +2692,7 @@ CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_CS42XX8_I2C is not set # CONFIG_SND_SOC_CS4349 is not set # CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_CX20810 is not set # CONFIG_SND_SOC_BT_SCO is not set # CONFIG_SND_SOC_ES8316 is not set CONFIG_SND_SOC_ES8323=y @@ -3115,6 +3120,8 @@ CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_EMBEDDED_SDIO is not set # CONFIG_MMC_PARANOID_SD_INIT is not set +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y # # MMC/SD/SDIO Card Drivers @@ -3499,6 +3506,7 @@ CONFIG_DW_APB_TIMER_OF=y CONFIG_ROCKCHIP_TIMER=y CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_VCT_ACCESS=y CONFIG_ARM_GLOBAL_TIMER=y # CONFIG_ARM_TIMER_SP804 is not set CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y @@ -3557,8 +3565,10 @@ CONFIG_DEVFREQ_GOV_USERSPACE=y # # DEVFREQ Drivers # -# CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ is not set -# CONFIG_PM_DEVFREQ_EVENT is not set +CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP=y # CONFIG_EXTCON is not set CONFIG_MEMORY=y # CONFIG_ARM_PL172_MPMC is not set diff --git a/projects/Rockchip/devices/TinkerBoard/patches/linux/rockchip-4.4/linux-0001-miniarm.patch b/projects/Rockchip/devices/TinkerBoard/patches/linux/rockchip-4.4/linux-0001-miniarm.patch index 9c4e190312..288827377f 100644 --- a/projects/Rockchip/devices/TinkerBoard/patches/linux/rockchip-4.4/linux-0001-miniarm.patch +++ b/projects/Rockchip/devices/TinkerBoard/patches/linux/rockchip-4.4/linux-0001-miniarm.patch @@ -1,7 +1,7 @@ -From 0d7fc599ad0450f8f8581b66dc77df80bb2ba6b9 Mon Sep 17 00:00:00 2001 +From 61d54b00c343c81af975a9742c17a01e4c343a31 Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Fri, 23 Sep 2016 13:43:18 +0800 -Subject: [PATCH 1/5] MINIARM: HACK: switch vccio_sd to 3.3v while shutdowning +Subject: [PATCH] MINIARM: HACK: switch vccio_sd to 3.3v while shutdowning Change-Id: I80d6d2b61b31f16b6b42b9ffcaab077231a7a91c Signed-off-by: Ziyuan Xu @@ -46,11 +46,11 @@ index 29e3ae99edbc..531ad93ff912 100644 .name = "dwmmc_rockchip", .of_match_table = dw_mci_rockchip_match, -From fe3a39115dbd63aee25d3aec6d46e4aed4f8faeb Mon Sep 17 00:00:00 2001 +From 834b425c19718d57c528806800a90ea0ac528472 Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Mon, 6 Feb 2017 08:39:46 +0800 -Subject: [PATCH 2/5] MINIARM: HACK: mmc: dw_mmc-rockchip: enable vmmc supply - for reboot +Subject: [PATCH] MINIARM: HACK: mmc: dw_mmc-rockchip: enable vmmc supply for + reboot Mmc core has already power off the vmmc since shutdown, re-enable it so that card is active in next reboot. @@ -87,10 +87,10 @@ index 531ad93ff912..eae304077e17 100644 if (!IS_ERR(mmc->supply.vqmmc)) regulator_set_voltage(mmc->supply.vqmmc, 3000000, 3300000); -From d1a6f5f0e4103138b4ef21bf89a54c90ba022bb9 Mon Sep 17 00:00:00 2001 +From ae8ebf01d7ff8e736cf85a720597ca9c94a1709a Mon Sep 17 00:00:00 2001 From: Jacob Chen Date: Sat, 22 Jul 2017 19:55:09 +0800 -Subject: [PATCH 3/5] MINIARM: drm/rockchip: update phy settings +Subject: [PATCH] MINIARM: drm/rockchip: update phy settings Change-Id: I9e92a4191115e13999183a5d7656d6708adda632 Signed-off-by: Jacob Chen @@ -99,10 +99,10 @@ Signed-off-by: Jacob Chen 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index b3b6fd7ed698..7b13c633e28f 100644 +index 257d0d0dcc3d..0c66a27bea93 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -343,8 +343,7 @@ static struct dw_hdmi_phy_config rockchip_phy_config[] = { +@@ -345,8 +345,7 @@ static struct dw_hdmi_phy_config rockchip_phy_config[] = { /*pixelclk symbol term vlev*/ { 74250000, 0x8009, 0x0004, 0x0272}, { 165000000, 0x802b, 0x0004, 0x0209}, @@ -113,10 +113,10 @@ index b3b6fd7ed698..7b13c633e28f 100644 }; -From e47a2375fceb317e4be6e6f6c83a4ec0ff7ad05c Mon Sep 17 00:00:00 2001 +From 79fb3a561bf55774b571c737537cada202f78044 Mon Sep 17 00:00:00 2001 From: Nickey Yang Date: Mon, 17 Jul 2017 16:35:34 +0800 -Subject: [PATCH 4/5] MINIARM: set npll be used for hdmi only +Subject: [PATCH] MINIARM: set npll be used for hdmi only Change-Id: I8bebfb2cfb68e3dad172e5547d3886526ad5e912 Signed-off-by: Nickey Yang @@ -126,10 +126,10 @@ Signed-off-by: Nickey Yang 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi -index 026288e9a2c9..7660a5e6ee95 100644 +index 0af92bd2a723..70f8a69cc9bd 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi -@@ -979,7 +979,7 @@ +@@ -1027,7 +1027,7 @@ <&cru PCLK_PERI>; assigned-clock-rates = <594000000>, <500000000>, <300000000>, @@ -138,7 +138,7 @@ index 026288e9a2c9..7660a5e6ee95 100644 <300000000>, <150000000>, <75000000>; }; -@@ -1201,6 +1201,8 @@ +@@ -1265,6 +1265,8 @@ resets = <&cru SRST_LCDC0_AXI>, <&cru SRST_LCDC0_AHB>, <&cru SRST_LCDC0_DCLK>; reset-names = "axi", "ahb", "dclk"; iommus = <&vopb_mmu>; @@ -148,7 +148,7 @@ index 026288e9a2c9..7660a5e6ee95 100644 vopb_out: port { diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c -index aedbb038c707..46bb0ae76839 100644 +index 72797f9479db..f79ebd843379 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -211,9 +211,9 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { @@ -173,17 +173,17 @@ index aedbb038c707..46bb0ae76839 100644 RK3288_CLKGATE_CON(3), 1, GFLAGS), COMPOSITE(DCLK_VOP1, "dclk_vop1", mux_pll_src_cpll_gpll_npll_p, 0, -From 6b9c7604687e5dac7116a40179228be268ea9067 Mon Sep 17 00:00:00 2001 +From 559fff078aedf673e1e4e191ec9a5eddc2a87f88 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 11 Dec 2017 23:09:54 +0100 -Subject: [PATCH 5/5] clk: rockchip: rk3288: add more pixel clock rates +Subject: [PATCH] clk: rockchip: rk3288: add more pixel clock rates --- drivers/clk/rockchip/clk-rk3288.c | 79 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c -index 46bb0ae76839..848025559aa8 100644 +index f79ebd843379..412a0165ec57 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -84,23 +84,94 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = { diff --git a/projects/Rockchip/linux/rockchip-4.4/linux.aarch64.conf b/projects/Rockchip/linux/rockchip-4.4/linux.aarch64.conf index f0b92a7106..f064a54541 100644 --- a/projects/Rockchip/linux/rockchip-4.4/linux.aarch64.conf +++ b/projects/Rockchip/linux/rockchip-4.4/linux.aarch64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.103 Kernel Configuration +# Linux/arm64 4.4.112 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -458,6 +458,7 @@ CONFIG_SECCOMP=y # CONFIG_CRASH_DUMP is not set # CONFIG_XEN is not set CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_UNMAP_KERNEL_AT_EL0=y # CONFIG_ARMV8_DEPRECATED is not set # CONFIG_ARM64_SW_TTBR0_PAN is not set @@ -1533,15 +1534,15 @@ CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RTL_CARDS is not set # CONFIG_RTL8XXXU is not set CONFIG_WL_ROCKCHIP=y -# CONFIG_WIFI_BUILD_MODULE is not set +CONFIG_WIFI_BUILD_MODULE=y # CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP is not set -# CONFIG_AP6XXX is not set +CONFIG_AP6XXX=m CONFIG_RTL_WIRELESS_SOLUTION=y # CONFIG_RTL8188EU is not set # CONFIG_RTL8188FU is not set # CONFIG_RTL8189ES is not set -# CONFIG_RTL8189FS is not set -# CONFIG_RTL8723BS is not set +CONFIG_RTL8189FS=m +CONFIG_RTL8723BS=m # CONFIG_RTL8723BU is not set # CONFIG_RTL8723CS is not set # CONFIG_RTL8723DS is not set @@ -1686,6 +1687,7 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y # CONFIG_TOUCHSCREEN_GSLX680_VR is not set # CONFIG_TOUCHSCREEN_GSLX680_FIREFLY is not set # CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_GSL3673_800X1280 is not set # CONFIG_TOUCHSCREEN_GT9XX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_GUNZE is not set @@ -1736,6 +1738,7 @@ CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y # CONFIG_TOUCHSCREEN_ZFORCE is not set # CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set # CONFIG_TOUCHSCREEN_VTL_CT36X is not set +# CONFIG_TOUCHSCREEN_GT1X is not set # CONFIG_ROCKCHIP_REMOTECTL is not set # @@ -2376,6 +2379,7 @@ CONFIG_MFD_CROS_EC_SPI=y # CONFIG_MFD_RT5033 is not set # CONFIG_MFD_RTSX_USB is not set # CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK618 is not set CONFIG_MFD_RK808=y # CONFIG_MFD_RN5T618 is not set # CONFIG_MFD_SEC_CORE is not set @@ -2598,14 +2602,15 @@ CONFIG_DRM_BRIDGE=y # # Display Interface Bridges # +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_RK1000 is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +CONFIG_DRM_ANALOGIX_DP=y CONFIG_DRM_DW_HDMI=y # CONFIG_DRM_DW_HDMI_AHB_AUDIO is not set CONFIG_DRM_DW_HDMI_I2S_AUDIO=y CONFIG_DRM_DW_HDMI_CEC=y -# CONFIG_DRM_NXP_PTN3460 is not set -# CONFIG_DRM_PARADE_PS8622 is not set -# CONFIG_DRM_RK1000 is not set -CONFIG_DRM_ANALOGIX_DP=y # CONFIG_POWERVR_ROGUE_M is not set CONFIG_MALI400=m CONFIG_MALI450=y @@ -2873,6 +2878,7 @@ CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_CS42XX8_I2C is not set # CONFIG_SND_SOC_CS4349 is not set # CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_CX20810 is not set # CONFIG_SND_SOC_BT_SCO is not set CONFIG_SND_SOC_ES8316=y # CONFIG_SND_SOC_ES8323 is not set @@ -3323,6 +3329,8 @@ CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_EMBEDDED_SDIO is not set # CONFIG_MMC_PARANOID_SD_INIT is not set +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y # # MMC/SD/SDIO Card Drivers @@ -3721,6 +3729,7 @@ CONFIG_CLKSRC_PROBE=y CONFIG_ROCKCHIP_TIMER=y CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set # CONFIG_ARM_TIMER_SP804 is not set # CONFIG_ATMEL_PIT is not set # CONFIG_SH_TIMER_CMT is not set @@ -3783,10 +3792,10 @@ CONFIG_DEVFREQ_GOV_USERSPACE=y # # DEVFREQ Drivers # -# CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ is not set +CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y CONFIG_PM_DEVFREQ_EVENT=y -# CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI is not set -# CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP is not set +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP=y CONFIG_EXTCON=y # diff --git a/projects/Rockchip/linux/rockchip-4.4/linux.arm.conf b/projects/Rockchip/linux/rockchip-4.4/linux.arm.conf index 3ccdeec7b9..e14a0b1b05 100644 --- a/projects/Rockchip/linux/rockchip-4.4/linux.arm.conf +++ b/projects/Rockchip/linux/rockchip-4.4/linux.arm.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.4.103 Kernel Configuration +# Linux/arm 4.4.112 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -1431,15 +1431,15 @@ CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RTL_CARDS is not set # CONFIG_RTL8XXXU is not set CONFIG_WL_ROCKCHIP=y -# CONFIG_WIFI_BUILD_MODULE is not set +CONFIG_WIFI_BUILD_MODULE=y # CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP is not set -# CONFIG_AP6XXX is not set +CONFIG_AP6XXX=m CONFIG_RTL_WIRELESS_SOLUTION=y # CONFIG_RTL8188EU is not set # CONFIG_RTL8188FU is not set # CONFIG_RTL8189ES is not set # CONFIG_RTL8189FS is not set -# CONFIG_RTL8723BS is not set +CONFIG_RTL8723BS=m # CONFIG_RTL8723BU is not set # CONFIG_RTL8723CS is not set # CONFIG_RTL8723DS is not set @@ -1582,6 +1582,7 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=y # CONFIG_TOUCHSCREEN_GSLX680_VR is not set # CONFIG_TOUCHSCREEN_GSLX680_FIREFLY is not set # CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_GSL3673_800X1280 is not set # CONFIG_TOUCHSCREEN_GT9XX is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_GUNZE is not set @@ -1632,6 +1633,7 @@ CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y # CONFIG_TOUCHSCREEN_ZFORCE is not set # CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set # CONFIG_TOUCHSCREEN_VTL_CT36X is not set +# CONFIG_TOUCHSCREEN_GT1X is not set # CONFIG_ROCKCHIP_REMOTECTL is not set # @@ -2221,6 +2223,7 @@ CONFIG_MFD_CROS_EC_SPI=y # CONFIG_MFD_RT5033 is not set # CONFIG_MFD_RTSX_USB is not set # CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK618 is not set CONFIG_MFD_RK808=y # CONFIG_MFD_RN5T618 is not set # CONFIG_MFD_SEC_CORE is not set @@ -2434,14 +2437,15 @@ CONFIG_DRM_BRIDGE=y # # Display Interface Bridges # +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_RK1000 is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +CONFIG_DRM_ANALOGIX_DP=y CONFIG_DRM_DW_HDMI=y # CONFIG_DRM_DW_HDMI_AHB_AUDIO is not set CONFIG_DRM_DW_HDMI_I2S_AUDIO=y # CONFIG_DRM_DW_HDMI_CEC is not set -# CONFIG_DRM_NXP_PTN3460 is not set -# CONFIG_DRM_PARADE_PS8622 is not set -# CONFIG_DRM_RK1000 is not set -CONFIG_DRM_ANALOGIX_DP=y # CONFIG_DRM_STI is not set # CONFIG_POWERVR_ROGUE_M is not set # CONFIG_MALI400 is not set @@ -2688,6 +2692,7 @@ CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_CS42XX8_I2C is not set # CONFIG_SND_SOC_CS4349 is not set # CONFIG_SND_SOC_CX2072X is not set +# CONFIG_SND_SOC_CX20810 is not set # CONFIG_SND_SOC_BT_SCO is not set # CONFIG_SND_SOC_ES8316 is not set CONFIG_SND_SOC_ES8323=y @@ -3115,6 +3120,8 @@ CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_EMBEDDED_SDIO is not set # CONFIG_MMC_PARANOID_SD_INIT is not set +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y # # MMC/SD/SDIO Card Drivers @@ -3499,6 +3506,7 @@ CONFIG_DW_APB_TIMER_OF=y CONFIG_ROCKCHIP_TIMER=y CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_VCT_ACCESS=y CONFIG_ARM_GLOBAL_TIMER=y # CONFIG_ARM_TIMER_SP804 is not set CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y @@ -3557,8 +3565,10 @@ CONFIG_DEVFREQ_GOV_USERSPACE=y # # DEVFREQ Drivers # -# CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ is not set -# CONFIG_PM_DEVFREQ_EVENT is not set +CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_NOCP=y # CONFIG_EXTCON is not set CONFIG_MEMORY=y # CONFIG_ARM_PL172_MPMC is not set diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0001-rockchip.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0001-rockchip.patch index 34f1292bb0..55c3275c2f 100644 --- a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0001-rockchip.patch +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0001-rockchip.patch @@ -1,3953 +1,7 @@ -From 2fd0d5bcaae905a4824a28ced4a953a580c74e62 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 13 Aug 2017 10:24:19 +0200 -Subject: [PATCH 01/46] arm: dts: rk3288-miniarm: update dts - ---- - arch/arm/boot/dts/rk3288-miniarm.dts | 26 ++++++++++++++++++++------ - 1 file changed, 20 insertions(+), 6 deletions(-) - -diff --git a/arch/arm/boot/dts/rk3288-miniarm.dts b/arch/arm/boot/dts/rk3288-miniarm.dts -index b746ad79b291..adeb3eeb51a7 100644 ---- a/arch/arm/boot/dts/rk3288-miniarm.dts -+++ b/arch/arm/boot/dts/rk3288-miniarm.dts -@@ -65,7 +65,7 @@ - wireless-wlan { - compatible = "wlan-platdata"; - rockchip,grf = <&grf>; -- wifi_chip_type = "ap6212"; -+ wifi_chip_type = "rtl8723bs"; - sdio_vref = <1800>; - WIFI,host_wake_irq = <&gpio4 30 GPIO_ACTIVE_HIGH>; - status = "okay"; -@@ -129,14 +129,14 @@ - - led1-led { - gpios=<&gpio1 25 GPIO_ACTIVE_HIGH>; -- linux,default-trigger="default-off"; -+ linux,default-trigger="heartbeat"; - }; - }; - - sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; -- simple-audio-card,name = "rockchip,miniarm-codec"; -+ simple-audio-card,name = "HDMI"; - simple-audio-card,mclk-fs = <512>; - simple-audio-card,cpu { - sound-dai = <&i2s>; -@@ -177,20 +177,33 @@ - cpu0-supply = <&vdd_cpu>; - }; - -+&cpu0_opp_table { -+ opp-1704000000 { -+ opp-hz = /bits/ 64 <1704000000>; -+ opp-microvolt = <1350000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1800000000 { -+ opp-hz = /bits/ 64 <1800000000>; -+ opp-microvolt = <1400000>; -+ clock-latency-ns = <40000>; -+ }; -+}; -+ - &gmac { - phy-supply = <&vcc33_lan>; - phy-mode = "rgmii"; - clock_in_out = "input"; - snps,reset-gpio = <&gpio4 7 0>; - snps,reset-active-low; -- snps,reset-delays-us = <0 10000 1000000>; -+ snps,reset-delays-us = <0 10000 50000>; - assigned-clocks = <&cru SCLK_MAC>; - assigned-clock-parents = <&ext_gmac>; - pinctrl-names = "default"; - pinctrl-0 = <&rgmii_pins>; - tx_delay = <0x30>; - rx_delay = <0x10>; -- status = "ok"; -+ status = "okay"; - }; - - &dsi0 { -@@ -468,6 +481,7 @@ - - &i2s { - #sound-dai-cells = <0>; -+ rockchip,bclk-fs = <128>; - status = "okay"; - }; - -@@ -491,7 +505,7 @@ - non-removable; - num-slots = <1>; - pinctrl-names = "default"; -- pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>; -+ pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk &sdio0_int>; - sd-uhs-sdr104; - supports-sdio; - }; - -From 5c0f628ab0345af1852e9b9544583d9df5ff34fc Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 13 Aug 2017 10:24:26 +0200 -Subject: [PATCH 02/46] arm64: dts: rockchip: rk3328: update dtsi - ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 27 ++++++++++++++++++++------- - 1 file changed, 20 insertions(+), 7 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index a88083f87bf4..8a730a25e58c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -86,6 +86,8 @@ - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x1>; -+ clocks = <&cru ARMCLK>; -+ dynamic-power-coefficient = <120>; - enable-method = "psci"; - operating-points-v2 = <&cpu0_opp_table>; - }; -@@ -93,6 +95,8 @@ - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x2>; -+ clocks = <&cru ARMCLK>; -+ dynamic-power-coefficient = <120>; - enable-method = "psci"; - operating-points-v2 = <&cpu0_opp_table>; - }; -@@ -100,6 +104,8 @@ - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x3>; -+ clocks = <&cru ARMCLK>; -+ dynamic-power-coefficient = <120>; - enable-method = "psci"; - operating-points-v2 = <&cpu0_opp_table>; - }; -@@ -109,6 +115,9 @@ - compatible = "operating-points-v2"; - opp-shared; - -+ nvmem-cells = <&cpu_leakage>; -+ nvmem-cell-names = "cpu_leakage"; -+ - opp-408000000 { - opp-hz = /bits/ 64 <408000000>; - opp-microvolt = <950000>; -@@ -165,7 +174,7 @@ - }; - - psci { -- compatible = "arm,psci-1.0"; -+ compatible = "arm,psci-1.0", "arm,psci-0.2"; - method = "smc"; - }; - -@@ -687,9 +696,11 @@ - <&cru SRST_VDEC_NIU_A>, <&cru SRST_VDEC_NIU_H>, - <&cru SRST_VDEC_CABAC>, <&cru SRST_VDEC_CORE>; - reset-names = "video_a", "video_h", "niu_a", "niu_h", -- "cabac", "video"; -+ "video_cabac", "video_core"; - rockchip,grf = <&grf>; - iommus = <&rkvdec_mmu>; -+ iommu_enabled = <1>; -+ dev_mode = <2>; - allocator = <1>; - power-domains = <&power RK3328_PD_VIDEO>; - status = "disabled"; -@@ -701,7 +712,7 @@ - interrupts = ; - interrupt-names = "rkvdec_mmu"; - clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; -- clock-names = "aclk_vcodec", "hclk_vcodec"; -+ clock-names = "aclk", "hclk"; - power-domains = <&power RK3328_PD_VIDEO>; - #iommu-cells = <0>; - }; -@@ -805,6 +816,8 @@ - reg = <0x0 0xff373f00 0x0 0x100>; - interrupts = ; - interrupt-names = "vop_mmu"; -+ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>; -+ clock-names = "aclk", "hclk"; - #iommu-cells = <0>; - status = "disabled"; - }; -@@ -1052,7 +1065,7 @@ - sdmmc: dwmmc@ff500000 { - compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xff500000 0x0 0x4000>; -- clock-freq-min-max = <400000 150000000>; -+ max-frequency = <150000000>; - clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>; - clock-names = "biu", "ciu"; - fifo-depth = <0x100>; -@@ -1063,7 +1076,7 @@ - sdio: dwmmc@ff510000 { - compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xff510000 0x0 0x4000>; -- clock-freq-min-max = <400000 150000000>; -+ max-frequency = <150000000>; - clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, - <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; - clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; -@@ -1075,7 +1088,7 @@ - emmc: dwmmc@ff520000 { - compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xff520000 0x0 0x4000>; -- clock-freq-min-max = <400000 150000000>; -+ max-frequency = <150000000>; - clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>; - clock-names = "biu", "ciu"; - fifo-depth = <0x100>; -@@ -1169,7 +1182,7 @@ - sdmmc_ext: dwmmc@ff5f0000 { - compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; - reg = <0x0 0xff5f0000 0x0 0x4000>; -- clock-freq-min-max = <400000 150000000>; -+ max-frequency = <150000000>; - clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>; - clock-names = "biu", "ciu"; - fifo-depth = <0x100>; - -From 4a447650937a1efbd3987468379368fa35fdc7d2 Mon Sep 17 00:00:00 2001 -From: LongChair -Date: Thu, 15 Jun 2017 21:00:59 +0200 -Subject: [PATCH 03/46] arm64: dts: rockchip: rk3328: add missing operating - performance point - ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index 8a730a25e58c..b2f312d1f662 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -654,6 +654,10 @@ - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <1100000>; - }; -+ opp-600000000 { -+ opp-hz = /bits/ 64 <600000000>; -+ opp-microvolt = <1150000>; -+ }; - }; - - vpu_service: vpu-service@ff350000 { - -From d0acfa1678807dea2a780ad6a9830a5a823387cb Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 13 Aug 2017 10:24:28 +0200 -Subject: [PATCH 04/46] arm64: dts: rockchip: add rk3328-box board - ---- - arch/arm64/boot/dts/rockchip/Makefile | 1 + - arch/arm64/boot/dts/rockchip/rk3328-box.dts | 498 ++++++++++++++++++++++++++++ - 2 files changed, 499 insertions(+) - create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-box.dts - -diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile -index f9034bf19a7a..67555a346b7e 100644 ---- a/arch/arm64/boot/dts/rockchip/Makefile -+++ b/arch/arm64/boot/dts/rockchip/Makefile -@@ -1,3 +1,4 @@ -+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-box.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb-android.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3366-fpga.dtb -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box.dts b/arch/arm64/boot/dts/rockchip/rk3328-box.dts -new file mode 100644 -index 000000000000..5b9dfb37469e ---- /dev/null -+++ b/arch/arm64/boot/dts/rockchip/rk3328-box.dts -@@ -0,0 +1,498 @@ -+/* -+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+/dts-v1/; -+#include "rk3328.dtsi" -+ -+/ { -+ model = "Rockchip RK3328 BOX"; -+ compatible = "rockchip,rk3328-box", "rockchip,rk3328"; -+ -+ chosen { -+ bootargs = "rockchip_jtag earlyprintk=uart8250-32bit,0xff130000"; -+ }; -+ -+ fiq-debugger { -+ compatible = "rockchip,fiq-debugger"; -+ rockchip,serial-id = <2>; -+ rockchip,signal-irq = <159>; -+ rockchip,wake-irq = <0>; -+ /* If enable uart uses irq instead of fiq */ -+ rockchip,irq-mode-enable = <0>; -+ rockchip,baudrate = <1500000>; /* Only 115200 and 1500000 */ -+ interrupts = ; -+ status = "okay"; -+ }; -+ -+ gmac_clkin: external-gmac-clock { -+ compatible = "fixed-clock"; -+ clock-frequency = <125000000>; -+ clock-output-names = "gmac_clkin"; -+ #clock-cells = <0>; -+ }; -+ -+ sdio_pwrseq: sdio-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_enable_h>; -+ -+ /* -+ * On the module itself this is one of these (depending -+ * on the actual card populated): -+ * - SDIO_RESET_L_WL_REG_ON -+ * - PDN (power down when low) -+ */ -+ reset-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; -+ }; -+ -+ hdmi-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,mclk-fs = <128>; -+ simple-audio-card,name = "HDMI"; -+ simple-audio-card,cpu { -+ sound-dai = <&i2s0>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ }; -+ -+ spdif-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "SPDIF"; -+ simple-audio-card,cpu { -+ sound-dai = <&spdif>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&spdif_out>; -+ }; -+ }; -+ -+ spdif_out: spdif-out { -+ compatible = "linux,spdif-dit"; -+ #sound-dai-cells = <0>; -+ }; -+ -+ vcc_phy: vcc-phy-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_phy"; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ vcc_sd: sdmmc-regulator { -+ compatible = "regulator-fixed"; -+ gpio = <&gpio0 30 GPIO_ACTIVE_LOW>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0m1_gpio>; -+ regulator-name = "vcc_sd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vcc_io>; -+ }; -+ -+ wireless-wlan { -+ compatible = "wlan-platdata"; -+ rockchip,grf = <&grf>; -+ wifi_chip_type = "rtl8188eu"; -+ sdio_vref = <1800>; -+ WIFI,poweren_gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>; -+ WIFI,host_wake_irq = <&gpio1 19 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ }; -+}; -+ -+&codec { -+ #sound-dai-cells = <0>; -+ status = "okay"; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&display_subsystem { -+ status = "okay"; -+}; -+ -+&emmc { -+ bus-width = <8>; -+ cap-mmc-highspeed; -+ supports-emmc; -+ disable-wp; -+ non-removable; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; -+ status = "okay"; -+}; -+ -+&gmac2io { -+ phy-supply = <&vcc_phy>; -+ phy-mode = "rgmii"; -+ clock_in_out = "input"; -+ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ snps,reset-delays-us = <0 10000 50000>; -+ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; -+ assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rgmiim1_pins>; -+ tx_delay = <0x26>; -+ rx_delay = <0x11>; -+ status = "disabled"; -+}; -+ -+&gmac2phy { -+ phy-supply = <&vcc_phy>; -+ clock_in_out = "output"; -+ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; -+ assigned-clock-rate = <50000000>; -+ assigned-clocks = <&cru SCLK_MAC2PHY>; -+ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; -+ status = "okay"; -+}; -+ -+&gpu { -+ status = "okay"; -+ mali-supply = <&vdd_logic>; -+}; -+ -+&hdmi { -+ #sound-dai-cells = <0>; -+ ddc-i2c-scl-high-time-ns = <9625>; -+ ddc-i2c-scl-low-time-ns = <10000>; -+ status = "okay"; -+}; -+ -+&hdmiphy { -+ status = "okay"; -+}; -+ -+&i2c1 { -+ status = "okay"; -+ -+ rk805: rk805@18 { -+ compatible = "rockchip,rk805"; -+ status = "okay"; -+ reg = <0x18>; -+ interrupt-parent = <&gpio2>; -+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_int_l>; -+ rockchip,system-power-controller; -+ wakeup-source; -+ gpio-controller; -+ #gpio-cells = <2>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; -+ -+ rtc { -+ status = "disabled"; -+ }; -+ -+ pwrkey { -+ status = "disabled"; -+ }; -+ -+ gpio { -+ status = "okay"; -+ }; -+ -+ regulators { -+ compatible = "rk805-regulator"; -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ vdd_logic: RK805_DCDC1@0 { -+ regulator-compatible = "RK805_DCDC1"; -+ regulator-name = "vdd_logic"; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-initial-mode = <0x1>; -+ regulator-ramp-delay = <12500>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ -+ vdd_arm: RK805_DCDC2@1 { -+ regulator-compatible = "RK805_DCDC2"; -+ regulator-name = "vdd_arm"; -+ regulator-init-microvolt = <1225000>; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-initial-mode = <0x1>; -+ regulator-ramp-delay = <12500>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <950000>; -+ }; -+ }; -+ -+ vcc_ddr: RK805_DCDC3@2 { -+ regulator-compatible = "RK805_DCDC3"; -+ regulator-name = "vcc_ddr"; -+ regulator-initial-mode = <0x1>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_io: RK805_DCDC4@3 { -+ regulator-compatible = "RK805_DCDC4"; -+ regulator-name = "vcc_io"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-initial-mode = <0x1>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vdd_18: RK805_LDO1@4 { -+ regulator-compatible = "RK805_LDO1"; -+ regulator-name = "vdd_18"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcc_18emmc: RK805_LDO2@5 { -+ regulator-compatible = "RK805_LDO2"; -+ regulator-name = "vcc_18emmc"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_10: RK805_LDO3@6 { -+ regulator-compatible = "RK805_LDO3"; -+ regulator-name = "vdd_10"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&h265e { -+ status = "okay"; -+}; -+ -+&i2s0 { -+ #sound-dai-cells = <0>; -+ rockchip,bclk-fs = <128>; -+ status = "okay"; -+}; -+ -+&io_domains { -+ status = "okay"; -+ -+ vccio1-supply = <&vcc_io>; -+ vccio2-supply = <&vcc_18emmc>; -+ vccio3-supply = <&vcc_io>; -+ vccio4-supply = <&vdd_18>; -+ vccio5-supply = <&vcc_io>; -+ vccio6-supply = <&vcc_io>; -+ pmuio-supply = <&vcc_io>; -+}; -+ -+&pinctrl { -+ pmic { -+ pmic_int_l: pmic-int-l { -+ rockchip,pins = -+ <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; /* gpio2_a6 */ -+ }; -+ }; -+ -+ sdio-pwrseq { -+ wifi_enable_h: wifi-enable-h { -+ rockchip,pins = -+ <1 18 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&rkvdec { -+ status = "okay"; -+}; -+ -+&sdio { -+ bus-width = <4>; -+ cap-sd-highspeed; -+ cap-sdio-irq; -+ disable-wp; -+ keep-power-in-suspend; -+ max-frequency = <150000000>; -+ mmc-pwrseq = <&sdio_pwrseq>; -+ non-removable; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; -+ supports-sdio; -+ status = "okay"; -+}; -+ -+&sdmmc { -+ bus-width = <4>; -+ cap-mmc-highspeed; -+ cap-sd-highspeed; -+ disable-wp; -+ max-frequency = <150000000>; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; -+ supports-sd; -+ status = "okay"; -+ vmmc-supply = <&vcc_sd>; -+}; -+ -+&spdif { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spdifm0_tx>; -+ #sound-dai-cells = <0>; -+ status = "okay"; -+}; -+ -+&tsadc { -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&u2phy { -+ otg-vbus-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ -+ u2phy_host: host-port { -+ status = "okay"; -+ }; -+ -+ u2phy_otg: otg-port { -+ status = "okay"; -+ }; -+}; -+ -+&u3phy { -+ vbus-drv-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+}; -+ -+&u3phy_utmi { -+ status = "okay"; -+}; -+ -+&u3phy_pipe { -+ status = "okay"; -+}; -+ -+&usb20_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usbdrd3 { -+ status = "okay"; -+}; -+ -+&usbdrd_dwc3 { -+ status = "okay"; -+}; -+ -+&vepu { -+ status = "okay"; -+}; -+ -+&vop { -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -+ -+&vpu_service { -+ status = "okay"; -+}; - -From cee160eea0818d70fffbc007652baf510d62d4cb Mon Sep 17 00:00:00 2001 -From: wlcheah -Date: Fri, 30 Jun 2017 12:27:25 +0800 -Subject: [PATCH 05/46] arm64: dts: rockchip: add rk3328-rock64 board - -(cherry picked from commit 8bbdca5562e9167d233c85655effde3c11ab6bf2) ---- - arch/arm64/boot/dts/rockchip/Makefile | 1 + - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 494 +++++++++++++++++++++++++ - 2 files changed, 495 insertions(+) - create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-rock64.dts - -diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile -index 67555a346b7e..bfb6053389d2 100644 ---- a/arch/arm64/boot/dts/rockchip/Makefile -+++ b/arch/arm64/boot/dts/rockchip/Makefile -@@ -1,6 +1,7 @@ - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-box.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb-android.dtb -+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3366-fpga.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3366-sheep.dtb - dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -new file mode 100644 -index 000000000000..e496c5697f02 ---- /dev/null -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -0,0 +1,494 @@ -+/* -+ * Copyright (c) 2017 PINE64 -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+/dts-v1/; -+#include "rk3328.dtsi" -+ -+/ { -+ model = "Pine64 Rock64"; -+ compatible = "pine64,rock64", "rockchip,rk3328"; -+ -+ chosen { -+ bootargs = "rockchip_jtag earlyprintk=uart8250-32bit,0xff130000"; -+ }; -+ -+ fiq-debugger { -+ compatible = "rockchip,fiq-debugger"; -+ rockchip,serial-id = <2>; -+ rockchip,signal-irq = <159>; -+ rockchip,wake-irq = <0>; -+ /* If enable uart uses irq instead of fiq */ -+ rockchip,irq-mode-enable = <0>; -+ rockchip,baudrate = <1500000>; /* Only 115200 and 1500000 */ -+ interrupts = ; -+ status = "okay"; -+ }; -+ -+ gmac_clkin: external-gmac-clock { -+ compatible = "fixed-clock"; -+ clock-frequency = <125000000>; -+ clock-output-names = "gmac_clkin"; -+ #clock-cells = <0>; -+ }; -+ -+ sdio_pwrseq: sdio-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_enable_h>; -+ -+ /* -+ * On the module itself this is one of these (depending -+ * on the actual card populated): -+ * - SDIO_RESET_L_WL_REG_ON -+ * - PDN (power down when low) -+ */ -+ reset-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; -+ }; -+ -+ sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,mclk-fs = <256>; -+ simple-audio-card,name = "rockchip,rk3328"; -+ simple-audio-card,cpu { -+ sound-dai = <&i2s1>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&codec>; -+ }; -+ }; -+ -+ hdmi-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,mclk-fs = <128>; -+ simple-audio-card,name = "rockchip,hdmi"; -+ simple-audio-card,cpu { -+ sound-dai = <&i2s0>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ }; -+ -+ spdif-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "rockchip,spdif"; -+ simple-audio-card,cpu { -+ sound-dai = <&spdif>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&spdif_out>; -+ }; -+ }; -+ -+ spdif_out: spdif-out { -+ compatible = "linux,spdif-dit"; -+ #sound-dai-cells = <0>; -+ }; -+ -+ vcc_phy: vcc-phy-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_phy"; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ vcc_sd: sdmmc-regulator { -+ compatible = "regulator-fixed"; -+ gpio = <&gpio0 30 GPIO_ACTIVE_LOW>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0m1_gpio>; -+ regulator-name = "vcc_sd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vcc_io>; -+ }; -+ -+ wireless-wlan { -+ compatible = "wlan-platdata"; -+ rockchip,grf = <&grf>; -+ wifi_chip_type = "ap6354"; -+ sdio_vref = <1800>; -+ WIFI,host_wake_irq = <&gpio1 19 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ }; -+}; -+ -+&codec { -+ #sound-dai-cells = <0>; -+ status = "okay"; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&display_subsystem { -+ status = "okay"; -+}; -+ -+&emmc { -+ bus-width = <8>; -+ cap-mmc-highspeed; -+ supports-emmc; -+ disable-wp; -+ non-removable; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; -+ status = "okay"; -+}; -+ -+&gmac2io { -+ phy-supply = <&vcc_phy>; -+ phy-mode = "rgmii"; -+ clock_in_out = "input"; -+ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ snps,reset-delays-us = <0 10000 50000>; -+ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; -+ assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rgmiim1_pins>; -+ tx_delay = <0x26>; -+ rx_delay = <0x11>; -+ status = "okay"; -+}; -+ -+&gpu { -+ status = "okay"; -+ mali-supply = <&vdd_logic>; -+}; -+ -+&hdmi { -+ #sound-dai-cells = <0>; -+ ddc-i2c-scl-high-time-ns = <9625>; -+ ddc-i2c-scl-low-time-ns = <10000>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ status = "okay"; -+ -+ rk805: rk805@18 { -+ compatible = "rockchip,rk805"; -+ status = "okay"; -+ reg = <0x18>; -+ interrupt-parent = <&gpio2>; -+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_int_l>; -+ rockchip,system-power-controller; -+ wakeup-source; -+ gpio-controller; -+ #gpio-cells = <2>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; -+ -+ rtc { -+ status = "disabled"; -+ }; -+ -+ pwrkey { -+ status = "disabled"; -+ }; -+ -+ gpio { -+ status = "okay"; -+ }; -+ -+ regulators { -+ compatible = "rk805-regulator"; -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ vdd_logic: RK805_DCDC1@0 { -+ regulator-compatible = "RK805_DCDC1"; -+ regulator-name = "vdd_logic"; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-initial-mode = <0x1>; -+ regulator-ramp-delay = <12500>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ -+ vdd_arm: RK805_DCDC2@1 { -+ regulator-compatible = "RK805_DCDC2"; -+ regulator-name = "vdd_arm"; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-initial-mode = <0x1>; -+ regulator-ramp-delay = <12500>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <950000>; -+ }; -+ }; -+ -+ vcc_ddr: RK805_DCDC3@2 { -+ regulator-compatible = "RK805_DCDC3"; -+ regulator-name = "vcc_ddr"; -+ regulator-initial-mode = <0x1>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_io: RK805_DCDC4@3 { -+ regulator-compatible = "RK805_DCDC4"; -+ regulator-name = "vcc_io"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-initial-mode = <0x1>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vdd_18: RK805_LDO1@4 { -+ regulator-compatible = "RK805_LDO1"; -+ regulator-name = "vdd_18"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcc_18emmc: RK805_LDO2@5 { -+ regulator-compatible = "RK805_LDO2"; -+ regulator-name = "vcc_18emmc"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_10: RK805_LDO3@6 { -+ regulator-compatible = "RK805_LDO3"; -+ regulator-name = "vdd_10"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&h265e { -+ status = "okay"; -+}; -+ -+&i2s0 { -+ #sound-dai-cells = <0>; -+ rockchip,bclk-fs = <128>; -+ status = "okay"; -+}; -+ -+&i2s1 { -+ #sound-dai-cells = <0>; -+ status = "okay"; -+}; -+ -+&io_domains { -+ status = "okay"; -+ -+ vccio1-supply = <&vcc_io>; -+ vccio2-supply = <&vcc_18emmc>; -+ vccio3-supply = <&vcc_io>; -+ vccio4-supply = <&vdd_18>; -+ vccio5-supply = <&vcc_io>; -+ vccio6-supply = <&vcc_io>; -+ pmuio-supply = <&vcc_io>; -+}; -+ -+&pinctrl { -+ pmic { -+ pmic_int_l: pmic-int-l { -+ rockchip,pins = -+ <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; /* gpio2_a6 */ -+ }; -+ }; -+ -+ sdio-pwrseq { -+ wifi_enable_h: wifi-enable-h { -+ rockchip,pins = -+ <1 18 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&rkvdec { -+ status = "okay"; -+}; -+ -+&sdio { -+ bus-width = <4>; -+ cap-sd-highspeed; -+ cap-sdio-irq; -+ disable-wp; -+ keep-power-in-suspend; -+ max-frequency = <150000000>; -+ mmc-pwrseq = <&sdio_pwrseq>; -+ non-removable; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; -+ supports-sdio; -+ status = "disabled"; -+}; -+ -+&sdmmc { -+ bus-width = <4>; -+ cap-mmc-highspeed; -+ cap-sd-highspeed; -+ disable-wp; -+ max-frequency = <150000000>; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; -+ supports-sd; -+ status = "okay"; -+ vmmc-supply = <&vcc_sd>; -+}; -+ -+&spdif { -+ #sound-dai-cells = <0>; -+ status = "okay"; -+}; -+ -+&tsadc { -+ status = "okay"; -+}; -+ -+&u2phy { -+ otg-vbus-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ -+ u2phy_host: host-port { -+ status = "okay"; -+ }; -+ -+ u2phy_otg: otg-port { -+ status = "okay"; -+ }; -+}; -+ -+&u3phy { -+ vbus-drv-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+}; -+ -+&u3phy_utmi { -+ status = "okay"; -+}; -+ -+&u3phy_pipe { -+ status = "okay"; -+}; -+ -+&usb20_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usbdrd3 { -+ status = "okay"; -+}; -+ -+&usbdrd_dwc3 { -+ status = "okay"; -+}; -+ -+&vepu { -+ status = "okay"; -+}; -+ -+&vop { -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -+ -+&vpu_service { -+ status = "okay"; -+}; - -From 1cb90bcdf95c3bc91d8cfa780e514e3b528e9f82 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 13 Aug 2017 10:24:29 +0200 -Subject: [PATCH 06/46] arm64: dts: rockchip: rk3328-rock64: sync with - ayufan-rock64 - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 116 ++++++++++++++----------- - 1 file changed, 67 insertions(+), 49 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index e496c5697f02..d0a94f448c66 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -70,20 +70,6 @@ - #clock-cells = <0>; - }; - -- sdio_pwrseq: sdio-pwrseq { -- compatible = "mmc-pwrseq-simple"; -- pinctrl-names = "default"; -- pinctrl-0 = <&wifi_enable_h>; -- -- /* -- * On the module itself this is one of these (depending -- * on the actual card populated): -- * - SDIO_RESET_L_WL_REG_ON -- * - PDN (power down when low) -- */ -- reset-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; -- }; -- - sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; -@@ -143,15 +129,6 @@ - regulator-max-microvolt = <3300000>; - vin-supply = <&vcc_io>; - }; -- -- wireless-wlan { -- compatible = "wlan-platdata"; -- rockchip,grf = <&grf>; -- wifi_chip_type = "ap6354"; -- sdio_vref = <1800>; -- WIFI,host_wake_irq = <&gpio1 19 GPIO_ACTIVE_HIGH>; -- status = "okay"; -- }; - }; - - &codec { -@@ -170,13 +147,20 @@ - &emmc { - bus-width = <8>; - cap-mmc-highspeed; -- supports-emmc; -+ clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, -+ <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; -+ clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; - disable-wp; -+ max-frequency = <200000000>; -+ mmc-hs200-1_8v; - non-removable; - num-slots = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; - status = "okay"; -+ supports-emmc; -+ vmmc-supply = <&vcc_io>; -+ vqmmc-supply = <&vcc_18emmc>; - }; - - &gmac2io { -@@ -226,11 +210,11 @@ - clock-output-names = "xin32k", "rk805-clkout2"; - - rtc { -- status = "disabled"; -+ status = "okay"; - }; - - pwrkey { -- status = "disabled"; -+ status = "okay"; - }; - - gpio { -@@ -344,6 +328,62 @@ - }; - }; - -+&spi0 { -+ status = "okay"; -+ -+ /* SPI DMA does not work currently */ -+ /delete-property/ dmas; -+ /delete-property/ #dma-cells; -+ /delete-property/ dma-names; -+ -+ gd25q128@0 { -+ #address-cells = <0x1>; -+ #size-cells = <0x0>; -+ compatible = "jedec,spi-nor"; -+ reg = <0x0>; -+ spi-max-frequency = <25000000>; -+ status = "okay"; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ system@0 { -+ label = "system"; -+ reg = <0x0 0x8000>; -+ read-only; -+ }; -+ -+ loader@8000 { -+ label = "loader"; -+ reg = <0x8000 0x3F8000>; -+ }; -+ -+ reserved@400000 { -+ label = "reserved"; -+ reg = <0x400000 0x3C0000>; -+ read-only; -+ }; -+ -+ vendor@7c0000 { -+ label = "vendor"; -+ reg = <0x7C0000 0x40000>; -+ }; -+ -+ uboot@800000 { -+ label = "uboot"; -+ reg = <0x800000 0x400000>; -+ }; -+ -+ atf@c00000 { -+ label = "atf"; -+ reg = <0xC00000 0x400000>; -+ }; -+ }; -+ }; -+}; -+ - &h265e { - status = "okay"; - }; -@@ -378,35 +418,12 @@ - <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; /* gpio2_a6 */ - }; - }; -- -- sdio-pwrseq { -- wifi_enable_h: wifi-enable-h { -- rockchip,pins = -- <1 18 RK_FUNC_GPIO &pcfg_pull_none>; -- }; -- }; - }; - - &rkvdec { - status = "okay"; - }; - --&sdio { -- bus-width = <4>; -- cap-sd-highspeed; -- cap-sdio-irq; -- disable-wp; -- keep-power-in-suspend; -- max-frequency = <150000000>; -- mmc-pwrseq = <&sdio_pwrseq>; -- non-removable; -- num-slots = <1>; -- pinctrl-names = "default"; -- pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; -- supports-sdio; -- status = "disabled"; --}; -- - &sdmmc { - bus-width = <4>; - cap-mmc-highspeed; -@@ -419,6 +436,7 @@ - supports-sd; - status = "okay"; - vmmc-supply = <&vcc_sd>; -+ vqmmc-supply = <&vcc_sd>; - }; - - &spdif { - -From 50f3bb6a6595dfd3e1b6cff5427fbbd770ccf012 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 13 Aug 2017 10:24:31 +0200 -Subject: [PATCH 07/46] arm64: dts: rockchip: rk3328-rock64: sync with mainline - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 34 +++++++++++++++++++------- - 1 file changed, 25 insertions(+), 9 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index d0a94f448c66..ea79630a0107 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -129,6 +129,15 @@ - regulator-max-microvolt = <3300000>; - vin-supply = <&vcc_io>; - }; -+ -+ vcc_sys: vcc-sys { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; - }; - - &codec { -@@ -160,7 +169,7 @@ - status = "okay"; - supports-emmc; - vmmc-supply = <&vcc_io>; -- vqmmc-supply = <&vcc_18emmc>; -+ vqmmc-supply = <&vcc18_emmc>; - }; - - &gmac2io { -@@ -200,14 +209,21 @@ - reg = <0x18>; - interrupt-parent = <&gpio2>; - interrupts = <6 IRQ_TYPE_LEVEL_LOW>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; - pinctrl-names = "default"; - pinctrl-0 = <&pmic_int_l>; - rockchip,system-power-controller; - wakeup-source; - gpio-controller; - #gpio-cells = <2>; -- #clock-cells = <1>; -- clock-output-names = "xin32k", "rk805-clkout2"; -+ -+ vcc1-supply = <&vcc_sys>; -+ vcc2-supply = <&vcc_sys>; -+ vcc3-supply = <&vcc_sys>; -+ vcc4-supply = <&vcc_sys>; -+ vcc5-supply = <&vcc_io>; -+ vcc6-supply = <&vcc_sys>; - - rtc { - status = "okay"; -@@ -286,9 +302,9 @@ - }; - }; - -- vdd_18: RK805_LDO1@4 { -+ vcc_18: RK805_LDO1@4 { - regulator-compatible = "RK805_LDO1"; -- regulator-name = "vdd_18"; -+ regulator-name = "vcc_18"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; -@@ -299,9 +315,9 @@ - }; - }; - -- vcc_18emmc: RK805_LDO2@5 { -+ vcc18_emmc: RK805_LDO2@5 { - regulator-compatible = "RK805_LDO2"; -- regulator-name = "vcc_18emmc"; -+ regulator-name = "vcc18_emmc"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; -@@ -403,9 +419,9 @@ - status = "okay"; - - vccio1-supply = <&vcc_io>; -- vccio2-supply = <&vcc_18emmc>; -+ vccio2-supply = <&vcc18_emmc>; - vccio3-supply = <&vcc_io>; -- vccio4-supply = <&vdd_18>; -+ vccio4-supply = <&vcc_18>; - vccio5-supply = <&vcc_io>; - vccio6-supply = <&vcc_io>; - pmuio-supply = <&vcc_io>; - -From 132f64c54b6ffeaf43e21b820d0e2e0cb65cdc28 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 13 Aug 2017 10:24:32 +0200 -Subject: [PATCH 08/46] arm64: dts: rockchip: rk3328-rock64: add hdmiphy - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index ea79630a0107..d48360162ab6 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -200,6 +200,10 @@ - status = "okay"; - }; - -+&hdmiphy { -+ status = "okay"; -+}; -+ - &i2c1 { - status = "okay"; - - -From 5d2887b0975c3d4549b1bccfe383f7916f09b00b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 13 Aug 2017 10:24:33 +0200 -Subject: [PATCH 09/46] arm64: dts: rockchip: rk3328-rock64: add gpio-leds - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index d48360162ab6..dcf071a9d61b 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -70,6 +70,30 @@ - #clock-cells = <0>; - }; - -+ leds { -+ compatible = "gpio-leds"; -+ -+ standby-led { -+ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ power-led { -+ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "mmc0"; -+ }; -+ }; -+ -+ switches { -+ compatible = "gpio-leds"; -+ -+ usb-switch { -+ default-state = "on"; -+ gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "none"; -+ }; -+ }; -+ - sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - -From 1bbf80391c2ffc30ca906c630a1ae79a2dcd899a Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 13 Aug 2017 10:24:36 +0200 -Subject: [PATCH 10/46] arm64: dts: rockchip: rk3328-rock64: rename and reorder - sound - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index dcf071a9d61b..5ebdd0f624ab 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -94,35 +94,35 @@ - }; - }; - -- sound { -+ hdmi-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; -- simple-audio-card,mclk-fs = <256>; -- simple-audio-card,name = "rockchip,rk3328"; -+ simple-audio-card,mclk-fs = <128>; -+ simple-audio-card,name = "HDMI"; - simple-audio-card,cpu { -- sound-dai = <&i2s1>; -+ sound-dai = <&i2s0>; - }; - simple-audio-card,codec { -- sound-dai = <&codec>; -+ sound-dai = <&hdmi>; - }; - }; - -- hdmi-sound { -+ sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; -- simple-audio-card,mclk-fs = <128>; -- simple-audio-card,name = "rockchip,hdmi"; -+ simple-audio-card,mclk-fs = <256>; -+ simple-audio-card,name = "ACODEC"; - simple-audio-card,cpu { -- sound-dai = <&i2s0>; -+ sound-dai = <&i2s1>; - }; - simple-audio-card,codec { -- sound-dai = <&hdmi>; -+ sound-dai = <&codec>; - }; - }; - - spdif-sound { - compatible = "simple-audio-card"; -- simple-audio-card,name = "rockchip,spdif"; -+ simple-audio-card,name = "SPDIF"; - simple-audio-card,cpu { - sound-dai = <&spdif>; - }; - -From 02ed81c1adee71d774a857dd4cd286fbeb1c6f6b Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 27 Aug 2017 20:50:55 +0200 -Subject: [PATCH 11/46] arm64: dts: rockchip: rk3328-rock64: add i2s1 and spdif - pinctrl - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index 5ebdd0f624ab..e76c31cf901e 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -439,6 +439,16 @@ - }; - - &i2s1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s1_mclk -+ &i2s1_sclk -+ &i2s1_lrcktx -+ &i2s1_lrckrx -+ &i2s1_sdo -+ &i2s1_sdi -+ &i2s1_sdio1 -+ &i2s1_sdio2 -+ &i2s1_sdio3>; - #sound-dai-cells = <0>; - status = "okay"; - }; -@@ -484,6 +494,8 @@ - }; - - &spdif { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spdifm0_tx>; - #sound-dai-cells = <0>; - status = "okay"; - }; - -From ecac1221e0a0960f6384c568feaf6b04ad68dded Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 30 Oct 2017 22:29:06 +0100 -Subject: [PATCH 12/46] arm64: dts: rockchip: rk3328-rock64: add uart2 - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index e76c31cf901e..7c2041eafb62 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -504,6 +504,10 @@ - status = "okay"; - }; - -+&uart2 { -+ status = "okay"; -+}; -+ - &u2phy { - otg-vbus-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; - status = "okay"; - -From ee1285ac3c958d704a1977b7cb89916245e335a6 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 30 Oct 2017 23:02:39 +0100 -Subject: [PATCH 13/46] arm64: dts: rockchip: add rk3328-rockbox board - ---- - arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts | 536 ++++++++++++++++++++++++ - 1 file changed, 536 insertions(+) - create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -new file mode 100644 -index 000000000000..8ac8a8cc04ed ---- /dev/null -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -@@ -0,0 +1,536 @@ -+/* -+ * Copyright (c) 2017 PINE64 -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+/dts-v1/; -+#include "rk3328.dtsi" -+ -+/ { -+ model = "Pine64 RockBox"; -+ compatible = "pine64,rockbox", "rockchip,rk3328"; -+ -+ chosen { -+ bootargs = "rockchip_jtag earlyprintk=uart8250-32bit,0xff130000"; -+ }; -+ -+ fiq-debugger { -+ compatible = "rockchip,fiq-debugger"; -+ rockchip,serial-id = <2>; -+ rockchip,signal-irq = <159>; -+ rockchip,wake-irq = <0>; -+ /* If enable uart uses irq instead of fiq */ -+ rockchip,irq-mode-enable = <0>; -+ rockchip,baudrate = <1500000>; /* Only 115200 and 1500000 */ -+ interrupts = ; -+ status = "okay"; -+ }; -+ -+ gmac_clkin: external-gmac-clock { -+ compatible = "fixed-clock"; -+ clock-frequency = <125000000>; -+ clock-output-names = "gmac_clkin"; -+ #clock-cells = <0>; -+ }; -+ -+ sdio_pwrseq: sdio-pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_enable_h>; -+ -+ /* -+ * On the module itself this is one of these (depending -+ * on the actual card populated): -+ * - SDIO_RESET_L_WL_REG_ON -+ * - PDN (power down when low) -+ */ -+ reset-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ standby-led { -+ gpios = <&rk805 0 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ power-led { -+ gpios = <&rk805 1 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "mmc0"; -+ }; -+ }; -+ -+ hdmi-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,mclk-fs = <128>; -+ simple-audio-card,name = "HDMI"; -+ simple-audio-card,cpu { -+ sound-dai = <&i2s0>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ }; -+ -+ spdif-sound { -+ compatible = "simple-audio-card"; -+ simple-audio-card,name = "SPDIF"; -+ simple-audio-card,cpu { -+ sound-dai = <&spdif>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&spdif_out>; -+ }; -+ }; -+ -+ spdif_out: spdif-out { -+ compatible = "linux,spdif-dit"; -+ #sound-dai-cells = <0>; -+ }; -+ -+ vcc_phy: vcc-phy-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_phy"; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ vcc_sd: sdmmc-regulator { -+ compatible = "regulator-fixed"; -+ gpio = <&gpio0 30 GPIO_ACTIVE_LOW>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0m1_gpio>; -+ regulator-name = "vcc_sd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vcc_io>; -+ }; -+ -+ wireless-wlan { -+ compatible = "wlan-platdata"; -+ rockchip,grf = <&grf>; -+ wifi_chip_type = "rtl8189fs"; -+ sdio_vref = <1800>; -+ WIFI,poweren_gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>; -+ WIFI,host_wake_irq = <&gpio1 19 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ }; -+ -+ vcc_sys: vcc-sys { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+}; -+ -+&codec { -+ #sound-dai-cells = <0>; -+ status = "okay"; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&display_subsystem { -+ status = "okay"; -+}; -+ -+&emmc { -+ bus-width = <8>; -+ cap-mmc-highspeed; -+ clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, -+ <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; -+ clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; -+ disable-wp; -+ max-frequency = <200000000>; -+ mmc-hs200-1_8v; -+ non-removable; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; -+ status = "okay"; -+ supports-emmc; -+ vmmc-supply = <&vcc_io>; -+ vqmmc-supply = <&vcc18_emmc>; -+}; -+ -+&gmac2io { -+ phy-supply = <&vcc_phy>; -+ phy-mode = "rgmii"; -+ clock_in_out = "input"; -+ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ snps,reset-delays-us = <0 10000 50000>; -+ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; -+ assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rgmiim1_pins>; -+ tx_delay = <0x26>; -+ rx_delay = <0x11>; -+ status = "disabled"; -+}; -+ -+&gmac2phy { -+ phy-supply = <&vcc_phy>; -+ clock_in_out = "output"; -+ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; -+ assigned-clock-rate = <50000000>; -+ assigned-clocks = <&cru SCLK_MAC2PHY>; -+ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; -+ status = "okay"; -+}; -+ -+&gpu { -+ status = "okay"; -+ mali-supply = <&vdd_logic>; -+}; -+ -+&hdmi { -+ #sound-dai-cells = <0>; -+ ddc-i2c-scl-high-time-ns = <9625>; -+ ddc-i2c-scl-low-time-ns = <10000>; -+ status = "okay"; -+}; -+ -+&hdmiphy { -+ status = "okay"; -+}; -+ -+&i2c1 { -+ status = "okay"; -+ -+ rk805: rk805@18 { -+ compatible = "rockchip,rk805"; -+ status = "okay"; -+ reg = <0x18>; -+ interrupt-parent = <&gpio2>; -+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_int_l>; -+ rockchip,system-power-controller; -+ wakeup-source; -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ vcc1-supply = <&vcc_sys>; -+ vcc2-supply = <&vcc_sys>; -+ vcc3-supply = <&vcc_sys>; -+ vcc4-supply = <&vcc_sys>; -+ vcc5-supply = <&vcc_io>; -+ vcc6-supply = <&vcc_sys>; -+ -+ rtc { -+ status = "okay"; -+ }; -+ -+ pwrkey { -+ status = "okay"; -+ }; -+ -+ gpio { -+ status = "okay"; -+ }; -+ -+ regulators { -+ compatible = "rk805-regulator"; -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ vdd_logic: RK805_DCDC1@0 { -+ regulator-compatible = "RK805_DCDC1"; -+ regulator-name = "vdd_logic"; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-initial-mode = <0x1>; -+ regulator-ramp-delay = <12500>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ -+ vdd_arm: RK805_DCDC2@1 { -+ regulator-compatible = "RK805_DCDC2"; -+ regulator-name = "vdd_arm"; -+ regulator-init-microvolt = <1225000>; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-initial-mode = <0x1>; -+ regulator-ramp-delay = <12500>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <950000>; -+ }; -+ }; -+ -+ vcc_ddr: RK805_DCDC3@2 { -+ regulator-compatible = "RK805_DCDC3"; -+ regulator-name = "vcc_ddr"; -+ regulator-initial-mode = <0x1>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_io: RK805_DCDC4@3 { -+ regulator-compatible = "RK805_DCDC4"; -+ regulator-name = "vcc_io"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-initial-mode = <0x1>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-mode = <0x2>; -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vcc_18: RK805_LDO1@4 { -+ regulator-compatible = "RK805_LDO1"; -+ regulator-name = "vcc_18"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcc18_emmc: RK805_LDO2@5 { -+ regulator-compatible = "RK805_LDO2"; -+ regulator-name = "vcc18_emmc"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_10: RK805_LDO3@6 { -+ regulator-compatible = "RK805_LDO3"; -+ regulator-name = "vdd_10"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&h265e { -+ status = "okay"; -+}; -+ -+&i2s0 { -+ #sound-dai-cells = <0>; -+ rockchip,bclk-fs = <128>; -+ status = "okay"; -+}; -+ -+&io_domains { -+ status = "okay"; -+ -+ vccio1-supply = <&vcc_io>; -+ vccio2-supply = <&vcc18_emmc>; -+ vccio3-supply = <&vcc_io>; -+ vccio4-supply = <&vcc_18>; -+ vccio5-supply = <&vcc_io>; -+ vccio6-supply = <&vcc_io>; -+ pmuio-supply = <&vcc_io>; -+}; -+ -+&pinctrl { -+ pmic { -+ pmic_int_l: pmic-int-l { -+ rockchip,pins = -+ <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; /* gpio2_a6 */ -+ }; -+ }; -+ -+ sdio-pwrseq { -+ wifi_enable_h: wifi-enable-h { -+ rockchip,pins = -+ <1 18 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&rkvdec { -+ status = "okay"; -+}; -+ -+&sdio { -+ bus-width = <4>; -+ cap-sd-highspeed; -+ cap-sdio-irq; -+ disable-wp; -+ keep-power-in-suspend; -+ max-frequency = <150000000>; -+ mmc-pwrseq = <&sdio_pwrseq>; -+ non-removable; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; -+ supports-sdio; -+ status = "okay"; -+}; -+ -+&sdmmc { -+ bus-width = <4>; -+ cap-mmc-highspeed; -+ cap-sd-highspeed; -+ disable-wp; -+ max-frequency = <150000000>; -+ num-slots = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; -+ supports-sd; -+ status = "okay"; -+ vmmc-supply = <&vcc_sd>; -+ vqmmc-supply = <&vcc_sd>; -+}; -+ -+&spdif { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spdifm0_tx>; -+ #sound-dai-cells = <0>; -+ status = "okay"; -+}; -+ -+&tsadc { -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&u2phy { -+ otg-vbus-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ -+ u2phy_host: host-port { -+ status = "okay"; -+ }; -+ -+ u2phy_otg: otg-port { -+ status = "okay"; -+ }; -+}; -+ -+&u3phy { -+ vbus-drv-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+}; -+ -+&u3phy_utmi { -+ status = "okay"; -+}; -+ -+&u3phy_pipe { -+ status = "okay"; -+}; -+ -+&usb20_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usbdrd3 { -+ status = "okay"; -+}; -+ -+&usbdrd_dwc3 { -+ status = "okay"; -+}; -+ -+&vepu { -+ status = "okay"; -+}; -+ -+&vop { -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -+ -+&vpu_service { -+ status = "okay"; -+}; - -From 6e84c62ce28e36c3a7788bedc8941c6b9e8d5159 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 30 Oct 2017 23:03:52 +0100 -Subject: [PATCH 14/46] arm64: dts: rockchip: rk3328: add operating performance - points - ---- - arch/arm64/boot/dts/rockchip/rk3328.dtsi | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index b2f312d1f662..70555f6db3cf 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -149,6 +149,18 @@ - opp-microvolt = <1300000>; - clock-latency-ns = <40000>; - }; -+ /* -+ opp-1392000000 { -+ opp-hz = /bits/ 64 <1392000000>; -+ opp-microvolt = <1350000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1512000000 { -+ opp-hz = /bits/ 64 <1512000000>; -+ opp-microvolt = <1350000>; -+ clock-latency-ns = <40000>; -+ }; -+ */ - }; - - arm-pmu { - -From ab04d7b56edb12da384848dae6ec893d6cd0d4cb Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Thu, 2 Nov 2017 23:17:46 +0100 -Subject: [PATCH 15/46] arm: dts: rk3288-miqi: update dts - ---- - arch/arm/boot/dts/rk3288-miqi.dts | 56 +++++++++++++++++++++++---------------- - 1 file changed, 33 insertions(+), 23 deletions(-) - -diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts -index b90b0e5969ec..ffced204abcf 100644 ---- a/arch/arm/boot/dts/rk3288-miqi.dts -+++ b/arch/arm/boot/dts/rk3288-miqi.dts -@@ -55,29 +55,14 @@ - sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; -- simple-audio-card,name = "DW-HDMI"; -+ simple-audio-card,name = "HDMI"; - simple-audio-card,mclk-fs = <512>; -- -- simple-audio-card,dai-link@0 { /* I2S - S/PDIF */ -- format = "i2s"; -- cpu { -- sound-dai = <&i2s>; -- }; -- codec { -- sound-dai = <&hdmi>; -- }; -+ simple-audio-card,cpu { -+ sound-dai = <&i2s>; -+ }; -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; - }; -- -- /* -- * If you want to support more cards, -- * you can add more dai-link node, -- * such as -- * -- * simple-audio-card,dai-link@1 { -- * ...... -- * } -- */ -- - }; - - ext_gmac: external-gmac-clock { -@@ -181,9 +166,23 @@ - cpu0-supply = <&vdd_cpu>; - }; - -+&cpu0_opp_table { -+ opp-1704000000 { -+ opp-hz = /bits/ 64 <1704000000>; -+ opp-microvolt = <1350000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1800000000 { -+ opp-hz = /bits/ 64 <1800000000>; -+ opp-microvolt = <1400000>; -+ clock-latency-ns = <40000>; -+ }; -+}; -+ - &gpu { - status = "okay"; - mali-supply = <&vdd_gpu>; -+ power-off-delay-ms = <200>; - }; - - &emmc { -@@ -203,6 +202,12 @@ - #size-cells = <0>; - #sound-dai-cells = <0>; - status = "okay"; -+ /* Don't use vopl for HDMI */ -+ ports { -+ hdmi_in: port { -+ /delete-node/ endpoint@1; -+ }; -+ }; - }; - - &hevc_service { -@@ -234,14 +239,14 @@ - clock_in_out = "input"; - snps,reset-gpio = <&gpio4 7 0>; - snps,reset-active-low; -- snps,reset-delays-us = <0 10000 1000000>; -+ snps,reset-delays-us = <0 10000 50000>; - assigned-clocks = <&cru SCLK_MAC>; - assigned-clock-parents = <&ext_gmac>; - pinctrl-names = "default"; - pinctrl-0 = <&rgmii_pins>; - tx_delay = <0x30>; - rx_delay = <0x10>; -- status = "ok"; -+ status = "okay"; - }; - - /* ---------------------------------------------------------------------------------- -@@ -413,6 +418,7 @@ I2C - - &i2s { - #sound-dai-cells = <0>; -+ rockchip,bclk-fs = <128>; - status = "okay"; - }; - -@@ -471,6 +477,10 @@ I2C - - &vopl { - status = "okay"; -+ /* Don't use vopl for HDMI */ -+ vopl_out: port { -+ /delete-node/ endpoint@0; -+ }; - }; - - &vopl_mmu { - -From c0984bc336a79be6e49ee2268d8df8d054a36159 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 4 Dec 2017 23:49:16 +0100 -Subject: [PATCH 16/46] arm64: dts: rockchip: rk3328-rock64: add - regulator-init-microvolt - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index 7c2041eafb62..32705c6ddebf 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -290,6 +290,7 @@ - vdd_arm: RK805_DCDC2@1 { - regulator-compatible = "RK805_DCDC2"; - regulator-name = "vdd_arm"; -+ regulator-init-microvolt = <1225000>; - regulator-min-microvolt = <712500>; - regulator-max-microvolt = <1450000>; - regulator-initial-mode = <0x1>; - -From 3c8b6aa4402174a7d289e8ade5f16aec5872f8ab Mon Sep 17 00:00:00 2001 -From: Chris Zhong -Date: Mon, 18 Jul 2016 22:34:34 +0800 -Subject: [PATCH 17/46] UPSTREAM: ASoC: rockchip: correct the spdif clk - -The spdif mclk should be 128 times of sample rate, and there is a -internal divider, the real rate of spdif mclk is mclk / (div + 1). -Hence, the original driver always get the good frequency for -48000/96000/44100/192000. But for 32000, the mclk is incorrect, -it should be 32000*128, but get 48000*128. Do not use the internal -divider here, just set all mclk to 128 * sample rate directly. - -Signed-off-by: Chris Zhong -Signed-off-by: Mark Brown -(cherry picked from commit 46dd2e28a90e48fbf1b7e253933fa3b7242e9b1b) ---- - sound/soc/rockchip/rockchip_spdif.c | 17 +---------------- - 1 file changed, 1 insertion(+), 16 deletions(-) - -diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c -index 44b8c72e6a16..feaba2ad6022 100644 ---- a/sound/soc/rockchip/rockchip_spdif.c -+++ b/sound/soc/rockchip/rockchip_spdif.c -@@ -105,21 +105,7 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, - int ret; - - srate = params_rate(params); -- switch (srate) { -- case 32000: -- case 48000: -- case 96000: -- mclk = 96000 * 128; /* 12288000 hz */ -- break; -- case 44100: -- mclk = 44100 * 256; /* 11289600 hz */ -- break; -- case 192000: -- mclk = 192000 * 128; /* 24576000 hz */ -- break; -- default: -- return -EINVAL; -- } -+ mclk = srate * 128; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: -@@ -143,7 +129,6 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, - return ret; - } - -- val |= SPDIF_CFGR_CLK_DIV(mclk/(srate * 256)); - ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, - SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE | - SDPIF_CFGR_VDW_MASK, - -From 58096e4d8d53e151c88d7b2d9d80ef0edf487594 Mon Sep 17 00:00:00 2001 -From: Sugar Zhang -Date: Wed, 7 Sep 2016 14:30:21 +0800 -Subject: [PATCH 18/46] UPSTREAM: ASoC: rockchip: spdif: restore register - during runtime_suspend/resume cycle - -when step into runtime_suspend, spdif pd will be disabled and loss state. -so need to restore register when runtime_resume. - -Signed-off-by: Sugar Zhang -Signed-off-by: Mark Brown -(cherry picked from commit 3628c6987fb45d719cd963805bbba9f15017290e) ---- - sound/soc/rockchip/rockchip_spdif.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c -index feaba2ad6022..cac85a5538d5 100644 ---- a/sound/soc/rockchip/rockchip_spdif.c -+++ b/sound/soc/rockchip/rockchip_spdif.c -@@ -69,6 +69,7 @@ static int rk_spdif_runtime_suspend(struct device *dev) - { - struct rk_spdif_dev *spdif = dev_get_drvdata(dev); - -+ regcache_cache_only(spdif->regmap, true); - clk_disable_unprepare(spdif->mclk); - clk_disable_unprepare(spdif->hclk); - -@@ -92,7 +93,16 @@ static int rk_spdif_runtime_resume(struct device *dev) - return ret; - } - -- return 0; -+ regcache_cache_only(spdif->regmap, false); -+ regcache_mark_dirty(spdif->regmap); -+ -+ ret = regcache_sync(spdif->regmap); -+ if (ret) { -+ clk_disable_unprepare(spdif->mclk); -+ clk_disable_unprepare(spdif->hclk); -+ } -+ -+ return ret; - } - - static int rk_spdif_hw_params(struct snd_pcm_substream *substream, - -From 78c9f1235fc18bb88940d535d4dc821810b4e8d0 Mon Sep 17 00:00:00 2001 -From: Arnaud Pouliquen -Date: Tue, 3 Jan 2017 16:52:50 +0100 -Subject: [PATCH 19/46] UPSTREAM: DRM: add help to get ELD speaker allocation - -Add helper to allow users to retrieve the speaker allocations without -knowledge of the ELD structure. - -Signed-off-by: Arnaud Pouliquen -Reviewed-by: Jani Nikula -Signed-off-by: Mark Brown -(cherry picked from commit c82dbe5c055e4d246bd07c4d7b24801c9445c241) ---- - include/drm/drm_edid.h | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h -index 85861b63e77a..55201e7e2ede 100644 ---- a/include/drm/drm_edid.h -+++ b/include/drm/drm_edid.h -@@ -254,6 +254,7 @@ struct detailed_timing { - # define DRM_ELD_AUD_SYNCH_DELAY_MAX 0xfa /* 500 ms */ - - #define DRM_ELD_SPEAKER 7 -+# define DRM_ELD_SPEAKER_MASK 0x7f - # define DRM_ELD_SPEAKER_RLRC (1 << 6) - # define DRM_ELD_SPEAKER_FLRC (1 << 5) - # define DRM_ELD_SPEAKER_RC (1 << 4) -@@ -417,6 +418,18 @@ static inline int drm_eld_size(const uint8_t *eld) - return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4; - } - -+/** -+ * drm_eld_get_spk_alloc - Get speaker allocation -+ * @eld: pointer to an ELD memory structure -+ * -+ * The returned value is the speakers mask. User has to use %DRM_ELD_SPEAKER -+ * field definitions to identify speakers. -+ */ -+static inline u8 drm_eld_get_spk_alloc(const uint8_t *eld) -+{ -+ return eld[DRM_ELD_SPEAKER] & DRM_ELD_SPEAKER_MASK; -+} -+ - struct edid *drm_do_get_edid(struct drm_connector *connector, - int (*get_edid_block)(void *data, u8 *buf, unsigned int block, - size_t len), - -From 0cc1be4514bde78454c58122494857cf6a37f1c6 Mon Sep 17 00:00:00 2001 -From: Arnaud Pouliquen -Date: Tue, 3 Jan 2017 16:52:51 +0100 -Subject: [PATCH 20/46] UPSTREAM: ASoC: core: add optional pcm_new callback for - DAI driver - -During probe, DAIs can need to perform some actions that requests -the knowledge of the pcm runtime handle. -The callback is called during DAIs linking, after PCM device creation. -For instance this can be used to add relationship between a DAI pcm -control and the pcm device. - -Signed-off-by: Arnaud Pouliquen -Signed-off-by: Mark Brown -(cherry picked from commit 25f7b701c20db3e9ae09e28dd652949bd977e5cd) ---- - include/sound/soc-dai.h | 3 +++ - sound/soc/soc-core.c | 28 ++++++++++++++++++++++++++++ - 2 files changed, 31 insertions(+) - -diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h -index 212eaaf172ed..345e4f8ee93f 100644 ---- a/include/sound/soc-dai.h -+++ b/include/sound/soc-dai.h -@@ -230,6 +230,9 @@ struct snd_soc_dai_driver { - int (*resume)(struct snd_soc_dai *dai); - /* compress dai */ - int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num); -+ /* Optional Callback used at pcm creation*/ -+ int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, -+ struct snd_soc_dai *dai); - /* DAI is also used for the control bus */ - bool bus_control; - -diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c -index 49263f3a50b0..c583022d7910 100644 ---- a/sound/soc/soc-core.c -+++ b/sound/soc/soc-core.c -@@ -1277,6 +1277,27 @@ static int soc_probe_dai(struct snd_soc_dai *dai, int order) - return 0; - } - -+static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais, -+ struct snd_soc_pcm_runtime *rtd) -+{ -+ int i, ret = 0; -+ -+ for (i = 0; i < num_dais; ++i) { -+ struct snd_soc_dai_driver *drv = dais[i]->driver; -+ -+ if (!rtd->dai_link->no_pcm && drv->pcm_new) -+ ret = drv->pcm_new(rtd, dais[i]); -+ if (ret < 0) { -+ dev_err(dais[i]->dev, -+ "ASoC: Failed to bind %s with pcm device\n", -+ dais[i]->name); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ - static int soc_link_dai_widgets(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_link, - struct snd_soc_pcm_runtime *rtd) -@@ -1388,6 +1409,13 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) - dai_link->stream_name, ret); - return ret; - } -+ ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); -+ if (ret < 0) -+ return ret; -+ ret = soc_link_dai_pcm_new(rtd->codec_dais, -+ rtd->num_codecs, rtd); -+ if (ret < 0) -+ return ret; - } else { - INIT_DELAYED_WORK(&rtd->delayed_work, - codec2codec_close_delayed_work); - -From e6a2942583e9404249b010a82401d5d2bd4683e7 Mon Sep 17 00:00:00 2001 -From: Arnaud Pouliquen -Date: Tue, 3 Jan 2017 16:52:52 +0100 -Subject: [PATCH 21/46] UPSTREAM: ASoC: hdmi-codec: add channel mapping control - -Add user interface to provide channel mapping. -In a first step this control is read only. - -As TLV type, the control provides all configuration available for -HDMI sink(ELD), and provides current channel mapping selected by codec -based on ELD and number of channels specified by user on open. -When control is called before the number of the channel is specified -(i.e. hw_params is set), it returns all channels set to UNKNOWN. - -Signed-off-by: Arnaud Pouliquen -Signed-off-by: Mark Brown -(cherry picked from commit cd6111b26280a2f38a9fb8e6630c63a96477e4bf) ---- - sound/soc/codecs/hdmi-codec.c | 377 +++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 376 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c -index 028d60c196ae..cb78d8971b41 100644 ---- a/sound/soc/codecs/hdmi-codec.c -+++ b/sound/soc/codecs/hdmi-codec.c -@@ -21,12 +21,264 @@ - #include - #include - #include -+#include - #include - #include - #include - - #include /* This is only to get MAX_ELD_BYTES */ - -+#define HDMI_CODEC_CHMAP_IDX_UNKNOWN -1 -+ -+struct hdmi_codec_channel_map_table { -+ unsigned char map; /* ALSA API channel map position */ -+ unsigned long spk_mask; /* speaker position bit mask */ -+}; -+ -+/* -+ * CEA speaker placement for HDMI 1.4: -+ * -+ * FL FLC FC FRC FR FRW -+ * -+ * LFE -+ * -+ * RL RLC RC RRC RR -+ * -+ * Speaker placement has to be extended to support HDMI 2.0 -+ */ -+enum hdmi_codec_cea_spk_placement { -+ FL = BIT(0), /* Front Left */ -+ FC = BIT(1), /* Front Center */ -+ FR = BIT(2), /* Front Right */ -+ FLC = BIT(3), /* Front Left Center */ -+ FRC = BIT(4), /* Front Right Center */ -+ RL = BIT(5), /* Rear Left */ -+ RC = BIT(6), /* Rear Center */ -+ RR = BIT(7), /* Rear Right */ -+ RLC = BIT(8), /* Rear Left Center */ -+ RRC = BIT(9), /* Rear Right Center */ -+ LFE = BIT(10), /* Low Frequency Effect */ -+}; -+ -+/* -+ * cea Speaker allocation structure -+ */ -+struct hdmi_codec_cea_spk_alloc { -+ const int ca_id; -+ unsigned int n_ch; -+ unsigned long mask; -+}; -+ -+/* Channel maps stereo HDMI */ -+const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = { -+ { .channels = 2, -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, -+ { } -+}; -+ -+/* Channel maps for multi-channel playbacks, up to 8 n_ch */ -+const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = { -+ { .channels = 2, /* CA_ID 0x00 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, -+ { .channels = 4, /* CA_ID 0x01 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_NA } }, -+ { .channels = 4, /* CA_ID 0x02 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FC } }, -+ { .channels = 4, /* CA_ID 0x03 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_FC } }, -+ { .channels = 6, /* CA_ID 0x04 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, -+ { .channels = 6, /* CA_ID 0x05 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, -+ { .channels = 6, /* CA_ID 0x06 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, -+ { .channels = 6, /* CA_ID 0x07 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, -+ { .channels = 6, /* CA_ID 0x08 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, -+ { .channels = 6, /* CA_ID 0x09 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, -+ { .channels = 6, /* CA_ID 0x0A */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, -+ { .channels = 6, /* CA_ID 0x0B */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, -+ { .channels = 8, /* CA_ID 0x0C */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, -+ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, -+ { .channels = 8, /* CA_ID 0x0D */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, -+ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, -+ { .channels = 8, /* CA_ID 0x0E */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, -+ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, -+ { .channels = 8, /* CA_ID 0x0F */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, -+ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, -+ { .channels = 8, /* CA_ID 0x10 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, -+ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, -+ { .channels = 8, /* CA_ID 0x11 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, -+ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, -+ { .channels = 8, /* CA_ID 0x12 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, -+ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, -+ { .channels = 8, /* CA_ID 0x13 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, -+ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, -+ { .channels = 8, /* CA_ID 0x14 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x15 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x16 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x17 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x18 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x19 */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x1A */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x1B */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x1C */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x1D */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x1E */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { .channels = 8, /* CA_ID 0x1F */ -+ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, -+ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, -+ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, -+ { } -+}; -+ -+/* -+ * hdmi_codec_channel_alloc: speaker configuration available for CEA -+ * -+ * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct -+ * The preceding ones have better chances to be selected by -+ * hdmi_codec_get_ch_alloc_table_idx(). -+ */ -+static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { -+ { .ca_id = 0x00, .n_ch = 2, -+ .mask = FL | FR}, -+ /* 2.1 */ -+ { .ca_id = 0x01, .n_ch = 4, -+ .mask = FL | FR | LFE}, -+ /* Dolby Surround */ -+ { .ca_id = 0x02, .n_ch = 4, -+ .mask = FL | FR | FC }, -+ /* surround51 */ -+ { .ca_id = 0x0b, .n_ch = 6, -+ .mask = FL | FR | LFE | FC | RL | RR}, -+ /* surround40 */ -+ { .ca_id = 0x08, .n_ch = 6, -+ .mask = FL | FR | RL | RR }, -+ /* surround41 */ -+ { .ca_id = 0x09, .n_ch = 6, -+ .mask = FL | FR | LFE | RL | RR }, -+ /* surround50 */ -+ { .ca_id = 0x0a, .n_ch = 6, -+ .mask = FL | FR | FC | RL | RR }, -+ /* 6.1 */ -+ { .ca_id = 0x0f, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | RL | RR | RC }, -+ /* surround71 */ -+ { .ca_id = 0x13, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC }, -+ /* others */ -+ { .ca_id = 0x03, .n_ch = 8, -+ .mask = FL | FR | LFE | FC }, -+ { .ca_id = 0x04, .n_ch = 8, -+ .mask = FL | FR | RC}, -+ { .ca_id = 0x05, .n_ch = 8, -+ .mask = FL | FR | LFE | RC }, -+ { .ca_id = 0x06, .n_ch = 8, -+ .mask = FL | FR | FC | RC }, -+ { .ca_id = 0x07, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | RC }, -+ { .ca_id = 0x0c, .n_ch = 8, -+ .mask = FL | FR | RC | RL | RR }, -+ { .ca_id = 0x0d, .n_ch = 8, -+ .mask = FL | FR | LFE | RL | RR | RC }, -+ { .ca_id = 0x0e, .n_ch = 8, -+ .mask = FL | FR | FC | RL | RR | RC }, -+ { .ca_id = 0x10, .n_ch = 8, -+ .mask = FL | FR | RL | RR | RLC | RRC }, -+ { .ca_id = 0x11, .n_ch = 8, -+ .mask = FL | FR | LFE | RL | RR | RLC | RRC }, -+ { .ca_id = 0x12, .n_ch = 8, -+ .mask = FL | FR | FC | RL | RR | RLC | RRC }, -+ { .ca_id = 0x14, .n_ch = 8, -+ .mask = FL | FR | FLC | FRC }, -+ { .ca_id = 0x15, .n_ch = 8, -+ .mask = FL | FR | LFE | FLC | FRC }, -+ { .ca_id = 0x16, .n_ch = 8, -+ .mask = FL | FR | FC | FLC | FRC }, -+ { .ca_id = 0x17, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | FLC | FRC }, -+ { .ca_id = 0x18, .n_ch = 8, -+ .mask = FL | FR | RC | FLC | FRC }, -+ { .ca_id = 0x19, .n_ch = 8, -+ .mask = FL | FR | LFE | RC | FLC | FRC }, -+ { .ca_id = 0x1a, .n_ch = 8, -+ .mask = FL | FR | RC | FC | FLC | FRC }, -+ { .ca_id = 0x1b, .n_ch = 8, -+ .mask = FL | FR | LFE | RC | FC | FLC | FRC }, -+ { .ca_id = 0x1c, .n_ch = 8, -+ .mask = FL | FR | RL | RR | FLC | FRC }, -+ { .ca_id = 0x1d, .n_ch = 8, -+ .mask = FL | FR | LFE | RL | RR | FLC | FRC }, -+ { .ca_id = 0x1e, .n_ch = 8, -+ .mask = FL | FR | FC | RL | RR | FLC | FRC }, -+ { .ca_id = 0x1f, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, -+}; -+ - struct hdmi_codec_priv { - struct hdmi_codec_pdata hcd; - struct snd_soc_dai_driver *daidrv; -@@ -41,6 +293,8 @@ struct hdmi_codec_priv { - struct notifier_block nb; - unsigned int jack_status; - unsigned int mode; -+ struct snd_pcm_chmap *chmap_info; -+ unsigned int chmap_idx; - }; - - static const struct snd_soc_dapm_widget hdmi_widgets[] = { -@@ -109,6 +363,83 @@ static int hdmi_audio_mode_put(struct snd_kcontrol *kcontrol, - return 0; - } - -+static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc) -+{ -+ int i; -+ const unsigned long hdmi_codec_eld_spk_alloc_bits[] = { -+ [0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR, -+ [4] = RC, [5] = FLC | FRC, [6] = RLC | RRC, -+ }; -+ unsigned long spk_mask = 0; -+ -+ for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) { -+ if (spk_alloc & (1 << i)) -+ spk_mask |= hdmi_codec_eld_spk_alloc_bits[i]; -+ } -+ -+ return spk_mask; -+} -+ -+void hdmi_codec_eld_chmap(struct hdmi_codec_priv *hcp) -+{ -+ u8 spk_alloc; -+ unsigned long spk_mask; -+ -+ spk_alloc = drm_eld_get_spk_alloc(hcp->eld); -+ spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc); -+ -+ /* Detect if only stereo supported, else return 8 channels mappings */ -+ if ((spk_mask & ~(FL | FR)) && hcp->chmap_info->max_channels > 2) -+ hcp->chmap_info->chmap = hdmi_codec_8ch_chmaps; -+ else -+ hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps; -+} -+ -+static int hdmi_codec_get_ch_alloc_table_idx(struct hdmi_codec_priv *hcp, -+ unsigned char channels) -+{ -+ int i; -+ u8 spk_alloc; -+ unsigned long spk_mask; -+ const struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc; -+ -+ spk_alloc = drm_eld_get_spk_alloc(hcp->eld); -+ spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc); -+ -+ for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) { -+ /* If spk_alloc == 0, HDMI is unplugged return stereo config*/ -+ if (!spk_alloc && cap->ca_id == 0) -+ return i; -+ if (cap->n_ch != channels) -+ continue; -+ if (!(cap->mask == (spk_mask & cap->mask))) -+ continue; -+ return i; -+ } -+ -+ return -EINVAL; -+} -+static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ unsigned const char *map; -+ unsigned int i; -+ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); -+ struct hdmi_codec_priv *hcp = info->private_data; -+ -+ map = info->chmap[hcp->chmap_idx].map; -+ -+ for (i = 0; i < info->max_channels; i++) { -+ if (hcp->chmap_idx == HDMI_CODEC_CHMAP_IDX_UNKNOWN) -+ ucontrol->value.integer.value[i] = 0; -+ else -+ ucontrol->value.integer.value[i] = map[i]; -+ } -+ -+ return 0; -+} -+ -+ - static const struct snd_kcontrol_new hdmi_controls[] = { - { - .access = SNDRV_CTL_ELEM_ACCESS_READ | -@@ -184,6 +515,9 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, - ret = snd_pcm_hw_constraint_eld(substream->runtime, - hcp->eld); - mutex_unlock(&hcp->eld_lock); -+ -+ /* Select chmap supported */ -+ hdmi_codec_eld_chmap(hcp); - } - return ret; - } -@@ -201,6 +535,7 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, - - WARN_ON(hcp->current_stream != substream); - -+ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; - hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data); - - mutex_lock(&hcp->current_stream_lock); -@@ -221,7 +556,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, - .dig_subframe = { 0 }, - } - }; -- int ret; -+ int ret, idx; - - dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__, - params_width(params), params_rate(params), -@@ -248,6 +583,17 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, - hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; - hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; - -+ /* Select a channel allocation that matches with ELD and pcm channels */ -+ idx = hdmi_codec_get_ch_alloc_table_idx(hcp, hp.cea.channels); -+ if (idx < 0) { -+ dev_err(dai->dev, "Not able to map channels to speakers (%d)\n", -+ idx); -+ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; -+ return idx; -+ } -+ hp.cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id; -+ hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id; -+ - hp.sample_width = params_width(params); - hp.sample_rate = params_rate(params); - hp.channels = params_channels(params); -@@ -377,6 +723,32 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = { - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ - SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) - -+static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, -+ struct snd_soc_dai *dai) -+{ -+ struct snd_soc_dai_driver *drv = dai->driver; -+ struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); -+ int ret; -+ -+ dev_dbg(dai->dev, "%s()\n", __func__); -+ -+ ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK, -+ NULL, drv->playback.channels_max, 0, -+ &hcp->chmap_info); -+ if (ret < 0) -+ return ret; -+ -+ /* override handlers */ -+ hcp->chmap_info->private_data = hcp; -+ hcp->chmap_info->kctl->get = hdmi_codec_chmap_ctl_get; -+ -+ /* default chmap supported is stereo */ -+ hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps; -+ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; -+ -+ return 0; -+} -+ - static struct snd_soc_dai_driver hdmi_i2s_dai = { - .name = "i2s-hifi", - .id = DAI_ID_I2S, -@@ -389,6 +761,7 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = { - .sig_bits = 24, - }, - .ops = &hdmi_dai_ops, -+ .pcm_new = hdmi_codec_pcm_new, - }; - - static const struct snd_soc_dai_driver hdmi_spdif_dai = { -@@ -402,6 +775,7 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = { - .formats = SPDIF_FORMATS, - }, - .ops = &hdmi_dai_ops, -+ .pcm_new = hdmi_codec_pcm_new, - }; - - static struct snd_soc_codec_driver hdmi_codec = { -@@ -534,6 +908,7 @@ static int hdmi_codec_remove(struct platform_device *pdev) - { - struct hdmi_codec_priv *hcp = platform_get_drvdata(pdev); - -+ kfree(hcp->chmap_info); - hdmi_unregister_notifier(&hcp->nb); - snd_soc_unregister_codec(&pdev->dev); - return 0; - -From c00c7e462482cebf24c9ad1d4183bd4e741406bc Mon Sep 17 00:00:00 2001 -From: Christophe Jaillet -Date: Thu, 15 Jun 2017 07:53:11 +0200 -Subject: [PATCH 22/46] UPSTREAM: ASoC: rockchip: Fix an error handling in - 'rockchip_i2s_probe' - -If this memory allocation fail, we must disable what has been enabled. -Do not return immediately but go thrue the error handling path instead. - -Also use 'devm_kmemdup' instead of 'devm_kzalloc+memcpy' to simplify code. - -Signed-off-by: Christophe JAILLET -Signed-off-by: Mark Brown -(cherry picked from commit c3a3d3c41b74b05267bab6173f2a8224a1443ba6) ---- - sound/soc/rockchip/rockchip_i2s.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c -index 2c7e5ccca2dc..ba32a2ef87b3 100644 ---- a/sound/soc/rockchip/rockchip_i2s.c -+++ b/sound/soc/rockchip/rockchip_i2s.c -@@ -644,12 +644,13 @@ static int rockchip_i2s_probe(struct platform_device *pdev) - goto err_pm_disable; - } - -- soc_dai = devm_kzalloc(&pdev->dev, -+ soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai, - sizeof(*soc_dai), GFP_KERNEL); -- if (!soc_dai) -- return -ENOMEM; -+ if (!soc_dai) { -+ ret = -ENOMEM; -+ goto err_pm_disable; -+ } - -- memcpy(soc_dai, &rockchip_i2s_dai, sizeof(*soc_dai)); - if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { - if (val >= 2 && val <= 8) - soc_dai->playback.channels_max = val; - -From c650fd3e51231d782891896704b6994fa22ed3d4 Mon Sep 17 00:00:00 2001 -From: Romain Perier -Date: Fri, 14 Apr 2017 10:31:12 +0200 -Subject: [PATCH 23/46] UPSTREAM: drm: dw-hdmi: add specific I2S and AHB - functions for stream handling - -Currently, CTS+N is forced to zero as a workaround of the IP block for -i.MX platforms. This is requested in the datasheet of the corresponding -IP for AHB mode only. However, we have seen that it introduces glitches -or delays when playing a sound on HDMI for I2S mode. This proves that we -cannot keep the current functions for handling audio stream as-is if -these contain workaround that are specific to a mode. - -This commit introduces two callbacks, one for each variant. -dw_hdmi_setup defines the right function depending on the detected -variant. Then, the exported functions dw_hdmi_audio_enable and -dw_hdmi_audio_disable calls the corresponding callbacks - -Reviewed-by: Neil Armstrong -Signed-off-by: Romain Perier -Signed-off-by: Archit Taneja -Link: http://patchwork.freedesktop.org/patch/msgid/20170414083113.4255-2-romain.perier@collabora.com -(cherry picked from commit a7d555d2f2bd675d641e742a202a5e4b37d4d019) ---- - drivers/gpu/drm/bridge/dw-hdmi.c | 26 ++++++++++++++++++++++++-- - 1 file changed, 24 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index 9254002971b6..b93a50395222 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -253,6 +253,8 @@ struct dw_hdmi { - - void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); - u8 (*read)(struct dw_hdmi *hdmi, int offset); -+ void (*enable_audio)(struct dw_hdmi *hdmi); -+ void (*disable_audio)(struct dw_hdmi *hdmi); - }; - - #define HDMI_IH_PHY_STAT0_RX_SENSE \ -@@ -792,13 +794,29 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) - } - EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); - -+static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi) -+{ -+ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); -+} -+ -+static void dw_hdmi_ahb_audio_disable(struct dw_hdmi *hdmi) -+{ -+ hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); -+} -+ -+static void dw_hdmi_i2s_audio_enable(struct dw_hdmi *hdmi) -+{ -+ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); -+} -+ - void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) - { - unsigned long flags; - - spin_lock_irqsave(&hdmi->audio_lock, flags); - hdmi->audio_enable = true; -- hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); -+ if (hdmi->enable_audio) -+ hdmi->enable_audio(hdmi); - spin_unlock_irqrestore(&hdmi->audio_lock, flags); - } - EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable); -@@ -809,7 +827,8 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi) - - spin_lock_irqsave(&hdmi->audio_lock, flags); - hdmi->audio_enable = false; -- hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); -+ if (hdmi->disable_audio) -+ hdmi->disable_audio(hdmi); - spin_unlock_irqrestore(&hdmi->audio_lock, flags); - } - EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable); -@@ -3490,6 +3509,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master, - audio.irq = irq; - audio.hdmi = hdmi; - audio.eld = hdmi->connector.eld; -+ hdmi->enable_audio = dw_hdmi_ahb_audio_enable; -+ hdmi->disable_audio = dw_hdmi_ahb_audio_disable; - - pdevinfo.name = "dw-hdmi-ahb-audio"; - pdevinfo.data = &audio; -@@ -3503,6 +3524,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, - audio.write = hdmi_writeb; - audio.read = hdmi_readb; - audio.mod = hdmi_modb; -+ hdmi->enable_audio = dw_hdmi_i2s_audio_enable; - - pdevinfo.name = "dw-hdmi-i2s-audio"; - pdevinfo.data = &audio; - -From 052b6ab670eb31d23c5143918d8da969bb7216f7 Mon Sep 17 00:00:00 2001 -From: Romain Perier -Date: Thu, 20 Apr 2017 14:34:34 +0530 -Subject: [PATCH 24/46] UPSTREAM: drm: dw-hdmi: gate audio clock from the I2S - enablement callbacks - -Currently, the audio sampler clock is enabled from dw_hdmi_setup() at -step E. and is kept enabled for later use. This clock should be enabled -and disabled along with the actual audio stream and not always on (that -is bad for PM). Furthermore, as described by the datasheet, the I2S -variant needs to gate/ungate the clock when the stream is -enabled/disabled. - -This commit adds a parameter to hdmi_audio_enable_clk() that controls -when the audio sample clock must be enabled or disabled. Then, it adds -the call to this function from dw_hdmi_i2s_audio_enable() and -dw_hdmi_i2s_audio_disable(). - -Reviewed-by: Neil Armstrong -Signed-off-by: Romain Perier -Link: http://patchwork.freedesktop.org/patch/msgid/20170414083113.4255-3-romain.perier@collabora.com -Signed-off-by: Archit Taneja -(cherry picked from commit 57fbc05585a9c841c910677228f1e3f8a3a62801) ---- - drivers/gpu/drm/bridge/dw-hdmi.c | 20 ++++++++++++++------ - 1 file changed, 14 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index b93a50395222..c594df820009 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -794,6 +794,12 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) - } - EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); - -+static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable) -+{ -+ hdmi_modb(hdmi, enable ? 0 : HDMI_MC_CLKDIS_AUDCLK_DISABLE, -+ HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS); -+} -+ - static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi) - { - hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); -@@ -807,6 +813,12 @@ static void dw_hdmi_ahb_audio_disable(struct dw_hdmi *hdmi) - static void dw_hdmi_i2s_audio_enable(struct dw_hdmi *hdmi) - { - hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); -+ hdmi_enable_audio_clk(hdmi, true); -+} -+ -+static void dw_hdmi_i2s_audio_disable(struct dw_hdmi *hdmi) -+{ -+ hdmi_enable_audio_clk(hdmi, false); - } - - void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) -@@ -2101,11 +2113,6 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) - HDMI_MC_FLOWCTRL); - } - --static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi) --{ -- hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS); --} -- - /* Workaround to clear the overflow condition */ - static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) - { -@@ -2257,7 +2264,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) - - /* HDMI Initialization Step E - Configure audio */ - hdmi_clk_regenerator_update_pixel_clock(hdmi); -- hdmi_enable_audio_clk(hdmi); -+ hdmi_enable_audio_clk(hdmi, true); - } - - /* not for DVI mode */ -@@ -3525,6 +3532,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, - audio.read = hdmi_readb; - audio.mod = hdmi_modb; - hdmi->enable_audio = dw_hdmi_i2s_audio_enable; -+ hdmi->disable_audio = dw_hdmi_i2s_audio_disable; - - pdevinfo.name = "dw-hdmi-i2s-audio"; - pdevinfo.data = &audio; - -From 128c42b87498104641cf2847cd16fa7f058a274e Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 7 Aug 2017 22:24:15 +0200 -Subject: [PATCH 25/46] drm: dw-hdmi-i2s: sync with upstream - ---- - drivers/gpu/drm/bridge/dw-hdmi-audio.h | 1 - - drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c | 20 +++++++++++++------- - 2 files changed, 13 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/dw-hdmi-audio.h -index d3194b4e186b..b9e839f4151a 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi-audio.h -+++ b/drivers/gpu/drm/bridge/dw-hdmi-audio.h -@@ -13,7 +13,6 @@ struct dw_hdmi_audio_data { - - struct dw_hdmi_i2s_audio_data { - struct dw_hdmi *hdmi; -- struct platform_device *pdev; - - void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); - u8 (*read)(struct dw_hdmi *hdmi, int offset); -diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c -index f1f62d8c1d16..5ff993a35ab6 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c -@@ -16,7 +16,8 @@ - - #define DRIVER_NAME "dw-hdmi-i2s-audio" - --static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio, u8 val, int offset) -+static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio, -+ u8 val, int offset) - { - struct dw_hdmi *hdmi = audio->hdmi; - -@@ -220,6 +221,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) - struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data; - struct platform_device_info pdevinfo; - struct hdmi_codec_pdata pdata; -+ struct platform_device *platform; - - pdata.ops = &dw_hdmi_i2s_ops; - pdata.i2s = 1; -@@ -234,23 +236,27 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) - pdevinfo.size_data = sizeof(pdata); - pdevinfo.dma_mask = DMA_BIT_MASK(32); - -- audio->pdev = platform_device_register_full(&pdevinfo); -- return IS_ERR_OR_NULL(audio->pdev); -+ platform = platform_device_register_full(&pdevinfo); -+ if (IS_ERR(platform)) -+ return PTR_ERR(platform); -+ -+ dev_set_drvdata(&pdev->dev, platform); -+ -+ return 0; - } - - static int snd_dw_hdmi_remove(struct platform_device *pdev) - { -- struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data; -+ struct platform_device *platform = dev_get_drvdata(&pdev->dev); - -- if (!IS_ERR_OR_NULL(audio->pdev)) -- platform_device_unregister(audio->pdev); -+ platform_device_unregister(platform); - - return 0; - } - - static struct platform_driver snd_dw_hdmi_driver = { - .probe = snd_dw_hdmi_probe, -- .remove = snd_dw_hdmi_remove, -+ .remove = snd_dw_hdmi_remove, - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - -From c98584e196e50fd168520ad68cfc83d4dadf2061 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 2 Apr 2017 11:33:39 +0200 -Subject: [PATCH 26/46] drm: dw-hdmi-i2s: implement get_eld - ---- - drivers/gpu/drm/bridge/dw-hdmi-audio.h | 1 + - drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c | 12 ++++++++++++ - drivers/gpu/drm/bridge/dw-hdmi.c | 1 + - 3 files changed, 14 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/dw-hdmi-audio.h -index b9e839f4151a..e75f458ef4df 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi-audio.h -+++ b/drivers/gpu/drm/bridge/dw-hdmi-audio.h -@@ -13,6 +13,7 @@ struct dw_hdmi_audio_data { - - struct dw_hdmi_i2s_audio_data { - struct dw_hdmi *hdmi; -+ u8 *eld; - - void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); - u8 (*read)(struct dw_hdmi *hdmi, int offset); -diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c -index 5ff993a35ab6..e7312571e2cb 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c -@@ -11,6 +11,8 @@ - - #include - -+#include /* This is only to get MAX_ELD_BYTES */ -+ - #include "dw-hdmi.h" - #include "dw-hdmi-audio.h" - -@@ -211,9 +213,19 @@ static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data) - hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); - } - -+static int dw_hdmi_i2s_get_eld(struct device *dev, void *data, u8 *buf, size_t len) -+{ -+ struct dw_hdmi_i2s_audio_data *audio = data; -+ -+ memcpy(buf, audio->eld, min(len, (size_t)MAX_ELD_BYTES)); -+ -+ return 0; -+} -+ - static struct hdmi_codec_ops dw_hdmi_i2s_ops = { - .hw_params = dw_hdmi_i2s_hw_params, - .audio_shutdown = dw_hdmi_i2s_audio_shutdown, -+ .get_eld = dw_hdmi_i2s_get_eld, - }; - - static int snd_dw_hdmi_probe(struct platform_device *pdev) -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index c594df820009..09b43a348525 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -3531,6 +3531,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, - audio.write = hdmi_writeb; - audio.read = hdmi_readb; - audio.mod = hdmi_modb; -+ audio.eld = hdmi->connector.eld; - hdmi->enable_audio = dw_hdmi_i2s_audio_enable; - hdmi->disable_audio = dw_hdmi_i2s_audio_disable; - - -From b70afef572e3abc8cbb2fd155b71fba62eed8d7d Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 17 Apr 2017 13:09:16 +0200 -Subject: [PATCH 27/46] drm: dw-hdmi-i2s: configure channel allocation - ---- - drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c -index e7312571e2cb..1d4570e3fbed 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c -@@ -188,7 +188,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, - hdmi_write(audio, 0x00, HDMI_FC_AUDICONF1); - - /* Set Channel Allocation */ -- hdmi_write(audio, 0x00, HDMI_FC_AUDICONF2); -+ hdmi_write(audio, hparms->cea.channel_allocation, HDMI_FC_AUDICONF2); - - /* Set LFEPBLDOWN-MIX INH and LSV */ - hdmi_write(audio, 0x00, HDMI_FC_AUDICONF3); - -From 535b0ea24dc20e11de8984ab9c06b840ab15b125 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 2 May 2017 18:57:19 +0200 -Subject: [PATCH 28/46] ASoC: hdmi-codec: fix I2S audio in Kodi - ---- - sound/soc/codecs/hdmi-codec.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c -index cb78d8971b41..9ebca57014e4 100644 ---- a/sound/soc/codecs/hdmi-codec.c -+++ b/sound/soc/codecs/hdmi-codec.c -@@ -758,7 +758,6 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = { - .channels_max = 8, - .rates = HDMI_RATES, - .formats = I2S_FORMATS, -- .sig_bits = 24, - }, - .ops = &hdmi_dai_ops, - .pcm_new = hdmi_codec_pcm_new, - -From 5a06cdd0b22a9ecee61c1e3d2505ddfc7078c4ee Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 14 Aug 2017 00:14:05 +0200 -Subject: [PATCH 29/46] ASoC: hdmi-codec: reorder channel map - ---- - sound/soc/codecs/hdmi-codec.c | 113 +++++++++++++++++++----------------------- - 1 file changed, 52 insertions(+), 61 deletions(-) - -diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c -index 9ebca57014e4..e65060ae8ffc 100644 ---- a/sound/soc/codecs/hdmi-codec.c -+++ b/sound/soc/codecs/hdmi-codec.c -@@ -205,78 +205,69 @@ const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = { - */ - static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { - { .ca_id = 0x00, .n_ch = 2, -- .mask = FL | FR}, -- /* 2.1 */ -- { .ca_id = 0x01, .n_ch = 4, -- .mask = FL | FR | LFE}, -- /* Dolby Surround */ -+ .mask = FL | FR }, -+ { .ca_id = 0x03, .n_ch = 4, -+ .mask = FL | FR | LFE | FC }, - { .ca_id = 0x02, .n_ch = 4, - .mask = FL | FR | FC }, -- /* surround51 */ -+ { .ca_id = 0x01, .n_ch = 4, -+ .mask = FL | FR | LFE }, - { .ca_id = 0x0b, .n_ch = 6, -- .mask = FL | FR | LFE | FC | RL | RR}, -- /* surround40 */ -- { .ca_id = 0x08, .n_ch = 6, -- .mask = FL | FR | RL | RR }, -- /* surround41 */ -- { .ca_id = 0x09, .n_ch = 6, -- .mask = FL | FR | LFE | RL | RR }, -- /* surround50 */ -+ .mask = FL | FR | LFE | FC | RL | RR }, - { .ca_id = 0x0a, .n_ch = 6, - .mask = FL | FR | FC | RL | RR }, -- /* 6.1 */ -- { .ca_id = 0x0f, .n_ch = 8, -- .mask = FL | FR | LFE | FC | RL | RR | RC }, -- /* surround71 */ -+ { .ca_id = 0x09, .n_ch = 6, -+ .mask = FL | FR | LFE | RL | RR }, -+ { .ca_id = 0x08, .n_ch = 6, -+ .mask = FL | FR | RL | RR }, -+ { .ca_id = 0x07, .n_ch = 6, -+ .mask = FL | FR | LFE | FC | RC }, -+ { .ca_id = 0x06, .n_ch = 6, -+ .mask = FL | FR | FC | RC }, -+ { .ca_id = 0x05, .n_ch = 6, -+ .mask = FL | FR | LFE | RC }, -+ { .ca_id = 0x04, .n_ch = 6, -+ .mask = FL | FR | RC }, - { .ca_id = 0x13, .n_ch = 8, - .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC }, -- /* others */ -- { .ca_id = 0x03, .n_ch = 8, -- .mask = FL | FR | LFE | FC }, -- { .ca_id = 0x04, .n_ch = 8, -- .mask = FL | FR | RC}, -- { .ca_id = 0x05, .n_ch = 8, -- .mask = FL | FR | LFE | RC }, -- { .ca_id = 0x06, .n_ch = 8, -- .mask = FL | FR | FC | RC }, -- { .ca_id = 0x07, .n_ch = 8, -- .mask = FL | FR | LFE | FC | RC }, -- { .ca_id = 0x0c, .n_ch = 8, -- .mask = FL | FR | RC | RL | RR }, -- { .ca_id = 0x0d, .n_ch = 8, -- .mask = FL | FR | LFE | RL | RR | RC }, -- { .ca_id = 0x0e, .n_ch = 8, -- .mask = FL | FR | FC | RL | RR | RC }, -- { .ca_id = 0x10, .n_ch = 8, -- .mask = FL | FR | RL | RR | RLC | RRC }, -- { .ca_id = 0x11, .n_ch = 8, -- .mask = FL | FR | LFE | RL | RR | RLC | RRC }, -+ { .ca_id = 0x1f, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, - { .ca_id = 0x12, .n_ch = 8, - .mask = FL | FR | FC | RL | RR | RLC | RRC }, -- { .ca_id = 0x14, .n_ch = 8, -- .mask = FL | FR | FLC | FRC }, -- { .ca_id = 0x15, .n_ch = 8, -- .mask = FL | FR | LFE | FLC | FRC }, -- { .ca_id = 0x16, .n_ch = 8, -- .mask = FL | FR | FC | FLC | FRC }, -- { .ca_id = 0x17, .n_ch = 8, -- .mask = FL | FR | LFE | FC | FLC | FRC }, -- { .ca_id = 0x18, .n_ch = 8, -- .mask = FL | FR | RC | FLC | FRC }, -- { .ca_id = 0x19, .n_ch = 8, -- .mask = FL | FR | LFE | RC | FLC | FRC }, -- { .ca_id = 0x1a, .n_ch = 8, -- .mask = FL | FR | RC | FC | FLC | FRC }, -- { .ca_id = 0x1b, .n_ch = 8, -- .mask = FL | FR | LFE | RC | FC | FLC | FRC }, -- { .ca_id = 0x1c, .n_ch = 8, -- .mask = FL | FR | RL | RR | FLC | FRC }, -- { .ca_id = 0x1d, .n_ch = 8, -- .mask = FL | FR | LFE | RL | RR | FLC | FRC }, - { .ca_id = 0x1e, .n_ch = 8, - .mask = FL | FR | FC | RL | RR | FLC | FRC }, -- { .ca_id = 0x1f, .n_ch = 8, -- .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, -+ { .ca_id = 0x11, .n_ch = 8, -+ .mask = FL | FR | LFE | RL | RR | RLC | RRC }, -+ { .ca_id = 0x1d, .n_ch = 8, -+ .mask = FL | FR | LFE | RL | RR | FLC | FRC }, -+ { .ca_id = 0x10, .n_ch = 8, -+ .mask = FL | FR | RL | RR | RLC | RRC }, -+ { .ca_id = 0x1c, .n_ch = 8, -+ .mask = FL | FR | RL | RR | FLC | FRC }, -+ { .ca_id = 0x0f, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | RL | RR | RC }, -+ { .ca_id = 0x1b, .n_ch = 8, -+ .mask = FL | FR | LFE | RC | FC | FLC | FRC }, -+ { .ca_id = 0x0e, .n_ch = 8, -+ .mask = FL | FR | FC | RL | RR | RC }, -+ { .ca_id = 0x1a, .n_ch = 8, -+ .mask = FL | FR | RC | FC | FLC | FRC }, -+ { .ca_id = 0x0d, .n_ch = 8, -+ .mask = FL | FR | LFE | RL | RR | RC }, -+ { .ca_id = 0x19, .n_ch = 8, -+ .mask = FL | FR | LFE | RC | FLC | FRC }, -+ { .ca_id = 0x0c, .n_ch = 8, -+ .mask = FL | FR | RC | RL | RR }, -+ { .ca_id = 0x18, .n_ch = 8, -+ .mask = FL | FR | RC | FLC | FRC }, -+ { .ca_id = 0x17, .n_ch = 8, -+ .mask = FL | FR | LFE | FC | FLC | FRC }, -+ { .ca_id = 0x16, .n_ch = 8, -+ .mask = FL | FR | FC | FLC | FRC }, -+ { .ca_id = 0x15, .n_ch = 8, -+ .mask = FL | FR | LFE | FLC | FRC }, -+ { .ca_id = 0x14, .n_ch = 8, -+ .mask = FL | FR | FLC | FRC }, - }; - - struct hdmi_codec_priv { - -From 64ff0d23d4b4a7832462b4ddb50b4d2cb14e21c2 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 27 Aug 2017 23:32:40 +0200 -Subject: [PATCH 30/46] ASoC: codecs: rk3328: limit to working rates - ---- - sound/soc/codecs/rk3328_codec.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c -index ceb2eb6dd69a..d20728bd48ba 100644 ---- a/sound/soc/codecs/rk3328_codec.c -+++ b/sound/soc/codecs/rk3328_codec.c -@@ -352,7 +352,12 @@ static struct snd_soc_dai_driver rk3328_dai[] = { - .stream_name = "HIFI Playback", - .channels_min = 1, - .channels_max = 2, -- .rates = SNDRV_PCM_RATE_8000_96000, -+ .rates = (SNDRV_PCM_RATE_8000 | -+ SNDRV_PCM_RATE_16000 | -+ SNDRV_PCM_RATE_32000 | -+ SNDRV_PCM_RATE_48000 | -+ SNDRV_PCM_RATE_64000 | -+ SNDRV_PCM_RATE_96000), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE | - -From 18c2e6ae90ef04553b19766de65469e7f3e107b3 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sun, 3 Sep 2017 11:19:19 +0200 -Subject: [PATCH 31/46] arm64: dts: rockchip: rk3328-rock64: use two dai-link - for i2s sound - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 28 ++++++++++++++++++++------ - sound/soc/soc-utils.c | 10 +++++++++ - 2 files changed, 32 insertions(+), 6 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index 32705c6ddebf..f2e3358a119b 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -94,6 +94,11 @@ - }; - }; - -+ dummy_codec: dummy-codec { -+ compatible = "linux,snd-soc-dummy"; -+ #sound-dai-cells = <0>; -+ }; -+ - hdmi-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; -@@ -109,14 +114,25 @@ - - sound { - compatible = "simple-audio-card"; -- simple-audio-card,format = "i2s"; - simple-audio-card,mclk-fs = <256>; -- simple-audio-card,name = "ACODEC"; -- simple-audio-card,cpu { -- sound-dai = <&i2s1>; -+ simple-audio-card,name = "I2S"; -+ simple-audio-card,dai-link@0 { -+ format = "i2s"; -+ cpu { -+ sound-dai = <&i2s1>; -+ }; -+ codec { -+ sound-dai = <&codec>; -+ }; - }; -- simple-audio-card,codec { -- sound-dai = <&codec>; -+ simple-audio-card,dai-link@1 { -+ format = "i2s"; -+ cpu { -+ sound-dai = <&i2s1>; -+ }; -+ codec { -+ sound-dai = <&dummy_codec>; -+ }; - }; - }; - -diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c -index 53dd085d3ee2..bf7ce34084a9 100644 ---- a/sound/soc/soc-utils.c -+++ b/sound/soc/soc-utils.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots) - { -@@ -160,9 +161,18 @@ static int snd_soc_dummy_remove(struct platform_device *pdev) - return 0; - } - -+#ifdef CONFIG_OF -+static const struct of_device_id soc_dummy_ids[] = { -+ { .compatible = "linux,snd-soc-dummy", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, soc_dummy_ids); -+#endif -+ - static struct platform_driver soc_dummy_driver = { - .driver = { - .name = "snd-soc-dummy", -+ .of_match_table = of_match_ptr(soc_dummy_ids), - }, - .probe = snd_soc_dummy_probe, - .remove = snd_soc_dummy_remove, - -From 955cdeedc8a9e9f83178b21d3fa75438ece236af Mon Sep 17 00:00:00 2001 -From: LongChair -Date: Sun, 26 Mar 2017 15:30:15 +0200 -Subject: [PATCH 32/46] video/rockchip: raise up vpu clock - ---- - drivers/video/rockchip/vcodec/vcodec_service.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/drivers/video/rockchip/vcodec/vcodec_service.c b/drivers/video/rockchip/vcodec/vcodec_service.c -index 2155ee6b0025..fd034060cac4 100644 ---- a/drivers/video/rockchip/vcodec/vcodec_service.c -+++ b/drivers/video/rockchip/vcodec/vcodec_service.c -@@ -1122,8 +1122,7 @@ static void get_reg_freq(struct vpu_subdev_data *data, struct vpu_reg *reg) - } - } - if (data->hw_id == HEVC_ID) { -- if (reg_probe_hevc_y_stride(reg) > 60000) -- reg->freq = VPU_FREQ_400M; -+ reg->freq = VPU_FREQ_600M; - } - if (reg->type == VPU_PP) - reg->freq = VPU_FREQ_400M; - -From 3bbac2c2d7a9f57c6acd7e8c8c1361778bc987a5 Mon Sep 17 00:00:00 2001 +From 7d28363c78715dbc7d9e9c3ea1208c000357e60f Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 29 Mar 2017 23:51:09 +0200 -Subject: [PATCH 33/46] gpu/arm/midgard: default to performance gpu governor +Subject: [PATCH] gpu/arm/midgard: default to performance gpu governor --- drivers/gpu/arm/midgard_for_linux/backend/gpu/mali_kbase_devfreq.c | 6 ++---- @@ -3993,10 +47,10 @@ index 9b00cce9b2b3..739ac83b484f 100644 /* * Power Management poweroff tick granuality. This is in nanoseconds to -From 7f29e729ed6789b8cbd5b395f5a560e9bc3d91cb Mon Sep 17 00:00:00 2001 +From 05bf0dd806a0621d8daf1a0ca0a057db52c766c7 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 17 Apr 2017 13:09:16 +0200 -Subject: [PATCH 34/46] sound/usb/quirks-table: add Realtek ALC4040 +Subject: [PATCH] sound/usb/quirks-table: add Realtek ALC4040 --- sound/usb/quirks-table.h | 9 +++++++++ @@ -4021,10 +75,10 @@ index 8a59d4782a0f..96e1e2fdc9c3 100644 + #undef USB_DEVICE_VENDOR_SPEC -From 4575feb7da25c2fe56f3bc3a73b623141f448d68 Mon Sep 17 00:00:00 2001 +From b9abd7bdaf549b7ab366ed00bf2bda82a3f27de2 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sun, 28 May 2017 09:08:50 +0200 -Subject: [PATCH 35/46] gpu/arm/mali400: default to performance gpu governor +Subject: [PATCH] gpu/arm/mali400: default to performance gpu governor --- drivers/gpu/arm/mali400/mali/linux/mali_devfreq.c | 2 +- @@ -4044,20 +98,20 @@ index 3eac07d76766..14916ea86905 100644 mali_devfreq_term_freq_table(mdev); return PTR_ERR(mdev->devfreq); -From 622e949444acbf09dab3ea2948dd9d3dd4a4d564 Mon Sep 17 00:00:00 2001 +From b23910f4b14b183874bb6ae3d2312a0dbb819558 Mon Sep 17 00:00:00 2001 From: LongChair Date: Fri, 21 Apr 2017 13:39:12 +0200 -Subject: [PATCH 36/46] drm/rockchip: remove unsupported 4K freqs +Subject: [PATCH] drm/rockchip: remove unsupported 4K freqs --- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index 6015e78ca05d..b3b6fd7ed698 100644 +index 257d0d0dcc3d..f3571e417c6c 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -@@ -504,9 +504,19 @@ dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, +@@ -506,9 +506,19 @@ dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, return MODE_BAD; hdmi = to_rockchip_hdmi(encoder); @@ -4079,22 +133,22 @@ index 6015e78ca05d..b3b6fd7ed698 100644 * ensure all drm display mode can work, if someone want support more * resolutions, please limit the possible_crtc, only connect to -From b80b60c1e0a96d7fff977db26817cea55761c6a1 Mon Sep 17 00:00:00 2001 +From d60669d40ac968f4a6f2d43dfe0ed4a1960cb50f Mon Sep 17 00:00:00 2001 From: xuhuicong Date: Fri, 23 Jun 2017 18:56:17 +0800 -Subject: [PATCH 37/46] drm/rockchip: hdmi: fix no sound some time +Subject: [PATCH] drm/rockchip: hdmi: fix no sound some time Change-Id: Ic9f931d9a5b7bca954363293a20ca242eb0bfa6f Signed-off-by: xuhuicong --- - drivers/gpu/drm/bridge/dw-hdmi.c | 7 +++---- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index 09b43a348525..0fc5b0e6ae77 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -1978,10 +1978,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 3616265dae0c..6f220dffe345 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1967,10 +1967,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, HDMI_FC_INVIDCONF_IN_I_P_INTERLACED : HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE; @@ -4105,7 +159,7 @@ index 09b43a348525..0fc5b0e6ae77 100644 hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF); hdisplay = mode->hdisplay; -@@ -2270,6 +2266,9 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) +@@ -2268,6 +2264,9 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) /* not for DVI mode */ if (hdmi->sink_is_hdmi) { dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); @@ -4116,21 +170,20 @@ index 09b43a348525..0fc5b0e6ae77 100644 /* HDMI Initialization Step F - Configure AVI InfoFrame */ hdmi_config_AVI(hdmi, mode); -From 8512fcf3e8120321619d7211005d121f3ff397db Mon Sep 17 00:00:00 2001 +From 8697d61bca564c67696cc10c0188b02ac3371309 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Fri, 25 Aug 2017 18:29:35 +0200 -Subject: [PATCH 38/46] video: rockchip: vpu: partial revise for rk322xh - feature +Subject: [PATCH] video: rockchip: vpu: partial revise for rk322xh feature --- drivers/video/rockchip/vcodec/vcodec_service.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/video/rockchip/vcodec/vcodec_service.c b/drivers/video/rockchip/vcodec/vcodec_service.c -index fd034060cac4..e77c022eae78 100644 +index 4b2eb9093d35..7dae54e2c984 100644 --- a/drivers/video/rockchip/vcodec/vcodec_service.c +++ b/drivers/video/rockchip/vcodec/vcodec_service.c -@@ -2806,21 +2806,15 @@ static irqreturn_t vdpu_irq(int irq, void *dev_id) +@@ -3662,21 +3662,15 @@ static irqreturn_t vdpu_irq(int irq, void *dev_id) time_record(task, 1); vpu_debug(DEBUG_IRQ_STATUS, "vdpu_irq dec status %08x\n", dec_status); @@ -4156,65 +209,20 @@ index fd034060cac4..e77c022eae78 100644 time_diff(task); pservice->irq_status = raw_status; -From f4a45d1a16557a2666c11caa820fca2cecfedbdf Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Sat, 12 Aug 2017 21:50:15 +0200 -Subject: [PATCH 39/46] net: stmmac: dwmac-rk: change vendor storage id for - integrated PHY - ---- - drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -index 8b7184c5508f..1cd719a8ff4e 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -@@ -1333,6 +1333,7 @@ void __weak rk_devinfo_get_eth_mac(u8 *mac) - - void rk_get_eth_addr(void *priv, unsigned char *addr) - { -+ u32 id; - int ret; - struct rk_priv_data *bsp_priv = priv; - struct device *dev = &bsp_priv->pdev->dev; -@@ -1341,15 +1342,18 @@ void rk_get_eth_addr(void *priv, unsigned char *addr) - if (is_valid_ether_addr(addr)) - goto out; - -- ret = rk_vendor_read(LAN_MAC_ID, addr, 6); -- if (ret != 6 || is_zero_ether_addr(addr)) { -+ /* use vendor storage id 7 for integrated phy */ -+ id = bsp_priv->integrated_phy ? 7 : LAN_MAC_ID; -+ -+ ret = rk_vendor_read(id, addr, 6); -+ if (ret != 6 || !is_valid_ether_addr(addr)) { - dev_err(dev, "%s: rk_vendor_read eth mac address failed (%d)", - __func__, ret); - random_ether_addr(addr); - dev_err(dev, "%s: generate random eth mac address: %02x:%02x:%02x:%02x:%02x:%02x", - __func__, addr[0], addr[1], addr[2], - addr[3], addr[4], addr[5]); -- ret = rk_vendor_write(LAN_MAC_ID, addr, 6); -+ ret = rk_vendor_write(id, addr, 6); - if (ret != 0) - dev_err(dev, "%s: rk_vendor_write eth mac address failed (%d)", - __func__, ret); - -From 823189e34a565a3e5a6d68e58e85b7dedc036157 Mon Sep 17 00:00:00 2001 +From 6b89c0851c7b9e5f30a344d7d9d10f339908406b Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 2 Oct 2017 21:53:19 +0200 -Subject: [PATCH 40/46] drm/rockchip: use limited range +Subject: [PATCH] drm/rockchip: use limited range --- - drivers/gpu/drm/bridge/dw-hdmi.c | 16 ++++++++++++++-- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index 0fc5b0e6ae77..beba78accfe3 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -144,6 +144,12 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = { +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 6f220dffe345..fde18ec6cb7f 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -147,6 +147,12 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = { { 0x6756, 0x78ab, 0x2000, 0x0200 } }; @@ -4227,7 +235,7 @@ index 0fc5b0e6ae77..beba78accfe3 100644 struct hdmi_vmode { bool mdataenablepolarity; -@@ -1008,7 +1014,9 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi) +@@ -996,7 +1002,9 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi) static int is_color_space_conversion(struct dw_hdmi *hdmi) { @@ -4238,7 +246,7 @@ index 0fc5b0e6ae77..beba78accfe3 100644 } static int is_color_space_decimation(struct dw_hdmi *hdmi) -@@ -1042,7 +1050,11 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) +@@ -1030,7 +1038,11 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) u32 csc_scale = 1; if (is_color_space_conversion(hdmi)) { @@ -4252,55 +260,32 @@ index 0fc5b0e6ae77..beba78accfe3 100644 V4L2_YCBCR_ENC_601) csc_coeff = &csc_coeff_rgb_out_eitu601; -From 20eb0b51b74f3be508b791b064ca2207692e8141 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 31 Oct 2017 21:17:10 +0100 -Subject: [PATCH 41/46] gpio: gpiolib: Make the dynamic gpio base start from - 1000 - ---- - drivers/gpio/gpiolib.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c -index 06d345b087f8..daae33ee55b5 100644 ---- a/drivers/gpio/gpiolib.c -+++ b/drivers/gpio/gpiolib.c -@@ -126,7 +126,7 @@ EXPORT_SYMBOL_GPL(gpiod_to_chip); - static int gpiochip_find_base(int ngpio) - { - struct gpio_chip *chip; -- int base = ARCH_NR_GPIOS - ngpio; -+ int base = ARCH_GPIO_BASE + ARCH_NR_GPIOS - ngpio; - - list_for_each_entry_reverse(chip, &gpio_chips, list) { - /* found a free space? */ - -From 230dcdaabb35693df1eae767a6214e96b492ea97 Mon Sep 17 00:00:00 2001 +From 4ff657ebf2730706c0929f341e5c403b0841cceb Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sat, 18 Nov 2017 11:09:39 +0100 -Subject: [PATCH 42/46] rockchip: vop: force skip lines if image too big +Subject: [PATCH] rockchip: vop: force skip lines if image too big --- - drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -index f7541a53ccba..0ca40d100e8b 100644 +index 2426c0f7d6ac..df44b8028a4e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c -@@ -1539,6 +1539,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, +@@ -1565,6 +1565,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, int ymirror, xmirror; uint32_t val; - bool rb_swap; + bool rb_swap, global_alpha_en; + int skip_lines = 0; /* * can't update plane when vop is disabled. -@@ -1551,8 +1552,13 @@ static void vop_plane_atomic_update(struct drm_plane *plane, - return; +@@ -1578,8 +1579,14 @@ static void vop_plane_atomic_update(struct drm_plane *plane, } + mode = &crtc->state->adjusted_mode; ++ + /* + * force skip lines if image too big. + */ @@ -4312,7 +297,7 @@ index f7541a53ccba..0ca40d100e8b 100644 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); dsp_info = (drm_rect_height(dest) - 1) << 16; -@@ -1574,10 +1580,10 @@ static void vop_plane_atomic_update(struct drm_plane *plane, +@@ -1601,10 +1608,10 @@ static void vop_plane_atomic_update(struct drm_plane *plane, VOP_WIN_SET(vop, win, xmirror, xmirror); VOP_WIN_SET(vop, win, ymirror, ymirror); VOP_WIN_SET(vop, win, format, vop_plane_state->format); @@ -4326,10 +311,10 @@ index f7541a53ccba..0ca40d100e8b 100644 } VOP_WIN_SET(vop, win, fmt_10, is_yuv_10bit(fb->pixel_format)); -From afb22f5649aed60ccd3c26977d3ced748a00a963 Mon Sep 17 00:00:00 2001 +From 65b437251804b8055f6a320e88068a4e8ac1dc1d Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sat, 18 Nov 2017 23:17:24 +0100 -Subject: [PATCH 43/46] gpu/arm/midgard: default to performance gpu governor +Subject: [PATCH] gpu/arm/midgard: default to performance gpu governor --- drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c | 5 ++--- @@ -4374,10 +359,10 @@ index e674cc2ea183..0f11388acfd7 100644 /* * Power Management poweroff tick granuality. This is in nanoseconds to -From cb8ec4e4c907a02c3c89789e8673aabf5719b7db Mon Sep 17 00:00:00 2001 +From 5fa6f2d6940c197ce66eb6c9dc9b66b8439c8b9b Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sun, 10 Dec 2017 14:16:09 +0100 -Subject: [PATCH 44/46] uapi: install rockchip_drm header +Subject: [PATCH] uapi: install rockchip_drm header --- include/uapi/drm/Kbuild | 1 + @@ -4396,20 +381,20 @@ index 38d437096c35..b7ae9969d41e 100644 header-y += sis_drm.h header-y += tegra_drm.h -From 805e82148be35c32177eb61f87401ee8eb93b6dc Mon Sep 17 00:00:00 2001 +From 5fd93ac070893b22220c3bf22a2a94d820f09710 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sun, 10 Dec 2017 18:03:53 +0100 -Subject: [PATCH 45/46] phy: rockchip-inno-hdmi-phy: add vesa dmt pixel clocks +Subject: [PATCH] phy: rockchip-inno-hdmi-phy: add vesa dmt pixel clocks --- drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c | 71 +++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c -index f761b9b2f78f..68af8ad7656e 100644 +index 5b28b33e8be4..f1915d4e7e01 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c -@@ -244,6 +244,77 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { +@@ -245,6 +245,77 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0}, {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B}, {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0}, @@ -4488,10 +473,10 @@ index f761b9b2f78f..68af8ad7656e 100644 }; -From 771dda175fac3649612c19a7e3c4313755b6bad4 Mon Sep 17 00:00:00 2001 +From ddcf34bd97e390948a327cb152e0c3ea8641c0da Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 12 Dec 2017 00:37:27 +0100 -Subject: [PATCH 46/46] clk: rockchip: fix round rate +Subject: [PATCH] clk: rockchip: fix round rate --- drivers/clk/rockchip/clk-pll.c | 11 +++++++++++ @@ -4519,3 +504,201 @@ index 781a92909a7c..ec41034041d0 100644 return drate; } + +From 67aa835849326a6cb61b0b3b5470a0a14611bae8 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 21 Jan 2018 17:20:00 +0100 +Subject: [PATCH] drm: fix HDR metadata infoframe length + +HDR metadata infoframe length is 26 bytes (not 30) according to [1] +(CTA-861-G: 6.9 Dynamic Range and Mastering InfoFrame) + +Fixes activation of HDR mode on my LG OLED + +[1] https://standards.cta.tech/kwspub/published_docs/CTA-861-G_FINAL_revised_2017.pdf +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- + drivers/gpu/drm/drm_edid.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index fde18ec6cb7f..48c46f4b25ae 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1845,7 +1845,7 @@ static void hdmi_config_hdr_infoframe(struct dw_hdmi *hdmi) + return; + } + +- hdmi_writeb(hdmi, 1, HDMI_FC_DRM_HB0); ++ hdmi_writeb(hdmi, frame.version, HDMI_FC_DRM_HB0); + hdmi_writeb(hdmi, frame.length, HDMI_FC_DRM_HB1); + hdmi_writeb(hdmi, frame.eotf, HDMI_FC_DRM_PB0); + hdmi_writeb(hdmi, frame.metadata_type, HDMI_FC_DRM_PB1); +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index 3e3ebdf34e9f..d06786a58ca1 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -4727,10 +4727,10 @@ drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame, + + hdr_source_metadata = (struct hdr_static_metadata *)hdr_metadata; + +- frame->length = sizeof(struct hdr_static_metadata); ++ frame->length = 26; + + frame->eotf = hdr_source_metadata->eotf; +- frame->type = hdr_source_metadata->type; ++ frame->metadata_type = hdr_source_metadata->type; + + for (i = 0; i < 3; i++) { + frame->display_primaries_x[i] = + +From 57597be2f7639355547ec5da5196cc09109fcd47 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 27 Jan 2018 09:39:09 +0100 +Subject: [PATCH] drm: add edid detection for Hybrid Log-Gamma EOTF + +--- + drivers/gpu/drm/drm_edid.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index d06786a58ca1..bfd64112178a 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -2737,7 +2737,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, + #define TRADITIONAL_GAMMA_SDR (0x1 << 0) + #define TRADITIONAL_GAMMA_HDR (0x1 << 1) + #define SMPTE_ST2084 (0x1 << 2) +-#define FUTURE_EOTF (0x1 << 3) ++#define HYBRID_LOG_GAMMA (0x1 << 3) + #define RESERVED_EOTF (0x3 << 4) + + #define STATIC_METADATA_TYPE1 (0x1 << 0) +@@ -3707,6 +3707,8 @@ static uint16_t eotf_supported(const u8 *edid_ext) + val |= TRADITIONAL_GAMMA_HDR; + if (edid_ext[2] & SMPTE_ST2084) + val |= SMPTE_ST2084; ++ if (edid_ext[2] & HYBRID_LOG_GAMMA) ++ val |= HYBRID_LOG_GAMMA; + + return val; + } + +From 2f32c637798915651318af4c193462ae3116174b Mon Sep 17 00:00:00 2001 +From: Martin Cerveny +Date: Wed, 31 Jan 2018 15:50:14 +0100 +Subject: [PATCH] phy: rockchip-inno-hdmi-phy: TMDS calculation overflow + +For example 3840x2160p60 (Pixel Clk: 594000000Hz) -> bus_width==5 (YUV420 10bit) -> TMDS Clk: 371250000 (and should not overflow) ! +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c +index f1915d4e7e01..dfde5d3f22dd 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c +@@ -411,16 +411,16 @@ static u32 inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno, int rate) + tmdsclk = rate / 2; + break; + case 5: +- tmdsclk = rate * 5 / 8; ++ tmdsclk = (uint64_t)rate * 5 / 8; + break; + case 6: +- tmdsclk = rate * 3 / 4; ++ tmdsclk = (uint64_t)rate * 3 / 4; + break; + case 10: +- tmdsclk = rate * 5 / 4; ++ tmdsclk = (uint64_t)rate * 5 / 4; + break; + case 12: +- tmdsclk = rate * 3 / 2; ++ tmdsclk = (uint64_t)rate * 3 / 2; + break; + case 16: + tmdsclk = rate * 2; + +From 67b544841243ffe0bd72938d64e8d3be6c27743d Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 11 Feb 2018 19:21:41 +0100 +Subject: [PATCH] drm: bridge: dw-hdmi: default to underscan mode + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 48c46f4b25ae..8086940664b4 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1679,7 +1679,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + break; + } + +- frame.scan_mode = HDMI_SCAN_MODE_NONE; ++ frame.scan_mode = HDMI_SCAN_MODE_UNDERSCAN; + + /* + * The Designware IP uses a different byte format from standard + +From ba31c3d5eb595d9b5266e1a52df6e71c1557d14d Mon Sep 17 00:00:00 2001 +From: David Carrillo-Cisneros +Date: Tue, 18 Jul 2017 18:18:37 -0700 +Subject: [PATCH] UPSTREAM: perf tools: Add EXCLUDE_EXTLIBS and EXTRA_PERFLIBS + to makefile + +The goal is to allow users to override linking of libraries that +were automatically added to PERFLIBS. + +EXCLUDE_EXTLIBS contains linker flags to be removed from LIBS +while EXTRA_PERFLIBS contains linker flags to be added. + +My use case is to force certain library to be build statically, +e.g. for libelf: + + EXCLUDE_EXTLIBS=-lelf EXTRA_PERFLIBS=path/libelf.a + +Signed-off-by: David Carrillo-Cisneros +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Elena Reshetova +Cc: Kees Kook +Cc: Paul Turner +Cc: Stephane Eranian +Cc: Sudeep Holla +Cc: Wang Nan +Link: http://lkml.kernel.org/r/20170719011839.99399-3-davidcc@google.com +Signed-off-by: Arnaldo Carvalho de Melo +(cherry picked from commit cb281fea4b0a326d2a2104f8ffae2b6895c561fd) +--- + tools/perf/Makefile.perf | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf +index fb1c9ddc3478..9b3b9bd50d54 100644 +--- a/tools/perf/Makefile.perf ++++ b/tools/perf/Makefile.perf +@@ -33,6 +33,11 @@ include config/utilities.mak + # + # Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. + # ++# Define EXCLUDE_EXTLIBS=-lmylib to exclude libmylib from the auto-generated ++# EXTLIBS. ++# ++# Define EXTRA_PERFLIBS to pass extra libraries to PERFLIBS. ++# + # Define NO_DWARF if you do not want debug-info analysis feature at all. + # + # Define WERROR=0 to disable treating any warnings as errors. +@@ -289,7 +294,8 @@ ifdef ASCIIDOC8 + export ASCIIDOC8 + endif + +-LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group ++EXTLIBS := $(call filter-out,$(EXCLUDE_EXTLIBS),$(EXTLIBS)) ++LIBS = -Wl,--whole-archive $(PERFLIBS) $(EXTRA_PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group + + export INSTALL SHELL_PATH + diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0002-ir.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0002-ir.patch index be1024e9c0..f2f41e2a64 100644 --- a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0002-ir.patch +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0002-ir.patch @@ -1,7 +1,35 @@ -From a91ba53b3b923f767aa500c2209ebeae364a1f4e Mon Sep 17 00:00:00 2001 +From 7ed1ed35ede3d6a5ad864924f65de15910690140 Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Thu, 19 Nov 2015 11:41:36 -0200 +Subject: [PATCH] UPSTREAM: smsir.h: remove a now duplicated definition + (IR_DEFAULT_TIMEOUT) + +This macro is now part of the core. Remove from Siano driver. + +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 850c8a7d68a761b5f11d5b443b5ece185e8068f4) +--- + drivers/media/common/siano/smsir.h | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/media/common/siano/smsir.h b/drivers/media/common/siano/smsir.h +index fc8b7925c532..d9abd96ef48b 100644 +--- a/drivers/media/common/siano/smsir.h ++++ b/drivers/media/common/siano/smsir.h +@@ -30,8 +30,6 @@ along with this program. If not, see . + #include + #include + +-#define IR_DEFAULT_TIMEOUT 100 +- + struct smscore_device_t; + + struct ir_t { + +From ae4106c9f6587e5bcbd414c1df4b59bf6a009794 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 6 Sep 2017 18:39:09 +0200 -Subject: [PATCH 1/7] [media] rc/keymaps: add keytable for Pine64 IR Remote +Subject: [PATCH] [media] rc/keymaps: add keytable for Pine64 IR Remote Controller --- @@ -107,52 +135,10 @@ index 7c4bbc4dfab4..3a34a9631dd1 100644 #define RC_MAP_PINNACLE_GREY "rc-pinnacle-grey" #define RC_MAP_PINNACLE_PCTV_HD "rc-pinnacle-pctv-hd" -From 6779fbca58a5e13f58b0ab1b68aabcc240631c1b Mon Sep 17 00:00:00 2001 +From d8df6397a5a354ff41e25d93a625fe517ec5d5a4 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 6 Sep 2017 18:39:09 +0200 -Subject: [PATCH 2/7] arm64: dts: rockchip: rk3328-rock64: add ir-receiver - ---- - arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -index f2e3358a119b..28528e0ad926 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts -@@ -70,6 +70,14 @@ - #clock-cells = <0>; - }; - -+ ir: ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; -+ linux,rc-map-name = "rc-pine64"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ir_int>; -+ }; -+ - leds { - compatible = "gpio-leds"; - -@@ -489,6 +497,12 @@ - <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; /* gpio2_a6 */ - }; - }; -+ -+ ir { -+ ir_int: ir-int { -+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; - }; - - &rkvdec { - -From 090e35d622cd9d8280c86fe5f199558d7e4918a3 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 6 Sep 2017 18:39:09 +0200 -Subject: [PATCH 3/7] [media] rc/keymaps: add keytable for ODROID IR Remote +Subject: [PATCH] [media] rc/keymaps: add keytable for ODROID IR Remote Controller --- @@ -245,10 +231,10 @@ index 3a34a9631dd1..f1badbfbca90 100644 #define RC_MAP_PINE64 "rc-pine64" #define RC_MAP_PINNACLE_COLOR "rc-pinnacle-color" -From 6f7300964103c68af09ba550844974369e8d6738 Mon Sep 17 00:00:00 2001 +From a256d6c59814dcdd1489c82368bb9e9937f11408 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 6 Sep 2017 18:39:09 +0200 -Subject: [PATCH 4/7] [media] rc/keymaps: add keytable for WeTek Hub Remote +Subject: [PATCH] [media] rc/keymaps: add keytable for WeTek Hub Remote Controller --- @@ -341,10 +327,10 @@ index f1badbfbca90..cd8590c99e22 100644 #define RC_MAP_VIDEOMATE_S350 "rc-videomate-s350" #define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr" -From fd26a6d33798774bef4a757eec1f3de8eba5235c Mon Sep 17 00:00:00 2001 +From def6431495bad6e916a10ce9ddfc5f4b3597422a Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 6 Sep 2017 18:39:09 +0200 -Subject: [PATCH 5/7] [media] rc/keymaps: add keytable for WeTek Play 2 Remote +Subject: [PATCH] [media] rc/keymaps: add keytable for WeTek Play 2 Remote Controller --- @@ -467,73 +453,3 @@ index cd8590c99e22..93cac05a5170 100644 #define RC_MAP_VIDEOMATE_K100 "rc-videomate-k100" #define RC_MAP_VIDEOMATE_S350 "rc-videomate-s350" #define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr" - -From 0136a4003d867331afacd22d182ff444da2c5495 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Mon, 30 Oct 2017 23:47:18 +0100 -Subject: [PATCH 6/7] arm64: dts: rockchip: rk3328-rockbox: add ir-receiver - ---- - arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -index 8ac8a8cc04ed..17ba816dc049 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts -@@ -84,6 +84,14 @@ - reset-gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; - }; - -+ ir: ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; -+ linux,rc-map-name = "rc-pine64"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ir_int>; -+ }; -+ - leds { - compatible = "gpio-leds"; - -@@ -414,6 +422,12 @@ - }; - }; - -+ ir { -+ ir_int: ir-int { -+ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - sdio-pwrseq { - wifi_enable_h: wifi-enable-h { - rockchip,pins = - -From 5e5a04d8a759f3799c9a623e4a41073091147d8e Mon Sep 17 00:00:00 2001 -From: Mauro Carvalho Chehab -Date: Thu, 19 Nov 2015 11:41:36 -0200 -Subject: [PATCH 7/7] UPSTREAM: smsir.h: remove a now duplicated definition - (IR_DEFAULT_TIMEOUT) - -This macro is now part of the core. Remove from Siano driver. - -Signed-off-by: Mauro Carvalho Chehab -(cherry picked from commit 850c8a7d68a761b5f11d5b443b5ece185e8068f4) ---- - drivers/media/common/siano/smsir.h | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/drivers/media/common/siano/smsir.h b/drivers/media/common/siano/smsir.h -index fc8b7925c532..d9abd96ef48b 100644 ---- a/drivers/media/common/siano/smsir.h -+++ b/drivers/media/common/siano/smsir.h -@@ -30,8 +30,6 @@ along with this program. If not, see . - #include - #include - --#define IR_DEFAULT_TIMEOUT 100 -- - struct smscore_device_t; - - struct ir_t { diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0003-cec.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0003-cec.patch index 69113e98d1..eb463eed3b 100644 --- a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0003-cec.patch +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0003-cec.patch @@ -1,50 +1,43 @@ -From e875d688b7a41ffe5ac958775e2a86020ddb7a87 Mon Sep 17 00:00:00 2001 +From 9e81a6caf8bceb87b3ea0d394f41f911fd92ff4b Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 4 Sep 2017 22:34:19 +0200 -Subject: [PATCH 01/11] BACKPORT: HDMI CEC support from v4.13 +Subject: [PATCH] BACKPORT: HDMI CEC support from v4.15 Skipped changes: 857313e51006ff51524579bcd8808b70f9a80812 "media: utilize new cdev_device_add helper function" 0f7499fddb153a333dff3c1dc4280c178b9b5a80 "[media] rc-main: assign driver type during allocation" --- Documentation/devicetree/bindings/media/cec.txt | 8 + - Documentation/media/kapi/cec-core.rst | 338 +++++++++++++++++++ - Documentation/media/uapi/cec/cec-api.rst | 43 +++ + Documentation/media/kapi/cec-core.rst | 381 +++++++++++++++++++++ + Documentation/media/uapi/cec/cec-api.rst | 46 +++ Documentation/media/uapi/cec/cec-func-close.rst | 47 +++ Documentation/media/uapi/cec/cec-func-ioctl.rst | 66 ++++ Documentation/media/uapi/cec/cec-func-open.rst | 78 +++++ Documentation/media/uapi/cec/cec-func-poll.rst | 77 +++++ - Documentation/media/uapi/cec/cec-funcs.rst | 21 ++ + Documentation/media/uapi/cec/cec-funcs.rst | 20 ++ Documentation/media/uapi/cec/cec-header.rst | 10 + Documentation/media/uapi/cec/cec-intro.rst | 40 +++ - .../media/uapi/cec/cec-ioc-adap-g-caps.rst | 132 ++++++++ - .../media/uapi/cec/cec-ioc-adap-g-log-addrs.rst | 366 +++++++++++++++++++++ - .../media/uapi/cec/cec-ioc-adap-g-phys-addr.rst | 93 ++++++ - Documentation/media/uapi/cec/cec-ioc-dqevent.rst | 187 +++++++++++ - Documentation/media/uapi/cec/cec-ioc-g-mode.rst | 263 +++++++++++++++ - Documentation/media/uapi/cec/cec-ioc-receive.rst | 342 +++++++++++++++++++ + .../media/uapi/cec/cec-ioc-adap-g-caps.rst | 139 ++++++++ + .../media/uapi/cec/cec-ioc-adap-g-log-addrs.rst | 371 ++++++++++++++++++++ + .../media/uapi/cec/cec-ioc-adap-g-phys-addr.rst | 93 +++++ + Documentation/media/uapi/cec/cec-ioc-dqevent.rst | 226 ++++++++++++ + Documentation/media/uapi/cec/cec-ioc-g-mode.rst | 293 ++++++++++++++++ + Documentation/media/uapi/cec/cec-ioc-receive.rst | 344 +++++++++++++++++++ MAINTAINERS | 16 + - drivers/media/Kconfig | 28 +- - drivers/media/Makefile | 10 +- - drivers/media/cec/Kconfig | 6 + - drivers/media/cec/Makefile | 8 +- - drivers/media/cec/cec-adap.c | 219 ++++++++---- - drivers/media/cec/cec-api.c | 32 +- - drivers/media/cec/cec-core.c | 48 ++- - drivers/media/{ => cec}/cec-edid.c | 6 +- - drivers/media/cec/cec-notifier.c | 136 ++++++++ + drivers/media/cec/cec-adap.c | 61 +++- + drivers/media/cec/cec-core.c | 15 +- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-cec.c | 182 ++++++++++ drivers/media/rc/rc-main.c | 1 + fs/compat_ioctl.c | 12 + - include/media/cec-edid.h | 104 ------ - include/media/cec-notifier.h | 136 ++++++++ - include/media/cec.h | 148 ++++++++- + include/media/cec-notifier.h | 22 ++ + include/media/cec.h | 32 +- include/media/rc-map.h | 5 +- - include/uapi/linux/cec.h | 4 +- + include/uapi/linux/cec-funcs.h | 1 + + include/uapi/linux/cec.h | 2 +- include/uapi/linux/input-event-codes.h | 31 ++ include/uapi/linux/input.h | 1 + - 37 files changed, 3019 insertions(+), 226 deletions(-) + 30 files changed, 2606 insertions(+), 15 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/cec.txt create mode 100644 Documentation/media/kapi/cec-core.rst create mode 100644 Documentation/media/uapi/cec/cec-api.rst @@ -61,12 +54,7 @@ Skipped changes: create mode 100644 Documentation/media/uapi/cec/cec-ioc-dqevent.rst create mode 100644 Documentation/media/uapi/cec/cec-ioc-g-mode.rst create mode 100644 Documentation/media/uapi/cec/cec-ioc-receive.rst - create mode 100644 drivers/media/cec/Kconfig - rename drivers/media/{ => cec}/cec-edid.c (96%) - create mode 100644 drivers/media/cec/cec-notifier.c create mode 100644 drivers/media/rc/keymaps/rc-cec.c - delete mode 100644 include/media/cec-edid.h - create mode 100644 include/media/cec-notifier.h diff --git a/Documentation/devicetree/bindings/media/cec.txt b/Documentation/devicetree/bindings/media/cec.txt new file mode 100644 @@ -84,10 +72,10 @@ index 000000000000..22d7aae3d3d7 + up or down. diff --git a/Documentation/media/kapi/cec-core.rst b/Documentation/media/kapi/cec-core.rst new file mode 100644 -index 000000000000..8a65c69ed071 +index 000000000000..d37e107f2fde --- /dev/null +++ b/Documentation/media/kapi/cec-core.rst -@@ -0,0 +1,338 @@ +@@ -0,0 +1,381 @@ +CEC Kernel Support +================== + @@ -197,6 +185,7 @@ index 000000000000..8a65c69ed071 + int (*adap_transmit)(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *msg); + void (*adap_status)(struct cec_adapter *adap, struct seq_file *file); ++ void (*adap_free)(struct cec_adapter *adap); + + /* High-level callbacks */ + ... @@ -274,6 +263,14 @@ index 000000000000..8a65c69ed071 +This optional callback can be used to show the status of the CEC hardware. +The status is available through debugfs: cat /sys/kernel/debug/cec/cecX/status + ++To free any resources when the adapter is deleted: ++ ++.. c:function:: ++ void (*adap_free)(struct cec_adapter *adap); ++ ++This optional callback can be used to free any resources that might have been ++allocated by the driver. It's called from cec_delete_adapter. ++ + +Your adapter driver will also have to react to events (typically interrupt +driven) by calling into the framework in the following situations: @@ -308,8 +305,8 @@ index 000000000000..8a65c69ed071 + retransmission. + +CEC_TX_STATUS_ERROR: -+ some unspecified error occurred: this can be one of -+ the previous two if the hardware cannot differentiate or something ++ some unspecified error occurred: this can be one of ARB_LOST ++ or LOW_DRIVE if the hardware cannot differentiate or something + else entirely. + +CEC_TX_STATUS_MAX_RETRIES: @@ -319,6 +316,9 @@ index 000000000000..8a65c69ed071 + doesn't have to make another attempt to transmit the message + since the hardware did that already. + ++The hardware must be able to differentiate between OK, NACK and 'something ++else'. ++ +The \*_cnt arguments are the number of error conditions that were seen. +This may be 0 if no information is available. Drivers that do not support +hardware retry can just set the counter corresponding to the transmit error @@ -426,12 +426,43 @@ index 000000000000..8a65c69ed071 +unconfiguring. This function will just return if the physical address is +invalid. Once the physical address becomes valid, then the framework will +attempt to claim these logical addresses. ++ ++CEC Pin framework ++----------------- ++ ++Most CEC hardware operates on full CEC messages where the software provides ++the message and the hardware handles the low-level CEC protocol. But some ++hardware only drives the CEC pin and software has to handle the low-level ++CEC protocol. The CEC pin framework was created to handle such devices. ++ ++Note that due to the close-to-realtime requirements it can never be guaranteed ++to work 100%. This framework uses highres timers internally, but if a ++timer goes off too late by more than 300 microseconds wrong results can ++occur. In reality it appears to be fairly reliable. ++ ++One advantage of this low-level implementation is that it can be used as ++a cheap CEC analyser, especially if interrupts can be used to detect ++CEC pin transitions from low to high or vice versa. ++ ++.. kernel-doc:: include/media/cec-pin.h ++ ++CEC Notifier framework ++---------------------- ++ ++Most drm HDMI implementations have an integrated CEC implementation and no ++notifier support is needed. But some have independent CEC implementations ++that have their own driver. This could be an IP block for an SoC or a ++completely separate chip that deals with the CEC pin. For those cases a ++drm driver can install a notifier and use the notifier to inform the ++CEC driver about changes in the physical address. ++ ++.. kernel-doc:: include/media/cec-notifier.h diff --git a/Documentation/media/uapi/cec/cec-api.rst b/Documentation/media/uapi/cec/cec-api.rst new file mode 100644 -index 000000000000..bb018709970c +index 000000000000..b68ca9c1d2e0 --- /dev/null +++ b/Documentation/media/uapi/cec/cec-api.rst -@@ -0,0 +1,43 @@ +@@ -0,0 +1,46 @@ +.. -*- coding: utf-8; mode: rst -*- + +.. include:: @@ -444,7 +475,10 @@ index 000000000000..bb018709970c + +This part describes the CEC: Consumer Electronics Control + -+.. class:: toc-title ++ ++.. only:: html ++ ++ .. class:: toc-title + + Table of Contents + @@ -477,7 +511,7 @@ index 000000000000..bb018709970c +Initial revision diff --git a/Documentation/media/uapi/cec/cec-func-close.rst b/Documentation/media/uapi/cec/cec-func-close.rst new file mode 100644 -index 000000000000..895d9c2d1c04 +index 000000000000..334358dfa72e --- /dev/null +++ b/Documentation/media/uapi/cec/cec-func-close.rst @@ -0,0 +1,47 @@ @@ -523,14 +557,14 @@ index 000000000000..895d9c2d1c04 +Return Value +============ + -+:c:func:`close()` returns 0 on success. On error, -1 is returned, and ++:c:func:`close() ` returns 0 on success. On error, -1 is returned, and +``errno`` is set appropriately. Possible error codes are: + +``EBADF`` + ``fd`` is not a valid open file descriptor. diff --git a/Documentation/media/uapi/cec/cec-func-ioctl.rst b/Documentation/media/uapi/cec/cec-func-ioctl.rst new file mode 100644 -index 000000000000..22fb6304a2df +index 000000000000..e2b6260b0086 --- /dev/null +++ b/Documentation/media/uapi/cec/cec-func-ioctl.rst @@ -0,0 +1,66 @@ @@ -575,7 +609,7 @@ index 000000000000..22fb6304a2df +Description +=========== + -+The :c:func:`ioctl()` function manipulates cec device parameters. The ++The :c:func:`ioctl() ` function manipulates cec device parameters. The +argument ``fd`` must be an open file descriptor. + +The ioctl ``request`` code specifies the cec function to be called. It @@ -602,7 +636,7 @@ index 000000000000..22fb6304a2df +parameter remains unmodified. diff --git a/Documentation/media/uapi/cec/cec-func-open.rst b/Documentation/media/uapi/cec/cec-func-open.rst new file mode 100644 -index 000000000000..18dfb62f2efe +index 000000000000..5d6663a649bd --- /dev/null +++ b/Documentation/media/uapi/cec/cec-func-open.rst @@ -0,0 +1,78 @@ @@ -654,7 +688,7 @@ index 000000000000..18dfb62f2efe +Description +=========== + -+To open a cec device applications call :c:func:`open()` with the ++To open a cec device applications call :c:func:`open() ` with the +desired device name. The function has no side effects; the device +configuration remain unchanged. + @@ -666,7 +700,7 @@ index 000000000000..18dfb62f2efe +Return Value +============ + -+:c:func:`open()` returns the new file descriptor on success. On error, ++:c:func:`open() ` returns the new file descriptor on success. On error, +-1 is returned, and ``errno`` is set appropriately. Possible error codes +include: + @@ -686,7 +720,7 @@ index 000000000000..18dfb62f2efe + No device corresponding to this device special file exists. diff --git a/Documentation/media/uapi/cec/cec-func-poll.rst b/Documentation/media/uapi/cec/cec-func-poll.rst new file mode 100644 -index 000000000000..fa0abd8fb160 +index 000000000000..d49f1ee0742d --- /dev/null +++ b/Documentation/media/uapi/cec/cec-func-poll.rst @@ -0,0 +1,77 @@ @@ -731,10 +765,10 @@ index 000000000000..fa0abd8fb160 +Description +=========== + -+With the :c:func:`poll()` function applications can wait for CEC ++With the :c:func:`poll() ` function applications can wait for CEC +events. + -+On success :c:func:`poll()` returns the number of file descriptors ++On success :c:func:`poll() ` returns the number of file descriptors +that have been selected (that is, file descriptors for which the +``revents`` field of the respective struct :c:type:`pollfd` +is non-zero). CEC devices set the ``POLLIN`` and ``POLLRDNORM`` flags in @@ -745,13 +779,13 @@ index 000000000000..fa0abd8fb160 +a value of zero, on failure it returns -1 and the ``errno`` variable is +set appropriately. + -+For more details see the :c:func:`poll()` manual page. ++For more details see the :c:func:`poll() ` manual page. + + +Return Value +============ + -+On success, :c:func:`poll()` returns the number structures which have ++On success, :c:func:`poll() ` returns the number structures which have +non-zero ``revents`` fields, or zero if the call timed out. On error -1 +is returned, and the ``errno`` variable is set appropriately: + @@ -769,10 +803,10 @@ index 000000000000..fa0abd8fb160 + The ``nfds`` argument is greater than ``OPEN_MAX``. diff --git a/Documentation/media/uapi/cec/cec-funcs.rst b/Documentation/media/uapi/cec/cec-funcs.rst new file mode 100644 -index 000000000000..5b7630f2e076 +index 000000000000..6d696cead5cb --- /dev/null +++ b/Documentation/media/uapi/cec/cec-funcs.rst -@@ -0,0 +1,21 @@ +@@ -0,0 +1,20 @@ +.. _cec-user-func: + +****************** @@ -782,7 +816,6 @@ index 000000000000..5b7630f2e076 + +.. toctree:: + :maxdepth: 1 -+ :numbered: + + cec-func-open + cec-func-close @@ -858,10 +891,10 @@ index 000000000000..07ee2b8f89d6 +- cec-follower: emulates a CEC follower. diff --git a/Documentation/media/uapi/cec/cec-ioc-adap-g-caps.rst b/Documentation/media/uapi/cec/cec-ioc-adap-g-caps.rst new file mode 100644 -index 000000000000..6d7bf7bef3eb +index 000000000000..6c1f6efb822e --- /dev/null +++ b/Documentation/media/uapi/cec/cec-ioc-adap-g-caps.rst -@@ -0,0 +1,132 @@ +@@ -0,0 +1,139 @@ +.. -*- coding: utf-8; mode: rst -*- + +.. _CEC_ADAP_G_CAPS: @@ -885,7 +918,7 @@ index 000000000000..6d7bf7bef3eb +========= + +``fd`` -+ File descriptor returned by :ref:`open() `. ++ File descriptor returned by :c:func:`open() `. + +``argp`` + @@ -985,6 +1018,13 @@ index 000000000000..6d7bf7bef3eb + high. This makes it impossible to use CEC to wake up displays that + set the HPD pin low when in standby mode, but keep the CEC bus + alive. ++ * .. _`CEC-CAP-MONITOR-PIN`: ++ ++ - ``CEC_CAP_MONITOR_PIN`` ++ - 0x00000080 ++ - The CEC hardware can monitor CEC pin changes from low to high voltage ++ and vice versa. When in pin monitoring mode the application will ++ receive ``CEC_EVENT_PIN_CEC_LOW`` and ``CEC_EVENT_PIN_CEC_HIGH`` events. + + + @@ -996,10 +1036,10 @@ index 000000000000..6d7bf7bef3eb +:ref:`Generic Error Codes ` chapter. diff --git a/Documentation/media/uapi/cec/cec-ioc-adap-g-log-addrs.rst b/Documentation/media/uapi/cec/cec-ioc-adap-g-log-addrs.rst new file mode 100644 -index 000000000000..fcf863ab6f43 +index 000000000000..84f431a022ad --- /dev/null +++ b/Documentation/media/uapi/cec/cec-ioc-adap-g-log-addrs.rst -@@ -0,0 +1,366 @@ +@@ -0,0 +1,371 @@ +.. -*- coding: utf-8; mode: rst -*- + +.. _CEC_ADAP_LOG_ADDRS: @@ -1050,7 +1090,9 @@ index 000000000000..fcf863ab6f43 +the ``EBUSY`` error code will be returned. + +To clear existing logical addresses set ``num_log_addrs`` to 0. All other fields -+will be ignored in that case. The adapter will go to the unconfigured state. ++will be ignored in that case. The adapter will go to the unconfigured state and the ++``cec_version``, ``vendor_id`` and ``osd_name`` fields are all reset to their default ++values (CEC version 2.0, no vendor ID and an empty OSD name). + +If the physical address is valid (see :ref:`ioctl CEC_ADAP_S_PHYS_ADDR `), +then this ioctl will block until all requested logical @@ -1065,7 +1107,7 @@ index 000000000000..fcf863ab6f43 + +.. c:type:: cec_log_addrs + -+.. tabularcolumns:: |p{1.0cm}|p{7.5cm}|p{8.0cm}| ++.. tabularcolumns:: |p{1.0cm}|p{8.0cm}|p{7.5cm}| + +.. cssclass:: longtable + @@ -1148,6 +1190,9 @@ index 000000000000..fcf863ab6f43 + give the CEC framework more information about the device type, even + though the framework won't use it directly in the CEC message. + ++ ++.. tabularcolumns:: |p{7.8cm}|p{1.0cm}|p{8.7cm}| ++ +.. _cec-log-addrs-flags: + +.. flat-table:: Flags for struct cec_log_addrs @@ -1175,7 +1220,7 @@ index 000000000000..fcf863ab6f43 + to avoid trivial snooping of the keystrokes. + * .. _`CEC-LOG-ADDRS-FL-CDC-ONLY`: + -+ - `CEC_LOG_ADDRS_FL_CDC_ONLY` ++ - ``CEC_LOG_ADDRS_FL_CDC_ONLY`` + - 4 + - If this flag is set, then the device is CDC-Only. CDC-Only CEC devices + are CEC devices that can only handle CDC messages. @@ -1183,7 +1228,7 @@ index 000000000000..fcf863ab6f43 + All other messages are ignored. + + -+.. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}| ++.. tabularcolumns:: |p{7.8cm}|p{1.0cm}|p{8.7cm}| + +.. _cec-versions: + @@ -1467,10 +1512,10 @@ index 000000000000..9e49d4be35d5 + The physical address is malformed. diff --git a/Documentation/media/uapi/cec/cec-ioc-dqevent.rst b/Documentation/media/uapi/cec/cec-ioc-dqevent.rst new file mode 100644 -index 000000000000..4d3570c2e0b3 +index 000000000000..b6fd86424fbb --- /dev/null +++ b/Documentation/media/uapi/cec/cec-ioc-dqevent.rst -@@ -0,0 +1,187 @@ +@@ -0,0 +1,226 @@ +.. -*- coding: utf-8; mode: rst -*- + +.. _CEC_DQEVENT: @@ -1495,7 +1540,7 @@ index 000000000000..4d3570c2e0b3 +========= + +``fd`` -+ File descriptor returned by :ref:`open() `. ++ File descriptor returned by :c:func:`open() `. + +``argp`` + @@ -1560,7 +1605,7 @@ index 000000000000..4d3570c2e0b3 + this is more than enough. + + -+.. tabularcolumns:: |p{1.0cm}|p{4.2cm}|p{2.5cm}|p{8.8cm}| ++.. tabularcolumns:: |p{1.0cm}|p{4.4cm}|p{2.5cm}|p{9.6cm}| + +.. c:type:: cec_event + @@ -1571,10 +1616,11 @@ index 000000000000..4d3570c2e0b3 + + * - __u64 + - ``ts`` -+ - :cspan:`1` Timestamp of the event in ns. ++ - :cspan:`1`\ Timestamp of the event in ns. + -+ The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access -+ the same clock from userspace use :c:func:`clock_gettime`. ++ The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. ++ ++ To access the same clock from userspace use :c:func:`clock_gettime`. + * - __u32 + - ``event`` + - :cspan:`1` The CEC event type, see :ref:`cec-events`. @@ -1619,6 +1665,38 @@ index 000000000000..4d3570c2e0b3 + - 2 + - Generated if one or more CEC messages were lost because the + application didn't dequeue CEC messages fast enough. ++ * .. _`CEC-EVENT-PIN-CEC-LOW`: ++ ++ - ``CEC_EVENT_PIN_CEC_LOW`` ++ - 3 ++ - Generated if the CEC pin goes from a high voltage to a low voltage. ++ Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN`` ++ capability set. ++ * .. _`CEC-EVENT-PIN-CEC-HIGH`: ++ ++ - ``CEC_EVENT_PIN_CEC_HIGH`` ++ - 4 ++ - Generated if the CEC pin goes from a low voltage to a high voltage. ++ Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN`` ++ capability set. ++ * .. _`CEC-EVENT-PIN-HPD-LOW`: ++ ++ - ``CEC_EVENT_PIN_HPD_LOW`` ++ - 5 ++ - Generated if the HPD pin goes from a high voltage to a low voltage. ++ Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN`` ++ capability set. When open() is called, the HPD pin can be read and ++ if the HPD is low, then an initial event will be generated for that ++ filehandle. ++ * .. _`CEC-EVENT-PIN-HPD-HIGH`: ++ ++ - ``CEC_EVENT_PIN_HPD_HIGH`` ++ - 6 ++ - Generated if the HPD pin goes from a low voltage to a high voltage. ++ Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN`` ++ capability set. When open() is called, the HPD pin can be read and ++ if the HPD is high, then an initial event will be generated for that ++ filehandle. + + +.. tabularcolumns:: |p{6.0cm}|p{0.6cm}|p{10.9cm}| @@ -1630,14 +1708,20 @@ index 000000000000..4d3570c2e0b3 + :stub-columns: 0 + :widths: 3 1 8 + -+ * .. _`CEC-EVENT-FL-INITIAL-VALUE`: ++ * .. _`CEC-EVENT-FL-INITIAL-STATE`: + -+ - ``CEC_EVENT_FL_INITIAL_VALUE`` ++ - ``CEC_EVENT_FL_INITIAL_STATE`` + - 1 + - Set for the initial events that are generated when the device is + opened. See the table above for which events do this. This allows + applications to learn the initial state of the CEC adapter at + open() time. ++ * .. _`CEC-EVENT-FL-DROPPED-EVENTS`: ++ ++ - ``CEC_EVENT_FL_DROPPED_EVENTS`` ++ - 2 ++ - Set if one or more events of the given event type have been dropped. ++ This is an indication that the application cannot keep up. + + + @@ -1660,10 +1744,10 @@ index 000000000000..4d3570c2e0b3 + events to arrive. diff --git a/Documentation/media/uapi/cec/cec-ioc-g-mode.rst b/Documentation/media/uapi/cec/cec-ioc-g-mode.rst new file mode 100644 -index 000000000000..664f0d47bbcd +index 000000000000..508e2e325683 --- /dev/null +++ b/Documentation/media/uapi/cec/cec-ioc-g-mode.rst -@@ -0,0 +1,263 @@ +@@ -0,0 +1,293 @@ +.. -*- coding: utf-8; mode: rst -*- + +.. _CEC_MODE: @@ -1774,6 +1858,8 @@ index 000000000000..664f0d47bbcd + +.. _cec-mode-follower_e: + ++.. cssclass:: longtable ++ +.. flat-table:: Follower Modes + :header-rows: 0 + :stub-columns: 0 @@ -1815,13 +1901,28 @@ index 000000000000..664f0d47bbcd + code. You cannot become a follower if :ref:`CEC_CAP_TRANSMIT ` + is not set or if :ref:`CEC_MODE_NO_INITIATOR ` was specified, + the ``EINVAL`` error code is returned in that case. ++ * .. _`CEC-MODE-MONITOR-PIN`: ++ ++ - ``CEC_MODE_MONITOR_PIN`` ++ - 0xd0 ++ - Put the file descriptor into pin monitoring mode. Can only be used in ++ combination with :ref:`CEC_MODE_NO_INITIATOR `, ++ otherwise the ``EINVAL`` error code will be returned. ++ This mode requires that the :ref:`CEC_CAP_MONITOR_PIN ` ++ capability is set, otherwise the ``EINVAL`` error code is returned. ++ While in pin monitoring mode this file descriptor can receive the ++ ``CEC_EVENT_PIN_CEC_LOW`` and ``CEC_EVENT_PIN_CEC_HIGH`` events to see the ++ low-level CEC pin transitions. This is very useful for debugging. ++ This mode is only allowed if the process has the ``CAP_NET_ADMIN`` ++ capability. If that is not set, then the ``EPERM`` error code is returned. + * .. _`CEC-MODE-MONITOR`: + + - ``CEC_MODE_MONITOR`` + - 0xe0 + - Put the file descriptor into monitor mode. Can only be used in -+ combination with :ref:`CEC_MODE_NO_INITIATOR `, otherwise EINVAL error -+ code will be returned. In monitor mode all messages this CEC ++ combination with :ref:`CEC_MODE_NO_INITIATOR `,i ++ otherwise the ``EINVAL`` error code will be returned. ++ In monitor mode all messages this CEC + device transmits and all messages it receives (both broadcast + messages and directed messages for one its logical addresses) will + be reported. This is very useful for debugging. This is only @@ -1857,55 +1958,68 @@ index 000000000000..664f0d47bbcd + * .. _`CEC-MSG-GET-CEC-VERSION`: + + - ``CEC_MSG_GET_CEC_VERSION`` -+ - When in passthrough mode this message has to be handled by -+ userspace, otherwise the core will return the CEC version that was -+ set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS `. ++ - The core will return the CEC version that was set with ++ :ref:`ioctl CEC_ADAP_S_LOG_ADDRS `, ++ except when in passthrough mode. In passthrough mode the core ++ does nothing and this message has to be handled by a follower ++ instead. + * .. _`CEC-MSG-GIVE-DEVICE-VENDOR-ID`: + + - ``CEC_MSG_GIVE_DEVICE_VENDOR_ID`` -+ - When in passthrough mode this message has to be handled by -+ userspace, otherwise the core will return the vendor ID that was -+ set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS `. ++ - The core will return the vendor ID that was set with ++ :ref:`ioctl CEC_ADAP_S_LOG_ADDRS `, ++ except when in passthrough mode. In passthrough mode the core ++ does nothing and this message has to be handled by a follower ++ instead. + * .. _`CEC-MSG-ABORT`: + + - ``CEC_MSG_ABORT`` -+ - When in passthrough mode this message has to be handled by -+ userspace, otherwise the core will return a feature refused -+ message as per the specification. ++ - The core will return a Feature Abort message with reason ++ 'Feature Refused' as per the specification, except when in ++ passthrough mode. In passthrough mode the core does nothing ++ and this message has to be handled by a follower instead. + * .. _`CEC-MSG-GIVE-PHYSICAL-ADDR`: + + - ``CEC_MSG_GIVE_PHYSICAL_ADDR`` -+ - When in passthrough mode this message has to be handled by -+ userspace, otherwise the core will report the current physical -+ address. ++ - The core will report the current physical address, except when ++ in passthrough mode. In passthrough mode the core does nothing ++ and this message has to be handled by a follower instead. + * .. _`CEC-MSG-GIVE-OSD-NAME`: + + - ``CEC_MSG_GIVE_OSD_NAME`` -+ - When in passthrough mode this message has to be handled by -+ userspace, otherwise the core will report the current OSD name as -+ was set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS `. ++ - The core will report the current OSD name that was set with ++ :ref:`ioctl CEC_ADAP_S_LOG_ADDRS `, ++ except when in passthrough mode. In passthrough mode the core ++ does nothing and this message has to be handled by a follower ++ instead. + * .. _`CEC-MSG-GIVE-FEATURES`: + + - ``CEC_MSG_GIVE_FEATURES`` -+ - When in passthrough mode this message has to be handled by -+ userspace, otherwise the core will report the current features as -+ was set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS ` -+ or the message is ignored if the CEC version was older than 2.0. ++ - The core will do nothing if the CEC version is older than 2.0, ++ otherwise it will report the current features that were set with ++ :ref:`ioctl CEC_ADAP_S_LOG_ADDRS `, ++ except when in passthrough mode. In passthrough mode the core ++ does nothing (for any CEC version) and this message has to be handled ++ by a follower instead. + * .. _`CEC-MSG-USER-CONTROL-PRESSED`: + + - ``CEC_MSG_USER_CONTROL_PRESSED`` -+ - If :ref:`CEC_CAP_RC ` is set, then generate a remote control key -+ press. This message is always passed on to userspace. ++ - If :ref:`CEC_CAP_RC ` is set and if ++ :ref:`CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU ` ++ is set, then generate a remote control key ++ press. This message is always passed on to the follower(s). + * .. _`CEC-MSG-USER-CONTROL-RELEASED`: + + - ``CEC_MSG_USER_CONTROL_RELEASED`` -+ - If :ref:`CEC_CAP_RC ` is set, then generate a remote control key -+ release. This message is always passed on to userspace. ++ - If :ref:`CEC_CAP_RC ` is set and if ++ :ref:`CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU ` ++ is set, then generate a remote control key ++ release. This message is always passed on to the follower(s). + * .. _`CEC-MSG-REPORT-PHYSICAL-ADDR`: + + - ``CEC_MSG_REPORT_PHYSICAL_ADDR`` + - The CEC framework will make note of the reported physical address -+ and then just pass the message on to userspace. ++ and then just pass the message on to the follower(s). + + + @@ -1929,10 +2043,10 @@ index 000000000000..664f0d47bbcd + Someone else is already an exclusive follower or initiator. diff --git a/Documentation/media/uapi/cec/cec-ioc-receive.rst b/Documentation/media/uapi/cec/cec-ioc-receive.rst new file mode 100644 -index 000000000000..267044f7ac30 +index 000000000000..bdad4b197bcd --- /dev/null +++ b/Documentation/media/uapi/cec/cec-ioc-receive.rst -@@ -0,0 +1,342 @@ +@@ -0,0 +1,344 @@ +.. -*- coding: utf-8; mode: rst -*- + +.. _CEC_TRANSMIT: @@ -2066,7 +2180,7 @@ index 000000000000..267044f7ac30 + - ``tx_status`` + - The status bits of the transmitted message. See + :ref:`cec-tx-status` for the possible status values. It is 0 if -+ this messages was received, not transmitted. ++ this message was received, not transmitted. + * - __u8 + - ``msg[16]`` + - The message payload. For :ref:`ioctl CEC_TRANSMIT ` this is filled in by the @@ -2103,7 +2217,7 @@ index 000000000000..267044f7ac30 + - ``tx_status`` + - The status bits of the transmitted message. See + :ref:`cec-tx-status` for the possible status values. It is 0 if -+ this messages was received, not transmitted. ++ this message was received, not transmitted. + * - __u8 + - ``tx_arb_lost_cnt`` + - A counter of the number of transmit attempts that resulted in the @@ -2130,6 +2244,8 @@ index 000000000000..267044f7ac30 + valid if the :ref:`CEC_TX_STATUS_ERROR ` status bit is set. + + ++.. tabularcolumns:: |p{6.2cm}|p{1.0cm}|p{10.3cm}| ++ +.. _cec-msg-flags: + +.. flat-table:: Flags for struct cec_msg @@ -2189,9 +2305,9 @@ index 000000000000..267044f7ac30 + - ``CEC_TX_STATUS_ERROR`` + - 0x10 + - Some error occurred. This is used for any errors that do not fit -+ the previous two, either because the hardware could not tell which -+ error occurred, or because the hardware tested for other -+ conditions besides those two. ++ ``CEC_TX_STATUS_ARB_LOST`` or ``CEC_TX_STATUS_LOW_DRIVE``, either because ++ the hardware could not tell which error occurred, or because the hardware ++ tested for other conditions besides those two. + * .. _`CEC-TX-STATUS-MAX-RETRIES`: + + - ``CEC_TX_STATUS_MAX_RETRIES`` @@ -2276,7 +2392,7 @@ index 000000000000..267044f7ac30 +ERESTARTSYS + The wait for a successful transmit was interrupted (e.g. by Ctrl-C). diff --git a/MAINTAINERS b/MAINTAINERS -index e86ddedc813c..124551e7b781 100644 +index b88e249026a1..bb1aa323019c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2657,6 +2657,22 @@ F: drivers/net/ieee802154/cc2520.c @@ -2302,709 +2418,125 @@ index e86ddedc813c..124551e7b781 100644 CELL BROADBAND ENGINE ARCHITECTURE M: Arnd Bergmann L: linuxppc-dev@lists.ozlabs.org -diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig -index 6758ca0d19af..d0b3412ea8f7 100644 ---- a/drivers/media/Kconfig -+++ b/drivers/media/Kconfig -@@ -2,6 +2,12 @@ - # Multimedia device configuration - # - -+config CEC_CORE -+ tristate -+ -+config CEC_NOTIFIER -+ bool -+ - menuconfig MEDIA_SUPPORT - tristate "Multimedia support" - depends on HAS_IOMEM -@@ -81,23 +87,15 @@ config MEDIA_RC_SUPPORT - Say Y when you have a TV or an IR device. - - config MEDIA_CEC_SUPPORT -- bool "HDMI CEC support" -- select MEDIA_CEC_EDID -- ---help--- -- Enable support for HDMI CEC (Consumer Electronics Control), -- which is an optional HDMI feature. -- -- Say Y when you have an HDMI receiver, transmitter or a USB CEC -- adapter that supports HDMI CEC. -+ bool "HDMI CEC support" -+ ---help--- -+ Enable support for HDMI CEC (Consumer Electronics Control), -+ which is an optional HDMI feature. - --config MEDIA_CEC_DEBUG -- bool "HDMI CEC debugfs interface" -- depends on MEDIA_CEC_SUPPORT && DEBUG_FS -- ---help--- -- Turns on the DebugFS interface for CEC devices. -+ Say Y when you have an HDMI receiver, transmitter or a USB CEC -+ adapter that supports HDMI CEC. - --config MEDIA_CEC_EDID -- bool -+source "drivers/media/cec/Kconfig" - - # - # Media controller -diff --git a/drivers/media/Makefile b/drivers/media/Makefile -index a74f2d92997f..6d5500a74c77 100644 ---- a/drivers/media/Makefile -+++ b/drivers/media/Makefile -@@ -2,14 +2,6 @@ - # Makefile for the kernel multimedia device drivers. - # - --ifeq ($(CONFIG_MEDIA_CEC_EDID),y) -- obj-$(CONFIG_MEDIA_SUPPORT) += cec-edid.o --endif -- --ifeq ($(CONFIG_MEDIA_CEC_SUPPORT),y) -- obj-$(CONFIG_MEDIA_SUPPORT) += cec/ --endif -- - media-objs := media-device.o media-devnode.o media-entity.o - - # -@@ -32,6 +24,8 @@ obj-$(CONFIG_DVB_CORE) += dvb-core/ - # There are both core and drivers at RC subtree - merge before drivers - obj-y += rc/ - -+obj-$(CONFIG_CEC_CORE) += cec/ -+ - # - # Finally, merge the drivers that require the core - # -diff --git a/drivers/media/cec/Kconfig b/drivers/media/cec/Kconfig -new file mode 100644 -index 000000000000..43428cec3a01 ---- /dev/null -+++ b/drivers/media/cec/Kconfig -@@ -0,0 +1,6 @@ -+config MEDIA_CEC_RC -+ bool "HDMI CEC RC integration" -+ depends on CEC_CORE && RC_CORE -+ depends on CEC_CORE=m || RC_CORE=y -+ ---help--- -+ Pass on CEC remote control messages to the RC framework. -diff --git a/drivers/media/cec/Makefile b/drivers/media/cec/Makefile -index d6686337275f..eaf408e64669 100644 ---- a/drivers/media/cec/Makefile -+++ b/drivers/media/cec/Makefile -@@ -1,5 +1,7 @@ --cec-objs := cec-core.o cec-adap.o cec-api.o -+cec-objs := cec-core.o cec-adap.o cec-api.o cec-edid.o - --ifeq ($(CONFIG_MEDIA_CEC_SUPPORT),y) -- obj-$(CONFIG_MEDIA_SUPPORT) += cec.o -+ifeq ($(CONFIG_CEC_NOTIFIER),y) -+ cec-objs += cec-notifier.o - endif -+ -+obj-$(CONFIG_CEC_CORE) += cec.o diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c -index ccda41c2c9e4..d596b601ff42 100644 +index 2e66ee402801..9d19003eddb2 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c -@@ -28,6 +28,8 @@ - #include - #include - -+#include -+ - #include "cec-priv.h" - - static void cec_fill_msg_report_features(struct cec_adapter *adap, -@@ -299,6 +301,40 @@ static void cec_data_cancel(struct cec_data *data) - cec_data_completed(data); - } - -+/* -+ * Flush all pending transmits and cancel any pending timeout work. -+ * -+ * This function is called with adap->lock held. -+ */ -+static void cec_flush(struct cec_adapter *adap) -+{ -+ struct cec_data *data, *n; -+ -+ /* -+ * If the adapter is disabled, or we're asked to stop, -+ * then cancel any pending transmits. -+ */ -+ while (!list_empty(&adap->transmit_queue)) { -+ data = list_first_entry(&adap->transmit_queue, -+ struct cec_data, list); -+ cec_data_cancel(data); -+ } -+ if (adap->transmitting) -+ cec_data_cancel(adap->transmitting); -+ -+ /* Cancel the pending timeout work. */ -+ list_for_each_entry_safe(data, n, &adap->wait_queue, list) { -+ if (cancel_delayed_work(&data->work)) -+ cec_data_cancel(data); -+ /* -+ * If cancel_delayed_work returned false, then -+ * the cec_wait_timeout function is running, -+ * which will call cec_data_completed. So no -+ * need to do anything special in that case. -+ */ -+ } -+} -+ - /* - * Main CEC state machine - * -@@ -332,8 +368,9 @@ int cec_thread_func(void *_adap) - * transmit should be canceled. - */ - err = wait_event_interruptible_timeout(adap->kthread_waitq, -+ (adap->needs_hpd && -+ (!adap->is_configured && !adap->is_configuring)) || - kthread_should_stop() || -- (!adap->is_configured && !adap->is_configuring) || - (!adap->transmitting && - !list_empty(&adap->transmit_queue)), - msecs_to_jiffies(CEC_XFER_TIMEOUT_MS)); -@@ -348,39 +385,10 @@ int cec_thread_func(void *_adap) - - mutex_lock(&adap->lock); - -- if ((!adap->is_configured && !adap->is_configuring) || -+ if ((adap->needs_hpd && -+ (!adap->is_configured && !adap->is_configuring)) || - kthread_should_stop()) { -- /* -- * If the adapter is disabled, or we're asked to stop, -- * then cancel any pending transmits. -- */ -- while (!list_empty(&adap->transmit_queue)) { -- data = list_first_entry(&adap->transmit_queue, -- struct cec_data, list); -- cec_data_cancel(data); -- } -- if (adap->transmitting) -- cec_data_cancel(adap->transmitting); -- -- /* -- * Cancel the pending timeout work. We have to unlock -- * the mutex when flushing the work since -- * cec_wait_timeout() will take it. This is OK since -- * no new entries can be added to wait_queue as long -- * as adap->transmitting is NULL, which it is due to -- * the cec_data_cancel() above. -- */ -- while (!list_empty(&adap->wait_queue)) { -- data = list_first_entry(&adap->wait_queue, -- struct cec_data, list); -- -- if (!cancel_delayed_work(&data->work)) { -- mutex_unlock(&adap->lock); -- flush_scheduled_work(); -- mutex_lock(&adap->lock); -- } -- cec_data_cancel(data); -- } -+ cec_flush(adap); - goto unlock; - } - -@@ -390,7 +398,7 @@ int cec_thread_func(void *_adap) - * happen and is an indication of a faulty CEC adapter - * driver, or the CEC bus is in some weird state. - */ -- dprintk(0, "message %*ph timed out!\n", -+ dprintk(0, "%s: message %*ph timed out!\n", __func__, - adap->transmitting->msg.len, - adap->transmitting->msg.msg); - /* Just give up on this. */ -@@ -410,6 +418,7 @@ int cec_thread_func(void *_adap) - struct cec_data, list); - list_del_init(&data->list); - adap->transmit_queue_sz--; -+ - /* Make this the current transmitting message */ - adap->transmitting = data; - -@@ -465,7 +474,7 @@ void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt, - struct cec_msg *msg; - u64 ts = ktime_get_ns(); - -- dprintk(2, "cec_transmit_done %02x\n", status); -+ dprintk(2, "%s: status %02x\n", __func__, status); - mutex_lock(&adap->lock); - data = adap->transmitting; - if (!data) { -@@ -474,7 +483,8 @@ void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt, - * unplugged while the transmit is ongoing. Ignore this - * transmit in that case. - */ -- dprintk(1, "cec_transmit_done without an ongoing transmit!\n"); -+ dprintk(1, "%s was called without an ongoing transmit!\n", -+ __func__); - goto unlock; - } - -@@ -501,6 +511,12 @@ void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt, - !(status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK))) { - /* Retry this message */ - data->attempts--; -+ if (msg->timeout) -+ dprintk(2, "retransmit: %*ph (attempts: %d, wait for 0x%02x)\n", -+ msg->len, msg->msg, data->attempts, msg->reply); -+ else -+ dprintk(2, "retransmit: %*ph (attempts: %d)\n", -+ msg->len, msg->msg, data->attempts); - /* Add the message in front of the transmit queue */ - list_add(&data->list, &adap->transmit_queue); - adap->transmit_queue_sz++; -@@ -541,6 +557,32 @@ unlock: - } - EXPORT_SYMBOL_GPL(cec_transmit_done); - -+void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status) -+{ -+ switch (status & ~CEC_TX_STATUS_MAX_RETRIES) { -+ case CEC_TX_STATUS_OK: -+ cec_transmit_done(adap, status, 0, 0, 0, 0); -+ return; -+ case CEC_TX_STATUS_ARB_LOST: -+ cec_transmit_done(adap, status, 1, 0, 0, 0); -+ return; -+ case CEC_TX_STATUS_NACK: -+ cec_transmit_done(adap, status, 0, 1, 0, 0); -+ return; -+ case CEC_TX_STATUS_LOW_DRIVE: -+ cec_transmit_done(adap, status, 0, 0, 1, 0); -+ return; -+ case CEC_TX_STATUS_ERROR: -+ cec_transmit_done(adap, status, 0, 0, 0, 1); -+ return; -+ default: -+ /* Should never happen */ -+ WARN(1, "cec-%s: invalid status 0x%02x\n", adap->name, status); -+ return; -+ } -+} -+EXPORT_SYMBOL_GPL(cec_transmit_attempt_done); -+ - /* - * Called when waiting for a reply times out. - */ -@@ -603,17 +645,17 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, - - /* Sanity checks */ - if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) { -- dprintk(1, "cec_transmit_msg: invalid length %d\n", msg->len); -+ dprintk(1, "%s: invalid length %d\n", __func__, msg->len); - return -EINVAL; - } - if (msg->timeout && msg->len == 1) { -- dprintk(1, "cec_transmit_msg: can't reply for poll msg\n"); -+ dprintk(1, "%s: can't reply for poll msg\n", __func__); - return -EINVAL; - } - memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len); - if (msg->len == 1) { - if (cec_msg_destination(msg) == 0xf) { -- dprintk(1, "cec_transmit_msg: invalid poll message\n"); -+ dprintk(1, "%s: invalid poll message\n", __func__); - return -EINVAL; - } - if (cec_has_log_addr(adap, cec_msg_destination(msg))) { -@@ -634,20 +676,30 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, - } - if (msg->len > 1 && !cec_msg_is_broadcast(msg) && - cec_has_log_addr(adap, cec_msg_destination(msg))) { -- dprintk(1, "cec_transmit_msg: destination is the adapter itself\n"); -+ dprintk(1, "%s: destination is the adapter itself\n", __func__); - return -EINVAL; - } - if (msg->len > 1 && adap->is_configured && - !cec_has_log_addr(adap, cec_msg_initiator(msg))) { -- dprintk(1, "cec_transmit_msg: initiator has unknown logical address %d\n", -- cec_msg_initiator(msg)); -+ dprintk(1, "%s: initiator has unknown logical address %d\n", -+ __func__, cec_msg_initiator(msg)); - return -EINVAL; - } -- if (!adap->is_configured && !adap->is_configuring) -- return -ENONET; -+ if (!adap->is_configured && !adap->is_configuring) { -+ if (adap->needs_hpd || msg->msg[0] != 0xf0) { -+ dprintk(1, "%s: adapter is unconfigured\n", __func__); -+ return -ENONET; -+ } -+ if (msg->reply) { -+ dprintk(1, "%s: invalid msg->reply\n", __func__); -+ return -EINVAL; -+ } -+ } - -- if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ) -+ if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ) { -+ dprintk(1, "%s: transmit queue full\n", __func__); - return -EBUSY; -+ } - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) -@@ -659,11 +711,11 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, - } - - if (msg->timeout) -- dprintk(2, "cec_transmit_msg: %*ph (wait for 0x%02x%s)\n", -- msg->len, msg->msg, msg->reply, !block ? ", nb" : ""); -+ dprintk(2, "%s: %*ph (wait for 0x%02x%s)\n", -+ __func__, msg->len, msg->msg, msg->reply, !block ? ", nb" : ""); - else -- dprintk(2, "cec_transmit_msg: %*ph%s\n", -- msg->len, msg->msg, !block ? " (nb)" : ""); -+ dprintk(2, "%s: %*ph%s\n", -+ __func__, msg->len, msg->msg, !block ? " (nb)" : ""); - - data->msg = *msg; - data->fh = fh; -@@ -692,6 +744,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, - - if (fh) - list_add_tail(&data->xfer_list, &fh->xfer_list); -+ - list_add_tail(&data->list, &adap->transmit_queue); - adap->transmit_queue_sz++; - if (!adap->transmitting) -@@ -897,7 +950,7 @@ void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg) - memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len); - - mutex_lock(&adap->lock); -- dprintk(2, "cec_received_msg: %*ph\n", msg->len, msg->msg); -+ dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg); - - /* Check if this message was for us (directed or broadcast). */ - if (!cec_msg_is_broadcast(msg)) -@@ -1098,9 +1151,6 @@ static int cec_config_log_addr(struct cec_adapter *adap, - las->log_addr[idx] = log_addr; - las->log_addr_mask |= 1 << log_addr; - adap->phys_addrs[log_addr] = adap->phys_addr; -- -- dprintk(2, "claimed addr %d (%d)\n", log_addr, -- las->primary_device_type[idx]); - return 1; - } - -@@ -1112,11 +1162,14 @@ static int cec_config_log_addr(struct cec_adapter *adap, - */ - static void cec_adap_unconfigure(struct cec_adapter *adap) +@@ -200,7 +200,10 @@ static void cec_queue_msg_fh(struct cec_fh *fh, const struct cec_msg *msg) { -- WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID)); -+ if (!adap->needs_hpd || -+ adap->phys_addr != CEC_PHYS_ADDR_INVALID) -+ WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID)); - adap->log_addrs.log_addr_mask = 0; - adap->is_configuring = false; - adap->is_configured = false; - memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs)); -+ cec_flush(adap); - wake_up_interruptible(&adap->kthread_waitq); - cec_post_state_event(adap); - } -@@ -1285,7 +1338,7 @@ configured: - /* Report Physical Address */ - cec_msg_report_physical_addr(&msg, adap->phys_addr, - las->primary_device_type[i]); -- dprintk(2, "config: la %d pa %x.%x.%x.%x\n", -+ dprintk(1, "config: la %d pa %x.%x.%x.%x\n", - las->log_addr[i], - cec_phys_addr_exp(adap->phys_addr)); - cec_transmit_msg_fh(adap, &msg, NULL, false); -@@ -1340,6 +1393,8 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) - if (phys_addr == adap->phys_addr || adap->devnode.unregistered) - return; + static const struct cec_event ev_lost_msgs = { + .event = CEC_EVENT_LOST_MSGS, +- .lost_msgs.lost_msgs = 1, ++ .flags = 0, ++ { ++ .lost_msgs = { 1 }, ++ }, + }; + struct cec_msg_entry *entry; -+ dprintk(1, "new physical address %x.%x.%x.%x\n", -+ cec_phys_addr_exp(phys_addr)); - if (phys_addr == CEC_PHYS_ADDR_INVALID || - adap->phys_addr != CEC_PHYS_ADDR_INVALID) { - adap->phys_addr = CEC_PHYS_ADDR_INVALID; -@@ -1348,19 +1403,30 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) - /* Disabling monitor all mode should always succeed */ - if (adap->monitor_all_cnt) - WARN_ON(call_op(adap, adap_monitor_all_enable, false)); -- WARN_ON(adap->ops->adap_enable(adap, false)); -+ mutex_lock(&adap->devnode.lock); -+ if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) -+ WARN_ON(adap->ops->adap_enable(adap, false)); -+ mutex_unlock(&adap->devnode.lock); - if (phys_addr == CEC_PHYS_ADDR_INVALID) - return; - } - -- if (adap->ops->adap_enable(adap, true)) -+ mutex_lock(&adap->devnode.lock); -+ if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) && -+ adap->ops->adap_enable(adap, true)) { -+ mutex_unlock(&adap->devnode.lock); - return; -+ } - - if (adap->monitor_all_cnt && - call_op(adap, adap_monitor_all_enable, true)) { -- WARN_ON(adap->ops->adap_enable(adap, false)); -+ if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) -+ WARN_ON(adap->ops->adap_enable(adap, false)); -+ mutex_unlock(&adap->devnode.lock); - return; - } -+ mutex_unlock(&adap->devnode.lock); -+ - adap->phys_addr = phys_addr; - cec_post_state_event(adap); - if (adap->log_addrs.num_log_addrs) -@@ -1378,6 +1444,18 @@ void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) - } - EXPORT_SYMBOL_GPL(cec_s_phys_addr); - -+void cec_s_phys_addr_from_edid(struct cec_adapter *adap, -+ const struct edid *edid) -+{ -+ u16 pa = CEC_PHYS_ADDR_INVALID; -+ -+ if (edid && edid->extensions) -+ pa = cec_get_edid_phys_addr((const u8 *)edid, -+ EDID_LENGTH * (edid->extensions + 1), NULL); -+ cec_s_phys_addr(adap, pa, false); -+} -+EXPORT_SYMBOL_GPL(cec_s_phys_addr_from_edid); -+ - /* - * Called from either the ioctl or a driver to set the logical addresses. - * -@@ -1435,12 +1513,16 @@ int __cec_s_log_addrs(struct cec_adapter *adap, - * within the correct range. - */ - if (log_addrs->vendor_id != CEC_VENDOR_ID_NONE && -- (log_addrs->vendor_id & 0xff000000) != 0) -+ (log_addrs->vendor_id & 0xff000000) != 0) { -+ dprintk(1, "invalid vendor ID\n"); - return -EINVAL; -+ } - - if (log_addrs->cec_version != CEC_OP_CEC_VERSION_1_4 && -- log_addrs->cec_version != CEC_OP_CEC_VERSION_2_0) -+ log_addrs->cec_version != CEC_OP_CEC_VERSION_2_0) { -+ dprintk(1, "invalid CEC version\n"); - return -EINVAL; -+ } - - if (log_addrs->num_log_addrs > 1) - for (i = 0; i < log_addrs->num_log_addrs; i++) -@@ -1504,12 +1586,12 @@ int __cec_s_log_addrs(struct cec_adapter *adap, - if (log_addrs->num_log_addrs == 2) { - if (!(type_mask & ((1 << CEC_LOG_ADDR_TYPE_AUDIOSYSTEM) | - (1 << CEC_LOG_ADDR_TYPE_TV)))) { -- dprintk(1, "Two LAs is only allowed for audiosystem and TV\n"); -+ dprintk(1, "two LAs is only allowed for audiosystem and TV\n"); - return -EINVAL; - } - if (!(type_mask & ((1 << CEC_LOG_ADDR_TYPE_PLAYBACK) | - (1 << CEC_LOG_ADDR_TYPE_RECORD)))) { -- dprintk(1, "An audiosystem/TV can only be combined with record or playback\n"); -+ dprintk(1, "an audiosystem/TV can only be combined with record or playback\n"); - return -EINVAL; - } - } -@@ -1585,6 +1667,9 @@ static int cec_feature_abort_reason(struct cec_adapter *adap, - */ - if (msg->msg[1] == CEC_MSG_FEATURE_ABORT) - return 0; -+ /* Don't Feature Abort messages from 'Unregistered' */ -+ if (cec_msg_initiator(msg) == CEC_LOG_ADDR_UNREGISTERED) -+ return 0; - cec_msg_set_reply_to(&tx_msg, msg); - cec_msg_feature_abort(&tx_msg, msg->msg[1], reason); - return cec_transmit_msg(adap, &tx_msg, false); -@@ -1620,7 +1705,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, +@@ -1791,6 +1794,9 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, + int la_idx = cec_log_addr2idx(adap, dest_laddr); bool from_unregistered = init_laddr == 0xf; struct cec_msg tx_cec_msg = { }; - -- dprintk(1, "cec_receive_notify: %*ph\n", msg->len, msg->msg); -+ dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg); - - /* If this is a CDC-Only device, then ignore any non-CDC messages */ - if (cec_is_cdc_only(&adap->log_addrs) && -@@ -1689,7 +1774,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, - - if (!from_unregistered) - adap->phys_addrs[init_laddr] = pa; -- dprintk(1, "Reported physical address %x.%x.%x.%x for logical address %d\n", -+ dprintk(1, "reported physical address %x.%x.%x.%x for logical address %d\n", - cec_phys_addr_exp(pa), init_laddr); - break; - } -@@ -1699,7 +1784,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, - !(adap->log_addrs.flags & CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU)) - break; - --#if IS_REACHABLE(CONFIG_RC_CORE) +#ifdef CONFIG_MEDIA_CEC_RC - switch (msg->msg[2]) { ++ int scancode; ++#endif + + dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg); + +@@ -1886,11 +1892,9 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, + */ + case 0x60: + if (msg->len == 2) +- rc_keydown(adap->rc, RC_TYPE_CEC, +- msg->msg[2], 0); ++ scancode = msg->msg[2]; + else +- rc_keydown(adap->rc, RC_TYPE_CEC, +- msg->msg[2] << 8 | msg->msg[3], 0); ++ scancode = msg->msg[2] << 8 | msg->msg[3]; + break; /* - * Play function, this message can have variable length -@@ -1736,7 +1821,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, - if (!(adap->capabilities & CEC_CAP_RC) || - !(adap->log_addrs.flags & CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU)) + * Other function messages that are not handled. +@@ -1903,11 +1907,54 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, + */ + case 0x56: case 0x57: + case 0x67: case 0x68: case 0x69: case 0x6a: ++ scancode = -1; break; --#if IS_REACHABLE(CONFIG_RC_CORE) -+#ifdef CONFIG_MEDIA_CEC_RC - rc_keyup(adap->rc); + default: +- rc_keydown(adap->rc, RC_TYPE_CEC, msg->msg[2], 0); ++ scancode = msg->msg[2]; ++ break; ++ } ++ ++ /* Was repeating, but keypress timed out */ ++ if (adap->rc_repeating && !adap->rc->keypressed) { ++ adap->rc_repeating = false; ++ adap->rc_last_scancode = -1; ++ } ++ /* Different keypress from last time, ends repeat mode */ ++ if (adap->rc_last_scancode != scancode) { ++ rc_keyup(adap->rc); ++ adap->rc_repeating = false; ++ } ++ /* We can't handle this scancode */ ++ if (scancode < 0) { ++ adap->rc_last_scancode = scancode; ++ break; ++ } ++ ++ /* Send key press */ ++ rc_keydown(adap->rc, RC_TYPE_CEC, scancode, 0); ++ ++ /* When in repeating mode, we're done */ ++ if (adap->rc_repeating) ++ break; ++ ++ /* ++ * We are not repeating, but the new scancode is ++ * the same as the last one, and this second key press is ++ * within 550 ms (the 'Follower Safety Timeout') from the ++ * previous key press, so we now enable the repeating mode. ++ */ ++ if (adap->rc_last_scancode == scancode && ++ msg->rx_ts - adap->rc_last_keypress < 550 * NSEC_PER_MSEC) { ++ adap->rc_repeating = true; + break; + } ++ /* ++ * Not in repeating mode, so avoid triggering repeat mode ++ * by calling keyup. ++ */ ++ rc_keyup(adap->rc); ++ adap->rc_last_scancode = scancode; ++ adap->rc_last_keypress = msg->rx_ts; #endif break; -@@ -1831,7 +1916,7 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap) - WARN_ON(call_op(adap, adap_monitor_all_enable, 0)); - } --#ifdef CONFIG_MEDIA_CEC_DEBUG -+#ifdef CONFIG_DEBUG_FS - /* - * Log the current state of the CEC adapter. - * Very useful for debugging. -diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c -index 8950b6c9d6a9..f7eb4c54a354 100644 ---- a/drivers/media/cec/cec-api.c -+++ b/drivers/media/cec/cec-api.c -@@ -198,7 +198,12 @@ static long cec_transmit(struct cec_adapter *adap, struct cec_fh *fh, - return -EINVAL; +@@ -1917,6 +1964,8 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, + break; + #ifdef CONFIG_MEDIA_CEC_RC + rc_keyup(adap->rc); ++ adap->rc_repeating = false; ++ adap->rc_last_scancode = -1; + #endif + break; - mutex_lock(&adap->lock); -- if (!adap->is_configured) -+ if (adap->log_addrs.num_log_addrs == 0) -+ err = -EPERM; -+ else if (adap->is_configuring) -+ err = -ENONET; -+ else if (!adap->is_configured && -+ (adap->needs_hpd || msg.msg[0] != 0xf0)) - err = -ENONET; - else if (cec_is_busy(adap, fh)) - err = -EBUSY; -@@ -267,16 +272,10 @@ static long cec_receive(struct cec_adapter *adap, struct cec_fh *fh, - bool block, struct cec_msg __user *parg) - { - struct cec_msg msg = {}; -- long err = 0; -+ long err; - - if (copy_from_user(&msg, parg, sizeof(msg))) - return -EFAULT; -- mutex_lock(&adap->lock); -- if (!adap->is_configured && fh->mode_follower < CEC_MODE_MONITOR) -- err = -ENONET; -- mutex_unlock(&adap->lock); -- if (err) -- return err; - - err = cec_receive_msg(fh, &msg, block); - if (err) -@@ -515,9 +514,19 @@ static int cec_open(struct inode *inode, struct file *filp) - return err; - } - -+ mutex_lock(&devnode->lock); -+ if (list_empty(&devnode->fhs) && -+ !adap->needs_hpd && -+ adap->phys_addr == CEC_PHYS_ADDR_INVALID) { -+ err = adap->ops->adap_enable(adap, true); -+ if (err) { -+ mutex_unlock(&devnode->lock); -+ kfree(fh); -+ return err; -+ } -+ } - filp->private_data = fh; - -- mutex_lock(&devnode->lock); - /* Queue up initial state events */ - ev_state.state_change.phys_addr = adap->phys_addr; - ev_state.state_change.log_addr_mask = adap->log_addrs.log_addr_mask; -@@ -551,6 +560,11 @@ static int cec_release(struct inode *inode, struct file *filp) - - mutex_lock(&devnode->lock); - list_del(&fh->list); -+ if (list_empty(&devnode->fhs) && -+ !adap->needs_hpd && -+ adap->phys_addr == CEC_PHYS_ADDR_INVALID) { -+ WARN_ON(adap->ops->adap_enable(adap, false)); -+ } - mutex_unlock(&devnode->lock); - - /* Unhook pending transmits from this filehandle. */ diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c -index 37217e205040..b8f0bf1da57a 100644 +index 969f770acf77..65d763be4385 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c -@@ -195,6 +195,24 @@ static void cec_devnode_unregister(struct cec_devnode *devnode) - put_device(&devnode->dev); - } - -+#ifdef CONFIG_CEC_NOTIFIER -+static void cec_cec_notify(struct cec_adapter *adap, u16 pa) -+{ -+ cec_s_phys_addr(adap, pa, false); -+} -+ -+void cec_register_cec_notifier(struct cec_adapter *adap, -+ struct cec_notifier *notifier) -+{ -+ if (WARN_ON(!adap->devnode.registered)) -+ return; -+ -+ adap->notifier = notifier; -+ cec_notifier_register(adap->notifier, adap, cec_cec_notify); -+} -+EXPORT_SYMBOL_GPL(cec_register_cec_notifier); -+#endif -+ - struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, - void *priv, const char *name, u32 caps, - u8 available_las) -@@ -202,6 +220,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, - struct cec_adapter *adap; - int res; - -+#ifndef CONFIG_MEDIA_CEC_RC -+ caps &= ~CEC_CAP_RC; -+#endif -+ - if (WARN_ON(!caps)) - return ERR_PTR(-EINVAL); - if (WARN_ON(!ops)) -@@ -216,6 +238,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, - adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; - adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE; - adap->capabilities = caps; -+ adap->needs_hpd = caps & CEC_CAP_NEEDS_HPD; - adap->available_log_addrs = available_las; - adap->sequence = 0; - adap->ops = ops; -@@ -234,12 +257,12 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, - return ERR_PTR(res); - } - -+#ifdef CONFIG_MEDIA_CEC_RC - if (!(caps & CEC_CAP_RC)) +@@ -263,7 +263,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, return adap; --#if IS_REACHABLE(CONFIG_RC_CORE) /* Prepare the RC input device */ - adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); + adap->rc = rc_allocate_device(); if (!adap->rc) { pr_err("cec-%s: failed to allocate memory for rc_dev\n", name); -@@ -259,13 +282,12 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, +@@ -283,11 +283,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, adap->rc->input_id.vendor = 0; adap->rc->input_id.product = 0; adap->rc->input_id.version = 1; @@ -3014,243 +2546,28 @@ index 37217e205040..b8f0bf1da57a 100644 adap->rc->priv = adap; adap->rc->map_name = RC_MAP_CEC; adap->rc->timeout = MS_TO_NS(100); --#else -- adap->capabilities &= ~CEC_CAP_RC; ++ adap->rc_last_scancode = -1; #endif return adap; } -@@ -285,9 +307,9 @@ int cec_register_adapter(struct cec_adapter *adap, - adap->owner = parent->driver->owner; - adap->devnode.dev.parent = parent; - --#if IS_REACHABLE(CONFIG_RC_CORE) -- adap->rc->dev.parent = parent; -+#ifdef CONFIG_MEDIA_CEC_RC - if (adap->capabilities & CEC_CAP_RC) { -+ adap->rc->dev.parent = parent; - res = rc_register_device(adap->rc); - - if (res) { -@@ -302,7 +324,7 @@ int cec_register_adapter(struct cec_adapter *adap, - - res = cec_devnode_register(&adap->devnode, adap->owner); - if (res) { --#if IS_REACHABLE(CONFIG_RC_CORE) -+#ifdef CONFIG_MEDIA_CEC_RC - /* Note: rc_unregister also calls rc_free */ - rc_unregister_device(adap->rc); - adap->rc = NULL; -@@ -311,7 +333,7 @@ int cec_register_adapter(struct cec_adapter *adap, +@@ -319,6 +321,17 @@ int cec_register_adapter(struct cec_adapter *adap, + adap->rc = NULL; + return res; + } ++ /* ++ * The REP_DELAY for CEC is really the time between the initial ++ * 'User Control Pressed' message and the second. The first ++ * keypress is always seen as non-repeating, the second ++ * (provided it has the same UI Command) will start the 'Press ++ * and Hold' (aka repeat) behavior. By setting REP_DELAY to the ++ * same value as REP_PERIOD the expected CEC behavior is ++ * reproduced. ++ */ ++ adap->rc->input_dev->rep[REP_DELAY] = ++ adap->rc->input_dev->rep[REP_PERIOD]; } - - dev_set_drvdata(&adap->devnode.dev, adap); --#ifdef CONFIG_MEDIA_CEC_DEBUG -+#ifdef CONFIG_DEBUG_FS - if (!top_cec_dir) - return 0; - -@@ -337,12 +359,16 @@ void cec_unregister_adapter(struct cec_adapter *adap) - if (IS_ERR_OR_NULL(adap)) - return; - --#if IS_REACHABLE(CONFIG_RC_CORE) -+#ifdef CONFIG_MEDIA_CEC_RC - /* Note: rc_unregister also calls rc_free */ - rc_unregister_device(adap->rc); - adap->rc = NULL; #endif - debugfs_remove_recursive(adap->cec_dir); -+#ifdef CONFIG_CEC_NOTIFIER -+ if (adap->notifier) -+ cec_notifier_unregister(adap->notifier); -+#endif - cec_devnode_unregister(&adap->devnode); - } - EXPORT_SYMBOL_GPL(cec_unregister_adapter); -@@ -357,7 +383,7 @@ void cec_delete_adapter(struct cec_adapter *adap) - kthread_stop(adap->kthread); - if (adap->kthread_config) - kthread_stop(adap->kthread_config); --#if IS_REACHABLE(CONFIG_RC_CORE) -+#ifdef CONFIG_MEDIA_CEC_RC - rc_free_device(adap->rc); - #endif - kfree(adap); -@@ -379,7 +405,7 @@ static int __init cec_devnode_init(void) - return ret; - } --#ifdef CONFIG_MEDIA_CEC_DEBUG -+#ifdef CONFIG_DEBUG_FS - top_cec_dir = debugfs_create_dir("cec", NULL); - if (IS_ERR_OR_NULL(top_cec_dir)) { - pr_warn("cec: Failed to create debugfs cec dir\n"); -diff --git a/drivers/media/cec-edid.c b/drivers/media/cec/cec-edid.c -similarity index 96% -rename from drivers/media/cec-edid.c -rename to drivers/media/cec/cec-edid.c -index 5719b991e340..38e3fec6152b 100644 ---- a/drivers/media/cec-edid.c -+++ b/drivers/media/cec/cec-edid.c -@@ -20,7 +20,7 @@ - #include - #include - #include --#include -+#include - - /* - * This EDID is expected to be a CEA-861 compliant, which means that there are -@@ -165,7 +165,3 @@ int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) - return 0; - } - EXPORT_SYMBOL_GPL(cec_phys_addr_validate); -- --MODULE_AUTHOR("Hans Verkuil "); --MODULE_DESCRIPTION("CEC EDID helper functions"); --MODULE_LICENSE("GPL"); -diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c -new file mode 100644 -index 000000000000..08b619d0ea1e ---- /dev/null -+++ b/drivers/media/cec/cec-notifier.c -@@ -0,0 +1,136 @@ -+/* -+ * cec-notifier.c - notify CEC drivers of physical address changes -+ * -+ * Copyright 2016 Russell King -+ * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. -+ * -+ * This program is free software; you may redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+struct cec_notifier { -+ struct mutex lock; -+ struct list_head head; -+ struct kref kref; -+ struct device *dev; -+ struct cec_adapter *cec_adap; -+ void (*callback)(struct cec_adapter *adap, u16 pa); -+ -+ u16 phys_addr; -+}; -+ -+static LIST_HEAD(cec_notifiers); -+static DEFINE_MUTEX(cec_notifiers_lock); -+ -+struct cec_notifier *cec_notifier_get(struct device *dev) -+{ -+ struct cec_notifier *n; -+ -+ mutex_lock(&cec_notifiers_lock); -+ list_for_each_entry(n, &cec_notifiers, head) { -+ if (n->dev == dev) { -+ kref_get(&n->kref); -+ mutex_unlock(&cec_notifiers_lock); -+ return n; -+ } -+ } -+ n = kzalloc(sizeof(*n), GFP_KERNEL); -+ if (!n) -+ goto unlock; -+ n->dev = dev; -+ n->phys_addr = CEC_PHYS_ADDR_INVALID; -+ mutex_init(&n->lock); -+ kref_init(&n->kref); -+ list_add_tail(&n->head, &cec_notifiers); -+unlock: -+ mutex_unlock(&cec_notifiers_lock); -+ return n; -+} -+EXPORT_SYMBOL_GPL(cec_notifier_get); -+ -+static void cec_notifier_release(struct kref *kref) -+{ -+ struct cec_notifier *n = -+ container_of(kref, struct cec_notifier, kref); -+ -+ list_del(&n->head); -+ kfree(n); -+} -+ -+void cec_notifier_put(struct cec_notifier *n) -+{ -+ mutex_lock(&cec_notifiers_lock); -+ kref_put(&n->kref, cec_notifier_release); -+ mutex_unlock(&cec_notifiers_lock); -+} -+EXPORT_SYMBOL_GPL(cec_notifier_put); -+ -+void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) -+{ -+ if (n == NULL) -+ return; -+ -+ mutex_lock(&n->lock); -+ n->phys_addr = pa; -+ if (n->callback) -+ n->callback(n->cec_adap, n->phys_addr); -+ mutex_unlock(&n->lock); -+} -+EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr); -+ -+void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n, -+ const struct edid *edid) -+{ -+ u16 pa = CEC_PHYS_ADDR_INVALID; -+ -+ if (n == NULL) -+ return; -+ -+ if (edid && edid->extensions) -+ pa = cec_get_edid_phys_addr((const u8 *)edid, -+ EDID_LENGTH * (edid->extensions + 1), NULL); -+ cec_notifier_set_phys_addr(n, pa); -+} -+EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr_from_edid); -+ -+void cec_notifier_register(struct cec_notifier *n, -+ struct cec_adapter *adap, -+ void (*callback)(struct cec_adapter *adap, u16 pa)) -+{ -+ kref_get(&n->kref); -+ mutex_lock(&n->lock); -+ n->cec_adap = adap; -+ n->callback = callback; -+ n->callback(adap, n->phys_addr); -+ mutex_unlock(&n->lock); -+} -+EXPORT_SYMBOL_GPL(cec_notifier_register); -+ -+void cec_notifier_unregister(struct cec_notifier *n) -+{ -+ mutex_lock(&n->lock); -+ n->callback = NULL; -+ mutex_unlock(&n->lock); -+ cec_notifier_put(n); -+} -+EXPORT_SYMBOL_GPL(cec_notifier_unregister); diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index fbbd3bbcd252..9cffcc61fdca 100644 --- a/drivers/media/rc/keymaps/Makefile @@ -3493,232 +2810,29 @@ index dcf26537c935..1957c340878d 100644 /* joystick */ COMPATIBLE_IOCTL(JSIOCGVERSION) -diff --git a/include/media/cec-edid.h b/include/media/cec-edid.h -deleted file mode 100644 -index bdf731ecba1a..000000000000 ---- a/include/media/cec-edid.h -+++ /dev/null -@@ -1,104 +0,0 @@ --/* -- * cec-edid - HDMI Consumer Electronics Control & EDID helpers -- * -- * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. -- * -- * This program is free software; you may redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; version 2 of the License. -- * -- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- * SOFTWARE. -- */ -- --#ifndef _MEDIA_CEC_EDID_H --#define _MEDIA_CEC_EDID_H -- --#include -- --#define CEC_PHYS_ADDR_INVALID 0xffff --#define cec_phys_addr_exp(pa) \ -- ((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf -- --/** -- * cec_get_edid_phys_addr() - find and return the physical address -- * -- * @edid: pointer to the EDID data -- * @size: size in bytes of the EDID data -- * @offset: If not %NULL then the location of the physical address -- * bytes in the EDID will be returned here. This is set to 0 -- * if there is no physical address found. -- * -- * Return: the physical address or CEC_PHYS_ADDR_INVALID if there is none. -- */ --u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, -- unsigned int *offset); -- --/** -- * cec_set_edid_phys_addr() - find and set the physical address -- * -- * @edid: pointer to the EDID data -- * @size: size in bytes of the EDID data -- * @phys_addr: the new physical address -- * -- * This function finds the location of the physical address in the EDID -- * and fills in the given physical address and updates the checksum -- * at the end of the EDID block. It does nothing if the EDID doesn't -- * contain a physical address. -- */ --void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr); -- --/** -- * cec_phys_addr_for_input() - calculate the PA for an input -- * -- * @phys_addr: the physical address of the parent -- * @input: the number of the input port, must be between 1 and 15 -- * -- * This function calculates a new physical address based on the input -- * port number. For example: -- * -- * PA = 0.0.0.0 and input = 2 becomes 2.0.0.0 -- * -- * PA = 3.0.0.0 and input = 1 becomes 3.1.0.0 -- * -- * PA = 3.2.1.0 and input = 5 becomes 3.2.1.5 -- * -- * PA = 3.2.1.3 and input = 5 becomes f.f.f.f since it maxed out the depth. -- * -- * Return: the new physical address or CEC_PHYS_ADDR_INVALID. -- */ --u16 cec_phys_addr_for_input(u16 phys_addr, u8 input); -- --/** -- * cec_phys_addr_validate() - validate a physical address from an EDID -- * -- * @phys_addr: the physical address to validate -- * @parent: if not %NULL, then this is filled with the parents PA. -- * @port: if not %NULL, then this is filled with the input port. -- * -- * This validates a physical address as read from an EDID. If the -- * PA is invalid (such as 1.0.1.0 since '0' is only allowed at the end), -- * then it will return -EINVAL. -- * -- * The parent PA is passed into %parent and the input port is passed into -- * %port. For example: -- * -- * PA = 0.0.0.0: has parent 0.0.0.0 and input port 0. -- * -- * PA = 1.0.0.0: has parent 0.0.0.0 and input port 1. -- * -- * PA = 3.2.0.0: has parent 3.0.0.0 and input port 2. -- * -- * PA = f.f.f.f: has parent f.f.f.f and input port 0. -- * -- * Return: 0 if the PA is valid, -EINVAL if not. -- */ --int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port); -- --#endif /* _MEDIA_CEC_EDID_H */ diff --git a/include/media/cec-notifier.h b/include/media/cec-notifier.h -new file mode 100644 -index 000000000000..a4f7429c4ae5 ---- /dev/null +index ca19a9305782..8bb169ac7afd 100644 +--- a/include/media/cec-notifier.h +++ b/include/media/cec-notifier.h -@@ -0,0 +1,136 @@ -+/* -+ * cec-notifier.h - notify CEC drivers of physical address changes -+ * -+ * Copyright 2016 Russell King -+ * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. -+ * -+ * This program is free software; you may redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#ifndef LINUX_CEC_NOTIFIER_H -+#define LINUX_CEC_NOTIFIER_H -+ -+#include -+#include -+ -+struct device; -+struct edid; -+struct cec_adapter; -+struct cec_notifier; -+ -+#if IS_REACHABLE(CONFIG_CEC_CORE) && IS_ENABLED(CONFIG_CEC_NOTIFIER) -+ +@@ -91,6 +91,14 @@ void cec_notifier_register(struct cec_notifier *n, + */ + void cec_notifier_unregister(struct cec_notifier *n); + +/** -+ * cec_notifier_get - find or create a new cec_notifier for the given device. -+ * @dev: device that sends the events. -+ * -+ * If a notifier for device @dev already exists, then increase the refcount -+ * and return that notifier. -+ * -+ * If it doesn't exist, then allocate a new notifier struct and return a -+ * pointer to that new struct. -+ * -+ * Return NULL if the memory could not be allocated. ++ * cec_register_cec_notifier - register the notifier with the cec adapter. ++ * @adap: the CEC adapter ++ * @notifier: the CEC notifier + */ -+struct cec_notifier *cec_notifier_get(struct device *dev); -+ -+/** -+ * cec_notifier_put - decrease refcount and delete when the refcount reaches 0. -+ * @n: notifier -+ */ -+void cec_notifier_put(struct cec_notifier *n); -+ -+/** -+ * cec_notifier_set_phys_addr - set a new physical address. -+ * @n: the CEC notifier -+ * @pa: the CEC physical address -+ * -+ * Set a new CEC physical address. -+ * Does nothing if @n == NULL. -+ */ -+void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa); -+ -+/** -+ * cec_notifier_set_phys_addr_from_edid - set parse the PA from the EDID. -+ * @n: the CEC notifier -+ * @edid: the struct edid pointer -+ * -+ * Parses the EDID to obtain the new CEC physical address and set it. -+ * Does nothing if @n == NULL. -+ */ -+void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n, -+ const struct edid *edid); -+ -+/** -+ * cec_notifier_register - register a callback with the notifier -+ * @n: the CEC notifier -+ * @adap: the CEC adapter, passed as argument to the callback function -+ * @callback: the callback function -+ */ -+void cec_notifier_register(struct cec_notifier *n, -+ struct cec_adapter *adap, -+ void (*callback)(struct cec_adapter *adap, u16 pa)); -+ -+/** -+ * cec_notifier_unregister - unregister the callback from the notifier. -+ * @n: the CEC notifier -+ */ -+void cec_notifier_unregister(struct cec_notifier *n); -+ -+#else -+static inline struct cec_notifier *cec_notifier_get(struct device *dev) -+{ -+ /* A non-NULL pointer is expected on success */ -+ return (struct cec_notifier *)0xdeadfeed; -+} -+ -+static inline void cec_notifier_put(struct cec_notifier *n) -+{ -+} -+ -+static inline void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) -+{ -+} -+ -+static inline void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n, -+ const struct edid *edid) -+{ -+} ++void cec_register_cec_notifier(struct cec_adapter *adap, ++ struct cec_notifier *notifier); + + #else + static inline struct cec_notifier *cec_notifier_get(struct device *dev) + { +@@ -111,6 +119,20 @@ static inline void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n, + { + } + +static inline void cec_notifier_register(struct cec_notifier *n, + struct cec_adapter *adap, + void (*callback)(struct cec_adapter *adap, u16 pa)) @@ -3729,215 +2843,71 @@ index 000000000000..a4f7429c4ae5 +{ +} + -+#endif -+ -+/** -+ * cec_notifier_phys_addr_invalidate() - set the physical address to INVALID -+ * -+ * @n: the CEC notifier -+ * -+ * This is a simple helper function to invalidate the physical -+ * address. Does nothing if @n == NULL. -+ */ -+static inline void cec_notifier_phys_addr_invalidate(struct cec_notifier *n) ++static inline void cec_register_cec_notifier(struct cec_adapter *adap, ++ struct cec_notifier *notifier) +{ -+ cec_notifier_set_phys_addr(n, CEC_PHYS_ADDR_INVALID); +} -+ -+#endif -diff --git a/include/media/cec.h b/include/media/cec.h -index 96a0aa770d61..56643b27e4b8 100644 ---- a/include/media/cec.h -+++ b/include/media/cec.h -@@ -29,7 +29,7 @@ - #include - #include - #include --#include -+#include + #endif + /** +diff --git a/include/media/cec.h b/include/media/cec.h +index df3c94f05aa5..f64807a78064 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -31,6 +31,9 @@ + #include + #include + ++#define CEC_CAP_DEFAULTS (CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT | \ ++ CEC_CAP_PASSTHROUGH | CEC_CAP_RC) ++ /** * struct cec_devnode - cec device node -@@ -164,6 +164,7 @@ struct cec_adapter { - u8 available_log_addrs; + * @dev: cec device +@@ -188,6 +191,11 @@ struct cec_adapter { - u16 phys_addr; -+ bool needs_hpd; - bool is_configuring; - bool is_configured; - u32 monitor_all_cnt; -@@ -173,6 +174,10 @@ struct cec_adapter { - bool passthrough; - struct cec_log_addrs log_addrs; + u32 tx_timeouts; -+#ifdef CONFIG_CEC_NOTIFIER -+ struct cec_notifier *notifier; ++#ifdef CONFIG_MEDIA_CEC_RC ++ bool rc_repeating; ++ int rc_last_scancode; ++ u64 rc_last_keypress; +#endif -+ - struct dentry *cec_dir; - struct dentry *status_file; + #ifdef CONFIG_CEC_NOTIFIER + struct cec_notifier *notifier; + #endif +@@ -226,7 +234,7 @@ static inline bool cec_is_sink(const struct cec_adapter *adap) -@@ -184,6 +189,11 @@ struct cec_adapter { - char input_drv[32]; - }; + struct edid; -+static inline void *cec_get_drvdata(const struct cec_adapter *adap) -+{ -+ return adap->priv; -+} -+ - static inline bool cec_has_log_addr(const struct cec_adapter *adap, u8 log_addr) - { - return adap->log_addrs.log_addr_mask & (1 << log_addr); -@@ -194,7 +204,12 @@ static inline bool cec_is_sink(const struct cec_adapter *adap) - return adap->phys_addr == 0; - } - --#if IS_ENABLED(CONFIG_MEDIA_CEC_SUPPORT) -+#define cec_phys_addr_exp(pa) \ -+ ((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf -+ -+struct edid; -+ +-#if IS_ENABLED(CONFIG_CEC_CORE) +#if IS_REACHABLE(CONFIG_CEC_CORE) struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, void *priv, const char *name, u32 caps, u8 available_las); int cec_register_adapter(struct cec_adapter *adap, struct device *parent); -@@ -205,14 +220,102 @@ int cec_s_log_addrs(struct cec_adapter *adap, struct cec_log_addrs *log_addrs, - bool block); - void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, - bool block); -+void cec_s_phys_addr_from_edid(struct cec_adapter *adap, -+ const struct edid *edid); - int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg, - bool block); +@@ -373,11 +381,6 @@ u16 cec_phys_addr_for_input(u16 phys_addr, u8 input); + */ + int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port); - /* Called by the adapter */ - void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt, - u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt); -+/* -+ * Simplified version of cec_transmit_done for hardware that doesn't retry -+ * failed transmits. So this is always just one attempt in which case -+ * the status is sufficient. -+ */ -+void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status); - void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg); - -+/** -+ * cec_get_edid_phys_addr() - find and return the physical address -+ * -+ * @edid: pointer to the EDID data -+ * @size: size in bytes of the EDID data -+ * @offset: If not %NULL then the location of the physical address -+ * bytes in the EDID will be returned here. This is set to 0 -+ * if there is no physical address found. -+ * -+ * Return: the physical address or CEC_PHYS_ADDR_INVALID if there is none. -+ */ -+u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, -+ unsigned int *offset); -+ -+/** -+ * cec_set_edid_phys_addr() - find and set the physical address -+ * -+ * @edid: pointer to the EDID data -+ * @size: size in bytes of the EDID data -+ * @phys_addr: the new physical address -+ * -+ * This function finds the location of the physical address in the EDID -+ * and fills in the given physical address and updates the checksum -+ * at the end of the EDID block. It does nothing if the EDID doesn't -+ * contain a physical address. -+ */ -+void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr); -+ -+/** -+ * cec_phys_addr_for_input() - calculate the PA for an input -+ * -+ * @phys_addr: the physical address of the parent -+ * @input: the number of the input port, must be between 1 and 15 -+ * -+ * This function calculates a new physical address based on the input -+ * port number. For example: -+ * -+ * PA = 0.0.0.0 and input = 2 becomes 2.0.0.0 -+ * -+ * PA = 3.0.0.0 and input = 1 becomes 3.1.0.0 -+ * -+ * PA = 3.2.1.0 and input = 5 becomes 3.2.1.5 -+ * -+ * PA = 3.2.1.3 and input = 5 becomes f.f.f.f since it maxed out the depth. -+ * -+ * Return: the new physical address or CEC_PHYS_ADDR_INVALID. -+ */ -+u16 cec_phys_addr_for_input(u16 phys_addr, u8 input); -+ -+/** -+ * cec_phys_addr_validate() - validate a physical address from an EDID -+ * -+ * @phys_addr: the physical address to validate -+ * @parent: if not %NULL, then this is filled with the parents PA. -+ * @port: if not %NULL, then this is filled with the input port. -+ * -+ * This validates a physical address as read from an EDID. If the -+ * PA is invalid (such as 1.0.1.0 since '0' is only allowed at the end), -+ * then it will return -EINVAL. -+ * -+ * The parent PA is passed into %parent and the input port is passed into -+ * %port. For example: -+ * -+ * PA = 0.0.0.0: has parent 0.0.0.0 and input port 0. -+ * -+ * PA = 1.0.0.0: has parent 0.0.0.0 and input port 1. -+ * -+ * PA = 3.2.0.0: has parent 3.0.0.0 and input port 2. -+ * -+ * PA = f.f.f.f: has parent f.f.f.f and input port 0. -+ * -+ * Return: 0 if the PA is valid, -EINVAL if not. -+ */ -+int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port); -+ -+#ifdef CONFIG_CEC_NOTIFIER -+void cec_register_cec_notifier(struct cec_adapter *adap, -+ struct cec_notifier *notifier); -+#endif -+ +-#ifdef CONFIG_CEC_NOTIFIER +-void cec_register_cec_notifier(struct cec_adapter *adap, +- struct cec_notifier *notifier); +-#endif +- #else static inline int cec_register_adapter(struct cec_adapter *adap, -@@ -234,6 +337,47 @@ static inline void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, +@@ -424,9 +427,26 @@ static inline u16 cec_phys_addr_for_input(u16 phys_addr, u8 input) + + static inline int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) { ++ if (parent) ++ *parent = phys_addr; ++ if (port) ++ *port = 0; + return 0; } -+static inline void cec_s_phys_addr_from_edid(struct cec_adapter *adap, -+ const struct edid *edid) -+{ -+} -+ -+static inline u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, -+ unsigned int *offset) -+{ -+ if (offset) -+ *offset = 0; -+ return CEC_PHYS_ADDR_INVALID; -+} -+ -+static inline void cec_set_edid_phys_addr(u8 *edid, unsigned int size, -+ u16 phys_addr) -+{ -+} -+ -+static inline u16 cec_phys_addr_for_input(u16 phys_addr, u8 input) -+{ -+ return CEC_PHYS_ADDR_INVALID; -+} -+ -+static inline int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) -+{ -+ return 0; -+} -+ #endif +/** @@ -3991,8 +2961,20 @@ index 7c4bbc4dfab4..d9f87d5b4468 100644 #define RC_MAP_CINERGY_1400 "rc-cinergy-1400" #define RC_MAP_CINERGY "rc-cinergy" #define RC_MAP_DELOCK_61959 "rc-delock-61959" +diff --git a/include/uapi/linux/cec-funcs.h b/include/uapi/linux/cec-funcs.h +index c451eec42a83..270b251a3d9b 100644 +--- a/include/uapi/linux/cec-funcs.h ++++ b/include/uapi/linux/cec-funcs.h +@@ -895,6 +895,7 @@ static inline void cec_ops_report_features(const struct cec_msg *msg, + *cec_version = msg->msg[2]; + *all_device_types = msg->msg[3]; + *rc_profile = p; ++ *dev_features = NULL; + while (p < &msg->msg[14] && (*p & CEC_OP_FEAT_EXT)) + p++; + if (!(*p & CEC_OP_FEAT_EXT)) { diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h -index 14b6f24b189e..44579a24f95d 100644 +index af6682f5ea85..b9f8df3a0477 100644 --- a/include/uapi/linux/cec.h +++ b/include/uapi/linux/cec.h @@ -223,7 +223,7 @@ static inline int cec_msg_status_is_ok(const struct cec_msg *msg) @@ -4004,15 +2986,6 @@ index 14b6f24b189e..44579a24f95d 100644 /* The logical address types that the CEC device wants to claim */ #define CEC_LOG_ADDR_TYPE_TV 0 -@@ -336,6 +336,8 @@ static inline int cec_is_unconfigured(__u16 log_addr_mask) - #define CEC_CAP_RC (1 << 4) - /* Hardware can monitor all messages, not just directed and broadcast. */ - #define CEC_CAP_MONITOR_ALL (1 << 5) -+/* Hardware can use CEC only if the HDMI HPD pin is high. */ -+#define CEC_CAP_NEEDS_HPD (1 << 6) - - /** - * struct cec_caps - CEC capabilities structure. diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index 87cf351bab03..b0c5c4888a4b 100644 --- a/include/uapi/linux/input-event-codes.h @@ -4068,10 +3041,10 @@ index 2758687300b4..41e8dff588e1 100644 /* * MT_TOOL types -From cc93c64855522d796adeba969872a0c0a3158f3e Mon Sep 17 00:00:00 2001 +From 03e885addf35184601cf77dd9cd72ca13ec92935 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 4 Sep 2017 22:34:22 +0200 -Subject: [PATCH 02/11] BACKPORT: Pulse Eight HDMI CEC from v4.13 +Subject: [PATCH] BACKPORT: Pulse Eight HDMI CEC from v4.15 --- MAINTAINERS | 7 + @@ -4080,18 +3053,18 @@ Subject: [PATCH 02/11] BACKPORT: Pulse Eight HDMI CEC from v4.13 drivers/media/usb/Makefile | 1 + drivers/media/usb/pulse8-cec/Kconfig | 11 + drivers/media/usb/pulse8-cec/Makefile | 1 + - drivers/media/usb/pulse8-cec/pulse8-cec.c | 758 ++++++++++++++++++++++++++++++ + drivers/media/usb/pulse8-cec/pulse8-cec.c | 757 ++++++++++++++++++++++++++++++ include/uapi/linux/serio.h | 1 + - 8 files changed, 798 insertions(+), 3 deletions(-) + 8 files changed, 797 insertions(+), 3 deletions(-) create mode 100644 drivers/media/usb/pulse8-cec/Kconfig create mode 100644 drivers/media/usb/pulse8-cec/Makefile create mode 100644 drivers/media/usb/pulse8-cec/pulse8-cec.c diff --git a/MAINTAINERS b/MAINTAINERS -index 124551e7b781..3f10c7b7f3eb 100644 +index bb1aa323019c..3ba807edf5c6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -8623,6 +8623,13 @@ F: include/linux/tracehook.h +@@ -8637,6 +8637,13 @@ F: include/linux/tracehook.h F: include/uapi/linux/ptrace.h F: kernel/ptrace.c @@ -4198,10 +3171,10 @@ index 000000000000..9800690bc25a +obj-$(CONFIG_USB_PULSE8_CEC) += pulse8-cec.o diff --git a/drivers/media/usb/pulse8-cec/pulse8-cec.c b/drivers/media/usb/pulse8-cec/pulse8-cec.c new file mode 100644 -index 000000000000..f9ed9c950247 +index 000000000000..50146f263d90 --- /dev/null +++ b/drivers/media/usb/pulse8-cec/pulse8-cec.c -@@ -0,0 +1,758 @@ +@@ -0,0 +1,757 @@ +/* + * Pulse Eight HDMI CEC driver + * @@ -4846,8 +3819,7 @@ index 000000000000..f9ed9c950247 + +static int pulse8_connect(struct serio *serio, struct serio_driver *drv) +{ -+ u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | CEC_CAP_PHYS_ADDR | -+ CEC_CAP_PASSTHROUGH | CEC_CAP_RC | CEC_CAP_MONITOR_ALL; ++ u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | CEC_CAP_MONITOR_ALL; + struct pulse8 *pulse8; + int err = -ENOMEM; + struct cec_log_addrs log_addrs = {}; @@ -4860,7 +3832,7 @@ index 000000000000..f9ed9c950247 + + pulse8->serio = serio; + pulse8->adap = cec_allocate_adapter(&pulse8_cec_adap_ops, pulse8, -+ "HDMI CEC", caps, 1); ++ dev_name(&serio->dev), caps, 1); + err = PTR_ERR_OR_ZERO(pulse8->adap); + if (err < 0) + goto free_device; @@ -4936,7 +3908,7 @@ index 000000000000..f9ed9c950247 + mutex_unlock(&pulse8->config_lock); +} + -+static struct serio_device_id pulse8_serio_ids[] = { ++static const struct serio_device_id pulse8_serio_ids[] = { + { + .type = SERIO_RS232, + .proto = SERIO_PULSE8_CEC, @@ -4972,10 +3944,10 @@ index becdd78295cc..4588c66a8df0 100644 #endif /* _UAPI_SERIO_H */ -From 54344a8c478c350fb4fefa7a09b413953d0acd6a Mon Sep 17 00:00:00 2001 +From ab37540e363f046bf03f4b590c76baef21eef971 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 4 Sep 2017 22:34:24 +0200 -Subject: [PATCH 03/11] BACKPORT: RainShadow Tech HDMI CEC from v4.13 +Subject: [PATCH] BACKPORT: RainShadow Tech HDMI CEC from v4.15 --- MAINTAINERS | 7 + @@ -4983,18 +3955,18 @@ Subject: [PATCH 03/11] BACKPORT: RainShadow Tech HDMI CEC from v4.13 drivers/media/usb/Makefile | 1 + drivers/media/usb/rainshadow-cec/Kconfig | 11 + drivers/media/usb/rainshadow-cec/Makefile | 1 + - drivers/media/usb/rainshadow-cec/rainshadow-cec.c | 385 ++++++++++++++++++++++ + drivers/media/usb/rainshadow-cec/rainshadow-cec.c | 384 ++++++++++++++++++++++ include/uapi/linux/serio.h | 1 + - 7 files changed, 407 insertions(+) + 7 files changed, 406 insertions(+) create mode 100644 drivers/media/usb/rainshadow-cec/Kconfig create mode 100644 drivers/media/usb/rainshadow-cec/Makefile create mode 100644 drivers/media/usb/rainshadow-cec/rainshadow-cec.c diff --git a/MAINTAINERS b/MAINTAINERS -index 3f10c7b7f3eb..ede39504b4b3 100644 +index 3ba807edf5c6..c6413ddaa627 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -8862,6 +8862,13 @@ L: linux-fbdev@vger.kernel.org +@@ -8876,6 +8876,13 @@ L: linux-fbdev@vger.kernel.org S: Maintained F: drivers/video/fbdev/aty/aty128fb.c @@ -5055,10 +4027,10 @@ index 000000000000..a79fbc77e1f7 +obj-$(CONFIG_USB_RAINSHADOW_CEC) += rainshadow-cec.o diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c new file mode 100644 -index 000000000000..65692576690f +index 000000000000..cecdcbcd400c --- /dev/null +++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c -@@ -0,0 +1,385 @@ +@@ -0,0 +1,384 @@ +/* + * RainShadow Tech HDMI CEC driver + * @@ -5370,8 +4342,7 @@ index 000000000000..65692576690f + +static int rain_connect(struct serio *serio, struct serio_driver *drv) +{ -+ u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | CEC_CAP_PHYS_ADDR | -+ CEC_CAP_PASSTHROUGH | CEC_CAP_RC | CEC_CAP_MONITOR_ALL; ++ u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | CEC_CAP_MONITOR_ALL; + struct rain *rain; + int err = -ENOMEM; + struct cec_log_addrs log_addrs = {}; @@ -5384,7 +4355,7 @@ index 000000000000..65692576690f + + rain->serio = serio; + rain->adap = cec_allocate_adapter(&rain_cec_adap_ops, rain, -+ "HDMI CEC", caps, 1); ++ dev_name(&serio->dev), caps, 1); + err = PTR_ERR_OR_ZERO(rain->adap); + if (err < 0) + goto free_device; @@ -5420,7 +4391,7 @@ index 000000000000..65692576690f + return err; +} + -+static struct serio_device_id rain_serio_ids[] = { ++static const struct serio_device_id rain_serio_ids[] = { + { + .type = SERIO_RS232, + .proto = SERIO_RAINSHADOW_CEC, @@ -5456,926 +4427,10 @@ index 4588c66a8df0..89b72003fb68 100644 #endif /* _UAPI_SERIO_H */ -From 90b8d3f3640bc08222d0a0bc418d7eacebe004e8 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 31 Jul 2017 15:29:41 +0100 -Subject: [PATCH 04/11] UPSTREAM: drm/bridge: dw-hdmi: add cec notifier support - -Add CEC notifier support to the HDMI bridge driver, so that the CEC -part of the IP can receive its physical address. - -Signed-off-by: Russell King -Tested-by: Neil Armstrong -Reviewed-by: Neil Armstrong -Tested-by: Laurent Pinchart -Acked-by: Hans Verkuil -Signed-off-by: Archit Taneja -Link: https://patchwork.freedesktop.org/patch/msgid/E1dcBhV-00088e-8x@rmk-PC.armlinux.org.uk -(cherry picked from commit e84b8d75ac116e67ac3bdb23cafbd03430aa50b9) ---- - drivers/gpu/drm/bridge/Kconfig | 1 + - drivers/gpu/drm/bridge/dw-hdmi.c | 18 ++++++++++++++++++ - 2 files changed, 19 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig -index df2dcc157f5a..0af0da74dde9 100644 ---- a/drivers/gpu/drm/bridge/Kconfig -+++ b/drivers/gpu/drm/bridge/Kconfig -@@ -10,6 +10,7 @@ menu "Display Interface Bridges" - config DRM_DW_HDMI - tristate - select DRM_KMS_HELPER -+ select CEC_CORE if CEC_NOTIFIER - - config DRM_DW_HDMI_AHB_AUDIO - tristate "Synopsis Designware AHB Audio interface" -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index beba78accfe3..98531e36f3b9 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -42,6 +42,8 @@ - #include "dw-hdmi-audio.h" - #include "dw-hdmi-hdcp.h" - -+#include -+ - #define HDMI_EDID_LEN 512 - #define DDC_SEGMENT_ADDR 0x30 - -@@ -261,6 +263,8 @@ struct dw_hdmi { - u8 (*read)(struct dw_hdmi *hdmi, int offset); - void (*enable_audio)(struct dw_hdmi *hdmi); - void (*disable_audio)(struct dw_hdmi *hdmi); -+ -+ struct cec_notifier *cec_notifier; - }; - - #define HDMI_IH_PHY_STAT0_RX_SENSE \ -@@ -2499,6 +2503,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) - hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); - hdmi->sink_has_audio = drm_detect_monitor_audio(edid); - drm_mode_connector_update_edid_property(connector, edid); -+ cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); - ret = drm_add_edid_modes(connector, edid); - /* Store the ELD */ - drm_edid_to_eld(connector, edid); -@@ -2840,6 +2845,10 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) - dw_hdmi_update_phy_mask(hdmi); - } - mutex_unlock(&hdmi->mutex); -+ -+ if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) -+ cec_notifier_set_phys_addr(hdmi->cec_notifier, -+ CEC_PHYS_ADDR_INVALID); - } - - check_hdmi_irq(hdmi, intr_stat, phy_int_pol); -@@ -3472,6 +3481,12 @@ int dw_hdmi_bind(struct device *dev, struct device *master, - if (ret) - goto err_iahb; - -+ hdmi->cec_notifier = cec_notifier_get(dev); -+ if (!hdmi->cec_notifier) { -+ ret = -ENOMEM; -+ goto err_iahb; -+ } -+ - /* - * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator - * N and cts values before enabling phy -@@ -3567,6 +3582,9 @@ err_iahb: - if (hdmi->i2c) - i2c_del_adapter(&hdmi->i2c->adap); - -+ if (hdmi->cec_notifier) -+ cec_notifier_put(hdmi->cec_notifier); -+ - clk_disable_unprepare(hdmi->iahb_clk); - err_isfr: - clk_disable_unprepare(hdmi->isfr_clk); - -From 96f9e4b9de8522f60735d163b1dfd29caf8ccf8d Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 31 Jul 2017 15:29:46 +0100 -Subject: [PATCH 05/11] UPSTREAM: drm/bridge: dw-hdmi: add better clock disable - control - -The video setup path aways sets the clock disable register to a specific -value, which has the effect of disabling the CEC engine. When we add the -CEC driver, this becomes a problem. - -Fix this by only setting/clearing the bits that the video path needs to. - -Reviewed-by: Jose Abreu -Signed-off-by: Russell King -Tested-by: Laurent Pinchart -Acked-by: Hans Verkuil -Signed-off-by: Archit Taneja -Link: https://patchwork.freedesktop.org/patch/msgid/E1dcBha-00088l-DE@rmk-PC.armlinux.org.uk -(cherry picked from commit 7cc4ab225ae30bd9ec9239e7dba5b2937f526ccc) ---- - drivers/gpu/drm/bridge/dw-hdmi.c | 33 ++++++++++++++++++++------------- - 1 file changed, 20 insertions(+), 13 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index 98531e36f3b9..90d9569fc66d 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -245,6 +245,7 @@ struct dw_hdmi { - bool bridge_is_on; /* indicates the bridge is on */ - bool rxsense; /* rxsense state */ - u8 phy_mask; /* desired phy int mask settings */ -+ u8 mc_clkdis; /* clock disable register */ - - spinlock_t audio_lock; - struct mutex audio_mutex; -@@ -806,8 +807,11 @@ EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); - - static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable) - { -- hdmi_modb(hdmi, enable ? 0 : HDMI_MC_CLKDIS_AUDCLK_DISABLE, -- HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS); -+ if (enable) -+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE; -+ else -+ hdmi->mc_clkdis |= HDMI_MC_CLKDIS_AUDCLK_DISABLE; -+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); - } - - static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi) -@@ -2084,8 +2088,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, - /* HDMI Initialization Step B.4 */ - static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) - { -- u8 clkdis; -- - /* control period minimum duration */ - hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR); - hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR); -@@ -2097,23 +2099,27 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) - hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM); - - /* Enable pixel clock and tmds data path */ -- clkdis = 0x7F; -- clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE; -- hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); -+ hdmi->mc_clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE | -+ HDMI_MC_CLKDIS_CSCCLK_DISABLE | -+ HDMI_MC_CLKDIS_AUDCLK_DISABLE | -+ HDMI_MC_CLKDIS_PREPCLK_DISABLE | -+ HDMI_MC_CLKDIS_TMDSCLK_DISABLE; -+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE; -+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); - -- clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE; -- hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); -+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE; -+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); - - /* Enable csc path */ - if (is_color_space_conversion(hdmi)) { -- clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; -- hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); -+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE; -+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); - } - - /* Enable pixel repetition path */ - if (hdmi->hdmi_data.video_mode.mpixelrepetitioninput) { -- clkdis &= ~HDMI_MC_CLKDIS_PREPCLK_DISABLE; -- hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS); -+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_PREPCLK_DISABLE; -+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); - } - - /* Enable color space conversion if needed */ -@@ -3368,6 +3374,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, - hdmi->rxsense = true; - hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE); - hdmi->irq = irq; -+ hdmi->mc_clkdis = 0x7f; - - mutex_init(&hdmi->mutex); - mutex_init(&hdmi->audio_mutex); - -From 06f190ff7d2e2fa76558b83d318fdc6913b6e10b Mon Sep 17 00:00:00 2001 -From: Hans Verkuil -Date: Mon, 7 Aug 2017 09:20:35 +0200 -Subject: [PATCH 06/11] UPSTREAM: drm/bridge: dw-hdmi: add missing - cec_notifier_put - -The __dw_hdmi_remove() function was missing a call to cec_notifier_put -to balance the cec_notifier_get in the probe function. - -Signed-off-by: Hans Verkuil -Signed-off-by: Archit Taneja -Link: https://patchwork.freedesktop.org/patch/msgid/a7688d13-2d61-ed16-f2df-28cbb5007f38@xs4all.nl -(cherry picked from commit e383bf85d32b5953f34fa0e3d619886ec49413b1) ---- - drivers/gpu/drm/bridge/dw-hdmi.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index 90d9569fc66d..88561176dc03 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -3622,6 +3622,9 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data) - /* Disable all interrupts */ - hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); - -+ if (hdmi->cec_notifier) -+ cec_notifier_put(hdmi->cec_notifier); -+ - #ifdef CONFIG_SWITCH - switch_dev_unregister(&hdmi->switchdev); - #endif - -From 4599487e4b0569ca27ca4a64d665a63deb5e8db7 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Wed, 2 Aug 2017 20:41:07 +0200 -Subject: [PATCH 07/11] UPSTREAM: drm/bridge: dw-hdmi: add cec driver - -Add a CEC driver for the dw-hdmi hardware. - -Reviewed-by: Neil Armstrong -Signed-off-by: Russell King -[hans.verkuil: unsigned -> unsigned int] -[hans.verkuil: cec_transmit_done -> cec_transmit_attempt_done] -[hans.verkuil: add missing CEC_CAP_PASSTHROUGH] -Acked-by: Hans Verkuil -Tested-by: Hans Verkuil -Tested-by: Laurent Pinchart -Signed-off-by: Archit Taneja -Link: https://patchwork.freedesktop.org/patch/msgid/20170802184108.7913-4-hverkuil@xs4all.nl -(cherry picked from commit a616e63c56ef35365b781f08c7d437840f56940f) ---- - drivers/gpu/drm/bridge/Kconfig | 9 + - drivers/gpu/drm/bridge/Makefile | 1 + - drivers/gpu/drm/bridge/dw-hdmi-cec.c | 327 +++++++++++++++++++++++++++++++++++ - drivers/gpu/drm/bridge/dw-hdmi-cec.h | 19 ++ - drivers/gpu/drm/bridge/dw-hdmi.c | 42 ++++- - drivers/gpu/drm/bridge/dw-hdmi.h | 1 + - 6 files changed, 398 insertions(+), 1 deletion(-) - create mode 100644 drivers/gpu/drm/bridge/dw-hdmi-cec.c - create mode 100644 drivers/gpu/drm/bridge/dw-hdmi-cec.h - -diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig -index 0af0da74dde9..dc2f6c157ea3 100644 ---- a/drivers/gpu/drm/bridge/Kconfig -+++ b/drivers/gpu/drm/bridge/Kconfig -@@ -31,6 +31,15 @@ config DRM_DW_HDMI_I2S_AUDIO - Support the I2S Audio interface which is part of the Synopsis - Designware HDMI block. - -+config DRM_DW_HDMI_CEC -+ tristate "Synopsis Designware CEC interface" -+ depends on DRM_DW_HDMI -+ select CEC_CORE -+ select CEC_NOTIFIER -+ help -+ Support the CE interface which is part of the Synopsys -+ Designware HDMI block. -+ - config DRM_NXP_PTN3460 - tristate "NXP PTN3460 DP/LVDS bridge" - depends on OF -diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile -index e582bbbb808b..80f162935fef 100644 ---- a/drivers/gpu/drm/bridge/Makefile -+++ b/drivers/gpu/drm/bridge/Makefile -@@ -3,6 +3,7 @@ ccflags-y := -Iinclude/drm - obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o dw-hdmi-hdcp.o - obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o - obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o -+obj-$(CONFIG_DRM_DW_HDMI_CEC) += dw-hdmi-cec.o - obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o - obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o - obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ -diff --git a/drivers/gpu/drm/bridge/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/dw-hdmi-cec.c -new file mode 100644 -index 000000000000..6c323510f128 ---- /dev/null -+++ b/drivers/gpu/drm/bridge/dw-hdmi-cec.c -@@ -0,0 +1,327 @@ -+/* -+ * Designware HDMI CEC driver -+ * -+ * Copyright (C) 2015-2017 Russell King. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#include "dw-hdmi-cec.h" -+ -+enum { -+ HDMI_IH_CEC_STAT0 = 0x0106, -+ HDMI_IH_MUTE_CEC_STAT0 = 0x0186, -+ -+ HDMI_CEC_CTRL = 0x7d00, -+ CEC_CTRL_START = BIT(0), -+ CEC_CTRL_FRAME_TYP = 3 << 1, -+ CEC_CTRL_RETRY = 0 << 1, -+ CEC_CTRL_NORMAL = 1 << 1, -+ CEC_CTRL_IMMED = 2 << 1, -+ -+ HDMI_CEC_STAT = 0x7d01, -+ CEC_STAT_DONE = BIT(0), -+ CEC_STAT_EOM = BIT(1), -+ CEC_STAT_NACK = BIT(2), -+ CEC_STAT_ARBLOST = BIT(3), -+ CEC_STAT_ERROR_INIT = BIT(4), -+ CEC_STAT_ERROR_FOLL = BIT(5), -+ CEC_STAT_WAKEUP = BIT(6), -+ -+ HDMI_CEC_MASK = 0x7d02, -+ HDMI_CEC_POLARITY = 0x7d03, -+ HDMI_CEC_INT = 0x7d04, -+ HDMI_CEC_ADDR_L = 0x7d05, -+ HDMI_CEC_ADDR_H = 0x7d06, -+ HDMI_CEC_TX_CNT = 0x7d07, -+ HDMI_CEC_RX_CNT = 0x7d08, -+ HDMI_CEC_TX_DATA0 = 0x7d10, -+ HDMI_CEC_RX_DATA0 = 0x7d20, -+ HDMI_CEC_LOCK = 0x7d30, -+ HDMI_CEC_WKUPCTRL = 0x7d31, -+}; -+ -+struct dw_hdmi_cec { -+ struct dw_hdmi *hdmi; -+ const struct dw_hdmi_cec_ops *ops; -+ u32 addresses; -+ struct cec_adapter *adap; -+ struct cec_msg rx_msg; -+ unsigned int tx_status; -+ bool tx_done; -+ bool rx_done; -+ struct cec_notifier *notify; -+ int irq; -+}; -+ -+static void dw_hdmi_write(struct dw_hdmi_cec *cec, u8 val, int offset) -+{ -+ cec->ops->write(cec->hdmi, val, offset); -+} -+ -+static u8 dw_hdmi_read(struct dw_hdmi_cec *cec, int offset) -+{ -+ return cec->ops->read(cec->hdmi, offset); -+} -+ -+static int dw_hdmi_cec_log_addr(struct cec_adapter *adap, u8 logical_addr) -+{ -+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap); -+ -+ if (logical_addr == CEC_LOG_ADDR_INVALID) -+ cec->addresses = 0; -+ else -+ cec->addresses |= BIT(logical_addr) | BIT(15); -+ -+ dw_hdmi_write(cec, cec->addresses & 255, HDMI_CEC_ADDR_L); -+ dw_hdmi_write(cec, cec->addresses >> 8, HDMI_CEC_ADDR_H); -+ -+ return 0; -+} -+ -+static int dw_hdmi_cec_transmit(struct cec_adapter *adap, u8 attempts, -+ u32 signal_free_time, struct cec_msg *msg) -+{ -+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap); -+ unsigned int i, ctrl; -+ -+ switch (signal_free_time) { -+ case CEC_SIGNAL_FREE_TIME_RETRY: -+ ctrl = CEC_CTRL_RETRY; -+ break; -+ case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR: -+ default: -+ ctrl = CEC_CTRL_NORMAL; -+ break; -+ case CEC_SIGNAL_FREE_TIME_NEXT_XFER: -+ ctrl = CEC_CTRL_IMMED; -+ break; -+ } -+ -+ for (i = 0; i < msg->len; i++) -+ dw_hdmi_write(cec, msg->msg[i], HDMI_CEC_TX_DATA0 + i); -+ -+ dw_hdmi_write(cec, msg->len, HDMI_CEC_TX_CNT); -+ dw_hdmi_write(cec, ctrl | CEC_CTRL_START, HDMI_CEC_CTRL); -+ -+ return 0; -+} -+ -+static irqreturn_t dw_hdmi_cec_hardirq(int irq, void *data) -+{ -+ struct cec_adapter *adap = data; -+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap); -+ unsigned int stat = dw_hdmi_read(cec, HDMI_IH_CEC_STAT0); -+ irqreturn_t ret = IRQ_HANDLED; -+ -+ if (stat == 0) -+ return IRQ_NONE; -+ -+ dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0); -+ -+ if (stat & CEC_STAT_ERROR_INIT) { -+ cec->tx_status = CEC_TX_STATUS_ERROR; -+ cec->tx_done = true; -+ ret = IRQ_WAKE_THREAD; -+ } else if (stat & CEC_STAT_DONE) { -+ cec->tx_status = CEC_TX_STATUS_OK; -+ cec->tx_done = true; -+ ret = IRQ_WAKE_THREAD; -+ } else if (stat & CEC_STAT_NACK) { -+ cec->tx_status = CEC_TX_STATUS_NACK; -+ cec->tx_done = true; -+ ret = IRQ_WAKE_THREAD; -+ } -+ -+ if (stat & CEC_STAT_EOM) { -+ unsigned int len, i; -+ -+ len = dw_hdmi_read(cec, HDMI_CEC_RX_CNT); -+ if (len > sizeof(cec->rx_msg.msg)) -+ len = sizeof(cec->rx_msg.msg); -+ -+ for (i = 0; i < len; i++) -+ cec->rx_msg.msg[i] = -+ dw_hdmi_read(cec, HDMI_CEC_RX_DATA0 + i); -+ -+ dw_hdmi_write(cec, 0, HDMI_CEC_LOCK); -+ -+ cec->rx_msg.len = len; -+ smp_wmb(); -+ cec->rx_done = true; -+ -+ ret = IRQ_WAKE_THREAD; -+ } -+ -+ return ret; -+} -+ -+static irqreturn_t dw_hdmi_cec_thread(int irq, void *data) -+{ -+ struct cec_adapter *adap = data; -+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap); -+ -+ if (cec->tx_done) { -+ cec->tx_done = false; -+ cec_transmit_attempt_done(adap, cec->tx_status); -+ } -+ if (cec->rx_done) { -+ cec->rx_done = false; -+ smp_rmb(); -+ cec_received_msg(adap, &cec->rx_msg); -+ } -+ return IRQ_HANDLED; -+} -+ -+static int dw_hdmi_cec_enable(struct cec_adapter *adap, bool enable) -+{ -+ struct dw_hdmi_cec *cec = cec_get_drvdata(adap); -+ -+ if (!enable) { -+ dw_hdmi_write(cec, ~0, HDMI_CEC_MASK); -+ dw_hdmi_write(cec, ~0, HDMI_IH_MUTE_CEC_STAT0); -+ dw_hdmi_write(cec, 0, HDMI_CEC_POLARITY); -+ -+ cec->ops->disable(cec->hdmi); -+ } else { -+ unsigned int irqs; -+ -+ dw_hdmi_write(cec, 0, HDMI_CEC_CTRL); -+ dw_hdmi_write(cec, ~0, HDMI_IH_CEC_STAT0); -+ dw_hdmi_write(cec, 0, HDMI_CEC_LOCK); -+ -+ dw_hdmi_cec_log_addr(cec->adap, CEC_LOG_ADDR_INVALID); -+ -+ cec->ops->enable(cec->hdmi); -+ -+ irqs = CEC_STAT_ERROR_INIT | CEC_STAT_NACK | CEC_STAT_EOM | -+ CEC_STAT_DONE; -+ dw_hdmi_write(cec, irqs, HDMI_CEC_POLARITY); -+ dw_hdmi_write(cec, ~irqs, HDMI_CEC_MASK); -+ dw_hdmi_write(cec, ~irqs, HDMI_IH_MUTE_CEC_STAT0); -+ } -+ return 0; -+} -+ -+static const struct cec_adap_ops dw_hdmi_cec_ops = { -+ .adap_enable = dw_hdmi_cec_enable, -+ .adap_log_addr = dw_hdmi_cec_log_addr, -+ .adap_transmit = dw_hdmi_cec_transmit, -+}; -+ -+static void dw_hdmi_cec_del(void *data) -+{ -+ struct dw_hdmi_cec *cec = data; -+ -+ cec_delete_adapter(cec->adap); -+} -+ -+static int dw_hdmi_cec_probe(struct platform_device *pdev) -+{ -+ struct dw_hdmi_cec_data *data = dev_get_platdata(&pdev->dev); -+ struct dw_hdmi_cec *cec; -+ int ret; -+ -+ if (!data) -+ return -ENXIO; -+ -+ /* -+ * Our device is just a convenience - we want to link to the real -+ * hardware device here, so that userspace can see the association -+ * between the HDMI hardware and its associated CEC chardev. -+ */ -+ cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL); -+ if (!cec) -+ return -ENOMEM; -+ -+ cec->irq = data->irq; -+ cec->ops = data->ops; -+ cec->hdmi = data->hdmi; -+ -+ platform_set_drvdata(pdev, cec); -+ -+ dw_hdmi_write(cec, 0, HDMI_CEC_TX_CNT); -+ dw_hdmi_write(cec, ~0, HDMI_CEC_MASK); -+ dw_hdmi_write(cec, ~0, HDMI_IH_MUTE_CEC_STAT0); -+ dw_hdmi_write(cec, 0, HDMI_CEC_POLARITY); -+ -+ cec->adap = cec_allocate_adapter(&dw_hdmi_cec_ops, cec, "dw_hdmi", -+ CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT | -+ CEC_CAP_RC | CEC_CAP_PASSTHROUGH, -+ CEC_MAX_LOG_ADDRS); -+ if (IS_ERR(cec->adap)) -+ return PTR_ERR(cec->adap); -+ -+ /* override the module pointer */ -+ cec->adap->owner = THIS_MODULE; -+ -+ ret = devm_add_action(&pdev->dev, dw_hdmi_cec_del, cec); -+ if (ret) { -+ cec_delete_adapter(cec->adap); -+ return ret; -+ } -+ -+ ret = devm_request_threaded_irq(&pdev->dev, cec->irq, -+ dw_hdmi_cec_hardirq, -+ dw_hdmi_cec_thread, IRQF_SHARED, -+ "dw-hdmi-cec", cec->adap); -+ if (ret < 0) -+ return ret; -+ -+ cec->notify = cec_notifier_get(pdev->dev.parent); -+ if (!cec->notify) -+ return -ENOMEM; -+ -+ ret = cec_register_adapter(cec->adap, pdev->dev.parent); -+ if (ret < 0) { -+ cec_notifier_put(cec->notify); -+ return ret; -+ } -+ -+ /* -+ * CEC documentation says we must not call cec_delete_adapter -+ * after a successful call to cec_register_adapter(). -+ */ -+ devm_remove_action(&pdev->dev, dw_hdmi_cec_del, cec); -+ -+ cec_register_cec_notifier(cec->adap, cec->notify); -+ -+ return 0; -+} -+ -+static int dw_hdmi_cec_remove(struct platform_device *pdev) -+{ -+ struct dw_hdmi_cec *cec = platform_get_drvdata(pdev); -+ -+ cec_unregister_adapter(cec->adap); -+ cec_notifier_put(cec->notify); -+ -+ return 0; -+} -+ -+static struct platform_driver dw_hdmi_cec_driver = { -+ .probe = dw_hdmi_cec_probe, -+ .remove = dw_hdmi_cec_remove, -+ .driver = { -+ .name = "dw-hdmi-cec", -+ }, -+}; -+module_platform_driver(dw_hdmi_cec_driver); -+ -+MODULE_AUTHOR("Russell King "); -+MODULE_DESCRIPTION("Synopsys Designware HDMI CEC driver for i.MX"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS(PLATFORM_MODULE_PREFIX "dw-hdmi-cec"); -diff --git a/drivers/gpu/drm/bridge/dw-hdmi-cec.h b/drivers/gpu/drm/bridge/dw-hdmi-cec.h -new file mode 100644 -index 000000000000..cf4dc121a2c4 ---- /dev/null -+++ b/drivers/gpu/drm/bridge/dw-hdmi-cec.h -@@ -0,0 +1,19 @@ -+#ifndef DW_HDMI_CEC_H -+#define DW_HDMI_CEC_H -+ -+struct dw_hdmi; -+ -+struct dw_hdmi_cec_ops { -+ void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); -+ u8 (*read)(struct dw_hdmi *hdmi, int offset); -+ void (*enable)(struct dw_hdmi *hdmi); -+ void (*disable)(struct dw_hdmi *hdmi); -+}; -+ -+struct dw_hdmi_cec_data { -+ struct dw_hdmi *hdmi; -+ const struct dw_hdmi_cec_ops *ops; -+ int irq; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index 88561176dc03..460c43b4cd89 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -41,6 +41,7 @@ - #include "dw-hdmi.h" - #include "dw-hdmi-audio.h" - #include "dw-hdmi-hdcp.h" -+#include "dw-hdmi-cec.h" - - #include - -@@ -207,6 +208,7 @@ struct dw_hdmi { - unsigned int version; - - struct platform_device *audio; -+ struct platform_device *cec; - struct device *dev; - struct clk *isfr_clk; - struct clk *iahb_clk; -@@ -2344,7 +2346,6 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi) - hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK); - hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK); - hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK); -- hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK); - hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT); - hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT); - -@@ -2983,6 +2984,29 @@ static void dw_hdmi_destroy_properties(struct dw_hdmi *hdmi) - hdmi->plat_data->phy_data); - } - -+static void dw_hdmi_cec_enable(struct dw_hdmi *hdmi) -+{ -+ mutex_lock(&hdmi->mutex); -+ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE; -+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); -+ mutex_unlock(&hdmi->mutex); -+} -+ -+static void dw_hdmi_cec_disable(struct dw_hdmi *hdmi) -+{ -+ mutex_lock(&hdmi->mutex); -+ hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CECCLK_DISABLE; -+ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); -+ mutex_unlock(&hdmi->mutex); -+} -+ -+static const struct dw_hdmi_cec_ops dw_hdmi_cec_ops = { -+ .write = hdmi_writeb, -+ .read = hdmi_readb, -+ .enable = dw_hdmi_cec_enable, -+ .disable = dw_hdmi_cec_disable, -+}; -+ - static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi) - { - struct drm_encoder *encoder = hdmi->encoder; -@@ -3349,6 +3373,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, - struct device_node *np = dev->of_node; - struct platform_device_info pdevinfo; - struct device_node *ddc_node; -+ struct dw_hdmi_cec_data cec; - struct dw_hdmi *hdmi; - int ret; - u8 prod_id0; -@@ -3575,6 +3600,19 @@ int dw_hdmi_bind(struct device *dev, struct device *master, - hdmi->audio = platform_device_register_full(&pdevinfo); - } - -+ if (config0 & HDMI_CONFIG0_CEC) { -+ cec.hdmi = hdmi; -+ cec.ops = &dw_hdmi_cec_ops; -+ cec.irq = irq; -+ -+ pdevinfo.name = "dw-hdmi-cec"; -+ pdevinfo.data = &cec; -+ pdevinfo.size_data = sizeof(cec); -+ pdevinfo.dma_mask = 0; -+ -+ hdmi->cec = platform_device_register_full(&pdevinfo); -+ } -+ - dev_set_drvdata(dev, hdmi); - - dw_hdmi_register_debugfs(dev, hdmi); -@@ -3615,6 +3653,8 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data) - - if (hdmi->audio && !IS_ERR(hdmi->audio)) - platform_device_unregister(hdmi->audio); -+ if (!IS_ERR(hdmi->cec)) -+ platform_device_unregister(hdmi->cec); - - if (hdmi->hdcp_dev && !IS_ERR(hdmi->hdcp_dev)) - platform_device_unregister(hdmi->hdcp_dev); -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h -index 64aeac725f81..099b621f8ce3 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.h -+++ b/drivers/gpu/drm/bridge/dw-hdmi.h -@@ -598,6 +598,7 @@ enum { - - /* CONFIG0_ID field values */ - HDMI_CONFIG0_I2S = 0x10, -+ HDMI_CONFIG0_CEC = 0x02, - - /* CONFIG1_ID field values */ - HDMI_CONFIG1_AHB = 0x01, - -From 6624749e9e3d8956893d2da3690b7b8801b7323e Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Wed, 2 Aug 2017 20:41:08 +0200 -Subject: [PATCH 08/11] UPSTREAM: drm/bridge: dw-hdmi: remove CEC engine - register definitions - -We don't need the CEC engine register definitions, so let's remove them. - -Signed-off-by: Russell King -Acked-by: Hans Verkuil -Tested-by: Hans Verkuil -Tested-by: Laurent Pinchart -Signed-off-by: Archit Taneja -Link: https://patchwork.freedesktop.org/patch/msgid/20170802184108.7913-5-hverkuil@xs4all.nl -(cherry picked from commit 2356c573ba0eca736ec156b82ca6a6b37b8fe609) ---- - drivers/gpu/drm/bridge/dw-hdmi.c | 2 +- - drivers/gpu/drm/bridge/dw-hdmi.h | 45 ---------------------------------------- - 2 files changed, 1 insertion(+), 46 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index 460c43b4cd89..4d566383de83 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -3197,7 +3197,7 @@ static const struct dw_hdmi_reg_table hdmi_reg_table[] = { - {HDMI_A_HDCPCFG0, 0x52bb}, - {0x7800, 0x7818}, - {0x7900, 0x790e}, -- {HDMI_CEC_CTRL, HDMI_CEC_WKUPCTRL}, -+ {0x7d00, 0x7d31}, - {HDMI_I2CM_SLAVE, 0x7e31}, - }; - -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h -index 099b621f8ce3..ec7296e70247 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.h -+++ b/drivers/gpu/drm/bridge/dw-hdmi.h -@@ -520,51 +520,6 @@ - #define HDMI_A_PRESETUP 0x501A - #define HDMI_A_SRM_BASE 0x5020 - --/* CEC Engine Registers */ --#define HDMI_CEC_CTRL 0x7D00 --#define HDMI_CEC_STAT 0x7D01 --#define HDMI_CEC_MASK 0x7D02 --#define HDMI_CEC_POLARITY 0x7D03 --#define HDMI_CEC_INT 0x7D04 --#define HDMI_CEC_ADDR_L 0x7D05 --#define HDMI_CEC_ADDR_H 0x7D06 --#define HDMI_CEC_TX_CNT 0x7D07 --#define HDMI_CEC_RX_CNT 0x7D08 --#define HDMI_CEC_TX_DATA0 0x7D10 --#define HDMI_CEC_TX_DATA1 0x7D11 --#define HDMI_CEC_TX_DATA2 0x7D12 --#define HDMI_CEC_TX_DATA3 0x7D13 --#define HDMI_CEC_TX_DATA4 0x7D14 --#define HDMI_CEC_TX_DATA5 0x7D15 --#define HDMI_CEC_TX_DATA6 0x7D16 --#define HDMI_CEC_TX_DATA7 0x7D17 --#define HDMI_CEC_TX_DATA8 0x7D18 --#define HDMI_CEC_TX_DATA9 0x7D19 --#define HDMI_CEC_TX_DATA10 0x7D1a --#define HDMI_CEC_TX_DATA11 0x7D1b --#define HDMI_CEC_TX_DATA12 0x7D1c --#define HDMI_CEC_TX_DATA13 0x7D1d --#define HDMI_CEC_TX_DATA14 0x7D1e --#define HDMI_CEC_TX_DATA15 0x7D1f --#define HDMI_CEC_RX_DATA0 0x7D20 --#define HDMI_CEC_RX_DATA1 0x7D21 --#define HDMI_CEC_RX_DATA2 0x7D22 --#define HDMI_CEC_RX_DATA3 0x7D23 --#define HDMI_CEC_RX_DATA4 0x7D24 --#define HDMI_CEC_RX_DATA5 0x7D25 --#define HDMI_CEC_RX_DATA6 0x7D26 --#define HDMI_CEC_RX_DATA7 0x7D27 --#define HDMI_CEC_RX_DATA8 0x7D28 --#define HDMI_CEC_RX_DATA9 0x7D29 --#define HDMI_CEC_RX_DATA10 0x7D2a --#define HDMI_CEC_RX_DATA11 0x7D2b --#define HDMI_CEC_RX_DATA12 0x7D2c --#define HDMI_CEC_RX_DATA13 0x7D2d --#define HDMI_CEC_RX_DATA14 0x7D2e --#define HDMI_CEC_RX_DATA15 0x7D2f --#define HDMI_CEC_LOCK 0x7D30 --#define HDMI_CEC_WKUPCTRL 0x7D31 -- - /* I2C Master Registers (E-DDC) */ - #define HDMI_I2CM_SLAVE 0x7E00 - #define HDMI_I2CM_ADDRESS 0x7E01 - -From 3e49dcd2e042c5f0699068fd7a8830db0083ccd2 Mon Sep 17 00:00:00 2001 -From: Jose Abreu -Date: Thu, 14 Sep 2017 11:23:38 -0400 -Subject: [PATCH 09/11] UPSTREAM: media: cec: Respond to unregistered - initiators, when applicable - -commit 845d6524d69b40bd6abd61dc1264a8657159aa55 upstream. - -Running CEC 1.4 compliance test we get the following error on test -11.1.6.2: "ERROR: The DUT did not broadcast a - message to the unregistered device." - -Fix this by letting GIVE_PHYSICAL_ADDR message respond to unregistered -device. Also, GIVE_DEVICE_VENDOR_ID and GIVE_FEATURES fall in the -same category so, respond also to these messages. - -With this fix we pass CEC 1.4 official compliance. - -Signed-off-by: Jose Abreu -Cc: Joao Pinto -Signed-off-by: Hans Verkuil -Signed-off-by: Mauro Carvalho Chehab -Signed-off-by: Greg Kroah-Hartman - -(cherry picked from commit c2c3a6a57a9502ea57298a1b4e7d4dd7b73dd57a) ---- - drivers/media/cec/cec-adap.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c -index d596b601ff42..8cfc5e84a129 100644 ---- a/drivers/media/cec/cec-adap.c -+++ b/drivers/media/cec/cec-adap.c -@@ -1726,12 +1726,19 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, - */ - switch (msg->msg[1]) { - case CEC_MSG_GET_CEC_VERSION: -- case CEC_MSG_GIVE_DEVICE_VENDOR_ID: - case CEC_MSG_ABORT: - case CEC_MSG_GIVE_DEVICE_POWER_STATUS: -- case CEC_MSG_GIVE_PHYSICAL_ADDR: - case CEC_MSG_GIVE_OSD_NAME: -+ /* -+ * These messages reply with a directed message, so ignore if -+ * the initiator is Unregistered. -+ */ -+ if (!adap->passthrough && from_unregistered) -+ return 0; -+ /* Fall through */ -+ case CEC_MSG_GIVE_DEVICE_VENDOR_ID: - case CEC_MSG_GIVE_FEATURES: -+ case CEC_MSG_GIVE_PHYSICAL_ADDR: - /* - * Skip processing these messages if the passthrough mode - * is on. -@@ -1739,7 +1746,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, - if (adap->passthrough) - goto skip_processing; - /* Ignore if addressing is wrong */ -- if (is_broadcast || from_unregistered) -+ if (is_broadcast) - return 0; - break; - - -From e3b10b8065ec19cf5872dda50a5e35367184964e Mon Sep 17 00:00:00 2001 +From 4a4bfdbc39eb4e39c0f55a444d3d1206934daba3 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sat, 2 Sep 2017 16:23:11 +0200 -Subject: [PATCH 10/11] [media] rc/keymaps: initialize rc-cec early +Subject: [PATCH] [media] rc/keymaps: initialize rc-cec early --- drivers/media/rc/keymaps/rc-cec.c | 2 +- @@ -6395,20 +4450,20 @@ index 354c8e724b8e..fb0c2b1f3814 100644 MODULE_LICENSE("GPL"); -From 15819325692d09b314bcf79b5334543c00d3776b Mon Sep 17 00:00:00 2001 +From 1f1667ea20cca6e24161a9d3087849a467004af0 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sat, 2 Sep 2017 16:23:11 +0200 -Subject: [PATCH 11/11] drm/bridge: dw-hdmi: read edid on hpd event +Subject: [PATCH] drm/bridge: dw-hdmi: read edid on hpd event --- - drivers/gpu/drm/bridge/dw-hdmi.c | 24 +++++++++++++++++++----- - 1 file changed, 19 insertions(+), 5 deletions(-) + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index 4d566383de83..a20a25d6d370 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -2476,6 +2476,7 @@ static void dw_hdmi_bridge_nop(struct drm_bridge *bridge) +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 3616265dae0c..3afc51dfccf8 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -2451,6 +2451,7 @@ static void dw_hdmi_bridge_nop(struct drm_bridge *bridge) static enum drm_connector_status dw_hdmi_connector_detect(struct drm_connector *connector, bool force) { @@ -6416,7 +4471,7 @@ index 4d566383de83..a20a25d6d370 100644 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector); -@@ -2485,7 +2486,24 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) +@@ -2460,7 +2461,24 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) dw_hdmi_update_phy_mask(hdmi); mutex_unlock(&hdmi->mutex); @@ -6442,12 +4497,11 @@ index 4d566383de83..a20a25d6d370 100644 } static int dw_hdmi_connector_get_modes(struct drm_connector *connector) -@@ -2852,10 +2870,6 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) +@@ -2842,9 +2860,6 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) dw_hdmi_update_phy_mask(hdmi); } mutex_unlock(&hdmi->mutex); -- -- if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0) +- if (!(phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD))) - cec_notifier_set_phys_addr(hdmi->cec_notifier, - CEC_PHYS_ADDR_INVALID); } diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0004-audio.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0004-audio.patch index 0c1a32eba8..875b5c0fdc 100644 --- a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0004-audio.patch +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0004-audio.patch @@ -1,17 +1,1532 @@ -From bdebc59d2964ccd9bebcda4af71137c1c25bc912 Mon Sep 17 00:00:00 2001 +From c533e47da64de8edfaa7451bae673e2e736cd888 Mon Sep 17 00:00:00 2001 +From: Chris Zhong +Date: Mon, 18 Jul 2016 22:34:34 +0800 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: correct the spdif clk + +The spdif mclk should be 128 times of sample rate, and there is a +internal divider, the real rate of spdif mclk is mclk / (div + 1). +Hence, the original driver always get the good frequency for +48000/96000/44100/192000. But for 32000, the mclk is incorrect, +it should be 32000*128, but get 48000*128. Do not use the internal +divider here, just set all mclk to 128 * sample rate directly. + +Signed-off-by: Chris Zhong +Signed-off-by: Mark Brown +(cherry picked from commit 46dd2e28a90e48fbf1b7e253933fa3b7242e9b1b) +--- + sound/soc/rockchip/rockchip_spdif.c | 17 +---------------- + 1 file changed, 1 insertion(+), 16 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c +index 44b8c72e6a16..feaba2ad6022 100644 +--- a/sound/soc/rockchip/rockchip_spdif.c ++++ b/sound/soc/rockchip/rockchip_spdif.c +@@ -105,21 +105,7 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, + int ret; + + srate = params_rate(params); +- switch (srate) { +- case 32000: +- case 48000: +- case 96000: +- mclk = 96000 * 128; /* 12288000 hz */ +- break; +- case 44100: +- mclk = 44100 * 256; /* 11289600 hz */ +- break; +- case 192000: +- mclk = 192000 * 128; /* 24576000 hz */ +- break; +- default: +- return -EINVAL; +- } ++ mclk = srate * 128; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: +@@ -143,7 +129,6 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, + return ret; + } + +- val |= SPDIF_CFGR_CLK_DIV(mclk/(srate * 256)); + ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, + SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE | + SDPIF_CFGR_VDW_MASK, + +From 75e844a16be8b2d264b02cac8c6d9c3246acf7ca Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Wed, 7 Sep 2016 14:30:21 +0800 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: spdif: restore register during + runtime_suspend/resume cycle + +when step into runtime_suspend, spdif pd will be disabled and loss state. +so need to restore register when runtime_resume. + +Signed-off-by: Sugar Zhang +Signed-off-by: Mark Brown +(cherry picked from commit 3628c6987fb45d719cd963805bbba9f15017290e) +--- + sound/soc/rockchip/rockchip_spdif.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c +index feaba2ad6022..cac85a5538d5 100644 +--- a/sound/soc/rockchip/rockchip_spdif.c ++++ b/sound/soc/rockchip/rockchip_spdif.c +@@ -69,6 +69,7 @@ static int rk_spdif_runtime_suspend(struct device *dev) + { + struct rk_spdif_dev *spdif = dev_get_drvdata(dev); + ++ regcache_cache_only(spdif->regmap, true); + clk_disable_unprepare(spdif->mclk); + clk_disable_unprepare(spdif->hclk); + +@@ -92,7 +93,16 @@ static int rk_spdif_runtime_resume(struct device *dev) + return ret; + } + +- return 0; ++ regcache_cache_only(spdif->regmap, false); ++ regcache_mark_dirty(spdif->regmap); ++ ++ ret = regcache_sync(spdif->regmap); ++ if (ret) { ++ clk_disable_unprepare(spdif->mclk); ++ clk_disable_unprepare(spdif->hclk); ++ } ++ ++ return ret; + } + + static int rk_spdif_hw_params(struct snd_pcm_substream *substream, + +From 184f7ad17dddaa81ed86f1a384fa460290db9d24 Mon Sep 17 00:00:00 2001 +From: Arnaud Pouliquen +Date: Tue, 3 Jan 2017 16:52:50 +0100 +Subject: [PATCH] UPSTREAM: DRM: add help to get ELD speaker allocation + +Add helper to allow users to retrieve the speaker allocations without +knowledge of the ELD structure. + +Signed-off-by: Arnaud Pouliquen +Reviewed-by: Jani Nikula +Signed-off-by: Mark Brown +(cherry picked from commit c82dbe5c055e4d246bd07c4d7b24801c9445c241) +--- + include/drm/drm_edid.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h +index 85861b63e77a..55201e7e2ede 100644 +--- a/include/drm/drm_edid.h ++++ b/include/drm/drm_edid.h +@@ -254,6 +254,7 @@ struct detailed_timing { + # define DRM_ELD_AUD_SYNCH_DELAY_MAX 0xfa /* 500 ms */ + + #define DRM_ELD_SPEAKER 7 ++# define DRM_ELD_SPEAKER_MASK 0x7f + # define DRM_ELD_SPEAKER_RLRC (1 << 6) + # define DRM_ELD_SPEAKER_FLRC (1 << 5) + # define DRM_ELD_SPEAKER_RC (1 << 4) +@@ -417,6 +418,18 @@ static inline int drm_eld_size(const uint8_t *eld) + return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4; + } + ++/** ++ * drm_eld_get_spk_alloc - Get speaker allocation ++ * @eld: pointer to an ELD memory structure ++ * ++ * The returned value is the speakers mask. User has to use %DRM_ELD_SPEAKER ++ * field definitions to identify speakers. ++ */ ++static inline u8 drm_eld_get_spk_alloc(const uint8_t *eld) ++{ ++ return eld[DRM_ELD_SPEAKER] & DRM_ELD_SPEAKER_MASK; ++} ++ + struct edid *drm_do_get_edid(struct drm_connector *connector, + int (*get_edid_block)(void *data, u8 *buf, unsigned int block, + size_t len), + +From 9965339e8800af62ff283d264673ecf1a2aadc34 Mon Sep 17 00:00:00 2001 +From: Arnaud Pouliquen +Date: Tue, 3 Jan 2017 16:52:51 +0100 +Subject: [PATCH] UPSTREAM: ASoC: core: add optional pcm_new callback for DAI + driver + +During probe, DAIs can need to perform some actions that requests +the knowledge of the pcm runtime handle. +The callback is called during DAIs linking, after PCM device creation. +For instance this can be used to add relationship between a DAI pcm +control and the pcm device. + +Signed-off-by: Arnaud Pouliquen +Signed-off-by: Mark Brown +(cherry picked from commit 25f7b701c20db3e9ae09e28dd652949bd977e5cd) +--- + include/sound/soc-dai.h | 3 +++ + sound/soc/soc-core.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 31 insertions(+) + +diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h +index 212eaaf172ed..345e4f8ee93f 100644 +--- a/include/sound/soc-dai.h ++++ b/include/sound/soc-dai.h +@@ -230,6 +230,9 @@ struct snd_soc_dai_driver { + int (*resume)(struct snd_soc_dai *dai); + /* compress dai */ + int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num); ++ /* Optional Callback used at pcm creation*/ ++ int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, ++ struct snd_soc_dai *dai); + /* DAI is also used for the control bus */ + bool bus_control; + +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index 49263f3a50b0..c583022d7910 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1277,6 +1277,27 @@ static int soc_probe_dai(struct snd_soc_dai *dai, int order) + return 0; + } + ++static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais, ++ struct snd_soc_pcm_runtime *rtd) ++{ ++ int i, ret = 0; ++ ++ for (i = 0; i < num_dais; ++i) { ++ struct snd_soc_dai_driver *drv = dais[i]->driver; ++ ++ if (!rtd->dai_link->no_pcm && drv->pcm_new) ++ ret = drv->pcm_new(rtd, dais[i]); ++ if (ret < 0) { ++ dev_err(dais[i]->dev, ++ "ASoC: Failed to bind %s with pcm device\n", ++ dais[i]->name); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ + static int soc_link_dai_widgets(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link, + struct snd_soc_pcm_runtime *rtd) +@@ -1388,6 +1409,13 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) + dai_link->stream_name, ret); + return ret; + } ++ ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); ++ if (ret < 0) ++ return ret; ++ ret = soc_link_dai_pcm_new(rtd->codec_dais, ++ rtd->num_codecs, rtd); ++ if (ret < 0) ++ return ret; + } else { + INIT_DELAYED_WORK(&rtd->delayed_work, + codec2codec_close_delayed_work); + +From ccb05c9bfcb986d05f4247fea1178f541e8aad5c Mon Sep 17 00:00:00 2001 +From: Arnaud Pouliquen +Date: Tue, 3 Jan 2017 16:52:52 +0100 +Subject: [PATCH] UPSTREAM: ASoC: hdmi-codec: add channel mapping control + +Add user interface to provide channel mapping. +In a first step this control is read only. + +As TLV type, the control provides all configuration available for +HDMI sink(ELD), and provides current channel mapping selected by codec +based on ELD and number of channels specified by user on open. +When control is called before the number of the channel is specified +(i.e. hw_params is set), it returns all channels set to UNKNOWN. + +Signed-off-by: Arnaud Pouliquen +Signed-off-by: Mark Brown +(cherry picked from commit cd6111b26280a2f38a9fb8e6630c63a96477e4bf) +--- + sound/soc/codecs/hdmi-codec.c | 377 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 376 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c +index 028d60c196ae..cb78d8971b41 100644 +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -21,12 +21,264 @@ + #include + #include + #include ++#include + #include + #include + #include + + #include /* This is only to get MAX_ELD_BYTES */ + ++#define HDMI_CODEC_CHMAP_IDX_UNKNOWN -1 ++ ++struct hdmi_codec_channel_map_table { ++ unsigned char map; /* ALSA API channel map position */ ++ unsigned long spk_mask; /* speaker position bit mask */ ++}; ++ ++/* ++ * CEA speaker placement for HDMI 1.4: ++ * ++ * FL FLC FC FRC FR FRW ++ * ++ * LFE ++ * ++ * RL RLC RC RRC RR ++ * ++ * Speaker placement has to be extended to support HDMI 2.0 ++ */ ++enum hdmi_codec_cea_spk_placement { ++ FL = BIT(0), /* Front Left */ ++ FC = BIT(1), /* Front Center */ ++ FR = BIT(2), /* Front Right */ ++ FLC = BIT(3), /* Front Left Center */ ++ FRC = BIT(4), /* Front Right Center */ ++ RL = BIT(5), /* Rear Left */ ++ RC = BIT(6), /* Rear Center */ ++ RR = BIT(7), /* Rear Right */ ++ RLC = BIT(8), /* Rear Left Center */ ++ RRC = BIT(9), /* Rear Right Center */ ++ LFE = BIT(10), /* Low Frequency Effect */ ++}; ++ ++/* ++ * cea Speaker allocation structure ++ */ ++struct hdmi_codec_cea_spk_alloc { ++ const int ca_id; ++ unsigned int n_ch; ++ unsigned long mask; ++}; ++ ++/* Channel maps stereo HDMI */ ++const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = { ++ { .channels = 2, ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, ++ { } ++}; ++ ++/* Channel maps for multi-channel playbacks, up to 8 n_ch */ ++const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = { ++ { .channels = 2, /* CA_ID 0x00 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, ++ { .channels = 4, /* CA_ID 0x01 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA } }, ++ { .channels = 4, /* CA_ID 0x02 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC } }, ++ { .channels = 4, /* CA_ID 0x03 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC } }, ++ { .channels = 6, /* CA_ID 0x04 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 6, /* CA_ID 0x05 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 6, /* CA_ID 0x06 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 6, /* CA_ID 0x07 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 6, /* CA_ID 0x08 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, ++ { .channels = 6, /* CA_ID 0x09 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, ++ { .channels = 6, /* CA_ID 0x0A */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, ++ { .channels = 6, /* CA_ID 0x0B */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, ++ { .channels = 8, /* CA_ID 0x0C */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 8, /* CA_ID 0x0D */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 8, /* CA_ID 0x0E */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 8, /* CA_ID 0x0F */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 8, /* CA_ID 0x10 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, ++ { .channels = 8, /* CA_ID 0x11 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, ++ { .channels = 8, /* CA_ID 0x12 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, ++ { .channels = 8, /* CA_ID 0x13 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, ++ { .channels = 8, /* CA_ID 0x14 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x15 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x16 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x17 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x18 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x19 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1A */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1B */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1C */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1D */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1E */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1F */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { } ++}; ++ ++/* ++ * hdmi_codec_channel_alloc: speaker configuration available for CEA ++ * ++ * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct ++ * The preceding ones have better chances to be selected by ++ * hdmi_codec_get_ch_alloc_table_idx(). ++ */ ++static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { ++ { .ca_id = 0x00, .n_ch = 2, ++ .mask = FL | FR}, ++ /* 2.1 */ ++ { .ca_id = 0x01, .n_ch = 4, ++ .mask = FL | FR | LFE}, ++ /* Dolby Surround */ ++ { .ca_id = 0x02, .n_ch = 4, ++ .mask = FL | FR | FC }, ++ /* surround51 */ ++ { .ca_id = 0x0b, .n_ch = 6, ++ .mask = FL | FR | LFE | FC | RL | RR}, ++ /* surround40 */ ++ { .ca_id = 0x08, .n_ch = 6, ++ .mask = FL | FR | RL | RR }, ++ /* surround41 */ ++ { .ca_id = 0x09, .n_ch = 6, ++ .mask = FL | FR | LFE | RL | RR }, ++ /* surround50 */ ++ { .ca_id = 0x0a, .n_ch = 6, ++ .mask = FL | FR | FC | RL | RR }, ++ /* 6.1 */ ++ { .ca_id = 0x0f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | RC }, ++ /* surround71 */ ++ { .ca_id = 0x13, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC }, ++ /* others */ ++ { .ca_id = 0x03, .n_ch = 8, ++ .mask = FL | FR | LFE | FC }, ++ { .ca_id = 0x04, .n_ch = 8, ++ .mask = FL | FR | RC}, ++ { .ca_id = 0x05, .n_ch = 8, ++ .mask = FL | FR | LFE | RC }, ++ { .ca_id = 0x06, .n_ch = 8, ++ .mask = FL | FR | FC | RC }, ++ { .ca_id = 0x07, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RC }, ++ { .ca_id = 0x0c, .n_ch = 8, ++ .mask = FL | FR | RC | RL | RR }, ++ { .ca_id = 0x0d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RC }, ++ { .ca_id = 0x0e, .n_ch = 8, ++ .mask = FL | FR | FC | RL | RR | RC }, ++ { .ca_id = 0x10, .n_ch = 8, ++ .mask = FL | FR | RL | RR | RLC | RRC }, ++ { .ca_id = 0x11, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RLC | RRC }, ++ { .ca_id = 0x12, .n_ch = 8, ++ .mask = FL | FR | FC | RL | RR | RLC | RRC }, ++ { .ca_id = 0x14, .n_ch = 8, ++ .mask = FL | FR | FLC | FRC }, ++ { .ca_id = 0x15, .n_ch = 8, ++ .mask = FL | FR | LFE | FLC | FRC }, ++ { .ca_id = 0x16, .n_ch = 8, ++ .mask = FL | FR | FC | FLC | FRC }, ++ { .ca_id = 0x17, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | FLC | FRC }, ++ { .ca_id = 0x18, .n_ch = 8, ++ .mask = FL | FR | RC | FLC | FRC }, ++ { .ca_id = 0x19, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FLC | FRC }, ++ { .ca_id = 0x1a, .n_ch = 8, ++ .mask = FL | FR | RC | FC | FLC | FRC }, ++ { .ca_id = 0x1b, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FC | FLC | FRC }, ++ { .ca_id = 0x1c, .n_ch = 8, ++ .mask = FL | FR | RL | RR | FLC | FRC }, ++ { .ca_id = 0x1d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | FLC | FRC }, ++ { .ca_id = 0x1e, .n_ch = 8, ++ .mask = FL | FR | FC | RL | RR | FLC | FRC }, ++ { .ca_id = 0x1f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, ++}; ++ + struct hdmi_codec_priv { + struct hdmi_codec_pdata hcd; + struct snd_soc_dai_driver *daidrv; +@@ -41,6 +293,8 @@ struct hdmi_codec_priv { + struct notifier_block nb; + unsigned int jack_status; + unsigned int mode; ++ struct snd_pcm_chmap *chmap_info; ++ unsigned int chmap_idx; + }; + + static const struct snd_soc_dapm_widget hdmi_widgets[] = { +@@ -109,6 +363,83 @@ static int hdmi_audio_mode_put(struct snd_kcontrol *kcontrol, + return 0; + } + ++static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc) ++{ ++ int i; ++ const unsigned long hdmi_codec_eld_spk_alloc_bits[] = { ++ [0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR, ++ [4] = RC, [5] = FLC | FRC, [6] = RLC | RRC, ++ }; ++ unsigned long spk_mask = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) { ++ if (spk_alloc & (1 << i)) ++ spk_mask |= hdmi_codec_eld_spk_alloc_bits[i]; ++ } ++ ++ return spk_mask; ++} ++ ++void hdmi_codec_eld_chmap(struct hdmi_codec_priv *hcp) ++{ ++ u8 spk_alloc; ++ unsigned long spk_mask; ++ ++ spk_alloc = drm_eld_get_spk_alloc(hcp->eld); ++ spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc); ++ ++ /* Detect if only stereo supported, else return 8 channels mappings */ ++ if ((spk_mask & ~(FL | FR)) && hcp->chmap_info->max_channels > 2) ++ hcp->chmap_info->chmap = hdmi_codec_8ch_chmaps; ++ else ++ hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps; ++} ++ ++static int hdmi_codec_get_ch_alloc_table_idx(struct hdmi_codec_priv *hcp, ++ unsigned char channels) ++{ ++ int i; ++ u8 spk_alloc; ++ unsigned long spk_mask; ++ const struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc; ++ ++ spk_alloc = drm_eld_get_spk_alloc(hcp->eld); ++ spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc); ++ ++ for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) { ++ /* If spk_alloc == 0, HDMI is unplugged return stereo config*/ ++ if (!spk_alloc && cap->ca_id == 0) ++ return i; ++ if (cap->n_ch != channels) ++ continue; ++ if (!(cap->mask == (spk_mask & cap->mask))) ++ continue; ++ return i; ++ } ++ ++ return -EINVAL; ++} ++static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ unsigned const char *map; ++ unsigned int i; ++ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); ++ struct hdmi_codec_priv *hcp = info->private_data; ++ ++ map = info->chmap[hcp->chmap_idx].map; ++ ++ for (i = 0; i < info->max_channels; i++) { ++ if (hcp->chmap_idx == HDMI_CODEC_CHMAP_IDX_UNKNOWN) ++ ucontrol->value.integer.value[i] = 0; ++ else ++ ucontrol->value.integer.value[i] = map[i]; ++ } ++ ++ return 0; ++} ++ ++ + static const struct snd_kcontrol_new hdmi_controls[] = { + { + .access = SNDRV_CTL_ELEM_ACCESS_READ | +@@ -184,6 +515,9 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, + ret = snd_pcm_hw_constraint_eld(substream->runtime, + hcp->eld); + mutex_unlock(&hcp->eld_lock); ++ ++ /* Select chmap supported */ ++ hdmi_codec_eld_chmap(hcp); + } + return ret; + } +@@ -201,6 +535,7 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, + + WARN_ON(hcp->current_stream != substream); + ++ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; + hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data); + + mutex_lock(&hcp->current_stream_lock); +@@ -221,7 +556,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, + .dig_subframe = { 0 }, + } + }; +- int ret; ++ int ret, idx; + + dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__, + params_width(params), params_rate(params), +@@ -248,6 +583,17 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, + hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; + hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; + ++ /* Select a channel allocation that matches with ELD and pcm channels */ ++ idx = hdmi_codec_get_ch_alloc_table_idx(hcp, hp.cea.channels); ++ if (idx < 0) { ++ dev_err(dai->dev, "Not able to map channels to speakers (%d)\n", ++ idx); ++ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; ++ return idx; ++ } ++ hp.cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id; ++ hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id; ++ + hp.sample_width = params_width(params); + hp.sample_rate = params_rate(params); + hp.channels = params_channels(params); +@@ -377,6 +723,32 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = { + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) + ++static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, ++ struct snd_soc_dai *dai) ++{ ++ struct snd_soc_dai_driver *drv = dai->driver; ++ struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); ++ int ret; ++ ++ dev_dbg(dai->dev, "%s()\n", __func__); ++ ++ ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK, ++ NULL, drv->playback.channels_max, 0, ++ &hcp->chmap_info); ++ if (ret < 0) ++ return ret; ++ ++ /* override handlers */ ++ hcp->chmap_info->private_data = hcp; ++ hcp->chmap_info->kctl->get = hdmi_codec_chmap_ctl_get; ++ ++ /* default chmap supported is stereo */ ++ hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps; ++ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; ++ ++ return 0; ++} ++ + static struct snd_soc_dai_driver hdmi_i2s_dai = { + .name = "i2s-hifi", + .id = DAI_ID_I2S, +@@ -389,6 +761,7 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = { + .sig_bits = 24, + }, + .ops = &hdmi_dai_ops, ++ .pcm_new = hdmi_codec_pcm_new, + }; + + static const struct snd_soc_dai_driver hdmi_spdif_dai = { +@@ -402,6 +775,7 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = { + .formats = SPDIF_FORMATS, + }, + .ops = &hdmi_dai_ops, ++ .pcm_new = hdmi_codec_pcm_new, + }; + + static struct snd_soc_codec_driver hdmi_codec = { +@@ -534,6 +908,7 @@ static int hdmi_codec_remove(struct platform_device *pdev) + { + struct hdmi_codec_priv *hcp = platform_get_drvdata(pdev); + ++ kfree(hcp->chmap_info); + hdmi_unregister_notifier(&hcp->nb); + snd_soc_unregister_codec(&pdev->dev); + return 0; + +From dfa634f7fa86acf2ea9d5343ddfaf8f928f05a9d Mon Sep 17 00:00:00 2001 +From: Christophe Jaillet +Date: Thu, 15 Jun 2017 07:53:11 +0200 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: Fix an error handling in + 'rockchip_i2s_probe' + +If this memory allocation fail, we must disable what has been enabled. +Do not return immediately but go thrue the error handling path instead. + +Also use 'devm_kmemdup' instead of 'devm_kzalloc+memcpy' to simplify code. + +Signed-off-by: Christophe JAILLET +Signed-off-by: Mark Brown +(cherry picked from commit c3a3d3c41b74b05267bab6173f2a8224a1443ba6) +--- + sound/soc/rockchip/rockchip_i2s.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 7687368779db..5a3436351efb 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -658,12 +658,13 @@ static int rockchip_i2s_probe(struct platform_device *pdev) + goto err_pm_disable; + } + +- soc_dai = devm_kzalloc(&pdev->dev, ++ soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai, + sizeof(*soc_dai), GFP_KERNEL); +- if (!soc_dai) +- return -ENOMEM; ++ if (!soc_dai) { ++ ret = -ENOMEM; ++ goto err_pm_disable; ++ } + +- memcpy(soc_dai, &rockchip_i2s_dai, sizeof(*soc_dai)); + if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { + if (val >= 2 && val <= 8) + soc_dai->playback.channels_max = val; + +From 2ec7b817abc647335792094109c346d66d2551be Mon Sep 17 00:00:00 2001 +From: Markus Elfring +Date: Thu, 10 Aug 2017 18:38:09 +0200 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: Delete an error message for a + failed memory allocation in rockchip_i2s_probe() + +Omit an extra message for a memory allocation failure in this function. + +This issue was detected by using the Coccinelle software. + +Link: http://events.linuxfoundation.org/sites/events/files/slides/LCJ16-Refactor_Strings-WSang_0.pdf +Signed-off-by: Markus Elfring +Signed-off-by: Mark Brown +(cherry picked from commit b48b2710913d583ff93c365413532e1a7cd60d84) +--- + sound/soc/rockchip/rockchip_i2s.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 5a3436351efb..1da10e79a1bb 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -594,10 +594,8 @@ static int rockchip_i2s_probe(struct platform_device *pdev) + int val; + + i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); +- if (!i2s) { +- dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n"); ++ if (!i2s) + return -ENOMEM; +- } + + i2s->dev = &pdev->dev; + + +From 2ce2fd399b40c0bbb1aad13344f4b79050a763ad Mon Sep 17 00:00:00 2001 +From: John Keeping +Date: Thu, 14 Sep 2017 16:58:55 +0100 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: i2s: fix unbalanced clk_disable + +mclk is enabled and disabled only in i2s_runtime_{resume,suspend}() and +we ensure that the device is runtime suspended before reaching this +clk_disable_unprepare() call, so it is wrong to call it again here. + +Signed-off-by: John Keeping +Signed-off-by: Mark Brown +(cherry picked from commit 32debfcd3ff0939c93238ddde03ffcc96cca5c60) +--- + sound/soc/rockchip/rockchip_i2s.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 1da10e79a1bb..f131dba7645d 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -713,7 +713,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev) + if (!pm_runtime_status_suspended(&pdev->dev)) + i2s_runtime_suspend(&pdev->dev); + +- clk_disable_unprepare(i2s->mclk); + clk_disable_unprepare(i2s->hclk); + + return 0; + +From 1fd8ed3e609084541a9343468e54d6b675377f93 Mon Sep 17 00:00:00 2001 +From: Stefan Potyra +Date: Wed, 6 Dec 2017 16:03:24 +0100 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: disable clock on error + +Disable the clocks in rk_spdif_probe when an error occurs after one +of the clocks has been enabled previously. + +Found by Linux Driver Verification project (linuxtesting.org). + +Fixes: f874b80e1571 ASoC: rockchip: Add rockchip SPDIF transceiver driver +Signed-off-by: Stefan Potyra +Signed-off-by: Mark Brown +(cherry picked from commit c7b92172a61b91936be985cb9bc499a4ebc6489b) +--- + sound/soc/rockchip/rockchip_spdif.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c +index cac85a5538d5..6ff8b195acf4 100644 +--- a/sound/soc/rockchip/rockchip_spdif.c ++++ b/sound/soc/rockchip/rockchip_spdif.c +@@ -322,26 +322,30 @@ static int rk_spdif_probe(struct platform_device *pdev) + spdif->mclk = devm_clk_get(&pdev->dev, "mclk"); + if (IS_ERR(spdif->mclk)) { + dev_err(&pdev->dev, "Can't retrieve rk_spdif master clock\n"); +- return PTR_ERR(spdif->mclk); ++ ret = PTR_ERR(spdif->mclk); ++ goto err_disable_hclk; + } + + ret = clk_prepare_enable(spdif->mclk); + if (ret) { + dev_err(spdif->dev, "clock enable failed %d\n", ret); +- return ret; ++ goto err_disable_clocks; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + regs = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(regs)) +- return PTR_ERR(regs); ++ if (IS_ERR(regs)) { ++ ret = PTR_ERR(regs); ++ goto err_disable_clocks; ++ } + + spdif->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "hclk", regs, + &rk_spdif_regmap_config); + if (IS_ERR(spdif->regmap)) { + dev_err(&pdev->dev, + "Failed to initialise managed register map\n"); +- return PTR_ERR(spdif->regmap); ++ ret = PTR_ERR(spdif->regmap); ++ goto err_disable_clocks; + } + + spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR; +@@ -373,6 +377,10 @@ static int rk_spdif_probe(struct platform_device *pdev) + + err_pm_runtime: + pm_runtime_disable(&pdev->dev); ++err_disable_clocks: ++ clk_disable_unprepare(spdif->mclk); ++err_disable_hclk: ++ clk_disable_unprepare(spdif->hclk); + + return ret; + } + +From 421ce8b8057331617a93c37b7f14199bac36f2c1 Mon Sep 17 00:00:00 2001 +From: John Keeping +Date: Mon, 8 Jan 2018 16:01:04 +0000 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: i2s: fix playback after runtime + resume + +When restoring registers during runtime resume, we must not write to +I2S_TXDR which is the transmit FIFO as this queues up a sample to be +output and pushes all of the output channels down by one. + +This can be demonstrated with the speaker-test utility: + + for i in a b c; do speaker-test -c 2 -s 1; done + +which should play a test through the left speaker three times but if the +I2S hardware starts runtime suspended the first sample will be played +through the right speaker. + +Fix this by marking I2S_TXDR as volatile (which also requires marking it +as readble, even though it technically isn't). This seems to be the +most robust fix, the alternative of giving I2S_TXDR a default value is +more fragile since it does not prevent regcache writing to the register +in all circumstances. + +While here, also fix the configuration of I2S_RXDR and I2S_FIFOLR; these +are not writable so they do not suffer from the same problem as I2S_TXDR +but reading from I2S_RXDR does suffer from a similar problem. + +Fixes: f0447f6cbb20 ("ASoC: rockchip: i2s: restore register during runtime_suspend/resume cycle", 2016-09-07) +Signed-off-by: John Keeping +(cherry picked from commit c66234cfedfc3e6e3b62563a5f2c1562be09a35d) +--- + sound/soc/rockchip/rockchip_i2s.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index f131dba7645d..0b9bb973b5a7 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -514,6 +514,7 @@ static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg) + case I2S_INTCR: + case I2S_XFER: + case I2S_CLR: ++ case I2S_TXDR: + case I2S_RXDR: + case I2S_FIFOLR: + case I2S_INTSR: +@@ -528,6 +529,9 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) + switch (reg) { + case I2S_INTSR: + case I2S_CLR: ++ case I2S_FIFOLR: ++ case I2S_TXDR: ++ case I2S_RXDR: + return true; + default: + return false; +@@ -537,6 +541,8 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) + static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg) + { + switch (reg) { ++ case I2S_RXDR: ++ return true; + default: + return false; + } + +From fccd2e78a518d2f396e684b9f77d4b6c1ee805c8 Mon Sep 17 00:00:00 2001 +From: Romain Perier +Date: Fri, 14 Apr 2017 10:31:12 +0200 +Subject: [PATCH] UPSTREAM: drm: dw-hdmi: add specific I2S and AHB functions + for stream handling + +Currently, CTS+N is forced to zero as a workaround of the IP block for +i.MX platforms. This is requested in the datasheet of the corresponding +IP for AHB mode only. However, we have seen that it introduces glitches +or delays when playing a sound on HDMI for I2S mode. This proves that we +cannot keep the current functions for handling audio stream as-is if +these contain workaround that are specific to a mode. + +This commit introduces two callbacks, one for each variant. +dw_hdmi_setup defines the right function depending on the detected +variant. Then, the exported functions dw_hdmi_audio_enable and +dw_hdmi_audio_disable calls the corresponding callbacks + +Reviewed-by: Neil Armstrong +Signed-off-by: Romain Perier +Signed-off-by: Archit Taneja +Link: http://patchwork.freedesktop.org/patch/msgid/20170414083113.4255-2-romain.perier@collabora.com +(cherry picked from commit a7d555d2f2bd675d641e742a202a5e4b37d4d019) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 26 ++++++++++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 3616265dae0c..ca4d64253757 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -261,6 +261,8 @@ struct dw_hdmi { + + void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); + u8 (*read)(struct dw_hdmi *hdmi, int offset); ++ void (*enable_audio)(struct dw_hdmi *hdmi); ++ void (*disable_audio)(struct dw_hdmi *hdmi); + }; + + #define HDMI_IH_PHY_STAT0_RX_SENSE \ +@@ -811,13 +813,29 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) + } + EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); + ++static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi) ++{ ++ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); ++} ++ ++static void dw_hdmi_ahb_audio_disable(struct dw_hdmi *hdmi) ++{ ++ hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); ++} ++ ++static void dw_hdmi_i2s_audio_enable(struct dw_hdmi *hdmi) ++{ ++ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); ++} ++ + void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) + { + unsigned long flags; + + spin_lock_irqsave(&hdmi->audio_lock, flags); + hdmi->audio_enable = true; +- hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); ++ if (hdmi->enable_audio) ++ hdmi->enable_audio(hdmi); + spin_unlock_irqrestore(&hdmi->audio_lock, flags); + } + EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable); +@@ -828,7 +846,8 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi) + + spin_lock_irqsave(&hdmi->audio_lock, flags); + hdmi->audio_enable = false; +- hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); ++ if (hdmi->disable_audio) ++ hdmi->disable_audio(hdmi); + spin_unlock_irqrestore(&hdmi->audio_lock, flags); + } + EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable); +@@ -3627,6 +3646,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master, + audio.irq = irq; + audio.hdmi = hdmi; + audio.eld = hdmi->connector.eld; ++ hdmi->enable_audio = dw_hdmi_ahb_audio_enable; ++ hdmi->disable_audio = dw_hdmi_ahb_audio_disable; + + pdevinfo.name = "dw-hdmi-ahb-audio"; + pdevinfo.data = &audio; +@@ -3640,6 +3661,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, + audio.write = hdmi_writeb; + audio.read = hdmi_readb; + audio.mod = hdmi_modb; ++ hdmi->enable_audio = dw_hdmi_i2s_audio_enable; + + pdevinfo.name = "dw-hdmi-i2s-audio"; + pdevinfo.data = &audio; + +From 5b3a2d7e71e94b7df6c9e88a72d9f17c8c177f3c Mon Sep 17 00:00:00 2001 +From: Romain Perier +Date: Thu, 20 Apr 2017 14:34:34 +0530 +Subject: [PATCH] UPSTREAM: drm: dw-hdmi: gate audio clock from the I2S + enablement callbacks + +Currently, the audio sampler clock is enabled from dw_hdmi_setup() at +step E. and is kept enabled for later use. This clock should be enabled +and disabled along with the actual audio stream and not always on (that +is bad for PM). Furthermore, as described by the datasheet, the I2S +variant needs to gate/ungate the clock when the stream is +enabled/disabled. + +This commit adds a parameter to hdmi_audio_enable_clk() that controls +when the audio sample clock must be enabled or disabled. Then, it adds +the call to this function from dw_hdmi_i2s_audio_enable() and +dw_hdmi_i2s_audio_disable(). + +Reviewed-by: Neil Armstrong +Signed-off-by: Romain Perier +Link: http://patchwork.freedesktop.org/patch/msgid/20170414083113.4255-3-romain.perier@collabora.com +Signed-off-by: Archit Taneja +(cherry picked from commit 57fbc05585a9c841c910677228f1e3f8a3a62801) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index ca4d64253757..01965c4e7128 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -813,6 +813,15 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) + } + EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); + ++static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable) ++{ ++ if (enable) ++ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE; ++ else ++ hdmi->mc_clkdis |= HDMI_MC_CLKDIS_AUDCLK_DISABLE; ++ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); ++} ++ + static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi) + { + hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); +@@ -826,6 +835,12 @@ static void dw_hdmi_ahb_audio_disable(struct dw_hdmi *hdmi) + static void dw_hdmi_i2s_audio_enable(struct dw_hdmi *hdmi) + { + hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); ++ hdmi_enable_audio_clk(hdmi, true); ++} ++ ++static void dw_hdmi_i2s_audio_disable(struct dw_hdmi *hdmi) ++{ ++ hdmi_enable_audio_clk(hdmi, false); + } + + void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) +@@ -2124,12 +2139,6 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) + HDMI_MC_FLOWCTRL); + } + +-static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi) +-{ +- hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE; +- hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); +-} +- + /* Workaround to clear the overflow condition */ + static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) + { +@@ -2281,7 +2290,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + + /* HDMI Initialization Step E - Configure audio */ + hdmi_clk_regenerator_update_pixel_clock(hdmi); +- hdmi_enable_audio_clk(hdmi); ++ hdmi_enable_audio_clk(hdmi, true); + } + + /* not for DVI mode */ +@@ -3662,6 +3671,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, + audio.read = hdmi_readb; + audio.mod = hdmi_modb; + hdmi->enable_audio = dw_hdmi_i2s_audio_enable; ++ hdmi->disable_audio = dw_hdmi_i2s_audio_disable; + + pdevinfo.name = "dw-hdmi-i2s-audio"; + pdevinfo.data = &audio; + +From 81fb01490b055b58d3695c064b2761ac4d4681d2 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 7 Aug 2017 22:24:15 +0200 +Subject: [PATCH] drm: dw-hdmi-i2s: sync with upstream + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | 1 - + drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 20 +++++++++++++------- + 2 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +index d3194b4e186b..b9e839f4151a 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +@@ -13,7 +13,6 @@ struct dw_hdmi_audio_data { + + struct dw_hdmi_i2s_audio_data { + struct dw_hdmi *hdmi; +- struct platform_device *pdev; + + void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); + u8 (*read)(struct dw_hdmi *hdmi, int offset); +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +index f1f62d8c1d16..5ff993a35ab6 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +@@ -16,7 +16,8 @@ + + #define DRIVER_NAME "dw-hdmi-i2s-audio" + +-static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio, u8 val, int offset) ++static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio, ++ u8 val, int offset) + { + struct dw_hdmi *hdmi = audio->hdmi; + +@@ -220,6 +221,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) + struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data; + struct platform_device_info pdevinfo; + struct hdmi_codec_pdata pdata; ++ struct platform_device *platform; + + pdata.ops = &dw_hdmi_i2s_ops; + pdata.i2s = 1; +@@ -234,23 +236,27 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) + pdevinfo.size_data = sizeof(pdata); + pdevinfo.dma_mask = DMA_BIT_MASK(32); + +- audio->pdev = platform_device_register_full(&pdevinfo); +- return IS_ERR_OR_NULL(audio->pdev); ++ platform = platform_device_register_full(&pdevinfo); ++ if (IS_ERR(platform)) ++ return PTR_ERR(platform); ++ ++ dev_set_drvdata(&pdev->dev, platform); ++ ++ return 0; + } + + static int snd_dw_hdmi_remove(struct platform_device *pdev) + { +- struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data; ++ struct platform_device *platform = dev_get_drvdata(&pdev->dev); + +- if (!IS_ERR_OR_NULL(audio->pdev)) +- platform_device_unregister(audio->pdev); ++ platform_device_unregister(platform); + + return 0; + } + + static struct platform_driver snd_dw_hdmi_driver = { + .probe = snd_dw_hdmi_probe, +- .remove = snd_dw_hdmi_remove, ++ .remove = snd_dw_hdmi_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + +From 84857277755016550e30b9c4d2021ea7e699bb54 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 2 Apr 2017 11:33:39 +0200 +Subject: [PATCH] drm: dw-hdmi-i2s: implement get_eld + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | 1 + + drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 12 ++++++++++++ + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 + + 3 files changed, 14 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +index b9e839f4151a..e75f458ef4df 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +@@ -13,6 +13,7 @@ struct dw_hdmi_audio_data { + + struct dw_hdmi_i2s_audio_data { + struct dw_hdmi *hdmi; ++ u8 *eld; + + void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); + u8 (*read)(struct dw_hdmi *hdmi, int offset); +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +index 5ff993a35ab6..e7312571e2cb 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +@@ -11,6 +11,8 @@ + + #include + ++#include /* This is only to get MAX_ELD_BYTES */ ++ + #include "dw-hdmi.h" + #include "dw-hdmi-audio.h" + +@@ -211,9 +213,19 @@ static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data) + hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); + } + ++static int dw_hdmi_i2s_get_eld(struct device *dev, void *data, u8 *buf, size_t len) ++{ ++ struct dw_hdmi_i2s_audio_data *audio = data; ++ ++ memcpy(buf, audio->eld, min(len, (size_t)MAX_ELD_BYTES)); ++ ++ return 0; ++} ++ + static struct hdmi_codec_ops dw_hdmi_i2s_ops = { + .hw_params = dw_hdmi_i2s_hw_params, + .audio_shutdown = dw_hdmi_i2s_audio_shutdown, ++ .get_eld = dw_hdmi_i2s_get_eld, + }; + + static int snd_dw_hdmi_probe(struct platform_device *pdev) +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 01965c4e7128..b9ec4a024276 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -3670,6 +3670,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, + audio.write = hdmi_writeb; + audio.read = hdmi_readb; + audio.mod = hdmi_modb; ++ audio.eld = hdmi->connector.eld; + hdmi->enable_audio = dw_hdmi_i2s_audio_enable; + hdmi->disable_audio = dw_hdmi_i2s_audio_disable; + + +From ae58251c3608aebf3e01ebbff8749d3424265702 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 17 Apr 2017 13:09:16 +0200 +Subject: [PATCH] drm: dw-hdmi-i2s: configure channel allocation + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +index e7312571e2cb..1d4570e3fbed 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +@@ -188,7 +188,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, + hdmi_write(audio, 0x00, HDMI_FC_AUDICONF1); + + /* Set Channel Allocation */ +- hdmi_write(audio, 0x00, HDMI_FC_AUDICONF2); ++ hdmi_write(audio, hparms->cea.channel_allocation, HDMI_FC_AUDICONF2); + + /* Set LFEPBLDOWN-MIX INH and LSV */ + hdmi_write(audio, 0x00, HDMI_FC_AUDICONF3); + +From 0ec4060f98de2f10639b400b4538bfd5ed6e4da6 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 2 May 2017 18:57:19 +0200 +Subject: [PATCH] ASoC: hdmi-codec: fix I2S audio in Kodi + +--- + sound/soc/codecs/hdmi-codec.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c +index cb78d8971b41..9ebca57014e4 100644 +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -758,7 +758,6 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = { + .channels_max = 8, + .rates = HDMI_RATES, + .formats = I2S_FORMATS, +- .sig_bits = 24, + }, + .ops = &hdmi_dai_ops, + .pcm_new = hdmi_codec_pcm_new, + +From 152015324ec711e9af13e9ab12d8a6aaf3f1a2f2 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 14 Aug 2017 00:14:05 +0200 +Subject: [PATCH] ASoC: hdmi-codec: reorder channel map + +--- + sound/soc/codecs/hdmi-codec.c | 113 +++++++++++++++++++----------------------- + 1 file changed, 52 insertions(+), 61 deletions(-) + +diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c +index 9ebca57014e4..e65060ae8ffc 100644 +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -205,78 +205,69 @@ const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = { + */ + static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { + { .ca_id = 0x00, .n_ch = 2, +- .mask = FL | FR}, +- /* 2.1 */ +- { .ca_id = 0x01, .n_ch = 4, +- .mask = FL | FR | LFE}, +- /* Dolby Surround */ ++ .mask = FL | FR }, ++ { .ca_id = 0x03, .n_ch = 4, ++ .mask = FL | FR | LFE | FC }, + { .ca_id = 0x02, .n_ch = 4, + .mask = FL | FR | FC }, +- /* surround51 */ ++ { .ca_id = 0x01, .n_ch = 4, ++ .mask = FL | FR | LFE }, + { .ca_id = 0x0b, .n_ch = 6, +- .mask = FL | FR | LFE | FC | RL | RR}, +- /* surround40 */ +- { .ca_id = 0x08, .n_ch = 6, +- .mask = FL | FR | RL | RR }, +- /* surround41 */ +- { .ca_id = 0x09, .n_ch = 6, +- .mask = FL | FR | LFE | RL | RR }, +- /* surround50 */ ++ .mask = FL | FR | LFE | FC | RL | RR }, + { .ca_id = 0x0a, .n_ch = 6, + .mask = FL | FR | FC | RL | RR }, +- /* 6.1 */ +- { .ca_id = 0x0f, .n_ch = 8, +- .mask = FL | FR | LFE | FC | RL | RR | RC }, +- /* surround71 */ ++ { .ca_id = 0x09, .n_ch = 6, ++ .mask = FL | FR | LFE | RL | RR }, ++ { .ca_id = 0x08, .n_ch = 6, ++ .mask = FL | FR | RL | RR }, ++ { .ca_id = 0x07, .n_ch = 6, ++ .mask = FL | FR | LFE | FC | RC }, ++ { .ca_id = 0x06, .n_ch = 6, ++ .mask = FL | FR | FC | RC }, ++ { .ca_id = 0x05, .n_ch = 6, ++ .mask = FL | FR | LFE | RC }, ++ { .ca_id = 0x04, .n_ch = 6, ++ .mask = FL | FR | RC }, + { .ca_id = 0x13, .n_ch = 8, + .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC }, +- /* others */ +- { .ca_id = 0x03, .n_ch = 8, +- .mask = FL | FR | LFE | FC }, +- { .ca_id = 0x04, .n_ch = 8, +- .mask = FL | FR | RC}, +- { .ca_id = 0x05, .n_ch = 8, +- .mask = FL | FR | LFE | RC }, +- { .ca_id = 0x06, .n_ch = 8, +- .mask = FL | FR | FC | RC }, +- { .ca_id = 0x07, .n_ch = 8, +- .mask = FL | FR | LFE | FC | RC }, +- { .ca_id = 0x0c, .n_ch = 8, +- .mask = FL | FR | RC | RL | RR }, +- { .ca_id = 0x0d, .n_ch = 8, +- .mask = FL | FR | LFE | RL | RR | RC }, +- { .ca_id = 0x0e, .n_ch = 8, +- .mask = FL | FR | FC | RL | RR | RC }, +- { .ca_id = 0x10, .n_ch = 8, +- .mask = FL | FR | RL | RR | RLC | RRC }, +- { .ca_id = 0x11, .n_ch = 8, +- .mask = FL | FR | LFE | RL | RR | RLC | RRC }, ++ { .ca_id = 0x1f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, + { .ca_id = 0x12, .n_ch = 8, + .mask = FL | FR | FC | RL | RR | RLC | RRC }, +- { .ca_id = 0x14, .n_ch = 8, +- .mask = FL | FR | FLC | FRC }, +- { .ca_id = 0x15, .n_ch = 8, +- .mask = FL | FR | LFE | FLC | FRC }, +- { .ca_id = 0x16, .n_ch = 8, +- .mask = FL | FR | FC | FLC | FRC }, +- { .ca_id = 0x17, .n_ch = 8, +- .mask = FL | FR | LFE | FC | FLC | FRC }, +- { .ca_id = 0x18, .n_ch = 8, +- .mask = FL | FR | RC | FLC | FRC }, +- { .ca_id = 0x19, .n_ch = 8, +- .mask = FL | FR | LFE | RC | FLC | FRC }, +- { .ca_id = 0x1a, .n_ch = 8, +- .mask = FL | FR | RC | FC | FLC | FRC }, +- { .ca_id = 0x1b, .n_ch = 8, +- .mask = FL | FR | LFE | RC | FC | FLC | FRC }, +- { .ca_id = 0x1c, .n_ch = 8, +- .mask = FL | FR | RL | RR | FLC | FRC }, +- { .ca_id = 0x1d, .n_ch = 8, +- .mask = FL | FR | LFE | RL | RR | FLC | FRC }, + { .ca_id = 0x1e, .n_ch = 8, + .mask = FL | FR | FC | RL | RR | FLC | FRC }, +- { .ca_id = 0x1f, .n_ch = 8, +- .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, ++ { .ca_id = 0x11, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RLC | RRC }, ++ { .ca_id = 0x1d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | FLC | FRC }, ++ { .ca_id = 0x10, .n_ch = 8, ++ .mask = FL | FR | RL | RR | RLC | RRC }, ++ { .ca_id = 0x1c, .n_ch = 8, ++ .mask = FL | FR | RL | RR | FLC | FRC }, ++ { .ca_id = 0x0f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | RC }, ++ { .ca_id = 0x1b, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FC | FLC | FRC }, ++ { .ca_id = 0x0e, .n_ch = 8, ++ .mask = FL | FR | FC | RL | RR | RC }, ++ { .ca_id = 0x1a, .n_ch = 8, ++ .mask = FL | FR | RC | FC | FLC | FRC }, ++ { .ca_id = 0x0d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RC }, ++ { .ca_id = 0x19, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FLC | FRC }, ++ { .ca_id = 0x0c, .n_ch = 8, ++ .mask = FL | FR | RC | RL | RR }, ++ { .ca_id = 0x18, .n_ch = 8, ++ .mask = FL | FR | RC | FLC | FRC }, ++ { .ca_id = 0x17, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | FLC | FRC }, ++ { .ca_id = 0x16, .n_ch = 8, ++ .mask = FL | FR | FC | FLC | FRC }, ++ { .ca_id = 0x15, .n_ch = 8, ++ .mask = FL | FR | LFE | FLC | FRC }, ++ { .ca_id = 0x14, .n_ch = 8, ++ .mask = FL | FR | FLC | FRC }, + }; + + struct hdmi_codec_priv { + +From f46805059adc970ca913cf200174de4d4a35c754 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 27 Aug 2017 23:32:40 +0200 +Subject: [PATCH] ASoC: codecs: rk3328: limit to working rates + +--- + sound/soc/codecs/rk3328_codec.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c +index af1b7429b6d4..d0b4578ffa0e 100644 +--- a/sound/soc/codecs/rk3328_codec.c ++++ b/sound/soc/codecs/rk3328_codec.c +@@ -354,7 +354,12 @@ static struct snd_soc_dai_driver rk3328_dai[] = { + .stream_name = "HIFI Playback", + .channels_min = 1, + .channels_max = 2, +- .rates = SNDRV_PCM_RATE_8000_96000, ++ .rates = (SNDRV_PCM_RATE_8000 | ++ SNDRV_PCM_RATE_16000 | ++ SNDRV_PCM_RATE_32000 | ++ SNDRV_PCM_RATE_48000 | ++ SNDRV_PCM_RATE_64000 | ++ SNDRV_PCM_RATE_96000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE | + +From b38b721277f213bb71cef58e00ad71982a0e700d Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 14 Aug 2017 00:14:05 +0200 Subject: [PATCH] drm: dw-hdmi: change audio config --- - drivers/gpu/drm/bridge/dw-hdmi.c | 14 +++++--------- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) -diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c -index 09b43a348525..a1cf88caeadd 100644 ---- a/drivers/gpu/drm/bridge/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/dw-hdmi.c -@@ -609,18 +609,14 @@ static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi) +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index b9ec4a024276..99e27f0dcdb6 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -628,18 +628,14 @@ static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi) static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, unsigned int n) { @@ -32,7 +1547,7 @@ index 09b43a348525..a1cf88caeadd 100644 hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2); hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1); } -@@ -765,7 +761,7 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, +@@ -784,7 +780,7 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, spin_lock_irq(&hdmi->audio_lock); hdmi->audio_n = n; hdmi->audio_cts = cts; @@ -41,7 +1556,7 @@ index 09b43a348525..a1cf88caeadd 100644 spin_unlock_irq(&hdmi->audio_lock); } -@@ -3532,8 +3528,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master, +@@ -3671,8 +3667,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master, audio.read = hdmi_readb; audio.mod = hdmi_modb; audio.eld = hdmi->connector.eld; diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0005-legacy.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0005-legacy.patch index 8611a2cdad..17bb37f34e 100644 --- a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0005-legacy.patch +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0005-legacy.patch @@ -1,17 +1,17 @@ -From 3b22d9e27321d9c4bb601bd859029d4ce62bd49b Mon Sep 17 00:00:00 2001 +From 23c1ed00568676ff958024283024a30b0c37565b Mon Sep 17 00:00:00 2001 From: LongChair Date: Sun, 26 Mar 2017 15:30:16 +0200 -Subject: [PATCH 1/2] drm/rockchip: make video overlay bottom layer +Subject: [PATCH] drm/rockchip: make video overlay bottom layer --- drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -index 9d92b9a55e67..833498ed6915 100644 +index d626acf00f10..2b0c739ade64 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c -@@ -281,9 +281,9 @@ static const struct vop_ctrl rk3288_ctrl_data = { +@@ -283,9 +283,9 @@ static const struct vop_ctrl rk3288_ctrl_data = { */ static const struct vop_win_data rk3288_vop_win_data[] = { { .base = 0x00, .phy = &rk3288_win01_data, @@ -23,7 +23,7 @@ index 9d92b9a55e67..833498ed6915 100644 { .base = 0x00, .phy = &rk3288_win23_data, .type = DRM_PLANE_TYPE_OVERLAY, .area = rk3288_area_data, -@@ -974,10 +974,10 @@ static const struct vop_csc rk3328_win2_csc = { +@@ -988,10 +988,10 @@ static const struct vop_csc rk3328_win2_csc = { static const struct vop_win_data rk3328_vop_win_data[] = { { .base = 0xd0, .phy = &rk3288_win01_data, .csc = &rk3328_win0_csc, @@ -37,11 +37,10 @@ index 9d92b9a55e67..833498ed6915 100644 { .base = 0x2d0, .phy = &rk3288_win01_data, .csc = &rk3328_win2_csc, .type = DRM_PLANE_TYPE_CURSOR, -From 04759d88467419ab1500908a909ed1775455b84d Mon Sep 17 00:00:00 2001 +From dfed31cd9c52c004a51ac4e673e2746aeb0977fa Mon Sep 17 00:00:00 2001 From: LongChair Date: Mon, 24 Apr 2017 09:48:54 +0200 -Subject: [PATCH 2/2] drm : allow framebuffer and videomodes not to have same - size +Subject: [PATCH] drm : allow framebuffer and videomodes not to have same size DRM legacy doesn't allow that, will be only available with drm atomic. Although, when running 4K modes, it's preferable to get a 1080p frambuffer that can be handlded properly by GPU and then use VOP to upscale that to 4K. @@ -51,10 +50,10 @@ Although, when running 4K modes, it's preferable to get a 1080p frambuffer that 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c -index 9a513abd8a47..193997a5c640 100644 +index f77d4aa1e58b..e611f93a80d6 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c -@@ -2208,11 +2208,11 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set, +@@ -2210,11 +2210,11 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set, primary_state->src_x = set->x << 16; primary_state->src_y = set->y << 16; if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) { diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0006-dts.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0006-dts.patch new file mode 100644 index 0000000000..327e720c4d --- /dev/null +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0006-dts.patch @@ -0,0 +1,4600 @@ +From 83f0db119a7b874af4db8d280e33fe0b541cb112 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 13 Aug 2017 10:24:19 +0200 +Subject: [PATCH] arm: dts: rk3288-miniarm: update dts + +--- + arch/arm/boot/dts/rk3288-miniarm.dts | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288-miniarm.dts b/arch/arm/boot/dts/rk3288-miniarm.dts +index 2fbec41f0b23..3d2507b8c864 100644 +--- a/arch/arm/boot/dts/rk3288-miniarm.dts ++++ b/arch/arm/boot/dts/rk3288-miniarm.dts +@@ -66,7 +66,7 @@ + wireless-wlan { + compatible = "wlan-platdata"; + rockchip,grf = <&grf>; +- wifi_chip_type = "ap6212"; ++ wifi_chip_type = "rtl8723bs"; + sdio_vref = <1800>; + WIFI,host_wake_irq = <&gpio4 30 GPIO_ACTIVE_HIGH>; + status = "okay"; +@@ -130,14 +130,14 @@ + + led1-led { + gpios=<&gpio1 25 GPIO_ACTIVE_HIGH>; +- linux,default-trigger="default-off"; ++ linux,default-trigger="heartbeat"; + }; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; +- simple-audio-card,name = "rockchip,miniarm-codec"; ++ simple-audio-card,name = "HDMI"; + simple-audio-card,mclk-fs = <512>; + simple-audio-card,cpu { + sound-dai = <&i2s>; +@@ -196,20 +196,33 @@ + cpu0-supply = <&vdd_cpu>; + }; + ++&cpu0_opp_table { ++ opp-1704000000 { ++ opp-hz = /bits/ 64 <1704000000>; ++ opp-microvolt = <1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <1400000>; ++ clock-latency-ns = <40000>; ++ }; ++}; ++ + &gmac { + phy-supply = <&vcc33_lan>; + phy-mode = "rgmii"; + clock_in_out = "input"; + snps,reset-gpio = <&gpio4 7 0>; + snps,reset-active-low; +- snps,reset-delays-us = <0 10000 1000000>; ++ snps,reset-delays-us = <0 10000 50000>; + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + tx_delay = <0x30>; + rx_delay = <0x10>; +- status = "ok"; ++ status = "okay"; + }; + + &dsi0 { +@@ -537,6 +550,7 @@ + + &i2s { + #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; + status = "okay"; + }; + +@@ -560,7 +574,7 @@ + non-removable; + num-slots = <1>; + pinctrl-names = "default"; +- pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>; ++ pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk &sdio0_int>; + sd-uhs-sdr104; + supports-sdio; + }; + +From 3d304e4b4d7146e29ebd22876d69dba212dd03b1 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Thu, 2 Nov 2017 23:17:46 +0100 +Subject: [PATCH] arm: dts: rk3288-miqi: update dts + +--- + arch/arm/boot/dts/rk3288-miqi.dts | 56 +++++++++++++++++++++++---------------- + 1 file changed, 33 insertions(+), 23 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts +index b90b0e5969ec..ffced204abcf 100644 +--- a/arch/arm/boot/dts/rk3288-miqi.dts ++++ b/arch/arm/boot/dts/rk3288-miqi.dts +@@ -55,29 +55,14 @@ + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; +- simple-audio-card,name = "DW-HDMI"; ++ simple-audio-card,name = "HDMI"; + simple-audio-card,mclk-fs = <512>; +- +- simple-audio-card,dai-link@0 { /* I2S - S/PDIF */ +- format = "i2s"; +- cpu { +- sound-dai = <&i2s>; +- }; +- codec { +- sound-dai = <&hdmi>; +- }; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; + }; +- +- /* +- * If you want to support more cards, +- * you can add more dai-link node, +- * such as +- * +- * simple-audio-card,dai-link@1 { +- * ...... +- * } +- */ +- + }; + + ext_gmac: external-gmac-clock { +@@ -181,9 +166,23 @@ + cpu0-supply = <&vdd_cpu>; + }; + ++&cpu0_opp_table { ++ opp-1704000000 { ++ opp-hz = /bits/ 64 <1704000000>; ++ opp-microvolt = <1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <1400000>; ++ clock-latency-ns = <40000>; ++ }; ++}; ++ + &gpu { + status = "okay"; + mali-supply = <&vdd_gpu>; ++ power-off-delay-ms = <200>; + }; + + &emmc { +@@ -203,6 +202,12 @@ + #size-cells = <0>; + #sound-dai-cells = <0>; + status = "okay"; ++ /* Don't use vopl for HDMI */ ++ ports { ++ hdmi_in: port { ++ /delete-node/ endpoint@1; ++ }; ++ }; + }; + + &hevc_service { +@@ -234,14 +239,14 @@ + clock_in_out = "input"; + snps,reset-gpio = <&gpio4 7 0>; + snps,reset-active-low; +- snps,reset-delays-us = <0 10000 1000000>; ++ snps,reset-delays-us = <0 10000 50000>; + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + tx_delay = <0x30>; + rx_delay = <0x10>; +- status = "ok"; ++ status = "okay"; + }; + + /* ---------------------------------------------------------------------------------- +@@ -413,6 +418,7 @@ I2C + + &i2s { + #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; + status = "okay"; + }; + +@@ -471,6 +477,10 @@ I2C + + &vopl { + status = "okay"; ++ /* Don't use vopl for HDMI */ ++ vopl_out: port { ++ /delete-node/ endpoint@0; ++ }; + }; + + &vopl_mmu { + +From 5036951993971301b25e23da49d1dd430fd941f0 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: rk3328: update dtsi + +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 49 +++++++++++++++++++++++++------- + 1 file changed, 38 insertions(+), 11 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index cfb645b45dd9..a3faafd88c28 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -88,6 +88,8 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x1>; ++ clocks = <&cru ARMCLK>; ++ dynamic-power-coefficient = <120>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; +@@ -95,6 +97,8 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x2>; ++ clocks = <&cru ARMCLK>; ++ dynamic-power-coefficient = <120>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; +@@ -102,6 +106,8 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x3>; ++ clocks = <&cru ARMCLK>; ++ dynamic-power-coefficient = <120>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; +@@ -161,6 +167,18 @@ + opp-microvolt-L1 = <1300000>; + clock-latency-ns = <40000>; + }; ++ /* ++ opp-1392000000 { ++ opp-hz = /bits/ 64 <1392000000>; ++ opp-microvolt = <1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ */ + }; + + arm-pmu { +@@ -186,7 +204,7 @@ + }; + + psci { +- compatible = "arm,psci-1.0"; ++ compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; + }; + +@@ -705,6 +723,10 @@ + opp-microvolt-L0 = <1125000>; + opp-microvolt-L1 = <1100000>; + }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <1150000>; ++ }; + }; + + vdpu: vpu_service@ff350000 { +@@ -828,7 +850,7 @@ + interrupts = ; + interrupt-names = "rkvdec_mmu"; + clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; +- clock-names = "aclk_vcodec", "hclk_vcodec"; ++ clock-names = "aclk", "hclk"; + power-domains = <&power RK3328_PD_VIDEO>; + #iommu-cells = <0>; + }; +@@ -932,6 +954,8 @@ + reg = <0x0 0xff373f00 0x0 0x100>; + interrupts = ; + interrupt-names = "vop_mmu"; ++ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>; ++ clock-names = "aclk", "hclk"; + #iommu-cells = <0>; + status = "disabled"; + }; +@@ -1207,9 +1231,10 @@ + sdmmc: dwmmc@ff500000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff500000 0x0 0x4000>; +- clock-freq-min-max = <400000 150000000>; +- clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>; +- clock-names = "biu", "ciu"; ++ max-frequency = <150000000>; ++ clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, ++ <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + status = "disabled"; +@@ -1218,10 +1243,10 @@ + sdio: dwmmc@ff510000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff510000 0x0 0x4000>; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, + <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; +- clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + status = "disabled"; +@@ -1230,9 +1255,10 @@ + emmc: dwmmc@ff520000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff520000 0x0 0x4000>; +- clock-freq-min-max = <400000 150000000>; +- clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>; +- clock-names = "biu", "ciu"; ++ max-frequency = <150000000>; ++ clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, ++ <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + status = "disabled"; +@@ -1254,6 +1280,7 @@ + "pclk_mac"; + resets = <&cru SRST_GMAC2IO_A>; + reset-names = "stmmaceth"; ++ snps,force_thresh_dma_mode; + status = "disabled"; + }; + +@@ -1324,7 +1351,7 @@ + sdmmc_ext: dwmmc@ff5f0000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff5f0000 0x0 0x4000>; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>; + clock-names = "biu", "ciu"; + fifo-depth = <0x100>; + +From ecdb644017db6d6b5e2efed64cb6631fab2e5054 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: rk3328-rock64: update dts + +--- + arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 204 ++++++++++++++++--------- + 1 file changed, 128 insertions(+), 76 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +index b5bb7bf0f34c..67a3ff2215e5 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +@@ -52,18 +52,6 @@ + stdout-path = "serial2:1500000n8"; + }; + +- fiq-debugger { +- compatible = "rockchip,fiq-debugger"; +- rockchip,serial-id = <2>; +- rockchip,signal-irq = <159>; +- rockchip,wake-irq = <0>; +- /* If enable uart uses irq instead of fiq */ +- rockchip,irq-mode-enable = <0>; +- rockchip,baudrate = <1500000>; /* Only 115200 and 1500000 */ +- interrupts = ; +- status = "okay"; +- }; +- + gmac_clkin: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; +@@ -73,7 +61,7 @@ + + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; +- gpio = <&gpio0 30 GPIO_ACTIVE_LOW>; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0m1_gpio>; + regulator-name = "vcc_sd"; +@@ -82,25 +70,15 @@ + vin-supply = <&vcc_io>; + }; + +- vcc_host_5v: vcc-host-5v-regulator { ++ vcc_host_5v: vcc_host1_5v: vcc_otg_5v: vcc-host-5v-regulator { + compatible = "regulator-fixed"; +- enable-active-high; +- gpio = <&gpio0 0 GPIO_ACTIVE_HIGH>; ++ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&usb30_host_drv>; ++ pinctrl-0 = <&usb_host_drv>; + regulator-name = "vcc_host_5v"; + regulator-always-on; +- vin-supply = <&vcc_sys>; +- }; +- +- vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { +- compatible = "regulator-fixed"; +- enable-active-high; +- gpio = <&gpio0 27 GPIO_ACTIVE_HIGH>; +- pinctrl-names = "default"; +- pinctrl-0 = <&usb20_host_drv>; +- regulator-name = "vcc_host1_5v"; +- regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_sys>; + }; + +@@ -113,18 +91,47 @@ + regulator-max-microvolt = <5000000>; + }; + ++ leds { ++ compatible = "gpio-leds"; ++ ++ standby-led { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ power-led { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ + ir-receiver { + compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ linux,rc-map-name = "rc-pine64"; + pinctrl-0 = <&ir_int>; + pinctrl-names = "default"; + status = "okay"; + }; + ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; +- simple-audio-card,name = "rockchip,rk3328"; ++ simple-audio-card,name = "I2S"; + simple-audio-card,cpu { + sound-dai = <&i2s1>; + }; +@@ -133,18 +140,21 @@ + }; + }; + +- hdmi-sound { ++ spdif-sound { + compatible = "simple-audio-card"; +- simple-audio-card,format = "i2s"; +- simple-audio-card,mclk-fs = <128>; +- simple-audio-card,name = "rockchip,hdmi"; ++ simple-audio-card,name = "SPDIF"; + simple-audio-card,cpu { +- sound-dai = <&i2s0>; ++ sound-dai = <&spdif>; + }; + simple-audio-card,codec { +- sound-dai = <&hdmi>; ++ sound-dai = <&spdif_out>; + }; + }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; + }; + + &codec { +@@ -168,6 +178,15 @@ + cpu-supply = <&vdd_arm>; + }; + ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ + &display_subsystem { + status = "okay"; + }; +@@ -175,31 +194,42 @@ + &emmc { + bus-width = <8>; + cap-mmc-highspeed; ++ mmc-hs200-1_8v; + non-removable; +- supports-emmc; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; + vmmc-supply = <&vcc_io>; + vqmmc-supply = <&vcc18_emmc>; + status = "okay"; + }; + + &gmac2io { +- phy-supply = <&vcc_io>; +- phy-mode = "rgmii"; + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; + clock_in_out = "input"; +- snps,reset-gpio = <&gpio1 18 GPIO_ACTIVE_LOW>; +- snps,reset-active-low; +- snps,reset-delays-us = <0 10000 50000>; ++ phy-supply = <&vcc_io>; ++ phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmiim1_pins>; +- tx_delay = <0x26>; +- rx_delay = <0x11>; ++ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ tx_delay = <0x24>; ++ rx_delay = <0x18>; + status = "okay"; + }; + ++&gmac2phy { ++ phy-supply = <&vcc_io>; ++ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; ++ assigned-clock-rate = <50000000>; ++ assigned-clocks = <&cru SCLK_MAC2PHY>; ++ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; ++ clock_in_out = "output"; ++ status = "disabled"; ++}; ++ + &gpu { + status = "okay"; + mali-supply = <&vdd_logic>; +@@ -215,6 +245,8 @@ + + &hdmi { + #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; + status = "okay"; + }; + +@@ -231,14 +263,14 @@ + reg = <0x18>; + interrupt-parent = <&gpio2>; + interrupts = <6 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk805-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + gpio-controller; +- clock-output-names = "xin32k", "rk805-clkout2"; + #gpio-cells = <2>; +- #clock-cells = <1>; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; +@@ -248,11 +280,11 @@ + vcc6-supply = <&vcc_sys>; + + rtc { +- status = "disabled"; ++ status = "okay"; + }; + + pwrkey { +- status = "disabled"; ++ status = "okay"; + }; + + gpio { +@@ -272,8 +304,8 @@ + regulator-max-microvolt = <1450000>; + regulator-initial-mode = <0x1>; + regulator-ramp-delay = <12500>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; +@@ -288,8 +320,8 @@ + regulator-max-microvolt = <1450000>; + regulator-initial-mode = <0x1>; + regulator-ramp-delay = <12500>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; +@@ -301,8 +333,8 @@ + regulator-compatible = "RK805_DCDC3"; + regulator-name = "vcc_ddr"; + regulator-initial-mode = <0x1>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; +@@ -315,8 +347,8 @@ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = <0x1>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; +@@ -324,13 +356,13 @@ + }; + }; + +- vdd_18: RK805_LDO1@4 { ++ vcc_18: RK805_LDO1@4 { + regulator-compatible = "RK805_LDO1"; +- regulator-name = "vdd_18"; ++ regulator-name = "vcc_18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; +@@ -342,8 +374,8 @@ + regulator-name = "vcc18_emmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; +@@ -355,8 +387,8 @@ + regulator-name = "vdd_10"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; +@@ -373,6 +405,16 @@ + }; + + &i2s1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s1_mclk ++ &i2s1_sclk ++ &i2s1_lrcktx ++ &i2s1_lrckrx ++ &i2s1_sdo ++ &i2s1_sdi ++ &i2s1_sdio1 ++ &i2s1_sdio2 ++ &i2s1_sdio3>; + #sound-dai-cells = <0>; + status = "okay"; + }; +@@ -383,7 +425,7 @@ + vccio1-supply = <&vcc_io>; + vccio2-supply = <&vcc18_emmc>; + vccio3-supply = <&vcc_io>; +- vccio4-supply = <&vdd_18>; ++ vccio4-supply = <&vcc_18>; + vccio5-supply = <&vcc_io>; + vccio6-supply = <&vcc_io>; + pmuio-supply = <&vcc_io>; +@@ -392,37 +434,26 @@ + &pinctrl { + ir { + ir_int: ir-int { +- rockchip,pins = <2 2 RK_FUNC_GPIO &pcfg_pull_none>; ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { +- rockchip,pins = <2 6 RK_FUNC_GPIO &pcfg_pull_up>; +- }; +- }; +- +- sdio-pwrseq { +- wifi_enable_h: wifi-enable-h { +- rockchip,pins = <1 18 RK_FUNC_GPIO &pcfg_pull_none>; +- }; +- }; +- +- usb2 { +- usb20_host_drv: usb20-host-drv { +- rockchip,pins = <0 27 RK_FUNC_GPIO &pcfg_pull_none>; ++ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + +- usb3 { +- usb30_host_drv: usb30-host-drv { +- rockchip,pins = <0 0 RK_FUNC_GPIO &pcfg_pull_none>; ++ usb { ++ usb_host_drv: usb-host-drv { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + }; + + &rkvdec { + status = "okay"; ++ vcodec-supply = <&vdd_logic>; + }; + + &rkvdec_mmu { +@@ -437,8 +468,15 @@ + max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; +- vmmc-supply = <&vcc_sd>; + supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; + status = "okay"; + }; + +@@ -456,9 +494,22 @@ + }; + }; + ++&threshold { ++ temperature = <90000>; /* millicelsius */ ++}; ++ ++&target { ++ temperature = <105000>; /* millicelsius */ ++}; ++ ++&soc_crit { ++ temperature = <110000>; /* millicelsius */ ++}; ++ + &tsadc { + rockchip,hw-tshut-mode = <0>; + rockchip,hw-tshut-polarity = <0>; ++ rockchip,hw-tshut-temp = <120000>; + status = "okay"; + }; + +@@ -482,15 +533,16 @@ + }; + + &u3phy { +- phy-supply = <&vcc_host_5v>; + status = "okay"; + }; + + &u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; + status = "okay"; + }; + + &u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; + status = "okay"; + }; + + +From 46a7e76341bde2abaf2177b4354a5601beb25b93 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3328-box board + +--- + arch/arm64/boot/dts/rockchip/rk3328-box.dts | 608 ++++++++++++++++++++++++++++ + 1 file changed, 608 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-box.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box.dts b/arch/arm64/boot/dts/rockchip/rk3328-box.dts +new file mode 100644 +index 000000000000..a2c5d616f4bd +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-box.dts +@@ -0,0 +1,608 @@ ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "rk3328.dtsi" ++ ++/ { ++ model = "Rockchip RK3328 BOX"; ++ compatible = "rockchip,rk3328-box", "rockchip,rk3328"; ++ ++ chosen { ++ bootargs = "rockchip_jtag earlyprintk=uart8250-32bit,0xff130000"; ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ ++ /* ++ * On the module itself this is one of these (depending ++ * on the actual card populated): ++ * - SDIO_RESET_L_WL_REG_ON ++ * - PDN (power down when low) ++ */ ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io>; ++ }; ++ ++ vcc_host_5v: vcc-host-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb30_host_drv>; ++ regulator-name = "vcc_host_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb20_host_drv>; ++ regulator-name = "vcc_host1_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led1 { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led2 { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ wireless-bluetooth { ++ compatible = "bluetooth-platdata"; ++ clocks = <&rk805 1>; ++ clock-names = "ext_clock"; ++ uart_rts_gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default", "rts_gpio"; ++ pinctrl-0 = <&uart0_rts>; ++ pinctrl-1 = <&uart0_gpios>; ++ BT,power_gpio = <&gpio1 RK_PC5 GPIO_ACTIVE_HIGH>; ++ BT,wake_host_irq = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wireless-wlan { ++ compatible = "wlan-platdata"; ++ rockchip,grf = <&grf>; ++ wifi_chip_type = "rtl8723bs"; ++ sdio_vref = <1800>; ++ WIFI,host_wake_irq = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++}; ++ ++&codec { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vcc18_emmc>; ++ status = "okay"; ++}; ++ ++&gmac2phy { ++ phy-supply = <&vcc_io>; ++ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; ++ assigned-clock-rate = <50000000>; ++ assigned-clocks = <&cru SCLK_MAC2PHY>; ++ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; ++ clock_in_out = "output"; ++ status = "okay"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_logic>; ++}; ++ ++&h265e { ++ status = "okay"; ++}; ++ ++&h265e_mmu { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; ++ status = "okay"; ++}; ++ ++&hdmiphy { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: rk805@18 { ++ compatible = "rockchip,rk805"; ++ status = "okay"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio2>; ++ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk805-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_io>; ++ vcc6-supply = <&vcc_sys>; ++ ++ rtc { ++ status = "okay"; ++ }; ++ ++ pwrkey { ++ status = "okay"; ++ }; ++ ++ gpio { ++ status = "okay"; ++ }; ++ ++ regulators { ++ compatible = "rk805-regulator"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vdd_logic: RK805_DCDC1@0 { ++ regulator-compatible = "RK805_DCDC1"; ++ regulator-name = "vdd_logic"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: RK805_DCDC2@1 { ++ regulator-compatible = "RK805_DCDC2"; ++ regulator-name = "vdd_arm"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: RK805_DCDC3@2 { ++ regulator-compatible = "RK805_DCDC3"; ++ regulator-name = "vcc_ddr"; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: RK805_DCDC4@3 { ++ regulator-compatible = "RK805_DCDC4"; ++ regulator-name = "vcc_io"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: RK805_LDO1@4 { ++ regulator-compatible = "RK805_LDO1"; ++ regulator-name = "vcc_18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: RK805_LDO2@5 { ++ regulator-compatible = "RK805_LDO2"; ++ regulator-name = "vcc18_emmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: RK805_LDO3@6 { ++ regulator-compatible = "RK805_LDO3"; ++ regulator-name = "vdd_10"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s0 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ vccio1-supply = <&vcc_io>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io>; ++ vccio6-supply = <&vcc_io>; ++ pmuio-supply = <&vcc_io>; ++}; ++ ++&pinctrl { ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb2 { ++ usb20_host_drv: usb20-host-drv { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb3 { ++ usb30_host_drv: usb30-host-drv { ++ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ wireless-bluetooth { ++ uart0_gpios: uart0-gpios { ++ rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ vcodec-supply = <&vdd_logic>; ++}; ++ ++&rkvdec_mmu { ++ status = "okay"; ++}; ++ ++&sdio { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ disable-wp; ++ keep-power-in-suspend; ++ max-frequency = <150000000>; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; ++ sd-uhs-sdr104; ++ supports-sdio; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; ++ supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_xfer &uart0_cts>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++ ++}; ++ ++&u2phy_host { ++ phy-supply = <&vcc_host1_5v>; ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ phy-supply = <&vcc_otg_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ ++&u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vpu_service { ++ status = "okay"; ++}; ++ ++&vpu_mmu { ++ status = "okay"; ++}; ++ ++&vepu { ++ status = "okay"; ++}; ++ ++&vepu_mmu { ++ status = "okay"; ++}; ++ ++&venc_srv { ++ status = "okay"; ++}; + +From 1298112e7e4aa23834943ad89a0f1495445c45b6 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3328-rockbox board + +--- + arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts | 555 ++++++++++++++++++++++++ + 1 file changed, 555 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts +new file mode 100644 +index 000000000000..ac1a6b21fd14 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts +@@ -0,0 +1,555 @@ ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "rk3328.dtsi" ++ ++/ { ++ model = "Pine64 RockBox"; ++ compatible = "pine64,rockbox", "rockchip,rk3328"; ++ ++ chosen { ++ bootargs = "rockchip_jtag earlyprintk=uart8250-32bit,0xff130000"; ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ ++ /* ++ * On the module itself this is one of these (depending ++ * on the actual card populated): ++ * - SDIO_RESET_L_WL_REG_ON ++ * - PDN (power down when low) ++ */ ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io>; ++ }; ++ ++ vcc_host_5v: vcc_host1_5v: vcc_otg_5v: vcc-host-5v-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_host_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led1 { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led2 { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ linux,rc-map-name = "rc-pine64"; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ wireless-wlan { ++ compatible = "wlan-platdata"; ++ rockchip,grf = <&grf>; ++ wifi_chip_type = "rtl8189fs"; ++ sdio_vref = <1800>; ++ WIFI,host_wake_irq = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++}; ++ ++&codec { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vcc18_emmc>; ++ status = "okay"; ++}; ++ ++&gmac2phy { ++ phy-supply = <&vcc_io>; ++ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; ++ assigned-clock-rate = <50000000>; ++ assigned-clocks = <&cru SCLK_MAC2PHY>; ++ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; ++ clock_in_out = "output"; ++ status = "okay"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_logic>; ++}; ++ ++&h265e { ++ status = "okay"; ++}; ++ ++&h265e_mmu { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; ++ status = "okay"; ++}; ++ ++&hdmiphy { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: rk805@18 { ++ compatible = "rockchip,rk805"; ++ status = "okay"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio2>; ++ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk805-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_io>; ++ vcc6-supply = <&vcc_sys>; ++ ++ rtc { ++ status = "okay"; ++ }; ++ ++ pwrkey { ++ status = "okay"; ++ }; ++ ++ gpio { ++ status = "okay"; ++ }; ++ ++ regulators { ++ compatible = "rk805-regulator"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vdd_logic: RK805_DCDC1@0 { ++ regulator-compatible = "RK805_DCDC1"; ++ regulator-name = "vdd_logic"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: RK805_DCDC2@1 { ++ regulator-compatible = "RK805_DCDC2"; ++ regulator-name = "vdd_arm"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: RK805_DCDC3@2 { ++ regulator-compatible = "RK805_DCDC3"; ++ regulator-name = "vcc_ddr"; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: RK805_DCDC4@3 { ++ regulator-compatible = "RK805_DCDC4"; ++ regulator-name = "vcc_io"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: RK805_LDO1@4 { ++ regulator-compatible = "RK805_LDO1"; ++ regulator-name = "vcc_18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: RK805_LDO2@5 { ++ regulator-compatible = "RK805_LDO2"; ++ regulator-name = "vcc18_emmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: RK805_LDO3@6 { ++ regulator-compatible = "RK805_LDO3"; ++ regulator-name = "vdd_10"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s0 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ vccio1-supply = <&vcc_io>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io>; ++ vccio6-supply = <&vcc_io>; ++ pmuio-supply = <&vcc_io>; ++}; ++ ++&pinctrl { ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ vcodec-supply = <&vdd_logic>; ++}; ++ ++&rkvdec_mmu { ++ status = "okay"; ++}; ++ ++&sdio { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ disable-wp; ++ keep-power-in-suspend; ++ max-frequency = <150000000>; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; ++ sd-uhs-sdr104; ++ supports-sdio; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; ++ supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++ ++}; ++ ++&u2phy_host { ++ phy-supply = <&vcc_host1_5v>; ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ phy-supply = <&vcc_otg_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ ++&u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vpu_service { ++ status = "okay"; ++}; ++ ++&vpu_mmu { ++ status = "okay"; ++}; ++ ++&vepu { ++ status = "okay"; ++}; ++ ++&vepu_mmu { ++ status = "okay"; ++}; ++ ++&venc_srv { ++ status = "okay"; ++}; + +From 4e58637cfc4366f4e9ae03152811e40cfd76e6f1 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3328-roc-cc board + +--- + arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 542 +++++++++++++++++++++++++ + 1 file changed, 542 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +new file mode 100644 +index 000000000000..929d7c16060b +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +@@ -0,0 +1,542 @@ ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "rk3328.dtsi" ++ ++/ { ++ model = "Firefly ROC-RK3328-CC Board"; ++ compatible = "firefly,roc-rk3328-cc", "rockchip,rk3328"; ++ ++ chosen { ++ bootargs = "rockchip_jtag earlyprintk=uart8250-32bit,0xff130000"; ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ gmac_clkin: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io>; ++ }; ++ ++ vccio_sd: sdmmcio-regulator { ++ compatible = "regulator-gpio"; ++ gpios = <&gpio0 RK_PD1 GPIO_ACTIVE_HIGH>; ++ states = <1800000 0x1 ++ 3300000 0x0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sd_pwr_1800_sel>; ++ regulator-name = "vccio_sd"; ++ regulator-type = "voltage"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ vcc_host_5v: vcc_host1_5v: vcc_otg_5v: vcc-host-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb_host_drv>; ++ regulator-name = "vcc_host_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ user { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <256>; ++ simple-audio-card,name = "I2S"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&codec>; ++ }; ++ }; ++}; ++ ++&codec { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vcc18_emmc>; ++ status = "okay"; ++}; ++ ++&gmac2io { ++ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; ++ assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; ++ clock_in_out = "input"; ++ phy-supply = <&vcc_io>; ++ phy-mode = "rgmii"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmiim1_pins>; ++ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ tx_delay = <0x25>; ++ rx_delay = <0x11>; ++ status = "okay"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_logic>; ++}; ++ ++&h265e { ++ status = "okay"; ++}; ++ ++&h265e_mmu { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; ++ status = "okay"; ++}; ++ ++&hdmiphy { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: rk805@18 { ++ compatible = "rockchip,rk805"; ++ status = "okay"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <24 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk805-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_io>; ++ vcc6-supply = <&vcc_sys>; ++ ++ rtc { ++ status = "okay"; ++ }; ++ ++ pwrkey { ++ status = "okay"; ++ }; ++ ++ gpio { ++ status = "okay"; ++ }; ++ ++ regulators { ++ compatible = "rk805-regulator"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vdd_logic: RK805_DCDC1@0 { ++ regulator-compatible = "RK805_DCDC1"; ++ regulator-name = "vdd_logic"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: RK805_DCDC2@1 { ++ regulator-compatible = "RK805_DCDC2"; ++ regulator-name = "vdd_arm"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: RK805_DCDC3@2 { ++ regulator-compatible = "RK805_DCDC3"; ++ regulator-name = "vcc_ddr"; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: RK805_DCDC4@3 { ++ regulator-compatible = "RK805_DCDC4"; ++ regulator-name = "vcc_io"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: RK805_LDO1@4 { ++ regulator-compatible = "RK805_LDO1"; ++ regulator-name = "vcc_18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: RK805_LDO2@5 { ++ regulator-compatible = "RK805_LDO2"; ++ regulator-name = "vcc18_emmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: RK805_LDO3@6 { ++ regulator-compatible = "RK805_LDO3"; ++ regulator-name = "vdd_10"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s0 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ vccio1-supply = <&vcc_io>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vccio_sd>; ++ vccio4-supply = <&vcc_io>; ++ vccio5-supply = <&vcc_io>; ++ vccio6-supply = <&vcc_io>; ++ pmuio-supply = <&vcc_io>; ++}; ++ ++&pinctrl { ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ sd-pwerset { ++ sd_pwr_1800_sel: sd-pwr-1800-sel { ++ rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ usb_host_drv: usb-host-drv { ++ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ vcodec-supply = <&vdd_logic>; ++}; ++ ++&rkvdec_mmu { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <100000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; ++ sd-uhs-sdr104; ++ supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ vqmmc-supply = <&vccio_sd>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++ ++}; ++ ++&u2phy_host { ++ phy-supply = <&vcc_host1_5v>; ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ phy-supply = <&vcc_otg_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ ++&u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vpu_service { ++ status = "okay"; ++}; ++ ++&vpu_mmu { ++ status = "okay"; ++}; ++ ++&vepu { ++ status = "okay"; ++}; ++ ++&vepu_mmu { ++ status = "okay"; ++}; ++ ++&venc_srv { ++ status = "okay"; ++}; + +From 4b28de8866e777301994ae85a237b02805faea2b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3328-box-plus board + +--- + arch/arm64/boot/dts/rockchip/rk3328-box-plus.dts | 638 +++++++++++++++++++++++ + 1 file changed, 638 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-box-plus.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box-plus.dts b/arch/arm64/boot/dts/rockchip/rk3328-box-plus.dts +new file mode 100644 +index 000000000000..aa2925cda274 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-box-plus.dts +@@ -0,0 +1,638 @@ ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "rk3328.dtsi" ++ ++/ { ++ model = "Rockchip RK3328 BOX Plus"; ++ compatible = "rockchip,rk3328-box-plus", "rockchip,rk3328"; ++ ++ chosen { ++ bootargs = "rockchip_jtag"; ++ }; ++ ++ gmac_clkin: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ ++ /* ++ * On the module itself this is one of these (depending ++ * on the actual card populated): ++ * - SDIO_RESET_L_WL_REG_ON ++ * - PDN (power down when low) ++ */ ++ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io>; ++ }; ++ ++ vcc_host_5v: vcc-host-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb30_host_drv>; ++ regulator-name = "vcc_host_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb20_host_drv>; ++ regulator-name = "vcc_host1_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led1 { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led2 { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <256>; ++ simple-audio-card,name = "I2S"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&codec>; ++ }; ++ }; ++ ++ spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ wireless-bluetooth { ++ compatible = "bluetooth-platdata"; ++ clocks = <&rk805 1>; ++ clock-names = "ext_clock"; ++ BT,power_gpio = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>; ++ BT,wake_host_irq = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wireless-wlan { ++ compatible = "wlan-platdata"; ++ rockchip,grf = <&grf>; ++ wifi_chip_type = "rtl8723bs"; ++ sdio_vref = <1800>; ++ WIFI,host_wake_irq = <&gpio3 RK_PA1 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++}; ++ ++&codec { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vcc18_emmc>; ++ status = "okay"; ++}; ++ ++&gmac2io { ++ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; ++ assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; ++ clock_in_out = "input"; ++ phy-supply = <&vcc_io>; ++ phy-mode = "rgmii"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmiim1_pins>; ++ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ tx_delay = <0x26>; ++ rx_delay = <0x11>; ++ status = "okay"; ++}; ++ ++&gmac2phy { ++ phy-supply = <&vcc_io>; ++ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; ++ assigned-clock-rate = <50000000>; ++ assigned-clocks = <&cru SCLK_MAC2PHY>; ++ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; ++ clock_in_out = "output"; ++ status = "disabled"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_logic>; ++}; ++ ++&h265e { ++ status = "okay"; ++}; ++ ++&h265e_mmu { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; ++ status = "okay"; ++}; ++ ++&hdmiphy { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: rk805@18 { ++ compatible = "rockchip,rk805"; ++ status = "okay"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio2>; ++ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk805-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_io>; ++ vcc6-supply = <&vcc_sys>; ++ ++ rtc { ++ status = "okay"; ++ }; ++ ++ pwrkey { ++ status = "okay"; ++ }; ++ ++ gpio { ++ status = "okay"; ++ }; ++ ++ regulators { ++ compatible = "rk805-regulator"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vdd_logic: RK805_DCDC1@0 { ++ regulator-compatible = "RK805_DCDC1"; ++ regulator-name = "vdd_logic"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: RK805_DCDC2@1 { ++ regulator-compatible = "RK805_DCDC2"; ++ regulator-name = "vdd_arm"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: RK805_DCDC3@2 { ++ regulator-compatible = "RK805_DCDC3"; ++ regulator-name = "vcc_ddr"; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: RK805_DCDC4@3 { ++ regulator-compatible = "RK805_DCDC4"; ++ regulator-name = "vcc_io"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: RK805_LDO1@4 { ++ regulator-compatible = "RK805_LDO1"; ++ regulator-name = "vcc_18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: RK805_LDO2@5 { ++ regulator-compatible = "RK805_LDO2"; ++ regulator-name = "vcc18_emmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: RK805_LDO3@6 { ++ regulator-compatible = "RK805_LDO3"; ++ regulator-name = "vdd_10"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s0 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&i2s1 { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ vccio1-supply = <&vcc_io>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io>; ++ vccio6-supply = <&vcc_io>; ++ pmuio-supply = <&vcc_io>; ++}; ++ ++&pinctrl { ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb2 { ++ usb20_host_drv: usb20-host-drv { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb3 { ++ usb30_host_drv: usb30-host-drv { ++ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ wireless-bluetooth { ++ uart0_gpios: uart0-gpios { ++ rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ vcodec-supply = <&vdd_logic>; ++}; ++ ++&rkvdec_mmu { ++ status = "okay"; ++}; ++ ++&sdmmc_ext { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ disable-wp; ++ keep-power-in-suspend; ++ max-frequency = <150000000>; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0ext_bus4 &sdmmc0ext_cmd &sdmmc0ext_clk>; ++ sd-uhs-sdr104; ++ supports-sdio; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; ++ supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++ ++}; ++ ++&u2phy_host { ++ phy-supply = <&vcc_host1_5v>; ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ phy-supply = <&vcc_otg_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ ++&u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vpu_service { ++ status = "okay"; ++}; ++ ++&vpu_mmu { ++ status = "okay"; ++}; ++ ++&vepu { ++ status = "okay"; ++}; ++ ++&vepu_mmu { ++ status = "okay"; ++}; ++ ++&venc_srv { ++ status = "okay"; ++}; + +From 05fdbaf77827cf77ade56c832093147bae42885e Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 3 Sep 2017 11:19:19 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3328-rock64: use two dai-link for i2s + sound + +--- + arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 26 +++++++++++++++++++++----- + sound/soc/soc-utils.c | 10 ++++++++++ + 2 files changed, 31 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +index 67a3ff2215e5..d25bcc36e32f 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +@@ -114,6 +114,11 @@ + status = "okay"; + }; + ++ dummy_codec: dummy-codec { ++ compatible = "linux,snd-soc-dummy"; ++ #sound-dai-cells = <0>; ++ }; ++ + hdmi-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; +@@ -129,14 +134,25 @@ + + sound { + compatible = "simple-audio-card"; +- simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,name = "I2S"; +- simple-audio-card,cpu { +- sound-dai = <&i2s1>; ++ simple-audio-card,dai-link@0 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&i2s1>; ++ }; ++ codec { ++ sound-dai = <&codec>; ++ }; + }; +- simple-audio-card,codec { +- sound-dai = <&codec>; ++ simple-audio-card,dai-link@1 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&i2s1>; ++ }; ++ codec { ++ sound-dai = <&dummy_codec>; ++ }; + }; + }; + +diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c +index 53dd085d3ee2..bf7ce34084a9 100644 +--- a/sound/soc/soc-utils.c ++++ b/sound/soc/soc-utils.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots) + { +@@ -160,9 +161,18 @@ static int snd_soc_dummy_remove(struct platform_device *pdev) + return 0; + } + ++#ifdef CONFIG_OF ++static const struct of_device_id soc_dummy_ids[] = { ++ { .compatible = "linux,snd-soc-dummy", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, soc_dummy_ids); ++#endif ++ + static struct platform_driver soc_dummy_driver = { + .driver = { + .name = "snd-soc-dummy", ++ .of_match_table = of_match_ptr(soc_dummy_ids), + }, + .probe = snd_soc_dummy_probe, + .remove = snd_soc_dummy_remove, + +From b765e2f30f2e05cbcf0a489b5239d078fd4c0583 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 26 Jan 2018 00:03:46 +0100 +Subject: [PATCH] arm64: dts: rockchip: rk3328-roc-cc: disable sd-card voltage + select + +Voltage select should set GRF_SOC_CON10 bit 1, +vendor kernel repurpose GPIO0_D1 to signal this, +RK kernel uses GRF_SOC_CON10 bit 1 to mute avcodec. +--- + arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +index 929d7c16060b..02b41b7a5776 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +@@ -75,8 +75,6 @@ + gpios = <&gpio0 RK_PD1 GPIO_ACTIVE_HIGH>; + states = <1800000 0x1 + 3300000 0x0>; +- pinctrl-names = "default"; +- pinctrl-0 = <&sd_pwr_1800_sel>; + regulator-name = "vccio_sd"; + regulator-type = "voltage"; + regulator-min-microvolt = <1800000>; +@@ -410,12 +408,6 @@ + }; + }; + +- sd-pwerset { +- sd_pwr_1800_sel: sd-pwr-1800-sel { +- rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; +- }; +- }; +- + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; +@@ -443,13 +435,11 @@ + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; +- max-frequency = <100000000>; ++ max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; +- sd-uhs-sdr104; + supports-sd; + vmmc-supply = <&vcc_sd>; +- vqmmc-supply = <&vccio_sd>; + status = "okay"; + }; + + +From 9e44b548e1803f1927e2dd0d4dacd89ffa12b040 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 28 Jan 2018 15:17:34 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3399-sapphire board + +--- + arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts | 142 +++++++++++++++++++++++ + 1 file changed, 142 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts +new file mode 100644 +index 000000000000..36613de5c68e +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts +@@ -0,0 +1,142 @@ ++/* ++ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++ ++#include "rk3399-sapphire.dtsi" ++#include "rk3399-linux.dtsi" ++#include ++ ++/ { ++ model = "Rockchip RK3399 Sapphire Board"; ++ compatible = "rockchip,rk3399-sapphire", "rockchip,rk3399"; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ autorepeat; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwrbtn>; ++ ++ button@0 { ++ gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ label = "GPIO Key Power"; ++ linux,input-type = <1>; ++ gpio-key,wakeup = <1>; ++ debounce-interval = <100>; ++ }; ++ }; ++ ++ vccadc_ref: vccadc-ref { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v8_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++}; ++ ++&hdmi_sound { ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ status = "okay"; ++}; ++ ++&i2s2 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&saradc { ++ vref-supply = <&vccadc_ref>; ++}; ++ ++&vpu { ++ status = "okay"; ++ /* 0 means ion, 1 means drm */ ++ //allocator = <0>; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ /* 0 means ion, 1 means drm */ ++ //allocator = <0>; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&vopb { ++ status = "okay"; ++}; ++ ++&vopb_mmu { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = ++ <0 10 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ buttons { ++ pwrbtn: pwrbtn { ++ rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; + +From e327e79ab50c8491950d8f9030fb52769336940c Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 28 Jan 2018 15:17:53 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3399-rock960 board + +--- + arch/arm64/boot/dts/rockchip/rk3399-rock960.dts | 983 ++++++++++++++++++++++++ + 1 file changed, 983 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-rock960.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dts +new file mode 100644 +index 000000000000..a5c906dd5961 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dts +@@ -0,0 +1,983 @@ ++/* ++ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++ ++#include ++#include ++#include "rk3399.dtsi" ++#include "rk3399-linux.dtsi" ++#include "rk3399-opp.dtsi" ++ ++ ++/ { ++ model = "ROCK960"; ++ compatible = "96rocks,rock960", "rockchip,rk3399"; ++ ++ vcc1v8_s0: vcc1v8-s0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v8_s0"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc3v3_sys: vcc3v3-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_sys"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc3v3_pcie: vcc3v3-pcie-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio3 11 GPIO_ACTIVE_LOW>; ++ //gpio = <&gpio3 8 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_drv>; ++ regulator-boot-on; ++ regulator-name = "vcc3v3_pcie"; ++ vin-supply = <&vcc3v3_sys>; ++ startup-delay-us = <70000>; ++ }; ++ ++ vcc5v0_host: vcc5v0-host-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&host_vbus_drv>; ++ regulator-name = "vcc5v0_host"; ++ regulator-always-on; ++ }; ++ ++ vdd_log: vdd-log { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm2 0 25000 1>; ++ regulator-name = "vdd_log"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ /* for rockchip boot on */ ++ rockchip,pwm_id= <2>; ++ rockchip,pwm_voltage = <900000>; ++ ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ clkin_gmac: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "clkin_gmac"; ++ #clock-cells = <0>; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s2>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ clocks = <&rk808 1>; ++ clock-names = "ext_clock"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ post-power-on-delay-ms = <200>; ++ power-off-delay-us = <10>; ++ ++ /* ++ * On the module itself this is one of these (depending ++ * on the actual card populated): ++ * - SDIO_RESET_L_WL_REG_ON ++ * - PDN (power down when low) ++ */ ++ reset-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wireless-wlan { ++ compatible = "wlan-platdata"; ++ rockchip,grf = <&grf>; ++ wifi_chip_type = "ap6354"; ++ sdio_vref = <1800>; ++ WIFI,host_wake_irq = <&gpio0 3 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wireless-bluetooth { ++ compatible = "bluetooth-platdata"; ++ clocks = <&rk808 1>; ++ clock-names = "ext_clock"; ++ /* wifi-bt-power-toggle; */ ++ uart_rts_gpios = <&gpio2 19 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default", "rts_gpio"; ++ pinctrl-0 = <&uart0_rts>; ++ pinctrl-1 = <&uart0_gpios>; ++ /* BT,power_gpio = <&gpio3 19 GPIO_ACTIVE_HIGH>; */ ++ BT,reset_gpio = <&gpio0 9 GPIO_ACTIVE_HIGH>; ++ BT,wake_gpio = <&gpio2 27 GPIO_ACTIVE_HIGH>; ++ BT,wake_host_irq = <&gpio0 4 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ test-power { ++ status = "okay"; ++ }; ++}; ++ ++&hdmi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ clock-frequency = <100000000>; ++ clock-freq-min-max = <100000 100000000>; ++ supports-sd; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ num-slots = <1>; ++ //sd-uhs-sdr104; ++ vqmmc-supply = <&vcc_sd>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; ++ card-detect-delay = <800>; ++ status = "okay"; ++}; ++ ++&sdio0 { ++ clock-frequency = <100000000>; ++ clock-freq-min-max = <200000 100000000>; ++ supports-sdio; ++ bus-width = <4>; ++ disable-wp; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ keep-power-in-suspend; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>; ++ sd-uhs-sdr104; ++ status = "okay"; ++}; ++ ++&emmc_phy { ++ status = "okay"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ mmc-hs400-1_8v; ++ supports-emmc; ++ non-removable; ++ mmc-hs400-enhanced-strobe; ++ status = "okay"; ++}; ++ ++&i2s0 { ++ status = "okay"; ++ rockchip,i2s-broken-burst-len; ++ rockchip,playback-channels = <8>; ++ rockchip,capture-channels = <8>; ++ #sound-dai-cells = <0>; ++}; ++ ++&i2s2 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&spdif { ++ pinctrl-0 = <&spdif_bus_1>; ++ status = "okay"; ++ #sound-dai-cells = <0>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ i2c-scl-rising-time-ns = <168>; ++ i2c-scl-falling-time-ns = <4>; ++ clock-frequency = <400000>; ++ ++ vdd_cpu_b: syr827@40 { ++ compatible = "silergy,syr827"; ++ reg = <0x40>; ++ regulator-compatible = "fan53555-reg"; ++ pinctrl-0 = <&vsel1_gpio>; ++ vsel-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>; ++ regulator-name = "vdd_cpu_b"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-ramp-delay = <1000>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc_sys>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: syr828@41 { ++ compatible = "silergy,syr828"; ++ reg = <0x41>; ++ regulator-compatible = "fan53555-reg"; ++ pinctrl-0 = <&vsel2_gpio>; ++ vsel-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; ++ regulator-name = "vdd_gpu"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-ramp-delay = <1000>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc_sys>; ++ regulator-initial-mode = <1>; /* 1:force PWM 2:auto */ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ rk808: pmic@1b { ++ compatible = "rockchip,rk808"; ++ reg = <0x1b>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <21 IRQ_TYPE_LEVEL_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk808-clkout2"; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc6-supply = <&vcc_sys>; ++ vcc7-supply = <&vcc_sys>; ++ vcc8-supply = <&vcc3v3_sys>; ++ vcc9-supply = <&vcc_sys>; ++ vcc10-supply = <&vcc_sys>; ++ vcc11-supply = <&vcc_sys>; ++ vcc12-supply = <&vcc3v3_sys>; ++ vddio-supply = <&vcc_1v8>; ++ ++ regulators { ++ vdd_center: DCDC_REG1 { ++ regulator-name = "vdd_center"; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_l: DCDC_REG2 { ++ regulator-name = "vdd_cpu_l"; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8: DCDC_REG4 { ++ regulator-name = "vcc_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc1v8_dvp: LDO_REG1 { ++ regulator-name = "vcc1v8_dvp"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcca1v8_hdmi: LDO_REG2 { ++ regulator-name = "vcca1v8_hdmi"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcca_1v8: LDO_REG3 { ++ regulator-name = "vcca_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc_sd: LDO_REG4 { ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc3v0_sd: LDO_REG5 { ++ regulator-name = "vcc3v0_sd"; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcc_1v5: LDO_REG6 { ++ regulator-name = "vcc_1v5"; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1500000>; ++ }; ++ }; ++ ++ vcca0v9_hdmi: LDO_REG7 { ++ regulator-name = "vcca0v9_hdmi"; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vcc_3v0: LDO_REG8 { ++ regulator-name = "vcc_3v0"; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcc3v3_s3: SWITCH_REG1 { ++ regulator-name = "vcc3v3_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_s0: SWITCH_REG2 { ++ regulator-name = "vcc3v3_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++}; ++ ++&i2c7 { ++ status = "okay"; ++}; ++ ++&i2c4 { ++ status = "okay"; ++ fusb0: fusb30x@22 { ++ compatible = "fairchild,fusb302"; ++ reg = <0x22>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fusb0_int>; ++ vbus-5v-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; ++ int-n-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++}; ++ ++&i2c2 { ++ status = "okay"; ++ camera0: camera-module@10 { ++ status = "disabled"; ++ compatible = "omnivision,ov13850-v4l2-i2c-subdev"; ++ reg = < 0x10 >; ++ device_type = "v4l2-i2c-subdev"; ++ clocks = <&cru SCLK_CIF_OUT>; ++ clock-names = "clk_cif_out"; ++ pinctrl-names = "rockchip,camera_default", ++ "rockchip,camera_sleep"; ++ pinctrl-0 = <&cam0_default_pins>; ++ pinctrl-1 = <&cam0_sleep_pins>; ++ //rockchip,pd-gpio = <&gpio4 4 GPIO_ACTIVE_LOW>; ++ rockchip,pwr-gpio = <&gpio4 4 GPIO_ACTIVE_HIGH>; ++ rockchip,rst-gpio = <&gpio3 29 GPIO_ACTIVE_LOW>; ++ rockchip,camera-module-mclk-name = "clk_cif_out"; ++ rockchip,camera-module-facing = "back"; ++ rockchip,camera-module-name = "cmk-cb0695-fv1"; ++ rockchip,camera-module-len-name = "lg9569a2"; ++ rockchip,camera-module-fov-h = "66.0"; ++ rockchip,camera-module-fov-v = "50.1"; ++ rockchip,camera-module-orientation = <0>; ++ rockchip,camera-module-iq-flip = <0>; ++ rockchip,camera-module-iq-mirror = <0>; ++ rockchip,camera-module-flip = <1>; ++ rockchip,camera-module-mirror = <0>; ++ ++ rockchip,camera-module-defrect0 = <2112 1568 0 0 2112 1568>; ++ rockchip,camera-module-defrect1 = <4224 3136 0 0 4224 3136>; ++ rockchip,camera-module-defrect3 = <3264 2448 0 0 3264 2448>; ++ rockchip,camera-module-flash-support = <1>; ++ rockchip,camera-module-mipi-dphy-index = <0>; ++ }; ++ ++ camera1: camera-module@36 { ++ status = "disabled"; ++ compatible = "omnivision,ov4690-v4l2-i2c-subdev"; ++ reg = <0x36>; ++ device_type = "v4l2-i2c-subdev"; ++ clocks = <&cru SCLK_CIF_OUT>; ++ clock-names = "clk_cif_out"; ++ pinctrl-names = "rockchip,camera_default", ++ "rockchip,camera_sleep"; ++ pinctrl-0 = <&cam0_default_pins>; ++ pinctrl-1 = <&cam0_sleep_pins>; ++ rockchip,pd-gpio = <&gpio3 4 GPIO_ACTIVE_LOW>; ++ //rockchip,pwr-gpio = <&gpio3 13 0>; ++ rockchip,rst-gpio = <&gpio2 10 GPIO_ACTIVE_LOW>; ++ rockchip,camera-module-mclk-name = "clk_cif_out"; ++ rockchip,camera-module-facing = "back"; ++ rockchip,camera-module-name = "LA6111PA"; ++ rockchip,camera-module-len-name = "YM6011P"; ++ rockchip,camera-module-fov-h = "116"; ++ rockchip,camera-module-fov-v = "61"; ++ rockchip,camera-module-orientation = <0>; ++ rockchip,camera-module-iq-flip = <0>; ++ rockchip,camera-module-iq-mirror = <0>; ++ rockchip,camera-module-flip = <0>; ++ rockchip,camera-module-mirror = <1>; ++ ++ rockchip,camera-module-defrect0 = <2688 1520 0 0 2688 1520>; ++ rockchip,camera-module-flash-support = <0>; ++ rockchip,camera-module-mipi-dphy-index = <0>; ++ }; ++ ++}; ++ ++&i2c7 { ++ status = "okay"; ++}; ++ ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l1 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l2 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l3 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&cpu_b1 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_gpu>; ++}; ++ ++&threshold { ++ temperature = <85000>; ++}; ++ ++&target { ++ temperature = <100000>; ++}; ++ ++&soc_crit { ++ temperature = <105000>; ++}; ++ ++&tcphy0 { ++ extcon = <&fusb0>; ++ status = "okay"; ++}; ++ ++&tcphy1 { ++ status = "okay"; ++}; ++ ++&tsadc { ++ /* tshut mode 0:CRU 1:GPIO */ ++ rockchip,hw-tshut-mode = <1>; ++ /* tshut polarity 0:LOW 1:HIGH */ ++ rockchip,hw-tshut-polarity = <1>; ++ rockchip,hw-tshut-temp = <110000>; ++ status = "okay"; ++}; ++ ++&u2phy0 { ++ status = "okay"; ++ extcon = <&fusb0>; ++ ++ u2phy0_otg: otg-port { ++ status = "okay"; ++ }; ++ ++ u2phy0_host: host-port { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++ }; ++}; ++ ++&u2phy1 { ++ status = "okay"; ++ ++ u2phy1_otg: otg-port { ++ status = "okay"; ++ }; ++ ++ u2phy1_host: host-port { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++ }; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_xfer &uart0_cts>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3_0 { ++ extcon = <&fusb0>; ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_0 { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&usbdrd3_1 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_1 { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&pwm2 { ++ status = "okay"; ++}; ++ ++&gmac { ++ phy-supply = <&vcc_phy>; ++ phy-mode = "rgmii"; ++ clock_in_out = "input"; ++ snps,reset-gpio = <&gpio3 15 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ assigned-clocks = <&cru SCLK_RMII_SRC>; ++ assigned-clock-parents = <&clkin_gmac>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&rgmii_pins>; ++ pinctrl-1 = <&rgmii_sleep_pins>; ++ tx_delay = <0x28>; ++ rx_delay = <0x11>; ++ status = "disabled"; ++}; ++ ++&saradc { ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ bt656-supply = <&vcc1v8_s0>; /* bt656_gpio2ab_ms */ ++ audio-supply = <&vcc1v8_s0>; /* audio_gpio3d4a_ms */ ++ sdmmc-supply = <&vcc_sd>; /* sdmmc_gpio4b_ms */ ++ gpio1830-supply = <&vcc_3v0>; /* gpio1833_gpio4cd_ms */ ++}; ++ ++&pcie_phy { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ ep-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>; ++ num-lanes = <4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_clkreqn_cpm>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ ++ sdio0 { ++ sdio0_bus1: sdio0-bus1 { ++ rockchip,pins = ++ <2 20 RK_FUNC_1 &pcfg_pull_up_20ma>; ++ }; ++ ++ sdio0_bus4: sdio0-bus4 { ++ rockchip,pins = ++ <2 20 RK_FUNC_1 &pcfg_pull_up_20ma>, ++ <2 21 RK_FUNC_1 &pcfg_pull_up_20ma>, ++ <2 22 RK_FUNC_1 &pcfg_pull_up_20ma>, ++ <2 23 RK_FUNC_1 &pcfg_pull_up_20ma>; ++ }; ++ ++ sdio0_cmd: sdio0-cmd { ++ rockchip,pins = ++ <2 24 RK_FUNC_1 &pcfg_pull_up_20ma>; ++ }; ++ ++ sdio0_clk: sdio0-clk { ++ rockchip,pins = ++ <2 25 RK_FUNC_1 &pcfg_pull_none_20ma>; ++ }; ++ }; ++ ++ sdmmc { ++ sdmmc_bus1: sdmmc-bus1 { ++ rockchip,pins = ++ <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>; ++ }; ++ ++ sdmmc_bus4: sdmmc-bus4 { ++ rockchip,pins = ++ <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>, ++ <4 9 RK_FUNC_1 &pcfg_pull_up_8ma>, ++ <4 10 RK_FUNC_1 &pcfg_pull_up_8ma>, ++ <4 11 RK_FUNC_1 &pcfg_pull_up_8ma>; ++ }; ++ ++ sdmmc_clk: sdmmc-clk { ++ rockchip,pins = ++ <4 12 RK_FUNC_1 &pcfg_pull_none_18ma>; ++ }; ++ ++ sdmmc_cmd: sdmmc-cmd { ++ rockchip,pins = ++ <4 13 RK_FUNC_1 &pcfg_pull_up_8ma>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = ++ <0 9 RK_FUNC_GPIO &pcfg_pull_none>, ++ <0 10 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ wireless-bluetooth { ++ uart0_gpios: uart0-gpios { ++ rockchip,pins = ++ <2 19 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb2 { ++ host_vbus_drv: host-vbus-drv { ++ rockchip,pins = ++ <4 25 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pcie { ++ pcie_drv: pcie-drv { ++ rockchip,pins = ++ <3 11 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = ++ <1 21 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ vsel1_gpio: vsel1-gpio { ++ rockchip,pins = ++ <1 17 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ ++ vsel2_gpio: vsel2-gpio { ++ rockchip,pins = ++ <1 14 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++ ++ gmac { ++ rgmii_sleep_pins: rgmii-sleep-pins { ++ rockchip,pins = ++ <3 15 RK_FUNC_GPIO &pcfg_output_low>; ++ }; ++ }; ++ ++ fusb30x { ++ fusb0_int: fusb0-int { ++ rockchip,pins = ++ <1 2 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; ++ ++&pvtm { ++ status = "okay"; ++}; ++ ++&pmu_pvtm { ++ status = "okay"; ++}; ++ ++&pmu_io_domains { ++ status = "okay"; ++ pmu1830-supply = <&vcc_1v8>; ++}; ++ ++&rockchip_suspend { ++ status = "okay"; ++ rockchip,sleep-debug-en = <0>; ++ rockchip,sleep-mode-config = < ++ (0 ++ | RKPM_SLP_ARMPD ++ | RKPM_SLP_PERILPPD ++ | RKPM_SLP_DDR_RET ++ | RKPM_SLP_PLLPD ++ | RKPM_SLP_CENTER_PD ++ | RKPM_SLP_AP_PWROFF ++ ) ++ >; ++ rockchip,wakeup-config = < ++ (0 ++ | RKPM_GPIO_WKUP_EN ++ | RKPM_PWM_WKUP_EN ++ ) ++ >; ++ rockchip,pwm-regulator-config = < ++ (0 ++ | PWM2_REGULATOR_EN ++ ) ++ >; ++ rockchip,power-ctrl = ++ <&gpio1 17 GPIO_ACTIVE_HIGH>, ++ <&gpio1 14 GPIO_ACTIVE_HIGH>; ++}; ++ ++&vopb { ++ status = "okay"; ++}; ++ ++&vopb_mmu { ++ status = "okay"; ++}; ++ ++&cif_isp0 { ++ rockchip,camera-modules-attached = <&camera0>; ++ status = "okay"; ++}; ++ ++&isp0_mmu { ++ status = "okay"; ++}; ++ ++&cif_isp1 { ++ rockchip,camera-modules-attached = <&camera1>; ++ status = "disabled"; ++}; ++ ++&isp1_mmu { ++ status = "okay"; ++}; ++ ++&vpu { ++ status = "okay"; ++ /* 0 means ion, 1 means drm */ ++ //allocator = <0>; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ /* 0 means ion, 1 means drm */ ++ //allocator = <0>; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; + +From 6dace0f751dbd697dd4481af949a102852f85c30 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 28 Jan 2018 15:38:32 +0100 +Subject: [PATCH] arm: dts: rk3288: add cec clock and pinctrl + +--- + arch/arm/boot/dts/rk3288.dtsi | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 0af92bd2a723..60a488b28f1c 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -947,6 +947,8 @@ + <&cru PCLK_MIPI_DSI1>, + <&cru SCLK_EDP_24M>, + <&cru SCLK_EDP>, ++ <&cru SCLK_HDMI_CEC>, ++ <&cru SCLK_HDMI_HDCP>, + <&cru SCLK_ISP_JPE>, + <&cru SCLK_ISP>, + <&cru SCLK_RGA>; +@@ -1524,10 +1526,10 @@ + reg-io-width = <4>; + rockchip,grf = <&grf>; + interrupts = ; +- clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>; +- clock-names = "iahb", "isfr"; ++ clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>; ++ clock-names = "iahb", "isfr", "cec"; + pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&hdmi_ddc>; ++ pinctrl-0 = <&hdmi_ddc>, <&hdmi_cec_c0>; + pinctrl-1 = <&hdmi_gpio>; + power-domains = <&power RK3288_PD_VIO>; + status = "disabled"; +@@ -1896,6 +1898,14 @@ + &pcfg_pull_none>; + }; + ++ hdmi_cec_c0: hdmi-cec-c0 { ++ rockchip,pins = <7 16 RK_FUNC_2 &pcfg_pull_none>; ++ }; ++ ++ hdmi_cec_c7: hdmi-cec-c7 { ++ rockchip,pins = <7 23 RK_FUNC_4 &pcfg_pull_none>; ++ }; ++ + hdmi_ddc: hdmi-ddc { + rockchip,pins = <7 19 RK_FUNC_2 &pcfg_pull_none>, + <7 20 RK_FUNC_2 &pcfg_pull_none>; diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0007-rtl8211f.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0007-rtl8211f.patch new file mode 100644 index 0000000000..d6d7b2c6e8 --- /dev/null +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0007-rtl8211f.patch @@ -0,0 +1,870 @@ +From 8c15967b21f2caf9897b1c4fa6c80b5de07aa7d0 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Fri, 25 Nov 2016 14:12:01 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: fix enabling of the TX-delay for + RTL8211F + +The old logic always enabled the TX-delay when the phy-mode was set to +PHY_INTERFACE_MODE_RGMII. There are dedicated phy-modes which tell the +PHY driver to enable the RX and/or TX delays: +- PHY_INTERFACE_MODE_RGMII should disable the RX and TX delay in the + PHY (if required, the MAC should add the delays in this case) +- PHY_INTERFACE_MODE_RGMII_ID should enable RX and TX delay in the PHY +- PHY_INTERFACE_MODE_RGMII_TXID should enable the TX delay in the PHY +- PHY_INTERFACE_MODE_RGMII_RXID should enable the RX delay in the PHY + (currently not supported by RTL8211F) + +With this patch we enable the TX delay for PHY_INTERFACE_MODE_RGMII_ID +and PHY_INTERFACE_MODE_RGMII_TXID. +Additionally we now explicity disable the TX-delay, which seems to be +enabled automatically after a hard-reset of the PHY (by triggering it's +reset pin) to get a consistent state (as defined by the phy-mode). + +This fixes a compatibility problem with some SoCs where the TX-delay was +also added by the MAC. With the TX-delay being applied twice the TX +clock was off and TX traffic was broken or very slow (<10Mbit/s) on +1000Mbit/s links. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +(cherry picked from commit e3230494b57ece68750e3e32d3e53d6b00917058) +--- + drivers/net/phy/realtek.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 43ab691362d4..686f3b259dc0 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -102,15 +102,19 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + +- if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { +- /* enable TXDLY */ +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08); +- reg = phy_read(phydev, 0x11); ++ phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08); ++ reg = phy_read(phydev, 0x11); ++ ++ /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ ++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) + reg |= RTL8211F_TX_DELAY; +- phy_write(phydev, 0x11, reg); +- /* restore to default page 0 */ +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); +- } ++ else ++ reg &= ~RTL8211F_TX_DELAY; ++ ++ phy_write(phydev, 0x11, reg); ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); + + return 0; + } + +From b3a985bdb18be879aa7a8ffe7fd9d7f1ee7a201d Mon Sep 17 00:00:00 2001 +From: Kunihiko Hayashi +Date: Tue, 12 Sep 2017 18:54:35 +0900 +Subject: [PATCH] UPSTREAM: net: phy: realtek: rename RTL8211F_PAGE_SELECT to + RTL821x_PAGE_SELECT + +This renames the definition of page select register from +RTL8211F_PAGE_SELECT to RTL821x_PAGE_SELECT to use it across models. + +Signed-off-by: Kunihiko Hayashi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit 013955a6556766a76f9f2cc31e740fc6db6ecff4) +--- + drivers/net/phy/realtek.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 686f3b259dc0..d58cc8f518ac 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -22,11 +22,11 @@ + #define RTL821x_INER 0x12 + #define RTL821x_INER_INIT 0x6400 + #define RTL821x_INSR 0x13 ++#define RTL821x_PAGE_SELECT 0x1f + #define RTL8211E_INER_LINK_STATUS 0x400 + + #define RTL8211F_INER_LINK_STATUS 0x0010 + #define RTL8211F_INSR 0x1d +-#define RTL8211F_PAGE_SELECT 0x1f + #define RTL8211F_TX_DELAY 0x100 + + MODULE_DESCRIPTION("Realtek PHY driver"); +@@ -46,10 +46,10 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev) + { + int err; + +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0xa43); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0xa43); + err = phy_read(phydev, RTL8211F_INSR); + /* restore to default page 0 */ +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); + + return (err < 0) ? err : 0; + } +@@ -102,7 +102,7 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0xd08); + reg = phy_read(phydev, 0x11); + + /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ +@@ -114,7 +114,7 @@ static int rtl8211f_config_init(struct phy_device *phydev) + + phy_write(phydev, 0x11, reg); + /* restore to default page 0 */ +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); + + return 0; + } + +From 3a2afedaf759bd28b2c94f4f1e9ef06909142728 Mon Sep 17 00:00:00 2001 +From: Jassi Brar +Date: Tue, 12 Sep 2017 18:54:36 +0900 +Subject: [PATCH] UPSTREAM: net: phy: realtek: add RTL8201F phy-id and + functions + +Add RTL8201F phy-id and the related functions to the driver. + +The original patch is as follows: +https://patchwork.kernel.org/patch/2538341/ + +Signed-off-by: Jongsung Kim +Signed-off-by: Jassi Brar +Signed-off-by: Kunihiko Hayashi +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +(cherry picked from commit 513588dd44b09bb5fdd5066a4fbc1e7443b86d1c) +--- + drivers/net/phy/realtek.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index d58cc8f518ac..422cf1f6a60c 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -29,10 +29,22 @@ + #define RTL8211F_INSR 0x1d + #define RTL8211F_TX_DELAY 0x100 + ++#define RTL8201F_ISR 0x1e ++#define RTL8201F_IER 0x13 ++ + MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); + MODULE_LICENSE("GPL"); + ++static int rtl8201_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read(phydev, RTL8201F_ISR); ++ ++ return (err < 0) ? err : 0; ++} ++ + static int rtl821x_ack_interrupt(struct phy_device *phydev) + { + int err; +@@ -54,6 +66,25 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev) + return (err < 0) ? err : 0; + } + ++static int rtl8201_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ ++ /* switch to page 7 */ ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x7); ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) ++ err = phy_write(phydev, RTL8201F_IER, ++ BIT(13) | BIT(12) | BIT(11)); ++ else ++ err = phy_write(phydev, RTL8201F_IER, 0); ++ ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ ++ return err; ++} ++ + static int rtl8211b_config_intr(struct phy_device *phydev) + { + int err; +@@ -129,6 +160,18 @@ static struct phy_driver realtek_drvs[] = { + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { .owner = THIS_MODULE,}, ++ }, { ++ .phy_id = 0x001cc816, ++ .name = "RTL8201F 10/100Mbps Ethernet", ++ .phy_id_mask = 0x001fffff, ++ .features = PHY_BASIC_FEATURES, ++ .flags = PHY_HAS_INTERRUPT, ++ .config_aneg = &genphy_config_aneg, ++ .read_status = &genphy_read_status, ++ .ack_interrupt = &rtl8201_ack_interrupt, ++ .config_intr = &rtl8201_config_intr, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, + }, { + .phy_id = 0x001cc912, + .name = "RTL8211B Gigabit Ethernet", +@@ -186,6 +229,7 @@ static struct phy_driver realtek_drvs[] = { + module_phy_driver(realtek_drvs); + + static struct mdio_device_id __maybe_unused realtek_tbl[] = { ++ { 0x001cc816, 0x001fffff }, + { 0x001cc912, 0x001fffff }, + { 0x001cc914, 0x001fffff }, + { 0x001cc915, 0x001fffff }, + +From 25fa2a3516b4836cc1ccf275dfb6f4eee1e21ba4 Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Sun, 12 Nov 2017 16:16:04 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: fix RTL8211F interrupt mode + +After commit b94d22d94ad22 "ARM64: dts: meson-gx: add external PHY +interrupt on some platforms" ethernet stopped working on my Odroid-C2 +which has a RTL8211F phy. + +It turned out that no interrupts were triggered. Further analysis +showed the register INER can't be altered on page 0. +Because register INSR needs to be accessed via page 0xa43 I assumed +that register INER needs to be accessed via some page too. +Some brute force check resulted in page 0xa42 being the right one. + +With this patch the phy is working properly in interrupt mode. + +Fixes: 3447cf2e9a11 ("net/phy: Add support for Realtek RTL8211F") +Signed-off-by: Heiner Kallweit +Tested-by: Jerome Brunet +Signed-off-by: David S. Miller +(cherry picked from commit 3697d058b08d5b874f0253de173ef72e5d648f9a) +--- + drivers/net/phy/realtek.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 422cf1f6a60c..a30d0c08c63b 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -115,11 +115,13 @@ static int rtl8211f_config_intr(struct phy_device *phydev) + { + int err; + ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0xa42); + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_write(phydev, RTL821x_INER, + RTL8211F_INER_LINK_STATUS); + else + err = phy_write(phydev, RTL821x_INER, 0); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0); + + return err; + } + +From 4c621c2c47a298310290c3a053f5d5b920470927 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:24 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: use the BIT and GENMASK macros + +This makes it easier to compare the #defines with the datasheets. +No functional changes. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit 8cc5baefbc0266b6d6c8e99cb8568f59be36a575) +--- + drivers/net/phy/realtek.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index a30d0c08c63b..f8dc29a75828 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -13,21 +13,22 @@ + * option) any later version. + * + */ ++#include + #include + #include + + #define RTL821x_PHYSR 0x11 +-#define RTL821x_PHYSR_DUPLEX 0x2000 +-#define RTL821x_PHYSR_SPEED 0xc000 ++#define RTL821x_PHYSR_DUPLEX BIT(13) ++#define RTL821x_PHYSR_SPEED GENMASK(15, 14) + #define RTL821x_INER 0x12 + #define RTL821x_INER_INIT 0x6400 + #define RTL821x_INSR 0x13 + #define RTL821x_PAGE_SELECT 0x1f +-#define RTL8211E_INER_LINK_STATUS 0x400 ++#define RTL8211E_INER_LINK_STATUS BIT(10) + +-#define RTL8211F_INER_LINK_STATUS 0x0010 ++#define RTL8211F_INER_LINK_STATUS BIT(4) + #define RTL8211F_INSR 0x1d +-#define RTL8211F_TX_DELAY 0x100 ++#define RTL8211F_TX_DELAY BIT(8) + + #define RTL8201F_ISR 0x1e + #define RTL8201F_IER 0x13 + +From 3167d5ad9d83b77af30fe513bef24430bc31bdb4 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:25 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: rename RTL821x_INER_INIT to + RTL8211B_INER_INIT + +This macro is only used by the RTL8211B code. RTL8211E and RTL8211F both +use other bits to initialize the RTL821x_INER register. +No functional changes. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit 69021e32ec3ef02170482f6ed8130febaed27357) +--- + drivers/net/phy/realtek.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index f8dc29a75828..89308eac4088 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -21,7 +21,7 @@ + #define RTL821x_PHYSR_DUPLEX BIT(13) + #define RTL821x_PHYSR_SPEED GENMASK(15, 14) + #define RTL821x_INER 0x12 +-#define RTL821x_INER_INIT 0x6400 ++#define RTL8211B_INER_INIT 0x6400 + #define RTL821x_INSR 0x13 + #define RTL821x_PAGE_SELECT 0x1f + #define RTL8211E_INER_LINK_STATUS BIT(10) +@@ -92,7 +92,7 @@ static int rtl8211b_config_intr(struct phy_device *phydev) + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_write(phydev, RTL821x_INER, +- RTL821x_INER_INIT); ++ RTL8211B_INER_INIT); + else + err = phy_write(phydev, RTL821x_INER, 0); + + +From 351cf2d39cbbf73ca6369f2967176bc24b30dba0 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:26 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: group all register bit #defines + for RTL821x_INER + +This simply moves all register bit #defines which describe the (PHY +specific) bits in the RTL821x_INER right below the RTL821x_INER register +definition. This makes it easier to spot which registers and bits belong +together. +No functional changes. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit a82f266d240d87e6111878bbfe287024fb6857c1) +--- + drivers/net/phy/realtek.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 89308eac4088..df97d903d2bf 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -20,13 +20,16 @@ + #define RTL821x_PHYSR 0x11 + #define RTL821x_PHYSR_DUPLEX BIT(13) + #define RTL821x_PHYSR_SPEED GENMASK(15, 14) ++ + #define RTL821x_INER 0x12 + #define RTL8211B_INER_INIT 0x6400 ++#define RTL8211E_INER_LINK_STATUS BIT(10) ++#define RTL8211F_INER_LINK_STATUS BIT(4) ++ + #define RTL821x_INSR 0x13 ++ + #define RTL821x_PAGE_SELECT 0x1f +-#define RTL8211E_INER_LINK_STATUS BIT(10) + +-#define RTL8211F_INER_LINK_STATUS BIT(4) + #define RTL8211F_INSR 0x1d + #define RTL8211F_TX_DELAY BIT(8) + + +From 2eca64452d4ba8d77ee9edf9a554ec122b2fe53a Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:27 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: use the same indentation for all + #defines + +This simply makes the code easier to read. No functional changes. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit f609ab0ed8e7bef2cd61d230bf9e83e1ec5b9ddb) +--- + drivers/net/phy/realtek.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index df97d903d2bf..701f34ad7d8d 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -17,24 +17,25 @@ + #include + #include + +-#define RTL821x_PHYSR 0x11 +-#define RTL821x_PHYSR_DUPLEX BIT(13) +-#define RTL821x_PHYSR_SPEED GENMASK(15, 14) ++#define RTL821x_PHYSR 0x11 ++#define RTL821x_PHYSR_DUPLEX BIT(13) ++#define RTL821x_PHYSR_SPEED GENMASK(15, 14) + +-#define RTL821x_INER 0x12 +-#define RTL8211B_INER_INIT 0x6400 +-#define RTL8211E_INER_LINK_STATUS BIT(10) +-#define RTL8211F_INER_LINK_STATUS BIT(4) ++#define RTL821x_INER 0x12 ++#define RTL8211B_INER_INIT 0x6400 ++#define RTL8211E_INER_LINK_STATUS BIT(10) ++#define RTL8211F_INER_LINK_STATUS BIT(4) + +-#define RTL821x_INSR 0x13 ++#define RTL821x_INSR 0x13 + +-#define RTL821x_PAGE_SELECT 0x1f ++#define RTL821x_PAGE_SELECT 0x1f + +-#define RTL8211F_INSR 0x1d +-#define RTL8211F_TX_DELAY BIT(8) ++#define RTL8211F_INSR 0x1d + +-#define RTL8201F_ISR 0x1e +-#define RTL8201F_IER 0x13 ++#define RTL8211F_TX_DELAY BIT(8) ++ ++#define RTL8201F_ISR 0x1e ++#define RTL8201F_IER 0x13 + + MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); + +From dedcf805b9b0cadc952d358a39ba5cfb7af7765e Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:28 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: add utility functions to + read/write page addresses + +Realtek PHYs implement the concept of so-called "extension pages". The +reason for this is probably because these PHYs expose more registers +than available in the standard address range. +After all read/write operations on such a page are done the driver +should switch back to page 0 where the standard MII registers (such as +MII_BMCR) are available. + +When referring to such a register the datasheets of RTL8211E and +RTL8211F always specify: +- the page / "ext. page" which has to be written to RTL821x_PAGE_SELECT +- an address (sometimes also called reg) + +These new utility functions make the existing code easier to read since +it removes some duplication (switching back to page 0 is done within the +new helpers for example). + +No functional changes are intended. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit 136819a6e8df374e6b9b424586ff11c9e241a1cb) +--- + drivers/net/phy/realtek.c | 83 ++++++++++++++++++++++++++++++----------------- + 1 file changed, 53 insertions(+), 30 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 701f34ad7d8d..b1d52e61d91c 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -41,6 +41,39 @@ MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); + MODULE_LICENSE("GPL"); + ++static int rtl8211x_page_read(struct phy_device *phydev, u16 page, u16 address) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, RTL821x_PAGE_SELECT, page); ++ if (ret) ++ return ret; ++ ++ ret = phy_read(phydev, address); ++ ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ ++ return ret; ++} ++ ++static int rtl8211x_page_write(struct phy_device *phydev, u16 page, ++ u16 address, u16 val) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, RTL821x_PAGE_SELECT, page); ++ if (ret) ++ return ret; ++ ++ ret = phy_write(phydev, address, val); ++ ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ ++ return ret; ++} ++ + static int rtl8201_ack_interrupt(struct phy_device *phydev) + { + int err; +@@ -63,31 +96,21 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev) + { + int err; + +- phy_write(phydev, RTL821x_PAGE_SELECT, 0xa43); +- err = phy_read(phydev, RTL8211F_INSR); +- /* restore to default page 0 */ +- phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ err = rtl8211x_page_read(phydev, 0xa43, RTL8211F_INSR); + + return (err < 0) ? err : 0; + } + + static int rtl8201_config_intr(struct phy_device *phydev) + { +- int err; +- +- /* switch to page 7 */ +- phy_write(phydev, RTL821x_PAGE_SELECT, 0x7); ++ u16 val; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) +- err = phy_write(phydev, RTL8201F_IER, +- BIT(13) | BIT(12) | BIT(11)); ++ val = BIT(13) | BIT(12) | BIT(11); + else +- err = phy_write(phydev, RTL8201F_IER, 0); ++ val = 0; + +- /* restore to default page 0 */ +- phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); +- +- return err; ++ return rtl8211x_page_write(phydev, 0x7, RTL8201F_IER, val); + } + + static int rtl8211b_config_intr(struct phy_device *phydev) +@@ -118,41 +141,41 @@ static int rtl8211e_config_intr(struct phy_device *phydev) + + static int rtl8211f_config_intr(struct phy_device *phydev) + { +- int err; ++ u16 val; + +- phy_write(phydev, RTL821x_PAGE_SELECT, 0xa42); + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) +- err = phy_write(phydev, RTL821x_INER, +- RTL8211F_INER_LINK_STATUS); ++ val = RTL8211F_INER_LINK_STATUS; + else +- err = phy_write(phydev, RTL821x_INER, 0); +- phy_write(phydev, RTL821x_PAGE_SELECT, 0); ++ val = 0; + +- return err; ++ return rtl8211x_page_write(phydev, 0xa42, RTL821x_INER, val); + } + + static int rtl8211f_config_init(struct phy_device *phydev) + { + int ret; +- u16 reg; ++ u16 val; + + ret = genphy_config_init(phydev); + if (ret < 0) + return ret; + +- phy_write(phydev, RTL821x_PAGE_SELECT, 0xd08); +- reg = phy_read(phydev, 0x11); ++ ret = rtl8211x_page_read(phydev, 0xd08, 0x11); ++ if (ret < 0) ++ return ret; ++ ++ val = ret & 0xffff; + + /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) +- reg |= RTL8211F_TX_DELAY; ++ val |= RTL8211F_TX_DELAY; + else +- reg &= ~RTL8211F_TX_DELAY; ++ val &= ~RTL8211F_TX_DELAY; + +- phy_write(phydev, 0x11, reg); +- /* restore to default page 0 */ +- phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ ret = rtl8211x_page_write(phydev, 0xd08, 0x11, val); ++ if (ret) ++ return ret; + + return 0; + } + +From 9fece68d69e33eadcb03bb9dfd4240be21357603 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 23:06:48 +0100 +Subject: [PATCH] FROMLIST: net: phy: realtek: add support for configuring the + RX delay on RTL8211F + +On RTL8211F the RX delay can also be enabled/disabled. +The overall behavior of the RX delay is similar to the behavior of the +TX delay, which was already supported by the driver. + +The RX delay (similar to the TX delay) may be enabled using hardware pin +strapping. If the MAC already configures the RX delay (if required) then +the RX delay generated by the RTL8211F PHY has to be turned off. + +While here, update the comment regarding the TX delay why it has to be +enabled or disabled within the driver. +Also avoid code-duplication by extracting the code to mask/unmask bits +in a paged register into a new rtl8211x_page_mask_bits helper function. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/phy/realtek.c | 55 ++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 45 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index b1d52e61d91c..890ea9d18d27 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -32,7 +32,10 @@ + + #define RTL8211F_INSR 0x1d + +-#define RTL8211F_TX_DELAY BIT(8) ++#define RTL8211F_RX_DELAY_REG 0x15 ++#define RTL8211F_RX_DELAY_EN BIT(3) ++#define RTL8211F_TX_DELAY_REG 0x11 ++#define RTL8211F_TX_DELAY_EN BIT(8) + + #define RTL8201F_ISR 0x1e + #define RTL8201F_IER 0x13 +@@ -74,6 +77,23 @@ static int rtl8211x_page_write(struct phy_device *phydev, u16 page, + return ret; + } + ++static int rtl8211x_page_mask_bits(struct phy_device *phydev, u16 page, ++ u16 address, u16 mask, u16 set) ++{ ++ int ret; ++ u16 val; ++ ++ ret = rtl8211x_page_read(phydev, page, address); ++ if (ret < 0) ++ return ret; ++ ++ val = ret & 0xffff; ++ val &= ~mask; ++ val |= (set & mask); ++ ++ return rtl8211x_page_write(phydev, page, address, val); ++} ++ + static int rtl8201_ack_interrupt(struct phy_device *phydev) + { + int err; +@@ -160,20 +180,35 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + +- ret = rtl8211x_page_read(phydev, 0xd08, 0x11); +- if (ret < 0) +- return ret; ++ /* ++ * enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it. ++ * this is needed because it can be enabled by pin strapping and ++ * conflict with the TX-delay configured by the MAC. ++ */ ++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ++ val = RTL8211F_TX_DELAY_EN; ++ else ++ val = 0; + +- val = ret & 0xffff; ++ ret = rtl8211x_page_mask_bits(phydev, 0xd08, RTL8211F_TX_DELAY_REG, ++ RTL8211F_TX_DELAY_EN, val); ++ if (ret) ++ return ret; + +- /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ ++ /* ++ * enable RX-delay for rgmii-id and rgmii-rxid, otherwise disable it. ++ * this is needed because it can be enabled by pin strapping and ++ * conflict with the RX-delay configured by the MAC. ++ */ + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || +- phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) +- val |= RTL8211F_TX_DELAY; ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ++ val = RTL8211F_RX_DELAY_EN; + else +- val &= ~RTL8211F_TX_DELAY; ++ val = 0; + +- ret = rtl8211x_page_write(phydev, 0xd08, 0x11, val); ++ ret = rtl8211x_page_mask_bits(phydev, 0xd08, RTL8211F_RX_DELAY_REG, ++ RTL8211F_RX_DELAY_EN, val); + if (ret) + return ret; + + +From 62c37a52b123444e2696963251428b0b9566721c Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 23:06:49 +0100 +Subject: [PATCH] FROMLIST: net: phy: realtek: configure the INTB pin on + RTL8211F + +The interrupt pin on the RTL8211F PHY can be used in two different +modes: +INTB +- the default mode of the PHY +- interrupts can be configured through page 0xa42 register RTL821x_INER +- interrupts can be ACK'ed through RTL8211F_INSR +- it acts as a level-interrupt which is active low +- Wake-on-LAN "wakeup" status is available in RTL8211F_INSR bit 7 + +PMEB: +- special mode for Wake-on-LAN +- interrupts configured through page 0xa42 register RTL821x_INER are + disabled +- it supports a "pulse low" waveform for the interrupt + +For now we simply force the pin into INTB mode since the PHY driver does +not support Wake-on-LAN yet. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/phy/realtek.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 890ea9d18d27..f307d220b49a 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -40,6 +40,9 @@ + #define RTL8201F_ISR 0x1e + #define RTL8201F_IER 0x13 + ++#define RTL8211F_INTBCR 0x16 ++#define RTL8211F_INTBCR_INTB_PMEB BIT(5) ++ + MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); + MODULE_LICENSE("GPL"); +@@ -161,12 +164,32 @@ static int rtl8211e_config_intr(struct phy_device *phydev) + + static int rtl8211f_config_intr(struct phy_device *phydev) + { ++ int err; + u16 val; + +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ /* ++ * The interrupt pin has two functions: ++ * 0: INTB: it acts as interrupt pin which can be configured ++ * through RTL821x_INER and the status can be read through ++ * RTL8211F_INSR ++ * 1: PMEB: a special "Power Management Event" mode for ++ * Wake-on-LAN operation (with support for a "pulse low" ++ * wave format). Interrupts configured through RTL821x_INER ++ * will not work in this mode ++ * ++ * select INTB mode in the "INTB pin control" register to ++ * ensure that the interrupt pin is in the correct mode. ++ */ ++ err = rtl8211x_page_mask_bits(phydev, 0xd40, RTL8211F_INTBCR, ++ RTL8211F_INTBCR_INTB_PMEB, 0); ++ if (err) ++ return err; ++ + val = RTL8211F_INER_LINK_STATUS; +- else ++ } else { + val = 0; ++ } + + return rtl8211x_page_write(phydev, 0xa42, RTL821x_INER, val); + } + +From 4ea16aca3e2095f6904f1a534d8c668c383f595b Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 23:06:50 +0100 +Subject: [PATCH] FROMLIST: net: phy: realtek: add more interrupt bits for + RTL8211E and RTL8211F + +This documents a few more bits in the RTL821x_INER register for RTL8211E +and RTL8211F. These are added only to document them (as no public +datasheets are available for these PHYs), they are currently not used. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/phy/realtek.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index f307d220b49a..15d342eefd6d 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -24,7 +24,14 @@ + #define RTL821x_INER 0x12 + #define RTL8211B_INER_INIT 0x6400 + #define RTL8211E_INER_LINK_STATUS BIT(10) ++#define RTL8211E_INER_ANEG_COMPLETED BIT(11) ++#define RTL8211E_INER_PAGE_RECEIVED BIT(12) ++#define RTL8211E_INER_ANEG_ERROR BIT(15) + #define RTL8211F_INER_LINK_STATUS BIT(4) ++#define RTL8211F_INER_PHY_REGISTER_ACCESSIBLE BIT(5) ++#define RTL8211F_INER_WOL_PME BIT(7) ++#define RTL8211F_INER_ALDPS_STATE_CHANGE BIT(9) ++#define RTL8211F_INER_JABBER BIT(10) + + #define RTL821x_INSR 0x13 + diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0008-dtoverlay-configfs.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0008-dtoverlay-configfs.patch new file mode 100644 index 0000000000..10faee01de --- /dev/null +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0008-dtoverlay-configfs.patch @@ -0,0 +1,1120 @@ +From 76d5a6e8f8b6a9574e52ff1ff303d09a55f2474c Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou +Date: Thu, 22 Oct 2015 23:30:04 +0300 +Subject: [PATCH] UPSTREAM: configfs: implement binary attributes + +ConfigFS lacked binary attributes up until now. This patch +introduces support for binary attributes in a somewhat similar +manner of sysfs binary attributes albeit with changes that +fit the configfs usage model. + +Problems that configfs binary attributes fix are everything that +requires a binary blob as part of the configuration of a resource, +such as bitstream loading for FPGAs, DTBs for dynamically created +devices etc. + +Look at Documentation/filesystems/configfs/configfs.txt for internals +and howto use them. + +This patch is against linux-next as of today that contains +Christoph's configfs rework. + +Signed-off-by: Pantelis Antoniou +[hch: folded a fix from Geert Uytterhoeven ] +[hch: a few tiny updates based on review feedback] +Signed-off-by: Christoph Hellwig +(cherry picked from commit 03607ace807b414eab46323c794b6fb8fcc2d48c) +--- + Documentation/filesystems/configfs/configfs.txt | 57 +++++- + fs/configfs/configfs_internal.h | 14 +- + fs/configfs/dir.c | 18 +- + fs/configfs/file.c | 255 +++++++++++++++++++++++- + fs/configfs/inode.c | 2 +- + include/linux/configfs.h | 50 +++++ + 6 files changed, 374 insertions(+), 22 deletions(-) + +diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt +index af68efdbbfad..e5fe521eea1d 100644 +--- a/Documentation/filesystems/configfs/configfs.txt ++++ b/Documentation/filesystems/configfs/configfs.txt +@@ -51,15 +51,27 @@ configfs tree is always there, whether mounted on /config or not. + An item is created via mkdir(2). The item's attributes will also + appear at this time. readdir(3) can determine what the attributes are, + read(2) can query their default values, and write(2) can store new +-values. Like sysfs, attributes should be ASCII text files, preferably +-with only one value per file. The same efficiency caveats from sysfs +-apply. Don't mix more than one attribute in one attribute file. +- +-Like sysfs, configfs expects write(2) to store the entire buffer at +-once. When writing to configfs attributes, userspace processes should +-first read the entire file, modify the portions they wish to change, and +-then write the entire buffer back. Attribute files have a maximum size +-of one page (PAGE_SIZE, 4096 on i386). ++values. Don't mix more than one attribute in one attribute file. ++ ++There are two types of configfs attributes: ++ ++* Normal attributes, which similar to sysfs attributes, are small ASCII text ++files, with a maximum size of one page (PAGE_SIZE, 4096 on i386). Preferably ++only one value per file should be used, and the same caveats from sysfs apply. ++Configfs expects write(2) to store the entire buffer at once. When writing to ++normal configfs attributes, userspace processes should first read the entire ++file, modify the portions they wish to change, and then write the entire ++buffer back. ++ ++* Binary attributes, which are somewhat similar to sysfs binary attributes, ++but with a few slight changes to semantics. The PAGE_SIZE limitation does not ++apply, but the whole binary item must fit in single kernel vmalloc'ed buffer. ++The write(2) calls from user space are buffered, and the attributes' ++write_bin_attribute method will be invoked on the final close, therefore it is ++imperative for user-space to check the return code of close(2) in order to ++verify that the operation finished successfully. ++To avoid a malicious user OOMing the kernel, there's a per-binary attribute ++maximum buffer value. + + When an item needs to be destroyed, remove it with rmdir(2). An + item cannot be destroyed if any other item has a link to it (via +@@ -171,6 +183,7 @@ among other things. For that, it needs a type. + struct configfs_item_operations *ct_item_ops; + struct configfs_group_operations *ct_group_ops; + struct configfs_attribute **ct_attrs; ++ struct configfs_bin_attribute **ct_bin_attrs; + }; + + The most basic function of a config_item_type is to define what +@@ -201,6 +214,32 @@ be called whenever userspace asks for a read(2) on the attribute. If an + attribute is writable and provides a ->store method, that method will be + be called whenever userspace asks for a write(2) on the attribute. + ++[struct configfs_bin_attribute] ++ ++ struct configfs_attribute { ++ struct configfs_attribute cb_attr; ++ void *cb_private; ++ size_t cb_max_size; ++ }; ++ ++The binary attribute is used when the one needs to use binary blob to ++appear as the contents of a file in the item's configfs directory. ++To do so add the binary attribute to the NULL-terminated array ++config_item_type->ct_bin_attrs, and the item appears in configfs, the ++attribute file will appear with the configfs_bin_attribute->cb_attr.ca_name ++filename. configfs_bin_attribute->cb_attr.ca_mode specifies the file ++permissions. ++The cb_private member is provided for use by the driver, while the ++cb_max_size member specifies the maximum amount of vmalloc buffer ++to be used. ++ ++If binary attribute is readable and the config_item provides a ++ct_item_ops->read_bin_attribute() method, that method will be called ++whenever userspace asks for a read(2) on the attribute. The converse ++will happen for write(2). The reads/writes are bufferred so only a ++single read/write will occur; the attributes' need not concern itself ++with it. ++ + [struct config_group] + + A config_item cannot live in a vacuum. The only way one can be created +diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h +index b65d1ef532d5..ccc31fa6f1a7 100644 +--- a/fs/configfs/configfs_internal.h ++++ b/fs/configfs/configfs_internal.h +@@ -53,13 +53,14 @@ struct configfs_dirent { + #define CONFIGFS_ROOT 0x0001 + #define CONFIGFS_DIR 0x0002 + #define CONFIGFS_ITEM_ATTR 0x0004 ++#define CONFIGFS_ITEM_BIN_ATTR 0x0008 + #define CONFIGFS_ITEM_LINK 0x0020 + #define CONFIGFS_USET_DIR 0x0040 + #define CONFIGFS_USET_DEFAULT 0x0080 + #define CONFIGFS_USET_DROPPING 0x0100 + #define CONFIGFS_USET_IN_MKDIR 0x0200 + #define CONFIGFS_USET_CREATING 0x0400 +-#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR) ++#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR) + + extern struct mutex configfs_symlink_mutex; + extern spinlock_t configfs_dirent_lock; +@@ -72,6 +73,8 @@ extern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *, + extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct inode *)); + + extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); ++extern int configfs_create_bin_file(struct config_item *, ++ const struct configfs_bin_attribute *); + extern int configfs_make_dirent(struct configfs_dirent *, + struct dentry *, void *, umode_t, int); + extern int configfs_dirent_is_ready(struct configfs_dirent *); +@@ -88,7 +91,7 @@ extern void configfs_release_fs(void); + extern struct rw_semaphore configfs_rename_sem; + extern const struct file_operations configfs_dir_operations; + extern const struct file_operations configfs_file_operations; +-extern const struct file_operations bin_fops; ++extern const struct file_operations configfs_bin_file_operations; + extern const struct inode_operations configfs_dir_inode_operations; + extern const struct inode_operations configfs_root_inode_operations; + extern const struct inode_operations configfs_symlink_inode_operations; +@@ -119,6 +122,13 @@ static inline struct configfs_attribute * to_attr(struct dentry * dentry) + return ((struct configfs_attribute *) sd->s_element); + } + ++static inline struct configfs_bin_attribute *to_bin_attr(struct dentry *dentry) ++{ ++ struct configfs_attribute *attr = to_attr(dentry); ++ ++ return container_of(attr, struct configfs_bin_attribute, cb_attr); ++} ++ + static inline struct config_item *configfs_get_config_item(struct dentry *dentry) + { + struct config_item * item = NULL; +diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c +index a7a1b218f308..7ae97e83f121 100644 +--- a/fs/configfs/dir.c ++++ b/fs/configfs/dir.c +@@ -255,6 +255,12 @@ static void configfs_init_file(struct inode * inode) + inode->i_fop = &configfs_file_operations; + } + ++static void configfs_init_bin_file(struct inode *inode) ++{ ++ inode->i_size = 0; ++ inode->i_fop = &configfs_bin_file_operations; ++} ++ + static void init_symlink(struct inode * inode) + { + inode->i_op = &configfs_symlink_inode_operations; +@@ -423,7 +429,9 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den + spin_unlock(&configfs_dirent_lock); + + error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, +- configfs_init_file); ++ (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) ? ++ configfs_init_bin_file : ++ configfs_init_file); + if (error) { + configfs_put(sd); + return error; +@@ -583,6 +591,7 @@ static int populate_attrs(struct config_item *item) + { + struct config_item_type *t = item->ci_type; + struct configfs_attribute *attr; ++ struct configfs_bin_attribute *bin_attr; + int error = 0; + int i; + +@@ -594,6 +603,13 @@ static int populate_attrs(struct config_item *item) + break; + } + } ++ if (t->ct_bin_attrs) { ++ for (i = 0; (bin_attr = t->ct_bin_attrs[i]) != NULL; i++) { ++ error = configfs_create_bin_file(item, bin_attr); ++ if (error) ++ break; ++ } ++ } + + if (error) + detach_attrs(item); +diff --git a/fs/configfs/file.c b/fs/configfs/file.c +index d39099ea7df7..3687187c8ea5 100644 +--- a/fs/configfs/file.c ++++ b/fs/configfs/file.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -48,6 +49,10 @@ struct configfs_buffer { + struct configfs_item_operations * ops; + struct mutex mutex; + int needs_read_fill; ++ bool read_in_progress; ++ bool write_in_progress; ++ char *bin_buffer; ++ int bin_buffer_size; + }; + + +@@ -123,6 +128,87 @@ out: + return retval; + } + ++/** ++ * configfs_read_bin_file - read a binary attribute. ++ * @file: file pointer. ++ * @buf: buffer to fill. ++ * @count: number of bytes to read. ++ * @ppos: starting offset in file. ++ * ++ * Userspace wants to read a binary attribute file. The attribute ++ * descriptor is in the file's ->d_fsdata. The target item is in the ++ * directory's ->d_fsdata. ++ * ++ * We check whether we need to refill the buffer. If so we will ++ * call the attributes' attr->read() twice. The first time we ++ * will pass a NULL as a buffer pointer, which the attributes' method ++ * will use to return the size of the buffer required. If no error ++ * occurs we will allocate the buffer using vmalloc and call ++ * attr->read() again passing that buffer as an argument. ++ * Then we just copy to user-space using simple_read_from_buffer. ++ */ ++ ++static ssize_t ++configfs_read_bin_file(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct configfs_buffer *buffer = file->private_data; ++ struct dentry *dentry = file->f_path.dentry; ++ struct config_item *item = to_item(dentry->d_parent); ++ struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); ++ ssize_t retval = 0; ++ ssize_t len = min_t(size_t, count, PAGE_SIZE); ++ ++ mutex_lock(&buffer->mutex); ++ ++ /* we don't support switching read/write modes */ ++ if (buffer->write_in_progress) { ++ retval = -ETXTBSY; ++ goto out; ++ } ++ buffer->read_in_progress = 1; ++ ++ if (buffer->needs_read_fill) { ++ /* perform first read with buf == NULL to get extent */ ++ len = bin_attr->read(item, NULL, 0); ++ if (len <= 0) { ++ retval = len; ++ goto out; ++ } ++ ++ /* do not exceed the maximum value */ ++ if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) { ++ retval = -EFBIG; ++ goto out; ++ } ++ ++ buffer->bin_buffer = vmalloc(len); ++ if (buffer->bin_buffer == NULL) { ++ retval = -ENOMEM; ++ goto out; ++ } ++ buffer->bin_buffer_size = len; ++ ++ /* perform second read to fill buffer */ ++ len = bin_attr->read(item, buffer->bin_buffer, len); ++ if (len < 0) { ++ retval = len; ++ vfree(buffer->bin_buffer); ++ buffer->bin_buffer_size = 0; ++ buffer->bin_buffer = NULL; ++ goto out; ++ } ++ ++ buffer->needs_read_fill = 0; ++ } ++ ++ retval = simple_read_from_buffer(buf, count, ppos, buffer->bin_buffer, ++ buffer->bin_buffer_size); ++out: ++ mutex_unlock(&buffer->mutex); ++ return retval; ++} ++ + + /** + * fill_write_buffer - copy buffer from userspace. +@@ -209,10 +295,80 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof + return len; + } + +-static int check_perm(struct inode * inode, struct file * file) ++/** ++ * configfs_write_bin_file - write a binary attribute. ++ * @file: file pointer ++ * @buf: data to write ++ * @count: number of bytes ++ * @ppos: starting offset ++ * ++ * Writing to a binary attribute file is similar to a normal read. ++ * We buffer the consecutive writes (binary attribute files do not ++ * support lseek) in a continuously growing buffer, but we don't ++ * commit until the close of the file. ++ */ ++ ++static ssize_t ++configfs_write_bin_file(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct configfs_buffer *buffer = file->private_data; ++ struct dentry *dentry = file->f_path.dentry; ++ struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); ++ void *tbuf = NULL; ++ ssize_t len; ++ ++ mutex_lock(&buffer->mutex); ++ ++ /* we don't support switching read/write modes */ ++ if (buffer->read_in_progress) { ++ len = -ETXTBSY; ++ goto out; ++ } ++ buffer->write_in_progress = 1; ++ ++ /* buffer grows? */ ++ if (*ppos + count > buffer->bin_buffer_size) { ++ ++ if (bin_attr->cb_max_size && ++ *ppos + count > bin_attr->cb_max_size) { ++ len = -EFBIG; ++ } ++ ++ tbuf = vmalloc(*ppos + count); ++ if (tbuf == NULL) { ++ len = -ENOMEM; ++ goto out; ++ } ++ ++ /* copy old contents */ ++ if (buffer->bin_buffer) { ++ memcpy(tbuf, buffer->bin_buffer, ++ buffer->bin_buffer_size); ++ vfree(buffer->bin_buffer); ++ } ++ ++ /* clear the new area */ ++ memset(tbuf + buffer->bin_buffer_size, 0, ++ *ppos + count - buffer->bin_buffer_size); ++ buffer->bin_buffer = tbuf; ++ buffer->bin_buffer_size = *ppos + count; ++ } ++ ++ len = simple_write_to_buffer(buffer->bin_buffer, ++ buffer->bin_buffer_size, ppos, buf, count); ++ if (len > 0) ++ *ppos += len; ++out: ++ mutex_unlock(&buffer->mutex); ++ return len; ++} ++ ++static int check_perm(struct inode * inode, struct file * file, int type) + { + struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent); + struct configfs_attribute * attr = to_attr(file->f_path.dentry); ++ struct configfs_bin_attribute *bin_attr = NULL; + struct configfs_buffer * buffer; + struct configfs_item_operations * ops = NULL; + int error = 0; +@@ -220,6 +376,9 @@ static int check_perm(struct inode * inode, struct file * file) + if (!item || !attr) + goto Einval; + ++ if (type & CONFIGFS_ITEM_BIN_ATTR) ++ bin_attr = to_bin_attr(file->f_path.dentry); ++ + /* Grab the module reference for this attribute if we have one */ + if (!try_module_get(attr->ca_owner)) { + error = -ENODEV; +@@ -236,9 +395,14 @@ static int check_perm(struct inode * inode, struct file * file) + * and we must have a store method. + */ + if (file->f_mode & FMODE_WRITE) { +- if (!(inode->i_mode & S_IWUGO) || !attr->store) ++ if (!(inode->i_mode & S_IWUGO)) ++ goto Eaccess; ++ ++ if ((type & CONFIGFS_ITEM_ATTR) && !attr->store) + goto Eaccess; + ++ if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->write) ++ goto Eaccess; + } + + /* File needs read support. +@@ -246,7 +410,13 @@ static int check_perm(struct inode * inode, struct file * file) + * must be a show method for it. + */ + if (file->f_mode & FMODE_READ) { +- if (!(inode->i_mode & S_IRUGO) || !attr->show) ++ if (!(inode->i_mode & S_IRUGO)) ++ goto Eaccess; ++ ++ if ((type & CONFIGFS_ITEM_ATTR) && !attr->show) ++ goto Eaccess; ++ ++ if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->read) + goto Eaccess; + } + +@@ -260,6 +430,8 @@ static int check_perm(struct inode * inode, struct file * file) + } + mutex_init(&buffer->mutex); + buffer->needs_read_fill = 1; ++ buffer->read_in_progress = 0; ++ buffer->write_in_progress = 0; + buffer->ops = ops; + file->private_data = buffer; + goto Done; +@@ -277,12 +449,7 @@ static int check_perm(struct inode * inode, struct file * file) + return error; + } + +-static int configfs_open_file(struct inode * inode, struct file * filp) +-{ +- return check_perm(inode,filp); +-} +- +-static int configfs_release(struct inode * inode, struct file * filp) ++static int configfs_release(struct inode *inode, struct file *filp) + { + struct config_item * item = to_item(filp->f_path.dentry->d_parent); + struct configfs_attribute * attr = to_attr(filp->f_path.dentry); +@@ -303,6 +470,47 @@ static int configfs_release(struct inode * inode, struct file * filp) + return 0; + } + ++static int configfs_open_file(struct inode *inode, struct file *filp) ++{ ++ return check_perm(inode, filp, CONFIGFS_ITEM_ATTR); ++} ++ ++static int configfs_open_bin_file(struct inode *inode, struct file *filp) ++{ ++ return check_perm(inode, filp, CONFIGFS_ITEM_BIN_ATTR); ++} ++ ++static int configfs_release_bin_file(struct inode *inode, struct file *filp) ++{ ++ struct configfs_buffer *buffer = filp->private_data; ++ struct dentry *dentry = filp->f_path.dentry; ++ struct config_item *item = to_item(dentry->d_parent); ++ struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); ++ ssize_t len = 0; ++ int ret; ++ ++ buffer->read_in_progress = 0; ++ ++ if (buffer->write_in_progress) { ++ buffer->write_in_progress = 0; ++ ++ len = bin_attr->write(item, buffer->bin_buffer, ++ buffer->bin_buffer_size); ++ ++ /* vfree on NULL is safe */ ++ vfree(buffer->bin_buffer); ++ buffer->bin_buffer = NULL; ++ buffer->bin_buffer_size = 0; ++ buffer->needs_read_fill = 1; ++ } ++ ++ ret = configfs_release(inode, filp); ++ if (len < 0) ++ return len; ++ return ret; ++} ++ ++ + const struct file_operations configfs_file_operations = { + .read = configfs_read_file, + .write = configfs_write_file, +@@ -311,6 +519,14 @@ const struct file_operations configfs_file_operations = { + .release = configfs_release, + }; + ++const struct file_operations configfs_bin_file_operations = { ++ .read = configfs_read_bin_file, ++ .write = configfs_write_bin_file, ++ .llseek = NULL, /* bin file is not seekable */ ++ .open = configfs_open_bin_file, ++ .release = configfs_release_bin_file, ++}; ++ + /** + * configfs_create_file - create an attribute file for an item. + * @item: item we're creating for. +@@ -332,3 +548,24 @@ int configfs_create_file(struct config_item * item, const struct configfs_attrib + return error; + } + ++/** ++ * configfs_create_bin_file - create a binary attribute file for an item. ++ * @item: item we're creating for. ++ * @attr: atrribute descriptor. ++ */ ++ ++int configfs_create_bin_file(struct config_item *item, ++ const struct configfs_bin_attribute *bin_attr) ++{ ++ struct dentry *dir = item->ci_dentry; ++ struct configfs_dirent *parent_sd = dir->d_fsdata; ++ umode_t mode = (bin_attr->cb_attr.ca_mode & S_IALLUGO) | S_IFREG; ++ int error = 0; ++ ++ mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_NORMAL); ++ error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode, ++ CONFIGFS_ITEM_BIN_ATTR); ++ mutex_unlock(&dir->d_inode->i_mutex); ++ ++ return error; ++} +diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c +index eae87575e681..0cc810e9dccc 100644 +--- a/fs/configfs/inode.c ++++ b/fs/configfs/inode.c +@@ -218,7 +218,7 @@ const unsigned char * configfs_get_name(struct configfs_dirent *sd) + if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK)) + return sd->s_dentry->d_name.name; + +- if (sd->s_type & CONFIGFS_ITEM_ATTR) { ++ if (sd->s_type & (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR)) { + attr = sd->s_element; + return attr->ca_name; + } +diff --git a/include/linux/configfs.h b/include/linux/configfs.h +index 758a029011b1..f7300d023dbe 100644 +--- a/include/linux/configfs.h ++++ b/include/linux/configfs.h +@@ -51,6 +51,7 @@ struct module; + struct configfs_item_operations; + struct configfs_group_operations; + struct configfs_attribute; ++struct configfs_bin_attribute; + struct configfs_subsystem; + + struct config_item { +@@ -84,6 +85,7 @@ struct config_item_type { + struct configfs_item_operations *ct_item_ops; + struct configfs_group_operations *ct_group_ops; + struct configfs_attribute **ct_attrs; ++ struct configfs_bin_attribute **ct_bin_attrs; + }; + + /** +@@ -154,6 +156,54 @@ static struct configfs_attribute _pfx##attr_##_name = { \ + .store = _pfx##_name##_store, \ + } + ++struct file; ++struct vm_area_struct; ++ ++struct configfs_bin_attribute { ++ struct configfs_attribute cb_attr; /* std. attribute */ ++ void *cb_private; /* for user */ ++ size_t cb_max_size; /* max core size */ ++ ssize_t (*read)(struct config_item *, void *, size_t); ++ ssize_t (*write)(struct config_item *, const void *, size_t); ++}; ++ ++#define CONFIGFS_BIN_ATTR(_pfx, _name, _priv, _maxsz) \ ++static struct configfs_bin_attribute _pfx##attr_##_name = { \ ++ .cb_attr = { \ ++ .ca_name = __stringify(_name), \ ++ .ca_mode = S_IRUGO | S_IWUSR, \ ++ .ca_owner = THIS_MODULE, \ ++ }, \ ++ .cb_private = _priv, \ ++ .cb_max_size = _maxsz, \ ++ .read = _pfx##_name##_read, \ ++ .write = _pfx##_name##_write, \ ++} ++ ++#define CONFIGFS_BIN_ATTR_RO(_pfx, _name, _priv, _maxsz) \ ++static struct configfs_attribute _pfx##attr_##_name = { \ ++ .cb_attr = { \ ++ .ca_name = __stringify(_name), \ ++ .ca_mode = S_IRUGO, \ ++ .ca_owner = THIS_MODULE, \ ++ }, \ ++ .cb_private = _priv, \ ++ .cb_max_size = _maxsz, \ ++ .read = _pfx##_name##_read, \ ++} ++ ++#define CONFIGFS_BIN_ATTR_WO(_pfx, _name, _priv, _maxsz) \ ++static struct configfs_attribute _pfx##attr_##_name = { \ ++ .cb_attr = { \ ++ .ca_name = __stringify(_name), \ ++ .ca_mode = S_IWUSR, \ ++ .ca_owner = THIS_MODULE, \ ++ }, \ ++ .cb_private = _priv, \ ++ .cb_max_size = _maxsz, \ ++ .write = _pfx##_name##_write, \ ++} ++ + /* + * If allow_link() exists, the item can symlink(2) out to other + * items. If the item is a group, it may support mkdir(2). + +From 31cda7c76173d5a63f153191237764201c6b0f6c Mon Sep 17 00:00:00 2001 +From: Octavian Purdila +Date: Wed, 23 Mar 2016 14:14:48 +0200 +Subject: [PATCH] UPSTREAM: configfs: fix CONFIGFS_BIN_ATTR_[RW]O definitions + +The type should be struct configfs_bin_attribute and not struct +configfs_attribute. + +Signed-off-by: Octavian Purdila +Signed-off-by: Christoph Hellwig +(cherry picked from commit 96c22a3293512ba684e73a981196430f524689da) +--- + include/linux/configfs.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/configfs.h b/include/linux/configfs.h +index f7300d023dbe..658066d63180 100644 +--- a/include/linux/configfs.h ++++ b/include/linux/configfs.h +@@ -181,7 +181,7 @@ static struct configfs_bin_attribute _pfx##attr_##_name = { \ + } + + #define CONFIGFS_BIN_ATTR_RO(_pfx, _name, _priv, _maxsz) \ +-static struct configfs_attribute _pfx##attr_##_name = { \ ++static struct configfs_bin_attribute _pfx##attr_##_name = { \ + .cb_attr = { \ + .ca_name = __stringify(_name), \ + .ca_mode = S_IRUGO, \ +@@ -193,7 +193,7 @@ static struct configfs_attribute _pfx##attr_##_name = { \ + } + + #define CONFIGFS_BIN_ATTR_WO(_pfx, _name, _priv, _maxsz) \ +-static struct configfs_attribute _pfx##attr_##_name = { \ ++static struct configfs_bin_attribute _pfx##attr_##_name = { \ + .cb_attr = { \ + .ca_name = __stringify(_name), \ + .ca_mode = S_IWUSR, \ + +From 8f9101e3d38691c7f17057173b32a57a2173382f Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou +Date: Wed, 4 Dec 2013 19:32:00 +0200 +Subject: [PATCH] FROMLIST: OF: DT-Overlay configfs interface (v7) + +Add a runtime interface to using configfs for generic device tree overlay +usage. With it its possible to use device tree overlays without having +to use a per-platform overlay manager. + +Please see Documentation/devicetree/configfs-overlays.txt for more info. + +Changes since v6: +- Default groups properties API changed. + +Changes since v5: +- New style configfs. + +Changes since v4: +- Loading fix for multiple overlays as found out by + Geert Uytterhoeven + +Changes since v3: +- Fixed compilation on SPARC & Xtensa + +Changes since v2: +- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) +- Created a documentation entry +- Slight rewording in Kconfig + +Changes since v1: +- of_resolve() -> of_resolve_phandles(). + +Signed-off-by: Pantelis Antoniou +[geert: Use %zu to format size_t] +[geert: Let OF_CONFIGFS select OF_FLATTREE to fix sparc all*config] +Signed-off-by: Geert Uytterhoeven +--- + Documentation/devicetree/configfs-overlays.txt | 31 +++ + drivers/of/Kconfig | 8 + + drivers/of/Makefile | 1 + + drivers/of/configfs.c | 314 +++++++++++++++++++++++++ + 4 files changed, 354 insertions(+) + create mode 100644 Documentation/devicetree/configfs-overlays.txt + create mode 100644 drivers/of/configfs.c + +diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt +new file mode 100644 +index 000000000000..5fa43e064307 +--- /dev/null ++++ b/Documentation/devicetree/configfs-overlays.txt +@@ -0,0 +1,31 @@ ++Howto use the configfs overlay interface. ++ ++A device-tree configfs entry is created in /config/device-tree/overlays ++and and it is manipulated using standard file system I/O. ++Note that this is a debug level interface, for use by developers and ++not necessarily something accessed by normal users due to the ++security implications of having direct access to the kernel's device tree. ++ ++* To create an overlay you mkdir the directory: ++ ++ # mkdir /config/device-tree/overlays/foo ++ ++* Either you echo the overlay firmware file to the path property file. ++ ++ # echo foo.dtbo >/config/device-tree/overlays/foo/path ++ ++* Or you cat the contents of the overlay to the dtbo file ++ ++ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo ++ ++The overlay file will be applied, and devices will be created/destroyed ++as required. ++ ++To remove it simply rmdir the directory. ++ ++ # rmdir /config/device-tree/overlays/foo ++ ++The rationalle of the dual interface (firmware & direct copy) is that each is ++better suited to different use patterns. The firmware interface is what's ++intended to be used by hardware managers in the kernel, while the copy interface ++make sense for developers (since it avoids problems with namespaces). +diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig +index e2a48415d969..c112c9f2ca6b 100644 +--- a/drivers/of/Kconfig ++++ b/drivers/of/Kconfig +@@ -112,4 +112,12 @@ config OF_OVERLAY + While this option is selected automatically when needed, you can + enable it manually to improve device tree unit test coverage. + ++config OF_CONFIGFS ++ bool "Device Tree Overlay ConfigFS interface" ++ select CONFIGFS_FS ++ select OF_FLATTREE ++ depends on OF_OVERLAY ++ help ++ Enable a simple user-space driven DT overlay interface. ++ + endif # OF +diff --git a/drivers/of/Makefile b/drivers/of/Makefile +index 478d4edcd763..732fa66b5263 100644 +--- a/drivers/of/Makefile ++++ b/drivers/of/Makefile +@@ -1,4 +1,5 @@ + obj-y = base.o device.o platform.o property.o ++obj-$(CONFIG_OF_CONFIGFS) += configfs.o + obj-$(CONFIG_OF_DYNAMIC) += dynamic.o + obj-$(CONFIG_OF_FLATTREE) += fdt.o + obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o +diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c +new file mode 100644 +index 000000000000..908ce4960c30 +--- /dev/null ++++ b/drivers/of/configfs.c +@@ -0,0 +1,314 @@ ++/* ++ * Configfs entries for device-tree ++ * ++ * Copyright (C) 2013 - Pantelis Antoniou ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "of_private.h" ++ ++struct cfs_overlay_item { ++ struct config_item item; ++ ++ char path[PATH_MAX]; ++ ++ const struct firmware *fw; ++ struct device_node *overlay; ++ int ov_id; ++ ++ void *dtbo; ++ int dtbo_size; ++}; ++ ++static int create_overlay(struct cfs_overlay_item *overlay, void *blob) ++{ ++ int err; ++ ++ /* unflatten the tree */ ++ of_fdt_unflatten_tree(blob, &overlay->overlay); ++ if (overlay->overlay == NULL) { ++ pr_err("%s: failed to unflatten tree\n", __func__); ++ err = -EINVAL; ++ goto out_err; ++ } ++ pr_debug("%s: unflattened OK\n", __func__); ++ ++ /* mark it as detached */ ++ of_node_set_flag(overlay->overlay, OF_DETACHED); ++ ++ /* perform resolution */ ++ err = of_resolve_phandles(overlay->overlay); ++ if (err != 0) { ++ pr_err("%s: Failed to resolve tree\n", __func__); ++ goto out_err; ++ } ++ pr_debug("%s: resolved OK\n", __func__); ++ ++ err = of_overlay_create(overlay->overlay); ++ if (err < 0) { ++ pr_err("%s: Failed to create overlay (err=%d)\n", ++ __func__, err); ++ goto out_err; ++ } ++ overlay->ov_id = err; ++ ++out_err: ++ return err; ++} ++ ++static inline struct cfs_overlay_item *to_cfs_overlay_item( ++ struct config_item *item) ++{ ++ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; ++} ++ ++static ssize_t cfs_overlay_item_path_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ return sprintf(page, "%s\n", overlay->path); ++} ++ ++static ssize_t cfs_overlay_item_path_store(struct config_item *item, ++ const char *page, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ const char *p = page; ++ char *s; ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy to path buffer (and make sure it's always zero terminated */ ++ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); ++ overlay->path[sizeof(overlay->path) - 1] = '\0'; ++ ++ /* strip trailing newlines */ ++ s = overlay->path + strlen(overlay->path); ++ while (s > overlay->path && *--s == '\n') ++ *s = '\0'; ++ ++ pr_debug("%s: path is '%s'\n", __func__, overlay->path); ++ ++ err = request_firmware(&overlay->fw, overlay->path, NULL); ++ if (err != 0) ++ goto out_err; ++ ++ err = create_overlay(overlay, (void *)overlay->fw->data); ++ if (err < 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ ++ release_firmware(overlay->fw); ++ overlay->fw = NULL; ++ ++ overlay->path[0] = '\0'; ++ return err; ++} ++ ++static ssize_t cfs_overlay_item_status_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ return sprintf(page, "%s\n", ++ overlay->ov_id >= 0 ? "applied" : "unapplied"); ++} ++ ++CONFIGFS_ATTR(cfs_overlay_item_, path); ++CONFIGFS_ATTR_RO(cfs_overlay_item_, status); ++ ++static struct configfs_attribute *cfs_overlay_attrs[] = { ++ &cfs_overlay_item_attr_path, ++ &cfs_overlay_item_attr_status, ++ NULL, ++}; ++ ++ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, ++ void *buf, size_t max_count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ pr_debug("%s: buf=%p max_count=%zu\n", __func__, ++ buf, max_count); ++ ++ if (overlay->dtbo == NULL) ++ return 0; ++ ++ /* copy if buffer provided */ ++ if (buf != NULL) { ++ /* the buffer must be large enough */ ++ if (overlay->dtbo_size > max_count) ++ return -ENOSPC; ++ ++ memcpy(buf, overlay->dtbo, overlay->dtbo_size); ++ } ++ ++ return overlay->dtbo_size; ++} ++ ++ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, ++ const void *buf, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy the contents */ ++ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); ++ if (overlay->dtbo == NULL) ++ return -ENOMEM; ++ ++ overlay->dtbo_size = count; ++ ++ err = create_overlay(overlay, overlay->dtbo); ++ if (err < 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ kfree(overlay->dtbo); ++ overlay->dtbo = NULL; ++ overlay->dtbo_size = 0; ++ ++ return err; ++} ++ ++CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); ++ ++static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { ++ &cfs_overlay_item_attr_dtbo, ++ NULL, ++}; ++ ++static void cfs_overlay_release(struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ if (overlay->ov_id >= 0) ++ of_overlay_destroy(overlay->ov_id); ++ if (overlay->fw) ++ release_firmware(overlay->fw); ++ /* kfree with NULL is safe */ ++ kfree(overlay->dtbo); ++ kfree(overlay); ++} ++ ++static struct configfs_item_operations cfs_overlay_item_ops = { ++ .release = cfs_overlay_release, ++}; ++ ++static struct config_item_type cfs_overlay_type = { ++ .ct_item_ops = &cfs_overlay_item_ops, ++ .ct_attrs = cfs_overlay_attrs, ++ .ct_bin_attrs = cfs_overlay_bin_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct config_item *cfs_overlay_group_make_item( ++ struct config_group *group, const char *name) ++{ ++ struct cfs_overlay_item *overlay; ++ ++ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); ++ if (!overlay) ++ return ERR_PTR(-ENOMEM); ++ overlay->ov_id = -1; ++ ++ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); ++ return &overlay->item; ++} ++ ++static void cfs_overlay_group_drop_item(struct config_group *group, ++ struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ config_item_put(&overlay->item); ++} ++ ++static struct configfs_group_operations overlays_ops = { ++ .make_item = cfs_overlay_group_make_item, ++ .drop_item = cfs_overlay_group_drop_item, ++}; ++ ++static struct config_item_type overlays_type = { ++ .ct_group_ops = &overlays_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct configfs_group_operations of_cfs_ops = { ++ /* empty - we don't allow anything to be created */ ++}; ++ ++static struct config_item_type of_cfs_type = { ++ .ct_group_ops = &of_cfs_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++struct config_group of_cfs_overlay_group; ++ ++struct config_group *of_cfs_def_groups[] = { ++ &of_cfs_overlay_group, ++ NULL ++}; ++ ++static struct configfs_subsystem of_cfs_subsys = { ++ .su_group = { ++ .cg_item = { ++ .ci_namebuf = "device-tree", ++ .ci_type = &of_cfs_type, ++ }, ++ .default_groups = of_cfs_def_groups, ++ }, ++ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), ++}; ++ ++static int __init of_cfs_init(void) ++{ ++ int ret; ++ ++ pr_info("%s\n", __func__); ++ ++ config_group_init(&of_cfs_subsys.su_group); ++ config_group_init_type_name(&of_cfs_overlay_group, "overlays", ++ &overlays_type); ++ ++ ret = configfs_register_subsystem(&of_cfs_subsys); ++ if (ret != 0) { ++ pr_err("%s: failed to register subsys\n", __func__); ++ goto out; ++ } ++ pr_info("%s: OK\n", __func__); ++out: ++ return ret; ++} ++late_initcall(of_cfs_init); diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-0009-mmc-pwrseq.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0009-mmc-pwrseq.patch new file mode 100644 index 0000000000..89219c55de --- /dev/null +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-0009-mmc-pwrseq.patch @@ -0,0 +1,949 @@ +From bbfc2a0527160401e8e668a0dbeb6fc7ad8ad625 Mon Sep 17 00:00:00 2001 +From: Julia Lawall +Date: Sat, 14 Nov 2015 18:05:20 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq: constify mmc_pwrseq_ops structures + +The mmc_pwrseq_ops structures are never modified, so declare them as const. + +Done with the help of Coccinelle. + +Signed-off-by: Julia Lawall +Signed-off-by: Ulf Hansson +(cherry picked from commit ffedbd2210f2f4cba490a9205adc11fd1b89a852) +--- + drivers/mmc/core/pwrseq.h | 2 +- + drivers/mmc/core/pwrseq_emmc.c | 2 +- + drivers/mmc/core/pwrseq_simple.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h +index 096da48c6a7e..133de0426687 100644 +--- a/drivers/mmc/core/pwrseq.h ++++ b/drivers/mmc/core/pwrseq.h +@@ -16,7 +16,7 @@ struct mmc_pwrseq_ops { + }; + + struct mmc_pwrseq { +- struct mmc_pwrseq_ops *ops; ++ const struct mmc_pwrseq_ops *ops; + }; + + #ifdef CONFIG_OF +diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c +index ad4f94ec7e8d..4a82bc77fe49 100644 +--- a/drivers/mmc/core/pwrseq_emmc.c ++++ b/drivers/mmc/core/pwrseq_emmc.c +@@ -51,7 +51,7 @@ static void mmc_pwrseq_emmc_free(struct mmc_host *host) + kfree(pwrseq); + } + +-static struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { ++static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { + .post_power_on = mmc_pwrseq_emmc_reset, + .free = mmc_pwrseq_emmc_free, + }; +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index d10538bb5e07..2b16263458af 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -87,7 +87,7 @@ static void mmc_pwrseq_simple_free(struct mmc_host *host) + kfree(pwrseq); + } + +-static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { ++static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { + .pre_power_on = mmc_pwrseq_simple_pre_power_on, + .post_power_on = mmc_pwrseq_simple_post_power_on, + .power_off = mmc_pwrseq_simple_power_off, + +From 20acf1170bc2135cd600fceb97a18dcd7468fcfc Mon Sep 17 00:00:00 2001 +From: Martin Fuzzey +Date: Wed, 20 Jan 2016 16:08:03 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq_simple: Make reset-gpios optional to + match doc + +The DT binding doc says reset-gpios is an optional property but the code +currently bails out if it is omitted. + +This is a regression since it breaks previously working device trees. +Fix it by restoring the original documented behaviour. + +Fixes: ce037275861e ("mmc: pwrseq_simple: use GPIO descriptors array API") +Tested-by: Tony Lindgren +Signed-off-by: Martin Fuzzey +Signed-off-by: Ulf Hansson +(cherry picked from commit 64a67d4762ce3ce4c9466eadd152d825fbf84967) +--- + drivers/mmc/core/pwrseq_simple.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index 2b16263458af..aba786daebca 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -29,15 +29,18 @@ struct mmc_pwrseq_simple { + static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, + int value) + { +- int i; + struct gpio_descs *reset_gpios = pwrseq->reset_gpios; +- int values[reset_gpios->ndescs]; + +- for (i = 0; i < reset_gpios->ndescs; i++) +- values[i] = value; ++ if (!IS_ERR(reset_gpios)) { ++ int i; ++ int values[reset_gpios->ndescs]; + +- gpiod_set_array_value_cansleep(reset_gpios->ndescs, reset_gpios->desc, +- values); ++ for (i = 0; i < reset_gpios->ndescs; i++) ++ values[i] = value; ++ ++ gpiod_set_array_value_cansleep( ++ reset_gpios->ndescs, reset_gpios->desc, values); ++ } + } + + static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) +@@ -79,7 +82,8 @@ static void mmc_pwrseq_simple_free(struct mmc_host *host) + struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, + struct mmc_pwrseq_simple, pwrseq); + +- gpiod_put_array(pwrseq->reset_gpios); ++ if (!IS_ERR(pwrseq->reset_gpios)) ++ gpiod_put_array(pwrseq->reset_gpios); + + if (!IS_ERR(pwrseq->ext_clk)) + clk_put(pwrseq->ext_clk); +@@ -112,7 +116,9 @@ struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, + } + + pwrseq->reset_gpios = gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH); +- if (IS_ERR(pwrseq->reset_gpios)) { ++ if (IS_ERR(pwrseq->reset_gpios) && ++ PTR_ERR(pwrseq->reset_gpios) != -ENOENT && ++ PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) { + ret = PTR_ERR(pwrseq->reset_gpios); + goto clk_put; + } + +From 6eab92ee9750e9e1f82f600ecfdd5e1990bb50e6 Mon Sep 17 00:00:00 2001 +From: Peter Chen +Date: Wed, 6 Jan 2016 11:34:10 +0800 +Subject: [PATCH] UPSTREAM: mmc: core: pwrseq_simple: remove unused header file + +Signed-off-by: Peter Chen +Signed-off-by: Ulf Hansson +(cherry picked from commit 62c03ca3ffa1ddf55a66411be02f7e4678771fce) +--- + drivers/mmc/core/pwrseq_simple.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index aba786daebca..bc173e18b71c 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -12,7 +12,6 @@ + #include + #include + #include +-#include + #include + + #include + +From 0eb034a2e78479467e7b0551f7b1ac3cfeec3c07 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Thu, 14 Apr 2016 14:02:14 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq_simple: add to_pwrseq_simple() macro + +This patch adds to_pwrseq_simple() macro to make the code more readable. + +Signed-off-by: Srinivas Kandagatla +Signed-off-by: Ulf Hansson +(cherry picked from commit 5b96fea730ab79bdf6f8071cadf8208296bf5e8d) +--- + drivers/mmc/core/pwrseq_simple.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index bc173e18b71c..f94271bb1f6b 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -25,6 +25,8 @@ struct mmc_pwrseq_simple { + struct gpio_descs *reset_gpios; + }; + ++#define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq) ++ + static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, + int value) + { +@@ -44,8 +46,7 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, + + static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) + { +- struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_simple, pwrseq); ++ struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + if (!IS_ERR(pwrseq->ext_clk) && !pwrseq->clk_enabled) { + clk_prepare_enable(pwrseq->ext_clk); +@@ -57,16 +58,14 @@ static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) + + static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host) + { +- struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_simple, pwrseq); ++ struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); + } + + static void mmc_pwrseq_simple_power_off(struct mmc_host *host) + { +- struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_simple, pwrseq); ++ struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); + +@@ -78,8 +77,7 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host) + + static void mmc_pwrseq_simple_free(struct mmc_host *host) + { +- struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_simple, pwrseq); ++ struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + if (!IS_ERR(pwrseq->reset_gpios)) + gpiod_put_array(pwrseq->reset_gpios); + +From adfbca02ae62674576d6d88a30ef9c1d8ec502fa Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Thu, 14 Apr 2016 14:02:15 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq_emmc: add to_pwrseq_emmc() macro + +This patch adds to_pwrseq_emmc() macro to make the code more readable. + +Signed-off-by: Srinivas Kandagatla +Signed-off-by: Ulf Hansson +(cherry picked from commit f01b72d0fd53b61cafd25b16d15e18b1ef8ae065) +--- + drivers/mmc/core/pwrseq_emmc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c +index 4a82bc77fe49..c2d732aa464c 100644 +--- a/drivers/mmc/core/pwrseq_emmc.c ++++ b/drivers/mmc/core/pwrseq_emmc.c +@@ -25,6 +25,8 @@ struct mmc_pwrseq_emmc { + struct gpio_desc *reset_gpio; + }; + ++#define to_pwrseq_emmc(p) container_of(p, struct mmc_pwrseq_emmc, pwrseq) ++ + static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq) + { + gpiod_set_value(pwrseq->reset_gpio, 1); +@@ -35,16 +37,14 @@ static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq) + + static void mmc_pwrseq_emmc_reset(struct mmc_host *host) + { +- struct mmc_pwrseq_emmc *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_emmc, pwrseq); ++ struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); + + __mmc_pwrseq_emmc_reset(pwrseq); + } + + static void mmc_pwrseq_emmc_free(struct mmc_host *host) + { +- struct mmc_pwrseq_emmc *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_emmc, pwrseq); ++ struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); + + unregister_restart_handler(&pwrseq->reset_nb); + gpiod_put(pwrseq->reset_gpio); + +From 107ec2633bdbfb18f18b80ad2b9bd9c1a43fe3d8 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Thu, 14 Apr 2016 14:02:16 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq: convert to proper platform device + +simple-pwrseq and emmc-pwrseq drivers rely on platform_device +structure from of_find_device_by_node(), this works mostly. But, as there +is no driver associated with this devices, cases like default/init pinctrl +setup would never be performed by pwrseq. This becomes problem when the +gpios used in pwrseq require pinctrl setup. + +Currently most of the common pinctrl setup is done in +drivers/base/pinctrl.c by pinctrl_bind_pins(). + +There are two ways to solve this issue on either convert pwrseq drivers +to a proper platform drivers or copy the exact code from +pcintrl_bind_pins(). I prefer converting pwrseq to proper drivers so that +other cases like setting up clks/parents from dt would also be possible. + +Signed-off-by: Srinivas Kandagatla +Signed-off-by: Ulf Hansson +(cherry picked from commit d97a1e5d7cd2b5b0edc02a40fe6897b710c9e10f) +--- + drivers/mmc/core/Kconfig | 22 ++++++++ + drivers/mmc/core/Makefile | 4 +- + drivers/mmc/core/pwrseq.c | 108 ++++++++++++++++++--------------------- + drivers/mmc/core/pwrseq.h | 19 ++++--- + drivers/mmc/core/pwrseq_emmc.c | 75 +++++++++++++++++---------- + drivers/mmc/core/pwrseq_simple.c | 79 +++++++++++++++------------- + 6 files changed, 178 insertions(+), 129 deletions(-) + +diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig +index 87cc07dedd9f..00dfaea06003 100644 +--- a/drivers/mmc/core/Kconfig ++++ b/drivers/mmc/core/Kconfig +@@ -16,3 +16,25 @@ config MMC_PARANOID_SD_INIT + about re-trying SD init requests. This can be a useful + work-around for buggy controllers and hardware. Enable + if you are experiencing issues with SD detection. ++ ++config PWRSEQ_EMMC ++ tristate "HW reset support for eMMC" ++ default y ++ depends on OF ++ help ++ This selects Hardware reset support aka pwrseq-emmc for eMMC ++ devices. By default this option is set to y. ++ ++ This driver can also be built as a module. If so, the module ++ will be called pwrseq_emmc. ++ ++config PWRSEQ_SIMPLE ++ tristate "Simple HW reset support for MMC" ++ default y ++ depends on OF ++ help ++ This selects simple hardware reset support aka pwrseq-simple for MMC ++ devices. By default this option is set to y. ++ ++ This driver can also be built as a module. If so, the module ++ will be called pwrseq_simple. +diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile +index 2c25138f28b7..f007151dfdc6 100644 +--- a/drivers/mmc/core/Makefile ++++ b/drivers/mmc/core/Makefile +@@ -8,5 +8,7 @@ mmc_core-y := core.o bus.o host.o \ + sdio.o sdio_ops.o sdio_bus.o \ + sdio_cis.o sdio_io.o sdio_irq.o \ + quirks.o slot-gpio.o +-mmc_core-$(CONFIG_OF) += pwrseq.o pwrseq_simple.o pwrseq_emmc.o ++mmc_core-$(CONFIG_OF) += pwrseq.o ++obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o ++obj-$(CONFIG_PWRSEQ_EMMC) += pwrseq_emmc.o + mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o +diff --git a/drivers/mmc/core/pwrseq.c b/drivers/mmc/core/pwrseq.c +index 4c1d1757dbf9..9386c4771814 100644 +--- a/drivers/mmc/core/pwrseq.c ++++ b/drivers/mmc/core/pwrseq.c +@@ -8,88 +8,55 @@ + * MMC power sequence management + */ + #include +-#include + #include ++#include + #include +-#include + + #include + + #include "pwrseq.h" + +-struct mmc_pwrseq_match { +- const char *compatible; +- struct mmc_pwrseq *(*alloc)(struct mmc_host *host, struct device *dev); +-}; +- +-static struct mmc_pwrseq_match pwrseq_match[] = { +- { +- .compatible = "mmc-pwrseq-simple", +- .alloc = mmc_pwrseq_simple_alloc, +- }, { +- .compatible = "mmc-pwrseq-emmc", +- .alloc = mmc_pwrseq_emmc_alloc, +- }, +-}; +- +-static struct mmc_pwrseq_match *mmc_pwrseq_find(struct device_node *np) +-{ +- struct mmc_pwrseq_match *match = ERR_PTR(-ENODEV); +- int i; +- +- for (i = 0; i < ARRAY_SIZE(pwrseq_match); i++) { +- if (of_device_is_compatible(np, pwrseq_match[i].compatible)) { +- match = &pwrseq_match[i]; +- break; +- } +- } +- +- return match; +-} ++static DEFINE_MUTEX(pwrseq_list_mutex); ++static LIST_HEAD(pwrseq_list); + + int mmc_pwrseq_alloc(struct mmc_host *host) + { +- struct platform_device *pdev; + struct device_node *np; +- struct mmc_pwrseq_match *match; +- struct mmc_pwrseq *pwrseq; +- int ret = 0; ++ struct mmc_pwrseq *p; + + np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0); + if (!np) + return 0; + +- pdev = of_find_device_by_node(np); +- if (!pdev) { +- ret = -ENODEV; +- goto err; +- } ++ mutex_lock(&pwrseq_list_mutex); ++ list_for_each_entry(p, &pwrseq_list, pwrseq_node) { ++ if (p->dev->of_node == np) { ++ if (!try_module_get(p->owner)) ++ dev_err(host->parent, ++ "increasing module refcount failed\n"); ++ else ++ host->pwrseq = p; + +- match = mmc_pwrseq_find(np); +- if (IS_ERR(match)) { +- ret = PTR_ERR(match); +- goto err; ++ break; ++ } + } + +- pwrseq = match->alloc(host, &pdev->dev); +- if (IS_ERR(pwrseq)) { +- ret = PTR_ERR(pwrseq); +- goto err; +- } ++ of_node_put(np); ++ mutex_unlock(&pwrseq_list_mutex); ++ ++ if (!host->pwrseq) ++ return -EPROBE_DEFER; + +- host->pwrseq = pwrseq; + dev_info(host->parent, "allocated mmc-pwrseq\n"); + +-err: +- of_node_put(np); +- return ret; ++ return 0; + } + + void mmc_pwrseq_pre_power_on(struct mmc_host *host) + { + struct mmc_pwrseq *pwrseq = host->pwrseq; + +- if (pwrseq && pwrseq->ops && pwrseq->ops->pre_power_on) ++ if (pwrseq && pwrseq->ops->pre_power_on) + pwrseq->ops->pre_power_on(host); + } + +@@ -97,7 +64,7 @@ void mmc_pwrseq_post_power_on(struct mmc_host *host) + { + struct mmc_pwrseq *pwrseq = host->pwrseq; + +- if (pwrseq && pwrseq->ops && pwrseq->ops->post_power_on) ++ if (pwrseq && pwrseq->ops->post_power_on) + pwrseq->ops->post_power_on(host); + } + +@@ -105,7 +72,7 @@ void mmc_pwrseq_power_off(struct mmc_host *host) + { + struct mmc_pwrseq *pwrseq = host->pwrseq; + +- if (pwrseq && pwrseq->ops && pwrseq->ops->power_off) ++ if (pwrseq && pwrseq->ops->power_off) + pwrseq->ops->power_off(host); + } + +@@ -113,8 +80,31 @@ void mmc_pwrseq_free(struct mmc_host *host) + { + struct mmc_pwrseq *pwrseq = host->pwrseq; + +- if (pwrseq && pwrseq->ops && pwrseq->ops->free) +- pwrseq->ops->free(host); ++ if (pwrseq) { ++ module_put(pwrseq->owner); ++ host->pwrseq = NULL; ++ } ++} ++ ++int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq) ++{ ++ if (!pwrseq || !pwrseq->ops || !pwrseq->dev) ++ return -EINVAL; + +- host->pwrseq = NULL; ++ mutex_lock(&pwrseq_list_mutex); ++ list_add(&pwrseq->pwrseq_node, &pwrseq_list); ++ mutex_unlock(&pwrseq_list_mutex); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(mmc_pwrseq_register); ++ ++void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq) ++{ ++ if (pwrseq) { ++ mutex_lock(&pwrseq_list_mutex); ++ list_del(&pwrseq->pwrseq_node); ++ mutex_unlock(&pwrseq_list_mutex); ++ } + } ++EXPORT_SYMBOL_GPL(mmc_pwrseq_unregister); +diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h +index 133de0426687..d69e751f148b 100644 +--- a/drivers/mmc/core/pwrseq.h ++++ b/drivers/mmc/core/pwrseq.h +@@ -8,32 +8,39 @@ + #ifndef _MMC_CORE_PWRSEQ_H + #define _MMC_CORE_PWRSEQ_H + ++#include ++ + struct mmc_pwrseq_ops { + void (*pre_power_on)(struct mmc_host *host); + void (*post_power_on)(struct mmc_host *host); + void (*power_off)(struct mmc_host *host); +- void (*free)(struct mmc_host *host); + }; + + struct mmc_pwrseq { + const struct mmc_pwrseq_ops *ops; ++ struct device *dev; ++ struct list_head pwrseq_node; ++ struct module *owner; + }; + + #ifdef CONFIG_OF + ++int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq); ++void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq); ++ + int mmc_pwrseq_alloc(struct mmc_host *host); + void mmc_pwrseq_pre_power_on(struct mmc_host *host); + void mmc_pwrseq_post_power_on(struct mmc_host *host); + void mmc_pwrseq_power_off(struct mmc_host *host); + void mmc_pwrseq_free(struct mmc_host *host); + +-struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, +- struct device *dev); +-struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, +- struct device *dev); +- + #else + ++static inline int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq) ++{ ++ return -ENOSYS; ++} ++static inline void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq) {} + static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; } + static inline void mmc_pwrseq_pre_power_on(struct mmc_host *host) {} + static inline void mmc_pwrseq_post_power_on(struct mmc_host *host) {} +diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c +index c2d732aa464c..adc9c0c614fb 100644 +--- a/drivers/mmc/core/pwrseq_emmc.c ++++ b/drivers/mmc/core/pwrseq_emmc.c +@@ -9,6 +9,9 @@ + */ + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -42,20 +45,6 @@ static void mmc_pwrseq_emmc_reset(struct mmc_host *host) + __mmc_pwrseq_emmc_reset(pwrseq); + } + +-static void mmc_pwrseq_emmc_free(struct mmc_host *host) +-{ +- struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); +- +- unregister_restart_handler(&pwrseq->reset_nb); +- gpiod_put(pwrseq->reset_gpio); +- kfree(pwrseq); +-} +- +-static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { +- .post_power_on = mmc_pwrseq_emmc_reset, +- .free = mmc_pwrseq_emmc_free, +-}; +- + static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, + unsigned long mode, void *cmd) + { +@@ -66,21 +55,22 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, + return NOTIFY_DONE; + } + +-struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, +- struct device *dev) ++static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { ++ .post_power_on = mmc_pwrseq_emmc_reset, ++}; ++ ++static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) + { + struct mmc_pwrseq_emmc *pwrseq; +- int ret = 0; ++ struct device *dev = &pdev->dev; + +- pwrseq = kzalloc(sizeof(struct mmc_pwrseq_emmc), GFP_KERNEL); ++ pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); + if (!pwrseq) +- return ERR_PTR(-ENOMEM); ++ return -ENOMEM; + +- pwrseq->reset_gpio = gpiod_get(dev, "reset", GPIOD_OUT_LOW); +- if (IS_ERR(pwrseq->reset_gpio)) { +- ret = PTR_ERR(pwrseq->reset_gpio); +- goto free; +- } ++ pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); ++ if (IS_ERR(pwrseq->reset_gpio)) ++ return PTR_ERR(pwrseq->reset_gpio); + + /* + * register reset handler to ensure emmc reset also from +@@ -92,9 +82,38 @@ struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, + register_restart_handler(&pwrseq->reset_nb); + + pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; ++ pwrseq->pwrseq.dev = dev; ++ pwrseq->pwrseq.owner = THIS_MODULE; ++ platform_set_drvdata(pdev, pwrseq); ++ ++ return mmc_pwrseq_register(&pwrseq->pwrseq); ++} ++ ++static int mmc_pwrseq_emmc_remove(struct platform_device *pdev) ++{ ++ struct mmc_pwrseq_emmc *pwrseq = platform_get_drvdata(pdev); ++ ++ unregister_restart_handler(&pwrseq->reset_nb); ++ mmc_pwrseq_unregister(&pwrseq->pwrseq); + +- return &pwrseq->pwrseq; +-free: +- kfree(pwrseq); +- return ERR_PTR(ret); ++ return 0; + } ++ ++static const struct of_device_id mmc_pwrseq_emmc_of_match[] = { ++ { .compatible = "mmc-pwrseq-emmc",}, ++ {/* sentinel */}, ++}; ++ ++MODULE_DEVICE_TABLE(of, mmc_pwrseq_emmc_of_match); ++ ++static struct platform_driver mmc_pwrseq_emmc_driver = { ++ .probe = mmc_pwrseq_emmc_probe, ++ .remove = mmc_pwrseq_emmc_remove, ++ .driver = { ++ .name = "pwrseq_emmc", ++ .of_match_table = mmc_pwrseq_emmc_of_match, ++ }, ++}; ++ ++module_platform_driver(mmc_pwrseq_emmc_driver); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index f94271bb1f6b..450d907c6e6c 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -8,7 +8,10 @@ + * Simple MMC power sequence management + */ + #include ++#include + #include ++#include ++#include + #include + #include + #include +@@ -75,58 +78,64 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host) + } + } + +-static void mmc_pwrseq_simple_free(struct mmc_host *host) +-{ +- struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); +- +- if (!IS_ERR(pwrseq->reset_gpios)) +- gpiod_put_array(pwrseq->reset_gpios); +- +- if (!IS_ERR(pwrseq->ext_clk)) +- clk_put(pwrseq->ext_clk); +- +- kfree(pwrseq); +-} +- + static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { + .pre_power_on = mmc_pwrseq_simple_pre_power_on, + .post_power_on = mmc_pwrseq_simple_post_power_on, + .power_off = mmc_pwrseq_simple_power_off, +- .free = mmc_pwrseq_simple_free, + }; + +-struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, +- struct device *dev) ++static const struct of_device_id mmc_pwrseq_simple_of_match[] = { ++ { .compatible = "mmc-pwrseq-simple",}, ++ {/* sentinel */}, ++}; ++MODULE_DEVICE_TABLE(of, mmc_pwrseq_simple_of_match); ++ ++static int mmc_pwrseq_simple_probe(struct platform_device *pdev) + { + struct mmc_pwrseq_simple *pwrseq; +- int ret = 0; ++ struct device *dev = &pdev->dev; + +- pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL); ++ pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); + if (!pwrseq) +- return ERR_PTR(-ENOMEM); ++ return -ENOMEM; + +- pwrseq->ext_clk = clk_get(dev, "ext_clock"); +- if (IS_ERR(pwrseq->ext_clk) && +- PTR_ERR(pwrseq->ext_clk) != -ENOENT) { +- ret = PTR_ERR(pwrseq->ext_clk); +- goto free; +- } ++ pwrseq->ext_clk = devm_clk_get(dev, "ext_clock"); ++ if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT) ++ return PTR_ERR(pwrseq->ext_clk); + +- pwrseq->reset_gpios = gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH); ++ pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", ++ GPIOD_OUT_HIGH); + if (IS_ERR(pwrseq->reset_gpios) && + PTR_ERR(pwrseq->reset_gpios) != -ENOENT && + PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) { +- ret = PTR_ERR(pwrseq->reset_gpios); +- goto clk_put; ++ return PTR_ERR(pwrseq->reset_gpios); + } + ++ pwrseq->pwrseq.dev = dev; + pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; ++ pwrseq->pwrseq.owner = THIS_MODULE; ++ platform_set_drvdata(pdev, pwrseq); + +- return &pwrseq->pwrseq; +-clk_put: +- if (!IS_ERR(pwrseq->ext_clk)) +- clk_put(pwrseq->ext_clk); +-free: +- kfree(pwrseq); +- return ERR_PTR(ret); ++ return mmc_pwrseq_register(&pwrseq->pwrseq); + } ++ ++static int mmc_pwrseq_simple_remove(struct platform_device *pdev) ++{ ++ struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev); ++ ++ mmc_pwrseq_unregister(&pwrseq->pwrseq); ++ ++ return 0; ++} ++ ++static struct platform_driver mmc_pwrseq_simple_driver = { ++ .probe = mmc_pwrseq_simple_probe, ++ .remove = mmc_pwrseq_simple_remove, ++ .driver = { ++ .name = "pwrseq_simple", ++ .of_match_table = mmc_pwrseq_simple_of_match, ++ }, ++}; ++ ++module_platform_driver(mmc_pwrseq_simple_driver); ++MODULE_LICENSE("GPL v2"); + +From d4986d574cca4ea8985a3d725ff4190b8ad584f3 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 7 Aug 2016 21:02:38 +0200 +Subject: [PATCH] UPSTREAM: mmc: pwrseq-simple: Add an optional + post-power-on-delay + +Some devices need a while to boot their firmware after providing clks / +de-asserting resets before they are ready to receive sdio commands. + +This commits adds a post-power-on-delay-ms devicetree property to +mmc-pwrseq-simple for use with such devices. + +Signed-off-by: Hans de Goede +Acked-by: Rob Herring +Signed-off-by: Ulf Hansson +(cherry picked from commit 721e0497172f0fa661eed2d63367cddf479f35e8) +--- + Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 2 ++ + drivers/mmc/core/pwrseq_simple.c | 9 +++++++++ + 2 files changed, 11 insertions(+) + +diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +index ce0e76749671..e25436861867 100644 +--- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt ++++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +@@ -16,6 +16,8 @@ Optional properties: + See ../clocks/clock-bindings.txt for details. + - clock-names : Must include the following entry: + "ext_clock" (External clock provided to the card). ++- post-power-on-delay-ms : Delay in ms after powering the card and ++ de-asserting the reset-gpios (if any) + + Example: + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index 450d907c6e6c..1304160de168 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -16,6 +16,8 @@ + #include + #include + #include ++#include ++#include + + #include + +@@ -24,6 +26,7 @@ + struct mmc_pwrseq_simple { + struct mmc_pwrseq pwrseq; + bool clk_enabled; ++ u32 post_power_on_delay_ms; + struct clk *ext_clk; + struct gpio_descs *reset_gpios; + }; +@@ -64,6 +67,9 @@ static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host) + struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); ++ ++ if (pwrseq->post_power_on_delay_ms) ++ msleep(pwrseq->post_power_on_delay_ms); + } + + static void mmc_pwrseq_simple_power_off(struct mmc_host *host) +@@ -111,6 +117,9 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev) + return PTR_ERR(pwrseq->reset_gpios); + } + ++ device_property_read_u32(dev, "post-power-on-delay-ms", ++ &pwrseq->post_power_on_delay_ms); ++ + pwrseq->pwrseq.dev = dev; + pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; + pwrseq->pwrseq.owner = THIS_MODULE; + +From dc809aa3772b2cbc912b34bf6a99daba7c071cac Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Sat, 6 May 2017 11:41:30 +0200 +Subject: [PATCH] UPSTREAM: mmc: dt: pwrseq-simple: Invent power-off-delay-us + +During power off, after the GPIO pin has been asserted, some devices like +the Wifi chip from TI, Wl18xx, needs a delay before the host continues with +clock gating and turning off regulators as to follow a graceful shutdown +sequence. + +Therefore invent an optional power-off-delay-us DT binding for +mmc-pwrseq-simple, to allow us to support this constraint. + +Cc: devicetree@vger.kernel.org +Cc: Rob Herring +Cc: linux-mmc@vger.kernel.org +Signed-off-by: Ulf Hansson +Acked-by: Arnd Bergmann +--- + Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +index e25436861867..9029b45b8a22 100644 +--- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt ++++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +@@ -18,6 +18,8 @@ Optional properties: + "ext_clock" (External clock provided to the card). + - post-power-on-delay-ms : Delay in ms after powering the card and + de-asserting the reset-gpios (if any) ++- power-off-delay-us : Delay in us after asserting the reset-gpios (if any) ++ during power off of the card. + + Example: + + +From e0841b21b5b9597b674ddbf3f62fe0c418467a93 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Sat, 6 May 2017 11:43:05 +0200 +Subject: [PATCH] UPSTREAM: mmc: pwrseq_simple: Parse DTS for the + power-off-delay-us property + +If the optional power-off-delay-us property is found, insert the +corresponding delay after asserting the GPIO during power off. This enables +a graceful shutdown sequence for some devices. + +Cc: linux-mmc@vger.kernel.org +Signed-off-by: Ulf Hansson +Acked-by: Arnd Bergmann +(cherry picked from commit e9256e142f597edf90c68cec22db4c4aebaa27de) +--- + drivers/mmc/core/pwrseq_simple.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index 1304160de168..13ef162cf066 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -27,6 +27,7 @@ struct mmc_pwrseq_simple { + struct mmc_pwrseq pwrseq; + bool clk_enabled; + u32 post_power_on_delay_ms; ++ u32 power_off_delay_us; + struct clk *ext_clk; + struct gpio_descs *reset_gpios; + }; +@@ -78,6 +79,10 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host) + + mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); + ++ if (pwrseq->power_off_delay_us) ++ usleep_range(pwrseq->power_off_delay_us, ++ 2 * pwrseq->power_off_delay_us); ++ + if (!IS_ERR(pwrseq->ext_clk) && pwrseq->clk_enabled) { + clk_disable_unprepare(pwrseq->ext_clk); + pwrseq->clk_enabled = false; +@@ -119,6 +124,8 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev) + + device_property_read_u32(dev, "post-power-on-delay-ms", + &pwrseq->post_power_on_delay_ms); ++ device_property_read_u32(dev, "power-off-delay-us", ++ &pwrseq->power_off_delay_us); + + pwrseq->pwrseq.dev = dev; + pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; diff --git a/projects/Rockchip/patches/linux/rockchip-4.4/linux-1000-pl330.patch b/projects/Rockchip/patches/linux/rockchip-4.4/linux-1000-pl330.patch index e83ca8ca7d..48005dcd77 100644 --- a/projects/Rockchip/patches/linux/rockchip-4.4/linux-1000-pl330.patch +++ b/projects/Rockchip/patches/linux/rockchip-4.4/linux-1000-pl330.patch @@ -1,8 +1,140 @@ -From c5762affa4dc61b624b0440a4b4846550a305552 Mon Sep 17 00:00:00 2001 +From b9995f420ecbdc8496a3f92f4e35173268fc2697 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Feb 2018 10:47:28 +0100 +Subject: [PATCH] Revert "dmaengine: pl330: fix bug that chan descdone is null" + +This reverts commit 636c30b38ae6ec499735ce7621ba474944b4e9b7. +--- + drivers/dma/pl330.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 08179f5d0428..766ab72d119e 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1785,17 +1785,16 @@ static int pl330_update(struct pl330_dmac *pl330) + + /* Detach the req */ + descdone = thrd->req[active].desc; +- if (descdone) { +- if (!descdone->cyclic) { +- thrd->req[active].desc = NULL; +- thrd->req_running = -1; +- /* Get going again ASAP */ +- _start(thrd); +- } + +- /* For now, just make a list of callbacks to be done */ +- list_add_tail(&descdone->rqd, &pl330->req_done); ++ if (!descdone->cyclic) { ++ thrd->req[active].desc = NULL; ++ thrd->req_running = -1; ++ /* Get going again ASAP */ ++ _start(thrd); + } ++ ++ /* For now, just make a list of callbacks to be done */ ++ list_add_tail(&descdone->rqd, &pl330->req_done); + } + } + + +From 4c25aa573e13f31f628d10ae41f24264fe15695c Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Feb 2018 10:47:38 +0100 +Subject: [PATCH] Revert "dmaengine: pl330: flush before first loop" + +This reverts commit 34be2cf4679cadbf910de9651d54b46930166446. +--- + drivers/dma/pl330.c | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 766ab72d119e..055e3cd8832c 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1347,11 +1347,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run, + /* forever loop */ + off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr); + off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr); +-#ifdef CONFIG_ARCH_ROCKCHIP +- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) +- off += _emit_FLUSHP(dry_run, &buf[off], +- pxs->desc->peri); +-#endif ++ + /* loop0 */ + off += _emit_LP(dry_run, &buf[off], 0, lcnt0); + ljmp0 = off; +@@ -1427,11 +1423,7 @@ static inline int _setup_loops(struct pl330_dmac *pl330, + u32 ccr = pxs->ccr; + unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr); + int off = 0; +-#ifdef CONFIG_ARCH_ROCKCHIP +- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) +- off += _emit_FLUSHP(dry_run, &buf[off], +- pxs->desc->peri); +-#endif ++ + while (bursts) { + c = bursts; + off += _loop(pl330, dry_run, &buf[off], &c, pxs); + +From 4977bdedb837ac640fd6be482ed7c501959e4a55 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Feb 2018 10:47:51 +0100 +Subject: [PATCH] Revert "dmaengine: pl330: fix 2 bursts transfer when dma + flushes" + +This reverts commit 98753e172dc1d06cf4d61c48f5c3487df0247472. +--- + drivers/dma/pl330.c | 20 -------------------- + 1 file changed, 20 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 055e3cd8832c..ce52aa411c0b 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1169,16 +1169,6 @@ static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run, + off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); + off += _emit_LDP(dry_run, &buf[off], cond, pxs->desc->peri); + off += _emit_ST(dry_run, &buf[off], ALWAYS); +-#ifdef CONFIG_ARCH_ROCKCHIP +- /* +- * Make suree dma has finish transmission, or later flush may +- * cause dma second transmission,and fifo is overrun. +- */ +- off += _emit_WMB(dry_run, &buf[off]); +- off += _emit_NOP(dry_run, &buf[off]); +- off += _emit_WMB(dry_run, &buf[off]); +- off += _emit_NOP(dry_run, &buf[off]); +-#endif + + if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) + off += _emit_FLUSHP(dry_run, &buf[off], +@@ -1199,16 +1189,6 @@ static inline int _ldst_memtodev(struct pl330_dmac *pl330, + off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); + off += _emit_LD(dry_run, &buf[off], ALWAYS); + off += _emit_STP(dry_run, &buf[off], cond, pxs->desc->peri); +-#ifdef CONFIG_ARCH_ROCKCHIP +- /* +- * Make suree dma has finish transmission, or later flush may +- * cause dma second transmission,and fifo is overrun. +- */ +- off += _emit_WMB(dry_run, &buf[off]); +- off += _emit_NOP(dry_run, &buf[off]); +- off += _emit_WMB(dry_run, &buf[off]); +- off += _emit_NOP(dry_run, &buf[off]); +-#endif + + if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) + off += _emit_FLUSHP(dry_run, &buf[off], + +From 29be0d6a2e7bace45bc18728b59d7bcac498cb0c Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sat, 21 Oct 2017 19:49:27 +0200 -Subject: [PATCH 01/16] Revert "dmaengine: pl330: _loop_cyclic fix cycles of - last loop" +Subject: [PATCH] Revert "dmaengine: pl330: _loop_cyclic fix cycles of last + loop" This reverts commit d7155171cbc65e45b5b0c8db03fd16fa57a181f2. --- @@ -10,7 +142,7 @@ This reverts commit d7155171cbc65e45b5b0c8db03fd16fa57a181f2. 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index cd05495735d7..1e5c79b20c5b 100644 +index ce52aa411c0b..9fbd8d863774 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1366,7 +1366,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run, @@ -23,11 +155,36 @@ index cd05495735d7..1e5c79b20c5b 100644 off += _bursts(pl330, dry_run, &buf[off], pxs, 1); lpend.cond = ALWAYS; -From 7d241ca0d9e3c658f92c54614cf50812557fb899 Mon Sep 17 00:00:00 2001 +From 350bb8b0d3efbeb398c058d6343a7a9466230b36 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Feb 2018 11:05:44 +0100 +Subject: [PATCH] Revert "dmaengine: pl330: pl330_tasklet init power_down by + pch->active" + +This reverts commit 796b13f24a158f14d540bcf7316d843f72242c0d. +--- + drivers/dma/pl330.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 9fbd8d863774..359475bbe89f 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2163,7 +2163,7 @@ static void pl330_tasklet(unsigned long data) + spin_lock(&pch->thread->dmac->lock); + _stop(pch->thread); + spin_unlock(&pch->thread->dmac->lock); +- power_down = pch->active; ++ power_down = true; + pch->active = false; + } else { + /* Make sure the PL330 Channel thread is active */ + +From 3eff212db53fd374baa1a9040212442057bb9110 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Fri, 16 Jun 2017 23:14:54 +0200 -Subject: [PATCH 02/16] Revert "dmaengine: pl330: _loop_cyclic supports - unaligned size" +Subject: [PATCH] Revert "dmaengine: pl330: _loop_cyclic supports unaligned + size" This reverts commit 13dbe2cccd5851540af8158b12499c33801b6ef6. --- @@ -35,7 +192,7 @@ This reverts commit 13dbe2cccd5851540af8158b12499c33801b6ef6. 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 1e5c79b20c5b..4661dfb1a195 100644 +index 359475bbe89f..3fa6a7e474de 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1356,28 +1356,6 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run, @@ -99,10 +256,10 @@ index 1e5c79b20c5b..4661dfb1a195 100644 pxs, thrd->ev); } -From a21f49560bf8cf38b5832a0f37d4c16610bec2df Mon Sep 17 00:00:00 2001 +From 7835c891fdb8016da760f81b95291333b03c9fbc Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Fri, 16 Jun 2017 23:14:54 +0200 -Subject: [PATCH 03/16] Revert "dmaengine: pl330: redefine the cyclic transfer" +Subject: [PATCH] Revert "dmaengine: pl330: redefine the cyclic transfer" This reverts commit 5f638786e66089344c9cf594b81fbf02cd794f15. --- @@ -110,7 +267,7 @@ This reverts commit 5f638786e66089344c9cf594b81fbf02cd794f15. 1 file changed, 29 insertions(+), 108 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 4661dfb1a195..d8912a4216df 100644 +index 3fa6a7e474de..0452a189d7fd 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1303,76 +1303,6 @@ static inline int _loop(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], @@ -291,7 +448,7 @@ index 4661dfb1a195..d8912a4216df 100644 } return off; -@@ -2656,7 +2583,6 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( +@@ -2649,7 +2576,6 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( { struct dma_pl330_desc *desc = NULL; struct dma_pl330_chan *pch = to_pchan(chan); @@ -299,7 +456,7 @@ index 4661dfb1a195..d8912a4216df 100644 dma_addr_t dst; dma_addr_t src; -@@ -2695,12 +2621,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( +@@ -2688,12 +2614,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( desc->rqtype = direction; desc->rqcfg.brst_size = pch->burst_sz; @@ -314,10 +471,10 @@ index 4661dfb1a195..d8912a4216df 100644 fill_px(&desc->px, dst, src, period_len); -From 7cd3fa397393d461d94167554653ef168b8e703d Mon Sep 17 00:00:00 2001 +From e5c15e6005f796dae98de9e7a0d844bd101cd974 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Fri, 16 Jun 2017 23:14:54 +0200 -Subject: [PATCH 04/16] Revert "dmaengine: pl330: make transfer run infinitely +Subject: [PATCH] Revert "dmaengine: pl330: make transfer run infinitely without CPU intervention" This reverts commit e8a6e5086cb82d59cae6ae029b1eb4432cc62288. @@ -326,7 +483,7 @@ This reverts commit e8a6e5086cb82d59cae6ae029b1eb4432cc62288. 1 file changed, 105 insertions(+), 94 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index d8912a4216df..58e99ae039f8 100644 +index 0452a189d7fd..47c2e67f0296 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -447,6 +447,9 @@ struct dma_pl330_chan { @@ -440,7 +597,7 @@ index d8912a4216df..58e99ae039f8 100644 /* For now, just make a list of callbacks to be done */ list_add_tail(&descdone->rqd, &pl330->req_done); -@@ -2051,27 +2028,12 @@ static void pl330_tasklet(unsigned long data) +@@ -2043,27 +2020,12 @@ static void pl330_tasklet(unsigned long data) spin_lock_irqsave(&pch->lock, flags); /* Pick up ripe tomatoes */ @@ -471,7 +628,7 @@ index d8912a4216df..58e99ae039f8 100644 /* Try to submit a req imm. next to the last completed cookie */ fill_queue(pch); -@@ -2099,8 +2061,20 @@ static void pl330_tasklet(unsigned long data) +@@ -2091,8 +2053,20 @@ static void pl330_tasklet(unsigned long data) callback = desc->txd.callback; callback_param = desc->txd.callback_param; @@ -494,15 +651,15 @@ index d8912a4216df..58e99ae039f8 100644 dma_descriptor_unmap(&desc->txd); -@@ -2160,6 +2134,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) - spin_lock_irqsave(&pch->lock, flags); +@@ -2152,6 +2126,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) + spin_lock_irqsave(&pl330->lock, flags); dma_cookie_init(chan); + pch->cyclic = false; pch->thread = pl330_request_channel(pl330); if (!pch->thread) { -@@ -2282,7 +2257,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan) +@@ -2275,7 +2250,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan) pl330_release_channel(pch->thread); pch->thread = NULL; @@ -510,9 +667,9 @@ index d8912a4216df..58e99ae039f8 100644 + if (pch->cyclic) + list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool); - spin_unlock_irqrestore(&pch->lock, flags); + spin_unlock_irqrestore(&pl330->lock, flags); pm_runtime_mark_last_busy(pch->dmac->ddma.dev); -@@ -2336,7 +2312,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, +@@ -2329,7 +2305,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, /* Check in pending list */ list_for_each_entry(desc, &pch->work_list, node) { @@ -521,7 +678,7 @@ index d8912a4216df..58e99ae039f8 100644 transferred = desc->bytes_requested; else if (running && desc == running) transferred = -@@ -2408,8 +2384,12 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx) +@@ -2401,8 +2377,12 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx) /* Assign cookies to all nodes */ while (!list_empty(&last->node)) { desc = list_entry(last->node.next, struct dma_pl330_desc, node); @@ -535,7 +692,7 @@ index d8912a4216df..58e99ae039f8 100644 dma_cookie_assign(&desc->txd); list_move_tail(&desc->node, &pch->submitted_list); -@@ -2509,9 +2489,6 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) +@@ -2502,9 +2482,6 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) desc->peri = peri_id ? pch->chan.chan_id : 0; desc->rqcfg.pcfg = &pch->dmac->pcfg; @@ -545,7 +702,7 @@ index d8912a4216df..58e99ae039f8 100644 dma_async_tx_descriptor_init(&desc->txd, &pch->chan); return desc; -@@ -2581,8 +2558,10 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( +@@ -2574,8 +2551,10 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( size_t period_len, enum dma_transfer_direction direction, unsigned long flags) { @@ -557,7 +714,7 @@ index d8912a4216df..58e99ae039f8 100644 dma_addr_t dst; dma_addr_t src; -@@ -2595,38 +2574,70 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( +@@ -2588,38 +2567,70 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( return NULL; } @@ -657,11 +814,11 @@ index d8912a4216df..58e99ae039f8 100644 return &desc->txd; -From 5e0a2880602942d120459525a752e86533300c44 Mon Sep 17 00:00:00 2001 +From 6fa8512feac35cc27a6b929a0a9b5baaf8ec104d Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Fri, 16 Jun 2017 23:14:55 +0200 -Subject: [PATCH 05/16] Revert "dmaengine: pl330: support transfer that doesn't - align with (burst len * burst size)" +Subject: [PATCH] Revert "dmaengine: pl330: support transfer that doesn't align + with (burst len * burst size)" This reverts commit c66ecf19b98ffac86177c29859e683de39f44e73. --- @@ -669,7 +826,7 @@ This reverts commit c66ecf19b98ffac86177c29859e683de39f44e73. 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 58e99ae039f8..f4837f5b4e87 100644 +index 47c2e67f0296..b5cf3fe9e9c3 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -240,7 +240,6 @@ enum pl330_byteswap { @@ -717,11 +874,11 @@ index 58e99ae039f8..f4837f5b4e87 100644 off += _setup_xfer(pl330, dry_run, &buf[off], pxs); -From fd77628162b4a13bc54a9187dc25fbc65ad79f37 Mon Sep 17 00:00:00 2001 +From 0e2fc7209d34d86502cfe4cf2a8808dc51e99492 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Fri, 16 Jun 2017 23:14:55 +0200 -Subject: [PATCH 06/16] Revert "dmaengine: pl330: add burst mode according to - dts config" +Subject: [PATCH] Revert "dmaengine: pl330: add burst mode according to dts + config" This reverts commit 8e770f371cc27f8828cb9ceb0516adc23fe75995. --- @@ -729,7 +886,7 @@ This reverts commit 8e770f371cc27f8828cb9ceb0516adc23fe75995. 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index f4837f5b4e87..778be86e908c 100644 +index b5cf3fe9e9c3..131763534a39 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -494,8 +494,6 @@ struct pl330_dmac { @@ -769,7 +926,7 @@ index f4837f5b4e87..778be86e908c 100644 while (cyc--) { off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); -@@ -2600,12 +2608,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( +@@ -2593,12 +2601,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( desc->rqtype = direction; desc->rqcfg.brst_size = pch->burst_sz; @@ -783,7 +940,7 @@ index f4837f5b4e87..778be86e908c 100644 desc->bytes_requested = period_len; fill_px(&desc->px, dst, src, period_len); -@@ -2707,7 +2710,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, +@@ -2700,7 +2703,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, { struct dma_pl330_desc *first, *desc = NULL; struct dma_pl330_chan *pch = to_pchan(chan); @@ -791,7 +948,7 @@ index f4837f5b4e87..778be86e908c 100644 struct scatterlist *sg; int i; dma_addr_t addr; -@@ -2751,12 +2753,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, +@@ -2744,12 +2746,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, } desc->rqcfg.brst_size = pch->burst_sz; @@ -805,7 +962,7 @@ index f4837f5b4e87..778be86e908c 100644 desc->rqtype = direction; desc->bytes_requested = sg_dma_len(sg); } -@@ -2852,11 +2849,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) +@@ -2845,11 +2842,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0; @@ -818,10 +975,10 @@ index f4837f5b4e87..778be86e908c 100644 for (i = 0; i < ARRAY_SIZE(of_quirks); i++) if (of_property_read_bool(np, of_quirks[i].quirk)) -From 754e41a208e456b127896f0c017ca523d7e93ccc Mon Sep 17 00:00:00 2001 +From 11bc7b36d8a54c6c1858c23a1e91a660ab8f34c8 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 5 Jul 2016 10:02:16 +0530 -Subject: [PATCH 07/16] UPSTREAM: dmaengine: pl330: explicitly freeup irq +Subject: [PATCH] UPSTREAM: dmaengine: pl330: explicitly freeup irq dmaengine device should explicitly call devm_free_irq() when using devm_request_irq(). @@ -838,10 +995,10 @@ Cc: Linus Walleij 1 file changed, 6 insertions(+) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 778be86e908c..4e6590f90994 100644 +index 131763534a39..5b4a419673fc 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c -@@ -3016,12 +3016,18 @@ static int pl330_remove(struct amba_device *adev) +@@ -3009,12 +3009,18 @@ static int pl330_remove(struct amba_device *adev) { struct pl330_dmac *pl330 = amba_get_drvdata(adev); struct dma_pl330_chan *pch, *_p; @@ -861,11 +1018,11 @@ index 778be86e908c..4e6590f90994 100644 /* Idle the DMAC */ -From d486322e47fdaaf0ba14c5dc1a3bad97400814b0 Mon Sep 17 00:00:00 2001 +From 0406b9fd94d38cc2de78e82bd7b7c3272991e7d5 Mon Sep 17 00:00:00 2001 From: Stephen Barber Date: Thu, 18 Aug 2016 17:59:59 -0700 -Subject: [PATCH 08/16] UPSTREAM: dmaengine: pl330: fix residual for - non-running BUSY descriptors +Subject: [PATCH] UPSTREAM: dmaengine: pl330: fix residual for non-running BUSY + descriptors Only one descriptor in the work list should be running at any given time, but it's possible to have an enqueued BUSY @@ -883,10 +1040,10 @@ Signed-off-by: Vinod Koul 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 4e6590f90994..16f578f1d050 100644 +index 5b4a419673fc..aab5abab5a10 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c -@@ -2284,7 +2284,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, +@@ -2277,7 +2277,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, { enum dma_status ret; unsigned long flags; @@ -895,7 +1052,7 @@ index 4e6590f90994..16f578f1d050 100644 struct dma_pl330_chan *pch = to_pchan(chan); unsigned int transferred, residual = 0; -@@ -2301,6 +2301,8 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, +@@ -2294,6 +2294,8 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, if (pch->thread->req_running != -1) running = pch->thread->req[pch->thread->req_running].desc; @@ -904,7 +1061,7 @@ index 4e6590f90994..16f578f1d050 100644 /* Check in pending list */ list_for_each_entry(desc, &pch->work_list, node) { if (desc->status == DONE) -@@ -2308,6 +2310,15 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, +@@ -2301,6 +2303,15 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, else if (running && desc == running) transferred = pl330_get_current_xferred_count(pch, desc); @@ -921,10 +1078,10 @@ index 4e6590f90994..16f578f1d050 100644 transferred = 0; residual += desc->bytes_requested - transferred; -From be63b825e6305654e11be4313e083fbafc09825c Mon Sep 17 00:00:00 2001 +From 9bda78186df672f7c813dfd7db3bcd6d557e11e5 Mon Sep 17 00:00:00 2001 From: Hsin-Yu Chao Date: Tue, 23 Aug 2016 17:16:55 +0800 -Subject: [PATCH 09/16] UPSTREAM: dmaengine: pl330: Acquire dmac's spinlock in +Subject: [PATCH] UPSTREAM: dmaengine: pl330: Acquire dmac's spinlock in pl330_tx_status There is a racing when accessing dmac thread in pl330_tx_status that @@ -946,10 +1103,10 @@ Signed-off-by: Vinod Koul 1 file changed, 2 insertions(+) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 16f578f1d050..642d07412d8d 100644 +index aab5abab5a10..1741cfbe311e 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c -@@ -2297,6 +2297,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, +@@ -2290,6 +2290,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, goto out; spin_lock_irqsave(&pch->lock, flags); @@ -957,7 +1114,7 @@ index 16f578f1d050..642d07412d8d 100644 if (pch->thread->req_running != -1) running = pch->thread->req[pch->thread->req_running].desc; -@@ -2339,6 +2340,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, +@@ -2332,6 +2333,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, if (desc->last) residual = 0; } @@ -966,11 +1123,11 @@ index 16f578f1d050..642d07412d8d 100644 out: -From 58befcac6b343442beba9af186e5585c1a159288 Mon Sep 17 00:00:00 2001 +From 6e3724a83db9e92e163261bc22c2e3f6f0865e69 Mon Sep 17 00:00:00 2001 From: Stephen Barber Date: Tue, 1 Nov 2016 16:44:27 -0700 -Subject: [PATCH 10/16] UPSTREAM: dmaengine: pl330: Handle xferred count if - DMAMOV hasn't finished +Subject: [PATCH] UPSTREAM: dmaengine: pl330: Handle xferred count if DMAMOV + hasn't finished After executing DMAGO it's possible that a request can come in for the current xferred count, but if that happens too soon then DMAMOV SAR/DAR @@ -985,10 +1142,10 @@ Signed-off-by: Vinod Koul 1 file changed, 5 insertions(+) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 642d07412d8d..700abe522316 100644 +index 1741cfbe311e..dd58cf886fa0 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c -@@ -2275,6 +2275,11 @@ static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch, +@@ -2268,6 +2268,11 @@ static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch, } pm_runtime_mark_last_busy(pch->dmac->ddma.dev); pm_runtime_put_autosuspend(pl330->ddma.dev); @@ -1001,11 +1158,10 @@ index 642d07412d8d..700abe522316 100644 } -From e169fa9c6afdc35362da8b6fee2822597400cb8c Mon Sep 17 00:00:00 2001 +From 529feba8e68c331c6385d51e820599466a24f6eb Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Wed, 7 Dec 2016 13:17:40 +0000 -Subject: [PATCH 11/16] UPSTREAM: dmaengine: pl330: do not generate unaligned - access +Subject: [PATCH] UPSTREAM: dmaengine: pl330: do not generate unaligned access When PL330 is used with !MMU the following fault is seen: @@ -1063,7 +1219,7 @@ Signed-off-by: Vinod Koul 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 700abe522316..c242c8634a58 100644 +index dd58cf886fa0..50a5f8e1e371 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -573,7 +573,8 @@ static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[], @@ -1104,11 +1260,11 @@ index 700abe522316..c242c8634a58 100644 return SZ_DMAGO; } -From 39f8d588ba2abc09f8232aab5de223eba7f2511c Mon Sep 17 00:00:00 2001 +From 6b7fb23e9950ce28ddc7303236bfe2e8c9505fa9 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 9 Dec 2016 15:24:12 +0530 -Subject: [PATCH 12/16] =?UTF-8?q?UPSTREAM:=20dmaengine:=20pl330:=20remove?= - =?UTF-8?q?=20unused=20=E2=80=98regs=E2=80=99?= +Subject: [PATCH] =?UTF-8?q?UPSTREAM:=20dmaengine:=20pl330:=20remove=20unus?= + =?UTF-8?q?ed=20=E2=80=98regs=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1129,10 +1285,10 @@ Signed-off-by: Vinod Koul 1 file changed, 3 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index c242c8634a58..da72d3d984e8 100644 +index 50a5f8e1e371..c725ceb4644d 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c -@@ -1891,11 +1891,8 @@ static int dmac_alloc_resources(struct pl330_dmac *pl330) +@@ -1883,11 +1883,8 @@ static int dmac_alloc_resources(struct pl330_dmac *pl330) static int pl330_add(struct pl330_dmac *pl330) { @@ -1145,152 +1301,10 @@ index c242c8634a58..da72d3d984e8 100644 if ((pl330->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) { dev_err(pl330->ddma.dev, "PERIPH_ID 0x%x !\n", -From 8906839d1e7292db9f36ca135d0c640811ac08ee Mon Sep 17 00:00:00 2001 -From: Iago Abal -Date: Wed, 11 Jan 2017 14:00:21 +0100 -Subject: [PATCH 13/16] UPSTREAM: dmaengine: pl330: fix double lock - -The static bug finder EBA (http://www.iagoabal.eu/eba/) reported the -following double-lock bug: - - Double lock: - 1. spin_lock_irqsave(pch->lock, flags) at pl330_free_chan_resources:2236; - 2. call to function `pl330_release_channel' immediately after; - 3. call to function `dma_pl330_rqcb' in line 1753; - 4. spin_lock_irqsave(pch->lock, flags) at dma_pl330_rqcb:1505. - -I have fixed it as suggested by Marek Szyprowski. - -First, I have replaced `pch->lock' with `pl330->lock' in functions -`pl330_alloc_chan_resources' and `pl330_free_chan_resources'. This avoids -the double-lock by acquiring a different lock than `dma_pl330_rqcb'. - -NOTE that, as a result, `pl330_free_chan_resources' executes -`list_splice_tail_init' on `pch->work_list' under lock `pl330->lock', -whereas in the rest of the code `pch->work_list' is protected by -`pch->lock'. I don't know if this may cause race conditions. Similarly -`pch->cyclic' is written by `pl330_alloc_chan_resources' under -`pl330->lock' but read by `pl330_tx_submit' under `pch->lock'. - -Second, I have removed locking from `pl330_request_channel' and -`pl330_release_channel' functions. Function `pl330_request_channel' is -only called from `pl330_alloc_chan_resources', so the lock is already -held. Function `pl330_release_channel' is called from -`pl330_free_chan_resources', which already holds the lock, and from -`pl330_del'. Function `pl330_del' is called in an error path of -`pl330_probe' and at the end of `pl330_remove', but I assume that there -cannot be concurrent accesses to the protected data at those points. - -Signed-off-by: Iago Abal -Reviewed-by: Marek Szyprowski -Signed-off-by: Vinod Koul -(cherry picked from commit 91539eb1fda2d530d3b268eef542c5414e54bf1a) ---- - drivers/dma/pl330.c | 19 ++++++------------- - 1 file changed, 6 insertions(+), 13 deletions(-) - -diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index da72d3d984e8..306186354e00 100644 ---- a/drivers/dma/pl330.c -+++ b/drivers/dma/pl330.c -@@ -1699,7 +1699,6 @@ static bool _chan_ns(const struct pl330_dmac *pl330, int i) - static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330) - { - struct pl330_thread *thrd = NULL; -- unsigned long flags; - int chans, i; - - if (pl330->state == DYING) -@@ -1707,8 +1706,6 @@ static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330) - - chans = pl330->pcfg.num_chan; - -- spin_lock_irqsave(&pl330->lock, flags); -- - for (i = 0; i < chans; i++) { - thrd = &pl330->channels[i]; - if ((thrd->free) && (!_manager_ns(thrd) || -@@ -1726,8 +1723,6 @@ static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330) - thrd = NULL; - } - -- spin_unlock_irqrestore(&pl330->lock, flags); -- - return thrd; - } - -@@ -1745,7 +1740,6 @@ static inline void _free_event(struct pl330_thread *thrd, int ev) - static void pl330_release_channel(struct pl330_thread *thrd) - { - struct pl330_dmac *pl330; -- unsigned long flags; - - if (!thrd || thrd->free) - return; -@@ -1757,10 +1751,8 @@ static void pl330_release_channel(struct pl330_thread *thrd) - - pl330 = thrd->dmac; - -- spin_lock_irqsave(&pl330->lock, flags); - _free_event(thrd, thrd->ev); - thrd->free = true; -- spin_unlock_irqrestore(&pl330->lock, flags); - } - - /* Initialize the structure for PL330 configuration, that can be used -@@ -2124,20 +2116,20 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) - struct pl330_dmac *pl330 = pch->dmac; - unsigned long flags; - -- spin_lock_irqsave(&pch->lock, flags); -+ spin_lock_irqsave(&pl330->lock, flags); - - dma_cookie_init(chan); - pch->cyclic = false; - - pch->thread = pl330_request_channel(pl330); - if (!pch->thread) { -- spin_unlock_irqrestore(&pch->lock, flags); -+ spin_unlock_irqrestore(&pl330->lock, flags); - return -ENOMEM; - } - - tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch); - -- spin_unlock_irqrestore(&pch->lock, flags); -+ spin_unlock_irqrestore(&pl330->lock, flags); - - return 1; - } -@@ -2240,12 +2232,13 @@ static int pl330_pause(struct dma_chan *chan) - static void pl330_free_chan_resources(struct dma_chan *chan) - { - struct dma_pl330_chan *pch = to_pchan(chan); -+ struct pl330_dmac *pl330 = pch->dmac; - unsigned long flags; - - tasklet_kill(&pch->task); - - pm_runtime_get_sync(pch->dmac->ddma.dev); -- spin_lock_irqsave(&pch->lock, flags); -+ spin_lock_irqsave(&pl330->lock, flags); - - pl330_release_channel(pch->thread); - pch->thread = NULL; -@@ -2253,7 +2246,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan) - if (pch->cyclic) - list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool); - -- spin_unlock_irqrestore(&pch->lock, flags); -+ spin_unlock_irqrestore(&pl330->lock, flags); - pm_runtime_mark_last_busy(pch->dmac->ddma.dev); - pm_runtime_put_autosuspend(pch->dmac->ddma.dev); - } - -From e6e9d20e0c601bc33868de2be0831d273851ddb6 Mon Sep 17 00:00:00 2001 +From 7c01c9e12f3c5ba64102d9cdf3022427c2cb87dd Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Thu, 1 Jun 2017 19:22:01 +0100 -Subject: [PATCH 14/16] UPSTREAM: dmaengine: pl330: fix warning in pl330_remove +Subject: [PATCH] UPSTREAM: dmaengine: pl330: fix warning in pl330_remove When removing a device with less than 9 IRQs (AMBA_NR_IRQS), we'll get a big WARN_ON from devres.c because pl330_remove calls devm_free_irqs for @@ -1305,7 +1319,7 @@ Signed-off-by: Vinod Koul 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 306186354e00..ddcb8029eddc 100644 +index c725ceb4644d..73eaf78871f1 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -3038,7 +3038,8 @@ static int pl330_remove(struct amba_device *adev) @@ -1319,11 +1333,10 @@ index 306186354e00..ddcb8029eddc 100644 dma_async_device_unregister(&pl330->ddma); -From 59636648043a2ed182cf745956cf970702783ffe Mon Sep 17 00:00:00 2001 +From e2cdb111e43e8ca7ac2682bb95a7d056e50c847e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 27 Mar 2017 07:31:03 +0200 -Subject: [PATCH 15/16] UPSTREAM: dmaengine: pl330: remove pdata based - initialization +Subject: [PATCH] UPSTREAM: dmaengine: pl330: remove pdata based initialization This driver is now used only on platforms which support device tree, so it is safe to remove legacy platform data based initialization code. @@ -1355,7 +1368,7 @@ index e212f9d804bd..2ef19ad5cb62 100644 #include #include diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index ddcb8029eddc..2044d36f81b1 100644 +index 73eaf78871f1..23fdb826c6e8 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -22,7 +22,6 @@ @@ -1499,10 +1512,10 @@ index fe93758e8403..000000000000 -extern bool pl330_filter(struct dma_chan *chan, void *param); -#endif /* __AMBA_PL330_H_ */ -From 163589ea5636b2eeb8d579251465ac1ce0fb0d8e Mon Sep 17 00:00:00 2001 +From 9093533777a0b008ac236ddf724312931e76a156 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 15 Jun 2017 16:55:57 -0700 -Subject: [PATCH 16/16] UPSTREAM: dmaengine: pl330: Delete unused functions +Subject: [PATCH] UPSTREAM: dmaengine: pl330: Delete unused functions The functions _queue_empty(), _emit_ADDH(), _emit_NOP(), _emit_STZ() and _emit_WFE() are not used. Delete them. @@ -1515,7 +1528,7 @@ Signed-off-by: Vinod Koul 1 file changed, 67 deletions(-) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c -index 2044d36f81b1..00ba5db20ec4 100644 +index 23fdb826c6e8..51aa1de88007 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -538,11 +538,6 @@ struct _xfer_spec { @@ -1613,3 +1626,160 @@ index 2044d36f81b1..00ba5db20ec4 100644 static inline u32 _emit_WFP(unsigned dry_run, u8 buf[], enum pl330_cond cond, u8 peri) { + +From f1dc421cf01a6fb47f157f6d15eb50955c9a0aef Mon Sep 17 00:00:00 2001 +From: Arvind Yadav +Date: Wed, 23 Aug 2017 21:57:31 +0530 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: constify amba_id + +amba_id are not supposed to change at runtime. All functions +working with const amba_id. So mark the non-const structs as const. + +Signed-off-by: Arvind Yadav +Signed-off-by: Vinod Koul +(cherry picked from commit b753351ec8f4c6a25c6d9b5c4eccce62e448a571) +--- + drivers/dma/pl330.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 51aa1de88007..defec1b4bc2f 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2970,7 +2970,7 @@ static int pl330_remove(struct amba_device *adev) + return 0; + } + +-static struct amba_id pl330_ids[] = { ++static const struct amba_id pl330_ids[] = { + { + .id = 0x00041330, + .mask = 0x000fffff, + +From efc0eb0c26f642db285a449c52d3d571d06206fe Mon Sep 17 00:00:00 2001 +From: Alexander Kochetkov +Date: Wed, 4 Oct 2017 14:37:23 +0300 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: fix descriptor allocation fail + +If two concurrent threads call pl330_get_desc() when DMAC descriptor +pool is empty it is possible that allocation for one of threads will fail +with message: + +kernel: dma-pl330 20078000.dma-controller: pl330_get_desc:2469 ALERT! + +Here how that can happen. Thread A calls pl330_get_desc() to get +descriptor. If DMAC descriptor pool is empty pl330_get_desc() allocates +new descriptor on shared pool using add_desc() and then get newly +allocated descriptor using pluck_desc(). At the same time thread B calls +pluck_desc() and take newly allocated descriptor. In that case descriptor +allocation for thread A will fail. + +Using on-stack pool for new descriptor allow avoid the issue described. +The patch modify pl330_get_desc() to use on-stack pool for allocation +new descriptors. + +Signed-off-by: Alexander Kochetkov +Tested-by: Marek Szyprowski +Signed-off-by: Vinod Koul +(cherry picked from commit e588710311ee5bece284871d613418831d56f2bd) +--- + drivers/dma/pl330.c | 39 ++++++++++++++++++++------------------- + 1 file changed, 20 insertions(+), 19 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index defec1b4bc2f..76f514efe9d0 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2338,7 +2338,8 @@ static inline void _init_desc(struct dma_pl330_desc *desc) + } + + /* Returns the number of descriptors added to the DMAC pool */ +-static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count) ++static int add_desc(struct list_head *pool, spinlock_t *lock, ++ gfp_t flg, int count) + { + struct dma_pl330_desc *desc; + unsigned long flags; +@@ -2348,27 +2349,28 @@ static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count) + if (!desc) + return 0; + +- spin_lock_irqsave(&pl330->pool_lock, flags); ++ spin_lock_irqsave(lock, flags); + + for (i = 0; i < count; i++) { + _init_desc(&desc[i]); +- list_add_tail(&desc[i].node, &pl330->desc_pool); ++ list_add_tail(&desc[i].node, pool); + } + +- spin_unlock_irqrestore(&pl330->pool_lock, flags); ++ spin_unlock_irqrestore(lock, flags); + + return count; + } + +-static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330) ++static struct dma_pl330_desc *pluck_desc(struct list_head *pool, ++ spinlock_t *lock) + { + struct dma_pl330_desc *desc = NULL; + unsigned long flags; + +- spin_lock_irqsave(&pl330->pool_lock, flags); ++ spin_lock_irqsave(lock, flags); + +- if (!list_empty(&pl330->desc_pool)) { +- desc = list_entry(pl330->desc_pool.next, ++ if (!list_empty(pool)) { ++ desc = list_entry(pool->next, + struct dma_pl330_desc, node); + + list_del_init(&desc->node); +@@ -2377,7 +2379,7 @@ static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330) + desc->txd.callback = NULL; + } + +- spin_unlock_irqrestore(&pl330->pool_lock, flags); ++ spin_unlock_irqrestore(lock, flags); + + return desc; + } +@@ -2389,20 +2391,18 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) + struct dma_pl330_desc *desc; + + /* Pluck one desc from the pool of DMAC */ +- desc = pluck_desc(pl330); ++ desc = pluck_desc(&pl330->desc_pool, &pl330->pool_lock); + + /* If the DMAC pool is empty, alloc new */ + if (!desc) { +- if (!add_desc(pl330, GFP_ATOMIC, 1)) +- return NULL; ++ DEFINE_SPINLOCK(lock); ++ LIST_HEAD(pool); + +- /* Try again */ +- desc = pluck_desc(pl330); +- if (!desc) { +- dev_err(pch->dmac->ddma.dev, +- "%s:%d ALERT!\n", __func__, __LINE__); ++ if (!add_desc(&pool, &lock, GFP_ATOMIC, 1)) + return NULL; +- } ++ ++ desc = pluck_desc(&pool, &lock); ++ WARN_ON(!desc || !list_empty(&pool)); + } + + /* Initialize the descriptor */ +@@ -2815,7 +2815,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + spin_lock_init(&pl330->pool_lock); + + /* Create a descriptor pool of default size */ +- if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC)) ++ if (!add_desc(&pl330->desc_pool, &pl330->pool_lock, ++ GFP_KERNEL, NR_DEFAULT_DESC)) + dev_warn(&adev->dev, "unable to allocate desc\n"); + + INIT_LIST_HEAD(&pd->channels);