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