Commit 565fefdf authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/davinci', 'asoc/topic/dmic',...

Merge remote-tracking branches 'asoc/topic/davinci', 'asoc/topic/dmic', 'asoc/topic/drivers', 'asoc/topic/es8328' and 'asoc/topic/fsl' into asoc-next
...@@ -12,10 +12,18 @@ ...@@ -12,10 +12,18 @@
#ifndef __LINUX_SND_RT5677_H #ifndef __LINUX_SND_RT5677_H
#define __LINUX_SND_RT5677_H #define __LINUX_SND_RT5677_H
enum rt5677_dmic2_clk {
RT5677_DMIC_CLK1 = 0,
RT5677_DMIC_CLK2 = 1,
};
struct rt5677_platform_data { struct rt5677_platform_data {
/* IN1 IN2 can optionally be differential */ /* IN1 IN2 can optionally be differential */
bool in1_diff; bool in1_diff;
bool in2_diff; bool in2_diff;
/* DMIC2 clock source selection */
enum rt5677_dmic2_clk dmic2_clk_pin;
}; };
#endif #endif
...@@ -588,7 +588,8 @@ struct snd_soc_dapm_context { ...@@ -588,7 +588,8 @@ struct snd_soc_dapm_context {
enum snd_soc_bias_level suspend_bias_level; enum snd_soc_bias_level suspend_bias_level;
struct delayed_work delayed_work; struct delayed_work delayed_work;
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
/* Go to BIAS_OFF in suspend if the DAPM context is idle */
unsigned int suspend_bias_off:1;
void (*seq_notifier)(struct snd_soc_dapm_context *, void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int); enum snd_soc_dapm_type, int);
......
...@@ -847,6 +847,7 @@ struct snd_soc_codec_driver { ...@@ -847,6 +847,7 @@ struct snd_soc_codec_driver {
int (*set_bias_level)(struct snd_soc_codec *, int (*set_bias_level)(struct snd_soc_codec *,
enum snd_soc_bias_level level); enum snd_soc_bias_level level);
bool idle_bias_off; bool idle_bias_off;
bool suspend_bias_off;
void (*seq_notifier)(struct snd_soc_dapm_context *, void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int); enum snd_soc_dapm_type, int);
......
...@@ -57,6 +57,7 @@ config SND_SOC_ALL_CODECS ...@@ -57,6 +57,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_DA7213 if I2C select SND_SOC_DA7213 if I2C
select SND_SOC_DA732X if I2C select SND_SOC_DA732X if I2C
select SND_SOC_DA9055 if I2C select SND_SOC_DA9055 if I2C
select SND_SOC_DMIC
select SND_SOC_BT_SCO select SND_SOC_BT_SCO
select SND_SOC_ES8328_SPI if SPI_MASTER select SND_SOC_ES8328_SPI if SPI_MASTER
select SND_SOC_ES8328_I2C if I2C select SND_SOC_ES8328_I2C if I2C
......
...@@ -1448,29 +1448,10 @@ static int adau1373_set_bias_level(struct snd_soc_codec *codec, ...@@ -1448,29 +1448,10 @@ static int adau1373_set_bias_level(struct snd_soc_codec *codec,
return 0; return 0;
} }
static int adau1373_remove(struct snd_soc_codec *codec)
{
adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int adau1373_suspend(struct snd_soc_codec *codec)
{
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
int ret;
ret = adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
regcache_cache_only(adau1373->regmap, true);
return ret;
}
static int adau1373_resume(struct snd_soc_codec *codec) static int adau1373_resume(struct snd_soc_codec *codec)
{ {
struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
regcache_cache_only(adau1373->regmap, false);
adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
regcache_sync(adau1373->regmap); regcache_sync(adau1373->regmap);
return 0; return 0;
...@@ -1501,8 +1482,6 @@ static const struct regmap_config adau1373_regmap_config = { ...@@ -1501,8 +1482,6 @@ static const struct regmap_config adau1373_regmap_config = {
static struct snd_soc_codec_driver adau1373_codec_driver = { static struct snd_soc_codec_driver adau1373_codec_driver = {
.probe = adau1373_probe, .probe = adau1373_probe,
.remove = adau1373_remove,
.suspend = adau1373_suspend,
.resume = adau1373_resume, .resume = adau1373_resume,
.set_bias_level = adau1373_set_bias_level, .set_bias_level = adau1373_set_bias_level,
.idle_bias_off = true, .idle_bias_off = true,
......
...@@ -714,9 +714,9 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec) ...@@ -714,9 +714,9 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec)
static const struct snd_soc_codec_driver adau1761_codec_driver = { static const struct snd_soc_codec_driver adau1761_codec_driver = {
.probe = adau1761_codec_probe, .probe = adau1761_codec_probe,
.suspend = adau17x1_suspend,
.resume = adau17x1_resume, .resume = adau17x1_resume,
.set_bias_level = adau1761_set_bias_level, .set_bias_level = adau1761_set_bias_level,
.suspend_bias_off = true,
.controls = adau1761_controls, .controls = adau1761_controls,
.num_controls = ARRAY_SIZE(adau1761_controls), .num_controls = ARRAY_SIZE(adau1761_controls),
......
...@@ -446,9 +446,9 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec) ...@@ -446,9 +446,9 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec)
static const struct snd_soc_codec_driver adau1781_codec_driver = { static const struct snd_soc_codec_driver adau1781_codec_driver = {
.probe = adau1781_codec_probe, .probe = adau1781_codec_probe,
.suspend = adau17x1_suspend,
.resume = adau17x1_resume, .resume = adau17x1_resume,
.set_bias_level = adau1781_set_bias_level, .set_bias_level = adau1781_set_bias_level,
.suspend_bias_off = true,
.controls = adau1781_controls, .controls = adau1781_controls,
.num_controls = ARRAY_SIZE(adau1781_controls), .num_controls = ARRAY_SIZE(adau1781_controls),
......
...@@ -815,13 +815,6 @@ int adau17x1_add_routes(struct snd_soc_codec *codec) ...@@ -815,13 +815,6 @@ int adau17x1_add_routes(struct snd_soc_codec *codec)
} }
EXPORT_SYMBOL_GPL(adau17x1_add_routes); EXPORT_SYMBOL_GPL(adau17x1_add_routes);
int adau17x1_suspend(struct snd_soc_codec *codec)
{
codec->driver->set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
EXPORT_SYMBOL_GPL(adau17x1_suspend);
int adau17x1_resume(struct snd_soc_codec *codec) int adau17x1_resume(struct snd_soc_codec *codec)
{ {
struct adau *adau = snd_soc_codec_get_drvdata(codec); struct adau *adau = snd_soc_codec_get_drvdata(codec);
...@@ -829,7 +822,6 @@ int adau17x1_resume(struct snd_soc_codec *codec) ...@@ -829,7 +822,6 @@ int adau17x1_resume(struct snd_soc_codec *codec)
if (adau->switch_mode) if (adau->switch_mode)
adau->switch_mode(codec->dev); adau->switch_mode(codec->dev);
codec->driver->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
regcache_sync(adau->regmap); regcache_sync(adau->regmap);
return 0; return 0;
......
...@@ -52,7 +52,6 @@ int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, ...@@ -52,7 +52,6 @@ int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
enum adau17x1_micbias_voltage micbias); enum adau17x1_micbias_voltage micbias);
bool adau17x1_readable_register(struct device *dev, unsigned int reg); bool adau17x1_readable_register(struct device *dev, unsigned int reg);
bool adau17x1_volatile_register(struct device *dev, unsigned int reg); bool adau17x1_volatile_register(struct device *dev, unsigned int reg);
int adau17x1_suspend(struct snd_soc_codec *codec);
int adau17x1_resume(struct snd_soc_codec *codec); int adau17x1_resume(struct snd_soc_codec *codec);
extern const struct snd_soc_dai_ops adau17x1_dai_ops; extern const struct snd_soc_dai_ops adau17x1_dai_ops;
......
...@@ -812,42 +812,23 @@ static int adav80x_probe(struct snd_soc_codec *codec) ...@@ -812,42 +812,23 @@ static int adav80x_probe(struct snd_soc_codec *codec)
/* Disable DAC zero flag */ /* Disable DAC zero flag */
regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6); regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6);
return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0;
}
static int adav80x_suspend(struct snd_soc_codec *codec)
{
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
int ret;
ret = adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
regcache_cache_only(adav80x->regmap, true);
return ret;
} }
static int adav80x_resume(struct snd_soc_codec *codec) static int adav80x_resume(struct snd_soc_codec *codec)
{ {
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
regcache_cache_only(adav80x->regmap, false);
adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
regcache_sync(adav80x->regmap); regcache_sync(adav80x->regmap);
return 0; return 0;
} }
static int adav80x_remove(struct snd_soc_codec *codec)
{
return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
static struct snd_soc_codec_driver adav80x_codec_driver = { static struct snd_soc_codec_driver adav80x_codec_driver = {
.probe = adav80x_probe, .probe = adav80x_probe,
.remove = adav80x_remove,
.suspend = adav80x_suspend,
.resume = adav80x_resume, .resume = adav80x_resume,
.set_bias_level = adav80x_set_bias_level, .set_bias_level = adav80x_set_bias_level,
.suspend_bias_off = true,
.set_pll = adav80x_set_pll, .set_pll = adav80x_set_pll,
.set_sysclk = adav80x_set_sysclk, .set_sysclk = adav80x_set_sysclk,
......
...@@ -602,8 +602,6 @@ static int es8328_suspend(struct snd_soc_codec *codec) ...@@ -602,8 +602,6 @@ static int es8328_suspend(struct snd_soc_codec *codec)
es8328 = snd_soc_codec_get_drvdata(codec); es8328 = snd_soc_codec_get_drvdata(codec);
es8328_set_bias_level(codec, SND_SOC_BIAS_OFF);
clk_disable_unprepare(es8328->clk); clk_disable_unprepare(es8328->clk);
ret = regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), ret = regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),
...@@ -643,7 +641,6 @@ static int es8328_resume(struct snd_soc_codec *codec) ...@@ -643,7 +641,6 @@ static int es8328_resume(struct snd_soc_codec *codec)
return ret; return ret;
} }
es8328_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0; return 0;
} }
...@@ -665,6 +662,7 @@ static int es8328_codec_probe(struct snd_soc_codec *codec) ...@@ -665,6 +662,7 @@ static int es8328_codec_probe(struct snd_soc_codec *codec)
es8328->clk = devm_clk_get(codec->dev, NULL); es8328->clk = devm_clk_get(codec->dev, NULL);
if (IS_ERR(es8328->clk)) { if (IS_ERR(es8328->clk)) {
dev_err(codec->dev, "codec clock missing or invalid\n"); dev_err(codec->dev, "codec clock missing or invalid\n");
ret = PTR_ERR(es8328->clk);
goto clk_fail; goto clk_fail;
} }
...@@ -711,6 +709,8 @@ static struct snd_soc_codec_driver es8328_codec_driver = { ...@@ -711,6 +709,8 @@ static struct snd_soc_codec_driver es8328_codec_driver = {
.resume = es8328_resume, .resume = es8328_resume,
.remove = es8328_remove, .remove = es8328_remove,
.set_bias_level = es8328_set_bias_level, .set_bias_level = es8328_set_bias_level,
.suspend_bias_off = true,
.controls = es8328_snd_controls, .controls = es8328_snd_controls,
.num_controls = ARRAY_SIZE(es8328_snd_controls), .num_controls = ARRAY_SIZE(es8328_snd_controls),
.dapm_widgets = es8328_dapm_widgets, .dapm_widgets = es8328_dapm_widgets,
......
...@@ -1395,18 +1395,6 @@ static struct snd_soc_dai_driver lm49453_dai[] = { ...@@ -1395,18 +1395,6 @@ static struct snd_soc_dai_driver lm49453_dai[] = {
}, },
}; };
static int lm49453_suspend(struct snd_soc_codec *codec)
{
lm49453_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int lm49453_resume(struct snd_soc_codec *codec)
{
lm49453_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
/* power down chip */ /* power down chip */
static int lm49453_remove(struct snd_soc_codec *codec) static int lm49453_remove(struct snd_soc_codec *codec)
{ {
...@@ -1416,8 +1404,6 @@ static int lm49453_remove(struct snd_soc_codec *codec) ...@@ -1416,8 +1404,6 @@ static int lm49453_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { static struct snd_soc_codec_driver soc_codec_dev_lm49453 = {
.remove = lm49453_remove, .remove = lm49453_remove,
.suspend = lm49453_suspend,
.resume = lm49453_resume,
.set_bias_level = lm49453_set_bias_level, .set_bias_level = lm49453_set_bias_level,
.controls = lm49453_snd_controls, .controls = lm49453_snd_controls,
.num_controls = ARRAY_SIZE(lm49453_snd_controls), .num_controls = ARRAY_SIZE(lm49453_snd_controls),
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
...@@ -1700,14 +1701,19 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { ...@@ -1700,14 +1701,19 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("Haptic Generator"), SND_SOC_DAPM_INPUT("Haptic Generator"),
SND_SOC_DAPM_PGA("DMIC1", RT5677_DMIC_CTRL1, RT5677_DMIC_1_EN_SFT, 0, SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0),
NULL, 0), SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("DMIC2", RT5677_DMIC_CTRL1, RT5677_DMIC_2_EN_SFT, 0, SND_SOC_DAPM_PGA("DMIC3", SND_SOC_NOPM, 0, 0, NULL, 0),
NULL, 0), SND_SOC_DAPM_PGA("DMIC4", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("DMIC3", RT5677_DMIC_CTRL1, RT5677_DMIC_3_EN_SFT, 0,
NULL, 0), SND_SOC_DAPM_SUPPLY("DMIC1 power", RT5677_DMIC_CTRL1,
SND_SOC_DAPM_PGA("DMIC4", RT5677_DMIC_CTRL2, RT5677_DMIC_4_EN_SFT, 0, RT5677_DMIC_1_EN_SFT, 0, NULL, 0),
NULL, 0), SND_SOC_DAPM_SUPPLY("DMIC2 power", RT5677_DMIC_CTRL1,
RT5677_DMIC_2_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DMIC3 power", RT5677_DMIC_CTRL1,
RT5677_DMIC_3_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DMIC4 power", RT5677_DMIC_CTRL2,
RT5677_DMIC_4_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
set_dmic_clk, SND_SOC_DAPM_PRE_PMU), set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
...@@ -2130,6 +2136,13 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { ...@@ -2130,6 +2136,13 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
{ "DMIC L4", NULL, "DMIC CLK" }, { "DMIC L4", NULL, "DMIC CLK" },
{ "DMIC R4", NULL, "DMIC CLK" }, { "DMIC R4", NULL, "DMIC CLK" },
{ "DMIC L1", NULL, "DMIC1 power" },
{ "DMIC R1", NULL, "DMIC1 power" },
{ "DMIC L3", NULL, "DMIC3 power" },
{ "DMIC R3", NULL, "DMIC3 power" },
{ "DMIC L4", NULL, "DMIC4 power" },
{ "DMIC R4", NULL, "DMIC4 power" },
{ "BST1", NULL, "IN1P" }, { "BST1", NULL, "IN1P" },
{ "BST1", NULL, "IN1N" }, { "BST1", NULL, "IN1N" },
{ "BST2", NULL, "IN2P" }, { "BST2", NULL, "IN2P" },
...@@ -2793,6 +2806,16 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { ...@@ -2793,6 +2806,16 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
{ "PDM2R", NULL, "PDM2 R Mux" }, { "PDM2R", NULL, "PDM2 R Mux" },
}; };
static const struct snd_soc_dapm_route rt5677_dmic2_clk_1[] = {
{ "DMIC L2", NULL, "DMIC1 power" },
{ "DMIC R2", NULL, "DMIC1 power" },
};
static const struct snd_soc_dapm_route rt5677_dmic2_clk_2[] = {
{ "DMIC L2", NULL, "DMIC2 power" },
{ "DMIC R2", NULL, "DMIC2 power" },
};
static int rt5677_hw_params(struct snd_pcm_substream *substream, static int rt5677_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{ {
...@@ -3138,12 +3161,148 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec, ...@@ -3138,12 +3161,148 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec,
return 0; return 0;
} }
#ifdef CONFIG_GPIOLIB
static inline struct rt5677_priv *gpio_to_rt5677(struct gpio_chip *chip)
{
return container_of(chip, struct rt5677_priv, gpio_chip);
}
static void rt5677_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct rt5677_priv *rt5677 = gpio_to_rt5677(chip);
switch (offset) {
case RT5677_GPIO1 ... RT5677_GPIO5:
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
0x1 << (offset * 3 + 1), !!value << (offset * 3 + 1));
break;
case RT5677_GPIO6:
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3,
RT5677_GPIO6_OUT_MASK, !!value << RT5677_GPIO6_OUT_SFT);
break;
default:
break;
}
}
static int rt5677_gpio_direction_out(struct gpio_chip *chip,
unsigned offset, int value)
{
struct rt5677_priv *rt5677 = gpio_to_rt5677(chip);
switch (offset) {
case RT5677_GPIO1 ... RT5677_GPIO5:
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
0x3 << (offset * 3 + 1),
(0x2 | !!value) << (offset * 3 + 1));
break;
case RT5677_GPIO6:
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3,
RT5677_GPIO6_DIR_MASK | RT5677_GPIO6_OUT_MASK,
RT5677_GPIO6_DIR_OUT | !!value << RT5677_GPIO6_OUT_SFT);
break;
default:
break;
}
return 0;
}
static int rt5677_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct rt5677_priv *rt5677 = gpio_to_rt5677(chip);
int value, ret;
ret = regmap_read(rt5677->regmap, RT5677_GPIO_ST, &value);
if (ret < 0)
return ret;
return (value & (0x1 << offset)) >> offset;
}
static int rt5677_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
struct rt5677_priv *rt5677 = gpio_to_rt5677(chip);
switch (offset) {
case RT5677_GPIO1 ... RT5677_GPIO5:
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
0x1 << (offset * 3 + 2), 0x0);
break;
case RT5677_GPIO6:
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3,
RT5677_GPIO6_DIR_MASK, RT5677_GPIO6_DIR_IN);
break;
default:
break;
}
return 0;
}
static struct gpio_chip rt5677_template_chip = {
.label = "rt5677",
.owner = THIS_MODULE,
.direction_output = rt5677_gpio_direction_out,
.set = rt5677_gpio_set,
.direction_input = rt5677_gpio_direction_in,
.get = rt5677_gpio_get,
.can_sleep = 1,
};
static void rt5677_init_gpio(struct i2c_client *i2c)
{
struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c);
int ret;
rt5677->gpio_chip = rt5677_template_chip;
rt5677->gpio_chip.ngpio = RT5677_GPIO_NUM;
rt5677->gpio_chip.dev = &i2c->dev;
rt5677->gpio_chip.base = -1;
ret = gpiochip_add(&rt5677->gpio_chip);
if (ret != 0)
dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret);
}
static void rt5677_free_gpio(struct i2c_client *i2c)
{
struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c);
gpiochip_remove(&rt5677->gpio_chip);
}
#else
static void rt5677_init_gpio(struct i2c_client *i2c)
{
}
static void rt5677_free_gpio(struct i2c_client *i2c)
{
}
#endif
static int rt5677_probe(struct snd_soc_codec *codec) static int rt5677_probe(struct snd_soc_codec *codec)
{ {
struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
rt5677->codec = codec; rt5677->codec = codec;
if (rt5677->pdata.dmic2_clk_pin == RT5677_DMIC_CLK2) {
snd_soc_dapm_add_routes(&codec->dapm,
rt5677_dmic2_clk_2,
ARRAY_SIZE(rt5677_dmic2_clk_2));
} else { /*use dmic1 clock by default*/
snd_soc_dapm_add_routes(&codec->dapm,
rt5677_dmic2_clk_1,
ARRAY_SIZE(rt5677_dmic2_clk_1));
}
rt5677_set_bias_level(codec, SND_SOC_BIAS_OFF); rt5677_set_bias_level(codec, SND_SOC_BIAS_OFF);
regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020); regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020);
...@@ -3381,6 +3540,17 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, ...@@ -3381,6 +3540,17 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt5677->regmap, RT5677_IN1, regmap_update_bits(rt5677->regmap, RT5677_IN1,
RT5677_IN_DF2, RT5677_IN_DF2); RT5677_IN_DF2, RT5677_IN_DF2);
if (rt5677->pdata.dmic2_clk_pin == RT5677_DMIC_CLK2) {
regmap_update_bits(rt5677->regmap, RT5677_GEN_CTRL2,
RT5677_GPIO5_FUNC_MASK,
RT5677_GPIO5_FUNC_DMIC);
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
RT5677_GPIO5_DIR_MASK,
RT5677_GPIO5_DIR_OUT);
}
rt5677_init_gpio(i2c);
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677,
rt5677_dai, ARRAY_SIZE(rt5677_dai)); rt5677_dai, ARRAY_SIZE(rt5677_dai));
} }
...@@ -3388,6 +3558,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, ...@@ -3388,6 +3558,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
static int rt5677_i2c_remove(struct i2c_client *i2c) static int rt5677_i2c_remove(struct i2c_client *i2c)
{ {
snd_soc_unregister_codec(&i2c->dev); snd_soc_unregister_codec(&i2c->dev);
rt5677_free_gpio(i2c);
return 0; return 0;
} }
......
...@@ -1287,16 +1287,16 @@ ...@@ -1287,16 +1287,16 @@
#define RT5677_PLL1_PD_SFT 8 #define RT5677_PLL1_PD_SFT 8
#define RT5677_PLL1_PD_1 (0x0 << 8) #define RT5677_PLL1_PD_1 (0x0 << 8)
#define RT5677_PLL1_PD_2 (0x1 << 8) #define RT5677_PLL1_PD_2 (0x1 << 8)
#define RT5671_DAC_OSR_MASK (0x3 << 6) #define RT5677_DAC_OSR_MASK (0x3 << 6)
#define RT5671_DAC_OSR_SFT 6 #define RT5677_DAC_OSR_SFT 6
#define RT5671_DAC_OSR_128 (0x0 << 6) #define RT5677_DAC_OSR_128 (0x0 << 6)
#define RT5671_DAC_OSR_64 (0x1 << 6) #define RT5677_DAC_OSR_64 (0x1 << 6)
#define RT5671_DAC_OSR_32 (0x2 << 6) #define RT5677_DAC_OSR_32 (0x2 << 6)
#define RT5671_ADC_OSR_MASK (0x3 << 4) #define RT5677_ADC_OSR_MASK (0x3 << 4)
#define RT5671_ADC_OSR_SFT 4 #define RT5677_ADC_OSR_SFT 4
#define RT5671_ADC_OSR_128 (0x0 << 4) #define RT5677_ADC_OSR_128 (0x0 << 4)
#define RT5671_ADC_OSR_64 (0x1 << 4) #define RT5677_ADC_OSR_64 (0x1 << 4)
#define RT5671_ADC_OSR_32 (0x2 << 4) #define RT5677_ADC_OSR_32 (0x2 << 4)
/* Global Clock Control 2 (0x81) */ /* Global Clock Control 2 (0x81) */
#define RT5677_PLL2_PR_SRC_MASK (0x1 << 15) #define RT5677_PLL2_PR_SRC_MASK (0x1 << 15)
...@@ -1312,18 +1312,18 @@ ...@@ -1312,18 +1312,18 @@
#define RT5677_PLL2_SRC_BCLK4 (0x4 << 12) #define RT5677_PLL2_SRC_BCLK4 (0x4 << 12)
#define RT5677_PLL2_SRC_RCCLK (0x5 << 12) #define RT5677_PLL2_SRC_RCCLK (0x5 << 12)
#define RT5677_PLL2_SRC_SLIM (0x6 << 12) #define RT5677_PLL2_SRC_SLIM (0x6 << 12)
#define RT5671_DSP_ASRC_O_SRC (0x3 << 10) #define RT5677_DSP_ASRC_O_SRC (0x3 << 10)
#define RT5671_DSP_ASRC_O_SRC_SFT 10 #define RT5677_DSP_ASRC_O_SRC_SFT 10
#define RT5671_DSP_ASRC_O_MCLK (0x0 << 10) #define RT5677_DSP_ASRC_O_MCLK (0x0 << 10)
#define RT5671_DSP_ASRC_O_PLL1 (0x1 << 10) #define RT5677_DSP_ASRC_O_PLL1 (0x1 << 10)
#define RT5671_DSP_ASRC_O_SLIM (0x2 << 10) #define RT5677_DSP_ASRC_O_SLIM (0x2 << 10)
#define RT5671_DSP_ASRC_O_RCCLK (0x3 << 10) #define RT5677_DSP_ASRC_O_RCCLK (0x3 << 10)
#define RT5671_DSP_ASRC_I_SRC (0x3 << 8) #define RT5677_DSP_ASRC_I_SRC (0x3 << 8)
#define RT5671_DSP_ASRC_I_SRC_SFT 8 #define RT5677_DSP_ASRC_I_SRC_SFT 8
#define RT5671_DSP_ASRC_I_MCLK (0x0 << 8) #define RT5677_DSP_ASRC_I_MCLK (0x0 << 8)
#define RT5671_DSP_ASRC_I_PLL1 (0x1 << 8) #define RT5677_DSP_ASRC_I_PLL1 (0x1 << 8)
#define RT5671_DSP_ASRC_I_SLIM (0x2 << 8) #define RT5677_DSP_ASRC_I_SLIM (0x2 << 8)
#define RT5671_DSP_ASRC_I_RCCLK (0x3 << 8) #define RT5677_DSP_ASRC_I_RCCLK (0x3 << 8)
#define RT5677_DSP_CLK_SRC_MASK (0x1 << 7) #define RT5677_DSP_CLK_SRC_MASK (0x1 << 7)
#define RT5677_DSP_CLK_SRC_SFT 7 #define RT5677_DSP_CLK_SRC_SFT 7
#define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7) #define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7)
...@@ -1363,6 +1363,110 @@ ...@@ -1363,6 +1363,110 @@
#define RT5677_SEL_SRC_IB01 (0x1 << 0) #define RT5677_SEL_SRC_IB01 (0x1 << 0)
#define RT5677_SEL_SRC_IB01_SFT 0 #define RT5677_SEL_SRC_IB01_SFT 0
/* GPIO status (0xbf) */
#define RT5677_GPIO6_STATUS_MASK (0x1 << 5)
#define RT5677_GPIO6_STATUS_SFT 5
#define RT5677_GPIO5_STATUS_MASK (0x1 << 4)
#define RT5677_GPIO5_STATUS_SFT 4
#define RT5677_GPIO4_STATUS_MASK (0x1 << 3)
#define RT5677_GPIO4_STATUS_SFT 3
#define RT5677_GPIO3_STATUS_MASK (0x1 << 2)
#define RT5677_GPIO3_STATUS_SFT 2
#define RT5677_GPIO2_STATUS_MASK (0x1 << 1)
#define RT5677_GPIO2_STATUS_SFT 1
#define RT5677_GPIO1_STATUS_MASK (0x1 << 0)
#define RT5677_GPIO1_STATUS_SFT 0
/* GPIO Control 1 (0xc0) */
#define RT5677_GPIO1_PIN_MASK (0x1 << 15)
#define RT5677_GPIO1_PIN_SFT 15
#define RT5677_GPIO1_PIN_GPIO1 (0x0 << 15)
#define RT5677_GPIO1_PIN_IRQ (0x1 << 15)
#define RT5677_IPTV_MODE_MASK (0x1 << 14)
#define RT5677_IPTV_MODE_SFT 14
#define RT5677_IPTV_MODE_GPIO (0x0 << 14)
#define RT5677_IPTV_MODE_IPTV (0x1 << 14)
#define RT5677_FUNC_MODE_MASK (0x1 << 13)
#define RT5677_FUNC_MODE_SFT 13
#define RT5677_FUNC_MODE_DMIC_GPIO (0x0 << 13)
#define RT5677_FUNC_MODE_JTAG (0x1 << 13)
/* GPIO Control 2 (0xc1) */
#define RT5677_GPIO5_DIR_MASK (0x1 << 14)
#define RT5677_GPIO5_DIR_SFT 14
#define RT5677_GPIO5_DIR_IN (0x0 << 14)
#define RT5677_GPIO5_DIR_OUT (0x1 << 14)
#define RT5677_GPIO5_OUT_MASK (0x1 << 13)
#define RT5677_GPIO5_OUT_SFT 13
#define RT5677_GPIO5_OUT_LO (0x0 << 13)
#define RT5677_GPIO5_OUT_HI (0x1 << 13)
#define RT5677_GPIO5_P_MASK (0x1 << 12)
#define RT5677_GPIO5_P_SFT 12
#define RT5677_GPIO5_P_NOR (0x0 << 12)
#define RT5677_GPIO5_P_INV (0x1 << 12)
#define RT5677_GPIO4_DIR_MASK (0x1 << 11)
#define RT5677_GPIO4_DIR_SFT 11
#define RT5677_GPIO4_DIR_IN (0x0 << 11)
#define RT5677_GPIO4_DIR_OUT (0x1 << 11)
#define RT5677_GPIO4_OUT_MASK (0x1 << 10)
#define RT5677_GPIO4_OUT_SFT 10
#define RT5677_GPIO4_OUT_LO (0x0 << 10)
#define RT5677_GPIO4_OUT_HI (0x1 << 10)
#define RT5677_GPIO4_P_MASK (0x1 << 9)
#define RT5677_GPIO4_P_SFT 9
#define RT5677_GPIO4_P_NOR (0x0 << 9)
#define RT5677_GPIO4_P_INV (0x1 << 9)
#define RT5677_GPIO3_DIR_MASK (0x1 << 8)
#define RT5677_GPIO3_DIR_SFT 8
#define RT5677_GPIO3_DIR_IN (0x0 << 8)
#define RT5677_GPIO3_DIR_OUT (0x1 << 8)
#define RT5677_GPIO3_OUT_MASK (0x1 << 7)
#define RT5677_GPIO3_OUT_SFT 7
#define RT5677_GPIO3_OUT_LO (0x0 << 7)
#define RT5677_GPIO3_OUT_HI (0x1 << 7)
#define RT5677_GPIO3_P_MASK (0x1 << 6)
#define RT5677_GPIO3_P_SFT 6
#define RT5677_GPIO3_P_NOR (0x0 << 6)
#define RT5677_GPIO3_P_INV (0x1 << 6)
#define RT5677_GPIO2_DIR_MASK (0x1 << 5)
#define RT5677_GPIO2_DIR_SFT 5
#define RT5677_GPIO2_DIR_IN (0x0 << 5)
#define RT5677_GPIO2_DIR_OUT (0x1 << 5)
#define RT5677_GPIO2_OUT_MASK (0x1 << 4)
#define RT5677_GPIO2_OUT_SFT 4
#define RT5677_GPIO2_OUT_LO (0x0 << 4)
#define RT5677_GPIO2_OUT_HI (0x1 << 4)
#define RT5677_GPIO2_P_MASK (0x1 << 3)
#define RT5677_GPIO2_P_SFT 3
#define RT5677_GPIO2_P_NOR (0x0 << 3)
#define RT5677_GPIO2_P_INV (0x1 << 3)
#define RT5677_GPIO1_DIR_MASK (0x1 << 2)
#define RT5677_GPIO1_DIR_SFT 2
#define RT5677_GPIO1_DIR_IN (0x0 << 2)
#define RT5677_GPIO1_DIR_OUT (0x1 << 2)
#define RT5677_GPIO1_OUT_MASK (0x1 << 1)
#define RT5677_GPIO1_OUT_SFT 1
#define RT5677_GPIO1_OUT_LO (0x0 << 1)
#define RT5677_GPIO1_OUT_HI (0x1 << 1)
#define RT5677_GPIO1_P_MASK (0x1 << 0)
#define RT5677_GPIO1_P_SFT 0
#define RT5677_GPIO1_P_NOR (0x0 << 0)
#define RT5677_GPIO1_P_INV (0x1 << 0)
/* GPIO Control 3 (0xc2) */
#define RT5677_GPIO6_DIR_MASK (0x1 << 2)
#define RT5677_GPIO6_DIR_SFT 2
#define RT5677_GPIO6_DIR_IN (0x0 << 2)
#define RT5677_GPIO6_DIR_OUT (0x1 << 2)
#define RT5677_GPIO6_OUT_MASK (0x1 << 1)
#define RT5677_GPIO6_OUT_SFT 1
#define RT5677_GPIO6_OUT_LO (0x0 << 1)
#define RT5677_GPIO6_OUT_HI (0x1 << 1)
#define RT5677_GPIO6_P_MASK (0x1 << 0)
#define RT5677_GPIO6_P_SFT 0
#define RT5677_GPIO6_P_NOR (0x0 << 0)
#define RT5677_GPIO6_P_INV (0x1 << 0)
/* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */ /* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */
#define RT5677_DSP_IB_01_H (0x1 << 15) #define RT5677_DSP_IB_01_H (0x1 << 15)
#define RT5677_DSP_IB_01_H_SFT 15 #define RT5677_DSP_IB_01_H_SFT 15
...@@ -1393,6 +1497,11 @@ ...@@ -1393,6 +1497,11 @@
#define RT5677_DSP_IB_9_L (0x1 << 1) #define RT5677_DSP_IB_9_L (0x1 << 1)
#define RT5677_DSP_IB_9_L_SFT 1 #define RT5677_DSP_IB_9_L_SFT 1
/* General Control2 (0xfc)*/
#define RT5677_GPIO5_FUNC_MASK (0x1 << 9)
#define RT5677_GPIO5_FUNC_GPIO (0x0 << 9)
#define RT5677_GPIO5_FUNC_DMIC (0x1 << 9)
/* System Clock Source */ /* System Clock Source */
enum { enum {
RT5677_SCLK_S_MCLK, RT5677_SCLK_S_MCLK,
...@@ -1418,6 +1527,16 @@ enum { ...@@ -1418,6 +1527,16 @@ enum {
RT5677_AIFS, RT5677_AIFS,
}; };
enum {
RT5677_GPIO1,
RT5677_GPIO2,
RT5677_GPIO3,
RT5677_GPIO4,
RT5677_GPIO5,
RT5677_GPIO6,
RT5677_GPIO_NUM,
};
struct rt5677_priv { struct rt5677_priv {
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
struct rt5677_platform_data pdata; struct rt5677_platform_data pdata;
...@@ -1431,6 +1550,9 @@ struct rt5677_priv { ...@@ -1431,6 +1550,9 @@ struct rt5677_priv {
int pll_src; int pll_src;
int pll_in; int pll_in;
int pll_out; int pll_out;
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
#endif
}; };
#endif /* __RT5677_H__ */ #endif /* __RT5677_H__ */
...@@ -646,17 +646,6 @@ static struct snd_soc_dai_driver ssm2518_dai = { ...@@ -646,17 +646,6 @@ static struct snd_soc_dai_driver ssm2518_dai = {
.ops = &ssm2518_dai_ops, .ops = &ssm2518_dai_ops,
}; };
static int ssm2518_probe(struct snd_soc_codec *codec)
{
return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
static int ssm2518_remove(struct snd_soc_codec *codec)
{
ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id, static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir) int source, unsigned int freq, int dir)
{ {
...@@ -727,8 +716,6 @@ static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id, ...@@ -727,8 +716,6 @@ static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id,
} }
static struct snd_soc_codec_driver ssm2518_codec_driver = { static struct snd_soc_codec_driver ssm2518_codec_driver = {
.probe = ssm2518_probe,
.remove = ssm2518_remove,
.set_bias_level = ssm2518_set_bias_level, .set_bias_level = ssm2518_set_bias_level,
.set_sysclk = ssm2518_set_sysclk, .set_sysclk = ssm2518_set_sysclk,
.idle_bias_off = true, .idle_bias_off = true,
......
...@@ -502,18 +502,11 @@ static struct snd_soc_dai_driver ssm2602_dai = { ...@@ -502,18 +502,11 @@ static struct snd_soc_dai_driver ssm2602_dai = {
.symmetric_samplebits = 1, .symmetric_samplebits = 1,
}; };
static int ssm2602_suspend(struct snd_soc_codec *codec)
{
ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int ssm2602_resume(struct snd_soc_codec *codec) static int ssm2602_resume(struct snd_soc_codec *codec)
{ {
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
regcache_sync(ssm2602->regmap); regcache_sync(ssm2602->regmap);
ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0; return 0;
} }
...@@ -586,27 +579,14 @@ static int ssm260x_codec_probe(struct snd_soc_codec *codec) ...@@ -586,27 +579,14 @@ static int ssm260x_codec_probe(struct snd_soc_codec *codec)
break; break;
} }
if (ret) return ret;
return ret;
ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
/* remove everything here */
static int ssm2602_remove(struct snd_soc_codec *codec)
{
ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
} }
static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
.probe = ssm260x_codec_probe, .probe = ssm260x_codec_probe,
.remove = ssm2602_remove,
.suspend = ssm2602_suspend,
.resume = ssm2602_resume, .resume = ssm2602_resume,
.set_bias_level = ssm2602_set_bias_level, .set_bias_level = ssm2602_set_bias_level,
.suspend_bias_off = true,
.controls = ssm260x_snd_controls, .controls = ssm260x_snd_controls,
.num_controls = ARRAY_SIZE(ssm260x_snd_controls), .num_controls = ARRAY_SIZE(ssm260x_snd_controls),
......
...@@ -1222,20 +1222,6 @@ static struct snd_soc_dai_driver aic3x_dai = { ...@@ -1222,20 +1222,6 @@ static struct snd_soc_dai_driver aic3x_dai = {
.symmetric_rates = 1, .symmetric_rates = 1,
}; };
static int aic3x_suspend(struct snd_soc_codec *codec)
{
aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int aic3x_resume(struct snd_soc_codec *codec)
{
aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
static void aic3x_mono_init(struct snd_soc_codec *codec) static void aic3x_mono_init(struct snd_soc_codec *codec)
{ {
/* DAC to Mono Line Out default volume and route to Output mixer */ /* DAC to Mono Line Out default volume and route to Output mixer */
...@@ -1429,8 +1415,6 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = { ...@@ -1429,8 +1415,6 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.idle_bias_off = true, .idle_bias_off = true,
.probe = aic3x_probe, .probe = aic3x_probe,
.remove = aic3x_remove, .remove = aic3x_remove,
.suspend = aic3x_suspend,
.resume = aic3x_resume,
.controls = aic3x_snd_controls, .controls = aic3x_snd_controls,
.num_controls = ARRAY_SIZE(aic3x_snd_controls), .num_controls = ARRAY_SIZE(aic3x_snd_controls),
.dapm_widgets = aic3x_dapm_widgets, .dapm_widgets = aic3x_dapm_widgets,
......
...@@ -2319,11 +2319,8 @@ static void wm5100_init_gpio(struct i2c_client *i2c) ...@@ -2319,11 +2319,8 @@ static void wm5100_init_gpio(struct i2c_client *i2c)
static void wm5100_free_gpio(struct i2c_client *i2c) static void wm5100_free_gpio(struct i2c_client *i2c)
{ {
struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c); struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
int ret;
ret = gpiochip_remove(&wm5100->gpio_chip); gpiochip_remove(&wm5100->gpio_chip);
if (ret != 0)
dev_err(&i2c->dev, "Failed to remove GPIOs: %d\n", ret);
} }
#else #else
static void wm5100_init_gpio(struct i2c_client *i2c) static void wm5100_init_gpio(struct i2c_client *i2c)
......
...@@ -518,23 +518,6 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec, ...@@ -518,23 +518,6 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
return 0; return 0;
} }
#ifdef CONFIG_PM
static int wm8804_suspend(struct snd_soc_codec *codec)
{
wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int wm8804_resume(struct snd_soc_codec *codec)
{
wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
#else
#define wm8804_suspend NULL
#define wm8804_resume NULL
#endif
static int wm8804_remove(struct snd_soc_codec *codec) static int wm8804_remove(struct snd_soc_codec *codec)
{ {
struct wm8804_priv *wm8804; struct wm8804_priv *wm8804;
...@@ -671,8 +654,6 @@ static struct snd_soc_dai_driver wm8804_dai = { ...@@ -671,8 +654,6 @@ static struct snd_soc_dai_driver wm8804_dai = {
static struct snd_soc_codec_driver soc_codec_dev_wm8804 = { static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
.probe = wm8804_probe, .probe = wm8804_probe,
.remove = wm8804_remove, .remove = wm8804_remove,
.suspend = wm8804_suspend,
.resume = wm8804_resume,
.set_bias_level = wm8804_set_bias_level, .set_bias_level = wm8804_set_bias_level,
.idle_bias_off = true, .idle_bias_off = true,
......
...@@ -1877,11 +1877,7 @@ static void wm8903_init_gpio(struct wm8903_priv *wm8903) ...@@ -1877,11 +1877,7 @@ static void wm8903_init_gpio(struct wm8903_priv *wm8903)
static void wm8903_free_gpio(struct wm8903_priv *wm8903) static void wm8903_free_gpio(struct wm8903_priv *wm8903)
{ {
int ret; gpiochip_remove(&wm8903->gpio_chip);
ret = gpiochip_remove(&wm8903->gpio_chip);
if (ret != 0)
dev_err(wm8903->dev, "Failed to remove GPIOs: %d\n", ret);
} }
#else #else
static void wm8903_init_gpio(struct wm8903_priv *wm8903) static void wm8903_init_gpio(struct wm8903_priv *wm8903)
......
...@@ -3398,11 +3398,8 @@ static void wm8962_init_gpio(struct snd_soc_codec *codec) ...@@ -3398,11 +3398,8 @@ static void wm8962_init_gpio(struct snd_soc_codec *codec)
static void wm8962_free_gpio(struct snd_soc_codec *codec) static void wm8962_free_gpio(struct snd_soc_codec *codec)
{ {
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
int ret;
ret = gpiochip_remove(&wm8962->gpio_chip); gpiochip_remove(&wm8962->gpio_chip);
if (ret != 0)
dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
} }
#else #else
static void wm8962_init_gpio(struct snd_soc_codec *codec) static void wm8962_init_gpio(struct snd_soc_codec *codec)
......
...@@ -1998,23 +1998,6 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec, ...@@ -1998,23 +1998,6 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec,
return 0; return 0;
} }
#ifdef CONFIG_PM
static int wm8995_suspend(struct snd_soc_codec *codec)
{
wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int wm8995_resume(struct snd_soc_codec *codec)
{
wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
#else
#define wm8995_suspend NULL
#define wm8995_resume NULL
#endif
static int wm8995_remove(struct snd_soc_codec *codec) static int wm8995_remove(struct snd_soc_codec *codec)
{ {
struct wm8995_priv *wm8995; struct wm8995_priv *wm8995;
...@@ -2220,8 +2203,6 @@ static struct snd_soc_dai_driver wm8995_dai[] = { ...@@ -2220,8 +2203,6 @@ static struct snd_soc_dai_driver wm8995_dai[] = {
static struct snd_soc_codec_driver soc_codec_dev_wm8995 = { static struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
.probe = wm8995_probe, .probe = wm8995_probe,
.remove = wm8995_remove, .remove = wm8995_remove,
.suspend = wm8995_suspend,
.resume = wm8995_resume,
.set_bias_level = wm8995_set_bias_level, .set_bias_level = wm8995_set_bias_level,
.idle_bias_off = true, .idle_bias_off = true,
}; };
......
...@@ -2216,11 +2216,7 @@ static void wm8996_init_gpio(struct wm8996_priv *wm8996) ...@@ -2216,11 +2216,7 @@ static void wm8996_init_gpio(struct wm8996_priv *wm8996)
static void wm8996_free_gpio(struct wm8996_priv *wm8996) static void wm8996_free_gpio(struct wm8996_priv *wm8996)
{ {
int ret; gpiochip_remove(&wm8996->gpio_chip);
ret = gpiochip_remove(&wm8996->gpio_chip);
if (ret != 0)
dev_err(wm8996->dev, "Failed to remove GPIOs: %d\n", ret);
} }
#else #else
static void wm8996_init_gpio(struct wm8996_priv *wm8996) static void wm8996_init_gpio(struct wm8996_priv *wm8996)
......
...@@ -42,14 +42,26 @@ ...@@ -42,14 +42,26 @@
#define MCASP_MAX_AFIFO_DEPTH 64 #define MCASP_MAX_AFIFO_DEPTH 64
static u32 context_regs[] = {
DAVINCI_MCASP_TXFMCTL_REG,
DAVINCI_MCASP_RXFMCTL_REG,
DAVINCI_MCASP_TXFMT_REG,
DAVINCI_MCASP_RXFMT_REG,
DAVINCI_MCASP_ACLKXCTL_REG,
DAVINCI_MCASP_ACLKRCTL_REG,
DAVINCI_MCASP_AHCLKXCTL_REG,
DAVINCI_MCASP_AHCLKRCTL_REG,
DAVINCI_MCASP_PDIR_REG,
DAVINCI_MCASP_RXMASK_REG,
DAVINCI_MCASP_TXMASK_REG,
DAVINCI_MCASP_RXTDM_REG,
DAVINCI_MCASP_TXTDM_REG,
};
struct davinci_mcasp_context { struct davinci_mcasp_context {
u32 txfmtctl; u32 config_regs[ARRAY_SIZE(context_regs)];
u32 rxfmtctl; u32 afifo_regs[2]; /* for read/write fifo control registers */
u32 txfmt; u32 *xrsr_regs; /* for serializer configuration */
u32 rxfmt;
u32 aclkxctl;
u32 aclkrctl;
u32 pdir;
}; };
struct davinci_mcasp { struct davinci_mcasp {
...@@ -874,14 +886,24 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai) ...@@ -874,14 +886,24 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
{ {
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
struct davinci_mcasp_context *context = &mcasp->context; struct davinci_mcasp_context *context = &mcasp->context;
u32 reg;
int i;
for (i = 0; i < ARRAY_SIZE(context_regs); i++)
context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
if (mcasp->txnumevt) {
reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
}
if (mcasp->rxnumevt) {
reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
}
context->txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); for (i = 0; i < mcasp->num_serializer; i++)
context->rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); context->xrsr_regs[i] = mcasp_get_reg(mcasp,
context->txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); DAVINCI_MCASP_XRSRCTL_REG(i));
context->rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG);
context->aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG);
context->aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG);
context->pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG);
return 0; return 0;
} }
...@@ -890,14 +912,24 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai) ...@@ -890,14 +912,24 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai)
{ {
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
struct davinci_mcasp_context *context = &mcasp->context; struct davinci_mcasp_context *context = &mcasp->context;
u32 reg;
int i;
for (i = 0; i < ARRAY_SIZE(context_regs); i++)
mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
if (mcasp->txnumevt) {
reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
}
if (mcasp->rxnumevt) {
reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
}
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, context->txfmtctl); for (i = 0; i < mcasp->num_serializer; i++)
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, context->rxfmtctl); mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, context->txfmt); context->xrsr_regs[i]);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, context->rxfmt);
mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, context->aclkxctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, context->aclkrctl);
mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, context->pdir);
return 0; return 0;
} }
...@@ -1216,6 +1248,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev) ...@@ -1216,6 +1248,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp->op_mode = pdata->op_mode; mcasp->op_mode = pdata->op_mode;
mcasp->tdm_slots = pdata->tdm_slots; mcasp->tdm_slots = pdata->tdm_slots;
mcasp->num_serializer = pdata->num_serializer; mcasp->num_serializer = pdata->num_serializer;
#ifdef CONFIG_PM_SLEEP
mcasp->context.xrsr_regs = devm_kzalloc(&pdev->dev,
sizeof(u32) * mcasp->num_serializer,
GFP_KERNEL);
#endif
mcasp->serial_dir = pdata->serial_dir; mcasp->serial_dir = pdata->serial_dir;
mcasp->version = pdata->version; mcasp->version = pdata->version;
mcasp->txnumevt = pdata->txnumevt; mcasp->txnumevt = pdata->txnumevt;
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <sound/dmaengine_pcm.h> #include <sound/dmaengine_pcm.h>
#include <linux/edma.h> #include <linux/edma.h>
#include "edma-pcm.h"
static const struct snd_pcm_hardware edma_pcm_hardware = { static const struct snd_pcm_hardware edma_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP | .info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_MMAP_VALID |
......
...@@ -288,9 +288,6 @@ config SND_SOC_FSL_ASOC_CARD ...@@ -288,9 +288,6 @@ config SND_SOC_FSL_ASOC_CARD
select SND_SOC_FSL_ESAI select SND_SOC_FSL_ESAI
select SND_SOC_FSL_SAI select SND_SOC_FSL_SAI
select SND_SOC_FSL_SSI select SND_SOC_FSL_SSI
select SND_SOC_CS42XX8_I2C
select SND_SOC_SGTL5000
select SND_SOC_WM8962
help help
ALSA SoC Audio support with ASRC feature for Freescale SoCs that have ALSA SoC Audio support with ASRC feature for Freescale SoCs that have
ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888 ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888
......
...@@ -637,7 +637,7 @@ int snd_soc_suspend(struct device *dev) ...@@ -637,7 +637,7 @@ int snd_soc_suspend(struct device *dev)
list_for_each_entry(codec, &card->codec_dev_list, card_list) { list_for_each_entry(codec, &card->codec_dev_list, card_list) {
/* If there are paths active then the CODEC will be held with /* If there are paths active then the CODEC will be held with
* bias _ON and should not be suspended. */ * bias _ON and should not be suspended. */
if (!codec->suspended && codec->driver->suspend) { if (!codec->suspended) {
switch (codec->dapm.bias_level) { switch (codec->dapm.bias_level) {
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
/* /*
...@@ -651,8 +651,10 @@ int snd_soc_suspend(struct device *dev) ...@@ -651,8 +651,10 @@ int snd_soc_suspend(struct device *dev)
"ASoC: idle_bias_off CODEC on over suspend\n"); "ASoC: idle_bias_off CODEC on over suspend\n");
break; break;
} }
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
codec->driver->suspend(codec); if (codec->driver->suspend)
codec->driver->suspend(codec);
codec->suspended = 1; codec->suspended = 1;
codec->cache_sync = 1; codec->cache_sync = 1;
if (codec->component.regmap) if (codec->component.regmap)
...@@ -726,11 +728,12 @@ static void soc_resume_deferred(struct work_struct *work) ...@@ -726,11 +728,12 @@ static void soc_resume_deferred(struct work_struct *work)
* left with bias OFF or STANDBY and suspended so we must now * left with bias OFF or STANDBY and suspended so we must now
* resume. Otherwise the suspend was suppressed. * resume. Otherwise the suspend was suppressed.
*/ */
if (codec->driver->resume && codec->suspended) { if (codec->suspended) {
switch (codec->dapm.bias_level) { switch (codec->dapm.bias_level) {
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
codec->driver->resume(codec); if (codec->driver->resume)
codec->driver->resume(codec);
codec->suspended = 0; codec->suspended = 0;
break; break;
default: default:
...@@ -3773,8 +3776,11 @@ EXPORT_SYMBOL_GPL(snd_soc_register_card); ...@@ -3773,8 +3776,11 @@ EXPORT_SYMBOL_GPL(snd_soc_register_card);
*/ */
int snd_soc_unregister_card(struct snd_soc_card *card) int snd_soc_unregister_card(struct snd_soc_card *card)
{ {
if (card->instantiated) if (card->instantiated) {
card->instantiated = false;
snd_soc_dapm_shutdown(card);
soc_cleanup_card_resources(card); soc_cleanup_card_resources(card);
}
dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
return 0; return 0;
...@@ -4348,6 +4354,7 @@ int snd_soc_register_codec(struct device *dev, ...@@ -4348,6 +4354,7 @@ int snd_soc_register_codec(struct device *dev,
codec->component.read = snd_soc_codec_drv_read; codec->component.read = snd_soc_codec_drv_read;
codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
codec->dapm.idle_bias_off = codec_drv->idle_bias_off; codec->dapm.idle_bias_off = codec_drv->idle_bias_off;
codec->dapm.suspend_bias_off = codec_drv->suspend_bias_off;
if (codec_drv->seq_notifier) if (codec_drv->seq_notifier)
codec->dapm.seq_notifier = codec_drv->seq_notifier; codec->dapm.seq_notifier = codec_drv->seq_notifier;
if (codec_drv->set_bias_level) if (codec_drv->set_bias_level)
......
...@@ -1684,6 +1684,22 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, ...@@ -1684,6 +1684,22 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
} }
} }
static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm)
{
if (dapm->idle_bias_off)
return true;
switch (snd_power_get_state(dapm->card->snd_card)) {
case SNDRV_CTL_POWER_D3hot:
case SNDRV_CTL_POWER_D3cold:
return dapm->suspend_bias_off;
default:
break;
}
return false;
}
/* /*
* Scan each dapm widget for complete audio path. * Scan each dapm widget for complete audio path.
* A complete path is a route that has valid endpoints i.e.:- * A complete path is a route that has valid endpoints i.e.:-
...@@ -1707,7 +1723,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) ...@@ -1707,7 +1723,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
trace_snd_soc_dapm_start(card); trace_snd_soc_dapm_start(card);
list_for_each_entry(d, &card->dapm_list, list) { list_for_each_entry(d, &card->dapm_list, list) {
if (d->idle_bias_off) if (dapm_idle_bias_off(d))
d->target_bias_level = SND_SOC_BIAS_OFF; d->target_bias_level = SND_SOC_BIAS_OFF;
else else
d->target_bias_level = SND_SOC_BIAS_STANDBY; d->target_bias_level = SND_SOC_BIAS_STANDBY;
...@@ -1773,7 +1789,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) ...@@ -1773,7 +1789,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event)
if (d->target_bias_level > bias) if (d->target_bias_level > bias)
bias = d->target_bias_level; bias = d->target_bias_level;
list_for_each_entry(d, &card->dapm_list, list) list_for_each_entry(d, &card->dapm_list, list)
if (!d->idle_bias_off) if (!dapm_idle_bias_off(d))
d->target_bias_level = bias; d->target_bias_level = bias;
trace_snd_soc_dapm_walk_done(card); trace_snd_soc_dapm_walk_done(card);
......
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