mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
ASoC: SDCA: Add basic system suspend support
Add basic system suspend support. Disable the IRQs and force runtime suspend, during system suspend, because the device will likely fully power down during suspend. Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> Link: https://patch.msgid.link/20260109145206.3456151-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
9e3d4f794c
commit
7a5214f769
|
|
@ -238,6 +238,38 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int class_suspend(struct device *dev)
|
||||
{
|
||||
struct sdca_class_drv *drv = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
disable_irq(drv->sdw->irq);
|
||||
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to force suspend: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int class_resume(struct device *dev)
|
||||
{
|
||||
struct sdca_class_drv *drv = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to force resume: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
enable_irq(drv->sdw->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int class_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct sdca_class_drv *drv = dev_get_drvdata(dev);
|
||||
|
|
@ -278,6 +310,7 @@ static int class_runtime_resume(struct device *dev)
|
|||
}
|
||||
|
||||
static const struct dev_pm_ops class_pm_ops = {
|
||||
SYSTEM_SLEEP_PM_OPS(class_suspend, class_resume)
|
||||
RUNTIME_PM_OPS(class_runtime_suspend, class_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ struct class_function_drv {
|
|||
struct sdca_class_drv *core;
|
||||
|
||||
struct sdca_function_data *function;
|
||||
bool suspended;
|
||||
};
|
||||
|
||||
static void class_function_regmap_lock(void *data)
|
||||
|
|
@ -417,6 +418,14 @@ static int class_function_runtime_resume(struct device *dev)
|
|||
regcache_mark_dirty(drv->regmap);
|
||||
regcache_cache_only(drv->regmap, false);
|
||||
|
||||
if (drv->suspended) {
|
||||
sdca_irq_enable_early(drv->function, drv->core->irq_info);
|
||||
/* TODO: Add FDL process between early and late IRQs */
|
||||
sdca_irq_enable(drv->function, drv->core->irq_info);
|
||||
|
||||
drv->suspended = false;
|
||||
}
|
||||
|
||||
ret = regcache_sync(drv->regmap);
|
||||
if (ret) {
|
||||
dev_err(drv->dev, "failed to restore register cache: %d\n", ret);
|
||||
|
|
@ -431,7 +440,49 @@ static int class_function_runtime_resume(struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int class_function_suspend(struct device *dev)
|
||||
{
|
||||
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
|
||||
struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
|
||||
int ret;
|
||||
|
||||
drv->suspended = true;
|
||||
|
||||
/* Ensure runtime resume runs on resume */
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to resume for suspend: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sdca_irq_disable(drv->function, drv->core->irq_info);
|
||||
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to force suspend: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_put_noidle(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int class_function_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to force resume: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops class_function_pm_ops = {
|
||||
SYSTEM_SLEEP_PM_OPS(class_function_suspend, class_function_resume)
|
||||
RUNTIME_PM_OPS(class_function_runtime_suspend,
|
||||
class_function_runtime_resume, NULL)
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user