summaryrefslogtreecommitdiff
path: root/sound/soc/fsl/imx-pdm.c
diff options
context:
space:
mode:
authorAdrian Alonso <adrian.alonso@nxp.com>2020-06-22 16:18:49 -0500
committerAdrian Alonso <adrian.alonso@nxp.com>2020-07-20 11:02:29 -0500
commitde79414d59918132220fa9ada8ad4342b1574986 (patch)
tree1301910bf82e116746e7f6df06cbfdc863da26ba /sound/soc/fsl/imx-pdm.c
parente48d0806361b068ff007e1111407da59291b0922 (diff)
MLK-24422: sound: soc: fsl: imx pdm: over sampling ratio control
Add Over sample ratio kcontrol interface, allow user to specify over sample ratio amixer -c1 cget numid=1 numid=1,iface=MIXER,name='over sampling ratio' ; type=ENUMERATED,access=rw------,values=1,items=5 ; Item #0 'OSR_4x12' ; Item #1 'OSR_4x16' ; Item #2 'OSR_4x24' ; Item #3 'OSR_4x32' ; Item #4 'OSR_4x48' : values=0 Set different OSR amixer -c1 cset numid=1 2 Signed-off-by: Adrian Alonso <adrian.alonso@nxp.com> Reviewed-by: Viorel Suman <viorel.suman@nxp.com>
Diffstat (limited to 'sound/soc/fsl/imx-pdm.c')
-rw-r--r--sound/soc/fsl/imx-pdm.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/sound/soc/fsl/imx-pdm.c b/sound/soc/fsl/imx-pdm.c
index f21abbf25295..b6db88db39dd 100644
--- a/sound/soc/fsl/imx-pdm.c
+++ b/sound/soc/fsl/imx-pdm.c
@@ -25,6 +25,7 @@ struct imx_pdm_data {
struct snd_soc_dai_link dai;
struct snd_soc_card card;
unsigned int decimation;
+ int osr_id;
};
static const struct imx_pdm_mic_fs_mul {
@@ -40,6 +41,84 @@ static const unsigned int imx_pdm_mic_rates[] = {
8000, 11025, 16000, 22050,
32000, 44100, 48000, 64000,
};
+
+static const struct imx_pdm_mic_osr_map {
+ int id;
+ unsigned int osr;
+} osr_map[] = {
+ { .id = 0, .osr = 48 }, /* 4x12 */
+ { .id = 1, .osr = 64 }, /* 4x16 */
+ { .id = 2, .osr = 96 }, /* 4x24 */
+ { .id = 3, .osr = 128 }, /* 4x32 */
+ { .id = 4, .osr = 192 }, /* 4x48 */
+};
+
+static int imx_pdm_mic_get_osr_id(int decimation)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(osr_map); i++) {
+ if (osr_map[i].osr == decimation)
+ return osr_map[i].id;
+ }
+
+ return -EINVAL;
+}
+
+static unsigned int imx_pdm_mic_get_osr_rate(int osr_id)
+{
+ int i;
+
+ for (i = 0; ARRAY_SIZE(osr_map); i++) {
+ if (osr_map[i].id == osr_id)
+ return osr_map[i].osr;
+ }
+
+ return -EINVAL;
+}
+
+static const char *const osr_rate_text[] = {
+ "OSR_4x12",
+ "OSR_4x16",
+ "OSR_4x24",
+ "OSR_4x32",
+ "OSR_4x48"
+};
+
+static int osr_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+ struct imx_pdm_data *data = snd_soc_card_get_drvdata(card);
+
+ ucontrol->value.enumerated.item[0] = data->osr_id;
+
+ return 0;
+}
+
+static int osr_rate_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+ struct imx_pdm_data *data = snd_soc_card_get_drvdata(card);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int *item = ucontrol->value.enumerated.item;
+ int osr = snd_soc_enum_item_to_val(e, item[0]);
+
+ data->decimation = imx_pdm_mic_get_osr_rate(osr);
+ data->osr_id = osr;
+
+ return 0;
+}
+
+static const struct soc_enum osr_rate_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(osr_rate_text), osr_rate_text);
+
+const struct snd_kcontrol_new imx_pdm_mic_snd_ctrls[] = {
+ SOC_ENUM_EXT("over sampling ratio", osr_rate_enum,
+ osr_rate_get, osr_rate_set),
+};
+
static struct snd_pcm_hw_constraint_list imx_pdm_mic_rate_constrains = {
.count = ARRAY_SIZE(imx_pdm_mic_rates),
.list = imx_pdm_mic_rates,
@@ -64,6 +143,7 @@ static unsigned long imx_pdm_mic_mclk_freq(unsigned int decimation,
return 0;
}
+
static int imx_pdm_mic_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -180,6 +260,12 @@ static int imx_pdm_mic_probe(struct platform_device *pdev)
goto fail;
}
+ data->osr_id = imx_pdm_mic_get_osr_id(data->decimation);
+ if (data->osr_id < 0) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
data->dai.cpus = &dlc[0];
data->dai.num_cpus = 1;
data->dai.platforms = &dlc[1];
@@ -207,6 +293,8 @@ static int imx_pdm_mic_probe(struct platform_device *pdev)
data->card.num_links = 1;
data->card.dai_link = &data->dai;
+ data->card.controls = imx_pdm_mic_snd_ctrls;
+ data->card.num_controls = ARRAY_SIZE(imx_pdm_mic_snd_ctrls);
platform_set_drvdata(pdev, &data->card);
snd_soc_card_set_drvdata(&data->card, data);