blob: ea6712b63c9f7a268eba7b72ef989d58fbda1056 [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-Dutton1baa7052005-05-21 22:35:58 +0200171 /* AudigyLS[SB0310] */
172 { .serial = 0x10021102,
173 .name = "AudigyLS [SB0310]",
174 .ac97 = 1 } ,
175 /* Unknown AudigyLS that also says SB0310 on it */
176 { .serial = 0x10051102,
177 .name = "AudigyLS [SB0310b]",
178 .ac97 = 1 } ,
179 /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
180 { .serial = 0x10061102,
181 .name = "Live! 7.1 24bit [SB0410]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200182 .gpio_type = 1,
183 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200184 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
185 { .serial = 0x10071102,
186 .name = "Live! 7.1 24bit [SB0413]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200187 .gpio_type = 1,
188 .i2c_adc = 1 } ,
James Courtier-Duttona5875152005-12-20 22:30:49 +0100189 /* New Audigy SE. Has a different DAC. */
190 /* SB0570:
191 * CTRL:CA0106-DAT
James Courtier-Dutton58398892006-06-10 09:16:49 +0100192 * ADC: WM8775EDS
193 * DAC: WM8768GEDS
James Courtier-Duttona5875152005-12-20 22:30:49 +0100194 */
195 { .serial = 0x100a1102,
196 .name = "Audigy SE [SB0570]",
197 .gpio_type = 1,
198 .i2c_adc = 1,
199 .spi_dac = 1 } ,
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000200 /* New Audigy LS. Has a different DAC. */
201 /* SB0570:
202 * CTRL:CA0106-DAT
203 * ADC: WM8775EDS
204 * DAC: WM8768GEDS
205 */
206 { .serial = 0x10111102,
James Courtier-Duttond5f6a382006-11-25 19:50:11 +0000207 .name = "Audigy SE OEM [SB0570a]",
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000208 .gpio_type = 1,
209 .i2c_adc = 1,
210 .spi_dac = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200211 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100212 /* SB0438
213 * CTRL:CA0106-DAT
214 * ADC: WM8775SEDS
215 * DAC: CS4382-KQZ
216 */
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200217 { .serial = 0x10091462,
218 .name = "MSI K8N Diamond MB [SB0438]",
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100219 .gpio_type = 2,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200220 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100221 /* Shuttle XPC SD31P which has an onboard Creative Labs
222 * Sound Blaster Live! 24-bit EAX
James Courtier-Dutton1b059622005-08-12 23:50:13 +0200223 * high-definition 7.1 audio processor".
224 * Added using info from andrewvegan in alsa bug #1298
225 */
226 { .serial = 0x30381297,
227 .name = "Shuttle XPC SD31P [SD31P]",
228 .gpio_type = 1,
229 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100230 /* Shuttle XPC SD11G5 which has an onboard Creative Labs
231 * Sound Blaster Live! 24-bit EAX
232 * high-definition 7.1 audio processor".
233 * Fixes ALSA bug#1600
234 */
235 { .serial = 0x30411297,
236 .name = "Shuttle XPC SD11G5 [SD11G5]",
237 .gpio_type = 1,
238 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200239 { .serial = 0,
240 .name = "AudigyLS [Unknown]" }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241};
242
243/* hardware definition */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100244static struct snd_pcm_hardware snd_ca0106_playback_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 .info = (SNDRV_PCM_INFO_MMAP |
246 SNDRV_PCM_INFO_INTERLEAVED |
247 SNDRV_PCM_INFO_BLOCK_TRANSFER |
248 SNDRV_PCM_INFO_MMAP_VALID),
249 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100250 .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
251 SNDRV_PCM_RATE_192000),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 .rate_min = 48000,
253 .rate_max = 192000,
254 .channels_min = 2, //1,
255 .channels_max = 2, //6,
256 .buffer_bytes_max = ((65536 - 64) * 8),
257 .period_bytes_min = 64,
258 .period_bytes_max = (65536 - 64),
259 .periods_min = 2,
260 .periods_max = 8,
261 .fifo_size = 0,
262};
263
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100264static struct snd_pcm_hardware snd_ca0106_capture_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 .info = (SNDRV_PCM_INFO_MMAP |
266 SNDRV_PCM_INFO_INTERLEAVED |
267 SNDRV_PCM_INFO_BLOCK_TRANSFER |
268 SNDRV_PCM_INFO_MMAP_VALID),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200269 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100270 .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
271 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200272 .rate_min = 44100,
273 .rate_max = 192000,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 .channels_min = 2,
275 .channels_max = 2,
276 .buffer_bytes_max = ((65536 - 64) * 8),
277 .period_bytes_min = 64,
278 .period_bytes_max = (65536 - 64),
279 .periods_min = 2,
280 .periods_max = 2,
281 .fifo_size = 0,
282};
283
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100284unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 unsigned int reg,
286 unsigned int chn)
287{
288 unsigned long flags;
289 unsigned int regptr, val;
290
291 regptr = (reg << 16) | chn;
292
293 spin_lock_irqsave(&emu->emu_lock, flags);
294 outl(regptr, emu->port + PTR);
295 val = inl(emu->port + DATA);
296 spin_unlock_irqrestore(&emu->emu_lock, flags);
297 return val;
298}
299
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100300void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 unsigned int reg,
302 unsigned int chn,
303 unsigned int data)
304{
305 unsigned int regptr;
306 unsigned long flags;
307
308 regptr = (reg << 16) | chn;
309
310 spin_lock_irqsave(&emu->emu_lock, flags);
311 outl(regptr, emu->port + PTR);
312 outl(data, emu->port + DATA);
313 spin_unlock_irqrestore(&emu->emu_lock, flags);
314}
315
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100316int snd_ca0106_spi_write(struct snd_ca0106 * emu,
317 unsigned int data)
James Courtier-Duttona5875152005-12-20 22:30:49 +0100318{
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100319 unsigned int reset, set;
320 unsigned int reg, tmp;
321 int n, result;
322 reg = SPI;
323 if (data > 0xffff) /* Only 16bit values allowed */
324 return 1;
325 tmp = snd_ca0106_ptr_read(emu, reg, 0);
326 reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
327 set = reset | 0x10000; /* Set xxx1xxxx */
328 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
329 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* write post */
330 snd_ca0106_ptr_write(emu, reg, 0, set | data);
331 result = 1;
332 /* Wait for status bit to return to 0 */
333 for (n = 0; n < 100; n++) {
334 udelay(10);
335 tmp = snd_ca0106_ptr_read(emu, reg, 0);
336 if (!(tmp & 0x10000)) {
337 result = 0;
338 break;
339 }
340 }
341 if (result) /* Timed out */
342 return 1;
343 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
344 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* Write post */
James Courtier-Duttona5875152005-12-20 22:30:49 +0100345 return 0;
346}
347
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100348/* The ADC does not support i2c read, so only write is implemented */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100349int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200350 u32 reg,
351 u32 value)
352{
353 u32 tmp;
Takashi Iwai95a98262005-11-17 10:40:18 +0100354 int timeout = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200355 int status;
356 int retry;
Takashi Iwai95a98262005-11-17 10:40:18 +0100357 if ((reg > 0x7f) || (value > 0x1ff)) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200358 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200359 return -EINVAL;
360 }
361
362 tmp = reg << 25 | value << 16;
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100363 // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
James Courtier-Dutton8fabab12005-05-28 16:35:49 +0200364 /* Not sure what this I2C channel controls. */
365 /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
366
367 /* This controls the I2C connected to the WM8775 ADC Codec */
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200368 snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
369
Takashi Iwai95a98262005-11-17 10:40:18 +0100370 for (retry = 0; retry < 10; retry++) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200371 /* Send the data to i2c */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100372 //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
373 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
374 tmp = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200375 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
376 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
377
378 /* Wait till the transaction ends */
Takashi Iwai95a98262005-11-17 10:40:18 +0100379 while (1) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200380 status = snd_ca0106_ptr_read(emu, I2C_A, 0);
381 //snd_printk("I2C:status=0x%x\n", status);
382 timeout++;
Takashi Iwai95a98262005-11-17 10:40:18 +0100383 if ((status & I2C_A_ADC_START) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200384 break;
385
Takashi Iwai95a98262005-11-17 10:40:18 +0100386 if (timeout > 1000)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200387 break;
388 }
389 //Read back and see if the transaction is successful
Takashi Iwai95a98262005-11-17 10:40:18 +0100390 if ((status & I2C_A_ADC_ABORT) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200391 break;
392 }
393
Takashi Iwai95a98262005-11-17 10:40:18 +0100394 if (retry == 10) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200395 snd_printk(KERN_ERR "Writing to ADC failed!\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200396 return -EINVAL;
397 }
398
399 return 0;
400}
401
402
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100403static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404{
405 unsigned long flags;
406 unsigned int enable;
407
408 spin_lock_irqsave(&emu->emu_lock, flags);
409 enable = inl(emu->port + INTE) | intrenb;
410 outl(enable, emu->port + INTE);
411 spin_unlock_irqrestore(&emu->emu_lock, flags);
412}
413
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100414static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +0200415{
416 unsigned long flags;
417 unsigned int enable;
418
419 spin_lock_irqsave(&emu->emu_lock, flags);
420 enable = inl(emu->port + INTE) & ~intrenb;
421 outl(enable, emu->port + INTE);
422 spin_unlock_irqrestore(&emu->emu_lock, flags);
423}
424
425
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100426static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427{
Jesper Juhl4d572772005-05-30 17:30:32 +0200428 kfree(runtime->private_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429}
430
431/* open_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100432static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
433 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100435 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
436 struct snd_ca0106_channel *channel = &(chip->playback_channels[channel_id]);
437 struct snd_ca0106_pcm *epcm;
438 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 int err;
440
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200441 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
443 if (epcm == NULL)
444 return -ENOMEM;
445 epcm->emu = chip;
446 epcm->substream = substream;
447 epcm->channel_id=channel_id;
448
449 runtime->private_data = epcm;
450 runtime->private_free = snd_ca0106_pcm_free_substream;
451
452 runtime->hw = snd_ca0106_playback_hw;
453
454 channel->emu = chip;
455 channel->number = channel_id;
456
Takashi Iwai95a98262005-11-17 10:40:18 +0100457 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
459 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwai95a98262005-11-17 10:40:18 +0100460 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
462 return err;
463 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
464 return err;
465 return 0;
466}
467
468/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100469static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100471 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
472 struct snd_pcm_runtime *runtime = substream->runtime;
473 struct snd_ca0106_pcm *epcm = runtime->private_data;
474 chip->playback_channels[epcm->channel_id].use = 0;
475 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 return 0;
477}
478
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100479static int snd_ca0106_pcm_open_playback_front(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
481 return snd_ca0106_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
482}
483
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100484static int snd_ca0106_pcm_open_playback_center_lfe(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485{
486 return snd_ca0106_pcm_open_playback_channel(substream, PCM_CENTER_LFE_CHANNEL);
487}
488
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100489static int snd_ca0106_pcm_open_playback_unknown(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
491 return snd_ca0106_pcm_open_playback_channel(substream, PCM_UNKNOWN_CHANNEL);
492}
493
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100494static int snd_ca0106_pcm_open_playback_rear(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495{
496 return snd_ca0106_pcm_open_playback_channel(substream, PCM_REAR_CHANNEL);
497}
498
499/* open_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100500static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substream,
501 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100503 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
504 struct snd_ca0106_channel *channel = &(chip->capture_channels[channel_id]);
505 struct snd_ca0106_pcm *epcm;
506 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 int err;
508
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200509 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 if (epcm == NULL) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200511 snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 return -ENOMEM;
513 }
514 epcm->emu = chip;
515 epcm->substream = substream;
516 epcm->channel_id=channel_id;
517
518 runtime->private_data = epcm;
519 runtime->private_free = snd_ca0106_pcm_free_substream;
520
521 runtime->hw = snd_ca0106_capture_hw;
522
523 channel->emu = chip;
524 channel->number = channel_id;
525
Takashi Iwai95a98262005-11-17 10:40:18 +0100526 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
528 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100529 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
531 return err;
532 //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
533 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
534 return err;
535 return 0;
536}
537
538/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100539static int snd_ca0106_pcm_close_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100541 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
542 struct snd_pcm_runtime *runtime = substream->runtime;
543 struct snd_ca0106_pcm *epcm = runtime->private_data;
544 chip->capture_channels[epcm->channel_id].use = 0;
545 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 return 0;
547}
548
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100549static int snd_ca0106_pcm_open_0_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550{
551 return snd_ca0106_pcm_open_capture_channel(substream, 0);
552}
553
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100554static int snd_ca0106_pcm_open_1_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
556 return snd_ca0106_pcm_open_capture_channel(substream, 1);
557}
558
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100559static int snd_ca0106_pcm_open_2_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
561 return snd_ca0106_pcm_open_capture_channel(substream, 2);
562}
563
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100564static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
566 return snd_ca0106_pcm_open_capture_channel(substream, 3);
567}
568
569/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100570static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream,
571 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572{
573 return snd_pcm_lib_malloc_pages(substream,
574 params_buffer_bytes(hw_params));
575}
576
577/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100578static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579{
580 return snd_pcm_lib_free_pages(substream);
581}
582
583/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100584static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream,
585 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586{
587 return snd_pcm_lib_malloc_pages(substream,
588 params_buffer_bytes(hw_params));
589}
590
591/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100592static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 return snd_pcm_lib_free_pages(substream);
595}
596
597/* prepare playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100598static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100600 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
601 struct snd_pcm_runtime *runtime = substream->runtime;
602 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 int channel = epcm->channel_id;
604 u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
605 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
606 u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
607 u32 hcfg_set = 0x00000000;
608 u32 hcfg;
609 u32 reg40_mask = 0x30000 << (channel<<1);
610 u32 reg40_set = 0;
611 u32 reg40;
612 /* FIXME: Depending on mixer selection of SPDIF out or not, select the spdif rate or the DAC rate. */
613 u32 reg71_mask = 0x03030000 ; /* Global. Set SPDIF rate. We only support 44100 to spdif, not to DAC. */
614 u32 reg71_set = 0;
615 u32 reg71;
616 int i;
617
618 //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));
619 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
620 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
621 /* Rate can be set per channel. */
622 /* reg40 control host to fifo */
623 /* reg71 controls DAC rate. */
624 switch (runtime->rate) {
625 case 44100:
626 reg40_set = 0x10000 << (channel<<1);
627 reg71_set = 0x01010000;
628 break;
629 case 48000:
630 reg40_set = 0;
631 reg71_set = 0;
632 break;
633 case 96000:
634 reg40_set = 0x20000 << (channel<<1);
635 reg71_set = 0x02020000;
636 break;
637 case 192000:
638 reg40_set = 0x30000 << (channel<<1);
639 reg71_set = 0x03030000;
640 break;
641 default:
642 reg40_set = 0;
643 reg71_set = 0;
644 break;
645 }
646 /* Format is a global setting */
647 /* FIXME: Only let the first channel accessed set this. */
648 switch (runtime->format) {
649 case SNDRV_PCM_FORMAT_S16_LE:
650 hcfg_set = 0;
651 break;
652 case SNDRV_PCM_FORMAT_S32_LE:
653 hcfg_set = HCFG_PLAYBACK_S32_LE;
654 break;
655 default:
656 hcfg_set = 0;
657 break;
658 }
659 hcfg = inl(emu->port + HCFG) ;
660 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
661 outl(hcfg, emu->port + HCFG);
662 reg40 = snd_ca0106_ptr_read(emu, 0x40, 0);
663 reg40 = (reg40 & ~reg40_mask) | reg40_set;
664 snd_ca0106_ptr_write(emu, 0x40, 0, reg40);
665 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
666 reg71 = (reg71 & ~reg71_mask) | reg71_set;
667 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
668
669 /* FIXME: Check emu->buffer.size before actually writing to it. */
670 for(i=0; i < runtime->periods; i++) {
Takashi Iwai95a98262005-11-17 10:40:18 +0100671 table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
672 table_base[i*2+1] = period_size_bytes << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 }
674
675 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
676 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
677 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
678 snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
679 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
680 /* FIXME test what 0 bytes does. */
681 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
682 snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
683 snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
684 snd_ca0106_ptr_write(emu, 0x08, channel, 0);
685 snd_ca0106_ptr_write(emu, PLAYBACK_MUTE, 0x0, 0x0); /* Unmute output */
686#if 0
687 snd_ca0106_ptr_write(emu, SPCS0, 0,
688 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
689 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
690 SPCS_GENERATIONSTATUS | 0x00001200 |
691 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
692 }
693#endif
694
695 return 0;
696}
697
698/* prepare capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100699static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100701 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
702 struct snd_pcm_runtime *runtime = substream->runtime;
703 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 int channel = epcm->channel_id;
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200705 u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
706 u32 hcfg_set = 0x00000000;
707 u32 hcfg;
708 u32 over_sampling=0x2;
709 u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
710 u32 reg71_set = 0;
711 u32 reg71;
712
713 //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));
714 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
715 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
716 /* reg71 controls ADC rate. */
717 switch (runtime->rate) {
718 case 44100:
719 reg71_set = 0x00004000;
720 break;
721 case 48000:
722 reg71_set = 0;
723 break;
724 case 96000:
725 reg71_set = 0x00008000;
726 over_sampling=0xa;
727 break;
728 case 192000:
729 reg71_set = 0x0000c000;
730 over_sampling=0xa;
731 break;
732 default:
733 reg71_set = 0;
734 break;
735 }
736 /* Format is a global setting */
737 /* FIXME: Only let the first channel accessed set this. */
738 switch (runtime->format) {
739 case SNDRV_PCM_FORMAT_S16_LE:
740 hcfg_set = 0;
741 break;
742 case SNDRV_PCM_FORMAT_S32_LE:
743 hcfg_set = HCFG_CAPTURE_S32_LE;
744 break;
745 default:
746 hcfg_set = 0;
747 break;
748 }
749 hcfg = inl(emu->port + HCFG) ;
750 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
751 outl(hcfg, emu->port + HCFG);
752 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
753 reg71 = (reg71 & ~reg71_mask) | reg71_set;
754 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
755 if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
756 snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
757 }
758
759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 //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));
761 snd_ca0106_ptr_write(emu, 0x13, channel, 0);
762 snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
763 snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
764 snd_ca0106_ptr_write(emu, CAPTURE_POINTER, channel, 0);
765
766 return 0;
767}
768
769/* trigger_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100770static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 int cmd)
772{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100773 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
774 struct snd_pcm_runtime *runtime;
775 struct snd_ca0106_pcm *epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 int channel;
777 int result = 0;
778 struct list_head *pos;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100779 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 u32 basic = 0;
781 u32 extended = 0;
782 int running=0;
783
784 switch (cmd) {
785 case SNDRV_PCM_TRIGGER_START:
786 running=1;
787 break;
788 case SNDRV_PCM_TRIGGER_STOP:
789 default:
790 running=0;
791 break;
792 }
793 snd_pcm_group_for_each(pos, substream) {
794 s = snd_pcm_group_substream_entry(pos);
795 runtime = s->runtime;
796 epcm = runtime->private_data;
797 channel = epcm->channel_id;
798 //snd_printk("channel=%d\n",channel);
799 epcm->running = running;
800 basic |= (0x1<<channel);
801 extended |= (0x10<<channel);
802 snd_pcm_trigger_done(s, substream);
803 }
804 //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
805
806 switch (cmd) {
807 case SNDRV_PCM_TRIGGER_START:
808 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
809 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
810 break;
811 case SNDRV_PCM_TRIGGER_STOP:
812 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
813 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
814 break;
815 default:
816 result = -EINVAL;
817 break;
818 }
819 return result;
820}
821
822/* trigger_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100823static int snd_ca0106_pcm_trigger_capture(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 int cmd)
825{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100826 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
827 struct snd_pcm_runtime *runtime = substream->runtime;
828 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 int channel = epcm->channel_id;
830 int result = 0;
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) | (0x110000<<channel));
835 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
836 epcm->running = 1;
837 break;
838 case SNDRV_PCM_TRIGGER_STOP:
839 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
840 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
841 epcm->running = 0;
842 break;
843 default:
844 result = -EINVAL;
845 break;
846 }
847 return result;
848}
849
850/* pointer_playback callback */
851static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100852snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100854 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
855 struct snd_pcm_runtime *runtime = substream->runtime;
856 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
858 int channel = epcm->channel_id;
859
860 if (!epcm->running)
861 return 0;
862
863 ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
864 ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
865 ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
866 if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
867 ptr2 = bytes_to_frames(runtime, ptr1);
868 ptr2+= (ptr4 >> 3) * runtime->period_size;
869 ptr=ptr2;
870 if (ptr >= runtime->buffer_size)
871 ptr -= runtime->buffer_size;
872 //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);
873
874 return ptr;
875}
876
877/* pointer_capture callback */
878static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100879snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100881 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
882 struct snd_pcm_runtime *runtime = substream->runtime;
883 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
885 int channel = channel=epcm->channel_id;
886
887 if (!epcm->running)
888 return 0;
889
890 ptr1 = snd_ca0106_ptr_read(emu, CAPTURE_POINTER, channel);
891 ptr2 = bytes_to_frames(runtime, ptr1);
892 ptr=ptr2;
893 if (ptr >= runtime->buffer_size)
894 ptr -= runtime->buffer_size;
895 //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);
896
897 return ptr;
898}
899
900/* operators */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100901static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 .open = snd_ca0106_pcm_open_playback_front,
903 .close = snd_ca0106_pcm_close_playback,
904 .ioctl = snd_pcm_lib_ioctl,
905 .hw_params = snd_ca0106_pcm_hw_params_playback,
906 .hw_free = snd_ca0106_pcm_hw_free_playback,
907 .prepare = snd_ca0106_pcm_prepare_playback,
908 .trigger = snd_ca0106_pcm_trigger_playback,
909 .pointer = snd_ca0106_pcm_pointer_playback,
910};
911
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100912static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 .open = snd_ca0106_pcm_open_0_capture,
914 .close = snd_ca0106_pcm_close_capture,
915 .ioctl = snd_pcm_lib_ioctl,
916 .hw_params = snd_ca0106_pcm_hw_params_capture,
917 .hw_free = snd_ca0106_pcm_hw_free_capture,
918 .prepare = snd_ca0106_pcm_prepare_capture,
919 .trigger = snd_ca0106_pcm_trigger_capture,
920 .pointer = snd_ca0106_pcm_pointer_capture,
921};
922
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100923static struct snd_pcm_ops snd_ca0106_capture_1_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 .open = snd_ca0106_pcm_open_1_capture,
925 .close = snd_ca0106_pcm_close_capture,
926 .ioctl = snd_pcm_lib_ioctl,
927 .hw_params = snd_ca0106_pcm_hw_params_capture,
928 .hw_free = snd_ca0106_pcm_hw_free_capture,
929 .prepare = snd_ca0106_pcm_prepare_capture,
930 .trigger = snd_ca0106_pcm_trigger_capture,
931 .pointer = snd_ca0106_pcm_pointer_capture,
932};
933
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100934static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 .open = snd_ca0106_pcm_open_2_capture,
936 .close = snd_ca0106_pcm_close_capture,
937 .ioctl = snd_pcm_lib_ioctl,
938 .hw_params = snd_ca0106_pcm_hw_params_capture,
939 .hw_free = snd_ca0106_pcm_hw_free_capture,
940 .prepare = snd_ca0106_pcm_prepare_capture,
941 .trigger = snd_ca0106_pcm_trigger_capture,
942 .pointer = snd_ca0106_pcm_pointer_capture,
943};
944
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100945static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 .open = snd_ca0106_pcm_open_3_capture,
947 .close = snd_ca0106_pcm_close_capture,
948 .ioctl = snd_pcm_lib_ioctl,
949 .hw_params = snd_ca0106_pcm_hw_params_capture,
950 .hw_free = snd_ca0106_pcm_hw_free_capture,
951 .prepare = snd_ca0106_pcm_prepare_capture,
952 .trigger = snd_ca0106_pcm_trigger_capture,
953 .pointer = snd_ca0106_pcm_pointer_capture,
954};
955
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100956static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 .open = snd_ca0106_pcm_open_playback_center_lfe,
958 .close = snd_ca0106_pcm_close_playback,
959 .ioctl = snd_pcm_lib_ioctl,
960 .hw_params = snd_ca0106_pcm_hw_params_playback,
961 .hw_free = snd_ca0106_pcm_hw_free_playback,
962 .prepare = snd_ca0106_pcm_prepare_playback,
963 .trigger = snd_ca0106_pcm_trigger_playback,
964 .pointer = snd_ca0106_pcm_pointer_playback,
965};
966
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100967static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 .open = snd_ca0106_pcm_open_playback_unknown,
969 .close = snd_ca0106_pcm_close_playback,
970 .ioctl = snd_pcm_lib_ioctl,
971 .hw_params = snd_ca0106_pcm_hw_params_playback,
972 .hw_free = snd_ca0106_pcm_hw_free_playback,
973 .prepare = snd_ca0106_pcm_prepare_playback,
974 .trigger = snd_ca0106_pcm_trigger_playback,
975 .pointer = snd_ca0106_pcm_pointer_playback,
976};
977
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100978static struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 .open = snd_ca0106_pcm_open_playback_rear,
980 .close = snd_ca0106_pcm_close_playback,
981 .ioctl = snd_pcm_lib_ioctl,
982 .hw_params = snd_ca0106_pcm_hw_params_playback,
983 .hw_free = snd_ca0106_pcm_hw_free_playback,
984 .prepare = snd_ca0106_pcm_prepare_playback,
985 .trigger = snd_ca0106_pcm_trigger_playback,
986 .pointer = snd_ca0106_pcm_pointer_playback,
987};
988
989
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100990static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 unsigned short reg)
992{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100993 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 unsigned long flags;
995 unsigned short val;
996
997 spin_lock_irqsave(&emu->emu_lock, flags);
998 outb(reg, emu->port + AC97ADDRESS);
999 val = inw(emu->port + AC97DATA);
1000 spin_unlock_irqrestore(&emu->emu_lock, flags);
1001 return val;
1002}
1003
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001004static void snd_ca0106_ac97_write(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 unsigned short reg, unsigned short val)
1006{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001007 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 unsigned long flags;
1009
1010 spin_lock_irqsave(&emu->emu_lock, flags);
1011 outb(reg, emu->port + AC97ADDRESS);
1012 outw(val, emu->port + AC97DATA);
1013 spin_unlock_irqrestore(&emu->emu_lock, flags);
1014}
1015
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001016static int snd_ca0106_ac97(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001018 struct snd_ac97_bus *pbus;
1019 struct snd_ac97_template ac97;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 int err;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001021 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 .write = snd_ca0106_ac97_write,
1023 .read = snd_ca0106_ac97_read,
1024 };
1025
1026 if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
1027 return err;
1028 pbus->no_vra = 1; /* we don't need VRA */
1029
1030 memset(&ac97, 0, sizeof(ac97));
1031 ac97.private_data = chip;
Takashi Iwai36c4dc42005-03-24 17:48:30 +01001032 ac97.scaps = AC97_SCAP_NO_SPDIF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
1034}
1035
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001036static int snd_ca0106_free(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037{
1038 if (chip->res_port != NULL) { /* avoid access to already used hardware */
1039 // disable interrupts
1040 snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
1041 outl(0, chip->port + INTE);
1042 snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
1043 udelay(1000);
1044 // disable audio
1045 //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
1046 outl(0, chip->port + HCFG);
1047 /* FIXME: We need to stop and DMA transfers here.
1048 * But as I am not sure how yet, we cannot from the dma pages.
1049 * So we can fix: snd-malloc: Memory leak? pages not freed = 8
1050 */
1051 }
1052 // release the data
1053#if 1
1054 if (chip->buffer.area)
1055 snd_dma_free_pages(&chip->buffer);
1056#endif
1057
1058 // release the i/o port
Takashi Iwaib1d57762005-10-10 11:56:31 +02001059 release_and_free_resource(chip->res_port);
1060
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 // release the irq
1062 if (chip->irq >= 0)
Takashi Iwai437a5a42006-11-21 12:14:23 +01001063 free_irq(chip->irq, chip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 pci_disable_device(chip->pci);
1065 kfree(chip);
1066 return 0;
1067}
1068
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001069static int snd_ca0106_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001071 struct snd_ca0106 *chip = device->device_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 return snd_ca0106_free(chip);
1073}
1074
David Howells7d12e782006-10-05 14:55:46 +01001075static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076{
1077 unsigned int status;
1078
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001079 struct snd_ca0106 *chip = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 int i;
1081 int mask;
1082 unsigned int stat76;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001083 struct snd_ca0106_channel *pchannel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 status = inl(chip->port + IPR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 if (! status)
1087 return IRQ_NONE;
1088
1089 stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0);
1090 //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76);
1091 //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0));
1092 mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
1093 for(i = 0; i < 4; i++) {
1094 pchannel = &(chip->playback_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001095 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096/* FIXME: Select the correct substream for period elapsed */
1097 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001098 snd_pcm_period_elapsed(pchannel->epcm->substream);
1099 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
1101 }
1102 //printk(KERN_INFO "channel=%p\n",pchannel);
1103 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1104 mask <<= 1;
1105 }
1106 mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */
1107 for(i = 0; i < 4; i++) {
1108 pchannel = &(chip->capture_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001109 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110/* FIXME: Select the correct substream for period elapsed */
1111 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001112 snd_pcm_period_elapsed(pchannel->epcm->substream);
1113 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 }
1115 }
1116 //printk(KERN_INFO "channel=%p\n",pchannel);
1117 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1118 mask <<= 1;
1119 }
1120
1121 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001122
1123 if (chip->midi.dev_id &&
Takashi Iwai95a98262005-11-17 10:40:18 +01001124 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001125 if (chip->midi.interrupt)
1126 chip->midi.interrupt(&chip->midi, status);
1127 else
1128 chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable);
1129 }
1130
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 // acknowledge the interrupt if necessary
1132 outl(status, chip->port+IPR);
1133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return IRQ_HANDLED;
1135}
1136
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001137static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001139 struct snd_pcm *pcm;
1140 struct snd_pcm_substream *substream;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 int err;
1142
1143 if (rpcm)
1144 *rpcm = NULL;
1145 if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
1146 return err;
1147
1148 pcm->private_data = emu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
1150 switch (device) {
1151 case 0:
1152 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops);
1153 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops);
1154 break;
1155 case 1:
1156 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops);
1157 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops);
1158 break;
1159 case 2:
1160 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops);
1161 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops);
1162 break;
1163 case 3:
1164 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops);
1165 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops);
1166 break;
1167 }
1168
1169 pcm->info_flags = 0;
1170 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
1171 strcpy(pcm->name, "CA0106");
1172 emu->pcm = pcm;
1173
1174 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1175 substream;
1176 substream = substream->next) {
1177 if ((err = snd_pcm_lib_preallocate_pages(substream,
1178 SNDRV_DMA_TYPE_DEV,
1179 snd_dma_pci_data(emu->pci),
1180 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
1181 return err;
1182 }
1183
1184 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1185 substream;
1186 substream = substream->next) {
1187 if ((err = snd_pcm_lib_preallocate_pages(substream,
1188 SNDRV_DMA_TYPE_DEV,
1189 snd_dma_pci_data(emu->pci),
1190 64*1024, 64*1024)) < 0)
1191 return err;
1192 }
1193
1194 if (rpcm)
1195 *rpcm = pcm;
1196
1197 return 0;
1198}
1199
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001200static unsigned int spi_dac_init[] = {
1201 0x00ff,
1202 0x02ff,
1203 0x0400,
1204 0x0520,
James Courtier-Dutton58398892006-06-10 09:16:49 +01001205 0x0620, /* Set 24 bit. Was 0x0600 */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001206 0x08ff,
1207 0x0aff,
1208 0x0cff,
1209 0x0eff,
1210 0x10ff,
1211 0x1200,
1212 0x1400,
1213 0x1480,
1214 0x1800,
1215 0x1aff,
1216 0x1cff,
1217 0x1e00,
1218 0x0530,
1219 0x0602,
1220 0x0622,
1221 0x1400,
1222};
1223
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001224static unsigned int i2c_adc_init[][2] = {
1225 { 0x17, 0x00 }, /* Reset */
1226 { 0x07, 0x00 }, /* Timeout */
1227 { 0x0b, 0x22 }, /* Interface control */
1228 { 0x0c, 0x22 }, /* Master mode control */
1229 { 0x0d, 0x08 }, /* Powerdown control */
1230 { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
1231 { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */
1232 { 0x10, 0x7b }, /* ALC Control 1 */
1233 { 0x11, 0x00 }, /* ALC Control 2 */
1234 { 0x12, 0x32 }, /* ALC Control 3 */
1235 { 0x13, 0x00 }, /* Noise gate control */
1236 { 0x14, 0xa6 }, /* Limiter control */
1237 { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
1238};
1239
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001240static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 struct pci_dev *pci,
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001242 struct snd_ca0106 **rchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001244 struct snd_ca0106 *chip;
1245 struct snd_ca0106_details *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 int err;
1247 int ch;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001248 static struct snd_device_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 .dev_free = snd_ca0106_dev_free,
1250 };
1251
1252 *rchip = NULL;
1253
1254 if ((err = pci_enable_device(pci)) < 0)
1255 return err;
Tobias Klauser299676b2005-05-29 15:21:02 +02001256 if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
1257 pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 printk(KERN_ERR "error to set 32bit mask DMA\n");
1259 pci_disable_device(pci);
1260 return -ENXIO;
1261 }
1262
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001263 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 if (chip == NULL) {
1265 pci_disable_device(pci);
1266 return -ENOMEM;
1267 }
1268
1269 chip->card = card;
1270 chip->pci = pci;
1271 chip->irq = -1;
1272
1273 spin_lock_init(&chip->emu_lock);
1274
1275 chip->port = pci_resource_start(pci, 0);
1276 if ((chip->res_port = request_region(chip->port, 0x20,
1277 "snd_ca0106")) == NULL) {
1278 snd_ca0106_free(chip);
1279 printk(KERN_ERR "cannot allocate the port\n");
1280 return -EBUSY;
1281 }
1282
1283 if (request_irq(pci->irq, snd_ca0106_interrupt,
Takashi Iwai437a5a42006-11-21 12:14:23 +01001284 IRQF_SHARED, "snd_ca0106", chip)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 snd_ca0106_free(chip);
1286 printk(KERN_ERR "cannot grab irq\n");
1287 return -EBUSY;
1288 }
1289 chip->irq = pci->irq;
1290
1291 /* This stores the periods table. */
1292 if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
1293 snd_ca0106_free(chip);
1294 return -ENOMEM;
1295 }
1296
1297 pci_set_master(pci);
1298 /* read revision & serial */
Takashi Iwai01f681d2006-11-16 15:39:07 +01001299 pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
1301 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
1302#if 1
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001303 printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 chip->revision, chip->serial);
1305#endif
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001306 strcpy(card->driver, "CA0106");
1307 strcpy(card->shortname, "CA0106");
1308
Takashi Iwai95a98262005-11-17 10:40:18 +01001309 for (c = ca0106_chip_details; c->serial; c++) {
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001310 if (subsystem[dev]) {
1311 if (c->serial == subsystem[dev])
1312 break;
1313 } else if (c->serial == chip->serial)
Takashi Iwai95a98262005-11-17 10:40:18 +01001314 break;
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001315 }
1316 chip->details = c;
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001317 if (subsystem[dev]) {
James Courtier-Duttond5f6a382006-11-25 19:50:11 +00001318 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 +00001319 c->name, chip->serial, subsystem[dev]);
1320 }
1321
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001322 sprintf(card->longname, "%s at 0x%lx irq %i",
1323 c->name, chip->port, chip->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
1325 outl(0, chip->port + INTE);
1326
1327 /*
1328 * Init to 0x02109204 :
1329 * Clock accuracy = 0 (1000ppm)
1330 * Sample Rate = 2 (48kHz)
1331 * Audio Channel = 1 (Left of 2)
1332 * Source Number = 0 (Unspecified)
1333 * Generation Status = 1 (Original for Cat Code 12)
1334 * Cat Code = 12 (Digital Signal Mixer)
1335 * Mode = 0 (Mode 0)
1336 * Emphasis = 0 (None)
1337 * CP = 1 (Copyright unasserted)
1338 * AN = 0 (Audio data)
1339 * P = 0 (Consumer)
1340 */
1341 snd_ca0106_ptr_write(chip, SPCS0, 0,
1342 chip->spdif_bits[0] =
1343 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1344 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1345 SPCS_GENERATIONSTATUS | 0x00001200 |
1346 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1347 /* Only SPCS1 has been tested */
1348 snd_ca0106_ptr_write(chip, SPCS1, 0,
1349 chip->spdif_bits[1] =
1350 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1351 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1352 SPCS_GENERATIONSTATUS | 0x00001200 |
1353 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1354 snd_ca0106_ptr_write(chip, SPCS2, 0,
1355 chip->spdif_bits[2] =
1356 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1357 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1358 SPCS_GENERATIONSTATUS | 0x00001200 |
1359 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1360 snd_ca0106_ptr_write(chip, SPCS3, 0,
1361 chip->spdif_bits[3] =
1362 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1363 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1364 SPCS_GENERATIONSTATUS | 0x00001200 |
1365 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1366
1367 snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
1368 snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
1369
1370 /* Write 0x8000 to AC97_REC_GAIN to mute it. */
1371 outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
1372 outw(0x8000, chip->port + AC97DATA);
1373#if 0
1374 snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
1375 snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
1376 snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
1377 snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
1378#endif
1379
1380 //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
1381 /* Analog or Digital output */
1382 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
James Courtier-Dutton8f55fbb2005-05-21 16:45:58 +02001383 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 -07001384 chip->spdif_enable = 0; /* Set digital SPDIF output off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
1386 //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
1387
1388 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
1389 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
1390 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
1391 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
1392 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
1393 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
1394 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
1395 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
1396 for(ch = 0; ch < 4; ch++) {
1397 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
1398 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
1399 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
1400 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
1401 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
1402 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
1403 }
James Courtier-Dutton7c157062006-12-10 00:00:38 +00001404 if (chip->details->i2c_adc == 1) {
1405 /* Select MIC, Line in, TAD in, AUX in */
1406 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1407 /* Default to CAPTURE_SOURCE to i2s in */
1408 chip->capture_source = 3;
1409 } else if (chip->details->ac97 == 1) {
1410 /* Default to AC97 in */
1411 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4);
1412 /* Default to CAPTURE_SOURCE to AC97 in */
1413 chip->capture_source = 4;
1414 } else {
1415 /* Select MIC, Line in, TAD in, AUX in */
1416 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1417 /* Default to Set CAPTURE_SOURCE to i2s in */
1418 chip->capture_source = 3;
1419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +01001421 if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001422 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1423 outl(0x0, chip->port+GPIO);
1424 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
1425 outl(0x005f5301, chip->port+GPIO); /* Analog */
1426 } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1428 outl(0x0, chip->port+GPIO);
1429 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
James Courtier-Duttonc82bf822005-06-04 15:03:06 +02001430 outl(0x005f5301, chip->port+GPIO); /* Analog */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 } else {
1432 outl(0x0, chip->port+GPIO);
1433 outl(0x005f03a3, chip->port+GPIO); /* Analog */
1434 //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
1435 }
1436 snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
1437
1438 //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
1439 //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
1440 //outl(0x00000009, chip->port+HCFG);
1441 outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
1442
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001443 if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001444 int size, n;
1445
1446 size = ARRAY_SIZE(i2c_adc_init);
1447 //snd_printk("I2C:array size=0x%x\n", size);
1448 for (n=0; n < size; n++) {
1449 snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
1450 }
1451 for (n=0; n < 4; n++) {
1452 chip->i2c_capture_volume[n][0]= 0xcf;
1453 chip->i2c_capture_volume[n][1]= 0xcf;
1454 }
1455 chip->i2c_capture_source=2; /* Line in */
1456 //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 +02001457 }
James Courtier-Duttona5875152005-12-20 22:30:49 +01001458 if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001459 int size, n;
1460
1461 size = ARRAY_SIZE(spi_dac_init);
1462 for (n=0; n < size; n++)
1463 snd_ca0106_spi_write(chip, spi_dac_init[n]);
James Courtier-Duttona5875152005-12-20 22:30:49 +01001464 }
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001465
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
1467 chip, &ops)) < 0) {
1468 snd_ca0106_free(chip);
1469 return err;
1470 }
1471 *rchip = chip;
1472 return 0;
1473}
1474
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001475
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001476static void ca0106_midi_interrupt_enable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001477{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001478 snd_ca0106_intr_enable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001479}
1480
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001481static void ca0106_midi_interrupt_disable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001482{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001483 snd_ca0106_intr_disable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001484}
1485
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001486static unsigned char ca0106_midi_read(struct snd_ca_midi *midi, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001487{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001488 return (unsigned char)snd_ca0106_ptr_read((struct snd_ca0106 *)(midi->dev_id),
1489 midi->port + idx, 0);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001490}
1491
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001492static void ca0106_midi_write(struct snd_ca_midi *midi, int data, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001493{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001494 snd_ca0106_ptr_write((struct snd_ca0106 *)(midi->dev_id), midi->port + idx, 0, data);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001495}
1496
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001497static struct snd_card *ca0106_dev_id_card(void *dev_id)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001498{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001499 return ((struct snd_ca0106 *)dev_id)->card;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001500}
1501
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001502static int ca0106_dev_id_port(void *dev_id)
1503{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001504 return ((struct snd_ca0106 *)dev_id)->port;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001505}
1506
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001507static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001508{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001509 struct snd_ca_midi *midi;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001510 char *name;
1511 int err;
1512
Takashi Iwai95a98262005-11-17 10:40:18 +01001513 if (channel == CA0106_MIDI_CHAN_B) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001514 name = "CA0106 MPU-401 (UART) B";
1515 midi = &chip->midi2;
1516 midi->tx_enable = INTE_MIDI_TX_B;
1517 midi->rx_enable = INTE_MIDI_RX_B;
1518 midi->ipr_tx = IPR_MIDI_TX_B;
1519 midi->ipr_rx = IPR_MIDI_RX_B;
1520 midi->port = MIDI_UART_B_DATA;
1521 } else {
1522 name = "CA0106 MPU-401 (UART)";
1523 midi = &chip->midi;
1524 midi->tx_enable = INTE_MIDI_TX_A;
1525 midi->rx_enable = INTE_MIDI_TX_B;
1526 midi->ipr_tx = IPR_MIDI_TX_A;
1527 midi->ipr_rx = IPR_MIDI_RX_A;
1528 midi->port = MIDI_UART_A_DATA;
1529 }
1530
1531 midi->reset = CA0106_MPU401_RESET;
1532 midi->enter_uart = CA0106_MPU401_ENTER_UART;
1533 midi->ack = CA0106_MPU401_ACK;
1534
1535 midi->input_avail = CA0106_MIDI_INPUT_AVAIL;
1536 midi->output_ready = CA0106_MIDI_OUTPUT_READY;
1537
1538 midi->channel = channel;
1539
1540 midi->interrupt_enable = ca0106_midi_interrupt_enable;
1541 midi->interrupt_disable = ca0106_midi_interrupt_disable;
1542
1543 midi->read = ca0106_midi_read;
1544 midi->write = ca0106_midi_write;
1545
1546 midi->get_dev_id_card = ca0106_dev_id_card;
1547 midi->get_dev_id_port = ca0106_dev_id_port;
1548
1549 midi->dev_id = chip;
1550
1551 if ((err = ca_midi_init(chip, midi, 0, name)) < 0)
1552 return err;
1553
1554 return 0;
1555}
1556
1557
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1559 const struct pci_device_id *pci_id)
1560{
1561 static int dev;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001562 struct snd_card *card;
1563 struct snd_ca0106 *chip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 int err;
1565
1566 if (dev >= SNDRV_CARDS)
1567 return -ENODEV;
1568 if (!enable[dev]) {
1569 dev++;
1570 return -ENOENT;
1571 }
1572
1573 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1574 if (card == NULL)
1575 return -ENOMEM;
1576
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001577 if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 snd_card_free(card);
1579 return err;
1580 }
1581
1582 if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
1583 snd_card_free(card);
1584 return err;
1585 }
1586 if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
1587 snd_card_free(card);
1588 return err;
1589 }
1590 if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
1591 snd_card_free(card);
1592 return err;
1593 }
1594 if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
1595 snd_card_free(card);
1596 return err;
1597 }
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001598 if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 if ((err = snd_ca0106_ac97(chip)) < 0) {
1600 snd_card_free(card);
1601 return err;
1602 }
1603 }
1604 if ((err = snd_ca0106_mixer(chip)) < 0) {
1605 snd_card_free(card);
1606 return err;
1607 }
1608
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001609 snd_printdd("ca0106: probe for MIDI channel A ...");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001610 if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
1611 snd_card_free(card);
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001612 snd_printdd(" failed, err=0x%x\n",err);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001613 return err;
1614 }
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001615 snd_printdd(" done.\n");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001616
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001617#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 snd_ca0106_proc_init(chip);
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001619#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
Takashi Iwaic6d6eee2007-02-08 14:50:31 +01001621 snd_card_set_dev(card, &pci->dev);
1622
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 if ((err = snd_card_register(card)) < 0) {
1624 snd_card_free(card);
1625 return err;
1626 }
1627
1628 pci_set_drvdata(pci, card);
1629 dev++;
1630 return 0;
1631}
1632
1633static void __devexit snd_ca0106_remove(struct pci_dev *pci)
1634{
1635 snd_card_free(pci_get_drvdata(pci));
1636 pci_set_drvdata(pci, NULL);
1637}
1638
1639// PCI IDs
Takashi Iwaif40b6892006-07-05 16:51:05 +02001640static struct pci_device_id snd_ca0106_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
1642 { 0, }
1643};
1644MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
1645
1646// pci_driver definition
1647static struct pci_driver driver = {
1648 .name = "CA0106",
1649 .id_table = snd_ca0106_ids,
1650 .probe = snd_ca0106_probe,
1651 .remove = __devexit_p(snd_ca0106_remove),
1652};
1653
1654// initialization of the module
1655static int __init alsa_card_ca0106_init(void)
1656{
Takashi Iwai95a98262005-11-17 10:40:18 +01001657 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658}
1659
1660// clean up the module
1661static void __exit alsa_card_ca0106_exit(void)
1662{
1663 pci_unregister_driver(&driver);
1664}
1665
1666module_init(alsa_card_ca0106_init)
1667module_exit(alsa_card_ca0106_exit)