]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/alsa-ca0106-pm-support
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / alsa-ca0106-pm-support
CommitLineData
2cb7cef9
BS
1From 2c5dd6425e72a6e97d9fb9fee9910a58f02d77df Mon Sep 17 00:00:00 2001
2From: Takashi Iwai <tiwai@suse.de>
3Subject: ALSA: ca0106 - Add power-amangement support
4Patch-mainline:
5References: bnc#447624
6
7Added the missing PM support for snd-ca0106 driver.
8
9Signed-off-by: Takashi Iwai <tiwai@suse.de>
10
11---
12
13---
14 sound/pci/ca0106/ca0106.h | 15 +
15 sound/pci/ca0106/ca0106_main.c | 532 +++++++++++++++++++++++-----------------
16 sound/pci/ca0106/ca0106_mixer.c | 182 +++++++++----
17 3 files changed, 457 insertions(+), 272 deletions(-)
18
19--- a/sound/pci/ca0106/ca0106.h
20+++ b/sound/pci/ca0106/ca0106.h
21@@ -686,7 +686,7 @@ struct snd_ca0106 {
22 spinlock_t emu_lock;
23
24 struct snd_ac97 *ac97;
25- struct snd_pcm *pcm;
26+ struct snd_pcm *pcm[4];
27
28 struct snd_ca0106_channel playback_channels[4];
29 struct snd_ca0106_channel capture_channels[4];
30@@ -703,6 +703,11 @@ struct snd_ca0106 {
31 struct snd_ca_midi midi2;
32
33 u16 spi_dac_reg[16];
34+
35+#ifdef CONFIG_PM
36+#define NUM_SAVED_VOLUMES 9
37+ unsigned int saved_vol[NUM_SAVED_VOLUMES];
38+#endif
39 };
40
41 int snd_ca0106_mixer(struct snd_ca0106 *emu);
42@@ -721,3 +726,11 @@ int snd_ca0106_i2c_write(struct snd_ca01
43
44 int snd_ca0106_spi_write(struct snd_ca0106 * emu,
45 unsigned int data);
46+
47+#ifdef CONFIG_PM
48+void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip);
49+void snd_ca0106_mixer_resume(struct snd_ca0106 *chip);
50+#else
51+#define snd_ca0106_mixer_suspend(chip) do { } while (0)
52+#define snd_ca0106_mixer_resume(chip) do { } while (0)
53+#endif
54--- a/sound/pci/ca0106/ca0106_main.c
55+++ b/sound/pci/ca0106/ca0106_main.c
56@@ -848,15 +848,18 @@ static int snd_ca0106_pcm_trigger_playba
57 struct snd_pcm_substream *s;
58 u32 basic = 0;
59 u32 extended = 0;
60- int running=0;
61+ u32 bits;
62+ int running = 0;
63
64 switch (cmd) {
65 case SNDRV_PCM_TRIGGER_START:
66- running=1;
67+ case SNDRV_PCM_TRIGGER_RESUME:
68+ running = 1;
69 break;
70 case SNDRV_PCM_TRIGGER_STOP:
71+ case SNDRV_PCM_TRIGGER_SUSPEND:
72 default:
73- running=0;
74+ running = 0;
75 break;
76 }
77 snd_pcm_group_for_each_entry(s, substream) {
78@@ -866,22 +869,32 @@ static int snd_ca0106_pcm_trigger_playba
79 runtime = s->runtime;
80 epcm = runtime->private_data;
81 channel = epcm->channel_id;
82- //snd_printk("channel=%d\n",channel);
83+ /* snd_printk("channel=%d\n",channel); */
84 epcm->running = running;
85- basic |= (0x1<<channel);
86- extended |= (0x10<<channel);
87+ basic |= (0x1 << channel);
88+ extended |= (0x10 << channel);
89 snd_pcm_trigger_done(s, substream);
90 }
91- //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
92+ /* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */
93
94 switch (cmd) {
95 case SNDRV_PCM_TRIGGER_START:
96- snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
97- snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
98+ case SNDRV_PCM_TRIGGER_RESUME:
99+ bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0);
100+ bits |= extended;
101+ snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits);
102+ bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0);
103+ bits |= basic;
104+ snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits);
105 break;
106 case SNDRV_PCM_TRIGGER_STOP:
107- snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
108- snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
109+ case SNDRV_PCM_TRIGGER_SUSPEND:
110+ bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0);
111+ bits &= ~basic;
112+ snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits);
113+ bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0);
114+ bits &= ~extended;
115+ snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits);
116 break;
117 default:
118 result = -EINVAL;
119@@ -1104,21 +1117,13 @@ static int snd_ca0106_ac97(struct snd_ca
120 return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
121 }
122
123+static void ca0106_stop_chip(struct snd_ca0106 *chip);
124+
125 static int snd_ca0106_free(struct snd_ca0106 *chip)
126 {
127- if (chip->res_port != NULL) { /* avoid access to already used hardware */
128- // disable interrupts
129- snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
130- outl(0, chip->port + INTE);
131- snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
132- udelay(1000);
133- // disable audio
134- //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
135- outl(0, chip->port + HCFG);
136- /* FIXME: We need to stop and DMA transfers here.
137- * But as I am not sure how yet, we cannot from the dma pages.
138- * So we can fix: snd-malloc: Memory leak? pages not freed = 8
139- */
140+ if (chip->res_port != NULL) {
141+ /* avoid access to already used hardware */
142+ ca0106_stop_chip(chip);
143 }
144 if (chip->irq >= 0)
145 free_irq(chip->irq, chip);
146@@ -1204,15 +1209,14 @@ static irqreturn_t snd_ca0106_interrupt(
147 return IRQ_HANDLED;
148 }
149
150-static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
151+static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
152 {
153 struct snd_pcm *pcm;
154 struct snd_pcm_substream *substream;
155 int err;
156
157- if (rpcm)
158- *rpcm = NULL;
159- if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
160+ err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm);
161+ if (err < 0)
162 return err;
163
164 pcm->private_data = emu;
165@@ -1239,7 +1243,6 @@ static int __devinit snd_ca0106_pcm(stru
166 pcm->info_flags = 0;
167 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
168 strcpy(pcm->name, "CA0106");
169- emu->pcm = pcm;
170
171 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
172 substream;
173@@ -1261,8 +1264,7 @@ static int __devinit snd_ca0106_pcm(stru
174 return err;
175 }
176
177- if (rpcm)
178- *rpcm = pcm;
179+ emu->pcm[device] = pcm;
180
181 return 0;
182 }
183@@ -1302,89 +1304,10 @@ static unsigned int i2c_adc_init[][2] =
184 { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
185 };
186
187-static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
188- struct pci_dev *pci,
189- struct snd_ca0106 **rchip)
190+static void ca0106_init_chip(struct snd_ca0106 *chip, int resume)
191 {
192- struct snd_ca0106 *chip;
193- struct snd_ca0106_details *c;
194- int err;
195 int ch;
196- static struct snd_device_ops ops = {
197- .dev_free = snd_ca0106_dev_free,
198- };
199-
200- *rchip = NULL;
201-
202- if ((err = pci_enable_device(pci)) < 0)
203- return err;
204- if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
205- pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
206- printk(KERN_ERR "error to set 32bit mask DMA\n");
207- pci_disable_device(pci);
208- return -ENXIO;
209- }
210-
211- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
212- if (chip == NULL) {
213- pci_disable_device(pci);
214- return -ENOMEM;
215- }
216-
217- chip->card = card;
218- chip->pci = pci;
219- chip->irq = -1;
220-
221- spin_lock_init(&chip->emu_lock);
222-
223- chip->port = pci_resource_start(pci, 0);
224- if ((chip->res_port = request_region(chip->port, 0x20,
225- "snd_ca0106")) == NULL) {
226- snd_ca0106_free(chip);
227- printk(KERN_ERR "cannot allocate the port\n");
228- return -EBUSY;
229- }
230-
231- if (request_irq(pci->irq, snd_ca0106_interrupt,
232- IRQF_SHARED, "snd_ca0106", chip)) {
233- snd_ca0106_free(chip);
234- printk(KERN_ERR "cannot grab irq\n");
235- return -EBUSY;
236- }
237- chip->irq = pci->irq;
238-
239- /* This stores the periods table. */
240- if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
241- snd_ca0106_free(chip);
242- return -ENOMEM;
243- }
244-
245- pci_set_master(pci);
246- /* read serial */
247- pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
248- pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
249-#if 1
250- printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
251- pci->revision, chip->serial);
252-#endif
253- strcpy(card->driver, "CA0106");
254- strcpy(card->shortname, "CA0106");
255-
256- for (c = ca0106_chip_details; c->serial; c++) {
257- if (subsystem[dev]) {
258- if (c->serial == subsystem[dev])
259- break;
260- } else if (c->serial == chip->serial)
261- break;
262- }
263- chip->details = c;
264- if (subsystem[dev]) {
265- printk(KERN_INFO "snd-ca0106: Sound card name=%s, subsystem=0x%x. Forced to subsystem=0x%x\n",
266- c->name, chip->serial, subsystem[dev]);
267- }
268-
269- sprintf(card->longname, "%s at 0x%lx irq %i",
270- c->name, chip->port, chip->irq);
271+ unsigned int def_bits;
272
273 outl(0, chip->port + INTE);
274
275@@ -1402,31 +1325,22 @@ static int __devinit snd_ca0106_create(i
276 * AN = 0 (Audio data)
277 * P = 0 (Consumer)
278 */
279- snd_ca0106_ptr_write(chip, SPCS0, 0,
280- chip->spdif_bits[0] =
281- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
282- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
283- SPCS_GENERATIONSTATUS | 0x00001200 |
284- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
285+ def_bits =
286+ SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
287+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
288+ SPCS_GENERATIONSTATUS | 0x00001200 |
289+ 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
290+ if (!resume) {
291+ chip->spdif_bits[0] = def_bits;
292+ chip->spdif_bits[1] = def_bits;
293+ chip->spdif_bits[2] = def_bits;
294+ chip->spdif_bits[3] = def_bits;
295+ }
296 /* Only SPCS1 has been tested */
297- snd_ca0106_ptr_write(chip, SPCS1, 0,
298- chip->spdif_bits[1] =
299- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
300- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
301- SPCS_GENERATIONSTATUS | 0x00001200 |
302- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
303- snd_ca0106_ptr_write(chip, SPCS2, 0,
304- chip->spdif_bits[2] =
305- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
306- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
307- SPCS_GENERATIONSTATUS | 0x00001200 |
308- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
309- snd_ca0106_ptr_write(chip, SPCS3, 0,
310- chip->spdif_bits[3] =
311- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
312- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
313- SPCS_GENERATIONSTATUS | 0x00001200 |
314- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
315+ snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_bits[1]);
316+ snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_bits[0]);
317+ snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_bits[2]);
318+ snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_bits[3]);
319
320 snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
321 snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
322@@ -1434,92 +1348,124 @@ static int __devinit snd_ca0106_create(i
323 /* Write 0x8000 to AC97_REC_GAIN to mute it. */
324 outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
325 outw(0x8000, chip->port + AC97DATA);
326-#if 0
327+#if 0 /* FIXME: what are these? */
328 snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
329 snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
330 snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
331 snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
332 #endif
333
334- //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
335+ /* OSS drivers set this. */
336+ /* snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); */
337+
338 /* Analog or Digital output */
339 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
340- snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
341+ /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers.
342+ * Use 0x000f0000 for surround71
343+ */
344+ snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000);
345+
346 chip->spdif_enable = 0; /* Set digital SPDIF output off */
347- //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
348- //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
349+ /*snd_ca0106_ptr_write(chip, 0x45, 0, 0);*/ /* Analogue out */
350+ /*snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00);*/ /* Digital out */
351+
352+ /* goes to 0x40c80000 when doing SPDIF IN/OUT */
353+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000);
354+ /* (Mute) CAPTURE feedback into PLAYBACK volume.
355+ * Only lower 16 bits matter.
356+ */
357+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff);
358+ /* SPDIF IN Volume */
359+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000);
360+ /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
361+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000);
362
363- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
364- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
365- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
366- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
367 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
368 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
369 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
370 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
371- for(ch = 0; ch < 4; ch++) {
372- snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
373+
374+ for (ch = 0; ch < 4; ch++) {
375+ /* Only high 16 bits matter */
376+ snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030);
377 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
378- //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
379- //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
380- snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
381- snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
382+#if 0 /* Mute */
383+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040);
384+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040);
385+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff);
386+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff);
387+#endif
388 }
389 if (chip->details->i2c_adc == 1) {
390 /* Select MIC, Line in, TAD in, AUX in */
391 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
392 /* Default to CAPTURE_SOURCE to i2s in */
393- chip->capture_source = 3;
394+ if (!resume)
395+ chip->capture_source = 3;
396 } else if (chip->details->ac97 == 1) {
397 /* Default to AC97 in */
398 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4);
399 /* Default to CAPTURE_SOURCE to AC97 in */
400- chip->capture_source = 4;
401+ if (!resume)
402+ chip->capture_source = 4;
403 } else {
404 /* Select MIC, Line in, TAD in, AUX in */
405 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
406 /* Default to Set CAPTURE_SOURCE to i2s in */
407- chip->capture_source = 3;
408+ if (!resume)
409+ chip->capture_source = 3;
410 }
411
412- if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
413- /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
414+ if (chip->details->gpio_type == 2) {
415+ /* The SB0438 use GPIO differently. */
416+ /* FIXME: Still need to find out what the other GPIO bits do.
417+ * E.g. For digital spdif out.
418+ */
419 outl(0x0, chip->port+GPIO);
420- //outl(0x00f0e000, chip->port+GPIO); /* Analog */
421+ /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */
422 outl(0x005f5301, chip->port+GPIO); /* Analog */
423- } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
424- /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
425+ } else if (chip->details->gpio_type == 1) {
426+ /* The SB0410 and SB0413 use GPIO differently. */
427+ /* FIXME: Still need to find out what the other GPIO bits do.
428+ * E.g. For digital spdif out.
429+ */
430 outl(0x0, chip->port+GPIO);
431- //outl(0x00f0e000, chip->port+GPIO); /* Analog */
432+ /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */
433 outl(0x005f5301, chip->port+GPIO); /* Analog */
434 } else {
435 outl(0x0, chip->port+GPIO);
436 outl(0x005f03a3, chip->port+GPIO); /* Analog */
437- //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
438+ /* outl(0x005f02a2, chip->port+GPIO); */ /* SPDIF */
439 }
440 snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
441
442- //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
443- //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
444- //outl(0x00000009, chip->port+HCFG);
445- outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
446+ /* outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); */
447+ /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
448+ /* outl(0x00001409, chip->port+HCFG); */
449+ /* outl(0x00000009, chip->port+HCFG); */
450+ /* AC97 2.0, Enable outputs. */
451+ outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG);
452
453- if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
454+ if (chip->details->i2c_adc == 1) {
455+ /* The SB0410 and SB0413 use I2C to control ADC. */
456 int size, n;
457
458 size = ARRAY_SIZE(i2c_adc_init);
459- //snd_printk("I2C:array size=0x%x\n", size);
460- for (n=0; n < size; n++) {
461- snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
462- }
463- for (n=0; n < 4; n++) {
464- chip->i2c_capture_volume[n][0]= 0xcf;
465- chip->i2c_capture_volume[n][1]= 0xcf;
466+ /* snd_printk("I2C:array size=0x%x\n", size); */
467+ for (n = 0; n < size; n++)
468+ snd_ca0106_i2c_write(chip, i2c_adc_init[n][0],
469+ i2c_adc_init[n][1]);
470+ for (n = 0; n < 4; n++) {
471+ chip->i2c_capture_volume[n][0] = 0xcf;
472+ chip->i2c_capture_volume[n][1] = 0xcf;
473 }
474- chip->i2c_capture_source=2; /* Line in */
475- //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
476+ chip->i2c_capture_source = 2; /* Line in */
477+ /* Enable Line-in capture. MIC in currently untested. */
478+ /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */
479 }
480- if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
481+
482+ if (chip->details->spi_dac == 1) {
483+ /* The SB0570 use SPI to control DAC. */
484 int size, n;
485
486 size = ARRAY_SIZE(spi_dac_init);
487@@ -1531,9 +1477,112 @@ static int __devinit snd_ca0106_create(i
488 chip->spi_dac_reg[reg] = spi_dac_init[n];
489 }
490 }
491+}
492+
493+static void ca0106_stop_chip(struct snd_ca0106 *chip)
494+{
495+ /* disable interrupts */
496+ snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
497+ outl(0, chip->port + INTE);
498+ snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
499+ udelay(1000);
500+ /* disable audio */
501+ /* outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); */
502+ outl(0, chip->port + HCFG);
503+ /* FIXME: We need to stop and DMA transfers here.
504+ * But as I am not sure how yet, we cannot from the dma pages.
505+ * So we can fix: snd-malloc: Memory leak? pages not freed = 8
506+ */
507+}
508
509- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
510- chip, &ops)) < 0) {
511+static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
512+ struct pci_dev *pci,
513+ struct snd_ca0106 **rchip)
514+{
515+ struct snd_ca0106 *chip;
516+ struct snd_ca0106_details *c;
517+ int err;
518+ static struct snd_device_ops ops = {
519+ .dev_free = snd_ca0106_dev_free,
520+ };
521+
522+ *rchip = NULL;
523+
524+ err = pci_enable_device(pci);
525+ if (err < 0)
526+ return err;
527+ if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
528+ pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
529+ printk(KERN_ERR "error to set 32bit mask DMA\n");
530+ pci_disable_device(pci);
531+ return -ENXIO;
532+ }
533+
534+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
535+ if (chip == NULL) {
536+ pci_disable_device(pci);
537+ return -ENOMEM;
538+ }
539+
540+ chip->card = card;
541+ chip->pci = pci;
542+ chip->irq = -1;
543+
544+ spin_lock_init(&chip->emu_lock);
545+
546+ chip->port = pci_resource_start(pci, 0);
547+ chip->res_port = request_region(chip->port, 0x20, "snd_ca0106");
548+ if (!chip->res_port) {
549+ snd_ca0106_free(chip);
550+ printk(KERN_ERR "cannot allocate the port\n");
551+ return -EBUSY;
552+ }
553+
554+ if (request_irq(pci->irq, snd_ca0106_interrupt,
555+ IRQF_SHARED, "snd_ca0106", chip)) {
556+ snd_ca0106_free(chip);
557+ printk(KERN_ERR "cannot grab irq\n");
558+ return -EBUSY;
559+ }
560+ chip->irq = pci->irq;
561+
562+ /* This stores the periods table. */
563+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
564+ 1024, &chip->buffer) < 0) {
565+ snd_ca0106_free(chip);
566+ return -ENOMEM;
567+ }
568+
569+ pci_set_master(pci);
570+ /* read serial */
571+ pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
572+ pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
573+ printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n",
574+ chip->model, pci->revision, chip->serial);
575+ strcpy(card->driver, "CA0106");
576+ strcpy(card->shortname, "CA0106");
577+
578+ for (c = ca0106_chip_details; c->serial; c++) {
579+ if (subsystem[dev]) {
580+ if (c->serial == subsystem[dev])
581+ break;
582+ } else if (c->serial == chip->serial)
583+ break;
584+ }
585+ chip->details = c;
586+ if (subsystem[dev]) {
587+ printk(KERN_INFO "snd-ca0106: Sound card name=%s, "
588+ "subsystem=0x%x. Forced to subsystem=0x%x\n",
589+ c->name, chip->serial, subsystem[dev]);
590+ }
591+
592+ sprintf(card->longname, "%s at 0x%lx irq %i",
593+ c->name, chip->port, chip->irq);
594+
595+ ca0106_init_chip(chip, 0);
596+
597+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
598+ if (err < 0) {
599 snd_ca0106_free(chip);
600 return err;
601 }
602@@ -1630,7 +1679,7 @@ static int __devinit snd_ca0106_probe(st
603 static int dev;
604 struct snd_card *card;
605 struct snd_ca0106 *chip;
606- int err;
607+ int i, err;
608
609 if (dev >= SNDRV_CARDS)
610 return -ENODEV;
611@@ -1643,44 +1692,31 @@ static int __devinit snd_ca0106_probe(st
612 if (card == NULL)
613 return -ENOMEM;
614
615- if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) {
616- snd_card_free(card);
617- return err;
618- }
619-
620- if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
621- snd_card_free(card);
622- return err;
623- }
624- if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
625- snd_card_free(card);
626- return err;
627- }
628- if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
629- snd_card_free(card);
630- return err;
631- }
632- if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
633- snd_card_free(card);
634- return err;
635- }
636- if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
637- if ((err = snd_ca0106_ac97(chip)) < 0) {
638- snd_card_free(card);
639- return err;
640- }
641- }
642- if ((err = snd_ca0106_mixer(chip)) < 0) {
643- snd_card_free(card);
644- return err;
645- }
646+ err = snd_ca0106_create(dev, card, pci, &chip);
647+ if (err < 0)
648+ goto error;
649+ card->private_data = chip;
650+
651+ for (i = 0; i < 4; i++) {
652+ err = snd_ca0106_pcm(chip, i);
653+ if (err < 0)
654+ goto error;
655+ }
656+
657+ if (chip->details->ac97 == 1) {
658+ /* The SB0410 and SB0413 do not have an AC97 chip. */
659+ err = snd_ca0106_ac97(chip);
660+ if (err < 0)
661+ goto error;
662+ }
663+ err = snd_ca0106_mixer(chip);
664+ if (err < 0)
665+ goto error;
666
667 snd_printdd("ca0106: probe for MIDI channel A ...");
668- if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
669- snd_card_free(card);
670- snd_printdd(" failed, err=0x%x\n",err);
671- return err;
672- }
673+ err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A);
674+ if (err < 0)
675+ goto error;
676 snd_printdd(" done.\n");
677
678 #ifdef CONFIG_PROC_FS
679@@ -1689,14 +1725,17 @@ static int __devinit snd_ca0106_probe(st
680
681 snd_card_set_dev(card, &pci->dev);
682
683- if ((err = snd_card_register(card)) < 0) {
684- snd_card_free(card);
685- return err;
686- }
687+ err = snd_card_register(card);
688+ if (err < 0)
689+ goto error;
690
691 pci_set_drvdata(pci, card);
692 dev++;
693 return 0;
694+
695+ error:
696+ snd_card_free(card);
697+ return err;
698 }
699
700 static void __devexit snd_ca0106_remove(struct pci_dev *pci)
701@@ -1705,6 +1744,59 @@ static void __devexit snd_ca0106_remove(
702 pci_set_drvdata(pci, NULL);
703 }
704
705+#ifdef CONFIG_PM
706+static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state)
707+{
708+ struct snd_card *card = pci_get_drvdata(pci);
709+ struct snd_ca0106 *chip = card->private_data;
710+ int i;
711+
712+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
713+ for (i = 0; i < 4; i++)
714+ snd_pcm_suspend_all(chip->pcm[i]);
715+ if (chip->details->ac97)
716+ snd_ac97_suspend(chip->ac97);
717+ snd_ca0106_mixer_suspend(chip);
718+
719+ ca0106_stop_chip(chip);
720+
721+ pci_disable_device(pci);
722+ pci_save_state(pci);
723+ pci_set_power_state(pci, pci_choose_state(pci, state));
724+ return 0;
725+}
726+
727+static int snd_ca0106_resume(struct pci_dev *pci)
728+{
729+ struct snd_card *card = pci_get_drvdata(pci);
730+ struct snd_ca0106 *chip = card->private_data;
731+ int i;
732+
733+ pci_set_power_state(pci, PCI_D0);
734+ pci_restore_state(pci);
735+
736+ if (pci_enable_device(pci) < 0) {
737+ snd_card_disconnect(card);
738+ return -EIO;
739+ }
740+
741+ pci_set_master(pci);
742+
743+ ca0106_init_chip(chip, 1);
744+
745+ if (chip->details->ac97)
746+ snd_ac97_resume(chip->ac97);
747+ snd_ca0106_mixer_resume(chip);
748+ if (chip->details->spi_dac) {
749+ for (i = 0; i < ARRAY_SIZE(chip->spi_dac_reg); i++)
750+ snd_ca0106_spi_write(chip, chip->spi_dac_reg[i]);
751+ }
752+
753+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
754+ return 0;
755+}
756+#endif
757+
758 // PCI IDs
759 static struct pci_device_id snd_ca0106_ids[] = {
760 { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
761@@ -1718,6 +1810,8 @@ static struct pci_driver driver = {
762 .id_table = snd_ca0106_ids,
763 .probe = snd_ca0106_probe,
764 .remove = __devexit_p(snd_ca0106_remove),
765+ .suspend = snd_ca0106_suspend,
766+ .resume = snd_ca0106_resume,
767 };
768
769 // initialization of the module
770--- a/sound/pci/ca0106/ca0106_mixer.c
771+++ b/sound/pci/ca0106/ca0106_mixer.c
772@@ -75,6 +75,84 @@
773
774 #include "ca0106.h"
775
776+static void ca0106_spdif_enable(struct snd_ca0106 *emu)
777+{
778+ unsigned int val;
779+
780+ if (emu->spdif_enable) {
781+ /* Digital */
782+ snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
783+ snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
784+ val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000;
785+ snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
786+ val = inl(emu->port + GPIO) & ~0x101;
787+ outl(val, emu->port + GPIO);
788+
789+ } else {
790+ /* Analog */
791+ snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
792+ snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
793+ val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000;
794+ snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
795+ val = inl(emu->port + GPIO) | 0x101;
796+ outl(val, emu->port + GPIO);
797+ }
798+}
799+
800+static void ca0106_set_capture_source(struct snd_ca0106 *emu)
801+{
802+ unsigned int val = emu->capture_source;
803+ unsigned int source, mask;
804+ source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
805+ mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
806+ snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
807+}
808+
809+static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu,
810+ unsigned int val, int force)
811+{
812+ unsigned int ngain, ogain;
813+ u32 source;
814+
815+ snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
816+ ngain = emu->i2c_capture_volume[val][0]; /* Left */
817+ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
818+ if (force || ngain != ogain)
819+ snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff);
820+ ngain = emu->i2c_capture_volume[val][1]; /* Right */
821+ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
822+ if (force || ngain != ogain)
823+ snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff);
824+ source = 1 << val;
825+ snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
826+ emu->i2c_capture_source = val;
827+}
828+
829+static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu)
830+{
831+ u32 tmp;
832+
833+ if (emu->capture_mic_line_in) {
834+ /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
835+ tmp = inl(emu->port+GPIO) & ~0x400;
836+ tmp = tmp | 0x400;
837+ outl(tmp, emu->port+GPIO);
838+ /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
839+ } else {
840+ /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
841+ tmp = inl(emu->port+GPIO) & ~0x400;
842+ outl(tmp, emu->port+GPIO);
843+ /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */
844+ }
845+}
846+
847+static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
848+{
849+ snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_bits[idx]);
850+}
851+
852+/*
853+ */
854 static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
855 static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
856
857@@ -95,30 +173,12 @@ static int snd_ca0106_shared_spdif_put(s
858 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
859 unsigned int val;
860 int change = 0;
861- u32 mask;
862
863 val = !!ucontrol->value.integer.value[0];
864 change = (emu->spdif_enable != val);
865 if (change) {
866 emu->spdif_enable = val;
867- if (val) {
868- /* Digital */
869- snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
870- snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
871- snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
872- snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000);
873- mask = inl(emu->port + GPIO) & ~0x101;
874- outl(mask, emu->port + GPIO);
875-
876- } else {
877- /* Analog */
878- snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
879- snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
880- snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
881- snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
882- mask = inl(emu->port + GPIO) | 0x101;
883- outl(mask, emu->port + GPIO);
884- }
885+ ca0106_spdif_enable(emu);
886 }
887 return change;
888 }
889@@ -154,8 +214,6 @@ static int snd_ca0106_capture_source_put
890 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
891 unsigned int val;
892 int change = 0;
893- u32 mask;
894- u32 source;
895
896 val = ucontrol->value.enumerated.item[0] ;
897 if (val >= 6)
898@@ -163,9 +221,7 @@ static int snd_ca0106_capture_source_put
899 change = (emu->capture_source != val);
900 if (change) {
901 emu->capture_source = val;
902- source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
903- mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
904- snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
905+ ca0106_set_capture_source(emu);
906 }
907 return change;
908 }
909@@ -200,9 +256,7 @@ static int snd_ca0106_i2c_capture_source
910 {
911 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
912 unsigned int source_id;
913- unsigned int ngain, ogain;
914 int change = 0;
915- u32 source;
916 /* If the capture source has changed,
917 * update the capture volume from the cached value
918 * for the particular source.
919@@ -212,18 +266,7 @@ static int snd_ca0106_i2c_capture_source
920 return -EINVAL;
921 change = (emu->i2c_capture_source != source_id);
922 if (change) {
923- snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
924- ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
925- ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
926- if (ngain != ogain)
927- snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
928- ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
929- ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
930- if (ngain != ogain)
931- snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
932- source = 1 << source_id;
933- snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
934- emu->i2c_capture_source = source_id;
935+ ca0106_set_i2c_capture_source(emu, source_id, 0);
936 }
937 return change;
938 }
939@@ -271,7 +314,6 @@ static int snd_ca0106_capture_mic_line_i
940 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
941 unsigned int val;
942 int change = 0;
943- u32 tmp;
944
945 val = ucontrol->value.enumerated.item[0] ;
946 if (val > 1)
947@@ -279,18 +321,7 @@ static int snd_ca0106_capture_mic_line_i
948 change = (emu->capture_mic_line_in != val);
949 if (change) {
950 emu->capture_mic_line_in = val;
951- if (val) {
952- //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
953- tmp = inl(emu->port+GPIO) & ~0x400;
954- tmp = tmp | 0x400;
955- outl(tmp, emu->port+GPIO);
956- //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
957- } else {
958- //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
959- tmp = inl(emu->port+GPIO) & ~0x400;
960- outl(tmp, emu->port+GPIO);
961- //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
962- }
963+ ca0106_set_capture_mic_line_in(emu);
964 }
965 return change;
966 }
967@@ -359,8 +390,8 @@ static int snd_ca0106_spdif_put(struct s
968 (ucontrol->value.iec958.status[3] << 24);
969 change = val != emu->spdif_bits[idx];
970 if (change) {
971- snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, val);
972 emu->spdif_bits[idx] = val;
973+ ca0106_set_spdif_bits(emu, idx);
974 }
975 return change;
976 }
977@@ -779,3 +810,50 @@ int __devinit snd_ca0106_mixer(struct sn
978 return 0;
979 }
980
981+#ifdef CONFIG_PM
982+struct ca0106_vol_tbl {
983+ unsigned int channel_id;
984+ unsigned int reg;
985+};
986+
987+static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
988+ { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
989+ { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
990+ { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
991+ { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
992+ { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
993+ { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
994+ { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
995+ { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
996+ { 1, CAPTURE_CONTROL },
997+};
998+
999+void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
1000+{
1001+ int i;
1002+
1003+ /* save volumes */
1004+ for (i = 0; i < NUM_SAVED_VOLUMES; i++)
1005+ chip->saved_vol[i] =
1006+ snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
1007+ saved_volumes[i].channel_id);
1008+}
1009+
1010+void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
1011+{
1012+ int i;
1013+
1014+ for (i = 0; i < NUM_SAVED_VOLUMES; i++)
1015+ snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
1016+ saved_volumes[i].channel_id,
1017+ chip->saved_vol[i]);
1018+
1019+ ca0106_spdif_enable(chip);
1020+ ca0106_set_capture_source(chip);
1021+ ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
1022+ for (i = 0; i < 4; i++)
1023+ ca0106_set_spdif_bits(chip, i);
1024+ if (chip->details->i2c_adc)
1025+ ca0106_set_capture_mic_line_in(chip);
1026+}
1027+#endif /* CONFIG_PM */