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
7 Added the missing PM support for snd-ca0106 driver.
9 Signed-off-by: Takashi Iwai <tiwai@suse.de>
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(-)
19 --- a/sound/pci/ca0106/ca0106.h
20 +++ b/sound/pci/ca0106/ca0106.h
21 @@ -686,7 +686,7 @@ struct snd_ca0106 {
24 struct snd_ac97 *ac97;
25 - struct snd_pcm *pcm;
26 + struct snd_pcm *pcm[4];
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;
36 +#define NUM_SAVED_VOLUMES 9
37 + unsigned int saved_vol[NUM_SAVED_VOLUMES];
41 int snd_ca0106_mixer(struct snd_ca0106 *emu);
42 @@ -721,3 +726,11 @@ int snd_ca0106_i2c_write(struct snd_ca01
44 int snd_ca0106_spi_write(struct snd_ca0106 * emu,
48 +void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip);
49 +void snd_ca0106_mixer_resume(struct snd_ca0106 *chip);
51 +#define snd_ca0106_mixer_suspend(chip) do { } while (0)
52 +#define snd_ca0106_mixer_resume(chip) do { } while (0)
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;
65 case SNDRV_PCM_TRIGGER_START:
67 + case SNDRV_PCM_TRIGGER_RESUME:
70 case SNDRV_PCM_TRIGGER_STOP:
71 + case SNDRV_PCM_TRIGGER_SUSPEND:
77 snd_pcm_group_for_each_entry(s, substream) {
78 @@ -866,22 +869,32 @@ static int snd_ca0106_pcm_trigger_playba
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);
91 - //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
92 + /* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */
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);
101 + snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits);
102 + bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0);
104 + snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits);
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);
112 + snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits);
113 + bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0);
115 + snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits);
119 @@ -1104,21 +1117,13 @@ static int snd_ca0106_ac97(struct snd_ca
120 return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
123 +static void ca0106_stop_chip(struct snd_ca0106 *chip);
125 static int snd_ca0106_free(struct snd_ca0106 *chip)
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);
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
140 + if (chip->res_port != NULL) {
141 + /* avoid access to already used hardware */
142 + ca0106_stop_chip(chip);
145 free_irq(chip->irq, chip);
146 @@ -1204,15 +1209,14 @@ static irqreturn_t snd_ca0106_interrupt(
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)
154 struct snd_pcm_substream *substream;
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);
164 pcm->private_data = emu;
165 @@ -1239,7 +1243,6 @@ static int __devinit snd_ca0106_pcm(stru
167 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
168 strcpy(pcm->name, "CA0106");
171 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
173 @@ -1261,8 +1264,7 @@ static int __devinit snd_ca0106_pcm(stru
179 + emu->pcm[device] = pcm;
183 @@ -1302,89 +1304,10 @@ static unsigned int i2c_adc_init[][2] =
184 { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
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)
192 - struct snd_ca0106 *chip;
193 - struct snd_ca0106_details *c;
196 - static struct snd_device_ops ops = {
197 - .dev_free = snd_ca0106_dev_free,
202 - if ((err = pci_enable_device(pci)) < 0)
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);
211 - chip = kzalloc(sizeof(*chip), GFP_KERNEL);
212 - if (chip == NULL) {
213 - pci_disable_device(pci);
221 - spin_lock_init(&chip->emu_lock);
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");
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");
237 - chip->irq = pci->irq;
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);
245 - pci_set_master(pci);
247 - pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
248 - pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
250 - printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
251 - pci->revision, chip->serial);
253 - strcpy(card->driver, "CA0106");
254 - strcpy(card->shortname, "CA0106");
256 - for (c = ca0106_chip_details; c->serial; c++) {
257 - if (subsystem[dev]) {
258 - if (c->serial == subsystem[dev])
260 - } else if (c->serial == chip->serial)
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]);
269 - sprintf(card->longname, "%s at 0x%lx irq %i",
270 - c->name, chip->port, chip->irq);
271 + unsigned int def_bits;
273 outl(0, chip->port + INTE);
275 @@ -1402,31 +1325,22 @@ static int __devinit snd_ca0106_create(i
276 * AN = 0 (Audio data)
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);
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;
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;
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]);
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);
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);
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); */
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
344 + snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000);
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 */
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.
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);
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 */
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 */
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);
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;
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;
402 + chip->capture_source = 4;
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;
409 + chip->capture_source = 3;
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.
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.
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 */
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 */
440 snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
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);
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. */
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]);
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;
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); */
480 - if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
482 + if (chip->details->spi_dac == 1) {
483 + /* The SB0570 use SPI to control DAC. */
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];
493 +static void ca0106_stop_chip(struct snd_ca0106 *chip)
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);
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
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)
515 + struct snd_ca0106 *chip;
516 + struct snd_ca0106_details *c;
518 + static struct snd_device_ops ops = {
519 + .dev_free = snd_ca0106_dev_free,
524 + err = pci_enable_device(pci);
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);
534 + chip = kzalloc(sizeof(*chip), GFP_KERNEL);
535 + if (chip == NULL) {
536 + pci_disable_device(pci);
544 + spin_lock_init(&chip->emu_lock);
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");
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");
560 + chip->irq = pci->irq;
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);
569 + pci_set_master(pci);
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");
578 + for (c = ca0106_chip_details; c->serial; c++) {
579 + if (subsystem[dev]) {
580 + if (c->serial == subsystem[dev])
582 + } else if (c->serial == chip->serial)
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]);
592 + sprintf(card->longname, "%s at 0x%lx irq %i",
593 + c->name, chip->port, chip->irq);
595 + ca0106_init_chip(chip, 0);
597 + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
599 snd_ca0106_free(chip);
602 @@ -1630,7 +1679,7 @@ static int __devinit snd_ca0106_probe(st
604 struct snd_card *card;
605 struct snd_ca0106 *chip;
609 if (dev >= SNDRV_CARDS)
611 @@ -1643,44 +1692,31 @@ static int __devinit snd_ca0106_probe(st
615 - if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) {
616 - snd_card_free(card);
620 - if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
621 - snd_card_free(card);
624 - if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
625 - snd_card_free(card);
628 - if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
629 - snd_card_free(card);
632 - if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
633 - snd_card_free(card);
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);
642 - if ((err = snd_ca0106_mixer(chip)) < 0) {
643 - snd_card_free(card);
646 + err = snd_ca0106_create(dev, card, pci, &chip);
649 + card->private_data = chip;
651 + for (i = 0; i < 4; i++) {
652 + err = snd_ca0106_pcm(chip, i);
657 + if (chip->details->ac97 == 1) {
658 + /* The SB0410 and SB0413 do not have an AC97 chip. */
659 + err = snd_ca0106_ac97(chip);
663 + err = snd_ca0106_mixer(chip);
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);
673 + err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A);
676 snd_printdd(" done.\n");
678 #ifdef CONFIG_PROC_FS
679 @@ -1689,14 +1725,17 @@ static int __devinit snd_ca0106_probe(st
681 snd_card_set_dev(card, &pci->dev);
683 - if ((err = snd_card_register(card)) < 0) {
684 - snd_card_free(card);
687 + err = snd_card_register(card);
691 pci_set_drvdata(pci, card);
696 + snd_card_free(card);
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);
706 +static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state)
708 + struct snd_card *card = pci_get_drvdata(pci);
709 + struct snd_ca0106 *chip = card->private_data;
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);
719 + ca0106_stop_chip(chip);
721 + pci_disable_device(pci);
722 + pci_save_state(pci);
723 + pci_set_power_state(pci, pci_choose_state(pci, state));
727 +static int snd_ca0106_resume(struct pci_dev *pci)
729 + struct snd_card *card = pci_get_drvdata(pci);
730 + struct snd_ca0106 *chip = card->private_data;
733 + pci_set_power_state(pci, PCI_D0);
734 + pci_restore_state(pci);
736 + if (pci_enable_device(pci) < 0) {
737 + snd_card_disconnect(card);
741 + pci_set_master(pci);
743 + ca0106_init_chip(chip, 1);
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]);
753 + snd_power_change_state(card, SNDRV_CTL_POWER_D0);
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,
769 // initialization of the module
770 --- a/sound/pci/ca0106/ca0106_mixer.c
771 +++ b/sound/pci/ca0106/ca0106_mixer.c
776 +static void ca0106_spdif_enable(struct snd_ca0106 *emu)
780 + if (emu->spdif_enable) {
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);
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);
800 +static void ca0106_set_capture_source(struct snd_ca0106 *emu)
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);
809 +static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu,
810 + unsigned int val, int force)
812 + unsigned int ngain, ogain;
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);
825 + snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
826 + emu->i2c_capture_source = val;
829 +static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu)
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;
837 + outl(tmp, emu->port+GPIO);
838 + /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
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); */
847 +static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
849 + snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_bits[idx]);
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);
857 @@ -95,30 +173,12 @@ static int snd_ca0106_shared_spdif_put(s
858 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
863 val = !!ucontrol->value.integer.value[0];
864 change = (emu->spdif_enable != val);
866 emu->spdif_enable = val;
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);
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);
885 + ca0106_spdif_enable(emu);
889 @@ -154,8 +214,6 @@ static int snd_ca0106_capture_source_put
890 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
896 val = ucontrol->value.enumerated.item[0] ;
898 @@ -163,9 +221,7 @@ static int snd_ca0106_capture_source_put
899 change = (emu->capture_source != val);
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);
909 @@ -200,9 +256,7 @@ static int snd_ca0106_i2c_capture_source
911 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
912 unsigned int source_id;
913 - unsigned int ngain, ogain;
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
921 change = (emu->i2c_capture_source != source_id);
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);
939 @@ -271,7 +314,6 @@ static int snd_ca0106_capture_mic_line_i
940 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
945 val = ucontrol->value.enumerated.item[0] ;
947 @@ -279,18 +321,7 @@ static int snd_ca0106_capture_mic_line_i
948 change = (emu->capture_mic_line_in != val);
950 emu->capture_mic_line_in = val;
952 - //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
953 - tmp = inl(emu->port+GPIO) & ~0x400;
955 - outl(tmp, emu->port+GPIO);
956 - //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
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);
963 + ca0106_set_capture_mic_line_in(emu);
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];
971 - snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, val);
972 emu->spdif_bits[idx] = val;
973 + ca0106_set_spdif_bits(emu, idx);
977 @@ -779,3 +810,50 @@ int __devinit snd_ca0106_mixer(struct sn
982 +struct ca0106_vol_tbl {
983 + unsigned int channel_id;
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 },
999 +void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
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);
1010 +void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
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]);
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);
1027 +#endif /* CONFIG_PM */