From: yujie.wu Date: Tue, 12 Mar 2019 02:58:30 +0000 (+0800) Subject: audio: Add PDM lane mask [1/1] X-Git-Tag: hardkernel-4.9.236-104~1638 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=42276afad41a9ce66f1e7193c2500e0cb037345f;p=platform%2Fkernel%2Flinux-amlogic.git audio: Add PDM lane mask [1/1] 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 --- diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts index 455d206..a7daad7 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot.dts @@ -1052,6 +1052,7 @@ "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"; }; diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts index d08f8c1..2efb4df 100644 --- a/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts +++ b/arch/arm64/boot/dts/amlogic/g12b_a311x_w411_buildroot_a.dts @@ -1017,6 +1017,7 @@ "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"; }; diff --git a/sound/soc/amlogic/auge/pdm.c b/sound/soc/amlogic/auge/pdm.c index bf92cac..717289e 100644 --- a/sound/soc/amlogic/auge/pdm.c +++ b/sound/soc/amlogic/auge/pdm.c @@ -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); diff --git a/sound/soc/amlogic/auge/pdm.h b/sound/soc/amlogic/auge/pdm.h index 60a0e1e..43100b8 100644 --- a/sound/soc/amlogic/auge/pdm.h +++ b/sound/soc/amlogic/auge/pdm.h @@ -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]; diff --git a/sound/soc/amlogic/auge/pdm_hw.c b/sound/soc/amlogic/auge/pdm_hw.c index d870dd0..d814c04 100644 --- a/sound/soc/amlogic/auge/pdm_hw.c +++ b/sound/soc/amlogic/auge/pdm_hw.c @@ -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 */ diff --git a/sound/soc/amlogic/auge/pdm_hw.h b/sound/soc/amlogic/auge/pdm_hw.h index b7d19c0..b7ad473 100644 --- a/sound/soc/amlogic/auge/pdm_hw.h +++ b/sound/soc/amlogic/auge/pdm_hw.h @@ -19,9 +19,19 @@ #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);