ASoC: rockchip: pdm_v2: support new features for rv1126b pdm

1.Support data shift.
2.Move the hpf after cic filter.
3.Separate the gain control.

Change-Id: I092360fad0945084c3b44f3a31be6ee67371755a
Signed-off-by: Jason Zhu <jason.zhu@rock-chips.com>
This commit is contained in:
Jason Zhu
2024-12-11 09:41:27 +08:00
committed by Tao Huang
parent e0d4c336d2
commit 240d040e41
2 changed files with 171 additions and 2 deletions

View File

@@ -29,11 +29,13 @@
#define PDM_V2_START_DELAY_MS_MIN (0)
#define PDM_V2_START_DELAY_MS_MAX (1000)
#define PDM_V2_REF_CLK_MAX 61440000
#define PDM_V2_CHANNEL_MAX 8
#define QUIRK_ALWAYS_ON BIT(0)
#define RK3506_PDM 0x2311
#define RK3576_PDM 0x2302
#define RV1126B_PDM 0x2411
struct rk_pdm_v2_clkref {
unsigned int sr;
@@ -73,6 +75,7 @@ struct rk_pdm_v2_dev {
unsigned int clk_ref_frq;
unsigned int quirks;
unsigned int version;
unsigned int data_shift[PDM_V2_CHANNEL_MAX];
};
static int get_pdm_v2_clkref(struct rk_pdm_v2_dev *pdm, unsigned int sr)
@@ -121,6 +124,12 @@ static void rockchip_pdm_v2_rxctrl(struct rk_pdm_v2_dev *pdm, int on)
regmap_update_bits(pdm->regmap, PDM_V2_SYSCONFIG,
PDM_V2_RX_MSK | PDM_V2_RX_CLR_MSK | PDM_V2_NUM_MSK,
PDM_V2_RX_STOP | PDM_V2_RX_CLR_WR | PDM_V2_NUM_STOP);
if (pdm->version == RV1126B_PDM) {
regmap_update_bits(pdm->regmap, PDM_V2_DATA_SHIFT0,
0xffffffff, 0x0);
regmap_update_bits(pdm->regmap, PDM_V2_DATA_SHIFT1,
0xffffffff, 0x0);
}
}
}
@@ -209,7 +218,7 @@ static int rockchip_pdm_v2_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rk_pdm_v2_dev *pdm = to_info(dai);
unsigned int val = 0;
unsigned int i, n = 0, val = 0;
regmap_update_bits(pdm->regmap, PDM_V2_CTRL,
PDM_V2_SJM_SEL_MSK, PDM_V2_SJM_SEL_L);
@@ -223,9 +232,42 @@ static int rockchip_pdm_v2_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(pdm->regmap, PDM_V2_FILTER_CTRL,
PDM_V2_HPF_R_MSK | PDM_V2_HPF_L_MSK | PDM_V2_HPF_FREQ_MSK,
PDM_V2_HPF_R_EN | PDM_V2_HPF_L_EN | PDM_V2_HPF_FREQ_60);
} else if (pdm->version == RV1126B_PDM) {
/* Move the hpf after cic filter */
regmap_update_bits(pdm->regmap, PDM_V2_FILTER_CTRL1,
PDM_V2_FILT1_HPF_V2_R_MSK | PDM_V2_FILT1_HPF_V2_L_MSK |
PDM_V2_FILT1_HPF_V2_FREQ_MSK,
PDM_V2_FILT1_HPF_V2_R_EN | PDM_V2_FILT1_HPF_V2_L_EN |
PDM_V2_FILT1_HPF_V2_FREQ_60);
}
if (pdm->version == RV1126B_PDM) {
/* PDM data shift */
n = params_channels(params);
if (n > PDM_V2_CHANNEL_MAX / 2) {
for (i = 0; i < PDM_V2_CHANNEL_MAX / 2; i++)
val += pdm->data_shift[i] << (i * 8);
regmap_update_bits(pdm->regmap, PDM_V2_DATA_SHIFT0,
0xffffffff, val);
val = 0;
for (i = 0; i < (n - PDM_V2_CHANNEL_MAX / 2); i++)
val += pdm->data_shift[i + PDM_V2_CHANNEL_MAX / 2] << (i * 8);
regmap_update_bits(pdm->regmap, PDM_V2_DATA_SHIFT1,
0xffffffff, val);
} else {
for (i = 0; i < n; i++)
val += pdm->data_shift[i] << (i * 8);
regmap_update_bits(pdm->regmap, PDM_V2_DATA_SHIFT0,
0xffffffff, val);
}
}
rockchip_pdm_v2_set_samplerate(pdm, params_rate(params));
val = 0;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
val |= PDM_V2_VDW(16);
@@ -336,6 +378,7 @@ static int rockchip_pdm_v2_prepare(struct snd_pcm_substream *substream,
static const struct snd_kcontrol_new rk3506_controls[];
static const struct snd_kcontrol_new rk3576_controls[];
static const struct snd_kcontrol_new rv1126b_controls[];
static int rockchip_pdm_v2_dai_probe(struct snd_soc_dai *dai)
{
@@ -347,6 +390,8 @@ static int rockchip_pdm_v2_dai_probe(struct snd_soc_dai *dai)
snd_soc_add_component_controls(dai->component, rk3506_controls, 1);
else if (pdm->version == RK3576_PDM)
snd_soc_add_component_controls(dai->component, rk3576_controls, 1);
else if (pdm->version == RV1126B_PDM)
snd_soc_add_component_controls(dai->component, rv1126b_controls, 1);
return 0;
}
@@ -446,6 +491,8 @@ static SOC_ENUM_SINGLE_DECL(hpf_cutoff_enum, PDM_V2_FILTER_CTRL,
19, hpf_cutoff_text);
static SOC_ENUM_SINGLE_DECL(hpf_v2_cutoff_enum, PDM_V2_FILTER_CTRL,
21, hpf_v2_cutoff_text);
static SOC_ENUM_SINGLE_DECL(hpf1_v2_cutoff_enum, PDM_V2_FILTER_CTRL1,
2, hpf_v2_cutoff_text);
static const DECLARE_TLV_DB_SCALE(pdm_v2_digtal_gain_tlv, -6563, 75, 0);
static const struct snd_kcontrol_new rockchip_pdm_v2_controls[] = {
@@ -487,6 +534,36 @@ static const struct snd_kcontrol_new rk3576_controls[] = {
SOC_SINGLE("HPFR Switch", PDM_V2_FILTER_CTRL, 21, 1, 0),
};
static const struct snd_kcontrol_new rv1126b_controls[] = {
SOC_SINGLE_RANGE_TLV("Gain Volume 0",
PDM_V2_GAIN_CTRL,
1,
PDM_V2_GAIN_CTRL_MIN,
PDM_V2_GAIN_CTRL_MAX,
0, pdm_v2_digtal_gain_tlv),
SOC_SINGLE_RANGE_TLV("Gain Volume 1",
PDM_V2_GAIN_CTRL,
9,
PDM_V2_GAIN_CTRL_MIN,
PDM_V2_GAIN_CTRL_MAX,
0, pdm_v2_digtal_gain_tlv),
SOC_SINGLE_RANGE_TLV("Gain Volume 2",
PDM_V2_GAIN_CTRL,
17,
PDM_V2_GAIN_CTRL_MIN,
PDM_V2_GAIN_CTRL_MAX,
0, pdm_v2_digtal_gain_tlv),
SOC_SINGLE_RANGE_TLV("Gain Volume 3",
PDM_V2_GAIN_CTRL,
25,
PDM_V2_GAIN_CTRL_MIN,
PDM_V2_GAIN_CTRL_MAX,
0, pdm_v2_digtal_gain_tlv),
SOC_ENUM("HPF Cutoff", hpf1_v2_cutoff_enum),
SOC_SINGLE("HPFL Switch", PDM_V2_FILTER_CTRL1, 1, 1, 0),
SOC_SINGLE("HPFR Switch", PDM_V2_FILTER_CTRL1, 0, 1, 0),
};
static const struct snd_soc_component_driver rockchip_pdm_v2_component = {
.name = "rockchip-pdm-v2",
.controls = rockchip_pdm_v2_controls,
@@ -584,6 +661,9 @@ static bool rockchip_pdm_v2_wr_reg(struct device *dev, unsigned int reg)
case PDM_V2_RXFIFO_DATA:
case PDM_V2_DATA_VALID:
case PDM_V2_GAIN_CTRL:
case PDM_V2_DATA_SHIFT0:
case PDM_V2_DATA_SHIFT1:
case PDM_V2_FILTER_CTRL1:
return true;
default:
return false;
@@ -601,6 +681,9 @@ static bool rockchip_pdm_v2_rd_reg(struct device *dev, unsigned int reg)
case PDM_V2_RXFIFO_DATA:
case PDM_V2_VERSION:
case PDM_V2_GAIN_CTRL:
case PDM_V2_DATA_SHIFT0:
case PDM_V2_DATA_SHIFT1:
case PDM_V2_FILTER_CTRL1:
return true;
default:
return false;
@@ -639,7 +722,7 @@ static const struct regmap_config rockchip_pdm_v2_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = PDM_V2_GAIN_CTRL,
.max_register = PDM_V2_FILTER_CTRL1,
.reg_defaults = rockchip_pdm_v2_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(rockchip_pdm_v2_reg_defaults),
.writeable_reg = rockchip_pdm_v2_wr_reg,
@@ -652,6 +735,7 @@ static const struct regmap_config rockchip_pdm_v2_regmap_config = {
static const struct of_device_id rockchip_pdm_v2_match[] __maybe_unused = {
{ .compatible = "rockchip,rk3506-pdm", },
{ .compatible = "rockchip,rk3576-pdm", },
{ .compatible = "rockchip,rv1126b-pdm", },
{},
};
MODULE_DEVICE_TABLE(of, rockchip_pdm_v2_match);
@@ -754,6 +838,49 @@ static int rockchip_pdm_v2_register_platform(struct device *dev)
return ret;
}
static int rockchip_pdm_v2_data_shift(struct rk_pdm_v2_dev *pdm,
struct device_node *np)
{
char *pdm_data_shift_prop = "rockchip,pdm-data-shift";
int num, ret = 0;
num = of_count_phandle_with_args(np, pdm_data_shift_prop, NULL);
if (num < 0) {
if (num != -ENOENT) {
dev_err(pdm->dev,
"Failed to read '%s' num: %d\n",
pdm_data_shift_prop, num);
ret = num;
}
return ret;
} else if (num != PDM_V2_CHANNEL_MAX) {
dev_err(pdm->dev,
"The num: %d should be: %d\n", num, PDM_V2_CHANNEL_MAX);
return -EINVAL;
}
ret = of_property_read_u32_array(np, pdm_data_shift_prop,
pdm->data_shift, num);
if (ret < 0) {
dev_err(pdm->dev, "Failed to read '%s': %d\n", pdm_data_shift_prop, ret);
return ret;
}
for (num = 0; num < PDM_V2_CHANNEL_MAX; num++) {
if (pdm->data_shift[num] > 0xff) {
dev_err(pdm->dev,
"The data_shift: %d exceed 0xff\n", num);
return -EINVAL;
}
}
return ret;
}
static int rockchip_pdm_v2_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -827,6 +954,16 @@ static int rockchip_pdm_v2_probe(struct platform_device *pdev)
} else if (pdm->version == RK3576_PDM) {
regmap_update_bits(pdm->regmap, PDM_V2_FILTER_CTRL, PDM_V2_GAIN_MSK,
PDM_V2_GAIN_0DB);
} else if (pdm->version == RV1126B_PDM) {
regmap_update_bits(pdm->regmap, PDM_V2_GAIN_CTRL,
PDM_V2_GAIN_CTRL_MSK |
PDM_V2_GAIN_CTRL_MSK << 8 |
PDM_V2_GAIN_CTRL_MSK << 16 |
PDM_V2_GAIN_CTRL_MSK << 24,
PDM_V2_GAIN_CTRL_0DB |
PDM_V2_GAIN_CTRL_0DB << 8 |
PDM_V2_GAIN_CTRL_0DB << 16 |
PDM_V2_GAIN_CTRL_0DB << 24);
}
ret = rockchip_pdm_v2_path_parse(pdm, node);
@@ -836,6 +973,12 @@ static int rockchip_pdm_v2_probe(struct platform_device *pdev)
ret = rockchip_pdm_v2_parse_quirks(pdm);
if (ret)
goto err_hclk;
if (pdm->version == RV1126B_PDM) {
ret = rockchip_pdm_v2_data_shift(pdm, node);
if (ret)
goto err_hclk;
}
/*
* MUST: after pm_runtime_enable step, any register R/W
* should be wrapped with pm_runtime_get_sync/put.

View File

@@ -24,6 +24,9 @@
#define PDM_V2_DATA3L 0x0034
#define PDM_V2_VERSION 0x0038
#define PDM_V2_GAIN_CTRL 0x003c
#define PDM_V2_DATA_SHIFT0 0x0040
#define PDM_V2_DATA_SHIFT1 0x0044
#define PDM_V2_FILTER_CTRL1 0x0048
#define PDM_V2_INCR_RXDR 0x0400
/* PDM_V2_SYSCONFIG */
@@ -152,4 +155,27 @@
#define PDM_V2_GAIN_CTRL_MAX 0x7f
#define PDM_V2_GAIN_CTRL_0DB (175 << 0)
/* PDM_V2_FILTER_CTRL1 */
#define PDM_V2_FILT1_HPF_V2_R_MSK (0x1 << 0)
#define PDM_V2_FILT1_HPF_V2_R_EN (0x1 << 0)
#define PDM_V2_FILT1_HPF_V2_R_DIS (0x0 << 0)
#define PDM_V2_FILT1_HPF_V2_L_MSK (0x1 << 1)
#define PDM_V2_FILT1_HPF_V2_L_EN (0x1 << 1)
#define PDM_V2_FILT1_HPF_V2_L_DIS (0x0 << 1)
#define PDM_V2_FILT1_HPF_V2_FREQ_MSK (0xf << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_0_234 (0x0 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_0_468 (0x1 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_0_937 (0x2 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_1_875 (0x3 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_3_75 (0x4 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_7_5 (0x5 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_15 (0x6 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_30 (0x7 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_60 (0x8 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_122 (0x9 << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_251 (0xa << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_528 (0xb << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_1183 (0xc << 2)
#define PDM_V2_FILT1_HPF_V2_FREQ_3152 (0xd << 2)
#endif