blob: 58ffa0cacfb12b5cde8f2cdc8e567188ebdecfb2 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
3 * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02004 * Version: 0.0.23
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
6 * FEATURES currently supported:
7 * Front, Rear and Center/LFE.
8 * Surround40 and Surround51.
9 * Capture from MIC an LINE IN input.
10 * SPDIF digital playback of PCM stereo and AC3/DTS works.
11 * (One can use a standard mono mini-jack to one RCA plugs cable.
12 * or one can use a standard stereo mini-jack to two RCA plugs cable.
13 * Plug one of the RCA plugs into the Coax input of the external decoder/receiver.)
14 * ( In theory one could output 3 different AC3 streams at once, to 3 different SPDIF outputs. )
15 * Notes on how to capture sound:
16 * The AC97 is used in the PLAYBACK direction.
17 * The output from the AC97 chip, instead of reaching the speakers, is fed into the Philips 1361T ADC.
18 * So, to record from the MIC, set the MIC Playback volume to max,
19 * unmute the MIC and turn up the MASTER Playback volume.
20 * So, to prevent feedback when capturing, minimise the "Capture feedback into Playback" volume.
21 *
22 * The only playback controls that currently do anything are: -
23 * Analog Front
24 * Analog Rear
25 * Analog Center/LFE
26 * SPDIF Front
27 * SPDIF Rear
28 * SPDIF Center/LFE
29 *
30 * For capture from Mic in or Line in.
31 * Digital/Analog ( switch must be in Analog mode for CAPTURE. )
32 *
33 * CAPTURE feedback into PLAYBACK
34 *
35 * Changelog:
36 * Support interrupts per period.
37 * Removed noise from Center/LFE channel when in Analog mode.
38 * Rename and remove mixer controls.
39 * 0.0.6
40 * Use separate card based DMA buffer for periods table list.
41 * 0.0.7
42 * Change remove and rename ctrls into lists.
43 * 0.0.8
44 * Try to fix capture sources.
45 * 0.0.9
46 * Fix AC3 output.
47 * Enable S32_LE format support.
48 * 0.0.10
49 * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".)
50 * 0.0.11
51 * Add Model name recognition.
52 * 0.0.12
53 * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period.
54 * Remove redundent "voice" handling.
55 * 0.0.13
56 * Single trigger call for multi channels.
57 * 0.0.14
58 * Set limits based on what the sound card hardware can do.
59 * playback periods_min=2, periods_max=8
60 * capture hw constraints require period_size = n * 64 bytes.
61 * playback hw constraints require period_size = n * 64 bytes.
62 * 0.0.15
63 * Minor updates.
64 * 0.0.16
65 * Implement 192000 sample rate.
66 * 0.0.17
67 * Add support for SB0410 and SB0413.
68 * 0.0.18
69 * Modified Copyright message.
70 * 0.0.19
71 * Finally fix support for SB Live 24 bit. SB0410 and SB0413.
72 * The output codec needs resetting, otherwise all output is muted.
73 * 0.0.20
74 * Merge "pci_disable_device(pci);" fixes.
75 * 0.0.21
76 * Add 4 capture channels. (SPDIF only comes in on channel 0. )
77 * Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.)
78 * 0.0.22
79 * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
James Courtier-Dutton7199acd2005-05-27 22:07:23 +020080 * 0.0.23
81 * Implement support for Line-in capture on SB Live 24bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 *
83 * BUGS:
84 * Some stability problems when unloading the snd-ca0106 kernel module.
85 * --
86 *
87 * TODO:
88 * 4 Capture channels, only one implemented so far.
89 * Other capture rates apart from 48khz not implemented.
90 * MIDI
91 * --
92 * GENERAL INFO:
93 * Model: SB0310
94 * P17 Chip: CA0106-DAT
95 * AC97 Codec: STAC 9721
96 * ADC: Philips 1361T (Stereo 24bit)
97 * DAC: WM8746EDS (6-channel, 24bit, 192Khz)
98 *
99 * GENERAL INFO:
100 * Model: SB0410
101 * P17 Chip: CA0106-DAT
102 * AC97 Codec: None
103 * ADC: WM8775EDS (4 Channel)
104 * DAC: CS4382 (114 dB, 24-Bit, 192 kHz, 8-Channel D/A Converter with DSD Support)
105 * SPDIF Out control switches between Mic in and SPDIF out.
106 * No sound out or mic input working yet.
107 *
108 * GENERAL INFO:
109 * Model: SB0413
110 * P17 Chip: CA0106-DAT
111 * AC97 Codec: None.
112 * ADC: Unknown
113 * DAC: Unknown
114 * Trying to handle it like the SB0410.
115 *
116 * This code was initally based on code from ALSA's emu10k1x.c which is:
117 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
118 *
119 * This program is free software; you can redistribute it and/or modify
120 * it under the terms of the GNU General Public License as published by
121 * the Free Software Foundation; either version 2 of the License, or
122 * (at your option) any later version.
123 *
124 * This program is distributed in the hope that it will be useful,
125 * but WITHOUT ANY WARRANTY; without even the implied warranty of
126 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
127 * GNU General Public License for more details.
128 *
129 * You should have received a copy of the GNU General Public License
130 * along with this program; if not, write to the Free Software
131 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
132 *
133 */
134#include <sound/driver.h>
135#include <linux/delay.h>
136#include <linux/init.h>
137#include <linux/interrupt.h>
138#include <linux/pci.h>
139#include <linux/slab.h>
140#include <linux/moduleparam.h>
Tobias Klauser299676b2005-05-29 15:21:02 +0200141#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142#include <sound/core.h>
143#include <sound/initval.h>
144#include <sound/pcm.h>
145#include <sound/ac97_codec.h>
146#include <sound/info.h>
147
148MODULE_AUTHOR("James Courtier-Dutton <James@superbug.demon.co.uk>");
149MODULE_DESCRIPTION("CA0106");
150MODULE_LICENSE("GPL");
151MODULE_SUPPORTED_DEVICE("{{Creative,SB CA0106 chip}}");
152
153// module parameters (see "Module Parameters")
154static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
155static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
156static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000157static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
159module_param_array(index, int, NULL, 0444);
160MODULE_PARM_DESC(index, "Index value for the CA0106 soundcard.");
161module_param_array(id, charp, NULL, 0444);
162MODULE_PARM_DESC(id, "ID string for the CA0106 soundcard.");
163module_param_array(enable, bool, NULL, 0444);
164MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard.");
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000165module_param_array(subsystem, uint, NULL, 0444);
166MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
168#include "ca0106.h"
169
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100170static struct snd_ca0106_details ca0106_chip_details[] = {
James Courtier-Dutton86326492007-05-18 20:35:50 +0100171 /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
172 /* It is really just a normal SB Live 24bit. */
James Courtier-Duttonaaccf542007-07-23 18:12:41 +0100173 /* Tested:
174 * See ALSA bug#3251
175 */
176 { .serial = 0x10131102,
177 .name = "X-Fi Extreme Audio [SBxxxx]",
178 .gpio_type = 1,
179 .i2c_adc = 1 } ,
180 /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
181 /* It is really just a normal SB Live 24bit. */
James Courtier-Dutton86326492007-05-18 20:35:50 +0100182 /*
183 * CTRL:CA0111-WTLF
184 * ADC: WM8775SEDS
185 * DAC: CS4382-KQZ
186 */
187 /* Tested:
188 * Playback on front, rear, center/lfe speakers
189 * Capture from Mic in.
190 * Not-Tested:
191 * Capture from Line in.
192 * Playback to digital out.
193 */
194 { .serial = 0x10121102,
195 .name = "X-Fi Extreme Audio [SB0790]",
196 .gpio_type = 1,
197 .i2c_adc = 1 } ,
198 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200199 /* AudigyLS[SB0310] */
200 { .serial = 0x10021102,
201 .name = "AudigyLS [SB0310]",
202 .ac97 = 1 } ,
203 /* Unknown AudigyLS that also says SB0310 on it */
204 { .serial = 0x10051102,
205 .name = "AudigyLS [SB0310b]",
206 .ac97 = 1 } ,
207 /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
208 { .serial = 0x10061102,
209 .name = "Live! 7.1 24bit [SB0410]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200210 .gpio_type = 1,
211 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200212 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
213 { .serial = 0x10071102,
214 .name = "Live! 7.1 24bit [SB0413]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200215 .gpio_type = 1,
216 .i2c_adc = 1 } ,
James Courtier-Duttona5875152005-12-20 22:30:49 +0100217 /* New Audigy SE. Has a different DAC. */
218 /* SB0570:
219 * CTRL:CA0106-DAT
James Courtier-Dutton58398892006-06-10 09:16:49 +0100220 * ADC: WM8775EDS
221 * DAC: WM8768GEDS
James Courtier-Duttona5875152005-12-20 22:30:49 +0100222 */
223 { .serial = 0x100a1102,
224 .name = "Audigy SE [SB0570]",
225 .gpio_type = 1,
226 .i2c_adc = 1,
227 .spi_dac = 1 } ,
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000228 /* New Audigy LS. Has a different DAC. */
229 /* SB0570:
230 * CTRL:CA0106-DAT
231 * ADC: WM8775EDS
232 * DAC: WM8768GEDS
233 */
234 { .serial = 0x10111102,
James Courtier-Duttond5f6a382006-11-25 19:50:11 +0000235 .name = "Audigy SE OEM [SB0570a]",
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000236 .gpio_type = 1,
237 .i2c_adc = 1,
238 .spi_dac = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200239 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100240 /* SB0438
241 * CTRL:CA0106-DAT
242 * ADC: WM8775SEDS
243 * DAC: CS4382-KQZ
244 */
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200245 { .serial = 0x10091462,
246 .name = "MSI K8N Diamond MB [SB0438]",
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100247 .gpio_type = 2,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200248 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100249 /* Shuttle XPC SD31P which has an onboard Creative Labs
250 * Sound Blaster Live! 24-bit EAX
James Courtier-Dutton1b059622005-08-12 23:50:13 +0200251 * high-definition 7.1 audio processor".
252 * Added using info from andrewvegan in alsa bug #1298
253 */
254 { .serial = 0x30381297,
255 .name = "Shuttle XPC SD31P [SD31P]",
256 .gpio_type = 1,
257 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100258 /* Shuttle XPC SD11G5 which has an onboard Creative Labs
259 * Sound Blaster Live! 24-bit EAX
260 * high-definition 7.1 audio processor".
261 * Fixes ALSA bug#1600
262 */
263 { .serial = 0x30411297,
264 .name = "Shuttle XPC SD11G5 [SD11G5]",
265 .gpio_type = 1,
266 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200267 { .serial = 0,
268 .name = "AudigyLS [Unknown]" }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269};
270
271/* hardware definition */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100272static struct snd_pcm_hardware snd_ca0106_playback_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 .info = (SNDRV_PCM_INFO_MMAP |
274 SNDRV_PCM_INFO_INTERLEAVED |
275 SNDRV_PCM_INFO_BLOCK_TRANSFER |
276 SNDRV_PCM_INFO_MMAP_VALID),
277 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100278 .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
279 SNDRV_PCM_RATE_192000),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 .rate_min = 48000,
281 .rate_max = 192000,
282 .channels_min = 2, //1,
283 .channels_max = 2, //6,
284 .buffer_bytes_max = ((65536 - 64) * 8),
285 .period_bytes_min = 64,
286 .period_bytes_max = (65536 - 64),
287 .periods_min = 2,
288 .periods_max = 8,
289 .fifo_size = 0,
290};
291
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100292static struct snd_pcm_hardware snd_ca0106_capture_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 .info = (SNDRV_PCM_INFO_MMAP |
294 SNDRV_PCM_INFO_INTERLEAVED |
295 SNDRV_PCM_INFO_BLOCK_TRANSFER |
296 SNDRV_PCM_INFO_MMAP_VALID),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200297 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100298 .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
299 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200300 .rate_min = 44100,
301 .rate_max = 192000,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 .channels_min = 2,
303 .channels_max = 2,
304 .buffer_bytes_max = ((65536 - 64) * 8),
305 .period_bytes_min = 64,
306 .period_bytes_max = (65536 - 64),
307 .periods_min = 2,
308 .periods_max = 2,
309 .fifo_size = 0,
310};
311
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100312unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 unsigned int reg,
314 unsigned int chn)
315{
316 unsigned long flags;
317 unsigned int regptr, val;
318
319 regptr = (reg << 16) | chn;
320
321 spin_lock_irqsave(&emu->emu_lock, flags);
322 outl(regptr, emu->port + PTR);
323 val = inl(emu->port + DATA);
324 spin_unlock_irqrestore(&emu->emu_lock, flags);
325 return val;
326}
327
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100328void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 unsigned int reg,
330 unsigned int chn,
331 unsigned int data)
332{
333 unsigned int regptr;
334 unsigned long flags;
335
336 regptr = (reg << 16) | chn;
337
338 spin_lock_irqsave(&emu->emu_lock, flags);
339 outl(regptr, emu->port + PTR);
340 outl(data, emu->port + DATA);
341 spin_unlock_irqrestore(&emu->emu_lock, flags);
342}
343
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100344int snd_ca0106_spi_write(struct snd_ca0106 * emu,
345 unsigned int data)
James Courtier-Duttona5875152005-12-20 22:30:49 +0100346{
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100347 unsigned int reset, set;
348 unsigned int reg, tmp;
349 int n, result;
350 reg = SPI;
351 if (data > 0xffff) /* Only 16bit values allowed */
352 return 1;
353 tmp = snd_ca0106_ptr_read(emu, reg, 0);
354 reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
355 set = reset | 0x10000; /* Set xxx1xxxx */
356 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
357 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* write post */
358 snd_ca0106_ptr_write(emu, reg, 0, set | data);
359 result = 1;
360 /* Wait for status bit to return to 0 */
361 for (n = 0; n < 100; n++) {
362 udelay(10);
363 tmp = snd_ca0106_ptr_read(emu, reg, 0);
364 if (!(tmp & 0x10000)) {
365 result = 0;
366 break;
367 }
368 }
369 if (result) /* Timed out */
370 return 1;
371 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
372 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* Write post */
James Courtier-Duttona5875152005-12-20 22:30:49 +0100373 return 0;
374}
375
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100376/* The ADC does not support i2c read, so only write is implemented */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100377int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200378 u32 reg,
379 u32 value)
380{
381 u32 tmp;
Takashi Iwai95a98262005-11-17 10:40:18 +0100382 int timeout = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200383 int status;
384 int retry;
Takashi Iwai95a98262005-11-17 10:40:18 +0100385 if ((reg > 0x7f) || (value > 0x1ff)) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200386 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200387 return -EINVAL;
388 }
389
390 tmp = reg << 25 | value << 16;
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100391 // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
James Courtier-Dutton8fabab12005-05-28 16:35:49 +0200392 /* Not sure what this I2C channel controls. */
393 /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
394
395 /* This controls the I2C connected to the WM8775 ADC Codec */
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200396 snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
397
Takashi Iwai95a98262005-11-17 10:40:18 +0100398 for (retry = 0; retry < 10; retry++) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200399 /* Send the data to i2c */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100400 //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
401 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
402 tmp = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200403 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
404 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
405
406 /* Wait till the transaction ends */
Takashi Iwai95a98262005-11-17 10:40:18 +0100407 while (1) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200408 status = snd_ca0106_ptr_read(emu, I2C_A, 0);
409 //snd_printk("I2C:status=0x%x\n", status);
410 timeout++;
Takashi Iwai95a98262005-11-17 10:40:18 +0100411 if ((status & I2C_A_ADC_START) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200412 break;
413
Takashi Iwai95a98262005-11-17 10:40:18 +0100414 if (timeout > 1000)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200415 break;
416 }
417 //Read back and see if the transaction is successful
Takashi Iwai95a98262005-11-17 10:40:18 +0100418 if ((status & I2C_A_ADC_ABORT) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200419 break;
420 }
421
Takashi Iwai95a98262005-11-17 10:40:18 +0100422 if (retry == 10) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200423 snd_printk(KERN_ERR "Writing to ADC failed!\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200424 return -EINVAL;
425 }
426
427 return 0;
428}
429
430
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100431static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
433 unsigned long flags;
434 unsigned int enable;
435
436 spin_lock_irqsave(&emu->emu_lock, flags);
437 enable = inl(emu->port + INTE) | intrenb;
438 outl(enable, emu->port + INTE);
439 spin_unlock_irqrestore(&emu->emu_lock, flags);
440}
441
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100442static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +0200443{
444 unsigned long flags;
445 unsigned int enable;
446
447 spin_lock_irqsave(&emu->emu_lock, flags);
448 enable = inl(emu->port + INTE) & ~intrenb;
449 outl(enable, emu->port + INTE);
450 spin_unlock_irqrestore(&emu->emu_lock, flags);
451}
452
453
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100454static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
Jesper Juhl4d572772005-05-30 17:30:32 +0200456 kfree(runtime->private_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457}
458
459/* open_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100460static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
461 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100463 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
464 struct snd_ca0106_channel *channel = &(chip->playback_channels[channel_id]);
465 struct snd_ca0106_pcm *epcm;
466 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 int err;
468
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200469 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
471 if (epcm == NULL)
472 return -ENOMEM;
473 epcm->emu = chip;
474 epcm->substream = substream;
475 epcm->channel_id=channel_id;
476
477 runtime->private_data = epcm;
478 runtime->private_free = snd_ca0106_pcm_free_substream;
479
480 runtime->hw = snd_ca0106_playback_hw;
481
482 channel->emu = chip;
483 channel->number = channel_id;
484
Takashi Iwai95a98262005-11-17 10:40:18 +0100485 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
487 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwai95a98262005-11-17 10:40:18 +0100488 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
490 return err;
491 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
492 return err;
493 return 0;
494}
495
496/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100497static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100499 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
500 struct snd_pcm_runtime *runtime = substream->runtime;
501 struct snd_ca0106_pcm *epcm = runtime->private_data;
502 chip->playback_channels[epcm->channel_id].use = 0;
503 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 return 0;
505}
506
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100507static int snd_ca0106_pcm_open_playback_front(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508{
509 return snd_ca0106_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
510}
511
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100512static int snd_ca0106_pcm_open_playback_center_lfe(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513{
514 return snd_ca0106_pcm_open_playback_channel(substream, PCM_CENTER_LFE_CHANNEL);
515}
516
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100517static int snd_ca0106_pcm_open_playback_unknown(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518{
519 return snd_ca0106_pcm_open_playback_channel(substream, PCM_UNKNOWN_CHANNEL);
520}
521
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100522static int snd_ca0106_pcm_open_playback_rear(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523{
524 return snd_ca0106_pcm_open_playback_channel(substream, PCM_REAR_CHANNEL);
525}
526
527/* open_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100528static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substream,
529 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100531 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
532 struct snd_ca0106_channel *channel = &(chip->capture_channels[channel_id]);
533 struct snd_ca0106_pcm *epcm;
534 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 int err;
536
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200537 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 if (epcm == NULL) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200539 snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return -ENOMEM;
541 }
542 epcm->emu = chip;
543 epcm->substream = substream;
544 epcm->channel_id=channel_id;
545
546 runtime->private_data = epcm;
547 runtime->private_free = snd_ca0106_pcm_free_substream;
548
549 runtime->hw = snd_ca0106_capture_hw;
550
551 channel->emu = chip;
552 channel->number = channel_id;
553
Takashi Iwai95a98262005-11-17 10:40:18 +0100554 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
556 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100557 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
559 return err;
560 //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
561 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
562 return err;
563 return 0;
564}
565
566/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100567static int snd_ca0106_pcm_close_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100569 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
570 struct snd_pcm_runtime *runtime = substream->runtime;
571 struct snd_ca0106_pcm *epcm = runtime->private_data;
572 chip->capture_channels[epcm->channel_id].use = 0;
573 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 return 0;
575}
576
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100577static int snd_ca0106_pcm_open_0_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578{
579 return snd_ca0106_pcm_open_capture_channel(substream, 0);
580}
581
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100582static int snd_ca0106_pcm_open_1_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583{
584 return snd_ca0106_pcm_open_capture_channel(substream, 1);
585}
586
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100587static int snd_ca0106_pcm_open_2_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588{
589 return snd_ca0106_pcm_open_capture_channel(substream, 2);
590}
591
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100592static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 return snd_ca0106_pcm_open_capture_channel(substream, 3);
595}
596
597/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100598static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream,
599 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600{
601 return snd_pcm_lib_malloc_pages(substream,
602 params_buffer_bytes(hw_params));
603}
604
605/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100606static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607{
608 return snd_pcm_lib_free_pages(substream);
609}
610
611/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100612static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream,
613 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614{
615 return snd_pcm_lib_malloc_pages(substream,
616 params_buffer_bytes(hw_params));
617}
618
619/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100620static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
622 return snd_pcm_lib_free_pages(substream);
623}
624
625/* prepare playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100626static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100628 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
629 struct snd_pcm_runtime *runtime = substream->runtime;
630 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 int channel = epcm->channel_id;
632 u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
633 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
634 u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
635 u32 hcfg_set = 0x00000000;
636 u32 hcfg;
637 u32 reg40_mask = 0x30000 << (channel<<1);
638 u32 reg40_set = 0;
639 u32 reg40;
640 /* FIXME: Depending on mixer selection of SPDIF out or not, select the spdif rate or the DAC rate. */
641 u32 reg71_mask = 0x03030000 ; /* Global. Set SPDIF rate. We only support 44100 to spdif, not to DAC. */
642 u32 reg71_set = 0;
643 u32 reg71;
644 int i;
645
646 //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
647 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
648 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
649 /* Rate can be set per channel. */
650 /* reg40 control host to fifo */
651 /* reg71 controls DAC rate. */
652 switch (runtime->rate) {
653 case 44100:
654 reg40_set = 0x10000 << (channel<<1);
655 reg71_set = 0x01010000;
656 break;
657 case 48000:
658 reg40_set = 0;
659 reg71_set = 0;
660 break;
661 case 96000:
662 reg40_set = 0x20000 << (channel<<1);
663 reg71_set = 0x02020000;
664 break;
665 case 192000:
666 reg40_set = 0x30000 << (channel<<1);
667 reg71_set = 0x03030000;
668 break;
669 default:
670 reg40_set = 0;
671 reg71_set = 0;
672 break;
673 }
674 /* Format is a global setting */
675 /* FIXME: Only let the first channel accessed set this. */
676 switch (runtime->format) {
677 case SNDRV_PCM_FORMAT_S16_LE:
678 hcfg_set = 0;
679 break;
680 case SNDRV_PCM_FORMAT_S32_LE:
681 hcfg_set = HCFG_PLAYBACK_S32_LE;
682 break;
683 default:
684 hcfg_set = 0;
685 break;
686 }
687 hcfg = inl(emu->port + HCFG) ;
688 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
689 outl(hcfg, emu->port + HCFG);
690 reg40 = snd_ca0106_ptr_read(emu, 0x40, 0);
691 reg40 = (reg40 & ~reg40_mask) | reg40_set;
692 snd_ca0106_ptr_write(emu, 0x40, 0, reg40);
693 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
694 reg71 = (reg71 & ~reg71_mask) | reg71_set;
695 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
696
697 /* FIXME: Check emu->buffer.size before actually writing to it. */
698 for(i=0; i < runtime->periods; i++) {
Takashi Iwai95a98262005-11-17 10:40:18 +0100699 table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
700 table_base[i*2+1] = period_size_bytes << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 }
702
703 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
704 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
705 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
706 snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
707 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
708 /* FIXME test what 0 bytes does. */
709 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
710 snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
711 snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
712 snd_ca0106_ptr_write(emu, 0x08, channel, 0);
713 snd_ca0106_ptr_write(emu, PLAYBACK_MUTE, 0x0, 0x0); /* Unmute output */
714#if 0
715 snd_ca0106_ptr_write(emu, SPCS0, 0,
716 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
717 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
718 SPCS_GENERATIONSTATUS | 0x00001200 |
719 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
720 }
721#endif
722
723 return 0;
724}
725
726/* prepare capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100727static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100729 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
730 struct snd_pcm_runtime *runtime = substream->runtime;
731 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 int channel = epcm->channel_id;
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200733 u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
734 u32 hcfg_set = 0x00000000;
735 u32 hcfg;
736 u32 over_sampling=0x2;
737 u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
738 u32 reg71_set = 0;
739 u32 reg71;
740
741 //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
742 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
743 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
744 /* reg71 controls ADC rate. */
745 switch (runtime->rate) {
746 case 44100:
747 reg71_set = 0x00004000;
748 break;
749 case 48000:
750 reg71_set = 0;
751 break;
752 case 96000:
753 reg71_set = 0x00008000;
754 over_sampling=0xa;
755 break;
756 case 192000:
757 reg71_set = 0x0000c000;
758 over_sampling=0xa;
759 break;
760 default:
761 reg71_set = 0;
762 break;
763 }
764 /* Format is a global setting */
765 /* FIXME: Only let the first channel accessed set this. */
766 switch (runtime->format) {
767 case SNDRV_PCM_FORMAT_S16_LE:
768 hcfg_set = 0;
769 break;
770 case SNDRV_PCM_FORMAT_S32_LE:
771 hcfg_set = HCFG_CAPTURE_S32_LE;
772 break;
773 default:
774 hcfg_set = 0;
775 break;
776 }
777 hcfg = inl(emu->port + HCFG) ;
778 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
779 outl(hcfg, emu->port + HCFG);
780 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
781 reg71 = (reg71 & ~reg71_mask) | reg71_set;
782 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
783 if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
784 snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
785 }
786
787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1));
789 snd_ca0106_ptr_write(emu, 0x13, channel, 0);
790 snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
791 snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
792 snd_ca0106_ptr_write(emu, CAPTURE_POINTER, channel, 0);
793
794 return 0;
795}
796
797/* trigger_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100798static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 int cmd)
800{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100801 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
802 struct snd_pcm_runtime *runtime;
803 struct snd_ca0106_pcm *epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 int channel;
805 int result = 0;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100806 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 u32 basic = 0;
808 u32 extended = 0;
809 int running=0;
810
811 switch (cmd) {
812 case SNDRV_PCM_TRIGGER_START:
813 running=1;
814 break;
815 case SNDRV_PCM_TRIGGER_STOP:
816 default:
817 running=0;
818 break;
819 }
Takashi Iwaief991b92007-02-22 12:52:53 +0100820 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 runtime = s->runtime;
822 epcm = runtime->private_data;
823 channel = epcm->channel_id;
824 //snd_printk("channel=%d\n",channel);
825 epcm->running = running;
826 basic |= (0x1<<channel);
827 extended |= (0x10<<channel);
828 snd_pcm_trigger_done(s, substream);
829 }
830 //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
831
832 switch (cmd) {
833 case SNDRV_PCM_TRIGGER_START:
834 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
835 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
836 break;
837 case SNDRV_PCM_TRIGGER_STOP:
838 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
839 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
840 break;
841 default:
842 result = -EINVAL;
843 break;
844 }
845 return result;
846}
847
848/* trigger_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100849static int snd_ca0106_pcm_trigger_capture(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 int cmd)
851{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100852 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
853 struct snd_pcm_runtime *runtime = substream->runtime;
854 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 int channel = epcm->channel_id;
856 int result = 0;
857
858 switch (cmd) {
859 case SNDRV_PCM_TRIGGER_START:
860 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
861 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
862 epcm->running = 1;
863 break;
864 case SNDRV_PCM_TRIGGER_STOP:
865 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
866 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
867 epcm->running = 0;
868 break;
869 default:
870 result = -EINVAL;
871 break;
872 }
873 return result;
874}
875
876/* pointer_playback callback */
877static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100878snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100880 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
881 struct snd_pcm_runtime *runtime = substream->runtime;
882 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
884 int channel = epcm->channel_id;
885
886 if (!epcm->running)
887 return 0;
888
889 ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
890 ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
891 ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
892 if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
893 ptr2 = bytes_to_frames(runtime, ptr1);
894 ptr2+= (ptr4 >> 3) * runtime->period_size;
895 ptr=ptr2;
896 if (ptr >= runtime->buffer_size)
897 ptr -= runtime->buffer_size;
898 //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
899
900 return ptr;
901}
902
903/* pointer_capture callback */
904static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100905snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100907 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
908 struct snd_pcm_runtime *runtime = substream->runtime;
909 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
911 int channel = channel=epcm->channel_id;
912
913 if (!epcm->running)
914 return 0;
915
916 ptr1 = snd_ca0106_ptr_read(emu, CAPTURE_POINTER, channel);
917 ptr2 = bytes_to_frames(runtime, ptr1);
918 ptr=ptr2;
919 if (ptr >= runtime->buffer_size)
920 ptr -= runtime->buffer_size;
921 //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
922
923 return ptr;
924}
925
926/* operators */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100927static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 .open = snd_ca0106_pcm_open_playback_front,
929 .close = snd_ca0106_pcm_close_playback,
930 .ioctl = snd_pcm_lib_ioctl,
931 .hw_params = snd_ca0106_pcm_hw_params_playback,
932 .hw_free = snd_ca0106_pcm_hw_free_playback,
933 .prepare = snd_ca0106_pcm_prepare_playback,
934 .trigger = snd_ca0106_pcm_trigger_playback,
935 .pointer = snd_ca0106_pcm_pointer_playback,
936};
937
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100938static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 .open = snd_ca0106_pcm_open_0_capture,
940 .close = snd_ca0106_pcm_close_capture,
941 .ioctl = snd_pcm_lib_ioctl,
942 .hw_params = snd_ca0106_pcm_hw_params_capture,
943 .hw_free = snd_ca0106_pcm_hw_free_capture,
944 .prepare = snd_ca0106_pcm_prepare_capture,
945 .trigger = snd_ca0106_pcm_trigger_capture,
946 .pointer = snd_ca0106_pcm_pointer_capture,
947};
948
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100949static struct snd_pcm_ops snd_ca0106_capture_1_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 .open = snd_ca0106_pcm_open_1_capture,
951 .close = snd_ca0106_pcm_close_capture,
952 .ioctl = snd_pcm_lib_ioctl,
953 .hw_params = snd_ca0106_pcm_hw_params_capture,
954 .hw_free = snd_ca0106_pcm_hw_free_capture,
955 .prepare = snd_ca0106_pcm_prepare_capture,
956 .trigger = snd_ca0106_pcm_trigger_capture,
957 .pointer = snd_ca0106_pcm_pointer_capture,
958};
959
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100960static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 .open = snd_ca0106_pcm_open_2_capture,
962 .close = snd_ca0106_pcm_close_capture,
963 .ioctl = snd_pcm_lib_ioctl,
964 .hw_params = snd_ca0106_pcm_hw_params_capture,
965 .hw_free = snd_ca0106_pcm_hw_free_capture,
966 .prepare = snd_ca0106_pcm_prepare_capture,
967 .trigger = snd_ca0106_pcm_trigger_capture,
968 .pointer = snd_ca0106_pcm_pointer_capture,
969};
970
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100971static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 .open = snd_ca0106_pcm_open_3_capture,
973 .close = snd_ca0106_pcm_close_capture,
974 .ioctl = snd_pcm_lib_ioctl,
975 .hw_params = snd_ca0106_pcm_hw_params_capture,
976 .hw_free = snd_ca0106_pcm_hw_free_capture,
977 .prepare = snd_ca0106_pcm_prepare_capture,
978 .trigger = snd_ca0106_pcm_trigger_capture,
979 .pointer = snd_ca0106_pcm_pointer_capture,
980};
981
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100982static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 .open = snd_ca0106_pcm_open_playback_center_lfe,
984 .close = snd_ca0106_pcm_close_playback,
985 .ioctl = snd_pcm_lib_ioctl,
986 .hw_params = snd_ca0106_pcm_hw_params_playback,
987 .hw_free = snd_ca0106_pcm_hw_free_playback,
988 .prepare = snd_ca0106_pcm_prepare_playback,
989 .trigger = snd_ca0106_pcm_trigger_playback,
990 .pointer = snd_ca0106_pcm_pointer_playback,
991};
992
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100993static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 .open = snd_ca0106_pcm_open_playback_unknown,
995 .close = snd_ca0106_pcm_close_playback,
996 .ioctl = snd_pcm_lib_ioctl,
997 .hw_params = snd_ca0106_pcm_hw_params_playback,
998 .hw_free = snd_ca0106_pcm_hw_free_playback,
999 .prepare = snd_ca0106_pcm_prepare_playback,
1000 .trigger = snd_ca0106_pcm_trigger_playback,
1001 .pointer = snd_ca0106_pcm_pointer_playback,
1002};
1003
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001004static struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 .open = snd_ca0106_pcm_open_playback_rear,
1006 .close = snd_ca0106_pcm_close_playback,
1007 .ioctl = snd_pcm_lib_ioctl,
1008 .hw_params = snd_ca0106_pcm_hw_params_playback,
1009 .hw_free = snd_ca0106_pcm_hw_free_playback,
1010 .prepare = snd_ca0106_pcm_prepare_playback,
1011 .trigger = snd_ca0106_pcm_trigger_playback,
1012 .pointer = snd_ca0106_pcm_pointer_playback,
1013};
1014
1015
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001016static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 unsigned short reg)
1018{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001019 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 unsigned long flags;
1021 unsigned short val;
1022
1023 spin_lock_irqsave(&emu->emu_lock, flags);
1024 outb(reg, emu->port + AC97ADDRESS);
1025 val = inw(emu->port + AC97DATA);
1026 spin_unlock_irqrestore(&emu->emu_lock, flags);
1027 return val;
1028}
1029
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001030static void snd_ca0106_ac97_write(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 unsigned short reg, unsigned short val)
1032{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001033 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 unsigned long flags;
1035
1036 spin_lock_irqsave(&emu->emu_lock, flags);
1037 outb(reg, emu->port + AC97ADDRESS);
1038 outw(val, emu->port + AC97DATA);
1039 spin_unlock_irqrestore(&emu->emu_lock, flags);
1040}
1041
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001042static int snd_ca0106_ac97(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001044 struct snd_ac97_bus *pbus;
1045 struct snd_ac97_template ac97;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 int err;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001047 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 .write = snd_ca0106_ac97_write,
1049 .read = snd_ca0106_ac97_read,
1050 };
1051
1052 if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
1053 return err;
1054 pbus->no_vra = 1; /* we don't need VRA */
1055
1056 memset(&ac97, 0, sizeof(ac97));
1057 ac97.private_data = chip;
Takashi Iwai36c4dc42005-03-24 17:48:30 +01001058 ac97.scaps = AC97_SCAP_NO_SPDIF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
1060}
1061
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001062static int snd_ca0106_free(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063{
1064 if (chip->res_port != NULL) { /* avoid access to already used hardware */
1065 // disable interrupts
1066 snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
1067 outl(0, chip->port + INTE);
1068 snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
1069 udelay(1000);
1070 // disable audio
1071 //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
1072 outl(0, chip->port + HCFG);
1073 /* FIXME: We need to stop and DMA transfers here.
1074 * But as I am not sure how yet, we cannot from the dma pages.
1075 * So we can fix: snd-malloc: Memory leak? pages not freed = 8
1076 */
1077 }
1078 // release the data
1079#if 1
1080 if (chip->buffer.area)
1081 snd_dma_free_pages(&chip->buffer);
1082#endif
1083
1084 // release the i/o port
Takashi Iwaib1d57762005-10-10 11:56:31 +02001085 release_and_free_resource(chip->res_port);
1086
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 // release the irq
1088 if (chip->irq >= 0)
Takashi Iwai437a5a42006-11-21 12:14:23 +01001089 free_irq(chip->irq, chip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 pci_disable_device(chip->pci);
1091 kfree(chip);
1092 return 0;
1093}
1094
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001095static int snd_ca0106_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001097 struct snd_ca0106 *chip = device->device_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 return snd_ca0106_free(chip);
1099}
1100
David Howells7d12e782006-10-05 14:55:46 +01001101static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102{
1103 unsigned int status;
1104
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001105 struct snd_ca0106 *chip = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 int i;
1107 int mask;
1108 unsigned int stat76;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001109 struct snd_ca0106_channel *pchannel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 status = inl(chip->port + IPR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 if (! status)
1113 return IRQ_NONE;
1114
1115 stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0);
1116 //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76);
1117 //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0));
1118 mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
1119 for(i = 0; i < 4; i++) {
1120 pchannel = &(chip->playback_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001121 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122/* FIXME: Select the correct substream for period elapsed */
1123 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001124 snd_pcm_period_elapsed(pchannel->epcm->substream);
1125 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 }
1127 }
1128 //printk(KERN_INFO "channel=%p\n",pchannel);
1129 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1130 mask <<= 1;
1131 }
1132 mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */
1133 for(i = 0; i < 4; i++) {
1134 pchannel = &(chip->capture_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001135 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136/* FIXME: Select the correct substream for period elapsed */
1137 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001138 snd_pcm_period_elapsed(pchannel->epcm->substream);
1139 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 }
1141 }
1142 //printk(KERN_INFO "channel=%p\n",pchannel);
1143 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1144 mask <<= 1;
1145 }
1146
1147 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001148
1149 if (chip->midi.dev_id &&
Takashi Iwai95a98262005-11-17 10:40:18 +01001150 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001151 if (chip->midi.interrupt)
1152 chip->midi.interrupt(&chip->midi, status);
1153 else
1154 chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable);
1155 }
1156
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 // acknowledge the interrupt if necessary
1158 outl(status, chip->port+IPR);
1159
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 return IRQ_HANDLED;
1161}
1162
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001163static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001165 struct snd_pcm *pcm;
1166 struct snd_pcm_substream *substream;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 int err;
1168
1169 if (rpcm)
1170 *rpcm = NULL;
1171 if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
1172 return err;
1173
1174 pcm->private_data = emu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
1176 switch (device) {
1177 case 0:
1178 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops);
1179 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops);
1180 break;
1181 case 1:
1182 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops);
1183 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops);
1184 break;
1185 case 2:
1186 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops);
1187 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops);
1188 break;
1189 case 3:
1190 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops);
1191 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops);
1192 break;
1193 }
1194
1195 pcm->info_flags = 0;
1196 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
1197 strcpy(pcm->name, "CA0106");
1198 emu->pcm = pcm;
1199
1200 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1201 substream;
1202 substream = substream->next) {
1203 if ((err = snd_pcm_lib_preallocate_pages(substream,
1204 SNDRV_DMA_TYPE_DEV,
1205 snd_dma_pci_data(emu->pci),
1206 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
1207 return err;
1208 }
1209
1210 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1211 substream;
1212 substream = substream->next) {
1213 if ((err = snd_pcm_lib_preallocate_pages(substream,
1214 SNDRV_DMA_TYPE_DEV,
1215 snd_dma_pci_data(emu->pci),
1216 64*1024, 64*1024)) < 0)
1217 return err;
1218 }
1219
1220 if (rpcm)
1221 *rpcm = pcm;
1222
1223 return 0;
1224}
1225
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001226static unsigned int spi_dac_init[] = {
1227 0x00ff,
1228 0x02ff,
1229 0x0400,
1230 0x0520,
James Courtier-Dutton58398892006-06-10 09:16:49 +01001231 0x0620, /* Set 24 bit. Was 0x0600 */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001232 0x08ff,
1233 0x0aff,
1234 0x0cff,
1235 0x0eff,
1236 0x10ff,
1237 0x1200,
1238 0x1400,
1239 0x1480,
1240 0x1800,
1241 0x1aff,
1242 0x1cff,
1243 0x1e00,
1244 0x0530,
1245 0x0602,
1246 0x0622,
1247 0x1400,
1248};
1249
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001250static unsigned int i2c_adc_init[][2] = {
1251 { 0x17, 0x00 }, /* Reset */
1252 { 0x07, 0x00 }, /* Timeout */
1253 { 0x0b, 0x22 }, /* Interface control */
1254 { 0x0c, 0x22 }, /* Master mode control */
1255 { 0x0d, 0x08 }, /* Powerdown control */
1256 { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
1257 { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */
1258 { 0x10, 0x7b }, /* ALC Control 1 */
1259 { 0x11, 0x00 }, /* ALC Control 2 */
1260 { 0x12, 0x32 }, /* ALC Control 3 */
1261 { 0x13, 0x00 }, /* Noise gate control */
1262 { 0x14, 0xa6 }, /* Limiter control */
1263 { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
1264};
1265
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001266static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 struct pci_dev *pci,
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001268 struct snd_ca0106 **rchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001270 struct snd_ca0106 *chip;
1271 struct snd_ca0106_details *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 int err;
1273 int ch;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001274 static struct snd_device_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 .dev_free = snd_ca0106_dev_free,
1276 };
1277
1278 *rchip = NULL;
1279
1280 if ((err = pci_enable_device(pci)) < 0)
1281 return err;
Tobias Klauser299676b2005-05-29 15:21:02 +02001282 if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
1283 pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 printk(KERN_ERR "error to set 32bit mask DMA\n");
1285 pci_disable_device(pci);
1286 return -ENXIO;
1287 }
1288
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001289 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 if (chip == NULL) {
1291 pci_disable_device(pci);
1292 return -ENOMEM;
1293 }
1294
1295 chip->card = card;
1296 chip->pci = pci;
1297 chip->irq = -1;
1298
1299 spin_lock_init(&chip->emu_lock);
1300
1301 chip->port = pci_resource_start(pci, 0);
1302 if ((chip->res_port = request_region(chip->port, 0x20,
1303 "snd_ca0106")) == NULL) {
1304 snd_ca0106_free(chip);
1305 printk(KERN_ERR "cannot allocate the port\n");
1306 return -EBUSY;
1307 }
1308
1309 if (request_irq(pci->irq, snd_ca0106_interrupt,
Takashi Iwai437a5a42006-11-21 12:14:23 +01001310 IRQF_SHARED, "snd_ca0106", chip)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 snd_ca0106_free(chip);
1312 printk(KERN_ERR "cannot grab irq\n");
1313 return -EBUSY;
1314 }
1315 chip->irq = pci->irq;
1316
1317 /* This stores the periods table. */
1318 if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
1319 snd_ca0106_free(chip);
1320 return -ENOMEM;
1321 }
1322
1323 pci_set_master(pci);
Auke Kok44c10132007-06-08 15:46:36 -07001324 /* read serial */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
1326 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
1327#if 1
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001328 printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
Auke Kok44c10132007-06-08 15:46:36 -07001329 pci->revision, chip->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330#endif
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001331 strcpy(card->driver, "CA0106");
1332 strcpy(card->shortname, "CA0106");
1333
Takashi Iwai95a98262005-11-17 10:40:18 +01001334 for (c = ca0106_chip_details; c->serial; c++) {
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001335 if (subsystem[dev]) {
1336 if (c->serial == subsystem[dev])
1337 break;
1338 } else if (c->serial == chip->serial)
Takashi Iwai95a98262005-11-17 10:40:18 +01001339 break;
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001340 }
1341 chip->details = c;
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001342 if (subsystem[dev]) {
James Courtier-Duttond5f6a382006-11-25 19:50:11 +00001343 printk(KERN_INFO "snd-ca0106: Sound card name=%s, subsystem=0x%x. Forced to subsystem=0x%x\n",
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001344 c->name, chip->serial, subsystem[dev]);
1345 }
1346
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001347 sprintf(card->longname, "%s at 0x%lx irq %i",
1348 c->name, chip->port, chip->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
1350 outl(0, chip->port + INTE);
1351
1352 /*
1353 * Init to 0x02109204 :
1354 * Clock accuracy = 0 (1000ppm)
1355 * Sample Rate = 2 (48kHz)
1356 * Audio Channel = 1 (Left of 2)
1357 * Source Number = 0 (Unspecified)
1358 * Generation Status = 1 (Original for Cat Code 12)
1359 * Cat Code = 12 (Digital Signal Mixer)
1360 * Mode = 0 (Mode 0)
1361 * Emphasis = 0 (None)
1362 * CP = 1 (Copyright unasserted)
1363 * AN = 0 (Audio data)
1364 * P = 0 (Consumer)
1365 */
1366 snd_ca0106_ptr_write(chip, SPCS0, 0,
1367 chip->spdif_bits[0] =
1368 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1369 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1370 SPCS_GENERATIONSTATUS | 0x00001200 |
1371 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1372 /* Only SPCS1 has been tested */
1373 snd_ca0106_ptr_write(chip, SPCS1, 0,
1374 chip->spdif_bits[1] =
1375 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1376 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1377 SPCS_GENERATIONSTATUS | 0x00001200 |
1378 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1379 snd_ca0106_ptr_write(chip, SPCS2, 0,
1380 chip->spdif_bits[2] =
1381 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1382 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1383 SPCS_GENERATIONSTATUS | 0x00001200 |
1384 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1385 snd_ca0106_ptr_write(chip, SPCS3, 0,
1386 chip->spdif_bits[3] =
1387 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1388 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1389 SPCS_GENERATIONSTATUS | 0x00001200 |
1390 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1391
1392 snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
1393 snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
1394
1395 /* Write 0x8000 to AC97_REC_GAIN to mute it. */
1396 outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
1397 outw(0x8000, chip->port + AC97DATA);
1398#if 0
1399 snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
1400 snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
1401 snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
1402 snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
1403#endif
1404
1405 //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
1406 /* Analog or Digital output */
1407 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
James Courtier-Dutton8f55fbb2005-05-21 16:45:58 +02001408 snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 chip->spdif_enable = 0; /* Set digital SPDIF output off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
1411 //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
1412
1413 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
1414 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
1415 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
1416 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
1417 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
1418 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
1419 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
1420 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
1421 for(ch = 0; ch < 4; ch++) {
1422 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
1423 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
1424 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
1425 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
1426 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
1427 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
1428 }
James Courtier-Dutton7c157062006-12-10 00:00:38 +00001429 if (chip->details->i2c_adc == 1) {
1430 /* Select MIC, Line in, TAD in, AUX in */
1431 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1432 /* Default to CAPTURE_SOURCE to i2s in */
1433 chip->capture_source = 3;
1434 } else if (chip->details->ac97 == 1) {
1435 /* Default to AC97 in */
1436 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4);
1437 /* Default to CAPTURE_SOURCE to AC97 in */
1438 chip->capture_source = 4;
1439 } else {
1440 /* Select MIC, Line in, TAD in, AUX in */
1441 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1442 /* Default to Set CAPTURE_SOURCE to i2s in */
1443 chip->capture_source = 3;
1444 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +01001446 if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001447 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1448 outl(0x0, chip->port+GPIO);
1449 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
1450 outl(0x005f5301, chip->port+GPIO); /* Analog */
1451 } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1453 outl(0x0, chip->port+GPIO);
1454 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
James Courtier-Duttonc82bf822005-06-04 15:03:06 +02001455 outl(0x005f5301, chip->port+GPIO); /* Analog */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 } else {
1457 outl(0x0, chip->port+GPIO);
1458 outl(0x005f03a3, chip->port+GPIO); /* Analog */
1459 //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
1460 }
1461 snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
1462
1463 //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
1464 //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
1465 //outl(0x00000009, chip->port+HCFG);
1466 outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
1467
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001468 if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001469 int size, n;
1470
1471 size = ARRAY_SIZE(i2c_adc_init);
1472 //snd_printk("I2C:array size=0x%x\n", size);
1473 for (n=0; n < size; n++) {
1474 snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
1475 }
1476 for (n=0; n < 4; n++) {
1477 chip->i2c_capture_volume[n][0]= 0xcf;
1478 chip->i2c_capture_volume[n][1]= 0xcf;
1479 }
1480 chip->i2c_capture_source=2; /* Line in */
1481 //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001482 }
James Courtier-Duttona5875152005-12-20 22:30:49 +01001483 if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001484 int size, n;
1485
1486 size = ARRAY_SIZE(spi_dac_init);
1487 for (n=0; n < size; n++)
1488 snd_ca0106_spi_write(chip, spi_dac_init[n]);
James Courtier-Duttona5875152005-12-20 22:30:49 +01001489 }
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001490
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
1492 chip, &ops)) < 0) {
1493 snd_ca0106_free(chip);
1494 return err;
1495 }
1496 *rchip = chip;
1497 return 0;
1498}
1499
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001500
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001501static void ca0106_midi_interrupt_enable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001502{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001503 snd_ca0106_intr_enable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001504}
1505
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001506static void ca0106_midi_interrupt_disable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001507{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001508 snd_ca0106_intr_disable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001509}
1510
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001511static unsigned char ca0106_midi_read(struct snd_ca_midi *midi, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001512{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001513 return (unsigned char)snd_ca0106_ptr_read((struct snd_ca0106 *)(midi->dev_id),
1514 midi->port + idx, 0);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001515}
1516
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001517static void ca0106_midi_write(struct snd_ca_midi *midi, int data, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001518{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001519 snd_ca0106_ptr_write((struct snd_ca0106 *)(midi->dev_id), midi->port + idx, 0, data);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001520}
1521
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001522static struct snd_card *ca0106_dev_id_card(void *dev_id)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001523{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001524 return ((struct snd_ca0106 *)dev_id)->card;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001525}
1526
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001527static int ca0106_dev_id_port(void *dev_id)
1528{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001529 return ((struct snd_ca0106 *)dev_id)->port;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001530}
1531
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001532static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001533{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001534 struct snd_ca_midi *midi;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001535 char *name;
1536 int err;
1537
Takashi Iwai95a98262005-11-17 10:40:18 +01001538 if (channel == CA0106_MIDI_CHAN_B) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001539 name = "CA0106 MPU-401 (UART) B";
1540 midi = &chip->midi2;
1541 midi->tx_enable = INTE_MIDI_TX_B;
1542 midi->rx_enable = INTE_MIDI_RX_B;
1543 midi->ipr_tx = IPR_MIDI_TX_B;
1544 midi->ipr_rx = IPR_MIDI_RX_B;
1545 midi->port = MIDI_UART_B_DATA;
1546 } else {
1547 name = "CA0106 MPU-401 (UART)";
1548 midi = &chip->midi;
1549 midi->tx_enable = INTE_MIDI_TX_A;
1550 midi->rx_enable = INTE_MIDI_TX_B;
1551 midi->ipr_tx = IPR_MIDI_TX_A;
1552 midi->ipr_rx = IPR_MIDI_RX_A;
1553 midi->port = MIDI_UART_A_DATA;
1554 }
1555
1556 midi->reset = CA0106_MPU401_RESET;
1557 midi->enter_uart = CA0106_MPU401_ENTER_UART;
1558 midi->ack = CA0106_MPU401_ACK;
1559
1560 midi->input_avail = CA0106_MIDI_INPUT_AVAIL;
1561 midi->output_ready = CA0106_MIDI_OUTPUT_READY;
1562
1563 midi->channel = channel;
1564
1565 midi->interrupt_enable = ca0106_midi_interrupt_enable;
1566 midi->interrupt_disable = ca0106_midi_interrupt_disable;
1567
1568 midi->read = ca0106_midi_read;
1569 midi->write = ca0106_midi_write;
1570
1571 midi->get_dev_id_card = ca0106_dev_id_card;
1572 midi->get_dev_id_port = ca0106_dev_id_port;
1573
1574 midi->dev_id = chip;
1575
1576 if ((err = ca_midi_init(chip, midi, 0, name)) < 0)
1577 return err;
1578
1579 return 0;
1580}
1581
1582
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1584 const struct pci_device_id *pci_id)
1585{
1586 static int dev;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001587 struct snd_card *card;
1588 struct snd_ca0106 *chip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 int err;
1590
1591 if (dev >= SNDRV_CARDS)
1592 return -ENODEV;
1593 if (!enable[dev]) {
1594 dev++;
1595 return -ENOENT;
1596 }
1597
1598 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1599 if (card == NULL)
1600 return -ENOMEM;
1601
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001602 if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 snd_card_free(card);
1604 return err;
1605 }
1606
1607 if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
1608 snd_card_free(card);
1609 return err;
1610 }
1611 if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
1612 snd_card_free(card);
1613 return err;
1614 }
1615 if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
1616 snd_card_free(card);
1617 return err;
1618 }
1619 if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
1620 snd_card_free(card);
1621 return err;
1622 }
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001623 if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 if ((err = snd_ca0106_ac97(chip)) < 0) {
1625 snd_card_free(card);
1626 return err;
1627 }
1628 }
1629 if ((err = snd_ca0106_mixer(chip)) < 0) {
1630 snd_card_free(card);
1631 return err;
1632 }
1633
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001634 snd_printdd("ca0106: probe for MIDI channel A ...");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001635 if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
1636 snd_card_free(card);
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001637 snd_printdd(" failed, err=0x%x\n",err);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001638 return err;
1639 }
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001640 snd_printdd(" done.\n");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001641
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001642#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 snd_ca0106_proc_init(chip);
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001644#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
Takashi Iwaic6d6eee2007-02-08 14:50:31 +01001646 snd_card_set_dev(card, &pci->dev);
1647
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 if ((err = snd_card_register(card)) < 0) {
1649 snd_card_free(card);
1650 return err;
1651 }
1652
1653 pci_set_drvdata(pci, card);
1654 dev++;
1655 return 0;
1656}
1657
1658static void __devexit snd_ca0106_remove(struct pci_dev *pci)
1659{
1660 snd_card_free(pci_get_drvdata(pci));
1661 pci_set_drvdata(pci, NULL);
1662}
1663
1664// PCI IDs
Takashi Iwaif40b6892006-07-05 16:51:05 +02001665static struct pci_device_id snd_ca0106_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
1667 { 0, }
1668};
1669MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
1670
1671// pci_driver definition
1672static struct pci_driver driver = {
1673 .name = "CA0106",
1674 .id_table = snd_ca0106_ids,
1675 .probe = snd_ca0106_probe,
1676 .remove = __devexit_p(snd_ca0106_remove),
1677};
1678
1679// initialization of the module
1680static int __init alsa_card_ca0106_init(void)
1681{
Takashi Iwai95a98262005-11-17 10:40:18 +01001682 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683}
1684
1685// clean up the module
1686static void __exit alsa_card_ca0106_exit(void)
1687{
1688 pci_unregister_driver(&driver);
1689}
1690
1691module_init(alsa_card_ca0106_init)
1692module_exit(alsa_card_ca0106_exit)