blob: 512fda946c66302e86e627ece99483963dd8b8d3 [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
Trent Piephob18cd532007-07-24 12:06:16 +02004 * Version: 0.0.24
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.
Trent Piephob18cd532007-07-24 12:06:16 +020082 * 0.0.24
83 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 *
85 * BUGS:
86 * Some stability problems when unloading the snd-ca0106 kernel module.
87 * --
88 *
89 * TODO:
90 * 4 Capture channels, only one implemented so far.
91 * Other capture rates apart from 48khz not implemented.
92 * MIDI
93 * --
94 * GENERAL INFO:
95 * Model: SB0310
96 * P17 Chip: CA0106-DAT
97 * AC97 Codec: STAC 9721
98 * ADC: Philips 1361T (Stereo 24bit)
99 * DAC: WM8746EDS (6-channel, 24bit, 192Khz)
100 *
101 * GENERAL INFO:
102 * Model: SB0410
103 * P17 Chip: CA0106-DAT
104 * AC97 Codec: None
105 * ADC: WM8775EDS (4 Channel)
106 * DAC: CS4382 (114 dB, 24-Bit, 192 kHz, 8-Channel D/A Converter with DSD Support)
107 * SPDIF Out control switches between Mic in and SPDIF out.
108 * No sound out or mic input working yet.
109 *
110 * GENERAL INFO:
111 * Model: SB0413
112 * P17 Chip: CA0106-DAT
113 * AC97 Codec: None.
114 * ADC: Unknown
115 * DAC: Unknown
116 * Trying to handle it like the SB0410.
117 *
118 * This code was initally based on code from ALSA's emu10k1x.c which is:
119 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
120 *
121 * This program is free software; you can redistribute it and/or modify
122 * it under the terms of the GNU General Public License as published by
123 * the Free Software Foundation; either version 2 of the License, or
124 * (at your option) any later version.
125 *
126 * This program is distributed in the hope that it will be useful,
127 * but WITHOUT ANY WARRANTY; without even the implied warranty of
128 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
129 * GNU General Public License for more details.
130 *
131 * You should have received a copy of the GNU General Public License
132 * along with this program; if not, write to the Free Software
133 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
134 *
135 */
136#include <sound/driver.h>
137#include <linux/delay.h>
138#include <linux/init.h>
139#include <linux/interrupt.h>
140#include <linux/pci.h>
141#include <linux/slab.h>
142#include <linux/moduleparam.h>
Tobias Klauser299676b2005-05-29 15:21:02 +0200143#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144#include <sound/core.h>
145#include <sound/initval.h>
146#include <sound/pcm.h>
147#include <sound/ac97_codec.h>
148#include <sound/info.h>
149
150MODULE_AUTHOR("James Courtier-Dutton <James@superbug.demon.co.uk>");
151MODULE_DESCRIPTION("CA0106");
152MODULE_LICENSE("GPL");
153MODULE_SUPPORTED_DEVICE("{{Creative,SB CA0106 chip}}");
154
155// module parameters (see "Module Parameters")
156static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
157static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
158static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000159static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
161module_param_array(index, int, NULL, 0444);
162MODULE_PARM_DESC(index, "Index value for the CA0106 soundcard.");
163module_param_array(id, charp, NULL, 0444);
164MODULE_PARM_DESC(id, "ID string for the CA0106 soundcard.");
165module_param_array(enable, bool, NULL, 0444);
166MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard.");
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000167module_param_array(subsystem, uint, NULL, 0444);
168MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169
170#include "ca0106.h"
171
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100172static struct snd_ca0106_details ca0106_chip_details[] = {
James Courtier-Dutton86326492007-05-18 20:35:50 +0100173 /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
174 /* It is really just a normal SB Live 24bit. */
James Courtier-Duttonaaccf542007-07-23 18:12:41 +0100175 /* Tested:
176 * See ALSA bug#3251
177 */
178 { .serial = 0x10131102,
179 .name = "X-Fi Extreme Audio [SBxxxx]",
180 .gpio_type = 1,
181 .i2c_adc = 1 } ,
182 /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
183 /* It is really just a normal SB Live 24bit. */
James Courtier-Dutton86326492007-05-18 20:35:50 +0100184 /*
185 * CTRL:CA0111-WTLF
186 * ADC: WM8775SEDS
187 * DAC: CS4382-KQZ
188 */
189 /* Tested:
190 * Playback on front, rear, center/lfe speakers
191 * Capture from Mic in.
192 * Not-Tested:
193 * Capture from Line in.
194 * Playback to digital out.
195 */
196 { .serial = 0x10121102,
197 .name = "X-Fi Extreme Audio [SB0790]",
198 .gpio_type = 1,
199 .i2c_adc = 1 } ,
200 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200201 /* AudigyLS[SB0310] */
202 { .serial = 0x10021102,
203 .name = "AudigyLS [SB0310]",
204 .ac97 = 1 } ,
205 /* Unknown AudigyLS that also says SB0310 on it */
206 { .serial = 0x10051102,
207 .name = "AudigyLS [SB0310b]",
208 .ac97 = 1 } ,
209 /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
210 { .serial = 0x10061102,
211 .name = "Live! 7.1 24bit [SB0410]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200212 .gpio_type = 1,
213 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200214 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
215 { .serial = 0x10071102,
216 .name = "Live! 7.1 24bit [SB0413]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200217 .gpio_type = 1,
218 .i2c_adc = 1 } ,
James Courtier-Duttona5875152005-12-20 22:30:49 +0100219 /* New Audigy SE. Has a different DAC. */
220 /* SB0570:
221 * CTRL:CA0106-DAT
James Courtier-Dutton58398892006-06-10 09:16:49 +0100222 * ADC: WM8775EDS
223 * DAC: WM8768GEDS
James Courtier-Duttona5875152005-12-20 22:30:49 +0100224 */
225 { .serial = 0x100a1102,
226 .name = "Audigy SE [SB0570]",
227 .gpio_type = 1,
228 .i2c_adc = 1,
229 .spi_dac = 1 } ,
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000230 /* New Audigy LS. Has a different DAC. */
231 /* SB0570:
232 * CTRL:CA0106-DAT
233 * ADC: WM8775EDS
234 * DAC: WM8768GEDS
235 */
236 { .serial = 0x10111102,
James Courtier-Duttond5f6a382006-11-25 19:50:11 +0000237 .name = "Audigy SE OEM [SB0570a]",
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000238 .gpio_type = 1,
239 .i2c_adc = 1,
240 .spi_dac = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200241 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100242 /* SB0438
243 * CTRL:CA0106-DAT
244 * ADC: WM8775SEDS
245 * DAC: CS4382-KQZ
246 */
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200247 { .serial = 0x10091462,
248 .name = "MSI K8N Diamond MB [SB0438]",
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100249 .gpio_type = 2,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200250 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100251 /* Shuttle XPC SD31P which has an onboard Creative Labs
252 * Sound Blaster Live! 24-bit EAX
James Courtier-Dutton1b059622005-08-12 23:50:13 +0200253 * high-definition 7.1 audio processor".
254 * Added using info from andrewvegan in alsa bug #1298
255 */
256 { .serial = 0x30381297,
257 .name = "Shuttle XPC SD31P [SD31P]",
258 .gpio_type = 1,
259 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100260 /* Shuttle XPC SD11G5 which has an onboard Creative Labs
261 * Sound Blaster Live! 24-bit EAX
262 * high-definition 7.1 audio processor".
263 * Fixes ALSA bug#1600
264 */
265 { .serial = 0x30411297,
266 .name = "Shuttle XPC SD11G5 [SD11G5]",
267 .gpio_type = 1,
268 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200269 { .serial = 0,
270 .name = "AudigyLS [Unknown]" }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271};
272
273/* hardware definition */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100274static struct snd_pcm_hardware snd_ca0106_playback_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 .info = (SNDRV_PCM_INFO_MMAP |
276 SNDRV_PCM_INFO_INTERLEAVED |
277 SNDRV_PCM_INFO_BLOCK_TRANSFER |
278 SNDRV_PCM_INFO_MMAP_VALID),
279 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100280 .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
281 SNDRV_PCM_RATE_192000),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 .rate_min = 48000,
283 .rate_max = 192000,
284 .channels_min = 2, //1,
285 .channels_max = 2, //6,
286 .buffer_bytes_max = ((65536 - 64) * 8),
287 .period_bytes_min = 64,
288 .period_bytes_max = (65536 - 64),
289 .periods_min = 2,
290 .periods_max = 8,
291 .fifo_size = 0,
292};
293
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100294static struct snd_pcm_hardware snd_ca0106_capture_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 .info = (SNDRV_PCM_INFO_MMAP |
296 SNDRV_PCM_INFO_INTERLEAVED |
297 SNDRV_PCM_INFO_BLOCK_TRANSFER |
298 SNDRV_PCM_INFO_MMAP_VALID),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200299 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100300 .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
301 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200302 .rate_min = 44100,
303 .rate_max = 192000,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 .channels_min = 2,
305 .channels_max = 2,
306 .buffer_bytes_max = ((65536 - 64) * 8),
307 .period_bytes_min = 64,
308 .period_bytes_max = (65536 - 64),
309 .periods_min = 2,
310 .periods_max = 2,
311 .fifo_size = 0,
312};
313
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100314unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 unsigned int reg,
316 unsigned int chn)
317{
318 unsigned long flags;
319 unsigned int regptr, val;
320
321 regptr = (reg << 16) | chn;
322
323 spin_lock_irqsave(&emu->emu_lock, flags);
324 outl(regptr, emu->port + PTR);
325 val = inl(emu->port + DATA);
326 spin_unlock_irqrestore(&emu->emu_lock, flags);
327 return val;
328}
329
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100330void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 unsigned int reg,
332 unsigned int chn,
333 unsigned int data)
334{
335 unsigned int regptr;
336 unsigned long flags;
337
338 regptr = (reg << 16) | chn;
339
340 spin_lock_irqsave(&emu->emu_lock, flags);
341 outl(regptr, emu->port + PTR);
342 outl(data, emu->port + DATA);
343 spin_unlock_irqrestore(&emu->emu_lock, flags);
344}
345
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100346int snd_ca0106_spi_write(struct snd_ca0106 * emu,
347 unsigned int data)
James Courtier-Duttona5875152005-12-20 22:30:49 +0100348{
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100349 unsigned int reset, set;
350 unsigned int reg, tmp;
351 int n, result;
352 reg = SPI;
353 if (data > 0xffff) /* Only 16bit values allowed */
354 return 1;
355 tmp = snd_ca0106_ptr_read(emu, reg, 0);
356 reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
357 set = reset | 0x10000; /* Set xxx1xxxx */
358 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
359 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* write post */
360 snd_ca0106_ptr_write(emu, reg, 0, set | data);
361 result = 1;
362 /* Wait for status bit to return to 0 */
363 for (n = 0; n < 100; n++) {
364 udelay(10);
365 tmp = snd_ca0106_ptr_read(emu, reg, 0);
366 if (!(tmp & 0x10000)) {
367 result = 0;
368 break;
369 }
370 }
371 if (result) /* Timed out */
372 return 1;
373 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
374 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* Write post */
James Courtier-Duttona5875152005-12-20 22:30:49 +0100375 return 0;
376}
377
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100378/* The ADC does not support i2c read, so only write is implemented */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100379int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200380 u32 reg,
381 u32 value)
382{
383 u32 tmp;
Takashi Iwai95a98262005-11-17 10:40:18 +0100384 int timeout = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200385 int status;
386 int retry;
Takashi Iwai95a98262005-11-17 10:40:18 +0100387 if ((reg > 0x7f) || (value > 0x1ff)) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200388 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200389 return -EINVAL;
390 }
391
392 tmp = reg << 25 | value << 16;
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100393 // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
James Courtier-Dutton8fabab12005-05-28 16:35:49 +0200394 /* Not sure what this I2C channel controls. */
395 /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
396
397 /* This controls the I2C connected to the WM8775 ADC Codec */
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200398 snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
399
Takashi Iwai95a98262005-11-17 10:40:18 +0100400 for (retry = 0; retry < 10; retry++) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200401 /* Send the data to i2c */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100402 //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
403 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
404 tmp = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200405 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
406 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
407
408 /* Wait till the transaction ends */
Takashi Iwai95a98262005-11-17 10:40:18 +0100409 while (1) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200410 status = snd_ca0106_ptr_read(emu, I2C_A, 0);
411 //snd_printk("I2C:status=0x%x\n", status);
412 timeout++;
Takashi Iwai95a98262005-11-17 10:40:18 +0100413 if ((status & I2C_A_ADC_START) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200414 break;
415
Takashi Iwai95a98262005-11-17 10:40:18 +0100416 if (timeout > 1000)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200417 break;
418 }
419 //Read back and see if the transaction is successful
Takashi Iwai95a98262005-11-17 10:40:18 +0100420 if ((status & I2C_A_ADC_ABORT) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200421 break;
422 }
423
Takashi Iwai95a98262005-11-17 10:40:18 +0100424 if (retry == 10) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200425 snd_printk(KERN_ERR "Writing to ADC failed!\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200426 return -EINVAL;
427 }
428
429 return 0;
430}
431
432
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100433static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
435 unsigned long flags;
436 unsigned int enable;
437
438 spin_lock_irqsave(&emu->emu_lock, flags);
439 enable = inl(emu->port + INTE) | intrenb;
440 outl(enable, emu->port + INTE);
441 spin_unlock_irqrestore(&emu->emu_lock, flags);
442}
443
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100444static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +0200445{
446 unsigned long flags;
447 unsigned int enable;
448
449 spin_lock_irqsave(&emu->emu_lock, flags);
450 enable = inl(emu->port + INTE) & ~intrenb;
451 outl(enable, emu->port + INTE);
452 spin_unlock_irqrestore(&emu->emu_lock, flags);
453}
454
455
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100456static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
Jesper Juhl4d572772005-05-30 17:30:32 +0200458 kfree(runtime->private_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459}
460
461/* open_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100462static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
463 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100465 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
466 struct snd_ca0106_channel *channel = &(chip->playback_channels[channel_id]);
467 struct snd_ca0106_pcm *epcm;
468 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 int err;
470
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200471 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472
473 if (epcm == NULL)
474 return -ENOMEM;
475 epcm->emu = chip;
476 epcm->substream = substream;
477 epcm->channel_id=channel_id;
478
479 runtime->private_data = epcm;
480 runtime->private_free = snd_ca0106_pcm_free_substream;
481
482 runtime->hw = snd_ca0106_playback_hw;
483
484 channel->emu = chip;
485 channel->number = channel_id;
486
Takashi Iwai95a98262005-11-17 10:40:18 +0100487 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
489 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwai95a98262005-11-17 10:40:18 +0100490 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
492 return err;
493 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
494 return err;
495 return 0;
496}
497
498/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100499static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100501 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
502 struct snd_pcm_runtime *runtime = substream->runtime;
503 struct snd_ca0106_pcm *epcm = runtime->private_data;
504 chip->playback_channels[epcm->channel_id].use = 0;
505 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 return 0;
507}
508
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100509static int snd_ca0106_pcm_open_playback_front(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510{
511 return snd_ca0106_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
512}
513
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100514static int snd_ca0106_pcm_open_playback_center_lfe(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
516 return snd_ca0106_pcm_open_playback_channel(substream, PCM_CENTER_LFE_CHANNEL);
517}
518
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100519static int snd_ca0106_pcm_open_playback_unknown(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520{
521 return snd_ca0106_pcm_open_playback_channel(substream, PCM_UNKNOWN_CHANNEL);
522}
523
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100524static int snd_ca0106_pcm_open_playback_rear(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525{
526 return snd_ca0106_pcm_open_playback_channel(substream, PCM_REAR_CHANNEL);
527}
528
529/* open_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100530static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substream,
531 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100533 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
534 struct snd_ca0106_channel *channel = &(chip->capture_channels[channel_id]);
535 struct snd_ca0106_pcm *epcm;
536 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 int err;
538
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200539 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 if (epcm == NULL) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200541 snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 return -ENOMEM;
543 }
544 epcm->emu = chip;
545 epcm->substream = substream;
546 epcm->channel_id=channel_id;
547
548 runtime->private_data = epcm;
549 runtime->private_free = snd_ca0106_pcm_free_substream;
550
551 runtime->hw = snd_ca0106_capture_hw;
552
553 channel->emu = chip;
554 channel->number = channel_id;
555
Takashi Iwai95a98262005-11-17 10:40:18 +0100556 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
558 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100559 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
561 return err;
562 //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
563 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
564 return err;
565 return 0;
566}
567
568/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100569static int snd_ca0106_pcm_close_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100571 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
572 struct snd_pcm_runtime *runtime = substream->runtime;
573 struct snd_ca0106_pcm *epcm = runtime->private_data;
574 chip->capture_channels[epcm->channel_id].use = 0;
575 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 return 0;
577}
578
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100579static int snd_ca0106_pcm_open_0_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
581 return snd_ca0106_pcm_open_capture_channel(substream, 0);
582}
583
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100584static int snd_ca0106_pcm_open_1_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585{
586 return snd_ca0106_pcm_open_capture_channel(substream, 1);
587}
588
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100589static int snd_ca0106_pcm_open_2_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
591 return snd_ca0106_pcm_open_capture_channel(substream, 2);
592}
593
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100594static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595{
596 return snd_ca0106_pcm_open_capture_channel(substream, 3);
597}
598
599/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100600static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream,
601 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602{
603 return snd_pcm_lib_malloc_pages(substream,
604 params_buffer_bytes(hw_params));
605}
606
607/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100608static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609{
610 return snd_pcm_lib_free_pages(substream);
611}
612
613/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100614static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream,
615 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616{
617 return snd_pcm_lib_malloc_pages(substream,
618 params_buffer_bytes(hw_params));
619}
620
621/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100622static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
624 return snd_pcm_lib_free_pages(substream);
625}
626
627/* prepare playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100628static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100630 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
631 struct snd_pcm_runtime *runtime = substream->runtime;
632 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 int channel = epcm->channel_id;
634 u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
635 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
636 u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
637 u32 hcfg_set = 0x00000000;
638 u32 hcfg;
639 u32 reg40_mask = 0x30000 << (channel<<1);
640 u32 reg40_set = 0;
641 u32 reg40;
642 /* FIXME: Depending on mixer selection of SPDIF out or not, select the spdif rate or the DAC rate. */
643 u32 reg71_mask = 0x03030000 ; /* Global. Set SPDIF rate. We only support 44100 to spdif, not to DAC. */
644 u32 reg71_set = 0;
645 u32 reg71;
646 int i;
647
648 //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));
649 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
650 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
651 /* Rate can be set per channel. */
652 /* reg40 control host to fifo */
653 /* reg71 controls DAC rate. */
654 switch (runtime->rate) {
655 case 44100:
656 reg40_set = 0x10000 << (channel<<1);
657 reg71_set = 0x01010000;
658 break;
659 case 48000:
660 reg40_set = 0;
661 reg71_set = 0;
662 break;
663 case 96000:
664 reg40_set = 0x20000 << (channel<<1);
665 reg71_set = 0x02020000;
666 break;
667 case 192000:
668 reg40_set = 0x30000 << (channel<<1);
669 reg71_set = 0x03030000;
670 break;
671 default:
672 reg40_set = 0;
673 reg71_set = 0;
674 break;
675 }
676 /* Format is a global setting */
677 /* FIXME: Only let the first channel accessed set this. */
678 switch (runtime->format) {
679 case SNDRV_PCM_FORMAT_S16_LE:
680 hcfg_set = 0;
681 break;
682 case SNDRV_PCM_FORMAT_S32_LE:
683 hcfg_set = HCFG_PLAYBACK_S32_LE;
684 break;
685 default:
686 hcfg_set = 0;
687 break;
688 }
689 hcfg = inl(emu->port + HCFG) ;
690 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
691 outl(hcfg, emu->port + HCFG);
692 reg40 = snd_ca0106_ptr_read(emu, 0x40, 0);
693 reg40 = (reg40 & ~reg40_mask) | reg40_set;
694 snd_ca0106_ptr_write(emu, 0x40, 0, reg40);
695 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
696 reg71 = (reg71 & ~reg71_mask) | reg71_set;
697 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
698
699 /* FIXME: Check emu->buffer.size before actually writing to it. */
700 for(i=0; i < runtime->periods; i++) {
Takashi Iwai95a98262005-11-17 10:40:18 +0100701 table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
702 table_base[i*2+1] = period_size_bytes << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 }
704
705 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
706 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
707 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
708 snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
709 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
710 /* FIXME test what 0 bytes does. */
711 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
712 snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
713 snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
714 snd_ca0106_ptr_write(emu, 0x08, channel, 0);
715 snd_ca0106_ptr_write(emu, PLAYBACK_MUTE, 0x0, 0x0); /* Unmute output */
716#if 0
717 snd_ca0106_ptr_write(emu, SPCS0, 0,
718 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
719 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
720 SPCS_GENERATIONSTATUS | 0x00001200 |
721 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
722 }
723#endif
724
725 return 0;
726}
727
728/* prepare capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100729static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100731 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
732 struct snd_pcm_runtime *runtime = substream->runtime;
733 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 int channel = epcm->channel_id;
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200735 u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
736 u32 hcfg_set = 0x00000000;
737 u32 hcfg;
738 u32 over_sampling=0x2;
739 u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
740 u32 reg71_set = 0;
741 u32 reg71;
742
743 //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));
744 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
745 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
746 /* reg71 controls ADC rate. */
747 switch (runtime->rate) {
748 case 44100:
749 reg71_set = 0x00004000;
750 break;
751 case 48000:
752 reg71_set = 0;
753 break;
754 case 96000:
755 reg71_set = 0x00008000;
756 over_sampling=0xa;
757 break;
758 case 192000:
759 reg71_set = 0x0000c000;
760 over_sampling=0xa;
761 break;
762 default:
763 reg71_set = 0;
764 break;
765 }
766 /* Format is a global setting */
767 /* FIXME: Only let the first channel accessed set this. */
768 switch (runtime->format) {
769 case SNDRV_PCM_FORMAT_S16_LE:
770 hcfg_set = 0;
771 break;
772 case SNDRV_PCM_FORMAT_S32_LE:
773 hcfg_set = HCFG_CAPTURE_S32_LE;
774 break;
775 default:
776 hcfg_set = 0;
777 break;
778 }
779 hcfg = inl(emu->port + HCFG) ;
780 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
781 outl(hcfg, emu->port + HCFG);
782 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
783 reg71 = (reg71 & ~reg71_mask) | reg71_set;
784 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
785 if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
786 snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
787 }
788
789
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 //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));
791 snd_ca0106_ptr_write(emu, 0x13, channel, 0);
792 snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
793 snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
794 snd_ca0106_ptr_write(emu, CAPTURE_POINTER, channel, 0);
795
796 return 0;
797}
798
799/* trigger_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100800static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 int cmd)
802{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100803 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
804 struct snd_pcm_runtime *runtime;
805 struct snd_ca0106_pcm *epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 int channel;
807 int result = 0;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100808 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 u32 basic = 0;
810 u32 extended = 0;
811 int running=0;
812
813 switch (cmd) {
814 case SNDRV_PCM_TRIGGER_START:
815 running=1;
816 break;
817 case SNDRV_PCM_TRIGGER_STOP:
818 default:
819 running=0;
820 break;
821 }
Takashi Iwaief991b92007-02-22 12:52:53 +0100822 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 runtime = s->runtime;
824 epcm = runtime->private_data;
825 channel = epcm->channel_id;
826 //snd_printk("channel=%d\n",channel);
827 epcm->running = running;
828 basic |= (0x1<<channel);
829 extended |= (0x10<<channel);
830 snd_pcm_trigger_done(s, substream);
831 }
832 //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
833
834 switch (cmd) {
835 case SNDRV_PCM_TRIGGER_START:
836 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
837 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
838 break;
839 case SNDRV_PCM_TRIGGER_STOP:
840 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
841 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
842 break;
843 default:
844 result = -EINVAL;
845 break;
846 }
847 return result;
848}
849
850/* trigger_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100851static int snd_ca0106_pcm_trigger_capture(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 int cmd)
853{
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 int channel = epcm->channel_id;
858 int result = 0;
859
860 switch (cmd) {
861 case SNDRV_PCM_TRIGGER_START:
862 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
863 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
864 epcm->running = 1;
865 break;
866 case SNDRV_PCM_TRIGGER_STOP:
867 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
868 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
869 epcm->running = 0;
870 break;
871 default:
872 result = -EINVAL;
873 break;
874 }
875 return result;
876}
877
878/* pointer_playback callback */
879static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100880snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100882 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
883 struct snd_pcm_runtime *runtime = substream->runtime;
884 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
886 int channel = epcm->channel_id;
887
888 if (!epcm->running)
889 return 0;
890
891 ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
892 ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
893 ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
894 if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
895 ptr2 = bytes_to_frames(runtime, ptr1);
896 ptr2+= (ptr4 >> 3) * runtime->period_size;
897 ptr=ptr2;
898 if (ptr >= runtime->buffer_size)
899 ptr -= runtime->buffer_size;
900 //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);
901
902 return ptr;
903}
904
905/* pointer_capture callback */
906static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100907snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100909 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
910 struct snd_pcm_runtime *runtime = substream->runtime;
911 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
913 int channel = channel=epcm->channel_id;
914
915 if (!epcm->running)
916 return 0;
917
918 ptr1 = snd_ca0106_ptr_read(emu, CAPTURE_POINTER, channel);
919 ptr2 = bytes_to_frames(runtime, ptr1);
920 ptr=ptr2;
921 if (ptr >= runtime->buffer_size)
922 ptr -= runtime->buffer_size;
923 //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);
924
925 return ptr;
926}
927
928/* operators */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100929static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 .open = snd_ca0106_pcm_open_playback_front,
931 .close = snd_ca0106_pcm_close_playback,
932 .ioctl = snd_pcm_lib_ioctl,
933 .hw_params = snd_ca0106_pcm_hw_params_playback,
934 .hw_free = snd_ca0106_pcm_hw_free_playback,
935 .prepare = snd_ca0106_pcm_prepare_playback,
936 .trigger = snd_ca0106_pcm_trigger_playback,
937 .pointer = snd_ca0106_pcm_pointer_playback,
938};
939
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100940static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 .open = snd_ca0106_pcm_open_0_capture,
942 .close = snd_ca0106_pcm_close_capture,
943 .ioctl = snd_pcm_lib_ioctl,
944 .hw_params = snd_ca0106_pcm_hw_params_capture,
945 .hw_free = snd_ca0106_pcm_hw_free_capture,
946 .prepare = snd_ca0106_pcm_prepare_capture,
947 .trigger = snd_ca0106_pcm_trigger_capture,
948 .pointer = snd_ca0106_pcm_pointer_capture,
949};
950
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100951static struct snd_pcm_ops snd_ca0106_capture_1_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 .open = snd_ca0106_pcm_open_1_capture,
953 .close = snd_ca0106_pcm_close_capture,
954 .ioctl = snd_pcm_lib_ioctl,
955 .hw_params = snd_ca0106_pcm_hw_params_capture,
956 .hw_free = snd_ca0106_pcm_hw_free_capture,
957 .prepare = snd_ca0106_pcm_prepare_capture,
958 .trigger = snd_ca0106_pcm_trigger_capture,
959 .pointer = snd_ca0106_pcm_pointer_capture,
960};
961
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100962static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 .open = snd_ca0106_pcm_open_2_capture,
964 .close = snd_ca0106_pcm_close_capture,
965 .ioctl = snd_pcm_lib_ioctl,
966 .hw_params = snd_ca0106_pcm_hw_params_capture,
967 .hw_free = snd_ca0106_pcm_hw_free_capture,
968 .prepare = snd_ca0106_pcm_prepare_capture,
969 .trigger = snd_ca0106_pcm_trigger_capture,
970 .pointer = snd_ca0106_pcm_pointer_capture,
971};
972
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100973static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 .open = snd_ca0106_pcm_open_3_capture,
975 .close = snd_ca0106_pcm_close_capture,
976 .ioctl = snd_pcm_lib_ioctl,
977 .hw_params = snd_ca0106_pcm_hw_params_capture,
978 .hw_free = snd_ca0106_pcm_hw_free_capture,
979 .prepare = snd_ca0106_pcm_prepare_capture,
980 .trigger = snd_ca0106_pcm_trigger_capture,
981 .pointer = snd_ca0106_pcm_pointer_capture,
982};
983
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100984static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 .open = snd_ca0106_pcm_open_playback_center_lfe,
986 .close = snd_ca0106_pcm_close_playback,
987 .ioctl = snd_pcm_lib_ioctl,
988 .hw_params = snd_ca0106_pcm_hw_params_playback,
989 .hw_free = snd_ca0106_pcm_hw_free_playback,
990 .prepare = snd_ca0106_pcm_prepare_playback,
991 .trigger = snd_ca0106_pcm_trigger_playback,
992 .pointer = snd_ca0106_pcm_pointer_playback,
993};
994
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100995static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 .open = snd_ca0106_pcm_open_playback_unknown,
997 .close = snd_ca0106_pcm_close_playback,
998 .ioctl = snd_pcm_lib_ioctl,
999 .hw_params = snd_ca0106_pcm_hw_params_playback,
1000 .hw_free = snd_ca0106_pcm_hw_free_playback,
1001 .prepare = snd_ca0106_pcm_prepare_playback,
1002 .trigger = snd_ca0106_pcm_trigger_playback,
1003 .pointer = snd_ca0106_pcm_pointer_playback,
1004};
1005
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001006static struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 .open = snd_ca0106_pcm_open_playback_rear,
1008 .close = snd_ca0106_pcm_close_playback,
1009 .ioctl = snd_pcm_lib_ioctl,
1010 .hw_params = snd_ca0106_pcm_hw_params_playback,
1011 .hw_free = snd_ca0106_pcm_hw_free_playback,
1012 .prepare = snd_ca0106_pcm_prepare_playback,
1013 .trigger = snd_ca0106_pcm_trigger_playback,
1014 .pointer = snd_ca0106_pcm_pointer_playback,
1015};
1016
1017
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001018static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 unsigned short reg)
1020{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001021 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 unsigned long flags;
1023 unsigned short val;
1024
1025 spin_lock_irqsave(&emu->emu_lock, flags);
1026 outb(reg, emu->port + AC97ADDRESS);
1027 val = inw(emu->port + AC97DATA);
1028 spin_unlock_irqrestore(&emu->emu_lock, flags);
1029 return val;
1030}
1031
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001032static void snd_ca0106_ac97_write(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 unsigned short reg, unsigned short val)
1034{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001035 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 unsigned long flags;
1037
1038 spin_lock_irqsave(&emu->emu_lock, flags);
1039 outb(reg, emu->port + AC97ADDRESS);
1040 outw(val, emu->port + AC97DATA);
1041 spin_unlock_irqrestore(&emu->emu_lock, flags);
1042}
1043
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001044static int snd_ca0106_ac97(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001046 struct snd_ac97_bus *pbus;
1047 struct snd_ac97_template ac97;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 int err;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001049 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 .write = snd_ca0106_ac97_write,
1051 .read = snd_ca0106_ac97_read,
1052 };
1053
1054 if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
1055 return err;
1056 pbus->no_vra = 1; /* we don't need VRA */
1057
1058 memset(&ac97, 0, sizeof(ac97));
1059 ac97.private_data = chip;
Takashi Iwai36c4dc42005-03-24 17:48:30 +01001060 ac97.scaps = AC97_SCAP_NO_SPDIF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
1062}
1063
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001064static int snd_ca0106_free(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065{
1066 if (chip->res_port != NULL) { /* avoid access to already used hardware */
1067 // disable interrupts
1068 snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
1069 outl(0, chip->port + INTE);
1070 snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
1071 udelay(1000);
1072 // disable audio
1073 //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
1074 outl(0, chip->port + HCFG);
1075 /* FIXME: We need to stop and DMA transfers here.
1076 * But as I am not sure how yet, we cannot from the dma pages.
1077 * So we can fix: snd-malloc: Memory leak? pages not freed = 8
1078 */
1079 }
1080 // release the data
1081#if 1
1082 if (chip->buffer.area)
1083 snd_dma_free_pages(&chip->buffer);
1084#endif
1085
1086 // release the i/o port
Takashi Iwaib1d57762005-10-10 11:56:31 +02001087 release_and_free_resource(chip->res_port);
1088
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 // release the irq
1090 if (chip->irq >= 0)
Takashi Iwai437a5a42006-11-21 12:14:23 +01001091 free_irq(chip->irq, chip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 pci_disable_device(chip->pci);
1093 kfree(chip);
1094 return 0;
1095}
1096
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001097static int snd_ca0106_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001099 struct snd_ca0106 *chip = device->device_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 return snd_ca0106_free(chip);
1101}
1102
David Howells7d12e782006-10-05 14:55:46 +01001103static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104{
1105 unsigned int status;
1106
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001107 struct snd_ca0106 *chip = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 int i;
1109 int mask;
1110 unsigned int stat76;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001111 struct snd_ca0106_channel *pchannel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 status = inl(chip->port + IPR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 if (! status)
1115 return IRQ_NONE;
1116
1117 stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0);
1118 //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76);
1119 //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0));
1120 mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
1121 for(i = 0; i < 4; i++) {
1122 pchannel = &(chip->playback_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001123 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124/* FIXME: Select the correct substream for period elapsed */
1125 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001126 snd_pcm_period_elapsed(pchannel->epcm->substream);
1127 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 }
1129 }
1130 //printk(KERN_INFO "channel=%p\n",pchannel);
1131 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1132 mask <<= 1;
1133 }
1134 mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */
1135 for(i = 0; i < 4; i++) {
1136 pchannel = &(chip->capture_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001137 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138/* FIXME: Select the correct substream for period elapsed */
1139 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001140 snd_pcm_period_elapsed(pchannel->epcm->substream);
1141 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 }
1143 }
1144 //printk(KERN_INFO "channel=%p\n",pchannel);
1145 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1146 mask <<= 1;
1147 }
1148
1149 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001150
1151 if (chip->midi.dev_id &&
Takashi Iwai95a98262005-11-17 10:40:18 +01001152 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001153 if (chip->midi.interrupt)
1154 chip->midi.interrupt(&chip->midi, status);
1155 else
1156 chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable);
1157 }
1158
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 // acknowledge the interrupt if necessary
1160 outl(status, chip->port+IPR);
1161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 return IRQ_HANDLED;
1163}
1164
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001165static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001167 struct snd_pcm *pcm;
1168 struct snd_pcm_substream *substream;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 int err;
1170
1171 if (rpcm)
1172 *rpcm = NULL;
1173 if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
1174 return err;
1175
1176 pcm->private_data = emu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
1178 switch (device) {
1179 case 0:
1180 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops);
1181 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops);
1182 break;
1183 case 1:
1184 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops);
1185 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops);
1186 break;
1187 case 2:
1188 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops);
1189 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops);
1190 break;
1191 case 3:
1192 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops);
1193 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops);
1194 break;
1195 }
1196
1197 pcm->info_flags = 0;
1198 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
1199 strcpy(pcm->name, "CA0106");
1200 emu->pcm = pcm;
1201
1202 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1203 substream;
1204 substream = substream->next) {
1205 if ((err = snd_pcm_lib_preallocate_pages(substream,
1206 SNDRV_DMA_TYPE_DEV,
1207 snd_dma_pci_data(emu->pci),
1208 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
1209 return err;
1210 }
1211
1212 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1213 substream;
1214 substream = substream->next) {
1215 if ((err = snd_pcm_lib_preallocate_pages(substream,
1216 SNDRV_DMA_TYPE_DEV,
1217 snd_dma_pci_data(emu->pci),
1218 64*1024, 64*1024)) < 0)
1219 return err;
1220 }
1221
1222 if (rpcm)
1223 *rpcm = pcm;
1224
1225 return 0;
1226}
1227
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001228static unsigned int spi_dac_init[] = {
1229 0x00ff,
1230 0x02ff,
1231 0x0400,
1232 0x0520,
James Courtier-Dutton58398892006-06-10 09:16:49 +01001233 0x0620, /* Set 24 bit. Was 0x0600 */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001234 0x08ff,
1235 0x0aff,
1236 0x0cff,
1237 0x0eff,
1238 0x10ff,
1239 0x1200,
1240 0x1400,
1241 0x1480,
1242 0x1800,
1243 0x1aff,
1244 0x1cff,
1245 0x1e00,
1246 0x0530,
1247 0x0602,
1248 0x0622,
1249 0x1400,
1250};
1251
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001252static unsigned int i2c_adc_init[][2] = {
1253 { 0x17, 0x00 }, /* Reset */
1254 { 0x07, 0x00 }, /* Timeout */
1255 { 0x0b, 0x22 }, /* Interface control */
1256 { 0x0c, 0x22 }, /* Master mode control */
1257 { 0x0d, 0x08 }, /* Powerdown control */
1258 { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
1259 { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */
1260 { 0x10, 0x7b }, /* ALC Control 1 */
1261 { 0x11, 0x00 }, /* ALC Control 2 */
1262 { 0x12, 0x32 }, /* ALC Control 3 */
1263 { 0x13, 0x00 }, /* Noise gate control */
1264 { 0x14, 0xa6 }, /* Limiter control */
1265 { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
1266};
1267
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001268static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 struct pci_dev *pci,
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001270 struct snd_ca0106 **rchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001272 struct snd_ca0106 *chip;
1273 struct snd_ca0106_details *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 int err;
1275 int ch;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001276 static struct snd_device_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 .dev_free = snd_ca0106_dev_free,
1278 };
1279
1280 *rchip = NULL;
1281
1282 if ((err = pci_enable_device(pci)) < 0)
1283 return err;
Tobias Klauser299676b2005-05-29 15:21:02 +02001284 if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
1285 pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 printk(KERN_ERR "error to set 32bit mask DMA\n");
1287 pci_disable_device(pci);
1288 return -ENXIO;
1289 }
1290
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001291 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (chip == NULL) {
1293 pci_disable_device(pci);
1294 return -ENOMEM;
1295 }
1296
1297 chip->card = card;
1298 chip->pci = pci;
1299 chip->irq = -1;
1300
1301 spin_lock_init(&chip->emu_lock);
1302
1303 chip->port = pci_resource_start(pci, 0);
1304 if ((chip->res_port = request_region(chip->port, 0x20,
1305 "snd_ca0106")) == NULL) {
1306 snd_ca0106_free(chip);
1307 printk(KERN_ERR "cannot allocate the port\n");
1308 return -EBUSY;
1309 }
1310
1311 if (request_irq(pci->irq, snd_ca0106_interrupt,
Takashi Iwai437a5a42006-11-21 12:14:23 +01001312 IRQF_SHARED, "snd_ca0106", chip)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 snd_ca0106_free(chip);
1314 printk(KERN_ERR "cannot grab irq\n");
1315 return -EBUSY;
1316 }
1317 chip->irq = pci->irq;
1318
1319 /* This stores the periods table. */
1320 if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
1321 snd_ca0106_free(chip);
1322 return -ENOMEM;
1323 }
1324
1325 pci_set_master(pci);
Auke Kok44c10132007-06-08 15:46:36 -07001326 /* read serial */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
1328 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
1329#if 1
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001330 printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
Auke Kok44c10132007-06-08 15:46:36 -07001331 pci->revision, chip->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332#endif
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001333 strcpy(card->driver, "CA0106");
1334 strcpy(card->shortname, "CA0106");
1335
Takashi Iwai95a98262005-11-17 10:40:18 +01001336 for (c = ca0106_chip_details; c->serial; c++) {
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001337 if (subsystem[dev]) {
1338 if (c->serial == subsystem[dev])
1339 break;
1340 } else if (c->serial == chip->serial)
Takashi Iwai95a98262005-11-17 10:40:18 +01001341 break;
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001342 }
1343 chip->details = c;
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001344 if (subsystem[dev]) {
James Courtier-Duttond5f6a382006-11-25 19:50:11 +00001345 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 +00001346 c->name, chip->serial, subsystem[dev]);
1347 }
1348
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001349 sprintf(card->longname, "%s at 0x%lx irq %i",
1350 c->name, chip->port, chip->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
1352 outl(0, chip->port + INTE);
1353
1354 /*
1355 * Init to 0x02109204 :
1356 * Clock accuracy = 0 (1000ppm)
1357 * Sample Rate = 2 (48kHz)
1358 * Audio Channel = 1 (Left of 2)
1359 * Source Number = 0 (Unspecified)
1360 * Generation Status = 1 (Original for Cat Code 12)
1361 * Cat Code = 12 (Digital Signal Mixer)
1362 * Mode = 0 (Mode 0)
1363 * Emphasis = 0 (None)
1364 * CP = 1 (Copyright unasserted)
1365 * AN = 0 (Audio data)
1366 * P = 0 (Consumer)
1367 */
1368 snd_ca0106_ptr_write(chip, SPCS0, 0,
1369 chip->spdif_bits[0] =
1370 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1371 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1372 SPCS_GENERATIONSTATUS | 0x00001200 |
1373 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1374 /* Only SPCS1 has been tested */
1375 snd_ca0106_ptr_write(chip, SPCS1, 0,
1376 chip->spdif_bits[1] =
1377 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1378 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1379 SPCS_GENERATIONSTATUS | 0x00001200 |
1380 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1381 snd_ca0106_ptr_write(chip, SPCS2, 0,
1382 chip->spdif_bits[2] =
1383 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1384 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1385 SPCS_GENERATIONSTATUS | 0x00001200 |
1386 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1387 snd_ca0106_ptr_write(chip, SPCS3, 0,
1388 chip->spdif_bits[3] =
1389 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1390 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1391 SPCS_GENERATIONSTATUS | 0x00001200 |
1392 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1393
1394 snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
1395 snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
1396
1397 /* Write 0x8000 to AC97_REC_GAIN to mute it. */
1398 outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
1399 outw(0x8000, chip->port + AC97DATA);
1400#if 0
1401 snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
1402 snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
1403 snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
1404 snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
1405#endif
1406
1407 //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
1408 /* Analog or Digital output */
1409 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
James Courtier-Dutton8f55fbb2005-05-21 16:45:58 +02001410 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 -07001411 chip->spdif_enable = 0; /* Set digital SPDIF output off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
1413 //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
1414
1415 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
1416 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
1417 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
1418 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
1419 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
1420 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
1421 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
1422 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
1423 for(ch = 0; ch < 4; ch++) {
1424 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
1425 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
1426 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
1427 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
1428 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
1429 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
1430 }
James Courtier-Dutton7c157062006-12-10 00:00:38 +00001431 if (chip->details->i2c_adc == 1) {
1432 /* Select MIC, Line in, TAD in, AUX in */
1433 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1434 /* Default to CAPTURE_SOURCE to i2s in */
1435 chip->capture_source = 3;
1436 } else if (chip->details->ac97 == 1) {
1437 /* Default to AC97 in */
1438 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4);
1439 /* Default to CAPTURE_SOURCE to AC97 in */
1440 chip->capture_source = 4;
1441 } else {
1442 /* Select MIC, Line in, TAD in, AUX in */
1443 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1444 /* Default to Set CAPTURE_SOURCE to i2s in */
1445 chip->capture_source = 3;
1446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +01001448 if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001449 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1450 outl(0x0, chip->port+GPIO);
1451 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
1452 outl(0x005f5301, chip->port+GPIO); /* Analog */
1453 } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1455 outl(0x0, chip->port+GPIO);
1456 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
James Courtier-Duttonc82bf822005-06-04 15:03:06 +02001457 outl(0x005f5301, chip->port+GPIO); /* Analog */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 } else {
1459 outl(0x0, chip->port+GPIO);
1460 outl(0x005f03a3, chip->port+GPIO); /* Analog */
1461 //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
1462 }
1463 snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
1464
1465 //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
1466 //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
1467 //outl(0x00000009, chip->port+HCFG);
1468 outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
1469
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001470 if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001471 int size, n;
1472
1473 size = ARRAY_SIZE(i2c_adc_init);
1474 //snd_printk("I2C:array size=0x%x\n", size);
1475 for (n=0; n < size; n++) {
1476 snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
1477 }
1478 for (n=0; n < 4; n++) {
1479 chip->i2c_capture_volume[n][0]= 0xcf;
1480 chip->i2c_capture_volume[n][1]= 0xcf;
1481 }
1482 chip->i2c_capture_source=2; /* Line in */
1483 //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 +02001484 }
James Courtier-Duttona5875152005-12-20 22:30:49 +01001485 if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001486 int size, n;
1487
1488 size = ARRAY_SIZE(spi_dac_init);
Trent Piephob18cd532007-07-24 12:06:16 +02001489 for (n = 0; n < size; n++) {
1490 int reg = spi_dac_init[n] >> SPI_REG_SHIFT;
1491
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001492 snd_ca0106_spi_write(chip, spi_dac_init[n]);
Trent Piephob18cd532007-07-24 12:06:16 +02001493 if (reg < ARRAY_SIZE(chip->spi_dac_reg))
1494 chip->spi_dac_reg[reg] = spi_dac_init[n];
1495 }
James Courtier-Duttona5875152005-12-20 22:30:49 +01001496 }
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001497
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
1499 chip, &ops)) < 0) {
1500 snd_ca0106_free(chip);
1501 return err;
1502 }
1503 *rchip = chip;
1504 return 0;
1505}
1506
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001507
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001508static void ca0106_midi_interrupt_enable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001509{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001510 snd_ca0106_intr_enable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001511}
1512
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001513static void ca0106_midi_interrupt_disable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001514{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001515 snd_ca0106_intr_disable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001516}
1517
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001518static unsigned char ca0106_midi_read(struct snd_ca_midi *midi, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001519{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001520 return (unsigned char)snd_ca0106_ptr_read((struct snd_ca0106 *)(midi->dev_id),
1521 midi->port + idx, 0);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001522}
1523
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001524static void ca0106_midi_write(struct snd_ca_midi *midi, int data, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001525{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001526 snd_ca0106_ptr_write((struct snd_ca0106 *)(midi->dev_id), midi->port + idx, 0, data);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001527}
1528
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001529static struct snd_card *ca0106_dev_id_card(void *dev_id)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001530{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001531 return ((struct snd_ca0106 *)dev_id)->card;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001532}
1533
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001534static int ca0106_dev_id_port(void *dev_id)
1535{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001536 return ((struct snd_ca0106 *)dev_id)->port;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001537}
1538
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001539static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001540{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001541 struct snd_ca_midi *midi;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001542 char *name;
1543 int err;
1544
Takashi Iwai95a98262005-11-17 10:40:18 +01001545 if (channel == CA0106_MIDI_CHAN_B) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001546 name = "CA0106 MPU-401 (UART) B";
1547 midi = &chip->midi2;
1548 midi->tx_enable = INTE_MIDI_TX_B;
1549 midi->rx_enable = INTE_MIDI_RX_B;
1550 midi->ipr_tx = IPR_MIDI_TX_B;
1551 midi->ipr_rx = IPR_MIDI_RX_B;
1552 midi->port = MIDI_UART_B_DATA;
1553 } else {
1554 name = "CA0106 MPU-401 (UART)";
1555 midi = &chip->midi;
1556 midi->tx_enable = INTE_MIDI_TX_A;
1557 midi->rx_enable = INTE_MIDI_TX_B;
1558 midi->ipr_tx = IPR_MIDI_TX_A;
1559 midi->ipr_rx = IPR_MIDI_RX_A;
1560 midi->port = MIDI_UART_A_DATA;
1561 }
1562
1563 midi->reset = CA0106_MPU401_RESET;
1564 midi->enter_uart = CA0106_MPU401_ENTER_UART;
1565 midi->ack = CA0106_MPU401_ACK;
1566
1567 midi->input_avail = CA0106_MIDI_INPUT_AVAIL;
1568 midi->output_ready = CA0106_MIDI_OUTPUT_READY;
1569
1570 midi->channel = channel;
1571
1572 midi->interrupt_enable = ca0106_midi_interrupt_enable;
1573 midi->interrupt_disable = ca0106_midi_interrupt_disable;
1574
1575 midi->read = ca0106_midi_read;
1576 midi->write = ca0106_midi_write;
1577
1578 midi->get_dev_id_card = ca0106_dev_id_card;
1579 midi->get_dev_id_port = ca0106_dev_id_port;
1580
1581 midi->dev_id = chip;
1582
1583 if ((err = ca_midi_init(chip, midi, 0, name)) < 0)
1584 return err;
1585
1586 return 0;
1587}
1588
1589
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1591 const struct pci_device_id *pci_id)
1592{
1593 static int dev;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001594 struct snd_card *card;
1595 struct snd_ca0106 *chip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 int err;
1597
1598 if (dev >= SNDRV_CARDS)
1599 return -ENODEV;
1600 if (!enable[dev]) {
1601 dev++;
1602 return -ENOENT;
1603 }
1604
1605 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1606 if (card == NULL)
1607 return -ENOMEM;
1608
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001609 if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 snd_card_free(card);
1611 return err;
1612 }
1613
1614 if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
1615 snd_card_free(card);
1616 return err;
1617 }
1618 if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
1619 snd_card_free(card);
1620 return err;
1621 }
1622 if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
1623 snd_card_free(card);
1624 return err;
1625 }
1626 if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
1627 snd_card_free(card);
1628 return err;
1629 }
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001630 if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 if ((err = snd_ca0106_ac97(chip)) < 0) {
1632 snd_card_free(card);
1633 return err;
1634 }
1635 }
1636 if ((err = snd_ca0106_mixer(chip)) < 0) {
1637 snd_card_free(card);
1638 return err;
1639 }
1640
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001641 snd_printdd("ca0106: probe for MIDI channel A ...");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001642 if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
1643 snd_card_free(card);
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001644 snd_printdd(" failed, err=0x%x\n",err);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001645 return err;
1646 }
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001647 snd_printdd(" done.\n");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001648
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001649#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 snd_ca0106_proc_init(chip);
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001651#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
Takashi Iwaic6d6eee2007-02-08 14:50:31 +01001653 snd_card_set_dev(card, &pci->dev);
1654
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 if ((err = snd_card_register(card)) < 0) {
1656 snd_card_free(card);
1657 return err;
1658 }
1659
1660 pci_set_drvdata(pci, card);
1661 dev++;
1662 return 0;
1663}
1664
1665static void __devexit snd_ca0106_remove(struct pci_dev *pci)
1666{
1667 snd_card_free(pci_get_drvdata(pci));
1668 pci_set_drvdata(pci, NULL);
1669}
1670
1671// PCI IDs
Takashi Iwaif40b6892006-07-05 16:51:05 +02001672static struct pci_device_id snd_ca0106_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
1674 { 0, }
1675};
1676MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
1677
1678// pci_driver definition
1679static struct pci_driver driver = {
1680 .name = "CA0106",
1681 .id_table = snd_ca0106_ids,
1682 .probe = snd_ca0106_probe,
1683 .remove = __devexit_p(snd_ca0106_remove),
1684};
1685
1686// initialization of the module
1687static int __init alsa_card_ca0106_init(void)
1688{
Takashi Iwai95a98262005-11-17 10:40:18 +01001689 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690}
1691
1692// clean up the module
1693static void __exit alsa_card_ca0106_exit(void)
1694{
1695 pci_unregister_driver(&driver);
1696}
1697
1698module_init(alsa_card_ca0106_init)
1699module_exit(alsa_card_ca0106_exit)