Skip to content

Commit 713e0f0

Browse files
CassivsGabriellistiwai
authored andcommitted
ALSA: sscape: Add suspend and resume support
The SoundScape ISA driver has lacked suspend and resume callbacks since commit 277e926 ("[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 acd4710 ("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ássio Gabriel <cassiogabrielcontato@gmail.com> Link: https://patch.msgid.link/20260411-alsa-sscape-pm-v2-2-aeb5682e14b0@gmail.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent f312f8b commit 713e0f0

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

sound/isa/sscape.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ struct soundscape {
144144

145145
unsigned char midi_vol;
146146
bool joystick;
147+
bool midi_enabled;
147148
struct device *dev;
148149
};
149150

@@ -1107,6 +1108,7 @@ static int create_sscape(struct snd_card *card)
11071108
}
11081109

11091110
sscape->midi_vol = 0;
1111+
sscape->midi_enabled = true;
11101112
err = sscape_restore_midi_state(sscape);
11111113
if (err < 0)
11121114
dev_warn(card->dev,
@@ -1118,6 +1120,77 @@ static int create_sscape(struct snd_card *card)
11181120
return 0;
11191121
}
11201122

1123+
#ifdef CONFIG_PM
1124+
/*
1125+
* Reload the MIDI firmware and restore the saved MIDI state for
1126+
* boards whose MPU-401 side was enabled during probe.
1127+
*/
1128+
static int sscape_resume_midi(struct snd_card *card)
1129+
{
1130+
struct soundscape *sscape = get_card_soundscape(card);
1131+
int err, version;
1132+
1133+
if (!sscape->midi_enabled)
1134+
return 0;
1135+
1136+
version = sscape_upload_bootblock(card);
1137+
if (version < 0)
1138+
return version;
1139+
1140+
err = sscape_upload_microcode(card, version);
1141+
if (err < 0)
1142+
return err;
1143+
1144+
outb(0, sscape->io_base);
1145+
1146+
return sscape_restore_midi_state(sscape);
1147+
}
1148+
1149+
/*
1150+
* Save the WSS codec state before the SoundScape is suspended.
1151+
*/
1152+
static int snd_sscape_suspend_card(struct snd_card *card)
1153+
{
1154+
struct soundscape *sscape = get_card_soundscape(card);
1155+
1156+
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1157+
sscape->chip->suspend(sscape->chip);
1158+
return 0;
1159+
}
1160+
1161+
/*
1162+
* Restore the board-specific state before resuming the WSS codec.
1163+
*/
1164+
static int snd_sscape_resume_card(struct snd_card *card)
1165+
{
1166+
struct soundscape *sscape = get_card_soundscape(card);
1167+
int err;
1168+
1169+
err = sscape_configure_board(sscape);
1170+
if (err < 0)
1171+
return err;
1172+
1173+
err = sscape_resume_midi(card);
1174+
if (err < 0)
1175+
dev_warn(card->dev, "sscape: MIDI restore failed: %d\n", err);
1176+
1177+
sscape->chip->resume(sscape->chip);
1178+
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
1179+
return 0;
1180+
}
1181+
1182+
static int snd_sscape_suspend(struct device *dev, unsigned int n,
1183+
pm_message_t state)
1184+
{
1185+
return snd_sscape_suspend_card(dev_get_drvdata(dev));
1186+
}
1187+
1188+
static int snd_sscape_resume(struct device *dev, unsigned int n)
1189+
{
1190+
return snd_sscape_resume_card(dev_get_drvdata(dev));
1191+
}
1192+
#endif
1193+
11211194

11221195
static int snd_sscape_match(struct device *pdev, unsigned int i)
11231196
{
@@ -1174,6 +1247,10 @@ static int snd_sscape_probe(struct device *pdev, unsigned int dev)
11741247
static struct isa_driver snd_sscape_driver = {
11751248
.match = snd_sscape_match,
11761249
.probe = snd_sscape_probe,
1250+
#ifdef CONFIG_PM
1251+
.suspend = snd_sscape_suspend,
1252+
.resume = snd_sscape_resume,
1253+
#endif
11771254
.driver = {
11781255
.name = DEV_NAME
11791256
},
@@ -1271,11 +1348,27 @@ static int sscape_pnp_detect(struct pnp_card_link *pcard,
12711348
return 0;
12721349
}
12731350

1351+
#ifdef CONFIG_PM
1352+
static int sscape_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
1353+
{
1354+
return snd_sscape_suspend_card(pnp_get_card_drvdata(pcard));
1355+
}
1356+
1357+
static int sscape_pnp_resume(struct pnp_card_link *pcard)
1358+
{
1359+
return snd_sscape_resume_card(pnp_get_card_drvdata(pcard));
1360+
}
1361+
#endif
1362+
12741363
static struct pnp_card_driver sscape_pnpc_driver = {
12751364
.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
12761365
.name = "sscape",
12771366
.id_table = sscape_pnpids,
12781367
.probe = sscape_pnp_detect,
1368+
#ifdef CONFIG_PM
1369+
.suspend = sscape_pnp_suspend,
1370+
.resume = sscape_pnp_resume,
1371+
#endif
12791372
};
12801373

12811374
#endif /* CONFIG_PNP */

0 commit comments

Comments
 (0)