Loading drivers/input/misc/arizona-haptics.c +9 −4 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ static void arizona_haptics_work(struct work_struct *work) struct arizona_haptics, work); struct arizona *arizona = haptics->arizona; struct snd_soc_component *component = snd_soc_dapm_to_component(arizona->dapm); int ret; if (!haptics->arizona->dapm) { Loading Loading @@ -66,7 +68,7 @@ static void arizona_haptics_work(struct work_struct *work) return; } ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS"); ret = snd_soc_component_enable_pin(component, "HAPTICS"); if (ret != 0) { dev_err(arizona->dev, "Failed to start HAPTICS: %d\n", ret); Loading @@ -81,7 +83,7 @@ static void arizona_haptics_work(struct work_struct *work) } } else { /* This disable sequence will be a noop if already enabled */ ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS"); ret = snd_soc_component_disable_pin(component, "HAPTICS"); if (ret != 0) { dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n", ret); Loading Loading @@ -140,11 +142,14 @@ static int arizona_haptics_play(struct input_dev *input, void *data, static void arizona_haptics_close(struct input_dev *input) { struct arizona_haptics *haptics = input_get_drvdata(input); struct snd_soc_component *component; cancel_work_sync(&haptics->work); if (haptics->arizona->dapm) snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS"); if (haptics->arizona->dapm) { component = snd_soc_dapm_to_component(haptics->arizona->dapm); snd_soc_component_disable_pin(component, "HAPTICS"); } } static int arizona_haptics_probe(struct platform_device *pdev) Loading sound/soc/codecs/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MAX98095 if I2C select SND_SOC_MAX98357A if GPIOLIB select SND_SOC_MAX98371 if I2C select SND_SOC_MAX98504 if I2C select SND_SOC_MAX9867 if I2C select SND_SOC_MAX98925 if I2C select SND_SOC_MAX98926 if I2C Loading sound/soc/codecs/nau8825.c +125 −17 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ #define GAIN_AUGMENT 22500 #define SIDETONE_BASE 207000 /* the maximum frequency of CLK_ADC and CLK_DAC */ #define CLK_DA_AD_MAX 6144000 static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, unsigned int freq); Loading Loading @@ -95,6 +97,27 @@ static const struct nau8825_fll_attr fll_pre_scalar[] = { { 8, 0x3 }, }; /* over sampling rate */ struct nau8825_osr_attr { unsigned int osr; unsigned int clk_src; }; static const struct nau8825_osr_attr osr_dac_sel[] = { { 64, 2 }, /* OSR 64, SRC 1/4 */ { 256, 0 }, /* OSR 256, SRC 1 */ { 128, 1 }, /* OSR 128, SRC 1/2 */ { 0, 0 }, { 32, 3 }, /* OSR 32, SRC 1/8 */ }; static const struct nau8825_osr_attr osr_adc_sel[] = { { 32, 3 }, /* OSR 32, SRC 1/8 */ { 64, 2 }, /* OSR 64, SRC 1/4 */ { 128, 1 }, /* OSR 128, SRC 1/2 */ { 256, 0 }, /* OSR 256, SRC 1 */ }; static const struct reg_default nau8825_reg_defaults[] = { { NAU8825_REG_ENA_CTRL, 0x00ff }, { NAU8825_REG_IIC_ADDR_SET, 0x0 }, Loading Loading @@ -1179,15 +1202,64 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = { {"HPOR", NULL, "Class G"}, }; static int nau8825_clock_check(struct nau8825 *nau8825, int stream, int rate, int osr) { int osrate; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { if (osr >= ARRAY_SIZE(osr_dac_sel)) return -EINVAL; osrate = osr_dac_sel[osr].osr; } else { if (osr >= ARRAY_SIZE(osr_adc_sel)) return -EINVAL; osrate = osr_adc_sel[osr].osr; } if (!osrate || rate * osr > CLK_DA_AD_MAX) { dev_err(nau8825->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n"); return -EINVAL; } return 0; } static int nau8825_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); unsigned int val_len = 0; unsigned int val_len = 0, osr; nau8825_sema_acquire(nau8825, 3 * HZ); nau8825_sema_acquire(nau8825, 2 * HZ); /* CLK_DAC or CLK_ADC = OSR * FS * DAC or ADC clock frequency is defined as Over Sampling Rate (OSR) * multiplied by the audio sample rate (Fs). Note that the OSR and Fs * values must be selected such that the maximum frequency is less * than 6.144 MHz. */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr); osr &= NAU8825_DAC_OVERSAMPLE_MASK; if (nau8825_clock_check(nau8825, substream->stream, params_rate(params), osr)) return -EINVAL; regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_DAC_SRC_MASK, osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT); } else { regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr); osr &= NAU8825_ADC_SYNC_DOWN_MASK; if (nau8825_clock_check(nau8825, substream->stream, params_rate(params), osr)) return -EINVAL; regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_ADC_SRC_MASK, osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT); } switch (params_width(params)) { case 16: Loading Loading @@ -1221,7 +1293,7 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); unsigned int ctrl1_val = 0, ctrl2_val = 0; nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: Loading Loading @@ -1774,9 +1846,10 @@ static void nau8825_init_regs(struct nau8825 *nau8825) * (audible hiss). Set it to something better. */ regmap_update_bits(regmap, NAU8825_REG_ADC_RATE, NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128); NAU8825_ADC_SYNC_DOWN_MASK | NAU8825_ADC_SINC4_EN, NAU8825_ADC_SYNC_DOWN_64); regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128); NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_64); /* Disable DACR/L power */ regmap_update_bits(regmap, NAU8825_REG_CHARGE_PUMP, NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL, Loading Loading @@ -1811,6 +1884,9 @@ static void nau8825_init_regs(struct nau8825 *nau8825) NAU8825_DACL_CH_SEL_MASK, NAU8825_DACL_CH_SEL_L); regmap_update_bits(nau8825->regmap, NAU8825_REG_DACR_CTRL, NAU8825_DACL_CH_SEL_MASK, NAU8825_DACL_CH_SEL_R); /* Disable short Frame Sync detection logic */ regmap_update_bits(regmap, NAU8825_REG_LEFT_TIME_SLOT, NAU8825_DIS_FS_SHORT_DET, NAU8825_DIS_FS_SHORT_DET); } static const struct regmap_config nau8825_regmap_config = { Loading Loading @@ -1919,8 +1995,10 @@ static void nau8825_fll_apply(struct nau8825 *nau8825, regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_SRC_MASK | NAU8825_CLK_MCLK_SRC_MASK, NAU8825_CLK_SRC_MCLK | fll_param->mclk_src); /* Make DSP operate at high speed for better performance. */ regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL1, NAU8825_FLL_RATIO_MASK, fll_param->ratio); NAU8825_FLL_RATIO_MASK | NAU8825_ICTRL_LATCH_MASK, fll_param->ratio | (0x6 << NAU8825_ICTRL_LATCH_SFT)); /* FLL 16-bit fractional input */ regmap_write(nau8825->regmap, NAU8825_REG_FLL2, fll_param->fll_frac); /* FLL 10-bit integer input */ Loading @@ -1936,19 +2014,22 @@ static void nau8825_fll_apply(struct nau8825 *nau8825, regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, 0); if (fll_param->fll_frac) { /* set FLL loop filter enable and cutoff frequency at 500Khz */ regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN | NAU8825_FLL_FTR_SW_MASK, NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN | NAU8825_FLL_FTR_SW_FILTER); regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, NAU8825_SDM_EN, NAU8825_SDM_EN); NAU8825_SDM_EN | NAU8825_CUTOFF500, NAU8825_SDM_EN | NAU8825_CUTOFF500); } else { /* disable FLL loop filter and cutoff frequency */ regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN | NAU8825_FLL_FTR_SW_MASK, NAU8825_FLL_FTR_SW_ACCU); regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, NAU8825_SDM_EN, 0); regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, NAU8825_SDM_EN | NAU8825_CUTOFF500, 0); } } Loading Loading @@ -2014,6 +2095,9 @@ static void nau8825_configure_mclk_as_sysclk(struct regmap *regmap) NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_MCLK); regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, 0); /* Make DSP operate as default setting for power saving. */ regmap_update_bits(regmap, NAU8825_REG_FLL1, NAU8825_ICTRL_LATCH_MASK, 0); } static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, Loading @@ -2038,7 +2122,7 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, * fered by cross talk process, the driver make the playback * preparation halted until cross talk process finish. */ nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); nau8825_configure_mclk_as_sysclk(regmap); /* MCLK not changed by clock tree */ regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, Loading @@ -2057,10 +2141,13 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, NAU8825_DCO_EN, NAU8825_DCO_EN); regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_VCO); /* Decrease the VCO frequency for power saving */ /* Decrease the VCO frequency and make DSP operate * as default setting for power saving. */ regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_MCLK_SRC_MASK, 0xf); regmap_update_bits(regmap, NAU8825_REG_FLL1, NAU8825_ICTRL_LATCH_MASK | NAU8825_FLL_RATIO_MASK, 0x10); regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_SDM_EN, NAU8825_SDM_EN); Loading @@ -2083,9 +2170,14 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, * fered by cross talk process, the driver make the playback * preparation halted until cross talk process finish. */ nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); /* Higher FLL reference input frequency can only set lower * gain error, such as 0000 for input reference from MCLK * 12.288Mhz. */ regmap_update_bits(regmap, NAU8825_REG_FLL3, NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_MCLK); NAU8825_FLL_CLK_SRC_MASK | NAU8825_GAIN_ERR_MASK, NAU8825_FLL_CLK_SRC_MCLK | 0); /* Release the semaphone. */ nau8825_sema_release(nau8825); Loading @@ -2100,9 +2192,17 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, * fered by cross talk process, the driver make the playback * preparation halted until cross talk process finish. */ nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); /* If FLL reference input is from low frequency source, * higher error gain can apply such as 0xf which has * the most sensitive gain error correction threshold, * Therefore, FLL has the most accurate DCO to * target frequency. */ regmap_update_bits(regmap, NAU8825_REG_FLL3, NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_BLK); NAU8825_FLL_CLK_SRC_MASK | NAU8825_GAIN_ERR_MASK, NAU8825_FLL_CLK_SRC_BLK | (0xf << NAU8825_GAIN_ERR_SFT)); /* Release the semaphone. */ nau8825_sema_release(nau8825); Loading @@ -2118,9 +2218,17 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, * fered by cross talk process, the driver make the playback * preparation halted until cross talk process finish. */ nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); /* If FLL reference input is from low frequency source, * higher error gain can apply such as 0xf which has * the most sensitive gain error correction threshold, * Therefore, FLL has the most accurate DCO to * target frequency. */ regmap_update_bits(regmap, NAU8825_REG_FLL3, NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_FS); NAU8825_FLL_CLK_SRC_MASK | NAU8825_GAIN_ERR_MASK, NAU8825_FLL_CLK_SRC_FS | (0xf << NAU8825_GAIN_ERR_SFT)); /* Release the semaphone. */ nau8825_sema_release(nau8825); Loading sound/soc/codecs/nau8825.h +16 −0 Original line number Diff line number Diff line Loading @@ -115,12 +115,20 @@ #define NAU8825_CLK_SRC_MASK (1 << NAU8825_CLK_SRC_SFT) #define NAU8825_CLK_SRC_VCO (1 << NAU8825_CLK_SRC_SFT) #define NAU8825_CLK_SRC_MCLK (0 << NAU8825_CLK_SRC_SFT) #define NAU8825_CLK_ADC_SRC_SFT 6 #define NAU8825_CLK_ADC_SRC_MASK (0x3 << NAU8825_CLK_ADC_SRC_SFT) #define NAU8825_CLK_DAC_SRC_SFT 4 #define NAU8825_CLK_DAC_SRC_MASK (0x3 << NAU8825_CLK_DAC_SRC_SFT) #define NAU8825_CLK_MCLK_SRC_MASK (0xf << 0) /* FLL1 (0x04) */ #define NAU8825_ICTRL_LATCH_SFT 10 #define NAU8825_ICTRL_LATCH_MASK (0x7 << NAU8825_ICTRL_LATCH_SFT) #define NAU8825_FLL_RATIO_MASK (0x7f << 0) /* FLL3 (0x06) */ #define NAU8825_GAIN_ERR_SFT 12 #define NAU8825_GAIN_ERR_MASK (0xf << NAU8825_GAIN_ERR_SFT) #define NAU8825_FLL_INTEGER_MASK (0x3ff << 0) #define NAU8825_FLL_CLK_SRC_SFT 10 #define NAU8825_FLL_CLK_SRC_MASK (0x3 << NAU8825_FLL_CLK_SRC_SFT) Loading @@ -144,6 +152,7 @@ /* FLL6 (0x9) */ #define NAU8825_DCO_EN (0x1 << 15) #define NAU8825_SDM_EN (0x1 << 14) #define NAU8825_CUTOFF500 (0x1 << 13) /* HSD_CTRL (0xc) */ #define NAU8825_HSD_AUTO_MODE (1 << 6) Loading Loading @@ -246,6 +255,11 @@ #define NAU8825_I2S_MS_SLAVE (0 << NAU8825_I2S_MS_SFT) #define NAU8825_I2S_BLK_DIV_MASK 0x7 /* LEFT_TIME_SLOT (0x1e) */ #define NAU8825_FS_ERR_CMP_SEL_SFT 14 #define NAU8825_FS_ERR_CMP_SEL_MASK (0x3 << NAU8825_FS_ERR_CMP_SEL_SFT) #define NAU8825_DIS_FS_SHORT_DET (1 << 13) /* BIQ_CTRL (0x20) */ #define NAU8825_BIQ_WRT_SFT 4 #define NAU8825_BIQ_WRT_EN (1 << NAU8825_BIQ_WRT_SFT) Loading @@ -255,6 +269,8 @@ #define NAU8825_BIQ_PATH_DAC (1 << NAU8825_BIQ_PATH_SFT) /* ADC_RATE (0x2b) */ #define NAU8825_ADC_SINC4_SFT 4 #define NAU8825_ADC_SINC4_EN (1 << NAU8825_ADC_SINC4_SFT) #define NAU8825_ADC_SYNC_DOWN_SFT 0 #define NAU8825_ADC_SYNC_DOWN_MASK 0x3 #define NAU8825_ADC_SYNC_DOWN_32 0 Loading Loading
drivers/input/misc/arizona-haptics.c +9 −4 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ static void arizona_haptics_work(struct work_struct *work) struct arizona_haptics, work); struct arizona *arizona = haptics->arizona; struct snd_soc_component *component = snd_soc_dapm_to_component(arizona->dapm); int ret; if (!haptics->arizona->dapm) { Loading Loading @@ -66,7 +68,7 @@ static void arizona_haptics_work(struct work_struct *work) return; } ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS"); ret = snd_soc_component_enable_pin(component, "HAPTICS"); if (ret != 0) { dev_err(arizona->dev, "Failed to start HAPTICS: %d\n", ret); Loading @@ -81,7 +83,7 @@ static void arizona_haptics_work(struct work_struct *work) } } else { /* This disable sequence will be a noop if already enabled */ ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS"); ret = snd_soc_component_disable_pin(component, "HAPTICS"); if (ret != 0) { dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n", ret); Loading Loading @@ -140,11 +142,14 @@ static int arizona_haptics_play(struct input_dev *input, void *data, static void arizona_haptics_close(struct input_dev *input) { struct arizona_haptics *haptics = input_get_drvdata(input); struct snd_soc_component *component; cancel_work_sync(&haptics->work); if (haptics->arizona->dapm) snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS"); if (haptics->arizona->dapm) { component = snd_soc_dapm_to_component(haptics->arizona->dapm); snd_soc_component_disable_pin(component, "HAPTICS"); } } static int arizona_haptics_probe(struct platform_device *pdev) Loading
sound/soc/codecs/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MAX98095 if I2C select SND_SOC_MAX98357A if GPIOLIB select SND_SOC_MAX98371 if I2C select SND_SOC_MAX98504 if I2C select SND_SOC_MAX9867 if I2C select SND_SOC_MAX98925 if I2C select SND_SOC_MAX98926 if I2C Loading
sound/soc/codecs/nau8825.c +125 −17 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ #define GAIN_AUGMENT 22500 #define SIDETONE_BASE 207000 /* the maximum frequency of CLK_ADC and CLK_DAC */ #define CLK_DA_AD_MAX 6144000 static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, unsigned int freq); Loading Loading @@ -95,6 +97,27 @@ static const struct nau8825_fll_attr fll_pre_scalar[] = { { 8, 0x3 }, }; /* over sampling rate */ struct nau8825_osr_attr { unsigned int osr; unsigned int clk_src; }; static const struct nau8825_osr_attr osr_dac_sel[] = { { 64, 2 }, /* OSR 64, SRC 1/4 */ { 256, 0 }, /* OSR 256, SRC 1 */ { 128, 1 }, /* OSR 128, SRC 1/2 */ { 0, 0 }, { 32, 3 }, /* OSR 32, SRC 1/8 */ }; static const struct nau8825_osr_attr osr_adc_sel[] = { { 32, 3 }, /* OSR 32, SRC 1/8 */ { 64, 2 }, /* OSR 64, SRC 1/4 */ { 128, 1 }, /* OSR 128, SRC 1/2 */ { 256, 0 }, /* OSR 256, SRC 1 */ }; static const struct reg_default nau8825_reg_defaults[] = { { NAU8825_REG_ENA_CTRL, 0x00ff }, { NAU8825_REG_IIC_ADDR_SET, 0x0 }, Loading Loading @@ -1179,15 +1202,64 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = { {"HPOR", NULL, "Class G"}, }; static int nau8825_clock_check(struct nau8825 *nau8825, int stream, int rate, int osr) { int osrate; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { if (osr >= ARRAY_SIZE(osr_dac_sel)) return -EINVAL; osrate = osr_dac_sel[osr].osr; } else { if (osr >= ARRAY_SIZE(osr_adc_sel)) return -EINVAL; osrate = osr_adc_sel[osr].osr; } if (!osrate || rate * osr > CLK_DA_AD_MAX) { dev_err(nau8825->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n"); return -EINVAL; } return 0; } static int nau8825_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); unsigned int val_len = 0; unsigned int val_len = 0, osr; nau8825_sema_acquire(nau8825, 3 * HZ); nau8825_sema_acquire(nau8825, 2 * HZ); /* CLK_DAC or CLK_ADC = OSR * FS * DAC or ADC clock frequency is defined as Over Sampling Rate (OSR) * multiplied by the audio sample rate (Fs). Note that the OSR and Fs * values must be selected such that the maximum frequency is less * than 6.144 MHz. */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr); osr &= NAU8825_DAC_OVERSAMPLE_MASK; if (nau8825_clock_check(nau8825, substream->stream, params_rate(params), osr)) return -EINVAL; regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_DAC_SRC_MASK, osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT); } else { regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr); osr &= NAU8825_ADC_SYNC_DOWN_MASK; if (nau8825_clock_check(nau8825, substream->stream, params_rate(params), osr)) return -EINVAL; regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_ADC_SRC_MASK, osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT); } switch (params_width(params)) { case 16: Loading Loading @@ -1221,7 +1293,7 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); unsigned int ctrl1_val = 0, ctrl2_val = 0; nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: Loading Loading @@ -1774,9 +1846,10 @@ static void nau8825_init_regs(struct nau8825 *nau8825) * (audible hiss). Set it to something better. */ regmap_update_bits(regmap, NAU8825_REG_ADC_RATE, NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128); NAU8825_ADC_SYNC_DOWN_MASK | NAU8825_ADC_SINC4_EN, NAU8825_ADC_SYNC_DOWN_64); regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128); NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_64); /* Disable DACR/L power */ regmap_update_bits(regmap, NAU8825_REG_CHARGE_PUMP, NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL, Loading Loading @@ -1811,6 +1884,9 @@ static void nau8825_init_regs(struct nau8825 *nau8825) NAU8825_DACL_CH_SEL_MASK, NAU8825_DACL_CH_SEL_L); regmap_update_bits(nau8825->regmap, NAU8825_REG_DACR_CTRL, NAU8825_DACL_CH_SEL_MASK, NAU8825_DACL_CH_SEL_R); /* Disable short Frame Sync detection logic */ regmap_update_bits(regmap, NAU8825_REG_LEFT_TIME_SLOT, NAU8825_DIS_FS_SHORT_DET, NAU8825_DIS_FS_SHORT_DET); } static const struct regmap_config nau8825_regmap_config = { Loading Loading @@ -1919,8 +1995,10 @@ static void nau8825_fll_apply(struct nau8825 *nau8825, regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_SRC_MASK | NAU8825_CLK_MCLK_SRC_MASK, NAU8825_CLK_SRC_MCLK | fll_param->mclk_src); /* Make DSP operate at high speed for better performance. */ regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL1, NAU8825_FLL_RATIO_MASK, fll_param->ratio); NAU8825_FLL_RATIO_MASK | NAU8825_ICTRL_LATCH_MASK, fll_param->ratio | (0x6 << NAU8825_ICTRL_LATCH_SFT)); /* FLL 16-bit fractional input */ regmap_write(nau8825->regmap, NAU8825_REG_FLL2, fll_param->fll_frac); /* FLL 10-bit integer input */ Loading @@ -1936,19 +2014,22 @@ static void nau8825_fll_apply(struct nau8825 *nau8825, regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, 0); if (fll_param->fll_frac) { /* set FLL loop filter enable and cutoff frequency at 500Khz */ regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN | NAU8825_FLL_FTR_SW_MASK, NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN | NAU8825_FLL_FTR_SW_FILTER); regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, NAU8825_SDM_EN, NAU8825_SDM_EN); NAU8825_SDM_EN | NAU8825_CUTOFF500, NAU8825_SDM_EN | NAU8825_CUTOFF500); } else { /* disable FLL loop filter and cutoff frequency */ regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN | NAU8825_FLL_FTR_SW_MASK, NAU8825_FLL_FTR_SW_ACCU); regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, NAU8825_SDM_EN, 0); regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, NAU8825_SDM_EN | NAU8825_CUTOFF500, 0); } } Loading Loading @@ -2014,6 +2095,9 @@ static void nau8825_configure_mclk_as_sysclk(struct regmap *regmap) NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_MCLK); regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, 0); /* Make DSP operate as default setting for power saving. */ regmap_update_bits(regmap, NAU8825_REG_FLL1, NAU8825_ICTRL_LATCH_MASK, 0); } static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, Loading @@ -2038,7 +2122,7 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, * fered by cross talk process, the driver make the playback * preparation halted until cross talk process finish. */ nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); nau8825_configure_mclk_as_sysclk(regmap); /* MCLK not changed by clock tree */ regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, Loading @@ -2057,10 +2141,13 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, NAU8825_DCO_EN, NAU8825_DCO_EN); regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_VCO); /* Decrease the VCO frequency for power saving */ /* Decrease the VCO frequency and make DSP operate * as default setting for power saving. */ regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_MCLK_SRC_MASK, 0xf); regmap_update_bits(regmap, NAU8825_REG_FLL1, NAU8825_ICTRL_LATCH_MASK | NAU8825_FLL_RATIO_MASK, 0x10); regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_SDM_EN, NAU8825_SDM_EN); Loading @@ -2083,9 +2170,14 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, * fered by cross talk process, the driver make the playback * preparation halted until cross talk process finish. */ nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); /* Higher FLL reference input frequency can only set lower * gain error, such as 0000 for input reference from MCLK * 12.288Mhz. */ regmap_update_bits(regmap, NAU8825_REG_FLL3, NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_MCLK); NAU8825_FLL_CLK_SRC_MASK | NAU8825_GAIN_ERR_MASK, NAU8825_FLL_CLK_SRC_MCLK | 0); /* Release the semaphone. */ nau8825_sema_release(nau8825); Loading @@ -2100,9 +2192,17 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, * fered by cross talk process, the driver make the playback * preparation halted until cross talk process finish. */ nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); /* If FLL reference input is from low frequency source, * higher error gain can apply such as 0xf which has * the most sensitive gain error correction threshold, * Therefore, FLL has the most accurate DCO to * target frequency. */ regmap_update_bits(regmap, NAU8825_REG_FLL3, NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_BLK); NAU8825_FLL_CLK_SRC_MASK | NAU8825_GAIN_ERR_MASK, NAU8825_FLL_CLK_SRC_BLK | (0xf << NAU8825_GAIN_ERR_SFT)); /* Release the semaphone. */ nau8825_sema_release(nau8825); Loading @@ -2118,9 +2218,17 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, * fered by cross talk process, the driver make the playback * preparation halted until cross talk process finish. */ nau8825_sema_acquire(nau8825, 2 * HZ); nau8825_sema_acquire(nau8825, 3 * HZ); /* If FLL reference input is from low frequency source, * higher error gain can apply such as 0xf which has * the most sensitive gain error correction threshold, * Therefore, FLL has the most accurate DCO to * target frequency. */ regmap_update_bits(regmap, NAU8825_REG_FLL3, NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_FS); NAU8825_FLL_CLK_SRC_MASK | NAU8825_GAIN_ERR_MASK, NAU8825_FLL_CLK_SRC_FS | (0xf << NAU8825_GAIN_ERR_SFT)); /* Release the semaphone. */ nau8825_sema_release(nau8825); Loading
sound/soc/codecs/nau8825.h +16 −0 Original line number Diff line number Diff line Loading @@ -115,12 +115,20 @@ #define NAU8825_CLK_SRC_MASK (1 << NAU8825_CLK_SRC_SFT) #define NAU8825_CLK_SRC_VCO (1 << NAU8825_CLK_SRC_SFT) #define NAU8825_CLK_SRC_MCLK (0 << NAU8825_CLK_SRC_SFT) #define NAU8825_CLK_ADC_SRC_SFT 6 #define NAU8825_CLK_ADC_SRC_MASK (0x3 << NAU8825_CLK_ADC_SRC_SFT) #define NAU8825_CLK_DAC_SRC_SFT 4 #define NAU8825_CLK_DAC_SRC_MASK (0x3 << NAU8825_CLK_DAC_SRC_SFT) #define NAU8825_CLK_MCLK_SRC_MASK (0xf << 0) /* FLL1 (0x04) */ #define NAU8825_ICTRL_LATCH_SFT 10 #define NAU8825_ICTRL_LATCH_MASK (0x7 << NAU8825_ICTRL_LATCH_SFT) #define NAU8825_FLL_RATIO_MASK (0x7f << 0) /* FLL3 (0x06) */ #define NAU8825_GAIN_ERR_SFT 12 #define NAU8825_GAIN_ERR_MASK (0xf << NAU8825_GAIN_ERR_SFT) #define NAU8825_FLL_INTEGER_MASK (0x3ff << 0) #define NAU8825_FLL_CLK_SRC_SFT 10 #define NAU8825_FLL_CLK_SRC_MASK (0x3 << NAU8825_FLL_CLK_SRC_SFT) Loading @@ -144,6 +152,7 @@ /* FLL6 (0x9) */ #define NAU8825_DCO_EN (0x1 << 15) #define NAU8825_SDM_EN (0x1 << 14) #define NAU8825_CUTOFF500 (0x1 << 13) /* HSD_CTRL (0xc) */ #define NAU8825_HSD_AUTO_MODE (1 << 6) Loading Loading @@ -246,6 +255,11 @@ #define NAU8825_I2S_MS_SLAVE (0 << NAU8825_I2S_MS_SFT) #define NAU8825_I2S_BLK_DIV_MASK 0x7 /* LEFT_TIME_SLOT (0x1e) */ #define NAU8825_FS_ERR_CMP_SEL_SFT 14 #define NAU8825_FS_ERR_CMP_SEL_MASK (0x3 << NAU8825_FS_ERR_CMP_SEL_SFT) #define NAU8825_DIS_FS_SHORT_DET (1 << 13) /* BIQ_CTRL (0x20) */ #define NAU8825_BIQ_WRT_SFT 4 #define NAU8825_BIQ_WRT_EN (1 << NAU8825_BIQ_WRT_SFT) Loading @@ -255,6 +269,8 @@ #define NAU8825_BIQ_PATH_DAC (1 << NAU8825_BIQ_PATH_SFT) /* ADC_RATE (0x2b) */ #define NAU8825_ADC_SINC4_SFT 4 #define NAU8825_ADC_SINC4_EN (1 << NAU8825_ADC_SINC4_SFT) #define NAU8825_ADC_SYNC_DOWN_SFT 0 #define NAU8825_ADC_SYNC_DOWN_MASK 0x3 #define NAU8825_ADC_SYNC_DOWN_32 0 Loading