Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41967b77 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'asoc/topic/max98088', 'asoc/topic/max98090',...

Merge remote-tracking branches 'asoc/topic/max98088', 'asoc/topic/max98090', 'asoc/topic/max98095', 'asoc/topic/max9850' and 'asoc/topic/mop500' into asoc-next
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+4 −27
Original line number Diff line number Diff line
@@ -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) {
@@ -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;

@@ -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);
@@ -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,
@@ -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;
@@ -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,
+154 −37
Original line number Diff line number Diff line
@@ -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);
@@ -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)
@@ -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);
@@ -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;
}
@@ -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;
@@ -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];
@@ -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);
+8 −0
Original line number Diff line number Diff line
@@ -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
 */
@@ -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;
+3 −8
Original line number Diff line number Diff line
@@ -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) {
@@ -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;

@@ -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:
@@ -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);

@@ -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