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

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
...@@ -16,6 +16,8 @@ Optional properties: ...@@ -16,6 +16,8 @@ Optional properties:
- clock-names: Should be "mclk" - clock-names: Should be "mclk"
- maxim,dmic-freq: Frequency at which to clock DMIC
Pins on the device (for linking into audio routes): Pins on the device (for linking into audio routes):
* MIC1 * MIC1
......
...@@ -875,7 +875,7 @@ static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = { ...@@ -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, static int max98088_mic_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) 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); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
switch (event) { switch (event) {
...@@ -905,7 +905,7 @@ static int max98088_mic_event(struct snd_soc_dapm_widget *w, ...@@ -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, static int max98088_line_pga(struct snd_soc_dapm_widget *w,
int event, int line, u8 channel) 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); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
u8 *state; u8 *state;
...@@ -1887,25 +1887,6 @@ static void max98088_handle_pdata(struct snd_soc_codec *codec) ...@@ -1887,25 +1887,6 @@ static void max98088_handle_pdata(struct snd_soc_codec *codec)
max98088_handle_eq_pdata(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) static int max98088_probe(struct snd_soc_codec *codec)
{ {
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
...@@ -1946,9 +1927,6 @@ static int max98088_probe(struct snd_soc_codec *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); 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_0F_IRQ_ENABLE, 0x00);
snd_soc_write(codec, M98088_REG_22_MIX_DAC, snd_soc_write(codec, M98088_REG_22_MIX_DAC,
...@@ -1974,7 +1952,6 @@ static int max98088_remove(struct snd_soc_codec *codec) ...@@ -1974,7 +1952,6 @@ static int max98088_remove(struct snd_soc_codec *codec)
{ {
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
kfree(max98088->eq_texts); kfree(max98088->eq_texts);
return 0; return 0;
...@@ -1983,9 +1960,9 @@ static int max98088_remove(struct snd_soc_codec *codec) ...@@ -1983,9 +1960,9 @@ static int max98088_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_max98088 = { static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
.probe = max98088_probe, .probe = max98088_probe,
.remove = max98088_remove, .remove = max98088_remove,
.suspend = max98088_suspend,
.resume = max98088_resume,
.set_bias_level = max98088_set_bias_level, .set_bias_level = max98088_set_bias_level,
.suspend_bias_off = true,
.controls = max98088_snd_controls, .controls = max98088_snd_controls,
.num_controls = ARRAY_SIZE(max98088_snd_controls), .num_controls = ARRAY_SIZE(max98088_snd_controls),
.dapm_widgets = max98088_dapm_widgets, .dapm_widgets = max98088_dapm_widgets,
......
...@@ -806,7 +806,7 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = { ...@@ -806,7 +806,7 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = {
static int max98090_micinput_event(struct snd_soc_dapm_widget *w, static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) 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); struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
unsigned int val = snd_soc_read(codec, w->reg); unsigned int val = snd_soc_read(codec, w->reg);
...@@ -1828,27 +1828,155 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec, ...@@ -1828,27 +1828,155 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
return 0; return 0;
} }
static const int comp_pclk_rates[] = { static const int dmic_divisors[] = { 2, 3, 4, 5, 6, 8 };
11289600, 12288000, 12000000, 13000000, 19200000
};
static const int dmic_micclk[] = {
2, 2, 2, 2, 4, 2
};
static const int comp_lrclk_rates[] = { static const int comp_lrclk_rates[] = {
8000, 16000, 32000, 44100, 48000, 96000 8000, 16000, 32000, 44100, 48000, 96000
}; };
static const int dmic_comp[6][6] = { struct dmic_table {
{7, 8, 3, 3, 3, 3}, int pclk;
{7, 8, 3, 3, 3, 3}, struct {
{7, 8, 3, 3, 3, 3}, int freq;
{7, 8, 3, 1, 1, 1}, int comp[6]; /* One each for 8, 16, 32, 44.1, 48, and 96 kHz */
{7, 8, 3, 1, 2, 2}, } settings[6]; /* One for each dmic divisor. */
{7, 8, 3, 3, 3, 3}
}; };
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, static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
...@@ -1856,7 +1984,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -1856,7 +1984,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec); struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
struct max98090_cdata *cdata; struct max98090_cdata *cdata;
int i, j;
cdata = &max98090->dai[0]; cdata = &max98090->dai[0];
max98090->bclk = snd_soc_params_to_bclk(params); max98090->bclk = snd_soc_params_to_bclk(params);
...@@ -1895,27 +2022,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream, ...@@ -1895,27 +2022,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
snd_soc_update_bits(codec, M98090_REG_FILTER_CONFIG, snd_soc_update_bits(codec, M98090_REG_FILTER_CONFIG,
M98090_DHF_MASK, M98090_DHF_MASK); M98090_DHF_MASK, M98090_DHF_MASK);
/* Check for supported PCLK to LRCLK ratios */ max98090_configure_dmic(max98090, max98090->dmic_freq, max98090->pclk,
for (j = 0; j < ARRAY_SIZE(comp_pclk_rates); j++) { max98090->lrclk);
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);
return 0; return 0;
} }
...@@ -1946,12 +2054,15 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, ...@@ -1946,12 +2054,15 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
if ((freq >= 10000000) && (freq <= 20000000)) { if ((freq >= 10000000) && (freq <= 20000000)) {
snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK,
M98090_PSCLK_DIV1); M98090_PSCLK_DIV1);
max98090->pclk = freq;
} else if ((freq > 20000000) && (freq <= 40000000)) { } else if ((freq > 20000000) && (freq <= 40000000)) {
snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK,
M98090_PSCLK_DIV2); M98090_PSCLK_DIV2);
max98090->pclk = freq >> 1;
} else if ((freq > 40000000) && (freq <= 60000000)) { } else if ((freq > 40000000) && (freq <= 60000000)) {
snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK,
M98090_PSCLK_DIV4); M98090_PSCLK_DIV4);
max98090->pclk = freq >> 2;
} else { } else {
dev_err(codec->dev, "Invalid master clock frequency\n"); dev_err(codec->dev, "Invalid master clock frequency\n");
return -EINVAL; return -EINVAL;
...@@ -2326,6 +2437,7 @@ static int max98090_probe(struct snd_soc_codec *codec) ...@@ -2326,6 +2437,7 @@ static int max98090_probe(struct snd_soc_codec *codec)
/* Initialize private data */ /* Initialize private data */
max98090->sysclk = (unsigned)-1; max98090->sysclk = (unsigned)-1;
max98090->pclk = (unsigned)-1;
max98090->master = false; max98090->master = false;
cdata = &max98090->dai[0]; cdata = &max98090->dai[0];
...@@ -2465,6 +2577,11 @@ static int max98090_i2c_probe(struct i2c_client *i2c, ...@@ -2465,6 +2577,11 @@ static int max98090_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, max98090); i2c_set_clientdata(i2c, max98090);
max98090->pdata = i2c->dev.platform_data; 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); max98090->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap);
if (IS_ERR(max98090->regmap)) { if (IS_ERR(max98090->regmap)) {
ret = PTR_ERR(max98090->regmap); ret = PTR_ERR(max98090->regmap);
......
...@@ -11,6 +11,12 @@ ...@@ -11,6 +11,12 @@
#ifndef _MAX98090_H #ifndef _MAX98090_H
#define _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 * MAX98090 Register Definitions
*/ */
...@@ -1518,8 +1524,10 @@ struct max98090_priv { ...@@ -1518,8 +1524,10 @@ struct max98090_priv {
struct max98090_pdata *pdata; struct max98090_pdata *pdata;
struct clk *mclk; struct clk *mclk;
unsigned int sysclk; unsigned int sysclk;
unsigned int pclk;
unsigned int bclk; unsigned int bclk;
unsigned int lrclk; unsigned int lrclk;
u32 dmic_freq;
struct max98090_cdata dai[1]; struct max98090_cdata dai[1];
int jack_state; int jack_state;
struct delayed_work jack_work; struct delayed_work jack_work;
......
...@@ -866,7 +866,7 @@ static const struct snd_kcontrol_new max98095_right_ADC_mixer_controls[] = { ...@@ -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, static int max98095_mic_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) 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); struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
switch (event) { switch (event) {
...@@ -896,7 +896,7 @@ static int max98095_mic_event(struct snd_soc_dapm_widget *w, ...@@ -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, static int max98095_line_pga(struct snd_soc_dapm_widget *w,
int event, u8 channel) 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); struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
u8 *state; u8 *state;
...@@ -944,7 +944,7 @@ static int max98095_pga_in2_event(struct snd_soc_dapm_widget *w, ...@@ -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, static int max98095_lineout_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) 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) { switch (event) {
case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_POST_PMU:
...@@ -2319,9 +2319,6 @@ static int max98095_probe(struct snd_soc_codec *codec) ...@@ -2319,9 +2319,6 @@ static int max98095_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); 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, snd_soc_write(codec, M98095_048_MIX_DAC_LR,
M98095_DAI1L_TO_DACL|M98095_DAI1R_TO_DACR); M98095_DAI1L_TO_DACL|M98095_DAI1R_TO_DACR);
...@@ -2361,8 +2358,6 @@ static int max98095_remove(struct snd_soc_codec *codec) ...@@ -2361,8 +2358,6 @@ static int max98095_remove(struct snd_soc_codec *codec)
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *client = to_i2c_client(codec->dev); 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) if (max98095->headphone_jack || max98095->mic_jack)
max98095_jack_detect_disable(codec); max98095_jack_detect_disable(codec);
......
...@@ -291,25 +291,6 @@ static struct snd_soc_dai_driver max9850_dai = { ...@@ -291,25 +291,6 @@ static struct snd_soc_dai_driver max9850_dai = {
.ops = &max9850_dai_ops, .ops = &max9850_dai_ops,
}; };
#ifdef CONFIG_PM
static int max9850_suspend(struct snd_soc_codec *codec)
{
max9850_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int max9850_resume(struct snd_soc_codec *codec)
{
max9850_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
#else
#define max9850_suspend NULL
#define max9850_resume NULL
#endif
static int max9850_probe(struct snd_soc_codec *codec) static int max9850_probe(struct snd_soc_codec *codec)
{ {
/* enable zero-detect */ /* enable zero-detect */
...@@ -324,9 +305,8 @@ static int max9850_probe(struct snd_soc_codec *codec) ...@@ -324,9 +305,8 @@ static int max9850_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_max9850 = { static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
.probe = max9850_probe, .probe = max9850_probe,
.suspend = max9850_suspend,
.resume = max9850_resume,
.set_bias_level = max9850_set_bias_level, .set_bias_level = max9850_set_bias_level,
.suspend_bias_off = true,
.controls = max9850_controls, .controls = max9850_controls,
.num_controls = ARRAY_SIZE(max9850_controls), .num_controls = ARRAY_SIZE(max9850_controls),
......
...@@ -29,7 +29,9 @@ struct simple_card_data { ...@@ -29,7 +29,9 @@ struct simple_card_data {
} *dai_props; } *dai_props;
unsigned int mclk_fs; unsigned int mclk_fs;
int gpio_hp_det; int gpio_hp_det;
int gpio_hp_det_invert;
int gpio_mic_det; int gpio_mic_det;
int gpio_mic_det_invert;
struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ struct snd_soc_dai_link dai_link[]; /* dynamically allocated */
}; };
...@@ -148,6 +150,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -148,6 +150,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
simple_card_hp_jack_pins); simple_card_hp_jack_pins);
simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det; simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det;
simple_card_hp_jack_gpio.invert = priv->gpio_hp_det_invert;
snd_soc_jack_add_gpios(&simple_card_hp_jack, 1, snd_soc_jack_add_gpios(&simple_card_hp_jack, 1,
&simple_card_hp_jack_gpio); &simple_card_hp_jack_gpio);
} }
...@@ -159,6 +162,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -159,6 +162,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
ARRAY_SIZE(simple_card_mic_jack_pins), ARRAY_SIZE(simple_card_mic_jack_pins),
simple_card_mic_jack_pins); simple_card_mic_jack_pins);
simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det; simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det;
simple_card_mic_jack_gpio.invert = priv->gpio_mic_det_invert;
snd_soc_jack_add_gpios(&simple_card_mic_jack, 1, snd_soc_jack_add_gpios(&simple_card_mic_jack, 1,
&simple_card_mic_jack_gpio); &simple_card_mic_jack_gpio);
} }
...@@ -226,6 +230,53 @@ asoc_simple_card_sub_parse_of(struct device_node *np, ...@@ -226,6 +230,53 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
return 0; return 0;
} }
static int asoc_simple_card_parse_daifmt(struct device_node *node,
struct simple_card_data *priv,
struct device_node *cpu,
struct device_node *codec,
char *prefix, int idx)
{
struct device *dev = simple_priv_to_dev(priv);
struct device_node *bitclkmaster = NULL;
struct device_node *framemaster = NULL;
struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
unsigned int daifmt;
daifmt = snd_soc_of_parse_daifmt(node, prefix,
&bitclkmaster, &framemaster);
daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
if (strlen(prefix) && !bitclkmaster && !framemaster) {
/*
* No dai-link level and master setting was not found from
* sound node level, revert back to legacy DT parsing and
* take the settings from codec node.
*/
dev_dbg(dev, "Revert to legacy daifmt parsing\n");
cpu_dai->fmt = codec_dai->fmt =
snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
} else {
if (codec == bitclkmaster)
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
else
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
cpu_dai->fmt = daifmt;
codec_dai->fmt = daifmt;
}
of_node_put(bitclkmaster);
of_node_put(framemaster);
return 0;
}
static int asoc_simple_card_dai_link_of(struct device_node *node, static int asoc_simple_card_dai_link_of(struct device_node *node,
struct simple_card_data *priv, struct simple_card_data *priv,
int idx, int idx,
...@@ -234,10 +285,8 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, ...@@ -234,10 +285,8 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
struct device *dev = simple_priv_to_dev(priv); struct device *dev = simple_priv_to_dev(priv);
struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
struct device_node *np = NULL; struct device_node *cpu = NULL;
struct device_node *bitclkmaster = NULL; struct device_node *codec = NULL;
struct device_node *framemaster = NULL;
unsigned int daifmt;
char *name; char *name;
char prop[128]; char prop[128];
char *prefix = ""; char *prefix = "";
...@@ -247,85 +296,36 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, ...@@ -247,85 +296,36 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
if (is_top_level_node) if (is_top_level_node)
prefix = "simple-audio-card,"; prefix = "simple-audio-card,";
daifmt = snd_soc_of_parse_daifmt(node, prefix,
&bitclkmaster, &framemaster);
daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
snprintf(prop, sizeof(prop), "%scpu", prefix); snprintf(prop, sizeof(prop), "%scpu", prefix);
np = of_get_child_by_name(node, prop); cpu = of_get_child_by_name(node, prop);
if (!np) {
snprintf(prop, sizeof(prop), "%scodec", prefix);
codec = of_get_child_by_name(node, prop);
if (!cpu || !codec) {
ret = -EINVAL; ret = -EINVAL;
dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
goto dai_link_of_err; goto dai_link_of_err;
} }
ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai, ret = asoc_simple_card_parse_daifmt(node, priv,
cpu, codec, prefix, idx);
if (ret < 0)
goto dai_link_of_err;
ret = asoc_simple_card_sub_parse_of(cpu, &dai_props->cpu_dai,
&dai_link->cpu_of_node, &dai_link->cpu_of_node,
&dai_link->cpu_dai_name, &dai_link->cpu_dai_name,
&cpu_args); &cpu_args);
if (ret < 0) if (ret < 0)
goto dai_link_of_err; goto dai_link_of_err;
dai_props->cpu_dai.fmt = daifmt; ret = asoc_simple_card_sub_parse_of(codec, &dai_props->codec_dai,
switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
case 0x11:
dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
break;
case 0x10:
dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
break;
case 0x01:
dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
break;
default:
dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
break;
}
of_node_put(np);
snprintf(prop, sizeof(prop), "%scodec", prefix);
np = of_get_child_by_name(node, prop);
if (!np) {
ret = -EINVAL;
dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
goto dai_link_of_err;
}
ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai,
&dai_link->codec_of_node, &dai_link->codec_of_node,
&dai_link->codec_dai_name, NULL); &dai_link->codec_dai_name, NULL);
if (ret < 0) if (ret < 0)
goto dai_link_of_err; goto dai_link_of_err;
if (strlen(prefix) && !bitclkmaster && !framemaster) {
/*
* No DAI link level and master setting was found
* from sound node level, revert back to legacy DT
* parsing and take the settings from codec node.
*/
dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n",
__func__);
dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt =
snd_soc_of_parse_daifmt(np, NULL, NULL, NULL) |
(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
} else {
dai_props->codec_dai.fmt = daifmt;
switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
case 0x11:
dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
break;
case 0x10:
dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
break;
case 0x01:
dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
break;
default:
dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
break;
}
}
if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
ret = -EINVAL; ret = -EINVAL;
goto dai_link_of_err; goto dai_link_of_err;
...@@ -368,12 +368,9 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, ...@@ -368,12 +368,9 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
dai_link->cpu_dai_name = NULL; dai_link->cpu_dai_name = NULL;
dai_link_of_err: dai_link_of_err:
if (np) of_node_put(cpu);
of_node_put(np); of_node_put(codec);
if (bitclkmaster)
of_node_put(bitclkmaster);
if (framemaster)
of_node_put(framemaster);
return ret; return ret;
} }
...@@ -381,6 +378,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -381,6 +378,7 @@ static int asoc_simple_card_parse_of(struct device_node *node,
struct simple_card_data *priv) struct simple_card_data *priv)
{ {
struct device *dev = simple_priv_to_dev(priv); struct device *dev = simple_priv_to_dev(priv);
enum of_gpio_flags flags;
u32 val; u32 val;
int ret; int ret;
...@@ -436,13 +434,15 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -436,13 +434,15 @@ static int asoc_simple_card_parse_of(struct device_node *node,
return ret; return ret;
} }
priv->gpio_hp_det = of_get_named_gpio(node, priv->gpio_hp_det = of_get_named_gpio_flags(node,
"simple-audio-card,hp-det-gpio", 0); "simple-audio-card,hp-det-gpio", 0, &flags);
priv->gpio_hp_det_invert = !!(flags & OF_GPIO_ACTIVE_LOW);
if (priv->gpio_hp_det == -EPROBE_DEFER) if (priv->gpio_hp_det == -EPROBE_DEFER)
return -EPROBE_DEFER; return -EPROBE_DEFER;
priv->gpio_mic_det = of_get_named_gpio(node, priv->gpio_mic_det = of_get_named_gpio_flags(node,
"simple-audio-card,mic-det-gpio", 0); "simple-audio-card,mic-det-gpio", 0, &flags);
priv->gpio_mic_det_invert = !!(flags & OF_GPIO_ACTIVE_LOW);
if (priv->gpio_mic_det == -EPROBE_DEFER) if (priv->gpio_mic_det == -EPROBE_DEFER)
return -EPROBE_DEFER; return -EPROBE_DEFER;
...@@ -457,18 +457,13 @@ static int asoc_simple_card_unref(struct platform_device *pdev) ...@@ -457,18 +457,13 @@ static int asoc_simple_card_unref(struct platform_device *pdev)
{ {
struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_card *card = platform_get_drvdata(pdev);
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
struct device_node *np;
int num_links; int num_links;
for (num_links = 0, dai_link = card->dai_link; for (num_links = 0, dai_link = card->dai_link;
num_links < card->num_links; num_links < card->num_links;
num_links++, dai_link++) { num_links++, dai_link++) {
np = (struct device_node *) dai_link->cpu_of_node; of_node_put(dai_link->cpu_of_node);
if (np) of_node_put(dai_link->codec_of_node);
of_node_put(np);
np = (struct device_node *) dai_link->codec_of_node;
if (np)
of_node_put(np);
} }
return 0; return 0;
} }
......
...@@ -153,8 +153,8 @@ static int odroidx2_audio_remove(struct platform_device *pdev) ...@@ -153,8 +153,8 @@ static int odroidx2_audio_remove(struct platform_device *pdev)
snd_soc_unregister_card(card); snd_soc_unregister_card(card);
of_node_put((struct device_node *)odroidx2_dai[0].cpu_of_node); of_node_put(odroidx2_dai[0].cpu_of_node);
of_node_put((struct device_node *)odroidx2_dai[0].codec_of_node); of_node_put(odroidx2_dai[0].codec_of_node);
return 0; return 0;
} }
......
...@@ -63,12 +63,8 @@ static void mop500_of_node_put(void) ...@@ -63,12 +63,8 @@ static void mop500_of_node_put(void)
int i; int i;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (mop500_dai_links[i].cpu_of_node) of_node_put(mop500_dai_links[i].cpu_of_node);
of_node_put((struct device_node *) of_node_put(mop500_dai_links[i].codec_of_node);
mop500_dai_links[i].cpu_of_node);
if (mop500_dai_links[i].codec_of_node)
of_node_put((struct device_node *)
mop500_dai_links[i].codec_of_node);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment