audio: Add PDM lane mask [1/1]
authoryujie.wu <yujie.wu@amlogic.com>
Tue, 12 Mar 2019 02:58:30 +0000 (10:58 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Tue, 12 Mar 2019 10:37:41 +0000 (02:37 -0800)
PD#SWPL-5594

Problem:
  The PDM input channel is not always in the
  first lane, we need a mask to detect which
  lane to use

Solution:
  Add lane config in PDM module
  Add lane-mask-in in W411 config

Verify:
  W411

Change-Id: I48ca5927402282611ba5e225d75d034eeceacad6
Signed-off-by: yujie.wu <yujie.wu@amlogic.com>
arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts
arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts
sound/soc/amlogic/auge/pdm.c
sound/soc/amlogic/auge/pdm.h
sound/soc/amlogic/auge/pdm_hw.c
sound/soc/amlogic/auge/pdm_hw.h

index 455d206..a7daad7 100644 (file)
                        "pdm_sysclk";
                pinctrl-names = "pdm_pins";
                pinctrl-0 = <&pdmin>;
+               lane-mask-in = <0 0 1 0>;
                filter_mode = <1>; /* mode 0~4, defalut:1 */
                status = "okay";
        };
index d08f8c1..2efb4df 100644 (file)
                        "pdm_sysclk";
                pinctrl-names = "pdm_pins";
                pinctrl-0 = <&pdmin>;
+               lane-mask-in = <0 0 1 0>;
                filter_mode = <1>; /* mode 0~4, defalut:1 */
                status = "okay";
        };
index bf92cac..717289e 100644 (file)
@@ -54,7 +54,7 @@ static struct snd_pcm_hardware aml_pdm_hardware = {
        .rate_max                       =       96000,
 
        .channels_min           =       PDM_CHANNELS_MIN,
-       .channels_max           =       PDM_CHANNELS_MAX,
+       .channels_max           =       PDM_CHANNELS_LB_MAX,
 
        .buffer_bytes_max       =       512 * 1024,
        .period_bytes_max       =       256 * 1024,
@@ -626,6 +626,7 @@ static int aml_pdm_dai_prepare(
                struct toddr *to = p_pdm->tddr;
                struct toddr_fmt fmt;
                unsigned int osr = 192;
+               struct pdm_info info;
 
                /* to ddr pdmin */
                fmt.type      = toddr_type;
@@ -639,8 +640,12 @@ static int aml_pdm_dai_prepare(
                aml_toddr_set_format(to, &fmt);
                aml_toddr_set_fifos(to, 0x40);
 
-               aml_pdm_ctrl(p_pdm->actrl,
-                       bitwidth, runtime->channels);
+               info.bitdepth   = bitwidth;
+               info.channels   = runtime->channels;
+               info.lane_masks = p_pdm->lane_mask_in;
+               info.dclk_idx   = pdm_dclk;
+               info.bypass     = p_pdm->bypass;
+               aml_pdm_ctrl(&info);
 
                /* filter for pdm */
                if (pdm_dclk == 1) {
@@ -918,6 +923,26 @@ static const struct of_device_id aml_pdm_device_id[] = {
 };
 MODULE_DEVICE_TABLE(of, aml_pdm_device_id);
 
+static int snd_soc_of_get_slot_mask(
+       struct device_node *np,
+       const char *prop_name,
+       unsigned int *mask)
+{
+       u32 val;
+       const __be32 *of_slot_mask = of_get_property(np, prop_name, &val);
+       int i;
+
+       if (!of_slot_mask)
+               return -EINVAL;
+
+       val /= sizeof(u32);
+       for (i = 0; i < val; i++)
+               if (be32_to_cpup(&of_slot_mask[i]))
+                       *mask |= (1 << i);
+
+       return val;
+}
+
 static int aml_pdm_platform_probe(struct platform_device *pdev)
 {
        struct aml_pdm *p_pdm;
@@ -1022,6 +1047,12 @@ static int aml_pdm_platform_probe(struct platform_device *pdev)
                goto err;
        }
 
+       ret = snd_soc_of_get_slot_mask(node, "lane-mask-in",
+                       &p_pdm->lane_mask_in);
+       if (ret < 0) {
+               pr_warn("default set lane_mask_in as all lanes.\n");
+               p_pdm->lane_mask_in = 0xf;
+       }
 
        ret = of_property_read_u32(node, "filter_mode",
                        &p_pdm->filter_mode);
index 60a0e1e..43100b8 100644 (file)
@@ -27,7 +27,9 @@
 #define DEFAULT_FS_RATIO               256
 
 #define PDM_CHANNELS_MIN               1
-#define PDM_CHANNELS_MAX               (8 + 8) /* 8ch pdm in, 8 ch tdmin_lb */
+/* 8ch pdm in, 8 ch tdmin_lb */
+#define PDM_CHANNELS_LB_MAX            (PDM_CHANNELS_MAX + 8)
+
 
 #define PDM_RATES                      (SNDRV_PCM_RATE_96000 |\
                                        SNDRV_PCM_RATE_64000 |\
@@ -72,6 +74,15 @@ struct aml_pdm {
         * the group delay (latency) is from high to low.
         */
        int filter_mode;
+       /* dclk index */
+       int dclk_idx;
+       /* PCM or Raw Data */
+       int bypass;
+       /* PDM clk on/off */
+       bool clk_on;
+
+       /* lane mask in, each lane carries two channels */
+       int lane_mask_in;
 
        struct pdm_chipinfo *chipinfo;
        struct snd_kcontrol *controls[PDM_RUN_MAX];
index d870dd0..d814c04 100644 (file)
@@ -59,29 +59,54 @@ void pdm_fifo_reset(void)
                0x1 << 16);
 }
 
-void aml_pdm_ctrl(
-       struct aml_audio_controller *actrl,
-       int bitdepth, int channels)
+void aml_pdm_ctrl(struct pdm_info *info)
 {
        int mode, i, ch_mask = 0, sample_count;
+       int pdm_chs, lane_chs = 0;
+
+       if (!info)
+               return;
 
        /* sameple count */
-       if (pdm_dclk == 1)
+       if (info->dclk_idx == 1)
                sample_count = 38;
-       else if (pdm_dclk == 2)
+       else if (info->dclk_idx == 2)
                sample_count = 48;
        else
                sample_count = 18;
 
-       if (bitdepth == 32)
+       if (info->bitdepth == 32)
                mode = 0;
        else
                mode = 1;
 
-       for (i = 0; i < channels; i++)
-               ch_mask |= (1 << i);
+       /* update pdm channels for loopback */
+       pdm_chs = info->channels;
+       if (info->channels > PDM_CHANNELS_MAX)
+               pdm_chs = PDM_CHANNELS_MAX;
+
+       if (pdm_chs > info->lane_masks * 2)
+               pr_warn("capturing channels more than lanes carried\n");
+
+       /* each lanes carries two channels */
+       for (i = 0; i < PDM_LANE_MAX; i++)
+               if ((1 << i) & info->lane_masks) {
+                       ch_mask |= (1 << (2 * i));
+                       lane_chs += 1;
+                       if (lane_chs >= info->channels)
+                               break;
+                       ch_mask |= (1 << (2 * i + 1));
+                       lane_chs += 1;
+                       if (lane_chs >= info->channels)
+                               break;
+               }
 
-       pr_info("%s, channels mask:%x\n", __func__, ch_mask);
+       pr_info("%s, lane mask:0x%x, channels:%d, channels mask:0x%x, bypass:%d\n",
+               __func__,
+               info->lane_masks,
+               info->channels,
+               ch_mask,
+               info->bypass);
 
        aml_pdm_write(PDM_CLKG_CTRL, 1);
 
@@ -96,7 +121,7 @@ void aml_pdm_ctrl(
                                /* bypass mode.
                                 * 1: bypass all filter. 0: normal mode.
                                 */
-                               (0 << 28) |
+                               (info->bypass << 28) |
                                /* PDM channel reset. */
                                (ch_mask << 8) |
                                /* PDM channel enable */
index b7d19c0..b7ad473 100644 (file)
 #define __AML_PDM_HW_H__
 #include "audio_io.h"
 
-extern void aml_pdm_ctrl(
-       struct aml_audio_controller *actrl,
-       int bitdepth, int channels);
+#define PDM_CHANNELS_MAX               8 /* 8ch pdm in */
+#define PDM_LANE_MAX            4 /* 4 data pins, for 8ch maxs*/
+
+struct pdm_info {
+       int bitdepth;
+       int channels;
+       int lane_masks;
+
+       int dclk_idx;  /* mapping for dclk value */
+       int bypass;    /* bypass all filter, capture raw data */
+};
+
+extern void aml_pdm_ctrl(struct pdm_info *info);
 
 extern void aml_pdm_arb_config(struct aml_audio_controller *actrl);