mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-04-21 12:27:27 +03:00
changed Makefile and profiles, added patches for kernel 2.6.24
(stable-branch of Openmoko) git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13613 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
From 2219855aa7835e082ec134fafd9ddba84589d345 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Green <andy@openmoko.com>
|
||||
Date: Wed, 2 Jul 2008 22:39:33 +0100
|
||||
Subject: [PATCH] ASoC: Don't block system resume
|
||||
|
||||
On OpenMoko soc-audio resume is taking 700ms of the whole resume time of
|
||||
1.3s, dominated by writes to the codec over I2C. This patch shunts the
|
||||
resume guts into a workqueue which then is done asynchronously.
|
||||
|
||||
The "card" is locked using the ALSA power state APIs as suggested by
|
||||
Mark Brown.
|
||||
|
||||
[Added fix for race with resume to suspend and fixed a couple of nits
|
||||
from checkpatch -- broonie.]
|
||||
|
||||
Signed-off-by: Andy Green <andy@openmoko.com>
|
||||
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||
---
|
||||
include/sound/soc.h | 1 +
|
||||
sound/soc/soc-core.c | 52 ++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
2 files changed, 47 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/include/sound/soc.h b/include/sound/soc.h
|
||||
index aedb348..2d6c0eb 100644
|
||||
--- a/include/sound/soc.h
|
||||
+++ b/include/sound/soc.h
|
||||
@@ -442,6 +442,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;
|
||||
};
|
||||
|
||||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
|
||||
index 9e20333..e96930e 100644
|
||||
--- a/sound/soc/soc-core.c
|
||||
+++ b/sound/soc/soc-core.c
|
||||
@@ -632,6 +632,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;
|
||||
@@ -684,16 +694,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_machine *machine = socdev->machine;
|
||||
- struct snd_soc_platform *platform = socdev->platform;
|
||||
- struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
|
||||
+ 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);
|
||||
|
||||
@@ -735,6 +756,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;
|
||||
}
|
||||
|
||||
@@ -781,6 +818,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:
|
||||
--
|
||||
1.5.6.5
|
||||
|
||||
Reference in New Issue
Block a user