diff options
| author | Mark Brown <broonie@kernel.org> | 2026-05-29 23:13:28 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-05-29 23:13:28 +0100 |
| commit | 9806d07c2f5635f9ae268f1200ee4a1a159b0e17 (patch) | |
| tree | 3eb048cc42b2a8cbe1b45eee1af7a0f0ea2e472e /drivers | |
| parent | 18b0a5c1b8f9ef4b603cb9334a731ad04e3a88e5 (diff) | |
| parent | 8a7fe10eec64bfb7cf4091bca540de4c55d56bfa (diff) | |
| download | linux-next-history-9806d07c2f5635f9ae268f1200ee4a1a159b0e17.tar.gz | |
Merge branch 'next' of https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire.git
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/soundwire/generic_bandwidth_allocation.c | 44 | ||||
| -rw-r--r-- | drivers/soundwire/intel.c | 31 | ||||
| -rw-r--r-- | drivers/soundwire/intel_ace2x.c | 40 | ||||
| -rw-r--r-- | drivers/soundwire/intel_auxdevice.c | 3 | ||||
| -rw-r--r-- | drivers/soundwire/slave.c | 4 | ||||
| -rw-r--r-- | drivers/soundwire/stream.c | 13 |
6 files changed, 71 insertions, 64 deletions
diff --git a/drivers/soundwire/generic_bandwidth_allocation.c b/drivers/soundwire/generic_bandwidth_allocation.c index fb3970e12dac9..3575d69ce1c50 100644 --- a/drivers/soundwire/generic_bandwidth_allocation.c +++ b/drivers/soundwire/generic_bandwidth_allocation.c @@ -299,39 +299,35 @@ static int sdw_add_element_group_count(struct sdw_group *group, int num = group->count; int i; - for (i = 0; i <= num; i++) { + for (i = 0; i < num; i++) { if (rate == group->rates[i] && lane == group->lanes[i]) - break; - - if (i != num) - continue; + return 0; + } - if (group->count >= group->max_size) { - unsigned int *rates; - unsigned int *lanes; + if (group->count >= group->max_size) { + unsigned int *rates; + unsigned int *lanes; - group->max_size += 1; - rates = krealloc(group->rates, - (sizeof(int) * group->max_size), - GFP_KERNEL); - if (!rates) - return -ENOMEM; + rates = krealloc_array(group->rates, group->max_size + 1, + sizeof(*group->rates), GFP_KERNEL); + if (!rates) + return -ENOMEM; - group->rates = rates; + group->rates = rates; - lanes = krealloc(group->lanes, - (sizeof(int) * group->max_size), - GFP_KERNEL); - if (!lanes) - return -ENOMEM; + lanes = krealloc_array(group->lanes, group->max_size + 1, + sizeof(*group->lanes), GFP_KERNEL); + if (!lanes) + return -ENOMEM; - group->lanes = lanes; - } + group->lanes = lanes; - group->rates[group->count] = rate; - group->lanes[group->count++] = lane; + group->max_size += 1; } + group->rates[group->count] = rate; + group->lanes[group->count++] = lane; + return 0; } diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index dcd7440e78fa6..af65214836b4d 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -906,19 +906,6 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn } switch (cmd) { - case SNDRV_PCM_TRIGGER_SUSPEND: - - /* - * The .prepare callback is used to deal with xruns and resume operations. - * In the case of xruns, the DMAs and SHIM registers cannot be touched, - * but for resume operations the DMAs and SHIM registers need to be initialized. - * the .trigger callback is used to track the suspend case only. - */ - - dai_runtime->suspended = true; - - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: dai_runtime->paused = true; break; @@ -955,10 +942,12 @@ static int intel_component_dais_suspend(struct snd_soc_component *component) struct snd_soc_dai *dai; /* - * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core - * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state. - * Since the component suspend is called last, we can trap this corner case - * and force the DAIs to release their resources. + * Mark all open streams as suspended. + * Open streams at this point can be in SUSPENDED, PAUSED or STOPPED + * state and during prepare the DMAs and SHIM registers need to be + * initialized for them. + * The STOPPED state is a special corner case which can happen if audio + * experiences xrun at suspend time. */ for_each_component_dais(component, dai) { struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); @@ -966,13 +955,7 @@ static int intel_component_dais_suspend(struct snd_soc_component *component) dai_runtime = cdns->dai_runtime_array[dai->id]; - if (!dai_runtime) - continue; - - if (dai_runtime->suspended) - continue; - - if (dai_runtime->paused) + if (dai_runtime) dai_runtime->suspended = true; } diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c index 20422534baf19..b37933efac5d2 100644 --- a/drivers/soundwire/intel_ace2x.c +++ b/drivers/soundwire/intel_ace2x.c @@ -317,6 +317,7 @@ static void intel_ace2x_bpt_close_stream(struct sdw_intel *sdw, struct sdw_slave dev_err(cdns->dev, "%s: remove slave failed: %d\n", __func__, ret); + sdw_release_stream(cdns->bus.bpt_stream); cdns->bus.bpt_stream = NULL; } @@ -894,19 +895,6 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn } switch (cmd) { - case SNDRV_PCM_TRIGGER_SUSPEND: - - /* - * The .prepare callback is used to deal with xruns and resume operations. - * In the case of xruns, the DMAs and SHIM registers cannot be touched, - * but for resume operations the DMAs and SHIM registers need to be initialized. - * the .trigger callback is used to track the suspend case only. - */ - - dai_runtime->suspended = true; - - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: dai_runtime->paused = true; break; @@ -930,8 +918,34 @@ static const struct snd_soc_dai_ops intel_pcm_dai_ops = { .get_stream = intel_get_sdw_stream, }; +static int intel_component_dais_suspend(struct snd_soc_component *component) +{ + struct snd_soc_dai *dai; + + /* + * Mark all open streams as suspended. + * Open streams at this point can be in SUSPENDED, PAUSED or STOPPED + * state and during prepare the DMAs and SHIM registers need to be + * initialized for them. + * The STOPPED state is a special corner case which can happen if audio + * experiences xrun at suspend time. + */ + for_each_component_dais(component, dai) { + struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); + struct sdw_cdns_dai_runtime *dai_runtime; + + dai_runtime = cdns->dai_runtime_array[dai->id]; + + if (dai_runtime) + dai_runtime->suspended = true; + } + + return 0; +} + static const struct snd_soc_component_driver dai_component = { .name = "soundwire", + .suspend = intel_component_dais_suspend, }; /* diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c index 913e95207ee1a..0b8107bec9abe 100644 --- a/drivers/soundwire/intel_auxdevice.c +++ b/drivers/soundwire/intel_auxdevice.c @@ -51,6 +51,8 @@ struct wake_capable_part { }; static struct wake_capable_part wake_capable_list[] = { + {0x01fa, 0x2A30}, + {0x01fa, 0x2A3B}, {0x01fa, 0x4243}, {0x01fa, 0x4245}, {0x01fa, 0x4249}, @@ -70,6 +72,7 @@ static struct wake_capable_part wake_capable_list[] = { {0x025d, 0x717}, {0x025d, 0x721}, {0x025d, 0x722}, + {0x04b3, 0x9356}, }; static bool is_wake_capable(struct sdw_slave *slave) diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index ff763b692078d..e0c49cbcb1bab 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -244,8 +244,8 @@ int sdw_of_find_slaves(struct sdw_bus *bus) struct sdw_slave_id id; const __be32 *addr; - compat = of_get_property(node, "compatible", NULL); - if (!compat) + ret = of_property_read_string(node, "compatible", &compat); + if (ret) continue; ret = sscanf(compat, "sdw%01x%04hx%04hx%02hhx", &sdw_version, diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 4ed8fb7663ad4..cdac009b1a756 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -697,6 +697,13 @@ static int sdw_program_params(struct sdw_bus *bus, bool prepare) if (scale_index < 0) return scale_index; + /* Skip the unattached Peripherals */ + if (!completion_done(&slave->enumeration_complete)) { + dev_warn(&slave->dev, + "Not enumerated, skip programming BUSCLOCK_SCALE\n"); + continue; + } + ret = sdw_write_no_pm(slave, addr1, scale_index); if (ret < 0) { dev_err(&slave->dev, "SDW_SCP_BUSCLOCK_SCALE register write failed\n"); @@ -2229,11 +2236,15 @@ EXPORT_SYMBOL(sdw_stream_add_slave); * @slave: SDW Slave instance * @stream: SoundWire stream * - * This removes and frees port_rt and slave_rt from a stream + * This removes and frees port_rt and slave_rt from a stream. + * If stream is NULL or an ERR_PTR, do nothing and return 0. */ int sdw_stream_remove_slave(struct sdw_slave *slave, struct sdw_stream_runtime *stream) { + if (IS_ERR_OR_NULL(stream)) + return 0; + mutex_lock(&slave->bus->bus_lock); sdw_slave_port_free(slave, stream); |
