From 5a2011bc59d0d9a727b845b545362a485a7f8a7d Mon Sep 17 00:00:00 2001 From: Peipeng Zhao Date: Thu, 25 Jan 2018 13:49:44 +0800 Subject: [PATCH] audio: add audio external loopback feature for axg chip PD#159617: audio: add audio external loopback feature for axg chip For S400 & S420 board, please modify dts to enable external loopback please read following file: Documentation/devicetree/bindings/amlogic/axg-sound-loopback.txt Change-Id: Ie96d10eb8e6ae81aaff0b3e6965aa4e22f07f0b8 Signed-off-by: Peipeng Zhao --- .../bindings/amlogic/axg-sound-loopback.txt | 115 +++++++++++++ MAINTAINERS | 6 +- arch/arm64/boot/dts/amlogic/axg_s400.dts | 20 +++ arch/arm64/boot/dts/amlogic/axg_s400_v03.dts | 22 +++ arch/arm64/boot/dts/amlogic/axg_s400emmc.dts | 19 +++ .../boot/dts/amlogic/axg_s400emmc_v03.dts | 19 +++ arch/arm64/boot/dts/amlogic/axg_s420.dts | 19 +++ arch/arm64/boot/dts/amlogic/axg_s420_128m.dts | 18 ++ arch/arm64/boot/dts/amlogic/axg_s420_v03.dts | 21 +++ sound/soc/amlogic/auge/audio_utils.c | 158 ++++++++++++++++-- sound/soc/amlogic/auge/audio_utils.h | 10 +- sound/soc/amlogic/auge/card.c | 5 +- sound/soc/amlogic/auge/loopback_hw.c | 57 ++++++- sound/soc/amlogic/auge/loopback_hw.h | 2 +- sound/soc/amlogic/auge/pdm_hw.c | 8 +- 15 files changed, 475 insertions(+), 24 deletions(-) create mode 100644 Documentation/devicetree/bindings/amlogic/axg-sound-loopback.txt diff --git a/Documentation/devicetree/bindings/amlogic/axg-sound-loopback.txt b/Documentation/devicetree/bindings/amlogic/axg-sound-loopback.txt new file mode 100644 index 000000000000..a54910afddc4 --- /dev/null +++ b/Documentation/devicetree/bindings/amlogic/axg-sound-loopback.txt @@ -0,0 +1,115 @@ +Enable external loopback for S420 & S400 board + +diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts +index 8038672..064de0f 100644 +--- a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts ++++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts +@@ -562,12 +562,12 @@ + *enable external loopback + *and tlv320adc3101 as loopback + */ +- /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ ++ sound-dai = <&pdm_codec &tlv320adc3101_32>; + /* + * enable internal loopback + * or disable loopback + */ +- sound-dai = <&pdm_codec>; ++ /*sound-dai = <&pdm_codec>;*/ + }; + }; + +@@ -1163,8 +1163,8 @@ + * external loopback clock config + * enable clk while pdm record data + */ +- /*clocks = <&clkc CLKID_MPLL1>;*/ +- /*clock-names = "datalb_mpll";*/ ++ clocks = <&clkc CLKID_MPLL1>; ++ clock-names = "datalb_mpll"; + + /* + * 0: out rate = in data rate; +@@ -1182,7 +1182,7 @@ + */ + datain_src = <4>; + datain_chnum = <8>; +- datain_chmask = <0x7f>; ++ datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA +@@ -1194,11 +1194,11 @@ + */ + + /*if tdmin_lb >= 3, use external loopback*/ +- datalb_src = <2>; ++ datalb_src = <4>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ +- /*datalb-lane-mask-in = <0 0 0 1>;*/ +- datalb_chmask = <0x1>; ++ datalb-lane-mask-in = <0 0 0 1>; ++ datalb_chmask = <0x3>; + + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts +index aaf05de..bb5b173 100644 +--- a/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts ++++ b/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts +@@ -427,12 +427,12 @@ + *enable external loopback + *and tlv320adc3101 as loopback + */ +- /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ ++ sound-dai = <&pdm_codec &tlv320adc3101_32>; + /* + * enable internal loopback + * or disable loopback + */ +- sound-dai = <&pdm_codec>; ++ /*sound-dai = <&pdm_codec>;*/ + }; + }; + +@@ -983,12 +983,13 @@ + + aml_loopback: loopback { + compatible = "amlogic, snd-loopback"; ++ + /* + * external loopback clk config + * enable clk while pdm record data + */ +- /*clocks = <&clkc CLKID_MPLL1>;*/ +- /*clock-names = "datalb_mpll";*/ ++ clocks = <&clkc CLKID_MPLL1>; ++ clock-names = "datalb_mpll"; + + /* + * 0: out rate = in data rate; +@@ -1005,7 +1006,7 @@ + */ + datain_src = <4>; + datain_chnum = <8>; +- datain_chmask = <0x7f>; ++ datain_chmask = <0x3f>; + + /* tdmin_lb src + * 0: tdmoutA +@@ -1017,11 +1018,11 @@ + */ + + /*if tdmin_lb >= 3, use external loopback*/ +- datalb_src = <2>; ++ datalb_src = <4>; + datalb_chnum = <2>; + /*config which data pin as loopback*/ +- /*datalb-lane-mask-in = <0 1>;*/ +- datalb_chmask = <0x1>; ++ datalb-lane-mask-in = <0 1>; ++ datalb_chmask = <0x3>; + + status = "okay"; + }; diff --git a/MAINTAINERS b/MAINTAINERS index ae410617cd65..47738512ceff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14261,4 +14261,8 @@ F: drivers/amlogic/input/touchscreen/goodix_gt9xx/* AMLOGIC ADD LCD_EXTERN P070ACB DRIVER M: Weiming Liu -F: drivers/amlogic/media/vout/lcd/lcd_extern/mipi_P070ACB.c \ No newline at end of file +F: drivers/amlogic/media/vout/lcd/lcd_extern/mipi_P070ACB.c + +AMLOGIC ADD SOUND EXTERNAL LOOPBACK FEATURE +M: Peipeng Zhao +F: Documentation/devicetree/bindings/amlogic/axg-sound-loopback.txt diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index 069e137f78f9..07a435cc3a4f 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -556,6 +556,15 @@ sound-dai = <&aml_pdm>; }; codec { + /* + * enable external loopback + * and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ sound-dai = <&pdm_codec>; }; }; @@ -1145,6 +1154,14 @@ aml_loopback: loopback { compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + /* * 0: out rate = in data rate; * 1: out rate = loopback data rate; @@ -1170,8 +1187,11 @@ * 4: PAD_tdminB * 5: PAD_tdminC */ + /*if tdmin_lb >= 3, use external loopback*/ datalb_src = <2>; datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ datalb_chmask = <0x1>; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts index 46ee8369b4e8..803867236250 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400_v03.dts @@ -558,6 +558,15 @@ sound-dai = <&aml_pdm>; }; codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ sound-dai = <&pdm_codec>; }; }; @@ -1149,10 +1158,19 @@ aml_loopback: loopback { compatible = "amlogic, snd-loopback"; + + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + /* * 0: out rate = in data rate; * 1: out rate = loopback data rate; */ + lb_mode = <0>; /* datain src @@ -1174,8 +1192,12 @@ * 4: PAD_tdminB * 5: PAD_tdminC */ + + /*if tdmin_lb >= 3, use external loopback*/ datalb_src = <2>; datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ datalb_chmask = <0x1>; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts b/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts index 0904993cb787..96ddaf74fda1 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400emmc.dts @@ -552,6 +552,15 @@ sound-dai = <&aml_pdm>; }; codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ sound-dai = <&pdm_codec>; }; }; @@ -1020,6 +1029,13 @@ aml_loopback: loopback { compatible = "amlogic, snd-loopback"; + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + /* * 0: out rate = in data rate; * 1: out rate = loopback data rate; @@ -1045,8 +1061,11 @@ * 4: PAD_tdminB * 5: PAD_tdminC */ + /*if tdmin_lb >= 3, use external loopback*/ datalb_src = <2>; datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ datalb_chmask = <0x1>; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts index f5d80360f29e..c1cae969e606 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400emmc_v03.dts @@ -552,6 +552,15 @@ sound-dai = <&aml_pdm>; }; codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ sound-dai = <&pdm_codec>; }; }; @@ -1022,6 +1031,13 @@ aml_loopback: loopback { compatible = "amlogic, snd-loopback"; + /* + * external loopback clock config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + /* * 0: out rate = in data rate; * 1: out rate = loopback data rate; @@ -1047,8 +1063,11 @@ * 4: PAD_tdminB * 5: PAD_tdminC */ + /*if tdmin_lb >= 3, use external loopback*/ datalb_src = <2>; datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 0 0 1>;*/ datalb_chmask = <0x1>; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s420.dts b/arch/arm64/boot/dts/amlogic/axg_s420.dts index 80805f6ca8f1..bb9f60451c36 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420.dts @@ -420,6 +420,15 @@ sound-dai = <&aml_pdm>; }; codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ sound-dai = <&pdm_codec>; }; }; @@ -969,6 +978,13 @@ aml_loopback: loopback { compatible = "amlogic, snd-loopback"; + /* + * external loopback clk config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + /* * 0: out rate = in data rate; * 1: out rate = loopback data rate; @@ -994,8 +1010,11 @@ * 4: PAD_tdminB * 5: PAD_tdminC */ + /*if tdmin_lb >= 3, use external loopback*/ datalb_src = <1>; datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 1>;*/ datalb_chmask = <0x1>; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_128m.dts b/arch/arm64/boot/dts/amlogic/axg_s420_128m.dts index b570b44b5ef9..f5ee084cbc73 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420_128m.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420_128m.dts @@ -418,6 +418,15 @@ sound-dai = <&aml_pdm>; }; codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ sound-dai = <&pdm_codec>; }; }; @@ -843,6 +852,12 @@ aml_loopback: loopback { compatible = "amlogic, snd-loopback"; + /* + * external loopback clk config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ /* * 0: out rate = in data rate; * 1: out rate = loopback data rate; @@ -868,8 +883,11 @@ * 4: PAD_tdminB * 5: PAD_tdminC */ + /*if tdmin_lb >= 3, use external loopback*/ datalb_src = <2>; datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 1>;*/ datalb_chmask = <0x1>; status = "okay"; diff --git a/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts b/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts index 270b8f0fae35..aaf05de99592 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420_v03.dts @@ -387,6 +387,7 @@ dai-tdm-slot-rx-mask = <1 1>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; + system-clock-frequency = <12288000>; }; codec { sound-dai = <&tlv320adc3101_32>; @@ -422,6 +423,15 @@ sound-dai = <&aml_pdm>; }; codec { + /* + *enable external loopback + *and tlv320adc3101 as loopback + */ + /*sound-dai = <&pdm_codec &tlv320adc3101_32>;*/ + /* + * enable internal loopback + * or disable loopback + */ sound-dai = <&pdm_codec>; }; }; @@ -973,6 +983,13 @@ aml_loopback: loopback { compatible = "amlogic, snd-loopback"; + /* + * external loopback clk config + * enable clk while pdm record data + */ + /*clocks = <&clkc CLKID_MPLL1>;*/ + /*clock-names = "datalb_mpll";*/ + /* * 0: out rate = in data rate; * 1: out rate = loopback data rate; @@ -998,8 +1015,12 @@ * 4: PAD_tdminB * 5: PAD_tdminC */ + + /*if tdmin_lb >= 3, use external loopback*/ datalb_src = <2>; datalb_chnum = <2>; + /*config which data pin as loopback*/ + /*datalb-lane-mask-in = <0 1>;*/ datalb_chmask = <0x1>; status = "okay"; diff --git a/sound/soc/amlogic/auge/audio_utils.c b/sound/soc/amlogic/auge/audio_utils.c index 5de8b4211025..d747d24c426b 100644 --- a/sound/soc/amlogic/auge/audio_utils.c +++ b/sound/soc/amlogic/auge/audio_utils.c @@ -24,6 +24,8 @@ #include "tdm_hw.h" #include "ddr_mngr.h" +#include + struct snd_elem_info { struct soc_enum *ee; int reg; @@ -892,7 +894,26 @@ int snd_card_add_kcontrols(struct snd_soc_card *card) int loopback_parse_of(struct device_node *node, struct loopback_cfg *lb_cfg) { - int ret; + struct platform_device *pdev; + const __be32 *of_slot_mask; + unsigned int lane_mask = 0; + int i, ret, set_num = 0; + u32 val; + + pdev = of_find_device_by_node(node); + if (!pdev) { + dev_err(&pdev->dev, "failed to find platform device\n"); + ret = -EINVAL; + goto fail; + } + + /*mpll used for tdmin*/ + lb_cfg->tdmin_mpll = devm_clk_get(&pdev->dev, "datalb_mpll"); + if (IS_ERR(lb_cfg->tdmin_mpll)) { + dev_err(&pdev->dev, + "Can't retrieve tdmin_mpll clock\n"); + lb_cfg->tdmin_mpll = NULL; + } ret = of_property_read_u32(node, "lb_mode", &lb_cfg->lb_mode); @@ -945,7 +966,25 @@ int loopback_parse_of(struct device_node *node, ret = -EINVAL; goto fail; } + of_slot_mask = of_get_property(node, "datalb-lane-mask-in", &val); + if (!of_slot_mask) { + pr_err("if use extern loopback, pls set datalb-lane-mask-in\n"); + } else { + val /= sizeof(u32); + for (i = 0; i < val; i++) + if (be32_to_cpup(&of_slot_mask[i])) + lane_mask |= (1 << i); + for (i = 0; i < 4; i++) { + if ((1 << i) & lane_mask) { + /*each lane only L/R masked*/ + lb_cfg->datalb_chswap |= + (i * 2) << (set_num++ * 4); + lb_cfg->datalb_chswap |= + (i * 2 + 1) << (set_num++ * 4); + } + } + } loopback_datain = lb_cfg->datain_src; loopback_tdminlb = lb_cfg->datalb_src; @@ -955,15 +994,77 @@ int loopback_parse_of(struct device_node *node, lb_cfg->datain_src, lb_cfg->datain_chnum, lb_cfg->datain_chmask); - pr_info("\tdatalb_src:%d, datalb_chnum:%d, datalb_chumask:%x\n", + pr_info("\tdatalb_src:%d, datalb_chnum:%d\n", lb_cfg->datalb_src, - lb_cfg->datalb_chnum, + lb_cfg->datalb_chnum); + pr_info("\tdatalb_chswap:0x%x,datalb_chumask:%x\n", + lb_cfg->datalb_chswap, lb_cfg->datalb_chmask); fail: return ret; } +int loopback_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct loopback_cfg *lb_cfg, + unsigned int mclk) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int bclk_sel, fsclk_sel; + int bit_depth; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return 0; + bit_depth = snd_pcm_format_width(runtime->format); + + if (lb_cfg->datalb_src >= 3) { + /*tdm in*/ + /*for i2s mode*/ + unsigned int sclk_div = 4 - 1; + unsigned int ratio = params_channels(params) * bit_depth - 1; + unsigned int fsclk_hi = ratio / 2; + unsigned int clk_id = lb_cfg->datalb_src - 3; + unsigned int mul = 2; + unsigned int mpll_freq, offset, reg; + + pr_info("%s, channels:%d, format:%d, ratio:%d\n", + __func__, + params_channels(params), + bit_depth, + ratio); + + bclk_sel = clk_id; + fsclk_sel = clk_id; + + /*mclk*/ + mpll_freq = mclk * mul; + clk_set_rate(lb_cfg->tdmin_mpll, mpll_freq); + pr_info("mpll freq:%d, %lu\n", mpll_freq, + clk_get_rate(lb_cfg->tdmin_mpll)); + offset = EE_AUDIO_MCLK_B_CTRL - EE_AUDIO_MCLK_A_CTRL; + reg = EE_AUDIO_MCLK_A_CTRL + offset * clk_id; + audiobus_write(reg, + 1 << 31 | /*clk enable*/ + clk_id << 24 | /*clk src*/ + (mul - 1)); /*clk_div mclk*/ + + /*sclk, lrclk*/ + offset = EE_AUDIO_MST_B_SCLK_CTRL0 - EE_AUDIO_MST_A_SCLK_CTRL0; + reg = EE_AUDIO_MST_A_SCLK_CTRL0 + offset * clk_id; + audiobus_update_bits(reg, + 0x3 << 30 | 0x3ff << 20 | 0x3ff<<10 | 0x3ff, + 0x3 << 30 | sclk_div << 20 | fsclk_hi << 10 + | ratio); + + audiobus_update_bits( + EE_AUDIO_CLK_TDMIN_LB_CTRL, + 0x3 << 30 | 1 << 29 | 0xf << 24 | 0xf << 20, + 0x3 << 30 | 1 << 29 | bclk_sel << 24 | fsclk_sel << 20); + } + return 0; +} + int loopback_prepare( struct snd_pcm_substream *substream, struct loopback_cfg *lb_cfg) @@ -1052,7 +1153,7 @@ int loopback_prepare( datain_config(&datain); datalb_config(&datalb); - datalb_ctrl(lb_cfg->datalb_src); + datalb_ctrl(lb_cfg); lb_mode(lb_cfg->lb_mode); return 0; @@ -1081,6 +1182,7 @@ void frddr_enable(int is_enable, int frddr_index) } static void loopback_modules_disable( + struct loopback_cfg *lb_cfg, int tdm_index, int frddr_index, int toddr_index) { @@ -1088,9 +1190,24 @@ static void loopback_modules_disable( tdmin_lb_fifo_enable(0); tdmin_lb_enable(tdm_index, 0); - /* pdmin */ - pdm_enable(0); - + /* datain src */ + switch (lb_cfg->datain_src) { + case 0: + case 1: + case 2: + /*tdm in*/ + break; + case 3: + /*spdif in*/ + break; + case 4: + /*pdm in*/ + pdm_enable(0); + break; + default: + pr_err("unsupport datain source!!\n"); + return; + } /* loopback */ lb_enable(0); @@ -1112,6 +1229,7 @@ static void loopback_modules_disable( } static void loopback_modules_enable( + struct loopback_cfg *lb_cfg, int tdm_index, int frddr_index, int toddr_index) { @@ -1132,6 +1250,9 @@ static void loopback_modules_enable( else if (frddr_index >= 0) frddr_enable(1, frddr_index); + tdm_fifo_enable(tdm_index, 1); + tdm_enable(tdm_index, 1); + frddr_enable(1, frddr_index); /* toddr */ if (toddr_index >= 0) toddr_enable(1, toddr_index); @@ -1139,9 +1260,24 @@ static void loopback_modules_enable( /* loopback */ lb_enable(1); - /* pdmin */ - pdm_enable(1); - + /* datain src */ + switch (lb_cfg->datain_src) { + case 0: + case 1: + case 2: + /*tdm in*/ + break; + case 3: + /*spdif in*/ + break; + case 4: + /*pdm in*/ + pdm_enable(1); + break; + default: + pr_err("unsupport datain source!!\n"); + return; + } /*tdminLB*/ tdmin_lb_fifo_enable(1); tdmin_lb_enable(tdm_index, 1); @@ -1182,11 +1318,13 @@ int loopback_trigger( /*if pdm overrun, re-set up the sequence*/ if (lb_cfg->frddr_index >= 0) loopback_modules_disable( + lb_cfg, lb_cfg->datalb_src, lb_cfg->frddr_index, lb_cfg->toddr_index); loopback_modules_enable( + lb_cfg, lb_cfg->datalb_src, lb_cfg->frddr_index, lb_cfg->toddr_index); diff --git a/sound/soc/amlogic/auge/audio_utils.h b/sound/soc/amlogic/auge/audio_utils.h index 530d07f17733..874e3da7c9db 100644 --- a/sound/soc/amlogic/auge/audio_utils.h +++ b/sound/soc/amlogic/auge/audio_utils.h @@ -18,6 +18,7 @@ #ifndef __AML_AUDIO_UTILS_H__ #define __AML_AUDIO_UTILS_H__ +#include #include #include #include @@ -109,6 +110,7 @@ struct audio_data { /**/ struct loopback_cfg { + struct clk *tdmin_mpll; /* lb_mode * 0: out rate = in data rate; * 1: out rate = loopback data rate; @@ -122,6 +124,7 @@ struct loopback_cfg { enum tdmin_lb_src datalb_src; unsigned int datalb_chnum; + unsigned int datalb_chswap; unsigned int datalb_chmask; int frddr_index; }; @@ -135,7 +138,12 @@ extern int loopback_check_enable(int src); extern int snd_card_add_kcontrols(struct snd_soc_card *card); extern int loopback_parse_of(struct device_node *node, - struct loopback_cfg *lb_cfg); + struct loopback_cfg *lb_cfg); + +extern int loopback_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct loopback_cfg *lb_cfg, + unsigned int mclk); extern int loopback_prepare( struct snd_pcm_substream *substream, diff --git a/sound/soc/amlogic/auge/card.c b/sound/soc/amlogic/auge/card.c index 4427cb064cc7..8f0b60d6084e 100644 --- a/sound/soc/amlogic/auge/card.c +++ b/sound/soc/amlogic/auge/card.c @@ -412,7 +412,7 @@ static int aml_card_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai_link *dai_link = aml_priv_to_link(priv, rtd->num); struct aml_dai_props *dai_props = aml_priv_to_props(priv, rtd->num); - unsigned int mclk, mclk_fs = 0; + unsigned int mclk = 0, mclk_fs = 0; int i = 0, ret = 0; if (priv->mclk_fs) @@ -442,6 +442,9 @@ static int aml_card_hw_params(struct snd_pcm_substream *substream, if (ret && ret != -ENOTSUPP) goto err; } + + if (loopback_is_enable() && mclk) + loopback_hw_params(substream, params, &priv->lb_cfg, mclk); return 0; err: return ret; diff --git a/sound/soc/amlogic/auge/loopback_hw.c b/sound/soc/amlogic/auge/loopback_hw.c index a609da0e61e0..63b3924e416e 100644 --- a/sound/soc/amlogic/auge/loopback_hw.c +++ b/sound/soc/amlogic/auge/loopback_hw.c @@ -50,9 +50,9 @@ void datalb_config(struct data_lb *datalb) ); } -void datalb_ctrl(int lb_src) +void datalb_ctrl(struct loopback_cfg *lb_cfg) { - int id = lb_src; + int id = lb_cfg->datalb_src; int offset = 0; int reg, reg_base; @@ -64,7 +64,7 @@ void datalb_ctrl(int lb_src) 1 << 30 | 1 << 29 | 1 << 28 | - lb_src << 20 | + lb_cfg->datalb_src << 20 | 3 << 16| 31 << 0 ); @@ -74,8 +74,47 @@ void datalb_ctrl(int lb_src) reg_base = EE_AUDIO_TDMOUT_A_SWAP; offset = EE_AUDIO_TDMOUT_B_SWAP - EE_AUDIO_TDMOUT_A_SWAP; } else if (id < 6) { - /* pad from tdmin_a, tdmin_b, tdmin_c */ - id -= 3; /*id offset from tdmin_a */ + /*lb_cfg->datalb_src for pad tdm in, + *pad from tdmin_a, tdmin_b, tdmin_c + */ + /* id offset from tdmin_a */ + id -= 3; + + reg_base = EE_AUDIO_TDMIN_A_CTRL; + offset = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; + reg = reg_base + offset * id; + audiobus_update_bits(reg, 3<<28, 0); + audiobus_update_bits(reg, 1<<29, 1<<29); + audiobus_update_bits(reg, 1<<28, 1<<28); + + /* just assume lb from tdm in is i2s mode */ + audiobus_update_bits( + reg, + 0xf << 28 | 0xf << 20 | 0x7 << 16 | 0x1f << 0, + 1 << 31 | + /* 0:tdm mode; 1: i2s mode */ + 1 << 30 | + 1 << 29 | + 1 << 28 | + id << 20 | + 3 << 16| + 31 << 0 + ); + + pr_info("reg:0x%x, EE_AUDIO_TDMIN_A_CTRL:0x%x\n", + reg, + audiobus_read(EE_AUDIO_TDMIN_A_CTRL)); + /* swap */ + reg += 1; + audiobus_write( + reg, + lb_cfg->datalb_chswap); + + /* mask 0 */ + reg += 1; + audiobus_write( + reg, + lb_cfg->datalb_chmask); reg_base = EE_AUDIO_TDMIN_A_SWAP; offset = EE_AUDIO_TDMIN_B_SWAP - EE_AUDIO_TDMIN_A_SWAP; } else { @@ -95,19 +134,19 @@ void datalb_ctrl(int lb_src) EE_AUDIO_TDMIN_LB_MASK0, audiobus_read(reg)); - /* mask 0 */ + /* mask 1 */ reg += 1; audiobus_write( EE_AUDIO_TDMIN_LB_MASK1, audiobus_read(reg)); - /* mask 0 */ + /* mask 2 */ reg += 1; audiobus_write( EE_AUDIO_TDMIN_LB_MASK2, audiobus_read(reg)); - /* mask 0 */ + /* mask 3 */ reg += 1; audiobus_write( EE_AUDIO_TDMIN_LB_MASK3, @@ -116,6 +155,8 @@ void datalb_ctrl(int lb_src) void lb_mode(int mode) { +// TODO: + return; audiobus_update_bits( EE_AUDIO_LB_CTRL0, 0x1 << 30, diff --git a/sound/soc/amlogic/auge/loopback_hw.h b/sound/soc/amlogic/auge/loopback_hw.h index f58dee3e3d4e..13115d846f2d 100644 --- a/sound/soc/amlogic/auge/loopback_hw.h +++ b/sound/soc/amlogic/auge/loopback_hw.h @@ -57,7 +57,7 @@ extern void datain_config(struct data_in *datain); extern void datalb_config(struct data_lb *datalb); -extern void datalb_ctrl(int lb_src); +extern void datalb_ctrl(struct loopback_cfg *lb_cfg); extern int lb_is_enable(void); diff --git a/sound/soc/amlogic/auge/pdm_hw.c b/sound/soc/amlogic/auge/pdm_hw.c index dd5f637cc0e5..a5fa0ce3960b 100644 --- a/sound/soc/amlogic/auge/pdm_hw.c +++ b/sound/soc/amlogic/auge/pdm_hw.c @@ -28,12 +28,16 @@ void pdm_enable(int is_enable) { - if (is_enable) + if (is_enable) { + aml_pdm_update_bits( + PDM_CTRL, + 0xffff, + 0xffff); aml_pdm_update_bits( PDM_CTRL, 0x1 << 31, is_enable << 31); - else { + } else { aml_pdm_update_bits( PDM_CTRL, 0x1 << 31 | 0x1 << 16,