Skip to content

Commit 47b5d02

Browse files
Giuliano Pochinitiwai
Giuliano Pochini
authored andcommitted
ALSA: Echoaudio - Add suspend support #2
This patch adds rearranges parts of the initialization code and adds suspend and resume callbacks. This patch adds suspend and resume callbacks. It also rearranges parts of the initialization code so it can be used in both the first initialization (when the module is loaded we also have to load default settings) and the resume callback (where we have to restore the previous settings). Signed-off-by: Giuliano Pochini <pochini@shiny.it> Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent ad3499f commit 47b5d02

File tree

3 files changed

+222
-78
lines changed

3 files changed

+222
-78
lines changed

sound/pci/echoaudio/echoaudio.c

+138-15
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,8 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
753753

754754
spin_lock(&chip->lock);
755755
switch (cmd) {
756+
case SNDRV_PCM_TRIGGER_RESUME:
757+
DE_ACT(("pcm_trigger resume\n"));
756758
case SNDRV_PCM_TRIGGER_START:
757759
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
758760
DE_ACT(("pcm_trigger start\n"));
@@ -776,6 +778,8 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
776778
err = start_transport(chip, channelmask,
777779
chip->pipe_cyclic_mask);
778780
break;
781+
case SNDRV_PCM_TRIGGER_SUSPEND:
782+
DE_ACT(("pcm_trigger suspend\n"));
779783
case SNDRV_PCM_TRIGGER_STOP:
780784
DE_ACT(("pcm_trigger stop\n"));
781785
for (i = 0; i < DSP_MAXPIPES; i++) {
@@ -1951,18 +1955,27 @@ static __devinit int snd_echo_create(struct snd_card *card,
19511955
return err;
19521956
pci_set_master(pci);
19531957

1954-
/* allocate a chip-specific data */
1955-
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1956-
if (!chip) {
1957-
pci_disable_device(pci);
1958-
return -ENOMEM;
1958+
/* Allocate chip if needed */
1959+
if (!*rchip) {
1960+
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1961+
if (!chip) {
1962+
pci_disable_device(pci);
1963+
return -ENOMEM;
1964+
}
1965+
DE_INIT(("chip=%p\n", chip));
1966+
spin_lock_init(&chip->lock);
1967+
chip->card = card;
1968+
chip->pci = pci;
1969+
chip->irq = -1;
1970+
atomic_set(&chip->opencount, 0);
1971+
mutex_init(&chip->mode_mutex);
1972+
chip->can_set_rate = 1;
1973+
} else {
1974+
/* If this was called from the resume function, chip is
1975+
* already allocated and it contains current card settings.
1976+
*/
1977+
chip = *rchip;
19591978
}
1960-
DE_INIT(("chip=%p\n", chip));
1961-
1962-
spin_lock_init(&chip->lock);
1963-
chip->card = card;
1964-
chip->pci = pci;
1965-
chip->irq = -1;
19661979

19671980
/* PCI resource allocation */
19681981
chip->dsp_registers_phys = pci_resource_start(pci, 0);
@@ -2002,7 +2015,9 @@ static __devinit int snd_echo_create(struct snd_card *card,
20022015
chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area;
20032016

20042017
err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
2005-
if (err) {
2018+
if (err >= 0)
2019+
err = set_mixer_defaults(chip);
2020+
if (err < 0) {
20062021
DE_INIT(("init_hw err=%d\n", err));
20072022
snd_echo_free(chip);
20082023
return err;
@@ -2013,9 +2028,6 @@ static __devinit int snd_echo_create(struct snd_card *card,
20132028
snd_echo_free(chip);
20142029
return err;
20152030
}
2016-
atomic_set(&chip->opencount, 0);
2017-
mutex_init(&chip->mode_mutex);
2018-
chip->can_set_rate = 1;
20192031
*rchip = chip;
20202032
/* Init done ! */
20212033
return 0;
@@ -2048,6 +2060,7 @@ static int __devinit snd_echo_probe(struct pci_dev *pci,
20482060

20492061
snd_card_set_dev(card, &pci->dev);
20502062

2063+
chip = NULL; /* Tells snd_echo_create to allocate chip */
20512064
if ((err = snd_echo_create(card, pci, &chip)) < 0) {
20522065
snd_card_free(card);
20532066
return err;
@@ -2187,6 +2200,112 @@ static int __devinit snd_echo_probe(struct pci_dev *pci,
21872200

21882201

21892202

2203+
#if defined(CONFIG_PM)
2204+
2205+
static int snd_echo_suspend(struct pci_dev *pci, pm_message_t state)
2206+
{
2207+
struct echoaudio *chip = pci_get_drvdata(pci);
2208+
2209+
DE_INIT(("suspend start\n"));
2210+
snd_pcm_suspend_all(chip->analog_pcm);
2211+
snd_pcm_suspend_all(chip->digital_pcm);
2212+
2213+
#ifdef ECHOCARD_HAS_MIDI
2214+
/* This call can sleep */
2215+
if (chip->midi_out)
2216+
snd_echo_midi_output_trigger(chip->midi_out, 0);
2217+
#endif
2218+
spin_lock_irq(&chip->lock);
2219+
if (wait_handshake(chip)) {
2220+
spin_unlock_irq(&chip->lock);
2221+
return -EIO;
2222+
}
2223+
clear_handshake(chip);
2224+
if (send_vector(chip, DSP_VC_GO_COMATOSE) < 0) {
2225+
spin_unlock_irq(&chip->lock);
2226+
return -EIO;
2227+
}
2228+
spin_unlock_irq(&chip->lock);
2229+
2230+
chip->dsp_code = NULL;
2231+
free_irq(chip->irq, chip);
2232+
chip->irq = -1;
2233+
pci_save_state(pci);
2234+
pci_disable_device(pci);
2235+
2236+
DE_INIT(("suspend done\n"));
2237+
return 0;
2238+
}
2239+
2240+
2241+
2242+
static int snd_echo_resume(struct pci_dev *pci)
2243+
{
2244+
struct echoaudio *chip = pci_get_drvdata(pci);
2245+
struct comm_page *commpage, *commpage_bak;
2246+
u32 pipe_alloc_mask;
2247+
int err;
2248+
2249+
DE_INIT(("resume start\n"));
2250+
pci_restore_state(pci);
2251+
commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
2252+
commpage = chip->comm_page;
2253+
memcpy(commpage_bak, commpage, sizeof(struct comm_page));
2254+
2255+
err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
2256+
if (err < 0) {
2257+
kfree(commpage_bak);
2258+
DE_INIT(("resume init_hw err=%d\n", err));
2259+
snd_echo_free(chip);
2260+
return err;
2261+
}
2262+
DE_INIT(("resume init OK\n"));
2263+
2264+
/* Temporarily set chip->pipe_alloc_mask=0 otherwise
2265+
* restore_dsp_settings() fails.
2266+
*/
2267+
pipe_alloc_mask = chip->pipe_alloc_mask;
2268+
chip->pipe_alloc_mask = 0;
2269+
err = restore_dsp_rettings(chip);
2270+
chip->pipe_alloc_mask = pipe_alloc_mask;
2271+
if (err < 0) {
2272+
kfree(commpage_bak);
2273+
return err;
2274+
}
2275+
DE_INIT(("resume restore OK\n"));
2276+
2277+
memcpy(&commpage->audio_format, &commpage_bak->audio_format,
2278+
sizeof(commpage->audio_format));
2279+
memcpy(&commpage->sglist_addr, &commpage_bak->sglist_addr,
2280+
sizeof(commpage->sglist_addr));
2281+
memcpy(&commpage->midi_output, &commpage_bak->midi_output,
2282+
sizeof(commpage->midi_output));
2283+
kfree(commpage_bak);
2284+
2285+
if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
2286+
ECHOCARD_NAME, chip)) {
2287+
snd_echo_free(chip);
2288+
snd_printk(KERN_ERR "cannot grab irq\n");
2289+
return -EBUSY;
2290+
}
2291+
chip->irq = pci->irq;
2292+
DE_INIT(("resume irq=%d\n", chip->irq));
2293+
2294+
#ifdef ECHOCARD_HAS_MIDI
2295+
if (chip->midi_input_enabled)
2296+
enable_midi_input(chip, TRUE);
2297+
if (chip->midi_out)
2298+
snd_echo_midi_output_trigger(chip->midi_out, 1);
2299+
#endif
2300+
2301+
DE_INIT(("resume done\n"));
2302+
return 0;
2303+
}
2304+
2305+
#endif /* CONFIG_PM */
2306+
2307+
2308+
21902309
static void __devexit snd_echo_remove(struct pci_dev *pci)
21912310
{
21922311
struct echoaudio *chip;
@@ -2209,6 +2328,10 @@ static struct pci_driver driver = {
22092328
.id_table = snd_echo_ids,
22102329
.probe = snd_echo_probe,
22112330
.remove = __devexit_p(snd_echo_remove),
2331+
#ifdef CONFIG_PM
2332+
.suspend = snd_echo_suspend,
2333+
.resume = snd_echo_resume,
2334+
#endif /* CONFIG_PM */
22122335
};
22132336

22142337

sound/pci/echoaudio/echoaudio.h

+2
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,8 @@ static void free_firmware(const struct firmware *fw_entry);
472472

473473
#ifdef ECHOCARD_HAS_MIDI
474474
static int enable_midi_input(struct echoaudio *chip, char enable);
475+
static void snd_echo_midi_output_trigger(
476+
struct snd_rawmidi_substream *substream, int up);
475477
static int midi_service_irq(struct echoaudio *chip);
476478
static int __devinit snd_echo_midi_create(struct snd_card *card,
477479
struct echoaudio *chip);

0 commit comments

Comments
 (0)