Skip to content

Commit c5fae31

Browse files
committed
ASoC: fsl_micfil: Set default quality and channel
Merge series from Chancel Liu <chancel.liu@nxp.com>: Add default quality for different platforms. Set channel range control.
2 parents 47857da + ef1a7e0 commit c5fae31

1 file changed

Lines changed: 109 additions & 23 deletions

File tree

sound/soc/fsl/fsl_micfil.c

Lines changed: 109 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/sysfs.h>
1818
#include <linux/types.h>
1919
#include <linux/dma/imx-dma.h>
20+
#include <linux/log2.h>
2021
#include <sound/dmaengine_pcm.h>
2122
#include <sound/pcm.h>
2223
#include <sound/pcm_params.h>
@@ -92,6 +93,9 @@ struct fsl_micfil_soc_data {
9293
bool volume_sx;
9394
u64 formats;
9495
int fifo_offset;
96+
enum quality default_quality;
97+
/* stores const value in formula to calculate range */
98+
int rangeadj_const[3][2];
9599
};
96100

97101
static struct fsl_micfil_soc_data fsl_micfil_imx8mm = {
@@ -102,6 +106,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx8mm = {
102106
.formats = SNDRV_PCM_FMTBIT_S16_LE,
103107
.volume_sx = true,
104108
.fifo_offset = 0,
109+
.default_quality = QUALITY_VLOW0,
105110
};
106111

107112
static struct fsl_micfil_soc_data fsl_micfil_imx8mp = {
@@ -112,6 +117,8 @@ static struct fsl_micfil_soc_data fsl_micfil_imx8mp = {
112117
.formats = SNDRV_PCM_FMTBIT_S32_LE,
113118
.volume_sx = false,
114119
.fifo_offset = 0,
120+
.default_quality = QUALITY_MEDIUM,
121+
.rangeadj_const = {{27, 7}, {27, 7}, {26, 7}},
115122
};
116123

117124
static struct fsl_micfil_soc_data fsl_micfil_imx93 = {
@@ -124,6 +131,8 @@ static struct fsl_micfil_soc_data fsl_micfil_imx93 = {
124131
.use_verid = true,
125132
.volume_sx = false,
126133
.fifo_offset = 0,
134+
.default_quality = QUALITY_MEDIUM,
135+
.rangeadj_const = {{30, 6}, {30, 6}, {29, 6}},
127136
};
128137

129138
static struct fsl_micfil_soc_data fsl_micfil_imx943 = {
@@ -136,6 +145,8 @@ static struct fsl_micfil_soc_data fsl_micfil_imx943 = {
136145
.use_verid = true,
137146
.volume_sx = false,
138147
.fifo_offset = -4,
148+
.default_quality = QUALITY_MEDIUM,
149+
.rangeadj_const = {{34, 6}, {34, 6}, {33, 6}},
139150
};
140151

141152
static const struct of_device_id fsl_micfil_dt_ids[] = {
@@ -162,9 +173,69 @@ static const struct soc_enum fsl_micfil_quality_enum =
162173

163174
static DECLARE_TLV_DB_SCALE(gain_tlv, 0, 100, 0);
164175

176+
static int micfil_get_max_range(struct fsl_micfil *micfil)
177+
{
178+
int max_range;
179+
180+
switch (micfil->quality) {
181+
case QUALITY_HIGH:
182+
case QUALITY_VLOW0:
183+
max_range = micfil->soc->rangeadj_const[0][0] - micfil->soc->rangeadj_const[0][1] *
184+
ilog2(2 * MICFIL_OSR_DEFAULT);
185+
break;
186+
case QUALITY_MEDIUM:
187+
case QUALITY_VLOW1:
188+
max_range = micfil->soc->rangeadj_const[1][0] - micfil->soc->rangeadj_const[1][1] *
189+
ilog2(MICFIL_OSR_DEFAULT);
190+
break;
191+
case QUALITY_LOW:
192+
case QUALITY_VLOW2:
193+
max_range = micfil->soc->rangeadj_const[2][0] - micfil->soc->rangeadj_const[2][1] *
194+
ilog2(MICFIL_OSR_DEFAULT);
195+
break;
196+
default:
197+
return 0;
198+
}
199+
max_range = max_range < 0 ? 0 : max_range;
200+
201+
return max_range;
202+
}
203+
204+
static int micfil_range_set(struct snd_kcontrol *kcontrol,
205+
struct snd_ctl_elem_value *ucontrol)
206+
{
207+
struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
208+
struct fsl_micfil *micfil = snd_soc_component_get_drvdata(cmpnt);
209+
struct soc_mixer_control *mc =
210+
(struct soc_mixer_control *)kcontrol->private_value;
211+
unsigned int shift = mc->shift;
212+
int max_range, new_range;
213+
214+
new_range = ucontrol->value.integer.value[0];
215+
max_range = micfil_get_max_range(micfil);
216+
if (new_range > max_range)
217+
dev_warn(&micfil->pdev->dev, "range makes channel %d data unreliable\n", shift / 4);
218+
219+
regmap_update_bits(micfil->regmap, REG_MICFIL_OUT_CTRL, 0xF << shift, new_range << shift);
220+
221+
return 0;
222+
}
223+
165224
static int micfil_set_quality(struct fsl_micfil *micfil)
166225
{
167-
u32 qsel;
226+
int range, max_range;
227+
u32 qsel, val;
228+
int i;
229+
230+
if (!micfil->soc->volume_sx) {
231+
regmap_read(micfil->regmap, REG_MICFIL_OUT_CTRL, &val);
232+
max_range = micfil_get_max_range(micfil);
233+
for (i = 0; i < micfil->soc->fifos; i++) {
234+
range = (val >> MICFIL_OUTGAIN_CHX_SHIFT(i)) & 0xF;
235+
if (range > max_range)
236+
dev_warn(&micfil->pdev->dev, "please reset channel %d range\n", i);
237+
}
238+
}
168239

169240
switch (micfil->quality) {
170241
case QUALITY_HIGH:
@@ -362,23 +433,31 @@ static int hwvad_detected(struct snd_kcontrol *kcontrol,
362433
return 0;
363434
}
364435

365-
static const struct snd_kcontrol_new fsl_micfil_volume_controls[] = {
366-
SOC_SINGLE_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL,
367-
MICFIL_OUTGAIN_CHX_SHIFT(0), 0xF, 0, gain_tlv),
368-
SOC_SINGLE_TLV("CH1 Volume", REG_MICFIL_OUT_CTRL,
369-
MICFIL_OUTGAIN_CHX_SHIFT(1), 0xF, 0, gain_tlv),
370-
SOC_SINGLE_TLV("CH2 Volume", REG_MICFIL_OUT_CTRL,
371-
MICFIL_OUTGAIN_CHX_SHIFT(2), 0xF, 0, gain_tlv),
372-
SOC_SINGLE_TLV("CH3 Volume", REG_MICFIL_OUT_CTRL,
373-
MICFIL_OUTGAIN_CHX_SHIFT(3), 0xF, 0, gain_tlv),
374-
SOC_SINGLE_TLV("CH4 Volume", REG_MICFIL_OUT_CTRL,
375-
MICFIL_OUTGAIN_CHX_SHIFT(4), 0xF, 0, gain_tlv),
376-
SOC_SINGLE_TLV("CH5 Volume", REG_MICFIL_OUT_CTRL,
377-
MICFIL_OUTGAIN_CHX_SHIFT(5), 0xF, 0, gain_tlv),
378-
SOC_SINGLE_TLV("CH6 Volume", REG_MICFIL_OUT_CTRL,
379-
MICFIL_OUTGAIN_CHX_SHIFT(6), 0xF, 0, gain_tlv),
380-
SOC_SINGLE_TLV("CH7 Volume", REG_MICFIL_OUT_CTRL,
381-
MICFIL_OUTGAIN_CHX_SHIFT(7), 0xF, 0, gain_tlv),
436+
static const struct snd_kcontrol_new fsl_micfil_range_controls[] = {
437+
SOC_SINGLE_EXT("CH0 Range", REG_MICFIL_OUT_CTRL,
438+
MICFIL_OUTGAIN_CHX_SHIFT(0), 0xF, 0,
439+
snd_soc_get_volsw, micfil_range_set),
440+
SOC_SINGLE_EXT("CH1 Range", REG_MICFIL_OUT_CTRL,
441+
MICFIL_OUTGAIN_CHX_SHIFT(1), 0xF, 0,
442+
snd_soc_get_volsw, micfil_range_set),
443+
SOC_SINGLE_EXT("CH2 Range", REG_MICFIL_OUT_CTRL,
444+
MICFIL_OUTGAIN_CHX_SHIFT(2), 0xF, 0,
445+
snd_soc_get_volsw, micfil_range_set),
446+
SOC_SINGLE_EXT("CH3 Range", REG_MICFIL_OUT_CTRL,
447+
MICFIL_OUTGAIN_CHX_SHIFT(3), 0xF, 0,
448+
snd_soc_get_volsw, micfil_range_set),
449+
SOC_SINGLE_EXT("CH4 Range", REG_MICFIL_OUT_CTRL,
450+
MICFIL_OUTGAIN_CHX_SHIFT(4), 0xF, 0,
451+
snd_soc_get_volsw, micfil_range_set),
452+
SOC_SINGLE_EXT("CH5 Range", REG_MICFIL_OUT_CTRL,
453+
MICFIL_OUTGAIN_CHX_SHIFT(5), 0xF, 0,
454+
snd_soc_get_volsw, micfil_range_set),
455+
SOC_SINGLE_EXT("CH6 Range", REG_MICFIL_OUT_CTRL,
456+
MICFIL_OUTGAIN_CHX_SHIFT(6), 0xF, 0,
457+
snd_soc_get_volsw, micfil_range_set),
458+
SOC_SINGLE_EXT("CH7 Range", REG_MICFIL_OUT_CTRL,
459+
MICFIL_OUTGAIN_CHX_SHIFT(7), 0xF, 0,
460+
snd_soc_get_volsw, micfil_range_set),
382461
};
383462

384463
static const struct snd_kcontrol_new fsl_micfil_volume_sx_controls[] = {
@@ -890,13 +969,20 @@ static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai)
890969
struct fsl_micfil *micfil = dev_get_drvdata(cpu_dai->dev);
891970
struct device *dev = cpu_dai->dev;
892971
unsigned int val = 0;
893-
int ret, i;
972+
int ret, i, max_range;
894973

895-
micfil->quality = QUALITY_VLOW0;
974+
micfil->quality = micfil->soc->default_quality;
896975
micfil->card = cpu_dai->component->card;
897976

898977
/* set default gain to 2 */
899-
regmap_write(micfil->regmap, REG_MICFIL_OUT_CTRL, 0x22222222);
978+
if (micfil->soc->volume_sx) {
979+
regmap_write(micfil->regmap, REG_MICFIL_OUT_CTRL, 0x22222222);
980+
} else {
981+
max_range = micfil_get_max_range(micfil);
982+
for (i = 1; i < micfil->soc->fifos; i++)
983+
max_range |= max_range << 4;
984+
regmap_write(micfil->regmap, REG_MICFIL_OUT_CTRL, max_range);
985+
}
900986

901987
/* set DC Remover in bypass mode*/
902988
for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++)
@@ -930,8 +1016,8 @@ static int fsl_micfil_component_probe(struct snd_soc_component *component)
9301016
snd_soc_add_component_controls(component, fsl_micfil_volume_sx_controls,
9311017
ARRAY_SIZE(fsl_micfil_volume_sx_controls));
9321018
else
933-
snd_soc_add_component_controls(component, fsl_micfil_volume_controls,
934-
ARRAY_SIZE(fsl_micfil_volume_controls));
1019+
snd_soc_add_component_controls(component, fsl_micfil_range_controls,
1020+
ARRAY_SIZE(fsl_micfil_range_controls));
9351021

9361022
return 0;
9371023
}

0 commit comments

Comments
 (0)