blob: 36b7cdda7c415e9c414f4c97aef772208fb5290b [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 Piepho48510072007-07-25 18:39:59 +02004 * Version: 0.0.25
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)
Trent Piepho48510072007-07-25 18:39:59 +020084 * 0.0.25
85 * Powerdown SPI DAC channels when not in use
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 *
87 * BUGS:
88 * Some stability problems when unloading the snd-ca0106 kernel module.
89 * --
90 *
91 * TODO:
92 * 4 Capture channels, only one implemented so far.
93 * Other capture rates apart from 48khz not implemented.
94 * MIDI
95 * --
96 * GENERAL INFO:
97 * Model: SB0310
98 * P17 Chip: CA0106-DAT
99 * AC97 Codec: STAC 9721
100 * ADC: Philips 1361T (Stereo 24bit)
101 * DAC: WM8746EDS (6-channel, 24bit, 192Khz)
102 *
103 * GENERAL INFO:
104 * Model: SB0410
105 * P17 Chip: CA0106-DAT
106 * AC97 Codec: None
107 * ADC: WM8775EDS (4 Channel)
108 * DAC: CS4382 (114 dB, 24-Bit, 192 kHz, 8-Channel D/A Converter with DSD Support)
109 * SPDIF Out control switches between Mic in and SPDIF out.
110 * No sound out or mic input working yet.
111 *
112 * GENERAL INFO:
113 * Model: SB0413
114 * P17 Chip: CA0106-DAT
115 * AC97 Codec: None.
116 * ADC: Unknown
117 * DAC: Unknown
118 * Trying to handle it like the SB0410.
119 *
120 * This code was initally based on code from ALSA's emu10k1x.c which is:
121 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
122 *
123 * This program is free software; you can redistribute it and/or modify
124 * it under the terms of the GNU General Public License as published by
125 * the Free Software Foundation; either version 2 of the License, or
126 * (at your option) any later version.
127 *
128 * This program is distributed in the hope that it will be useful,
129 * but WITHOUT ANY WARRANTY; without even the implied warranty of
130 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
131 * GNU General Public License for more details.
132 *
133 * You should have received a copy of the GNU General Public License
134 * along with this program; if not, write to the Free Software
135 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
136 *
137 */
138#include <sound/driver.h>
139#include <linux/delay.h>
140#include <linux/init.h>
141#include <linux/interrupt.h>
142#include <linux/pci.h>
143#include <linux/slab.h>
144#include <linux/moduleparam.h>
Tobias Klauser299676b2005-05-29 15:21:02 +0200145#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146#include <sound/core.h>
147#include <sound/initval.h>
148#include <sound/pcm.h>
149#include <sound/ac97_codec.h>
150#include <sound/info.h>
151
152MODULE_AUTHOR("James Courtier-Dutton <James@superbug.demon.co.uk>");
153MODULE_DESCRIPTION("CA0106");
154MODULE_LICENSE("GPL");
155MODULE_SUPPORTED_DEVICE("{{Creative,SB CA0106 chip}}");
156
157// module parameters (see "Module Parameters")
158static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
159static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
160static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000161static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
163module_param_array(index, int, NULL, 0444);
164MODULE_PARM_DESC(index, "Index value for the CA0106 soundcard.");
165module_param_array(id, charp, NULL, 0444);
166MODULE_PARM_DESC(id, "ID string for the CA0106 soundcard.");
167module_param_array(enable, bool, NULL, 0444);
168MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard.");
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000169module_param_array(subsystem, uint, NULL, 0444);
170MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
172#include "ca0106.h"
173
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100174static struct snd_ca0106_details ca0106_chip_details[] = {
James Courtier-Dutton86326492007-05-18 20:35:50 +0100175 /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
176 /* It is really just a normal SB Live 24bit. */
James Courtier-Duttonaaccf542007-07-23 18:12:41 +0100177 /* Tested:
178 * See ALSA bug#3251
179 */
180 { .serial = 0x10131102,
181 .name = "X-Fi Extreme Audio [SBxxxx]",
182 .gpio_type = 1,
183 .i2c_adc = 1 } ,
184 /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
185 /* It is really just a normal SB Live 24bit. */
James Courtier-Dutton86326492007-05-18 20:35:50 +0100186 /*
187 * CTRL:CA0111-WTLF
188 * ADC: WM8775SEDS
189 * DAC: CS4382-KQZ
190 */
191 /* Tested:
192 * Playback on front, rear, center/lfe speakers
193 * Capture from Mic in.
194 * Not-Tested:
195 * Capture from Line in.
196 * Playback to digital out.
197 */
198 { .serial = 0x10121102,
199 .name = "X-Fi Extreme Audio [SB0790]",
200 .gpio_type = 1,
201 .i2c_adc = 1 } ,
202 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200203 /* AudigyLS[SB0310] */
204 { .serial = 0x10021102,
205 .name = "AudigyLS [SB0310]",
206 .ac97 = 1 } ,
207 /* Unknown AudigyLS that also says SB0310 on it */
208 { .serial = 0x10051102,
209 .name = "AudigyLS [SB0310b]",
210 .ac97 = 1 } ,
211 /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
212 { .serial = 0x10061102,
213 .name = "Live! 7.1 24bit [SB0410]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200214 .gpio_type = 1,
215 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200216 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
217 { .serial = 0x10071102,
218 .name = "Live! 7.1 24bit [SB0413]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200219 .gpio_type = 1,
220 .i2c_adc = 1 } ,
James Courtier-Duttona5875152005-12-20 22:30:49 +0100221 /* New Audigy SE. Has a different DAC. */
222 /* SB0570:
223 * CTRL:CA0106-DAT
James Courtier-Dutton58398892006-06-10 09:16:49 +0100224 * ADC: WM8775EDS
225 * DAC: WM8768GEDS
James Courtier-Duttona5875152005-12-20 22:30:49 +0100226 */
227 { .serial = 0x100a1102,
228 .name = "Audigy SE [SB0570]",
229 .gpio_type = 1,
230 .i2c_adc = 1,
231 .spi_dac = 1 } ,
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000232 /* New Audigy LS. Has a different DAC. */
233 /* SB0570:
234 * CTRL:CA0106-DAT
235 * ADC: WM8775EDS
236 * DAC: WM8768GEDS
237 */
238 { .serial = 0x10111102,
James Courtier-Duttond5f6a382006-11-25 19:50:11 +0000239 .name = "Audigy SE OEM [SB0570a]",
James Courtier-Duttone4f55d82006-11-25 19:42:29 +0000240 .gpio_type = 1,
241 .i2c_adc = 1,
242 .spi_dac = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200243 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100244 /* SB0438
245 * CTRL:CA0106-DAT
246 * ADC: WM8775SEDS
247 * DAC: CS4382-KQZ
248 */
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200249 { .serial = 0x10091462,
250 .name = "MSI K8N Diamond MB [SB0438]",
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100251 .gpio_type = 2,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200252 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100253 /* Shuttle XPC SD31P which has an onboard Creative Labs
254 * Sound Blaster Live! 24-bit EAX
James Courtier-Dutton1b059622005-08-12 23:50:13 +0200255 * high-definition 7.1 audio processor".
256 * Added using info from andrewvegan in alsa bug #1298
257 */
258 { .serial = 0x30381297,
259 .name = "Shuttle XPC SD31P [SD31P]",
260 .gpio_type = 1,
261 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100262 /* Shuttle XPC SD11G5 which has an onboard Creative Labs
263 * Sound Blaster Live! 24-bit EAX
264 * high-definition 7.1 audio processor".
265 * Fixes ALSA bug#1600
266 */
267 { .serial = 0x30411297,
268 .name = "Shuttle XPC SD11G5 [SD11G5]",
269 .gpio_type = 1,
270 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200271 { .serial = 0,
272 .name = "AudigyLS [Unknown]" }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273};
274
275/* hardware definition */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100276static struct snd_pcm_hardware snd_ca0106_playback_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 .info = (SNDRV_PCM_INFO_MMAP |
278 SNDRV_PCM_INFO_INTERLEAVED |
279 SNDRV_PCM_INFO_BLOCK_TRANSFER |
280 SNDRV_PCM_INFO_MMAP_VALID),
281 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100282 .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
283 SNDRV_PCM_RATE_192000),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 .rate_min = 48000,
285 .rate_max = 192000,
286 .channels_min = 2, //1,
287 .channels_max = 2, //6,
288 .buffer_bytes_max = ((65536 - 64) * 8),
289 .period_bytes_min = 64,
290 .period_bytes_max = (65536 - 64),
291 .periods_min = 2,
292 .periods_max = 8,
293 .fifo_size = 0,
294};
295
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100296static struct snd_pcm_hardware snd_ca0106_capture_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 .info = (SNDRV_PCM_INFO_MMAP |
298 SNDRV_PCM_INFO_INTERLEAVED |
299 SNDRV_PCM_INFO_BLOCK_TRANSFER |
300 SNDRV_PCM_INFO_MMAP_VALID),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200301 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100302 .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
303 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200304 .rate_min = 44100,
305 .rate_max = 192000,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 .channels_min = 2,
307 .channels_max = 2,
308 .buffer_bytes_max = ((65536 - 64) * 8),
309 .period_bytes_min = 64,
310 .period_bytes_max = (65536 - 64),
311 .periods_min = 2,
312 .periods_max = 2,
313 .fifo_size = 0,
314};
315
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100316unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 unsigned int reg,
318 unsigned int chn)
319{
320 unsigned long flags;
321 unsigned int regptr, val;
322
323 regptr = (reg << 16) | chn;
324
325 spin_lock_irqsave(&emu->emu_lock, flags);
326 outl(regptr, emu->port + PTR);
327 val = inl(emu->port + DATA);
328 spin_unlock_irqrestore(&emu->emu_lock, flags);
329 return val;
330}
331
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100332void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 unsigned int reg,
334 unsigned int chn,
335 unsigned int data)
336{
337 unsigned int regptr;
338 unsigned long flags;
339
340 regptr = (reg << 16) | chn;
341
342 spin_lock_irqsave(&emu->emu_lock, flags);
343 outl(regptr, emu->port + PTR);
344 outl(data, emu->port + DATA);
345 spin_unlock_irqrestore(&emu->emu_lock, flags);
346}
347
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100348int snd_ca0106_spi_write(struct snd_ca0106 * emu,
349 unsigned int data)
James Courtier-Duttona5875152005-12-20 22:30:49 +0100350{
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100351 unsigned int reset, set;
352 unsigned int reg, tmp;
353 int n, result;
354 reg = SPI;
355 if (data > 0xffff) /* Only 16bit values allowed */
356 return 1;
357 tmp = snd_ca0106_ptr_read(emu, reg, 0);
358 reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
359 set = reset | 0x10000; /* Set xxx1xxxx */
360 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
361 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* write post */
362 snd_ca0106_ptr_write(emu, reg, 0, set | data);
363 result = 1;
364 /* Wait for status bit to return to 0 */
365 for (n = 0; n < 100; n++) {
366 udelay(10);
367 tmp = snd_ca0106_ptr_read(emu, reg, 0);
368 if (!(tmp & 0x10000)) {
369 result = 0;
370 break;
371 }
372 }
373 if (result) /* Timed out */
374 return 1;
375 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
376 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* Write post */
James Courtier-Duttona5875152005-12-20 22:30:49 +0100377 return 0;
378}
379
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100380/* The ADC does not support i2c read, so only write is implemented */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100381int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200382 u32 reg,
383 u32 value)
384{
385 u32 tmp;
Takashi Iwai95a98262005-11-17 10:40:18 +0100386 int timeout = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200387 int status;
388 int retry;
Takashi Iwai95a98262005-11-17 10:40:18 +0100389 if ((reg > 0x7f) || (value > 0x1ff)) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200390 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200391 return -EINVAL;
392 }
393
394 tmp = reg << 25 | value << 16;
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100395 // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
James Courtier-Dutton8fabab12005-05-28 16:35:49 +0200396 /* Not sure what this I2C channel controls. */
397 /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
398
399 /* This controls the I2C connected to the WM8775 ADC Codec */
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200400 snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
401
Takashi Iwai95a98262005-11-17 10:40:18 +0100402 for (retry = 0; retry < 10; retry++) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200403 /* Send the data to i2c */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100404 //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
405 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
406 tmp = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200407 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
408 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
409
410 /* Wait till the transaction ends */
Takashi Iwai95a98262005-11-17 10:40:18 +0100411 while (1) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200412 status = snd_ca0106_ptr_read(emu, I2C_A, 0);
413 //snd_printk("I2C:status=0x%x\n", status);
414 timeout++;
Takashi Iwai95a98262005-11-17 10:40:18 +0100415 if ((status & I2C_A_ADC_START) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200416 break;
417
Takashi Iwai95a98262005-11-17 10:40:18 +0100418 if (timeout > 1000)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200419 break;
420 }
421 //Read back and see if the transaction is successful
Takashi Iwai95a98262005-11-17 10:40:18 +0100422 if ((status & I2C_A_ADC_ABORT) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200423 break;
424 }
425
Takashi Iwai95a98262005-11-17 10:40:18 +0100426 if (retry == 10) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200427 snd_printk(KERN_ERR "Writing to ADC failed!\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200428 return -EINVAL;
429 }
430
431 return 0;
432}
433
434
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100435static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436{
437 unsigned long flags;
438 unsigned int enable;
439
440 spin_lock_irqsave(&emu->emu_lock, flags);
441 enable = inl(emu->port + INTE) | intrenb;
442 outl(enable, emu->port + INTE);
443 spin_unlock_irqrestore(&emu->emu_lock, flags);
444}
445
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100446static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +0200447{
448 unsigned long flags;
449 unsigned int enable;
450
451 spin_lock_irqsave(&emu->emu_lock, flags);
452 enable = inl(emu->port + INTE) & ~intrenb;
453 outl(enable, emu->port + INTE);
454 spin_unlock_irqrestore(&emu->emu_lock, flags);
455}
456
457
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100458static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
Jesper Juhl4d572772005-05-30 17:30:32 +0200460 kfree(runtime->private_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461}
462
Trent Piepho48510072007-07-25 18:39:59 +0200463static const int spi_dacd_reg[] = {
464 [PCM_FRONT_CHANNEL] = SPI_DACD4_REG,
465 [PCM_REAR_CHANNEL] = SPI_DACD0_REG,
466 [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_REG,
467 [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_REG,
468};
469static const int spi_dacd_bit[] = {
470 [PCM_FRONT_CHANNEL] = 1<<SPI_DACD4_BIT,
471 [PCM_REAR_CHANNEL] = 1<<SPI_DACD0_BIT,
472 [PCM_CENTER_LFE_CHANNEL]= 1<<SPI_DACD2_BIT,
473 [PCM_UNKNOWN_CHANNEL] = 1<<SPI_DACD1_BIT,
474};
475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476/* open_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100477static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
478 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100480 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
481 struct snd_ca0106_channel *channel = &(chip->playback_channels[channel_id]);
482 struct snd_ca0106_pcm *epcm;
483 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 int err;
485
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200486 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 if (epcm == NULL)
489 return -ENOMEM;
490 epcm->emu = chip;
491 epcm->substream = substream;
492 epcm->channel_id=channel_id;
493
494 runtime->private_data = epcm;
495 runtime->private_free = snd_ca0106_pcm_free_substream;
496
497 runtime->hw = snd_ca0106_playback_hw;
498
499 channel->emu = chip;
500 channel->number = channel_id;
501
Takashi Iwai95a98262005-11-17 10:40:18 +0100502 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
504 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwai95a98262005-11-17 10:40:18 +0100505 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
507 return err;
508 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
509 return err;
Trent Piepho48510072007-07-25 18:39:59 +0200510
511 if (chip->details->spi_dac && channel_id != PCM_FRONT_CHANNEL) {
512 const int reg = spi_dacd_reg[channel_id];
513
514 /* Power up dac */
515 chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id];
516 err = snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
517 if (err < 0)
518 return err;
519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 return 0;
521}
522
523/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100524static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100526 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
527 struct snd_pcm_runtime *runtime = substream->runtime;
528 struct snd_ca0106_pcm *epcm = runtime->private_data;
529 chip->playback_channels[epcm->channel_id].use = 0;
Trent Piepho48510072007-07-25 18:39:59 +0200530
531 if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) {
532 const int reg = spi_dacd_reg[epcm->channel_id];
533
534 /* Power down DAC */
535 chip->spi_dac_reg[reg] |= spi_dacd_bit[epcm->channel_id];
536 snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
537 }
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100538 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 return 0;
540}
541
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100542static int snd_ca0106_pcm_open_playback_front(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
544 return snd_ca0106_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
545}
546
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100547static int snd_ca0106_pcm_open_playback_center_lfe(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548{
549 return snd_ca0106_pcm_open_playback_channel(substream, PCM_CENTER_LFE_CHANNEL);
550}
551
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100552static int snd_ca0106_pcm_open_playback_unknown(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553{
554 return snd_ca0106_pcm_open_playback_channel(substream, PCM_UNKNOWN_CHANNEL);
555}
556
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100557static int snd_ca0106_pcm_open_playback_rear(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
559 return snd_ca0106_pcm_open_playback_channel(substream, PCM_REAR_CHANNEL);
560}
561
562/* open_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100563static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substream,
564 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100566 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
567 struct snd_ca0106_channel *channel = &(chip->capture_channels[channel_id]);
568 struct snd_ca0106_pcm *epcm;
569 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 int err;
571
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200572 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 if (epcm == NULL) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200574 snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 return -ENOMEM;
576 }
577 epcm->emu = chip;
578 epcm->substream = substream;
579 epcm->channel_id=channel_id;
580
581 runtime->private_data = epcm;
582 runtime->private_free = snd_ca0106_pcm_free_substream;
583
584 runtime->hw = snd_ca0106_capture_hw;
585
586 channel->emu = chip;
587 channel->number = channel_id;
588
Takashi Iwai95a98262005-11-17 10:40:18 +0100589 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
591 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100592 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
594 return err;
595 //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
596 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
597 return err;
598 return 0;
599}
600
601/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100602static int snd_ca0106_pcm_close_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100604 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
605 struct snd_pcm_runtime *runtime = substream->runtime;
606 struct snd_ca0106_pcm *epcm = runtime->private_data;
607 chip->capture_channels[epcm->channel_id].use = 0;
608 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 return 0;
610}
611
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100612static int snd_ca0106_pcm_open_0_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613{
614 return snd_ca0106_pcm_open_capture_channel(substream, 0);
615}
616
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100617static int snd_ca0106_pcm_open_1_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618{
619 return snd_ca0106_pcm_open_capture_channel(substream, 1);
620}
621
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100622static int snd_ca0106_pcm_open_2_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
624 return snd_ca0106_pcm_open_capture_channel(substream, 2);
625}
626
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100627static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
629 return snd_ca0106_pcm_open_capture_channel(substream, 3);
630}
631
632/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100633static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream,
634 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635{
636 return snd_pcm_lib_malloc_pages(substream,
637 params_buffer_bytes(hw_params));
638}
639
640/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100641static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
643 return snd_pcm_lib_free_pages(substream);
644}
645
646/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100647static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream,
648 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649{
650 return snd_pcm_lib_malloc_pages(substream,
651 params_buffer_bytes(hw_params));
652}
653
654/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100655static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656{
657 return snd_pcm_lib_free_pages(substream);
658}
659
660/* prepare playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100661static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100663 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
664 struct snd_pcm_runtime *runtime = substream->runtime;
665 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 int channel = epcm->channel_id;
667 u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
668 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
669 u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
670 u32 hcfg_set = 0x00000000;
671 u32 hcfg;
672 u32 reg40_mask = 0x30000 << (channel<<1);
673 u32 reg40_set = 0;
674 u32 reg40;
675 /* FIXME: Depending on mixer selection of SPDIF out or not, select the spdif rate or the DAC rate. */
676 u32 reg71_mask = 0x03030000 ; /* Global. Set SPDIF rate. We only support 44100 to spdif, not to DAC. */
677 u32 reg71_set = 0;
678 u32 reg71;
679 int i;
680
681 //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));
682 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
683 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
684 /* Rate can be set per channel. */
685 /* reg40 control host to fifo */
686 /* reg71 controls DAC rate. */
687 switch (runtime->rate) {
688 case 44100:
689 reg40_set = 0x10000 << (channel<<1);
690 reg71_set = 0x01010000;
691 break;
692 case 48000:
693 reg40_set = 0;
694 reg71_set = 0;
695 break;
696 case 96000:
697 reg40_set = 0x20000 << (channel<<1);
698 reg71_set = 0x02020000;
699 break;
700 case 192000:
701 reg40_set = 0x30000 << (channel<<1);
702 reg71_set = 0x03030000;
703 break;
704 default:
705 reg40_set = 0;
706 reg71_set = 0;
707 break;
708 }
709 /* Format is a global setting */
710 /* FIXME: Only let the first channel accessed set this. */
711 switch (runtime->format) {
712 case SNDRV_PCM_FORMAT_S16_LE:
713 hcfg_set = 0;
714 break;
715 case SNDRV_PCM_FORMAT_S32_LE:
716 hcfg_set = HCFG_PLAYBACK_S32_LE;
717 break;
718 default:
719 hcfg_set = 0;
720 break;
721 }
722 hcfg = inl(emu->port + HCFG) ;
723 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
724 outl(hcfg, emu->port + HCFG);
725 reg40 = snd_ca0106_ptr_read(emu, 0x40, 0);
726 reg40 = (reg40 & ~reg40_mask) | reg40_set;
727 snd_ca0106_ptr_write(emu, 0x40, 0, reg40);
728 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
729 reg71 = (reg71 & ~reg71_mask) | reg71_set;
730 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
731
732 /* FIXME: Check emu->buffer.size before actually writing to it. */
733 for(i=0; i < runtime->periods; i++) {
Takashi Iwai95a98262005-11-17 10:40:18 +0100734 table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
735 table_base[i*2+1] = period_size_bytes << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 }
737
738 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
739 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
740 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
741 snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
742 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
743 /* FIXME test what 0 bytes does. */
744 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
745 snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
746 snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
747 snd_ca0106_ptr_write(emu, 0x08, channel, 0);
748 snd_ca0106_ptr_write(emu, PLAYBACK_MUTE, 0x0, 0x0); /* Unmute output */
749#if 0
750 snd_ca0106_ptr_write(emu, SPCS0, 0,
751 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
752 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
753 SPCS_GENERATIONSTATUS | 0x00001200 |
754 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
755 }
756#endif
757
758 return 0;
759}
760
761/* prepare capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100762static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100764 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
765 struct snd_pcm_runtime *runtime = substream->runtime;
766 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 int channel = epcm->channel_id;
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200768 u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
769 u32 hcfg_set = 0x00000000;
770 u32 hcfg;
771 u32 over_sampling=0x2;
772 u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
773 u32 reg71_set = 0;
774 u32 reg71;
775
776 //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));
777 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
778 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
779 /* reg71 controls ADC rate. */
780 switch (runtime->rate) {
781 case 44100:
782 reg71_set = 0x00004000;
783 break;
784 case 48000:
785 reg71_set = 0;
786 break;
787 case 96000:
788 reg71_set = 0x00008000;
789 over_sampling=0xa;
790 break;
791 case 192000:
792 reg71_set = 0x0000c000;
793 over_sampling=0xa;
794 break;
795 default:
796 reg71_set = 0;
797 break;
798 }
799 /* Format is a global setting */
800 /* FIXME: Only let the first channel accessed set this. */
801 switch (runtime->format) {
802 case SNDRV_PCM_FORMAT_S16_LE:
803 hcfg_set = 0;
804 break;
805 case SNDRV_PCM_FORMAT_S32_LE:
806 hcfg_set = HCFG_CAPTURE_S32_LE;
807 break;
808 default:
809 hcfg_set = 0;
810 break;
811 }
812 hcfg = inl(emu->port + HCFG) ;
813 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
814 outl(hcfg, emu->port + HCFG);
815 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
816 reg71 = (reg71 & ~reg71_mask) | reg71_set;
817 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
818 if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
819 snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
820 }
821
822
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 //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));
824 snd_ca0106_ptr_write(emu, 0x13, channel, 0);
825 snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
826 snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
827 snd_ca0106_ptr_write(emu, CAPTURE_POINTER, channel, 0);
828
829 return 0;
830}
831
832/* trigger_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100833static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 int cmd)
835{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100836 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
837 struct snd_pcm_runtime *runtime;
838 struct snd_ca0106_pcm *epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 int channel;
840 int result = 0;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100841 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 u32 basic = 0;
843 u32 extended = 0;
844 int running=0;
845
846 switch (cmd) {
847 case SNDRV_PCM_TRIGGER_START:
848 running=1;
849 break;
850 case SNDRV_PCM_TRIGGER_STOP:
851 default:
852 running=0;
853 break;
854 }
Takashi Iwaief991b92007-02-22 12:52:53 +0100855 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 runtime = s->runtime;
857 epcm = runtime->private_data;
858 channel = epcm->channel_id;
859 //snd_printk("channel=%d\n",channel);
860 epcm->running = running;
861 basic |= (0x1<<channel);
862 extended |= (0x10<<channel);
863 snd_pcm_trigger_done(s, substream);
864 }
865 //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
866
867 switch (cmd) {
868 case SNDRV_PCM_TRIGGER_START:
869 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
870 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
871 break;
872 case SNDRV_PCM_TRIGGER_STOP:
873 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
874 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
875 break;
876 default:
877 result = -EINVAL;
878 break;
879 }
880 return result;
881}
882
883/* trigger_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100884static int snd_ca0106_pcm_trigger_capture(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 int cmd)
886{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100887 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
888 struct snd_pcm_runtime *runtime = substream->runtime;
889 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 int channel = epcm->channel_id;
891 int result = 0;
892
893 switch (cmd) {
894 case SNDRV_PCM_TRIGGER_START:
895 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
896 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
897 epcm->running = 1;
898 break;
899 case SNDRV_PCM_TRIGGER_STOP:
900 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
901 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
902 epcm->running = 0;
903 break;
904 default:
905 result = -EINVAL;
906 break;
907 }
908 return result;
909}
910
911/* pointer_playback callback */
912static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100913snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100915 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
916 struct snd_pcm_runtime *runtime = substream->runtime;
917 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
919 int channel = epcm->channel_id;
920
921 if (!epcm->running)
922 return 0;
923
924 ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
925 ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
926 ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
927 if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
928 ptr2 = bytes_to_frames(runtime, ptr1);
929 ptr2+= (ptr4 >> 3) * runtime->period_size;
930 ptr=ptr2;
931 if (ptr >= runtime->buffer_size)
932 ptr -= runtime->buffer_size;
933 //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);
934
935 return ptr;
936}
937
938/* pointer_capture callback */
939static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100940snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100942 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
943 struct snd_pcm_runtime *runtime = substream->runtime;
944 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
946 int channel = channel=epcm->channel_id;
947
948 if (!epcm->running)
949 return 0;
950
951 ptr1 = snd_ca0106_ptr_read(emu, CAPTURE_POINTER, channel);
952 ptr2 = bytes_to_frames(runtime, ptr1);
953 ptr=ptr2;
954 if (ptr >= runtime->buffer_size)
955 ptr -= runtime->buffer_size;
956 //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);
957
958 return ptr;
959}
960
961/* operators */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100962static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 .open = snd_ca0106_pcm_open_playback_front,
964 .close = snd_ca0106_pcm_close_playback,
965 .ioctl = snd_pcm_lib_ioctl,
966 .hw_params = snd_ca0106_pcm_hw_params_playback,
967 .hw_free = snd_ca0106_pcm_hw_free_playback,
968 .prepare = snd_ca0106_pcm_prepare_playback,
969 .trigger = snd_ca0106_pcm_trigger_playback,
970 .pointer = snd_ca0106_pcm_pointer_playback,
971};
972
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100973static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 .open = snd_ca0106_pcm_open_0_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_capture_1_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 .open = snd_ca0106_pcm_open_1_capture,
986 .close = snd_ca0106_pcm_close_capture,
987 .ioctl = snd_pcm_lib_ioctl,
988 .hw_params = snd_ca0106_pcm_hw_params_capture,
989 .hw_free = snd_ca0106_pcm_hw_free_capture,
990 .prepare = snd_ca0106_pcm_prepare_capture,
991 .trigger = snd_ca0106_pcm_trigger_capture,
992 .pointer = snd_ca0106_pcm_pointer_capture,
993};
994
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100995static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 .open = snd_ca0106_pcm_open_2_capture,
997 .close = snd_ca0106_pcm_close_capture,
998 .ioctl = snd_pcm_lib_ioctl,
999 .hw_params = snd_ca0106_pcm_hw_params_capture,
1000 .hw_free = snd_ca0106_pcm_hw_free_capture,
1001 .prepare = snd_ca0106_pcm_prepare_capture,
1002 .trigger = snd_ca0106_pcm_trigger_capture,
1003 .pointer = snd_ca0106_pcm_pointer_capture,
1004};
1005
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001006static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 .open = snd_ca0106_pcm_open_3_capture,
1008 .close = snd_ca0106_pcm_close_capture,
1009 .ioctl = snd_pcm_lib_ioctl,
1010 .hw_params = snd_ca0106_pcm_hw_params_capture,
1011 .hw_free = snd_ca0106_pcm_hw_free_capture,
1012 .prepare = snd_ca0106_pcm_prepare_capture,
1013 .trigger = snd_ca0106_pcm_trigger_capture,
1014 .pointer = snd_ca0106_pcm_pointer_capture,
1015};
1016
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001017static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 .open = snd_ca0106_pcm_open_playback_center_lfe,
1019 .close = snd_ca0106_pcm_close_playback,
1020 .ioctl = snd_pcm_lib_ioctl,
1021 .hw_params = snd_ca0106_pcm_hw_params_playback,
1022 .hw_free = snd_ca0106_pcm_hw_free_playback,
1023 .prepare = snd_ca0106_pcm_prepare_playback,
1024 .trigger = snd_ca0106_pcm_trigger_playback,
1025 .pointer = snd_ca0106_pcm_pointer_playback,
1026};
1027
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001028static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 .open = snd_ca0106_pcm_open_playback_unknown,
1030 .close = snd_ca0106_pcm_close_playback,
1031 .ioctl = snd_pcm_lib_ioctl,
1032 .hw_params = snd_ca0106_pcm_hw_params_playback,
1033 .hw_free = snd_ca0106_pcm_hw_free_playback,
1034 .prepare = snd_ca0106_pcm_prepare_playback,
1035 .trigger = snd_ca0106_pcm_trigger_playback,
1036 .pointer = snd_ca0106_pcm_pointer_playback,
1037};
1038
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001039static struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 .open = snd_ca0106_pcm_open_playback_rear,
1041 .close = snd_ca0106_pcm_close_playback,
1042 .ioctl = snd_pcm_lib_ioctl,
1043 .hw_params = snd_ca0106_pcm_hw_params_playback,
1044 .hw_free = snd_ca0106_pcm_hw_free_playback,
1045 .prepare = snd_ca0106_pcm_prepare_playback,
1046 .trigger = snd_ca0106_pcm_trigger_playback,
1047 .pointer = snd_ca0106_pcm_pointer_playback,
1048};
1049
1050
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001051static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 unsigned short reg)
1053{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001054 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 unsigned long flags;
1056 unsigned short val;
1057
1058 spin_lock_irqsave(&emu->emu_lock, flags);
1059 outb(reg, emu->port + AC97ADDRESS);
1060 val = inw(emu->port + AC97DATA);
1061 spin_unlock_irqrestore(&emu->emu_lock, flags);
1062 return val;
1063}
1064
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001065static void snd_ca0106_ac97_write(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 unsigned short reg, unsigned short val)
1067{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001068 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 unsigned long flags;
1070
1071 spin_lock_irqsave(&emu->emu_lock, flags);
1072 outb(reg, emu->port + AC97ADDRESS);
1073 outw(val, emu->port + AC97DATA);
1074 spin_unlock_irqrestore(&emu->emu_lock, flags);
1075}
1076
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001077static int snd_ca0106_ac97(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001079 struct snd_ac97_bus *pbus;
1080 struct snd_ac97_template ac97;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 int err;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001082 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 .write = snd_ca0106_ac97_write,
1084 .read = snd_ca0106_ac97_read,
1085 };
1086
1087 if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
1088 return err;
1089 pbus->no_vra = 1; /* we don't need VRA */
1090
1091 memset(&ac97, 0, sizeof(ac97));
1092 ac97.private_data = chip;
Takashi Iwai36c4dc42005-03-24 17:48:30 +01001093 ac97.scaps = AC97_SCAP_NO_SPDIF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
1095}
1096
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001097static int snd_ca0106_free(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098{
1099 if (chip->res_port != NULL) { /* avoid access to already used hardware */
1100 // disable interrupts
1101 snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
1102 outl(0, chip->port + INTE);
1103 snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
1104 udelay(1000);
1105 // disable audio
1106 //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
1107 outl(0, chip->port + HCFG);
1108 /* FIXME: We need to stop and DMA transfers here.
1109 * But as I am not sure how yet, we cannot from the dma pages.
1110 * So we can fix: snd-malloc: Memory leak? pages not freed = 8
1111 */
1112 }
1113 // release the data
1114#if 1
1115 if (chip->buffer.area)
1116 snd_dma_free_pages(&chip->buffer);
1117#endif
1118
1119 // release the i/o port
Takashi Iwaib1d57762005-10-10 11:56:31 +02001120 release_and_free_resource(chip->res_port);
1121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 // release the irq
1123 if (chip->irq >= 0)
Takashi Iwai437a5a42006-11-21 12:14:23 +01001124 free_irq(chip->irq, chip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 pci_disable_device(chip->pci);
1126 kfree(chip);
1127 return 0;
1128}
1129
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001130static int snd_ca0106_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001132 struct snd_ca0106 *chip = device->device_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 return snd_ca0106_free(chip);
1134}
1135
David Howells7d12e782006-10-05 14:55:46 +01001136static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137{
1138 unsigned int status;
1139
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001140 struct snd_ca0106 *chip = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 int i;
1142 int mask;
1143 unsigned int stat76;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001144 struct snd_ca0106_channel *pchannel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 status = inl(chip->port + IPR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 if (! status)
1148 return IRQ_NONE;
1149
1150 stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0);
1151 //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76);
1152 //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0));
1153 mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
1154 for(i = 0; i < 4; i++) {
1155 pchannel = &(chip->playback_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001156 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157/* FIXME: Select the correct substream for period elapsed */
1158 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001159 snd_pcm_period_elapsed(pchannel->epcm->substream);
1160 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 }
1162 }
1163 //printk(KERN_INFO "channel=%p\n",pchannel);
1164 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1165 mask <<= 1;
1166 }
1167 mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */
1168 for(i = 0; i < 4; i++) {
1169 pchannel = &(chip->capture_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001170 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171/* FIXME: Select the correct substream for period elapsed */
1172 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001173 snd_pcm_period_elapsed(pchannel->epcm->substream);
1174 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 }
1176 }
1177 //printk(KERN_INFO "channel=%p\n",pchannel);
1178 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1179 mask <<= 1;
1180 }
1181
1182 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001183
1184 if (chip->midi.dev_id &&
Takashi Iwai95a98262005-11-17 10:40:18 +01001185 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001186 if (chip->midi.interrupt)
1187 chip->midi.interrupt(&chip->midi, status);
1188 else
1189 chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable);
1190 }
1191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 // acknowledge the interrupt if necessary
1193 outl(status, chip->port+IPR);
1194
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 return IRQ_HANDLED;
1196}
1197
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001198static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001200 struct snd_pcm *pcm;
1201 struct snd_pcm_substream *substream;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 int err;
1203
1204 if (rpcm)
1205 *rpcm = NULL;
1206 if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
1207 return err;
1208
1209 pcm->private_data = emu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 switch (device) {
1212 case 0:
1213 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops);
1214 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops);
1215 break;
1216 case 1:
1217 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops);
1218 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops);
1219 break;
1220 case 2:
1221 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops);
1222 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops);
1223 break;
1224 case 3:
1225 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops);
1226 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops);
1227 break;
1228 }
1229
1230 pcm->info_flags = 0;
1231 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
1232 strcpy(pcm->name, "CA0106");
1233 emu->pcm = pcm;
1234
1235 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1236 substream;
1237 substream = substream->next) {
1238 if ((err = snd_pcm_lib_preallocate_pages(substream,
1239 SNDRV_DMA_TYPE_DEV,
1240 snd_dma_pci_data(emu->pci),
1241 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
1242 return err;
1243 }
1244
1245 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1246 substream;
1247 substream = substream->next) {
1248 if ((err = snd_pcm_lib_preallocate_pages(substream,
1249 SNDRV_DMA_TYPE_DEV,
1250 snd_dma_pci_data(emu->pci),
1251 64*1024, 64*1024)) < 0)
1252 return err;
1253 }
1254
1255 if (rpcm)
1256 *rpcm = pcm;
1257
1258 return 0;
1259}
1260
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001261static unsigned int spi_dac_init[] = {
1262 0x00ff,
1263 0x02ff,
1264 0x0400,
1265 0x0520,
James Courtier-Dutton58398892006-06-10 09:16:49 +01001266 0x0620, /* Set 24 bit. Was 0x0600 */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001267 0x08ff,
1268 0x0aff,
1269 0x0cff,
1270 0x0eff,
1271 0x10ff,
1272 0x1200,
1273 0x1400,
1274 0x1480,
1275 0x1800,
1276 0x1aff,
1277 0x1cff,
1278 0x1e00,
1279 0x0530,
1280 0x0602,
1281 0x0622,
Trent Piepho48510072007-07-25 18:39:59 +02001282 0x140e,
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001283};
1284
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001285static unsigned int i2c_adc_init[][2] = {
1286 { 0x17, 0x00 }, /* Reset */
1287 { 0x07, 0x00 }, /* Timeout */
1288 { 0x0b, 0x22 }, /* Interface control */
1289 { 0x0c, 0x22 }, /* Master mode control */
1290 { 0x0d, 0x08 }, /* Powerdown control */
1291 { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
1292 { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */
1293 { 0x10, 0x7b }, /* ALC Control 1 */
1294 { 0x11, 0x00 }, /* ALC Control 2 */
1295 { 0x12, 0x32 }, /* ALC Control 3 */
1296 { 0x13, 0x00 }, /* Noise gate control */
1297 { 0x14, 0xa6 }, /* Limiter control */
1298 { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
1299};
1300
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001301static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 struct pci_dev *pci,
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001303 struct snd_ca0106 **rchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001305 struct snd_ca0106 *chip;
1306 struct snd_ca0106_details *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 int err;
1308 int ch;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001309 static struct snd_device_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 .dev_free = snd_ca0106_dev_free,
1311 };
1312
1313 *rchip = NULL;
1314
1315 if ((err = pci_enable_device(pci)) < 0)
1316 return err;
Tobias Klauser299676b2005-05-29 15:21:02 +02001317 if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
1318 pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 printk(KERN_ERR "error to set 32bit mask DMA\n");
1320 pci_disable_device(pci);
1321 return -ENXIO;
1322 }
1323
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001324 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 if (chip == NULL) {
1326 pci_disable_device(pci);
1327 return -ENOMEM;
1328 }
1329
1330 chip->card = card;
1331 chip->pci = pci;
1332 chip->irq = -1;
1333
1334 spin_lock_init(&chip->emu_lock);
1335
1336 chip->port = pci_resource_start(pci, 0);
1337 if ((chip->res_port = request_region(chip->port, 0x20,
1338 "snd_ca0106")) == NULL) {
1339 snd_ca0106_free(chip);
1340 printk(KERN_ERR "cannot allocate the port\n");
1341 return -EBUSY;
1342 }
1343
1344 if (request_irq(pci->irq, snd_ca0106_interrupt,
Takashi Iwai437a5a42006-11-21 12:14:23 +01001345 IRQF_SHARED, "snd_ca0106", chip)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 snd_ca0106_free(chip);
1347 printk(KERN_ERR "cannot grab irq\n");
1348 return -EBUSY;
1349 }
1350 chip->irq = pci->irq;
1351
1352 /* This stores the periods table. */
1353 if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
1354 snd_ca0106_free(chip);
1355 return -ENOMEM;
1356 }
1357
1358 pci_set_master(pci);
Auke Kok44c10132007-06-08 15:46:36 -07001359 /* read serial */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
1361 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
1362#if 1
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001363 printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
Auke Kok44c10132007-06-08 15:46:36 -07001364 pci->revision, chip->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365#endif
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001366 strcpy(card->driver, "CA0106");
1367 strcpy(card->shortname, "CA0106");
1368
Takashi Iwai95a98262005-11-17 10:40:18 +01001369 for (c = ca0106_chip_details; c->serial; c++) {
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001370 if (subsystem[dev]) {
1371 if (c->serial == subsystem[dev])
1372 break;
1373 } else if (c->serial == chip->serial)
Takashi Iwai95a98262005-11-17 10:40:18 +01001374 break;
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001375 }
1376 chip->details = c;
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001377 if (subsystem[dev]) {
James Courtier-Duttond5f6a382006-11-25 19:50:11 +00001378 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 +00001379 c->name, chip->serial, subsystem[dev]);
1380 }
1381
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001382 sprintf(card->longname, "%s at 0x%lx irq %i",
1383 c->name, chip->port, chip->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
1385 outl(0, chip->port + INTE);
1386
1387 /*
1388 * Init to 0x02109204 :
1389 * Clock accuracy = 0 (1000ppm)
1390 * Sample Rate = 2 (48kHz)
1391 * Audio Channel = 1 (Left of 2)
1392 * Source Number = 0 (Unspecified)
1393 * Generation Status = 1 (Original for Cat Code 12)
1394 * Cat Code = 12 (Digital Signal Mixer)
1395 * Mode = 0 (Mode 0)
1396 * Emphasis = 0 (None)
1397 * CP = 1 (Copyright unasserted)
1398 * AN = 0 (Audio data)
1399 * P = 0 (Consumer)
1400 */
1401 snd_ca0106_ptr_write(chip, SPCS0, 0,
1402 chip->spdif_bits[0] =
1403 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1404 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1405 SPCS_GENERATIONSTATUS | 0x00001200 |
1406 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1407 /* Only SPCS1 has been tested */
1408 snd_ca0106_ptr_write(chip, SPCS1, 0,
1409 chip->spdif_bits[1] =
1410 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1411 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1412 SPCS_GENERATIONSTATUS | 0x00001200 |
1413 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1414 snd_ca0106_ptr_write(chip, SPCS2, 0,
1415 chip->spdif_bits[2] =
1416 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1417 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1418 SPCS_GENERATIONSTATUS | 0x00001200 |
1419 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1420 snd_ca0106_ptr_write(chip, SPCS3, 0,
1421 chip->spdif_bits[3] =
1422 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1423 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1424 SPCS_GENERATIONSTATUS | 0x00001200 |
1425 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1426
1427 snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
1428 snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
1429
1430 /* Write 0x8000 to AC97_REC_GAIN to mute it. */
1431 outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
1432 outw(0x8000, chip->port + AC97DATA);
1433#if 0
1434 snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
1435 snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
1436 snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
1437 snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
1438#endif
1439
1440 //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
1441 /* Analog or Digital output */
1442 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
James Courtier-Dutton8f55fbb2005-05-21 16:45:58 +02001443 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 -07001444 chip->spdif_enable = 0; /* Set digital SPDIF output off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
1446 //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
1447
1448 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
1449 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
1450 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
1451 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
1452 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
1453 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
1454 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
1455 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
1456 for(ch = 0; ch < 4; ch++) {
1457 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
1458 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
1459 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
1460 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
1461 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
1462 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
1463 }
James Courtier-Dutton7c157062006-12-10 00:00:38 +00001464 if (chip->details->i2c_adc == 1) {
1465 /* Select MIC, Line in, TAD in, AUX in */
1466 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1467 /* Default to CAPTURE_SOURCE to i2s in */
1468 chip->capture_source = 3;
1469 } else if (chip->details->ac97 == 1) {
1470 /* Default to AC97 in */
1471 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4);
1472 /* Default to CAPTURE_SOURCE to AC97 in */
1473 chip->capture_source = 4;
1474 } else {
1475 /* Select MIC, Line in, TAD in, AUX in */
1476 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1477 /* Default to Set CAPTURE_SOURCE to i2s in */
1478 chip->capture_source = 3;
1479 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +01001481 if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001482 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1483 outl(0x0, chip->port+GPIO);
1484 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
1485 outl(0x005f5301, chip->port+GPIO); /* Analog */
1486 } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1488 outl(0x0, chip->port+GPIO);
1489 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
James Courtier-Duttonc82bf822005-06-04 15:03:06 +02001490 outl(0x005f5301, chip->port+GPIO); /* Analog */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 } else {
1492 outl(0x0, chip->port+GPIO);
1493 outl(0x005f03a3, chip->port+GPIO); /* Analog */
1494 //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
1495 }
1496 snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
1497
1498 //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
1499 //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
1500 //outl(0x00000009, chip->port+HCFG);
1501 outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
1502
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001503 if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001504 int size, n;
1505
1506 size = ARRAY_SIZE(i2c_adc_init);
1507 //snd_printk("I2C:array size=0x%x\n", size);
1508 for (n=0; n < size; n++) {
1509 snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
1510 }
1511 for (n=0; n < 4; n++) {
1512 chip->i2c_capture_volume[n][0]= 0xcf;
1513 chip->i2c_capture_volume[n][1]= 0xcf;
1514 }
1515 chip->i2c_capture_source=2; /* Line in */
1516 //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 +02001517 }
James Courtier-Duttona5875152005-12-20 22:30:49 +01001518 if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001519 int size, n;
1520
1521 size = ARRAY_SIZE(spi_dac_init);
Trent Piephob18cd532007-07-24 12:06:16 +02001522 for (n = 0; n < size; n++) {
1523 int reg = spi_dac_init[n] >> SPI_REG_SHIFT;
1524
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001525 snd_ca0106_spi_write(chip, spi_dac_init[n]);
Trent Piephob18cd532007-07-24 12:06:16 +02001526 if (reg < ARRAY_SIZE(chip->spi_dac_reg))
1527 chip->spi_dac_reg[reg] = spi_dac_init[n];
1528 }
James Courtier-Duttona5875152005-12-20 22:30:49 +01001529 }
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001530
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
1532 chip, &ops)) < 0) {
1533 snd_ca0106_free(chip);
1534 return err;
1535 }
1536 *rchip = chip;
1537 return 0;
1538}
1539
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001540
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001541static void ca0106_midi_interrupt_enable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001542{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001543 snd_ca0106_intr_enable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001544}
1545
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001546static void ca0106_midi_interrupt_disable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001547{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001548 snd_ca0106_intr_disable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001549}
1550
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001551static unsigned char ca0106_midi_read(struct snd_ca_midi *midi, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001552{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001553 return (unsigned char)snd_ca0106_ptr_read((struct snd_ca0106 *)(midi->dev_id),
1554 midi->port + idx, 0);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001555}
1556
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001557static void ca0106_midi_write(struct snd_ca_midi *midi, int data, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001558{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001559 snd_ca0106_ptr_write((struct snd_ca0106 *)(midi->dev_id), midi->port + idx, 0, data);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001560}
1561
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001562static struct snd_card *ca0106_dev_id_card(void *dev_id)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001563{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001564 return ((struct snd_ca0106 *)dev_id)->card;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001565}
1566
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001567static int ca0106_dev_id_port(void *dev_id)
1568{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001569 return ((struct snd_ca0106 *)dev_id)->port;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001570}
1571
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001572static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001573{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001574 struct snd_ca_midi *midi;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001575 char *name;
1576 int err;
1577
Takashi Iwai95a98262005-11-17 10:40:18 +01001578 if (channel == CA0106_MIDI_CHAN_B) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001579 name = "CA0106 MPU-401 (UART) B";
1580 midi = &chip->midi2;
1581 midi->tx_enable = INTE_MIDI_TX_B;
1582 midi->rx_enable = INTE_MIDI_RX_B;
1583 midi->ipr_tx = IPR_MIDI_TX_B;
1584 midi->ipr_rx = IPR_MIDI_RX_B;
1585 midi->port = MIDI_UART_B_DATA;
1586 } else {
1587 name = "CA0106 MPU-401 (UART)";
1588 midi = &chip->midi;
1589 midi->tx_enable = INTE_MIDI_TX_A;
1590 midi->rx_enable = INTE_MIDI_TX_B;
1591 midi->ipr_tx = IPR_MIDI_TX_A;
1592 midi->ipr_rx = IPR_MIDI_RX_A;
1593 midi->port = MIDI_UART_A_DATA;
1594 }
1595
1596 midi->reset = CA0106_MPU401_RESET;
1597 midi->enter_uart = CA0106_MPU401_ENTER_UART;
1598 midi->ack = CA0106_MPU401_ACK;
1599
1600 midi->input_avail = CA0106_MIDI_INPUT_AVAIL;
1601 midi->output_ready = CA0106_MIDI_OUTPUT_READY;
1602
1603 midi->channel = channel;
1604
1605 midi->interrupt_enable = ca0106_midi_interrupt_enable;
1606 midi->interrupt_disable = ca0106_midi_interrupt_disable;
1607
1608 midi->read = ca0106_midi_read;
1609 midi->write = ca0106_midi_write;
1610
1611 midi->get_dev_id_card = ca0106_dev_id_card;
1612 midi->get_dev_id_port = ca0106_dev_id_port;
1613
1614 midi->dev_id = chip;
1615
1616 if ((err = ca_midi_init(chip, midi, 0, name)) < 0)
1617 return err;
1618
1619 return 0;
1620}
1621
1622
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1624 const struct pci_device_id *pci_id)
1625{
1626 static int dev;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001627 struct snd_card *card;
1628 struct snd_ca0106 *chip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 int err;
1630
1631 if (dev >= SNDRV_CARDS)
1632 return -ENODEV;
1633 if (!enable[dev]) {
1634 dev++;
1635 return -ENOENT;
1636 }
1637
1638 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1639 if (card == NULL)
1640 return -ENOMEM;
1641
James Courtier-Duttone4f55d82006-11-25 19:42:29 +00001642 if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 snd_card_free(card);
1644 return err;
1645 }
1646
1647 if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
1648 snd_card_free(card);
1649 return err;
1650 }
1651 if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
1652 snd_card_free(card);
1653 return err;
1654 }
1655 if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
1656 snd_card_free(card);
1657 return err;
1658 }
1659 if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
1660 snd_card_free(card);
1661 return err;
1662 }
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001663 if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 if ((err = snd_ca0106_ac97(chip)) < 0) {
1665 snd_card_free(card);
1666 return err;
1667 }
1668 }
1669 if ((err = snd_ca0106_mixer(chip)) < 0) {
1670 snd_card_free(card);
1671 return err;
1672 }
1673
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001674 snd_printdd("ca0106: probe for MIDI channel A ...");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001675 if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
1676 snd_card_free(card);
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001677 snd_printdd(" failed, err=0x%x\n",err);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001678 return err;
1679 }
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001680 snd_printdd(" done.\n");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001681
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001682#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 snd_ca0106_proc_init(chip);
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001684#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685
Takashi Iwaic6d6eee2007-02-08 14:50:31 +01001686 snd_card_set_dev(card, &pci->dev);
1687
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 if ((err = snd_card_register(card)) < 0) {
1689 snd_card_free(card);
1690 return err;
1691 }
1692
1693 pci_set_drvdata(pci, card);
1694 dev++;
1695 return 0;
1696}
1697
1698static void __devexit snd_ca0106_remove(struct pci_dev *pci)
1699{
1700 snd_card_free(pci_get_drvdata(pci));
1701 pci_set_drvdata(pci, NULL);
1702}
1703
1704// PCI IDs
Takashi Iwaif40b6892006-07-05 16:51:05 +02001705static struct pci_device_id snd_ca0106_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
1707 { 0, }
1708};
1709MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
1710
1711// pci_driver definition
1712static struct pci_driver driver = {
1713 .name = "CA0106",
1714 .id_table = snd_ca0106_ids,
1715 .probe = snd_ca0106_probe,
1716 .remove = __devexit_p(snd_ca0106_remove),
1717};
1718
1719// initialization of the module
1720static int __init alsa_card_ca0106_init(void)
1721{
Takashi Iwai95a98262005-11-17 10:40:18 +01001722 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723}
1724
1725// clean up the module
1726static void __exit alsa_card_ca0106_exit(void)
1727{
1728 pci_unregister_driver(&driver);
1729}
1730
1731module_init(alsa_card_ca0106_init)
1732module_exit(alsa_card_ca0106_exit)