mirror of https://gitee.com/openkylin/linux.git
soundwire: intel: Add basic power management support
Implement suspend/resume capabilities (not runtime_pm for now) The resume part is essentially a full-blown re-enumeration. When S0ix is supported, we will select clock stop mode when the ACPI target state is S0, and tear down the link for S3. Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com> Link: https://lore.kernel.org/r/20200721203723.18305-2-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
bd84256e86
commit
9b3b4b3f2f
|
@ -463,7 +463,7 @@ static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable)
|
|||
mutex_unlock(sdw->link_res->shim_lock);
|
||||
}
|
||||
|
||||
static int __maybe_unused intel_link_power_down(struct sdw_intel *sdw)
|
||||
static int intel_link_power_down(struct sdw_intel *sdw)
|
||||
{
|
||||
int link_control, spa_mask, cpa_mask;
|
||||
unsigned int link_id = sdw->instance;
|
||||
|
@ -1376,12 +1376,89 @@ int intel_master_process_wakeen_event(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* PM calls
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int intel_suspend(struct device *dev)
|
||||
{
|
||||
struct sdw_cdns *cdns = dev_get_drvdata(dev);
|
||||
struct sdw_intel *sdw = cdns_to_intel(cdns);
|
||||
struct sdw_bus *bus = &cdns->bus;
|
||||
int ret;
|
||||
|
||||
if (bus->prop.hw_disabled) {
|
||||
dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
|
||||
bus->link_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = sdw_cdns_enable_interrupt(cdns, false);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "cannot disable interrupts on suspend\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = intel_link_power_down(sdw);
|
||||
if (ret) {
|
||||
dev_err(dev, "Link power down failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
intel_shim_wake(sdw, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_resume(struct device *dev)
|
||||
{
|
||||
struct sdw_cdns *cdns = dev_get_drvdata(dev);
|
||||
struct sdw_intel *sdw = cdns_to_intel(cdns);
|
||||
struct sdw_bus *bus = &cdns->bus;
|
||||
int ret;
|
||||
|
||||
if (bus->prop.hw_disabled) {
|
||||
dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
|
||||
bus->link_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = intel_init(sdw);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s failed: %d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sdw_cdns_enable_interrupt(cdns, true);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "cannot enable interrupts during resume\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sdw_cdns_exit_reset(cdns);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "unable to exit bus reset sequence during resume\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops intel_pm = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(intel_suspend, intel_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver sdw_intel_drv = {
|
||||
.probe = intel_master_probe,
|
||||
.remove = intel_master_remove,
|
||||
.driver = {
|
||||
.name = "intel-sdw",
|
||||
},
|
||||
.pm = &intel_pm,
|
||||
}
|
||||
};
|
||||
|
||||
module_platform_driver(sdw_intel_drv);
|
||||
|
|
Loading…
Reference in New Issue