2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-17 01:34:00 +08:00

Merge branch 'fix/asoc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

* 'fix/asoc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ASoC: wm2000: Fix use-after-free - don't release_firmware() twice on error
  ASoC: wm8958: Use correct format string in dev_err() call
  ASoC: wm8996: Call _POST_PMU callback for CPVDD
  ASoC: mxs: Fix mxs-saif timeout
  ASoC: Disable register synchronisation for low frequency WM8996 SYSCLK
  ASoC: Don't go through cache when applying WM5100 rev A updates
  ASoC: Mark WM5100 register map cache only when going into BIAS_OFF
  ASoC: tlv320aic32x4: always enable analouge block
  ASoC: tlv320aic32x4: always enable dividers
  ASoC: sgtl5000: Fix wrong register name in restore
This commit is contained in:
Linus Torvalds 2012-01-25 15:13:04 -08:00
commit 486bc794ab
8 changed files with 86 additions and 73 deletions

View File

@ -987,12 +987,12 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
/* restore regular registers */ /* restore regular registers */
for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) { for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
/* this regs depends on the others */ /* These regs should restore in particular order */
if (reg == SGTL5000_CHIP_ANA_POWER || if (reg == SGTL5000_CHIP_ANA_POWER ||
reg == SGTL5000_CHIP_CLK_CTRL || reg == SGTL5000_CHIP_CLK_CTRL ||
reg == SGTL5000_CHIP_LINREG_CTRL || reg == SGTL5000_CHIP_LINREG_CTRL ||
reg == SGTL5000_CHIP_LINE_OUT_CTRL || reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
reg == SGTL5000_CHIP_CLK_CTRL) reg == SGTL5000_CHIP_REF_CTRL)
continue; continue;
snd_soc_write(codec, reg, cache[reg]); snd_soc_write(codec, reg, cache[reg]);
@ -1003,8 +1003,17 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
snd_soc_write(codec, reg, cache[reg]); snd_soc_write(codec, reg, cache[reg]);
/* /*
* restore power and other regs according * restore these regs according to the power setting sequence in
* to set_power() and set_clock() * sgtl5000_set_power_regs() and clock setting sequence in
* sgtl5000_set_clock().
*
* The order of restore is:
* 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
* SGTL5000_CHIP_ANA_POWER PLL bits set
* 2. SGTL5000_CHIP_LINREG_CTRL should be set before
* SGTL5000_CHIP_ANA_POWER LINREG_D restored
* 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
* prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
*/ */
snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
cache[SGTL5000_CHIP_LINREG_CTRL]); cache[SGTL5000_CHIP_LINREG_CTRL]);

View File

@ -60,7 +60,6 @@ struct aic32x4_rate_divs {
struct aic32x4_priv { struct aic32x4_priv {
u32 sysclk; u32 sysclk;
s32 master;
u8 page_no; u8 page_no;
void *control_data; void *control_data;
u32 power_cfg; u32 power_cfg;
@ -369,7 +368,6 @@ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
u8 iface_reg_1; u8 iface_reg_1;
u8 iface_reg_2; u8 iface_reg_2;
u8 iface_reg_3; u8 iface_reg_3;
@ -384,11 +382,9 @@ static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
/* set master/slave audio interface */ /* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_CBM_CFM:
aic32x4->master = 1;
iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER; iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER;
break; break;
case SND_SOC_DAIFMT_CBS_CFS: case SND_SOC_DAIFMT_CBS_CFS:
aic32x4->master = 0;
break; break;
default: default:
printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n"); printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n");
@ -526,64 +522,58 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute)
static int aic32x4_set_bias_level(struct snd_soc_codec *codec, static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
if (aic32x4->master) { /* Switch on PLL */
/* Switch on PLL */ snd_soc_update_bits(codec, AIC32X4_PLLPR,
snd_soc_update_bits(codec, AIC32X4_PLLPR, AIC32X4_PLLEN, AIC32X4_PLLEN);
AIC32X4_PLLEN, AIC32X4_PLLEN);
/* Switch on NDAC Divider */ /* Switch on NDAC Divider */
snd_soc_update_bits(codec, AIC32X4_NDAC, snd_soc_update_bits(codec, AIC32X4_NDAC,
AIC32X4_NDACEN, AIC32X4_NDACEN); AIC32X4_NDACEN, AIC32X4_NDACEN);
/* Switch on MDAC Divider */ /* Switch on MDAC Divider */
snd_soc_update_bits(codec, AIC32X4_MDAC, snd_soc_update_bits(codec, AIC32X4_MDAC,
AIC32X4_MDACEN, AIC32X4_MDACEN); AIC32X4_MDACEN, AIC32X4_MDACEN);
/* Switch on NADC Divider */ /* Switch on NADC Divider */
snd_soc_update_bits(codec, AIC32X4_NADC, snd_soc_update_bits(codec, AIC32X4_NADC,
AIC32X4_NADCEN, AIC32X4_NADCEN); AIC32X4_NADCEN, AIC32X4_NADCEN);
/* Switch on MADC Divider */ /* Switch on MADC Divider */
snd_soc_update_bits(codec, AIC32X4_MADC, snd_soc_update_bits(codec, AIC32X4_MADC,
AIC32X4_MADCEN, AIC32X4_MADCEN); AIC32X4_MADCEN, AIC32X4_MADCEN);
/* Switch on BCLK_N Divider */ /* Switch on BCLK_N Divider */
snd_soc_update_bits(codec, AIC32X4_BCLKN, snd_soc_update_bits(codec, AIC32X4_BCLKN,
AIC32X4_BCLKEN, AIC32X4_BCLKEN); AIC32X4_BCLKEN, AIC32X4_BCLKEN);
}
break; break;
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
if (aic32x4->master) { /* Switch off PLL */
/* Switch off PLL */ snd_soc_update_bits(codec, AIC32X4_PLLPR,
snd_soc_update_bits(codec, AIC32X4_PLLPR, AIC32X4_PLLEN, 0);
AIC32X4_PLLEN, 0);
/* Switch off NDAC Divider */ /* Switch off NDAC Divider */
snd_soc_update_bits(codec, AIC32X4_NDAC, snd_soc_update_bits(codec, AIC32X4_NDAC,
AIC32X4_NDACEN, 0); AIC32X4_NDACEN, 0);
/* Switch off MDAC Divider */ /* Switch off MDAC Divider */
snd_soc_update_bits(codec, AIC32X4_MDAC, snd_soc_update_bits(codec, AIC32X4_MDAC,
AIC32X4_MDACEN, 0); AIC32X4_MDACEN, 0);
/* Switch off NADC Divider */ /* Switch off NADC Divider */
snd_soc_update_bits(codec, AIC32X4_NADC, snd_soc_update_bits(codec, AIC32X4_NADC,
AIC32X4_NADCEN, 0); AIC32X4_NADCEN, 0);
/* Switch off MADC Divider */ /* Switch off MADC Divider */
snd_soc_update_bits(codec, AIC32X4_MADC, snd_soc_update_bits(codec, AIC32X4_MADC,
AIC32X4_MADCEN, 0); AIC32X4_MADCEN, 0);
/* Switch off BCLK_N Divider */ /* Switch off BCLK_N Divider */
snd_soc_update_bits(codec, AIC32X4_BCLKN, snd_soc_update_bits(codec, AIC32X4_BCLKN,
AIC32X4_BCLKEN, 0); AIC32X4_BCLKEN, 0);
}
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
break; break;
@ -651,9 +641,11 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) { if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
} }
if (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) {
snd_soc_write(codec, AIC32X4_LDOCTL, AIC32X4_LDOCTLEN); tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
} AIC32X4_LDOCTLEN : 0;
snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg);
tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE); tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) { if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
tmp_reg |= AIC32X4_LDOIN_18_36; tmp_reg |= AIC32X4_LDOIN_18_36;

View File

@ -733,8 +733,9 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
struct wm2000_priv *wm2000; struct wm2000_priv *wm2000;
struct wm2000_platform_data *pdata; struct wm2000_platform_data *pdata;
const char *filename; const char *filename;
const struct firmware *fw; const struct firmware *fw = NULL;
int reg, ret; int ret;
int reg;
u16 id; u16 id;
wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv), wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
@ -751,7 +752,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
ret = PTR_ERR(wm2000->regmap); ret = PTR_ERR(wm2000->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n", dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret); ret);
goto err; goto out;
} }
/* Verify that this is a WM2000 */ /* Verify that this is a WM2000 */
@ -763,7 +764,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
if (id != 0x2000) { if (id != 0x2000) {
dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
ret = -ENODEV; ret = -ENODEV;
goto err_regmap; goto out_regmap_exit;
} }
reg = wm2000_read(i2c, WM2000_REG_REVISON); reg = wm2000_read(i2c, WM2000_REG_REVISON);
@ -782,7 +783,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
ret = request_firmware(&fw, filename, &i2c->dev); ret = request_firmware(&fw, filename, &i2c->dev);
if (ret != 0) { if (ret != 0) {
dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
goto err_regmap; goto out_regmap_exit;
} }
/* Pre-cook the concatenation of the register address onto the image */ /* Pre-cook the concatenation of the register address onto the image */
@ -793,15 +794,13 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
if (wm2000->anc_download == NULL) { if (wm2000->anc_download == NULL) {
dev_err(&i2c->dev, "Out of memory\n"); dev_err(&i2c->dev, "Out of memory\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_fw; goto out_regmap_exit;
} }
wm2000->anc_download[0] = 0x80; wm2000->anc_download[0] = 0x80;
wm2000->anc_download[1] = 0x00; wm2000->anc_download[1] = 0x00;
memcpy(wm2000->anc_download + 2, fw->data, fw->size); memcpy(wm2000->anc_download + 2, fw->data, fw->size);
release_firmware(fw);
wm2000->anc_eng_ena = 1; wm2000->anc_eng_ena = 1;
wm2000->anc_active = 1; wm2000->anc_active = 1;
wm2000->spk_ena = 1; wm2000->spk_ena = 1;
@ -809,18 +808,14 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
wm2000_reset(wm2000); wm2000_reset(wm2000);
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0);
NULL, 0); if (!ret)
if (ret != 0) goto out;
goto err_fw;
return 0; out_regmap_exit:
err_fw:
release_firmware(fw);
err_regmap:
regmap_exit(wm2000->regmap); regmap_exit(wm2000->regmap);
err: out:
release_firmware(fw);
return ret; return ret;
} }

View File

@ -1377,6 +1377,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,
switch (wm5100->rev) { switch (wm5100->rev) {
case 0: case 0:
regcache_cache_bypass(wm5100->regmap, true);
snd_soc_write(codec, 0x11, 0x3); snd_soc_write(codec, 0x11, 0x3);
snd_soc_write(codec, 0x203, 0xc); snd_soc_write(codec, 0x203, 0xc);
snd_soc_write(codec, 0x206, 0); snd_soc_write(codec, 0x206, 0);
@ -1392,6 +1393,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,
snd_soc_write(codec, snd_soc_write(codec,
wm5100_reva_patches[i].reg, wm5100_reva_patches[i].reg,
wm5100_reva_patches[i].val); wm5100_reva_patches[i].val);
regcache_cache_bypass(wm5100->regmap, false);
break; break;
default: default:
break; break;
@ -1402,6 +1404,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
regcache_cache_only(wm5100->regmap, true);
if (wm5100->pdata.ldo_ena) if (wm5100->pdata.ldo_ena)
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),

View File

@ -55,7 +55,7 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name,
return 0; return 0;
if (fw->size < 32) { if (fw->size < 32) {
dev_err(codec->dev, "%s: firmware too short (%d bytes)\n", dev_err(codec->dev, "%s: firmware too short (%zd bytes)\n",
name, fw->size); name, fw->size);
goto err; goto err;
} }

View File

@ -1120,7 +1120,8 @@ SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event, SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
@ -2007,6 +2008,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int lfclk = 0; int lfclk = 0;
int ratediv = 0; int ratediv = 0;
int sync = WM8996_REG_SYNC;
int src; int src;
int old; int old;
@ -2051,6 +2053,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
case 32000: case 32000:
case 32768: case 32768:
lfclk = WM8996_LFCLK_ENA; lfclk = WM8996_LFCLK_ENA;
sync = 0;
break; break;
default: default:
dev_warn(codec->dev, "Unsupported clock rate %dHz\n", dev_warn(codec->dev, "Unsupported clock rate %dHz\n",
@ -2064,6 +2067,8 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
WM8996_SYSCLK_SRC_MASK | WM8996_SYSCLK_DIV_MASK, WM8996_SYSCLK_SRC_MASK | WM8996_SYSCLK_DIV_MASK,
src << WM8996_SYSCLK_SRC_SHIFT | ratediv); src << WM8996_SYSCLK_SRC_SHIFT | ratediv);
snd_soc_update_bits(codec, WM8996_CLOCKING_1, WM8996_LFCLK_ENA, lfclk); snd_soc_update_bits(codec, WM8996_CLOCKING_1, WM8996_LFCLK_ENA, lfclk);
snd_soc_update_bits(codec, WM8996_CONTROL_INTERFACE_1,
WM8996_REG_SYNC, sync);
snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1, snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1,
WM8996_SYSCLK_ENA, old); WM8996_SYSCLK_ENA, old);

View File

@ -1567,6 +1567,10 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
/* /*
* R257 (0x101) - Control Interface (1) * R257 (0x101) - Control Interface (1)
*/ */
#define WM8996_REG_SYNC 0x8000 /* REG_SYNC */
#define WM8996_REG_SYNC_MASK 0x8000 /* REG_SYNC */
#define WM8996_REG_SYNC_SHIFT 15 /* REG_SYNC */
#define WM8996_REG_SYNC_WIDTH 1 /* REG_SYNC */
#define WM8996_AUTO_INC 0x0004 /* AUTO_INC */ #define WM8996_AUTO_INC 0x0004 /* AUTO_INC */
#define WM8996_AUTO_INC_MASK 0x0004 /* AUTO_INC */ #define WM8996_AUTO_INC_MASK 0x0004 /* AUTO_INC */
#define WM8996_AUTO_INC_SHIFT 2 /* AUTO_INC */ #define WM8996_AUTO_INC_SHIFT 2 /* AUTO_INC */

View File

@ -124,6 +124,8 @@ static int mxs_saif_set_clk(struct mxs_saif *saif,
* *
* If MCLK is not used, we just set saif clk to 512*fs. * If MCLK is not used, we just set saif clk to 512*fs.
*/ */
clk_prepare_enable(master_saif->clk);
if (master_saif->mclk_in_use) { if (master_saif->mclk_in_use) {
if (mclk % 32 == 0) { if (mclk % 32 == 0) {
scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
@ -133,6 +135,7 @@ static int mxs_saif_set_clk(struct mxs_saif *saif,
ret = clk_set_rate(master_saif->clk, 384 * rate); ret = clk_set_rate(master_saif->clk, 384 * rate);
} else { } else {
/* SAIF MCLK should be either 32x or 48x */ /* SAIF MCLK should be either 32x or 48x */
clk_disable_unprepare(master_saif->clk);
return -EINVAL; return -EINVAL;
} }
} else { } else {
@ -140,6 +143,8 @@ static int mxs_saif_set_clk(struct mxs_saif *saif,
scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
} }
clk_disable_unprepare(master_saif->clk);
if (ret) if (ret)
return ret; return ret;