From bcba9ce1ac335b8b521683b599cfba0d1d6e423c Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Thu, 21 Mar 2019 20:20:21 +0800 Subject: [PATCH] audio: add I2S samesrc channel mapping to spdif [1/1] PD#SWPL-6147 Problem: I2S has 8 channels but spdif only 2. Need map every single i2s lane to spdif sharebuffer. Solution: Add the DTS setting MASKS as former does. Verify: Local tested. Change-Id: If212fc1b9c937a42778682948773874951b8a55a Signed-off-by: Shuai Li --- arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 6 ++ arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts | 6 ++ arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 6 ++ arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts | 6 ++ arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts | 6 ++ sound/soc/amlogic/auge/sharebuffer.c | 11 ++-- sound/soc/amlogic/auge/sharebuffer.h | 2 +- sound/soc/amlogic/auge/spdif_hw.c | 27 ++++++--- sound/soc/amlogic/auge/spdif_hw.h | 2 +- sound/soc/amlogic/auge/tdm.c | 74 ++++++++++++++++++++++--- 10 files changed, 125 insertions(+), 21 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 028d8a8..55595d6 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -1247,6 +1247,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index bec1a97..4a62607 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1288,6 +1288,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index a5913c3..a044246c 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1349,6 +1349,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts index 8d99594b..a2d0a40c 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -1286,6 +1286,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { diff --git a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts index 7006bcb8..465e88f 100644 --- a/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -1343,6 +1343,12 @@ acodec_adc = <1>; status = "okay"; + + /* !!!For --TV platform-- ONLY */ + Channel_Mask { + /*i2s has 4 pins, 8channel, mux output*/ + Spdif_samesource_Channel_Mask = "i2s_2/3"; + }; }; tdmb:tdm@1 { diff --git a/sound/soc/amlogic/auge/sharebuffer.c b/sound/soc/amlogic/auge/sharebuffer.c index 855d7a6..1a740c4 100644 --- a/sound/soc/amlogic/auge/sharebuffer.c +++ b/sound/soc/amlogic/auge/sharebuffer.c @@ -24,7 +24,7 @@ #include "spdif_hw.h" static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream, - struct frddr *fr, int spdif_id) + struct frddr *fr, int spdif_id, int lane_i2s) { struct snd_pcm_runtime *runtime = substream->runtime; int bit_depth; @@ -36,7 +36,8 @@ static int sharebuffer_spdifout_prepare(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - true); + true, + lane_i2s); /* spdif to hdmitx */ spdifout_to_hdmitx_ctrl(spdif_id); @@ -63,7 +64,7 @@ static int sharebuffer_spdifout_free(struct snd_pcm_substream *substream, aml_frddr_get_fifo_id(fr), bit_depth, runtime->channels, - false); + false, 0); return 0; } @@ -82,7 +83,7 @@ void sharebuffer_enable(int sel, bool enable, bool reenable) } int sharebuffer_prepare(struct snd_pcm_substream *substream, - void *pfrddr, int samesource_sel) + void *pfrddr, int samesource_sel, int lane_i2s) { struct frddr *fr = (struct frddr *)pfrddr; @@ -95,7 +96,7 @@ int sharebuffer_prepare(struct snd_pcm_substream *substream, } else if (samesource_sel < 5) { /* same source with spdif a/b */ sharebuffer_spdifout_prepare(substream, - fr, samesource_sel - 3); + fr, samesource_sel - 3, lane_i2s); } /* frddr, share buffer, src_sel1 */ diff --git a/sound/soc/amlogic/auge/sharebuffer.h b/sound/soc/amlogic/auge/sharebuffer.h index e32a9f4..c8e39c5 100644 --- a/sound/soc/amlogic/auge/sharebuffer.h +++ b/sound/soc/amlogic/auge/sharebuffer.h @@ -18,7 +18,7 @@ #define __AML_AUDIO_SHAREBUFFER_H__ extern int sharebuffer_prepare(struct snd_pcm_substream *substream, - void *pfrddr, int samesource_sel); + void *pfrddr, int samesource_sel, int lane_i2s); extern int sharebuffer_free(struct snd_pcm_substream *substream, void *pfrddr, int samesource_sel); extern int sharebuffer_trigger(int cmd, int samesource_sel, bool reenable); diff --git a/sound/soc/amlogic/auge/spdif_hw.c b/sound/soc/amlogic/auge/spdif_hw.c index 417c86c..971d29b 100644 --- a/sound/soc/amlogic/auge/spdif_hw.c +++ b/sound/soc/amlogic/auge/spdif_hw.c @@ -420,19 +420,31 @@ static void spdifout_clk_ctrl(int spdif_id, bool is_enable) } #endif static void spdifout_fifo_ctrl(int spdif_id, - int fifo_id, int bitwidth, int channels) + int fifo_id, int bitwidth, int channels, int lane_i2s) { unsigned int frddr_type = spdifout_get_frddr_type(bitwidth); unsigned int offset, reg, i, chmask = 0; + unsigned int swap_masks = 0; + + /* spdif always masks two channel */ + if (lane_i2s * 2 >= channels) { + pr_err("invalid lane(%d) and channels(%d)\n", + lane_i2s, channels); + return; + } for (i = 0; i < channels; i++) chmask |= (1 << i); - pr_debug("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits\n", + swap_masks = (2 * lane_i2s) | + (2 * lane_i2s + 1) << 4; + pr_debug("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits, chmask %#x, swap %#x\n", (spdif_id == 0) ? "a":"b", fifo_id, frddr_type, - bitwidth); + bitwidth, + chmask, + swap_masks); /* mask lane 0 L/R channels */ offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0; @@ -449,7 +461,7 @@ static void spdifout_fifo_ctrl(int spdif_id, offset = EE_AUDIO_SPDIFOUT_B_SWAP - EE_AUDIO_SPDIFOUT_SWAP; reg = EE_AUDIO_SPDIFOUT_SWAP + offset * spdif_id; - audiobus_write(reg, 1<<4); + audiobus_write(reg, swap_masks); } static bool spdifout_is_enable(int spdif_id) @@ -493,7 +505,7 @@ void spdifout_enable(int spdif_id, bool is_enable, bool reenable) } void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable) + int bitwidth, int channels, bool is_enable, int lane_i2s) { int spdif_id; @@ -503,7 +515,8 @@ void spdifout_samesource_set(int spdif_index, int fifo_id, spdif_id = 0; if (is_enable) - spdifout_fifo_ctrl(spdif_id, fifo_id, bitwidth, channels); + spdifout_fifo_ctrl(spdif_id, + fifo_id, bitwidth, channels, lane_i2s); } int spdifin_get_sample_rate(void) @@ -655,7 +668,7 @@ void spdifout_play_with_zerodata(unsigned int spdif_id, bool reenable) /* spdif ctrl */ spdifout_fifo_ctrl(spdif_id, - frddr_index, bitwidth, runtime.channels); + frddr_index, bitwidth, runtime.channels, 0); /* channel status info */ spdif_get_channel_status_info(&chsts, sample_rate); diff --git a/sound/soc/amlogic/auge/spdif_hw.h b/sound/soc/amlogic/auge/spdif_hw.h index 689dc7e7..e15efa3 100644 --- a/sound/soc/amlogic/auge/spdif_hw.h +++ b/sound/soc/amlogic/auge/spdif_hw.h @@ -78,7 +78,7 @@ extern void aml_spdifout_get_aed_info(int spdifout_id, extern void spdifout_to_hdmitx_ctrl(int spdif_index); extern void spdifout_samesource_set(int spdif_index, int fifo_id, - int bitwidth, int channels, bool is_enable); + int bitwidth, int channels, bool is_enable, int lane_i2s); extern void spdifout_enable(int spdif_id, bool is_enable, bool reenable); extern int spdifin_get_sample_rate(void); diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 0d0c150..4ed034b 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -118,12 +118,16 @@ struct aml_tdm { struct tdm_chipinfo *chipinfo; /* share buffer with module */ int samesource_sel; + /* share buffer lane setting from DTS */ + int lane_ss; /* virtual link for i2s to hdmitx */ int i2s2hdmitx; int acodec_adc; uint last_mpll_freq; uint last_mclk_freq; uint last_fmt; + + bool en_share; }; static const struct snd_pcm_hardware aml_tdm_hardware = { @@ -442,9 +446,11 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { sharebuffer_prepare(substream, - fr, p_tdm->samesource_sel); + fr, p_tdm->samesource_sel, + p_tdm->lane_ss); } /* i2s source to hdmix */ @@ -569,7 +575,7 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, p_tdm->samesource_sel)) - ) + && p_tdm->en_share) sharebuffer_trigger(cmd, p_tdm->samesource_sel, p_tdm->chipinfo->same_src_spdif_reen); @@ -604,7 +610,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { aml_spdifout_mute_without_actrl(0, false); } } else { @@ -633,7 +640,8 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd, && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { aml_spdifout_mute_without_actrl(0, true); } } else { @@ -806,7 +814,8 @@ static int aml_dai_tdm_hw_params(struct snd_pcm_substream *substream, && (p_tdm->chipinfo->same_src_fn) && (p_tdm->samesource_sel >= 0) && (aml_check_sharebuffer_valid(p_tdm->fddr, - p_tdm->samesource_sel))) { + p_tdm->samesource_sel)) + && p_tdm->en_share) { int mux = 0, ratio = 0; sharebuffer_get_mclk_fs_ratio(p_tdm->samesource_sel, @@ -858,7 +867,8 @@ static int aml_dai_tdm_hw_free(struct snd_pcm_substream *substream, && p_tdm->chipinfo->same_src_fn && (p_tdm->samesource_sel >= 0) && fr - && (aml_check_sharebuffer_valid(fr, p_tdm->samesource_sel))) { + && (aml_check_sharebuffer_valid(fr, p_tdm->samesource_sel)) + && p_tdm->en_share) { sharebuffer_free(substream, fr, p_tdm->samesource_sel); } @@ -1359,6 +1369,51 @@ static const struct of_device_id aml_tdm_device_id[] = { }; MODULE_DEVICE_TABLE(of, aml_tdm_device_id); +static int check_channel_mask(const char *str) +{ + int ret = -1; + + if (!strncmp(str, "i2s_0/1", 7)) + ret = 0; + else if (!strncmp(str, "i2s_2/3", 7)) + ret = 1; + else if (!strncmp(str, "i2s_4/5", 7)) + ret = 2; + else if (!strncmp(str, "i2s_6/7", 7)) + ret = 3; + return ret; +} + +/* spdif same source with i2s */ +static void parse_samesrc_channel_mask(struct aml_tdm *p_tdm) +{ + struct device_node *node = p_tdm->dev->of_node; + struct device_node *np = NULL; + const char *str = NULL; + int ret = 0; + + /* channel mask */ + np = of_get_child_by_name(node, "Channel_Mask"); + if (np == NULL) { + pr_info("No channel mask node %s\n", + "Channel_Mask"); + return; + } + + /* If spdif is same source to i2s, + * it can be muxed to i2s 2 channels + */ + ret = of_property_read_string(np, + "Spdif_samesource_Channel_Mask", &str); + if (ret) { + pr_err("error:read Spdif_samesource_Channel_Mask\n"); + return; + } + p_tdm->lane_ss = check_channel_mask(str); + + pr_info("Channel_Mask: lane_ss = %d\n", p_tdm->lane_ss); +} + static int aml_tdm_platform_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -1515,8 +1570,13 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) } p_tdm->dev = dev; + /* For debug to disable share buffer */ + p_tdm->en_share = 1; dev_set_drvdata(dev, p_tdm); + /* spdif same source with i2s */ + parse_samesrc_channel_mask(p_tdm); + ret = devm_snd_soc_register_component(dev, &aml_tdm_component, &aml_tdm_dai[p_tdm->id], 1); if (ret) { -- 2.7.4