diff options
28 files changed, 438 insertions, 239 deletions
diff --git a/include/sound/rt5677.h b/include/sound/rt5677.h index 3da1431..a676717 100644 --- a/include/sound/rt5677.h +++ b/include/sound/rt5677.h @@ -12,10 +12,18 @@ #ifndef __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 { /* IN1 IN2 can optionally be differential */ bool in1_diff; bool in2_diff; + /* DMIC2 clock source selection */ + enum rt5677_dmic2_clk dmic2_clk_pin; }; #endif diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 507d58a..3a4d7da 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -588,7 +588,8 @@ struct snd_soc_dapm_context { enum snd_soc_bias_level suspend_bias_level; struct delayed_work delayed_work; 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 *, enum snd_soc_dapm_type, int); diff --git a/include/sound/soc.h b/include/sound/soc.h index f90f605..7ba7130 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -847,6 +847,7 @@ struct snd_soc_codec_driver { int (*set_bias_level)(struct snd_soc_codec *, enum snd_soc_bias_level level); bool idle_bias_off; + bool suspend_bias_off; void (*seq_notifier)(struct snd_soc_dapm_context *, enum snd_soc_dapm_type, int); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 184ee7e..7678122 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -57,6 +57,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_DA7213 if I2C select SND_SOC_DA732X if I2C select SND_SOC_DA9055 if I2C + select SND_SOC_DMIC select SND_SOC_BT_SCO select SND_SOC_ES8328_SPI if SPI_MASTER select SND_SOC_ES8328_I2C if I2C diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 1ff7d4d..7c784ad 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1448,29 +1448,10 @@ static int adau1373_set_bias_level(struct snd_soc_codec *codec, 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) { 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); return 0; @@ -1501,8 +1482,6 @@ static const struct regmap_config adau1373_regmap_config = { static struct snd_soc_codec_driver adau1373_codec_driver = { .probe = adau1373_probe, - .remove = adau1373_remove, - .suspend = adau1373_suspend, .resume = adau1373_resume, .set_bias_level = adau1373_set_bias_level, .idle_bias_off = true, diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 848cab8..5518ebd 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c @@ -714,9 +714,9 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec) static const struct snd_soc_codec_driver adau1761_codec_driver = { .probe = adau1761_codec_probe, - .suspend = adau17x1_suspend, .resume = adau17x1_resume, .set_bias_level = adau1761_set_bias_level, + .suspend_bias_off = true, .controls = adau1761_controls, .num_controls = ARRAY_SIZE(adau1761_controls), diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c index 045a614..e9fc00f 100644 --- a/sound/soc/codecs/adau1781.c +++ b/sound/soc/codecs/adau1781.c @@ -446,9 +446,9 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec) static const struct snd_soc_codec_driver adau1781_codec_driver = { .probe = adau1781_codec_probe, - .suspend = adau17x1_suspend, .resume = adau17x1_resume, .set_bias_level = adau1781_set_bias_level, + .suspend_bias_off = true, .controls = adau1781_controls, .num_controls = ARRAY_SIZE(adau1781_controls), diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 0b65970..3e16c1c 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -815,13 +815,6 @@ int adau17x1_add_routes(struct snd_soc_codec *codec) } 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) { struct adau *adau = snd_soc_codec_get_drvdata(codec); @@ -829,7 +822,6 @@ int adau17x1_resume(struct snd_soc_codec *codec) if (adau->switch_mode) adau->switch_mode(codec->dev); - codec->driver->set_bias_level(codec, SND_SOC_BIAS_STANDBY); regcache_sync(adau->regmap); return 0; diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h index 3ffabaf..e4a557f 100644 --- a/sound/soc/codecs/adau17x1.h +++ b/sound/soc/codecs/adau17x1.h @@ -52,7 +52,6 @@ int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, enum adau17x1_micbias_voltage micbias); bool adau17x1_readable_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); extern const struct snd_soc_dai_ops adau17x1_dai_ops; diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index c43b93f..ce3cdca 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -812,42 +812,23 @@ static int adav80x_probe(struct snd_soc_codec *codec) /* Disable DAC zero flag */ regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6); - return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -} - -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; + return 0; } static int adav80x_resume(struct snd_soc_codec *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); 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 = { .probe = adav80x_probe, - .remove = adav80x_remove, - .suspend = adav80x_suspend, .resume = adav80x_resume, .set_bias_level = adav80x_set_bias_level, + .suspend_bias_off = true, .set_pll = adav80x_set_pll, .set_sysclk = adav80x_set_sysclk, diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 7a9f65a..f273251 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -602,8 +602,6 @@ static int es8328_suspend(struct snd_soc_codec *codec) es8328 = snd_soc_codec_get_drvdata(codec); - es8328_set_bias_level(codec, SND_SOC_BIAS_OFF); - clk_disable_unprepare(es8328->clk); ret = regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), @@ -643,7 +641,6 @@ static int es8328_resume(struct snd_soc_codec *codec) return ret; } - es8328_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } @@ -665,6 +662,7 @@ static int es8328_codec_probe(struct snd_soc_codec *codec) es8328->clk = devm_clk_get(codec->dev, NULL); if (IS_ERR(es8328->clk)) { dev_err(codec->dev, "codec clock missing or invalid\n"); + ret = PTR_ERR(es8328->clk); goto clk_fail; } @@ -711,6 +709,8 @@ static struct snd_soc_codec_driver es8328_codec_driver = { .resume = es8328_resume, .remove = es8328_remove, .set_bias_level = es8328_set_bias_level, + .suspend_bias_off = true, + .controls = es8328_snd_controls, .num_controls = ARRAY_SIZE(es8328_snd_controls), .dapm_widgets = es8328_dapm_widgets, diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 275b3f7..c1ae576 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -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 */ 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 = { .remove = lm49453_remove, - .suspend = lm49453_suspend, - .resume = lm49453_resume, .set_bias_level = lm49453_set_bias_level, .controls = lm49453_snd_controls, .num_controls = ARRAY_SIZE(lm49453_snd_controls), diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 5337c44..dc978ad 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/gpio.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -1700,14 +1701,19 @@ static const struct snd_soc_dapm_widget rt5677_dapm_widgets[] = { SND_SOC_DAPM_INPUT("Haptic Generator"), - SND_SOC_DAPM_PGA("DMIC1", RT5677_DMIC_CTRL1, RT5677_DMIC_1_EN_SFT, 0, - NULL, 0), - SND_SOC_DAPM_PGA("DMIC2", RT5677_DMIC_CTRL1, RT5677_DMIC_2_EN_SFT, 0, - NULL, 0), - SND_SOC_DAPM_PGA("DMIC3", RT5677_DMIC_CTRL1, RT5677_DMIC_3_EN_SFT, 0, - NULL, 0), - SND_SOC_DAPM_PGA("DMIC4", RT5677_DMIC_CTRL2, RT5677_DMIC_4_EN_SFT, 0, - NULL, 0), + SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DMIC3", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DMIC4", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("DMIC1 power", RT5677_DMIC_CTRL1, + RT5677_DMIC_1_EN_SFT, 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, set_dmic_clk, SND_SOC_DAPM_PRE_PMU), @@ -2130,6 +2136,13 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { { "DMIC L4", 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, "IN1N" }, { "BST2", NULL, "IN2P" }, @@ -2793,6 +2806,16 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = { { "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, 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, 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) { struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(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); regmap_write(rt5677->regmap, RT5677_DIG_MISC, 0x0020); @@ -3381,6 +3540,17 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, regmap_update_bits(rt5677->regmap, RT5677_IN1, 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, rt5677_dai, ARRAY_SIZE(rt5677_dai)); } @@ -3388,6 +3558,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, static int rt5677_i2c_remove(struct i2c_client *i2c) { snd_soc_unregister_codec(&i2c->dev); + rt5677_free_gpio(i2c); return 0; } diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 863393e..b61b72c 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h @@ -1287,16 +1287,16 @@ #define RT5677_PLL1_PD_SFT 8 #define RT5677_PLL1_PD_1 (0x0 << 8) #define RT5677_PLL1_PD_2 (0x1 << 8) -#define RT5671_DAC_OSR_MASK (0x3 << 6) -#define RT5671_DAC_OSR_SFT 6 -#define RT5671_DAC_OSR_128 (0x0 << 6) -#define RT5671_DAC_OSR_64 (0x1 << 6) -#define RT5671_DAC_OSR_32 (0x2 << 6) -#define RT5671_ADC_OSR_MASK (0x3 << 4) -#define RT5671_ADC_OSR_SFT 4 -#define RT5671_ADC_OSR_128 (0x0 << 4) -#define RT5671_ADC_OSR_64 (0x1 << 4) -#define RT5671_ADC_OSR_32 (0x2 << 4) +#define RT5677_DAC_OSR_MASK (0x3 << 6) +#define RT5677_DAC_OSR_SFT 6 +#define RT5677_DAC_OSR_128 (0x0 << 6) +#define RT5677_DAC_OSR_64 (0x1 << 6) +#define RT5677_DAC_OSR_32 (0x2 << 6) +#define RT5677_ADC_OSR_MASK (0x3 << 4) +#define RT5677_ADC_OSR_SFT 4 +#define RT5677_ADC_OSR_128 (0x0 << 4) +#define RT5677_ADC_OSR_64 (0x1 << 4) +#define RT5677_ADC_OSR_32 (0x2 << 4) /* Global Clock Control 2 (0x81) */ #define RT5677_PLL2_PR_SRC_MASK (0x1 << 15) @@ -1312,18 +1312,18 @@ #define RT5677_PLL2_SRC_BCLK4 (0x4 << 12) #define RT5677_PLL2_SRC_RCCLK (0x5 << 12) #define RT5677_PLL2_SRC_SLIM (0x6 << 12) -#define RT5671_DSP_ASRC_O_SRC (0x3 << 10) -#define RT5671_DSP_ASRC_O_SRC_SFT 10 -#define RT5671_DSP_ASRC_O_MCLK (0x0 << 10) -#define RT5671_DSP_ASRC_O_PLL1 (0x1 << 10) -#define RT5671_DSP_ASRC_O_SLIM (0x2 << 10) -#define RT5671_DSP_ASRC_O_RCCLK (0x3 << 10) -#define RT5671_DSP_ASRC_I_SRC (0x3 << 8) -#define RT5671_DSP_ASRC_I_SRC_SFT 8 -#define RT5671_DSP_ASRC_I_MCLK (0x0 << 8) -#define RT5671_DSP_ASRC_I_PLL1 (0x1 << 8) -#define RT5671_DSP_ASRC_I_SLIM (0x2 << 8) -#define RT5671_DSP_ASRC_I_RCCLK (0x3 << 8) +#define RT5677_DSP_ASRC_O_SRC (0x3 << 10) +#define RT5677_DSP_ASRC_O_SRC_SFT 10 +#define RT5677_DSP_ASRC_O_MCLK (0x0 << 10) +#define RT5677_DSP_ASRC_O_PLL1 (0x1 << 10) +#define RT5677_DSP_ASRC_O_SLIM (0x2 << 10) +#define RT5677_DSP_ASRC_O_RCCLK (0x3 << 10) +#define RT5677_DSP_ASRC_I_SRC (0x3 << 8) +#define RT5677_DSP_ASRC_I_SRC_SFT 8 +#define RT5677_DSP_ASRC_I_MCLK (0x0 << 8) +#define RT5677_DSP_ASRC_I_PLL1 (0x1 << 8) +#define RT5677_DSP_ASRC_I_SLIM (0x2 << 8) +#define RT5677_DSP_ASRC_I_RCCLK (0x3 << 8) #define RT5677_DSP_CLK_SRC_MASK (0x1 << 7) #define RT5677_DSP_CLK_SRC_SFT 7 #define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7) @@ -1363,6 +1363,110 @@ #define RT5677_SEL_SRC_IB01 (0x1 << 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) */ #define RT5677_DSP_IB_01_H (0x1 << 15) #define RT5677_DSP_IB_01_H_SFT 15 @@ -1393,6 +1497,11 @@ #define RT5677_DSP_IB_9_L (0x1 << 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 */ enum { RT5677_SCLK_S_MCLK, @@ -1418,6 +1527,16 @@ enum { RT5677_AIFS, }; +enum { + RT5677_GPIO1, + RT5677_GPIO2, + RT5677_GPIO3, + RT5677_GPIO4, + RT5677_GPIO5, + RT5677_GPIO6, + RT5677_GPIO_NUM, +}; + struct rt5677_priv { struct snd_soc_codec *codec; struct rt5677_platform_data pdata; @@ -1431,6 +1550,9 @@ struct rt5677_priv { int pll_src; int pll_in; int pll_out; +#ifdef CONFIG_GPIOLIB + struct gpio_chip gpio_chip; +#endif }; #endif /* __RT5677_H__ */ diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index e8680be..67ea55a 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -646,17 +646,6 @@ static struct snd_soc_dai_driver ssm2518_dai = { .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, int source, unsigned int freq, int dir) { @@ -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 = { - .probe = ssm2518_probe, - .remove = ssm2518_remove, .set_bias_level = ssm2518_set_bias_level, .set_sysclk = ssm2518_set_sysclk, .idle_bias_off = true, diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 4021cd4..527de04 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -502,18 +502,11 @@ static struct snd_soc_dai_driver ssm2602_dai = { .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) { struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); regcache_sync(ssm2602->regmap); - ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } @@ -586,27 +579,14 @@ static int ssm260x_codec_probe(struct snd_soc_codec *codec) break; } - if (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; + return ret; } static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { .probe = ssm260x_codec_probe, - .remove = ssm2602_remove, - .suspend = ssm2602_suspend, .resume = ssm2602_resume, .set_bias_level = ssm2602_set_bias_level, + .suspend_bias_off = true, .controls = ssm260x_snd_controls, .num_controls = ARRAY_SIZE(ssm260x_snd_controls), diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 64f179e..f2c416d 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1222,20 +1222,6 @@ static struct snd_soc_dai_driver aic3x_dai = { .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) { /* 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 = { .idle_bias_off = true, .probe = aic3x_probe, .remove = aic3x_remove, - .suspend = aic3x_suspend, - .resume = aic3x_resume, .controls = aic3x_snd_controls, .num_controls = ARRAY_SIZE(aic3x_snd_controls), .dapm_widgets = aic3x_dapm_widgets, diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 7bb0d36..a01ad62 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2319,11 +2319,8 @@ static void wm5100_init_gpio(struct i2c_client *i2c) static void wm5100_free_gpio(struct i2c_client *i2c) { struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c); - int ret; - ret = gpiochip_remove(&wm5100->gpio_chip); - if (ret != 0) - dev_err(&i2c->dev, "Failed to remove GPIOs: %d\n", ret); + gpiochip_remove(&wm5100->gpio_chip); } #else static void wm5100_init_gpio(struct i2c_client *i2c) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 0ea01df..3addc5f 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -518,23 +518,6 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec, 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) { struct wm8804_priv *wm8804; @@ -671,8 +654,6 @@ static struct snd_soc_dai_driver wm8804_dai = { static struct snd_soc_codec_driver soc_codec_dev_wm8804 = { .probe = wm8804_probe, .remove = wm8804_remove, - .suspend = wm8804_suspend, - .resume = wm8804_resume, .set_bias_level = wm8804_set_bias_level, .idle_bias_off = true, diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index aa09848..c038b3e 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1877,11 +1877,7 @@ static void wm8903_init_gpio(struct wm8903_priv *wm8903) static void wm8903_free_gpio(struct wm8903_priv *wm8903) { - int ret; - - ret = gpiochip_remove(&wm8903->gpio_chip); - if (ret != 0) - dev_err(wm8903->dev, "Failed to remove GPIOs: %d\n", ret); + gpiochip_remove(&wm8903->gpio_chip); } #else static void wm8903_init_gpio(struct wm8903_priv *wm8903) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 1098ae3..9077411 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3398,11 +3398,8 @@ static void wm8962_init_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); - int ret; - ret = gpiochip_remove(&wm8962->gpio_chip); - if (ret != 0) - dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); + gpiochip_remove(&wm8962->gpio_chip); } #else static void wm8962_init_gpio(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index cae4ac5..1288ede 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -1998,23 +1998,6 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec, 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) { struct wm8995_priv *wm8995; @@ -2220,8 +2203,6 @@ static struct snd_soc_dai_driver wm8995_dai[] = { static struct snd_soc_codec_driver soc_codec_dev_wm8995 = { .probe = wm8995_probe, .remove = wm8995_remove, - .suspend = wm8995_suspend, - .resume = wm8995_resume, .set_bias_level = wm8995_set_bias_level, .idle_bias_off = true, }; diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index f16ff4f..b1dcc11 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2216,11 +2216,7 @@ static void wm8996_init_gpio(struct wm8996_priv *wm8996) static void wm8996_free_gpio(struct wm8996_priv *wm8996) { - int ret; - - ret = gpiochip_remove(&wm8996->gpio_chip); - if (ret != 0) - dev_err(wm8996->dev, "Failed to remove GPIOs: %d\n", ret); + gpiochip_remove(&wm8996->gpio_chip); } #else static void wm8996_init_gpio(struct wm8996_priv *wm8996) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 68347b5..0eed9b1 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -42,14 +42,26 @@ #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 { - u32 txfmtctl; - u32 rxfmtctl; - u32 txfmt; - u32 rxfmt; - u32 aclkxctl; - u32 aclkrctl; - u32 pdir; + u32 config_regs[ARRAY_SIZE(context_regs)]; + u32 afifo_regs[2]; /* for read/write fifo control registers */ + u32 *xrsr_regs; /* for serializer configuration */ }; struct davinci_mcasp { @@ -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_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); - context->rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); - context->txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); - 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); + for (i = 0; i < mcasp->num_serializer; i++) + context->xrsr_regs[i] = mcasp_get_reg(mcasp, + DAVINCI_MCASP_XRSRCTL_REG(i)); return 0; } @@ -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_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); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, context->rxfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, context->txfmt); - 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); + for (i = 0; i < mcasp->num_serializer; i++) + mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), + context->xrsr_regs[i]); return 0; } @@ -1216,6 +1248,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev) mcasp->op_mode = pdata->op_mode; mcasp->tdm_slots = pdata->tdm_slots; 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->version = pdata->version; mcasp->txnumevt = pdata->txnumevt; diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c index 605e643..59e588a 100644 --- a/sound/soc/davinci/edma-pcm.c +++ b/sound/soc/davinci/edma-pcm.c @@ -25,6 +25,8 @@ #include <sound/dmaengine_pcm.h> #include <linux/edma.h> +#include "edma-pcm.h" + static const struct snd_pcm_hardware edma_pcm_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 6164e78..081e406 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -288,9 +288,6 @@ config SND_SOC_FSL_ASOC_CARD select SND_SOC_FSL_ESAI select SND_SOC_FSL_SAI select SND_SOC_FSL_SSI - select SND_SOC_CS42XX8_I2C - select SND_SOC_SGTL5000 - select SND_SOC_WM8962 help ALSA SoC Audio support with ASRC feature for Freescale SoCs that have ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888 diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 57de6a7..3d8cff6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -637,7 +637,7 @@ int snd_soc_suspend(struct device *dev) list_for_each_entry(codec, &card->codec_dev_list, card_list) { /* If there are paths active then the CODEC will be held with * bias _ON and should not be suspended. */ - if (!codec->suspended && codec->driver->suspend) { + if (!codec->suspended) { switch (codec->dapm.bias_level) { case SND_SOC_BIAS_STANDBY: /* @@ -651,8 +651,10 @@ int snd_soc_suspend(struct device *dev) "ASoC: idle_bias_off CODEC on over suspend\n"); break; } + case SND_SOC_BIAS_OFF: - codec->driver->suspend(codec); + if (codec->driver->suspend) + codec->driver->suspend(codec); codec->suspended = 1; codec->cache_sync = 1; if (codec->component.regmap) @@ -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 * resume. Otherwise the suspend was suppressed. */ - if (codec->driver->resume && codec->suspended) { + if (codec->suspended) { switch (codec->dapm.bias_level) { case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_OFF: - codec->driver->resume(codec); + if (codec->driver->resume) + codec->driver->resume(codec); codec->suspended = 0; break; default: @@ -3773,8 +3776,11 @@ EXPORT_SYMBOL_GPL(snd_soc_register_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); + } dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); return 0; @@ -4348,6 +4354,7 @@ int snd_soc_register_codec(struct device *dev, codec->component.read = snd_soc_codec_drv_read; codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; 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) codec->dapm.seq_notifier = codec_drv->seq_notifier; if (codec_drv->set_bias_level) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5c21cde..2c456a3 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -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. * 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) trace_snd_soc_dapm_start(card); 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; else d->target_bias_level = SND_SOC_BIAS_STANDBY; @@ -1773,7 +1789,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) if (d->target_bias_level > bias) bias = d->target_bias_level; 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; trace_snd_soc_dapm_walk_done(card); |