audio: support the number of datain+loopback beyond 8 channel feature
authorRenjun Xu <renjun.xu@amlogic.com>
Tue, 12 Jun 2018 08:34:14 +0000 (16:34 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Mon, 23 Jul 2018 06:53:31 +0000 (23:53 -0700)
PD#168268: add support datain+loopback beyond 8 channel feature

   You need add  datain_datalb_total = <10>; at the end
   of aml_loopback node on dts or amixer command to enable.

   e.g. pdm 8ch + loopback 2ch case
        pdm 8ch + loopback 8ch case
        pdm 6ch + loopback 4ch case

   if total number of channel beyond 8 , must utilize 16ch to capture.
   so that  we change relevant parameter like this:
   if (lb_cfg->datain_datalb_total > 8) {
     lb_cfg->datain_chnum = 8;
     lb_cfg->datain_chmask = 0xff;
     lb_cfg->datalb_chnum = 8;
     lb_cfg->datalb_chmask = 0xff;
     lb_cfg->datalb_chswap = 0x76543210;
   }
   capture command:
   arecord -Dhw:0,3 -c 16 -r 48000 -f S32_LE /test.wav

   You can use asound.conf to choose your channel.

Change-Id: I0a59c4c12da603efd8709bf36d6dac640fdf788a
Signed-off-by: Renjun Xu <renjun.xu@amlogic.com>
sound/soc/amlogic/auge/audio_utils.c
sound/soc/amlogic/auge/audio_utils.h
sound/soc/amlogic/auge/loopback_hw.c

index 668ed08e7b086b4743d61e2e96aa083cf52b227b..d0d5dd6a753ffbb4d7cb7bd0d8973c8de5e1af10 100644 (file)
@@ -38,6 +38,7 @@ struct snd_elem_info {
 
 static unsigned int loopback_enable;
 static unsigned int loopback_is_running;
+static unsigned int datain_datalb_total;
 
 static const char *const loopback_enable_texts[] = {
        "Disable",
@@ -69,6 +70,23 @@ static int loopback_enable_set_enum(
        return 0;
 }
 
+static int datain_datalb_total_get_param(
+       struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.bytes.data[0] = datain_datalb_total;
+
+       return 0;
+}
+
+static int datain_datalb_total_set_param(
+       struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       datain_datalb_total = ucontrol->value.bytes.data[0];
+
+       return 0;
+}
 
 static unsigned int loopback_datain;
 
@@ -626,6 +644,10 @@ static const struct snd_kcontrol_new snd_auge_controls[] = {
                     loopback_enable_get_enum,
                     loopback_enable_set_enum),
 
+       SND_SOC_BYTES_EXT("datain_datalb_total", 1,
+                          datain_datalb_total_get_param,
+                          datain_datalb_total_set_param),
+
        /* loopback data in source */
        SOC_ENUM_EXT("Loopback datain source",
                     loopback_datain_enum,
@@ -995,6 +1017,7 @@ 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");
@@ -1012,8 +1035,30 @@ int loopback_parse_of(struct device_node *node,
                                        (i * 2 + 1) << (set_num++ * 4);
                        }
                }
+       }
+       ret = of_property_read_u32(node, "datalb_clk",
+               &lb_cfg->datalb_clk);
+       if (ret) {
+               pr_err("if no datalb_clk on dts, it equal is datalb_src\n");
+               lb_cfg->datalb_clk = lb_cfg->datalb_src;
+       }
 
+       ret = of_property_read_u32(node, "datain_datalb_total",
+               &lb_cfg->datain_datalb_total);
+       if (ret) {
+               pr_err("no register datain_datalb_total,it also can work\n");
+               lb_cfg->datain_datalb_total = 0;
+       } else {
+               if (lb_cfg->datain_datalb_total > 8) {
+                       lb_cfg->datain_chnum = 8;
+                       lb_cfg->datain_chmask = 0xff;
+                       lb_cfg->datalb_chnum = 8;
+                       lb_cfg->datalb_chmask = 0xff;
+                       lb_cfg->datalb_chswap = 0x76543210;
+               }
        }
+       datain_datalb_total = lb_cfg->datain_datalb_total;
+
        loopback_datain = lb_cfg->datain_src;
        loopback_tdminlb = lb_cfg->datalb_src;
 
@@ -1026,7 +1071,7 @@ int loopback_parse_of(struct device_node *node,
        pr_info("\tdatalb_src:%d, datalb_chnum:%d\n",
                lb_cfg->datalb_src,
                lb_cfg->datalb_chnum);
-       pr_info("\tdatalb_chswap:0x%x,datalb_chumask:%x\n",
+       pr_info("\tdatalb_chswap:0x%x,datalb_chmask:%x\n",
                lb_cfg->datalb_chswap,
                lb_cfg->datalb_chmask);
 
@@ -1189,6 +1234,15 @@ int loopback_prepare(
        datain_config(&datain);
        datalb_config(&datalb);
 
+       lb_cfg->datain_datalb_total = datain_datalb_total;
+
+       if (lb_cfg->datain_datalb_total > 8) {
+               lb_cfg->datain_chnum = 8;
+               lb_cfg->datain_chmask = 0xff;
+               lb_cfg->datalb_chnum = 8;
+               lb_cfg->datalb_chmask = 0xff;
+               lb_cfg->datalb_chswap = 0x76543210;
+       }
        datalb_ctrl(lb_cfg);
        lb_mode(lb_cfg->lb_mode);
 
index 31a9dd3343f46b10e30fd3876904bc2734084639..e77a2d2cd212930243c70fa3b57d8f5debe0fc71 100644 (file)
@@ -123,10 +123,12 @@ struct loopback_cfg {
        int toddr_index;
 
        enum tdmin_lb_src datalb_src;
+       enum tdmin_lb_src datalb_clk;
        unsigned int datalb_chnum;
        unsigned int datalb_chswap;
        unsigned int datalb_chmask;
        int frddr_index;
+       unsigned int datain_datalb_total;
 };
 
 extern void loopback_set_status(int is_running);
index 63b3924e416e2b438a1bd323ea55d29a06630658..5f9ba3f5917adf0c727b348ca960401a253b741d 100644 (file)
@@ -122,35 +122,46 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg)
                return;
        }
 
-       /*swap same as tdmout */
-       reg = reg_base + offset * id;
-       audiobus_write(EE_AUDIO_TDMIN_LB_SWAP,
-               audiobus_read(reg));
-
-       /*mask same as datalb*/
-       /* mask 0 */
-       reg += 1;
-       audiobus_write(
-               EE_AUDIO_TDMIN_LB_MASK0,
-               audiobus_read(reg));
+       if (lb_cfg->datain_datalb_total > 8) {
+               audiobus_write(
+                               EE_AUDIO_TDMIN_LB_SWAP,
+                               lb_cfg->datalb_chswap);
 
-       /* mask 1 */
-       reg += 1;
-       audiobus_write(
-               EE_AUDIO_TDMIN_LB_MASK1,
-               audiobus_read(reg));
+               audiobus_write(EE_AUDIO_TDMIN_LB_MASK0, 3);
+               audiobus_write(EE_AUDIO_TDMIN_LB_MASK1, 3);
+               audiobus_write(EE_AUDIO_TDMIN_LB_MASK2, 3);
+               audiobus_write(EE_AUDIO_TDMIN_LB_MASK3, 3);
+       } else {
+               /*swap same as tdmout */
+               reg = reg_base + offset * id;
+               audiobus_write(EE_AUDIO_TDMIN_LB_SWAP,
+                               audiobus_read(reg));
 
-       /* mask 2 */
-       reg += 1;
-       audiobus_write(
-               EE_AUDIO_TDMIN_LB_MASK2,
-               audiobus_read(reg));
+               /*mask same as datalb*/
+               /* mask 0 */
+               reg += 1;
+               audiobus_write(
+                               EE_AUDIO_TDMIN_LB_MASK0,
+                               audiobus_read(reg));
 
-       /* mask 3 */
-       reg += 1;
-       audiobus_write(
-               EE_AUDIO_TDMIN_LB_MASK3,
-               audiobus_read(reg));
+               /* mask 1 */
+               reg += 1;
+               audiobus_write(
+                               EE_AUDIO_TDMIN_LB_MASK1,
+                               audiobus_read(reg));
+
+               /* mask 2 */
+               reg += 1;
+               audiobus_write(
+                               EE_AUDIO_TDMIN_LB_MASK2,
+                               audiobus_read(reg));
+
+               /* mask 3 */
+               reg += 1;
+               audiobus_write(
+                               EE_AUDIO_TDMIN_LB_MASK3,
+                               audiobus_read(reg));
+       }
 }
 
 void lb_mode(int mode)