@@ -670,36 +670,49 @@ static const struct snd_soc_dapm_route nau8821_dapm_routes[] = {
670
670
{"HPOR" , NULL , "Class G" },
671
671
};
672
672
673
- static int nau8821_clock_check ( struct nau8821 * nau8821 ,
674
- int stream , int rate , int osr )
673
+ static const struct nau8821_osr_attr *
674
+ nau8821_get_osr ( struct nau8821 * nau8821 , int stream )
675
675
{
676
- int osrate = 0 ;
676
+ unsigned int osr ;
677
677
678
678
if (stream == SNDRV_PCM_STREAM_PLAYBACK ) {
679
+ regmap_read (nau8821 -> regmap , NAU8821_R2C_DAC_CTRL1 , & osr );
680
+ osr &= NAU8821_DAC_OVERSAMPLE_MASK ;
679
681
if (osr >= ARRAY_SIZE (osr_dac_sel ))
680
- return - EINVAL ;
681
- osrate = osr_dac_sel [osr ]. osr ;
682
+ return NULL ;
683
+ return & osr_dac_sel [osr ];
682
684
} else {
685
+ regmap_read (nau8821 -> regmap , NAU8821_R2B_ADC_RATE , & osr );
686
+ osr &= NAU8821_ADC_SYNC_DOWN_MASK ;
683
687
if (osr >= ARRAY_SIZE (osr_adc_sel ))
684
- return - EINVAL ;
685
- osrate = osr_adc_sel [osr ]. osr ;
688
+ return NULL ;
689
+ return & osr_adc_sel [osr ];
686
690
}
691
+ }
687
692
688
- if (!osrate || rate * osrate > CLK_DA_AD_MAX ) {
689
- dev_err (nau8821 -> dev ,
690
- "exceed the maximum frequency of CLK_ADC or CLK_DAC" );
693
+ static int nau8821_dai_startup (struct snd_pcm_substream * substream ,
694
+ struct snd_soc_dai * dai )
695
+ {
696
+ struct snd_soc_component * component = dai -> component ;
697
+ struct nau8821 * nau8821 = snd_soc_component_get_drvdata (component );
698
+ const struct nau8821_osr_attr * osr ;
699
+
700
+ osr = nau8821_get_osr (nau8821 , substream -> stream );
701
+ if (!osr || !osr -> osr )
691
702
return - EINVAL ;
692
- }
693
703
694
- return 0 ;
704
+ return snd_pcm_hw_constraint_minmax (substream -> runtime ,
705
+ SNDRV_PCM_HW_PARAM_RATE ,
706
+ 0 , CLK_DA_AD_MAX / osr -> osr );
695
707
}
696
708
697
709
static int nau8821_hw_params (struct snd_pcm_substream * substream ,
698
710
struct snd_pcm_hw_params * params , struct snd_soc_dai * dai )
699
711
{
700
712
struct snd_soc_component * component = dai -> component ;
701
713
struct nau8821 * nau8821 = snd_soc_component_get_drvdata (component );
702
- unsigned int val_len = 0 , osr , ctrl_val , bclk_fs , clk_div ;
714
+ unsigned int val_len = 0 , ctrl_val , bclk_fs , clk_div ;
715
+ const struct nau8821_osr_attr * osr ;
703
716
704
717
nau8821 -> fs = params_rate (params );
705
718
/* CLK_DAC or CLK_ADC = OSR * FS
@@ -708,27 +721,19 @@ static int nau8821_hw_params(struct snd_pcm_substream *substream,
708
721
* values must be selected such that the maximum frequency is less
709
722
* than 6.144 MHz.
710
723
*/
711
- if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK ) {
712
- regmap_read (nau8821 -> regmap , NAU8821_R2C_DAC_CTRL1 , & osr );
713
- osr &= NAU8821_DAC_OVERSAMPLE_MASK ;
714
- if (nau8821_clock_check (nau8821 , substream -> stream ,
715
- nau8821 -> fs , osr )) {
716
- return - EINVAL ;
717
- }
724
+ osr = nau8821_get_osr (nau8821 , substream -> stream );
725
+ if (!osr || !osr -> osr )
726
+ return - EINVAL ;
727
+ if (nau8821 -> fs * osr -> osr > CLK_DA_AD_MAX )
728
+ return - EINVAL ;
729
+ if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK )
718
730
regmap_update_bits (nau8821 -> regmap , NAU8821_R03_CLK_DIVIDER ,
719
731
NAU8821_CLK_DAC_SRC_MASK ,
720
- osr_dac_sel [osr ].clk_src << NAU8821_CLK_DAC_SRC_SFT );
721
- } else {
722
- regmap_read (nau8821 -> regmap , NAU8821_R2B_ADC_RATE , & osr );
723
- osr &= NAU8821_ADC_SYNC_DOWN_MASK ;
724
- if (nau8821_clock_check (nau8821 , substream -> stream ,
725
- nau8821 -> fs , osr )) {
726
- return - EINVAL ;
727
- }
732
+ osr -> clk_src << NAU8821_CLK_DAC_SRC_SFT );
733
+ else
728
734
regmap_update_bits (nau8821 -> regmap , NAU8821_R03_CLK_DIVIDER ,
729
735
NAU8821_CLK_ADC_SRC_MASK ,
730
- osr_adc_sel [osr ].clk_src << NAU8821_CLK_ADC_SRC_SFT );
731
- }
736
+ osr -> clk_src << NAU8821_CLK_ADC_SRC_SFT );
732
737
733
738
/* make BCLK and LRC divde configuration if the codec as master. */
734
739
regmap_read (nau8821 -> regmap , NAU8821_R1D_I2S_PCM_CTRL2 , & ctrl_val );
@@ -843,6 +848,7 @@ static int nau8821_digital_mute(struct snd_soc_dai *dai, int mute,
843
848
}
844
849
845
850
static const struct snd_soc_dai_ops nau8821_dai_ops = {
851
+ .startup = nau8821_dai_startup ,
846
852
.hw_params = nau8821_hw_params ,
847
853
.set_fmt = nau8821_set_dai_fmt ,
848
854
.mute_stream = nau8821_digital_mute ,
0 commit comments