Skip to content

Commit

Permalink
Staging: sst: Add runtime PM support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vinod Koul authored and Greg Kroah-Hartman committed Nov 29, 2010
1 parent 951c44e commit 964c697
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 8 deletions.
43 changes: 40 additions & 3 deletions drivers/staging/intel_sst/intel_sst.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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},
Expand All @@ -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
};

Expand Down
13 changes: 12 additions & 1 deletion drivers/staging/intel_sst/intel_sst_app_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions drivers/staging/intel_sst/intel_sst_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
16 changes: 13 additions & 3 deletions drivers/staging/intel_sst/intel_sst_drv_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
}

Expand All @@ -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;
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/staging/intel_sst/intel_sst_dsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions drivers/staging/intel_sst/intel_sst_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 964c697

Please sign in to comment.