From 7d38ead3b432f8e2026c9aa7dc7909a9d2ffab86 Mon Sep 17 00:00:00 2001 From: Han Gao Date: Sun, 30 Jul 2023 05:23:20 +0800 Subject: [PATCH] feat: update SDK1.2.0 Signed-off-by: Han Gao --- arch/riscv/boot/dts/thead/Makefile | 3 +- arch/riscv/boot/dts/thead/fire.dtsi | 11 +- .../boot/dts/thead/light-a-val-audio-hdmi.dts | 35 +- .../boot/dts/thead/light-a-val-audio-tdm.dts | 125 ++++ .../boot/dts/thead/light-a-val-audio.dts | 20 +- .../boot/dts/thead/light-a-val-ddr1G.dts | 2 +- .../boot/dts/thead/light-a-val-ddr2G.dts | 2 +- .../dts/thead/light-a-val-dsi0-hdmi-audio.dts | 71 ++ .../riscv/boot/dts/thead/light-a-val-full.dts | 28 +- .../dts/thead/light-a-val-miniapp-hdmi.dts | 12 + arch/riscv/boot/dts/thead/light-a-val-sec.dts | 2 +- arch/riscv/boot/dts/thead/light-a-val.dts | 51 +- .../boot/dts/thead/light-ant-discrete.dts | 19 +- arch/riscv/boot/dts/thead/light-ant-ref.dts | 32 +- .../boot/dts/thead/light-b-product-ddr1G.dts | 2 +- arch/riscv/boot/dts/thead/light-b-product.dts | 23 +- .../riscv/boot/dts/thead/light-beagle-ref.dts | 19 +- arch/riscv/boot/dts/thead/light-crash.dts | 10 +- arch/riscv/boot/dts/thead/light-emu.dtsi | 2 +- arch/riscv/boot/dts/thead/light-evb.dtsi | 11 +- .../boot/dts/thead/light-lpi4a-ddr2G.dts | 2 +- arch/riscv/boot/dts/thead/light-lpi4a-ref.dts | 22 +- arch/riscv/boot/dts/thead/light-lpi4a-sec.dts | 13 + arch/riscv/boot/dts/thead/light-lpi4a.dts | 9 +- arch/riscv/boot/dts/thead/light.dtsi | 200 +++++- arch/riscv/configs/light_defconfig | 11 + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 24 + drivers/mmc/host/sdhci-of-dwcmshc.c | 10 - drivers/net/ethernet/stmicro/stmmac/Kconfig | 10 + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 9 +- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 231 ++++++- drivers/pinctrl/thead/pinctrl-light.c | 102 ++- drivers/soc/thead/Kconfig | 6 + drivers/soc/thead/Makefile | 1 + drivers/soc/thead/light_event.c | 278 ++++++++ drivers/watchdog/dw_wdt.c | 2 + drivers/watchdog/light_wdt.c | 2 + .../pinctrl/light-fm-audio-pinctrl.h | 38 ++ include/linux/bpf.h | 10 + include/linux/firmware/thead/ipc.h | 1 + include/linux/firmware/thead/light_event.h | 35 + include/uapi/linux/bpf.h | 5 +- kernel/panic.c | 5 + kernel/softirq.c | 3 +- net/bpf/test_run.c | 249 +++++-- net/core/filter.c | 1 + sound/soc/codecs/es7210.c | 589 +++++++++------- sound/soc/codecs/es7210.h | 16 +- sound/soc/codecs/es8156.c | 234 ++----- sound/soc/generic/simple-card-utils.c | 20 +- sound/soc/thead/Makefile | 2 + sound/soc/thead/aw87519_audio.c | 90 ++- sound/soc/thead/aw87519_audio.h | 4 + sound/soc/thead/light-dummy-pcm.c | 96 +++ sound/soc/thead/light-i2s.c | 31 +- sound/soc/thead/light-tdm.c | 629 ++++++++++++++++++ sound/soc/thead/light-tdm.h | 125 ++++ tools/include/uapi/linux/bpf.h | 5 +- tools/lib/bpf/bpf_tracing.h | 31 + tools/testing/selftests/bpf/Makefile | 2 +- tools/testing/selftests/bpf/progs/pyperf.h | 4 + tools/testing/selftests/bpf/progs/pyperf600.c | 11 +- tools/testing/selftests/bpf/test_verifier.c | 4 +- .../selftests/bpf/verifier/ctx_sk_lookup.c | 1 + 64 files changed, 2990 insertions(+), 663 deletions(-) create mode 100644 arch/riscv/boot/dts/thead/light-a-val-audio-tdm.dts create mode 100644 arch/riscv/boot/dts/thead/light-a-val-dsi0-hdmi-audio.dts create mode 100644 arch/riscv/boot/dts/thead/light-lpi4a-sec.dts create mode 100644 drivers/soc/thead/light_event.c create mode 100644 include/dt-bindings/pinctrl/light-fm-audio-pinctrl.h create mode 100644 include/linux/firmware/thead/light_event.h create mode 100644 sound/soc/thead/light-dummy-pcm.c create mode 100644 sound/soc/thead/light-tdm.c create mode 100644 sound/soc/thead/light-tdm.h diff --git a/arch/riscv/boot/dts/thead/Makefile b/arch/riscv/boot/dts/thead/Makefile index 898f5682c..a2d12534b 100644 --- a/arch/riscv/boot/dts/thead/Makefile +++ b/arch/riscv/boot/dts/thead/Makefile @@ -13,7 +13,8 @@ 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-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-dpi0.dtb light-a-val-dpi0-dpi1.dtb +dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio-tdm.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 dtb-$(CONFIG_SOC_THEAD) += light-a-val-khv.dtb diff --git a/arch/riscv/boot/dts/thead/fire.dtsi b/arch/riscv/boot/dts/thead/fire.dtsi index 55020f1dd..3d8c56ce7 100644 --- a/arch/riscv/boot/dts/thead/fire.dtsi +++ b/arch/riscv/boot/dts/thead/fire.dtsi @@ -373,7 +373,7 @@ entry-cnt = <4>; control-reg = <0xff 0xff015004>; control-val = <0x1c>; - csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>; + csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>; }; clint0: clint@ffdc000000 { @@ -1335,8 +1335,7 @@ emmc: sdhci@ffe7080000 { compatible = "snps,dwcmshc-sdhci"; - reg = <0xff 0xe7080000 0x0 0x10000 - 0xff 0xef014060 0x0 0x4>; + reg = <0xff 0xe7080000 0x0 0x10000>; interrupt-parent = <&intc>; interrupts = <62>; interrupt-names = "sdhciirq"; @@ -1346,8 +1345,7 @@ sdhci0: sd@ffe7090000 { compatible = "snps,dwcmshc-sdhci"; - reg = <0xff 0xe7090000 0x0 0x10000 - 0xff 0xef014064 0x0 0x4>; + reg = <0xff 0xe7090000 0x0 0x10000>; interrupt-parent = <&intc>; interrupts = <64>; interrupt-names = "sdhci0irq"; @@ -1357,8 +1355,7 @@ sdhci1: sd@ffe70a0000 { compatible = "snps,dwcmshc-sdhci"; - reg = <0xff 0xe70a0000 0x0 0x10000 - 0xff 0xef014064 0x0 0x4>; + reg = <0xff 0xe70a0000 0x0 0x10000>; interrupt-parent = <&intc>; interrupts = <71>; interrupt-names = "sdhci1irq"; 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 1e1a0b42b..05eeba8a8 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 @@ -5,7 +5,7 @@ /dts-v1/; -#include "light-a-val.dts" +#include "light-a-val-audio.dts" / { display-subsystem { @@ -40,28 +40,6 @@ &lightsound { status = "okay"; - - simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ - reg = <0>; - format = "i2s"; - cpu { - sound-dai = <&i2s0 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 = <&i2s3 0>; - }; - codec { - sound-dai = <&es7210_audio_codec>; - }; - }; simple-audio-card,dai-link@2 { /* I2S - HDMI */ reg = <2>; @@ -77,13 +55,4 @@ &light_i2s { status = "okay"; -}; - -&i2s0 { - status = "okay"; -}; - -&i2s3 { - status = "okay"; -}; - +}; \ 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 new file mode 100644 index 000000000..5f95cab76 --- /dev/null +++ b/arch/riscv/boot/dts/thead/light-a-val-audio-tdm.dts @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + +#include "light-a-val.dts" + +&tdm_slot1 { + status = "okay"; +}; + +&tdm_slot2 { + status = "okay"; +}; + +&tdm_slot3 { + status = "okay"; +}; + +&tdm_slot4 { + status = "okay"; +}; + +&tdm_slot5 { + status = "okay"; +}; + +&tdm_slot6 { + status = "okay"; +}; + +&tdm_slot7 { + status = "okay"; +}; + +&tdm_slot8 { + status = "okay"; +}; + +&audio_i2c0 { + clock-frequency = <100000>; + status = "okay"; + + es7210_adc2: es7210@42 { + #sound-dai-cells = <0>; + compatible = "MicArray_0"; + reg = <0x42>; + work-mode = "ES7210_TDM_1LRCK_DSPB"; + channels-max = <8>; + sound-name-prefix = "ES7210_ADC2"; + }; + + es7210_adc3: es7210@43 { + #sound-dai-cells = <0>; + compatible = "MicArray_1"; + reg = <0x43>; + work-mode = "ES7210_TDM_1LRCK_DSPB"; + channels-max = <8>; + sound-name-prefix = "ES7210_ADC3"; + status = "okay"; + }; +}; + +&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 = <&i2s0 0>; + }; + codec { + sound-dai = <&es8156_audio_codec>; + }; + }; + + simple-audio-card,dai-link@1 { /* TDM - AUDIO SYS CODEC 7210*/ + reg = <1>; + format = "dsp_b"; + cpu@0 { + sound-dai = <&tdm_slot1 0>; + }; + cpu@1 { + sound-dai = <&tdm_slot2 1>; + }; + cpu@2 { + sound-dai = <&tdm_slot3 2>; + }; + cpu@3 { + sound-dai = <&tdm_slot4 3>; + }; + cpu@4 { + sound-dai = <&tdm_slot5 4>; + }; + cpu@5 { + sound-dai = <&tdm_slot6 5>; + }; + cpu@6 { + sound-dai = <&tdm_slot7 6>; + }; + cpu@7 { + sound-dai = <&tdm_slot8 7>; + }; + codec { + sound-dai = <&es7210_adc2>; + }; + }; +}; + +&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 1e97fc303..e99192efb 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-audio.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-audio.dts @@ -10,9 +10,25 @@ compatible = "thead,light-val-audio", "thead,light"; }; -&lightsound { - status = "okay"; +&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"; + 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"; diff --git a/arch/riscv/boot/dts/thead/light-a-val-ddr1G.dts b/arch/riscv/boot/dts/thead/light-a-val-ddr1G.dts index 4361d13c8..c9a20172b 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-ddr1G.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-ddr1G.dts @@ -11,7 +11,7 @@ memory@0 { device_type = "memory"; - reg = <0x0 0x00000000 0x0 0x40000000>; + reg = <0x0 0x200000 0x0 0x3fe00000>; }; }; diff --git a/arch/riscv/boot/dts/thead/light-a-val-ddr2G.dts b/arch/riscv/boot/dts/thead/light-a-val-ddr2G.dts index 31c515fe9..ea5a73268 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-ddr2G.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-ddr2G.dts @@ -11,7 +11,7 @@ memory@0 { device_type = "memory"; - reg = <0x0 0x00000000 0x0 0x80000000>; + reg = <0x0 0x200000 0x0 0x7fe00000>; }; }; 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 new file mode 100644 index 000000000..fd99ac975 --- /dev/null +++ b/arch/riscv/boot/dts/thead/light-a-val-dsi0-hdmi-audio.dts @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + +/dts-v1/; + +#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"; + 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 = <&i2s0 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 = <&i2s3 0>; + }; + 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"; +}; + +&i2s3 { + 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 3559b8eac..2a2c92680 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-full.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-full.dts @@ -93,9 +93,25 @@ }; }; -&lightsound { +&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"; + 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"; @@ -106,7 +122,7 @@ sound-dai = <&es8156_audio_codec>; }; }; - + simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/ reg = <1>; format = "i2s"; @@ -118,19 +134,19 @@ }; }; }; - + &light_i2s { status = "okay"; }; - + &i2s0 { status = "okay"; }; - + &i2s3 { status = "okay"; }; - + &qspi0 { 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 a131f8d94..00ec00b13 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,6 +38,18 @@ }; }; +&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"; 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 215336cdc..b7aa04f45 100644 --- a/arch/riscv/boot/dts/thead/light-a-val-sec.dts +++ b/arch/riscv/boot/dts/thead/light-a-val-sec.dts @@ -5,7 +5,7 @@ /dts-v1/; -#include "light-a-val-dsi0-hdmi.dts" +#include "light-a-val-dsi0-hdmi-audio.dts" &light_iopmp { diff --git a/arch/riscv/boot/dts/thead/light-a-val.dts b/arch/riscv/boot/dts/thead/light-a-val.dts index 1ab09f202..8da963255 100644 --- a/arch/riscv/boot/dts/thead/light-a-val.dts +++ b/arch/riscv/boot/dts/thead/light-a-val.dts @@ -193,8 +193,9 @@ }; dummy_codec: dummy_codec { - #sound-dai-cells = <1>; - compatible = "linux,bt-sco"; + #sound-dai-cells = <0>; + compatible = "thead,light-dummy-pcm"; + sound-name-prefix = "DUMMY"; status = "okay"; }; @@ -561,12 +562,27 @@ #sound-dai-cells = <0>; compatible = "everest,es8156"; reg = <0x08>; + sound-name-prefix = "ES8156"; }; - es7210_audio_codec: es7210@40 { - #sound-dai-cells = <0>; - compatible = "MicArray_0"; - reg = <0x40>; + audio_aw87519_pa: amp@58 { + compatible = "awinic,aw87519_pa"; + reg = <0x58>; + reset-gpio = <&pcal6408ahk_b 3 0x1>; + sound-name-prefix = "AW87519"; + status = "okay"; + }; +}; + +&audio_i2c1 { + clock-frequency = <100000>; + status = "okay"; + + pcal6408ahk_b: gpio@20 { + compatible = "nxp,pcal9554b"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; }; }; @@ -848,8 +864,27 @@ pinctrl_volume: volume_grp { thead,pins = < - FM_CPU_JTG_TDI 0x3 0x208 - FM_CPU_JTG_TDO 0x3 0x208 + FM_CPU_JTG_TDI 0x3 0x238 + FM_CPU_JTG_TDO 0x3 0x238 + >; + }; + }; +}; + +&padctrl_audiosys { + + status = "okay"; + + light-audio-padctrl { + /* + * Pin Configuration Node: + * Format: + */ + + pinctrl_audio_i2c1: audio_i2c1_grp { + thead,pins = < + FM_AUDIO_IO_PA6 0x2 0x008 + FM_AUDIO_IO_PA7 0x2 0x008 >; }; }; diff --git a/arch/riscv/boot/dts/thead/light-ant-discrete.dts b/arch/riscv/boot/dts/thead/light-ant-discrete.dts index d2321a732..fe683e5a7 100644 --- a/arch/riscv/boot/dts/thead/light-ant-discrete.dts +++ b/arch/riscv/boot/dts/thead/light-ant-discrete.dts @@ -15,7 +15,7 @@ memory@0 { device_type = "memory"; - reg = <0x0 0x00000000 0x0 0x80000000>; + reg = <0x0 0x200000 0x0 0x7fe00000>; }; chosen { @@ -194,9 +194,10 @@ }; dummy_codec: dummy_codec { - #sound-dai-cells = <1>; - compatible = "linux,bt-sco"; + #sound-dai-cells = <0>; + compatible = "thead,light-dummy-pcm"; status = "okay"; + sound-name-prefix = "DUMMY"; }; reg_vref_1v8: regulator-adc-verf { @@ -585,18 +586,21 @@ #sound-dai-cells = <0>; compatible = "everest,es8156"; reg = <0x08>; + sound-name-prefix = "ES8156"; }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; + sound-name-prefix = "ES7210"; }; - audio_aw87519_pa@58 { + audio_aw87519_pa: amp@58 { compatible = "awinic,aw87519_pa"; reg = <0x58>; reset-gpio = <&ao_gpio4_porta 9 0x1>; + sound-name-prefix = "AW87519"; status = "okay"; }; }; @@ -2091,6 +2095,11 @@ &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"; @@ -2118,7 +2127,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-ant-ref.dts b/arch/riscv/boot/dts/thead/light-ant-ref.dts index 6ff86decf..510cb104a 100644 --- a/arch/riscv/boot/dts/thead/light-ant-ref.dts +++ b/arch/riscv/boot/dts/thead/light-ant-ref.dts @@ -15,7 +15,7 @@ memory@0 { device_type = "memory"; - reg = <0x0 0x00000000 0x0 0x80000000>; + reg = <0x0 0x200000 0x0 0x7fe00000>; }; chosen { @@ -194,9 +194,10 @@ }; dummy_codec: dummy_codec { - #sound-dai-cells = <1>; - compatible = "linux,bt-sco"; + #sound-dai-cells = <0>; + compatible = "thead,light-dummy-pcm"; status = "okay"; + sound-name-prefix = "DUMMY"; }; reg_vref_1v8: regulator-adc-verf { @@ -238,7 +239,8 @@ gpio-keys { compatible = "gpio-keys"; - pinctrl-0 = <&pinctrl_volume>; + pinctrl-0 = <&pinctrl_volume_up + &pinctrl_volume_down>; pinctrl-names = "default"; key-volumedown { label = "Volume Down Key"; @@ -592,18 +594,21 @@ #sound-dai-cells = <0>; compatible = "everest,es8156"; reg = <0x08>; + sound-name-prefix = "ES8156"; }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; + sound-name-prefix = "ES7210"; }; - audio_aw87519_pa@58 { + audio_aw87519_pa: amp@58 { compatible = "awinic,aw87519_pa"; reg = <0x58>; reset-gpio = <&ao_gpio4_porta 9 0x1>; + sound-name-prefix = "AW87519"; status = "okay"; }; }; @@ -797,6 +802,12 @@ FM_GPIO3_2 0x1 0x208 /* pwm0 */ >; }; + + pinctrl_volume_up: volume_up_grp { + thead,pins = < + FM_GPIO2_25 0x0 0x238 + >; + }; }; }; @@ -842,9 +853,9 @@ >; }; - pinctrl_volume: volume_grp { + pinctrl_volume_down: volume_down_grp { thead,pins = < - FM_CLK_OUT_2 0x3 0x208 + FM_CLK_OUT_2 0x3 0x238 >; }; }; @@ -2265,6 +2276,11 @@ &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"; @@ -2292,7 +2308,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-b-product-ddr1G.dts b/arch/riscv/boot/dts/thead/light-b-product-ddr1G.dts index a4e81ff2e..e4b91e7d9 100644 --- a/arch/riscv/boot/dts/thead/light-b-product-ddr1G.dts +++ b/arch/riscv/boot/dts/thead/light-b-product-ddr1G.dts @@ -11,7 +11,7 @@ memory@0 { device_type = "memory"; - reg = <0x0 0x00000000 0x0 0x40000000>; + reg = <0x0 0x200000 0x0 0x3fe00000>; }; }; diff --git a/arch/riscv/boot/dts/thead/light-b-product.dts b/arch/riscv/boot/dts/thead/light-b-product.dts index d20ba7bf0..6eda6e511 100644 --- a/arch/riscv/boot/dts/thead/light-b-product.dts +++ b/arch/riscv/boot/dts/thead/light-b-product.dts @@ -15,7 +15,7 @@ memory@0 { device_type = "memory"; - reg = <0x0 0x00000000 0x0 0x80000000>; + reg = <0x0 0x200000 0x0 0x7fe00000>; }; chosen { @@ -194,9 +194,10 @@ }; dummy_codec: dummy_codec { - #sound-dai-cells = <1>; - compatible = "linux,bt-sco"; + #sound-dai-cells = <0>; + compatible = "thead,light-dummy-pcm"; status = "okay"; + sound-name-prefix = "DUMMY"; }; reg_vref_1v8: regulator-adc-verf { @@ -605,18 +606,21 @@ #sound-dai-cells = <0>; compatible = "everest,es8156"; reg = <0x08>; + sound-name-prefix = "ES8156"; }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; + sound-name-prefix = "ES7210"; }; - audio_aw87519_pa@58 { + audio_aw87519_pa: amp@58 { compatible = "awinic,aw87519_pa"; reg = <0x58>; reset-gpio = <&ao_gpio4_porta 9 0x1>; + sound-name-prefix = "AW87519"; status = "okay"; }; }; @@ -880,8 +884,8 @@ pinctrl_volume: volume_grp { thead,pins = < - FM_AOGPIO_11 0x0 0x208 - FM_AOGPIO_10 0x3 0x208 + FM_AOGPIO_11 0x0 0x238 + FM_AOGPIO_10 0x3 0x238 >; }; }; @@ -2313,6 +2317,11 @@ &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"; @@ -2340,7 +2349,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-beagle-ref.dts b/arch/riscv/boot/dts/thead/light-beagle-ref.dts index a5303262d..00414ffe3 100644 --- a/arch/riscv/boot/dts/thead/light-beagle-ref.dts +++ b/arch/riscv/boot/dts/thead/light-beagle-ref.dts @@ -15,7 +15,7 @@ memory@0 { device_type = "memory"; - reg = <0x0 0x00000000 0x0 0x80000000>; + reg = <0x0 0x200000 0x0 0x7fe00000>; }; chosen { @@ -194,9 +194,10 @@ }; dummy_codec: dummy_codec { - #sound-dai-cells = <1>; - compatible = "linux,bt-sco"; + #sound-dai-cells = <0>; + compatible = "thead,light-dummy-pcm"; status = "okay"; + sound-name-prefix = "DUMMY"; }; reg_vref_1v8: regulator-adc-verf { @@ -573,18 +574,21 @@ #sound-dai-cells = <0>; compatible = "everest,es8156"; reg = <0x08>; + sound-name-prefix = "ES8156"; }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; + sound-name-prefix = "ES7210"; }; - audio_aw87519_pa@58 { + audio_aw87519_pa: amp@58 { compatible = "awinic,aw87519_pa"; reg = <0x58>; reset-gpio = <&ao_gpio4_porta 9 0x1>; + sound-name-prefix = "AW87519"; status = "okay"; }; }; @@ -2249,6 +2253,11 @@ &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"; @@ -2276,7 +2285,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-crash.dts b/arch/riscv/boot/dts/thead/light-crash.dts index be9178c10..ffdbf6357 100644 --- a/arch/riscv/boot/dts/thead/light-crash.dts +++ b/arch/riscv/boot/dts/thead/light-crash.dts @@ -191,8 +191,9 @@ }; dummy_codec: dummy_codec { - #sound-dai-cells = <1>; - compatible = "linux,bt-sco"; + #sound-dai-cells = <0>; + compatible = "thead,light-dummy-pcm"; + sound-name-prefix = "DUMMY"; status = "okay"; }; @@ -341,18 +342,21 @@ #sound-dai-cells = <0>; compatible = "everest,es8156"; reg = <0x08>; + sound-name-prefix = "ES8156"; }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; + sound-name-prefix = "ES7210"; }; - audio_aw87519_pa@58 { + audio_aw87519_pa: amp@58 { compatible = "awinic,aw87519_pa"; reg = <0x58>; reset-gpio = <&ao_gpio4_porta 9 0x1>; + sound-name-prefix = "AW87519"; status = "okay"; }; }; diff --git a/arch/riscv/boot/dts/thead/light-emu.dtsi b/arch/riscv/boot/dts/thead/light-emu.dtsi index 0e92e94b0..a9090ba2f 100644 --- a/arch/riscv/boot/dts/thead/light-emu.dtsi +++ b/arch/riscv/boot/dts/thead/light-emu.dtsi @@ -309,7 +309,7 @@ entry-cnt = <4>; control-reg = <0xff 0xff015004>; control-val = <0x1c>; - csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>; + csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>; }; clint0: clint@ffdc000000 { diff --git a/arch/riscv/boot/dts/thead/light-evb.dtsi b/arch/riscv/boot/dts/thead/light-evb.dtsi index 1d2d3323f..9224181f8 100644 --- a/arch/riscv/boot/dts/thead/light-evb.dtsi +++ b/arch/riscv/boot/dts/thead/light-evb.dtsi @@ -318,7 +318,7 @@ entry-cnt = <4>; control-reg = <0xff 0xff015004>; control-val = <0x1c>; - csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>; + csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>; }; clint0: clint@ffdc000000 { @@ -1193,8 +1193,7 @@ emmc: sdhci@ffe7080000 { compatible = "snps,dwcmshc-sdhci"; - reg = <0xff 0xe7080000 0x0 0x10000 - 0xff 0xef014060 0x0 0x4>; + reg = <0xff 0xe7080000 0x0 0x10000>; interrupt-parent = <&intc>; interrupts = <62>; interrupt-names = "sdhciirq"; @@ -1204,8 +1203,7 @@ sdhci0: sd@ffe7090000 { compatible = "snps,dwcmshc-sdhci"; - reg = <0xff 0xe7090000 0x0 0x10000 - 0xff 0xef014064 0x0 0x4>; + reg = <0xff 0xe7090000 0x0 0x10000>; interrupt-parent = <&intc>; interrupts = <64>; interrupt-names = "sdhci0irq"; @@ -1215,8 +1213,7 @@ sdhci1: sd@ffe70a0000 { compatible = "snps,dwcmshc-sdhci"; - reg = <0xff 0xe70a0000 0x0 0x10000 - 0xff 0xef014064 0x0 0x4>; + reg = <0xff 0xe70a0000 0x0 0x10000>; interrupt-parent = <&intc>; interrupts = <71>; interrupt-names = "sdhci1irq"; diff --git a/arch/riscv/boot/dts/thead/light-lpi4a-ddr2G.dts b/arch/riscv/boot/dts/thead/light-lpi4a-ddr2G.dts index dd85d2932..8b75b5ee0 100644 --- a/arch/riscv/boot/dts/thead/light-lpi4a-ddr2G.dts +++ b/arch/riscv/boot/dts/thead/light-lpi4a-ddr2G.dts @@ -11,7 +11,7 @@ memory@0 { device_type = "memory"; - reg = <0x0 0x00000000 0x0 0x80000000>; + reg = <0x0 0x200000 0x0 0x7fe00000>; }; }; diff --git a/arch/riscv/boot/dts/thead/light-lpi4a-ref.dts b/arch/riscv/boot/dts/thead/light-lpi4a-ref.dts index 0fe7951af..19f8c7ffc 100644 --- a/arch/riscv/boot/dts/thead/light-lpi4a-ref.dts +++ b/arch/riscv/boot/dts/thead/light-lpi4a-ref.dts @@ -186,9 +186,10 @@ }; dummy_codec: dummy_codec { - #sound-dai-cells = <1>; - compatible = "linux,bt-sco"; + #sound-dai-cells = <0>; + compatible = "thead,light-dummy-pcm"; status = "okay"; + sound-name-prefix = "DUMMY"; }; fan: pwm-fan { @@ -658,17 +659,20 @@ #sound-dai-cells = <0>; compatible = "everest,es8156"; reg = <0x08>; + sound-name-prefix = "ES8156"; }; es7210_audio_codec: es7210@40 { #sound-dai-cells = <0>; compatible = "MicArray_0"; reg = <0x40>; + sound-name-prefix = "ES7210"; }; - audio_aw87519_pa@58 { + audio_aw87519_pa: amp@58 { compatible = "awinic,aw87519_pa"; reg = <0x58>; + sound-name-prefix = "AW87519"; status = "okay"; }; @@ -1391,6 +1395,11 @@ &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"; @@ -1444,6 +1453,13 @@ status = "okay"; }; +&usb_1 { + hubswitch-gpio = <&ao_gpio_porta 4 0>; + vbus-supply = <&soc_vbus_en_reg>; + hub1v2-supply = <®_usb_hub_vdd1v2>; + hub5v-supply = <®_usb_hub_vcc5v>; +}; + &cpus { c910_0: cpu@0 { operating-points = < diff --git a/arch/riscv/boot/dts/thead/light-lpi4a-sec.dts b/arch/riscv/boot/dts/thead/light-lpi4a-sec.dts new file mode 100644 index 000000000..e5a511345 --- /dev/null +++ b/arch/riscv/boot/dts/thead/light-lpi4a-sec.dts @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + +/dts-v1/; + +#include "light-lpi4a.dts" + + +&light_iopmp { + status = "disabled"; +}; diff --git a/arch/riscv/boot/dts/thead/light-lpi4a.dts b/arch/riscv/boot/dts/thead/light-lpi4a.dts index cae29d3f0..2058f6868 100644 --- a/arch/riscv/boot/dts/thead/light-lpi4a.dts +++ b/arch/riscv/boot/dts/thead/light-lpi4a.dts @@ -11,17 +11,10 @@ memory@0 { device_type = "memory"; - reg = <0x0 0x00000000 0x2 0x00000000>; + reg = <0x0 0x200000 0x1 0xffe00000>; }; }; &cmamem { alloc-ranges = <0x1 0xe4000000 0 0x14000000>; // [0x1E400_0000 ~ 0x1F800_0000] }; - -&usb_1 { - hubswitch-gpio = <&ao_gpio_porta 4 0>; - vbus-supply = <&soc_vbus_en_reg>; - hub1v2-supply = <®_usb_hub_vdd1v2>; - hub5v-supply = <®_usb_hub_vcc5v>; -}; diff --git a/arch/riscv/boot/dts/thead/light.dtsi b/arch/riscv/boot/dts/thead/light.dtsi index e9e0e3357..2d8db6ad8 100644 --- a/arch/riscv/boot/dts/thead/light.dtsi +++ b/arch/riscv/boot/dts/thead/light.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +95,12 @@ }; }; + aon_iram: aon-iram@ffffef8000 { + compatible = "syscon"; + reg = <0xff 0xffef8000 0x0 0x10000>; + }; + + thermal-zones { cpu-thermal-zone { polling-delay-passive = <250>; @@ -383,7 +390,7 @@ entry-cnt = <4>; control-reg = <0xff 0xff015004>; control-val = <0x1c>; - csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>; + csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>; }; clint0: clint@ffdc000000 { @@ -855,6 +862,12 @@ status = "okay"; }; + padctrl_audiosys: padctrl-audiosys@ffcb01d000 { + compatible = "thead,light-fm-audio-pinctrl"; + reg = <0xff 0xcb01d000 0x0 0x1000>; + status = "disabled"; + }; + timer4: timer@ffffc33000 { compatible = "snps,dw-apb-timer"; reg = <0xff 0xffc33000 0x0 0x14>; @@ -1301,7 +1314,7 @@ 65536 65536 65536 65536 65536 65536 65536 65536 65536 65536 65536 65536>; - snps,priority = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; + snps,priority = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; // <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; snps,dma-masters = <1>; snps,data-width = <4>; snps,axi-max-burst-len = <16>; @@ -1354,8 +1367,7 @@ emmc: sdhci@ffe7080000 { compatible = "snps,dwcmshc-sdhci"; - reg = <0xff 0xe7080000 0x0 0x10000 - 0xff 0xef014060 0x0 0x4>; + reg = <0xff 0xe7080000 0x0 0x10000>; interrupt-parent = <&intc>; interrupts = <62>; interrupt-names = "sdhciirq"; @@ -1365,8 +1377,7 @@ sdhci0: sd@ffe7090000 { compatible = "snps,dwcmshc-sdhci"; - reg = <0xff 0xe7090000 0x0 0x10000 - 0xff 0xef014064 0x0 0x4>; + reg = <0xff 0xe7090000 0x0 0x10000>; interrupt-parent = <&intc>; interrupts = <64>; interrupt-names = "sdhci0irq"; @@ -1376,8 +1387,7 @@ sdhci1: sd@ffe70a0000 { compatible = "snps,dwcmshc-sdhci"; - reg = <0xff 0xe70a0000 0x0 0x10000 - 0xff 0xef014064 0x0 0x4>; + reg = <0xff 0xe70a0000 0x0 0x10000>; interrupt-parent = <&intc>; interrupts = <71>; interrupt-names = "sdhci1irq"; @@ -1573,6 +1583,174 @@ status = "disabled"; }; + tdm_slot1: audio_tdm_slot1@0xffcb012000 { + #sound-dai-cells = <1>; + compatible = "light,light-tdm"; + reg = <0xff 0xcb012000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,tdm_slots = <8>; + light,tdm_slot_num = <1>; + interrupt-parent = <&intc>; + interrupts = <178>; + dmas = <&dmac2 28>; + dma-names = "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + tdm_slot2: audio_tdm_slot2@0xffcb012000 { + #sound-dai-cells = <1>; + compatible = "light,light-tdm"; + reg = <0xff 0xcb012000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,tdm_slots = <8>; + light,tdm_slot_num = <2>; + interrupt-parent = <&intc>; + interrupts = <178>; + dmas = <&dmac2 29>; + dma-names = "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + tdm_slot3: audio_tdm_slot3@0xffcb012000 { + #sound-dai-cells = <1>; + compatible = "light,light-tdm"; + reg = <0xff 0xcb012000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,tdm_slots = <8>; + light,tdm_slot_num = <3>; + interrupt-parent = <&intc>; + interrupts = <178>; + dmas = <&dmac2 30>; + dma-names = "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + tdm_slot4: audio_tdm_slot4@0xffcb012000 { + #sound-dai-cells = <1>; + compatible = "light,light-tdm"; + reg = <0xff 0xcb012000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,tdm_slots = <8>; + light,tdm_slot_num = <4>; + interrupt-parent = <&intc>; + interrupts = <178>; + dmas = <&dmac2 31>; + dma-names = "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + tdm_slot5: audio_tdm_slot5@0xffcb012000 { + #sound-dai-cells = <1>; + compatible = "light,light-tdm"; + reg = <0xff 0xcb012000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,tdm_slots = <8>; + light,tdm_slot_num = <5>; + interrupt-parent = <&intc>; + interrupts = <178>; + dmas = <&dmac2 32>; + dma-names = "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + tdm_slot6: audio_tdm_slot6@0xffcb012000 { + #sound-dai-cells = <1>; + compatible = "light,light-tdm"; + reg = <0xff 0xcb012000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,tdm_slots = <8>; + light,tdm_slot_num = <6>; + interrupt-parent = <&intc>; + interrupts = <178>; + dmas = <&dmac2 33>; + dma-names = "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + tdm_slot7: audio_tdm_slot7@0xffcb012000 { + #sound-dai-cells = <1>; + compatible = "light,light-tdm"; + reg = <0xff 0xcb012000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,tdm_slots = <8>; + light,tdm_slot_num = <7>; + interrupt-parent = <&intc>; + interrupts = <178>; + dmas = <&dmac2 34>; + dma-names = "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + + tdm_slot8: audio_tdm_slot8@0xffcb012000 { + #sound-dai-cells = <1>; + compatible = "light,light-tdm"; + reg = <0xff 0xcb012000 0x0 0x1000>; + audio-pin-regmap = <&audio_ioctrl>; + audio-cpr-regmap = <&audio_cpr>; + pinctrl-names = "default"; + light,mode = "i2s-master"; + light,tdm_slots = <8>; + light,tdm_slot_num = <8>; + interrupt-parent = <&intc>; + interrupts = <178>; + dmas = <&dmac2 35>; + dma-names = "rx"; + light,dma_maxburst = <4>; + #dma-cells = <1>; + clocks = <&dummy_clock_apb>; + clock-names = "pclk"; + status = "disabled"; + }; + pvt: pvt@fffff4e000 { compatible = "moortec,mr75203"; reg = <0xff 0xfff4e000 0x0 0x80>, @@ -2154,6 +2332,12 @@ interrupts = <215>; /* TEE INT SRC_7 */ }; + 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"; visys-regmap = <&visys_reg>; diff --git a/arch/riscv/configs/light_defconfig b/arch/riscv/configs/light_defconfig index 74b8b47da..db5633009 100644 --- a/arch/riscv/configs/light_defconfig +++ b/arch/riscv/configs/light_defconfig @@ -20,6 +20,7 @@ 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 @@ -91,6 +92,7 @@ CONFIG_TUN=y CONFIG_VIRTIO_NET=y CONFIG_MACB=y CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_RX_ZERO_COPY=y CONFIG_DWMAC_LIGHT=y CONFIG_MICROSEMI_PHY=y CONFIG_REALTEK_PHY=y @@ -265,6 +267,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 @@ -298,13 +301,21 @@ CONFIG_CRYPTO_AUTHENC=y CONFIG_CRYPTO_DH=y CONFIG_CRYPTO_CURVE25519=y CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y CONFIG_CRYPTO_OFB=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_SHA3=y CONFIG_CRYPTO_SM3=y CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_SM4=y +CONFIG_CRYPTO_USER=y CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_RNG=y +# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set +CONFIG_CRYPTO_USER_API_AEAD=y CONFIG_DMA_CMA=y CONFIG_DMA_PERNUMA_CMA=y CONFIG_CMA_SIZE_MBYTES=32 diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 8af46a6b9..619f4620d 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -6,6 +6,7 @@ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. * Copyright (C) 2010, Guennadi Liakhovetski */ +#include #include #include #include @@ -103,6 +104,11 @@ static const u16 csc_coeff_rgb_full_to_rgb_limited[3][4] = { { 0x0000, 0x0000, 0x1b7c, 0x0020 } }; +static const unsigned int hdmi_extcon_cable[] = { + EXTCON_DISP_HDMI, + EXTCON_NONE, +}; + struct hdmi_vmode { bool mdataenablepolarity; @@ -160,6 +166,7 @@ struct dw_hdmi { struct clk *pix_clk; struct clk *i2s_clk; struct dw_hdmi_i2c *i2c; + struct extcon_dev *edev; struct hdmi_data_info hdmi_data; const struct dw_hdmi_plat_data *plat_data; @@ -3117,6 +3124,10 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) dev_dbg(hdmi->dev, "EVENT=%s\n", status == connector_status_connected ? "plugin" : "plugout"); + if (status == connector_status_connected) + extcon_set_state_sync(hdmi->edev, EXTCON_DISP_HDMI, true); + else + extcon_set_state_sync(hdmi->edev, EXTCON_DISP_HDMI, false); if (hdmi->bridge.dev) { drm_helper_hpd_irq_event(hdmi->bridge.dev); @@ -3423,6 +3434,19 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, dw_hdmi_init_hw(hdmi); + hdmi->edev = devm_extcon_dev_allocate(dev, hdmi_extcon_cable); + if (IS_ERR(hdmi->edev)) { + dev_err(dev, "failed to allocate extcon device\n"); + ret = -ENOMEM; + goto err_res; + } + + ret = devm_extcon_dev_register(dev, hdmi->edev); + if (ret < 0) { + dev_err(dev, "failed to register extcon device\n"); + goto err_res; + } + irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 011e14080..5b5ebf346 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -28,7 +28,6 @@ struct dwcmshc_priv { struct clk *bus_clk; - void __iomem *soc_base; bool is_emmc_card; bool pull_up_en; bool io_fixed_1v8; @@ -289,12 +288,6 @@ static void snps_sdhci_reset(struct sdhci_host *host, u8 mask) pltfm_host = sdhci_priv(host); priv = sdhci_pltfm_priv(pltfm_host); - /*soc reset, fix host reset error*/ - //soc_reg = readl( priv->soc_base); - //soc_reg &= ~1; - //writel(soc_reg, priv->soc_base); - //soc_reg |= 1; - //writel(soc_reg, priv->soc_base); /*host reset*/ sdhci_reset(host, mask); @@ -604,9 +597,6 @@ static int dwcmshc_probe(struct platform_device *pdev) pltfm_host = sdhci_priv(host); priv = sdhci_pltfm_priv(pltfm_host); - /*used fix sdhci reset error*/ - priv->soc_base = devm_platform_ioremap_resource(pdev, 1); - if (device_property_present(&pdev->dev, "is_emmc")) { priv->is_emmc_card = 1; } else { diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 6133e9f61..f81419db8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -25,6 +25,16 @@ config STMMAC_SELFTESTS feature if you are facing problems with your HW and submit the test results to the netdev Mailing List. +config STMMAC_RX_ZERO_COPY + bool "Support for STMMAC Zero Copy in Recv" + default n + help + This adds support for STMMAC reduce memcpy packet ring_buffer data + to skb data in stmmac_rx. Enable this feature will alloc skb in filling + ring buffer, mapping skb->data to ring buffer DMA addr. + + If unsure, say N. + config STMMAC_PLATFORM tristate "STMMAC Platform bus support" depends on STMMAC_ETH diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 617c960cf..73e6e545f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -67,12 +67,18 @@ struct stmmac_rx_buffer { dma_addr_t addr; dma_addr_t sec_addr; }; - +struct stmmac_rx_skbuffer { + struct sk_buff *rx_skbuff; + struct page *sec_page; + dma_addr_t addr; + dma_addr_t sec_addr; +}; struct stmmac_rx_queue { u32 rx_count_frames; u32 queue_index; struct page_pool *page_pool; struct stmmac_rx_buffer *buf_pool; + struct stmmac_rx_skbuffer *skbuf_pool; struct stmmac_priv *priv_data; struct dma_extended_desc *dma_erx; struct dma_desc *dma_rx ____cacheline_aligned_in_smp; @@ -210,6 +216,7 @@ struct stmmac_priv { unsigned int mode; unsigned int chain_mode; int extend_desc; + bool extend_stat_need; struct hwtstamp_config tstamp_config; struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_ops; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a46c32257..42132137b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1324,7 +1324,7 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) for (queue = 0; queue < tx_queue_cnt; queue++) stmmac_clear_tx_descriptors(priv, queue); } - +#ifndef CONFIG_STMMAC_RX_ZERO_COPY /** * stmmac_init_rx_buffers - init the RX descriptor buffer. * @priv: driver private structure @@ -1335,7 +1335,7 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv) * Description: this function is called to allocate a receive buffer, perform * the DMA mapping and init the descriptor. */ -static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, +static int __stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, int i, gfp_t flags, u32 queue) { struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; @@ -1364,14 +1364,13 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, return 0; } - /** * stmmac_free_rx_buffer - free RX dma buffers * @priv: private structure * @queue: RX queue index * @i: buffer index. */ -static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i) +static void __stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i) { struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; @@ -1385,6 +1384,118 @@ static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i) buf->sec_page = NULL; } +#else + +static inline unsigned int stmmac_get_rx_buf_frsize(struct stmmac_priv *priv) +{ + return priv->dma_buf_sz; +} + +#define STMMAC_RX_ALIGN 0x3f +static int +stmmac_get_skb_dma_addr(struct stmmac_priv *priv,struct sk_buff *skb,dma_addr_t *dma_addr) +{ + int off; + + off = ((unsigned long)skb->data) & STMMAC_RX_ALIGN; + if (off) + skb_reserve(skb, STMMAC_RX_ALIGN + 1 - off); + *dma_addr = dma_map_single(priv->device,skb->data,stmmac_get_rx_buf_frsize(priv) - off,DMA_FROM_DEVICE); + if (dma_mapping_error(priv->device, *dma_addr)) { + //if (net_ratelimit()) + netdev_err(priv->dev, "Rx DMA memory map failed\n"); + return -ENOMEM; + } + + return 0; +} +/** + * stmmac_init_rx_skbuffers - init the RX descriptor buffer. + * @priv: driver private structure + * @p: descriptor pointer + * @i: descriptor index + * @flags: gfp flag + * @queue: RX queue index + * Description: this function is called to allocate a receive buffer, perform + * the DMA mapping and init the descriptor. + */ +static int __stmmac_init_rx_skbuffers(struct stmmac_priv *priv, struct dma_desc *p, + int i, gfp_t flags, u32 queue) +{ + struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; + struct stmmac_rx_skbuffer *buf = &rx_q->skbuf_pool[i]; + struct sk_buff *skb = NULL; + skb = netdev_alloc_skb(priv->dev, stmmac_get_rx_buf_frsize(priv)); + if (!skb) + return -ENOMEM; + + if(stmmac_get_skb_dma_addr(priv,skb,&buf->addr) < 0) + return -ENOMEM; + + if (priv->sph) { + buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); + if (!buf->sec_page) + return -ENOMEM; + + buf->sec_addr = page_pool_get_dma_addr(buf->sec_page); + stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true); + } else { + buf->sec_page = NULL; + stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false); + } + stmmac_set_desc_addr(priv, p, buf->addr); + if (priv->dma_buf_sz == BUF_SIZE_16KiB) + stmmac_init_desc3(priv, p); + buf->rx_skbuff = skb; + return 0; +} + +/** + * stmmac_free_rx_skbuffer - free RX dma buffers + * @priv: private structure + * @queue: RX queue index + * @i: buffer index. + */ +static void __stmmac_free_rx_skbuffer(struct stmmac_priv *priv, u32 queue, int i) +{ + struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; + struct stmmac_rx_skbuffer *buf = &rx_q->skbuf_pool[i]; + + if (buf->rx_skbuff){ + dma_unmap_single(priv->device, + buf->addr, + stmmac_get_rx_buf_frsize(priv) - STMMAC_RX_ALIGN, + DMA_FROM_DEVICE); + dev_kfree_skb(buf->rx_skbuff); + buf->rx_skbuff = NULL; + } + + if (buf->sec_page) + page_pool_put_full_page(rx_q->page_pool, buf->sec_page, false); + buf->sec_page = NULL; + +} +#endif + +static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, + int i, gfp_t flags, u32 queue) +{ + #ifndef CONFIG_STMMAC_RX_ZERO_COPY + return __stmmac_init_rx_buffers(priv,p,i,flags,queue); + #else + return __stmmac_init_rx_skbuffers(priv,p,i,flags,queue); + #endif +} + +static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i) +{ + #ifndef CONFIG_STMMAC_RX_ZERO_COPY + __stmmac_free_rx_buffer(priv,queue,i); + #else + __stmmac_free_rx_skbuffer(priv,queue,i); + #endif +} + /** * stmmac_free_tx_buffer - free RX dma buffers * @priv: private structure @@ -1644,8 +1755,11 @@ static void free_dma_rx_desc_resources(struct stmmac_priv *priv) dma_free_coherent(priv->device, priv->dma_rx_size * sizeof(struct dma_extended_desc), rx_q->dma_erx, rx_q->dma_rx_phy); - +#ifndef CONFIG_STMMAC_RX_ZERO_COPY kfree(rx_q->buf_pool); +#else + kfree(rx_q->skbuf_pool); +#endif if (rx_q->page_pool) page_pool_destroy(rx_q->page_pool); } @@ -1711,7 +1825,6 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv) rx_q->queue_index = queue; rx_q->priv_data = priv; - pp_params.flags = PP_FLAG_DMA_MAP; pp_params.pool_size = priv->dma_rx_size; num_pages = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE); @@ -1726,13 +1839,19 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv) rx_q->page_pool = NULL; goto err_dma; } - +#ifndef CONFIG_STMMAC_RX_ZERO_COPY rx_q->buf_pool = kcalloc(priv->dma_rx_size, sizeof(*rx_q->buf_pool), GFP_KERNEL); if (!rx_q->buf_pool) goto err_dma; - +#else + rx_q->skbuf_pool = kcalloc(priv->dma_rx_size, + sizeof(*rx_q->skbuf_pool), + GFP_KERNEL); + if (!rx_q->skbuf_pool) + goto err_dma; +#endif if (priv->extend_desc) { rx_q->dma_erx = dma_alloc_coherent(priv->device, priv->dma_rx_size * @@ -3664,18 +3783,24 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; int len, dirty = stmmac_rx_dirty(priv, queue); unsigned int entry = rx_q->dirty_rx; +#ifndef CONFIG_STMMAC_RX_ZERO_COPY + struct stmmac_rx_buffer *buf; +#else + struct stmmac_rx_skbuffer *buf ; + struct sk_buff *skb = NULL; +#endif len = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE) * PAGE_SIZE; while (dirty-- > 0) { - struct stmmac_rx_buffer *buf = &rx_q->buf_pool[entry]; struct dma_desc *p; bool use_rx_wd; - if (priv->extend_desc) p = (struct dma_desc *)(rx_q->dma_erx + entry); else p = rx_q->dma_rx + entry; +#ifndef CONFIG_STMMAC_RX_ZERO_COPY + buf = &rx_q->buf_pool[entry]; if (!buf->page) { buf->page = page_pool_dev_alloc_pages(rx_q->page_pool); @@ -3695,12 +3820,47 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) } buf->addr = page_pool_get_dma_addr(buf->page); + /* Sync whole allocation to device. This will invalidate old + * data. + */ + dma_sync_single_for_device(priv->device, buf->addr, len, + DMA_FROM_DEVICE); +#else + buf = &rx_q->skbuf_pool[entry]; + + if(likely(!buf->rx_skbuff)){ + len = stmmac_get_rx_buf_frsize(priv); + skb = netdev_alloc_skb(priv->dev, len); + if (!skb){ + //priv->dev->stats.rx_dropped += (1ul<<32); + netdev_err(priv->dev, "%s: dalloc_skb failed,dirty ring %d :\n", __func__,dirty); + break; + } + if(stmmac_get_skb_dma_addr(priv,skb,&buf->addr) < 0){ + //priv->dev->stats.rx_dropped += (1ul<<32); + break; + } + buf->rx_skbuff = skb; + } /* Sync whole allocation to device. This will invalidate old * data. */ dma_sync_single_for_device(priv->device, buf->addr, len, DMA_FROM_DEVICE); + + if (priv->sph && !buf->sec_page) { + buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); + if (!buf->sec_page) + break; + + buf->sec_addr = page_pool_get_dma_addr(buf->sec_page); + + dma_sync_single_for_device(priv->device, buf->sec_addr, + len, DMA_FROM_DEVICE); + } + +#endif stmmac_set_desc_addr(priv, p, buf->addr); if (priv->sph) @@ -3815,7 +3975,11 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) while (count < limit) { unsigned int buf1_len = 0, buf2_len = 0; enum pkt_hash_types hash_type; + #ifndef CONFIG_STMMAC_RX_ZERO_COPY struct stmmac_rx_buffer *buf; + #else + struct stmmac_rx_skbuffer *skbuf; + #endif struct dma_desc *np, *p; int entry; u32 hash; @@ -3838,8 +4002,11 @@ read_again: buf1_len = 0; buf2_len = 0; entry = next_entry; + #ifndef CONFIG_STMMAC_RX_ZERO_COPY buf = &rx_q->buf_pool[entry]; - + #else + skbuf = &rx_q->skbuf_pool[entry]; + #endif if (priv->extend_desc) p = (struct dma_desc *)(rx_q->dma_erx + entry); else @@ -3863,12 +4030,14 @@ read_again: prefetch(np); - if (priv->extend_desc) + if (priv->extend_desc && priv->extend_stat_need) stmmac_rx_extended_status(priv, &priv->dev->stats, &priv->xstats, rx_q->dma_erx + entry); if (unlikely(status == discard_frame)) { + #ifndef CONFIG_STMMAC_RX_ZERO_COPY page_pool_recycle_direct(rx_q->page_pool, buf->page); buf->page = NULL; + #endif error = 1; if (!priv->hwts_rx_en) priv->dev->stats.rx_errors++; @@ -3884,11 +4053,14 @@ read_again: } /* Buffer is good. Go on. */ - +#ifndef CONFIG_STMMAC_RX_ZERO_COPY prefetch(page_address(buf->page)); if (buf->sec_page) prefetch(page_address(buf->sec_page)); - +#else + skb = skbuf->rx_skbuff; + prefetch(skb->data); +#endif buf1_len = stmmac_rx_buf1_len(priv, p, status, len); len += buf1_len; buf2_len = stmmac_rx_buf2_len(priv, p, status, len); @@ -3911,7 +4083,30 @@ read_again: len -= ETH_FCS_LEN; } +#ifdef CONFIG_STMMAC_RX_ZERO_COPY + skb = skbuf->rx_skbuff; + if (!skb) { + priv->dev->stats.rx_dropped++; + count++; + goto drain_data; + } + dma_sync_single_for_cpu(priv->device, skbuf->addr, + buf1_len, DMA_FROM_DEVICE); + skb_put(skb, buf1_len); + skbuf->rx_skbuff = NULL; + + if (buf2_len) { + dma_sync_single_for_cpu(priv->device, skbuf->sec_addr, + buf2_len, DMA_FROM_DEVICE); + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + skbuf->sec_page, 0, buf2_len, + priv->dma_buf_sz); + /* Data payload appended into SKB */ + page_pool_release_page(rx_q->page_pool, skbuf->sec_page); + skbuf->sec_page = NULL; + } +#else if (!skb) { skb = napi_alloc_skb(&ch->rx_napi, buf1_len); if (!skb) { @@ -3952,7 +4147,7 @@ read_again: page_pool_release_page(rx_q->page_pool, buf->sec_page); buf->sec_page = NULL; } - +#endif drain_data: if (likely(status & rx_not_ls)) goto read_again; @@ -4104,8 +4299,12 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) new_mtu = STMMAC_ALIGN(new_mtu); /* If condition true, FIFO is too small or MTU too large */ - if ((txfifosz < new_mtu) || (new_mtu > BUF_SIZE_16KiB)) + if ((txfifosz && txfifosz < new_mtu) || (new_mtu > BUF_SIZE_16KiB)){ + netdev_err(priv->dev,"FIFO is too small or MTU too large\n"); + printk("new_mtu %d -- %d,%d,%d \n",new_mtu,txfifosz,priv->plat->tx_fifo_size,priv->dma_cap.tx_fifo_size); return -EINVAL; + } + dev->mtu = mtu; diff --git a/drivers/pinctrl/thead/pinctrl-light.c b/drivers/pinctrl/thead/pinctrl-light.c index 544727e10..5c50ab40d 100644 --- a/drivers/pinctrl/thead/pinctrl-light.c +++ b/drivers/pinctrl/thead/pinctrl-light.c @@ -18,9 +18,18 @@ #include #include #include +#include #include "../core.h" +enum light_pinctrl_type { + LIGHT_MPW, + LIGHT_FM_RIGHT, + LIGHT_FM_LEFT, + LIGHT_FM_AON, + LIGHT_FM_AUDIO, +}; + struct light_pin { unsigned int pin_id; unsigned int mux_mode; @@ -50,6 +59,8 @@ struct light_pinctrl_soc_info { unsigned int grp_index; struct light_pmx_func *functions; unsigned int nfunctions; + char *label; + enum light_pinctrl_type type; unsigned int cfg_off; unsigned int mux_off; @@ -66,6 +77,7 @@ struct light_pinctrl { #define LIGHT_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin) #define LIGHT_PAD_CONFIG(idx) (priv->info->cfg_off + (idx >> 1) * 4) #define LIGHT_PAD_MUX(idx) (priv->info->mux_off + ((idx >> 3) * 4)) +#define LIGHT_AUDIO_PAD_MUX(idx) (priv->info->mux_off + ((idx >> 4) * 4)) static const char *pin_get_name_from_info(struct light_pinctrl_soc_info *info, const unsigned int pin_id) @@ -247,13 +259,31 @@ static int light_pmx_set(struct pinctrl_dev *pctldev, unsigned int selector, continue; } - mux = readl(priv->base + LIGHT_PAD_MUX(pin_id)); - shift = ((pin_id % 8) << 2); - mux &= ~(0xF << shift); /* 4 mux bits for one pad */ - mux |= (pin->mux_mode << shift); - writel(mux, priv->base + LIGHT_PAD_MUX(pin_id)); - dev_dbg(priv->dev, "write: offset 0x%x val 0x%x\n", - LIGHT_PAD_MUX(pin_id), mux); + if (info->type == LIGHT_FM_AUDIO) { + if (pin->mux_mode == AUDIO_IO_GPIO) { + mux = ~(1 << pin_id) & readl(priv->base); + writel(mux, priv->base); /* Controlled by GPIO under AUDIO_SUBSYS */ + continue; + } + mux = (1 << pin_id) | readl(priv->base); + writel(mux, priv->base); + + mux = readl(priv->base + LIGHT_AUDIO_PAD_MUX(pin_id)); + shift = ((pin_id % 16) << 1); + mux &= ~(0x3 << shift); /* 2 mux bits for one pad */ + mux |= (pin->mux_mode << shift); + writel(mux, priv->base + LIGHT_AUDIO_PAD_MUX(pin_id)); + dev_dbg(priv->dev, "write: offset 0x%x val 0x%x\n", + LIGHT_AUDIO_PAD_MUX(pin_id), mux); + } else { + mux = readl(priv->base + LIGHT_PAD_MUX(pin_id)); + shift = ((pin_id % 8) << 2); + mux &= ~(0xF << shift); /* 4 mux bits for one pad */ + mux |= (pin->mux_mode << shift); + writel(mux, priv->base + LIGHT_PAD_MUX(pin_id)); + dev_dbg(priv->dev, "write: offset 0x%x val 0x%x\n", + LIGHT_PAD_MUX(pin_id), mux); + } } return 0; @@ -430,7 +460,15 @@ static int light_pinctrl_parse_groups(struct device_node *np, struct light_pin *pin = &grp->pins[i]; pin->pin_id = be32_to_cpu(*list++); - pin->mux_mode = be32_to_cpu(*list++) & 0xF; + if (info->type == LIGHT_FM_AUDIO) { + pin->mux_mode = be32_to_cpu(*list++); + if (pin->mux_mode != AUDIO_IO_GPIO){ + pin->mux_mode &= 0x3; + } + } else { + pin->mux_mode = be32_to_cpu(*list++) & 0xF; + + } pin->config = be32_to_cpu(*list++) & 0xFFFF; grp->pin_ids[i] = grp->pins[i].pin_id; @@ -841,6 +879,40 @@ static const struct pinctrl_pin_desc light_fm_aon_pinctrl_pads[] = { LIGHT_PINCTRL_PIN(FM_AUDIO_PA30), }; +static const struct pinctrl_pin_desc light_fm_audio_pinctrl_pads[] = { + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA0), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA1), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA2), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA3), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA4), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA5), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA6), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA7), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA8), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA9), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA10), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA11), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA12), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA13), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA14), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA15), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA16), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA17), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA18), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA19), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA20), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA21), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA22), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA23), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA24), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA25), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA26), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA27), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA28), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA29), + LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA30), +}; + static int light_pinctrl_mpw_convert_pin_off(const unsigned int pin_id) { unsigned int cov_pin_id = pin_id; @@ -865,6 +937,7 @@ static int light_pinctrl_fm_aon_covert_pin_off(const unsigned int pin_id) static struct light_pinctrl_soc_info light_mpw_pinctrl_info = { .pins = light_mpw_pinctrl_pads, .npins = ARRAY_SIZE(light_mpw_pinctrl_pads), + .type = LIGHT_MPW, .cfg_off = 0x4c, .mux_off = 0x404, .covert_pin_off = light_pinctrl_mpw_convert_pin_off, @@ -873,6 +946,7 @@ static struct light_pinctrl_soc_info light_mpw_pinctrl_info = { static struct light_pinctrl_soc_info light_fm_right_pinctrl_info = { .pins = light_fm_right_pinctrl_pads, .npins = ARRAY_SIZE(light_fm_right_pinctrl_pads), + .type = LIGHT_FM_RIGHT, .cfg_off = 0x0, .mux_off = 0x400, }; @@ -880,6 +954,7 @@ static struct light_pinctrl_soc_info light_fm_right_pinctrl_info = { static struct light_pinctrl_soc_info light_fm_left_pinctrl_info = { .pins = light_fm_left_pinctrl_pads, .npins = ARRAY_SIZE(light_fm_left_pinctrl_pads), + .type = LIGHT_FM_LEFT, .cfg_off = 0x0, .mux_off = 0x400, }; @@ -887,16 +962,27 @@ static struct light_pinctrl_soc_info light_fm_left_pinctrl_info = { static struct light_pinctrl_soc_info light_fm_aon_pinctrl_info = { .pins = light_fm_aon_pinctrl_pads, .npins = ARRAY_SIZE(light_fm_aon_pinctrl_pads), + .type = LIGHT_FM_AON, .cfg_off = 0x0, .mux_off = 0x400, .covert_pin_off = light_pinctrl_fm_aon_covert_pin_off, }; +static struct light_pinctrl_soc_info light_fm_audio_pinctrl_info = { + .pins = light_fm_audio_pinctrl_pads, + .npins = ARRAY_SIZE(light_fm_audio_pinctrl_pads), + .label = "LIGHT-AUDIO-IO", + .type = LIGHT_FM_AUDIO, + .cfg_off = 0x0C, + .mux_off = 0x4, +}; + static const struct of_device_id light_pinctrl_of_match[] = { { .compatible = "thead,light-mpw-pinctrl", .data = &light_mpw_pinctrl_info}, { .compatible = "thead,light-fm-right-pinctrl", .data = &light_fm_right_pinctrl_info}, { .compatible = "thead,light-fm-left-pinctrl", .data = &light_fm_left_pinctrl_info}, { .compatible = "thead,light-fm-aon-pinctrl", .data = &light_fm_aon_pinctrl_info}, + { .compatible = "thead,light-fm-audio-pinctrl", .data = &light_fm_audio_pinctrl_info}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, light_pinctrl_of_match); diff --git a/drivers/soc/thead/Kconfig b/drivers/soc/thead/Kconfig index b70d23168..b595d42d7 100644 --- a/drivers/soc/thead/Kconfig +++ b/drivers/soc/thead/Kconfig @@ -16,6 +16,12 @@ config LIGHT_SUSPEND help This driver supports system suspend low power feature in Light FM platform +config LIGHT_REBOOTMODE + bool "Thead light rebootmode support" + default y + help + This driver supports check rebootmode feature in Light FM platform + endmenu endif diff --git a/drivers/soc/thead/Makefile b/drivers/soc/thead/Makefile index 421e8bb46..be437ceb1 100644 --- a/drivers/soc/thead/Makefile +++ b/drivers/soc/thead/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_LIGHT_IOPMP) += light-iopmp.o obj-$(CONFIG_LIGHT_SUSPEND) += pm-light.o +obj-$(CONFIG_LIGHT_REBOOTMODE) += light_event.o diff --git a/drivers/soc/thead/light_event.c b/drivers/soc/thead/light_event.c new file mode 100644 index 000000000..c6151e1c0 --- /dev/null +++ b/drivers/soc/thead/light_event.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * AON SRAM total size is 0x10000, reserve 0x100 for event. + * Notice: c902 *.ld also need resize. + * -------------- 0xff_ffef8000 + * | | + * | | + * | | + * | c902 | + * | | + * | | + * | | + * -------------- 0xff_fff07f00 + * | reserve | + * | | + * -------------- + */ +#define LIGHT_AON_SRAM_LEN 0x10000 +#define LIGHT_AON_SRAM_RESERV (LIGHT_AON_SRAM_LEN - 0x100) +#define LIGHT_EVENT_OFFSET (LIGHT_AON_SRAM_RESERV + 0x10) +#define LIGHT_EVENT_CHECK (LIGHT_EVENT_OFFSET + 0x4) + +#define LIGHT_EVENT_MAGIC 0x5A5A5A5A + +struct light_aon_msg_event_ctrl { + struct light_aon_rpc_msg_hdr hdr; + u32 reserve_offset; + u32 reserved[5]; +} __packed __aligned(4); + +struct light_event { + struct device *dev; + + struct light_aon_ipc *ipc_handle; + struct light_aon_msg_event_ctrl msg; + + struct regmap *aon_iram; + bool init; +}; + +struct light_event *light_event; + +static void light_event_msg_hdr_fill(struct light_aon_rpc_msg_hdr *hdr, enum light_aon_misc_func func) +{ + hdr->ver = LIGHT_AON_RPC_VERSION; + hdr->svc = (uint8_t)LIGHT_AON_RPC_SVC_MISC; + hdr->func = (uint8_t)func; + hdr->size = LIGHT_AON_RPC_MSG_NUM; +} + +static int light_event_aon_reservemem(struct light_event *event) +{ + struct light_aon_ipc *ipc = event->ipc_handle; + int ret = 0; + + dev_dbg(light_event->dev, "aon reservemem...\n"); + + light_event_msg_hdr_fill(&event->msg.hdr, LIGHT_AON_MISC_FUNC_AON_RESERVE_MEM); + event->msg.reserve_offset = LIGHT_EVENT_OFFSET; + + ret = light_aon_call_rpc(ipc, &event->msg, true); + if (ret) + dev_err(light_event->dev, "failed to set aon reservemem\n"); + + return ret; +} + +int light_event_set_rebootmode(enum light_rebootmode_index mode) +{ + int ret; + + if (!light_event->init) + return -EINVAL; + + ret = regmap_write(light_event->aon_iram, LIGHT_EVENT_OFFSET, mode); + if (ret) { + dev_err(light_event->dev, "set rebootmode failed,ret:%d\n", ret); + return ret; + } + + dev_info(light_event->dev, "set rebootmode:0x%x\n", mode); + + return 0; +} +EXPORT_SYMBOL_GPL(light_event_set_rebootmode); + +int light_event_get_rebootmode(enum light_rebootmode_index *mode) +{ + int ret; + + if (!light_event->init) + return -EINVAL; + + ret = regmap_read(light_event->aon_iram, LIGHT_EVENT_OFFSET, mode); + if (ret) { + dev_err(light_event->dev, "get rebootmode failed,ret:%d\n", ret); + return ret; + } + dev_dbg(light_event->dev, "%s get rebootmode:0x%x\n", __func__, *mode); + + return 0; +} +EXPORT_SYMBOL_GPL(light_event_get_rebootmode); + +static int light_event_check_powerup(void) +{ + enum light_rebootmode_index mode; + unsigned int val; + int ret; + + if (!light_event->init) + return -EINVAL; + + ret = regmap_read(light_event->aon_iram, LIGHT_EVENT_CHECK, &val); + if (ret) { + dev_err(light_event->dev, "get magicnum failed,ret:%d\n", ret); + return ret; + } + ret = regmap_read(light_event->aon_iram, LIGHT_EVENT_OFFSET, &mode); + if (ret) { + dev_err(light_event->dev, "get rebootmode failed,ret:%d\n", ret); + return ret; + } + dev_info(light_event->dev, "magicnum:0x%x mode:0x%x\n", val, mode); + + /* powerup means SRAM data is randam */ + if (val != LIGHT_EVENT_MAGIC && mode != LIGHT_EVENT_PMIC_ONKEY) + light_event_set_rebootmode(LIGHT_EVENT_PMIC_POWERUP); + + ret = regmap_write(light_event->aon_iram, LIGHT_EVENT_CHECK, LIGHT_EVENT_MAGIC); + if (ret) { + dev_err(light_event->dev, "set magicnum failed,ret:%d\n", ret); + return ret; + } + + return 0; +} + +static ssize_t rebootmode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + enum light_rebootmode_index mode; + + if (kstrtouint(buf, 0, &mode) < 0) + return -EINVAL; + light_event_set_rebootmode(mode); + + return count; +} + +static ssize_t +rebootmode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + enum light_rebootmode_index mode; + + light_event_get_rebootmode(&mode); + + return sprintf(buf, "0x%x\n", mode); +} +static DEVICE_ATTR_RW(rebootmode); + +static struct attribute *event_attrs[] = { + &dev_attr_rebootmode.attr, + NULL +}; +ATTRIBUTE_GROUPS(event); + +static int light_event_open(struct inode *inode, struct file *f) +{ + return 0; +} + +static int light_event_release(struct inode *inode, struct file *f) +{ + return 0; +} + +static long light_event_ioctl(struct file *f, unsigned int ioctl, + unsigned long arg) +{ + return 0; +} + +static const struct file_operations light_event_fops = { + .owner = THIS_MODULE, + .release = light_event_release, + .open = light_event_open, + .unlocked_ioctl = light_event_ioctl, +}; + +static struct miscdevice light_event_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "light-event", + .fops = &light_event_fops, +}; + +static int light_event_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct light_event *thead; + int ret; + + thead = devm_kzalloc(&pdev->dev, sizeof(*thead), GFP_KERNEL); + if (!thead) + return -ENOMEM; + light_event = thead; + + ret = light_aon_get_handle(&(thead->ipc_handle)); + if (ret == -EPROBE_DEFER) + return ret; + + platform_set_drvdata(pdev, thead); + thead->dev = &pdev->dev; + + thead->aon_iram = syscon_regmap_lookup_by_phandle(np, "aon-iram-regmap"); + if (IS_ERR(thead->aon_iram)) + return PTR_ERR(thead->aon_iram); + + ret = misc_register(&light_event_misc); + if (ret < 0) + return ret; + + ret = light_event_aon_reservemem(thead); + if (ret) { + dev_err(dev, "set aon reservemem failed!\n"); + return -EPERM; + } + thead->init = true; + + ret = light_event_check_powerup(); + if (ret) { + dev_err(dev, "check powerup failed!\n"); + return -EPERM; + } + dev_info(dev, "light-event driver init successfully\n"); + + return 0; +} + +static int light_event_remove(struct platform_device *pdev) +{ + misc_deregister(&light_event_misc); + + return 0; +} + +static const struct of_device_id light_event_of_match[] = { + { .compatible = "thead,light-event" }, + { }, +}; +MODULE_DEVICE_TABLE(of, light_event_of_match); + +static struct platform_driver light_event_driver = { + .probe = light_event_probe, + .remove = light_event_remove, + .driver = { + .name = "light-event", + .dev_groups = event_groups, + .of_match_table = light_event_of_match, + }, +}; + +module_platform_driver(light_event_driver); + +MODULE_DESCRIPTION("light-event driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 76dfce326..36c7d5b1c 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -29,6 +29,7 @@ #include #include #include +#include #define WDOG_CONTROL_REG_OFFSET 0x00 #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 @@ -376,6 +377,7 @@ static irqreturn_t dw_wdt_irq(int irq, void *devid) pr_warn("watchdog irq enter. however status is 0\n"); return IRQ_NONE; } + light_event_set_rebootmode(LIGHT_EVENT_SW_WATCHDOG); WARN(1, "watchdog app was stuck! watchdog pretimeout event\n"); watchdog_notify_pretimeout(&dw_wdt->wdd); diff --git a/drivers/watchdog/light_wdt.c b/drivers/watchdog/light_wdt.c index 41922940e..d5fa5f77c 100644 --- a/drivers/watchdog/light_wdt.c +++ b/drivers/watchdog/light_wdt.c @@ -17,6 +17,7 @@ #include #include #include +#include #define DRV_NAME "light-wdt" @@ -189,6 +190,7 @@ static int light_wdt_restart(struct watchdog_device *wdd, unsigned long action, pr_debug("[%s,%d]: Inform aon to restart the whole system....\n", __func__, __LINE__); + light_event_set_rebootmode(LIGHT_EVENT_SW_REBOOT); ret = light_aon_call_rpc(ipc, &wdt_dev->msg, false); if (ret) return ret; diff --git a/include/dt-bindings/pinctrl/light-fm-audio-pinctrl.h b/include/dt-bindings/pinctrl/light-fm-audio-pinctrl.h new file mode 100644 index 000000000..1f92d75d5 --- /dev/null +++ b/include/dt-bindings/pinctrl/light-fm-audio-pinctrl.h @@ -0,0 +1,38 @@ +#ifndef _LIGHT_FM_AUDIO_IO_PINCTRL_H +#define _LIGHT_FM_AUDIO_IO_PINCTRL_H + +#define FM_AUDIO_IO_PA0 0 +#define FM_AUDIO_IO_PA1 1 +#define FM_AUDIO_IO_PA2 2 +#define FM_AUDIO_IO_PA3 3 +#define FM_AUDIO_IO_PA4 4 +#define FM_AUDIO_IO_PA5 5 +#define FM_AUDIO_IO_PA6 6 +#define FM_AUDIO_IO_PA7 7 +#define FM_AUDIO_IO_PA8 8 +#define FM_AUDIO_IO_PA9 9 +#define FM_AUDIO_IO_PA10 10 +#define FM_AUDIO_IO_PA11 11 +#define FM_AUDIO_IO_PA12 12 +#define FM_AUDIO_IO_PA13 13 +#define FM_AUDIO_IO_PA14 14 +#define FM_AUDIO_IO_PA15 15 +#define FM_AUDIO_IO_PA16 16 +#define FM_AUDIO_IO_PA17 17 +#define FM_AUDIO_IO_PA18 18 +#define FM_AUDIO_IO_PA19 19 +#define FM_AUDIO_IO_PA20 20 +#define FM_AUDIO_IO_PA21 21 +#define FM_AUDIO_IO_PA22 22 +#define FM_AUDIO_IO_PA23 23 +#define FM_AUDIO_IO_PA24 24 +#define FM_AUDIO_IO_PA25 25 +#define FM_AUDIO_IO_PA26 26 +#define FM_AUDIO_IO_PA27 27 +#define FM_AUDIO_IO_PA28 28 +#define FM_AUDIO_IO_PA29 29 +#define FM_AUDIO_IO_PA30 30 + +#define AUDIO_IO_GPIO 0xF /* Flag set to gpio */ + +#endif /* _LIGHT_FM_AUDIO_IO_PINCTRL_H */ diff --git a/include/linux/bpf.h b/include/linux/bpf.h index f33c425cd..1886f4024 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1472,6 +1472,9 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, int bpf_prog_test_run_raw_tp(struct bpf_prog *prog, const union bpf_attr *kattr, union bpf_attr __user *uattr); +int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, + const union bpf_attr *kattr, + union bpf_attr __user *uattr); bool btf_ctx_access(int off, int size, enum bpf_access_type type, const struct bpf_prog *prog, struct bpf_insn_access_aux *info); @@ -1686,6 +1689,13 @@ static inline int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, return -ENOTSUPP; } +static inline int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, + const union bpf_attr *kattr, + union bpf_attr __user *uattr) +{ + return -ENOTSUPP; +} + static inline void bpf_map_put(struct bpf_map *map) { } diff --git a/include/linux/firmware/thead/ipc.h b/include/linux/firmware/thead/ipc.h index 7e67dfdad..dd23f3201 100644 --- a/include/linux/firmware/thead/ipc.h +++ b/include/linux/firmware/thead/ipc.h @@ -36,6 +36,7 @@ enum light_aon_misc_func { LIGHT_AON_MISC_FUNC_WDG_POWER_OFF = 9, LIGHT_AON_MISC_FUNC_AON_WDT_ON = 10, LIGHT_AON_MISC_FUNC_AON_WDT_OFF = 11, + LIGHT_AON_MISC_FUNC_AON_RESERVE_MEM = 12, }; enum light_aon_pm_func { diff --git a/include/linux/firmware/thead/light_event.h b/include/linux/firmware/thead/light_event.h new file mode 100644 index 000000000..a4f99d41c --- /dev/null +++ b/include/linux/firmware/thead/light_event.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LIGHT_EVENT_H +#define _LIGHT_EVENT_H + +enum light_rebootmode_index { + /* C902 event rebootmode */ + LIGHT_EVENT_PMIC_RESET = 0x0, + LIGHT_EVENT_PMIC_ONKEY, + LIGHT_EVENT_PMIC_POWERUP, + + /* C910 event rebootmode */ + LIGHT_EVENT_SW_REBOOT = 0x20, + LIGHT_EVENT_SW_WATCHDOG, + LIGHT_EVENT_SW_PANIC, + LIGHT_EVENT_SW_HANG, + LIGHT_EVENT_MAX, +}; + +#if IS_ENABLED(CONFIG_LIGHT_REBOOTMODE) +extern int light_event_set_rebootmode(enum light_rebootmode_index mode); +extern int light_event_get_rebootmode(enum light_rebootmode_index *mode); +#else +static int light_event_set_rebootmode(enum light_rebootmode_index mode) +{ + return 0; +} +static int light_event_get_rebootmode(enum light_rebootmode_index *mode) +{ + *mode = LIGHT_EVENT_MAX; + + return 0; +} +#endif + +#endif diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 0f39fdcb2..2a2340238 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -5007,7 +5007,10 @@ struct bpf_pidns_info { /* User accessible data for SK_LOOKUP programs. Add new fields at the end. */ struct bpf_sk_lookup { - __bpf_md_ptr(struct bpf_sock *, sk); /* Selected socket */ + union { + __bpf_md_ptr(struct bpf_sock *, sk); /* Selected socket */ + __u64 cookie; /* Non-zero if socket was selected in PROG_TEST_RUN */ + }; __u32 family; /* Protocol family (AF_INET, AF_INET6) */ __u32 protocol; /* IP protocol (IPPROTO_TCP, IPPROTO_UDP) */ diff --git a/kernel/panic.c b/kernel/panic.c index 332736a72..5acc7d5b3 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -32,6 +32,7 @@ #include #include #include +#include #define PANIC_TIMER_STEP 100 #define PANIC_BLINK_SPD 18 @@ -182,7 +183,11 @@ void panic(const char *fmt, ...) int state = 0; int old_cpu, this_cpu; bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers; + enum light_rebootmode_index mode; + if (!light_event_get_rebootmode(&mode) && + mode != LIGHT_EVENT_SW_WATCHDOG) + light_event_set_rebootmode(LIGHT_EVENT_SW_PANIC); /* * Disable local interrupts. This will prevent panic_smp_self_stop * from deadlocking the first cpu that invokes the panic, since diff --git a/kernel/softirq.c b/kernel/softirq.c index a6da60be6..d3da7f6b8 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -328,10 +328,9 @@ restart: goto restart; } -#ifdef CONFIG_RT_SOFTINT_OPTIMIZATION if (pending | deferred) wakeup_softirqd(); -#endif + lockdep_softirq_end(in_hardirq); account_irq_exit_time(current); __local_bh_enable(SOFTIRQ_OFFSET); diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index eb684f31f..194616eb0 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -10,20 +10,86 @@ #include #include #include +#include #include #include +#include #define CREATE_TRACE_POINTS #include +struct bpf_test_timer { + enum { NO_PREEMPT, NO_MIGRATE } mode; + u32 i; + u64 time_start, time_spent; +}; + +static void bpf_test_timer_enter(struct bpf_test_timer *t) + __acquires(rcu) +{ + rcu_read_lock(); + if (t->mode == NO_PREEMPT) + preempt_disable(); + else + migrate_disable(); + + t->time_start = ktime_get_ns(); +} + +static void bpf_test_timer_leave(struct bpf_test_timer *t) + __releases(rcu) +{ + t->time_start = 0; + + if (t->mode == NO_PREEMPT) + preempt_enable(); + else + migrate_enable(); + rcu_read_unlock(); +} + +static bool bpf_test_timer_continue(struct bpf_test_timer *t, u32 repeat, int *err, u32 *duration) + __must_hold(rcu) +{ + t->i++; + if (t->i >= repeat) { + /* We're done. */ + t->time_spent += ktime_get_ns() - t->time_start; + do_div(t->time_spent, t->i); + *duration = t->time_spent > U32_MAX ? U32_MAX : (u32)t->time_spent; + *err = 0; + goto reset; + } + + if (signal_pending(current)) { + /* During iteration: we've been cancelled, abort. */ + *err = -EINTR; + goto reset; + } + + if (need_resched()) { + /* During iteration: we need to reschedule between runs. */ + t->time_spent += ktime_get_ns() - t->time_start; + bpf_test_timer_leave(t); + cond_resched(); + bpf_test_timer_enter(t); + } + + /* Do another round. */ + return true; + +reset: + t->i = 0; + return false; +} + static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, u32 *retval, u32 *time, bool xdp) { struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE] = { NULL }; + struct bpf_test_timer t = { NO_MIGRATE }; enum bpf_cgroup_storage_type stype; - u64 time_start, time_spent = 0; - int ret = 0; - u32 i; + int ret; for_each_cgroup_storage_type(stype) { storage[stype] = bpf_cgroup_storage_alloc(prog, stype); @@ -38,10 +104,8 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, if (!repeat) repeat = 1; - rcu_read_lock(); - migrate_disable(); - time_start = ktime_get_ns(); - for (i = 0; i < repeat; i++) { + bpf_test_timer_enter(&t); + do { ret = bpf_cgroup_storage_set(storage); if (ret) break; @@ -53,29 +117,8 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, bpf_cgroup_storage_unset(); - if (signal_pending(current)) { - ret = -EINTR; - break; - } - - if (need_resched()) { - time_spent += ktime_get_ns() - time_start; - migrate_enable(); - rcu_read_unlock(); - - cond_resched(); - - rcu_read_lock(); - migrate_disable(); - time_start = ktime_get_ns(); - } - } - time_spent += ktime_get_ns() - time_start; - migrate_enable(); - rcu_read_unlock(); - - do_div(time_spent, repeat); - *time = time_spent > U32_MAX ? U32_MAX : (u32)time_spent; + } while (bpf_test_timer_continue(&t, repeat, &ret, time)); + bpf_test_timer_leave(&t); for_each_cgroup_storage_type(stype) bpf_cgroup_storage_free(storage[stype]); @@ -688,18 +731,17 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, const union bpf_attr *kattr, union bpf_attr __user *uattr) { + struct bpf_test_timer t = { NO_PREEMPT }; u32 size = kattr->test.data_size_in; struct bpf_flow_dissector ctx = {}; u32 repeat = kattr->test.repeat; struct bpf_flow_keys *user_ctx; struct bpf_flow_keys flow_keys; - u64 time_start, time_spent = 0; const struct ethhdr *eth; unsigned int flags = 0; u32 retval, duration; void *data; int ret; - u32 i; if (prog->type != BPF_PROG_TYPE_FLOW_DISSECTOR) return -EINVAL; @@ -735,39 +777,15 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, ctx.data = data; ctx.data_end = (__u8 *)data + size; - rcu_read_lock(); - preempt_disable(); - time_start = ktime_get_ns(); - for (i = 0; i < repeat; i++) { - retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN, - size, flags); + bpf_test_timer_enter(&t); + do { + retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN, + size, flags); + } while (bpf_test_timer_continue(&t, repeat, &ret, &duration)); + bpf_test_timer_leave(&t); - if (signal_pending(current)) { - preempt_enable(); - rcu_read_unlock(); - - ret = -EINTR; - goto out; - } - - if (need_resched()) { - time_spent += ktime_get_ns() - time_start; - preempt_enable(); - rcu_read_unlock(); - - cond_resched(); - - rcu_read_lock(); - preempt_disable(); - time_start = ktime_get_ns(); - } - } - time_spent += ktime_get_ns() - time_start; - preempt_enable(); - rcu_read_unlock(); - - do_div(time_spent, repeat); - duration = time_spent > U32_MAX ? U32_MAX : (u32)time_spent; + if (ret < 0) + goto out; ret = bpf_test_finish(kattr, uattr, &flow_keys, sizeof(flow_keys), retval, duration); @@ -780,3 +798,106 @@ out: kfree(data); return ret; } + +int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, const union bpf_attr *kattr, + union bpf_attr __user *uattr) +{ + struct bpf_test_timer t = { NO_PREEMPT }; + struct bpf_prog_array *progs = NULL; + struct bpf_sk_lookup_kern ctx = {}; + u32 repeat = kattr->test.repeat; + struct bpf_sk_lookup *user_ctx; + u32 retval, duration; + int ret = -EINVAL; + + if (prog->type != BPF_PROG_TYPE_SK_LOOKUP) + return -EINVAL; + + if (kattr->test.flags || kattr->test.cpu) + return -EINVAL; + + if (kattr->test.data_in || kattr->test.data_size_in || kattr->test.data_out || + kattr->test.data_size_out) + return -EINVAL; + + if (!repeat) + repeat = 1; + + user_ctx = bpf_ctx_init(kattr, sizeof(*user_ctx)); + if (IS_ERR(user_ctx)) + return PTR_ERR(user_ctx); + + if (!user_ctx) + return -EINVAL; + + if (user_ctx->sk) + goto out; + + if (!range_is_zero(user_ctx, offsetofend(typeof(*user_ctx), local_port), sizeof(*user_ctx))) + goto out; + + if (user_ctx->local_port > U16_MAX || user_ctx->remote_port > U16_MAX) { + ret = -ERANGE; + goto out; + } + + ctx.family = (u16)user_ctx->family; + ctx.protocol = (u16)user_ctx->protocol; + ctx.dport = (u16)user_ctx->local_port; + ctx.sport = (__force __be16)user_ctx->remote_port; + + switch (ctx.family) { + case AF_INET: + ctx.v4.daddr = (__force __be32)user_ctx->local_ip4; + ctx.v4.saddr = (__force __be32)user_ctx->remote_ip4; + break; + +#if IS_ENABLED(CONFIG_IPV6) + case AF_INET6: + ctx.v6.daddr = (struct in6_addr *)user_ctx->local_ip6; + ctx.v6.saddr = (struct in6_addr *)user_ctx->remote_ip6; + break; +#endif + + default: + ret = -EAFNOSUPPORT; + goto out; + } + + progs = bpf_prog_array_alloc(1, GFP_KERNEL); + if (!progs) { + ret = -ENOMEM; + goto out; + } + + progs->items[0].prog = prog; + + bpf_test_timer_enter(&t); + do { + ctx.selected_sk = NULL; + retval = BPF_PROG_SK_LOOKUP_RUN_ARRAY(progs, ctx, BPF_PROG_RUN); + } while (bpf_test_timer_continue(&t, repeat, &ret, &duration)); + bpf_test_timer_leave(&t); + + if (ret < 0) + goto out; + + user_ctx->cookie = 0; + if (ctx.selected_sk) { + if (ctx.selected_sk->sk_reuseport && !ctx.no_reuseport) { + ret = -EOPNOTSUPP; + goto out; + } + + user_ctx->cookie = sock_gen_cookie(ctx.selected_sk); + } + + ret = bpf_test_finish(kattr, uattr, NULL, 0, retval, duration); + if (!ret) + ret = bpf_ctx_finish(kattr, uattr, user_ctx, sizeof(*user_ctx)); + +out: + bpf_prog_array_free(progs); + kfree(user_ctx); + return ret; +} diff --git a/net/core/filter.c b/net/core/filter.c index 7cb594602..5ee343c6a 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -10295,6 +10295,7 @@ static u32 sk_lookup_convert_ctx_access(enum bpf_access_type type, } const struct bpf_prog_ops sk_lookup_prog_ops = { + .test_run = bpf_prog_test_run_sk_lookup, }; const struct bpf_verifier_ops sk_lookup_verifier_ops = { diff --git a/sound/soc/codecs/es7210.c b/sound/soc/codecs/es7210.c index 8d5d3a245..402387ec6 100644 --- a/sound/soc/codecs/es7210.c +++ b/sound/soc/codecs/es7210.c @@ -46,8 +46,11 @@ #define MIC_CHN_2 2 #define ES7210_TDM_ENABLE ENABLE -#define ES7210_CHANNELS_MAX MIC_CHN_2 +//#define ES7210_CHANNELS_MAX MIC_CHN_8 +static int ADC_DEV_MAXNUM = 1; +static int ES7210_CHANNELS_MAX = 1; +#if 0 #if ES7210_CHANNELS_MAX == MIC_CHN_2 #define ADC_DEV_MAXNUM 1 #endif @@ -72,6 +75,7 @@ #if ES7210_CHANNELS_MAX == MIC_CHN_16 #define ADC_DEV_MAXNUM 4 #endif +#endif #define ES7210_TDM_1LRCK_DSPA 0 #define ES7210_TDM_1LRCK_DSPB 1 @@ -83,7 +87,7 @@ #define ES7210_TDM_NLRCK_LJ 7 #define ES7210_NORMAL_I2S 8 -#define ES7210_WORK_MODE ES7210_NORMAL_I2S +#define ES7210_WORK_MODE ES7210_TDM_1LRCK_DSPB #define ES7210_I2C_BUS_NUM 1 @@ -100,26 +104,16 @@ #define RATIO_128 0x01 #define RATIO_64 0x41 /* mclk from bclk pin */ -#define ES7210_MCLK_LRCK_RATIO RATIO_64 +#define ES7210_MCLK_LRCK_RATIO RATIO_256 // mclk=sclk. mclk/lrck = sclk / lrck = 16bit*4slot=RATIO_64. 32bit*4slot=16bit*8slot=RATIO_128 32bit*8slot=RATIO_256 -struct i2c_client *i2c_clt1[ADC_DEV_MAXNUM]; +struct i2c_client *i2c_clt1[4] = {0}; struct es7210_priv *resume_es7210 = NULL; -/* codec private data */ -struct es7210_priv { - struct regmap *regmap; - struct i2c_client *i2c_client; - unsigned int dmic_enable; - unsigned int sysclk; - struct clk *mclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; - unsigned int tdm_mode; - struct delayed_work pcm_pop_work; -}; -struct snd_soc_component *tron_codec1[ADC_DEV_MAXNUM]; +struct snd_soc_component *tron_codec1[4]; int es7210_init_reg = 0; +int es7210_hw_param_reg = 0; static int es7210_codec_num = 0; static const struct regmap_config es7210_regmap_config = { @@ -162,9 +156,6 @@ static const struct es7210_reg_config es7210_tdm_reg_fmt_cfg[] = { }; static const struct es7210_reg_config es7210_tdm_reg_common_cfg2[] = { { 0x40, 0xC3 }, - { 0x14, 0x3C }, - { 0x15, 0x3C }, - { 0x17, 0x00 }, { 0x41, 0x70 }, { 0x42, 0x70 }, { 0x43, 0x1E }, @@ -286,6 +277,150 @@ static int es7210_set_dai_fmt(struct snd_soc_dai *codec_dai, { return 0; } +static void es7210_tdm_init_ratio(struct es7210_priv *priv) +{ + int cnt, channel, i; + + if (priv->tdm_mode == ES7210_TDM_1LRCK_DSPB) { + if (priv->pcm_format == SNDRV_PCM_FORMAT_S16_LE) { + priv->mclk_lrck_ratio = RATIO_128; + } else if (priv->pcm_format == SNDRV_PCM_FORMAT_S32_LE) { + priv->mclk_lrck_ratio = RATIO_256; + } else { + pr_err("unsupported format in es7210 tdm mode!"); + } + } else { // ratio remain default for i2s + priv->mclk_lrck_ratio = RATIO_768; + } + + switch (priv->tdm_mode) { + case ES7210_TDM_1LRCK_DSPA: + case ES7210_TDM_1LRCK_DSPB: + case ES7210_TDM_1LRCK_I2S: + case ES7210_TDM_1LRCK_LJ: + case ES7210_NORMAL_I2S: + /* + * to set internal mclk + * here, we assume that cpu/soc always provides + * 256FS i2s clock + * to es7210. + * dll bypassed, use clock doubler to get double + * frequency for + * internal modem which need + * 512FS clock. the clk divider ratio is 1. + * user must modify the setting of register0x02 + * according to FS + * ratio provided by CPU/SOC. + */ + + for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) { + es7210_write(ES7210_MCLK_CTL_REG02, + priv->mclk_lrck_ratio, i2c_clt1[cnt]); + } + // es7210_multi_chips_write(ES7210_MCLK_CTL_REG02, + // 0xc1); + break; + case ES7210_TDM_NLRCK_DSPA: + case ES7210_TDM_NLRCK_DSPB: + case ES7210_TDM_NLRCK_I2S: + case ES7210_TDM_NLRCK_LJ: + /* + * Here to set TDM format for DSP-A with + * multiple LRCK TDM mode + */ + channel = ES7210_CHANNELS_MAX; + /* + * Set the microphone numbers in array + */ + switch (channel) { + case 2: + /* ES7210_CHANNELS_MAX=2 */ + es7210_multi_chips_write( + ES7210_MODE_CFG_REG08, 0x10); + break; + case 4: + /* ES7210_CHANNELS_MAX=4 */ + es7210_multi_chips_write( + ES7210_MODE_CFG_REG08, 0x20); + break; + case 6: + /* ES7210_CHANNELS_MAX=6 */ + es7210_multi_chips_write( + ES7210_MODE_CFG_REG08, 0x30); + break; + case 8: + /* ES7210_CHANNELS_MAX=8 */ + es7210_multi_chips_write( + ES7210_MODE_CFG_REG08, 0x40); + break; + case 10: + /* ES7210_CHANNELS_MAX=10 */ + es7210_multi_chips_write( + ES7210_MODE_CFG_REG08, 0x50); + break; + case 12: + /* ES7210_CHANNELS_MAX=12 */ + es7210_multi_chips_write( + ES7210_MODE_CFG_REG08, 0x60); + break; + case 14: + /* ES7210_CHANNELS_MAX=14 */ + es7210_multi_chips_write( + ES7210_MODE_CFG_REG08, 0x70); + break; + case 16: + /* ES7210_CHANNELS_MAX=16 */ + es7210_multi_chips_write( + ES7210_MODE_CFG_REG08, 0x80); + break; + default: + break; + } + /* + * to set internal mclk + * here, we assume that cpu/soc always provides + * 256FS i2s clock + * to es7210 and there is four + * es7210 devices in tdm link. so the + * internal FS in es7210 + * is only FS/4; + * dll bypassed, clock doubler bypassed. the clk + * divider ratio is + * 2. so the clock of internal + * modem equals to (256FS / (FS/4) / 2) * FS + * = 512FS + * user must modify the setting of register0x02 + * according to FS + * ratio provided by CPU/SOC. + */ + + es7210_multi_chips_write(ES7210_MCLK_CTL_REG02, + priv->mclk_lrck_ratio);// NFS MODE:RATIO_768 ,12.288M/48K(16K 6 CH),12.288M/64K(16K 8 CH) + break; + default: + /* + * to set internal mclk for normal mode + * here, we assume that cpu/soc always provides + * 256FS i2s clock + * to es7210. + * dll bypassed, use clock doubler to get double + * frequency for + * internal modem which need + * 512FS clock. the clk divider ratio is 1. + * user must modify the setting of register0x02 + * according to FS + * ratio provided by CPU/SOC. + */ + for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) { + es7210_write(ES7210_MCLK_CTL_REG02, + priv->mclk_lrck_ratio, i2c_clt1[cnt]); + } + + break; + } + return; +} + /* * to initialize es7210 for tdm mode */ @@ -302,9 +437,7 @@ static void es7210_tdm_init_codec(u8 mode) es7210_tdm_reg_common_cfg1[cnt].reg_v); } if(DOUBLESPEED) - es7210_multi_chips_write(ES7210_MODE_CFG_REG08, 0x16); - else - es7210_multi_chips_write(ES7210_MODE_CFG_REG08, 0x14); + es7210_multi_chips_update_bits(ES7210_MODE_CFG_REG08, 0x02, 0x02); switch (mode) { case ES7210_TDM_1LRCK_DSPA: @@ -324,7 +457,7 @@ static void es7210_tdm_init_codec(u8 mode) */ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) { es7210_write(ES7210_SDP_CFG1_REG11, - 0x83, i2c_clt1[cnt]); + 0x73, i2c_clt1[cnt]); es7210_write(ES7210_SDP_CFG2_REG12, 0x01, i2c_clt1[cnt]); } @@ -385,7 +518,7 @@ static void es7210_tdm_init_codec(u8 mode) */ for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) { es7210_write(ES7210_SDP_CFG1_REG11, - 0x83, i2c_clt1[cnt]); + 0x73, i2c_clt1[cnt]); } for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) { if (cnt == 0) { @@ -491,134 +624,7 @@ static void es7210_tdm_init_codec(u8 mode) es7210_tdm_reg_common_cfg2[cnt].reg_addr, es7210_tdm_reg_common_cfg2[cnt].reg_v); } - es7210_multi_chips_write(0x4, 0x00); - es7210_multi_chips_write(0x5, 0x40); - switch (mode) { - case ES7210_TDM_1LRCK_DSPA: - case ES7210_TDM_1LRCK_DSPB: - case ES7210_TDM_1LRCK_I2S: - case ES7210_TDM_1LRCK_LJ: - case ES7210_NORMAL_I2S: - /* - * to set internal mclk - * here, we assume that cpu/soc always provides - * 256FS i2s clock - * to es7210. - * dll bypassed, use clock doubler to get double - * frequency for - * internal modem which need - * 512FS clock. the clk divider ratio is 1. - * user must modify the setting of register0x02 - * according to FS - * ratio provided by CPU/SOC. - */ - - for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) { - es7210_write(ES7210_MCLK_CTL_REG02, - ES7210_MCLK_LRCK_RATIO, i2c_clt1[cnt]); - } - // es7210_multi_chips_write(ES7210_MCLK_CTL_REG02, - // 0xc1); - break; - case ES7210_TDM_NLRCK_DSPA: - case ES7210_TDM_NLRCK_DSPB: - case ES7210_TDM_NLRCK_I2S: - case ES7210_TDM_NLRCK_LJ: - /* - * Here to set TDM format for DSP-A with - * multiple LRCK TDM mode - */ - channel = ES7210_CHANNELS_MAX; - /* - * Set the microphone numbers in array - */ - switch (channel) { - case 2: - /* ES7210_CHANNELS_MAX=2 */ - es7210_multi_chips_write( - ES7210_MODE_CFG_REG08, 0x10); - break; - case 4: - /* ES7210_CHANNELS_MAX=4 */ - es7210_multi_chips_write( - ES7210_MODE_CFG_REG08, 0x20); - break; - case 6: - /* ES7210_CHANNELS_MAX=6 */ - es7210_multi_chips_write( - ES7210_MODE_CFG_REG08, 0x30); - break; - case 8: - /* ES7210_CHANNELS_MAX=8 */ - es7210_multi_chips_write( - ES7210_MODE_CFG_REG08, 0x40); - break; - case 10: - /* ES7210_CHANNELS_MAX=10 */ - es7210_multi_chips_write( - ES7210_MODE_CFG_REG08, 0x50); - break; - case 12: - /* ES7210_CHANNELS_MAX=12 */ - es7210_multi_chips_write( - ES7210_MODE_CFG_REG08, 0x60); - break; - case 14: - /* ES7210_CHANNELS_MAX=14 */ - es7210_multi_chips_write( - ES7210_MODE_CFG_REG08, 0x70); - break; - case 16: - /* ES7210_CHANNELS_MAX=16 */ - es7210_multi_chips_write( - ES7210_MODE_CFG_REG08, 0x80); - break; - default: - break; - } - /* - * to set internal mclk - * here, we assume that cpu/soc always provides - * 256FS i2s clock - * to es7210 and there is four - * es7210 devices in tdm link. so the - * internal FS in es7210 - * is only FS/4; - * dll bypassed, clock doubler bypassed. the clk - * divider ratio is - * 2. so the clock of internal - * modem equals to (256FS / (FS/4) / 2) * FS - * = 512FS - * user must modify the setting of register0x02 - * according to FS - * ratio provided by CPU/SOC. - */ - - es7210_multi_chips_write(ES7210_MCLK_CTL_REG02, - ES7210_MCLK_LRCK_RATIO);// NFS MODE:RATIO_768 ,12.288M/48K(16K 6 CH),12.288M/64K(16K 8 CH) - break; - default: - /* - * to set internal mclk for normal mode - * here, we assume that cpu/soc always provides - * 256FS i2s clock - * to es7210. - * dll bypassed, use clock doubler to get double - * frequency for - * internal modem which need - * 512FS clock. the clk divider ratio is 1. - * user must modify the setting of register0x02 - * according to FS - * ratio provided by CPU/SOC. - */ - for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) { - es7210_write(ES7210_MCLK_CTL_REG02, - ES7210_MCLK_LRCK_RATIO, i2c_clt1[cnt]); - } - - break; - } for (cnt = 0; cnt < sizeof(es7210_tdm_reg_common_cfg3) / sizeof(es7210_tdm_reg_common_cfg3[0]); @@ -651,52 +657,53 @@ static void es7210_tdm_init_codec(u8 mode) } if (i == 1) { /* set second es7210 PGA GAIN */ - es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_MIC_GAIN, i2c_clt1[i]); - es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_MIC_GAIN, i2c_clt1[i]); - es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_MIC_GAIN, i2c_clt1[i]); - es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_MIC_GAIN, i2c_clt1[i]); } if (i == 2) { /* set third es7210 PGA GAIN */ - es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_MIC_GAIN, i2c_clt1[i]); - es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_MIC_GAIN, i2c_clt1[i]); - es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_MIC_GAIN, i2c_clt1[i]); - es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_MIC_GAIN, i2c_clt1[i]); } if (i == 3) { /* set third es7210 PGA GAIN */ - es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC1_GAIN_REG43, ES7210_MIC_GAIN, i2c_clt1[i]); - es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC2_GAIN_REG44, ES7210_MIC_GAIN, i2c_clt1[i]); - es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC3_GAIN_REG45, ES7210_MIC_GAIN, i2c_clt1[i]); - es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_AEC_GAIN, + es7210_write(ES7210_MIC4_GAIN_REG46, ES7210_MIC_GAIN, i2c_clt1[i]); } } } static void es7210_unmute(void) { - printk("enter into %s\n", __func__); es7210_multi_chips_update_bits(ES7210_ADC34_MUTE_REG14, 0x03, 0x00); es7210_multi_chips_update_bits(ES7210_ADC12_MUTE_REG15, 0x03, 0x00); + es7210_multi_chips_update_bits(ES7210_MIC1_GAIN_REG43, 0x1f, ES7210_MIC_GAIN); + es7210_multi_chips_update_bits(ES7210_MIC2_GAIN_REG44, 0x1f, ES7210_MIC_GAIN); + es7210_multi_chips_update_bits(ES7210_MIC3_GAIN_REG45, 0x1f, ES7210_MIC_GAIN); + es7210_multi_chips_update_bits(ES7210_MIC4_GAIN_REG46, 0x1f, ES7210_MIC_GAIN); } static void pcm_pop_work_events(struct work_struct *work) { - printk("enter into %s\n", __func__); es7210_unmute(); - es7210_init_reg = 1; } static int es7210_pcm_startup(struct snd_pcm_substream *substream, @@ -706,6 +713,7 @@ static int es7210_pcm_startup(struct snd_pcm_substream *substream, struct es7210_priv *es7210 = snd_soc_component_get_drvdata(component); if (es7210_init_reg == 0) { + es7210_init_reg = 1; schedule_delayed_work(&es7210->pcm_pop_work, msecs_to_jiffies(100)); } return 0; @@ -714,13 +722,22 @@ static int es7210_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - + struct snd_soc_component *component = dai->component; + struct es7210_priv *priv = snd_soc_component_get_drvdata(component); int i; + if (es7210_hw_param_reg == 1 && params_format(params) == priv->pcm_format) { + return 0; + } + + es7210_hw_param_reg = 1; + priv->pcm_format = params_format(params); + es7210_tdm_init_ratio(priv); + es7210_multi_chips_update_bits(ES7210_RESET_CTL_REG00, 0x30, 0x30); for (i = 0; i < ADC_DEV_MAXNUM; i++) { /* set es7210 bit size */ - switch (params_format(params)) { + switch (priv->pcm_format) { case SNDRV_PCM_FORMAT_S16_LE: es7210_update_bits(0x11, 0xE0, 0x60, i2c_clt1[i]); @@ -753,6 +770,7 @@ static int es7210_pcm_hw_params(struct snd_pcm_substream *substream, default: break; } + return 0; } @@ -767,7 +785,7 @@ static struct snd_soc_dai_ops es7210_ops = { .set_fmt = es7210_set_dai_fmt, .set_sysclk = es7210_set_dai_sysclk, }; -#if ES7210_CHANNELS_MAX > 0 + static struct snd_soc_dai_driver es7210_dai0 = { .name = "ES7210 ADC 0", .capture = { @@ -780,8 +798,8 @@ static struct snd_soc_dai_driver es7210_dai0 = { .ops = &es7210_ops, .symmetric_rates = 1, }; -#endif -#if ES7210_CHANNELS_MAX > 4 + + static struct snd_soc_dai_driver es7210_dai1 = { .name = "ES7210 4CH ADC 1", .capture = { @@ -794,8 +812,7 @@ static struct snd_soc_dai_driver es7210_dai1 = { .ops = &es7210_ops, .symmetric_rates = 1, }; -#endif -#if ES7210_CHANNELS_MAX > 8 + static struct snd_soc_dai_driver es7210_dai2 = { .name = "ES7210 4CH ADC 2", .capture = { @@ -808,8 +825,7 @@ static struct snd_soc_dai_driver es7210_dai2 = { .ops = &es7210_ops, .symmetric_rates = 1, }; -#endif -#if ES7210_CHANNELS_MAX > 12 + static struct snd_soc_dai_driver es7210_dai3 = { .name = "ES7210 4CH ADC 3", .capture = { @@ -822,20 +838,12 @@ static struct snd_soc_dai_driver es7210_dai3 = { .ops = &es7210_ops, .symmetric_rates = 1, }; -#endif + static struct snd_soc_dai_driver *es7210_dai[] = { -#if ES7210_CHANNELS_MAX > 0 &es7210_dai0, -#endif -#if ES7210_CHANNELS_MAX > 4 &es7210_dai1, -#endif -#if ES7210_CHANNELS_MAX > 8 &es7210_dai2, -#endif -#if ES7210_CHANNELS_MAX > 12 &es7210_dai3, -#endif }; static int es7210_suspend(struct snd_soc_component *component) @@ -886,7 +894,7 @@ static int es7210_resume(struct snd_soc_component *component) static int es7210_probe(struct snd_soc_component *component) { struct es7210_priv *es7210 = snd_soc_component_get_drvdata(component); - u8 val, val1; + u8 val, val1, cnt; int ret = 0; resume_es7210 = es7210; @@ -896,15 +904,18 @@ static int es7210_probe(struct snd_soc_component *component) } tron_codec1[es7210_codec_num++] = component; - INIT_DELAYED_WORK(&es7210->pcm_pop_work, pcm_pop_work_events); - /* es7210 chip id */ - ret = es7210_read(0x3D, &val, i2c_clt1[0]); - ret = es7210_read(0x3E, &val1, i2c_clt1[0]); - if (ret < 0) { - pr_err("%s: read chipid failed %d\n", __func__, ret); - goto exit_i2c_check_id_failed; - } + INIT_DELAYED_WORK(&es7210->pcm_pop_work, pcm_pop_work_events); + + for (cnt = 0; cnt < ADC_DEV_MAXNUM; cnt++) { + /* es7210 chip id */ + ret = es7210_read(0x3D, &val, i2c_clt1[cnt]); + ret = es7210_read(0x3E, &val1, i2c_clt1[cnt]); + if (ret < 0) { + pr_err("%s: read chipid failed %d\n", __func__, ret); + goto exit_i2c_check_id_failed; + } + } es7210_tdm_init_codec(es7210->tdm_mode); @@ -934,7 +945,6 @@ static int es7210_set_bias_level(struct snd_soc_component *component, static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, 0, 300, 0); -#if ES7210_CHANNELS_MAX > 0 static int es7210_micboost1_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1065,12 +1075,11 @@ static int es7210_adc4_mute_get(struct snd_kcontrol *kcontrol, return 0; } -#endif - -#if ES7210_CHANNELS_MAX > 4 static int es7210_micboost5_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[1] == NULL) + return 0; es7210_update_bits(0x43, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[1]); return 0; } @@ -1079,6 +1088,8 @@ static int es7210_micboost5_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[1] == NULL) + return 0; es7210_read(0x43, &val, i2c_clt1[1]); ucontrol->value.integer.value[0] = val; return 0; @@ -1086,6 +1097,8 @@ static int es7210_micboost5_setting_get(struct snd_kcontrol *kcontrol, static int es7210_micboost6_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[1] == NULL) + return 0; es7210_update_bits(0x44, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[1]); return 0; } @@ -1094,6 +1107,8 @@ static int es7210_micboost6_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[1] == NULL) + return 0; es7210_read(0x44, &val, i2c_clt1[1]); ucontrol->value.integer.value[0] = val; return 0; @@ -1101,6 +1116,8 @@ static int es7210_micboost6_setting_get(struct snd_kcontrol *kcontrol, static int es7210_micboost7_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[1] == NULL) + return 0; es7210_update_bits(0x45, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[1]); return 0; } @@ -1109,6 +1126,8 @@ static int es7210_micboost7_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[1] == NULL) + return 0; es7210_read(0x45, &val, i2c_clt1[1]); ucontrol->value.integer.value[0] = val; return 0; @@ -1116,6 +1135,8 @@ static int es7210_micboost7_setting_get(struct snd_kcontrol *kcontrol, static int es7210_micboost8_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[1] == NULL) + return 0; es7210_update_bits(0x46, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[1]); return 0; } @@ -1124,6 +1145,8 @@ static int es7210_micboost8_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[1] == NULL) + return 0; es7210_read(0x46, &val, i2c_clt1[1]); ucontrol->value.integer.value[0] = val; return 0; @@ -1131,8 +1154,10 @@ static int es7210_micboost8_setting_get(struct snd_kcontrol *kcontrol, static int es7210_adc5_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[1] == NULL) + return 0; es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x01, - ucontrol->value.integer.value[0]&0x01, i2c_clt1[1]); + ucontrol->value.integer.value[0]&0x01, i2c_clt1[1]); return 0; } @@ -1140,6 +1165,8 @@ static int es7210_adc5_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[1] == NULL) + return 0; es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[1]); ucontrol->value.integer.value[0] = val & 0x01; return 0; @@ -1148,6 +1175,8 @@ static int es7210_adc5_mute_get(struct snd_kcontrol *kcontrol, static int es7210_adc6_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[1] == NULL) + return 0; es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x02, (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[1]); return 0; @@ -1157,6 +1186,8 @@ static int es7210_adc6_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[1] == NULL) + return 0; es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[1]); ucontrol->value.integer.value[0] = (val & 0x02) >> 1; return 0; @@ -1165,6 +1196,8 @@ static int es7210_adc6_mute_get(struct snd_kcontrol *kcontrol, static int es7210_adc7_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[1] == NULL) + return 0; es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x01, ucontrol->value.integer.value[0]&0x01, i2c_clt1[1]); return 0; @@ -1174,6 +1207,8 @@ static int es7210_adc7_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[1] == NULL) + return 0; es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[1]); ucontrol->value.integer.value[0] = val & 0x01; return 0; @@ -1181,6 +1216,8 @@ static int es7210_adc7_mute_get(struct snd_kcontrol *kcontrol, static int es7210_adc8_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[1] == NULL) + return 0; es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x02, (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[1]); return 0; @@ -1190,16 +1227,18 @@ static int es7210_adc8_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[1] == NULL) + return 0; es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[1]); ucontrol->value.integer.value[0] = (val & 0x02) >> 1; return 0; } -#endif -#if ES7210_CHANNELS_MAX > 8 static int es7210_micboost9_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[2] == NULL) + return 0; es7210_update_bits(0x43, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[2]); return 0; } @@ -1208,6 +1247,8 @@ static int es7210_micboost9_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[2] == NULL) + return 0; es7210_read(0x43, &val, i2c_clt1[2]); ucontrol->value.integer.value[0] = val; return 0; @@ -1215,6 +1256,8 @@ static int es7210_micboost9_setting_get(struct snd_kcontrol *kcontrol, static int es7210_micboost10_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[2] == NULL) + return 0; es7210_update_bits(0x44, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[2]); return 0; } @@ -1223,6 +1266,8 @@ static int es7210_micboost10_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[2] == NULL) + return 0; es7210_read(0x44, &val, i2c_clt1[2]); ucontrol->value.integer.value[0] = val; return 0; @@ -1230,6 +1275,8 @@ static int es7210_micboost10_setting_get(struct snd_kcontrol *kcontrol, static int es7210_micboost11_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[2] == NULL) + return 0; es7210_update_bits(0x45, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[2]); return 0; } @@ -1238,6 +1285,8 @@ static int es7210_micboost11_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[2] == NULL) + return 0; es7210_read(0x45, &val, i2c_clt1[2]); ucontrol->value.integer.value[0] = val; return 0; @@ -1245,6 +1294,8 @@ static int es7210_micboost11_setting_get(struct snd_kcontrol *kcontrol, static int es7210_micboost12_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[2] == NULL) + return 0; es7210_update_bits(0x46, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[2]); return 0; } @@ -1253,6 +1304,8 @@ static int es7210_micboost12_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[2] == NULL) + return 0; es7210_read(0x46, &val, i2c_clt1[2]); ucontrol->value.integer.value[0] = val; return 0; @@ -1260,8 +1313,10 @@ static int es7210_micboost12_setting_get(struct snd_kcontrol *kcontrol, static int es7210_adc9_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[2] == NULL) + return 0; es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x01, - ucontrol->value.integer.value[0]&0x01, i2c_clt1[2]); + ucontrol->value.integer.value[0]&0x01, i2c_clt1[2]); return 0; } @@ -1269,6 +1324,8 @@ static int es7210_adc9_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[2] == NULL) + return 0; es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[2]); ucontrol->value.integer.value[0] = val & 0x01; return 0; @@ -1277,6 +1334,8 @@ static int es7210_adc9_mute_get(struct snd_kcontrol *kcontrol, static int es7210_adc10_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[2] == NULL) + return 0; es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x02, (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[2]); return 0; @@ -1286,6 +1345,8 @@ static int es7210_adc10_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[2] == NULL) + return 0; es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[2]); ucontrol->value.integer.value[0] = (val & 0x02) >> 1; return 0; @@ -1294,6 +1355,8 @@ static int es7210_adc10_mute_get(struct snd_kcontrol *kcontrol, static int es7210_adc11_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[2] == NULL) + return 0; es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x01, ucontrol->value.integer.value[0]&0x01, i2c_clt1[2]); return 0; @@ -1303,6 +1366,8 @@ static int es7210_adc11_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[2] == NULL) + return 0; es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[2]); ucontrol->value.integer.value[0] = val & 0x01; return 0; @@ -1310,6 +1375,8 @@ static int es7210_adc11_mute_get(struct snd_kcontrol *kcontrol, static int es7210_adc12_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[2] == NULL) + return 0; es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x02, (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[2]); return 0; @@ -1319,16 +1386,18 @@ static int es7210_adc12_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[2] == NULL) + return 0; es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[2]); ucontrol->value.integer.value[0] = (val & 0x02) >> 1; return 0; } -#endif -#if ES7210_CHANNELS_MAX > 12 static int es7210_micboost13_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[3] == NULL) + return 0; es7210_update_bits(0x43, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[3]); return 0; } @@ -1337,6 +1406,8 @@ static int es7210_micboost13_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[3] == NULL) + return 0; es7210_read(0x43, &val, i2c_clt1[3]); ucontrol->value.integer.value[0] = val; return 0; @@ -1344,6 +1415,8 @@ static int es7210_micboost13_setting_get(struct snd_kcontrol *kcontrol, static int es7210_micboost14_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[3] == NULL) + return 0; es7210_update_bits(0x44, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[3]); return 0; } @@ -1352,6 +1425,8 @@ static int es7210_micboost14_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[3] == NULL) + return 0; es7210_read(0x44, &val, i2c_clt1[3]); ucontrol->value.integer.value[0] = val; return 0; @@ -1359,6 +1434,8 @@ static int es7210_micboost14_setting_get(struct snd_kcontrol *kcontrol, static int es7210_micboost15_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[3] == NULL) + return 0; es7210_update_bits(0x45, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[3]); return 0; } @@ -1367,6 +1444,8 @@ static int es7210_micboost15_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[3] == NULL) + return 0; es7210_read(0x45, &val, i2c_clt1[3]); ucontrol->value.integer.value[0] = val; return 0; @@ -1374,6 +1453,8 @@ static int es7210_micboost15_setting_get(struct snd_kcontrol *kcontrol, static int es7210_micboost16_setting_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[3] == NULL) + return 0; es7210_update_bits(0x46, 0x0F, ucontrol->value.integer.value[0], i2c_clt1[3]); return 0; } @@ -1382,6 +1463,8 @@ static int es7210_micboost16_setting_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[3] == NULL) + return 0; es7210_read(0x46, &val, i2c_clt1[3]); ucontrol->value.integer.value[0] = val; return 0; @@ -1389,8 +1472,10 @@ static int es7210_micboost16_setting_get(struct snd_kcontrol *kcontrol, static int es7210_adc13_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[3] == NULL) + return 0; es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x01, - ucontrol->value.integer.value[0]&0x01, i2c_clt1[3]); + ucontrol->value.integer.value[0]&0x01, i2c_clt1[3]); return 0; } @@ -1398,6 +1483,8 @@ static int es7210_adc13_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[3] == NULL) + return 0; es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[3]); ucontrol->value.integer.value[0] = val & 0x01; return 0; @@ -1406,6 +1493,8 @@ static int es7210_adc13_mute_get(struct snd_kcontrol *kcontrol, static int es7210_adc14_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[3] == NULL) + return 0; es7210_update_bits(ES7210_ADC12_MUTE_REG15, 0x02, (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[3]); return 0; @@ -1415,6 +1504,8 @@ static int es7210_adc14_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[3] == NULL) + return 0; es7210_read(ES7210_ADC12_MUTE_REG15, &val, i2c_clt1[3]); ucontrol->value.integer.value[0] = (val & 0x02) >> 1; return 0; @@ -1423,6 +1514,8 @@ static int es7210_adc14_mute_get(struct snd_kcontrol *kcontrol, static int es7210_adc15_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[3] == NULL) + return 0; es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x01, ucontrol->value.integer.value[0]&0x01, i2c_clt1[3]); return 0; @@ -1432,6 +1525,8 @@ static int es7210_adc15_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[3] == NULL) + return 0; es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[3]); ucontrol->value.integer.value[0] = val & 0x01; return 0; @@ -1439,6 +1534,8 @@ static int es7210_adc15_mute_get(struct snd_kcontrol *kcontrol, static int es7210_adc16_mute_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + if (i2c_clt1[3] == NULL) + return 0; es7210_update_bits(ES7210_ADC34_MUTE_REG14, 0x02, (ucontrol->value.integer.value[0] & 0x01) << 1, i2c_clt1[3]); return 0; @@ -1448,14 +1545,14 @@ static int es7210_adc16_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u8 val; + if (i2c_clt1[3] == NULL) + return 0; es7210_read(ES7210_ADC34_MUTE_REG14, &val, i2c_clt1[3]); ucontrol->value.integer.value[0] = (val & 0x02) >> 1; return 0; } -#endif static const struct snd_kcontrol_new es7210_snd_controls[] = { -#if ES7210_CHANNELS_MAX > 0 SOC_SINGLE_EXT_TLV("PGA1_setting", 0x43, 0, 0x0E, 0, es7210_micboost1_setting_get, es7210_micboost1_setting_set, @@ -1480,8 +1577,6 @@ static const struct snd_kcontrol_new es7210_snd_controls[] = { es7210_adc3_mute_get, es7210_adc3_mute_set), SOC_SINGLE_EXT("ADC4_MUTE", ES7210_ADC34_MUTE_REG14, 1, 1, 0, es7210_adc4_mute_get, es7210_adc4_mute_set), -#endif -#if ES7210_CHANNELS_MAX > 4 SOC_SINGLE_EXT_TLV("PGA5_setting", 0x43, 0, 0x0E, 0, es7210_micboost5_setting_get, es7210_micboost5_setting_set, @@ -1506,9 +1601,6 @@ static const struct snd_kcontrol_new es7210_snd_controls[] = { es7210_adc7_mute_get, es7210_adc7_mute_set), SOC_SINGLE_EXT("ADC8_MUTE", ES7210_ADC34_MUTE_REG14, 1, 1, 0, es7210_adc8_mute_get, es7210_adc8_mute_set), - -#endif -#if ES7210_CHANNELS_MAX > 8 SOC_SINGLE_EXT_TLV("PGA9_setting", 0x43, 0, 0x0E, 0, es7210_micboost9_setting_get, es7210_micboost9_setting_set, @@ -1533,9 +1625,6 @@ static const struct snd_kcontrol_new es7210_snd_controls[] = { es7210_adc11_mute_get, es7210_adc11_mute_set), SOC_SINGLE_EXT("ADC12_MUTE", ES7210_ADC34_MUTE_REG14, 1, 1, 0, es7210_adc12_mute_get, es7210_adc12_mute_set), - -#endif -#if ES7210_CHANNELS_MAX > 12 SOC_SINGLE_EXT_TLV("PGA13_setting", 0x43, 0, 0x0E, 0, es7210_micboost13_setting_get, es7210_micboost13_setting_set, @@ -1560,12 +1649,10 @@ static const struct snd_kcontrol_new es7210_snd_controls[] = { es7210_adc15_mute_get, es7210_adc15_mute_set), SOC_SINGLE_EXT("ADC16_MUTE", ES7210_ADC34_MUTE_REG14, 1, 1, 0, es7210_adc16_mute_get, es7210_adc16_mute_set), - -#endif - }; static struct snd_soc_component_driver soc_codec_dev_es7210 = { + .name = "es7210", .probe = es7210_probe, .suspend = es7210_suspend, .resume = es7210_resume, @@ -1615,6 +1702,12 @@ static ssize_t es7210_show(struct device *dev, struct device_attribute *attr, ch printk("echo flag|reg|val > es7210\n"); printk("eg read star address=0x06,count 0x10:echo 0610 >es7210\n"); printk("eg write star address=0x90,value=0x3c,count=4:echo 4903c >es7210\n"); + struct es7210_priv *es7210 = dev_get_drvdata(dev); + u8 value, i; + for (i = 0; i < 0x4d; i++) { + es7210_read(i, &value, es7210->i2c_client); + printk("reg[0x%x]=0x%x\n", i, value); + } return 0; } @@ -1638,6 +1731,9 @@ static int es7210_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *i2c_id) { struct es7210_priv *es7210; + struct device_node *np = i2c_client->dev.of_node; + char* property; + int ret; es7210 = devm_kzalloc(&i2c_client->dev, sizeof(struct es7210_priv), @@ -1645,7 +1741,42 @@ static int es7210_i2c_probe(struct i2c_client *i2c_client, if (es7210 == NULL) return -ENOMEM; es7210->i2c_client = i2c_client; - es7210->tdm_mode = ES7210_WORK_MODE; //to set tdm mode or normal mode + + property = of_get_property(np, "work-mode", NULL); + if (property) { + if (!strcmp(property, "ES7210_TDM_1LRCK_DSPB")) { + es7210->tdm_mode = ES7210_TDM_1LRCK_DSPB; + } else if (!strcmp(property, "ES7210_NORMAL_I2S")) { + es7210->tdm_mode = ES7210_NORMAL_I2S; + } else { + pr_err("unsupported work mode\n"); + return -EINVAL; + } + } else { + pr_warn("es7210 work-mode not defined.using ES7210_NORMAL_I2S by default\n"); + es7210->tdm_mode = ES7210_NORMAL_I2S; + } + + if (of_property_read_u32(np, "channels-max", &ES7210_CHANNELS_MAX) == 0) { + if (ES7210_CHANNELS_MAX == MIC_CHN_2 || ES7210_CHANNELS_MAX == MIC_CHN_4) { + ADC_DEV_MAXNUM = 1; + } else if (ES7210_CHANNELS_MAX == MIC_CHN_6 || ES7210_CHANNELS_MAX == MIC_CHN_8) { + ADC_DEV_MAXNUM = 2; + } else if (ES7210_CHANNELS_MAX == MIC_CHN_10 || ES7210_CHANNELS_MAX == MIC_CHN_12) { + ADC_DEV_MAXNUM = 3; + } else if (ES7210_CHANNELS_MAX == MIC_CHN_14 || ES7210_CHANNELS_MAX == MIC_CHN_16) { + ADC_DEV_MAXNUM = 4; + } else { + pr_err("es7210 unsupported channels-max\n"); + return -EINVAL; + } + } else { + pr_warn("es7210 channels-max not defined.using MIC_CHN_2 by default\n"); + ES7210_CHANNELS_MAX = MIC_CHN_2; + ADC_DEV_MAXNUM = 1; + } + //printk("%s es7210->tdm_mode=%d channels-max=%d ADC_DEV_MAXNUM=%d\n", __func__, es7210->tdm_mode, ES7210_CHANNELS_MAX, ADC_DEV_MAXNUM); + i2c_set_clientdata(i2c_client, es7210); if (i2c_id->driver_data < ADC_DEV_MAXNUM) { i2c_clt1[i2c_id->driver_data] = i2c_client; @@ -1665,41 +1796,19 @@ static int es7210_i2c_probe(struct i2c_client *i2c_client, static const struct i2c_device_id es7210_i2c_id[] = { -#if ES7210_CHANNELS_MAX > 0 { "MicArray_0", 0 },//es7210_0 -#endif - -#if ES7210_CHANNELS_MAX > 4 { "MicArray_1", 1 },//es7210_1 -#endif - -#if ES7210_CHANNELS_MAX > 8 { "MicArray_2", 2 },//es7210_2 -#endif - -#if ES7210_CHANNELS_MAX > 12 { "MicArray_3", 3 },//es7210_3 -#endif { } }; MODULE_DEVICE_TABLE(i2c_client, es7210_i2c_id); static const struct of_device_id es7210_dt_ids[] = { -#if ES7210_CHANNELS_MAX > 0 { .compatible = "MicArray_0", },//es7210_0 -#endif - -#if ES7210_CHANNELS_MAX > 4 { .compatible = "MicArray_1", },//es7210_1 -#endif - -#if ES7210_CHANNELS_MAX > 8 { .compatible = "MicArray_2", },//es7210_2 -#endif - -#if ES7210_CHANNELS_MAX > 12 { .compatible = "MicArray_3", },//es7210_3 -#endif {} }; MODULE_DEVICE_TABLE(of, es7210_dt_ids); diff --git a/sound/soc/codecs/es7210.h b/sound/soc/codecs/es7210.h index c3b89fd4d..9b0fcccc4 100644 --- a/sound/soc/codecs/es7210.h +++ b/sound/soc/codecs/es7210.h @@ -69,5 +69,19 @@ #define ES7210_MIC4_LP_REG4A 0x4A #define ES7210_MIC12_PDN_REG4B 0x4B #define ES7210_MIC34_PDN_REG4C 0x4C - + +/* codec private data */ +struct es7210_priv { + struct regmap *regmap; + struct i2c_client *i2c_client; + unsigned int dmic_enable; + unsigned int sysclk; + struct clk *mclk; + struct snd_pcm_hw_constraint_list *sysclk_constraints; + unsigned int tdm_mode; + struct delayed_work pcm_pop_work; + int mclk_lrck_ratio; + int pcm_format; +}; + #endif /* _ES7210_H_ */ diff --git a/sound/soc/codecs/es8156.c b/sound/soc/codecs/es8156.c index 47ab55ef0..36f9840e3 100644 --- a/sound/soc/codecs/es8156.c +++ b/sound/soc/codecs/es8156.c @@ -36,6 +36,7 @@ #define GPIO_LOW 0 #define GPIO_HIGH 1 #define es8156_DEF_VOL 0xBF +#define ES8156_VOL_MAX 0xBF /* * If your system doesn't have MCLK, define this to 0 or the * driver will crash. @@ -115,7 +116,7 @@ static const struct snd_kcontrol_new es8156_snd_controls[] = { 4,0,15,0), /* DAC Digital controls */ SOC_SINGLE_TLV("DAC Playback Volume", ES8156_VOLUME_CONTROL_REG14, - 0, 0xff, 0, dac_vol_tlv), + 0, ES8156_VOL_MAX, 0, dac_vol_tlv), SOC_SINGLE("HP Switch",ES8156_ANALOG_SYS3_REG22,3,1,0), @@ -123,7 +124,7 @@ static const struct snd_kcontrol_new es8156_snd_controls[] = { static const struct snd_soc_dapm_widget es8156_dapm_widgets[] = { - SND_SOC_DAPM_AIF_OUT("SDOUT", "I2S Capture", 0, + SND_SOC_DAPM_AIF_OUT("AIFSDOUT", "I2S Capture", 0, ES8156_P2S_CONTROL_REG0D, 2, 0), SND_SOC_DAPM_AIF_IN("SDIN", "I2S Playback", 0, @@ -161,150 +162,6 @@ static const struct snd_soc_dapm_route es8156_dapm_routes[] = { { "ROUT", NULL, "DACR" }, }; -/*************** 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 -#define 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 -#define MCLK_SOURCE SCLK_PIN // 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_sequence(struct snd_soc_component *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)); - snd_soc_component_write(codec,0x14,DAC_Volume); - 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_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { @@ -412,7 +269,25 @@ static int es8156_set_bias_level(struct snd_soc_component *codec, if (!IS_ERR(priv->mclk)) { ret = clk_prepare_enable(priv->mclk); - es8156_init_sequence(codec); + snd_soc_component_write(codec, ES8156_SCLK_MODE_REG02,0x04); + snd_soc_component_write(codec, ES8156_ANALOG_SYS1_REG20,0x2A); + snd_soc_component_write(codec, ES8156_ANALOG_SYS2_REG21,0x3C); + snd_soc_component_write(codec, ES8156_ANALOG_SYS3_REG22,0x08); + snd_soc_component_write(codec, ES8156_ANALOG_LP_REG24,0x07); + if(ES8156_DVDD==ES8156_1V8) + snd_soc_component_write(codec, ES8156_ANALOG_SYS4_REG23,VMIDLEVEL3<<4); + else + snd_soc_component_write(codec, ES8156_ANALOG_SYS4_REG23,0x00); + snd_soc_component_write(codec, ES8156_TIME_CONTROL1_REG0A,0x01); + snd_soc_component_write(codec, ES8156_TIME_CONTROL2_REG0B,0x01); + //snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14,0xBF); + snd_soc_component_write(codec, ES8156_MAINCLOCK_CTL_REG01,0x21); + snd_soc_component_write(codec, ES8156_P2S_CONTROL_REG0D,0x14); + snd_soc_component_write(codec, ES8156_MISC_CONTROL3_REG18,0x00); + snd_soc_component_write(codec, ES8156_CLOCK_ON_OFF_REG08,0x3F); + snd_soc_component_write(codec, ES8156_RESET_REG00,0x02); + snd_soc_component_write(codec, ES8156_RESET_REG00,0x03); + snd_soc_component_write(codec, ES8156_ANALOG_SYS5_REG25,0x20); if (ret) { dev_err(codec->dev, @@ -425,23 +300,22 @@ static int es8156_set_bias_level(struct snd_soc_component *codec, break; case SND_SOC_BIAS_OFF: - snd_soc_component_write(codec,0x14,0x00); - snd_soc_component_write(codec,0x19,0x02); - snd_soc_component_write(codec,0x22,0x02); - snd_soc_component_write(codec,0x25,0x81); - snd_soc_component_write(codec,0x18,0x01); - snd_soc_component_write(codec,0x09,0x02); - snd_soc_component_write(codec,0x09,0x01); - snd_soc_component_write(codec,0x08,0x00); - mdelay(500); - snd_soc_component_write(codec,0x25,0x87); + //snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14, 0x00); + snd_soc_component_write(codec, ES8156_EQ_CONTROL1_REG19, 0x02); + snd_soc_component_write(codec, ES8156_ANALOG_SYS2_REG21, 0x1F); + snd_soc_component_write(codec, ES8156_ANALOG_SYS3_REG22, 0x02); + snd_soc_component_write(codec, ES8156_ANALOG_SYS5_REG25, 0x21); + snd_soc_component_write(codec, ES8156_ANALOG_SYS5_REG25, 0x01); + snd_soc_component_write(codec, ES8156_ANALOG_SYS5_REG25, 0x87); + snd_soc_component_write(codec, ES8156_MISC_CONTROL3_REG18, 0x01); + snd_soc_component_write(codec, ES8156_MISC_CONTROL2_REG09, 0x02); + snd_soc_component_write(codec, ES8156_MISC_CONTROL2_REG09, 0x01); + snd_soc_component_write(codec, ES8156_CLOCK_ON_OFF_REG08, 0x00); /* *close i2s clock */ - if (!IS_ERR(priv->mclk)) { - pr_info("%s codec_uninit_sequence\n", __func__); + if (!IS_ERR(priv->mclk)) clk_disable_unprepare(priv->mclk); - } break; } return 0; @@ -474,6 +348,43 @@ static struct snd_soc_dai_driver es8156_dai = { }; +static int es8156_init_regs(struct snd_soc_component *codec) +{ + /* + *set clock and analog power + */ + snd_soc_component_write(codec, ES8156_SCLK_MODE_REG02,0x04); + snd_soc_component_write(codec, ES8156_ANALOG_SYS1_REG20,0x2A); + snd_soc_component_write(codec, ES8156_ANALOG_SYS2_REG21,0x3C); + snd_soc_component_write(codec, ES8156_ANALOG_SYS3_REG22,0x08); + snd_soc_component_write(codec, ES8156_ANALOG_LP_REG24,0x07); + if(ES8156_DVDD==ES8156_1V8) + snd_soc_component_write(codec, ES8156_ANALOG_SYS4_REG23,VMIDLEVEL3<<4); + else + snd_soc_component_write(codec, ES8156_ANALOG_SYS4_REG23,0x00); + /* + *set powerup time + */ + snd_soc_component_write(codec, ES8156_TIME_CONTROL1_REG0A,0x01); + snd_soc_component_write(codec, ES8156_TIME_CONTROL2_REG0B,0x01); + /* + *set digtal volume + */ + snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14,0xBF); + /* + *set MCLK + */ + snd_soc_component_write(codec, ES8156_MAINCLOCK_CTL_REG01,0x21); + snd_soc_component_write(codec, ES8156_P2S_CONTROL_REG0D,0x14); + snd_soc_component_write(codec, ES8156_MISC_CONTROL3_REG18,0x00); + snd_soc_component_write(codec, ES8156_CLOCK_ON_OFF_REG08,0x3F); + snd_soc_component_write(codec, ES8156_RESET_REG00,0x02); + snd_soc_component_write(codec, ES8156_RESET_REG00,0x03); + snd_soc_component_write(codec, ES8156_ANALOG_SYS5_REG25,0x20); + + return 0; +} + static int es8156_suspend(struct snd_soc_component *codec) { es8156_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -560,7 +471,7 @@ static int es8156_probe(struct snd_soc_component *codec) ret = clk_prepare_enable(es8156->mclk); #endif es8156_reset(codec); - es8156_init_sequence(codec); + es8156_init_regs(codec); return ret; } @@ -579,6 +490,7 @@ const struct regmap_config es8156_regmap_config = { }; static struct snd_soc_component_driver soc_codec_dev_es8156 = { + .name = "es8156", .probe = es8156_probe, .remove = es8156_remove, .suspend = es8156_suspend, diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index d0d79f47b..97e8bd7fc 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -145,16 +145,19 @@ EXPORT_SYMBOL_GPL(asoc_simple_parse_card_name); static int asoc_simple_clk_enable(struct asoc_simple_dai *dai) { - if (dai) - return clk_prepare_enable(dai->clk); - + if (dai) { + if (!IS_ERR_OR_NULL(dai->clk)) + return clk_prepare_enable(dai->clk); + } return 0; } static void asoc_simple_clk_disable(struct asoc_simple_dai *dai) { - if (dai) - clk_disable_unprepare(dai->clk); + if (dai) { + if (!IS_ERR_OR_NULL(dai->clk)) + clk_disable_unprepare(dai->clk); + } } int asoc_simple_parse_clk(struct device *dev, @@ -182,6 +185,7 @@ 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")) @@ -242,7 +246,11 @@ static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai, if (clk_get_rate(simple_dai->clk) == rate) return 0; - return clk_set_rate(simple_dai->clk, rate); + if (!IS_ERR_OR_NULL(simple_dai->clk)) { + return clk_set_rate(simple_dai->clk, rate); + } else { + return 0; + } } int asoc_simple_hw_params(struct snd_pcm_substream *substream, diff --git a/sound/soc/thead/Makefile b/sound/soc/thead/Makefile index 59895f9a4..6c8b733d8 100644 --- a/sound/soc/thead/Makefile +++ b/sound/soc/thead/Makefile @@ -1,5 +1,7 @@ # CPU DAI drivers 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-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/aw87519_audio.c b/sound/soc/thead/aw87519_audio.c index a50d54f4d..42762f59d 100644 --- a/sound/soc/thead/aw87519_audio.c +++ b/sound/soc/thead/aw87519_audio.c @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include #include "aw87519_audio.h" /******************************************************************************* @@ -140,7 +143,6 @@ unsigned char aw87519_audio_receiver(void) unsigned int i; unsigned int length; - pr_info("%s enter\n", __func__); if (aw87519 == NULL) return 2; @@ -169,8 +171,6 @@ unsigned char aw87519_audio_speaker(void) unsigned int i; unsigned int length; - pr_info("%s enter\n", __func__); - if (aw87519 == NULL) return 2; @@ -577,6 +577,79 @@ retry: return -EINVAL; } +static const DECLARE_TLV_DB_RANGE(aw87519_tlv, + 8, 12, TLV_DB_SCALE_ITEM(1200,150, 0) +); + +static const struct snd_kcontrol_new aw87519_controls[] = { + SOC_SINGLE_TLV("Speaker Playback Volume", REG_PAGR, 0, 12, 0, aw87519_tlv), +}; + +static int aw87519_component_probe(struct snd_soc_component* component) +{ + struct aw87519 *pa = snd_soc_component_get_drvdata(component); + + return 0; // snd_soc_add_component_controls(component, aw87519_controls, ARRAY_SIZE(aw87519_controls)); +} + +static int aw87519_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kctrl, int event) +{ + struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); + struct aw87519 *pa = snd_soc_component_get_drvdata(c); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Before widget power up: turn chip on, sync registers */ + aw87519_audio_speaker(); + } else { + /* After widget power down: turn chip off */ + aw87519_audio_off(); + } + + return 0; +} + +static const struct snd_soc_dapm_widget aw87519_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("IN"), + SND_SOC_DAPM_OUTPUT("VO"), + SND_SOC_DAPM_PGA("PGA", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Power", SND_SOC_NOPM, 0, 0, + aw87519_power_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route aw87519_dapm_routes[] = { + { "PGA", NULL, "IN"}, + { "VO", NULL, "PGA"}, + { "PGA", NULL, "Power"}, +}; + +static const struct reg_default aw87519_reg_defaults[] = { + {0x69, 0x80}, {0x69, 0xB7}, {0x01, 0xF0}, {0x02, 0x09}, + {0x03, 0xE8}, {0x04, 0x11}, {0x05, 0x10}, {0x06, 0x43}, + {0x07, 0x4E}, {0x08, 0x03}, {0x09, 0x08}, {0x0A, 0x4A}, + {0x60, 0x16}, {0x61, 0x20}, {0x62, 0x01}, {0x63, 0x0B}, + {0x64, 0xC5}, {0x65, 0xA4}, {0x66, 0x78}, {0x67, 0xC4}, + {0x68, 0XD0}, +}; + +const struct regmap_config aw87519_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xff, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = aw87519_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(aw87519_reg_defaults), +}; + +static const struct snd_soc_component_driver aw87519_component_driver = { + .name = "aw87519", + .probe = aw87519_component_probe, + .dapm_widgets = aw87519_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aw87519_dapm_widgets), + .dapm_routes = aw87519_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(aw87519_dapm_routes), +}; + /******************************************************************************* * aw87519 i2c driver ******************************************************************************/ @@ -599,6 +672,13 @@ static int aw87519_i2c_probe(struct i2c_client *client, goto exit_devm_kzalloc_failed; } + aw87519->regmap = devm_regmap_init_i2c(client, &aw87519_regmap_config); + if (IS_ERR(aw87519->regmap)) { + ret = PTR_ERR(aw87519->regmap); + dev_err(&client->dev, "Failed to init regmap: %d\n", ret); + return ret; + } + aw87519->i2c_client = client; i2c_set_clientdata(client, aw87519); @@ -650,7 +730,7 @@ static int aw87519_i2c_probe(struct i2c_client *client, /* aw87519 hardware off */ aw87519_hw_off(aw87519); - return 0; + return devm_snd_soc_register_component(&client->dev, &aw87519_component_driver, NULL, 0); exit_i2c_check_id_failed: exit_gpio_request_failed: @@ -711,7 +791,7 @@ static void __exit aw87519_pa_exit(void) i2c_del_driver(&aw87519_i2c_driver); } -late_initcall(aw87519_pa_init); +module_init(aw87519_pa_init); module_exit(aw87519_pa_exit); MODULE_DESCRIPTION("AWINIC AW87519 PA driver"); diff --git a/sound/soc/thead/aw87519_audio.h b/sound/soc/thead/aw87519_audio.h index 2e6dce70d..e15fd561c 100644 --- a/sound/soc/thead/aw87519_audio.h +++ b/sound/soc/thead/aw87519_audio.h @@ -72,6 +72,9 @@ unsigned char aw87519_rcv_cfg_default[] = { #define REG_PAGC2PR 0x09 #define REG_PAGC1PR 0x0A +#define AW87519_EN_SW_SHIFT 7 +#define AW87519_EN_PA_SHIFT 4 + #define AW87519_CHIPID 0x59 #define AW87519_REG_MAX 11 @@ -90,6 +93,7 @@ struct aw87519 { struct mutex cfg_lock; struct work_struct cfg_work; struct delayed_work ram_work; + struct regmap *regmap; }; /******************************************************************************* diff --git a/sound/soc/thead/light-dummy-pcm.c b/sound/soc/thead/light-dummy-pcm.c new file mode 100644 index 000000000..bc8e12ad2 --- /dev/null +++ b/sound/soc/thead/light-dummy-pcm.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for ASoC dummy pcm dai + * Copyright 2023 Yan Dong + */ + +#include +#include +#include + +#include + +static const struct snd_soc_dapm_widget light_dummy_pcm_widgets[] = { + SND_SOC_DAPM_INPUT("RX"), + SND_SOC_DAPM_OUTPUT("TX"), +}; + +static const struct snd_soc_dapm_route light_dummy_pcm_routes[] = { + { "Capture", NULL, "RX" }, + { "TX", NULL, "Playback" }, +}; + +static struct snd_soc_dai_driver light_dummy_pcm_dai[] = { + { + .name = "dummy-pcm", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + +static const struct snd_soc_component_driver soc_component_dev_light_dummy_pcm = { + .dapm_widgets = light_dummy_pcm_widgets, + .num_dapm_widgets = ARRAY_SIZE(light_dummy_pcm_widgets), + .dapm_routes = light_dummy_pcm_routes, + .num_dapm_routes = ARRAY_SIZE(light_dummy_pcm_routes), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static int light_dummy_pcm_probe(struct platform_device *pdev) +{ + return devm_snd_soc_register_component(&pdev->dev, + &soc_component_dev_light_dummy_pcm, + light_dummy_pcm_dai, ARRAY_SIZE(light_dummy_pcm_dai)); +} + +static int light_dummy_pcm_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct platform_device_id light_dummy_pcm_driver_ids[] = { + { + .name = "light-dummy-pcm", + }, + {}, +}; +MODULE_DEVICE_TABLE(platform, light_dummy_pcm_driver_ids); + +#if defined(CONFIG_OF) +static const struct of_device_id light_dummy_pcm_codec_of_match[] = { + { .compatible = "thead,light-dummy-pcm", }, + {}, +}; +MODULE_DEVICE_TABLE(of, light_dummy_pcm_codec_of_match); +#endif + +static struct platform_driver light_dummy_pcm_driver = { + .driver = { + .name = "light-dummy-pcm", + .of_match_table = of_match_ptr(light_dummy_pcm_codec_of_match), + }, + .probe = light_dummy_pcm_probe, + .remove = light_dummy_pcm_remove, + .id_table = light_dummy_pcm_driver_ids, +}; + +module_platform_driver(light_dummy_pcm_driver); + +MODULE_AUTHOR("Yan Dong "); +MODULE_DESCRIPTION("ASoC dummy pcm dai driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/thead/light-i2s.c b/sound/soc/thead/light-i2s.c index 59a98eca8..31c80cf5f 100644 --- a/sound/soc/thead/light-i2s.c +++ b/sound/soc/thead/light-i2s.c @@ -122,27 +122,11 @@ static inline void light_snd_txctrl(struct light_i2s_priv *chip, bool on) } else { dma_en &= ~DMACR_TDMAE_EN; i2s_en &= ~IISEN_I2SEN; - i2s_status = readl(chip->regs + I2S_SR); - while ((i2s_status & SR_TXBUSY_STATUS) || !(i2s_status & SR_TFNF_TX_FIFO_NOT_FULL)) { - i2s_status = readl(chip->regs + I2S_SR); - } - i2s_imr = readl(chip->regs + I2S_IMR); - i2s_imr &= ~(IMR_TXUIRM_INTR_MSK); i2s_imr &= ~(IMR_TXEIM_INTR_MSK); - writel(i2s_imr, chip->regs + I2S_IMR); - i2s_imr = readl(chip->regs + I2S_IMR); - writel(dma_en, chip->regs + I2S_DMACR); - - i2s_status = readl(chip->regs + I2S_SR); - while ((i2s_status & SR_TXBUSY_STATUS) || !(i2s_status & SR_TFE_TX_FIFO_EMPTY)) { - i2s_status = readl(chip->regs + I2S_SR); - } - - mdelay(10); writel(i2s_en, chip->regs + I2S_IISEN); } } @@ -205,14 +189,15 @@ static int light_i2s_dai_trigger(struct snd_pcm_substream *substream, int cmd, light_snd_rxctrl(i2s_private, 1); break; case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (tx) + 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(i2s_private, 0); - break; - - default: - return -EINVAL; + } + break; + default: + return -EINVAL; } diff --git a/sound/soc/thead/light-tdm.c b/sound/soc/thead/light-tdm.c new file mode 100644 index 000000000..e8ecd578a --- /dev/null +++ b/sound/soc/thead/light-tdm.c @@ -0,0 +1,629 @@ +/* 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-tdm.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#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) + +static int light_tdm_dai_probe(struct snd_soc_dai *dai) +{ + struct light_tdm_priv *tdm = snd_soc_dai_get_drvdata(dai); + + if (tdm) { + snd_soc_dai_init_dma_data(dai, NULL, &tdm->dma_params_rx); + } else { + return -EIO; + } + + return 0; +} + +static int light_tdm_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return 0; +} + +static void light_tdm_snd_rxctrl(struct light_tdm_priv *priv, char on) +{ + if (priv->slot_num != 1) { + return; + } + + regmap_update_bits(priv->regmap, TDM_DMACTL, + DMACTL_DMAEN_MSK, DMACTL_DMAEN_SEL(on)); + regmap_update_bits(priv->regmap, TDM_TDMEN, + TDMCTL_TDMEN_MSK, TDMCTL_TDMEN_SEL(on)); + u32 dmactl; + u32 tdmen; + regmap_read(priv->regmap, TDM_DMACTL, &dmactl); + regmap_read(priv->regmap, TDM_TDMEN, &tdmen); + //printk("%s TDM_DMACTL=0x%x TDM_TDMEN=0x%x\n", __func__, dmactl, tdmen); + return; +} + +static void light_tdm_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + light_tdm_snd_rxctrl(priv, 0); + + clk_disable_unprepare(priv->clk); +} + +static int light_tdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) +{ + int ret = 0; + struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai); + + switch(cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + light_tdm_snd_rxctrl(priv, 1); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + light_tdm_snd_rxctrl(priv, 0); + break; + default: + return -EINVAL; + } + + return ret; +} + +static int light_tdm_set_fmt_dai(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai); + u32 cnfin = 0; + + if (priv->slot_num != 1) { + return 0; + } + + printk("%s fmt=%d\n", __func__, fmt); + switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_B: + break; + default: + pr_err("Unknown fmt dai\n"); + return -EIO; + } + + regmap_update_bits(priv->regmap, TDM_TDMCTL, + TDMCTL_MODE_MSK, + TDMCTL_MODE_SEL(TDM_MODE_MASTER)); + regmap_update_bits(priv->regmap, TDM_TDMCTL, + TDMCTL_SPEDGE_MSK, + TDMCTL_SPEDGE_SEL(1)); + regmap_update_bits(priv->regmap, TDM_DMADL, + DMACTL_DMADL_MSK, DMACTL_DMADL_SEL(0)); + u32 tdmctl; + 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; +} + +static u32 light_special_sample_rates[] = { 11025, 22050, 44100, 88200 }; +#define AUDIO_DIVCLK0 49152000 +#define AUDIO_DIVCLK1 135475200 + +static void light_tdm_set_div(struct light_tdm_priv *priv, struct snd_pcm_hw_params *params) +{ + bool is_divclk1 = false; //audio_divclk1 for 44.1k...etc. audio_divclk0 for 48k....etc + u32 src_clk; + u32 div0, i, width; + u32 sample_rate = params_rate(params); + + switch(params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + width = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + width = 24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + width = 32; + break; + default: + pr_err("Unknown data format\n"); + return; + } + + 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=49152000 for 48k + regmap_update_bits(priv->audio_cpr_regmap, + CPR_PERI_CLK_SEL_REG, CPR_TDM_SRC_SEL_MSK, CPR_TDM_SRC_SEL(0)); + src_clk = AUDIO_DIVCLK0; + } else { // audio_divclk1=135475200 for 44.1k + regmap_update_bits(priv->audio_cpr_regmap, + CPR_PERI_CLK_SEL_REG, CPR_TDM_SRC_SEL_MSK, CPR_TDM_SRC_SEL(2)); + src_clk = AUDIO_DIVCLK1; + } + div0 = src_clk / (sample_rate * (width * priv->slots)); + regmap_update_bits(priv->regmap, TDM_DIV0_LEVEL, + TDMCTL_DIV0_MASK, div0); + //printk("src_clk=%d sample_rate=%d priv->slots=%d width=%d div0=%d\n", src_clk, sample_rate, priv->slots, width, div0); +} + + +static int light_tdm_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai); + u32 datawth, chn_num; + + if ( params_channels(params) != 1) { + pr_err("Not support channel num\n"); + return -EINVAL; + } + + if (priv->slot_num != 1) { + return 0; + } + + switch(params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + datawth = TDMCTL_DATAWTH_16BIT_PACKED; // TDMCTL_DATAWTH_16BIT + break; + case SNDRV_PCM_FORMAT_S24_LE: + datawth = TDMCTL_DATAWTH_24BIT; + break; + case SNDRV_PCM_FORMAT_S32_LE: + datawth = TDMCTL_DATAWTH_32BIT; + break; + default: + pr_err("Unknown data format\n"); + return -EINVAL; + } + + switch(priv->slots) { + case 2: + chn_num = TDMCTL_CHNUM_2; + break; + case 4: + chn_num = TDMCTL_CHNUM_4; + break; + case 6: + chn_num = TDMCTL_CHNUM_6; + break; + case 8: + chn_num = TDMCTL_CHNUM_8; + break; + default: + pr_err("Not support slot num\n"); + return -EINVAL; + } + + regmap_update_bits(priv->regmap, TDM_TDMCTL, + TDMCTL_DATAWTH_MSK, TDMCTL_DATAWTH_SEL(datawth)); + regmap_update_bits(priv->regmap, TDM_TDMCTL, + TDMCTL_CHNUM_MSK, TDMCTL_CHNUM_SEL(chn_num)); + u32 tdmctl; + regmap_read(priv->regmap, TDM_TDMCTL, &tdmctl); + //printk("%s TDM_TDMCTL=0x%x\n", __func__, tdmctl); + light_tdm_set_div(priv, params); + + return 0; +} + + +static const struct snd_soc_dai_ops light_tdm_dai_ops = { + .startup = light_tdm_dai_startup, + .shutdown = light_tdm_dai_shutdown, + .trigger = light_tdm_dai_trigger, + .set_fmt = light_tdm_set_fmt_dai, + .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, + }, + { + .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, + }, +}; + +static const struct snd_soc_component_driver light_tdm_soc_component = { + .name = "light_tdm", +}; + +static void light_tdm_pinctrl(struct light_tdm_priv *tdm_priv) +{ + //GPIO_SEL + regmap_update_bits(tdm_priv->audio_pin_regmap, + 0x0,0x38000000, 0x38000000); + //MUX + regmap_update_bits(tdm_priv->audio_pin_regmap, + 0x8,0xFC00000, 0x5400000); + //strength + regmap_update_bits(tdm_priv->audio_pin_regmap, + 0x44,0x0f, 0x07); // AUDIO_PA28 + regmap_update_bits(tdm_priv->audio_pin_regmap, + 0x40,0xF0000, 0x70000); // AUDIO_PA27 + return; +} + +static const struct regmap_config light_tdm_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TDM_DIV0_LEVEL, + .cache_type = REGCACHE_FLAT, +}; + +static int light_tdm_runtime_suspend(struct device *dev) +{ + struct light_tdm_priv *priv = dev_get_drvdata(dev); + + if (priv->slot_num != 1) { + return 0; + } + + regcache_cache_only(priv->regmap, true); + clk_disable_unprepare(priv->clk); + + return 0; +} + +static int light_tdm_runtime_resume(struct device *dev) +{ + struct light_tdm_priv *priv = dev_get_drvdata(dev); + int ret; + + if (priv->slot_num != 1) { + 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_tdm_of_match[] = { + { .compatible = "light,light-tdm"}, + {}, +}; +MODULE_DEVICE_TABLE(of, light_tdm_of_match); + +irqreturn_t tdm_interrupt(int irq, void* dev_id) +{ + struct light_tdm_priv* priv = (struct light_tdm_priv*)dev_id; + return IRQ_HANDLED; +} + +static int light_tdm_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const char *sprop; + const uint32_t *iprop; + struct light_tdm_priv *tdm_priv; + struct resource *res; + struct device *dev = &pdev->dev; + unsigned int irq; + int data_register, ret = 0; + + tdm_priv = devm_kzalloc(&pdev->dev, sizeof(struct light_tdm_priv), GFP_KERNEL); + if (!tdm_priv) { + return -ENOMEM; + } + + tdm_priv->dev = dev; + sprop = of_get_property(np, "light,mode", NULL); + if (sprop) { + if (!strcmp(sprop, "i2s-master")) { + tdm_priv->mode = TDM_MODE_MASTER; + } else if (!strcmp(sprop, "i2s-slave")) { + tdm_priv->mode = TDM_MODE_SLAVE; + } else { + dev_err(dev, "invalid light,mode\n"); + return -EINVAL; + } + } + + iprop = of_get_property(np, "light,dma_maxburst", NULL); + if (iprop) + tdm_priv->dma_maxburst = be32_to_cpup(iprop); + else + tdm_priv->dma_maxburst = 8; + + iprop = of_get_property(np, "light,tdm_slots", NULL); + if (iprop) { + if (be32_to_cpup(iprop) == 2 || be32_to_cpup(iprop) == 4 || be32_to_cpup(iprop) == 6 || be32_to_cpup(iprop) == 8) { + tdm_priv->slots = be32_to_cpup(iprop); + } else { + dev_err(dev, "invalid light,tdm_slots\n"); + return -EINVAL; + } + } else { + tdm_priv->slots = 8; + } + + iprop = of_get_property(np, "light,tdm_slot_num", NULL); + if (iprop) { + if (be32_to_cpup(iprop) >=1 && be32_to_cpup(iprop) <=8 ) { + tdm_priv->slot_num = be32_to_cpup(iprop); + } else { + dev_err(dev, "invalid light,tdm_slot_num\n"); + return -EINVAL; + } + } else { + dev_err(dev, "invalid light,tdm_slot_num\n"); + return -EINVAL; + } + + dev_set_drvdata(dev, tdm_priv); + + 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->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(tdm_priv->regs)) { + return PTR_ERR(tdm_priv->regs); + } + + tdm_priv->regmap = devm_regmap_init_mmio(dev, tdm_priv->regs, + &light_tdm_regmap_config); + if (IS_ERR(tdm_priv->regmap)) { + dev_err(dev, "Failed to initialise managed register map\n"); + return PTR_ERR(tdm_priv->regmap); + } + + tdm_priv->audio_pin_regmap = syscon_regmap_lookup_by_phandle(np, "audio-pin-regmap"); + if (IS_ERR(tdm_priv->audio_pin_regmap)) { + dev_err(dev, "cannot find regmap for audio system register\n"); + return -EINVAL; + } else { + light_tdm_pinctrl(tdm_priv); + } + + tdm_priv->audio_cpr_regmap = syscon_regmap_lookup_by_phandle(np, "audio-cpr-regmap"); + if (IS_ERR(tdm_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(tdm_priv->audio_cpr_regmap, + CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV1_SEL_MSK, CPR_AUDIO_DIV1_SEL(5)); + //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; + + tdm_priv->irq = platform_get_irq(pdev, 0); + if (tdm_priv->irq== 0) { + dev_err(dev, "could not map IRQ.\n"); + return -ENXIO; + } + + //ret = request_irq(tdm_priv->irq , tdm_interrupt, + // IRQF_SHARED|IRQF_TRIGGER_RISING, "AUDIO_TDM_IRQ", (char *)tdm_priv); + //if (ret) { + // dev_err(dev, "%s[%d]:request irq error!\n", __func__, __LINE__); + // return ret; + //} + } + + switch(tdm_priv->slot_num) { + case 1: + data_register = TDM_LDR1; + break; + case 2: + data_register = TDM_RDR1; + break; + case 3: + data_register = TDM_LDR2; + break; + case 4: + data_register = TDM_RDR2; + break; + case 5: + data_register = TDM_LDR3; + break; + case 6: + data_register = TDM_RDR3; + break; + case 7: + data_register = TDM_LDR4; + break; + case 8: + data_register = TDM_RDR4; + break; + default: + dev_err(dev, "invalid slot_num\n"); + return -EINVAL; + } + + tdm_priv->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + tdm_priv->dma_params_rx.maxburst = tdm_priv->dma_maxburst; + tdm_priv->dma_params_rx.addr = res->start + data_register; + + 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_tdm_soc_component, + light_tdm_soc_dai, ARRAY_SIZE(light_tdm_soc_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "cannot snd component register\n"); + } + + return ret; +} + +static int light_tdm_remove(struct platform_device *pdev) +{ + struct light_tdm_priv *tdm_priv = dev_get_drvdata(&pdev->dev); + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + light_tdm_runtime_suspend(&pdev->dev); + clk_disable_unprepare(tdm_priv->clk); + return 0; +} + +static const struct dev_pm_ops light_tdm_pm_ops = { + SET_RUNTIME_PM_OPS(light_tdm_runtime_suspend, light_tdm_runtime_resume, NULL) +}; + +static struct platform_driver light_tdm_driver = { + .driver = { + .name = "light-tdm-audio", + .pm = &light_tdm_pm_ops, + .of_match_table = light_tdm_of_match, + }, + .probe = light_tdm_probe, + .remove = light_tdm_remove, +}; + +module_platform_driver(light_tdm_driver); + +MODULE_AUTHOR("nanli.yd "); +MODULE_DESCRIPTION("Thead Light audio driver"); +MODULE_LICENSE("GPL v2"); \ No newline at end of file diff --git a/sound/soc/thead/light-tdm.h b/sound/soc/thead/light-tdm.h new file mode 100644 index 000000000..565cf87ae --- /dev/null +++ b/sound/soc/thead/light-tdm.h @@ -0,0 +1,125 @@ +#ifndef _LIGHT_TDM_H +#define _LIGHT_TDM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "light-pcm.h" +#include + +#define TDM_TDMEN 0x00 +#define TDM_TDMCTL 0x04 +#define TDM_CHOFFSET1 0x08 +#define TDM_CHOFFSET2 0x0c +#define TDM_CHOFFSET3 0x10 +#define TDM_CHOFFSET4 0x14 +#define TDM_FIFOTL1 0x18 +#define TDM_FIFOTL2 0x1C +#define TDM_FIFOTL3 0x20 +#define TDM_FIFOTL4 0x24 +#define TDM_SR 0x28 +#define TDM_IMR 0x2C +#define TDM_ISR 0x30 +#define TDM_RISR 0x34 +#define TDM_ICR 0x38 +#define TDM_DMACTL 0x3C +#define TDM_DMADL 0x40 +#define TDM_LDR1 0x44 +#define TDM_RDR1 0x48 +#define TDM_LDR2 0x4C +#define TDM_RDR2 0x50 +#define TDM_LDR3 0x54 +#define TDM_RDR3 0x58 +#define TDM_LDR4 0x5C +#define TDM_RDR4 0x60 +#define TDM_DIV0_LEVEL 0x64 + +#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_IP_CG_REG 0x010 /* ip clock gate register */ + +/* 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) +#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_TDM_CG_SEL_POS (21U) +#define CPR_TDM_CG_SEL_MSK (0x1U << CPR_TDM_CG_SEL_POS) +#define CPR_TDM_CG_SEL(X) (X << CPR_TDM_CG_SEL_POS) +#define CPR_TDM_SRC_SEL_POS (16U) +#define CPR_TDM_SRC_SEL_MSK (0x3U << CPR_TDM_SRC_SEL_POS) +#define CPR_TDM_SRC_SEL(X) (X << CPR_TDM_SRC_SEL_POS) + +#define TDM_MODE_MASTER 0x1 +#define TDM_MODE_SLAVE 0x0 +#define TDMCTL_MODE_POS (0U) +#define TDMCTL_MODE_MSK (0x1U << TDMCTL_MODE_POS) +#define TDMCTL_MODE_SEL(X) (X << TDMCTL_MODE_POS) +#define TDMCTL_DATAWTH_POS (4U) +#define TDMCTL_DATAWTH_MSK (0x3U << TDMCTL_DATAWTH_POS) +#define TDMCTL_DATAWTH_SEL(X) (X << TDMCTL_DATAWTH_POS) +#define TDMCTL_CHNUM_POS (8U) +#define TDMCTL_CHNUM_MSK (0x3U << TDMCTL_CHNUM_POS) +#define TDMCTL_CHNUM_SEL(X) (X << TDMCTL_CHNUM_POS) +#define TDMCTL_CHNUM_2 0x0 +#define TDMCTL_CHNUM_4 0x1 +#define TDMCTL_CHNUM_6 0x2 +#define TDMCTL_CHNUM_8 0x3 +#define TDMCTL_SPEDGE_POS (13U) +#define TDMCTL_SPEDGE_MSK (0x1U << TDMCTL_SPEDGE_POS) +#define TDMCTL_SPEDGE_SEL(X) (X << TDMCTL_SPEDGE_POS) + +#define TDMCTL_DATAWTH_16BIT_PACKED 0x0 +#define TDMCTL_DATAWTH_16BIT 0x1 +#define TDMCTL_DATAWTH_24BIT 0x2 +#define TDMCTL_DATAWTH_32BIT 0x3 + +#define TDMCTL_DIV0_MASK 0xFFF + +#define DMACTL_DMAEN_POS (0U) +#define DMACTL_DMAEN_MSK (0x1U << DMACTL_DMAEN_POS) +#define DMACTL_DMAEN_SEL(X) (X << DMACTL_DMAEN_POS) + +#define DMACTL_DMADL_POS (0U) +#define DMACTL_DMADL_MSK (0x3U << DMACTL_DMADL_POS) +#define DMACTL_DMADL_SEL(X) (X << DMACTL_DMADL_POS) + +#define TDMCTL_TDMEN_POS (0U) +#define TDMCTL_TDMEN_MSK (0x1U << TDMCTL_TDMEN_POS) +#define TDMCTL_TDMEN_SEL(X) (X << TDMCTL_TDMEN_POS) + +#define LIGHT_TDM_DMABUF_SIZE (64 * 1024) + +struct light_tdm_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_rx; + unsigned int dai_fmt; + u32 dma_maxburst; + unsigned int cfg_off; + struct device *dev; + char mode; + char slots; + char slot_num; + unsigned int irq; +}; + + +#endif \ No newline at end of file diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index e440cd7f3..b9ee2ded3 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -5006,7 +5006,10 @@ struct bpf_pidns_info { /* User accessible data for SK_LOOKUP programs. Add new fields at the end. */ struct bpf_sk_lookup { - __bpf_md_ptr(struct bpf_sock *, sk); /* Selected socket */ + union { + __bpf_md_ptr(struct bpf_sock *, sk); /* Selected socket */ + __u64 cookie; /* Non-zero if socket was selected in PROG_TEST_RUN */ + }; __u32 family; /* Protocol family (AF_INET, AF_INET6) */ __u32 protocol; /* IP protocol (IPPROTO_TCP, IPPROTO_UDP) */ diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h index 1c2e91ee0..6e262dad7 100644 --- a/tools/lib/bpf/bpf_tracing.h +++ b/tools/lib/bpf/bpf_tracing.h @@ -24,6 +24,9 @@ #elif defined(__TARGET_ARCH_sparc) #define bpf_target_sparc #define bpf_target_defined +#elif defined(__TARGET_ARCH_riscv) + #define bpf_target_riscv + #define bpf_target_defined #else #undef bpf_target_defined #endif @@ -44,6 +47,8 @@ #define bpf_target_powerpc #elif defined(__sparc__) #define bpf_target_sparc +#elif defined(__riscv) && __riscv_xlen == 64 + #define bpf_target_riscv #endif #endif @@ -279,6 +284,32 @@ struct pt_regs; #define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), pc) #endif +#elif defined(bpf_target_riscv) + +struct pt_regs; +#define PT_REGS_RV const volatile struct user_regs_struct +#define PT_REGS_PARM1(x) (((PT_REGS_RV *)(x))->a0) +#define PT_REGS_PARM2(x) (((PT_REGS_RV *)(x))->a1) +#define PT_REGS_PARM3(x) (((PT_REGS_RV *)(x))->a2) +#define PT_REGS_PARM4(x) (((PT_REGS_RV *)(x))->a3) +#define PT_REGS_PARM5(x) (((PT_REGS_RV *)(x))->a4) +#define PT_REGS_RET(x) (((PT_REGS_RV *)(x))->ra) +#define PT_REGS_FP(x) (((PT_REGS_RV *)(x))->s0) +#define PT_REGS_RC(x) (((PT_REGS_RV *)(x))->a0) +#define PT_REGS_SP(x) (((PT_REGS_RV *)(x))->sp) +#define PT_REGS_IP(x) (((PT_REGS_RV *)(x))->pc) + +#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a0) +#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a1) +#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a2) +#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a3) +#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a4) +#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), ra) +#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), s0) +#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a0) +#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), sp) +#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), pc) + #endif #if defined(bpf_target_powerpc) diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 1d9155533..11b90fe86 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -224,7 +224,7 @@ $(RESOLVE_BTFIDS): $(BPFOBJ) | $(BUILD_DIR)/resolve_btfids \ define get_sys_includes $(shell $(1) -v -E - &1 \ | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \ -$(shell $(1) -dM -E - = 0) { + if (!alignment_prevented_execution && fd_prog >= 0 && test->runs >= 0) { uint32_t expected_val; int i; diff --git a/tools/testing/selftests/bpf/verifier/ctx_sk_lookup.c b/tools/testing/selftests/bpf/verifier/ctx_sk_lookup.c index 2ad5f9744..fd3b62a08 100644 --- a/tools/testing/selftests/bpf/verifier/ctx_sk_lookup.c +++ b/tools/testing/selftests/bpf/verifier/ctx_sk_lookup.c @@ -239,6 +239,7 @@ .result = ACCEPT, .prog_type = BPF_PROG_TYPE_SK_LOOKUP, .expected_attach_type = BPF_SK_LOOKUP, + .runs = -1, }, /* invalid 8-byte reads from a 4-byte fields in bpf_sk_lookup */ {