diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-08-01 11:09:27 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-08-01 11:09:27 -0700 |
commit | 6fac1139d99e283ba0c7ed2d1acad9ec2807ba3a (patch) | |
tree | 348cebd051fc5c19c12f929271c0303b491123f3 | |
parent | d6f38c12396397e48092ad9e8a4d7be4de51b942 (diff) | |
parent | 34b1cb4ec286603127aa8c4191ea527eb8dd3567 (diff) |
Merge tag 'soundwire-6.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire
Pull soundwire updates from Vinod Koul:
"A couple of small core changes and driver updates:
- Core: handling of nesting irqs to outside the lock, stream
parameters handing on port prep failures.
- AMD driver support for ACP 7.2 platforms and improved handing of
slave alerts and resume sequences
- Qualcomm updating driver debug spew
- Intel BPT message length limitations, rt721 codec as wake capable
etc"
* tag 'soundwire-6.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire:
soundwire: amd: Add support for acp7.2 platform
soundwire: stream: restore params when prepare ports fail
soundwire: debugfs: move debug statement outside of error handling
soundwire: amd: add check for status update registers
soundwire: intel_auxdevice: add rt721 codec to wake_capable_list
soundwire: Correct some property names
soundwire: update Intel BPT message length limitation
soundwire: intel_ace2.x: Use str_read_write() helper
soundwire: amd: cancel pending slave status handling workqueue during remove sequence
soundwire: amd: serialize amd manager resume sequence during pm_prepare
soundwire: qcom: demote probe registration printk
ASoC: cs42l43: Remove unnecessary work functions
soundwire: Move handle_nested_irq outside of sdw_dev_lock
MAINTAINERS: Remove Sanyog Kale as reviewer on SoundWire
-rw-r--r-- | Documentation/driver-api/soundwire/bra.rst | 2 | ||||
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | drivers/soundwire/amd_manager.c | 14 | ||||
-rw-r--r-- | drivers/soundwire/bus.c | 6 | ||||
-rw-r--r-- | drivers/soundwire/debugfs.c | 6 | ||||
-rw-r--r-- | drivers/soundwire/intel_ace2x.c | 11 | ||||
-rw-r--r-- | drivers/soundwire/intel_auxdevice.c | 1 | ||||
-rw-r--r-- | drivers/soundwire/mipi_disco.c | 4 | ||||
-rw-r--r-- | drivers/soundwire/qcom.c | 6 | ||||
-rw-r--r-- | drivers/soundwire/stream.c | 2 | ||||
-rw-r--r-- | include/linux/soundwire/sdw_amd.h | 1 | ||||
-rw-r--r-- | sound/soc/codecs/cs42l43-jack.c | 46 | ||||
-rw-r--r-- | sound/soc/codecs/cs42l43.c | 24 | ||||
-rw-r--r-- | sound/soc/codecs/cs42l43.h | 5 |
14 files changed, 55 insertions, 74 deletions
diff --git a/Documentation/driver-api/soundwire/bra.rst b/Documentation/driver-api/soundwire/bra.rst index 8500253fa3e8..c08ab2591496 100644 --- a/Documentation/driver-api/soundwire/bra.rst +++ b/Documentation/driver-api/soundwire/bra.rst @@ -333,4 +333,4 @@ FIFO sizes to avoid xruns. Alignment requirements are currently not enforced at the core level but at the platform-level, e.g. for Intel the data sizes must be -multiples of 32 bytes. +equal to or larger than 16 bytes. diff --git a/MAINTAINERS b/MAINTAINERS index 901afe4a7cff..d5a47d4fe9ad 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23637,7 +23637,6 @@ SOUNDWIRE SUBSYSTEM M: Vinod Koul <vkoul@kernel.org> M: Bard Liao <yung-chuan.liao@linux.intel.com> R: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> -R: Sanyog Kale <sanyog.r.kale@intel.com> L: linux-sound@vger.kernel.org S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire.git diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c index 7a671a786197..5fd311ee4107 100644 --- a/drivers/soundwire/amd_manager.c +++ b/drivers/soundwire/amd_manager.c @@ -499,6 +499,7 @@ static int amd_sdw_port_params(struct sdw_bus *bus, struct sdw_port_params *p_pa break; case ACP70_PCI_REV_ID: case ACP71_PCI_REV_ID: + case ACP72_PCI_REV_ID: frame_fmt_reg = acp70_sdw_dp_reg[p_params->num].frame_fmt_reg; break; default: @@ -551,6 +552,7 @@ static int amd_sdw_transport_params(struct sdw_bus *bus, break; case ACP70_PCI_REV_ID: case ACP71_PCI_REV_ID: + case ACP72_PCI_REV_ID: frame_fmt_reg = acp70_sdw_dp_reg[params->port_num].frame_fmt_reg; sample_int_reg = acp70_sdw_dp_reg[params->port_num].sample_int_reg; hctrl_dp0_reg = acp70_sdw_dp_reg[params->port_num].hctrl_dp0_reg; @@ -614,6 +616,7 @@ static int amd_sdw_port_enable(struct sdw_bus *bus, break; case ACP70_PCI_REV_ID: case ACP71_PCI_REV_ID: + case ACP72_PCI_REV_ID: lane_ctrl_ch_en_reg = acp70_sdw_dp_reg[enable_ch->port_num].lane_ctrl_ch_en_reg; break; default: @@ -931,6 +934,9 @@ static void amd_sdw_irq_thread(struct work_struct *work) status_change_8to11 = readl(amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_8TO11); status_change_0to7 = readl(amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_0TO7); + if (!status_change_0to7 && !status_change_8to11) + return; + dev_dbg(amd_manager->dev, "[SDW%d] SDW INT: 0to7=0x%x, 8to11=0x%x\n", amd_manager->instance, status_change_0to7, status_change_8to11); if (status_change_8to11 & AMD_SDW_WAKE_STAT_MASK) @@ -1035,6 +1041,7 @@ static int amd_sdw_manager_probe(struct platform_device *pdev) break; case ACP70_PCI_REV_ID: case ACP71_PCI_REV_ID: + case ACP72_PCI_REV_ID: amd_manager->num_dout_ports = AMD_ACP70_SDW_MAX_TX_PORTS; amd_manager->num_din_ports = AMD_ACP70_SDW_MAX_RX_PORTS; break; @@ -1074,6 +1081,7 @@ static void amd_sdw_manager_remove(struct platform_device *pdev) int ret; pm_runtime_disable(&pdev->dev); + cancel_work_sync(&amd_manager->amd_sdw_work); amd_disable_sdw_interrupts(amd_manager); sdw_bus_master_delete(&amd_manager->bus); ret = amd_disable_sdw_manager(amd_manager); @@ -1178,10 +1186,10 @@ static int __maybe_unused amd_pm_prepare(struct device *dev) * device is not in runtime suspend state, observed that device alerts are missing * without pm_prepare on AMD platforms in clockstop mode0. */ - if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) { - ret = pm_request_resume(dev); + if (amd_manager->power_mode_mask) { + ret = pm_runtime_resume(dev); if (ret < 0) { - dev_err(bus->dev, "pm_request_resume failed: %d\n", ret); + dev_err(bus->dev, "pm_runtime_resume failed: %d\n", ret); return 0; } } diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 68db4b67a86f..4fd5cac799c5 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1753,15 +1753,15 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) /* Update the Slave driver */ if (slave_notify) { + if (slave->prop.use_domain_irq && slave->irq) + handle_nested_irq(slave->irq); + mutex_lock(&slave->sdw_dev_lock); if (slave->probed) { struct device *dev = &slave->dev; struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); - if (slave->prop.use_domain_irq && slave->irq) - handle_nested_irq(slave->irq); - if (drv->ops && drv->ops->interrupt_callback) { slave_intr.sdca_cascade = sdca_cascade; slave_intr.control_port = clear; diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c index 3099ea074f10..230a51489486 100644 --- a/drivers/soundwire/debugfs.c +++ b/drivers/soundwire/debugfs.c @@ -291,6 +291,9 @@ static int cmd_go(void *data, u64 value) finish_t = ktime_get(); + dev_dbg(&slave->dev, "command completed, num_byte %zu status %d, time %lld ms\n", + num_bytes, ret, div_u64(finish_t - start_t, NSEC_PER_MSEC)); + out: if (fw) release_firmware(fw); @@ -298,9 +301,6 @@ out: pm_runtime_mark_last_busy(&slave->dev); pm_runtime_put(&slave->dev); - dev_dbg(&slave->dev, "command completed, num_byte %zu status %d, time %lld ms\n", - num_bytes, ret, div_u64(finish_t - start_t, NSEC_PER_MSEC)); - return ret; } DEFINE_DEBUGFS_ATTRIBUTE(cmd_go_fops, NULL, diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c index 5b31e1f69591..5d08364ad6d1 100644 --- a/drivers/soundwire/intel_ace2x.c +++ b/drivers/soundwire/intel_ace2x.c @@ -11,6 +11,7 @@ #include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_intel.h> +#include <linux/string_choices.h> #include <sound/hdaudio.h> #include <sound/hda-mlink.h> #include <sound/hda-sdw-bpt.h> @@ -183,7 +184,7 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave * return 0; dev_err(cdns->dev, "%s: sdw_prepare_%s_dma_buffer failed %d\n", - __func__, command ? "read" : "write", ret); + __func__, str_read_write(command), ret); ret1 = hda_sdw_bpt_close(cdns->dev->parent, /* PCI device */ sdw->bpt_ctx.bpt_tx_stream, &sdw->bpt_ctx.dmab_tx_bdl, @@ -245,7 +246,7 @@ static void intel_ace2x_bpt_close_stream(struct sdw_intel *sdw, struct sdw_slave cdns->bus.bpt_stream = NULL; } -#define INTEL_BPT_MSG_BYTE_ALIGNMENT 32 +#define INTEL_BPT_MSG_BYTE_MIN 16 static int intel_ace2x_bpt_send_async(struct sdw_intel *sdw, struct sdw_slave *slave, struct sdw_bpt_msg *msg) @@ -253,9 +254,9 @@ static int intel_ace2x_bpt_send_async(struct sdw_intel *sdw, struct sdw_slave *s struct sdw_cdns *cdns = &sdw->cdns; int ret; - if (msg->len % INTEL_BPT_MSG_BYTE_ALIGNMENT) { - dev_err(cdns->dev, "BPT message length %d is not a multiple of %d bytes\n", - msg->len, INTEL_BPT_MSG_BYTE_ALIGNMENT); + if (msg->len < INTEL_BPT_MSG_BYTE_MIN) { + dev_err(cdns->dev, "BPT message length %d is less than the minimum bytes %d\n", + msg->len, INTEL_BPT_MSG_BYTE_MIN); return -EINVAL; } diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c index 10a602d4843a..6df2601fff90 100644 --- a/drivers/soundwire/intel_auxdevice.c +++ b/drivers/soundwire/intel_auxdevice.c @@ -65,6 +65,7 @@ static struct wake_capable_part wake_capable_list[] = { {0x025d, 0x715}, {0x025d, 0x716}, {0x025d, 0x717}, + {0x025d, 0x721}, {0x025d, 0x722}, }; diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index 65afb28ef8fa..c69b78cd0b62 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -451,10 +451,10 @@ int sdw_slave_read_prop(struct sdw_slave *slave) "mipi-sdw-highPHY-capable"); prop->paging_support = mipi_device_property_read_bool(dev, - "mipi-sdw-paging-support"); + "mipi-sdw-paging-supported"); prop->bank_delay_support = mipi_device_property_read_bool(dev, - "mipi-sdw-bank-delay-support"); + "mipi-sdw-bank-delay-supported"); device_property_read_u32(dev, "mipi-sdw-port15-read-behavior", &prop->p15_behave); diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 0f45e3404756..bd2b293b44f2 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -1622,9 +1622,9 @@ static int qcom_swrm_probe(struct platform_device *pdev) if (ret) goto err_master_add; - dev_info(dev, "Qualcomm Soundwire controller v%x.%x.%x Registered\n", - (ctrl->version >> 24) & 0xff, (ctrl->version >> 16) & 0xff, - ctrl->version & 0xffff); + dev_dbg(dev, "Qualcomm Soundwire controller v%x.%x.%x registered\n", + (ctrl->version >> 24) & 0xff, (ctrl->version >> 16) & 0xff, + ctrl->version & 0xffff); pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index a4bea742b5d9..38c9dbd35606 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -1510,7 +1510,7 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream, if (ret < 0) { dev_err(bus->dev, "Prepare port(s) failed ret = %d\n", ret); - return ret; + goto restore_params; } } diff --git a/include/linux/soundwire/sdw_amd.h b/include/linux/soundwire/sdw_amd.h index 6b839987f14c..fe31773d5210 100644 --- a/include/linux/soundwire/sdw_amd.h +++ b/include/linux/soundwire/sdw_amd.h @@ -30,6 +30,7 @@ #define ACP63_PCI_REV_ID 0x63 #define ACP70_PCI_REV_ID 0x70 #define ACP71_PCI_REV_ID 0x71 +#define ACP72_PCI_REV_ID 0x72 struct acp_sdw_pdata { u16 instance; diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c index f5c5150c25e5..2a0a4986a9ce 100644 --- a/sound/soc/codecs/cs42l43-jack.c +++ b/sound/soc/codecs/cs42l43-jack.c @@ -361,14 +361,15 @@ static void cs42l43_stop_button_detect(struct cs42l43_codec *priv) priv->button_detect_running = false; } +#define CS42L43_BUTTON_COMB_US 11000 #define CS42L43_BUTTON_COMB_MAX 512 #define CS42L43_BUTTON_ROUT 2210 -void cs42l43_button_press_work(struct work_struct *work) +irqreturn_t cs42l43_button_press(int irq, void *data) { - struct cs42l43_codec *priv = container_of(work, struct cs42l43_codec, - button_press_work.work); + struct cs42l43_codec *priv = data; struct cs42l43 *cs42l43 = priv->core; + irqreturn_t iret = IRQ_NONE; unsigned int buttons = 0; unsigned int val = 0; int i, ret; @@ -376,7 +377,7 @@ void cs42l43_button_press_work(struct work_struct *work) ret = pm_runtime_resume_and_get(priv->dev); if (ret) { dev_err(priv->dev, "Failed to resume for button press: %d\n", ret); - return; + return iret; } mutex_lock(&priv->jack_lock); @@ -386,6 +387,9 @@ void cs42l43_button_press_work(struct work_struct *work) goto error; } + // Wait for 2 full cycles of comb filter to ensure good reading + usleep_range(2 * CS42L43_BUTTON_COMB_US, 2 * CS42L43_BUTTON_COMB_US + 50); + regmap_read(cs42l43->regmap, CS42L43_DETECT_STATUS_1, &val); /* Bail if jack removed, the button is irrelevant and likely invalid */ @@ -419,33 +423,26 @@ void cs42l43_button_press_work(struct work_struct *work) snd_soc_jack_report(priv->jack_hp, buttons, CS42L43_JACK_BUTTONS); + iret = IRQ_HANDLED; + error: mutex_unlock(&priv->jack_lock); pm_runtime_put_autosuspend(priv->dev); -} - -irqreturn_t cs42l43_button_press(int irq, void *data) -{ - struct cs42l43_codec *priv = data; - - // Wait for 2 full cycles of comb filter to ensure good reading - queue_delayed_work(system_wq, &priv->button_press_work, - msecs_to_jiffies(20)); - return IRQ_HANDLED; + return iret; } -void cs42l43_button_release_work(struct work_struct *work) +irqreturn_t cs42l43_button_release(int irq, void *data) { - struct cs42l43_codec *priv = container_of(work, struct cs42l43_codec, - button_release_work); + struct cs42l43_codec *priv = data; + irqreturn_t iret = IRQ_NONE; int ret; ret = pm_runtime_resume_and_get(priv->dev); if (ret) { dev_err(priv->dev, "Failed to resume for button release: %d\n", ret); - return; + return iret; } mutex_lock(&priv->jack_lock); @@ -454,6 +451,8 @@ void cs42l43_button_release_work(struct work_struct *work) dev_dbg(priv->dev, "Button release IRQ\n"); snd_soc_jack_report(priv->jack_hp, 0, CS42L43_JACK_BUTTONS); + + iret = IRQ_HANDLED; } else { dev_dbg(priv->dev, "Spurious button release IRQ\n"); } @@ -461,15 +460,8 @@ void cs42l43_button_release_work(struct work_struct *work) mutex_unlock(&priv->jack_lock); pm_runtime_put_autosuspend(priv->dev); -} -irqreturn_t cs42l43_button_release(int irq, void *data) -{ - struct cs42l43_codec *priv = data; - - queue_work(system_wq, &priv->button_release_work); - - return IRQ_HANDLED; + return iret; } void cs42l43_bias_sense_timeout(struct work_struct *work) @@ -782,8 +774,6 @@ irqreturn_t cs42l43_tip_sense(int irq, void *data) cancel_delayed_work(&priv->bias_sense_timeout); cancel_delayed_work(&priv->tip_sense_work); - cancel_delayed_work(&priv->button_press_work); - cancel_work(&priv->button_release_work); // Ensure delay after suspend is long enough to avoid false detection if (priv->suspend_jack_debounce) diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c index d84ad8d43438..b0c27d696c58 100644 --- a/sound/soc/codecs/cs42l43.c +++ b/sound/soc/codecs/cs42l43.c @@ -167,13 +167,14 @@ static void cs42l43_hp_ilimit_clear_work(struct work_struct *work) snd_soc_dapm_mutex_unlock(dapm); } -static void cs42l43_hp_ilimit_work(struct work_struct *work) +static irqreturn_t cs42l43_hp_ilimit(int irq, void *data) { - struct cs42l43_codec *priv = container_of(work, struct cs42l43_codec, - hp_ilimit_work); + struct cs42l43_codec *priv = data; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(priv->component); struct cs42l43 *cs42l43 = priv->core; + dev_dbg(priv->dev, "headphone ilimit IRQ\n"); + snd_soc_dapm_mutex_lock(dapm); if (priv->hp_ilimit_count < CS42L43_HP_ILIMIT_MAX_COUNT) { @@ -183,7 +184,7 @@ static void cs42l43_hp_ilimit_work(struct work_struct *work) priv->hp_ilimit_count++; snd_soc_dapm_mutex_unlock(dapm); - return; + return IRQ_HANDLED; } dev_err(priv->dev, "Disabling headphone for %dmS, due to frequent current limit\n", @@ -218,15 +219,6 @@ static void cs42l43_hp_ilimit_work(struct work_struct *work) priv->hp_ilimited = false; snd_soc_dapm_mutex_unlock(dapm); -} - -static irqreturn_t cs42l43_hp_ilimit(int irq, void *data) -{ - struct cs42l43_codec *priv = data; - - dev_dbg(priv->dev, "headphone ilimit IRQ\n"); - - queue_work(system_long_wq, &priv->hp_ilimit_work); return IRQ_HANDLED; } @@ -2158,10 +2150,7 @@ static void cs42l43_component_remove(struct snd_soc_component *component) cancel_delayed_work_sync(&priv->bias_sense_timeout); cancel_delayed_work_sync(&priv->tip_sense_work); - cancel_delayed_work_sync(&priv->button_press_work); - cancel_work_sync(&priv->button_release_work); - cancel_work_sync(&priv->hp_ilimit_work); cancel_delayed_work_sync(&priv->hp_ilimit_clear_work); priv->component = NULL; @@ -2313,10 +2302,7 @@ static int cs42l43_codec_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&priv->tip_sense_work, cs42l43_tip_sense_work); INIT_DELAYED_WORK(&priv->bias_sense_timeout, cs42l43_bias_sense_timeout); - INIT_DELAYED_WORK(&priv->button_press_work, cs42l43_button_press_work); INIT_DELAYED_WORK(&priv->hp_ilimit_clear_work, cs42l43_hp_ilimit_clear_work); - INIT_WORK(&priv->button_release_work, cs42l43_button_release_work); - INIT_WORK(&priv->hp_ilimit_work, cs42l43_hp_ilimit_work); pm_runtime_set_autosuspend_delay(priv->dev, 100); pm_runtime_use_autosuspend(priv->dev); diff --git a/sound/soc/codecs/cs42l43.h b/sound/soc/codecs/cs42l43.h index 1cd9d8a71c43..3ea36362b11a 100644 --- a/sound/soc/codecs/cs42l43.h +++ b/sound/soc/codecs/cs42l43.h @@ -88,8 +88,6 @@ struct cs42l43_codec { struct delayed_work tip_sense_work; struct delayed_work bias_sense_timeout; - struct delayed_work button_press_work; - struct work_struct button_release_work; struct completion type_detect; struct completion load_detect; @@ -99,7 +97,6 @@ struct cs42l43_codec { int jack_override; bool suspend_jack_debounce; - struct work_struct hp_ilimit_work; struct delayed_work hp_ilimit_clear_work; bool hp_ilimited; int hp_ilimit_count; @@ -134,8 +131,6 @@ int cs42l43_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jack, void *d); void cs42l43_bias_sense_timeout(struct work_struct *work); void cs42l43_tip_sense_work(struct work_struct *work); -void cs42l43_button_press_work(struct work_struct *work); -void cs42l43_button_release_work(struct work_struct *work); irqreturn_t cs42l43_bias_detect_clamp(int irq, void *data); irqreturn_t cs42l43_button_press(int irq, void *data); irqreturn_t cs42l43_button_release(int irq, void *data); |