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 <yujie.wu@amlogic.com>
This commit is contained in:
yujie.wu
2019-03-12 10:58:30 +08:00
committed by Luke Go
parent 63dde3fa44
commit 1745b54633
6 changed files with 96 additions and 17 deletions

View File

@@ -1046,6 +1046,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";
};

View File

@@ -1015,6 +1015,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";
};

View 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);

View 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];

View 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;
pr_info("%s, channels mask:%x\n", __func__, ch_mask);
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, 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 */

View File

@@ -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);