"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";
};
"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";
};
.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,
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;
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) {
};
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;
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);
#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 |\
* 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];
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);
/* bypass mode.
* 1: bypass all filter. 0: normal mode.
*/
- (0 << 28) |
+ (info->bypass << 28) |
/* PDM channel reset. */
(ch_mask << 8) |
/* PDM channel enable */
#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);