mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-30 08:02:30 +00:00
Staging: sst: Add 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@intel.com> Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
951c44e0db
commit
964c6975e8
6 changed files with 69 additions and 8 deletions
|
@ -36,6 +36,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <asm/mrst.h>
|
||||
#include "intel_sst.h"
|
||||
#include "intel_sst_ioctl.h"
|
||||
|
@ -320,6 +321,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("...successfully done!!!\n");
|
||||
return ret;
|
||||
|
||||
|
@ -408,8 +412,10 @@ int intel_sst_suspend(struct pci_dev *pci, pm_message_t state)
|
|||
|
||||
pr_debug("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("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;
|
||||
|
@ -439,7 +445,7 @@ int intel_sst_resume(struct pci_dev *pci)
|
|||
pr_debug("intel_sst_resume called\n");
|
||||
if (sst_drv_ctx->sst_state != SST_SUSPENDED) {
|
||||
pr_err("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);
|
||||
|
@ -454,6 +460,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("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("runtime_resume called\n");
|
||||
return intel_sst_resume(pci_dev);
|
||||
}
|
||||
|
||||
static int intel_sst_runtime_idle(struct device *dev)
|
||||
{
|
||||
pr_debug("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},
|
||||
|
@ -470,6 +504,9 @@ static struct pci_driver driver = {
|
|||
#ifdef CONFIG_PM
|
||||
.suspend = intel_sst_suspend,
|
||||
.resume = intel_sst_resume,
|
||||
.driver = {
|
||||
.pm = &intel_sst_pm,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -35,6 +35,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
|
||||
|
@ -103,8 +104,10 @@ int intel_sst_open(struct inode *i_node, struct file *file_ptr)
|
|||
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;
|
||||
}
|
||||
|
@ -113,6 +116,7 @@ int intel_sst_open(struct inode *i_node, struct file *file_ptr)
|
|||
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;
|
||||
}
|
||||
|
@ -125,6 +129,7 @@ int intel_sst_open(struct inode *i_node, struct file *file_ptr)
|
|||
pr_debug("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;
|
||||
|
@ -147,8 +152,10 @@ int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -157,8 +164,10 @@ int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr)
|
|||
sst_drv_ctx->am_cnt++;
|
||||
pr_debug("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;
|
||||
|
@ -181,6 +190,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);
|
||||
|
@ -192,6 +202,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("AM handle closed\n");
|
||||
return 0;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include "intel_sst.h"
|
||||
#include "intel_sst_ioctl.h"
|
||||
#include "intel_sst_fw_ipc.h"
|
||||
|
@ -310,12 +311,15 @@ 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*/
|
||||
/* LPE is suspended, resume it before proceding*/
|
||||
pr_debug("Resuming from Suspended state\n");
|
||||
retval = intel_sst_resume(sst_drv_ctx->pci);
|
||||
if (retval) {
|
||||
pr_err("Resume Failed = %#x, abort\n", retval);
|
||||
pm_runtime_put(&sst_drv_ctx->pci->dev);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
@ -325,20 +329,25 @@ int sst_open_pcm_stream(struct snd_sst_params *str_param)
|
|||
retval = sst_download_fw();
|
||||
if (retval) {
|
||||
pr_err("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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -364,6 +373,7 @@ int sst_close_pcm_stream(unsigned int str_id)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@ static int intel_sst_reset_dsp_mrst(void)
|
|||
union config_status_reg csr;
|
||||
|
||||
pr_debug("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;
|
||||
|
|
|
@ -182,6 +182,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("FW Version %x.%x\n",
|
||||
init->fw_version.major, init->fw_version.minor);
|
||||
|
|
Loading…
Reference in a new issue