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
98101static 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
120124static 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
133138static 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
146152static const struct of_device_id fsl_micfil_dt_ids [] = {
@@ -167,9 +173,69 @@ static const struct soc_enum fsl_micfil_quality_enum =
167173
168174static 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+
170224static 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
389463static 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