From 79ab113bc5c7e475f6cec5c1a2c41c1a3a9d711c Mon Sep 17 00:00:00 2001 From: "curry.zhang" Date: Mon, 20 Jun 2022 09:12:55 -0700 Subject: [PATCH] [Audio: I2S & WM8960] Porting i2s to match wm8960 driver Signed-off-by: curry.zhang --- arch/riscv/boot/dts/starfive/codecs/sf_wm8960.dtsi | 2 +- arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 6 +- arch/riscv/boot/dts/starfive/jh7110-evb.dts | 1 + arch/riscv/boot/dts/starfive/jh7110.dtsi | 35 +- arch/riscv/boot/dts/starfive/jh7110_pinctrl.dtsi | 24 +- arch/riscv/configs/starfive_jh7110_defconfig | 3 +- sound/last.c | 2 + sound/soc/codecs/wm8960.c | 117 ++-- sound/soc/dwc/dwc-i2s.c | 616 +++++++++++++++++---- sound/soc/dwc/local.h | 58 +- 10 files changed, 675 insertions(+), 189 deletions(-) mode change 100644 => 100755 arch/riscv/boot/dts/starfive/jh7110.dtsi mode change 100644 => 100755 arch/riscv/boot/dts/starfive/jh7110_pinctrl.dtsi mode change 100644 => 100755 sound/soc/dwc/dwc-i2s.c mode change 100644 => 100755 sound/soc/dwc/local.h diff --git a/arch/riscv/boot/dts/starfive/codecs/sf_wm8960.dtsi b/arch/riscv/boot/dts/starfive/codecs/sf_wm8960.dtsi index c5cb532a..2ae96e4 100644 --- a/arch/riscv/boot/dts/starfive/codecs/sf_wm8960.dtsi +++ b/arch/riscv/boot/dts/starfive/codecs/sf_wm8960.dtsi @@ -31,7 +31,7 @@ sndcodec1:codec { sound-dai = <&wm8960>; - clocks = <&clkgen JH7110_MCLK>; + clocks = <&wm8960_mclk>; clock-names = "mclk"; }; }; diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi index 33acdd6..32e3cfa 100644 --- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi @@ -463,18 +463,18 @@ &i2srx_3ch { pinctrl-names = "default"; - pinctrl-0 = <&i2s_clk_pins>; + pinctrl-0 = <&i2srx_pins>; status = "okay"; }; &i2stx_4ch0 { - status = "okay"; + status = "disabled"; }; &i2stx_4ch1 { pinctrl-names = "default"; pinctrl-0 = <&i2s_clk_pins &i2stx_pins>; - status = "disabled"; + status = "okay"; }; &ptc { diff --git a/arch/riscv/boot/dts/starfive/jh7110-evb.dts b/arch/riscv/boot/dts/starfive/jh7110-evb.dts index 2e9f6dd..e63875c 100644 --- a/arch/riscv/boot/dts/starfive/jh7110-evb.dts +++ b/arch/riscv/boot/dts/starfive/jh7110-evb.dts @@ -6,6 +6,7 @@ /dts-v1/; #include "jh7110-common.dtsi" +#include "codecs/sf_wm8960.dtsi" / { model = "StarFive JH7110 EVB"; diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi old mode 100644 new mode 100755 index 61621ba..db8c161 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -1117,13 +1117,16 @@ reg = <0x0 0x100e0000 0x0 0x1000>; clocks = <&clkgen JH7110_APB0>, <&clkgen JH7110_I2SRX0_3CH_CLK_APB>, + <&clkgen JH7110_AUDIO_ROOT>, + <&clkgen JH7110_MCLK_INNER>, <&clkgen JH7110_I2SRX_3CH_BCLK_MST>, <&clkgen JH7110_I2SRX_3CH_LRCK_MST>, <&clkgen JH7110_I2SRX0_3CH_BCLK>, <&clkgen JH7110_I2SRX0_3CH_LRCK>; - clock-names = "apb0", "i2srx_apb", - "i2srx_bclk_mst", "i2srx_lrck_mst", - "i2srx_bclk", "i2srx_lrck"; + clock-names = "apb0", "3ch-apb", + "audioroot", "mclk-inner", + "bclk_mst", "3ch-lrck", + "rx-bclk", "rx-lrck"; resets = <&rstgen RSTN_U0_I2SRX_3CH_APB>, <&rstgen RSTN_U0_I2SRX_3CH_BCLK>; reset-names = "rst_apb_rx", "rst_bclk_rx"; @@ -1149,8 +1152,6 @@ resets = <&rstgen RSTN_U0_I2STX_4CH_APB>, <&rstgen RSTN_U0_I2STX_4CH_BCLK>; reset-names = "rst_apb0", "rst_bclk0"; - interrupts = <58>; - interrupt-names = "tx"; dmas = <&dma 47 1>; dma-names = "tx"; #sound-dai-cells = <0>; @@ -1160,20 +1161,28 @@ i2stx_4ch1: i2stx_4ch1@120c0000 { compatible = "snps,designware-i2stx-4ch1"; reg = <0x0 0x120c0000 0x0 0x1000>; - clocks = <&clkgen JH7110_MCLK_INNER>, + clocks = <&clkgen JH7110_AUDIO_ROOT>, + <&clkgen JH7110_MCLK_INNER>, <&clkgen JH7110_I2STX_4CH1_BCLK_MST>, <&clkgen JH7110_I2STX_4CH1_LRCK_MST>, <&clkgen JH7110_MCLK>, <&clkgen JH7110_I2STX1_4CHBCLK>, - <&clkgen JH7110_I2STX1_4CHLRCK>; - clock-names = "inner", "bclk-mst1", - "lrck-mst1", "mclk", - "bclk1", "lrck1"; + <&clkgen JH7110_I2STX1_4CHLRCK>, + <&clkgen JH7110_MCLK_OUT>, + <&clkgen JH7110_APB0>, + <&clkgen JH7110_I2STX1_4CHCLK_APB>, + <&mclk_ext>, + <&i2stx_bclk_ext>, + <&i2stx_lrck_ext>; + clock-names = "audroot", "mclk_inner", "bclk_mst", + "lrck_mst", "mclk", "4chbclk", + "4chlrck", "mclk_out", + "apb0", "clk_apb", + "mclk_ext", "bclk_ext", "lrck_ext"; + resets = <&rstgen RSTN_U1_I2STX_4CH_APB>, <&rstgen RSTN_U1_I2STX_4CH_BCLK>; reset-names = "rst_apb1", "rst_bclk1"; - interrupts = <59>; - interrupt-names = "tx"; dmas = <&dma 48 1>; dma-names = "tx"; #sound-dai-cells = <0>; @@ -1622,6 +1631,8 @@ clock-names = "mclk"; }; }; + + }; co_process: e24@0 { diff --git a/arch/riscv/boot/dts/starfive/jh7110_pinctrl.dtsi b/arch/riscv/boot/dts/starfive/jh7110_pinctrl.dtsi old mode 100644 new mode 100755 index 0d05b3c..1ea1bc8 --- a/arch/riscv/boot/dts/starfive/jh7110_pinctrl.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110_pinctrl.dtsi @@ -493,12 +493,28 @@ sf,pin-gpio-doen = ; }; */ + i2s-clk0_bclk { + sf,pins = ; + sf,pinmux = ; + sf,pin-ioconfig = ; + sf,pin-gpio-din = ; + sf,pin-gpio-doen = ; + }; + + i2s-clk0_lrclk { + sf,pins = ; + sf,pinmux = ; + sf,pin-ioconfig = ; + sf,pin-gpio-din = ; + sf,pin-gpio-doen = ; + }; + }; i2stx_pins: i2stx-pins { i2stx-pins0 { - sf,pins = ; - sf,pinmux = ; + sf,pins = ; + sf,pinmux = ; sf,pin-ioconfig = ; sf,pin-gpio-dout = ; sf,pin-gpio-doen = ; @@ -507,8 +523,8 @@ i2srx_pins: i2srx-pins { i2srx-pins0 { - sf,pins = ; - sf,pinmux = ; + sf,pins = ; + sf,pinmux = ; sf,pin-ioconfig = ; sf,pin-gpio-doen = ; sf,pin-gpio-din = ; diff --git a/arch/riscv/configs/starfive_jh7110_defconfig b/arch/riscv/configs/starfive_jh7110_defconfig index 627ba81..9675024 100644 --- a/arch/riscv/configs/starfive_jh7110_defconfig +++ b/arch/riscv/configs/starfive_jh7110_defconfig @@ -192,7 +192,8 @@ CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y -CONFIG_SND_STARFIVE_TDM=y +CONFIG_SND_DESIGNWARE_I2S=y +CONFIG_SND_DESIGNWARE_I2S_STARFIVE_JH7110=y CONFIG_SND_SOC_WM8960=y CONFIG_SND_SIMPLE_CARD=y CONFIG_USB=y diff --git a/sound/last.c b/sound/last.c index f0bb987..37d32e3 100644 --- a/sound/last.c +++ b/sound/last.c @@ -5,12 +5,14 @@ */ #include +#include #include static int __init alsa_sound_last_init(void) { struct snd_card *card; int idx, ok = 0; + msleep(2000); printk(KERN_INFO "ALSA device list:\n"); for (idx = 0; idx < SNDRV_CARDS; idx++) { diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 2827428..f5bb359 100755 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -815,6 +816,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component); u16 iface = snd_soc_component_read(component, WM8960_IFACE1) & 0xfff3; + u16 audio_format = iface & 0x3; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; int i; @@ -860,56 +862,78 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, /* set iface */ snd_soc_component_write(component, WM8960_IFACE1, iface); - /* Temp add by walker */ - snd_soc_component_write(component, WM8960_POWER1, 0xfe); - snd_soc_component_write(component, WM8960_POWER2, 0x1f8); - snd_soc_component_write(component, WM8960_POWER2, 0x1f9); - snd_soc_component_write(component, WM8960_PLL1, 0x28); - snd_soc_component_write(component, WM8960_PLL1, 0x38); - snd_soc_component_write(component, WM8960_CLOCK1, 0xdd); - snd_soc_component_write(component, WM8960_CLOCK2, 0x1cc); - snd_soc_component_write(component, WM8960_POWER3, 0x3c); - - if (tx) { - snd_soc_component_write(component, WM8960_LOUTMIX, 0x100); - snd_soc_component_write(component, WM8960_ROUTMIX, 0x100); - snd_soc_component_write(component, WM8960_POWER3, 0xc); + if (audio_format == 0x3) //TDM Format + { + snd_soc_component_write(component, WM8960_POWER1, 0xfe); + snd_soc_component_write(component, WM8960_POWER2, 0x1f8); snd_soc_component_write(component, WM8960_POWER2, 0x1f9); + snd_soc_component_write(component, WM8960_PLL1, 0x28); + snd_soc_component_write(component, WM8960_PLL1, 0x38); + snd_soc_component_write(component, WM8960_CLOCK1, 0xdd); + snd_soc_component_write(component, WM8960_CLOCK2, 0x1cc); + snd_soc_component_write(component, WM8960_POWER3, 0x3c); + + if (tx) { + snd_soc_component_write(component, WM8960_LOUTMIX, 0x100); + snd_soc_component_write(component, WM8960_ROUTMIX, 0x100); + snd_soc_component_write(component, WM8960_POWER3, 0xc); + snd_soc_component_write(component, WM8960_POWER2, 0x1f9); + snd_soc_component_write(component, WM8960_POWER2, 0x1f9); + snd_soc_component_write(component, WM8960_IFACE1, 0x3); + snd_soc_component_write(component, WM8960_IFACE1, 0x43); + snd_soc_component_write(component, WM8960_POWER1, 0xd6); + snd_soc_component_write(component, WM8960_POWER1, 0xc6); + } else { + snd_soc_component_write(component, WM8960_POWER3, 0x30); + snd_soc_component_write(component, WM8960_POWER1, 0xfe); + snd_soc_component_write(component, WM8960_POWER1, 0xfe); + snd_soc_component_write(component, WM8960_POWER3, 0x30); + snd_soc_component_write(component, WM8960_POWER3, 0x30); + snd_soc_component_write(component, WM8960_POWER1, 0xfe); + snd_soc_component_write(component, WM8960_POWER1, 0xfe); + snd_soc_component_write(component, WM8960_ADDCTL2, 0x0); + snd_soc_component_write(component, WM8960_IFACE1, 0x3); + snd_soc_component_write(component, WM8960_IFACE1, 0x43); + snd_soc_component_write(component, WM8960_POWER1, 0xfe); + snd_soc_component_write(component, WM8960_LINPATH, 0x108); + snd_soc_component_write(component, WM8960_POWER1, 0xfe); + snd_soc_component_write(component, WM8960_RINPATH, 0x108); + } + + snd_soc_component_write(component, WM8960_ADDCTL1, 0xc0); + snd_soc_component_write(component, WM8960_ADDCTL4, 0x0); + snd_soc_component_write(component, WM8960_BYPASS1, 0x0); + snd_soc_component_write(component, WM8960_BYPASS2, 0x0); + snd_soc_component_write(component, WM8960_CLASSD1, 0xf7); + snd_soc_component_write(component, WM8960_DACCTL1, 0x0); + snd_soc_component_write(component, WM8960_NOISEG, 0xf9); + snd_soc_component_write(component, WM8960_ALC1, 0x1bb); + snd_soc_component_write(component, WM8960_ALC2, 0x30); + /* bclk inverted */ + snd_soc_component_update_bits(component, WM8960_IFACE1, 0x80, 0x80); snd_soc_component_write(component, WM8960_POWER2, 0x1f9); - snd_soc_component_write(component, WM8960_IFACE1, 0x3); - snd_soc_component_write(component, WM8960_IFACE1, 0x43); - snd_soc_component_write(component, WM8960_POWER1, 0xd6); - snd_soc_component_write(component, WM8960_POWER1, 0xc6); - } else { - snd_soc_component_write(component, WM8960_POWER3, 0x30); - snd_soc_component_write(component, WM8960_POWER1, 0xfe); - snd_soc_component_write(component, WM8960_POWER1, 0xfe); - snd_soc_component_write(component, WM8960_POWER3, 0x30); - snd_soc_component_write(component, WM8960_POWER3, 0x30); - snd_soc_component_write(component, WM8960_POWER1, 0xfe); - snd_soc_component_write(component, WM8960_POWER1, 0xfe); - snd_soc_component_write(component, WM8960_ADDCTL2, 0x0); - snd_soc_component_write(component, WM8960_IFACE1, 0x3); - snd_soc_component_write(component, WM8960_IFACE1, 0x43); - snd_soc_component_write(component, WM8960_POWER1, 0xfe); - snd_soc_component_write(component, WM8960_LINPATH, 0x108); - snd_soc_component_write(component, WM8960_POWER1, 0xfe); - snd_soc_component_write(component, WM8960_RINPATH, 0x108); + } else if (audio_format == 0x2) { //I2S Format + if (!tx) + { + snd_soc_component_update_bits(component, WM8960_LINVOL, 0x3<<7, 0x2<<7); + snd_soc_component_update_bits(component, WM8960_RINVOL, 0x3<<7, 0x2<<7); + snd_soc_component_write(component, WM8960_CLOCK1, 0x00); //0xd8 + snd_soc_component_write(component, WM8960_ALC1, 0x1bb); + snd_soc_component_write(component, WM8960_ALC2, 0x30); + snd_soc_component_write(component, WM8960_ALC3, 0x30); + snd_soc_component_write(component, WM8960_NOISEG, 0xf9); + snd_soc_component_write(component, WM8960_LADC, 0x197); + snd_soc_component_write(component, WM8960_RADC, 0x197); + snd_soc_component_write(component, WM8960_ADDCTL1, 0xc0); + snd_soc_component_write(component, WM8960_ADDCTL3, 0x03); + snd_soc_component_write(component, WM8960_LOUT2, 0x1ff); + snd_soc_component_write(component, WM8960_ROUT2, 0x1ff); + snd_soc_component_write(component, WM8960_BYPASS1, 0x00); + snd_soc_component_write(component, WM8960_BYPASS2, 0x00); + snd_soc_component_write(component, WM8960_ADDCTL4, 0x00); + } } - snd_soc_component_write(component, WM8960_ADDCTL1, 0xc0); - snd_soc_component_write(component, WM8960_ADDCTL4, 0x0); - snd_soc_component_write(component, WM8960_BYPASS1, 0x0); - snd_soc_component_write(component, WM8960_BYPASS2, 0x0); - snd_soc_component_write(component, WM8960_CLASSD1, 0xf7); - snd_soc_component_write(component, WM8960_DACCTL1, 0x0); - snd_soc_component_write(component, WM8960_NOISEG, 0xf9); - snd_soc_component_write(component, WM8960_ALC1, 0x1bb); - snd_soc_component_write(component, WM8960_ALC2, 0x30); - /* bclk inverted */ - snd_soc_component_update_bits(component, WM8960_IFACE1, 0x80, 0x80); - snd_soc_component_write(component, WM8960_POWER2, 0x1f9); - wm8960->is_stream_in_use[tx] = true; if (!wm8960->is_stream_in_use[!tx]) @@ -1611,6 +1635,7 @@ static struct i2c_driver wm8960_i2c_driver = { module_i2c_driver(wm8960_i2c_driver); + MODULE_DESCRIPTION("ASoC WM8960 driver"); MODULE_AUTHOR("Liam Girdwood"); diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c old mode 100644 new mode 100755 index 76ff62d..ab8aaf1 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -29,6 +29,26 @@ #include #include "local.h" +static const char * const rst_name[RST_AUDIO_NUM] = { + [RST_APB0_BUS] = "rst_apb0", + [RST_BCLK_0] = "rst_bclk0", + [RST_APB1_BUS] = "rst_apb1", + [RST_BCLK_1] = "rst_bclk1", + [RST_APB_RX] = "rst_apb_rx", + [RST_BCLK_RX] = "rst_bclk_rx", +}; + +#define CLOCK_BASE 0x13020000UL + +static void saif_set_reg(void __iomem *addr, u32 data, u32 shift, u32 mask) +{ + u32 tmp; + tmp = readl(addr); + tmp &= ~mask; + tmp |= (data << shift) & mask; + writel(tmp, addr); +} + static inline void i2s_write_reg(void __iomem *io_base, int reg, u32 val) { writel(val, io_base + reg); @@ -166,7 +186,6 @@ static void i2s_start(struct dw_i2s_dev *dev, i2s_write_reg(dev->i2s_base, IRER, 1); i2s_write_reg(dev->i2s_base, CER, 1); - } static void i2s_stop(struct dw_i2s_dev *dev, @@ -246,7 +265,7 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); struct i2s_clk_config_data *config = &dev->config; int ret; - unsigned int bclk_rate; + unsigned int txrx = substream->stream; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: @@ -272,19 +291,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - switch (params_rate(params)) { - case 8000: - bclk_rate = 512000; - break; - case 16000: - bclk_rate = 1024000; - break; - default: - dev_err(dai->dev, "%d rate not supported\n", - params_rate(params)); - return -EINVAL; - } - config->chan_nr = params_channels(params); switch (config->chan_nr) { @@ -298,13 +304,35 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + if (txrx == SNDRV_PCM_STREAM_PLAYBACK) + { + //_SWITCH_CLOCK_CLK_MCLK_SOURCE_CLK_MCLK_EXT_; + saif_set_reg(dev->clk_base + 0x48, 1, 24, 0x1000000); + + //_SWITCH_CLOCK_CLK_U1_I2STX_4CH_BCLK_SOURCE_CLK_I2STX_BCLK_EXT_; + saif_set_reg(dev->clk_base + 0x2B0, 1, 24, 0x1000000); + + //_SWITCH_CLOCK_CLK_U1_I2STX_4CH_LRCK_SOURCE_CLK_I2STX_LRCK_EXT_; + saif_set_reg(dev->clk_base + 0x2B8, 1, 24, 0x1000000); + } + else if (txrx == SNDRV_PCM_STREAM_CAPTURE) + { + //_SWITCH_CLOCK_CLK_MCLK_SOURCE_CLK_MCLK_EXT_; + saif_set_reg(dev->clk_base + 0x48, 1, 24, 0x1000000); + + //_SWITCH_CLOCK_CLK_U1_I2STX_4CH_BCLK_SOURCE_CLK_I2STX_BCLK_EXT_; + saif_set_reg(dev->clk_base + 0x2CC, 1, 24, 0x1000000); + + //_SWITCH_CLOCK_CLK_U1_I2STX_4CH_LRCK_SOURCE_CLK_I2STX_LRCK_EXT_; + saif_set_reg(dev->clk_base + 0x2D4, 1, 24, 0x1000000); + } + dw_i2s_config(dev, substream->stream); i2s_write_reg(dev->i2s_base, CCR, dev->ccr); config->sample_rate = params_rate(params); - if (dev->capability & DW_I2S_MASTER) { if (dev->i2s_clk_cfg) { ret = dev->i2s_clk_cfg(config); @@ -313,9 +341,13 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, return ret; } } else { - ret = clk_set_rate(dev->clk_i2srx_bclk_mst, bclk_rate); + u32 bitclk = config->sample_rate * + config->data_width * 2; + + ret = clk_set_rate(dev->clk, bitclk); if (ret) { - dev_err(dev->dev, "Can't set i2s bclk: %d\n", ret); + dev_err(dev->dev, "Can't set I2S clock rate: %d\n", + ret); return ret; } } @@ -473,97 +505,428 @@ static int dw_i2srx_clk_init(struct platform_device *pdev, struct dw_i2s_dev *de static struct clk_bulk_data clks[] = { { .id = "apb0" }, - { .id = "i2srx_apb" }, - { .id = "i2srx_bclk_mst" }, - { .id = "i2srx_lrck_mst" }, - { .id = "i2srx_bclk" }, - { .id = "i2srx_lrck" }, + { .id = "3ch-apb" }, + { .id = "audioroot" }, + { .id = "mclk-inner" }, + { .id = "bclk_mst" }, + { .id = "3ch-lrck" }, + { .id = "rx-bclk" }, + { .id = "rx-lrck" }, }; ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(clks), clks); if (ret) { - dev_err(&pdev->dev, "%s: failed to get i2srx clocks\n", __func__); - goto exit; + dev_err(&pdev->dev, "%s: failed to get audio_subsys clocks\n", __func__); + return ret; + } + dev->clks[CLK_ADC_APB0] = clks[0].clk; + dev->clks[CLK_ADC_APB] = clks[1].clk; + dev->clks[CLK_ADC_AUDROOT] = clks[2].clk; + dev->clks[CLK_ADC_MCLK_INNER] = clks[3].clk; + dev->clks[CLK_ADC_BCLK] = clks[4].clk; + dev->clks[CLK_ADC_LRCLK] = clks[5].clk; + dev->clks[CLK_ADC_RX_BCLK] = clks[6].clk; + dev->clks[CLK_ADC_RX_LRCK] = clks[7].clk; + + ret = clk_prepare_enable(dev->clks[CLK_ADC_APB0]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_ADC_APB0\n", __func__); + goto disable_APB0_clk; + } + + ret = clk_prepare_enable(dev->clks[CLK_ADC_APB]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_ADC_APB\n", __func__); + goto disable_APB_clk; + } + + ret = clk_prepare_enable(dev->clks[CLK_ADC_AUDROOT]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_ADC_AUDROOT\n", __func__); + goto disable_audroot_clk; + } + ret = clk_set_rate(dev->clks[CLK_ADC_AUDROOT], 204800000); + if (ret) { + dev_err(&pdev->dev, "failed to set rate for CLK_ADC_MCLK \n"); + goto disable_audroot_clk; + } + + ret = clk_prepare_enable(dev->clks[CLK_ADC_MCLK_INNER]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_ADC_MCLK_INNER\n", __func__); + goto disable_inner_clk; + } + + ret = clk_set_rate(dev->clks[CLK_ADC_MCLK_INNER], 4096000); + if (ret) { + dev_err(&pdev->dev, "failed to set rate for CLK_ADC_MCLK \n"); + goto disable_inner_clk; + } + + ret = clk_prepare_enable(dev->clks[CLK_ADC_BCLK]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_ADC_BCLK\n", __func__); + goto disable_bclk; + } + + ret = clk_prepare_enable(dev->clks[CLK_ADC_LRCLK]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_ADC_LRCLK\n", __func__); + goto disable_lrclk; } - dev->clk_apb0 = clks[0].clk; - dev->clk_i2srx_apb = clks[1].clk; - dev->clk_i2srx_bclk_mst = clks[2].clk; - dev->clk_i2srx_lrck_mst = clks[3].clk; - dev->clk_i2srx_bclk = clks[4].clk; - dev->clk_i2srx_lrck = clks[5].clk; + ret = clk_prepare_enable(dev->clks[CLK_ADC_RX_BCLK]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_ADC_RX_BCLK\n", __func__); + goto disable_rx_bclk; + } - dev->rst_i2srx_apb = devm_reset_control_get_exclusive(&pdev->dev, "rst_apb_rx"); - if (IS_ERR(dev->rst_i2srx_apb)) { - dev_err(&pdev->dev, "failed to get apb_i2srx reset control\n"); - ret = PTR_ERR(dev->rst_i2srx_apb); - goto exit; + ret = clk_prepare_enable(dev->clks[CLK_ADC_RX_LRCK]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_ADC_RX_LRCK\n", __func__); + goto disable_rx_lrclk; + } + dev_dbg(&pdev->dev, "dev->clks[CLK_ADC_APB0] = %lu \n", clk_get_rate(dev->clks[CLK_ADC_APB0])); + dev_dbg(&pdev->dev, "dev->clks[CLK_ADC_APB] = %lu \n", clk_get_rate(dev->clks[CLK_ADC_APB])); + dev_dbg(&pdev->dev, "dev->clks[CLK_ADC_BCLK] = %lu \n", clk_get_rate(dev->clks[CLK_ADC_BCLK])); + dev_dbg(&pdev->dev, "dev->clks[CLK_ADC_LRCLK] = %lu \n", clk_get_rate(dev->clks[CLK_ADC_LRCLK])); + dev_dbg(&pdev->dev, "dev->clks[CLK_ADC_RX_BCLK] = %lu \n", clk_get_rate(dev->clks[CLK_ADC_RX_BCLK])); + dev_dbg(&pdev->dev, "dev->clks[CLK_ADC_RX_LRCK] = %lu \n", clk_get_rate(dev->clks[CLK_ADC_RX_LRCK])); + + dev->rstc[RST_APB_RX] = devm_reset_control_get_exclusive(&pdev->dev, rst_name[RST_APB_RX]); + if (IS_ERR(dev->rstc[RST_APB_RX])) { + dev_err(&pdev->dev, "%s: failed to get apb_i2srx reset control\n", __func__); + return PTR_ERR(dev->rstc[RST_APB_RX]); } - dev->rst_i2srx_bclk = devm_reset_control_get_exclusive(&pdev->dev, "rst_bclk_rx"); - if (IS_ERR(dev->rst_i2srx_bclk)) { - dev_err(&pdev->dev, "failed to get i2s bclk rx reset control\n"); - ret = PTR_ERR(dev->rst_i2srx_bclk); - goto exit; + dev->rstc[RST_BCLK_RX] = devm_reset_control_get_exclusive(&pdev->dev, rst_name[RST_BCLK_RX]); + if (IS_ERR(dev->rstc[RST_BCLK_RX])) { + dev_err(&pdev->dev, "%s: failed to get i2s bclk rx reset control", __func__); + return PTR_ERR(dev->rstc[RST_BCLK_RX]); } + reset_control_assert(dev->rstc[RST_APB_RX]); + reset_control_assert(dev->rstc[RST_BCLK_RX]); + + udelay(5); + + reset_control_deassert(dev->rstc[RST_APB_RX]); + reset_control_deassert(dev->rstc[RST_BCLK_RX]); + + /*i2srx_3ch_adc_enable*/ + regmap_update_bits(dev->syscon_base, dev->syscon_offset_18, + 0x1 << 1, 0x1 << 1); + + /*set i2sdin_sel*/ + regmap_update_bits(dev->syscon_base, dev->syscon_offset_34, + (0x1 << 10) | (0x1 << 14) | (0x1<<17), (0x0<<10) | (0x0<<14) | (0x0<<17)); + + return 0; - reset_control_assert(dev->rst_i2srx_apb); - reset_control_assert(dev->rst_i2srx_bclk); +disable_rx_lrclk: + clk_disable_unprepare(dev->clks[CLK_ADC_RX_LRCK]); +disable_rx_bclk: + clk_disable_unprepare(dev->clks[CLK_ADC_RX_BCLK]); +disable_lrclk: + clk_disable_unprepare(dev->clks[CLK_ADC_LRCLK]); +disable_bclk: + clk_disable_unprepare(dev->clks[CLK_ADC_BCLK]); +disable_inner_clk: + clk_disable_unprepare(dev->clks[CLK_ADC_MCLK_INNER]); +disable_audroot_clk: + clk_disable_unprepare(dev->clks[CLK_ADC_AUDROOT]); +disable_APB_clk: + clk_disable_unprepare(dev->clks[CLK_ADC_APB]); +disable_APB0_clk: + clk_disable_unprepare(dev->clks[CLK_ADC_APB0]); - ret = clk_prepare_enable(dev->clk_apb0); + return ret; +} + +static int dw_i2stx_4ch0_clk_init(struct platform_device *pdev, struct dw_i2s_dev *dev) +{ + static struct clk_bulk_data i2sclk[] = { + { .id = "inner" }, //clock-names in dts file + { .id = "bclk-mst" }, + { .id = "lrck-mst" }, + { .id = "mclk" }, + { .id = "bclk0" }, + { .id = "lrck0" }, + }; + + int ret = 0; + + ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(i2sclk), i2sclk); if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_apb0\n"); - goto exit; + printk(KERN_INFO "%s: failed to get i2stx 4ch0 clocks\n", __func__); + return ret; } - ret = clk_prepare_enable(dev->clk_i2srx_apb); + dev->clks[CLK_DAC_INNER] = i2sclk[0].clk; + dev->clks[CLK_DAC_BCLK_MST] = i2sclk[1].clk; + dev->clks[CLK_DAC_LRCLK_MST] = i2sclk[2].clk; + dev->clks[CLK_MCLK] = i2sclk[3].clk; + dev->clks[CLK_DAC_BCLK0] = i2sclk[4].clk; + dev->clks[CLK_DAC_LRCLK0] = i2sclk[5].clk; + + ret = clk_prepare_enable(dev->clks[CLK_DAC_INNER]); if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_i2srx_apb\n"); - goto err_dis_i2srx_apb; + dev_err(&pdev->dev, "%s: failed to enable CLK_DAC_INNER\n", __func__); + goto disable_inner_clk; } - ret = clk_prepare_enable(dev->clk_i2srx_bclk_mst); + ret = clk_prepare_enable(dev->clks[CLK_DAC_BCLK_MST]); if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_i2srx_3ch_bclk_mst\n"); - goto err_dis_bclk_mst; + dev_err(&pdev->dev, "%s: failed to enable CLK_DAC_BCLK_MST\n", __func__); + goto disable_bclk_mst; } - ret = clk_prepare_enable(dev->clk_i2srx_lrck_mst); + ret = clk_prepare_enable(dev->clks[CLK_DAC_LRCLK_MST]); if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_i2srx_3ch_lrck_mst\n"); - goto err_dis_lrck_mst; + dev_err(&pdev->dev, "%s: failed to enable CLK_DAC_LRCLK_MST\n", __func__); + goto disable_lrclk_mst; } - ret = clk_prepare_enable(dev->clk_i2srx_bclk); + ret = clk_prepare_enable(dev->clks[CLK_MCLK]); if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_i2srx_3ch_bclk\n"); - goto err_dis_bclk; + dev_err(&pdev->dev, "%s: failed to enable CLK_MCLK\n", __func__); + goto disable_mclk; } - ret = clk_prepare_enable(dev->clk_i2srx_lrck); + ret = clk_prepare_enable(dev->clks[CLK_DAC_BCLK0]); if (ret) { - dev_err(&pdev->dev, "failed to prepare enable clk_i2srx_3ch_lrck\n"); - goto err_dis_lrck; + dev_err(&pdev->dev, "%s: failed to enable CLK_DAC_BCLK0\n", __func__); + goto disable_bclk0; } - reset_control_deassert(dev->rst_i2srx_apb); - reset_control_deassert(dev->rst_i2srx_bclk); + ret = clk_prepare_enable(dev->clks[CLK_DAC_LRCLK0]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_DAC_LRCLK0\n", __func__); + goto disable_lrclk0; + } + + dev->rstc[RST_APB0_BUS] = devm_reset_control_get_exclusive(&pdev->dev, rst_name[RST_APB0_BUS]); + if (IS_ERR(dev->rstc[RST_APB0_BUS])) { + dev_err(&pdev->dev, "%s: failed to get apb_i2stx reset control\n", __func__); + return PTR_ERR(dev->rstc[RST_APB0_BUS]); + } + + dev->rstc[RST_BCLK_0] = devm_reset_control_get_exclusive(&pdev->dev, rst_name[RST_BCLK_0]); + if (IS_ERR(dev->rstc[RST_BCLK_0])) { + dev_err(&pdev->dev, "%s: failed to get i2s bclk0 reset control\n", __func__); + return PTR_ERR(dev->rstc[RST_BCLK_0]); + } + + reset_control_deassert(dev->rstc[RST_APB0_BUS]); + reset_control_deassert(dev->rstc[RST_BCLK_0]); - regmap_update_bits(dev->syscon_base, dev->syscon_offset_18, - I2SRX_3CH_ADC_MASK, I2SRX_3CH_ADC_EN); return 0; -err_dis_i2srx_apb: - clk_disable_unprepare(dev->clk_apb0); -err_dis_bclk_mst: - clk_disable_unprepare(dev->clk_i2srx_apb); -err_dis_lrck_mst: - clk_disable_unprepare(dev->clk_i2srx_bclk_mst); -err_dis_bclk: - clk_disable_unprepare(dev->clk_i2srx_lrck_mst); -err_dis_lrck: - clk_disable_unprepare(dev->clk_i2srx_bclk); -exit: +disable_lrclk0: + clk_disable_unprepare(dev->clks[CLK_DAC_LRCLK0]); +disable_bclk0: + clk_disable_unprepare(dev->clks[CLK_DAC_BCLK0]); +disable_mclk: + clk_disable_unprepare(dev->clks[CLK_MCLK]); +disable_lrclk_mst: + clk_disable_unprepare(dev->clks[CLK_DAC_LRCLK_MST]); +disable_bclk_mst: + clk_disable_unprepare(dev->clks[CLK_DAC_BCLK_MST]); +disable_inner_clk: + clk_disable_unprepare(dev->clks[CLK_DAC_INNER]); + + return ret; +} + +static int dw_i2stx_4ch1_clk_init(struct platform_device *pdev, struct dw_i2s_dev *dev) +{ + int ret = 0; + + dev->clks_audroot = devm_clk_get(&pdev->dev, "audroot"); + if (IS_ERR(dev->clks_audroot)) + return PTR_ERR(dev->clks_audroot); + + dev->clks_inner = devm_clk_get(&pdev->dev, "mclk_inner"); + if (IS_ERR(dev->clks_inner)) + return PTR_ERR(dev->clks_inner); + + dev->clks_bclk_mst = devm_clk_get(&pdev->dev, "bclk_mst"); + if (IS_ERR(dev->clks_bclk_mst)) + return PTR_ERR(dev->clks_bclk_mst); + + dev->clks_lrclk_mst = devm_clk_get(&pdev->dev, "lrck_mst"); + if (IS_ERR(dev->clks_lrclk_mst)) + return PTR_ERR(dev->clks_lrclk_mst); + + dev->clks_mclk = devm_clk_get(&pdev->dev, "mclk"); + if (IS_ERR(dev->clks_mclk)) + return PTR_ERR(dev->clks_mclk); + + dev->clks_bclk = devm_clk_get(&pdev->dev, "4chbclk"); + if (IS_ERR(dev->clks_bclk)) + return PTR_ERR(dev->clks_bclk); + + dev->clks_lrclk = devm_clk_get(&pdev->dev, "4chlrck"); + if (IS_ERR(dev->clks_lrclk)) + return PTR_ERR(dev->clks_lrclk); + + dev->clks_mclk_out = devm_clk_get(&pdev->dev, "mclk_out"); + if (IS_ERR(dev->clks_mclk_out)) + return PTR_ERR(dev->clks_mclk_out); + + dev->clks_apb0 = devm_clk_get(&pdev->dev, "apb0"); + if (IS_ERR(dev->clks_apb0)) + return PTR_ERR(dev->clks_apb0); + + dev->clks_4ch_apb = devm_clk_get(&pdev->dev, "clk_apb"); + if (IS_ERR(dev->clks_4ch_apb)) + return PTR_ERR(dev->clks_4ch_apb); + + ret = clk_prepare_enable(dev->clks_audroot); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_audroot\n", __func__); + goto disable_audioroot_clk; + } + ret = clk_set_rate(dev->clks_audroot, 204800000); + if (ret) { + dev_err(&pdev->dev, "failed to set rate for clks_audroot ret=%d\n", ret); + goto disable_audioroot_clk; + } + + ret = clk_prepare_enable(dev->clks_inner); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_inner\n", __func__); + goto disable_audinner_clk; + } + + ret = clk_set_rate(dev->clks_inner, 4096000); + if (ret) { + dev_err(&pdev->dev, "failed to set rate for clks_inner ret=%d\n", ret); + goto disable_audinner_clk; + } + + ret = clk_prepare_enable(dev->clks_bclk_mst); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_bclk_mst\n", __func__); + goto disable_mst_bclk; + } + + ret = clk_set_rate(dev->clks_bclk_mst, 1024000); + if (ret) { + dev_err(&pdev->dev, "failed to set rate for clks_bclk_mst ret=%d\n", ret); + goto disable_mst_bclk; + } + + ret = clk_prepare_enable(dev->clks_lrclk_mst); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_lrclk_mst\n", __func__); + goto disable_mst_lrclk; + } + + ret = clk_prepare_enable(dev->clks_mclk); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_mclk\n", __func__); + goto disable_mclk; + } + + ret = clk_prepare_enable(dev->clks_bclk); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_bclk\n", __func__); + goto disable_bclk; + } + + ret = clk_prepare_enable(dev->clks_lrclk); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_lrclk\n", __func__); + goto disable_lrclk; + } + + ret = clk_prepare_enable(dev->clks_mclk_out); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_mclk_out\n", __func__); + goto disable_mclk_out; + } + + ret = clk_prepare_enable(dev->clks_apb0); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_apb0\n", __func__); + goto disable_apb0; + } + + ret = clk_prepare_enable(dev->clks_4ch_apb); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable clks_4ch_apb\n", __func__); + goto disable_4ch_apb; + } + + + dev_dbg(&pdev->dev, "dev->clks_inner = %lu \n", clk_get_rate(dev->clks_inner)); + dev_dbg(&pdev->dev, "dev->clks_bclk_mst = %lu \n", clk_get_rate(dev->clks_bclk_mst)); + dev_dbg(&pdev->dev, "dev->clks_lrclk_mst = %lu \n", clk_get_rate(dev->clks_lrclk_mst)); + dev_dbg(&pdev->dev, "dev->clks_mclk = %lu \n", clk_get_rate(dev->clks_mclk)); + dev_dbg(&pdev->dev, "dev->clks_bclk = %lu \n", clk_get_rate(dev->clks_bclk)); + dev_dbg(&pdev->dev, "dev->clks_lrclk = %lu \n", clk_get_rate(dev->clks_lrclk)); + dev_dbg(&pdev->dev, "dev->clks_mclk_out = %lu \n", clk_get_rate(dev->clks_mclk_out)); + dev_dbg(&pdev->dev, "dev->clks_apb0 = %lu \n", clk_get_rate(dev->clks_apb0)); + dev_dbg(&pdev->dev, "dev->clks_4ch_apb = %lu \n", clk_get_rate(dev->clks_4ch_apb)); + + dev->rstc[RST_APB1_BUS] = devm_reset_control_get_exclusive(&pdev->dev, rst_name[RST_APB1_BUS]); + if (IS_ERR(dev->rstc[RST_APB1_BUS])) { + dev_err(&pdev->dev, "%s: failed to get apb_i2stx reset control\n", __func__); + return PTR_ERR(dev->rstc[RST_APB1_BUS]); + } + + dev->rstc[RST_BCLK_1] = devm_reset_control_get_exclusive(&pdev->dev, rst_name[RST_BCLK_1]); + if (IS_ERR(dev->rstc[RST_BCLK_1])) { + dev_err(&pdev->dev, "%s: failed to get i2s bclk1 reset control\n", __func__); + return PTR_ERR(dev->rstc[RST_BCLK_1]); + } + + ret = reset_control_assert(dev->rstc[RST_APB1_BUS]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to reset control assert RST_APB1_BUS\n", __func__); + goto disable_4ch_apb; + } + ret = reset_control_assert(dev->rstc[RST_BCLK_1]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to reset control assert RST_BCLK_1\n", __func__); + goto disable_4ch_apb; + } + + ret = reset_control_deassert(dev->rstc[RST_APB1_BUS]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to reset control deassert RST_APB1_BUS\n", __func__); + goto disable_4ch_apb; + } + + ret = reset_control_deassert(dev->rstc[RST_BCLK_1]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to reset control deassert RST_APB1_BUS\n", __func__); + goto disable_4ch_apb; + } + + return 0; + +disable_4ch_apb: + clk_disable_unprepare(dev->clks_4ch_apb); +disable_apb0: + clk_disable_unprepare(dev->clks_apb0); +disable_mclk_out: + clk_disable_unprepare(dev->clks_mclk_out); +disable_lrclk: + clk_disable_unprepare(dev->clks_lrclk); +disable_bclk: + clk_disable_unprepare(dev->clks_bclk); +disable_mclk: + clk_disable_unprepare(dev->clks_mclk); +disable_mst_lrclk: + clk_disable_unprepare(dev->clks_lrclk_mst); +disable_mst_bclk: + clk_disable_unprepare(dev->clks_bclk_mst); +disable_audinner_clk: + clk_disable_unprepare(dev->clks_inner); +disable_audioroot_clk: + clk_disable_unprepare(dev->clks_audroot); + return ret; } @@ -622,7 +985,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev, comp1 = comp1 & ~BIT(6); if (COMP1_TX_ENABLED(comp1)) { - dev_dbg(dev->dev, " designware: play supported\n"); + dev_err(dev->dev, " designware: play supported\n"); idx = COMP1_TX_WORDSIZE_0(comp1); if (WARN_ON(idx >= ARRAY_SIZE(formats))) return -EINVAL; @@ -636,7 +999,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev, } if (COMP1_RX_ENABLED(comp1)) { - dev_dbg(dev->dev, "designware: record supported\n"); + dev_err(dev->dev, "designware: record supported\n"); idx = COMP2_RX_WORDSIZE_0(comp2); if (WARN_ON(idx >= ARRAY_SIZE(formats))) return -EINVAL; @@ -645,12 +1008,18 @@ static int dw_configure_dai(struct dw_i2s_dev *dev, dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; dw_i2s_dai->capture.channels_max = 1 << (COMP1_RX_CHANNELS(comp1) + 1); - dw_i2s_dai->capture.formats = SNDRV_PCM_FMTBIT_S16_LE; + dw_i2s_dai->capture.formats = formats[idx]; dw_i2s_dai->capture.rates = rates; } - dev_dbg(dev->dev, "designware: i2s master mode supported\n"); - dev->capability |= DW_I2S_MASTER; + if (COMP1_MODE_EN(comp1)) { + dev_err(dev->dev, "designware: i2s master mode supported\n"); + dev->capability |= DW_I2S_MASTER; + } else { + dev_err(dev->dev, "designware: i2s slave mode supported\n"); + dev->capability |= DW_I2S_SLAVE; + } + dev->fifo_th = fifo_depth / 2; return 0; } @@ -719,9 +1088,6 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev, if (COMP1_RX_ENABLED(comp1)) { idx2 = COMP2_RX_WORDSIZE_0(comp2); - /* force change to 1 */ - idx = 1; - idx2 = 1; dev->capability |= DWC_I2S_RECORD; dev->capture_dma_data.dt.addr = res->start + I2S_RXDMA; dev->capture_dma_data.dt.addr_width = bus_widths[idx]; @@ -763,7 +1129,6 @@ static int dw_i2s_probe(struct platform_device *pdev) if (!dw_i2s_dai) return -ENOMEM; - dw_i2s_dai->ops = &dw_i2s_dai_ops; #ifdef CONFIG_SND_DESIGNWARE_I2S_STARFIVE_JH7110 dw_i2s_dai->probe = dw_i2s_dai_probe; @@ -773,22 +1138,13 @@ static int dw_i2s_probe(struct platform_device *pdev) if (IS_ERR(dev->i2s_base)) return PTR_ERR(dev->i2s_base); - dev->dev = &pdev->dev; - - ret = of_parse_phandle_with_fixed_args(dev->dev->of_node, - "starfive,sys-syscon", 2, 0, &args); - if (ret) { - dev_err(dev->dev, "Failed to parse starfive,sys-syscon\n"); - return -EINVAL; - } - - dev->syscon_base = syscon_node_to_regmap(args.np); - of_node_put(args.np); - if (IS_ERR(dev->syscon_base)) - return PTR_ERR(dev->syscon_base); + dev->clk_base = ioremap(CLOCK_BASE, 0x300); + if (IS_ERR(dev->clk_base)) { + printk(KERN_INFO "%s: failed to alloc memory for clk_base\n", __func__); + return PTR_ERR(dev->clk_base); + } - dev->syscon_offset_18 = args.args[0]; - dev->syscon_offset_34 = args.args[1]; + dev->dev = &pdev->dev; irq = platform_get_irq_optional(pdev, 0); if (irq >= 0) { @@ -800,14 +1156,31 @@ static int dw_i2s_probe(struct platform_device *pdev) } } - if (of_device_is_compatible(np, "snps,designware-i2srx")) { - /* config i2s data source: PDM */ - regmap_update_bits(dev->syscon_base, dev->syscon_offset_34, - AUDIO_SDIN_MUX_MASK, I2SRX_DATA_SRC_PDM); + if (of_device_is_compatible(np, "snps,designware-i2srx")) { //record + ret = of_parse_phandle_with_fixed_args(dev->dev->of_node, + "starfive,sys-syscon", 2, 0, &args); + if (ret) { + dev_err(dev->dev, "Failed to parse starfive,sys-syscon\n"); + return -EINVAL; + } + dev->syscon_base = syscon_node_to_regmap(args.np); + of_node_put(args.np); + if (IS_ERR(dev->syscon_base)) + return PTR_ERR(dev->syscon_base); + dev->syscon_offset_18 = args.args[0]; + dev->syscon_offset_34 = args.args[1]; ret = dw_i2srx_clk_init(pdev, dev); if (ret < 0) goto err_clk_disable; + } else if (of_device_is_compatible(np, "snps,designware-i2stx-4ch0")) { //playback + ret = dw_i2stx_4ch0_clk_init(pdev, dev); + if (ret < 0) + goto err_clk_disable; + } else if (of_device_is_compatible(np, "snps,designware-i2stx-4ch1")) { //playback + ret = dw_i2stx_4ch1_clk_init(pdev, dev); + if (ret < 0) + goto err_clk_disable; } dev->i2s_reg_comp1 = I2S_COMP_PARAM_1; @@ -822,7 +1195,7 @@ static int dw_i2s_probe(struct platform_device *pdev) } ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata); } else { - clk_id = "i2srx_bclk"; + clk_id = "bclk_mst"; ret = dw_configure_dai_by_dt(dev, dw_i2s_dai, res); } if (ret < 0) @@ -836,6 +1209,14 @@ static int dw_i2s_probe(struct platform_device *pdev) return -ENODEV; } } + dev->clk = devm_clk_get(&pdev->dev, clk_id); + + if (IS_ERR(dev->clk)) + return PTR_ERR(dev->clk); + + ret = clk_prepare_enable(dev->clk); + if (ret < 0) + return ret; } dev_set_drvdata(&pdev->dev, dev); @@ -864,11 +1245,14 @@ static int dw_i2s_probe(struct platform_device *pdev) } pm_runtime_enable(&pdev->dev); + clk_disable_unprepare(dev->clks_mclk_out); + clk_disable_unprepare(dev->clks_bclk_mst); + clk_disable_unprepare(dev->clks_lrclk_mst); return 0; err_clk_disable: if (dev->capability & DW_I2S_MASTER) - clk_disable_unprepare(dev->clk_i2srx_bclk_mst); + clk_disable_unprepare(dev->clk); return ret; } @@ -877,7 +1261,7 @@ static int dw_i2s_remove(struct platform_device *pdev) struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev); if (dev->capability & DW_I2S_MASTER) - clk_disable_unprepare(dev->clk_i2srx_bclk_mst); + clk_disable_unprepare(dev->clk); pm_runtime_disable(&pdev->dev); return 0; @@ -885,7 +1269,9 @@ static int dw_i2s_remove(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id dw_i2s_of_match[] = { - { .compatible = "snps,designware-i2srx", }, + { .compatible = "snps,designware-i2stx-4ch1", }, + { .compatible = "snps,designware-i2srx", }, + { .compatible = "snps,designware-i2stx-4ch0", }, {}, }; @@ -906,7 +1292,19 @@ static struct platform_driver dw_i2s_driver = { }, }; -module_platform_driver(dw_i2s_driver); +static int __init dwci2s_driver_init(void) +{ + return platform_driver_register(&dw_i2s_driver); +} + +static void dwci2s_driver_exit(void) +{ + platform_driver_unregister(&dw_i2s_driver); +} + +late_initcall(dwci2s_driver_init); +module_exit(dwci2s_driver_exit); + MODULE_AUTHOR("Rajeev Kumar "); MODULE_DESCRIPTION("DESIGNWARE I2S SoC Interface"); diff --git a/sound/soc/dwc/local.h b/sound/soc/dwc/local.h old mode 100644 new mode 100755 index a0b9adc..2836a69 --- a/sound/soc/dwc/local.h +++ b/sound/soc/dwc/local.h @@ -81,11 +81,37 @@ #define MAX_CHANNEL_NUM 8 #define MIN_CHANNEL_NUM 2 -/* SYSCON Registers */ -#define I2SRX_3CH_ADC_MASK 0x2 -#define I2SRX_3CH_ADC_EN BIT(1) -#define AUDIO_SDIN_MUX_MASK 0x3FC00 -#define I2SRX_DATA_SRC_PDM (0x91 << 10) +enum { + CLK_DAC_INNER = 0, + CLK_DAC_BCLK_MST, + CLK_DAC_LRCLK_MST, + CLK_MCLK, + CLK_DAC_BCLK0, + CLK_DAC_LRCLK0, + CLK_DAC_BCLK_MST_1, + CLK_DAC_LRCLK_MST_1, + CLK_DAC_BCLK_1, + CLK_DAC_LRCLK_1, + CLK_ADC_APB0, + CLK_ADC_APB, + CLK_ADC_AUDROOT, + CLK_ADC_MCLK_INNER, + CLK_ADC_BCLK, + CLK_ADC_LRCLK, + CLK_ADC_RX_BCLK, + CLK_ADC_RX_LRCK, + CLK_AUDIO_NUM, +}; + +enum { + RST_APB0_BUS = 0, + RST_BCLK_0, + RST_APB1_BUS, + RST_BCLK_1, + RST_APB_RX, + RST_BCLK_RX, + RST_AUDIO_NUM, +}; union dw_i2s_snd_dma_data { struct i2s_dma_data pd; @@ -94,7 +120,9 @@ union dw_i2s_snd_dma_data { struct dw_i2s_dev { void __iomem *i2s_base; + void __iomem *clk_base; struct regmap *syscon_base; + struct clk *clk; int active; unsigned int capability; unsigned int quirks; @@ -107,14 +135,18 @@ struct dw_i2s_dev { u32 syscon_offset_18; u32 syscon_offset_34; - struct clk *clk_apb0; - struct clk *clk_i2srx_apb; - struct clk *clk_i2srx_bclk_mst; - struct clk *clk_i2srx_lrck_mst; - struct clk *clk_i2srx_bclk; - struct clk *clk_i2srx_lrck; - struct reset_control *rst_i2srx_apb; - struct reset_control *rst_i2srx_bclk; + struct clk *clks[CLK_AUDIO_NUM]; + struct clk *clks_audroot; + struct clk *clks_inner; + struct clk *clks_bclk_mst; + struct clk *clks_lrclk_mst; + struct clk *clks_mclk; + struct clk *clks_bclk; + struct clk *clks_lrclk; + struct clk *clks_mclk_out; + struct clk *clks_apb0; + struct clk *clks_4ch_apb; + struct reset_control *rstc[RST_AUDIO_NUM]; /* data related to DMA transfers b/w i2s and DMAC */ union dw_i2s_snd_dma_data play_dma_data; -- 2.7.4