mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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:
@@ -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";
|
||||
};
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user