audio: add I2S samesrc channel mapping to spdif [1/1]
authorShuai Li <shuai.li@amlogic.com>
Thu, 21 Mar 2019 12:20:21 +0000 (20:20 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Fri, 22 Mar 2019 09:34:12 +0000 (02:34 -0700)
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 <shuai.li@amlogic.com>
arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts
arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts
arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts
arch/arm64/boot/dts/amlogic/tl1_t962x2_t309.dts
arch/arm64/boot/dts/amlogic/tl1_t962x2_x301.dts
sound/soc/amlogic/auge/sharebuffer.c
sound/soc/amlogic/auge/sharebuffer.h
sound/soc/amlogic/auge/spdif_hw.c
sound/soc/amlogic/auge/spdif_hw.h
sound/soc/amlogic/auge/tdm.c

index 028d8a8..55595d6 100644 (file)
                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 {
index bec1a97..4a62607 100644 (file)
                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 {
index a5913c3..a044246 100644 (file)
                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 {
index 8d99594..a2d0a40 100644 (file)
                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 {
index 7006bcb..465e88f 100644 (file)
                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 {
index 855d7a6..1a740c4 100644 (file)
@@ -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 */
index e32a9f4..c8e39c5 100644 (file)
@@ -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);
index 417c86c..971d29b 100644 (file)
@@ -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);
index 689dc7e..e15efa3 100644 (file)
@@ -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);
index 0d0c150..4ed034b 100644 (file)
@@ -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) {