From nobody Mon Jun 15 15:08:12 2026 Received: from mail-dy1-f172.google.com (mail-dy1-f172.google.com [74.125.82.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 913372E2EF9 for ; Sat, 11 Apr 2026 04:54:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775883283; cv=none; b=RQ79OgVZX+mgnggk1iRH8Qt4HXm5+/Vmfud/iUfaSypjj2eYYKCBXq1Q+6EKWtQdneet6lvnvnz9sJpPUhIMn38lsJIOQMdBqKSz8logR0kyO5WatxlXq/u7bG0km6DWqL4XBfAVoSOGLkjLJogY1V8NdKgUkTLmCGgrocnEIKU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775883283; c=relaxed/simple; bh=yC5W6bSUIYMX3dHsvMHSJERX+BChWerrSP13apEg1Cc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OWkS+x3cwqhXi0OxLe+jfX7ns05yTbIx5Cr5scVz91xhmsDKmWC7FpinYQy+Fyf3NRK7zyLiHY23sPfVi2VDw2MQ+5Jz9jUo8yarz2IgPz/PdzEhVh1Zyo72oLNGGyl00F/fO/GIhQ/PqeZ1nAXlnx7RDgjQ/yU/teGhl2xiNU0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kA7wTYZA; arc=none smtp.client-ip=74.125.82.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kA7wTYZA" Received: by mail-dy1-f172.google.com with SMTP id 5a478bee46e88-2d73f41b4f2so293797eec.1 for ; Fri, 10 Apr 2026 21:54:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775883281; x=1776488081; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=tLscJC43HBKbTT8zpntHphEX5063DkOG1/JtZ6+kZuQ=; b=kA7wTYZAEtErwm7y6qi92Inwmu39FDgOb6cG8MapsVxFkrVhtKI7K6lymXBR7BMjA4 UUVjrnT64f8pEXycpJZ88yI62dp9Hp0My9bezvKzPOL3JToWEvcHQIfWellPfDFmYV7h Sl2hHMwwOXYPDhimIYsZBAQE3XOVldVoEM7731VZWZg1x+5zP7GDGhMe7uYywT7Tb1JP dBulXNifTAeRgYE7gX15tJlclQgnnSfvF8KvTfhK/zGYgaePHLJoelEAGhQ0YbY7Gcch s9CdqGk9ytRDAnL3xhH/O4A822qnVuXCfGzkkCsl3PgBbjkfn6fy3kFR6kMvelGUKXpu J5nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775883281; x=1776488081; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=tLscJC43HBKbTT8zpntHphEX5063DkOG1/JtZ6+kZuQ=; b=BNmYam9NcU+bX1LqF6SkzmThv2e2tctrLPz67QireJiasyTQQyqC862HxaDV4OGHq8 xKxVbhBYQT+zLrmBh89G/djKcGErmhUf9SgXpg56TDgQztll13VJUSlWkajGQbG+oheo zNe/GHuTbxTUku6H73pwaFOImhp8z2nd/yGl2MYksSwIMFzZV+9AecLgD7t2hoaL9MBU mNe2teKraYZX1qoD9j3lV5plUbxBlnW7duurueeVze4MVOeFB+ZLNdDjWHnePzr7HzQZ g79gLFJgHHvdk1FOZJ7Rd08XEhgJd5SQb/z2paF9Hrr1YPoGWKUYOIVTNRK1K+fmHwW1 yjYw== X-Forwarded-Encrypted: i=1; AJvYcCV9ueQKOgy8VfcFweM/skM3G6AT93ciXcuiiJhm5XBTo5s97+zubha0xG7bMgpBg544ekpjXaRbPiQmP5Y=@vger.kernel.org X-Gm-Message-State: AOJu0YzS9MNTZmPDvVYm2jhpP0w+iy1iNmNonIqVeuBHlYB6iThJgKU5 cZeevSaIInH5Anu3OQR/KqVIFzP5Y7jVaQPqsW9QKZQ298RSYqzuS7LP X-Gm-Gg: AeBDiesMtk6PVg+NU7X9/f9QUxdxEKt8mZNp6BGi+GuUomIcXsBI2CV8udJ25BUbj1K 4exxh7R2YMr5tQF9whDU+J8wDnRTgM1eL25M/ox3oftP7ftEu3c86WMmCbGryQOmgjSgxfSolE6 3Z9dXls4k1G4hvKL3PcoditxtqFRcpLAmBOFVMtu/bei8ESXNvw/4yCj4ZTKTTyTl27wUtcEhJ9 JIwgl2LvaHl3ZrgAg6jZUPnhvvYcT5chuHuLnU8b52NTArF0RYR26bA8IMLltM8tMuXlD9uBnpa KXuYcxdFGpdEtlEoz6ncyCLpYuAceQpSXFlUEid4wYE9TAUK2Dd3I2cv7i28nKxf9z9SvpQVGNZ OZjiBmMxNIF6Nq3+ljw+taEWUlqox4DRu2cTwOjqxMD4+gZissha0ubuJSZl5xJ/DCXygulV82e ha530ymdR0aMYOBSUOI/PlPuZGb8aBpbysYy5RyvLF9LxNSkA1VrsdurKSlLz6GxT01CMKIPacI 67l X-Received: by 2002:a05:7300:430a:b0:2d4:2cc8:67e with SMTP id 5a478bee46e88-2d589dafcadmr3774829eec.23.1775883280479; Fri, 10 Apr 2026 21:54:40 -0700 (PDT) Received: from [192.168.1.18] (177-4-160-195.user3p.v-tal.net.br. [177.4.160.195]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2d561bde68bsm7378754eec.17.2026.04.10.21.54.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Apr 2026 21:54:40 -0700 (PDT) From: =?utf-8?q?C=C3=A1ssio_Gabriel?= Date: Sat, 11 Apr 2026 01:54:29 -0300 Subject: [PATCH 1/2] ALSA: sscape: Cache per-card resources for board reinitialization Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260411-alsa-sscape-pm-v1-1-3058d988783a@gmail.com> References: <20260411-alsa-sscape-pm-v1-0-3058d988783a@gmail.com> In-Reply-To: <20260411-alsa-sscape-pm-v1-0-3058d988783a@gmail.com> To: Takashi Iwai , Jaroslav Kysela Cc: linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?C=C3=A1ssio_Gabriel?= X-Mailer: b4 0.15.1 X-Developer-Signature: v=1; a=openpgp-sha256; l=11999; i=cassiogabrielcontato@gmail.com; h=from:subject:message-id; bh=yC5W6bSUIYMX3dHsvMHSJERX+BChWerrSP13apEg1Cc=; b=owGbwMvMwCV2IdZeKur/u2bG02pJDJk3r3BlJEwSYf6k/qRFOzSWx6Bw9Ty1pWsmldSqhV1tN bss4be/o5SFQYyLQVZMkWV10iLLPV0PrtbHrfCAmcPKBDKEgYtTACZicoeR4fuLecolkx62OQae Dp7Ylbfv23fPZ7/NrTdPWcHFsF/ipwUjwyX/X8KlNgYtf7c+7zn1PD9tZ1YGv5rfroboGt7Kh/l L+QE= X-Developer-Key: i=cassiogabrielcontato@gmail.com; a=openpgp; fpr=AB62A239BC8AE0D57F5EA848D05D3F1A5AFFEE83 The SoundScape driver programs the gate-array directly from the global resource arrays during probe. That is sufficient for initial bring-up, but a PM resume path also needs the resolved per-card IRQ, DMA, MPU IRQ and joystick settings after probe has finished. Store the resolved resources in struct soundscape and move the board setup into a reusable helper. Also factor the MIDI state programming so the same sequence can be reused by a later PM resume path. This is preparatory work for suspend/resume support and is not intended to change runtime behaviour. Signed-off-by: C=C3=A1ssio Gabriel --- sound/isa/sscape.c | 210 +++++++++++++++++++++++++++++++------------------= ---- 1 file changed, 125 insertions(+), 85 deletions(-) diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index a31ca75774a6..3e9465bc64ed 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -131,6 +131,11 @@ enum card_type { struct soundscape { spinlock_t lock; unsigned io_base; + unsigned long wss_base; + int irq; + int mpu_irq; + int dma1; + int dma2; int ic_type; enum card_type type; struct resource *io_res; @@ -138,6 +143,7 @@ struct soundscape { struct snd_wss *chip; =20 unsigned char midi_vol; + bool joystick; struct device *dev; }; =20 @@ -149,6 +155,21 @@ static inline struct soundscape *get_card_soundscape(s= truct snd_card *c) return (struct soundscape *) (c->private_data); } =20 +/* + * Store the resolved board settings in the per-card state so that + * the same configuration can be replayed later if necessary. + */ +static void sscape_store_settings(struct soundscape *sscape, int dev) +{ + sscape->io_base =3D port[dev]; + sscape->wss_base =3D wss_port[dev]; + sscape->irq =3D irq[dev]; + sscape->mpu_irq =3D mpu_irq[dev]; + sscape->dma1 =3D dma[dev]; + sscape->dma2 =3D dma2[dev]; + sscape->joystick =3D joystick[dev]; +} + /* * Allocates some kernel memory that we can use for DMA. * I think this means that the memory has to map to @@ -560,6 +581,28 @@ static int sscape_upload_microcode(struct snd_card *ca= rd, int version) return err; } =20 +/* + * Restore the SoundScape's MIDI control state after the firmware + * upload has made the host interface available again. + */ +static int sscape_restore_midi_state(struct soundscape *sscape) +{ + int err =3D 1; + + guard(spinlock_irqsave)(&sscape->lock); + set_host_mode_unsafe(sscape->io_base); + err &=3D host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); + err &=3D host_write_ctrl_unsafe(sscape->io_base, sscape->midi_vol, 100); + err &=3D host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100); + err &=3D host_write_ctrl_unsafe(sscape->io_base, sscape->midi_vol, 100); + err &=3D host_write_ctrl_unsafe(sscape->io_base, CMD_SET_EXTMIDI, 100); + err &=3D host_write_ctrl_unsafe(sscape->io_base, 0, 100); + err &=3D host_write_ctrl_unsafe(sscape->io_base, CMD_ACK, 100); + set_midi_mode_unsafe(sscape->io_base); + + return err ? 0 : -EIO; +} + /* * Mixer control for the SoundScape's MIDI device. */ @@ -660,6 +703,59 @@ static unsigned get_irq_config(int sscape_type, int ir= q) return INVALID_IRQ; } =20 +/* + * Program the SoundScape's board-specific routing and enable the + * codec path using the resolved IRQ, DMA and joystick settings. + */ +static int sscape_configure_board(struct soundscape *sscape) +{ + unsigned int dma_cfg; + unsigned int irq_cfg; + unsigned int mpu_irq_cfg; + int val; + + irq_cfg =3D get_irq_config(sscape->type, sscape->irq); + if (irq_cfg =3D=3D INVALID_IRQ) + return -ENXIO; + + mpu_irq_cfg =3D get_irq_config(sscape->type, sscape->mpu_irq); + if (mpu_irq_cfg =3D=3D INVALID_IRQ) + return -ENXIO; + + scoped_guard(spinlock_irqsave, &sscape->lock) { + if (sscape->ic_type =3D=3D IC_OPUS) + activate_ad1845_unsafe(sscape->io_base); + + sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e); + sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00); + + /* + * Enable and configure the DMA channels ... + */ + sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50); + dma_cfg =3D (sscape->ic_type =3D=3D IC_OPUS ? 0x40 : 0x70); + sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg); + sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20); + + mpu_irq_cfg |=3D mpu_irq_cfg << 2; + val =3D sscape_read_unsafe(sscape->io_base, GA_HMCTL_REG) & 0xf7; + if (sscape->joystick) + val |=3D 0x08; + sscape_write_unsafe(sscape->io_base, GA_HMCTL_REG, val | 0xd0); + sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, + 0xf0 | mpu_irq_cfg); + sscape_write_unsafe(sscape->io_base, GA_CDCFG_REG, + 0x09 | DMA_8BIT | + (sscape->dma1 << 4) | (irq_cfg << 1)); + /* + * Enable the master IRQ ... + */ + sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x80); + } + + return 0; +} + /* * Perform certain arcane port-checks to see whether there * is a SoundScape board lurking behind the given ports. @@ -890,37 +986,33 @@ static int create_ad1845(struct snd_card *card, unsig= ned port, =20 /* * Create an ALSA soundcard entry for the SoundScape, using - * the given list of port, IRQ and DMA resources. + * the resolved port, IRQ and DMA resources. */ -static int create_sscape(int dev, struct snd_card *card) +static int create_sscape(struct snd_card *card) { struct soundscape *sscape =3D get_card_soundscape(card); - unsigned dma_cfg; - unsigned irq_cfg; - unsigned mpu_irq_cfg; struct resource *io_res; struct resource *wss_res; int err; - int val; const char *name; =20 /* * Grab IO ports that we will need to probe so that we * can detect and control this hardware ... */ - io_res =3D devm_request_region(card->dev, port[dev], 8, "SoundScape"); + io_res =3D devm_request_region(card->dev, sscape->io_base, 8, "SoundScape= "); if (!io_res) { dev_err(card->dev, - "sscape: can't grab port 0x%lx\n", port[dev]); + "sscape: can't grab port 0x%x\n", sscape->io_base); return -EBUSY; } wss_res =3D NULL; if (sscape->type =3D=3D SSCAPE_VIVO) { - wss_res =3D devm_request_region(card->dev, wss_port[dev], 4, + wss_res =3D devm_request_region(card->dev, sscape->wss_base, 4, "SoundScape"); if (!wss_res) { dev_err(card->dev, "sscape: can't grab port 0x%lx\n", - wss_port[dev]); + sscape->wss_base); return -EBUSY; } } @@ -928,18 +1020,17 @@ static int create_sscape(int dev, struct snd_card *c= ard) /* * Grab one DMA channel ... */ - err =3D snd_devm_request_dma(card->dev, dma[dev], "SoundScape"); + err =3D snd_devm_request_dma(card->dev, sscape->dma1, "SoundScape"); if (err < 0) { - dev_err(card->dev, "sscape: can't grab DMA %d\n", dma[dev]); + dev_err(card->dev, "sscape: can't grab DMA %d\n", sscape->dma1); return err; } =20 spin_lock_init(&sscape->lock); sscape->io_res =3D io_res; sscape->wss_res =3D wss_res; - sscape->io_base =3D port[dev]; =20 - if (!detect_sscape(sscape, wss_port[dev])) { + if (!detect_sscape(sscape, sscape->wss_base)) { dev_err(card->dev, "sscape: hardware not detected at 0x%x\n", sscape->io_base); return -ENODEV; @@ -964,66 +1055,28 @@ static int create_sscape(int dev, struct snd_card *c= ard) } =20 dev_info(card->dev, "sscape: %s card detected at 0x%x, using IRQ %d, DMA = %d\n", - name, sscape->io_base, irq[dev], dma[dev]); - - /* - * Check that the user didn't pass us garbage data ... - */ - irq_cfg =3D get_irq_config(sscape->type, irq[dev]); - if (irq_cfg =3D=3D INVALID_IRQ) { - dev_err(card->dev, "sscape: Invalid IRQ %d\n", irq[dev]); - return -ENXIO; - } - - mpu_irq_cfg =3D get_irq_config(sscape->type, mpu_irq[dev]); - if (mpu_irq_cfg =3D=3D INVALID_IRQ) { - dev_err(card->dev, "sscape: Invalid IRQ %d\n", mpu_irq[dev]); - return -ENXIO; - } + name, sscape->io_base, sscape->irq, sscape->dma1); =20 /* * Tell the on-board devices where their resources are (I think - * I can't be sure without a datasheet ... So many magic values!) */ - scoped_guard(spinlock_irqsave, &sscape->lock) { - - sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e); - sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00); - - /* - * Enable and configure the DMA channels ... - */ - sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50); - dma_cfg =3D (sscape->ic_type =3D=3D IC_OPUS ? 0x40 : 0x70); - sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg); - sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20); - - mpu_irq_cfg |=3D mpu_irq_cfg << 2; - val =3D sscape_read_unsafe(sscape->io_base, GA_HMCTL_REG) & 0xF7; - if (joystick[dev]) - val |=3D 8; - sscape_write_unsafe(sscape->io_base, GA_HMCTL_REG, val | 0x10); - sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg); - sscape_write_unsafe(sscape->io_base, - GA_CDCFG_REG, 0x09 | DMA_8BIT - | (dma[dev] << 4) | (irq_cfg << 1)); - /* - * Enable the master IRQ ... - */ - sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x80); - + err =3D sscape_configure_board(sscape); + if (err < 0) { + dev_err(card->dev, "sscape: Invalid IRQ configuration\n"); + return err; } =20 /* * We have now enabled the codec chip, and so we should * detect the AD1845 device ... */ - err =3D create_ad1845(card, wss_port[dev], irq[dev], - dma[dev], dma2[dev]); + err =3D create_ad1845(card, sscape->wss_base, sscape->irq, + sscape->dma1, sscape->dma2); if (err < 0) { dev_err(card->dev, "sscape: No AD1845 device at 0x%lx, IRQ %d\n", - wss_port[dev], irq[dev]); + sscape->wss_base, sscape->irq); return err; } strscpy(card->driver, "SoundScape"); @@ -1040,35 +1093,21 @@ static int create_sscape(int dev, struct snd_card *= card) err =3D sscape_upload_microcode(card, err); =20 if (err =3D=3D 0) { - err =3D create_mpu401(card, MIDI_DEVNUM, port[dev], - mpu_irq[dev]); + err =3D create_mpu401(card, MIDI_DEVNUM, sscape->io_base, + sscape->mpu_irq); if (err < 0) { dev_err(card->dev, "sscape: Failed to create MPU-401 device at 0x%lx\n", - port[dev]); + (unsigned long)sscape->io_base); return err; } =20 - /* - * Initialize mixer - */ - guard(spinlock_irqsave)(&sscape->lock); sscape->midi_vol =3D 0; - host_write_ctrl_unsafe(sscape->io_base, - CMD_SET_MIDI_VOL, 100); - host_write_ctrl_unsafe(sscape->io_base, - sscape->midi_vol, 100); - host_write_ctrl_unsafe(sscape->io_base, - CMD_XXX_MIDI_VOL, 100); - host_write_ctrl_unsafe(sscape->io_base, - sscape->midi_vol, 100); - host_write_ctrl_unsafe(sscape->io_base, - CMD_SET_EXTMIDI, 100); - host_write_ctrl_unsafe(sscape->io_base, - 0, 100); - host_write_ctrl_unsafe(sscape->io_base, CMD_ACK, 100); - - set_midi_mode_unsafe(sscape->io_base); + err =3D sscape_restore_midi_state(sscape); + if (err < 0) + dev_warn(card->dev, + "sscape: MIDI init incomplete: %d\n", + err); } } =20 @@ -1111,8 +1150,9 @@ static int snd_sscape_probe(struct device *pdev, unsi= gned int dev) sscape->type =3D SSCAPE; =20 dma[dev] &=3D 0x03; + sscape_store_settings(sscape, dev); =20 - ret =3D create_sscape(dev, card); + ret =3D create_sscape(card); if (ret < 0) return ret; =20 @@ -1130,7 +1170,6 @@ static int snd_sscape_probe(struct device *pdev, unsi= gned int dev) static struct isa_driver snd_sscape_driver =3D { .match =3D snd_sscape_match, .probe =3D snd_sscape_probe, - /* FIXME: suspend/resume */ .driver =3D { .name =3D DEV_NAME }, @@ -1211,8 +1250,9 @@ static int sscape_pnp_detect(struct pnp_card_link *pc= ard, wss_port[idx] =3D pnp_port_start(dev, 1); dma2[idx] =3D pnp_dma(dev, 1); } + sscape_store_settings(sscape, idx); =20 - ret =3D create_sscape(idx, card); + ret =3D create_sscape(card); if (ret < 0) return ret; =20 --=20 2.53.0 From nobody Mon Jun 15 15:08:12 2026 Received: from mail-dl1-f41.google.com (mail-dl1-f41.google.com [74.125.82.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F4262E92D2 for ; Sat, 11 Apr 2026 04:54:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775883285; cv=none; b=eqI5friza8xler3OgBgUrCQrIh30av/MchiQQwal31GnEmo5uccb9fZmibVKMKGAnNzsL6HqkFDL9EFl62e2KutNmp6fH3G6GHs71pzjRb2yG+K/Lz3oIO2d78+0s0OzD4+vBIpPy42ZjWo7Yck6aQvtgTsoZk2EgsgP0RN/+ek= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775883285; c=relaxed/simple; bh=44VU8sEg3pSU05phaWthjAuCttLZNp5eU+EubpFEzns=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lTyZQKPe5teOgCuSAx1SNA8IIvA+GACnm99dae+FKxdbjNX7NNXnwUTu2VQ6C1rZjvIS1McUZjQllG12rgpZCHofqCb6toncoqIO0QfAwnZNWZSFoDfvwPn/MAmnrJIrh4+Gqogl0rTGRAHaCbBngt12xaCgBZH7E+pEjjYadVk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=EkdwY5Xd; arc=none smtp.client-ip=74.125.82.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="EkdwY5Xd" Received: by mail-dl1-f41.google.com with SMTP id a92af1059eb24-1279eced0b9so4057115c88.0 for ; Fri, 10 Apr 2026 21:54:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775883283; x=1776488083; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=byGIJZB003iIrAl7vLNw6wWjasi/2CrJc6DHYo+7Dlo=; b=EkdwY5XdCYtsPGWfSbFeY+lDiXoZvz5HjVPqrcutr5vB9xpA2j9m1mim0sRMERm1xJ T5p+kon8NVKNZddCUrzuGb2T6/VLHGsSdkI6R8kV9mq2202aGY5Gz11eECsrnNjQauIc 75F1HSDr1CbMM+BnhIKc40Jpvm76Yl9BXTmW8Z8V2J5dbruEnC7tkZxD7xmCYBfgirzE PfWcEkf/pem8xsKW35Yx8953m5vztkME2xF5hruSF901/SPzDxfUjRnyehW+SQdmPao9 UOXF1PZNPHFlD06UybiuIBn+k/tZN7WfGGhnfFYogMIk8EBkBP8HhwH1cOzkeu4EykC3 TQGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775883283; x=1776488083; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=byGIJZB003iIrAl7vLNw6wWjasi/2CrJc6DHYo+7Dlo=; b=UzM64XfhlRPkh45osqAUq66X1Wc9Y8ut9keBi8/pLhlZKdzg4T+E6ERtqDW4e/haBl FItiaNTzb/3jJvcNVWq5Q8u25rQgwPSdD6qEeF+WBfEw6NvEiNaSis3iusFIMBB7LtOq S7uD3B84r90SL5LkgHfb3PQVl1HAq3AcLgg9ufnrgJRmvXWNAmiAxYrGzOWCBn6pHFVV mmZL8ow+gLl6xiLxzRX+1acG43z7IO2V/5tPKghjSxkdBojToVuFEiNeuLSIuGbCjN/6 O4mOzJUx9LkhNr02vwv+zQ5igFabmtOS/dG8jK8ZSUMBB9jnrNpqGLMA9VxlEgzlhNqZ Mtbw== X-Forwarded-Encrypted: i=1; AJvYcCU/6/7goOp1a3BVruUQEXVSpxZm71eJL3RVLCSKOqAmE4Vd3wZ75Fs8GagNXP4MOehU0EVigTLSv6K9fvo=@vger.kernel.org X-Gm-Message-State: AOJu0YyOAjQt51gcZxuFp6Zufh9nRdvXxb0MOgrO3ptepqO+J2313dYP nAx7dZsKrMYVDy/qlmqjJ0RGP/b+ocfgJecv1opVtJ0ya2jR54qR2kKY X-Gm-Gg: AeBDieuRY3FTrMs9KErLZ6HSQh0FSoLlTIDvTNLALsudtD9s6yCBC3u5RdbewoLmHYc tRdMmFE1OiMhQ5WBtSVkf1sTdTiVuWGuxUCAS7RHv4TKgSuc/Tq7u/57GH7Y7YGt/BUzE1EmNTl ejyBINFuo7GiViyIwVOer3efkZBQ94bkoVPE+ZtosEdzLEpdIC7R8hIk9fCMweep86A1ma3QsE6 6DWAv9TKSAZC5VJOUcEhcExwxgv1sTQpTlfAwASuzSUzAKFg0nBvXsazLZrYEs4d/bcm0aa+VIr Bc9BeIiZ6GOBTE76ABb/ootPaCCLs9YNVmut2NEqQ0RPyN86bCnWxqjXh/7I13gH7sHXTdb2YVg 7nQ5v9gzRkxOvsDXkOVr2pAp8MBuZ9pIkQgeaWVTKPj/DR1DV/n9CGohpnFesCUYpfkhGfAPNE4 RSd/nV7ikFAKryMiscCcHIGEjx1YZgeb6ez6t/dPTAUa3jKIns08AWTsW3fSjAaV6sc047XLDxH Aef X-Received: by 2002:a05:7022:3d12:b0:128:d967:4678 with SMTP id a92af1059eb24-12c34eea0f0mr3260109c88.23.1775883283133; Fri, 10 Apr 2026 21:54:43 -0700 (PDT) Received: from [192.168.1.18] (177-4-160-195.user3p.v-tal.net.br. [177.4.160.195]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2d561bde68bsm7378754eec.17.2026.04.10.21.54.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Apr 2026 21:54:42 -0700 (PDT) From: =?utf-8?q?C=C3=A1ssio_Gabriel?= Date: Sat, 11 Apr 2026 01:54:30 -0300 Subject: [PATCH 2/2] ALSA: sscape: Add suspend and resume support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260411-alsa-sscape-pm-v1-2-3058d988783a@gmail.com> References: <20260411-alsa-sscape-pm-v1-0-3058d988783a@gmail.com> In-Reply-To: <20260411-alsa-sscape-pm-v1-0-3058d988783a@gmail.com> To: Takashi Iwai , Jaroslav Kysela Cc: linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?C=C3=A1ssio_Gabriel?= X-Mailer: b4 0.15.1 X-Developer-Signature: v=1; a=openpgp-sha256; l=4588; i=cassiogabrielcontato@gmail.com; h=from:subject:message-id; bh=44VU8sEg3pSU05phaWthjAuCttLZNp5eU+EubpFEzns=; b=owGbwMvMwCV2IdZeKur/u2bG02pJDJk3r3CtmPVEK8f723vb+GX7Phz//XOPb0TCl7t6E9T+J hqVTny4vqOUhUGMi0FWTJFlddIiyz1dD67Wx63wgJnDygQyhIGLUwAmcpmD4X/kckPmqXtnpdbw dDY89nndclav65Bh54tfLn/Ysxpuym5n+M3S/u55vGXG/0CWZzKr/ApcWk6s+cg5edprC/7y2Yf EU9kB X-Developer-Key: i=cassiogabrielcontato@gmail.com; a=openpgp; fpr=AB62A239BC8AE0D57F5EA848D05D3F1A5AFFEE83 The SoundScape ISA driver has lacked suspend and resume callbacks since commit 277e926c9b27 ("[ALSA] sscape - Use platform_device"). A plain snd_wss resume is not sufficient for SoundScape. Resume also needs to restore the board-specific gate-array routing, and non-VIVO boards need to reinitialize the probe-time MIDI firmware and MIDI control state when the MPU-401 side was enabled during probe. That firmware reload can be handled in-kernel because commit acd47100914b ("ALSA: sscape: convert to firmware loader framework") moved the driver to request_firmware(). Add ISA and ISA-PnP PM callbacks, reconfigure the board on resume, reload the non-VIVO MIDI firmware, restore the MIDI state, and then resume the WSS codec. If MIDI firmware reload fails, keep the WSS resume path alive and leave MIDI unavailable instead of failing the whole device resume. Signed-off-by: C=C3=A1ssio Gabriel --- sound/isa/sscape.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 93 insertions(+) diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 3e9465bc64ed..ff3d9e2498d9 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -144,6 +144,7 @@ struct soundscape { =20 unsigned char midi_vol; bool joystick; + bool midi_enabled; struct device *dev; }; =20 @@ -1103,6 +1104,7 @@ static int create_sscape(struct snd_card *card) } =20 sscape->midi_vol =3D 0; + sscape->midi_enabled =3D true; err =3D sscape_restore_midi_state(sscape); if (err < 0) dev_warn(card->dev, @@ -1114,6 +1116,77 @@ static int create_sscape(struct snd_card *card) return 0; } =20 +#ifdef CONFIG_PM +/* + * Reload the MIDI firmware and restore the saved MIDI state for + * boards whose MPU-401 side was enabled during probe. + */ +static int sscape_resume_midi(struct snd_card *card) +{ + struct soundscape *sscape =3D get_card_soundscape(card); + int err, version; + + if (!sscape->midi_enabled) + return 0; + + version =3D sscape_upload_bootblock(card); + if (version < 0) + return version; + + err =3D sscape_upload_microcode(card, version); + if (err < 0) + return err; + + outb(0, sscape->io_base); + + return sscape_restore_midi_state(sscape); +} + +/* + * Save the WSS codec state before the SoundScape is suspended. + */ +static int snd_sscape_suspend_card(struct snd_card *card) +{ + struct soundscape *sscape =3D get_card_soundscape(card); + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + sscape->chip->suspend(sscape->chip); + return 0; +} + +/* + * Restore the board-specific state before resuming the WSS codec. + */ +static int snd_sscape_resume_card(struct snd_card *card) +{ + struct soundscape *sscape =3D get_card_soundscape(card); + int err; + + err =3D sscape_configure_board(sscape); + if (err < 0) + return err; + + err =3D sscape_resume_midi(card); + if (err < 0) + dev_warn(card->dev, "sscape: MIDI restore failed: %d\n", err); + + sscape->chip->resume(sscape->chip); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} + +static int snd_sscape_suspend(struct device *dev, unsigned int n, + pm_message_t state) +{ + return snd_sscape_suspend_card(dev_get_drvdata(dev)); +} + +static int snd_sscape_resume(struct device *dev, unsigned int n) +{ + return snd_sscape_resume_card(dev_get_drvdata(dev)); +} +#endif + =20 static int snd_sscape_match(struct device *pdev, unsigned int i) { @@ -1170,6 +1243,10 @@ static int snd_sscape_probe(struct device *pdev, uns= igned int dev) static struct isa_driver snd_sscape_driver =3D { .match =3D snd_sscape_match, .probe =3D snd_sscape_probe, +#ifdef CONFIG_PM + .suspend =3D snd_sscape_suspend, + .resume =3D snd_sscape_resume, +#endif .driver =3D { .name =3D DEV_NAME }, @@ -1267,11 +1344,27 @@ static int sscape_pnp_detect(struct pnp_card_link *= pcard, return 0; } =20 +#ifdef CONFIG_PM +static int sscape_pnp_suspend(struct pnp_card_link *pcard, pm_message_t st= ate) +{ + return snd_sscape_suspend_card(pnp_get_card_drvdata(pcard)); +} + +static int sscape_pnp_resume(struct pnp_card_link *pcard) +{ + return snd_sscape_resume_card(pnp_get_card_drvdata(pcard)); +} +#endif + static struct pnp_card_driver sscape_pnpc_driver =3D { .flags =3D PNP_DRIVER_RES_DO_NOT_CHANGE, .name =3D "sscape", .id_table =3D sscape_pnpids, .probe =3D sscape_pnp_detect, +#ifdef CONFIG_PM + .suspend =3D sscape_pnp_suspend, + .resume =3D sscape_pnp_resume, +#endif }; =20 #endif /* CONFIG_PNP */ --=20 2.53.0