From afef388b8e26f0d77f9d2261b6e57991941a213f Mon Sep 17 00:00:00 2001 From: thead_admin Date: Mon, 7 Aug 2023 11:23:02 +0800 Subject: [PATCH] Linux_SDK_V1.2.1 Signed-off-by: thead_admin --- arch/riscv/Kconfig | 2 +- arch/riscv/boot/dts/thead/Makefile | 6 +- arch/riscv/boot/dts/thead/fire-crash.dts | 2 +- .../boot/dts/thead/fire-emu-soc-base-sec.dts | 13 + arch/riscv/boot/dts/thead/fire-emu.dts | 8 +- arch/riscv/boot/dts/thead/fire.dtsi | 2 +- arch/riscv/boot/dts/thead/light-a-product.dts | 3 +- .../boot/dts/thead/light-a-val-android.dts | 2 +- .../boot/dts/thead/light-a-val-audio-hdmi.dts | 4 +- .../dts/thead/light-a-val-audio-i2s-8ch.dts | 100 + .../dts/thead/light-a-val-audio-spdif.dts | 42 + .../boot/dts/thead/light-a-val-audio-tdm.dts | 115 +- .../boot/dts/thead/light-a-val-audio.dts | 28 +- .../dts/thead/light-a-val-dsi0-hdmi-audio.dts | 23 +- .../riscv/boot/dts/thead/light-a-val-full.dts | 32 +- .../riscv/boot/dts/thead/light-a-val-hdmi.dts | 2 +- .../dts/thead/light-a-val-miniapp-dsi0.dts | 31 +- .../dts/thead/light-a-val-miniapp-hdmi.dts | 22 +- arch/riscv/boot/dts/thead/light-a-val-sec.dts | 6 +- arch/riscv/boot/dts/thead/light-a-val.dts | 316 ++- .../boot/dts/thead/light-ant-discrete.dts | 37 +- arch/riscv/boot/dts/thead/light-ant-ref.dts | 37 +- .../boot/dts/thead/light-b-audio-hdmi.dts | 2515 +++++++++++++++++ .../boot/dts/thead/light-b-product-sec.dts | 2 +- arch/riscv/boot/dts/thead/light-b-product.dts | 243 +- .../riscv/boot/dts/thead/light-beagle-ref.dts | 40 +- arch/riscv/boot/dts/thead/light-crash.dts | 21 +- arch/riscv/boot/dts/thead/light-evb.dtsi | 2 +- arch/riscv/boot/dts/thead/light-fm-emu.dts | 4 +- arch/riscv/boot/dts/thead/light-lpi4a-ref.dts | 183 +- arch/riscv/boot/dts/thead/light-lpi4a-sec.dts | 5 + arch/riscv/boot/dts/thead/light-lpi4a.dts | 2 +- .../boot/dts/thead/light-vi-devices.dtsi | 6 + arch/riscv/boot/dts/thead/light.dtsi | 257 +- arch/riscv/configs/fire_defconfig | 1 + arch/riscv/configs/fire_emu_defconfig | 1 + arch/riscv/configs/light_defconfig | 5 +- arch/riscv/include/asm/Kbuild | 3 +- arch/riscv/include/asm/cmpxchg.h | 24 + arch/riscv/include/asm/io.h | 1 - arch/riscv/include/asm/mmio.h | 2 +- arch/riscv/include/asm/mmiowb.h | 15 - arch/riscv/include/asm/spinlock.h | 85 +- arch/riscv/include/asm/spinlock_types.h | 12 +- arch/riscv/kernel/probes/decode-insn.c | 5 +- arch/riscv/kernel/probes/simulate-insn.c | 112 + drivers/clk/thead/gate/Makefile | 2 +- drivers/clk/thead/gate/audiosys-gate.c | 124 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-designware-core.h | 18 + drivers/i2c/busses/i2c-designware-master.c | 67 +- .../i2c/busses/i2c-designware-master_dma.c | 318 +++ .../i2c/busses/i2c-designware-master_dma.h | 6 + drivers/mailbox/Makefile | 2 +- drivers/mmc/host/sdhci-of-dwcmshc.c | 121 +- drivers/mmc/host/sdhci-of-dwcmshc.h | 4 + drivers/reset/reset-light.c | 20 + drivers/rpmsg/Kconfig | 4 + drivers/rpmsg/Makefile | 1 + drivers/rpmsg/light_rpmsg.c | 763 +++++ drivers/rpmsg/rpmsg_char.c | 9 + drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- drivers/usb/dwc3/dwc3-thead.c | 11 +- drivers/virtio/virtio_vdmabuf.c | 10 +- include/asm-generic/rwonce.h | 1 + include/dt-bindings/clock/light-audiosys.h | 35 + .../pinctrl/light-fm-pinctrl-def.h | 36 + include/dt-bindings/reset/light-reset.h | 5 + include/linux/light_rpmsg.h | 88 + include/uapi/linux/virtio_vdmabuf.h | 3 +- kernel/locking/qspinlock.c | 2 +- kernel/rcu/tree_plugin.h | 10 +- sound/soc/codecs/es7210.c | 14 + sound/soc/codecs/es8156.c | 205 +- sound/soc/generic/simple-card-utils.c | 20 +- sound/soc/thead/Makefile | 2 + sound/soc/thead/light-audio-cpr.h | 49 + sound/soc/thead/light-dummy-pcm.c | 10 +- sound/soc/thead/light-i2s-8ch.c | 797 ++++++ sound/soc/thead/light-i2s.c | 19 +- sound/soc/thead/light-i2s.h | 27 - sound/soc/thead/light-spdif.c | 454 +++ sound/soc/thead/light-spdif.h | 209 ++ sound/soc/thead/light-tdm.c | 145 +- 84 files changed, 7359 insertions(+), 634 deletions(-) create mode 100644 arch/riscv/boot/dts/thead/fire-emu-soc-base-sec.dts create mode 100644 arch/riscv/boot/dts/thead/light-a-val-audio-i2s-8ch.dts create mode 100644 arch/riscv/boot/dts/thead/light-a-val-audio-spdif.dts create mode 100644 arch/riscv/boot/dts/thead/light-b-audio-hdmi.dts delete mode 100644 arch/riscv/include/asm/mmiowb.h create mode 100644 drivers/clk/thead/gate/audiosys-gate.c create mode 100644 drivers/i2c/busses/i2c-designware-master_dma.c create mode 100644 drivers/i2c/busses/i2c-designware-master_dma.h create mode 100644 drivers/rpmsg/light_rpmsg.c create mode 100644 include/dt-bindings/clock/light-audiosys.h create mode 100644 include/dt-bindings/pinctrl/light-fm-pinctrl-def.h create mode 100644 include/linux/light_rpmsg.h create mode 100644 sound/soc/thead/light-audio-cpr.h create mode 100644 sound/soc/thead/light-i2s-8ch.c create mode 100644 sound/soc/thead/light-spdif.c create mode 100644 sound/soc/thead/light-spdif.h diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 8d9715b87..8eb0a52d3 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -21,7 +21,6 @@ config RISCV select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_GIGANTIC_PAGE select ARCH_HAS_KCOV - select ARCH_HAS_MMIOWB select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_SET_DIRECT_MAP select ARCH_HAS_SET_MEMORY @@ -35,6 +34,7 @@ config RISCV select ARCH_KEEP_MEMBLOCK select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT + select ARCH_USE_QUEUED_SPINLOCKS select ARCH_USE_QUEUED_RWLOCKS select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU select ARCH_WANT_FRAME_POINTERS diff --git a/arch/riscv/boot/dts/thead/Makefile b/arch/riscv/boot/dts/thead/Makefile index 68f33952c..a9b5e424b 100644 --- a/arch/riscv/boot/dts/thead/Makefile +++ b/arch/riscv/boot/dts/thead/Makefile @@ -12,8 +12,9 @@ dtb-$(CONFIG_SOC_THEAD) += light-a-val-ddr2G.dtb light-a-val-ddr1G.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-npu-fce.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-iso7816.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-nand.dtb -dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio.dtb +dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio.dtb light-a-val-audio-i2s-8ch.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio-tdm.dtb +dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio-spdif.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-dsi0.dtb light-a-val-dsi1.dtb light-a-val-hdmi.dtb light-a-val-dsi0-dsi1.dtb light-a-val-dsi0-hdmi.dtb light-a-val-dsi0-hdmi-audio.dtb light-a-val-dpi0.dtb light-a-val-dpi0-dpi1.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-wcn.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-gpio-keys.dtb @@ -21,7 +22,7 @@ dtb-$(CONFIG_SOC_THEAD) += light-a-val-khv.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-sec.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-miniapp-hdmi.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-product.dtb -dtb-$(CONFIG_SOC_THEAD) += light-b-product.dtb +dtb-$(CONFIG_SOC_THEAD) += light-b-product.dtb light-b-product-sec.dtb dtb-$(CONFIG_SOC_THEAD) += light-b-product-ddr1G.dtb dtb-$(CONFIG_SOC_THEAD) += light-b-product-miniapp-hdmi.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-full.dtb @@ -38,3 +39,4 @@ dtb-$(CONFIG_SOC_THEAD) += light-a-val-android.dtb dtb-$(CONFIG_SOC_THEAD) += fire-emu.dtb fire-emu-crash.dtb dtb-$(CONFIG_SOC_THEAD) += fire-emu-soc-base.dtb fire-emu-soc-c910x4.dtb fire-emu-gpu-dpu-dsi0.dtb fire-emu-vi-dsp-vo.dtb fire-emu-vi-vp-vo.dtb +dtb-$(CONFIG_SOC_THEAD) += fire-emu-soc-base-sec.dtb diff --git a/arch/riscv/boot/dts/thead/fire-crash.dts b/arch/riscv/boot/dts/thead/fire-crash.dts index e67492628..730dd5c80 100644 --- a/arch/riscv/boot/dts/thead/fire-crash.dts +++ b/arch/riscv/boot/dts/thead/fire-crash.dts @@ -523,7 +523,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 diff --git a/arch/riscv/boot/dts/thead/fire-emu-soc-base-sec.dts b/arch/riscv/boot/dts/thead/fire-emu-soc-base-sec.dts new file mode 100644 index 000000000..21e96ca2a --- /dev/null +++ b/arch/riscv/boot/dts/thead/fire-emu-soc-base-sec.dts @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + +/dts-v1/; + +/* #include "fire-emu.dts" */ +#include "fire-emu-soc-base.dts" + +&light_iopmp { + status = "disabled"; +}; diff --git a/arch/riscv/boot/dts/thead/fire-emu.dts b/arch/riscv/boot/dts/thead/fire-emu.dts index b253add80..63fd37546 100644 --- a/arch/riscv/boot/dts/thead/fire-emu.dts +++ b/arch/riscv/boot/dts/thead/fire-emu.dts @@ -338,16 +338,18 @@ clock-frequency = <100000>; status = "disabled"; - es8156_audio_codec: es8156@8 { + es8156_audio_codec: es8156@8 { #sound-dai-cells = <0>; compatible = "everest,es8156"; reg = <0x08>; - }; + status = "disabled"; + }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; + status = "disabled"; }; }; @@ -488,7 +490,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 diff --git a/arch/riscv/boot/dts/thead/fire.dtsi b/arch/riscv/boot/dts/thead/fire.dtsi index 3d8c56ce7..c2ad7bd40 100644 --- a/arch/riscv/boot/dts/thead/fire.dtsi +++ b/arch/riscv/boot/dts/thead/fire.dtsi @@ -1430,7 +1430,7 @@ compatible = "light,light-i2s"; reg = <0xff 0xe7034000 0x0 0x4000>; pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_audio_i2s0>; + pinctrl-0 = <&pinctrl_light_i2s0>; light,mode = "i2s-master"; light,sel = "ap_i2s"; interrupt-parent = <&intc>; diff --git a/arch/riscv/boot/dts/thead/light-a-product.dts b/arch/riscv/boot/dts/thead/light-a-product.dts index 8f66318ad..ca550a804 100644 --- a/arch/riscv/boot/dts/thead/light-a-product.dts +++ b/arch/riscv/boot/dts/thead/light-a-product.dts @@ -687,6 +687,7 @@ no-mmc; non-removable; io_fixed_1v8; + rxclk-sample-delay = <80>; post-power-on-delay-ms = <50>; wprtn_ignore; cap-sd-highspeed; @@ -729,7 +730,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 diff --git a/arch/riscv/boot/dts/thead/light-a-val-android.dts b/arch/riscv/boot/dts/thead/light-a-val-android.dts index 9b656fe7a..ef3605546 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-android.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-android.dts @@ -63,7 +63,7 @@ sound-dai = <&light_i2s 1>; }; codec { - sound-dai = <&dummy_codec 2>; + sound-dai = <&dummy_codec>; }; }; }; diff --git a/arch/riscv/boot/dts/thead/light-a-val-audio-hdmi.dts b/arch/riscv/boot/dts/thead/light-a-val-audio-hdmi.dts index 05eeba8a8..023897519 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-audio-hdmi.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-audio-hdmi.dts @@ -48,11 +48,11 @@ sound-dai = <&light_i2s 1>; }; codec { - sound-dai = <&dummy_codec 2>; + sound-dai = <&dummy_codec>; }; }; }; &light_i2s { status = "okay"; -}; \ No newline at end of file +}; diff --git a/arch/riscv/boot/dts/thead/light-a-val-audio-i2s-8ch.dts b/arch/riscv/boot/dts/thead/light-a-val-audio-i2s-8ch.dts new file mode 100644 index 000000000..215f57b2c --- /dev/null +++ b/arch/riscv/boot/dts/thead/light-a-val-audio-i2s-8ch.dts @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + +#include "light-a-val-audio.dts" + +/ { + model = "T-HEAD Light FM Audio VAL board"; + compatible = "thead,light-val-audio-i2s-8ch", "thead,light"; +}; + + +&lightsound { + status = "okay"; + + simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/ + reg = <1>; + format = "i2s"; + cpu { + sound-dai = <&i2s_8ch_sd2 2>; + }; + codec { + mclk-fs = <512>; + sound-dai = <&es7210_audio_codec_adc0>; + }; + }; + + simple-audio-card,dai-link@2 { /* I2S - AUDIO SYS CODEC 7210*/ + reg = <2>; + format = "i2s"; + cpu { + sound-dai = <&i2s_8ch_sd3 3>; + }; + codec { + mclk-fs = <512>; + sound-dai = <&es7210_audio_codec_adc0>; + }; + }; + + simple-audio-card,dai-link@3 { /* I2S - AUDIO SYS CODEC 7210_1*/ + reg = <3>; + format = "i2s"; + cpu { + sound-dai = <&i2s_8ch_sd0 0>; + }; + codec { + mclk-fs = <512>; + sound-dai = <&es7210_audio_codec_adc1>; + }; + }; + + simple-audio-card,dai-link@4 { /* I2S - AUDIO SYS CODEC 7210_1*/ + reg = <4>; + format = "i2s"; + cpu { + sound-dai = <&i2s_8ch_sd1 1>; + }; + codec { + mclk-fs = <512>; + sound-dai = <&es7210_audio_codec_adc1>; + }; + }; +}; + +&i2s_8ch_sd0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa4>, + <&pinctrl_audio_i2s_8ch_sd0>, + <&pinctrl_audiopa2>, + <&pinctrl_audiopa3>, + <&pinctrl_audiopa8>, + <&pinctrl_audio_i2s_8ch_bus>; +}; + +&i2s_8ch_sd1 { + status = "okay"; +}; + +&i2s_8ch_sd2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa0>, + <&pinctrl_audio_i2s_8ch_sd2>; +}; + +&i2s_8ch_sd3 { + status = "okay"; +}; + +&es7210_audio_codec_adc0 { + status = "okay"; + channels-max = <8>; +}; + +&es7210_audio_codec_adc1 { + status = "okay"; + channels-max = <8>; +}; diff --git a/arch/riscv/boot/dts/thead/light-a-val-audio-spdif.dts b/arch/riscv/boot/dts/thead/light-a-val-audio-spdif.dts new file mode 100644 index 000000000..91282bc91 --- /dev/null +++ b/arch/riscv/boot/dts/thead/light-a-val-audio-spdif.dts @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + +#include "light-a-val.dts" + +&spdif0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_spdif0>; + status = "okay"; +}; + +&spdif1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_spdif1>; + status = "okay"; +}; + +&lightsound { + status = "okay"; + simple-audio-card,dai-link@0 { /* SPDIF0 */ + reg = <1>; + format = "i2s"; + cpu { + sound-dai = <&spdif0>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; + simple-audio-card,dai-link@1 { /* SPDIF1 */ + reg = <1>; + format = "i2s"; + cpu { + sound-dai = <&spdif1>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; +}; \ No newline at end of file diff --git a/arch/riscv/boot/dts/thead/light-a-val-audio-tdm.dts b/arch/riscv/boot/dts/thead/light-a-val-audio-tdm.dts index 5f95cab76..39683e209 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-audio-tdm.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-audio-tdm.dts @@ -6,6 +6,8 @@ #include "light-a-val.dts" &tdm_slot1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_tdm>; status = "okay"; }; @@ -45,19 +47,26 @@ #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x42>; - work-mode = "ES7210_TDM_1LRCK_DSPB"; + work-mode = "ES7210_TDM_1LRCK_DSPB"; channels-max = <8>; sound-name-prefix = "ES7210_ADC2"; + MVDD-supply = <&soc_aud_adc_3v3_en_reg>; + AVDD-supply = <&soc_aud_adc_3v3_en_reg>; + DVDD-supply = <&soc_dvdd18_aon_reg>; + PVDD-supply = <&soc_dvdd18_aon_reg>; }; es7210_adc3: es7210@43 { #sound-dai-cells = <0>; compatible = "MicArray_1"; reg = <0x43>; - work-mode = "ES7210_TDM_1LRCK_DSPB"; + work-mode = "ES7210_TDM_1LRCK_DSPB"; channels-max = <8>; sound-name-prefix = "ES7210_ADC3"; - status = "okay"; + MVDD-supply = <&soc_aud_adc_3v3_en_reg>; + AVDD-supply = <&soc_aud_adc_3v3_en_reg>; + DVDD-supply = <&soc_dvdd18_aon_reg>; + PVDD-supply = <&soc_dvdd18_aon_reg>; }; }; @@ -65,8 +74,8 @@ status = "okay"; simple-audio-card,widgets = "Speaker", "Speaker"; simple-audio-card,routing = - "Speaker", "AW87519 VO", - "AW87519 IN", "ES8156 ROUT"; + "AW87519 IN", "ES8156 ROUT", + "Speaker", "AW87519 VO"; simple-audio-card,aux-devs = <&audio_aw87519_pa>; simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ reg = <0>; @@ -82,29 +91,85 @@ simple-audio-card,dai-link@1 { /* TDM - AUDIO SYS CODEC 7210*/ reg = <1>; format = "dsp_b"; - cpu@0 { - sound-dai = <&tdm_slot1 0>; + cpu { + sound-dai = <&tdm_slot1>; }; - cpu@1 { - sound-dai = <&tdm_slot2 1>; + codec { + sound-dai = <&es7210_adc2>; }; - cpu@2 { - sound-dai = <&tdm_slot3 2>; + }; + + simple-audio-card,dai-link@2 { + reg = <1>; + format = "dsp_b"; + cpu { + sound-dai = <&tdm_slot2>; }; - cpu@3 { - sound-dai = <&tdm_slot4 3>; + codec { + sound-dai = <&es7210_adc2>; }; - cpu@4 { - sound-dai = <&tdm_slot5 4>; + }; + + simple-audio-card,dai-link@3 { + reg = <1>; + format = "dsp_b"; + cpu { + sound-dai = <&tdm_slot3>; }; - cpu@5 { - sound-dai = <&tdm_slot6 5>; + codec { + sound-dai = <&es7210_adc2>; }; - cpu@6 { - sound-dai = <&tdm_slot7 6>; + }; + + simple-audio-card,dai-link@4 { + reg = <1>; + format = "dsp_b"; + cpu { + sound-dai = <&tdm_slot4>; }; - cpu@7 { - sound-dai = <&tdm_slot8 7>; + codec { + sound-dai = <&es7210_adc2>; + }; + }; + + simple-audio-card,dai-link@5 { + reg = <1>; + format = "dsp_b"; + cpu { + sound-dai = <&tdm_slot5>; + }; + codec { + sound-dai = <&es7210_adc2>; + }; + }; + + simple-audio-card,dai-link@6 { + reg = <1>; + format = "dsp_b"; + cpu { + sound-dai = <&tdm_slot6>; + }; + codec { + sound-dai = <&es7210_adc2>; + }; + }; + + simple-audio-card,dai-link@7 { + reg = <1>; + format = "dsp_b"; + cpu { + sound-dai = <&tdm_slot7>; + }; + codec { + sound-dai = <&es7210_adc2>; + }; + }; + + simple-audio-card,dai-link@8 { + reg = <1>; + format = "dsp_b"; + cpu { + sound-dai = <&tdm_slot8>; }; codec { sound-dai = <&es7210_adc2>; @@ -112,14 +177,6 @@ }; }; -&light_i2s { - status = "okay"; -}; - &i2s0 { status = "okay"; }; - -&i2s3 { - status = "okay"; -}; diff --git a/arch/riscv/boot/dts/thead/light-a-val-audio.dts b/arch/riscv/boot/dts/thead/light-a-val-audio.dts index e99192efb..ede93c44b 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-audio.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-audio.dts @@ -10,18 +10,6 @@ compatible = "thead,light-val-audio", "thead,light"; }; -&audio_i2c0 { - clock-frequency = <100000>; - status = "okay"; - - es7210_audio_codec: es7210@40 { - #sound-dai-cells = <0>; - compatible = "MicArray_0"; - reg = <0x40>; - sound-name-prefix = "ES7210"; - }; -}; - &lightsound { status = "okay"; simple-audio-card,widgets = "Speaker", "Speaker"; @@ -44,22 +32,24 @@ reg = <1>; format = "i2s"; cpu { - sound-dai = <&i2s3 0>; + sound-dai = <&i2s_8ch_sd2 2>; }; codec { - sound-dai = <&es7210_audio_codec>; + sound-dai = <&es7210_audio_codec_adc0>; }; }; }; -&light_i2s { - status = "okay"; -}; - &i2s0 { status = "okay"; }; -&i2s3 { +&i2s_8ch_sd2 { status = "okay"; }; + +&es7210_audio_codec_adc0 { + status = "okay"; +}; + + diff --git a/arch/riscv/boot/dts/thead/light-a-val-dsi0-hdmi-audio.dts b/arch/riscv/boot/dts/thead/light-a-val-dsi0-hdmi-audio.dts index fd99ac975..6d54c69c9 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-dsi0-hdmi-audio.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-dsi0-hdmi-audio.dts @@ -7,17 +7,6 @@ #include "light-a-val-dsi0-hdmi.dts" -&audio_i2c0 { - status = "okay"; - - es7210_audio_codec: es7210@40 { - #sound-dai-cells = <0>; - compatible = "MicArray_0"; - reg = <0x40>; - sound-name-prefix = "ES7210"; - }; -}; - &lightsound { status = "okay"; simple-audio-card,widgets = "Speaker", "Speaker"; @@ -35,14 +24,15 @@ sound-dai = <&es8156_audio_codec>; }; }; + simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/ reg = <1>; format = "i2s"; cpu { - sound-dai = <&i2s3 0>; + sound-dai = <&i2s_8ch_sd2 2>; }; codec { - sound-dai = <&es7210_audio_codec>; + sound-dai = <&es7210_audio_codec_adc0>; }; }; simple-audio-card,dai-link@2 { /* I2S - HDMI */ @@ -58,14 +48,17 @@ }; &light_i2s { - status = "okay"; + status = "okay"; }; &i2s0 { status = "okay"; }; -&i2s3 { +&i2s_8ch_sd2 { status = "okay"; }; +&es7210_audio_codec_adc0 { + status = "okay"; +}; diff --git a/arch/riscv/boot/dts/thead/light-a-val-full.dts b/arch/riscv/boot/dts/thead/light-a-val-full.dts index 2a2c92680..149b1a2a9 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-full.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-full.dts @@ -93,18 +93,6 @@ }; }; -&audio_i2c0 { - clock-frequency = <100000>; - status = "okay"; - - es7210_audio_codec: es7210@40 { - #sound-dai-cells = <0>; - compatible = "MicArray_0"; - reg = <0x40>; - sound-name-prefix = "ES7210"; - }; -}; - &lightsound { status = "okay"; simple-audio-card,widgets = "Speaker", "Speaker"; @@ -122,31 +110,35 @@ sound-dai = <&es8156_audio_codec>; }; }; - + simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/ reg = <1>; format = "i2s"; cpu { - sound-dai = <&i2s3 0>; + sound-dai = <&i2s_8ch_sd2 2>; }; codec { - sound-dai = <&es7210_audio_codec>; + sound-dai = <&es7210_audio_codec_adc0>; }; }; }; - + &light_i2s { - status = "okay"; + status = "okay"; }; - + &i2s0 { status = "okay"; }; - -&i2s3 { + +&i2s_8ch_sd2 { status = "okay"; }; +&es7210_audio_codec_adc0 { + status = "okay"; +}; + &qspi0 { status = "okay"; }; diff --git a/arch/riscv/boot/dts/thead/light-a-val-hdmi.dts b/arch/riscv/boot/dts/thead/light-a-val-hdmi.dts index 233d246dc..23bf31b32 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-hdmi.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-hdmi.dts @@ -48,7 +48,7 @@ sound-dai = <&light_i2s 1>; }; codec { - sound-dai = <&dummy_codec 2>; + sound-dai = <&dummy_codec>; }; }; }; diff --git a/arch/riscv/boot/dts/thead/light-a-val-miniapp-dsi0.dts b/arch/riscv/boot/dts/thead/light-a-val-miniapp-dsi0.dts index 9b97ce58d..1bf9d5e18 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-miniapp-dsi0.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-miniapp-dsi0.dts @@ -74,6 +74,26 @@ }; }; +&padctrl_audiosys { + status = "okay"; + + light-audio-padctrl { + /* + * Pin Configuration Node: + * Format: + */ + + pinctrl_audio_i2s_8ch: audio_i2s_8ch_grp { + thead,pins = < + FM_AUDIO_IO_PA0 0x2 0x008 + FM_AUDIO_IO_PA2 0x2 0x008 + FM_AUDIO_IO_PA3 0x2 0x008 + FM_AUDIO_IO_PA8 0x2 0x008 + >; + }; + }; +}; + &lightsound { status = "okay"; @@ -92,15 +112,14 @@ reg = <1>; format = "i2s"; cpu { - sound-dai = <&i2s3 0>; + sound-dai = <&i2s_8ch_sd2 2>; }; codec { - sound-dai = <&es7210_audio_codec>; + sound-dai = <&es7210_audio_codec_adc0>; }; }; }; - &light_i2s { status = "okay"; }; @@ -109,7 +128,11 @@ status = "okay"; }; -&i2s3 { +&i2s_8ch_sd2 { + status = "okay"; +}; + +&es7210_audio_codec_adc0 { status = "okay"; }; diff --git a/arch/riscv/boot/dts/thead/light-a-val-miniapp-hdmi.dts b/arch/riscv/boot/dts/thead/light-a-val-miniapp-hdmi.dts index 00ec00b13..107a9a1ed 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-miniapp-hdmi.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-miniapp-hdmi.dts @@ -38,18 +38,6 @@ }; }; -&audio_i2c0 { - clock-frequency = <100000>; - status = "okay"; - - es7210_audio_codec: es7210@40 { - #sound-dai-cells = <0>; - compatible = "MicArray_0"; - reg = <0x40>; - sound-name-prefix = "ES7210"; - }; -}; - &lightsound { status = "okay"; @@ -68,10 +56,10 @@ reg = <1>; format = "i2s"; cpu { - sound-dai = <&i2s3 0>; + sound-dai = <&i2s_8ch_sd2 2>; }; codec { - sound-dai = <&es7210_audio_codec>; + sound-dai = <&es7210_audio_codec_adc0>; }; }; }; @@ -85,7 +73,11 @@ status = "okay"; }; -&i2s3 { +&i2s_8ch_sd2 { + status = "okay"; +}; + +&es7210_audio_codec_adc0 { status = "okay"; }; diff --git a/arch/riscv/boot/dts/thead/light-a-val-sec.dts b/arch/riscv/boot/dts/thead/light-a-val-sec.dts index b7aa04f45..841798258 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-sec.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-sec.dts @@ -5,9 +5,13 @@ /dts-v1/; -#include "light-a-val-dsi0-hdmi-audio.dts" +#include "light-a-val-audio-hdmi.dts" &light_iopmp { status = "disabled"; }; +&qspi1 { + status = "disabled"; +}; + diff --git a/arch/riscv/boot/dts/thead/light-a-val.dts b/arch/riscv/boot/dts/thead/light-a-val.dts index 8da963255..d7fa8033b 100644 --- a/arch/riscv/boot/dts/thead/light-a-val.dts +++ b/arch/riscv/boot/dts/thead/light-a-val.dts @@ -179,7 +179,8 @@ compatible = "thead,light-mbox-client"; mbox-names = "906"; mboxes = <&mbox_910t 2 0>; - status = "disabled"; + audio-mbox-regmap = <&audio_mbox>; + status = "okay"; }; lightsound: lightsound@1 { @@ -192,6 +193,20 @@ status = "disabled"; }; + light_rpmsg: light_rpmsg { + compatible = "light,rpmsg-bus", "simple-bus"; + memory-region = <&rpmsgmem>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + rpmsg: rpmsg{ + vdev-nums = <1>; + reg = <0x0 0x1E000000 0 0x10000>; + compatible = "light,light-rpmsg"; + status = "okay"; + }; + }; + dummy_codec: dummy_codec { #sound-dai-cells = <0>; compatible = "thead,light-dummy-pcm"; @@ -263,6 +278,24 @@ enable-active-high; }; + soc_aud_adc_3v3_en_reg: soc-aud-adc-3v3-en { + compatible = "regulator-fixed"; + regulator-name = "soc_aud_adc_3v3_en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pcal6408ahk_b 1 1>; + enable-active-high; + }; + + soc_aud_dac_3v3_en_reg: soc-aud-dac-3v3-en { + compatible = "regulator-fixed"; + regulator-name = "soc_aud_dac_3v3_en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pcal6408ahk_b 2 1>; + enable-active-high; + }; + wcn_wifi: wireless-wlan { compatible = "wlan-platdata"; clock-names = "clk_wifi"; @@ -513,7 +546,14 @@ reg = <0x0 0x22000000 0x0 0x10000000>; no-map; }; - + audio_mem: memory@32000000 { + reg = <0x0 0x32000000 0x0 0x6400000>; + no-map; + }; + rpmsgmem: memory@1E000000 { + reg = <0x0 0x1E000000 0x0 0x10000>; + no-map; + }; }; &adc { @@ -557,13 +597,51 @@ &audio_i2c0 { clock-frequency = <100000>; status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa6>, + <&pinctrl_audiopa7>, + <&pinctrl_audio_i2c0>; - es8156_audio_codec: es8156@8 { - #sound-dai-cells = <0>; - compatible = "everest,es8156"; - reg = <0x08>; - sound-name-prefix = "ES8156"; - }; + es8156_audio_codec: es8156@8 { + #sound-dai-cells = <0>; + compatible = "everest,es8156"; + reg = <0x08>; + sound-name-prefix = "ES8156"; + AVDD-supply = <&soc_aud_dac_3v3_en_reg>; + DVDD-supply = <&soc_dvdd18_aon_reg>; + PVDD-supply = <&soc_dvdd18_aon_reg>; + mclk-sclk-ratio = <4>; + }; + + es7210_audio_codec_adc0: es7210@40 { + #sound-dai-cells = <0>; + compatible = "MicArray_0"; + reg = <0x40>; + status = "disabled"; + work-mode = "ES7210_NORMAL_I2S"; + channels-max = <2>; + mclk-sclk-ratio = <4>; + sound-name-prefix = "ES7210_ADC0"; + MVDD-supply = <&soc_aud_adc_3v3_en_reg>; + AVDD-supply = <&soc_aud_adc_3v3_en_reg>; + DVDD-supply = <&soc_dvdd18_aon_reg>; + PVDD-supply = <&soc_dvdd18_aon_reg>; + }; + + es7210_audio_codec_adc1: es7210@41 { + #sound-dai-cells = <0>; + compatible = "MicArray_1"; + reg = <0x41>; + status = "disabled"; + work-mode = "ES7210_NORMAL_I2S"; + channels-max = <2>; + mclk-sclk-ratio = <4>; + sound-name-prefix = "ES7210_ADC1"; + MVDD-supply = <&soc_aud_adc_3v3_en_reg>; + AVDD-supply = <&soc_aud_adc_3v3_en_reg>; + DVDD-supply = <&soc_dvdd18_aon_reg>; + PVDD-supply = <&soc_dvdd18_aon_reg>; + }; audio_aw87519_pa: amp@58 { compatible = "awinic,aw87519_pa"; @@ -577,6 +655,10 @@ &audio_i2c1 { clock-frequency = <100000>; status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa13>, + <&pinctrl_audiopa16>, + <&pinctrl_audio_i2c1>; pcal6408ahk_b: gpio@20 { compatible = "nxp,pcal9554b"; @@ -733,6 +815,7 @@ no-mmc; non-removable; io_fixed_1v8; + rxclk-sample-delay = <80>; post-power-on-delay-ms = <50>; wprtn_ignore; cap-sd-highspeed; @@ -775,7 +858,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 @@ -850,16 +933,59 @@ * Format: */ - pinctrl_audiopa1: audiopa1_grp { - thead,pins = < - FM_AUDIO_PA1 0x3 0x72 - >; + pinctrl_audiopa0: audiopa0 { + thead,pins = < FM_AUDIO_PA0 LIGHT_PIN_FUNC_0 0x000 >; }; - - pinctrl_audiopa2: audiopa2_grp { - thead,pins = < - FM_AUDIO_PA2 0x0 0x72 - >; + pinctrl_audiopa1: audiopa1 { + thead,pins = < FM_AUDIO_PA1 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa2: audiopa2 { + thead,pins = < FM_AUDIO_PA2 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa3: audiopa3 { + thead,pins = < FM_AUDIO_PA3 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa4: audiopa4 { + thead,pins = < FM_AUDIO_PA4 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa5: audiopa5 { + thead,pins = < FM_AUDIO_PA5 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa6: audiopa6 { + thead,pins = < FM_AUDIO_PA6 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa7: audiopa7 { + thead,pins = < FM_AUDIO_PA7 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa8: audiopa8 { + thead,pins = < FM_AUDIO_PA8 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa9: audiopa9 { + thead,pins = < FM_AUDIO_PA9 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa10: audiopa10 { + thead,pins = < FM_AUDIO_PA10 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa11: audiopa11 { + thead,pins = < FM_AUDIO_PA11 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa12: audiopa12 { + thead,pins = < FM_AUDIO_PA12 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa13: audiopa13 { + thead,pins = < FM_AUDIO_PA13 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa14: audiopa14 { + thead,pins = < FM_AUDIO_PA14 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa15: audiopa15 { + thead,pins = < FM_AUDIO_PA15 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa16: audiopa16 { + thead,pins = < FM_AUDIO_PA16 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa17: audiopa17 { + thead,pins = < FM_AUDIO_PA17 LIGHT_PIN_FUNC_0 0x000 >; }; pinctrl_volume: volume_grp { @@ -881,10 +1007,77 @@ * Format: */ + pinctrl_audio_i2c0: audio_i2c0_grp { + thead,pins = < + FM_AUDIO_IO_PA6 LIGHT_PIN_FUNC_0 0x004 + FM_AUDIO_IO_PA7 LIGHT_PIN_FUNC_0 0x004 + >; + }; pinctrl_audio_i2c1: audio_i2c1_grp { thead,pins = < - FM_AUDIO_IO_PA6 0x2 0x008 - FM_AUDIO_IO_PA7 0x2 0x008 + FM_AUDIO_IO_PA13 LIGHT_PIN_FUNC_1 0x004 + FM_AUDIO_IO_PA16 LIGHT_PIN_FUNC_3 0x004 + >; + }; + pinctrl_audio_i2s0: audio_i2s0_grp { + thead,pins = < + FM_AUDIO_IO_PA9 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA10 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA11 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA12 LIGHT_PIN_FUNC_0 0x008 + >; + }; + pinctrl_audio_i2s1: audio_i2s1_grp { + thead,pins = < + FM_AUDIO_IO_PA14 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA15 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA17 LIGHT_PIN_FUNC_0 0x008 + >; + }; + pinctrl_audio_i2s_8ch_bus: audio_i2s_8ch_bus_grp { + thead,pins = < + FM_AUDIO_IO_PA2 LIGHT_PIN_FUNC_3 0x008 + FM_AUDIO_IO_PA3 LIGHT_PIN_FUNC_3 0x008 + FM_AUDIO_IO_PA8 LIGHT_PIN_FUNC_3 0x008 + >; + }; + pinctrl_audio_i2s_8ch_sd0: audio_i2s_8ch_sd0_grp { + thead,pins = < + FM_AUDIO_IO_PA4 LIGHT_PIN_FUNC_3 0x008 + >; + }; + pinctrl_audio_i2s_8ch_sd1: audio_i2s_8ch_sd1_grp { + thead,pins = < + FM_AUDIO_IO_PA5 LIGHT_PIN_FUNC_3 0x008 + >; + }; + pinctrl_audio_i2s_8ch_sd2: audio_i2s_8ch_sd2_grp { + thead,pins = < + FM_AUDIO_IO_PA0 LIGHT_PIN_FUNC_3 0x008 + >; + }; + pinctrl_audio_i2s_8ch_sd3: audio_i2s_8ch_sd3_grp { + thead,pins = < + FM_AUDIO_IO_PA1 LIGHT_PIN_FUNC_3 0x008 + >; + }; + pinctrl_audio_tdm: audio_tdm_grp { + thead,pins = < + FM_AUDIO_IO_PA27 LIGHT_PIN_FUNC_1 0x007 + FM_AUDIO_IO_PA28 LIGHT_PIN_FUNC_1 0x007 + FM_AUDIO_IO_PA29 LIGHT_PIN_FUNC_1 0x000 + >; + }; + pinctrl_audio_spdif0: audio_spdif0_grp { + thead,pins = < + FM_AUDIO_IO_PA21 LIGHT_PIN_FUNC_1 0x000 + FM_AUDIO_IO_PA22 LIGHT_PIN_FUNC_1 0x007 + >; + }; + pinctrl_audio_spdif1: audio_spdif1_grp { + thead,pins = < + FM_AUDIO_IO_PA23 LIGHT_PIN_FUNC_1 0x007 + FM_AUDIO_IO_PA24 LIGHT_PIN_FUNC_1 0x000 >; }; }; @@ -1024,6 +1217,24 @@ status = "disabled"; }; + +&vvcam_sensor1 { + sensor_name = "OV5693"; + sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; + sensor_regulator_voltage_uV = <1800000 1200000 2800000>; + sensor_regulator_timing_us = <70 50 20>; + sensor_rst = <&gpio1_porta 16 0>; + sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; + DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; + AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; + i2c_reg_width = /bits/ 8 <2>; + i2c_data_width = /bits/ 8 <1>; + i2c_addr = /bits/ 8 <0x36>; + i2c_bus = /bits/ 8 <3>; + status = "okay"; +}; + &vvcam_sensor2 { sensor_name = "GC5035"; sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN"; @@ -1108,6 +1319,22 @@ status = "okay"; }; +&vvcam_sensor7 { + sensor_name = "IMX334"; + sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; + sensor_regulator_timing_us = <70 50 20>; + sensor_rst = <&gpio1_porta 16 0>; + sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; + DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; + AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; + i2c_reg_width = /bits/ 8 <2>; + i2c_data_width = /bits/ 8 <1>; + i2c_addr = /bits/ 8 <0x1a>; + i2c_bus = /bits/ 8 <3>; + status = "okay"; +}; + &video0{ vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2] channel0 { @@ -1314,13 +1541,20 @@ mode_idx = <0>; path_type = "SENSOR_1600x1200_RAW10_LINER"; }; + sensor2 { + subdev_name = "vivcam"; + idx = <7>; //imx334 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_3840x2180_RAW12_LINER"; + }; isp { subdev_name = "isp"; idx = <1>; path_type = "ISP_MI_PATH_MP"; output { - max_width = <1920>; - max_height = <1088>; + max_width = <3840>; + max_height = <2180>; bit_per_pixel = <16>; frame_count = <3>; }; @@ -2173,6 +2407,44 @@ status = "okay"; }; +&i2s0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa9>, + <&pinctrl_audiopa10>, + <&pinctrl_audiopa11>, + <&pinctrl_audiopa12>, + <&pinctrl_audio_i2s0>; +}; + +&i2s_8ch_sd0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa4>, + <&pinctrl_audio_i2s_8ch_sd0>; +}; + +&i2s_8ch_sd1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa5>, + <&pinctrl_audio_i2s_8ch_sd1>; +}; + +&i2s_8ch_sd2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa0>, + <&pinctrl_audio_i2s_8ch_sd2>, + <&pinctrl_audiopa2>, + <&pinctrl_audiopa3>, + <&pinctrl_audiopa8>, + <&pinctrl_audio_i2s_8ch_bus>; +}; + +&i2s_8ch_sd3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa1>, + <&pinctrl_audio_i2s_8ch_sd3>; +}; + + &cpus { c910_0: cpu@0 { operating-points = < diff --git a/arch/riscv/boot/dts/thead/light-ant-discrete.dts b/arch/riscv/boot/dts/thead/light-ant-discrete.dts index fe683e5a7..79f012311 100644 --- a/arch/riscv/boot/dts/thead/light-ant-discrete.dts +++ b/arch/riscv/boot/dts/thead/light-ant-discrete.dts @@ -582,27 +582,31 @@ clock-frequency = <100000>; status = "okay"; - es8156_audio_codec: es8156@8 { - #sound-dai-cells = <0>; - compatible = "everest,es8156"; - reg = <0x08>; - sound-name-prefix = "ES8156"; - }; + es8156_audio_codec: es8156@8 { + #sound-dai-cells = <0>; + compatible = "everest,es8156"; + reg = <0x08>; + sound-name-prefix = "ES8156"; + AVDD-supply = <&soc_aud_3v3_en_reg>; + DVDD-supply = <&soc_aud_1v8_en_reg>; + PVDD-supply = <&soc_aud_1v8_en_reg>; + }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; sound-name-prefix = "ES7210"; + status = "disabled"; }; - audio_aw87519_pa: amp@58 { - compatible = "awinic,aw87519_pa"; - reg = <0x58>; - reset-gpio = <&ao_gpio4_porta 9 0x1>; - sound-name-prefix = "AW87519"; - status = "okay"; - }; + audio_aw87519_pa: amp@58 { + compatible = "awinic,aw87519_pa"; + reg = <0x58>; + reset-gpio = <&ao_gpio4_porta 9 0x1>; + sound-name-prefix = "AW87519"; + status = "okay"; + }; }; &i2c1 { @@ -735,6 +739,7 @@ no-mmc; non-removable; io_fixed_1v8; + rxclk-sample-delay = <80>; post-power-on-delay-ms = <50>; wprtn_ignore; cap-sd-highspeed; @@ -777,7 +782,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 @@ -2114,7 +2119,7 @@ reg = <1>; format = "i2s"; cpu { - sound-dai = <&i2s3 0>; + sound-dai = <&i2s_8ch_sd2 2>; }; codec { sound-dai = <&es7210_audio_codec>; @@ -2144,7 +2149,7 @@ status = "okay"; }; -&i2s3 { +&i2s_8ch_sd2 { status = "okay"; }; diff --git a/arch/riscv/boot/dts/thead/light-ant-ref.dts b/arch/riscv/boot/dts/thead/light-ant-ref.dts index 510cb104a..8ac65feca 100644 --- a/arch/riscv/boot/dts/thead/light-ant-ref.dts +++ b/arch/riscv/boot/dts/thead/light-ant-ref.dts @@ -590,27 +590,31 @@ clock-frequency = <100000>; status = "okay"; - es8156_audio_codec: es8156@8 { - #sound-dai-cells = <0>; - compatible = "everest,es8156"; - reg = <0x08>; - sound-name-prefix = "ES8156"; - }; + es8156_audio_codec: es8156@8 { + #sound-dai-cells = <0>; + compatible = "everest,es8156"; + reg = <0x08>; + sound-name-prefix = "ES8156"; + AVDD-supply = <&soc_aud_3v3_en_reg>; + DVDD-supply = <&soc_aud_1v8_en_reg>; + PVDD-supply = <&soc_aud_1v8_en_reg>; + }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; sound-name-prefix = "ES7210"; + status = "disabled"; }; - audio_aw87519_pa: amp@58 { - compatible = "awinic,aw87519_pa"; - reg = <0x58>; - reset-gpio = <&ao_gpio4_porta 9 0x1>; - sound-name-prefix = "AW87519"; - status = "okay"; - }; + audio_aw87519_pa: amp@58 { + compatible = "awinic,aw87519_pa"; + reg = <0x58>; + reset-gpio = <&ao_gpio4_porta 9 0x1>; + sound-name-prefix = "AW87519"; + status = "okay"; + }; }; &i2c1 { @@ -743,6 +747,7 @@ no-mmc; non-removable; io_fixed_1v8; + rxclk-sample-delay = <80>; post-power-on-delay-ms = <50>; wprtn_ignore; cap-sd-highspeed; @@ -785,7 +790,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 @@ -2295,7 +2300,7 @@ reg = <1>; format = "i2s"; cpu { - sound-dai = <&i2s3 0>; + sound-dai = <&i2s_8ch_sd2 2>; }; codec { sound-dai = <&es7210_audio_codec>; @@ -2325,7 +2330,7 @@ status = "okay"; }; -&i2s3 { +&i2s_8ch_sd2 { status = "okay"; }; diff --git a/arch/riscv/boot/dts/thead/light-b-audio-hdmi.dts b/arch/riscv/boot/dts/thead/light-b-audio-hdmi.dts new file mode 100644 index 000000000..f4e4f958a --- /dev/null +++ b/arch/riscv/boot/dts/thead/light-b-audio-hdmi.dts @@ -0,0 +1,2515 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + +/dts-v1/; + +#include "light.dtsi" +#include +#include +#include "light-vi-devices.dtsi" +/ { + model = "T-HEAD Light val board"; + compatible = "thead,light-val", "thead,light"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x200000 0x0 0x7fe00000>; + }; + + chosen { + bootargs = "console=ttyS0,115200 crashkernel=256M-:128M earlycon clk_ignore_unused sram=0xffe0000000,0x180000"; + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + status = "disabled"; + led0 { + label = "SYS_STATUS"; + gpios = <&gpio1_porta 15 0>; /* GPIO_ACTIVE_HIGH: 0 */ + default-state = "off"; + }; + }; + + display-subsystem { + status = "okay"; + }; + + lcd0_backlight: pwm-backlight@0 { + compatible = "pwm-backlight"; + pwms = <&pwm 0 5000000>; + brightness-levels = <0 4 8 16 32 64 128 255>; + default-brightness-level = <7>; + }; + + light_iopmp: iopmp { + compatible = "thead,light-iopmp"; + + /* config#1: multiple valid regions */ + iopmp_emmc: IOPMP_EMMC { + regions = <0x000000 0x100000>, + <0x100000 0x200000>; + attr = <0xFFFFFFFF>; + dummy_slave= <0x800000>; + }; + + /* config#2: iopmp bypass */ + iopmp_sdio0: IOPMP_SDIO0 { + bypass_en; + }; + + /* config#3: iopmp default region set */ + iopmp_sdio1: IOPMP_SDIO1 { + attr = <0xFFFFFFFF>; + is_default_region; + }; + + iopmp_usb0: IOPMP_USB0 { + attr = <0xFFFFFFFF>; + is_default_region; + }; + + iopmp_ao: IOPMP_AO { + is_default_region; + }; + + iopmp_aud: IOPMP_AUD { + is_default_region; + }; + + iopmp_chip_dbg: IOPMP_CHIP_DBG { + is_default_region; + }; + + iopmp_eip120i: IOPMP_EIP120I { + is_default_region; + }; + + iopmp_eip120ii: IOPMP_EIP120II { + is_default_region; + }; + + iopmp_eip120iii: IOPMP_EIP120III { + is_default_region; + }; + + iopmp_isp0: IOPMP_ISP0 { + is_default_region; + }; + + iopmp_isp1: IOPMP_ISP1 { + is_default_region; + }; + + iopmp_dw200: IOPMP_DW200 { + is_default_region; + }; + + iopmp_vipre: IOPMP_VIPRE { + is_default_region; + }; + + iopmp_venc: IOPMP_VENC { + is_default_region; + }; + + iopmp_vdec: IOPMP_VDEC { + is_default_region; + }; + + iopmp_g2d: IOPMP_G2D { + is_default_region; + }; + + iopmp_fce: IOPMP_FCE { + is_default_region; + }; + + iopmp_npu: IOPMP_NPU { + is_default_region; + }; + + iopmp0_dpu: IOPMP0_DPU { + bypass_en; + }; + + iopmp1_dpu: IOPMP1_DPU { + bypass_en; + }; + + iopmp_gpu: IOPMP_GPU { + is_default_region; + }; + + iopmp_gmac1: IOPMP_GMAC1 { + is_default_region; + }; + + iopmp_gmac2: IOPMP_GMAC2 { + is_default_region; + }; + + iopmp_dmac: IOPMP_DMAC { + is_default_region; + }; + + iopmp_tee_dmac: IOPMP_TEE_DMAC { + is_default_region; + }; + + iopmp_dsp0: IOPMP_DSP0 { + is_default_region; + }; + + iopmp_dsp1: IOPMP_DSP1 { + is_default_region; + }; + }; + + mbox_910t_client1: mbox_910t_client1 { + compatible = "thead,light-mbox-client"; + mbox-names = "902"; + mboxes = <&mbox_910t 1 0>; + status = "disabled"; + }; + + + mbox_910t_client2: mbox_910t_client2 { + compatible = "thead,light-mbox-client"; + mbox-names = "906"; + mboxes = <&mbox_910t 2 0>; + audio-mbox-regmap = <&audio_mbox>; + status = "okay"; + }; + + lightsound: lightsound@1 { + compatible = "simple-audio-card"; + simple-audio-card,name = "Light-Sound-Card"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + light_rpmsg: light_rpmsg { + compatible = "light,rpmsg-bus", "simple-bus"; + memory-region = <&rpmsgmem>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + rpmsg: rpmsg{ + vdev-nums = <1>; + reg = <0x0 0x1E000000 0 0x10000>; + compatible = "light,light-rpmsg"; + status = "okay"; + }; + }; + + dummy_codec: dummy_codec { + #sound-dai-cells = <0>; + compatible = "thead,light-dummy-pcm"; + status = "okay"; + sound-name-prefix = "DUMMY"; + }; + + reg_vref_1v8: regulator-adc-verf { + compatible = "regulator-fixed"; + regulator-name = "vref-1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + status = "okay"; + }; + + reg_tp_pwr_en: regulator-pwr-en { + compatible = "regulator-fixed"; + regulator-name = "PWR_EN"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpio1_porta 12 1>; + enable-active-high; + regulator-always-on; + }; + + wcn_wifi: wireless-wlan { + compatible = "wlan-platdata"; + clock-names = "clk_wifi"; + ref-clock-frequency = <24000000>; + keep_wifi_power_on; + pinctrl-names = "default"; + wifi_chip_type = "rtl8723ds"; + WIFI,poweren_gpio = <&gpio2_porta 29 0>; + WIFI,reset_n = <&gpio2_porta 24 0>; + status = "okay"; + }; + + wcn_bt: wireless-bluetooth { + compatible = "bluetooth-platdata"; + pinctrl-names = "default", "rts_gpio"; + BT,power_gpio = <&gpio2_porta 25 0>; + status = "okay"; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-0 = <&pinctrl_volume>; + pinctrl-names = "default"; + key-volumedown { + label = "Volume Down Key"; + linux,code = ; + debounce-interval = <1>; + gpios = <&ao_gpio_porta 11 0x1>; + }; + key-volumeup { + label = "Volume Up Key"; + linux,code = ; + debounce-interval = <1>; + gpios = <&ao_gpio_porta 10 0x1>; + }; + }; + + aon: aon@0 { + compatible = "thead,light-aon"; + mbox-names = "aon"; + mboxes = <&mbox_910t 1 0>; + status = "okay"; + + pd: light-aon-pd { + compatible = "thead,light-aon-pd"; + #power-domain-cells = <1>; + }; + + soc_aud_3v3_en_reg: soc_aud_3v3_en { + compatible = "regulator-fixed"; + regulator-name = "soc_aud_3v3_en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_3v3_en>; + gpio = <&ao_gpio_porta 7 1>; + enable-active-high; + regulator-always-on; + }; + + soc_aud_1v8_en_reg: soc_aud_1v8_en { + compatible = "regulator-fixed"; + regulator-name = "soc_aud_1v8_en"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_1v8_en>; + gpio = <&ao_gpio_porta 8 1>; + enable-active-high; + regulator-always-on; + }; + + soc_vdd_3v3_en_reg: soc_vdd_3v3_en { + compatible = "regulator-fixed"; + regulator-name = "soc_vdd_3v3_en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio0_porta 30 1>; + enable-active-high; + regulator-always-on; + }; + + soc_lcd0_bias_en_reg: soc_lcd0_bias_en { + compatible = "regulator-fixed"; + regulator-name = "soc_lcd0_bias_en"; + regulator-min-microvolt = <5700000>; + regulator-max-microvolt = <5700000>; + gpio = <&gpio1_porta 10 1>; + enable-active-high; + }; + + soc_vdd5v_se_en_reg: soc_vdd5v_se_en { + compatible = "regulator-fixed"; + regulator-name = "soc_vdd5v_se_en"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio2_porta 14 1>; + enable-active-high; + regulator-always-on; + }; + + soc_wcn33_en_reg: soc_wcn33_en { + compatible = "regulator-fixed"; + regulator-name = "soc_wcn33_en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2_porta 29 1>; + enable-active-high; + regulator-always-on; + }; + + soc_vbus_en_reg: soc_vbus_en { + compatible = "regulator-fixed"; + regulator-name = "soc_vbus_en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2_porta 28 1>; + enable-active-high; + regulator-always-on; + }; + + soc_dovdd18_scan_reg: soc_dovdd18_scan { + compatible = "regulator-fixed"; + regulator-name = "soc_dovdd18_scan"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio2_porta 31 1>; + enable-active-high; + }; + + soc_dvdd12_scan_reg: soc_dvdd12_scan { + compatible = "regulator-fixed"; + regulator-name = "soc_dvdd12_scan"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + gpio = <&gpio3_porta 0 1>; + enable-active-high; + }; + + soc_avdd28_scan_en_reg: soc_avdd28_scan_en { + compatible = "regulator-fixed"; + regulator-name = "soc_avdd28_scan_en"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpio2_porta 30 1>; + enable-active-high; + }; + + soc_avdd28_rgb_reg: soc_avdd28_rgb { + compatible = "regulator-fixed"; + regulator-name = "soc_avdd28_rgb"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpio1_porta 15 1>; + enable-active-high; + }; + + soc_dovdd18_rgb_reg: soc_dovdd18_rgb { + compatible = "regulator-fixed"; + regulator-name = "soc_dovdd18_rgb"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpio1_porta 13 1>; + enable-active-high; + }; + + soc_dvdd12_rgb_reg: soc_dvdd12_rgb { + compatible = "regulator-fixed"; + regulator-name = "soc_dvdd12_rgb"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpio1_porta 14 1>; + enable-active-high; + }; + + soc_avdd25_ir_reg: soc_avdd25_ir { + compatible = "regulator-fixed"; + regulator-name = "soc_avdd25_ir"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + gpio = <&gpio0_porta 28 1>; + enable-active-high; + }; + + soc_dovdd18_ir_reg: soc_dovdd18_ir { + compatible = "regulator-fixed"; + regulator-name = "soc_dovdd18_ir"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio0_porta 27 1>; + enable-active-high; + }; + + soc_dvdd12_ir_reg: soc_dvdd12_ir { + compatible = "regulator-fixed"; + regulator-name = "soc_dvdd12_ir"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + gpio = <&gpio0_porta 29 1>; + enable-active-high; + }; + + aon_reg_ricoh: light-ricoh-reg { + compatible = "thead,light-ricoh-pmic"; + status = "okay"; + + dvdd_cpu_reg: appcpu_dvdd { + regulator-name = "appcpu_dvdd"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + + dvddm_cpu_reg: appcpu_dvddm { + regulator-name = "appcpu_dvddm"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + soc_dvdd18_aon_reg: soc_dvdd18_aon { + regulator-name = "soc_dvdd18_aon"; + regulator-boot-on; + regulator-always-on; + }; + + soc_avdd33_usb3_reg: soc_avdd33_usb3 { + regulator-name = "soc_avdd33_usb3"; + regulator-boot-on; + regulator-always-on; + }; + + soc_dvdd08_aon_reg: soc_dvdd08_aon { + regulator-name = "soc_dvdd08_aon"; + regulator-boot-on; + regulator-always-on; + }; + + soc_dvdd08_ddr_reg: soc_dvdd08_ddr { + regulator-name = "soc_dvdd08_ddr"; + regulator-boot-on; + regulator-always-on; + }; + + soc_vdd_ddr_1v8_reg: soc_vdd_ddr_1v8 { + regulator-name = "soc_vdd_ddr_1v8"; + regulator-boot-on; + regulator-always-on; + }; + + soc_vdd_ddr_1v1_reg: soc_vdd_ddr_1v1 { + regulator-name = "soc_vdd_ddr_1v1"; + regulator-boot-on; + regulator-always-on; + }; + + soc_vdd_ddr_0v6_reg: soc_vdd_ddr_0v6 { + regulator-name = "soc_vdd_ddr_0v6"; + regulator-boot-on; + regulator-always-on; + }; + + soc_dvdd18_ap_reg: soc_dvdd18_ap { + regulator-name = "soc_dvdd18_ap"; + regulator-boot-on; + regulator-always-on; + }; + + soc_dvdd08_ap_reg: soc_dvdd08_ap { + regulator-name = "soc_dvdd08_ap"; + regulator-boot-on; + regulator-always-on; + }; + + soc_avdd08_mipi_hdmi_reg: soc_avdd08_mipi_hdmi { + regulator-name = "soc_avdd08_mipi_hdmi"; + regulator-boot-on; + regulator-always-on; + }; + + soc_avdd18_mipi_hdmi_reg: soc_avdd18_mipi_hdmi { + regulator-name = "soc_avdd18_mipi_hdmi"; + regulator-boot-on; + regulator-always-on; + }; + + soc_vdd33_emmc_reg: soc_vdd33_emmc { + regulator-name = "soc_vdd33_emmc"; + regulator-boot-on; + regulator-always-on; + }; + + soc_vdd18_emmc_reg: soc_vdd18_emmc { + regulator-name = "soc_vdd18_emmc"; + regulator-boot-on; + regulator-always-on; + }; + + soc_vdd18_lcd0_en_reg: soc_lcd0_en { + regulator-name = "soc_lcd0_en"; + }; + soc_vext_1v8_reg: soc_vext_1v8 { + regulator-name = "soc_vext_1v8"; + regulator-boot-on; + regulator-always-on; + }; + }; + + c910_cpufreq { + compatible = "thead,light-mpw-cpufreq"; + status = "okay"; + }; + + test: light-aon-test { + compatible = "thead,light-aon-test"; + }; + }; + +}; + +&resmem { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + tee_mem: memory@1a000000 { + reg = <0x0 0x1a000000 0 0x4000000>; + no-map; + }; + + dsp0_mem: memory@20000000 { /**0x2000_0000~0x2040_0000 4M**/ + reg = <0x0 0x20000000 0x0 0x00280000 /* DSP FW code&data section 2.5M*/ + 0x0 0x20280000 0x0 0x00001000 /* DSP communication area 4K*/ + 0x0 0x20281000 0x0 0x00007000 /* Panic/log page 28K */ + 0x0 0x20288000 0x0 0x00178000>; /* DSP shared memory 1.5M-32K*/ + no-map; + }; + dsp1_mem: memory@20400000 { /**0x2040_0000~0x2080_0000 4M**/ + reg = <0x0 0x20400000 0x0 0x00280000 /* DSP FW code&data section */ + 0x0 0x20680000 0x0 0x00001000 /* DSP communication area */ + 0x0 0x20681000 0x0 0x00007000 /* Panic/log page*/ + 0x0 0x20688000 0x0 0x00178000>; /* DSP shared memory */ + no-map; + }; + vi_mem: framebuffer@10000000 { + reg = <0x0 0x10000000 0x0 0x02C00000 /* vi_mem_pool_region[0] 44 MB (default) */ + 0x0 0x12C00000 0x0 0x01D00000 /* vi_mem_pool_region[1] 29 MB */ + 0x0 0x14900000 0x0 0x01E00000>; /* vi_mem_pool_region[2] 30 MB */ + no-map; + }; + + facelib_mem: memory@17000000 { + reg = <0x0 0x17000000 0 0x02000000>; + no-map; + }; + + audio_mem: memory@32000000 { + reg = <0x0 0x32000000 0x0 0x6400000>; + no-map; + }; + rpmsgmem: memory@1E000000 { + reg = <0x0 0x1E000000 0x0 0x10000>; + no-map; + }; + +}; + +&adc { + vref-supply = <®_vref_1v8>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <100000>; + status = "okay"; + + touch@5d { + #gpio-cells = <2>; + compatible = "goodix,gt911"; + reg = <0x5d>; + interrupt-parent = <&gpio1_porta>; + interrupts = <8 0>; + irq-gpios = <&gpio1_porta 8 0>; + reset-gpios = <&gpio1_porta 7 0>; + AVDD28-supply = <®_tp_pwr_en>; + touchscreen-size-x = <800>; + touchscreen-size-y = <1280>; + }; + +}; + +&audio_i2c0 { + clock-frequency = <100000>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa6>, + <&pinctrl_audiopa7>, + <&pinctrl_audio_i2c0>; + + es8156_audio_codec: es8156@8 { + #sound-dai-cells = <0>; + compatible = "everest,es8156"; + reg = <0x08>; + sound-name-prefix = "ES8156"; + AVDD-supply = <&soc_aud_3v3_en_reg>; + DVDD-supply = <&soc_aud_1v8_en_reg>; + PVDD-supply = <&soc_aud_1v8_en_reg>; + mclk-sclk-ratio = <4>; + }; + + es7210_audio_codec: es7210@40 { + #sound-dai-cells = <0>; + compatible = "MicArray_0"; + reg = <0x40>; + work-mode = "ES7210_NORMAL_I2S"; + channels-max = <2>; + mclk-sclk-ratio = <4>; + sound-name-prefix = "ES7210_ADC0"; + MVDD-supply = <&soc_aud_3v3_en_reg>; + AVDD-supply = <&soc_aud_3v3_en_reg>; + DVDD-supply = <&soc_aud_1v8_en_reg>; + PVDD-supply = <&soc_aud_1v8_en_reg>; + }; + + audio_aw87519_pa: amp@58 { + compatible = "awinic,aw87519_pa"; + reg = <0x58>; + pingctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_pa_rst0>; + reset-gpio = <&ao_gpio4_porta 9 0x1>; + sound-name-prefix = "AW87519"; + status = "okay"; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + status = "okay"; +}; + +&spi0 { + num-cs = <1>; + cs-gpios = <&gpio2_porta 15 0>; // GPIO_ACTIVE_HIGH: 0 + rx-sample-delay-ns = <10>; + status = "disabled"; + + spi_norflash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "winbond,w25q64jwm", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + w25q,fast-read; + }; + + spidev@1 { + compatible = "spidev"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0x1>; + spi-max-frequency = <50000000>; + }; +}; + +&uart0 { + clock-frequency = <100000000>; +}; + +&qspi0 { + num-cs = <1>; + cs-gpios = <&gpio2_porta 3 0>; + rx-sample-dly = <4>; + status = "disabled"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + spi-max-frequency = <100000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + reg = <0>; + + partition@0 { + label = "ubi1"; + reg = <0x00000000 0x08000000>; + }; + }; +}; + +&qspi1 { + compatible = "snps,dw-apb-ssi"; + num-cs = <1>; + cs-gpios = <&gpio0_porta 1 0>; + status = "okay"; + + spidev@0 { + compatible = "spidev"; + #address-cells = <0x1>; + #size-cells = <0x1>; + reg = <0x0>; + spi-max-frequency = <50000000>; + }; +}; + +&gmac0 { + phy-mode = "rgmii-id"; + rx-clk-delay = <0x00>; /* for RGMII */ + tx-clk-delay = <0x00>; /* for RGMII */ + phy-handle = <&phy_88E1111_0>; + status = "okay"; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + + phy_88E1111_0: ethernet-phy@0 { + reg = <0x1>; + }; + + phy_88E1111_1: ethernet-phy@1 { + reg = <0x2>; + }; + }; +}; + +&gmac1 { + phy-mode = "rgmii-id"; + rx-clk-delay = <0x00>; /* for RGMII */ + tx-clk-delay = <0x00>; /* for RGMII */ + phy-handle = <&phy_88E1111_1>; + status = "disabled"; +}; + +&emmc { + max-frequency = <198000000>; + non-removable; + mmc-hs400-1_8v; + io_fixed_1v8; + is_emmc; + no-sdio; + no-sd; + pull_up; + bus-width = <8>; + status = "okay"; +}; + +&sdhci0 { + max-frequency = <198000000>; + bus-width = <4>; + pull_up; + wprtn_ignore; + status = "okay"; +}; + +&sdhci1 { + max-frequency = <100000000>; + bus-width = <4>; + pull_up; + no-sd; + no-mmc; + non-removable; + io_fixed_1v8; + rxclk-sample-delay = <80>; + post-power-on-delay-ms = <50>; + wprtn_ignore; + cap-sd-highspeed; + keep-power-in-suspend; + wakeup-source; + status = "okay"; +}; + +&padctrl0_apsys { /* right-pinctrl */ + light-evb-padctrl0 { + /* + * Pin Configuration Node: + * Format: + */ + pinctrl_uart0: uart0grp { + thead,pins = < + FM_UART0_TXD 0x0 0x72 + FM_UART0_RXD 0x0 0x72 + >; + }; + + pinctrl_spi0: spi0grp { + thead,pins = < + FM_SPI_CSN 0x3 0x20a + FM_SPI_SCLK 0x0 0x20a + FM_SPI_MISO 0x0 0x23a + FM_SPI_MOSI 0x0 0x23a + >; + }; + + pinctrl_qspi0: qspi0grp { + thead,pins = < + FM_QSPI0_SCLK 0x0 0x20f + FM_QSPI0_CSN0 0x3 0x20f + FM_QSPI0_CSN1 0x0 0x20f + FM_QSPI0_D0_MOSI 0x0 0x23f + FM_QSPI0_D1_MISO 0x0 0x23f + FM_QSPI0_D2_WP 0x0 0x23f + FM_QSPI0_D3_HOLD 0x0 0x23f + >; + }; + + pinctrl_light_i2s0: i2s0grp { + thead,pins = < + FM_QSPI0_SCLK 0x2 0x208 + FM_QSPI0_CSN0 0x2 0x238 + FM_QSPI0_CSN1 0x2 0x208 + FM_QSPI0_D0_MOSI 0x2 0x238 + FM_QSPI0_D1_MISO 0x2 0x238 + FM_QSPI0_D2_WP 0x2 0x238 + FM_QSPI0_D3_HOLD 0x2 0x238 + >; + }; + + pinctrl_pwm: pwmgrp { + thead,pins = < + FM_GPIO3_2 0x1 0x208 /* pwm0 */ + >; + }; + }; +}; + +&padctrl1_apsys { /* left-pinctrl */ + light-evb-padctrl1 { + /* + * Pin Configuration Node: + * Format: + */ + pinctrl_uart3: uart3grp { + thead,pins = < + FM_UART3_TXD 0x0 0x72 + FM_UART3_RXD 0x0 0x72 + >; + }; + + pinctrl_uart4: uart4grp { + thead,pins = < + FM_UART4_TXD 0x0 0x72 + FM_UART4_RXD 0x0 0x72 + FM_UART4_CTSN 0x0 0x72 + FM_UART4_RTSN 0x0 0x72 + >; + }; + + pinctrl_qspi1: qspi1grp { + thead,pins = < + FM_QSPI1_SCLK 0x0 0x20a + FM_QSPI1_CSN0 0x3 0x20a + FM_QSPI1_D0_MOSI 0x0 0x23a + FM_QSPI1_D1_MISO 0x0 0x23a + FM_QSPI1_D2_WP 0x0 0x23a + FM_QSPI1_D3_HOLD 0x0 0x23a + >; + }; + + + pinctrl_iso7816: iso7816grp { + thead,pins = < + FM_QSPI1_SCLK 0x1 0x208 + FM_QSPI1_D0_MOSI 0x1 0x238 + FM_QSPI1_D1_MISO 0x1 0x238 + FM_QSPI1_D2_WP 0x1 0x238 + FM_QSPI1_D3_HOLD 0x1 0x238 + >; + }; + + }; +}; + +&padctrl_aosys { + light-aon-padctrl { + /* + * Pin Configuration Node: + * Format: + */ + + pinctrl_audiopa0: audiopa0 { + thead,pins = < FM_AUDIO_PA0 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa1: audiopa1 { + thead,pins = < FM_AUDIO_PA1 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa2: audiopa2 { + thead,pins = < FM_AUDIO_PA2 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa3: audiopa3 { + thead,pins = < FM_AUDIO_PA3 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa6: audiopa6 { + thead,pins = < FM_AUDIO_PA6 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa7: audiopa7 { + thead,pins = < FM_AUDIO_PA7 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa8: audiopa8 { + thead,pins = < FM_AUDIO_PA8 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audio_pa_rst0: audio_pa_rst0 { + thead,pins = < FM_AUDIO_PA9 LIGHT_PIN_FUNC_3 0x000 >; + }; + pinctrl_audiopa13: audiopa13 { + thead,pins = < FM_AUDIO_PA13 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa14: audiopa14 { + thead,pins = < FM_AUDIO_PA14 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa15: audiopa15 { + thead,pins = < FM_AUDIO_PA15 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa17: audiopa17 { + thead,pins = < FM_AUDIO_PA17 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audio_3v3_en: audio_3v3_en { + thead,pins = < FM_AOGPIO_7 LIGHT_PIN_FUNC_3 0x008 >; + }; + pinctrl_audio_1v8_en: audio_1v8_en { + thead,pins = < FM_AOGPIO_8 LIGHT_PIN_FUNC_3 0x008 >; + }; + + pinctrl_volume: volume_grp { + thead,pins = < + FM_AOGPIO_11 0x0 0x238 + FM_AOGPIO_10 0x3 0x238 + >; + }; + }; +}; + +&padctrl_audiosys { + + status = "okay"; + + light-audio-padctrl { + /* + * Pin Configuration Node: + * Format: + */ + + pinctrl_audio_i2c0: audio_i2c0_grp { + thead,pins = < + FM_AUDIO_IO_PA6 LIGHT_PIN_FUNC_0 0x004 + FM_AUDIO_IO_PA7 LIGHT_PIN_FUNC_0 0x004 + >; + }; + pinctrl_audio_i2s1: audio_i2s1_grp { + thead,pins = < + FM_AUDIO_IO_PA13 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA14 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA15 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA17 LIGHT_PIN_FUNC_0 0x008 + >; + }; + pinctrl_audio_i2s_8ch_bus: audio_i2s_8ch_bus_grp { + thead,pins = < + FM_AUDIO_IO_PA2 LIGHT_PIN_FUNC_3 0x008 + FM_AUDIO_IO_PA3 LIGHT_PIN_FUNC_3 0x008 + FM_AUDIO_IO_PA8 LIGHT_PIN_FUNC_3 0x008 + >; + }; + pinctrl_audio_i2s_8ch_sd2: audio_i2s_8ch_sd2_grp { + thead,pins = < + FM_AUDIO_IO_PA0 LIGHT_PIN_FUNC_3 0x008 + >; + }; + pinctrl_audio_i2s_8ch_sd3: audio_i2s_8ch_sd3_grp { + thead,pins = < + FM_AUDIO_IO_PA1 LIGHT_PIN_FUNC_3 0x008 + >; + }; + }; +}; + + +&i2c0 { + clock-frequency = <400000>; + status = "okay"; +}; + +&i2c1 { + clock-frequency = <400000>; + status = "okay"; +}; + +&i2c2 { + clock-frequency = <400000>; + status = "okay"; +}; + +&i2c3 { + clock-frequency = <400000>; + status = "okay"; +}; + +&i2c4 { + clock-frequency = <400000>; + status = "okay"; +}; + +&isp0 { + status = "okay"; +}; + +&isp1 { + status = "okay"; +}; + +&isp_ry0 { + status = "okay"; +}; + +&dewarp { + status = "okay"; +}; + +&dec400_isp0 { + status = "okay"; +}; + +&dec400_isp1 { + status = "okay"; +}; + +&dec400_isp2 { + status = "okay"; +}; + +&bm_visys { + status = "okay"; +}; + +&bm_csi0 { + status = "okay"; +}; + +&bm_csi1 { + status = "okay"; +}; + +&bm_csi2 { + status = "okay"; +}; + +&vi_pre { + vi_pre_irq_en = <1>; + status = "okay"; +}; + +&xtensa_dsp { + status = "okay"; +}; + +&xtensa_dsp0 { + status = "okay"; + memory-region = <&dsp0_mem>; +}; + +&xtensa_dsp1 { + status = "okay"; + memory-region = <&dsp1_mem>; +}; + +&vvcam_flash_led0{ + flash_led_name = "aw36413_aw36515"; + floodlight_i2c_bus = /bits/ 8 <2>; + floodlight_en_pin = <&gpio1_porta 25 0>; + //projection_i2c_bus = /bits/ 8 <2>; + flash_led_touch_pin = <&gpio1_porta 27 0>; //flash led touch pin + status = "okay"; +}; + +&vvcam_sensor0 { + sensor_name = "SC2310"; + sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; + sensor_regulator_timing_us = <70 50 20>; + sensor_rst = <&gpio1_porta 16 0>; + sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; + DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; + AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; + i2c_reg_width = /bits/ 8 <2>; + i2c_data_width = /bits/ 8 <1>; + i2c_addr = /bits/ 8 <0x30>; + i2c_bus = /bits/ 8 <3>; + status = "okay"; +}; + +/* +&vvcam_sensor0 { + sensor_name = "IMX334"; + sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; + sensor_regulator_timing_us = <70 50 20>; + sensor_rst = <&gpio1_porta 16 0>; + sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; + DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; + AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; + i2c_reg_width = /bits/ 8 <2>; + i2c_data_width = /bits/ 8 <1>; + i2c_addr = /bits/ 8 <0x1a>; + i2c_bus = /bits/ 8 <3>; + status = "okay"; +}; +*/ + +&vvcam_sensor1 { + sensor_name = "OV5693"; + i2c_bus = /bits/ 8 <3>; + i2c_reg_width = /bits/ 8 <1>; + i2c_data_width = /bits/ 8 <1>; + status = "disabled"; +}; + +&vvcam_sensor2 { + sensor_name = "GC5035"; + sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN"; + sensor_regulator_timing_us = <100 50 0>; + sensor_pdn = <&gpio1_porta 30 0>; //powerdown pin / shutdown pin + sensor_rst = <&gpio1_porta 29 0>; + sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_SCAN-supply = <&soc_dovdd18_scan_reg>; + DVDD12_SCAN-supply = <&soc_dvdd12_scan_reg>; + AVDD28_SCAN-supply = <&soc_avdd28_scan_en_reg>; + i2c_addr = /bits/ 8 <0x37>; + i2c_bus = /bits/ 8 <4>; + i2c_reg_width = /bits/ 8 <1>; + i2c_data_width = /bits/ 8 <1>; + status = "okay"; +}; + +&vvcam_sensor3 { + sensor_name = "SC2310"; + sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN"; + sensor_regulator_timing_us = <70 50 20>; + sensor_pdn = <&gpio1_porta 30 0>; //powerdown pin / shutdown pin + sensor_rst = <&gpio1_porta 29 0>; + sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_SCAN-supply = <&soc_dovdd18_scan_reg>; + DVDD12_SCAN-supply = <&soc_dvdd12_scan_reg>; + AVDD28_SCAN-supply = <&soc_avdd28_scan_en_reg>; + i2c_bus = /bits/ 8 <4>; + i2c_reg_width = /bits/ 8 <2>; + i2c_data_width = /bits/ 8 <1>; + i2c_addr = /bits/ 8 <0x30>; + status = "okay"; +}; + +&vvcam_sensor4 { + sensor_name = "SC132GS"; + sensor_regulators = "DOVDD18_IR", "DVDD12_IR", "AVDD25_IR"; + sensor_regulator_timing_us = <70 1000 2000>; + i2c_addr = /bits/ 8 <0x31>; + sensor_rst = <&gpio1_porta 24 0>; + sensor_pdn_delay_us = <2000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_IR-supply = <&soc_dovdd18_ir_reg>; + DVDD12_IR-supply = <&soc_dvdd12_ir_reg>; + AVDD25_IR-supply = <&soc_avdd25_ir_reg>; + i2c_reg_width = /bits/ 8 <2>; + i2c_data_width = /bits/ 8 <1>; + i2c_bus = /bits/ 8 <2>; + status = "okay"; +}; + +&vvcam_sensor5 { + sensor_name = "OV12870"; + sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; + sensor_regulator_timing_us = <100 50 0>; + sensor_rst = <&gpio1_porta 16 0>; + sensor_pdn_delay_us = <60>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; + DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; + AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; + i2c_addr = /bits/ 8 <0x10>; + i2c_reg_width = /bits/ 8 <2>; + i2c_data_width = /bits/ 8 <1>; + i2c_bus = /bits/ 8 <3>; + status = "okay"; +}; + +&vvcam_sensor6 { + sensor_name = "GC02M1B"; + sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; + sensor_regulator_timing_us = <70 50 20>; + sensor_rst = <&gpio1_porta 16 0>; + sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; + DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; + AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; + i2c_reg_width = /bits/ 8 <1>; + i2c_data_width = /bits/ 8 <1>; + i2c_addr = /bits/ 8 <0x37>; + i2c_bus = /bits/ 8 <3>; + status = "okay"; +}; + +&video0{ + vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2] + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <3>; + path_type = "SENSOR_1296x972_RAW10_LINER"; //SENSOR_VGA_RAW10_LINER// + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + }; + channel1 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <3>; + path_type = "SENSOR_1296x972_RAW10_LINER"; //SENSOR_VGA_RAW10_LINER// + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_SP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + }; + channel2 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <3>; + path_type = "SENSOR_1296x972_RAW10_LINER"; //SENSOR_VGA_RAW10_LINER// + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_SP2_BP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + }; +}; + + +&video1{ + vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2] + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <3>; + path_type = "SENSOR_1296x972_RAW10_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE0"; + dw_dst_depth = <2>; + }; + }; + channel1 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <3>; + path_type = "SENSOR_1296x972_RAW10_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE1"; + dw_dst_depth = <2>; + }; + }; + channel2 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <3>; + path_type = "SENSOR_1296x972_RAW10_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE2"; + dw_dst_depth = <2>; + }; + }; +}; + +&video2{ + vi_mem_pool_region = <0>; // vi_mem: framebuffer, region[0] + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <16>; + frame_count = <3>; + }; + }; + }; + channel1 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_SP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <16>; + frame_count = <3>; + }; + }; + }; + channel2 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_SP2_BP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <16>; + frame_count = <3>; + }; + }; + }; +}; + +&video3{ + vi_mem_pool_region = <0>; // vi_mem: framebuffer, region[0] + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE0"; + dw_dst_depth = <2>; + }; + }; + channel1 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE1"; + dw_dst_depth = <2>; + }; + }; + channel2 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE2"; + dw_dst_depth = <2>; + }; + }; +}; + +&video4{ + vi_mem_pool_region = <0>; // vi_mem: framebuffer, region[0] + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_PP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dsp { + subdev_name = "dsp"; + idx = <0>; + path_type = "DSP_PATH_ISP_RY"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + ry { + subdev_name = "ry"; + idx = <0>; + path_type = "ISP_RY_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + }; + channel1 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_PP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dsp { + subdev_name = "dsp"; + idx = <0>; + path_type = "DSP_PATH_ISP_RY"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + ry { + subdev_name = "ry"; + idx = <0>; + path_type = "ISP_RY_MI_PATH_SP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + }; + channel2 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_PP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dsp { + subdev_name = "dsp"; + idx = <0>; + path_type = "DSP_PATH_ISP_RY"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + ry { + subdev_name = "ry"; + idx = <0>; + path_type = "ISP_RY_MI_PATH_SP2_BP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + }; +}; + +&video5{ + vi_mem_pool_region = <0>; // vi_mem: framebuffer, region[0] + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_PP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dsp { + subdev_name = "dsp"; + idx = <0>; + path_type = "DSP_PATH_ISP_RY"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + ry { + subdev_name = "ry"; + idx = <0>; + path_type = "ISP_RY_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE0"; + dw_dst_depth = <2>; + }; + }; + channel1 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_PP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dsp { + subdev_name = "dsp"; + idx = <0>; + path_type = "DSP_PATH_ISP_RY"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + ry { + subdev_name = "ry"; + idx = <0>; + path_type = "ISP_RY_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE1"; + dw_dst_depth = <2>; + }; + }; + channel2 { + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_PATH_PP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dsp { + subdev_name = "dsp"; + idx = <0>; + path_type = "DSP_PATH_ISP_RY"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + ry { + subdev_name = "ry"; + idx = <0>; + path_type = "ISP_RY_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE2"; + dw_dst_depth = <2>; + }; + }; +}; + +&video6{ + vi_mem_pool_region = <1>; // vi_mem: framebuffer, region[1] + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <4>; //sc132gs + csi_idx = <2>; //<2>=CSI2X2_A + flash_led_idx = <0>; + mode_idx = <0>; + path_type = "SENSOR_1080X1280_30FPS_RAW10_LINER"; + }; + dsp{ + output { + max_width = <1080>; + max_height = <1280>; + bit_per_pixel = <16>; + frame_count = <3>; + }; + }; + }; + channel1 { + sensor0 { + subdev_name = "vivcam"; + idx = <4>; //sc132gs + csi_idx = <2>; //<2>=CSI2X2_A + flash_led_idx = <0>; + mode_idx = <0>; + path_type = "SENSOR_1080X1280_30FPS_RAW10_LINER"; + }; + dsp{ + output { + max_width = <1080>; + max_height = <1280>; + bit_per_pixel = <16>; + frame_count = <3>; + }; + }; + }; + +}; + +&video7{ + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1080P_RAW10_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_PP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dsp { + subdev_name = "dsp"; + idx = <1>; + path_type = "DSP_PATH_ISP_RY"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + ry { + subdev_name = "ry"; + idx = <0>; + path_type = "ISP_RY_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE0"; + dw_dst_depth = <2>; + }; + }; + channel1 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <3>; + path_type = "SENSOR_1296x972_RAW10_LINER"; //SENSOR_VGA_RAW10_LINER// + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_PP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dsp { + subdev_name = "dsp"; + idx = <1>; + path_type = "DSP_PATH_ISP_RY"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + ry { + subdev_name = "ry"; + idx = <0>; + path_type = "ISP_RY_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE1"; + dw_dst_depth = <2>; + }; + }; + channel2 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <3>; + path_type = "SENSOR_1296x972_RAW10_LINER"; //SENSOR_VGA_RAW10_LINER// + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_PP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dsp { + subdev_name = "dsp"; + idx = <1>; + path_type = "DSP_PATH_ISP_RY"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + ry { + subdev_name = "ry"; + idx = <0>; + path_type = "ISP_RY_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + dw { + subdev_name = "dw"; + idx = <0>; + path_type = "DW_DWE_VSE2"; + dw_dst_depth = <2>; + }; + }; +}; + + +&video8{ + vi_mem_pool_region = <1>; // vi_mem: framebuffer, region[1] + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <3>; + path_type = "SENSOR_1296x972_RAW10_LINER"; //SENSOR_VGA_RAW10_LINER// + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + dsp { + subdev_name = "dsp"; + idx = <0>; + path_type = "DSP_PATH_VIPRE_DDR"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + }; +}; + +&video9{ + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <4>; //sc132gs + csi_idx = <2>; //<2>=CSI2X2_A + mode_idx = <0>; + path_type = "SENSOR_1080X1280_30FPS_RAW10_LINER"; + }; + dsp{ + output { + max_width = <1080>; + max_height = <1280>; + bit_per_pixel = <16>; + frame_count = <3>; + }; + }; + }; +}; + + +&video10{ // TUNINGTOOL + channel0 { + sensor0 { + subdev_name = "vivcam"; + idx = <2>; //<2>=vivcam2 : gc5035 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1080P_RAW10_LINER"; //SENSOR_VGA_RAW10_LINER// + skip_init = <1>; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; //<3>=vivcam3 : sc2310 + csi_idx = <1>; //<1>=CSI2X2_B + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + skip_init = <1>; + }; + }; +}; + +&video11{ + channel0 { + channel_id = <0>; + status = "okay"; + sensor0 { + subdev_name = "vivcam"; + idx = <4>; //sc132gs + csi_idx = <2>; //<2>=CSI2X2_A + flash_led_idx = <0>; + mode_idx = <0>; + path_type = "SENSOR_1080X1280_30FPS_RAW10_LINER"; + }; + isp { + subdev_name = "isp"; + idx = <0>; + path_type = "ISP_MI_PATH_MP"; + output { + max_width = <1920>; + max_height = <1088>; + bit_per_pixel = <12>; + frame_count = <3>; + }; + }; + }; +}; + +&video12{ // TUNINGTOOL + channel0 { // CSI2 + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //sc2310 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + skip_init = <1>; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <6>; //gc02m1b + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_1600x1200_RAW10_LINER"; + skip_init = <1>; + }; + }; +}; + +&video14{ + vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[0] + status = "okay"; + channel0 { + channel_id = <0>; + status = "okay"; + sensor0 { + subdev_name = "vivcam"; + idx = <4>; //sc132gs + csi_idx = <2>; //<2>=CSI2X2_A + flash_led_idx = <0>; + mode_idx = <0>; + path_type = "SENSOR_1080X1280_30FPS_RAW10_LINER"; + }; + dma { + subdev_name = "vipre"; + idx = <0>; + path_type = "VIPRE_CSI2_ISP1"; + }; + isp { + subdev_name = "isp"; + idx = <1>; + path_type = "ISP_MI_MCM_WR0"; + output { + max_width = <1080>; + max_height = <1280>; + bit_per_pixel = <16>; + frame_count = <3>; + }; + }; + }; +}; + +&video15{ + status = "okay"; + //vi_mem_pool_region = <0>; + channel0 { + channel_id = <0>; + status = "okay"; + sensor0 { + subdev_name = "vivcam"; + idx = <0>; //<0>=vivcam0 :2310 + csi_idx = <0>; //<0>=CSI2 + flash_led_idx = <0>; + mode_idx = <1>; + path_type = "SENSOR_1920X1088_26FPS_RAW12_LINER"; + }; + dma { + subdev_name = "vipre"; + idx = <0>; + path_type = "VIPRE_CSI0_DDR"; + }; + }; +}; + +&trng { + status = "disabled"; +}; + +&eip_28 { + status = "okay"; +}; + +&vdec { + status = "okay"; +}; + +&venc { + status = "okay"; +}; + +&isp_venc_shake { + status = "okay"; +}; + +&vidmem { + status = "okay"; + memory-region = <&vi_mem>; +}; + +&gpu { + status = "okay"; +}; + +&npu { + vha_clk_rate = <1000000000>; + status = "okay"; +}; + +&fce { + memory-region = <&facelib_mem>; + status = "okay"; +}; + +&dpu_enc1 { + ports { + /delete-node/ port@0; + }; +}; + +&dpu { + status = "okay"; +}; + +&disp1_out { + remote-endpoint = <&hdmi_tx_in>; +}; + +&hdmi_tx { + status = "okay"; + + port@0 { + /* input */ + hdmi_tx_in: endpoint { + remote-endpoint = <&disp1_out>; + }; + }; +}; + +&lightsound { + status = "okay"; + simple-audio-card,widgets = "Speaker", "Speaker"; + simple-audio-card,routing = + "Speaker", "AW87519 VO", + "AW87519 IN", "ES8156 ROUT"; + simple-audio-card,aux-devs = <&audio_aw87519_pa>; + simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ + reg = <0>; + format = "i2s"; + cpu { + sound-dai = <&i2s1 0>; + }; + codec { + sound-dai = <&es8156_audio_codec>; + }; + }; + simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/ + reg = <1>; + format = "i2s"; + cpu { + sound-dai = <&i2s_8ch_sd2 2>; + }; + codec { + sound-dai = <&es7210_audio_codec>; + }; + }; + simple-audio-card,dai-link@2 { /* I2S - HDMI */ + reg = <2>; + format = "i2s"; + cpu { + sound-dai = <&light_i2s 1>; + }; + codec { + sound-dai = <&dummy_codec>; + }; + }; +}; + +&light_i2s { + status = "okay"; +}; + +&i2s0 { + status = "okay"; +}; + +&i2s1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa13>, + <&pinctrl_audiopa14>, + <&pinctrl_audiopa15>, + <&pinctrl_audiopa17>, + <&pinctrl_audio_i2s1>; +}; + +&i2s_8ch_sd2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa0>, + <&pinctrl_audio_i2s_8ch_sd2>, + <&pinctrl_audiopa2>, + <&pinctrl_audiopa3>, + <&pinctrl_audiopa8>, + <&pinctrl_audio_i2s_8ch_bus>; +}; + +&i2s_8ch_sd3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa1>, + <&pinctrl_audio_i2s_8ch_sd3>; +}; + +&cpus { + c910_0: cpu@0 { + operating-points = < + /* kHz uV */ + 300000 600000 + 800000 700000 + 1500000 800000 + >; + light,dvddm-operating-points = < + /* kHz uV */ + 300000 800000 + 800000 800000 + 1500000 800000 + >; + }; + c910_1: cpu@1 { + operating-points = < + /* kHz uV */ + 300000 600000 + 800000 700000 + 1500000 800000 + >; + light,dvddm-operating-points = < + /* kHz uV */ + 300000 800000 + 800000 800000 + 1500000 800000 + >; + }; + c910_2: cpu@2 { + + operating-points = < + /* kHz uV */ + 300000 600000 + 800000 700000 + 1500000 800000 + >; + light,dvddm-operating-points = < + /* kHz uV */ + 300000 800000 + 800000 800000 + 1500000 800000 + >; + }; + c910_3: cpu@3 { + + operating-points = < + /* kHz uV */ + 300000 600000 + 800000 700000 + 1500000 800000 + >; + light,dvddm-operating-points = < + /* kHz uV */ + 300000 800000 + 800000 800000 + 1500000 800000 + >; + }; +}; diff --git a/arch/riscv/boot/dts/thead/light-b-product-sec.dts b/arch/riscv/boot/dts/thead/light-b-product-sec.dts index 7e53d5b19..d4862ca6a 100644 --- a/arch/riscv/boot/dts/thead/light-b-product-sec.dts +++ b/arch/riscv/boot/dts/thead/light-b-product-sec.dts @@ -5,7 +5,7 @@ /dts-v1/; -#include "light-b-product.dts" +#include "light-b-audio-hdmi.dts" diff --git a/arch/riscv/boot/dts/thead/light-b-product.dts b/arch/riscv/boot/dts/thead/light-b-product.dts index 6eda6e511..3b0d92ec7 100644 --- a/arch/riscv/boot/dts/thead/light-b-product.dts +++ b/arch/riscv/boot/dts/thead/light-b-product.dts @@ -180,7 +180,8 @@ compatible = "thead,light-mbox-client"; mbox-names = "906"; mboxes = <&mbox_910t 2 0>; - status = "disabled"; + audio-mbox-regmap = <&audio_mbox>; + status = "okay"; }; lightsound: lightsound@1 { @@ -193,6 +194,20 @@ status = "disabled"; }; + light_rpmsg: light_rpmsg { + compatible = "light,rpmsg-bus", "simple-bus"; + memory-region = <&rpmsgmem>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + rpmsg: rpmsg{ + vdev-nums = <1>; + reg = <0x0 0x1E000000 0 0x10000>; + compatible = "light,light-rpmsg"; + status = "okay"; + }; + }; + dummy_codec: dummy_codec { #sound-dai-cells = <0>; compatible = "thead,light-dummy-pcm"; @@ -271,6 +286,8 @@ regulator-name = "soc_aud_3v3_en"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_3v3_en>; gpio = <&ao_gpio_porta 7 1>; enable-active-high; regulator-always-on; @@ -281,6 +298,8 @@ regulator-name = "soc_aud_1v8_en"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_1v8_en>; gpio = <&ao_gpio_porta 8 1>; enable-active-high; regulator-always-on; @@ -570,7 +589,14 @@ reg = <0x0 0x17000000 0 0x02000000>; no-map; }; - + audio_mem: memory@32000000 { + reg = <0x0 0x32000000 0x0 0x6400000>; + no-map; + }; + rpmsgmem: memory@1E000000 { + reg = <0x0 0x1E000000 0x0 0x10000>; + no-map; + }; }; @@ -601,24 +627,41 @@ &audio_i2c0 { clock-frequency = <100000>; status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa6>, + <&pinctrl_audiopa7>, + <&pinctrl_audio_i2c0>; - es8156_audio_codec: es8156@8 { - #sound-dai-cells = <0>; - compatible = "everest,es8156"; - reg = <0x08>; - sound-name-prefix = "ES8156"; - }; + es8156_audio_codec: es8156@8 { + #sound-dai-cells = <0>; + compatible = "everest,es8156"; + reg = <0x08>; + sound-name-prefix = "ES8156"; + AVDD-supply = <&soc_aud_3v3_en_reg>; + DVDD-supply = <&soc_aud_1v8_en_reg>; + PVDD-supply = <&soc_aud_1v8_en_reg>; + mclk-sclk-ratio = <4>; + }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; - sound-name-prefix = "ES7210"; + work-mode = "ES7210_NORMAL_I2S"; + channels-max = <2>; + mclk-sclk-ratio = <4>; + sound-name-prefix = "ES7210_ADC0"; + MVDD-supply = <&soc_aud_3v3_en_reg>; + AVDD-supply = <&soc_aud_3v3_en_reg>; + DVDD-supply = <&soc_aud_1v8_en_reg>; + PVDD-supply = <&soc_aud_1v8_en_reg>; }; audio_aw87519_pa: amp@58 { compatible = "awinic,aw87519_pa"; reg = <0x58>; + pingctrl-names = "default"; + pinctrl-0 = <&pinctrl_audio_pa_rst0>; reset-gpio = <&ao_gpio4_porta 9 0x1>; sound-name-prefix = "AW87519"; status = "okay"; @@ -754,6 +797,7 @@ no-mmc; non-removable; io_fixed_1v8; + rxclk-sample-delay = <80>; post-power-on-delay-ms = <50>; wprtn_ignore; cap-sd-highspeed; @@ -796,7 +840,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 @@ -870,16 +914,47 @@ * Format: */ - pinctrl_audiopa1: audiopa1_grp { - thead,pins = < - FM_AUDIO_PA1 0x3 0x72 - >; + pinctrl_audiopa0: audiopa0 { + thead,pins = < FM_AUDIO_PA0 LIGHT_PIN_FUNC_0 0x000 >; }; - - pinctrl_audiopa2: audiopa2_grp { - thead,pins = < - FM_AUDIO_PA2 0x0 0x72 - >; + pinctrl_audiopa1: audiopa1 { + thead,pins = < FM_AUDIO_PA1 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa2: audiopa2 { + thead,pins = < FM_AUDIO_PA2 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa3: audiopa3 { + thead,pins = < FM_AUDIO_PA3 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa6: audiopa6 { + thead,pins = < FM_AUDIO_PA6 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa7: audiopa7 { + thead,pins = < FM_AUDIO_PA7 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa8: audiopa8 { + thead,pins = < FM_AUDIO_PA8 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audio_pa_rst0: audio_pa_rst0 { + thead,pins = < FM_AUDIO_PA9 LIGHT_PIN_FUNC_3 0x000 >; + }; + pinctrl_audiopa13: audiopa13 { + thead,pins = < FM_AUDIO_PA13 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa14: audiopa14 { + thead,pins = < FM_AUDIO_PA14 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa15: audiopa15 { + thead,pins = < FM_AUDIO_PA15 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa17: audiopa17 { + thead,pins = < FM_AUDIO_PA17 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audio_3v3_en: audio_3v3_en { + thead,pins = < FM_AOGPIO_7 LIGHT_PIN_FUNC_3 0x008 >; + }; + pinctrl_audio_1v8_en: audio_1v8_en { + thead,pins = < FM_AOGPIO_8 LIGHT_PIN_FUNC_3 0x008 >; }; pinctrl_volume: volume_grp { @@ -891,6 +966,51 @@ }; }; +&padctrl_audiosys { + + status = "okay"; + + light-audio-padctrl { + /* + * Pin Configuration Node: + * Format: + */ + + pinctrl_audio_i2c0: audio_i2c0_grp { + thead,pins = < + FM_AUDIO_IO_PA6 LIGHT_PIN_FUNC_0 0x004 + FM_AUDIO_IO_PA7 LIGHT_PIN_FUNC_0 0x004 + >; + }; + pinctrl_audio_i2s1: audio_i2s1_grp { + thead,pins = < + FM_AUDIO_IO_PA13 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA14 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA15 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA17 LIGHT_PIN_FUNC_0 0x008 + >; + }; + pinctrl_audio_i2s_8ch_bus: audio_i2s_8ch_bus_grp { + thead,pins = < + FM_AUDIO_IO_PA2 LIGHT_PIN_FUNC_3 0x008 + FM_AUDIO_IO_PA3 LIGHT_PIN_FUNC_3 0x008 + FM_AUDIO_IO_PA8 LIGHT_PIN_FUNC_3 0x008 + >; + }; + pinctrl_audio_i2s_8ch_sd2: audio_i2s_8ch_sd2_grp { + thead,pins = < + FM_AUDIO_IO_PA0 LIGHT_PIN_FUNC_3 0x008 + >; + }; + pinctrl_audio_i2s_8ch_sd3: audio_i2s_8ch_sd3_grp { + thead,pins = < + FM_AUDIO_IO_PA1 LIGHT_PIN_FUNC_3 0x008 + >; + }; + }; +}; + + &i2c0 { clock-frequency = <400000>; status = "okay"; @@ -1004,30 +1124,21 @@ status = "okay"; }; -/* -&vvcam_sensor0 { - sensor_name = "IMX334"; - sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; - sensor_regulator_timing_us = <70 50 20>; - sensor_rst = <&gpio1_porta 16 0>; - sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready - DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; - DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; - AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; +&vvcam_sensor1 { + sensor_name = "OV5693"; + sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; + sensor_regulator_voltage_uV = <1800000 1200000 2800000>; + sensor_regulator_timing_us = <70 50 20>; + sensor_rst = <&gpio1_porta 16 0>; + sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; + DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; + AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; i2c_reg_width = /bits/ 8 <2>; i2c_data_width = /bits/ 8 <1>; - i2c_addr = /bits/ 8 <0x1a>; - i2c_bus = /bits/ 8 <3>; - status = "okay"; -}; -*/ - -&vvcam_sensor1 { - sensor_name = "OV5693"; - i2c_bus = /bits/ 8 <3>; - i2c_reg_width = /bits/ 8 <1>; - i2c_data_width = /bits/ 8 <1>; - status = "disabled"; + i2c_addr = /bits/ 8 <0x36>; + i2c_bus = /bits/ 8 <3>; + status = "okay"; }; &vvcam_sensor2 { @@ -1112,6 +1223,22 @@ status = "okay"; }; +&vvcam_sensor7 { + sensor_name = "IMX334"; + sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; + sensor_regulator_timing_us = <70 50 20>; + sensor_rst = <&gpio1_porta 16 0>; + sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; + DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; + AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; + i2c_reg_width = /bits/ 8 <2>; + i2c_data_width = /bits/ 8 <1>; + i2c_addr = /bits/ 8 <0x1a>; + i2c_bus = /bits/ 8 <3>; + status = "okay"; +}; + &video0{ vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2] channel0 { @@ -1318,13 +1445,20 @@ mode_idx = <0>; path_type = "SENSOR_1600x1200_RAW10_LINER"; }; + sensor2 { + subdev_name = "vivcam"; + idx = <7>; //imx334 + csi_idx = <0>; //<0>=CSI2 + mode_idx = <0>; + path_type = "SENSOR_3840x2180_RAW12_LINER"; + }; isp { subdev_name = "isp"; idx = <1>; path_type = "ISP_MI_PATH_MP"; output { - max_width = <1920>; - max_height = <1088>; + max_width = <3840>; + max_height = <2180>; bit_per_pixel = <16>; frame_count = <3>; }; @@ -2336,7 +2470,7 @@ reg = <1>; format = "i2s"; cpu { - sound-dai = <&i2s3 0>; + sound-dai = <&i2s_8ch_sd2 2>; }; codec { sound-dai = <&es7210_audio_codec>; @@ -2364,10 +2498,29 @@ &i2s1 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa13>, + <&pinctrl_audiopa14>, + <&pinctrl_audiopa15>, + <&pinctrl_audiopa17>, + <&pinctrl_audio_i2s1>; }; -&i2s3 { +&i2s_8ch_sd2 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa0>, + <&pinctrl_audio_i2s_8ch_sd2>, + <&pinctrl_audiopa2>, + <&pinctrl_audiopa3>, + <&pinctrl_audiopa8>, + <&pinctrl_audio_i2s_8ch_bus>; +}; + +&i2s_8ch_sd3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa1>, + <&pinctrl_audio_i2s_8ch_sd3>; }; &cpus { diff --git a/arch/riscv/boot/dts/thead/light-beagle-ref.dts b/arch/riscv/boot/dts/thead/light-beagle-ref.dts index 00414ffe3..0987478c9 100644 --- a/arch/riscv/boot/dts/thead/light-beagle-ref.dts +++ b/arch/riscv/boot/dts/thead/light-beagle-ref.dts @@ -570,27 +570,34 @@ clock-frequency = <100000>; status = "okay"; - es8156_audio_codec: es8156@8 { - #sound-dai-cells = <0>; - compatible = "everest,es8156"; - reg = <0x08>; - sound-name-prefix = "ES8156"; - }; + es8156_audio_codec: es8156@8 { + #sound-dai-cells = <0>; + compatible = "everest,es8156"; + reg = <0x08>; + sound-name-prefix = "ES8156"; + AVDD-supply = <&soc_aud_3v3_en_reg>; + DVDD-supply = <&soc_aud_1v8_en_reg>; + PVDD-supply = <&soc_aud_1v8_en_reg>; + }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; sound-name-prefix = "ES7210"; + MVDD-supply = <&soc_aud_3v3_en_reg>; + AVDD-supply = <&soc_aud_3v3_en_reg>; + DVDD-supply = <&soc_aud_1v8_en_reg>; + PVDD-supply = <&soc_aud_1v8_en_reg>; }; - audio_aw87519_pa: amp@58 { - compatible = "awinic,aw87519_pa"; - reg = <0x58>; - reset-gpio = <&ao_gpio4_porta 9 0x1>; - sound-name-prefix = "AW87519"; - status = "okay"; - }; + audio_aw87519_pa: amp@58 { + compatible = "awinic,aw87519_pa"; + reg = <0x58>; + reset-gpio = <&ao_gpio4_porta 9 0x1>; + sound-name-prefix = "AW87519"; + status = "okay"; + }; }; &i2c1 { @@ -723,6 +730,7 @@ no-mmc; non-removable; io_fixed_1v8; + rxclk-sample-delay = <80>; post-power-on-delay-ms = <50>; wprtn_ignore; cap-sd-highspeed; @@ -765,7 +773,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 @@ -2272,7 +2280,7 @@ reg = <1>; format = "i2s"; cpu { - sound-dai = <&i2s3 0>; + sound-dai = <&i2s_8ch_sd2 2>; }; codec { sound-dai = <&es7210_audio_codec>; @@ -2302,7 +2310,7 @@ status = "okay"; }; -&i2s3 { +&i2s_8ch_sd2 { status = "okay"; }; diff --git a/arch/riscv/boot/dts/thead/light-crash.dts b/arch/riscv/boot/dts/thead/light-crash.dts index ffdbf6357..03aa9967b 100644 --- a/arch/riscv/boot/dts/thead/light-crash.dts +++ b/arch/riscv/boot/dts/thead/light-crash.dts @@ -343,6 +343,7 @@ compatible = "everest,es8156"; reg = <0x08>; sound-name-prefix = "ES8156"; + status = "disabled"; }; es7210_audio_codec: es7210@40 { @@ -350,6 +351,7 @@ compatible = "MicArray_0"; reg = <0x40>; sound-name-prefix = "ES7210"; + status = "disabled"; }; audio_aw87519_pa: amp@58 { @@ -492,6 +494,7 @@ no-mmc; non-removable; io_fixed_1v8; + rxclk-sample-delay = <80>; post-power-on-delay-ms = <50>; wprtn_ignore; cap-sd-highspeed; @@ -534,7 +537,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 @@ -866,22 +869,6 @@ status = "disabled"; }; -&light_i2s { - status = "okay"; -}; - -&i2s0 { - status = "okay"; -}; - -&i2s1 { - status = "okay"; -}; - -&i2s3 { - status = "okay"; -}; - &khvhost { status = "disabled"; }; diff --git a/arch/riscv/boot/dts/thead/light-evb.dtsi b/arch/riscv/boot/dts/thead/light-evb.dtsi index 9224181f8..ee82e3df5 100644 --- a/arch/riscv/boot/dts/thead/light-evb.dtsi +++ b/arch/riscv/boot/dts/thead/light-evb.dtsi @@ -1299,7 +1299,7 @@ compatible = "light,light-i2s"; reg = <0xff 0xe7034000 0x0 0x4000>; pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_audio_i2s0>; + pinctrl-0 = <&pinctrl_light_i2s0>; light,mode = "i2s-master"; interrupt-parent = <&intc>; interrupts = <70>; diff --git a/arch/riscv/boot/dts/thead/light-fm-emu.dts b/arch/riscv/boot/dts/thead/light-fm-emu.dts index 13b076d54..9bb7ba0f5 100644 --- a/arch/riscv/boot/dts/thead/light-fm-emu.dts +++ b/arch/riscv/boot/dts/thead/light-fm-emu.dts @@ -185,7 +185,7 @@ sound-dai = <&light_i2s 0>; }; codec { - sound-dai = <&dummy_codec 2>; + sound-dai = <&dummy_codec>; }; }; @@ -196,7 +196,7 @@ sound-dai = <&light_i2s 1>; }; codec { - sound-dai = <&dummy_codec 2>; + sound-dai = <&dummy_codec>; }; }; }; diff --git a/arch/riscv/boot/dts/thead/light-lpi4a-ref.dts b/arch/riscv/boot/dts/thead/light-lpi4a-ref.dts index 02104476e..126ddf3a5 100644 --- a/arch/riscv/boot/dts/thead/light-lpi4a-ref.dts +++ b/arch/riscv/boot/dts/thead/light-lpi4a-ref.dts @@ -172,7 +172,8 @@ compatible = "thead,light-mbox-client"; mbox-names = "906"; mboxes = <&mbox_910t 2 0>; - status = "disabled"; + audio-mbox-regmap = <&audio_mbox>; + status = "okay"; }; lightsound: lightsound@1 { @@ -185,6 +186,20 @@ status = "disabled"; }; + light_rpmsg: light_rpmsg { + compatible = "light,rpmsg-bus", "simple-bus"; + memory-region = <&rpmsgmem>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + rpmsg: rpmsg{ + vdev-nums = <1>; + reg = <0x0 0x1E000000 0 0x10000>; + compatible = "light,light-rpmsg"; + status = "okay"; + }; + }; + dummy_codec: dummy_codec { #sound-dai-cells = <0>; compatible = "thead,light-dummy-pcm"; @@ -367,6 +382,7 @@ regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; gpio = <&pcal6408ahk_b 1 1>; + regulator-always-on; enable-active-high; }; @@ -376,6 +392,7 @@ regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; gpio = <&pcal6408ahk_b 2 1>; + regulator-always-on; enable-active-high; }; @@ -385,6 +402,7 @@ regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; gpio = <&pcal6408ahk_b 0 1>; + regulator-always-on; enable-active-high; }; @@ -642,6 +660,14 @@ reg = <0x0 0x17000000 0 0x02000000>; no-map; }; + audio_mem: memory@32000000 { + reg = <0x0 0x32000000 0x0 0x6400000>; + no-map; + }; + rpmsgmem: memory@1E000000 { + reg = <0x0 0x1E000000 0x0 0x10000>; + no-map; + }; }; @@ -654,12 +680,19 @@ &audio_i2c0 { clock-frequency = <100000>; status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa29>, + <&pinctrl_audiopa30>, + <&pinctrl_audio_i2c0>; es8156_audio_codec: es8156@8 { #sound-dai-cells = <0>; compatible = "everest,es8156"; reg = <0x08>; sound-name-prefix = "ES8156"; + AVDD-supply = <&soc_aud_3v3_en_reg>; + DVDD-supply = <&soc_aud_1v8_en_reg>; + PVDD-supply = <&soc_aud_1v8_en_reg>; }; es7210_audio_codec: es7210@40 { @@ -882,7 +915,7 @@ >; }; - pinctrl_audio_i2s0: i2s0grp { + pinctrl_light_i2s0: i2s0grp { thead,pins = < FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_CSN0 0x2 0x238 @@ -970,10 +1003,87 @@ FM_AUDIO_PA2 0x0 0x72 >; }; + pinctrl_audiopa6: audiopa6 { + thead,pins = < FM_AUDIO_PA6 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa7: audiopa7 { + thead,pins = < FM_AUDIO_PA7 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa14: audiopa14 { + thead,pins = < FM_AUDIO_PA14 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa15: audiopa15 { + thead,pins = < FM_AUDIO_PA15 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa16: audiopa16 { + thead,pins = < FM_AUDIO_PA16 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa17: audiopa17 { + thead,pins = < FM_AUDIO_PA17 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa18: audiopa18 { + thead,pins = < FM_AOGPIO_7 LIGHT_PIN_FUNC_1 0x000 >; + }; + pinctrl_audiopa19: audiopa19 { + thead,pins = < FM_AOGPIO_8 LIGHT_PIN_FUNC_1 0x000 >; + }; + pinctrl_audiopa21: audiopa21 { + thead,pins = < FM_AOGPIO_10 LIGHT_PIN_FUNC_1 0x000 >; + }; + pinctrl_audiopa22: audiopa22 { + thead,pins = < FM_AOGPIO_11 LIGHT_PIN_FUNC_1 0x000 >; + }; + pinctrl_audiopa29: audiopa29 { + thead,pins = < FM_AUDIO_PA29 LIGHT_PIN_FUNC_0 0x000 >; + }; + pinctrl_audiopa30: audiopa30 { + thead,pins = < FM_AUDIO_PA30 LIGHT_PIN_FUNC_0 0x000 >; + }; }; }; +&padctrl_audiosys { + + status = "okay"; + + light-audio-padctrl { + /* + * Pin Configuration Node: + * Format: + */ + + pinctrl_audio_i2c0: audio_i2c0_grp { + thead,pins = < + FM_AUDIO_IO_PA29 LIGHT_PIN_FUNC_2 0x004 + FM_AUDIO_IO_PA30 LIGHT_PIN_FUNC_2 0x004 + >; + }; + pinctrl_audio_i2c1: audio_i2c1_grp { + thead,pins = < + FM_AUDIO_IO_PA6 LIGHT_PIN_FUNC_2 0x004 + FM_AUDIO_IO_PA7 LIGHT_PIN_FUNC_2 0x004 + >; + }; + pinctrl_audio_i2s1: audio_i2s1_grp { + thead,pins = < + FM_AUDIO_IO_PA14 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA15 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA16 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA17 LIGHT_PIN_FUNC_0 0x008 + >; + }; + pinctrl_audio_i2s2: audio_i2s2_grp { + thead,pins = < + FM_AUDIO_IO_PA18 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA19 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA21 LIGHT_PIN_FUNC_0 0x008 + FM_AUDIO_IO_PA22 LIGHT_PIN_FUNC_0 0x008 + >; + }; + }; +}; + &i2c0 { clock-frequency = <400000>; status = "okay"; @@ -1134,6 +1244,24 @@ status = "okay"; }; +&vvcam_sensor3 {//cam3 csi0 modified + sensor_name = "OV5693"; + sensor_regulators = "soc_dovdd18_rgb", "soc_dvdd12_rgb", "soc_avdd28_rgb"; + sensor_regulator_voltage_uV = <1800000 1200000 2800000>; + sensor_regulator_timing_us = <70 50 20>; + sensor_pdn = <&gpio1_porta 28 0>; //powerdown pin / shutdown pin + sensor_rst = <&pcal6408ahk_c 1 0>; + sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready + DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; + DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; + AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; + i2c_reg_width = /bits/ 8 <2>; + i2c_data_width = /bits/ 8 <1>; + i2c_addr = /bits/ 8 <0x36>; + i2c_bus = /bits/ 8 <0>; + status = "okay"; +}; + &video2 { vi_mem_pool_region = <0>; // vi_mem: framebuffer, region[0] status = "okay"; @@ -1142,11 +1270,18 @@ status = "okay"; sensor0 { subdev_name = "vivcam"; - idx = <0>; + idx = <0>; csi_idx = <0>; mode_idx = <0>; path_type = "SENSOR_VGA_RAW12_LINER"; }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; + csi_idx = <0>; + mode_idx = <1>; + path_type = "SENSOR_2592x1944_LINER"; + }; dma { subdev_name = "vipre"; idx = <0>; @@ -1157,8 +1292,8 @@ idx = <1>; path_type = "ISP_MI_PATH_MP"; output { - max_width = <1920>; - max_height = <1088>; + max_width = <2600>; + max_height = <2000>; bit_per_pixel = <12>; frame_count = <3>; }; @@ -1179,6 +1314,13 @@ path_type = "SENSOR_VGA_RAW12_LINER"; }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; + csi_idx = <0>; + mode_idx = <1>; + path_type = "SENSOR_2592x1944_LINER"; + }; dma { subdev_name = "vipre"; idx = <0>; @@ -1316,15 +1458,22 @@ status = "okay"; sensor0 { subdev_name = "vivcam"; - idx = <2>; - csi_idx = <1>; //csi_b + idx = <0>; + csi_idx = <0>; mode_idx = <0>; - path_type = "SENSOR_1080X1280_30FPS_RAW10_LINER"; + path_type = "SENSOR_VGA_RAW12_LINER"; + }; + sensor1 { + subdev_name = "vivcam"; + idx = <3>; + csi_idx = <0>; + mode_idx = <1>; + path_type = "SENSOR_2592x1944_LINER"; }; dma { subdev_name = "vipre"; idx = <0>; - path_type = "VIPRE_CSI1_DDR"; + path_type = "VIPRE_CSI0_DDR"; }; }; }; @@ -1438,14 +1587,22 @@ &i2s1 { status = "okay"; dmas = <&dmac2 11>, <&dmac2 10>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa14>, + <&pinctrl_audiopa15>, + <&pinctrl_audiopa16>, + <&pinctrl_audiopa17>, + <&pinctrl_audio_i2s1>; }; &i2s2 { status = "okay"; -}; - -&i2s3 { - status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audiopa18>, + <&pinctrl_audiopa19>, + <&pinctrl_audiopa21>, + <&pinctrl_audiopa22>, + <&pinctrl_audio_i2s2>; }; &usb_1 { diff --git a/arch/riscv/boot/dts/thead/light-lpi4a-sec.dts b/arch/riscv/boot/dts/thead/light-lpi4a-sec.dts index e5a511345..cefaf9105 100644 --- a/arch/riscv/boot/dts/thead/light-lpi4a-sec.dts +++ b/arch/riscv/boot/dts/thead/light-lpi4a-sec.dts @@ -11,3 +11,8 @@ &light_iopmp { status = "disabled"; }; + +&qspi1 { + status = "disabled"; +}; + diff --git a/arch/riscv/boot/dts/thead/light-lpi4a.dts b/arch/riscv/boot/dts/thead/light-lpi4a.dts index 2058f6868..0591f6ce1 100644 --- a/arch/riscv/boot/dts/thead/light-lpi4a.dts +++ b/arch/riscv/boot/dts/thead/light-lpi4a.dts @@ -16,5 +16,5 @@ }; &cmamem { - alloc-ranges = <0x1 0xe4000000 0 0x14000000>; // [0x1E400_0000 ~ 0x1F800_0000] + alloc-ranges = <0 0xe4000000 0 0x14000000>; // [0x0E400_0000 ~ 0x0F800_0000] }; diff --git a/arch/riscv/boot/dts/thead/light-vi-devices.dtsi b/arch/riscv/boot/dts/thead/light-vi-devices.dtsi index bc2fd8d90..4bd13a419 100644 --- a/arch/riscv/boot/dts/thead/light-vi-devices.dtsi +++ b/arch/riscv/boot/dts/thead/light-vi-devices.dtsi @@ -199,6 +199,12 @@ csi_idx = <0xff>; path_type = "SENSOR_VGA_RAW10_LINER"; }; + sensor2 { + subdev_name = "vivcam"; + idx = <0xff>; // invalid + csi_idx = <0xff>; + path_type = "SENSOR_VGA_RAW10_LINER"; + }; dma { subdev_name = "vipre"; idx = <0>; diff --git a/arch/riscv/boot/dts/thead/light.dtsi b/arch/riscv/boot/dts/thead/light.dtsi index 2d8db6ad8..af281ef35 100644 --- a/arch/riscv/boot/dts/thead/light.dtsi +++ b/arch/riscv/boot/dts/thead/light.dtsi @@ -7,11 +7,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -35,7 +37,7 @@ i2c3 = &i2c3; i2c4 = &i2c4; audio_i2c0 = &audio_i2c0; - audio_i2c1 = &audio_i2c1; + audio_i2c1 = &audio_i2c1; mmc0 = &emmc; mmc1 = &sdhci0; serial0 = &uart0; @@ -56,6 +58,7 @@ vivcam4 = &vvcam_sensor4; vivcam5 = &vvcam_sensor5; vivcam6 = &vvcam_sensor6; + vivcam7 = &vvcam_sensor7; viv_video0 = &video0; viv_video1 = &video1; @@ -95,11 +98,10 @@ }; }; - aon_iram: aon-iram@ffffef8000 { - compatible = "syscon"; - reg = <0xff 0xffef8000 0x0 0x10000>; - }; - + aon_iram: aon-iram@ffffef8000 { + compatible = "syscon"; + reg = <0xff 0xffef8000 0x0 0x10000>; + }; thermal-zones { cpu-thermal-zone { @@ -641,6 +643,12 @@ status = "okay"; }; + audio_mbox: audio_mbox@0xffefc48000 { + compatible = "thead,light-audio-mbox-reg", "syscon"; + reg = <0xff 0xefc48000 0x0 0x1000>; + status = "okay"; + }; + nvmem_controller: efuse@ffff210000 { compatible = "thead,light-fm-efuse", "syscon"; reg = <0xff 0xff210000 0x0 0x10000>; @@ -1261,6 +1269,13 @@ status = "okay"; }; + vpsys_rst: vpsys-reset-controller@ffecc30000 { + compatible = "thead,light-vpsys-reset-src","syscon"; + reg = <0xff 0xecc30000 0x0 0x1000>; + #reset-cells = <1>; + status = "okay"; + }; + sys_reg: sys_reg@ffef010100 { compatible = "thead,light_sys_reg"; reg = <0xff 0xef010100 0x0 0x100>; @@ -1413,7 +1428,8 @@ clock-names = "pclk", "aclk"; vha_clk_rate = <1000000000>; ldo_vha-supply = <&npu>; - dma-mask = <0xf 0xffffffff>; + dma-mask = <0xff 0xffffffff>; + resets = <&rst LIGHT_RESET_NPU>; status = "disabled"; }; @@ -1442,6 +1458,7 @@ clocks = <&vpsys_clk_gate LIGHT_VPSYS_FCE_ACLK>, <&vpsys_clk_gate LIGHT_VPSYS_FCE_PCLK>; clock-names = "aclk", "pclk"; + resets = <&vpsys_rst LIGHT_RESET_FCE>; dma-mask = <0xf 0xffffffff>; status = "disabled"; }; @@ -1491,7 +1508,7 @@ compatible = "light,light-i2s"; reg = <0xff 0xe7034000 0x0 0x4000>; pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_audio_i2s0>; + pinctrl-0 = <&pinctrl_light_i2s0>; light,mode = "i2s-master"; light,sel = "ap_i2s"; interrupt-parent = <&intc>; @@ -1516,7 +1533,7 @@ light,sel = "i2s0"; interrupt-parent = <&intc>; interrupts = <174>; - dmas = <&dmac2 9>, <&dmac2 16>; + dmas = <&dmac2 9>, <&dmac2 8>; dma-names = "tx", "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; @@ -1565,16 +1582,74 @@ status = "disabled"; }; - i2s3: audio_i2s3@0xffcb017000 { + i2s_8ch_sd0: audio_i2s_8ch_sd0@0xffcb017000 { #sound-dai-cells = <1>; - compatible = "light,light-i2s"; + compatible = "light,light-i2s-8ch"; reg = <0xff 0xcb017000 0x0 0x1000>; + audio-cpr-regmap = <&audio_cpr>; pinctrl-names = "default"; light,mode = "i2s-master"; - light,sel = "i2s3"; + light,sel = "i2s_8ch_sd0"; interrupt-parent = <&intc>; interrupts = <177>; - dmas = <&dmac2 14>, <&dmac2 16>; + dmas = <&dmac2 36>, <&dmac2 14>; + dma-names = "tx", "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + i2s_8ch_sd1: audio_i2s_8ch_sd1@0xffcb017000 { + #sound-dai-cells = <1>; + compatible = "light,light-i2s-8ch"; + reg = <0xff 0xcb017000 0x0 0x1000>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,sel = "i2s_8ch_sd1"; + interrupt-parent = <&intc>; + interrupts = <177>; + dmas = <&dmac2 37>, <&dmac2 15>; + dma-names = "tx", "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + i2s_8ch_sd2: audio_i2s_8ch_sd2@0xffcb017000 { + #sound-dai-cells = <1>; + compatible = "light,light-i2s-8ch"; + reg = <0xff 0xcb017000 0x0 0x1000>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,sel = "i2s_8ch_sd2"; + interrupt-parent = <&intc>; + interrupts = <177>; + dmas = <&dmac2 38>, <&dmac2 16>; + dma-names = "tx", "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + i2s_8ch_sd3: audio_i2s_8ch_sd3@0xffcb017000 { + #sound-dai-cells = <1>; + compatible = "light,light-i2s-8ch"; + reg = <0xff 0xcb017000 0x0 0x1000>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,sel = "i2s_8ch_sd3"; + interrupt-parent = <&intc>; + interrupts = <177>; + dmas = <&dmac2 39>, <&dmac2 17>; dma-names = "tx", "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; @@ -1584,7 +1659,7 @@ }; tdm_slot1: audio_tdm_slot1@0xffcb012000 { - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; compatible = "light,light-tdm"; reg = <0xff 0xcb012000 0x0 0x1000>; audio-pin-regmap = <&audio_ioctrl>; @@ -1599,13 +1674,13 @@ dma-names = "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; - clocks = <&dummy_clock_apb>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>; clock-names = "pclk"; status = "disabled"; }; tdm_slot2: audio_tdm_slot2@0xffcb012000 { - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; compatible = "light,light-tdm"; reg = <0xff 0xcb012000 0x0 0x1000>; audio-pin-regmap = <&audio_ioctrl>; @@ -1620,13 +1695,13 @@ dma-names = "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; - clocks = <&dummy_clock_apb>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>; clock-names = "pclk"; status = "disabled"; }; tdm_slot3: audio_tdm_slot3@0xffcb012000 { - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; compatible = "light,light-tdm"; reg = <0xff 0xcb012000 0x0 0x1000>; audio-pin-regmap = <&audio_ioctrl>; @@ -1641,13 +1716,13 @@ dma-names = "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; - clocks = <&dummy_clock_apb>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>; clock-names = "pclk"; status = "disabled"; }; tdm_slot4: audio_tdm_slot4@0xffcb012000 { - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; compatible = "light,light-tdm"; reg = <0xff 0xcb012000 0x0 0x1000>; audio-pin-regmap = <&audio_ioctrl>; @@ -1662,13 +1737,13 @@ dma-names = "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; - clocks = <&dummy_clock_apb>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>; clock-names = "pclk"; status = "disabled"; }; tdm_slot5: audio_tdm_slot5@0xffcb012000 { - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; compatible = "light,light-tdm"; reg = <0xff 0xcb012000 0x0 0x1000>; audio-pin-regmap = <&audio_ioctrl>; @@ -1683,13 +1758,13 @@ dma-names = "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; - clocks = <&dummy_clock_apb>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>; clock-names = "pclk"; status = "disabled"; }; tdm_slot6: audio_tdm_slot6@0xffcb012000 { - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; compatible = "light,light-tdm"; reg = <0xff 0xcb012000 0x0 0x1000>; audio-pin-regmap = <&audio_ioctrl>; @@ -1704,13 +1779,13 @@ dma-names = "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; - clocks = <&dummy_clock_apb>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>; clock-names = "pclk"; status = "disabled"; }; tdm_slot7: audio_tdm_slot7@0xffcb012000 { - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; compatible = "light,light-tdm"; reg = <0xff 0xcb012000 0x0 0x1000>; audio-pin-regmap = <&audio_ioctrl>; @@ -1725,13 +1800,13 @@ dma-names = "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; - clocks = <&dummy_clock_apb>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>; clock-names = "pclk"; status = "disabled"; }; tdm_slot8: audio_tdm_slot8@0xffcb012000 { - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; compatible = "light,light-tdm"; reg = <0xff 0xcb012000 0x0 0x1000>; audio-pin-regmap = <&audio_ioctrl>; @@ -1746,7 +1821,43 @@ dma-names = "rx"; light,dma_maxburst = <4>; #dma-cells = <1>; - clocks = <&dummy_clock_apb>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>; + clock-names = "pclk"; + status = "disabled"; + }; + + spdif0: audio_spdif0@0xffcb018000 { + #sound-dai-cells = <0>; + compatible = "light,light-spdif"; + reg = <0xff 0xcb018000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + interrupt-parent = <&intc>; + interrupts = <179>; + dmas = <&dmac2 25>, <&dmac2 24>; + dma-names = "tx", "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_SPDIF0>; + clock-names = "pclk"; + status = "disabled"; + }; + + spdif1: audio_spdif1@0xffcb019000 { + #sound-dai-cells = <0>; + compatible = "light,light-spdif"; + reg = <0xff 0xcb019000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + interrupt-parent = <&intc>; + interrupts = <180>; + dmas = <&dmac2 27>, <&dmac2 26>; + dma-names = "tx", "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_SPDIF1>; clock-names = "pclk"; status = "disabled"; }; @@ -1770,6 +1881,10 @@ interrupts = <44>; clocks = <&dummy_clock_apb>; clock-frequency = <100000>; + i2c_mode = "dma"; + dmas = <&dmac0 12>, <&dmac0 13>; + dma-names = "tx", "rx"; + #dma-cells = <1>; ss_hcnt = /bits/ 16 <0x104>; ss_lcnt = /bits/ 16 <0xec>; fs_hcnt = /bits/ 16 <0x37>; @@ -1789,6 +1904,10 @@ interrupts = <45>; clocks = <&dummy_clock_apb>; clock-frequency = <100000>; + i2c_mode = "dma"; + dmas = <&dmac0 14>, <&dmac0 15>; + dma-names = "tx", "rx"; + #dma-cells = <1>; ss_hcnt = /bits/ 16 <0x104>; ss_lcnt = /bits/ 16 <0xec>; fs_hcnt = /bits/ 16 <0x37>; @@ -1808,6 +1927,10 @@ interrupts = <46>; clocks = <&dummy_clock_apb>; clock-frequency = <100000>; + i2c_mode = "dma"; + dmas = <&dmac0 16>, <&dmac0 17>; + dma-names = "tx", "rx"; + #dma-cells = <1>; ss_hcnt = /bits/ 16 <0x104>; ss_lcnt = /bits/ 16 <0xec>; fs_hcnt = /bits/ 16 <0x37>; @@ -1829,6 +1952,10 @@ interrupts = <47>; clocks = <&dummy_clock_apb>; clock-frequency = <100000>; + i2c_mode = "dma"; + dmas = <&dmac0 18>, <&dmac0 19>; + dma-names = "tx", "rx"; + #dma-cells = <1>; ss_hcnt = /bits/ 16 <0x104>; ss_lcnt = /bits/ 16 <0xec>; fs_hcnt = /bits/ 16 <0x37>; @@ -1850,6 +1977,10 @@ interrupts = <48>; clocks = <&dummy_clock_apb>; clock-frequency = <100000>; + i2c_mode = "dma"; + dmas = <&dmac0 20>, <&dmac0 21>; + dma-names = "tx", "rx"; + #dma-cells = <1>; ss_hcnt = /bits/ 16 <0x104>; ss_lcnt = /bits/ 16 <0xec>; fs_hcnt = /bits/ 16 <0x37>; @@ -1871,6 +2002,10 @@ interrupts = <182>; clocks = <&dummy_clock_apb>; clock-frequency = <100000>; + i2c_mode = "dma"; + dmas = <&dmac2 21>, <&dmac2 20>; + dma-names = "tx", "rx"; + #dma-cells = <1>; ss_hcnt = /bits/ 16 <0x82>; ss_lcnt = /bits/ 16 <0x78>; fs_hcnt = /bits/ 16 <0x37>; @@ -1883,26 +2018,30 @@ #size-cells = <0>; }; - audio_i2c1: i2c@0xffcb01b000 { - compatible = "snps,designware-i2c"; - reg = <0xff 0xcb01b000 0x0 0x1000>; - interrupt-parent = <&intc>; - interrupts = <183>; - clocks = <&dummy_clock_apb>; - clock-frequency = <100000>; - ss_hcnt = /bits/ 16 <0x82>; - ss_lcnt = /bits/ 16 <0x78>; - fs_hcnt = /bits/ 16 <0x37>; - fs_lcnt = /bits/ 16 <0x42>; - fp_hcnt = /bits/ 16 <0x14>; - fp_lcnt = /bits/ 16 <0x1a>; - hs_hcnt = /bits/ 16 <0x5>; - hs_lcnt = /bits/ 16 <0x15>; - status = "disabled"; + audio_i2c1: i2c@0xffcb01b000 { + compatible = "snps,designware-i2c"; + reg = <0xff 0xcb01b000 0x0 0x1000>; + interrupt-parent = <&intc>; + interrupts = <183>; + clocks = <&dummy_clock_apb>; + clock-frequency = <100000>; + i2c_mode = "dma"; + dmas = <&dmac2 23>, <&dmac2 22>; + dma-names = "tx", "rx"; + #dma-cells = <1>; + ss_hcnt = /bits/ 16 <0x82>; + ss_lcnt = /bits/ 16 <0x78>; + fs_hcnt = /bits/ 16 <0x37>; + fs_lcnt = /bits/ 16 <0x42>; + fp_hcnt = /bits/ 16 <0x14>; + fp_lcnt = /bits/ 16 <0x1a>; + hs_hcnt = /bits/ 16 <0x5>; + hs_lcnt = /bits/ 16 <0x15>; + status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; + }; isp0: isp@ffe4100000 { compatible = "thead,light-isp"; @@ -2183,6 +2322,11 @@ status = "disabled"; }; + vvcam_sensor7: vvcam_sensor@7 { + compatible = "thead,light-vvcam-sensor"; + status = "disabled"; + }; + xtensa_dsp: dsp@01{ compatible = "thead,dsp-hw-common"; reg = <0xff 0xef040000 0x0 0x001000 >; /*DSP_SYSREG(0x0000-0xFFF) */ @@ -2332,11 +2476,11 @@ interrupts = <215>; /* TEE INT SRC_7 */ }; - light_event: light-event { - compatible = "thead,light-event"; - aon-iram-regmap = <&aon_iram>; - status = "okay"; - }; + light_event: light-event { + compatible = "thead,light-event"; + aon-iram-regmap = <&aon_iram>; + status = "okay"; + }; visys_clk_gate: visys-clk-gate { /* VI_SYSREG_R */ compatible = "thead,visys-gate-controller"; @@ -2365,6 +2509,13 @@ #clock-cells = <1>; status = "okay"; }; + + audiosys_clk_gate: audiosys-clk-gate { + compatible = "thead,audiosys-gate-controller"; + audiosys-regmap = <&audio_cpr>; + #clock-cells = <1>; + status = "okay"; + }; }; }; diff --git a/arch/riscv/configs/fire_defconfig b/arch/riscv/configs/fire_defconfig index 41cad23e9..59b699dd8 100644 --- a/arch/riscv/configs/fire_defconfig +++ b/arch/riscv/configs/fire_defconfig @@ -251,6 +251,7 @@ CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_LIGHT=y CONFIG_HWSPINLOCK_LIGHT_TEST=m CONFIG_MAILBOX=y +CONFIG_EXTCON=y CONFIG_IIO=y CONFIG_IIO_SW_DEVICE=y CONFIG_PWM=y diff --git a/arch/riscv/configs/fire_emu_defconfig b/arch/riscv/configs/fire_emu_defconfig index 2e52816e0..5432f4d97 100644 --- a/arch/riscv/configs/fire_emu_defconfig +++ b/arch/riscv/configs/fire_emu_defconfig @@ -252,6 +252,7 @@ CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_LIGHT=y CONFIG_HWSPINLOCK_LIGHT_TEST=m CONFIG_MAILBOX=y +CONFIG_EXTCON=y CONFIG_IIO=y CONFIG_IIO_SW_DEVICE=y CONFIG_PWM=y diff --git a/arch/riscv/configs/light_defconfig b/arch/riscv/configs/light_defconfig index db5633009..28c91fb56 100644 --- a/arch/riscv/configs/light_defconfig +++ b/arch/riscv/configs/light_defconfig @@ -20,7 +20,6 @@ CONFIG_SOC_THEAD=y CONFIG_SMP=y CONFIG_VECTOR=y CONFIG_VECTOR_0_7=y -CONFIG_THEAD_ISA=y CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y CONFIG_CPU_IDLE=y @@ -267,6 +266,10 @@ CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK_LIGHT=y CONFIG_HWSPINLOCK_LIGHT_TEST=m CONFIG_MAILBOX=y +CONFIG_RPMSG=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_VIRTIO=y +CONFIG_RPMSG_THEAD_LIGHT=y CONFIG_EXTCON=y CONFIG_IIO=y CONFIG_IIO_SW_DEVICE=y diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild index 4be104a25..240452e38 100644 --- a/arch/riscv/include/asm/Kbuild +++ b/arch/riscv/include/asm/Kbuild @@ -3,7 +3,8 @@ generic-y += early_ioremap.h generic-y += extable.h generic-y += flat.h generic-y += kvm_para.h +generic-y += mcs_spinlock.h +generic-y += qspinlock.h generic-y += qrwlock.h -generic-y += qrwlock_types.h generic-y += user.h generic-y += vmlinux.lds.h diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h index 262e5bbb2..fe0d9a037 100644 --- a/arch/riscv/include/asm/cmpxchg.h +++ b/arch/riscv/include/asm/cmpxchg.h @@ -11,12 +11,36 @@ #include #include +static inline ulong __xchg16_relaxed(ulong new, void *ptr) +{ + ulong ret, tmp; + ulong shif = ((ulong)ptr & 2) ? 16 : 0; + ulong mask = 0xffff << shif; + ulong *__ptr = (ulong *)((ulong)ptr & ~2); + + __asm__ __volatile__ ( + "0: lr.w %0, %2\n" + " and %1, %0, %z3\n" + " or %1, %1, %z4\n" + " sc.w %1, %1, %2\n" + " bnez %1, 0b\n" + : "=&r" (ret), "=&r" (tmp), "+A" (*__ptr) + : "rJ" (~mask), "rJ" (new << shif) + : "memory"); + + return (ulong)((ret & mask) >> shif); +} + #define __xchg_relaxed(ptr, new, size) \ ({ \ __typeof__(ptr) __ptr = (ptr); \ __typeof__(new) __new = (new); \ __typeof__(*(ptr)) __ret; \ switch (size) { \ + case 2: { \ + __ret = (__typeof__(*(ptr))) \ + __xchg16_relaxed((ulong)__new, __ptr); \ + break;} \ case 4: \ __asm__ __volatile__ ( \ " amoswap.w %0, %2, %1\n" \ diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h index c025a746a..eeb5db833 100644 --- a/arch/riscv/include/asm/io.h +++ b/arch/riscv/include/asm/io.h @@ -13,7 +13,6 @@ #include #include -#include #include /* diff --git a/arch/riscv/include/asm/mmio.h b/arch/riscv/include/asm/mmio.h index aff6c33ab..88414b5a7 100644 --- a/arch/riscv/include/asm/mmio.h +++ b/arch/riscv/include/asm/mmio.h @@ -133,7 +133,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) #define __io_br() do {} while (0) #define __io_ar(v) __asm__ __volatile__ ("fence i,r" : : : "memory") #define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory") -#define __io_aw() mmiowb_set_pending() +#define __io_aw() __asm__ __volatile__ ("fence o,w" : : : "memory") #define readb(c) ({ u8 __v; __io_br(); __v = readb_cpu(c); __io_ar(__v); __v; }) #define readw(c) ({ u16 __v; __io_br(); __v = readw_cpu(c); __io_ar(__v); __v; }) diff --git a/arch/riscv/include/asm/mmiowb.h b/arch/riscv/include/asm/mmiowb.h deleted file mode 100644 index 0b2333e71..000000000 --- a/arch/riscv/include/asm/mmiowb.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef _ASM_RISCV_MMIOWB_H -#define _ASM_RISCV_MMIOWB_H - -/* - * "o,w" is sufficient to ensure that all writes to the device have completed - * before the write to the spinlock is allowed to commit. - */ -#define mmiowb() __asm__ __volatile__ ("fence o,w" : : : "memory"); - -#include -#include - -#endif /* _ASM_RISCV_MMIOWB_H */ diff --git a/arch/riscv/include/asm/spinlock.h b/arch/riscv/include/asm/spinlock.h index f1f79bce2..4e2696d54 100644 --- a/arch/riscv/include/asm/spinlock.h +++ b/arch/riscv/include/asm/spinlock.h @@ -1,92 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* - * 'Generic' ticket-lock implementation. - * - * It relies on atomic_fetch_add() having well defined forward progress - * guarantees under contention. If your architecture cannot provide this, stick - * to a test-and-set lock. - * - * It also relies on atomic_fetch_add() being safe vs smp_store_release() on a - * sub-word of the value. This is generally true for anything LL/SC although - * you'd be hard pressed to find anything useful in architecture specifications - * about this. If your architecture cannot do this you might be better off with - * a test-and-set. - * - * It further assumes atomic_*_release() + atomic_*_acquire() is RCpc and hence - * uses atomic_fetch_add() which is RCsc to create an RCsc hot path, along with - * a full fence after the spin to upgrade the otherwise-RCpc - * atomic_cond_read_acquire(). - * - * The implementation uses smp_cond_load_acquire() to spin, so if the - * architecture has WFE like instructions to sleep instead of poll for word - * modifications be sure to implement that (see ARM64 for example). - * - */ - #ifndef __ASM_GENERIC_SPINLOCK_H #define __ASM_GENERIC_SPINLOCK_H -#include -#include - -static __always_inline void arch_spin_lock(arch_spinlock_t *lock) -{ - u32 val = atomic_fetch_add(1<<16, lock); - u16 ticket = val >> 16; - - if (ticket == (u16)val) - return; - - /* - * atomic_cond_read_acquire() is RCpc, but rather than defining a - * custom cond_read_rcsc() here we just emit a full fence. We only - * need the prior reads before subsequent writes ordering from - * smb_mb(), but as atomic_cond_read_acquire() just emits reads and we - * have no outstanding writes due to the atomic_fetch_add() the extra - * orderings are free. - */ - atomic_cond_read_acquire(lock, ticket == (u16)VAL); - smp_mb(); -} - -static __always_inline bool arch_spin_trylock(arch_spinlock_t *lock) -{ - u32 old = atomic_read(lock); - - if ((old >> 16) != (old & 0xffff)) - return false; - - return atomic_try_cmpxchg(lock, &old, old + (1<<16)); /* SC, for RCsc */ -} - -static __always_inline void arch_spin_unlock(arch_spinlock_t *lock) -{ - u16 *ptr = (u16 *)lock + IS_ENABLED(CONFIG_CPU_BIG_ENDIAN); - u32 val = atomic_read(lock); - - smp_store_release(ptr, (u16)val + 1); -} - -static __always_inline int arch_spin_is_locked(arch_spinlock_t *lock) -{ - u32 val = atomic_read(lock); - - return ((val >> 16) != (val & 0xffff)); -} - -static __always_inline int arch_spin_is_contended(arch_spinlock_t *lock) -{ - u32 val = atomic_read(lock); - - return (s16)((val >> 16) - (val & 0xffff)) > 1; -} - -static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock) -{ - return !arch_spin_is_locked(&lock); -} - +#include #include #endif /* __ASM_GENERIC_SPINLOCK_H */ diff --git a/arch/riscv/include/asm/spinlock_types.h b/arch/riscv/include/asm/spinlock_types.h index 8962bb730..f534aa5de 100644 --- a/arch/riscv/include/asm/spinlock_types.h +++ b/arch/riscv/include/asm/spinlock_types.h @@ -3,15 +3,7 @@ #ifndef __ASM_GENERIC_SPINLOCK_TYPES_H #define __ASM_GENERIC_SPINLOCK_TYPES_H -#include -typedef atomic_t arch_spinlock_t; - -/* - * qrwlock_types depends on arch_spinlock_t, so we must typedef that before the - * include. - */ -#include - -#define __ARCH_SPIN_LOCK_UNLOCKED ATOMIC_INIT(0) +#include +#include #endif /* __ASM_GENERIC_SPINLOCK_TYPES_H */ diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c index 0876c304c..d17446827 100644 --- a/arch/riscv/kernel/probes/decode-insn.c +++ b/arch/riscv/kernel/probes/decode-insn.c @@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api) RISCV_INSN_REJECTED(c_ebreak, insn); #endif - RISCV_INSN_REJECTED(auipc, insn); - RISCV_INSN_REJECTED(branch, insn); - RISCV_INSN_SET_SIMULATE(jal, insn); RISCV_INSN_SET_SIMULATE(jalr, insn); + RISCV_INSN_SET_SIMULATE(auipc, insn); + RISCV_INSN_SET_SIMULATE(branch, insn); return INSN_GOOD; } diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c index 2519ce263..d0f3b3fde 100644 --- a/arch/riscv/kernel/probes/simulate-insn.c +++ b/arch/riscv/kernel/probes/simulate-insn.c @@ -83,3 +83,115 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg return ret; } + +#define auipc_rd_idx(opcode) \ + ((opcode >> 7) & 0x1f) + +#define auipc_imm(opcode) \ + ((((opcode) >> 12) & 0xfffff) << 12) + +#if __riscv_xlen == 64 +#define auipc_offset(opcode) sign_extend64(auipc_imm(opcode), 31) +#elif __riscv_xlen == 32 +#define auipc_offset(opcode) auipc_imm(opcode) +#else +#error "Unexpected __riscv_xlen" +#endif + +bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *regs) +{ + /* + * auipc instruction: + * 31 12 11 7 6 0 + * | imm[31:12] | rd | opcode | + * 20 5 7 + */ + + u32 rd_idx = auipc_rd_idx(opcode); + unsigned long rd_val = addr + auipc_offset(opcode); + + if (!rv_insn_reg_set_val(regs, rd_idx, rd_val)) + return false; + + instruction_pointer_set(regs, addr + 4); + + return true; +} + +#define branch_rs1_idx(opcode) \ + (((opcode) >> 15) & 0x1f) + +#define branch_rs2_idx(opcode) \ + (((opcode) >> 20) & 0x1f) + +#define branch_funct3(opcode) \ + (((opcode) >> 12) & 0x7) + +#define branch_imm(opcode) \ + (((((opcode) >> 8) & 0xf ) << 1) | \ + ((((opcode) >> 25) & 0x3f) << 5) | \ + ((((opcode) >> 7) & 0x1 ) << 11) | \ + ((((opcode) >> 31) & 0x1 ) << 12)) + +#define branch_offset(opcode) \ + sign_extend32((branch_imm(opcode)), 12) + +#define BRANCH_BEQ 0x0 +#define BRANCH_BNE 0x1 +#define BRANCH_BLT 0x4 +#define BRANCH_BGE 0x5 +#define BRANCH_BLTU 0x6 +#define BRANCH_BGEU 0x7 + +bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs) +{ + /* + * branch instructions: + * 31 30 25 24 20 19 15 14 12 11 8 7 6 0 + * | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode | + * 1 6 5 5 3 4 1 7 + * imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 BEQ + * imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 BNE + * imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 BLT + * imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 BGE + * imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 BLTU + * imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 BGEU + */ + + s32 offset; + s32 offset_tmp; + unsigned long rs1_val; + unsigned long rs2_val; + + if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) || + !rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val)) + return false; + + offset_tmp = branch_offset(opcode); + switch (branch_funct3(opcode)) { + case BRANCH_BEQ: + offset = (rs1_val == rs2_val) ? offset_tmp : 4; + break; + case BRANCH_BNE: + offset = (rs1_val != rs2_val) ? offset_tmp : 4; + break; + case BRANCH_BLT: + offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4; + break; + case BRANCH_BGE: + offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4; + break; + case BRANCH_BLTU: + offset = (rs1_val < rs2_val) ? offset_tmp : 4; + break; + case BRANCH_BGEU: + offset = (rs1_val >= rs2_val) ? offset_tmp : 4; + break; + default: + return false; + } + + instruction_pointer_set(regs, addr + offset); + + return true; +} \ No newline at end of file diff --git a/drivers/clk/thead/gate/Makefile b/drivers/clk/thead/gate/Makefile index b0ad8b201..07be9f11a 100644 --- a/drivers/clk/thead/gate/Makefile +++ b/drivers/clk/thead/gate/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_CLK_LIGHT_FM) += thead-gate.o visys-gate.o vpsys-gate.o vosys-gate.o dspsys-gate.o +obj-$(CONFIG_CLK_LIGHT_FM) += thead-gate.o visys-gate.o vpsys-gate.o vosys-gate.o dspsys-gate.o audiosys-gate.o diff --git a/drivers/clk/thead/gate/audiosys-gate.c b/drivers/clk/thead/gate/audiosys-gate.c new file mode 100644 index 000000000..55320c064 --- /dev/null +++ b/drivers/clk/thead/gate/audiosys-gate.c @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Alibaba Group Holding Limited. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clk-gate.h" +#include "../clk.h" + +static struct clk *gates[LIGHT_CLKGEN_AUDIO_CLK_END]; +static struct clk_onecell_data clk_gate_data; + +static int light_audiosys_clk_probe(struct platform_device *pdev) +{ + struct regmap *audiosys_regmap; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int ret; + + audiosys_regmap = syscon_regmap_lookup_by_phandle(np, "audiosys-regmap"); + if (IS_ERR(audiosys_regmap)) { + dev_err(&pdev->dev, "cannot find regmap for vi system register\n"); + return PTR_ERR(audiosys_regmap); + } + + printk("%s audiosys_regmap=0x%px\n", __func__, audiosys_regmap); + + /* we assume that the gate clock is a root clock */ + gates[LIGHT_CLKGEN_AUDIO_CPU] = thead_gate_clk_register("clkgen_audiosys_cpu_clk", NULL, + audiosys_regmap, 0x10, 0, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_SRAM0] = thead_gate_clk_register("clkgen_audiosys_sram0_clk", NULL, + audiosys_regmap, 0x10, 1, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_SRAM1] = thead_gate_clk_register("clkgen_audiosys_sram1_clk", NULL, + audiosys_regmap, 0x10, 2, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_DMA] = thead_gate_clk_register("clkgen_audiosys_dma_clk", NULL, + audiosys_regmap, 0x10, 3, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_BSM] = thead_gate_clk_register("clkgen_audiosys_bsm_clk", NULL, + audiosys_regmap, 0x10, 4, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_TIMER] = thead_gate_clk_register("clkgen_audiosys_timer_clk", NULL, + audiosys_regmap, 0x10, 8, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_TIMER_CNT1] = thead_gate_clk_register("clkgen_audiosys_timer_cnt1_clk", NULL, + audiosys_regmap, 0x10, 9, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_TIMER_CNT2] = thead_gate_clk_register("clkgen_audiosys_timer_cnt2_clk", NULL, + audiosys_regmap, 0x10, 10, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_TIMER_CNT3] = thead_gate_clk_register("clkgen_audiosys_timer_cnt3_clk", NULL, + audiosys_regmap, 0x10, 11, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_TIMER_CNT4] = thead_gate_clk_register("clkgen_audiosys_timer_cnt4_clk", NULL, + audiosys_regmap, 0x10, 12, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_WDR] = thead_gate_clk_register("clkgen_audiosys_wdr_clk", NULL, + audiosys_regmap, 0x10, 13, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_I2C0] = thead_gate_clk_register("clkgen_audiosys_i2c0_clk", NULL, + audiosys_regmap, 0x10, 14, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_I2C1] = thead_gate_clk_register("clkgen_audiosys_i2c1_clk", NULL, + audiosys_regmap, 0x10, 15, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_UART] = thead_gate_clk_register("clkgen_audiosys_uart_clk", NULL, + audiosys_regmap, 0x10, 16, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_I2S0] = thead_gate_clk_register("clkgen_audiosys_i2s0_clk", NULL, + audiosys_regmap, 0x10, 17, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_I2S1] = thead_gate_clk_register("clkgen_audiosys_i2s1_clk", NULL, + audiosys_regmap, 0x10, 18, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_I2S2] = thead_gate_clk_register("clkgen_audiosys_i2s2_clk", NULL, + audiosys_regmap, 0x10, 19, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_I2S8CH] = thead_gate_clk_register("clkgen_audiosys_i2s8ch_clk", NULL, + audiosys_regmap, 0x10, 20, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_TDM] = thead_gate_clk_register("clkgen_audiosys_tdm_clk", NULL, + audiosys_regmap, 0x10, 21, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_GPIO] = thead_gate_clk_register("clkgen_audiosys_gpio_clk", NULL, + audiosys_regmap, 0x10, 22, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_SPDIF0] = thead_gate_clk_register("clkgen_audiosys_spdif0_clk", NULL, + audiosys_regmap, 0x10, 23, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_SPDIF1] = thead_gate_clk_register("clkgen_audiosys_spdif1_clk", NULL, + audiosys_regmap, 0x10, 24, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_VAD] = thead_gate_clk_register("clkgen_audiosys_vad_clk", NULL, + audiosys_regmap, 0x10, 25, GATE_NOT_SHARED, NULL, dev); + gates[LIGHT_CLKGEN_AUDIO_IOMUX] = thead_gate_clk_register("clkgen_audiosys_iomux_clk", NULL, + audiosys_regmap, 0x10, 26, GATE_NOT_SHARED, NULL, dev); + + clk_gate_data.clks = gates; + clk_gate_data.clk_num = ARRAY_SIZE(gates); + + ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_gate_data); + if (ret < 0) { + dev_err(dev, "failed to register gate clks for light audiosys\n"); + goto unregister_clks; + } + + dev_info(dev, "succeed to register audiosys gate clock provider\n"); + + return 0; + +unregister_clks: + thead_unregister_clocks(gates, ARRAY_SIZE(gates)); + return ret; +} + +static const struct of_device_id audiosys_clk_gate_of_match[] = { + { .compatible = "thead,audiosys-gate-controller" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, audiosys_clk_gate_of_match); + +static struct platform_driver light_audiosys_clk_driver = { + .probe = light_audiosys_clk_probe, + .driver = { + .name = "audiosys-clk-gate-provider", + .of_match_table = of_match_ptr(audiosys_clk_gate_of_match), + }, +}; + +module_platform_driver(light_audiosys_clk_driver); +MODULE_AUTHOR("nanli.yd "); +MODULE_DESCRIPTION("Thead Light Fullmask audiosys clock gate provider"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 1db3a4f70..f0a33b33c 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o i2c-designware-core-y := i2c-designware-common.o +i2c-designware-core-y += i2c-designware-master_dma.o i2c-designware-core-y += i2c-designware-master.o i2c-designware-core-$(CONFIG_I2C_DESIGNWARE_SLAVE) += i2c-designware-slave.o obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index b85ffe0fc..604c3fd6e 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -17,6 +17,7 @@ #include #include #include +#include #define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \ I2C_FUNC_SMBUS_BYTE | \ @@ -234,6 +235,18 @@ struct reset_control; * values than the one computed based only on the input clock frequency. * Leave them to be %0 if not used. */ +struct i2c_dw_dma { + struct dma_chan *dma_chan; + struct dma_async_tx_descriptor *desc; + dma_cookie_t cookie; + dma_addr_t dma_addr; //phy addr + u32 *buf; //Store the virtual address of the data to be transferred by dma + u32 buf_size; + u32 transfer_len; //dma transfer data num + //volatile int dma_complete; + struct completion dma_complete; +}; + struct dw_i2c_dev { struct device *dev; struct regmap *map; @@ -257,6 +270,7 @@ struct dw_i2c_dev { u8 *rx_buf; int msg_err; unsigned int status; + unsigned int tx_status; u32 abort_source; int irq; u32 flags; @@ -287,6 +301,10 @@ struct dw_i2c_dev { int mode; struct i2c_bus_recovery_info rinfo; bool suspended; + struct i2c_dw_dma dma; + u32 laststat; + u32 laststatus; + int dw_i2c_enable_dma; }; #define ACCESS_INTR_MASK 0x00000001 diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 6841c89f6..dfef1925f 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -22,6 +22,7 @@ #include #include "i2c-designware-core.h" +#include "i2c-designware-master_dma.h" static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev) { @@ -257,7 +258,13 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) /* Clear and enable interrupts */ regmap_read(dev->map, DW_IC_CLR_INTR, &dummy); - regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_MASTER_MASK); + + if (dev->dw_i2c_enable_dma) { + i2c_dw_xfer_dma_init(dev); + regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_MASTER_MASK & (~DW_IC_INTR_TX_EMPTY)); + } else { + regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_MASTER_MASK); + } } /* @@ -289,9 +296,9 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) * adapter when we are done with this transfer. */ if (msgs[dev->msg_write_idx].addr != addr) { - dev_err(dev->dev, - "%s: invalid target address\n", __func__); dev->msg_err = -EINVAL; + dev_err(dev->dev, + "%s: invalid target address\n", __func__); break; } @@ -476,6 +483,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) dev->msg_read_idx = 0; dev->msg_err = 0; dev->status = STATUS_IDLE; + dev->tx_status = STATUS_IDLE; dev->abort_source = 0; dev->rx_outstanding = 0; @@ -491,6 +499,16 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) i2c_dw_xfer_init(dev); /* Wait for tx to complete */ + if (dev->dw_i2c_enable_dma) { + if(i2c_dw_dma_tx_transfer(dev, adap->timeout) != 0) { + dev_err(dev->dev, "i2c dw dma transfer error\n"); + i2c_recover_bus(&dev->adapter); + i2c_dw_init_master(dev); + ret = -ETIMEDOUT; + goto done; + } + } + if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) { dev_err(dev->dev, "controller timed out\n"); /* i2c_dw_init implicitly disables the adapter */ @@ -527,15 +545,21 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) goto done; } - if (dev->status) - dev_err(dev->dev, - "transfer terminated early - interrupt latency too high?\n"); + if (dev->status || dev->tx_status) { + dev_err(dev->dev, "transfer terminated early - interrupt latency too high? sta 0x%x\n", dev->status); + + dev_err(dev->dev, "laststa 0x%x, laststatus 0x%x\n", dev->laststat, dev->laststatus); + dev_err(dev->dev, "dev->tx_status 0x%x\n", dev->tx_status); + dev_err(dev->dev, "dev->rx_outstanding %d\n", dev->rx_outstanding); + } ret = -EIO; done: + if (dev->dw_i2c_enable_dma) { + i2c_dw_xfer_dma_deinit(dev); + } i2c_dw_release_lock(dev); - done_nolock: pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); @@ -631,8 +655,9 @@ static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev) if (stat & DW_IC_INTR_RX_FULL) i2c_dw_read(dev); - if (stat & DW_IC_INTR_TX_EMPTY) + if (stat & DW_IC_INTR_TX_EMPTY) { i2c_dw_xfer_msg(dev); + } /* * No need to modify or disable the interrupt mask here. @@ -645,9 +670,11 @@ tx_aborted: if ((stat & DW_IC_INTR_TX_ABRT) || dev->msg_err || ((status & DW_IC_STATUS_TFE) && (!(status & DW_IC_STATUS_RFNE)) && - (!(status & DW_IC_STATUS_MASTER_ACTIVITY)))) + (!(status & DW_IC_STATUS_MASTER_ACTIVITY)))) { complete(&dev->cmd_complete); - else if (unlikely(dev->flags & ACCESS_INTR_MASK)) { + dev->laststat = stat; + dev->laststatus = status; + } else if (unlikely(dev->flags & ACCESS_INTR_MASK)) { /* Workaround to trigger pending interrupt */ regmap_read(dev->map, DW_IC_INTR_MASK, &stat); i2c_dw_disable_int(dev); @@ -747,9 +774,25 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; unsigned long irq_flags; + struct device_node *np; int ret; + const char *i2c_mode; + + //default used interrupt mode + dev->dw_i2c_enable_dma = 0; + + np = dev->dev->of_node; + ret = of_property_read_string(np, "i2c_mode", &i2c_mode); + if (ret == 0) { + if (strcmp(i2c_mode, "dma") == 0) { + dev->dw_i2c_enable_dma = 1; + } + } init_completion(&dev->cmd_complete); + if (dev->dw_i2c_enable_dma) { + init_completion(&dev->dma.dma_complete); + } dev->init = i2c_dw_init_master; dev->disable = i2c_dw_disable; @@ -787,10 +830,10 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev) i2c_dw_disable_int(dev); ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags, - dev_name(dev->dev), dev); + dev_name(dev->dev), dev); if (ret) { dev_err(dev->dev, "failure requesting irq %i: %d\n", - dev->irq, ret); + dev->irq, ret); return ret; } diff --git a/drivers/i2c/busses/i2c-designware-master_dma.c b/drivers/i2c/busses/i2c-designware-master_dma.c new file mode 100644 index 000000000..8f370696d --- /dev/null +++ b/drivers/i2c/busses/i2c-designware-master_dma.c @@ -0,0 +1,318 @@ +#include +#include +#include +#include +#include +#include +#include "i2c-designware-core.h" + +#define DEBUG + +#define DW_IC_DMA_CR (0x88) +#define DW_IC_DMA_TDLR (0x8c) +#define DW_IC_DMA_RDLR (0x90) +#define DW_IC_DMA_CR_TXEN (0x2) +#define DW_IC_DMA_CR_DIS (0x0) + +//Because the fifo register bit width is 32bits, each transfer data is 4byte +#define DW_IC_DMA_DATA_BLOCK_BYTES (0x4) + +//#define __dev_vdgb dev_dbg +#define __dev_vdgb(fmt, ...) + +static int i2c_dw_hwparams_to_dma_slave_config(struct dw_i2c_dev *dev) +{ + int ret = 0; + struct dma_slave_config slave_config; + struct i2c_dw_dma *dma = &dev->dma; + struct platform_device *pdev; + struct resource *iores_mem; + phys_addr_t reg_addr; + + __dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__); + memset(&slave_config, 0, sizeof(slave_config)); + + //get i2c fifo addr + pdev = to_platform_device(dev->dev); + iores_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg_addr = iores_mem->start + DW_IC_DATA_CMD; + slave_config.direction = DMA_MEM_TO_DEV; + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.dst_addr = reg_addr; + //for light only support "false" + slave_config.device_fc = false; + + ret = dmaengine_slave_config(dma->dma_chan, &slave_config); + if (ret) { + dev_err(dev->dev, "dmaengine_slave_config failed\n"); + return ret; + } + + __dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__); + return 0; +} + +static void i2c_dw_dma_callback(void *data) +{ + struct dw_i2c_dev *dev = (struct dw_i2c_dev *)data; + struct i2c_dw_dma *dma = &dev->dma; + + dev->tx_status &= ~STATUS_WRITE_IN_PROGRESS; + complete(&dma->dma_complete); + dmaengine_terminate_async(dma->dma_chan); +} + +static int get_msg_size(struct dw_i2c_dev *dev) +{ + struct i2c_msg *msgs = dev->msgs; + u32 addr = msgs[dev->msg_write_idx].addr; + int i = 0; + int len = 0; + + __dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__); + for (i = dev->msg_write_idx; i < dev->msgs_num; i++) { + if (msgs[i].addr != addr) { + dev_err(dev->dev, "%s: invalid target address\n", __func__); + dev->msg_err = -EINVAL; + break; + } + + len += msgs[i].len; + } + + __dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__); + return len; +} + +static int alloc_dma_buf(struct dw_i2c_dev *dev, int size) +{ + struct i2c_dw_dma *dma = &dev->dma; + __dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__); + + dma->buf = dma_alloc_coherent(dev->dev, size, &dma->dma_addr, GFP_KERNEL); + if (!dma->buf) { + dev_err(dev->dev, "i2c alloc dma buf failed\n"); + return -1; + } + + dma->buf_size = size; + dma->transfer_len = 0; + __dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__); + return 0; +} + +static int i2c_dw_release_tx_packets(struct dw_i2c_dev *dev) +{ + struct i2c_dw_dma *dma = &dev->dma; + + __dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__); + + if(dma->buf && dma->dma_addr && dma->buf_size) { + dma_free_coherent(dev->dev, dma->buf_size, dma->buf, dma->dma_addr); + } + + dma->buf = 0; + dma->dma_addr = 0; + dma->buf_size = 0; + + __dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__); + return 0; +} + +static int i2c_dw_synthetic_tx_packets(struct dw_i2c_dev *dev) +{ + int ret = 0; + struct i2c_dw_dma *dma = &dev->dma; + struct i2c_msg *msgs = dev->msgs; + bool need_restart = false; + uint32_t *tx_buf; + int dma_tx_buf_size; + u32 addr = msgs[dev->msg_write_idx].addr; + + __dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__); + + dma_tx_buf_size = get_msg_size(dev) * 4; + if (dma_tx_buf_size <= 0) { + dev_err(dev->dev, "i2c get_msg_size size is error %d\n", dma_tx_buf_size); + return -1; + } + + ret = alloc_dma_buf(dev, dma_tx_buf_size); + if (ret) { + dev_err(dev->dev, "i2c alloc_dma_buf failed\n"); + return -1; + } + + tx_buf = dma->buf; + + for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { + unsigned char *buf; + int buf_len; + u32 flags = msgs[dev->msg_write_idx].flags; + + if (msgs[dev->msg_write_idx].addr != addr) { + dev_err(dev->dev, "%s: invalid target address\n", __func__); + dev->msg_err = -EINVAL; + break; + } + + /* new i2c_msg */ + buf = msgs[dev->msg_write_idx].buf; + buf_len = msgs[dev->msg_write_idx].len; + + if ((dev->master_cfg & DW_IC_CON_RESTART_EN) && + (dev->msg_write_idx > 0)) + need_restart = true; + + //dev_err(dev->dev, " msg_buf_len %d\n", buf_len); + while (buf_len > 0) { + u32 cmd = 0; + + if (dev->msg_write_idx == dev->msgs_num - 1 && + buf_len == 1 && !(flags & I2C_M_RECV_LEN)) + cmd |= BIT(9); + + if (need_restart) { + cmd |= BIT(10); + need_restart = false; + } + + if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { + *tx_buf = cmd | 0x100; + dev->rx_outstanding++; + } else { + *tx_buf = cmd | *buf++; + } + tx_buf++; + dma->transfer_len++; + buf_len--; + } + } + + dma_sync_single_for_device(dev->dev, dma->dma_addr, dma->buf_size, DMA_TO_DEVICE); + + __dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__); + return 0; +} + +int i2c_dw_xfer_dma_deinit(struct dw_i2c_dev *dev); + +int i2c_dw_dma_tx_transfer(struct dw_i2c_dev *dev, unsigned int timeout) +{ + int ret = 0; + struct i2c_dw_dma *dma = &dev->dma; + unsigned long start_jiffies = 0; + u32 stat; + + __dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__); + if (dma->dma_chan == NULL) { + goto error; + } + + ret = i2c_dw_hwparams_to_dma_slave_config(dev); + if (ret != 0) { + goto error; + } + + regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat); + if (stat & DW_IC_INTR_TX_ABRT) { + dev->cmd_err |= DW_IC_ERR_TX_ABRT; + dev->tx_status = STATUS_IDLE; + goto error; + } + + ret = i2c_dw_synthetic_tx_packets(dev); + if (ret != 0) { + dev_err(dev->dev, "%s: i2c_dw_synthetic_tx_packets failed\n", __func__); + goto error; + } + + dev->tx_status |= STATUS_WRITE_IN_PROGRESS; + dma->desc = dmaengine_prep_slave_single(dma->dma_chan, dma->dma_addr, + dma->transfer_len * DW_IC_DMA_DATA_BLOCK_BYTES, + DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (dma->desc == NULL) { + dev_err(dev->dev, "%s: dmaengine_prep_slave_single failed\n", __func__); + goto error; + } + + dma->desc->callback = i2c_dw_dma_callback; + dma->desc->callback_param = dev; + dma->cookie = dmaengine_submit(dma->desc); + dma_async_issue_pending(dma->dma_chan); + + //wait dma transfer complete + if (!wait_for_completion_timeout(&dma->dma_complete, timeout)) { + dev_err(dev->dev, "i2c dma_ch%d write timed out\n", dma->dma_chan->chan_id); + ret = dmaengine_terminate_async(dma->dma_chan); + if (ret !=0) { + dev_err(dev->dev, "i2c dma dmaengine_terminate_async failed,\ + dma_ch is %d\n", dma->dma_chan->chan_id); + } + dmaengine_synchronize(dma->dma_chan); + goto error; + } + + dmaengine_synchronize(dma->dma_chan); + + //Release the dma channel immediately after the dma transfer is completed, + //reducing the dma occupation time + //i2c_dw_xfer_dma_init(dev); + return 0; + +error: + //i2c_dw_xfer_dma_init(dev); + __dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__); + return -1; +} + +int i2c_dw_xfer_dma_init(struct dw_i2c_dev *dev) +{ + struct i2c_dw_dma *dma = &dev->dma; + __dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__); + + // i2c dma set tx data level + regmap_write(dev->map, DW_IC_DMA_TDLR, dev->tx_fifo_depth / 2); + + // i2c dma tx enable + regmap_write(dev->map, DW_IC_DMA_CR, DW_IC_DMA_CR_TXEN); + + if (dma->dma_chan == NULL) { + //Alloc i2c dma channel. + //The function is to configure the handshake number in i2c dts into the channel + dma->dma_chan = dma_request_slave_channel(dev->dev, "tx"); + if (!dma->dma_chan) { + dev_err(dev->dev, "Failed to request dma channel"); + return -EIO; + } + + __dev_vdgb(dev->dev,"i2c request dma_ch %d\n", dma->dma_chan->chan_id); + } + + __dev_vdgb(dev->dev,"i2c dma_ch %d\n", dma->dma_chan->chan_id); + reinit_completion(&dma->dma_complete); + __dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__); + return 0; +} + +int i2c_dw_xfer_dma_deinit(struct dw_i2c_dev *dev) +{ + struct i2c_dw_dma *dma = &dev->dma; + + __dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__); + + i2c_dw_release_tx_packets(dev); + if (dma->dma_chan != NULL) { + dma_release_channel(dma->dma_chan); + } + dma->dma_chan = NULL; + + // i2c dma disable + regmap_write(dev->map, DW_IC_DMA_CR, DW_IC_DMA_CR_DIS); + __dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__); + + return 0; +} + diff --git a/drivers/i2c/busses/i2c-designware-master_dma.h b/drivers/i2c/busses/i2c-designware-master_dma.h new file mode 100644 index 000000000..e25cc243c --- /dev/null +++ b/drivers/i2c/busses/i2c-designware-master_dma.h @@ -0,0 +1,6 @@ +//#include "i2c-designware-core.h" + +int i2c_dw_dma_tx_transfer(struct dw_i2c_dev *dev, unsigned int timeout); +int i2c_dw_xfer_dma_init(struct dw_i2c_dev *dev); +int i2c_dw_xfer_dma_deinit(struct dw_i2c_dev *dev); + diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 978c74cae..797c489a4 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -56,7 +56,7 @@ obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o obj-$(CONFIG_THEAD_LIGHT_MBOX) += light-mailbox.o -obj-$(CONFIG_THEAD_LIGHT_MBOX) += light-mailbox-client.o +#obj-$(CONFIG_THEAD_LIGHT_MBOX) += light-mailbox-client.o obj-$(CONFIG_VIRTIO_MAILBOX) += virtio-mailbox.o obj-$(CONFIG_VIRTIO_MAILBOX_TEST) += virtio-mailbox-test.o diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 5b5ebf346..79f404363 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -33,11 +33,15 @@ struct dwcmshc_priv { bool io_fixed_1v8; bool wprtn_ignore; long reset_cnt; + uint32_t delay_line[MMC_TIMING_MMC_HS400+1]; + uint32_t clk_delay_set; + bool rxclk_sw_tune_en; + uint32_t rxclk_delay_set; }; #define HS400_DELAY_LINE 24 -static uint32_t delay_line = 50; +//static uint32_t delay_line = 50; static void sdhci_phy_1_8v_init_no_pull(struct sdhci_host *host) { @@ -113,12 +117,13 @@ static void snps_phy_1_8v_init(struct sdhci_host *host) //disable delay lane sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R); //set delay lane - sdhci_writeb(host, delay_line, PHY_SDCLKDL_DC_R); + sdhci_writeb(host, priv->clk_delay_set, PHY_SDCLKDL_DC_R); sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R); //enable delay lane val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R); val &= ~(1 << UPDATE_DC); sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R); + pr_debug("%s: snps_phy_1_8v_init clk delay %d\n",host->hw_name,priv->clk_delay_set); val = (1 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N); sdhci_writew(host, val, PHY_CMDPAD_CNFG_R); @@ -155,12 +160,13 @@ static void snps_phy_3_3v_init(struct sdhci_host *host) //disable delay lane sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R); //set delay lane - sdhci_writeb(host, delay_line, PHY_SDCLKDL_DC_R); + sdhci_writeb(host, priv->clk_delay_set, PHY_SDCLKDL_DC_R); sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R); //enable delay lane val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R); val &= ~(1 << UPDATE_DC); sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R); + pr_debug("%s: snps_phy_3_3v_init clk delay %d\n",host->hw_name,priv->clk_delay_set); val = (2 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N); sdhci_writew(host, val, PHY_CMDPAD_CNFG_R); @@ -254,6 +260,61 @@ static int snps_execute_tuning(struct sdhci_host *host, u32 opcode) return 0; } +static int snps_rxclk_sw_tuned_sample_delay_set(struct sdhci_host *host, u32 sample_delay,u32 timeout) +{ + struct sdhci_pltfm_host *pltfm_host; + struct dwcmshc_priv *priv; + u32 reg_val; + u32 tune_clk_set; + u16 ctrl_2; + u32 i=0; + pltfm_host = sdhci_priv(host); + priv = sdhci_pltfm_priv(pltfm_host); + /*0x320:SMPLDL_CNFG + 0x540:AT_CTRL + 0x544:AT_STAT */ + reg_val = sdhci_readb(host, PHY_SMPLDL_CNFG_R); + if(sample_delay >= 0x80){ + /*if larger than 128,DelayLine works with extended delay range setting*/ + reg_val |= (1 << SMPLDL_CNFG_EXTDLY_EN); + }else{ + reg_val &= ~(1 << SMPLDL_CNFG_EXTDLY_EN); + } + sdhci_writeb(host, reg_val, PHY_SMPLDL_CNFG_R); + + reg_val = sdhci_readl(host, AT_CTRL_R); + reg_val |= (1 << TUNE_CLK_STOP_EN); + reg_val |= (1 << SW_TUNE_EN); + sdhci_writel(host, reg_val, AT_CTRL_R); + + if(sample_delay >= 0x80){ + tune_clk_set = (sample_delay - 0x80) & 0xff; + } + else { + tune_clk_set = sample_delay ; + } + reg_val = sdhci_readl(host, AT_STAT_R); + reg_val &= ~(0xff<hw_name,timeout); + return -1; +} + +void snps_rxclk_sw_tuned_sample_delay_dump(struct sdhci_host *host) +{ + pr_info("PHY_SMPLDL_CNFG_R = %x\n",sdhci_readb(host, PHY_SMPLDL_CNFG_R)); + pr_info("AT_CTRL_R = %x\n", sdhci_readl(host, AT_CTRL_R)); + pr_info("AT_STAT_R = %x\n", sdhci_readl(host, AT_STAT_R)); + pr_info("SDHCI_HOST_CONTROL2 = %x\n",sdhci_readw(host, SDHCI_HOST_CONTROL2)); +} static void snps_sdhci_set_phy(struct sdhci_host *host) { @@ -383,7 +444,7 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, ctrl_2 |= SDHCI_CTRL_VDD_180; sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); - + pr_debug("%s: %s timing %d\n",host->hw_name,__func__,timing); if (timing == MMC_TIMING_MMC_HS400) { // //disable delay lane // sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R); @@ -399,10 +460,18 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, reg &= ~1; sdhci_writel(host, reg, AT_CTRL_R); - delay_line = HS400_DELAY_LINE; + priv->clk_delay_set = priv->delay_line[MMC_TIMING_MMC_HS400]; + snps_sdhci_set_phy(host); /* update tx delay*/ + } else if(timing == MMC_TIMING_UHS_SDR104){ + priv->clk_delay_set = priv->delay_line[MMC_TIMING_UHS_SDR104]; snps_sdhci_set_phy(host); /* update tx delay*/ - } else { sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R); + }else { + sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R); + if(priv->rxclk_sw_tune_en && (timing == MMC_TIMING_SD_HS)){ + snps_rxclk_sw_tuned_sample_delay_set(host,priv->rxclk_delay_set,10000); + //snps_rxclk_sw_tuned_sample_delay_dump(host); + } } } @@ -464,7 +533,8 @@ static void dwcmshc_set_power_noreg(struct sdhci_host *host, unsigned char mode, unsigned short vdd) { u8 pwr = 0; - + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); if (mode != MMC_POWER_OFF) { switch (1 << vdd) { case MMC_VDD_165_195: @@ -502,6 +572,8 @@ static void dwcmshc_set_power_noreg(struct sdhci_host *host, unsigned char mode, return; host->pwr = pwr; + pr_debug("%s: %s set pwr %d\n",host->hw_name,__func__,pwr); + priv->clk_delay_set = priv->delay_line[0]; snps_sdhci_set_phy(host); if (pwr == 0) { @@ -572,6 +644,20 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, }; +static int device_property_get_clk_delay(struct device *dev, + const char *propname, u32 *val) +{ + int ret = device_property_read_u32(dev, propname, val); + if(ret < 0){ + return ret; + } + if(*val > 0xff){ + pr_info("Note: invalid clk delay property :%s, val: %u\n",propname,*val); + return -1; + } + return ret; +} + static int dwcmshc_probe(struct platform_device *pdev) { struct sdhci_pltfm_host *pltfm_host; @@ -599,8 +685,29 @@ static int dwcmshc_probe(struct platform_device *pdev) if (device_property_present(&pdev->dev, "is_emmc")) { priv->is_emmc_card = 1; + + if(device_property_get_clk_delay(&pdev->dev, "clk-delay-default", &(priv->delay_line[0]) ) < 0 ) + priv->delay_line[0] = 50; + if(device_property_get_clk_delay(&pdev->dev, "clk-delay-mmc-hs400", &(priv->delay_line[MMC_TIMING_MMC_HS400]) ) < 0 ) + priv->delay_line[MMC_TIMING_MMC_HS400] = HS400_DELAY_LINE; } else { priv->is_emmc_card = 0; + + if(device_property_get_clk_delay(&pdev->dev, "clk-delay-default", &(priv->delay_line[0]) ) < 0 ) + priv->delay_line[0] = 0x7d; + if(device_property_get_clk_delay(&pdev->dev, "clk-delay-uhs-sdr104", &(priv->delay_line[MMC_TIMING_UHS_SDR104]) ) < 0 ) + priv->delay_line[MMC_TIMING_UHS_SDR104] = 0x32; + + + if(device_property_get_clk_delay(&pdev->dev, "rxclk-sample-delay", &(priv->rxclk_delay_set) ) == 0 ){ + priv->rxclk_sw_tune_en = 1; + dev_info(&pdev->dev,"rxclk-sample-delay get val = 0x%x\n",priv->rxclk_delay_set); + + } + else { + priv->rxclk_sw_tune_en = 0; + priv->rxclk_delay_set = 0; + } } if (device_property_present(&pdev->dev, "pull_up")) { diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.h b/drivers/mmc/host/sdhci-of-dwcmshc.h index 6a68ae8e7..315034af5 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.h +++ b/drivers/mmc/host/sdhci-of-dwcmshc.h @@ -36,6 +36,8 @@ #define PHY_SDCLKDL_DC_R (DWC_MSHC_PTR_PHY_R + 0x1e) #define PHY_SMPLDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x20) +#define SMPLDL_CNFG_EXTDLY_EN 0x0 //1bit + #define PHY_ATDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x21) #define INPSEL_CNFG 2 //2bit @@ -72,4 +74,6 @@ #define POST_CHANGE_DLY 0x13 //2bit #define SWIN_TH_VAL 0x18 //9bit +#define AT_STAT_R (P_VENDOR_SPECIFIC_AREA + 0x44) // 32bit +#define AT_STAT_CENTER_PH_CODE 0x0 //0-7bit #endif /* _SDHCI_OF_DWCMSHC_H_*/ diff --git a/drivers/reset/reset-light.c b/drivers/reset/reset-light.c index 8deafacb8..3a554e49f 100644 --- a/drivers/reset/reset-light.c +++ b/drivers/reset/reset-light.c @@ -34,6 +34,11 @@ struct light_src { enum light_src_registers { SRC_WDT0 = 0x0034, SRC_WDT1 = 0x0038, + SRC_NPU = 0x01b0, +}; + +enum light_vpsys_src_registers { + SRC_FCE = 0x0004, }; static int light_reset_update(struct light_src *lightsrc, @@ -48,6 +53,11 @@ static int light_reset_update(struct light_src *lightsrc, static const struct light_src_signal light_src_signals[] = { [LIGHT_RESET_WDT0] = { SRC_WDT0, BIT(0) }, [LIGHT_RESET_WDT1] = { SRC_WDT1, BIT(0) }, + [LIGHT_RESET_NPU] = { SRC_NPU, BIT(0) }, +}; + +static const struct light_src_signal light_vpsys_src_signals[] = { + [LIGHT_RESET_FCE] = { SRC_FCE, BIT(0)|BIT(1)|BIT(4)|BIT(5) }, }; static struct light_src *to_light_src(struct reset_controller_dev *rcdev) @@ -94,6 +104,15 @@ static const struct light_src_variant variant_light = { }, }; +static const struct light_src_variant variant_light_vpsys = { + .signals = light_vpsys_src_signals, + .signals_num = ARRAY_SIZE(light_vpsys_src_signals), + .ops = { + .assert = light_reset_assert, + .deassert = light_reset_deassert, + }, +}; + static int light_reset_probe(struct platform_device *pdev) { struct light_src *lightsrc; @@ -123,6 +142,7 @@ static int light_reset_probe(struct platform_device *pdev) static const struct of_device_id light_reset_dt_ids[] = { { .compatible = "thead,light-reset-src", .data = &variant_light }, + { .compatible = "thead,light-vpsys-reset-src", .data = &variant_light_vpsys }, }; MODULE_DEVICE_TABLE(of, light_reset_dt_ids); diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index f96716893..1926f8990 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -58,6 +58,10 @@ config RPMSG_QCOM_SMD providing communication channels to remote processors in Qualcomm platforms. +config RPMSG_THEAD_LIGHT + tristate "THEAD Light RPM Driver" + depends on RPMSG + config RPMSG_VIRTIO tristate "Virtio RPMSG bus driver" depends on HAS_DMA diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile index ffe932ef6..c63184873 100644 --- a/drivers/rpmsg/Makefile +++ b/drivers/rpmsg/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o +obj-$(CONFIG_RPMSG_THEAD_LIGHT) += light_rpmsg.o diff --git a/drivers/rpmsg/light_rpmsg.c b/drivers/rpmsg/light_rpmsg.c new file mode 100644 index 000000000..493ea8c09 --- /dev/null +++ b/drivers/rpmsg/light_rpmsg.c @@ -0,0 +1,763 @@ +/* + * Copyright (C) 2023 Alibaba Group Holding Limited. + * + * derived from the omap-rpmsg implementation. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MBOX_MAX_MSG_LEN 28 +#define WJ_MBOX_SEND_MAX_MESSAGE_LENGTH 28 +#define HEXDUMP_BYTES_PER_LINE 28 +#define HEXDUMP_LINE_LEN ((HEXDUMP_BYTES_PER_LINE * 4) + 2) +#define HEXDUMP_MAX_LEN (HEXDUMP_LINE_LEN * \ + (MBOX_MAX_MSG_LEN / HEXDUMP_BYTES_PER_LINE)) + +//extern struct light_rpmsg_vproc *pri_rpdev; +static struct dentry *root_debugfs_dir; + +struct mbox_client_light_device { + struct device *dev; + void __iomem *tx_mmio; + void __iomem *rx_mmio; + struct mbox_chan *tx_channel; + struct mbox_chan *rx_channel; + char *rx_buffer; + struct regmap *audio_mbox_regmap; + char *message; + spinlock_t lock; +}; + +struct mbox_client_light_device *tdev_priv; + +static volatile uint32_t *p_mbox_reg; +static volatile uint32_t *p_mbox_reg1; +static volatile uint32_t *p_mbox_reg2; + +/* + * For now, allocate 256 buffers of 512 bytes for each side. each buffer + * will then have 16B for the msg header and 496B for the payload. + * This will require a total space of 256KB for the buffers themselves, and + * 3 pages for every vring (the size of the vring depends on the number of + * buffers it supports). + */ +#define RPMSG_NUM_BUFS (512) +//#define RPMSG_BUF_SIZE (512) +//#define RPMSG_BUFS_SPACE (RPMSG_NUM_BUFS * RPMSG_BUF_SIZE) + +/* + * The alignment between the consumer and producer parts of the vring. + * Note: this is part of the "wire" protocol. If you change this, you need + * to update your BIOS image as well + */ +#define RPMSG_VRING_ALIGN (4096) + +/* With 256 buffers, our vring will occupy 3 pages */ +#define RPMSG_RING_SIZE ((DIV_ROUND_UP(vring_size(RPMSG_NUM_BUFS / 2, \ + RPMSG_VRING_ALIGN), PAGE_SIZE)) * PAGE_SIZE) + +#define to_light_virdev(vd) container_of(vd, struct light_virdev, vdev) +#define to_light_rpdev(vd, id) container_of(vd, struct light_rpmsg_vproc, ivdev[id]) + +struct light_rpmsg_vq_info { + __u16 num; /* number of entries in the virtio_ring */ + __u16 vq_id; /* a globaly unique index of this virtqueue */ + void *addr; /* address where we mapped the virtio ring */ + struct light_rpmsg_vproc *rpdev; +}; + +static u64 light_rpmsg_get_features(struct virtio_device *vdev) +{ + /* VIRTIO_RPMSG_F_NS has been made private */ + return 1 << 0; +} + +static int light_rpmsg_finalize_features(struct virtio_device *vdev) +{ + /* Give virtio_ring a chance to accept features */ + vring_transport_features(vdev); + return 0; +} + +/* kick the remote processor, and let it know which virtqueue to poke at */ +static bool light_rpmsg_notify(struct virtqueue *vq) +{ + unsigned int mu_rpmsg = 0; + int ret; + struct light_rpmsg_vq_info *rpvq = vq->priv; + + mu_rpmsg = rpvq->vq_id << 16; + mutex_lock(&rpvq->rpdev->lock); + + //pr_info("light rpmsg: notify %d\n", rpvq->rpdev->first_notify); + if (unlikely(rpvq->rpdev->first_notify > 0)) { + rpvq->rpdev->first_notify--; + if (!tdev_priv->tx_channel) { + dev_err(tdev_priv->dev, "Channel cannot do Tx+++\n"); + return -EINVAL; + } + + ret = mbox_send_message(tdev_priv->tx_channel, "Hello, Queue!"); + } else { + *p_mbox_reg1 |= 1 << 0; + *p_mbox_reg2 |= 1 << 0; + } + mutex_unlock(&rpvq->rpdev->lock); + + return true; +} + +static int light_mu_rpmsg_callback(struct notifier_block *this, + unsigned long index, void *data) +{ + u32 mu_msg = (phys_addr_t) data; + struct light_virdev *virdev; + + virdev = container_of(this, struct light_virdev, nb); + + pr_debug("light rpmsg: %s notifier_call mu_msg: 0x%x\n", __func__, mu_msg); + /* ignore vq indices which are clearly not for us */ + mu_msg = mu_msg >> 16; + if (mu_msg < virdev->base_vq_id || mu_msg > virdev->base_vq_id + 1) { + pr_debug("light rpmsg: mu_msg 0x%x is invalid\n", mu_msg); + //return NOTIFY_DONE; + } + + mu_msg -= virdev->base_vq_id; + pr_debug("%smu_msg 0x%xbase_vq_id 0x%xvirdev num_of_vqs0x%x\n", __func__, mu_msg, virdev->base_vq_id, virdev->num_of_vqs); + + /* + * Currently both PENDING_MSG and explicit-virtqueue-index + * messaging are supported. + * Whatever approach is taken, at this point 'mu_msg' contains + * the index of the vring which was just triggered. + */ + //if (mu_msg < virdev->num_of_vqs) + vring_interrupt(mu_msg, virdev->vq[mu_msg]); + + return NOTIFY_DONE; +} + +static int light_mu_rpmsg_register_nb(struct light_rpmsg_vproc *rpdev, + struct notifier_block *nb) +{ + if ((rpdev == NULL) || (nb == NULL)) + return -EINVAL; + + blocking_notifier_chain_register(&(rpdev->notifier), nb); + + return 0; +} + +static int light_mu_rpmsg_unregister_nb(struct light_rpmsg_vproc *rpdev, + struct notifier_block *nb) +{ + if ((rpdev == NULL) || (nb == NULL)) + return -EINVAL; + + blocking_notifier_chain_unregister(&(rpdev->notifier), nb); + + return 0; +} + +static struct virtqueue *rp_find_vq(struct virtio_device *vdev, + unsigned int index, + void (*callback)(struct virtqueue *vq), + const char *name, + bool ctx) +{ + struct light_virdev *virdev = to_light_virdev(vdev); + struct light_rpmsg_vproc *rpdev = to_light_rpdev(virdev, + virdev->base_vq_id / 2); + struct light_rpmsg_vq_info *rpvq; + struct virtqueue *vq; + int err; + //static void __iomem *brd_io; + + rpvq = kmalloc(sizeof(*rpvq), GFP_KERNEL); + if (!rpvq) + return ERR_PTR(-ENOMEM); + + /* ioremap'ing normal memory, so we cast away sparse's complaints */ + //rpvq->addr = (__force void *) ioremap_nocache(virdev->vring[index], + // RPMSG_RING_SIZE); + rpvq->addr = (__force void *) ioremap(virdev->vring[index], + RPMSG_RING_SIZE); + if (!rpvq->addr) { + err = -ENOMEM; + goto free_rpvq; + } + + p_mbox_reg = ioremap(0xffefc48000,25); + p_mbox_reg1 = p_mbox_reg + 4; + p_mbox_reg2 = p_mbox_reg + 5; + + memset_io(rpvq->addr, 0, RPMSG_RING_SIZE); + + pr_debug("vring%d: phys 0x%x, virt 0x%p\n", index, virdev->vring[index], + rpvq->addr); + + vq = vring_new_virtqueue(index, RPMSG_NUM_BUFS / 2, RPMSG_VRING_ALIGN, + vdev, true, ctx, + rpvq->addr, + light_rpmsg_notify, callback, + name); + if (!vq) { + pr_err("light rpmsg: vring_new_virtqueue failed\n"); + err = -ENOMEM; + goto unmap_vring; + } + + virdev->vq[index] = vq; + vq->priv = rpvq; + /* system-wide unique id for this virtqueue */ + rpvq->vq_id = virdev->base_vq_id + index; + rpvq->rpdev = rpdev; + mutex_init(&rpdev->lock); + + return vq; + +unmap_vring: + /* iounmap normal memory, so make sparse happy */ + iounmap((__force void __iomem *) rpvq->addr); +free_rpvq: + kfree(rpvq); + return ERR_PTR(err); +} + +static void light_rpmsg_del_vqs(struct virtio_device *vdev) +{ + struct virtqueue *vq, *n; + struct light_virdev *virdev = to_light_virdev(vdev); + struct light_rpmsg_vproc *rpdev = to_light_rpdev(virdev, + virdev->base_vq_id / 2); + + list_for_each_entry_safe(vq, n, &vdev->vqs, list) { + struct light_rpmsg_vq_info *rpvq = vq->priv; + + iounmap(rpvq->addr); + vring_del_virtqueue(vq); + kfree(rpvq); + } + + if (&virdev->nb) + light_mu_rpmsg_unregister_nb(rpdev, &virdev->nb); +} + +static int light_rpmsg_find_vqs(struct virtio_device *vdev, unsigned int nvqs, + struct virtqueue *vqs[], + vq_callback_t *callbacks[], + const char * const names[], + const bool *ctx, + struct irq_affinity *desc) +{ + struct light_virdev *virdev = to_light_virdev(vdev); + struct light_rpmsg_vproc *rpdev = to_light_rpdev(virdev, + virdev->base_vq_id / 2); + int i, err; + + /* we maintain two virtqueues per remote processor (for RX and TX) */ + if (nvqs != 2) + return -EINVAL; + + for (i = 0; i < nvqs; ++i) { + vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i], + ctx ? ctx[i] : false); + if (IS_ERR(vqs[i])) { + err = PTR_ERR(vqs[i]); + goto error; + } + } + + virdev->num_of_vqs = nvqs; + + virdev->nb.notifier_call = light_mu_rpmsg_callback; + light_mu_rpmsg_register_nb(rpdev, &virdev->nb); + + return 0; + +error: + light_rpmsg_del_vqs(vdev); + return err; +} + +static void light_rpmsg_reset(struct virtio_device *vdev) +{ + dev_dbg(&vdev->dev, "reset!\n"); +} + +static u8 light_rpmsg_get_status(struct virtio_device *vdev) +{ + return 0; +} + +static void light_rpmsg_set_status(struct virtio_device *vdev, u8 status) +{ + dev_dbg(&vdev->dev, "%s new status: %d\n", __func__, status); +} + +static void light_rpmsg_vproc_release(struct device *dev) +{ + /* this handler is provided so driver core doesn't yell at us */ +} + +static struct virtio_config_ops light_rpmsg_config_ops = { + .get_features = light_rpmsg_get_features, + .finalize_features = light_rpmsg_finalize_features, + .find_vqs = light_rpmsg_find_vqs, + .del_vqs = light_rpmsg_del_vqs, + .reset = light_rpmsg_reset, + .set_status = light_rpmsg_set_status, + .get_status = light_rpmsg_get_status, +}; + +static struct light_rpmsg_vproc light_rpmsg_vprocs[] = { + { + .rproc_name = "m4", + }, + { + .rproc_name = "m4", + }, +}; + +static const struct of_device_id light_rpmsg_dt_ids[] = { + { .compatible = "light,light-rpmsg", .data = (void *)LIGHT_RPMSG, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, light_rpmsg_dt_ids); + +static int set_vring_phy_buf(struct platform_device *pdev, + struct light_rpmsg_vproc *rpdev, int vdev_nums) +{ + struct resource *res; + resource_size_t size; + unsigned int start, end; + int i, ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + size = resource_size(res); + start = res->start; + end = res->start + size; + for (i = 0; i < vdev_nums; i++) { + rpdev->ivdev[i].vring[0] = start; + rpdev->ivdev[i].vring[1] = start + + 0x8000; + start += 0x10000; + if (start > end) { + pr_err("Too small memory size %x!\n", + (u32)size); + ret = -EINVAL; + break; + } + } + } else { + return -ENOMEM; + } + + return ret; +} + +static void rpmsg_work_handler(struct work_struct *work) +{ + u32 message = 0; + struct delayed_work *dwork = to_delayed_work(work); + struct light_rpmsg_vproc *rpdev = container_of(dwork, + struct light_rpmsg_vproc, rpmsg_work); + + //spin_lock_irqsave(&rpdev->mu_lock, flags); + blocking_notifier_call_chain(&(rpdev->notifier), 4, + (void *)(phys_addr_t)message); + //spin_unlock_irqrestore(&rpdev->mu_lock, flags); +} + +struct light_rpmsg_vproc *pri_rpdev; +EXPORT_SYMBOL_GPL(pri_rpdev); + +static int light_rpmsg_probe(struct platform_device *pdev) +{ + int core_id, j, ret = 0; + struct device *dev = &pdev->dev; + struct device_node *np = pdev->dev.of_node; + struct light_rpmsg_vproc *rpdev; + + if (of_property_read_u32(np, "multi-core-id", &core_id)) + core_id = 0; + rpdev = &light_rpmsg_vprocs[core_id]; + rpdev->core_id = core_id; + rpdev->variant = (enum light_rpmsg_variants)of_device_get_match_data(dev); + + spin_lock_init(&rpdev->mu_lock); + + pri_rpdev = rpdev; + + INIT_DELAYED_WORK(&(rpdev->rpmsg_work), rpmsg_work_handler); + BLOCKING_INIT_NOTIFIER_HEAD(&(rpdev->notifier)); + + pr_info("light rpmsg: Ready for cross core communication!\n"); + + ret = of_property_read_u32(np, "vdev-nums", &rpdev->vdev_nums); + if (ret) { + rpdev->vdev_nums = 1; + } + + if (rpdev->vdev_nums > MAX_VDEV_NUMS) { + pr_err("light rpmsg: vdev-nums exceed the max %d\n", MAX_VDEV_NUMS); + return -EINVAL; + } + + rpdev->first_notify = rpdev->vdev_nums; + + pr_info("light rpmsg: rproc_name = %s",rpdev->rproc_name); + if (!strcmp(rpdev->rproc_name, "m4")) { + ret = set_vring_phy_buf(pdev, rpdev, + rpdev->vdev_nums); + if (ret) { + pr_err("light rpmsg: No vring buffer.\n"); + return -ENOMEM; + } + } else { + pr_err("light rpmsg: No remote processor.\n"); + return -ENODEV; + } + + for (j = 0; j < rpdev->vdev_nums; j++) { + pr_debug("%s rpdev%d vdev%d: vring0 0x%x, vring1 0x%x\n", + __func__, rpdev->core_id, rpdev->vdev_nums, + rpdev->ivdev[j].vring[0], + rpdev->ivdev[j].vring[1]); + rpdev->ivdev[j].vdev.id.device = VIRTIO_ID_RPMSG; + rpdev->ivdev[j].vdev.config = &light_rpmsg_config_ops; + rpdev->ivdev[j].vdev.dev.parent = &pdev->dev; + rpdev->ivdev[j].vdev.dev.release = light_rpmsg_vproc_release; + rpdev->ivdev[j].base_vq_id = j * 2; + + ret = register_virtio_device(&rpdev->ivdev[j].vdev); + if (ret) { + pr_err("light rpmsg: %s failed to register rpdev: %d\n", __func__, ret); + return ret; + } + + } + platform_set_drvdata(pdev, rpdev); + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int light_rpmsg_suspend(struct device *dev) +{ + struct light_rpmsg_vproc *rpdev = dev_get_drvdata(dev); + + clk_disable_unprepare(rpdev->mu_clk); + + return 0; +} + +static int light_rpmsg_resume(struct device *dev) +{ + struct light_rpmsg_vproc *rpdev = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(rpdev->mu_clk); + if (ret) { + pr_err("unable to enable mu clock\n"); + return ret; + } + + return ret; +} +#endif + +static SIMPLE_DEV_PM_OPS(light_rpmsg_pm_ops, light_rpmsg_suspend, light_rpmsg_resume); + +static struct platform_driver light_rpmsg_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "light-rpmsg", + .of_match_table = light_rpmsg_dt_ids, + .pm = &light_rpmsg_pm_ops, + }, + .probe = light_rpmsg_probe, +}; + +static int __init light_rpmsg_init(void) +{ + int ret; + + ret = platform_driver_register(&light_rpmsg_driver); + if (ret) + pr_err("light rpmsg: Unable to initialize\n"); + else + pr_info("light rpmsg: driver is registered.\n"); + + return ret; +} + +MODULE_AUTHOR(",Inc."); +MODULE_DESCRIPTION("remote processor messaging virtio device"); +MODULE_LICENSE("GPL v2"); +late_initcall(light_rpmsg_init); + +static ssize_t mbox_client_light_message_write(struct file *filp, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct mbox_client_light_device *tdev = filp->private_data; + void *data; + int ret; + + if (!tdev->tx_channel) { + dev_err(tdev->dev, "Channel cannot do Tx\n"); + return -EINVAL; + } + + if (count > WJ_MBOX_SEND_MAX_MESSAGE_LENGTH) + count = WJ_MBOX_SEND_MAX_MESSAGE_LENGTH; + + tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL); + if (!tdev->message) + return -ENOMEM; + + ret = copy_from_user(tdev->message, userbuf, count); + if (ret) { + ret = -EFAULT; + goto out; + } + + data = tdev->message; + print_hex_dump(KERN_INFO, __func__, DUMP_PREFIX_NONE, 16, 1, tdev->message, MBOX_MAX_MSG_LEN, true); + + ret = mbox_send_message(tdev->tx_channel, data); + if (ret < 0) + dev_err(tdev->dev, "Failed to send message via mailbox\n"); + +out: + kfree(tdev->message); + return ret < 0 ? ret : count; +} + +static ssize_t mbox_client_light_message_read(struct file *filp, + char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct mbox_client_light_device *tdev = filp->private_data; + unsigned long flags; + + print_hex_dump(KERN_INFO, __func__, DUMP_PREFIX_NONE, 16, 1, tdev->rx_buffer, MBOX_MAX_MSG_LEN, true); + spin_lock_irqsave(&tdev->lock, flags); + memset(tdev->rx_buffer, 0, MBOX_MAX_MSG_LEN); + spin_unlock_irqrestore(&tdev->lock, flags); + + return MBOX_MAX_MSG_LEN; +} + +static const struct file_operations mbox_client_light_message_ops = { + .write = mbox_client_light_message_write, + .read = mbox_client_light_message_read, + .open = simple_open, + .llseek = generic_file_llseek, +}; + +static int index_names = 0; +static bool debugfs_dir_created = false; +static const char* file_names[] = {"mbox-client0", "mbox-client1"}; + +static int mbox_client_light_add_debugfs(struct platform_device *pdev, + struct mbox_client_light_device *tdev) +{ + if (!debugfs_initialized()) + return 0; + + if (index_names > 2) { + dev_err(&pdev->dev, "Max device index is 2\n"); + return 0; + } + + if (!debugfs_dir_created) { + root_debugfs_dir = debugfs_create_dir("mailbox",NULL); + if (!root_debugfs_dir) { + dev_err(&pdev->dev, + "Failed to create mailbox debugfs\n"); + return -EINVAL; + } + debugfs_dir_created = true; + } + + debugfs_create_file(file_names[index_names], 0600, root_debugfs_dir, + tdev, &mbox_client_light_message_ops); + + index_names++; + return 0; +} + +static void mbox_client_light_receive_message(struct mbox_client *client, + void *message) +{ + struct mbox_client_light_device *tdev = dev_get_drvdata(client->dev); + char *data = message; + + spin_lock(&tdev->lock); + memcpy(tdev->rx_buffer, data, MBOX_MAX_MSG_LEN); + spin_unlock(&tdev->lock); + + //printk("mbox_client receive rpmsg_work\n"); + schedule_delayed_work(&(pri_rpdev->rpmsg_work), 0); + + //print_hex_dump(KERN_INFO, __func__, DUMP_PREFIX_NONE, 16, 1, tdev->rx_buffer, MBOX_MAX_MSG_LEN, true); +} + +static struct mbox_chan * +mbox_client_light_request_channel(struct platform_device *pdev, + const char *name) +{ + struct mbox_client *client; + struct mbox_chan *channel; + + client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL); + if (!client) + return ERR_PTR(-ENOMEM); + + client->dev = &pdev->dev; + client->tx_block = true; + client->knows_txdone = false; + client->tx_tout = 500; + client->rx_callback = mbox_client_light_receive_message; + + channel = mbox_request_channel_byname(client, name); + if (IS_ERR(channel)) { + devm_kfree(&pdev->dev, client); + dev_warn(&pdev->dev, "Failed to request %s channel\n", name); + return NULL; + } + + return channel; +} + +static int mbox_client_light_probe(struct platform_device *pdev) +{ + struct mbox_client_light_device *tdev; + struct device_node *np = pdev->dev.of_node; + int ret; + + static int chan_idx = 1; + + tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL); + if (!tdev) + return -ENOMEM; + + tdev_priv = tdev; + + if (!chan_idx) + tdev->tx_channel = mbox_client_light_request_channel(pdev, "902"); + else + tdev->tx_channel = mbox_client_light_request_channel(pdev, "906"); + + if (!tdev->tx_channel) { + dev_err(&pdev->dev, "Request channel failed\n"); + return -EPROBE_DEFER; + } + chan_idx++; + + /* In fact, rx_channel is same with tx_channel in C-SKY's mailbox */ + tdev->rx_channel = tdev->tx_channel; + + tdev->dev = &pdev->dev; + platform_set_drvdata(pdev, tdev); + + tdev->audio_mbox_regmap = syscon_regmap_lookup_by_phandle(np, "audio-mbox-regmap"); + if (IS_ERR(tdev->audio_mbox_regmap)) { + dev_err(&pdev->dev, "cannot find regmap for audio mbox register\n"); + } else { + dev_dbg(&pdev->dev, "audio_mbox_regmap ok\n"); + } + + spin_lock_init(&tdev->lock); + + tdev->rx_buffer = devm_kzalloc(&pdev->dev, + MBOX_MAX_MSG_LEN, GFP_KERNEL); + if (!tdev->rx_buffer) + return -ENOMEM; + + ret = mbox_client_light_add_debugfs(pdev, tdev); + if (ret) + return ret; + + dev_err(&pdev->dev, "Successfully registered\n"); + + return 0; +} + +static int mbox_client_light_remove(struct platform_device *pdev) +{ + struct mbox_client_light_device *tdev = platform_get_drvdata(pdev); + + debugfs_remove_recursive(root_debugfs_dir); + + if (tdev->tx_channel) + mbox_free_channel(tdev->tx_channel); + + if (tdev->rx_channel && tdev->rx_channel != tdev->tx_channel) + mbox_free_channel(tdev->rx_channel); + + return 0; +} + +static const struct of_device_id mbox_client_light_match[] = { + { .compatible = "thead,light-mbox-client" }, + {}, +}; + +static struct platform_driver mbox_client_light_driver = { + .driver = { + .name = "thead,light-mbox-client", + .of_match_table = mbox_client_light_match, + }, + .probe = mbox_client_light_probe, + .remove = mbox_client_light_remove, +}; +module_platform_driver(mbox_client_light_driver); + +MODULE_AUTHOR("Alibaba Group Holding Limited"); +MODULE_DESCRIPTION("Thead Light mailbox IPC client driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index be90d77c5..aba443817 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -521,7 +521,16 @@ static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev) put_device(&ctrldev->dev); } +static struct rpmsg_device_id rpmsg_driver_char_id_table[] = { + { .name = "rpmsg-virtual-char-channel-1" }, + { }, +}; + + +MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_char_id_table); + static struct rpmsg_driver rpmsg_chrdev_driver = { + .id_table = rpmsg_driver_char_id_table, .probe = rpmsg_chrdev_probe, .remove = rpmsg_chrdev_remove, .drv = { diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 7d7ed4e5c..7315fe2d1 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -158,7 +158,7 @@ struct virtio_rpmsg_channel { * processor. */ #define MAX_RPMSG_NUM_BUFS (512) -#define MAX_RPMSG_BUF_SIZE (512) +#define MAX_RPMSG_BUF_SIZE (4096) /* * Local addresses are dynamically allocated on-demand. diff --git a/drivers/usb/dwc3/dwc3-thead.c b/drivers/usb/dwc3/dwc3-thead.c index 2caf73a39..035671e29 100644 --- a/drivers/usb/dwc3/dwc3-thead.c +++ b/drivers/usb/dwc3/dwc3-thead.c @@ -73,6 +73,14 @@ #define USB3_DRD_PRST BIT(0) #define USB3_DRD_MASK GENMASK(2, 0) +/* USB as host or device*/ +#define USB_AS_HOST (true) +#define USB_AS_DEVICE (false) + +static bool usb_role = USB_AS_HOST; +module_param(usb_role, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(usb_role, "USB role"); + struct dwc3_thead { struct device *dev; struct platform_device *dwc3; @@ -255,9 +263,10 @@ static int dwc3_thead_probe(struct platform_device *pdev) platform_set_drvdata(pdev, thead); thead->dev = &pdev->dev; - thead->hubswitch = devm_gpiod_get(dev, "hubswitch", GPIOD_OUT_HIGH); + thead->hubswitch = devm_gpiod_get(dev, "hubswitch", (usb_role == USB_AS_DEVICE) ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH); if (IS_ERR(thead->hubswitch)) dev_dbg(dev, "no need to get hubswitch GPIO\n"); + dev_info(dev, "hubswitch usb_role = %d\n", usb_role); thead->vbus = devm_regulator_get(dev, "vbus"); if (IS_ERR(thead->vbus)) diff --git a/drivers/virtio/virtio_vdmabuf.c b/drivers/virtio/virtio_vdmabuf.c index 4a019ec6a..503f08794 100644 --- a/drivers/virtio/virtio_vdmabuf.c +++ b/drivers/virtio/virtio_vdmabuf.c @@ -1226,6 +1226,12 @@ static int virtio_vdmabuf_create_dmabuf(struct virtio_vdmabuf *vdmabuf, exp_info.flags = O_RDWR; exp_info.priv = exp_buf; + unsigned int gfp = GFP_KERNEL; + if(attr->flags & VIRTIO_VDAMBUF_DMA32) + { + gfp |= __GFP_DMA32; + } + switch (heap_type) { case VIRTIO_VDMABUF_HEAP_TYPE_USER: return -EINVAL; /* Not support currently */ @@ -1235,7 +1241,7 @@ static int virtio_vdmabuf_create_dmabuf(struct virtio_vdmabuf *vdmabuf, exp_buf->bp_num = npages; for (i = 0; i < npages; i++) { - page = alloc_page(GFP_KERNEL); + page = alloc_page(gfp); if (!page) { ret = -ENOMEM; goto err_alloc; @@ -1253,7 +1259,7 @@ static int virtio_vdmabuf_create_dmabuf(struct virtio_vdmabuf *vdmabuf, /* only need 1 bp to record Compound Page */ exp_buf->bp_num = 1; - page = alloc_pages(GFP_KERNEL, get_order(exp_buf->size)); + page = alloc_pages(gfp, get_order(exp_buf->size)); if (!page) { ret = -ENOMEM; goto err_exp; diff --git a/include/asm-generic/rwonce.h b/include/asm-generic/rwonce.h index 8d0a6280e..2671e2439 100644 --- a/include/asm-generic/rwonce.h +++ b/include/asm-generic/rwonce.h @@ -53,6 +53,7 @@ #define __WRITE_ONCE(x, val) \ do { \ *(volatile typeof(x) *)&(x) = (val); \ + smp_mb(); \ } while (0) #define WRITE_ONCE(x, val) \ diff --git a/include/dt-bindings/clock/light-audiosys.h b/include/dt-bindings/clock/light-audiosys.h new file mode 100644 index 000000000..3a0ba5d82 --- /dev/null +++ b/include/dt-bindings/clock/light-audiosys.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Alibaba Group Holding Limited. + */ + +#ifndef _LIGHT_AUDIOSYS_H_ +#define _LIGHT_AUDIOSYS_H_ + +#define LIGHT_CLKGEN_AUDIO_CPU 0 +#define LIGHT_CLKGEN_AUDIO_SRAM0 1 +#define LIGHT_CLKGEN_AUDIO_SRAM1 2 +#define LIGHT_CLKGEN_AUDIO_DMA 3 +#define LIGHT_CLKGEN_AUDIO_BSM 4 +#define LIGHT_CLKGEN_AUDIO_TIMER 5 +#define LIGHT_CLKGEN_AUDIO_TIMER_CNT1 6 +#define LIGHT_CLKGEN_AUDIO_TIMER_CNT2 7 +#define LIGHT_CLKGEN_AUDIO_TIMER_CNT3 8 +#define LIGHT_CLKGEN_AUDIO_TIMER_CNT4 9 +#define LIGHT_CLKGEN_AUDIO_WDR 10 +#define LIGHT_CLKGEN_AUDIO_I2C0 11 +#define LIGHT_CLKGEN_AUDIO_I2C1 12 +#define LIGHT_CLKGEN_AUDIO_UART 13 +#define LIGHT_CLKGEN_AUDIO_I2S0 14 +#define LIGHT_CLKGEN_AUDIO_I2S1 15 +#define LIGHT_CLKGEN_AUDIO_I2S2 16 +#define LIGHT_CLKGEN_AUDIO_I2S8CH 17 +#define LIGHT_CLKGEN_AUDIO_TDM 18 +#define LIGHT_CLKGEN_AUDIO_GPIO 19 +#define LIGHT_CLKGEN_AUDIO_SPDIF0 20 +#define LIGHT_CLKGEN_AUDIO_SPDIF1 21 +#define LIGHT_CLKGEN_AUDIO_VAD 22 +#define LIGHT_CLKGEN_AUDIO_IOMUX 23 +#define LIGHT_CLKGEN_AUDIO_CLK_END 24 + +#endif diff --git a/include/dt-bindings/pinctrl/light-fm-pinctrl-def.h b/include/dt-bindings/pinctrl/light-fm-pinctrl-def.h new file mode 100644 index 000000000..3b2a23547 --- /dev/null +++ b/include/dt-bindings/pinctrl/light-fm-pinctrl-def.h @@ -0,0 +1,36 @@ + + +#ifndef __DT_BINDINGS_LIGHT_FM_PINCTRL_DEF_H__ +#define __DT_BINDINGS_LIGHT_FM_PINCTRL_DEF_H__ + +#define LIGHT_PIN_PULL_NONE 0 +#define LIGHT_PIN_PULL_DOWN 1 +#define LIGHT_PIN_PULL_UP 2 + +#define LIGHT_PIN_DRV_LV0 0 +#define LIGHT_PIN_DRV_LV1 1 +#define LIGHT_PIN_DRV_LV2 2 +#define LIGHT_PIN_DRV_LV3 3 +#define LIGHT_PIN_DRV_LV4 4 +#define LIGHT_PIN_DRV_LV5 5 +#define LIGHT_PIN_DRV_LV6 6 +#define LIGHT_PIN_DRV_LV7 7 +#define LIGHT_PIN_DRV_LV8 8 +#define LIGHT_PIN_DRV_LV9 9 +#define LIGHT_PIN_DRV_LV10 10 +#define LIGHT_PIN_DRV_LV11 11 +#define LIGHT_PIN_DRV_LV12 12 +#define LIGHT_PIN_DRV_LV13 13 +#define LIGHT_PIN_DRV_LV14 14 +#define LIGHT_PIN_DRV_LV15 15 + +#define LIGHT_PIN_FUNC_0 0 +#define LIGHT_PIN_FUNC_1 1 +#define LIGHT_PIN_FUNC_2 2 +#define LIGHT_PIN_FUNC_3 3 +#define LIGHT_PIN_FUNC_4 4 +#define LIGHT_PIN_FUNC_5 5 +#define LIGHT_PIN_FUNC_6 6 +#define LIGHT_PIN_FUNC_7 7 + +#endif // __DT_BINDINGS_LIGHT_FM_PINCTRL_DEF_H__ diff --git a/include/dt-bindings/reset/light-reset.h b/include/dt-bindings/reset/light-reset.h index e99470368..44d5a722f 100644 --- a/include/dt-bindings/reset/light-reset.h +++ b/include/dt-bindings/reset/light-reset.h @@ -10,5 +10,10 @@ #define LIGHT_RESET_WDT0 0 #define LIGHT_RESET_WDT1 1 +#define LIGHT_RESET_NPU 2 + +// vpsys reset +#define LIGHT_RESET_FCE 100 + #endif diff --git a/include/linux/light_rpmsg.h b/include/linux/light_rpmsg.h new file mode 100644 index 000000000..9c70c50b9 --- /dev/null +++ b/include/linux/light_rpmsg.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023 Alibaba Group Holding Limited. + */ + +/* + * The code contained herein is licensed under the GNU Lesser General + * Public License. You may obtain a copy of the GNU Lesser General + * Public License Version 2.1 or later at the following locations: + * + * http://www.opensource.org/licenses/lgpl-license.html + * http://www.gnu.org/copyleft/lgpl.html + */ + +/* + * @file linux/light_rpmsg.h + * + * @brief Global header file for imx RPMSG + * + * @ingroup RPMSG + */ +#ifndef __LINUX_LIGHT_RPMSG_H__ +#define __LINUX_LIGHT_RPMSG_H__ + +#include +#include +#include +#include +#include +#include + +/* Category define */ +#define LIGHT_RMPSG_LIFECYCLE 1 +#define LIGHT_RPMSG_PMIC 2 +#define LIGHT_RPMSG_AUDIO 3 +#define LIGHT_RPMSG_KEY 4 +#define LIGHT_RPMSG_GPIO 5 +#define LIGHT_RPMSG_RTC 6 +#define LIGHT_RPMSG_SENSOR 7 +/* rpmsg version */ +#define LIGHT_RMPSG_MAJOR 1 +#define LIGHT_RMPSG_MINOR 0 + +enum light_rpmsg_variants { + LIGHTA, + LIGHTB, + LIGHT_RPMSG, +}; + +struct light_virdev { + struct virtio_device vdev; + unsigned int vring[2]; + struct virtqueue *vq[2]; + int base_vq_id; + int num_of_vqs; + struct notifier_block nb; +}; + +struct light_rpmsg_vproc { + char *rproc_name; + struct mutex lock; + struct clk *mu_clk; + enum light_rpmsg_variants variant; + int vdev_nums; + int first_notify; +#define MAX_VDEV_NUMS 8 + struct light_virdev ivdev[MAX_VDEV_NUMS]; + void __iomem *mu_base; + struct delayed_work rpmsg_work; + struct blocking_notifier_head notifier; +#define MAX_NUM 10 /* enlarge it if overflow happen */ + u32 m4_message[MAX_NUM]; + u32 in_idx; + u32 out_idx; + u32 core_id; + spinlock_t mu_lock; +}; + +struct light_rpmsg_head { + u8 cate; + u8 major; + u8 minor; + u8 type; + u8 cmd; + u8 reserved[5]; +} __attribute__ ((packed)); + +#endif /* __LINUX_LIGHT_RPMSG_H__*/ + diff --git a/include/uapi/linux/virtio_vdmabuf.h b/include/uapi/linux/virtio_vdmabuf.h index 93785c320..fa4fd1e60 100644 --- a/include/uapi/linux/virtio_vdmabuf.h +++ b/include/uapi/linux/virtio_vdmabuf.h @@ -17,7 +17,8 @@ _IOC(_IOC_NONE, 'G', 2, sizeof(struct virtio_vdmabuf_alloc)) _IOC(_IOC_NONE, 'G', 3, sizeof(struct virtio_vdmabuf_import)) /* dmabuf flag */ -#define VIRTIO_VDAMBUF_NONCACHED 0x1 +#define VIRTIO_VDAMBUF_NONCACHED 0x1 +#define VIRTIO_VDAMBUF_DMA32 0x4 /* * Max single alloc size is (768 * PAGE_SIZE) only for diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index cbff6ba53..f6bc1015b 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c @@ -94,7 +94,7 @@ struct qnode { * progress. */ #ifndef _Q_PENDING_LOOPS -#define _Q_PENDING_LOOPS 1 +#define _Q_PENDING_LOOPS 9 #endif /* diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index f5ba0740f..5b881b72f 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -435,7 +435,7 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp) * be quite short, for example, in the case of the call from * rcu_read_unlock_special(). */ -static void +static notrace void rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags) { bool empty_exp; @@ -556,7 +556,7 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags) * is disabled. This function cannot be expected to understand these * nuances, so the caller must handle them. */ -static bool rcu_preempt_need_deferred_qs(struct task_struct *t) +static notrace bool rcu_preempt_need_deferred_qs(struct task_struct *t) { return (__this_cpu_read(rcu_data.exp_deferred_qs) || READ_ONCE(t->rcu_read_unlock_special.s)) && @@ -570,7 +570,7 @@ static bool rcu_preempt_need_deferred_qs(struct task_struct *t) * evaluate safety in terms of interrupt, softirq, and preemption * disabling. */ -static void rcu_preempt_deferred_qs(struct task_struct *t) +static notrace void rcu_preempt_deferred_qs(struct task_struct *t) { unsigned long flags; @@ -897,11 +897,11 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp) * Because there is no preemptible RCU, there can be no deferred quiescent * states. */ -static bool rcu_preempt_need_deferred_qs(struct task_struct *t) +static notrace bool rcu_preempt_need_deferred_qs(struct task_struct *t) { return false; } -static void rcu_preempt_deferred_qs(struct task_struct *t) { } +static notrace void rcu_preempt_deferred_qs(struct task_struct *t) { } /* * Because there is no preemptible RCU, there can be no readers blocked, diff --git a/sound/soc/codecs/es7210.c b/sound/soc/codecs/es7210.c index 8d5d3a245..a395c7547 100644 --- a/sound/soc/codecs/es7210.c +++ b/sound/soc/codecs/es7210.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "es7210.h" @@ -912,7 +913,20 @@ exit_i2c_check_id_failed: return 0; } +static void es7210_remove(struct snd_soc_component *component) +{ + struct es7210_priv *es7210 = snd_soc_component_get_drvdata(component); + /* power down the controller */ + if (es7210->pvdd) + regulator_disable(es7210->pvdd); + if (es7210->dvdd) + regulator_disable(es7210->dvdd); + if (es7210->avdd) + regulator_disable(es7210->avdd); + if (es7210->mvdd) + regulator_disable(es7210->mvdd); +} static int es7210_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) diff --git a/sound/soc/codecs/es8156.c b/sound/soc/codecs/es8156.c index 47ab55ef0..1e0b58056 100644 --- a/sound/soc/codecs/es8156.c +++ b/sound/soc/codecs/es8156.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "es8156.h" #define INVALID_GPIO -1 @@ -63,6 +64,9 @@ struct es8156_priv { unsigned int sysclk; struct snd_pcm_hw_constraint_list *sysclk_constraints; struct clk *mclk; + struct regulator *avdd; + struct regulator *dvdd; + struct regulator *pvdd; int debounce_time; int hp_det_invert; struct delayed_work work; @@ -74,6 +78,7 @@ struct es8156_priv { bool spk_active_level; int pwr_count; + u32 mclk_sclk_ratio; }; /* @@ -143,6 +148,158 @@ static const struct snd_soc_dapm_widget es8156_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("ROUT"), }; +/*************** parameter define ***************/ +#define STATEconfirm 0x0C +#define NORMAL_I2S 0x00 +#define NORMAL_LJ 0x01 +#define NORMAL_DSPA 0x03 +#define NORMAL_DSPB 0x07 +#define Format_Len24 0x00 +#define Format_Len20 0x01 +#define Format_Len18 0x02 +#define Format_Len16 0x03 +#define Format_Len32 0x04 + +#define VDDA_3V3 0x00 +#define VDDA_1V8 0x01 +#define MCLK_PIN 0x00 +#define SCLK_PIN 0x01 + +/**************************************************/ +#define MSMode_MasterSelOn 0 // SlaveMode:0, MasterMode:1 +static unsigned int Ratio = 64; // Ratio = MCLK/LRCK on board +#define Format NORMAL_I2S +#define Format_Len Format_Len16 // data format +#define SCLK_DIV 8 // SCLK_DIV = MCLK/SCLK +#define SCLK_INV 0 +static unsigned int MCLK_SOURCE; // select MCLK source, MCLK_PIN or SCLK_PIN +#define EQ7bandOn 0 +#define VDDA_VOLTAGE VDDA_3V3 +#define DAC_Volume 191 // DAC digital gain +#define DACHPModeOn 0 // disable:0, enable:1 + +/**************************************************/ + +static int es8156_init_regs(struct snd_soc_component *codec) +{ + struct es8156_priv *priv = snd_soc_component_get_drvdata(codec); + pr_debug("%s\n", __func__); + + snd_soc_component_write(codec,0x02,(MCLK_SOURCE<<7) + (SCLK_INV<<4) + (EQ7bandOn<<3) + 0x04 + MSMode_MasterSelOn); + snd_soc_component_write(codec,0x19,0x20); + + if(DACHPModeOn == 0) // output from PA + { + snd_soc_component_write(codec,0x20,0x2A); + snd_soc_component_write(codec,0x21,0x3C); + snd_soc_component_write(codec,0x22,0x02); + snd_soc_component_write(codec,0x24,0x07); + snd_soc_component_write(codec,0x23,0x40 + (0x30*VDDA_VOLTAGE)); + } + if(DACHPModeOn == 1) // output from headphone + { + snd_soc_component_write(codec,0x20,0x16); + snd_soc_component_write(codec,0x21,0x3F); + snd_soc_component_write(codec,0x22,0x0A); + snd_soc_component_write(codec,0x24,0x01); + snd_soc_component_write(codec,0x23,0xCA + (0x30*VDDA_VOLTAGE)); + } + snd_soc_component_write(codec,0x0A,0x01); + snd_soc_component_write(codec,0x0B,0x01); + //snd_soc_component_write(codec,0x11,NORMAL_I2S + (Format_Len<<4)); + + if(Ratio == 1536) // Ratio=MCLK/LRCK=1536; 12M288/8K; 24M576/16K + { + snd_soc_component_write(codec,0x01,0x26 - (0x03*EQ7bandOn)); // 1536 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x09,0x00); // 1536 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x03,0x06); // LRCK H + snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/1536 + snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4 + } + if(Ratio == 1024) // Ratio=MCLK/LRCK=1024; 12M288/12K; 24M576/24K + { + snd_soc_component_write(codec,0x01,0x24 - (0x02*EQ7bandOn)); // 256 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x09,0x00); // 256 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x03,0x04); // LRCK H + snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/256 + snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4 + } + if(Ratio == 768) // Ratio=MCLK/LRCK=768; 12M288/16K; 24M576/32K + { + snd_soc_component_write(codec,0x01,0x23 + (0x40*EQ7bandOn)); // 768 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x09,0x00); // 768 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x03,0x03); // LRCK H + snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/768 + snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4 + } + if(Ratio == 512) // Ratio=MCLK/LRCK=512; 12M288/24K; 24M576/48K + { + snd_soc_component_write(codec,0x01,0xC0 + 0x22 - (0x01*EQ7bandOn)); // 512 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x09,0x00); // 512 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x03,0x02); // LRCK H + snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/512 + snd_soc_component_write(codec,0x05,SCLK_DIV); //BCLK=MCLK/4 + } + if(Ratio == 400) // Ratio=MCLK/LRCK=400; 19M2/48K + { // DVDD must be 3.3V + snd_soc_component_write(codec,0x01,0x21 + (0x40*EQ7bandOn)); // 384 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x09,0x00); // 400 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x10,0x64); // 400 OSR + snd_soc_component_write(codec,0x03,0x01); // LRCK H + snd_soc_component_write(codec,0x04,0x90); // LRCK=MCLK/400 + snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4 + } + if(Ratio == 384) // Ratio=MCLK/LRCK=384; 12M288/32K; 6M144/16K + { + snd_soc_component_write(codec,0x01,0x63 + (0x40*EQ7bandOn)); // 384 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x09,0x00); // 384 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x03,0x01); // LRCK H + snd_soc_component_write(codec,0x04,0x80); // LRCK=MCLK/384 + snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4 + } + if(Ratio == 256) // Ratio=MCLK/LRCK=256; 12M288/48K + { + snd_soc_component_write(codec,0x01,0x21 + (0x40*EQ7bandOn)); // 256 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x09,0x00); // 256 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x03,0x01); // LRCK H + snd_soc_component_write(codec,0x04,0x00); // LRCK=MCLK/256 + snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4 + } + if(Ratio == 128) // Ratio=MCLK/LRCK=128; 6M144/48K + { + snd_soc_component_write(codec,0x01,0x61 + (0x40*EQ7bandOn)); // 128 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x09,0x00); // 128 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x03,0x00); // LRCK H + snd_soc_component_write(codec,0x04,0x80); // LRCK=MCLK/128 + snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/4 + } + if(Ratio == 64) // Ratio=MCLK/LRCK=64; 3M072/48K + { + snd_soc_component_write(codec,0x01,0xE1); // 64 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x09,0x02); // 64 Ratio(MCLK/LRCK) + snd_soc_component_write(codec,0x03,0x00); // LRCK H + snd_soc_component_write(codec,0x04,0x40); // LRCK=MCLK/64 + snd_soc_component_write(codec,0x05,SCLK_DIV); // BCLK=MCLK/2 + } + + snd_soc_component_write(codec,0x0D,0x14); + snd_soc_component_write(codec,0x18,0x00); + snd_soc_component_write(codec,0x08,0x3F); + snd_soc_component_write(codec,0x00,0x02); + snd_soc_component_write(codec,0x00,0x03); + snd_soc_component_write(codec,0x25,0x20); + + return 0; +} + +static int es8156_init_sequence(struct snd_soc_component *codec) +{ + es8156_init_regs(codec); + snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14, DAC_Volume); + + return 0; +} + static const struct snd_soc_dapm_route es8156_dapm_routes[] = { {"SDOUT TRISTATE",NULL,"SDIN"}, {"SDOUT",NULL,"SDOUT TRISTATE"}, @@ -392,7 +549,7 @@ static int es8156_pcm_hw_params(struct snd_pcm_substream *substream, static int es8156_set_bias_level(struct snd_soc_component *codec, enum snd_soc_bias_level level) { - int ret; + int ret, i; struct es8156_priv *priv = snd_soc_component_get_drvdata(codec); switch (level) @@ -547,12 +704,23 @@ static void hp_work(struct work_struct *work) static int es8156_probe(struct snd_soc_component *codec) { -#if MCLK struct es8156_priv *es8156 = snd_soc_component_get_drvdata(codec); -#endif int ret = 0; es8156_codec = codec; + + /* power up the controller */ + if (es8156->avdd) + ret |= regulator_enable(es8156->avdd); + if (es8156->dvdd) + ret |= regulator_enable(es8156->dvdd); + if (es8156->pvdd) + ret |= regulator_enable(es8156->pvdd); + if (ret) { + pr_err("Failed to enable VDD regulator: %d\n", ret); + return ret; + } + #if MCLK es8156->mclk = devm_clk_get(codec->dev, "mclk"); if (PTR_ERR(es8156->mclk) == -EPROBE_DEFER) @@ -600,10 +768,10 @@ static int es8156_i2c_probe(struct i2c_client *i2c, { struct es8156_priv *es8156; int ret = -1; + struct device_node *np = i2c->dev.of_node; #ifdef HP_DET_FUNTION int hp_irq; enum of_gpio_flags flags; - struct device_node *np = i2c->dev.of_node; #endif es8156 = devm_kzalloc(&i2c->dev, sizeof(*es8156), GFP_KERNEL); if (!es8156) @@ -622,6 +790,35 @@ static int es8156_i2c_probe(struct i2c_client *i2c, return ret; } + es8156->avdd = devm_regulator_get(&i2c->dev, "AVDD"); + if (IS_ERR(es8156->avdd)) { + ret = PTR_ERR(es8156->avdd); + dev_warn(&i2c->dev, "Failed to get AVDD regulator: %d\n", ret); + es8156->avdd = NULL; + } + es8156->dvdd = devm_regulator_get(&i2c->dev, "DVDD"); + if (IS_ERR(es8156->dvdd)) { + ret = PTR_ERR(es8156->dvdd); + dev_warn(&i2c->dev, "Failed to get DVDD regulator: %d\n", ret); + es8156->dvdd = NULL; + } + es8156->pvdd = devm_regulator_get(&i2c->dev, "PVDD"); + if (IS_ERR(es8156->pvdd)) { + ret = PTR_ERR(es8156->pvdd); + dev_warn(&i2c->dev, "Failed to get PVDD regulator: %d\n", ret); + es8156->pvdd = NULL; + } + + if (of_property_read_u32(np, "mclk-sclk-ratio", &es8156->mclk_sclk_ratio) != 0) { + es8156->mclk_sclk_ratio = 1; + } + Ratio *= es8156->mclk_sclk_ratio; + if (es8156->mclk_sclk_ratio == 1) { + MCLK_SOURCE = SCLK_PIN; + } else { + MCLK_SOURCE = MCLK_PIN; + } + i2c_set_clientdata(i2c, es8156); #ifdef HP_DET_FUNTION es8156->spk_ctl_gpio = of_get_named_gpio_flags(np, diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 97e8bd7fc..d0d79f47b 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -145,19 +145,16 @@ EXPORT_SYMBOL_GPL(asoc_simple_parse_card_name); static int asoc_simple_clk_enable(struct asoc_simple_dai *dai) { - if (dai) { - if (!IS_ERR_OR_NULL(dai->clk)) - return clk_prepare_enable(dai->clk); - } + if (dai) + return clk_prepare_enable(dai->clk); + return 0; } static void asoc_simple_clk_disable(struct asoc_simple_dai *dai) { - if (dai) { - if (!IS_ERR_OR_NULL(dai->clk)) - clk_disable_unprepare(dai->clk); - } + if (dai) + clk_disable_unprepare(dai->clk); } int asoc_simple_parse_clk(struct device *dev, @@ -185,7 +182,6 @@ int asoc_simple_parse_clk(struct device *dev, clk = devm_get_clk_from_child(dev, dlc->of_node, NULL); if (!IS_ERR(clk)) simple_dai->sysclk = clk_get_rate(clk); - simple_dai->clk = NULL; // avoid invalid clk pointer like 0x00000000d } if (of_property_read_bool(node, "system-clock-direction-out")) @@ -246,11 +242,7 @@ static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai, if (clk_get_rate(simple_dai->clk) == rate) return 0; - if (!IS_ERR_OR_NULL(simple_dai->clk)) { - return clk_set_rate(simple_dai->clk, rate); - } else { - return 0; - } + return clk_set_rate(simple_dai->clk, rate); } int asoc_simple_hw_params(struct snd_pcm_substream *substream, diff --git a/sound/soc/thead/Makefile b/sound/soc/thead/Makefile index 6c8b733d8..fc918f4a6 100644 --- a/sound/soc/thead/Makefile +++ b/sound/soc/thead/Makefile @@ -2,6 +2,8 @@ obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-i2s.o obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-tdm.o +obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-i2s-8ch.o +obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-spdif.o obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-pcm-dma.o obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-dummy-pcm.o obj-$(CONFIG_SND_SOC_AW87519) += aw87519_audio.o diff --git a/sound/soc/thead/light-audio-cpr.h b/sound/soc/thead/light-audio-cpr.h new file mode 100644 index 000000000..0b4422f0f --- /dev/null +++ b/sound/soc/thead/light-audio-cpr.h @@ -0,0 +1,49 @@ +#ifndef _LIGHT_AUDIO_CPR_H +#define _LIGHT_AUDIO_CPR_H + +#define CPR_PERI_DIV_SEL_REG 0x004 /*audio sys i2s clock div Register*/ +#define CPR_PERI_CLK_SEL_REG 0x008 /*audio sys i2s clock selection Register*/ +#define CPR_PERI_CTRL_REG 0x00C /*Peripheral control signal configuration register*/ + + +/* AUDIO SYS DIV SEL REG, offset: 0x4 */ +#define CPR_AUDIO_DIV0_SEL_POS (4U) +#define CPR_AUDIO_DIV0_SEL_MSK (0x1FU << CPR_AUDIO_DIV0_SEL_POS) +#define CPR_AUDIO_DIV0_SEL(X) (X << CPR_AUDIO_DIV0_SEL_POS) +#define CPR_AUDIO_DIV1_SEL_POS (12U) +#define CPR_AUDIO_DIV1_SEL_MSK (0x1FU << CPR_AUDIO_DIV1_SEL_POS) +#define CPR_AUDIO_DIV1_SEL(X) (X << CPR_AUDIO_DIV1_SEL_POS) + +/* AUDIO SYS CLK SEL REG, offset: 0x8 */ +#define CPR_I2S0_SRC_SEL_POS (0U) +#define CPR_I2S0_SRC_SEL_MSK (0x3U << CPR_I2S0_SRC_SEL_POS) +#define CPR_I2S0_SRC_SEL(X) (X << CPR_I2S0_SRC_SEL_POS) +#define CPR_I2S0_SRC_SEL_24M (0x1U << AUDIOSYS_I2S0_SRC_SEL_POS) +#define CPR_I2S0_SRC_SEL_AUDIO_DIVCLK1 (0x2U << AUDIOSYS_I2S0_SRC_SEL_POS) + +#define CPR_I2S1_SRC_SEL_POS (4U) +#define CPR_I2S1_SRC_SEL_MSK (0x3U << CPR_I2S1_SRC_SEL_POS) +#define CPR_I2S1_SRC_SEL(X) (X << CPR_I2S1_SRC_SEL_POS) +#define CPR_I2S1_SRC_SEL_24M (0x1U << AUDIOSYS_I2S1_SRC_SEL_POS) +#define CPR_I2S1_SRC_SEL_AUDIO_DIVCLK1 (0x2U << AUDIOSYS_I2S1_SRC_SEL_POS) + +#define CPR_I2S2_SRC_SEL_POS (8U) +#define CPR_I2S2_SRC_SEL_MSK (0x3U << CPR_I2S2_SRC_SEL_POS) +#define CPR_I2S2_SRC_SEL(X) (X << CPR_I2S2_SRC_SEL_POS) +#define CPR_I2S2_SRC_SEL_24M (0x1U << AUDIOSYS_I2S2_SRC_SEL_POS) +#define CPR_I2S2_SRC_SEL_AUDIO_DIVCLK1 (0x2U << AUDIOSYS_I2S2_SRC_SEL_POS) + +/* PERI_CTRL_REG, Offset: 0xC */ +#define CPR_VAD_I2SIN_SYNC_POS (12U) +#define CPR_VAD_I2SIN_SYNC_MSK (0x1U << CPR_VAD_I2SIN_SYNC_POS) +#define CPR_VAD_I2SIN_SYNC_EN (CPR_VAD_I2SIN_SYNC_MSK) +#define CPR_I2S_SYNC_POS (13U) +#define CPR_I2S_SYNC_MSK (0x1U << CPR_I2S_SYNC_POS) +#define CPR_I2S_SYNC_EN (CPR_I2S_SYNC_MSK) +#define CPR_SPDIF_SYNC_POS (14U) +#define CPR_SPDIF_SYNC_MSK (0x1U << CPR_SPDIF_SYNC_POS) +#define CPR_SPDIF_SYNC_EN (CPR_SPDIF_SYNC_MSK) + + +#endif /* _LIGHT_AUDIO_CPR_H */ + diff --git a/sound/soc/thead/light-dummy-pcm.c b/sound/soc/thead/light-dummy-pcm.c index bc8e12ad2..4475e2fc5 100644 --- a/sound/soc/thead/light-dummy-pcm.c +++ b/sound/soc/thead/light-dummy-pcm.c @@ -25,17 +25,17 @@ static struct snd_soc_dai_driver light_dummy_pcm_dai[] = { .name = "dummy-pcm", .playback = { .stream_name = "Playback", - .channels_min = 2, + .channels_min = 1, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, }, .capture = { .stream_name = "Capture", .channels_min = 1, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, }, }, }; diff --git a/sound/soc/thead/light-i2s-8ch.c b/sound/soc/thead/light-i2s-8ch.c new file mode 100644 index 000000000..32843f09d --- /dev/null +++ b/sound/soc/thead/light-i2s-8ch.c @@ -0,0 +1,797 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "light-i2s.h" +#include "light-pcm.h" +#include "light-audio-cpr.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define IIS_SRC_CLK 294912000 +#define AUDIO_IIS_SRC0_CLK 49152000 +#define AUDIO_IIS_SRC1_CLK 135475200 +#define IIS_MCLK_SEL 256 +#define HDMI_DIV_VALUE 2 +#define DIV_DEFAULT 1 +#define MONO_SOURCE 1 +#define STEREO_CHANNEL 2 + +#define I2S_DMA_TX_THRESHOLD 16 +#define I2S_DMA_RX_THRESHOLD 16 + +#define AUDIO_I2S_8CH "i2s_8ch" +#define AUDIO_I2S_8CH_SD0 "i2s_8ch_sd0" +#define AUDIO_I2S_8CH_SD1 "i2s_8ch_sd1" +#define AUDIO_I2S_8CH_SD2 "i2s_8ch_sd2" +#define AUDIO_I2S_8CH_SD3 "i2s_8ch_sd3" + +#define LIGHT_I2S_DMABUF_SIZE (64 * 1024 * 10) + +#define LIGHT_RATES SNDRV_PCM_RATE_8000_384000 +#define LIGHT_FMTS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8) + +#define LIGHT_AUDIO_PAD_CONFIG(idx) (priv->cfg_off + ((idx-25) >> 1) * 4) + +static int i2s_8ch_probe_flag = 0; +static u32 light_special_sample_rates[] = { 11025, 22050, 44100, 88200 }; + +static int light_audio_cpr_set(struct light_i2s_priv *chip, unsigned int cpr_off, + unsigned int mask, unsigned int val) +{ + if(!chip->audio_cpr_regmap) { + return 0; + } + + return regmap_update_bits(chip->audio_cpr_regmap, + cpr_off, mask, val); +} + +static void light_i2s_8ch_set_div_sclk(struct light_i2s_priv *chip, u32 sample_rate, unsigned int div_val) +{ + u32 div; + u32 div0; + u32 cpr_div = (IIS_SRC_CLK/AUDIO_IIS_SRC0_CLK)-1; + if(!chip->regs) { + return; + } + + div = AUDIO_IIS_SRC0_CLK / IIS_MCLK_SEL; + div0 = (div + div % sample_rate) / sample_rate / div_val; + writel(div0, chip->regs + I2S_DIV0_LEVEL); + light_audio_cpr_set(chip, CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV0_SEL_MSK, CPR_AUDIO_DIV0_SEL(cpr_div)); +} + +static inline void light_snd_txctrl(struct light_i2s_priv *chip, bool on) +{ + u32 dma_en = 0; + u32 i2s_8ch_en = 0; + u32 i2s_8ch_imr = 0; + + if(!chip->regs) { + return; + } + + if (on) { + dma_en |= DMACR_TDMAE_EN; + i2s_8ch_en |= IISEN_I2SEN; + writel(dma_en, chip->regs + I2S_DMACR); + writel(i2s_8ch_en, chip->regs + I2S_IISEN); + } else { + dma_en &= ~DMACR_TDMAE_EN; + i2s_8ch_en &= ~IISEN_I2SEN; + i2s_8ch_imr = readl(chip->regs + I2S_IMR); + i2s_8ch_imr &= ~(IMR_TXUIRM_INTR_MSK); + i2s_8ch_imr &= ~(IMR_TXEIM_INTR_MSK); + writel(i2s_8ch_imr, chip->regs + I2S_IMR); + writel(dma_en, chip->regs + I2S_DMACR); + writel(i2s_8ch_en, chip->regs + I2S_IISEN); + } +} + +static inline void light_snd_rxctrl(struct light_i2s_priv *chip, bool on) +{ + u32 dma_en = 0; + u32 i2s_8ch_en = 0; + + if(!chip->regs) { + return; + } + + if (on) { + dma_en |= DMACR_RDMAE_EN; + i2s_8ch_en |= IISEN_I2SEN; + writel(I2S_DMA_RX_THRESHOLD, chip->regs + I2S_DMARDLR); + } else { + dma_en &= ~DMACR_RDMAE_EN; + i2s_8ch_en &= ~IISEN_I2SEN; + } + + writel(dma_en, chip->regs + I2S_DMACR); + writel(i2s_8ch_en, chip->regs + I2S_IISEN); +} + +static int light_i2s_8ch_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return 0; +} + +static void light_i2s_8ch_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct light_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); + + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + light_snd_rxctrl(priv, 0); + + clk_disable_unprepare(priv->clk); +} + +/** + * light_i2s_8ch_dai_trigger: start and stop the DMA transfer. + * + * This function is called by ALSA to start, stop, pause, and resume the DMA + * transfer of data. + */ +static int light_i2s_8ch_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + int ret = 0; + + struct light_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (tx) + light_snd_txctrl(priv, 1); + else + light_snd_rxctrl(priv, 1); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (tx) { + dmaengine_terminate_async(snd_dmaengine_pcm_get_chan(substream)); // work around for DMAC stop issue + light_snd_txctrl(priv, 0); + } + break; + default: + return -EINVAL; + + } + + return ret; +} + +static int light_i2s_8ch_set_fmt_dai(struct snd_soc_dai *cpu_dai, unsigned int fmt) +{ + struct light_i2s_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); + u32 cnfout = 0; + u32 cnfin = 0; + + if(!priv->regmap) { + return 0; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + cnfout |= IISCNFOUT_TSAFS_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + cnfout |= IISCNFOUT_TSAFS_RIGHT_JUSTIFIED; + break; + case SND_SOC_DAIFMT_LEFT_J: + cnfout |= IISCNFOUT_TSAFS_LEFT_JUSTIFIED; + break; + default: + pr_err("Unknown fmt dai\n"); + return -EINVAL; + } + + regmap_update_bits(priv->regmap, I2S_IISCNF_OUT, + IISCNFOUT_TSAFS_MSK, + cnfout); + + cnfin |= CNFIN_I2S_RXMODE_MASTER_MODE; + regmap_update_bits(priv->regmap, I2S_IISCNF_IN, + CNFIN_I2S_RXMODE_Msk, + cnfin); + + return 0; +} + +static int light_i2s_8ch_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct light_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + u32 val; + u32 len = 0; + u32 sclk_sel = 0; + u32 rate; + u32 funcmode; + u32 iiscnf_out; + u32 iiscnf_in; + u32 i2s_8ch_en; + + u32 channels = params_channels(params); + + if(!priv->regs || !priv->regmap) { + return 0; + } + + rate = params_rate(params); + + iiscnf_out = readl(priv->regs + I2S_IISCNF_OUT); + iiscnf_in = readl(priv->regs + I2S_IISCNF_IN); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + val |= I2S_DATA_8BIT_WIDTH_32BIT; + len = 32; + break; + case SNDRV_PCM_FORMAT_S16_LE: + val |= I2S_DATA_WIDTH_16BIT; + len = 32; + break; + case SNDRV_PCM_FORMAT_S24_LE: + val |= I2S_DATA_WIDTH_24BIT; + len = 32; + break; + case SNDRV_PCM_FORMAT_S32_LE: + val |= I2S_DATA_WIDTH_32BIT; + len = 32; + break; + default: + pr_err("Unknown data format\n"); + return -EINVAL; + } + + sclk_sel = len*STEREO_CHANNEL; + + switch (sclk_sel) { + case 16: + val |= FSSTA_SCLK_SEL_16; + break; + case 32: + val |= FSSTA_SCLK_SEL_32; + break; + case 48: + val |= FSSTA_SCLK_SEL_48; + break; + case 64: + val |= FSSTA_SCLK_SEL_64; + break; + default: + pr_err("Not support channel num %d\n", channels); + return -EINVAL; + } + + i2s_8ch_en &= ~IISEN_I2SEN; + writel(i2s_8ch_en, priv->regs + I2S_IISEN); + + regmap_update_bits(priv->regmap, I2S_FSSTA, + FSSTA_DATAWTH_Msk | FSSTA_SCLK_SEL_Msk, + val); + funcmode = readl(priv->regs + I2S_FUNCMODE); + if (tx) { + funcmode |= FUNCMODE_TMODE_WEN; + funcmode &= ~FUNCMODE_CH1_ENABLE; + funcmode |= FUNCMODE_RMODE_WEN; + funcmode &= ~FUNCMODE_RMODE; + funcmode &= ~FUNCMODE_TMODE; + funcmode |= FUNCMODE_TMODE; + } else { + funcmode |= FUNCMODE_RMODE_WEN; + funcmode |= FUNCMODE_CH0_ENABLE; + funcmode |= FUNCMODE_CH1_ENABLE; + funcmode |= FUNCMODE_CH2_ENABLE; + funcmode |= FUNCMODE_CH3_ENABLE; + funcmode |= FUNCMODE_TMODE_WEN; + funcmode &= ~FUNCMODE_TMODE; + funcmode &= ~FUNCMODE_RMODE; + funcmode |= FUNCMODE_RMODE; + } + + writel(funcmode, priv->regs + I2S_FUNCMODE); + + if (channels == MONO_SOURCE) { + iiscnf_out |= IISCNFOUT_TX_VOICE_EN_MONO; + iiscnf_in |= CNFIN_RX_CH_SEL_LEFT; + iiscnf_in |= CNFIN_RVOICEEN_MONO; + } else { + iiscnf_out &= ~IISCNFOUT_TX_VOICE_EN_MONO; + iiscnf_in &= ~CNFIN_RX_CH_SEL_LEFT; + iiscnf_in &= ~CNFIN_RVOICEEN_MONO; + } + + if (tx) + writel(iiscnf_out, priv->regs + I2S_IISCNF_OUT); + else + writel(iiscnf_in, priv->regs + I2S_IISCNF_IN); + + light_i2s_8ch_set_div_sclk(priv, rate, DIV_DEFAULT); + + return 0; +} + +static int light_hdmi_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct light_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + u32 val; + u32 len = 0; + u32 rate; + u32 funcmode; + u32 iiscnf_out; + u32 i2s_8ch_en; + + u32 channels = params_channels(params); + + if(!priv->regs || !priv->regmap) { + return 0; + } + + rate = params_rate(params); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + val |= I2S_DATA_WIDTH_16BIT; + len = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + val |= I2S_DATA_WIDTH_24BIT; + len = 24; + break; + default: + pr_err("Unknown data format\n"); + return -EINVAL; + } + + val |= FSSTA_SCLK_SEL_64; + + i2s_8ch_en &= ~IISEN_I2SEN; + writel(i2s_8ch_en, priv->regs + I2S_IISEN); + + regmap_update_bits(priv->regmap, I2S_FSSTA, + FSSTA_DATAWTH_Msk | FSSTA_SCLK_SEL_Msk, + val); + funcmode = readl(priv->regs + I2S_FUNCMODE); + if (tx) { + funcmode |= FUNCMODE_TMODE_WEN; + funcmode &= ~FUNCMODE_TMODE; + funcmode |= FUNCMODE_TMODE; + } else { + funcmode |= FUNCMODE_RMODE_WEN; + funcmode &= ~FUNCMODE_RMODE; + funcmode |= FUNCMODE_RMODE; + } + + writel(funcmode, priv->regs + I2S_FUNCMODE); + + iiscnf_out = readl(priv->regs + I2S_IISCNF_OUT); + if (channels == MONO_SOURCE) + iiscnf_out |= IISCNFOUT_TX_VOICE_EN_MONO; + else + iiscnf_out &= ~IISCNFOUT_TX_VOICE_EN_MONO; + + writel(iiscnf_out, priv->regs + I2S_IISCNF_OUT); + + light_i2s_8ch_set_div_sclk(priv, rate, DIV_DEFAULT); + + return 0; +} + +static int light_i2s_8ch_dai_probe(struct snd_soc_dai *dai) +{ + struct light_i2s_priv *i2s_8ch = snd_soc_dai_get_drvdata(dai); + + if(i2s_8ch) + snd_soc_dai_init_dma_data(dai, &i2s_8ch->dma_params_tx, + &i2s_8ch->dma_params_rx); + + return 0; +} + +static const struct snd_soc_dai_ops light_i2s_8ch_dai_ops = { + .startup = light_i2s_8ch_dai_startup, + .shutdown = light_i2s_8ch_dai_shutdown, + .trigger = light_i2s_8ch_dai_trigger, + .set_fmt = light_i2s_8ch_set_fmt_dai, + .hw_params = light_i2s_8ch_dai_hw_params, +}; + +static const struct snd_soc_dai_ops light_hdmi_dai_ops = { + .startup = light_i2s_8ch_dai_startup, + .shutdown = light_i2s_8ch_dai_shutdown, + .trigger = light_i2s_8ch_dai_trigger, + .set_fmt = light_i2s_8ch_set_fmt_dai, + .hw_params = light_hdmi_dai_hw_params, +}; + +static struct snd_soc_dai_driver light_i2s_8ch_soc_dai[] = { + { + .probe = light_i2s_8ch_dai_probe, + .name = "light-i2s-dai-8ch-sd0", + .playback = { + .rates = LIGHT_RATES, + .formats = LIGHT_FMTS, + .channels_min = 1, + .channels_max = 2, + }, + .capture = { + .rates = LIGHT_RATES, + .formats = LIGHT_FMTS, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &light_i2s_8ch_dai_ops, + }, + { + .probe = light_i2s_8ch_dai_probe, + .name = "light-i2s-dai-8ch-sd1", + .playback = { + .rates = LIGHT_RATES, + .formats = LIGHT_FMTS, + .channels_min = 1, + .channels_max = 2, + }, + .capture = { + .rates = LIGHT_RATES, + .formats = LIGHT_FMTS, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &light_i2s_8ch_dai_ops, + }, + { + .probe = light_i2s_8ch_dai_probe, + .name = "light-i2s-dai-8ch-sd2", + .playback = { + .rates = LIGHT_RATES, + .formats = LIGHT_FMTS, + .channels_min = 1, + .channels_max = 2, + }, + .capture = { + .rates = LIGHT_RATES, + .formats = LIGHT_FMTS, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &light_i2s_8ch_dai_ops, + }, + { + .probe = light_i2s_8ch_dai_probe, + .name = "light-i2s-dai-8ch-sd3", + .playback = { + .rates = LIGHT_RATES, + .formats = LIGHT_FMTS, + .channels_min = 1, + .channels_max = 2, + }, + .capture = { + .rates = LIGHT_RATES, + .formats = LIGHT_FMTS, + .channels_min = 1, + .channels_max = 2, + }, + .ops = &light_i2s_8ch_dai_ops, + }, +}; + + +static const struct snd_soc_component_driver light_i2s_8ch_soc_component = { + .name = "light_i2s_8ch", +}; + +static int light_pcm_probe(struct platform_device *pdev,struct light_i2s_priv *i2s_8ch) +{ + int ret; + + ret = light_pcm_dma_init(pdev, LIGHT_I2S_DMABUF_SIZE); + + if (ret) { + pr_err("light_pcm_dma_init error\n"); + return 0; + } + return 0; +} + +static bool light_i2s_8ch_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case I2S_IISEN: + case I2S_FUNCMODE: + case I2S_IISCNF_IN: + case I2S_FSSTA: + case I2S_IISCNF_OUT: + case I2S_DMACR: + return true; + default: + return false; + } +} + +static bool light_i2s_8ch_rd_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case I2S_IISEN: + case I2S_FUNCMODE: + case I2S_IISCNF_IN: + case I2S_FSSTA: + case I2S_IISCNF_OUT: + case I2S_DMACR: + return true; + default: + return false; + } +} + +static const struct regmap_config light_i2s_8ch_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = I2S_DR4, + .writeable_reg = light_i2s_8ch_wr_reg, + .readable_reg = light_i2s_8ch_rd_reg, + .cache_type = REGCACHE_FLAT, +}; + +static int light_audio_pinconf_set(struct device *dev, unsigned int pin_id, unsigned int val) +{ + struct light_i2s_priv *priv = dev_get_drvdata(dev); + unsigned int shift; + unsigned int mask = 0; + + if(!priv->audio_pin_regmap) { + return 0; + } + + priv->cfg_off = 0xC; + + shift = (((pin_id-25) % 2) << 4); + mask |= (0xFFFF << shift); + val = (val << shift); + + return regmap_update_bits(priv->audio_pin_regmap, + LIGHT_AUDIO_PAD_CONFIG(pin_id),mask, val); +} + +static int light_audio_pinctrl(struct device *dev) +{ + return 0; +} + +static int light_i2s_8ch_runtime_suspend(struct device *dev) +{ + struct light_i2s_priv *priv = dev_get_drvdata(dev); + + if(!priv->regmap) { + return 0; + } + + regcache_cache_only(priv->regmap, true); + clk_disable_unprepare(priv->clk); + + return 0; +} + +static int light_i2s_8ch_runtime_resume(struct device *dev) +{ + struct light_i2s_priv *priv = dev_get_drvdata(dev); + int ret; + + if(!priv->regmap) { + return 0; + } + + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(priv->dev, "clock enable failed %d\n", ret); + return ret; + } + + regcache_cache_only(priv->regmap, false); + + return ret; +} + +static const struct of_device_id light_i2s_8ch_of_match[] = { + { .compatible = "light,light-i2s-8ch"}, + {}, +}; +MODULE_DEVICE_TABLE(of, light_i2s_8ch_of_match); + +struct light_i2s_priv *host_priv; + +static int light_audio_i2s_8ch_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + + const char *sprop; + const uint32_t *iprop; + struct light_i2s_priv *priv; + struct resource *res; + struct device *dev = &pdev->dev; + unsigned int irq; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), + GFP_KERNEL); + + if (!priv) + return -ENOMEM; + + priv->dev = dev; + + sprop = of_get_property(np, "light,mode", NULL); + if (sprop) { + if (!strcmp(sprop, "i2s-master")) + priv->dai_fmt = SND_SOC_DAIFMT_I2S; + else + printk("mode is not i2s-master"); + } + + sprop = of_get_property(np, "light,sel", NULL); + if (sprop) { + strcpy(priv->name, sprop); + } + + iprop = of_get_property(np, "light,dma_maxburst", NULL); + if (iprop) + priv->dma_maxburst = be32_to_cpup(iprop); + else + priv->dma_maxburst = 8; + + dev_set_drvdata(&pdev->dev, priv); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if(i2s_8ch_probe_flag) { + printk("i2s_8ch already probe\n"); + priv->regs = NULL; + priv->regmap = NULL; + priv->audio_cpr_regmap = NULL; + } else { + printk("i2s_8ch probing\n"); + i2s_8ch_probe_flag = 1; + host_priv = priv; + + priv->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->regs)) + return PTR_ERR(priv->regs); + + priv->regmap = devm_regmap_init_mmio(&pdev->dev, priv->regs, + &light_i2s_8ch_regmap_config); + if (IS_ERR(priv->regmap)) { + dev_err(&pdev->dev, + "Failed to initialise managed register map\n"); + return PTR_ERR(priv->regmap); + } + + priv->audio_cpr_regmap = syscon_regmap_lookup_by_phandle(np, "audio-cpr-regmap"); + if (IS_ERR(priv->audio_cpr_regmap)) { + dev_err(dev, "cannot find regmap for audio cpr register\n"); + return -EINVAL; + } + + // enable i2s sync + light_audio_cpr_set(priv, CPR_PERI_CTRL_REG, CPR_VAD_I2SIN_SYNC_MSK, CPR_VAD_I2SIN_SYNC_EN); + + priv->clk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + pm_runtime_enable(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) { + ret = light_i2s_8ch_runtime_resume(&pdev->dev); + if (ret) + goto err_pm_disable; + } + + irq = platform_get_irq(pdev, 0); + + if (!res || (int)irq <= 0) { + dev_err(&pdev->dev, "Not enough light platform resources.\n"); + return -ENODEV; + } + } + + priv->audio_pin_regmap = NULL; + + priv->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + priv->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + priv->dma_params_tx.maxburst = priv->dma_maxburst; + priv->dma_params_rx.maxburst = priv->dma_maxburst; + + if (!strcmp(priv->name, AUDIO_I2S_8CH_SD0)) { + priv->dma_params_tx.addr = res->start + I2S_DR; + priv->dma_params_rx.addr = res->start + I2S_DR; + } else if (!strcmp(priv->name, AUDIO_I2S_8CH_SD1)) { + priv->dma_params_tx.addr = res->start + I2S_DR1; + priv->dma_params_rx.addr = res->start + I2S_DR1; + } else if (!strcmp(priv->name, AUDIO_I2S_8CH_SD2)) { + priv->dma_params_tx.addr = res->start + I2S_DR2; + priv->dma_params_rx.addr = res->start + I2S_DR2; + } else if (!strcmp(priv->name, AUDIO_I2S_8CH_SD3)) { + priv->dma_params_tx.addr = res->start + I2S_DR3; + priv->dma_params_rx.addr = res->start + I2S_DR3; + } + + light_pcm_probe(pdev, priv); + + ret = devm_snd_soc_register_component(&pdev->dev, &light_i2s_8ch_soc_component, + light_i2s_8ch_soc_dai, ARRAY_SIZE(light_i2s_8ch_soc_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "cannot snd component register\n"); + goto err_pm_disable; + } + + return ret; + +err_pm_disable: + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static int light_i2s_8ch_remove(struct platform_device *pdev) +{ + struct light_i2s_priv *priv = dev_get_drvdata(&pdev->dev); + + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + light_i2s_8ch_runtime_suspend(&pdev->dev); + + clk_disable_unprepare(priv->clk); + + return 0; +} + +static const struct dev_pm_ops light_i2s_8ch_pm_ops = { + SET_RUNTIME_PM_OPS(light_i2s_8ch_runtime_suspend, light_i2s_8ch_runtime_resume, + NULL) +}; + +static struct platform_driver light_i2s_8ch_driver = { + .driver = { + .name = "light-pcm-audio-8ch", + .pm = &light_i2s_8ch_pm_ops, + .of_match_table = light_i2s_8ch_of_match, + }, + .probe = light_audio_i2s_8ch_probe, + .remove = light_i2s_8ch_remove, +}; + +module_platform_driver(light_i2s_8ch_driver); + +MODULE_AUTHOR("shuofeng.ren "); +MODULE_DESCRIPTION("Thead Light audio driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/thead/light-i2s.c b/sound/soc/thead/light-i2s.c index 31c80cf5f..250980fcc 100644 --- a/sound/soc/thead/light-i2s.c +++ b/sound/soc/thead/light-i2s.c @@ -18,6 +18,7 @@ #include #include "light-i2s.h" #include "light-pcm.h" +#include "light-audio-cpr.h" #include #include #include @@ -54,6 +55,10 @@ static u32 light_special_sample_rates[] = { 11025, 22050, 44100, 88200 }; static int light_audio_cpr_set(struct light_i2s_priv *chip, unsigned int cpr_off, unsigned int mask, unsigned int val) { + if(!chip->audio_cpr_regmap) { + return 0; + } + return regmap_update_bits(chip->audio_cpr_regmap, cpr_off, mask, val); } @@ -62,6 +67,7 @@ static void light_i2s_set_div_sclk(struct light_i2s_priv *chip, u32 sample_rate, { u32 div; u32 div0; + u32 cpr_div = (IIS_SRC_CLK/AUDIO_IIS_SRC0_CLK)-1; int i; u32 i2s_src_clk = 0; @@ -105,6 +111,7 @@ static void light_i2s_set_div_sclk(struct light_i2s_priv *chip, u32 sample_rate, div0 = (div + div % sample_rate) / sample_rate / div_val; writel(div0, chip->regs + I2S_DIV0_LEVEL); + light_audio_cpr_set(chip, CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV0_SEL_MSK, CPR_AUDIO_DIV0_SEL(cpr_div)); } static inline void light_snd_txctrl(struct light_i2s_priv *chip, bool on) @@ -159,7 +166,8 @@ static void light_i2s_dai_shutdown(struct snd_pcm_substream *substream, { struct light_i2s_priv *i2s_private = snd_soc_dai_get_drvdata(dai); - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) light_snd_rxctrl(i2s_private, 0); clk_disable_unprepare(i2s_private->clk); @@ -275,7 +283,7 @@ static int light_i2s_dai_hw_params(struct snd_pcm_substream *substream, struct s len = 32; break; default: - pr_err("Unknown data format\n"); + pr_err("Unknown data format: %d\n", params_format(params)); return -EINVAL; } @@ -371,7 +379,7 @@ static int light_hdmi_dai_hw_params(struct snd_pcm_substream *substream, struct len = 24; break; default: - pr_err("Unknown data format\n"); + pr_err("Unknown data format: %d\n", params_format(params)); return -EINVAL; } @@ -459,7 +467,7 @@ static struct snd_soc_dai_driver light_i2s_soc_dai[] = { .name = "light-hdmi-dai", .playback = { .rates = LIGHT_RATES, - .formats = LIGHT_FMTS, + .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, .channels_min = 1, .channels_max = 2, }, @@ -669,6 +677,9 @@ static int light_audio_i2s_probe(struct platform_device *pdev) dev_err(&pdev->dev, "cannot find regmap for audio cpr register\n"); } else light_audio_cpr_set(i2s_priv, CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV1_SEL_MSK, CPR_AUDIO_DIV1_SEL(5)); + + // enable i2s sync + light_audio_cpr_set(i2s_priv, CPR_PERI_CTRL_REG, CPR_I2S_SYNC_MSK, CPR_I2S_SYNC_EN); } pm_runtime_enable(&pdev->dev); diff --git a/sound/soc/thead/light-i2s.h b/sound/soc/thead/light-i2s.h index f9dfd4416..a8efe74f5 100644 --- a/sound/soc/thead/light-i2s.h +++ b/sound/soc/thead/light-i2s.h @@ -48,9 +48,6 @@ #define I2S_DR3 0x068 /* CH3_Data Register */ #define I2S_DR4 0x06C /* CH4_Data Register */ -#define CPR_PERI_DIV_SEL_REG 0x004 /*audio sys i2s clock div Register*/ -#define CPR_PERI_CLK_SEL_REG 0x008 /*audio sys i2s clock selection Register*/ - /* IISEN , offset: 0x00 */ #define IISEN_I2SEN_POS (0U) #define IISEN_I2SEN_MSK (0x1U << IISEN_I2SEN_POS) @@ -459,30 +456,6 @@ #define RXFIFO_IRQ_TH (0x20U) #define I2S_MAX_FIFO (0x20U) -/* AUDIO SYS DIV SEL REG, offset: 0x4 */ -#define CPR_AUDIO_DIV1_SEL_POS (12U) -#define CPR_AUDIO_DIV1_SEL_MSK (0x1FU << CPR_AUDIO_DIV1_SEL_POS) -#define CPR_AUDIO_DIV1_SEL(X) (X << CPR_AUDIO_DIV1_SEL_POS) - -/* AUDIO SYS CLK SEL REG, offset: 0x8 */ -#define CPR_I2S0_SRC_SEL_POS (0U) -#define CPR_I2S0_SRC_SEL_MSK (0x3U << CPR_I2S0_SRC_SEL_POS) -#define CPR_I2S0_SRC_SEL(X) (X << CPR_I2S0_SRC_SEL_POS) -#define CPR_I2S0_SRC_SEL_24M (0x1U << AUDIOSYS_I2S0_SRC_SEL_POS) -#define CPR_I2S0_SRC_SEL_AUDIO_DIVCLK1 (0x2U << AUDIOSYS_I2S0_SRC_SEL_POS) - -#define CPR_I2S1_SRC_SEL_POS (4U) -#define CPR_I2S1_SRC_SEL_MSK (0x3U << CPR_I2S1_SRC_SEL_POS) -#define CPR_I2S1_SRC_SEL(X) (X << CPR_I2S1_SRC_SEL_POS) -#define CPR_I2S1_SRC_SEL_24M (0x1U << AUDIOSYS_I2S1_SRC_SEL_POS) -#define CPR_I2S1_SRC_SEL_AUDIO_DIVCLK1 (0x2U << AUDIOSYS_I2S1_SRC_SEL_POS) - -#define CPR_I2S2_SRC_SEL_POS (8U) -#define CPR_I2S2_SRC_SEL_MSK (0x3U << CPR_I2S2_SRC_SEL_POS) -#define CPR_I2S2_SRC_SEL(X) (X << CPR_I2S2_SRC_SEL_POS) -#define CPR_I2S2_SRC_SEL_24M (0x1U << AUDIOSYS_I2S2_SRC_SEL_POS) -#define CPR_I2S2_SRC_SEL_AUDIO_DIVCLK1 (0x2U << AUDIOSYS_I2S2_SRC_SEL_POS) - struct light_i2s_priv { void __iomem *base; phys_addr_t phys; diff --git a/sound/soc/thead/light-spdif.c b/sound/soc/thead/light-spdif.c new file mode 100644 index 000000000..76b6955ad --- /dev/null +++ b/sound/soc/thead/light-spdif.c @@ -0,0 +1,454 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "light-pcm.h" +#include "light-spdif.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define LIGHT_RATES SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 + +static int light_spdif_dai_probe(struct snd_soc_dai *dai) +{ + struct light_spdif_priv *priv = snd_soc_dai_get_drvdata(dai); + + if (priv) { + snd_soc_dai_init_dma_data(dai, &priv->dma_params_tx, &priv->dma_params_rx); + } else { + return -EIO; + } + + return 0; +} + +static int light_spdif_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct light_spdif_priv *priv = snd_soc_dai_get_drvdata(dai); + + pm_runtime_get_sync(dai->dev); + regmap_update_bits(priv->regmap, SPDIF_EN, + SPDIF_SPDIFEN_MSK, SPDIF_SPDIFEN_SEL(1)); + atomic_inc(&priv->spdif_ref_cnt); + + return 0; +} + +static void light_spdif_snd_txctrl(struct light_spdif_priv *priv, char on) +{ + unsigned int reg[24]; + int i; + regmap_update_bits(priv->regmap, SPDIF_TX_DMA_EN, + SPDIF_TDMA_EN_MSK, SPDIF_TDMA_EN_SEL(on)); + regmap_update_bits(priv->regmap, SPDIF_TX_EN, + SPDIF_TXEN_MSK, SPDIF_TXEN_SEL(on)); + + return; +} + +static void light_spdif_snd_rxctrl(struct light_spdif_priv *priv, char on) +{ + + regmap_update_bits(priv->regmap, SPDIF_RX_DMA_EN, + SPDIF_RDMA_EN_MSK, SPDIF_RDMA_EN_SEL(on)); + regmap_update_bits(priv->regmap, SPDIF_RX_EN, + SPDIF_RXEN_MSK, SPDIF_RXEN_SEL(on)); + + return; +} + +static void light_spdif_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct light_spdif_priv *priv = snd_soc_dai_get_drvdata(dai); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + light_spdif_snd_rxctrl(priv, 0); + else + light_spdif_snd_txctrl(priv, 0); + + atomic_dec(&priv->spdif_ref_cnt); + if (atomic_read(&priv->spdif_ref_cnt) == 0) { + regmap_update_bits(priv->regmap, SPDIF_EN, + SPDIF_SPDIFEN_MSK, SPDIF_SPDIFEN_SEL(0)); + } + pm_runtime_put(dai->dev); +} + +static int light_spdif_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) +{ + int ret = 0; + struct light_spdif_priv *priv = snd_soc_dai_get_drvdata(dai); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + + switch(cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (tx) + light_spdif_snd_txctrl(priv, 1); + else + light_spdif_snd_rxctrl(priv, 1); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (tx) { + dmaengine_terminate_async(snd_dmaengine_pcm_get_chan(substream)); // work around for DMAC stop issue + light_spdif_snd_txctrl(priv, 0); + } + else + light_spdif_snd_rxctrl(priv, 0); + break; + default: + return -EINVAL; + } + + return ret; +} + +static u32 light_special_sample_rates[] = { 44100, 88200 }; +#define AUDIO_DIVCLK0 98304000 // 49152000 +#define AUDIO_DIVCLK1 135475200 + +static int light_spdif_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct light_spdif_priv *priv = snd_soc_dai_get_drvdata(dai); + u32 datawidth, chn_num, i; + u32 sample_rate = params_rate(params); + bool is_divclk1 = false; //audio_divclk1 for 44.1k...etc. audio_divclk0 for 48k....etc + u32 src_clk, tx_div, rx_div; + + switch (params_channels(params)) { + case 1: + chn_num = SPDIF_TX_DATAMODE_1CH; + break; + case 2: + chn_num = SPDIF_TX_DATAMODE_2CH; + break; + default: + dev_err(priv->dev, "unsupported channel num\n"); + return -EINVAL; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + datawidth = SPDIF_TX_DATAMODE_16BIT_PACKED; + break; + case SNDRV_PCM_FORMAT_S20_LE: + datawidth = SPDIF_TX_DATAMODE_20BIT; + break; + case SNDRV_PCM_FORMAT_S24_LE: + datawidth = SPDIF_TX_DATAMODE_24BIT; + break; + default: + dev_err(priv->dev, "unsupported data format\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(light_special_sample_rates); i++) { + if (light_special_sample_rates[i] == sample_rate) { + is_divclk1 = true; + break; + } + } + + if (is_divclk1 == false) { // audio_divclk0=98304000 for 48k + regmap_update_bits(priv->audio_cpr_regmap, + CPR_PERI_CLK_SEL_REG, CPR_SPDIF_SRC_SEL_MSK, CPR_SPDIF_SRC_SEL(2)); + src_clk = AUDIO_DIVCLK0; + } else { // audio_divclk1=135475200 for 44.1k + regmap_update_bits(priv->audio_cpr_regmap, + CPR_PERI_CLK_SEL_REG, CPR_SPDIF_SRC_SEL_MSK, CPR_SPDIF_SRC_SEL(1)); + src_clk = AUDIO_DIVCLK1; + } + //printk("selected src_clk=%d substream->stream=%d sample_rate=%d\n", src_clk, substream->stream, sample_rate); + regmap_update_bits(priv->regmap, SPDIF_EN, + SPDIF_SPDIFEN_MSK, SPDIF_SPDIFEN_SEL(1)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + tx_div = src_clk / (sample_rate * (32 * 2) * 2); + tx_div = tx_div / 2 - 1; + + regmap_update_bits(priv->regmap, SPDIF_TX_CTL, + SPDIF_TX_DIV_MSK, SPDIF_TX_DIV_SEL(tx_div)); + regmap_update_bits(priv->regmap, SPDIF_TX_CTL, + SPDIF_TX_DIV_BYPASS_MSK, SPDIF_TX_DIV_BYPASS_SEL(1)); + regmap_update_bits(priv->regmap, SPDIF_TX_CTL, + SPDIF_TX_CH_SEL_MSK, SPDIF_TX_CH_SEL_SEL(chn_num)); + regmap_update_bits(priv->regmap, SPDIF_TX_CTL, + SPDIF_TX_DATAMODE_MSK, SPDIF_TX_DATAMODE_SEL(datawidth)); + // Channel Status + regmap_update_bits(priv->regmap, SPDIF_TX_CS_A, + SPDIF_TX_T_FS_SEL_MSK, SPDIF_TX_T_FS_SEL_SEL(2)); // 2 for 48k + regmap_update_bits(priv->regmap, SPDIF_TX_CS_A, + SPDIF_TX_T_CH_NUM_MSK, SPDIF_TX_T_CH_NUM_SEL(1)); // Left in 2 channel format + regmap_update_bits(priv->regmap, SPDIF_TX_CS_B, + SPDIF_TX_T_B_FS_SEL_MSK, SPDIF_TX_T_B_FS_SEL_SEL(2)); // 2 for 48k + regmap_update_bits(priv->regmap, SPDIF_TX_CS_B, + SPDIF_TX_T_B_CH_NUM_MSK, SPDIF_TX_T_B_CH_NUM_SEL(2)); // Right in 2 channel format + } else { + regmap_update_bits(priv->regmap, SPDIF_RX_CTL, + SPDIF_RX_DIV_MSK, SPDIF_RX_DIV_SEL(0)); + regmap_update_bits(priv->regmap, SPDIF_RX_CTL, + SPDIF_RX_DIV_BYPASS_MSK, SPDIF_RX_DIV_BYPASS_SEL(0)); // spdif_rx_clk = src_clk + regmap_update_bits(priv->regmap, SPDIF_RX_CTL, + SPDIF_RX_DATAMODE_MSK, SPDIF_RX_DATAMODE_SEL(datawidth)); + regmap_update_bits(priv->regmap, SPDIF_RX_DMA_TH, + SPDIF_RDMA_TH_MSK, SPDIF_RDMA_TH_SEL(8)); + } + + return 0; +} + +static const struct snd_soc_dai_ops light_spdif_dai_ops = { + .startup = light_spdif_dai_startup, + .shutdown = light_spdif_dai_shutdown, + .trigger = light_spdif_dai_trigger, + .hw_params = light_spdif_dai_hw_params, +}; + +static struct snd_soc_dai_driver light_spdif_soc_dai = { + .probe = light_spdif_dai_probe, + .playback = { + .stream_name = "Playback", + .rates = LIGHT_RATES, + .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_S16_LE, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Capture", + .rates = LIGHT_RATES, + .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S20_LE, + .channels_min = 2, + .channels_max = 2, + }, + .ops = &light_spdif_dai_ops, + .symmetric_rates = 1, +}; + +static const struct snd_soc_component_driver light_spdif_soc_component = { + .name = "light_spdif", +}; + +static void light_spdif_pinctrl(struct light_spdif_priv *priv) +{ + //GPIO_SEL AUDIO_PA21~24 + regmap_update_bits(priv->audio_pin_regmap, + 0x0,0x1E00000, 0x1E00000); + //MUX + regmap_update_bits(priv->audio_pin_regmap, + 0x8,0x3FC00, 0x15400); + //strength + regmap_update_bits(priv->audio_pin_regmap, + 0x38,0xF000F, 0x70007); // AUDIO_PA22 SPDIF0_DOUT / AUDIO_PA23 SPDIF1_DOUT + return; +} + +static const struct regmap_config light_spdif_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = SPDIF_RX_USER_B5, + .cache_type = REGCACHE_FLAT, +}; + +static int light_spdif_runtime_suspend(struct device *dev) +{ + struct light_spdif_priv *priv = dev_get_drvdata(dev); + + regcache_cache_only(priv->regmap, true); + clk_disable_unprepare(priv->clk); + + return 0; +} + +static int light_spdif_runtime_resume(struct device *dev) +{ + struct light_spdif_priv *priv = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(priv->dev, "clock enable failed %d\n", ret); + return ret; + } + + regcache_cache_only(priv->regmap, false); + + return ret; +} + +static const struct of_device_id light_spdif_of_match[] = { + { .compatible = "light,light-spdif"}, + {}, +}; +MODULE_DEVICE_TABLE(of, light_spdif_of_match); + +irqreturn_t spdif_interrupt(int irq, void* dev_id) +{ + struct light_spdif_priv* priv = (struct light_spdif_priv*)dev_id; + return IRQ_HANDLED; +} + +static int light_spdif_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const char *sprop; + const uint32_t *iprop; + struct light_spdif_priv *priv; + struct resource *res; + struct device *dev = &pdev->dev; + unsigned int irq; + int data_register, ret = 0; + + priv = devm_kzalloc(&pdev->dev, sizeof(struct light_spdif_priv), GFP_KERNEL); + if (!priv) { + return -ENOMEM; + } + + priv->dev = dev; + + iprop = of_get_property(np, "light,dma_maxburst", NULL); + if (iprop) + priv->dma_maxburst = be32_to_cpup(iprop); + else + priv->dma_maxburst = 8; + + dev_set_drvdata(dev, priv); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + priv->clk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + priv->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->regs)) { + return PTR_ERR(priv->regs); + } + + priv->regmap = devm_regmap_init_mmio(dev, priv->regs, + &light_spdif_regmap_config); + if (IS_ERR(priv->regmap)) { + dev_err(dev, "Failed to initialise managed register map\n"); + return PTR_ERR(priv->regmap); + } + + priv->audio_pin_regmap = syscon_regmap_lookup_by_phandle(np, "audio-pin-regmap"); + if (IS_ERR(priv->audio_pin_regmap)) { + dev_err(dev, "cannot find regmap for audio system register\n"); + return -EINVAL; + } else { + //light_spdif_pinctrl(priv); + } + + priv->audio_cpr_regmap = syscon_regmap_lookup_by_phandle(np, "audio-cpr-regmap"); + if (IS_ERR(priv->audio_cpr_regmap)) { + dev_err(dev, "cannot find regmap for audio cpr register\n"); + return -EINVAL; + } + //AUDIO_DIV1 set to 1/6. 812.8512MHz / 6 = 135.4752MHz + regmap_update_bits(priv->audio_cpr_regmap, + CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV1_SEL_MSK, CPR_AUDIO_DIV1_SEL(5)); + regmap_update_bits(priv->audio_cpr_regmap, + CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV1_CG_MSK, CPR_AUDIO_DIV1_CG(1)); + //AUDIO_DIV0 set to 1/3. 294.912MHz / 3 = 98304000Hz + regmap_update_bits(priv->audio_cpr_regmap, + CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV0_SEL_MSK, CPR_AUDIO_DIV0_SEL(2)); // 2=98304000 5=49152000 + regmap_update_bits(priv->audio_cpr_regmap, + CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV0_CG_MSK, CPR_AUDIO_DIV0_CG(1)); + //enable spdif0/1 sync + regmap_update_bits(priv->audio_cpr_regmap, + CPR_PERI_CTRL_REG, CPR_SPDIF_SYNC_MSK, CPR_SPDIF_SYNC_EN); + + pm_runtime_enable(&pdev->dev); + pm_runtime_resume_and_get(&pdev->dev); // clk gate is enabled by hardware as default register value + pm_runtime_put_sync(&pdev->dev); + + priv->irq = platform_get_irq(pdev, 0); + if (priv->irq== 0) { + dev_err(dev, "could not map IRQ.\n"); + return -ENXIO; + } + + //ret = request_irq(priv->irq , spdif_interrupt, + // IRQF_SHARED|IRQF_TRIGGER_RISING, "AUDIO_TDM_IRQ", (char *)priv); + //if (ret) { + // dev_err(dev, "%s[%d]:request irq error!\n", __func__, __LINE__); + // return ret; + //} + + priv->dma_params_tx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + priv->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + priv->dma_params_tx.maxburst = priv->dma_maxburst; + priv->dma_params_rx.maxburst = priv->dma_maxburst; + priv->dma_params_tx.addr = res->start + SPDIF_TX_FIFO_DR; + priv->dma_params_rx.addr = res->start + SPDIF_RX_FIFO_DR; + + ret = light_pcm_dma_init(pdev, LIGHT_TDM_DMABUF_SIZE); + if (ret) { + dev_err(dev, "light_pcm_dma_init error\n"); + return -EIO; + } + + ret = devm_snd_soc_register_component(dev, &light_spdif_soc_component, + &light_spdif_soc_dai, 1); + if (ret < 0) { + dev_err(&pdev->dev, "cannot snd component register\n"); + } + + return ret; +} + +static int light_spdif_remove(struct platform_device *pdev) +{ + struct light_spdif_priv *priv = dev_get_drvdata(&pdev->dev); + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + light_spdif_runtime_suspend(&pdev->dev); + clk_disable_unprepare(priv->clk); + return 0; +} + +static const struct dev_pm_ops light_spdif_pm_ops = { + SET_RUNTIME_PM_OPS(light_spdif_runtime_suspend, light_spdif_runtime_resume, NULL) +}; + +static struct platform_driver light_spdif_driver = { + .driver = { + .name = "light-spdif-audio", + .pm = &light_spdif_pm_ops, + .of_match_table = light_spdif_of_match, + }, + .probe = light_spdif_probe, + .remove = light_spdif_remove, +}; + +module_platform_driver(light_spdif_driver); + +MODULE_AUTHOR("nanli.yd "); +MODULE_DESCRIPTION("Thead Light spdif driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/thead/light-spdif.h b/sound/soc/thead/light-spdif.h new file mode 100644 index 000000000..c390ad85f --- /dev/null +++ b/sound/soc/thead/light-spdif.h @@ -0,0 +1,209 @@ +#ifndef _LIGHT_SPDIF_H_ +#define _LIGHT_SPDIF_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "light-pcm.h" +#include + +#define SPDIF_EN 0x00 +#define SPDIF_TX_EN 0x04 +#define SPDIF_TX_CTL 0x08 +#define SPDIF_TX_CS_A 0x0c +#define SPDIF_TX_USER_A0 0x10 +#define SPDIF_TX_USER_A1 0x14 +#define SPDIF_TX_USER_A2 0x18 +#define SPDIF_TX_USER_A3 0x1C +#define SPDIF_TX_USER_A4 0x20 +#define SPDIF_TX_USER_A5 0x24 +#define SPDIF_TX_FIFO_DR 0x28 +#define SPDIF_TX_FIFO_TH 0x2C +#define SPDIF_TX_FIFO_DL 0x30 +#define SPDIF_TX_DMA_EN 0x34 +#define SPDIF_TX_DMA_TH 0x38 +#define SPDIF_SR 0x3C +#define SPDIF_IMR 0x40 +#define SPDIF_ISR 0x44 +#define SPDIF_RISR 0x48 +#define SPDIF_ICR 0x4C +#define SPDIF_RX_EN 0x50 +#define SPDIF_RX_CTL 0x54 +#define SPDIF_RX_CS_A 0x58 +#define SPDIF_RX_USER_A0 0x5C +#define SPDIF_RX_USER_A1 0x60 +#define SPDIF_RX_USER_A2 0x64 +#define SPDIF_RX_USER_A3 0x68 +#define SPDIF_RX_USER_A4 0x6C +#define SPDIF_RX_USER_A5 0x70 +#define SPDIF_RX_FIFO_DR 0x74 +#define SPDIF_RX_FIFO_TH 0x78 +#define SPDIF_RX_FIFO_DL 0x7C +#define SPDIF_RX_DMA_EN 0x80 +#define SPDIF_RX_DMA_TH 0x84 +#define SPDIF_TX_CS_B 0x88 +#define SPDIF_TX_USER_B0 0x8C +#define SPDIF_TX_USER_B1 0x90 +#define SPDIF_TX_USER_B2 0x94 +#define SPDIF_TX_USER_B3 0x98 +#define SPDIF_TX_USER_B4 0x9C +#define SPDIF_TX_USER_B5 0xa0 +#define SPDIF_RX_CS_B 0xa4 +#define SPDIF_RX_USER_B0 0xa8 +#define SPDIF_RX_USER_B1 0xaC +#define SPDIF_RX_USER_B2 0xb0 +#define SPDIF_RX_USER_B3 0xb4 +#define SPDIF_RX_USER_B4 0xb8 +#define SPDIF_RX_USER_B5 0xbC + +/* SPDIF_EN */ +#define SPDIF_SPDIFEN_POS (0U) +#define SPDIF_SPDIFEN_MSK (0x1U << SPDIF_SPDIFEN_POS) +#define SPDIF_SPDIFEN_SEL(X) (X << SPDIF_SPDIFEN_POS) + +/* SPDIF_TX_EN */ +#define SPDIF_TXEN_POS (0U) +#define SPDIF_TXEN_MSK (0x1U << SPDIF_TXEN_POS) +#define SPDIF_TXEN_SEL(X) (X << SPDIF_TXEN_POS) + +/* SPDIF_TX_CTL */ +#define SPDIF_TX_DIV_POS (9U) +#define SPDIF_TX_DIV_MSK (0x7FU << SPDIF_TX_DIV_POS) +#define SPDIF_TX_DIV_SEL(X) (X << SPDIF_TX_DIV_POS) +#define SPDIF_TX_DIV_BYPASS_POS (8U) +#define SPDIF_TX_DIV_BYPASS_MSK (0x1U << SPDIF_TX_DIV_BYPASS_POS) +#define SPDIF_TX_DIV_BYPASS_SEL(X) (X << SPDIF_TX_DIV_BYPASS_POS) +#define SPDIF_TX_CH_SEL_POS (4U) +#define SPDIF_TX_CH_SEL_MSK (0x1U << SPDIF_TX_CH_SEL_POS) +#define SPDIF_TX_CH_SEL_SEL(X) (X << SPDIF_TX_CH_SEL_POS) +#define SPDIF_TX_DATAMODE_POS (0U) +#define SPDIF_TX_DATAMODE_MSK (0x3U << SPDIF_TX_DATAMODE_POS) +#define SPDIF_TX_DATAMODE_SEL(X) (X << SPDIF_TX_DATAMODE_POS) + +#define SPDIF_TX_DATAMODE_2CH 0x0 +#define SPDIF_TX_DATAMODE_1CH 0x1 +#define SPDIF_TX_DATAMODE_16BIT_PACKED 0x3 +#define SPDIF_TX_DATAMODE_16BIT 0x2 +#define SPDIF_TX_DATAMODE_20BIT 0x1 +#define SPDIF_TX_DATAMODE_24BIT 0x0 + +/* SPDIF_TX_CS_A */ +#define SPDIF_TX_T_FS_SEL_POS (24U) +#define SPDIF_TX_T_FS_SEL_MSK (0xFU << SPDIF_TX_T_FS_SEL_POS) +#define SPDIF_TX_T_FS_SEL_SEL(X) (X << SPDIF_TX_T_FS_SEL_POS) +#define SPDIF_TX_T_CH_NUM_POS (20U) +#define SPDIF_TX_T_CH_NUM_MSK (0xFU << SPDIF_TX_T_CH_NUM_POS) +#define SPDIF_TX_T_CH_NUM_SEL(X) (X << SPDIF_TX_T_CH_NUM_POS) + +/* SPDIF_RX_DMA_TH */ +#define SPDIF_RDMA_TH_POS (0U) +#define SPDIF_RDMA_TH_MSK (0xFU << SPDIF_RDMA_TH_POS) +#define SPDIF_RDMA_TH_SEL(X) (X << SPDIF_RDMA_TH_POS) + +/* SPDIF_TX_CS_B */ +#define SPDIF_TX_T_B_FS_SEL_POS (24U) +#define SPDIF_TX_T_B_FS_SEL_MSK (0xFU << SPDIF_TX_T_B_FS_SEL_POS) +#define SPDIF_TX_T_B_FS_SEL_SEL(X) (X << SPDIF_TX_T_B_FS_SEL_POS) +#define SPDIF_TX_T_B_CH_NUM_POS (20U) +#define SPDIF_TX_T_B_CH_NUM_MSK (0xFU << SPDIF_TX_T_B_CH_NUM_POS) +#define SPDIF_TX_T_B_CH_NUM_SEL(X) (X << SPDIF_TX_T_B_CH_NUM_POS) + +/* SPDIF_TX_DMA_EN */ +#define SPDIF_TDMA_EN_POS (0U) +#define SPDIF_TDMA_EN_MSK (0x1U << SPDIF_TDMA_EN_POS) +#define SPDIF_TDMA_EN_SEL(X) (X << SPDIF_TDMA_EN_POS) + +/* SPDIF_RX_EN */ +#define SPDIF_RXEN_POS (0U) +#define SPDIF_RXEN_MSK (0x1U << SPDIF_RXEN_POS) +#define SPDIF_RXEN_SEL(X) (X << SPDIF_RXEN_POS) + +/* SPDIF_RX_CTL */ +#define SPDIF_RX_DIV_POS (13U) +#define SPDIF_RX_DIV_MSK (0x7FU << SPDIF_RX_DIV_POS) +#define SPDIF_RX_DIV_SEL(X) (X << SPDIF_RX_DIV_POS) +#define SPDIF_RX_DIV_BYPASS_POS (12U) +#define SPDIF_RX_DIV_BYPASS_MSK (0x1U << SPDIF_RX_DIV_BYPASS_POS) +#define SPDIF_RX_DIV_BYPASS_SEL(X) (X << SPDIF_RX_DIV_BYPASS_POS) +#define SPDIF_RX_VALID_EN_POS (8U) +#define SPDIF_RX_VALID_EN_MSK (0x1U << SPDIF_RX_VALID_EN_POS) +#define SPDIF_RX_VALID_EN_SEL(X) (X << SPDIF_RX_VALID_EN_POS) +#define SPDIF_RX_PARITY_EN_POS (4U) +#define SPDIF_RX_PARITY_EN_MSK (0x1U << SPDIF_RX_PARITY_EN_POS) +#define SPDIF_RX_PARITY_EN_SEL(X) (X << SPDIF_RX_PARITY_EN_POS) +#define SPDIF_RX_DATAMODE_POS (0U) +#define SPDIF_RX_DATAMODE_MSK (0x3U << SPDIF_RX_DATAMODE_POS) +#define SPDIF_RX_DATAMODE_SEL(X) (X << SPDIF_RX_DATAMODE_POS) + +/* SPDIF_RX_DMA_EN */ +#define SPDIF_RDMA_EN_POS (0U) +#define SPDIF_RDMA_EN_MSK (0x1U << SPDIF_RDMA_EN_POS) +#define SPDIF_RDMA_EN_SEL(X) (X << SPDIF_RDMA_EN_POS) + + +#define CPR_PERI_DIV_SEL_REG 0x004 /*audio sys clock div Register*/ +#define CPR_PERI_CLK_SEL_REG 0x008 /*audio sys clock selection Register*/ +#define CPR_PERI_CTRL_REG 0x00C /*Peripheral control signal configuration register*/ +#define CPR_IP_CG_REG 0x010 /* ip clock gate register */ + +/* AUDIO SYS DIV SEL REG, offset: 0x4 */ +#define CPR_AUDIO_DIV1_CG_POS (17U) +#define CPR_AUDIO_DIV1_CG_MSK (0x1U << CPR_AUDIO_DIV1_CG_POS) +#define CPR_AUDIO_DIV1_CG(X) (X << CPR_AUDIO_DIV1_CG_POS) +#define CPR_AUDIO_DIV1_SEL_POS (12U) +#define CPR_AUDIO_DIV1_SEL_MSK (0x1FU << CPR_AUDIO_DIV1_SEL_POS) +#define CPR_AUDIO_DIV1_SEL(X) (X << CPR_AUDIO_DIV1_SEL_POS) +#define CPR_AUDIO_DIV0_CG_POS (9U) +#define CPR_AUDIO_DIV0_CG_MSK (0x1U << CPR_AUDIO_DIV0_CG_POS) +#define CPR_AUDIO_DIV0_CG(X) (X << CPR_AUDIO_DIV0_CG_POS) +#define CPR_AUDIO_DIV0_SEL_POS (4U) +#define CPR_AUDIO_DIV0_SEL_MSK (0x1FU << CPR_AUDIO_DIV0_SEL_POS) +#define CPR_AUDIO_DIV0_SEL(X) (X << CPR_AUDIO_DIV0_SEL_POS) +/* CPR_PERI_CLK_SEL_REG 0x008 */ +#define CPR_SPDIF_SRC_SEL_POS (24U) +#define CPR_SPDIF_SRC_SEL_MSK (0x3U << CPR_SPDIF_SRC_SEL_POS) +#define CPR_SPDIF_SRC_SEL(X) (X << CPR_SPDIF_SRC_SEL_POS) +/* PERI_CTRL_REG, Offset: 0xC */ +#define CPR_SPDIF_SYNC_POS (14U) +#define CPR_SPDIF_SYNC_MSK (0x1U << CPR_SPDIF_SYNC_POS) +#define CPR_SPDIF_SYNC_EN (CPR_SPDIF_SYNC_MSK) +/* CPR_IP_CG_REG 0x010 */ +#define CPR_SPDIF0_CG_SEL_POS (23U) +#define CPR_SPDIF0_CG_SEL_MSK (0x1U << CPR_SPDIF0_CG_SEL_POS) +#define CPR_SPDIF0_CG_SEL(X) (X << CPR_SPDIF0_CG_SEL_POS) +#define CPR_SPDIF1_CG_SEL_POS (24U) +#define CPR_SPDIF1_CG_SEL_MSK (0x1U << CPR_SPDIF1_CG_SEL_POS) +#define CPR_SPDIF1_CG_SEL(X) (X << CPR_SPDIF1_CG_SEL_POS) + + +#define LIGHT_TDM_DMABUF_SIZE (64 * 1024) + +struct light_spdif_priv { + void __iomem *regs; + struct regmap *regmap; + struct regmap *audio_pin_regmap; + struct regmap *audio_cpr_regmap; + struct clk *clk; + struct snd_dmaengine_dai_dma_data dma_params_tx; + struct snd_dmaengine_dai_dma_data dma_params_rx; + unsigned int dai_fmt; + u32 dma_maxburst; + struct device *dev; + unsigned int irq; + atomic_t spdif_ref_cnt; +}; + + +#endif diff --git a/sound/soc/thead/light-tdm.c b/sound/soc/thead/light-tdm.c index e8ecd578a..959307d3e 100644 --- a/sound/soc/thead/light-tdm.c +++ b/sound/soc/thead/light-tdm.c @@ -46,7 +46,13 @@ static int light_tdm_dai_probe(struct snd_soc_dai *dai) static int light_tdm_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - return 0; + struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai); + + if (priv->slot_num != 1) { + return 0; + } + + return pm_runtime_get_sync(dai->dev); } static void light_tdm_snd_rxctrl(struct light_tdm_priv *priv, char on) @@ -72,10 +78,15 @@ static void light_tdm_dai_shutdown(struct snd_pcm_substream *substream, { struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai); - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + if (priv->slot_num != 1) { + return; + } + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) light_tdm_snd_rxctrl(priv, 0); - clk_disable_unprepare(priv->clk); + pm_runtime_put(dai->dev); + return; } static int light_tdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) @@ -110,7 +121,6 @@ static int light_tdm_set_fmt_dai(struct snd_soc_dai *dai, unsigned int fmt) return 0; } - printk("%s fmt=%d\n", __func__, fmt); switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: break; @@ -131,8 +141,7 @@ static int light_tdm_set_fmt_dai(struct snd_soc_dai *dai, unsigned int fmt) u32 dmadl; regmap_read(priv->regmap, TDM_TDMCTL, &tdmctl); regmap_read(priv->regmap, TDM_DMADL, &dmadl); - printk("%s TDM_TDMCTL=0x%x TDM_DMADL=0x%x\n", __func__, tdmctl, dmadl); - printk("%s %d\n", __func__, __LINE__); + return 0; } @@ -253,95 +262,15 @@ static const struct snd_soc_dai_ops light_tdm_dai_ops = { .hw_params = light_tdm_dai_hw_params, }; -static struct snd_soc_dai_driver light_tdm_soc_dai[] = { - { - .probe = light_tdm_dai_probe, - .name = "light-tdm-dai-slot1", - .capture = { - .rates = LIGHT_RATES, - .formats = LIGHT_FMTS, - .channels_min = 1, - .channels_max = 1, - }, - .ops = &light_tdm_dai_ops, +static struct snd_soc_dai_driver light_tdm_soc_dai = { + .probe = light_tdm_dai_probe, + .capture = { + .rates = LIGHT_RATES, + .formats = LIGHT_FMTS, + .channels_min = 1, + .channels_max = 1, }, - { - .probe = light_tdm_dai_probe, - .name = "light-tdm-dai-slot2", - .capture = { - .rates = LIGHT_RATES, - .formats = LIGHT_FMTS, - .channels_min = 1, - .channels_max = 1, - }, - .ops = &light_tdm_dai_ops, - }, - { - .probe = light_tdm_dai_probe, - .name = "light-tdm-dai-slot3", - .capture = { - .rates = LIGHT_RATES, - .formats = LIGHT_FMTS, - .channels_min = 1, - .channels_max = 1, - }, - .ops = &light_tdm_dai_ops, - }, - { - .probe = light_tdm_dai_probe, - .name = "light-tdm-dai-slot4", - .capture = { - .rates = LIGHT_RATES, - .formats = LIGHT_FMTS, - .channels_min = 1, - .channels_max = 1, - }, - .ops = &light_tdm_dai_ops, - }, - { - .probe = light_tdm_dai_probe, - .name = "light-tdm-dai-slot5", - .capture = { - .rates = LIGHT_RATES, - .formats = LIGHT_FMTS, - .channels_min = 1, - .channels_max = 1, - }, - .ops = &light_tdm_dai_ops, - }, - { - .probe = light_tdm_dai_probe, - .name = "light-tdm-dai-slot6", - .capture = { - .rates = LIGHT_RATES, - .formats = LIGHT_FMTS, - .channels_min = 1, - .channels_max = 1, - }, - .ops = &light_tdm_dai_ops, - }, - { - .probe = light_tdm_dai_probe, - .name = "light-tdm-dai-slot7", - .capture = { - .rates = LIGHT_RATES, - .formats = LIGHT_FMTS, - .channels_min = 1, - .channels_max = 1, - }, - .ops = &light_tdm_dai_ops, - }, - { - .probe = light_tdm_dai_probe, - .name = "light-tdm-dai-slot8", - .capture = { - .rates = LIGHT_RATES, - .formats = LIGHT_FMTS, - .channels_min = 1, - .channels_max = 1, - }, - .ops = &light_tdm_dai_ops, - }, + .ops = &light_tdm_dai_ops, }; static const struct snd_soc_component_driver light_tdm_soc_component = { @@ -482,11 +411,13 @@ static int light_tdm_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tdm_priv->clk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(tdm_priv->clk)) - return PTR_ERR(tdm_priv->clk); + if (tdm_priv->slot_num == 1) { + tdm_priv->clk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(tdm_priv->clk)) + return PTR_ERR(tdm_priv->clk); + tdm_priv->regs = devm_ioremap_resource(dev, res); if (IS_ERR(tdm_priv->regs)) { return PTR_ERR(tdm_priv->regs); @@ -504,7 +435,7 @@ static int light_tdm_probe(struct platform_device *pdev) dev_err(dev, "cannot find regmap for audio system register\n"); return -EINVAL; } else { - light_tdm_pinctrl(tdm_priv); + //light_tdm_pinctrl(tdm_priv); } tdm_priv->audio_cpr_regmap = syscon_regmap_lookup_by_phandle(np, "audio-cpr-regmap"); @@ -518,22 +449,10 @@ static int light_tdm_probe(struct platform_device *pdev) //AUDIO_DIV0 set to 1/6. 294.912MHz / 6 = 49.152MHz regmap_update_bits(tdm_priv->audio_cpr_regmap, CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV0_SEL_MSK, CPR_AUDIO_DIV0_SEL(5)); - //enable clock gate - regmap_update_bits(tdm_priv->audio_cpr_regmap, - CPR_IP_CG_REG, CPR_TDM_CG_SEL_MSK, CPR_TDM_CG_SEL(1)); pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { - ret = light_tdm_runtime_resume(&pdev->dev); - if (ret) { - pm_runtime_disable(&pdev->dev); - return -EIO; - } - } - - ret = clk_prepare_enable(tdm_priv->clk); - if (ret < 0) - return ret; + pm_runtime_resume_and_get(&pdev->dev); // clk gate is enabled by hardware as default register value + pm_runtime_put_sync(&pdev->dev); tdm_priv->irq = platform_get_irq(pdev, 0); if (tdm_priv->irq== 0) { @@ -590,7 +509,7 @@ static int light_tdm_probe(struct platform_device *pdev) } ret = devm_snd_soc_register_component(dev, &light_tdm_soc_component, - light_tdm_soc_dai, ARRAY_SIZE(light_tdm_soc_dai)); + &light_tdm_soc_dai, 1); if (ret < 0) { dev_err(&pdev->dev, "cannot snd component register\n"); }