Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 99116
b: refs/heads/master
c: 6ed2597
h: refs/heads/master
v: v3
  • Loading branch information
Andy Green authored and Jaroslav Kysela committed Jun 16, 2008
1 parent 006b429 commit 294d676
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: abb68c26ba15f8e84e580a40c0b1bc349cb534b0
refs/heads/master: 6ed2597883b1b03ca94f62f0cfe908314cba6d6b
1 change: 1 addition & 0 deletions trunk/include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ struct snd_soc_device {
struct snd_soc_codec *codec;
struct snd_soc_codec_device *codec_dev;
struct delayed_work delayed_work;
struct work_struct deferred_resume_work;
void *codec_data;
};

Expand Down
46 changes: 43 additions & 3 deletions trunk/sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,16 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
struct snd_soc_codec *codec = socdev->codec;
int i;

/* Due to the resume being scheduled into a workqueue we could
* suspend before that's finished - wait for it to complete.
*/
snd_power_lock(codec->card);
snd_power_wait(codec->card, SNDRV_CTL_POWER_D0);
snd_power_unlock(codec->card);

/* we're going to block userspace touching us until resume completes */
snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot);

/* mute any active DAC's */
for (i = 0; i < machine->num_links; i++) {
struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
Expand Down Expand Up @@ -691,16 +701,27 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}

/* powers up audio subsystem after a suspend */
static int soc_resume(struct platform_device *pdev)
/* deferred resume work, so resume can complete before we finished
* setting our codec back up, which can be very slow on I2C
*/
static void soc_resume_deferred(struct work_struct *work)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_device *socdev = container_of(work,
struct snd_soc_device,
deferred_resume_work);
struct snd_soc_machine *machine = socdev->machine;
struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
struct snd_soc_codec *codec = socdev->codec;
struct platform_device *pdev = to_platform_device(socdev->dev);
int i;

/* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
* so userspace apps are blocked from touching us
*/

dev_info(socdev->dev, "starting resume work\n");

if (machine->resume_pre)
machine->resume_pre(pdev);

Expand Down Expand Up @@ -742,6 +763,22 @@ static int soc_resume(struct platform_device *pdev)
if (machine->resume_post)
machine->resume_post(pdev);

dev_info(socdev->dev, "resume work completed\n");

/* userspace can access us now we are back as we were before */
snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0);
}

/* powers up audio subsystem after a suspend */
static int soc_resume(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);

dev_info(socdev->dev, "scheduling resume work\n");

if (!schedule_work(&socdev->deferred_resume_work))
dev_err(socdev->dev, "work item may be lost\n");

return 0;
}

Expand Down Expand Up @@ -788,6 +825,9 @@ static int soc_probe(struct platform_device *pdev)

/* DAPM stream work */
INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
/* deferred resume work */
INIT_WORK(&socdev->deferred_resume_work, soc_resume_deferred);

return 0;

platform_err:
Expand Down

0 comments on commit 294d676

Please sign in to comment.