Skip to content

Commit

Permalink
Merge tag 'asoc-fix-ac97-v3.19-rc7' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/broonie/sound into for-linus

ASoC: AC'97 fixes

These are rather too large for this late in the release cycle but
they're clear, well understood and have been tested to fix a regression
which was introduced for v3.19.  The details are all in Lars' changelog
and they've been cooking in -next for a while, to a large extent out
of conservatism about the size.
  • Loading branch information
Takashi Iwai committed Feb 5, 2015
2 parents deb0873 + f8d71be commit d2255c0
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 20 deletions.
1 change: 1 addition & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
unsigned int mask, unsigned int value);

#ifdef CONFIG_SND_SOC_AC97_BUS
struct snd_ac97 *snd_soc_alloc_ac97_codec(struct snd_soc_codec *codec);
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec);
void snd_soc_free_ac97_codec(struct snd_ac97 *ac97);

Expand Down
16 changes: 10 additions & 6 deletions sound/soc/codecs/wm9705.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,23 +344,27 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec)
struct snd_ac97 *ac97;
int ret = 0;

ac97 = snd_soc_new_ac97_codec(codec);
ac97 = snd_soc_alloc_ac97_codec(codec);
if (IS_ERR(ac97)) {
ret = PTR_ERR(ac97);
dev_err(codec->dev, "Failed to register AC97 codec\n");
return ret;
}

snd_soc_codec_set_drvdata(codec, ac97);

ret = wm9705_reset(codec);
if (ret)
goto reset_err;
goto err_put_device;

ret = device_add(&ac97->dev);
if (ret)
goto err_put_device;

snd_soc_codec_set_drvdata(codec, ac97);

return 0;

reset_err:
snd_soc_free_ac97_codec(ac97);
err_put_device:
put_device(&ac97->dev);
return ret;
}

Expand Down
12 changes: 8 additions & 4 deletions sound/soc/codecs/wm9712.c
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec);
int ret = 0;

wm9712->ac97 = snd_soc_new_ac97_codec(codec);
wm9712->ac97 = snd_soc_alloc_ac97_codec(codec);
if (IS_ERR(wm9712->ac97)) {
ret = PTR_ERR(wm9712->ac97);
dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
Expand All @@ -675,15 +675,19 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)

ret = wm9712_reset(codec, 0);
if (ret < 0)
goto reset_err;
goto err_put_device;

ret = device_add(&wm9712->ac97->dev);
if (ret)
goto err_put_device;

/* set alc mux to none */
ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);

return 0;

reset_err:
snd_soc_free_ac97_codec(wm9712->ac97);
err_put_device:
put_device(&wm9712->ac97->dev);
return ret;
}

Expand Down
12 changes: 8 additions & 4 deletions sound/soc/codecs/wm9713.c
Original file line number Diff line number Diff line change
Expand Up @@ -1225,7 +1225,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
int ret = 0, reg;

wm9713->ac97 = snd_soc_new_ac97_codec(codec);
wm9713->ac97 = snd_soc_alloc_ac97_codec(codec);
if (IS_ERR(wm9713->ac97))
return PTR_ERR(wm9713->ac97);

Expand All @@ -1234,16 +1234,20 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
wm9713_reset(codec, 0);
ret = wm9713_reset(codec, 1);
if (ret < 0)
goto reset_err;
goto err_put_device;

ret = device_add(&wm9713->ac97->dev);
if (ret)
goto err_put_device;

/* unmute the adc - move to kcontrol */
reg = ac97_read(codec, AC97_CD) & 0x7fff;
ac97_write(codec, AC97_CD, reg);

return 0;

reset_err:
snd_soc_free_ac97_codec(wm9713->ac97);
err_put_device:
put_device(&wm9713->ac97->dev);
return ret;
}

Expand Down
36 changes: 30 additions & 6 deletions sound/soc/soc-ac97.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,18 @@ static void soc_ac97_device_release(struct device *dev)
}

/**
* snd_soc_new_ac97_codec - initailise AC97 device
* @codec: audio codec
* snd_soc_alloc_ac97_codec() - Allocate new a AC'97 device
* @codec: The CODEC for which to create the AC'97 device
*
* Initialises AC97 codec resources for use by ad-hoc devices only.
* Allocated a new snd_ac97 device and intializes it, but does not yet register
* it. The caller is responsible to either call device_add(&ac97->dev) to
* register the device, or to call put_device(&ac97->dev) to free the device.
*
* Returns: A snd_ac97 device or a PTR_ERR in case of an error.
*/
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec)
struct snd_ac97 *snd_soc_alloc_ac97_codec(struct snd_soc_codec *codec)
{
struct snd_ac97 *ac97;
int ret;

ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
if (ac97 == NULL)
Expand All @@ -73,7 +76,28 @@ struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec)
codec->component.card->snd_card->number, 0,
codec->component.name);

ret = device_register(&ac97->dev);
device_initialize(&ac97->dev);

return ac97;
}
EXPORT_SYMBOL(snd_soc_alloc_ac97_codec);

/**
* snd_soc_new_ac97_codec - initailise AC97 device
* @codec: audio codec
*
* Initialises AC97 codec resources for use by ad-hoc devices only.
*/
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec)
{
struct snd_ac97 *ac97;
int ret;

ac97 = snd_soc_alloc_ac97_codec(codec);
if (IS_ERR(ac97))
return ac97;

ret = device_add(&ac97->dev);
if (ret) {
put_device(&ac97->dev);
return ERR_PTR(ret);
Expand Down

0 comments on commit d2255c0

Please sign in to comment.