Loading Documentation/devicetree/bindings/sound/max98090.txt +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ Optional properties: - clock-names: Should be "mclk" - maxim,dmic-freq: Frequency at which to clock DMIC Pins on the device (for linking into audio routes): * MIC1 Loading sound/soc/codecs/max98088.c +4 −27 Original line number Diff line number Diff line Loading @@ -875,7 +875,7 @@ static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = { static int max98088_mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); switch (event) { Loading Loading @@ -905,7 +905,7 @@ static int max98088_mic_event(struct snd_soc_dapm_widget *w, static int max98088_line_pga(struct snd_soc_dapm_widget *w, int event, int line, u8 channel) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); u8 *state; Loading Loading @@ -1887,25 +1887,6 @@ static void max98088_handle_pdata(struct snd_soc_codec *codec) max98088_handle_eq_pdata(codec); } #ifdef CONFIG_PM static int max98088_suspend(struct snd_soc_codec *codec) { max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } static int max98088_resume(struct snd_soc_codec *codec) { max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } #else #define max98088_suspend NULL #define max98088_resume NULL #endif static int max98088_probe(struct snd_soc_codec *codec) { struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); Loading Loading @@ -1946,9 +1927,6 @@ static int max98088_probe(struct snd_soc_codec *codec) snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); /* initialize registers cache to hardware default */ max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00); snd_soc_write(codec, M98088_REG_22_MIX_DAC, Loading @@ -1974,7 +1952,6 @@ static int max98088_remove(struct snd_soc_codec *codec) { struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); kfree(max98088->eq_texts); return 0; Loading @@ -1983,9 +1960,9 @@ static int max98088_remove(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_max98088 = { .probe = max98088_probe, .remove = max98088_remove, .suspend = max98088_suspend, .resume = max98088_resume, .set_bias_level = max98088_set_bias_level, .suspend_bias_off = true, .controls = max98088_snd_controls, .num_controls = ARRAY_SIZE(max98088_snd_controls), .dapm_widgets = max98088_dapm_widgets, Loading sound/soc/codecs/max98090.c +154 −37 Original line number Diff line number Diff line Loading @@ -806,7 +806,7 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = { static int max98090_micinput_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); unsigned int val = snd_soc_read(codec, w->reg); Loading Loading @@ -1828,27 +1828,155 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, return 0; } static const int comp_pclk_rates[] = { 11289600, 12288000, 12000000, 13000000, 19200000 }; static const int dmic_micclk[] = { 2, 2, 2, 2, 4, 2 }; static const int dmic_divisors[] = { 2, 3, 4, 5, 6, 8 }; static const int comp_lrclk_rates[] = { 8000, 16000, 32000, 44100, 48000, 96000 }; static const int dmic_comp[6][6] = { {7, 8, 3, 3, 3, 3}, {7, 8, 3, 3, 3, 3}, {7, 8, 3, 3, 3, 3}, {7, 8, 3, 1, 1, 1}, {7, 8, 3, 1, 2, 2}, {7, 8, 3, 3, 3, 3} struct dmic_table { int pclk; struct { int freq; int comp[6]; /* One each for 8, 16, 32, 44.1, 48, and 96 kHz */ } settings[6]; /* One for each dmic divisor. */ }; static const struct dmic_table dmic_table[] = { /* One for each pclk freq. */ { .pclk = 11289600, .settings = { { .freq = 2, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 1, .comp = { 7, 8, 2, 2, 2, 2 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 6, 6, 6, 6 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, }, }, { .pclk = 12000000, .settings = { { .freq = 2, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 1, .comp = { 7, 8, 2, 2, 2, 2 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 5, 5, 6, 6 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, } }, { .pclk = 12288000, .settings = { { .freq = 2, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 1, .comp = { 7, 8, 2, 2, 2, 2 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 6, 6, 6, 6 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, } }, { .pclk = 13000000, .settings = { { .freq = 2, .comp = { 7, 8, 1, 1, 1, 1 } }, { .freq = 1, .comp = { 7, 8, 0, 0, 0, 0 } }, { .freq = 0, .comp = { 7, 8, 1, 1, 1, 1 } }, { .freq = 0, .comp = { 7, 8, 4, 4, 5, 5 } }, { .freq = 0, .comp = { 7, 8, 1, 1, 1, 1 } }, { .freq = 0, .comp = { 7, 8, 1, 1, 1, 1 } }, } }, { .pclk = 19200000, .settings = { { .freq = 2, .comp = { 0, 0, 0, 0, 0, 0 } }, { .freq = 1, .comp = { 7, 8, 1, 1, 1, 1 } }, { .freq = 0, .comp = { 7, 8, 5, 5, 6, 6 } }, { .freq = 0, .comp = { 7, 8, 2, 2, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 1, 1, 2, 2 } }, { .freq = 0, .comp = { 7, 8, 5, 5, 6, 6 } }, } }, }; static int max98090_find_divisor(int target_freq, int pclk) { int current_diff = INT_MAX; int test_diff = INT_MAX; int divisor_index = 0; int i; for (i = 0; i < ARRAY_SIZE(dmic_divisors); i++) { test_diff = abs(target_freq - (pclk / dmic_divisors[i])); if (test_diff < current_diff) { current_diff = test_diff; divisor_index = i; } } return divisor_index; } static int max98090_find_closest_pclk(int pclk) { int m1; int m2; int i; for (i = 0; i < ARRAY_SIZE(dmic_table); i++) { if (pclk == dmic_table[i].pclk) return i; if (pclk < dmic_table[i].pclk) { if (i == 0) return i; m1 = pclk - dmic_table[i-1].pclk; m2 = dmic_table[i].pclk - pclk; if (m1 < m2) return i - 1; else return i; } } return -EINVAL; } static int max98090_configure_dmic(struct max98090_priv *max98090, int target_dmic_clk, int pclk, int fs) { int micclk_index; int pclk_index; int dmic_freq; int dmic_comp; int i; pclk_index = max98090_find_closest_pclk(pclk); if (pclk_index < 0) return pclk_index; micclk_index = max98090_find_divisor(target_dmic_clk, pclk); for (i = 0; i < ARRAY_SIZE(comp_lrclk_rates) - 1; i++) { if (fs <= (comp_lrclk_rates[i] + comp_lrclk_rates[i+1]) / 2) break; } dmic_freq = dmic_table[pclk_index].settings[micclk_index].freq; dmic_comp = dmic_table[pclk_index].settings[micclk_index].comp[i]; regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_ENABLE, M98090_MICCLK_MASK, micclk_index << M98090_MICCLK_SHIFT); regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_CONFIG, M98090_DMIC_COMP_MASK | M98090_DMIC_FREQ_MASK, dmic_comp << M98090_DMIC_COMP_SHIFT | dmic_freq << M98090_DMIC_FREQ_SHIFT); return 0; } static int max98090_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) Loading @@ -1856,7 +1984,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); struct max98090_cdata *cdata; int i, j; cdata = &max98090->dai[0]; max98090->bclk = snd_soc_params_to_bclk(params); Loading Loading @@ -1895,27 +2022,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, snd_soc_update_bits(codec, M98090_REG_FILTER_CONFIG, M98090_DHF_MASK, M98090_DHF_MASK); /* Check for supported PCLK to LRCLK ratios */ for (j = 0; j < ARRAY_SIZE(comp_pclk_rates); j++) { if (comp_pclk_rates[j] == max98090->sysclk) { break; } } for (i = 0; i < ARRAY_SIZE(comp_lrclk_rates) - 1; i++) { if (max98090->lrclk <= (comp_lrclk_rates[i] + comp_lrclk_rates[i + 1]) / 2) { break; } } snd_soc_update_bits(codec, M98090_REG_DIGITAL_MIC_ENABLE, M98090_MICCLK_MASK, dmic_micclk[j] << M98090_MICCLK_SHIFT); snd_soc_update_bits(codec, M98090_REG_DIGITAL_MIC_CONFIG, M98090_DMIC_COMP_MASK, dmic_comp[j][i] << M98090_DMIC_COMP_SHIFT); max98090_configure_dmic(max98090, max98090->dmic_freq, max98090->pclk, max98090->lrclk); return 0; } Loading Loading @@ -1946,12 +2054,15 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, if ((freq >= 10000000) && (freq <= 20000000)) { snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, M98090_PSCLK_DIV1); max98090->pclk = freq; } else if ((freq > 20000000) && (freq <= 40000000)) { snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, M98090_PSCLK_DIV2); max98090->pclk = freq >> 1; } else if ((freq > 40000000) && (freq <= 60000000)) { snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, M98090_PSCLK_DIV4); max98090->pclk = freq >> 2; } else { dev_err(codec->dev, "Invalid master clock frequency\n"); return -EINVAL; Loading Loading @@ -2326,6 +2437,7 @@ static int max98090_probe(struct snd_soc_codec *codec) /* Initialize private data */ max98090->sysclk = (unsigned)-1; max98090->pclk = (unsigned)-1; max98090->master = false; cdata = &max98090->dai[0]; Loading Loading @@ -2465,6 +2577,11 @@ static int max98090_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, max98090); max98090->pdata = i2c->dev.platform_data; ret = of_property_read_u32(i2c->dev.of_node, "maxim,dmic-freq", &max98090->dmic_freq); if (ret < 0) max98090->dmic_freq = MAX98090_DEFAULT_DMIC_FREQ; max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap); if (IS_ERR(max98090->regmap)) { ret = PTR_ERR(max98090->regmap); Loading sound/soc/codecs/max98090.h +8 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,12 @@ #ifndef _MAX98090_H #define _MAX98090_H /* * The default operating frequency for a DMIC attached to the codec. * This can be overridden by a device tree property. */ #define MAX98090_DEFAULT_DMIC_FREQ 2500000 /* * MAX98090 Register Definitions */ Loading Loading @@ -1518,8 +1524,10 @@ struct max98090_priv { struct max98090_pdata *pdata; struct clk *mclk; unsigned int sysclk; unsigned int pclk; unsigned int bclk; unsigned int lrclk; u32 dmic_freq; struct max98090_cdata dai[1]; int jack_state; struct delayed_work jack_work; Loading sound/soc/codecs/max98095.c +3 −8 Original line number Diff line number Diff line Loading @@ -866,7 +866,7 @@ static const struct snd_kcontrol_new max98095_right_ADC_mixer_controls[] = { static int max98095_mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); switch (event) { Loading Loading @@ -896,7 +896,7 @@ static int max98095_mic_event(struct snd_soc_dapm_widget *w, static int max98095_line_pga(struct snd_soc_dapm_widget *w, int event, u8 channel) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); u8 *state; Loading Loading @@ -944,7 +944,7 @@ static int max98095_pga_in2_event(struct snd_soc_dapm_widget *w, static int max98095_lineout_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); switch (event) { case SND_SOC_DAPM_POST_PMU: Loading Loading @@ -2319,9 +2319,6 @@ static int max98095_probe(struct snd_soc_codec *codec) snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); /* initialize registers cache to hardware default */ max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_write(codec, M98095_048_MIX_DAC_LR, M98095_DAI1L_TO_DACL|M98095_DAI1R_TO_DACR); Loading Loading @@ -2361,8 +2358,6 @@ static int max98095_remove(struct snd_soc_codec *codec) struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); struct i2c_client *client = to_i2c_client(codec->dev); max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); if (max98095->headphone_jack || max98095->mic_jack) max98095_jack_detect_disable(codec); Loading Loading
Documentation/devicetree/bindings/sound/max98090.txt +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ Optional properties: - clock-names: Should be "mclk" - maxim,dmic-freq: Frequency at which to clock DMIC Pins on the device (for linking into audio routes): * MIC1 Loading
sound/soc/codecs/max98088.c +4 −27 Original line number Diff line number Diff line Loading @@ -875,7 +875,7 @@ static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = { static int max98088_mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); switch (event) { Loading Loading @@ -905,7 +905,7 @@ static int max98088_mic_event(struct snd_soc_dapm_widget *w, static int max98088_line_pga(struct snd_soc_dapm_widget *w, int event, int line, u8 channel) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); u8 *state; Loading Loading @@ -1887,25 +1887,6 @@ static void max98088_handle_pdata(struct snd_soc_codec *codec) max98088_handle_eq_pdata(codec); } #ifdef CONFIG_PM static int max98088_suspend(struct snd_soc_codec *codec) { max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } static int max98088_resume(struct snd_soc_codec *codec) { max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } #else #define max98088_suspend NULL #define max98088_resume NULL #endif static int max98088_probe(struct snd_soc_codec *codec) { struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); Loading Loading @@ -1946,9 +1927,6 @@ static int max98088_probe(struct snd_soc_codec *codec) snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); /* initialize registers cache to hardware default */ max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00); snd_soc_write(codec, M98088_REG_22_MIX_DAC, Loading @@ -1974,7 +1952,6 @@ static int max98088_remove(struct snd_soc_codec *codec) { struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); kfree(max98088->eq_texts); return 0; Loading @@ -1983,9 +1960,9 @@ static int max98088_remove(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_max98088 = { .probe = max98088_probe, .remove = max98088_remove, .suspend = max98088_suspend, .resume = max98088_resume, .set_bias_level = max98088_set_bias_level, .suspend_bias_off = true, .controls = max98088_snd_controls, .num_controls = ARRAY_SIZE(max98088_snd_controls), .dapm_widgets = max98088_dapm_widgets, Loading
sound/soc/codecs/max98090.c +154 −37 Original line number Diff line number Diff line Loading @@ -806,7 +806,7 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = { static int max98090_micinput_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); unsigned int val = snd_soc_read(codec, w->reg); Loading Loading @@ -1828,27 +1828,155 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, return 0; } static const int comp_pclk_rates[] = { 11289600, 12288000, 12000000, 13000000, 19200000 }; static const int dmic_micclk[] = { 2, 2, 2, 2, 4, 2 }; static const int dmic_divisors[] = { 2, 3, 4, 5, 6, 8 }; static const int comp_lrclk_rates[] = { 8000, 16000, 32000, 44100, 48000, 96000 }; static const int dmic_comp[6][6] = { {7, 8, 3, 3, 3, 3}, {7, 8, 3, 3, 3, 3}, {7, 8, 3, 3, 3, 3}, {7, 8, 3, 1, 1, 1}, {7, 8, 3, 1, 2, 2}, {7, 8, 3, 3, 3, 3} struct dmic_table { int pclk; struct { int freq; int comp[6]; /* One each for 8, 16, 32, 44.1, 48, and 96 kHz */ } settings[6]; /* One for each dmic divisor. */ }; static const struct dmic_table dmic_table[] = { /* One for each pclk freq. */ { .pclk = 11289600, .settings = { { .freq = 2, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 1, .comp = { 7, 8, 2, 2, 2, 2 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 6, 6, 6, 6 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, }, }, { .pclk = 12000000, .settings = { { .freq = 2, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 1, .comp = { 7, 8, 2, 2, 2, 2 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 5, 5, 6, 6 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, } }, { .pclk = 12288000, .settings = { { .freq = 2, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 1, .comp = { 7, 8, 2, 2, 2, 2 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 6, 6, 6, 6 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 3, 3, 3, 3 } }, } }, { .pclk = 13000000, .settings = { { .freq = 2, .comp = { 7, 8, 1, 1, 1, 1 } }, { .freq = 1, .comp = { 7, 8, 0, 0, 0, 0 } }, { .freq = 0, .comp = { 7, 8, 1, 1, 1, 1 } }, { .freq = 0, .comp = { 7, 8, 4, 4, 5, 5 } }, { .freq = 0, .comp = { 7, 8, 1, 1, 1, 1 } }, { .freq = 0, .comp = { 7, 8, 1, 1, 1, 1 } }, } }, { .pclk = 19200000, .settings = { { .freq = 2, .comp = { 0, 0, 0, 0, 0, 0 } }, { .freq = 1, .comp = { 7, 8, 1, 1, 1, 1 } }, { .freq = 0, .comp = { 7, 8, 5, 5, 6, 6 } }, { .freq = 0, .comp = { 7, 8, 2, 2, 3, 3 } }, { .freq = 0, .comp = { 7, 8, 1, 1, 2, 2 } }, { .freq = 0, .comp = { 7, 8, 5, 5, 6, 6 } }, } }, }; static int max98090_find_divisor(int target_freq, int pclk) { int current_diff = INT_MAX; int test_diff = INT_MAX; int divisor_index = 0; int i; for (i = 0; i < ARRAY_SIZE(dmic_divisors); i++) { test_diff = abs(target_freq - (pclk / dmic_divisors[i])); if (test_diff < current_diff) { current_diff = test_diff; divisor_index = i; } } return divisor_index; } static int max98090_find_closest_pclk(int pclk) { int m1; int m2; int i; for (i = 0; i < ARRAY_SIZE(dmic_table); i++) { if (pclk == dmic_table[i].pclk) return i; if (pclk < dmic_table[i].pclk) { if (i == 0) return i; m1 = pclk - dmic_table[i-1].pclk; m2 = dmic_table[i].pclk - pclk; if (m1 < m2) return i - 1; else return i; } } return -EINVAL; } static int max98090_configure_dmic(struct max98090_priv *max98090, int target_dmic_clk, int pclk, int fs) { int micclk_index; int pclk_index; int dmic_freq; int dmic_comp; int i; pclk_index = max98090_find_closest_pclk(pclk); if (pclk_index < 0) return pclk_index; micclk_index = max98090_find_divisor(target_dmic_clk, pclk); for (i = 0; i < ARRAY_SIZE(comp_lrclk_rates) - 1; i++) { if (fs <= (comp_lrclk_rates[i] + comp_lrclk_rates[i+1]) / 2) break; } dmic_freq = dmic_table[pclk_index].settings[micclk_index].freq; dmic_comp = dmic_table[pclk_index].settings[micclk_index].comp[i]; regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_ENABLE, M98090_MICCLK_MASK, micclk_index << M98090_MICCLK_SHIFT); regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_CONFIG, M98090_DMIC_COMP_MASK | M98090_DMIC_FREQ_MASK, dmic_comp << M98090_DMIC_COMP_SHIFT | dmic_freq << M98090_DMIC_FREQ_SHIFT); return 0; } static int max98090_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) Loading @@ -1856,7 +1984,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); struct max98090_cdata *cdata; int i, j; cdata = &max98090->dai[0]; max98090->bclk = snd_soc_params_to_bclk(params); Loading Loading @@ -1895,27 +2022,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, snd_soc_update_bits(codec, M98090_REG_FILTER_CONFIG, M98090_DHF_MASK, M98090_DHF_MASK); /* Check for supported PCLK to LRCLK ratios */ for (j = 0; j < ARRAY_SIZE(comp_pclk_rates); j++) { if (comp_pclk_rates[j] == max98090->sysclk) { break; } } for (i = 0; i < ARRAY_SIZE(comp_lrclk_rates) - 1; i++) { if (max98090->lrclk <= (comp_lrclk_rates[i] + comp_lrclk_rates[i + 1]) / 2) { break; } } snd_soc_update_bits(codec, M98090_REG_DIGITAL_MIC_ENABLE, M98090_MICCLK_MASK, dmic_micclk[j] << M98090_MICCLK_SHIFT); snd_soc_update_bits(codec, M98090_REG_DIGITAL_MIC_CONFIG, M98090_DMIC_COMP_MASK, dmic_comp[j][i] << M98090_DMIC_COMP_SHIFT); max98090_configure_dmic(max98090, max98090->dmic_freq, max98090->pclk, max98090->lrclk); return 0; } Loading Loading @@ -1946,12 +2054,15 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, if ((freq >= 10000000) && (freq <= 20000000)) { snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, M98090_PSCLK_DIV1); max98090->pclk = freq; } else if ((freq > 20000000) && (freq <= 40000000)) { snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, M98090_PSCLK_DIV2); max98090->pclk = freq >> 1; } else if ((freq > 40000000) && (freq <= 60000000)) { snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, M98090_PSCLK_DIV4); max98090->pclk = freq >> 2; } else { dev_err(codec->dev, "Invalid master clock frequency\n"); return -EINVAL; Loading Loading @@ -2326,6 +2437,7 @@ static int max98090_probe(struct snd_soc_codec *codec) /* Initialize private data */ max98090->sysclk = (unsigned)-1; max98090->pclk = (unsigned)-1; max98090->master = false; cdata = &max98090->dai[0]; Loading Loading @@ -2465,6 +2577,11 @@ static int max98090_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, max98090); max98090->pdata = i2c->dev.platform_data; ret = of_property_read_u32(i2c->dev.of_node, "maxim,dmic-freq", &max98090->dmic_freq); if (ret < 0) max98090->dmic_freq = MAX98090_DEFAULT_DMIC_FREQ; max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap); if (IS_ERR(max98090->regmap)) { ret = PTR_ERR(max98090->regmap); Loading
sound/soc/codecs/max98090.h +8 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,12 @@ #ifndef _MAX98090_H #define _MAX98090_H /* * The default operating frequency for a DMIC attached to the codec. * This can be overridden by a device tree property. */ #define MAX98090_DEFAULT_DMIC_FREQ 2500000 /* * MAX98090 Register Definitions */ Loading Loading @@ -1518,8 +1524,10 @@ struct max98090_priv { struct max98090_pdata *pdata; struct clk *mclk; unsigned int sysclk; unsigned int pclk; unsigned int bclk; unsigned int lrclk; u32 dmic_freq; struct max98090_cdata dai[1]; int jack_state; struct delayed_work jack_work; Loading
sound/soc/codecs/max98095.c +3 −8 Original line number Diff line number Diff line Loading @@ -866,7 +866,7 @@ static const struct snd_kcontrol_new max98095_right_ADC_mixer_controls[] = { static int max98095_mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); switch (event) { Loading Loading @@ -896,7 +896,7 @@ static int max98095_mic_event(struct snd_soc_dapm_widget *w, static int max98095_line_pga(struct snd_soc_dapm_widget *w, int event, u8 channel) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); u8 *state; Loading Loading @@ -944,7 +944,7 @@ static int max98095_pga_in2_event(struct snd_soc_dapm_widget *w, static int max98095_lineout_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); switch (event) { case SND_SOC_DAPM_POST_PMU: Loading Loading @@ -2319,9 +2319,6 @@ static int max98095_probe(struct snd_soc_codec *codec) snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); /* initialize registers cache to hardware default */ max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY); snd_soc_write(codec, M98095_048_MIX_DAC_LR, M98095_DAI1L_TO_DACL|M98095_DAI1R_TO_DACR); Loading Loading @@ -2361,8 +2358,6 @@ static int max98095_remove(struct snd_soc_codec *codec) struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); struct i2c_client *client = to_i2c_client(codec->dev); max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); if (max98095->headphone_jack || max98095->mic_jack) max98095_jack_detect_disable(codec); Loading