[Meego-kernel] [PATCH 03/10] Audio: Add SST driver runtime PM support
Koul, Vinod
vinod.koul
Mon Sep 27 02:45:05 PDT 2010
>From 5dcfa16eb26bbbea5e2df9aa99dc42a31b843893 Mon Sep 17 00:00:00 2001
From: Vinod Koul <vinod.koul at intel.com>
Date: Wed, 22 Sep 2010 16:21:26 +0530
Subject: [PATCH 03/10] Audio: Add SST driver runtime PM support
This adds runtime PM support for audio driver.
This also fixes LPA audio mode for moorestown platform
Signed-off-by: Vinod Koul <vinod.koul at intel.com>
---
sound/pci/sst/intel_sst.c | 44 ++++++++++++++++++++++++++++---
sound/pci/sst/intel_sst_app_interface.c | 33 ++++++++++++++++++-----
sound/pci/sst/intel_sst_common.h | 1 +
sound/pci/sst/intel_sst_drv_interface.c | 26 ++++++++++++------
sound/pci/sst/intel_sst_dsp.c | 3 +-
sound/pci/sst/intel_sst_ipc.c | 1 +
6 files changed, 87 insertions(+), 21 deletions(-)
diff --git a/sound/pci/sst/intel_sst.c b/sound/pci/sst/intel_sst.c
index 59fa05d..7cf58b8 100644
--- a/sound/pci/sst/intel_sst.c
+++ b/sound/pci/sst/intel_sst.c
@@ -34,6 +34,7 @@
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/miscdevice.h>
+#include <linux/pm_runtime.h>
#include <asm/mrst.h>
#include <sound/intel_sst.h>
#include <sound/intel_sst_ioctl.h>
@@ -318,6 +319,9 @@ static int __devinit intel_sst_probe(struct pci_dev *pci,
}
}
sst_drv_ctx->lpe_stalled = 0;
+ pm_runtime_set_active(&pci->dev);
+ pm_runtime_enable(&pci->dev);
+ pm_runtime_allow(&pci->dev);
pr_debug("sst: ...successfully done!!!\n");
return ret;
@@ -405,9 +409,10 @@ int intel_sst_suspend(struct pci_dev *pci, pm_message_t state)
union config_status_reg csr;
pr_debug("sst: intel_sst_suspend called\n");
-
- if (sst_drv_ctx->pb_streams != 0 || sst_drv_ctx->cp_streams != 0)
- return -EPERM;
+ if (sst_drv_ctx->stream_cnt) {
+ pr_err("sst: active streams,not able to suspend\n");
+ return -EBUSY;
+ }
/*Assert RESET on LPE Processor*/
csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
csr.full = csr.full | 0x2;
@@ -437,7 +442,7 @@ int intel_sst_resume(struct pci_dev *pci)
pr_debug("sst: intel_sst_resume called\n");
if (sst_drv_ctx->sst_state != SST_SUSPENDED) {
pr_err("sst: SST is not in suspended state\n");
- return -EPERM;
+ return 0;
}
sst_drv_ctx = pci_get_drvdata(pci);
pci_set_power_state(pci, PCI_D0);
@@ -452,6 +457,34 @@ int intel_sst_resume(struct pci_dev *pci)
return 0;
}
+static int intel_sst_runtime_suspend(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ pr_debug("sst: runtime_suspend called\n");
+ return intel_sst_suspend(pci_dev, PMSG_SUSPEND);
+}
+
+static int intel_sst_runtime_resume(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ pr_debug("sst: runtime_resume called\n");
+ return intel_sst_resume(pci_dev);
+}
+
+static int intel_sst_runtime_idle(struct device *dev)
+{
+ pr_debug("sst: runtime_idle called\n");
+ if (sst_drv_ctx->stream_cnt == 0 && sst_drv_ctx->am_cnt == 0)
+ pm_schedule_suspend(dev, SST_SUSPEND_DELAY);
+ return -EBUSY;
+}
+
+static const struct dev_pm_ops intel_sst_pm = {
+ .runtime_suspend = intel_sst_runtime_suspend,
+ .runtime_resume = intel_sst_runtime_resume,
+ .runtime_idle = intel_sst_runtime_idle,
+};
+
/* PCI Routines */
static struct pci_device_id intel_sst_ids[] = {
{ PCI_VDEVICE(INTEL, SST_MRST_PCI_ID), 3},
@@ -468,6 +501,9 @@ static struct pci_driver driver = {
#ifdef CONFIG_PM
.suspend = intel_sst_suspend,
.resume = intel_sst_resume,
+ .driver = {
+ .pm = &intel_sst_pm,
+ },
#endif
};
diff --git a/sound/pci/sst/intel_sst_app_interface.c b/sound/pci/sst/intel_sst_app_interface.c
index a7e83cc..357f577 100644
--- a/sound/pci/sst/intel_sst_app_interface.c
+++ b/sound/pci/sst/intel_sst_app_interface.c
@@ -33,6 +33,7 @@
#include <linux/aio.h>
#include <linux/uaccess.h>
#include <linux/firmware.h>
+#include <linux/pm_runtime.h>
#include <linux/ioctl.h>
#include <linux/smp_lock.h>
#ifdef CONFIG_MRST_RAR_HANDLER
@@ -98,15 +99,22 @@ static int intel_sst_check_device(void)
*/
int intel_sst_open(struct inode *i_node, struct file *file_ptr)
{
- unsigned int retval = intel_sst_check_device();
- if (retval)
- return retval;
+ unsigned int retval;
mutex_lock(&sst_drv_ctx->stream_lock);
+ pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
+ retval = intel_sst_check_device();
+ if (retval) {
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
+ mutex_unlock(&sst_drv_ctx->stream_lock);
+ return retval;
+ }
+
if (sst_drv_ctx->encoded_cnt < MAX_ENC_STREAM) {
struct ioctl_pvt_data *data =
kzalloc(sizeof(struct ioctl_pvt_data), GFP_KERNEL);
if (!data) {
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
mutex_unlock(&sst_drv_ctx->stream_lock);
return -ENOMEM;
}
@@ -119,6 +127,7 @@ int intel_sst_open(struct inode *i_node, struct file *file_ptr)
pr_debug("sst: pvt_id handle = %d!\n", data->pvt_id);
} else {
retval = -EUSERS;
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
mutex_unlock(&sst_drv_ctx->stream_lock);
}
return retval;
@@ -137,18 +146,26 @@ int intel_sst_open(struct inode *i_node, struct file *file_ptr)
*/
int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
{
- unsigned int retval = intel_sst_check_device();
- if (retval)
- return retval;
+ unsigned int retval;
/* audio manager open */
mutex_lock(&sst_drv_ctx->stream_lock);
+ pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
+ retval = intel_sst_check_device();
+ if (retval) {
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
+ mutex_unlock(&sst_drv_ctx->stream_lock);
+ return retval;
+ }
+
if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) {
sst_drv_ctx->am_cnt++;
pr_debug("sst: AM handle opened...\n");
file_ptr->private_data = NULL;
- } else
+ } else {
retval = -EACCES;
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
+ }
mutex_unlock(&sst_drv_ctx->stream_lock);
return retval;
@@ -171,6 +188,7 @@ int intel_sst_release(struct inode *i_node, struct file *file_ptr)
mutex_lock(&sst_drv_ctx->stream_lock);
sst_drv_ctx->encoded_cnt--;
sst_drv_ctx->stream_cnt--;
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
mutex_unlock(&sst_drv_ctx->stream_lock);
free_stream_context(data->str_id);
kfree(data);
@@ -182,6 +200,7 @@ int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr)
/* audio manager close */
mutex_lock(&sst_drv_ctx->stream_lock);
sst_drv_ctx->am_cnt--;
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
mutex_unlock(&sst_drv_ctx->stream_lock);
pr_debug("sst: AM handle closed\n");
return 0;
diff --git a/sound/pci/sst/intel_sst_common.h b/sound/pci/sst/intel_sst_common.h
index 73a98c8..4fe9c6a 100644
--- a/sound/pci/sst/intel_sst_common.h
+++ b/sound/pci/sst/intel_sst_common.h
@@ -37,6 +37,7 @@
#define SST_FW_FILENAME_MFLD "fw_sst_082f.bin"
#define SST_MRST_PCI_ID 0x080A
#define SST_MFLD_PCI_ID 0x082F
+#define SST_SUSPEND_DELAY 2000
enum sst_states {
SST_FW_LOADED = 1,
diff --git a/sound/pci/sst/intel_sst_drv_interface.c b/sound/pci/sst/intel_sst_drv_interface.c
index a4dd919..4a1dede 100644
--- a/sound/pci/sst/intel_sst_drv_interface.c
+++ b/sound/pci/sst/intel_sst_drv_interface.c
@@ -29,6 +29,7 @@
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/firmware.h>
+#include <linux/pm_runtime.h>
#include <sound/intel_sst.h>
#include <sound/intel_sst_ioctl.h>
#include "intel_sst_fw_ipc.h"
@@ -307,6 +308,7 @@ int sst_open_pcm_stream(struct snd_sst_params *str_param)
struct stream_info *str_info;
int retval;
+ pm_runtime_get_sync(&sst_drv_ctx->pci->dev);
if (sst_drv_ctx->sst_state == SST_SUSPENDED) {
/*LPE is suspended, resume it before proceding*/
@@ -314,6 +316,7 @@ int sst_open_pcm_stream(struct snd_sst_params *str_param)
retval = intel_sst_resume(sst_drv_ctx->pci);
if (retval) {
pr_err("sst: Resume Failed = %#x, abort\n", retval);
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
return retval;
}
}
@@ -323,20 +326,24 @@ int sst_open_pcm_stream(struct snd_sst_params *str_param)
retval = sst_download_fw();
if (retval) {
pr_err("sst: FW download fail %x, abort\n", retval);
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
return retval;
}
send_intial_rx_timeslot();
}
- if (!str_param)
+ if (!str_param) {
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
return -EINVAL;
+ }
- retval = sst_get_stream(str_param);
+ retval = sst_get_stream(str_param);
if (retval > 0) {
sst_drv_ctx->stream_cnt++;
str_info = &sst_drv_ctx->streams[retval];
str_info->src = MAD_DRV;
- }
+ } else
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
return retval;
}
@@ -356,13 +363,14 @@ int sst_close_pcm_stream(unsigned int str_id)
pr_debug("sst: stream free called\n");
if (sst_validate_strid(str_id))
return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
- free_stream_context(str_id);
- stream->pcm_substream = NULL;
- stream->status = STREAM_UN_INIT;
- stream->period_elapsed = NULL;
- sst_drv_ctx->stream_cnt--;
+ stream = &sst_drv_ctx->streams[str_id];
+ free_stream_context(str_id);
+ stream->pcm_substream = NULL;
+ stream->status = STREAM_UN_INIT;
+ stream->period_elapsed = NULL;
+ sst_drv_ctx->stream_cnt--;
pr_debug("sst: will call runtime put now\n");
+ pm_runtime_put(&sst_drv_ctx->pci->dev);
return 0;
}
/*
diff --git a/sound/pci/sst/intel_sst_dsp.c b/sound/pci/sst/intel_sst_dsp.c
index c35cb76..585e2c1 100644
--- a/sound/pci/sst/intel_sst_dsp.c
+++ b/sound/pci/sst/intel_sst_dsp.c
@@ -48,7 +48,8 @@ static int intel_sst_reset_dsp_mrst(void)
union config_status_reg csr;
pr_debug("sst: Resetting the DSP in mrst\n");
- csr.full = 0x3a2;
+ csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
+ csr.full |= 0x382;
sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR);
csr.part.strb_cntr_rst = 0;
diff --git a/sound/pci/sst/intel_sst_ipc.c b/sound/pci/sst/intel_sst_ipc.c
index f23772f..acbd8bc 100644
--- a/sound/pci/sst/intel_sst_ipc.c
+++ b/sound/pci/sst/intel_sst_ipc.c
@@ -179,6 +179,7 @@ int process_fw_init(struct sst_ipc_msg_wq *msg)
sst_send_sound_card_type();
mutex_lock(&sst_drv_ctx->sst_lock);
sst_drv_ctx->sst_state = SST_FW_RUNNING;
+ sst_drv_ctx->lpe_stalled = 0;
mutex_unlock(&sst_drv_ctx->sst_lock);
pr_debug("sst: FW Version %x.%x\n",
init->fw_version.major, init->fw_version.minor);
--
1.6.6.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-Audio-Add-SST-driver-runtime-PM-support.patch
Type: application/octet-stream
Size: 10270 bytes
Desc: 0003-Audio-Add-SST-driver-runtime-PM-support.patch
URL: <http://lists.meego.com/pipermail/meego-kernel/attachments/20100927/2d0a8637/attachment.obj>
More information about the Meego-kernel
mailing list