]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.drivers/alsa-ca0106-pm-support
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / alsa-ca0106-pm-support
1 From 2c5dd6425e72a6e97d9fb9fee9910a58f02d77df Mon Sep 17 00:00:00 2001
2 From: Takashi Iwai <tiwai@suse.de>
3 Subject: ALSA: ca0106 - Add power-amangement support
4 Patch-mainline:
5 References: bnc#447624
6
7 Added the missing PM support for snd-ca0106 driver.
8
9 Signed-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 */