#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
++#include <linux/of.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
+#include <linux/acpi.h>
+ +#include <linux/clk.h>
#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
static bool max98090_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
++ case M98090_REG_SOFTWARE_RESET:
case M98090_REG_DEVICE_STATUS:
case M98090_REG_JACK_STATUS:
case M98090_REG_REVISION_ID:
static const DECLARE_TLV_DB_SCALE(max98090_alcmakeup_tlv, 0, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_alccomp_tlv, -3100, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_drcexp_tlv, -6600, 100, 0);
++static const DECLARE_TLV_DB_SCALE(max98090_sdg_tlv, 50, 200, 0);
static const unsigned int max98090_mixout_tlv[] = {
TLV_DB_RANGE_HEAD(2),
static int max98090_get_enab_tlv(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
static int max98090_put_enab_tlv(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98090_priv *max98090 = snd_soc_codec_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
SOC_SINGLE_EXT_TLV("Digital Sidetone Volume",
M98090_REG_ADC_SIDETONE, M98090_DVST_SHIFT,
M98090_DVST_NUM - 1, 1, max98090_get_enab_tlv,
-- max98090_put_enab_tlv, max98090_micboost_tlv),
++ max98090_put_enab_tlv, max98090_sdg_tlv),
SOC_SINGLE_TLV("Digital Coarse Volume", M98090_REG_DAI_PLAYBACK_LEVEL,
M98090_DVG_SHIFT, M98090_DVG_NUM - 1, 0,
max98090_dvg_tlv),
static SOC_ENUM_SINGLE_VIRT_DECL(dmic_mux_enum, dmic_mux_text);
static const struct snd_kcontrol_new max98090_dmic_mux =
-- SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum);
++ SOC_DAPM_ENUM("DMIC Mux", dmic_mux_enum);
static const char *max98090_micpre_text[] = { "Off", "On" };
SND_SOC_DAPM_MUX("MIC2 Mux", SND_SOC_NOPM,
0, 0, &max98090_mic2_mux),
-- SND_SOC_DAPM_VIRT_MUX("DMIC Mux", SND_SOC_NOPM,
-- 0, 0, &max98090_dmic_mux),
++ SND_SOC_DAPM_MUX("DMIC Mux", SND_SOC_NOPM, 0, 0, &max98090_dmic_mux),
SND_SOC_DAPM_PGA_E("MIC1 Input", M98090_REG_MIC1_INPUT_LEVEL,
M98090_MIC_PA1EN_SHIFT, 0, NULL, 0, max98090_micinput_event,
};
static const int user_pclk_rates[] = {
- - 13000000, 13000000
+ + 13000000, 13000000, 19200000, 19200000,
};
static const int user_lrclk_rates[] = {
- - 44100, 48000
+ + 44100, 48000, 44100, 48000,
};
static const unsigned long long ni_value[] = {
- - 3528, 768
+ + 3528, 768, 441, 8
};
static const unsigned long long mi_value[] = {
- - 8125, 1625
+ + 8125, 1625, 1500, 25
};
static void max98090_configure_bclk(struct snd_soc_codec *codec)
M98090_REG_CLOCK_RATIO_NI_LSB, 0x00);
snd_soc_update_bits(codec, M98090_REG_CLOCK_MODE,
M98090_USE_M1_MASK, 0);
+ max98090->master = false;
break;
case SND_SOC_DAIFMT_CBM_CFM:
/* Set to master mode */
regval |= M98090_MAS_MASK |
M98090_BSEL_32;
}
+ max98090->master = true;
break;
case SND_SOC_DAIFMT_CBS_CFM:
case SND_SOC_DAIFMT_CBM_CFS:
switch (level) {
case SND_SOC_BIAS_ON:
- if (max98090->jack_state == M98090_JACK_STATE_HEADSET) {
- /*
- * Set to normal bias level.
- */
- snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
- M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
- }
break;
case SND_SOC_BIAS_PREPARE:
+ + /*
+ + * SND_SOC_BIAS_PREPARE is called while preparing for a
+ + * transition to ON or away from ON. If current bias_level
+ + * is SND_SOC_BIAS_ON, then it is preparing for a transition
+ + * away from ON. Disable the clock in that case, otherwise
+ + * enable it.
+ + */
+ + if (!IS_ERR(max98090->mclk)) {
+ + if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+ + clk_disable_unprepare(max98090->mclk);
+ + else
+ + clk_prepare_enable(max98090->mclk);
+ + }
break;
case SND_SOC_BIAS_STANDBY:
return -EINVAL;
}
- max98090_configure_bclk(codec);
+ if (max98090->master)
+ max98090_configure_bclk(codec);
cdata->rate = max98090->lrclk;
if (freq == max98090->sysclk)
return 0;
+ + if (!IS_ERR(max98090->mclk)) {
+ + freq = clk_round_rate(max98090->mclk, freq);
+ + clk_set_rate(max98090->mclk, freq);
+ + }
+ +
/* Setup clocks for slave mode, and using the PLL
* PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
* 0x02 (when master clk is 20MHz to 40MHz)..
max98090->sysclk = freq;
- max98090_configure_bclk(codec);
-
return 0;
}
dev_dbg(codec->dev, "max98090_probe\n");
+ + max98090->mclk = devm_clk_get(codec->dev, "mclk");
+ + if (PTR_ERR(max98090->mclk) == -EPROBE_DEFER)
+ + return -EPROBE_DEFER;
+ +
max98090->codec = codec;
/* Reset the codec, the DSP core, and disable all interrupts */
/* Initialize private data */
max98090->sysclk = (unsigned)-1;
+ max98090->master = false;
cdata = &max98090->dai[0];
cdata->rate = (unsigned)-1;
snd_soc_write(codec, M98090_REG_BIAS_CONTROL,
M98090_VCM_MODE_MASK);
+ snd_soc_update_bits(codec, M98090_REG_MIC_BIAS_VOLTAGE,
+ M98090_MBVSEL_MASK, M98090_MBVSEL_2V8);
+
max98090_handle_pdata(codec);
max98090_add_widgets(codec);
};
static int max98090_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *i2c_id)
{
struct max98090_priv *max98090;
+ const struct acpi_device_id *acpi_id;
+ kernel_ulong_t driver_data = 0;
int ret;
pr_debug("max98090_i2c_probe\n");
if (max98090 == NULL)
return -ENOMEM;
- max98090->devtype = id->driver_data;
+ if (ACPI_HANDLE(&i2c->dev)) {
+ acpi_id = acpi_match_device(i2c->dev.driver->acpi_match_table,
+ &i2c->dev);
+ if (!acpi_id) {
+ dev_err(&i2c->dev, "No driver data\n");
+ return -EINVAL;
+ }
+ driver_data = acpi_id->driver_data;
+ } else if (i2c_id) {
+ driver_data = i2c_id->driver_data;
+ }
+
+ max98090->devtype = driver_data;
i2c_set_clientdata(i2c, max98090);
max98090->pdata = i2c->dev.platform_data;
max98090->irq = i2c->irq;
regcache_cache_only(max98090->regmap, false);
++ max98090_reset(max98090);
++
regcache_sync(max98090->regmap);
return 0;
}
#endif
++#ifdef CONFIG_PM
++static int max98090_resume(struct device *dev)
++{
++ struct max98090_priv *max98090 = dev_get_drvdata(dev);
++ unsigned int status;
++
++ regcache_mark_dirty(max98090->regmap);
++
++ max98090_reset(max98090);
++
++ /* clear IRQ status */
++ regmap_read(max98090->regmap, M98090_REG_DEVICE_STATUS, &status);
++
++ regcache_sync(max98090->regmap);
++
++ return 0;
++}
++
++static int max98090_suspend(struct device *dev)
++{
++ return 0;
++}
++#endif
++
static const struct dev_pm_ops max98090_pm = {
SET_RUNTIME_PM_OPS(max98090_runtime_suspend,
max98090_runtime_resume, NULL)
++ SET_SYSTEM_SLEEP_PM_OPS(max98090_suspend, max98090_resume)
};
static const struct i2c_device_id max98090_i2c_id[] = {
};
MODULE_DEVICE_TABLE(of, max98090_of_match);
+#ifdef CONFIG_ACPI
+static struct acpi_device_id max98090_acpi_match[] = {
+ { "193C9890", MAX98090 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, max98090_acpi_match);
+#endif
+
static struct i2c_driver max98090_i2c_driver = {
.driver = {
.name = "max98090",
.owner = THIS_MODULE,
.pm = &max98090_pm,
.of_match_table = of_match_ptr(max98090_of_match),
+ .acpi_match_table = ACPI_PTR(max98090_acpi_match),
},
.probe = max98090_i2c_probe,
.remove = max98090_i2c_remove,
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
++ #include <linux/clk.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
struct regmap *regmap;
enum max98095_type devtype;
struct max98095_pdata *pdata;
++ struct clk *mclk;
unsigned int sysclk;
struct max98095_cdata dai[3];
const char **eq_texts;
static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
unsigned int sel = ucontrol->value.integer.value[0];
static int max98095_mic1pre_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = max98095->mic1pre;
static int max98095_mic2pre_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
unsigned int sel = ucontrol->value.integer.value[0];
static int max98095_mic2pre_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = max98095->mic2pre;
if (freq == max98095->sysclk)
return 0;
++ if (!IS_ERR(max98095->mclk)) {
++ freq = clk_round_rate(max98095->mclk, freq);
++ clk_set_rate(max98095->mclk, freq);
++ }
++
/* Setup clocks for slave mode, and using the PLL
* PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
* 0x02 (when master clk is 20MHz to 40MHz)..
break;
case SND_SOC_BIAS_PREPARE:
++ /*
++ * SND_SOC_BIAS_PREPARE is called while preparing for a
++ * transition to ON or away from ON. If current bias_level
++ * is SND_SOC_BIAS_ON, then it is preparing for a transition
++ * away from ON. Disable the clock in that case, otherwise
++ * enable it.
++ */
++ if (!IS_ERR(max98095->mclk)) {
++ if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
++ clk_disable_unprepare(max98095->mclk);
++ else
++ clk_prepare_enable(max98095->mclk);
++ }
break;
case SND_SOC_BIAS_STANDBY:
static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
struct max98095_pdata *pdata = max98095->pdata;
int channel = max98095_get_eq_channel(kcontrol->id.name);
static int max98095_get_eq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
int channel = max98095_get_eq_channel(kcontrol->id.name);
struct max98095_cdata *cdata;
static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
struct max98095_pdata *pdata = max98095->pdata;
int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
-- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
struct max98095_cdata *cdata;
struct i2c_client *client;
int ret = 0;
++ max98095->mclk = devm_clk_get(codec->dev, "mclk");
++ if (PTR_ERR(max98095->mclk) == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++
/* reset the codec, the DSP core, and disable all interrupts */
max98095_reset(codec);
};
MODULE_DEVICE_TABLE(i2c, max98095_i2c_id);
+ static const struct of_device_id max98095_of_match[] = {
+ { .compatible = "maxim,max98095", },
+ { }
+ };
+ MODULE_DEVICE_TABLE(of, max98095_of_match);
+
static struct i2c_driver max98095_i2c_driver = {
.driver = {
.name = "max98095",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(max98095_of_match),
},
.probe = max98095_i2c_probe,
.remove = max98095_i2c_remove,