ASoC: Intel: catpt: Round of fixes and PM changes

Merge series from Cezary Rojewski <cezary.rojewski@intel.com>:

Set of changes addressing gaps in DRAM offset checks, error paths and
PM.

The first three patches are straight-forward, the last three relate to
the power management. The standing out PM change is removal of the
catpt-driver as a system-suspend (S3) blocker. This is a suggestion from
Andy as indeed, audio is not a critical component that should prevent
the system from going into S3. Whatever happens, the driver can recover
on a follow up resume (S3 -> S0).
This commit is contained in:
Mark Brown 2025-11-27 21:50:47 +00:00
commit a76e1d951f
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
4 changed files with 37 additions and 25 deletions

View File

@ -28,7 +28,7 @@
#define CREATE_TRACE_POINTS
#include "trace.h"
static int catpt_suspend(struct device *dev)
static int catpt_do_suspend(struct device *dev)
{
struct catpt_dev *cdev = dev_get_drvdata(dev);
struct dma_chan *chan;
@ -72,6 +72,13 @@ static int catpt_suspend(struct device *dev)
return catpt_dsp_power_down(cdev);
}
/* Do not block the system from suspending, recover on resume() if needed. */
static int catpt_suspend(struct device *dev)
{
catpt_do_suspend(dev);
return 0;
}
static int catpt_resume(struct device *dev)
{
struct catpt_dev *cdev = dev_get_drvdata(dev);
@ -114,7 +121,7 @@ static int catpt_runtime_suspend(struct device *dev)
}
module_put(dev->driver->owner);
return catpt_suspend(dev);
return catpt_do_suspend(dev);
}
static int catpt_runtime_resume(struct device *dev)
@ -184,22 +191,25 @@ static int catpt_probe_components(struct catpt_dev *cdev)
goto err_boot_fw;
}
ret = catpt_register_board(cdev);
if (ret) {
dev_err(cdev->dev, "register board failed: %d\n", ret);
goto err_reg_board;
}
/* reflect actual ADSP state in pm_runtime */
pm_runtime_set_active(cdev->dev);
pm_runtime_set_autosuspend_delay(cdev->dev, 2000);
pm_runtime_use_autosuspend(cdev->dev);
pm_runtime_mark_last_busy(cdev->dev);
/* Enable PM before spawning child device. See catpt_dai_pcm_new(). */
pm_runtime_enable(cdev->dev);
ret = catpt_register_board(cdev);
if (ret) {
dev_err(cdev->dev, "register board failed: %d\n", ret);
goto err_reg_board;
}
return 0;
err_reg_board:
pm_runtime_disable(cdev->dev);
snd_soc_unregister_component(cdev->dev);
err_boot_fw:
catpt_dmac_remove(cdev);

View File

@ -208,6 +208,7 @@ static int catpt_restore_memdumps(struct catpt_dev *cdev, struct dma_chan *chan)
for (i = 0; i < cdev->dx_ctx.num_meminfo; i++) {
struct catpt_save_meminfo *info;
struct resource r = {};
u32 off;
int ret;
@ -216,7 +217,8 @@ static int catpt_restore_memdumps(struct catpt_dev *cdev, struct dma_chan *chan)
continue;
off = catpt_to_host_offset(info->offset);
if (off < cdev->dram.start || off > cdev->dram.end)
resource_set_range(&r, off, info->size);
if (!resource_contains(&cdev->dram, &r))
continue;
dev_dbg(cdev->dev, "restoring memdump: off 0x%08x size %d\n",
@ -239,34 +241,32 @@ static int catpt_restore_fwimage(struct catpt_dev *cdev,
struct dma_chan *chan, dma_addr_t paddr,
struct catpt_fw_block_hdr *blk)
{
struct resource r1, r2, common;
struct resource r1 = {};
int i;
print_hex_dump_debug(__func__, DUMP_PREFIX_OFFSET, 8, 4,
blk, sizeof(*blk), false);
r1.start = cdev->dram.start + blk->ram_offset;
r1.end = r1.start + blk->size - 1;
resource_set_range(&r1, cdev->dram.start + blk->ram_offset, blk->size);
/* advance to data area */
paddr += sizeof(*blk);
for (i = 0; i < cdev->dx_ctx.num_meminfo; i++) {
struct catpt_save_meminfo *info;
struct resource common = {};
struct resource r2 = {};
u32 off;
int ret;
info = &cdev->dx_ctx.meminfo[i];
if (info->source != CATPT_DX_TYPE_FW_IMAGE)
continue;
off = catpt_to_host_offset(info->offset);
if (off < cdev->dram.start || off > cdev->dram.end)
resource_set_range(&r2, off, info->size);
if (!resource_contains(&cdev->dram, &r2))
continue;
r2.start = off;
r2.end = r2.start + info->size - 1;
if (!resource_intersection(&r2, &r1, &common))
continue;
/* calculate start offset of common data area */

View File

@ -417,8 +417,10 @@ static int catpt_dai_hw_params(struct snd_pcm_substream *substream,
return CATPT_IPC_ERROR(ret);
ret = catpt_dai_apply_usettings(dai, stream);
if (ret)
if (ret) {
catpt_ipc_free_stream(cdev, stream->info.stream_hw_id);
return ret;
}
stream->allocated = true;
return 0;
@ -669,7 +671,7 @@ static int catpt_dai_pcm_new(struct snd_soc_pcm_runtime *rtm,
return 0;
ret = pm_runtime_resume_and_get(cdev->dev);
if (ret < 0 && ret != -EACCES)
if (ret)
return ret;
ret = catpt_ipc_set_device_format(cdev, &devfmt);
@ -872,7 +874,7 @@ static int catpt_mixer_volume_get(struct snd_kcontrol *kcontrol,
int i;
ret = pm_runtime_resume_and_get(cdev->dev);
if (ret < 0 && ret != -EACCES)
if (ret)
return ret;
for (i = 0; i < CATPT_CHANNELS_MAX; i++) {
@ -893,7 +895,7 @@ static int catpt_mixer_volume_put(struct snd_kcontrol *kcontrol,
int ret;
ret = pm_runtime_resume_and_get(cdev->dev);
if (ret < 0 && ret != -EACCES)
if (ret)
return ret;
ret = catpt_set_dspvol(cdev, cdev->mixer.mixer_hw_id,
@ -924,7 +926,7 @@ static int catpt_stream_volume_get(struct snd_kcontrol *kcontrol,
}
ret = pm_runtime_resume_and_get(cdev->dev);
if (ret < 0 && ret != -EACCES)
if (ret)
return ret;
for (i = 0; i < CATPT_CHANNELS_MAX; i++) {
@ -955,7 +957,7 @@ static int catpt_stream_volume_put(struct snd_kcontrol *kcontrol,
}
ret = pm_runtime_resume_and_get(cdev->dev);
if (ret < 0 && ret != -EACCES)
if (ret)
return ret;
ret = catpt_set_dspvol(cdev, stream->info.stream_hw_id,
@ -1031,7 +1033,7 @@ static int catpt_loopback_switch_put(struct snd_kcontrol *kcontrol,
}
ret = pm_runtime_resume_and_get(cdev->dev);
if (ret < 0 && ret != -EACCES)
if (ret)
return ret;
ret = catpt_ipc_mute_loopback(cdev, stream->info.stream_hw_id, mute);

View File

@ -16,7 +16,7 @@ static ssize_t fw_version_show(struct device *dev,
int ret;
ret = pm_runtime_resume_and_get(cdev->dev);
if (ret < 0 && ret != -EACCES)
if (ret)
return ret;
ret = catpt_ipc_get_fw_version(cdev, &version);