mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user