Skip to content

Commit ef1a7e0

Browse files
Chancel Liubroonie
authored andcommitted
ASoC: fsl_micfil: Set channel range control
The range control register can't directly adjust volume gain according to specification. It's the dynamic range of the CIC filter. The range value should meet some conditions otherwise the channel data is not reliable. Add an array in soc data to store const value in formula with which range with all quality on different platforms can be calculated. If the value set to range control exceeds the max range there'll be warning logs. Signed-off-by: Chancel Liu <chancel.liu@nxp.com> Acked-by: Shengjiu Wang <shengjiu.wang@gmail.com> Link: https://patch.msgid.link/20251127022652.674574-3-chancel.liu@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent e04aab9 commit ef1a7e0

1 file changed

Lines changed: 103 additions & 22 deletions

File tree

sound/soc/fsl/fsl_micfil.c

Lines changed: 103 additions & 22 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>
@@ -93,6 +94,8 @@ struct fsl_micfil_soc_data {
9394
u64 formats;
9495
int fifo_offset;
9596
enum quality default_quality;
97+
/* stores const value in formula to calculate range */
98+
int rangeadj_const[3][2];
9699
};
97100

98101
static struct fsl_micfil_soc_data fsl_micfil_imx8mm = {
@@ -115,6 +118,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx8mp = {
115118
.volume_sx = false,
116119
.fifo_offset = 0,
117120
.default_quality = QUALITY_MEDIUM,
121+
.rangeadj_const = {{27, 7}, {27, 7}, {26, 7}},
118122
};
119123

120124
static struct fsl_micfil_soc_data fsl_micfil_imx93 = {
@@ -128,6 +132,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx93 = {
128132
.volume_sx = false,
129133
.fifo_offset = 0,
130134
.default_quality = QUALITY_MEDIUM,
135+
.rangeadj_const = {{30, 6}, {30, 6}, {29, 6}},
131136
};
132137

133138
static struct fsl_micfil_soc_data fsl_micfil_imx943 = {
@@ -141,6 +146,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx943 = {
141146
.volume_sx = false,
142147
.fifo_offset = -4,
143148
.default_quality = QUALITY_MEDIUM,
149+
.rangeadj_const = {{34, 6}, {34, 6}, {33, 6}},
144150
};
145151

146152
static const struct of_device_id fsl_micfil_dt_ids[] = {
@@ -167,9 +173,69 @@ static const struct soc_enum fsl_micfil_quality_enum =
167173

168174
static DECLARE_TLV_DB_SCALE(gain_tlv, 0, 100, 0);
169175

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+
170224
static int micfil_set_quality(struct fsl_micfil *micfil)
171225
{
172-
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+
}
173239

174240
switch (micfil->quality) {
175241
case QUALITY_HIGH:
@@ -367,23 +433,31 @@ static int hwvad_detected(struct snd_kcontrol *kcontrol,
367433
return 0;
368434
}
369435

370-
static const struct snd_kcontrol_new fsl_micfil_volume_controls[] = {
371-
SOC_SINGLE_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL,
372-
MICFIL_OUTGAIN_CHX_SHIFT(0), 0xF, 0, gain_tlv),
373-
SOC_SINGLE_TLV("CH1 Volume", REG_MICFIL_OUT_CTRL,
374-
MICFIL_OUTGAIN_CHX_SHIFT(1), 0xF, 0, gain_tlv),
375-
SOC_SINGLE_TLV("CH2 Volume", REG_MICFIL_OUT_CTRL,
376-
MICFIL_OUTGAIN_CHX_SHIFT(2), 0xF, 0, gain_tlv),
377-
SOC_SINGLE_TLV("CH3 Volume", REG_MICFIL_OUT_CTRL,
378-
MICFIL_OUTGAIN_CHX_SHIFT(3), 0xF, 0, gain_tlv),
379-
SOC_SINGLE_TLV("CH4 Volume", REG_MICFIL_OUT_CTRL,
380-
MICFIL_OUTGAIN_CHX_SHIFT(4), 0xF, 0, gain_tlv),
381-
SOC_SINGLE_TLV("CH5 Volume", REG_MICFIL_OUT_CTRL,
382-
MICFIL_OUTGAIN_CHX_SHIFT(5), 0xF, 0, gain_tlv),
383-
SOC_SINGLE_TLV("CH6 Volume", REG_MICFIL_OUT_CTRL,
384-
MICFIL_OUTGAIN_CHX_SHIFT(6), 0xF, 0, gain_tlv),
385-
SOC_SINGLE_TLV("CH7 Volume", REG_MICFIL_OUT_CTRL,
386-
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),
387461
};
388462

389463
static const struct snd_kcontrol_new fsl_micfil_volume_sx_controls[] = {
@@ -895,13 +969,20 @@ static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai)
895969
struct fsl_micfil *micfil = dev_get_drvdata(cpu_dai->dev);
896970
struct device *dev = cpu_dai->dev;
897971
unsigned int val = 0;
898-
int ret, i;
972+
int ret, i, max_range;
899973

900974
micfil->quality = micfil->soc->default_quality;
901975
micfil->card = cpu_dai->component->card;
902976

903977
/* set default gain to 2 */
904-
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+
}
905986

906987
/* set DC Remover in bypass mode*/
907988
for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++)
@@ -935,8 +1016,8 @@ static int fsl_micfil_component_probe(struct snd_soc_component *component)
9351016
snd_soc_add_component_controls(component, fsl_micfil_volume_sx_controls,
9361017
ARRAY_SIZE(fsl_micfil_volume_sx_controls));
9371018
else
938-
snd_soc_add_component_controls(component, fsl_micfil_volume_controls,
939-
ARRAY_SIZE(fsl_micfil_volume_controls));
1019+
snd_soc_add_component_controls(component, fsl_micfil_range_controls,
1020+
ARRAY_SIZE(fsl_micfil_range_controls));
9401021

9411022
return 0;
9421023
}

0 commit comments

Comments
 (0)