blob: 6fa4a302f7de06d7371007b49a8109ea2a2d031b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
3 * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02004 * Version: 0.0.23
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
6 * FEATURES currently supported:
7 * Front, Rear and Center/LFE.
8 * Surround40 and Surround51.
9 * Capture from MIC an LINE IN input.
10 * SPDIF digital playback of PCM stereo and AC3/DTS works.
11 * (One can use a standard mono mini-jack to one RCA plugs cable.
12 * or one can use a standard stereo mini-jack to two RCA plugs cable.
13 * Plug one of the RCA plugs into the Coax input of the external decoder/receiver.)
14 * ( In theory one could output 3 different AC3 streams at once, to 3 different SPDIF outputs. )
15 * Notes on how to capture sound:
16 * The AC97 is used in the PLAYBACK direction.
17 * The output from the AC97 chip, instead of reaching the speakers, is fed into the Philips 1361T ADC.
18 * So, to record from the MIC, set the MIC Playback volume to max,
19 * unmute the MIC and turn up the MASTER Playback volume.
20 * So, to prevent feedback when capturing, minimise the "Capture feedback into Playback" volume.
21 *
22 * The only playback controls that currently do anything are: -
23 * Analog Front
24 * Analog Rear
25 * Analog Center/LFE
26 * SPDIF Front
27 * SPDIF Rear
28 * SPDIF Center/LFE
29 *
30 * For capture from Mic in or Line in.
31 * Digital/Analog ( switch must be in Analog mode for CAPTURE. )
32 *
33 * CAPTURE feedback into PLAYBACK
34 *
35 * Changelog:
36 * Support interrupts per period.
37 * Removed noise from Center/LFE channel when in Analog mode.
38 * Rename and remove mixer controls.
39 * 0.0.6
40 * Use separate card based DMA buffer for periods table list.
41 * 0.0.7
42 * Change remove and rename ctrls into lists.
43 * 0.0.8
44 * Try to fix capture sources.
45 * 0.0.9
46 * Fix AC3 output.
47 * Enable S32_LE format support.
48 * 0.0.10
49 * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".)
50 * 0.0.11
51 * Add Model name recognition.
52 * 0.0.12
53 * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period.
54 * Remove redundent "voice" handling.
55 * 0.0.13
56 * Single trigger call for multi channels.
57 * 0.0.14
58 * Set limits based on what the sound card hardware can do.
59 * playback periods_min=2, periods_max=8
60 * capture hw constraints require period_size = n * 64 bytes.
61 * playback hw constraints require period_size = n * 64 bytes.
62 * 0.0.15
63 * Minor updates.
64 * 0.0.16
65 * Implement 192000 sample rate.
66 * 0.0.17
67 * Add support for SB0410 and SB0413.
68 * 0.0.18
69 * Modified Copyright message.
70 * 0.0.19
71 * Finally fix support for SB Live 24 bit. SB0410 and SB0413.
72 * The output codec needs resetting, otherwise all output is muted.
73 * 0.0.20
74 * Merge "pci_disable_device(pci);" fixes.
75 * 0.0.21
76 * Add 4 capture channels. (SPDIF only comes in on channel 0. )
77 * Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.)
78 * 0.0.22
79 * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
James Courtier-Dutton7199acd2005-05-27 22:07:23 +020080 * 0.0.23
81 * Implement support for Line-in capture on SB Live 24bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 *
83 * BUGS:
84 * Some stability problems when unloading the snd-ca0106 kernel module.
85 * --
86 *
87 * TODO:
88 * 4 Capture channels, only one implemented so far.
89 * Other capture rates apart from 48khz not implemented.
90 * MIDI
91 * --
92 * GENERAL INFO:
93 * Model: SB0310
94 * P17 Chip: CA0106-DAT
95 * AC97 Codec: STAC 9721
96 * ADC: Philips 1361T (Stereo 24bit)
97 * DAC: WM8746EDS (6-channel, 24bit, 192Khz)
98 *
99 * GENERAL INFO:
100 * Model: SB0410
101 * P17 Chip: CA0106-DAT
102 * AC97 Codec: None
103 * ADC: WM8775EDS (4 Channel)
104 * DAC: CS4382 (114 dB, 24-Bit, 192 kHz, 8-Channel D/A Converter with DSD Support)
105 * SPDIF Out control switches between Mic in and SPDIF out.
106 * No sound out or mic input working yet.
107 *
108 * GENERAL INFO:
109 * Model: SB0413
110 * P17 Chip: CA0106-DAT
111 * AC97 Codec: None.
112 * ADC: Unknown
113 * DAC: Unknown
114 * Trying to handle it like the SB0410.
115 *
116 * This code was initally based on code from ALSA's emu10k1x.c which is:
117 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
118 *
119 * This program is free software; you can redistribute it and/or modify
120 * it under the terms of the GNU General Public License as published by
121 * the Free Software Foundation; either version 2 of the License, or
122 * (at your option) any later version.
123 *
124 * This program is distributed in the hope that it will be useful,
125 * but WITHOUT ANY WARRANTY; without even the implied warranty of
126 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
127 * GNU General Public License for more details.
128 *
129 * You should have received a copy of the GNU General Public License
130 * along with this program; if not, write to the Free Software
131 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
132 *
133 */
134#include <sound/driver.h>
135#include <linux/delay.h>
136#include <linux/init.h>
137#include <linux/interrupt.h>
138#include <linux/pci.h>
139#include <linux/slab.h>
140#include <linux/moduleparam.h>
Tobias Klauser299676b2005-05-29 15:21:02 +0200141#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142#include <sound/core.h>
143#include <sound/initval.h>
144#include <sound/pcm.h>
145#include <sound/ac97_codec.h>
146#include <sound/info.h>
147
148MODULE_AUTHOR("James Courtier-Dutton <James@superbug.demon.co.uk>");
149MODULE_DESCRIPTION("CA0106");
150MODULE_LICENSE("GPL");
151MODULE_SUPPORTED_DEVICE("{{Creative,SB CA0106 chip}}");
152
153// module parameters (see "Module Parameters")
154static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
155static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
156static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
157
158module_param_array(index, int, NULL, 0444);
159MODULE_PARM_DESC(index, "Index value for the CA0106 soundcard.");
160module_param_array(id, charp, NULL, 0444);
161MODULE_PARM_DESC(id, "ID string for the CA0106 soundcard.");
162module_param_array(enable, bool, NULL, 0444);
163MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard.");
164
165#include "ca0106.h"
166
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100167static struct snd_ca0106_details ca0106_chip_details[] = {
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200168 /* AudigyLS[SB0310] */
169 { .serial = 0x10021102,
170 .name = "AudigyLS [SB0310]",
171 .ac97 = 1 } ,
172 /* Unknown AudigyLS that also says SB0310 on it */
173 { .serial = 0x10051102,
174 .name = "AudigyLS [SB0310b]",
175 .ac97 = 1 } ,
176 /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
177 { .serial = 0x10061102,
178 .name = "Live! 7.1 24bit [SB0410]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200179 .gpio_type = 1,
180 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200181 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
182 { .serial = 0x10071102,
183 .name = "Live! 7.1 24bit [SB0413]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200184 .gpio_type = 1,
185 .i2c_adc = 1 } ,
James Courtier-Duttona5875152005-12-20 22:30:49 +0100186 /* New Audigy SE. Has a different DAC. */
187 /* SB0570:
188 * CTRL:CA0106-DAT
James Courtier-Dutton58398892006-06-10 09:16:49 +0100189 * ADC: WM8775EDS
190 * DAC: WM8768GEDS
James Courtier-Duttona5875152005-12-20 22:30:49 +0100191 */
192 { .serial = 0x100a1102,
193 .name = "Audigy SE [SB0570]",
194 .gpio_type = 1,
195 .i2c_adc = 1,
196 .spi_dac = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200197 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100198 /* SB0438
199 * CTRL:CA0106-DAT
200 * ADC: WM8775SEDS
201 * DAC: CS4382-KQZ
202 */
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200203 { .serial = 0x10091462,
204 .name = "MSI K8N Diamond MB [SB0438]",
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +0100205 .gpio_type = 2,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200206 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100207 /* Shuttle XPC SD31P which has an onboard Creative Labs
208 * Sound Blaster Live! 24-bit EAX
James Courtier-Dutton1b059622005-08-12 23:50:13 +0200209 * high-definition 7.1 audio processor".
210 * Added using info from andrewvegan in alsa bug #1298
211 */
212 { .serial = 0x30381297,
213 .name = "Shuttle XPC SD31P [SD31P]",
214 .gpio_type = 1,
215 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100216 /* Shuttle XPC SD11G5 which has an onboard Creative Labs
217 * Sound Blaster Live! 24-bit EAX
218 * high-definition 7.1 audio processor".
219 * Fixes ALSA bug#1600
220 */
221 { .serial = 0x30411297,
222 .name = "Shuttle XPC SD11G5 [SD11G5]",
223 .gpio_type = 1,
224 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200225 { .serial = 0,
226 .name = "AudigyLS [Unknown]" }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227};
228
229/* hardware definition */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100230static struct snd_pcm_hardware snd_ca0106_playback_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 .info = (SNDRV_PCM_INFO_MMAP |
232 SNDRV_PCM_INFO_INTERLEAVED |
233 SNDRV_PCM_INFO_BLOCK_TRANSFER |
234 SNDRV_PCM_INFO_MMAP_VALID),
235 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100236 .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
237 SNDRV_PCM_RATE_192000),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 .rate_min = 48000,
239 .rate_max = 192000,
240 .channels_min = 2, //1,
241 .channels_max = 2, //6,
242 .buffer_bytes_max = ((65536 - 64) * 8),
243 .period_bytes_min = 64,
244 .period_bytes_max = (65536 - 64),
245 .periods_min = 2,
246 .periods_max = 8,
247 .fifo_size = 0,
248};
249
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100250static struct snd_pcm_hardware snd_ca0106_capture_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 .info = (SNDRV_PCM_INFO_MMAP |
252 SNDRV_PCM_INFO_INTERLEAVED |
253 SNDRV_PCM_INFO_BLOCK_TRANSFER |
254 SNDRV_PCM_INFO_MMAP_VALID),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200255 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100256 .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
257 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200258 .rate_min = 44100,
259 .rate_max = 192000,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 .channels_min = 2,
261 .channels_max = 2,
262 .buffer_bytes_max = ((65536 - 64) * 8),
263 .period_bytes_min = 64,
264 .period_bytes_max = (65536 - 64),
265 .periods_min = 2,
266 .periods_max = 2,
267 .fifo_size = 0,
268};
269
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100270unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 unsigned int reg,
272 unsigned int chn)
273{
274 unsigned long flags;
275 unsigned int regptr, val;
276
277 regptr = (reg << 16) | chn;
278
279 spin_lock_irqsave(&emu->emu_lock, flags);
280 outl(regptr, emu->port + PTR);
281 val = inl(emu->port + DATA);
282 spin_unlock_irqrestore(&emu->emu_lock, flags);
283 return val;
284}
285
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100286void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 unsigned int reg,
288 unsigned int chn,
289 unsigned int data)
290{
291 unsigned int regptr;
292 unsigned long flags;
293
294 regptr = (reg << 16) | chn;
295
296 spin_lock_irqsave(&emu->emu_lock, flags);
297 outl(regptr, emu->port + PTR);
298 outl(data, emu->port + DATA);
299 spin_unlock_irqrestore(&emu->emu_lock, flags);
300}
301
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100302int snd_ca0106_spi_write(struct snd_ca0106 * emu,
303 unsigned int data)
James Courtier-Duttona5875152005-12-20 22:30:49 +0100304{
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100305 unsigned int reset, set;
306 unsigned int reg, tmp;
307 int n, result;
308 reg = SPI;
309 if (data > 0xffff) /* Only 16bit values allowed */
310 return 1;
311 tmp = snd_ca0106_ptr_read(emu, reg, 0);
312 reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
313 set = reset | 0x10000; /* Set xxx1xxxx */
314 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
315 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* write post */
316 snd_ca0106_ptr_write(emu, reg, 0, set | data);
317 result = 1;
318 /* Wait for status bit to return to 0 */
319 for (n = 0; n < 100; n++) {
320 udelay(10);
321 tmp = snd_ca0106_ptr_read(emu, reg, 0);
322 if (!(tmp & 0x10000)) {
323 result = 0;
324 break;
325 }
326 }
327 if (result) /* Timed out */
328 return 1;
329 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
330 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* Write post */
James Courtier-Duttona5875152005-12-20 22:30:49 +0100331 return 0;
332}
333
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100334/* The ADC does not support i2c read, so only write is implemented */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100335int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200336 u32 reg,
337 u32 value)
338{
339 u32 tmp;
Takashi Iwai95a98262005-11-17 10:40:18 +0100340 int timeout = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200341 int status;
342 int retry;
Takashi Iwai95a98262005-11-17 10:40:18 +0100343 if ((reg > 0x7f) || (value > 0x1ff)) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200344 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200345 return -EINVAL;
346 }
347
348 tmp = reg << 25 | value << 16;
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100349 // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
James Courtier-Dutton8fabab12005-05-28 16:35:49 +0200350 /* Not sure what this I2C channel controls. */
351 /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
352
353 /* This controls the I2C connected to the WM8775 ADC Codec */
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200354 snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
355
Takashi Iwai95a98262005-11-17 10:40:18 +0100356 for (retry = 0; retry < 10; retry++) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200357 /* Send the data to i2c */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100358 //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
359 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
360 tmp = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200361 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
362 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
363
364 /* Wait till the transaction ends */
Takashi Iwai95a98262005-11-17 10:40:18 +0100365 while (1) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200366 status = snd_ca0106_ptr_read(emu, I2C_A, 0);
367 //snd_printk("I2C:status=0x%x\n", status);
368 timeout++;
Takashi Iwai95a98262005-11-17 10:40:18 +0100369 if ((status & I2C_A_ADC_START) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200370 break;
371
Takashi Iwai95a98262005-11-17 10:40:18 +0100372 if (timeout > 1000)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200373 break;
374 }
375 //Read back and see if the transaction is successful
Takashi Iwai95a98262005-11-17 10:40:18 +0100376 if ((status & I2C_A_ADC_ABORT) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200377 break;
378 }
379
Takashi Iwai95a98262005-11-17 10:40:18 +0100380 if (retry == 10) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200381 snd_printk(KERN_ERR "Writing to ADC failed!\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200382 return -EINVAL;
383 }
384
385 return 0;
386}
387
388
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100389static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390{
391 unsigned long flags;
392 unsigned int enable;
393
394 spin_lock_irqsave(&emu->emu_lock, flags);
395 enable = inl(emu->port + INTE) | intrenb;
396 outl(enable, emu->port + INTE);
397 spin_unlock_irqrestore(&emu->emu_lock, flags);
398}
399
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100400static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +0200401{
402 unsigned long flags;
403 unsigned int enable;
404
405 spin_lock_irqsave(&emu->emu_lock, flags);
406 enable = inl(emu->port + INTE) & ~intrenb;
407 outl(enable, emu->port + INTE);
408 spin_unlock_irqrestore(&emu->emu_lock, flags);
409}
410
411
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100412static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413{
Jesper Juhl4d572772005-05-30 17:30:32 +0200414 kfree(runtime->private_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415}
416
417/* open_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100418static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
419 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100421 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
422 struct snd_ca0106_channel *channel = &(chip->playback_channels[channel_id]);
423 struct snd_ca0106_pcm *epcm;
424 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 int err;
426
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200427 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 if (epcm == NULL)
430 return -ENOMEM;
431 epcm->emu = chip;
432 epcm->substream = substream;
433 epcm->channel_id=channel_id;
434
435 runtime->private_data = epcm;
436 runtime->private_free = snd_ca0106_pcm_free_substream;
437
438 runtime->hw = snd_ca0106_playback_hw;
439
440 channel->emu = chip;
441 channel->number = channel_id;
442
Takashi Iwai95a98262005-11-17 10:40:18 +0100443 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
445 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwai95a98262005-11-17 10:40:18 +0100446 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
448 return err;
449 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
450 return err;
451 return 0;
452}
453
454/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100455static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100457 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
458 struct snd_pcm_runtime *runtime = substream->runtime;
459 struct snd_ca0106_pcm *epcm = runtime->private_data;
460 chip->playback_channels[epcm->channel_id].use = 0;
461 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 return 0;
463}
464
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100465static int snd_ca0106_pcm_open_playback_front(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
467 return snd_ca0106_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
468}
469
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100470static int snd_ca0106_pcm_open_playback_center_lfe(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471{
472 return snd_ca0106_pcm_open_playback_channel(substream, PCM_CENTER_LFE_CHANNEL);
473}
474
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100475static int snd_ca0106_pcm_open_playback_unknown(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476{
477 return snd_ca0106_pcm_open_playback_channel(substream, PCM_UNKNOWN_CHANNEL);
478}
479
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100480static int snd_ca0106_pcm_open_playback_rear(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481{
482 return snd_ca0106_pcm_open_playback_channel(substream, PCM_REAR_CHANNEL);
483}
484
485/* open_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100486static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substream,
487 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100489 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
490 struct snd_ca0106_channel *channel = &(chip->capture_channels[channel_id]);
491 struct snd_ca0106_pcm *epcm;
492 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 int err;
494
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200495 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 if (epcm == NULL) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200497 snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 return -ENOMEM;
499 }
500 epcm->emu = chip;
501 epcm->substream = substream;
502 epcm->channel_id=channel_id;
503
504 runtime->private_data = epcm;
505 runtime->private_free = snd_ca0106_pcm_free_substream;
506
507 runtime->hw = snd_ca0106_capture_hw;
508
509 channel->emu = chip;
510 channel->number = channel_id;
511
Takashi Iwai95a98262005-11-17 10:40:18 +0100512 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
514 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100515 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
517 return err;
518 //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
519 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
520 return err;
521 return 0;
522}
523
524/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100525static int snd_ca0106_pcm_close_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100527 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
528 struct snd_pcm_runtime *runtime = substream->runtime;
529 struct snd_ca0106_pcm *epcm = runtime->private_data;
530 chip->capture_channels[epcm->channel_id].use = 0;
531 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 return 0;
533}
534
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100535static int snd_ca0106_pcm_open_0_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536{
537 return snd_ca0106_pcm_open_capture_channel(substream, 0);
538}
539
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100540static int snd_ca0106_pcm_open_1_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541{
542 return snd_ca0106_pcm_open_capture_channel(substream, 1);
543}
544
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100545static int snd_ca0106_pcm_open_2_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546{
547 return snd_ca0106_pcm_open_capture_channel(substream, 2);
548}
549
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100550static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
552 return snd_ca0106_pcm_open_capture_channel(substream, 3);
553}
554
555/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100556static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream,
557 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
559 return snd_pcm_lib_malloc_pages(substream,
560 params_buffer_bytes(hw_params));
561}
562
563/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100564static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
566 return snd_pcm_lib_free_pages(substream);
567}
568
569/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100570static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream,
571 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572{
573 return snd_pcm_lib_malloc_pages(substream,
574 params_buffer_bytes(hw_params));
575}
576
577/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100578static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579{
580 return snd_pcm_lib_free_pages(substream);
581}
582
583/* prepare playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100584static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100586 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
587 struct snd_pcm_runtime *runtime = substream->runtime;
588 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 int channel = epcm->channel_id;
590 u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
591 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
592 u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
593 u32 hcfg_set = 0x00000000;
594 u32 hcfg;
595 u32 reg40_mask = 0x30000 << (channel<<1);
596 u32 reg40_set = 0;
597 u32 reg40;
598 /* FIXME: Depending on mixer selection of SPDIF out or not, select the spdif rate or the DAC rate. */
599 u32 reg71_mask = 0x03030000 ; /* Global. Set SPDIF rate. We only support 44100 to spdif, not to DAC. */
600 u32 reg71_set = 0;
601 u32 reg71;
602 int i;
603
604 //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));
605 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
606 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
607 /* Rate can be set per channel. */
608 /* reg40 control host to fifo */
609 /* reg71 controls DAC rate. */
610 switch (runtime->rate) {
611 case 44100:
612 reg40_set = 0x10000 << (channel<<1);
613 reg71_set = 0x01010000;
614 break;
615 case 48000:
616 reg40_set = 0;
617 reg71_set = 0;
618 break;
619 case 96000:
620 reg40_set = 0x20000 << (channel<<1);
621 reg71_set = 0x02020000;
622 break;
623 case 192000:
624 reg40_set = 0x30000 << (channel<<1);
625 reg71_set = 0x03030000;
626 break;
627 default:
628 reg40_set = 0;
629 reg71_set = 0;
630 break;
631 }
632 /* Format is a global setting */
633 /* FIXME: Only let the first channel accessed set this. */
634 switch (runtime->format) {
635 case SNDRV_PCM_FORMAT_S16_LE:
636 hcfg_set = 0;
637 break;
638 case SNDRV_PCM_FORMAT_S32_LE:
639 hcfg_set = HCFG_PLAYBACK_S32_LE;
640 break;
641 default:
642 hcfg_set = 0;
643 break;
644 }
645 hcfg = inl(emu->port + HCFG) ;
646 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
647 outl(hcfg, emu->port + HCFG);
648 reg40 = snd_ca0106_ptr_read(emu, 0x40, 0);
649 reg40 = (reg40 & ~reg40_mask) | reg40_set;
650 snd_ca0106_ptr_write(emu, 0x40, 0, reg40);
651 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
652 reg71 = (reg71 & ~reg71_mask) | reg71_set;
653 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
654
655 /* FIXME: Check emu->buffer.size before actually writing to it. */
656 for(i=0; i < runtime->periods; i++) {
Takashi Iwai95a98262005-11-17 10:40:18 +0100657 table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
658 table_base[i*2+1] = period_size_bytes << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 }
660
661 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
662 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
663 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
664 snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
665 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
666 /* FIXME test what 0 bytes does. */
667 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
668 snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
669 snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
670 snd_ca0106_ptr_write(emu, 0x08, channel, 0);
671 snd_ca0106_ptr_write(emu, PLAYBACK_MUTE, 0x0, 0x0); /* Unmute output */
672#if 0
673 snd_ca0106_ptr_write(emu, SPCS0, 0,
674 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
675 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
676 SPCS_GENERATIONSTATUS | 0x00001200 |
677 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
678 }
679#endif
680
681 return 0;
682}
683
684/* prepare capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100685static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100687 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
688 struct snd_pcm_runtime *runtime = substream->runtime;
689 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 int channel = epcm->channel_id;
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200691 u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
692 u32 hcfg_set = 0x00000000;
693 u32 hcfg;
694 u32 over_sampling=0x2;
695 u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
696 u32 reg71_set = 0;
697 u32 reg71;
698
699 //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));
700 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
701 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
702 /* reg71 controls ADC rate. */
703 switch (runtime->rate) {
704 case 44100:
705 reg71_set = 0x00004000;
706 break;
707 case 48000:
708 reg71_set = 0;
709 break;
710 case 96000:
711 reg71_set = 0x00008000;
712 over_sampling=0xa;
713 break;
714 case 192000:
715 reg71_set = 0x0000c000;
716 over_sampling=0xa;
717 break;
718 default:
719 reg71_set = 0;
720 break;
721 }
722 /* Format is a global setting */
723 /* FIXME: Only let the first channel accessed set this. */
724 switch (runtime->format) {
725 case SNDRV_PCM_FORMAT_S16_LE:
726 hcfg_set = 0;
727 break;
728 case SNDRV_PCM_FORMAT_S32_LE:
729 hcfg_set = HCFG_CAPTURE_S32_LE;
730 break;
731 default:
732 hcfg_set = 0;
733 break;
734 }
735 hcfg = inl(emu->port + HCFG) ;
736 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
737 outl(hcfg, emu->port + HCFG);
738 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
739 reg71 = (reg71 & ~reg71_mask) | reg71_set;
740 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
741 if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
742 snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
743 }
744
745
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 //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));
747 snd_ca0106_ptr_write(emu, 0x13, channel, 0);
748 snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
749 snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
750 snd_ca0106_ptr_write(emu, CAPTURE_POINTER, channel, 0);
751
752 return 0;
753}
754
755/* trigger_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100756static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 int cmd)
758{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100759 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
760 struct snd_pcm_runtime *runtime;
761 struct snd_ca0106_pcm *epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 int channel;
763 int result = 0;
764 struct list_head *pos;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100765 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 u32 basic = 0;
767 u32 extended = 0;
768 int running=0;
769
770 switch (cmd) {
771 case SNDRV_PCM_TRIGGER_START:
772 running=1;
773 break;
774 case SNDRV_PCM_TRIGGER_STOP:
775 default:
776 running=0;
777 break;
778 }
779 snd_pcm_group_for_each(pos, substream) {
780 s = snd_pcm_group_substream_entry(pos);
781 runtime = s->runtime;
782 epcm = runtime->private_data;
783 channel = epcm->channel_id;
784 //snd_printk("channel=%d\n",channel);
785 epcm->running = running;
786 basic |= (0x1<<channel);
787 extended |= (0x10<<channel);
788 snd_pcm_trigger_done(s, substream);
789 }
790 //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
791
792 switch (cmd) {
793 case SNDRV_PCM_TRIGGER_START:
794 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
795 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
796 break;
797 case SNDRV_PCM_TRIGGER_STOP:
798 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
799 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
800 break;
801 default:
802 result = -EINVAL;
803 break;
804 }
805 return result;
806}
807
808/* trigger_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100809static int snd_ca0106_pcm_trigger_capture(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 int cmd)
811{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100812 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
813 struct snd_pcm_runtime *runtime = substream->runtime;
814 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 int channel = epcm->channel_id;
816 int result = 0;
817
818 switch (cmd) {
819 case SNDRV_PCM_TRIGGER_START:
820 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
821 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
822 epcm->running = 1;
823 break;
824 case SNDRV_PCM_TRIGGER_STOP:
825 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
826 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
827 epcm->running = 0;
828 break;
829 default:
830 result = -EINVAL;
831 break;
832 }
833 return result;
834}
835
836/* pointer_playback callback */
837static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100838snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100840 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
841 struct snd_pcm_runtime *runtime = substream->runtime;
842 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
844 int channel = epcm->channel_id;
845
846 if (!epcm->running)
847 return 0;
848
849 ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
850 ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
851 ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
852 if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
853 ptr2 = bytes_to_frames(runtime, ptr1);
854 ptr2+= (ptr4 >> 3) * runtime->period_size;
855 ptr=ptr2;
856 if (ptr >= runtime->buffer_size)
857 ptr -= runtime->buffer_size;
858 //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);
859
860 return ptr;
861}
862
863/* pointer_capture callback */
864static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100865snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100867 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
868 struct snd_pcm_runtime *runtime = substream->runtime;
869 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
871 int channel = channel=epcm->channel_id;
872
873 if (!epcm->running)
874 return 0;
875
876 ptr1 = snd_ca0106_ptr_read(emu, CAPTURE_POINTER, channel);
877 ptr2 = bytes_to_frames(runtime, ptr1);
878 ptr=ptr2;
879 if (ptr >= runtime->buffer_size)
880 ptr -= runtime->buffer_size;
881 //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);
882
883 return ptr;
884}
885
886/* operators */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100887static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 .open = snd_ca0106_pcm_open_playback_front,
889 .close = snd_ca0106_pcm_close_playback,
890 .ioctl = snd_pcm_lib_ioctl,
891 .hw_params = snd_ca0106_pcm_hw_params_playback,
892 .hw_free = snd_ca0106_pcm_hw_free_playback,
893 .prepare = snd_ca0106_pcm_prepare_playback,
894 .trigger = snd_ca0106_pcm_trigger_playback,
895 .pointer = snd_ca0106_pcm_pointer_playback,
896};
897
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100898static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 .open = snd_ca0106_pcm_open_0_capture,
900 .close = snd_ca0106_pcm_close_capture,
901 .ioctl = snd_pcm_lib_ioctl,
902 .hw_params = snd_ca0106_pcm_hw_params_capture,
903 .hw_free = snd_ca0106_pcm_hw_free_capture,
904 .prepare = snd_ca0106_pcm_prepare_capture,
905 .trigger = snd_ca0106_pcm_trigger_capture,
906 .pointer = snd_ca0106_pcm_pointer_capture,
907};
908
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100909static struct snd_pcm_ops snd_ca0106_capture_1_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 .open = snd_ca0106_pcm_open_1_capture,
911 .close = snd_ca0106_pcm_close_capture,
912 .ioctl = snd_pcm_lib_ioctl,
913 .hw_params = snd_ca0106_pcm_hw_params_capture,
914 .hw_free = snd_ca0106_pcm_hw_free_capture,
915 .prepare = snd_ca0106_pcm_prepare_capture,
916 .trigger = snd_ca0106_pcm_trigger_capture,
917 .pointer = snd_ca0106_pcm_pointer_capture,
918};
919
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100920static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 .open = snd_ca0106_pcm_open_2_capture,
922 .close = snd_ca0106_pcm_close_capture,
923 .ioctl = snd_pcm_lib_ioctl,
924 .hw_params = snd_ca0106_pcm_hw_params_capture,
925 .hw_free = snd_ca0106_pcm_hw_free_capture,
926 .prepare = snd_ca0106_pcm_prepare_capture,
927 .trigger = snd_ca0106_pcm_trigger_capture,
928 .pointer = snd_ca0106_pcm_pointer_capture,
929};
930
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100931static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 .open = snd_ca0106_pcm_open_3_capture,
933 .close = snd_ca0106_pcm_close_capture,
934 .ioctl = snd_pcm_lib_ioctl,
935 .hw_params = snd_ca0106_pcm_hw_params_capture,
936 .hw_free = snd_ca0106_pcm_hw_free_capture,
937 .prepare = snd_ca0106_pcm_prepare_capture,
938 .trigger = snd_ca0106_pcm_trigger_capture,
939 .pointer = snd_ca0106_pcm_pointer_capture,
940};
941
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100942static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 .open = snd_ca0106_pcm_open_playback_center_lfe,
944 .close = snd_ca0106_pcm_close_playback,
945 .ioctl = snd_pcm_lib_ioctl,
946 .hw_params = snd_ca0106_pcm_hw_params_playback,
947 .hw_free = snd_ca0106_pcm_hw_free_playback,
948 .prepare = snd_ca0106_pcm_prepare_playback,
949 .trigger = snd_ca0106_pcm_trigger_playback,
950 .pointer = snd_ca0106_pcm_pointer_playback,
951};
952
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100953static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 .open = snd_ca0106_pcm_open_playback_unknown,
955 .close = snd_ca0106_pcm_close_playback,
956 .ioctl = snd_pcm_lib_ioctl,
957 .hw_params = snd_ca0106_pcm_hw_params_playback,
958 .hw_free = snd_ca0106_pcm_hw_free_playback,
959 .prepare = snd_ca0106_pcm_prepare_playback,
960 .trigger = snd_ca0106_pcm_trigger_playback,
961 .pointer = snd_ca0106_pcm_pointer_playback,
962};
963
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100964static struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 .open = snd_ca0106_pcm_open_playback_rear,
966 .close = snd_ca0106_pcm_close_playback,
967 .ioctl = snd_pcm_lib_ioctl,
968 .hw_params = snd_ca0106_pcm_hw_params_playback,
969 .hw_free = snd_ca0106_pcm_hw_free_playback,
970 .prepare = snd_ca0106_pcm_prepare_playback,
971 .trigger = snd_ca0106_pcm_trigger_playback,
972 .pointer = snd_ca0106_pcm_pointer_playback,
973};
974
975
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100976static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 unsigned short reg)
978{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100979 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 unsigned long flags;
981 unsigned short val;
982
983 spin_lock_irqsave(&emu->emu_lock, flags);
984 outb(reg, emu->port + AC97ADDRESS);
985 val = inw(emu->port + AC97DATA);
986 spin_unlock_irqrestore(&emu->emu_lock, flags);
987 return val;
988}
989
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100990static void snd_ca0106_ac97_write(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 unsigned short reg, unsigned short val)
992{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100993 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 unsigned long flags;
995
996 spin_lock_irqsave(&emu->emu_lock, flags);
997 outb(reg, emu->port + AC97ADDRESS);
998 outw(val, emu->port + AC97DATA);
999 spin_unlock_irqrestore(&emu->emu_lock, flags);
1000}
1001
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001002static int snd_ca0106_ac97(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001004 struct snd_ac97_bus *pbus;
1005 struct snd_ac97_template ac97;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 int err;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001007 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 .write = snd_ca0106_ac97_write,
1009 .read = snd_ca0106_ac97_read,
1010 };
1011
1012 if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
1013 return err;
1014 pbus->no_vra = 1; /* we don't need VRA */
1015
1016 memset(&ac97, 0, sizeof(ac97));
1017 ac97.private_data = chip;
Takashi Iwai36c4dc42005-03-24 17:48:30 +01001018 ac97.scaps = AC97_SCAP_NO_SPDIF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
1020}
1021
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001022static int snd_ca0106_free(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023{
1024 if (chip->res_port != NULL) { /* avoid access to already used hardware */
1025 // disable interrupts
1026 snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
1027 outl(0, chip->port + INTE);
1028 snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
1029 udelay(1000);
1030 // disable audio
1031 //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
1032 outl(0, chip->port + HCFG);
1033 /* FIXME: We need to stop and DMA transfers here.
1034 * But as I am not sure how yet, we cannot from the dma pages.
1035 * So we can fix: snd-malloc: Memory leak? pages not freed = 8
1036 */
1037 }
1038 // release the data
1039#if 1
1040 if (chip->buffer.area)
1041 snd_dma_free_pages(&chip->buffer);
1042#endif
1043
1044 // release the i/o port
Takashi Iwaib1d57762005-10-10 11:56:31 +02001045 release_and_free_resource(chip->res_port);
1046
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 // release the irq
1048 if (chip->irq >= 0)
1049 free_irq(chip->irq, (void *)chip);
1050 pci_disable_device(chip->pci);
1051 kfree(chip);
1052 return 0;
1053}
1054
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001055static int snd_ca0106_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001057 struct snd_ca0106 *chip = device->device_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 return snd_ca0106_free(chip);
1059}
1060
David Howells7d12e782006-10-05 14:55:46 +01001061static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062{
1063 unsigned int status;
1064
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001065 struct snd_ca0106 *chip = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 int i;
1067 int mask;
1068 unsigned int stat76;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001069 struct snd_ca0106_channel *pchannel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 status = inl(chip->port + IPR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 if (! status)
1073 return IRQ_NONE;
1074
1075 stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0);
1076 //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76);
1077 //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0));
1078 mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
1079 for(i = 0; i < 4; i++) {
1080 pchannel = &(chip->playback_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001081 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082/* FIXME: Select the correct substream for period elapsed */
1083 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001084 snd_pcm_period_elapsed(pchannel->epcm->substream);
1085 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 }
1087 }
1088 //printk(KERN_INFO "channel=%p\n",pchannel);
1089 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1090 mask <<= 1;
1091 }
1092 mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */
1093 for(i = 0; i < 4; i++) {
1094 pchannel = &(chip->capture_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001095 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096/* FIXME: Select the correct substream for period elapsed */
1097 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001098 snd_pcm_period_elapsed(pchannel->epcm->substream);
1099 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
1101 }
1102 //printk(KERN_INFO "channel=%p\n",pchannel);
1103 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1104 mask <<= 1;
1105 }
1106
1107 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001108
1109 if (chip->midi.dev_id &&
Takashi Iwai95a98262005-11-17 10:40:18 +01001110 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001111 if (chip->midi.interrupt)
1112 chip->midi.interrupt(&chip->midi, status);
1113 else
1114 chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable);
1115 }
1116
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 // acknowledge the interrupt if necessary
1118 outl(status, chip->port+IPR);
1119
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 return IRQ_HANDLED;
1121}
1122
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001123static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001125 struct snd_pcm *pcm;
1126 struct snd_pcm_substream *substream;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 int err;
1128
1129 if (rpcm)
1130 *rpcm = NULL;
1131 if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
1132 return err;
1133
1134 pcm->private_data = emu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 switch (device) {
1137 case 0:
1138 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops);
1139 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops);
1140 break;
1141 case 1:
1142 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops);
1143 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops);
1144 break;
1145 case 2:
1146 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops);
1147 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops);
1148 break;
1149 case 3:
1150 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops);
1151 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops);
1152 break;
1153 }
1154
1155 pcm->info_flags = 0;
1156 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
1157 strcpy(pcm->name, "CA0106");
1158 emu->pcm = pcm;
1159
1160 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1161 substream;
1162 substream = substream->next) {
1163 if ((err = snd_pcm_lib_preallocate_pages(substream,
1164 SNDRV_DMA_TYPE_DEV,
1165 snd_dma_pci_data(emu->pci),
1166 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
1167 return err;
1168 }
1169
1170 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1171 substream;
1172 substream = substream->next) {
1173 if ((err = snd_pcm_lib_preallocate_pages(substream,
1174 SNDRV_DMA_TYPE_DEV,
1175 snd_dma_pci_data(emu->pci),
1176 64*1024, 64*1024)) < 0)
1177 return err;
1178 }
1179
1180 if (rpcm)
1181 *rpcm = pcm;
1182
1183 return 0;
1184}
1185
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001186static unsigned int spi_dac_init[] = {
1187 0x00ff,
1188 0x02ff,
1189 0x0400,
1190 0x0520,
James Courtier-Dutton58398892006-06-10 09:16:49 +01001191 0x0620, /* Set 24 bit. Was 0x0600 */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001192 0x08ff,
1193 0x0aff,
1194 0x0cff,
1195 0x0eff,
1196 0x10ff,
1197 0x1200,
1198 0x1400,
1199 0x1480,
1200 0x1800,
1201 0x1aff,
1202 0x1cff,
1203 0x1e00,
1204 0x0530,
1205 0x0602,
1206 0x0622,
1207 0x1400,
1208};
1209
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001210static unsigned int i2c_adc_init[][2] = {
1211 { 0x17, 0x00 }, /* Reset */
1212 { 0x07, 0x00 }, /* Timeout */
1213 { 0x0b, 0x22 }, /* Interface control */
1214 { 0x0c, 0x22 }, /* Master mode control */
1215 { 0x0d, 0x08 }, /* Powerdown control */
1216 { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
1217 { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */
1218 { 0x10, 0x7b }, /* ALC Control 1 */
1219 { 0x11, 0x00 }, /* ALC Control 2 */
1220 { 0x12, 0x32 }, /* ALC Control 3 */
1221 { 0x13, 0x00 }, /* Noise gate control */
1222 { 0x14, 0xa6 }, /* Limiter control */
1223 { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
1224};
1225
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001226static int __devinit snd_ca0106_create(struct snd_card *card,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 struct pci_dev *pci,
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001228 struct snd_ca0106 **rchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001230 struct snd_ca0106 *chip;
1231 struct snd_ca0106_details *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 int err;
1233 int ch;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001234 static struct snd_device_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 .dev_free = snd_ca0106_dev_free,
1236 };
1237
1238 *rchip = NULL;
1239
1240 if ((err = pci_enable_device(pci)) < 0)
1241 return err;
Tobias Klauser299676b2005-05-29 15:21:02 +02001242 if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
1243 pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 printk(KERN_ERR "error to set 32bit mask DMA\n");
1245 pci_disable_device(pci);
1246 return -ENXIO;
1247 }
1248
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001249 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 if (chip == NULL) {
1251 pci_disable_device(pci);
1252 return -ENOMEM;
1253 }
1254
1255 chip->card = card;
1256 chip->pci = pci;
1257 chip->irq = -1;
1258
1259 spin_lock_init(&chip->emu_lock);
1260
1261 chip->port = pci_resource_start(pci, 0);
1262 if ((chip->res_port = request_region(chip->port, 0x20,
1263 "snd_ca0106")) == NULL) {
1264 snd_ca0106_free(chip);
1265 printk(KERN_ERR "cannot allocate the port\n");
1266 return -EBUSY;
1267 }
1268
1269 if (request_irq(pci->irq, snd_ca0106_interrupt,
Thomas Gleixner65ca68b2006-07-01 19:29:46 -07001270 IRQF_DISABLED|IRQF_SHARED, "snd_ca0106",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 (void *)chip)) {
1272 snd_ca0106_free(chip);
1273 printk(KERN_ERR "cannot grab irq\n");
1274 return -EBUSY;
1275 }
1276 chip->irq = pci->irq;
1277
1278 /* This stores the periods table. */
1279 if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
1280 snd_ca0106_free(chip);
1281 return -ENOMEM;
1282 }
1283
1284 pci_set_master(pci);
1285 /* read revision & serial */
1286 pci_read_config_byte(pci, PCI_REVISION_ID, (char *)&chip->revision);
1287 pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
1288 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
1289#if 1
1290 printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
1291 chip->revision, chip->serial);
1292#endif
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001293 strcpy(card->driver, "CA0106");
1294 strcpy(card->shortname, "CA0106");
1295
Takashi Iwai95a98262005-11-17 10:40:18 +01001296 for (c = ca0106_chip_details; c->serial; c++) {
1297 if (c->serial == chip->serial)
1298 break;
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001299 }
1300 chip->details = c;
1301 sprintf(card->longname, "%s at 0x%lx irq %i",
1302 c->name, chip->port, chip->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
1304 outl(0, chip->port + INTE);
1305
1306 /*
1307 * Init to 0x02109204 :
1308 * Clock accuracy = 0 (1000ppm)
1309 * Sample Rate = 2 (48kHz)
1310 * Audio Channel = 1 (Left of 2)
1311 * Source Number = 0 (Unspecified)
1312 * Generation Status = 1 (Original for Cat Code 12)
1313 * Cat Code = 12 (Digital Signal Mixer)
1314 * Mode = 0 (Mode 0)
1315 * Emphasis = 0 (None)
1316 * CP = 1 (Copyright unasserted)
1317 * AN = 0 (Audio data)
1318 * P = 0 (Consumer)
1319 */
1320 snd_ca0106_ptr_write(chip, SPCS0, 0,
1321 chip->spdif_bits[0] =
1322 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1323 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1324 SPCS_GENERATIONSTATUS | 0x00001200 |
1325 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1326 /* Only SPCS1 has been tested */
1327 snd_ca0106_ptr_write(chip, SPCS1, 0,
1328 chip->spdif_bits[1] =
1329 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1330 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1331 SPCS_GENERATIONSTATUS | 0x00001200 |
1332 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1333 snd_ca0106_ptr_write(chip, SPCS2, 0,
1334 chip->spdif_bits[2] =
1335 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1336 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1337 SPCS_GENERATIONSTATUS | 0x00001200 |
1338 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1339 snd_ca0106_ptr_write(chip, SPCS3, 0,
1340 chip->spdif_bits[3] =
1341 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1342 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1343 SPCS_GENERATIONSTATUS | 0x00001200 |
1344 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1345
1346 snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
1347 snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
1348
1349 /* Write 0x8000 to AC97_REC_GAIN to mute it. */
1350 outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
1351 outw(0x8000, chip->port + AC97DATA);
1352#if 0
1353 snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
1354 snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
1355 snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
1356 snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
1357#endif
1358
1359 //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
1360 /* Analog or Digital output */
1361 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
James Courtier-Dutton8f55fbb2005-05-21 16:45:58 +02001362 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 -07001363 chip->spdif_enable = 0; /* Set digital SPDIF output off */
1364 chip->capture_source = 3; /* Set CAPTURE_SOURCE */
1365 //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
1366 //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
1367
1368 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
1369 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
1370 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
1371 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
1372 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
1373 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
1374 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
1375 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
1376 for(ch = 0; ch < 4; ch++) {
1377 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
1378 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
1379 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
1380 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
1381 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
1382 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
1383 }
1384 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
1385 chip->capture_source = 3; /* Set CAPTURE_SOURCE */
1386
James Courtier-Duttonbe0b7b02006-04-09 20:48:44 +01001387 if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001388 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1389 outl(0x0, chip->port+GPIO);
1390 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
1391 outl(0x005f5301, chip->port+GPIO); /* Analog */
1392 } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1394 outl(0x0, chip->port+GPIO);
1395 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
James Courtier-Duttonc82bf822005-06-04 15:03:06 +02001396 outl(0x005f5301, chip->port+GPIO); /* Analog */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 } else {
1398 outl(0x0, chip->port+GPIO);
1399 outl(0x005f03a3, chip->port+GPIO); /* Analog */
1400 //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
1401 }
1402 snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
1403
1404 //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
1405 //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
1406 //outl(0x00000009, chip->port+HCFG);
1407 outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
1408
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001409 if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001410 int size, n;
1411
1412 size = ARRAY_SIZE(i2c_adc_init);
1413 //snd_printk("I2C:array size=0x%x\n", size);
1414 for (n=0; n < size; n++) {
1415 snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
1416 }
1417 for (n=0; n < 4; n++) {
1418 chip->i2c_capture_volume[n][0]= 0xcf;
1419 chip->i2c_capture_volume[n][1]= 0xcf;
1420 }
1421 chip->i2c_capture_source=2; /* Line in */
1422 //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 +02001423 }
James Courtier-Duttona5875152005-12-20 22:30:49 +01001424 if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001425 int size, n;
1426
1427 size = ARRAY_SIZE(spi_dac_init);
1428 for (n=0; n < size; n++)
1429 snd_ca0106_spi_write(chip, spi_dac_init[n]);
James Courtier-Duttona5875152005-12-20 22:30:49 +01001430 }
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001431
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
1433 chip, &ops)) < 0) {
1434 snd_ca0106_free(chip);
1435 return err;
1436 }
1437 *rchip = chip;
1438 return 0;
1439}
1440
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001441
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001442static void ca0106_midi_interrupt_enable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001443{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001444 snd_ca0106_intr_enable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001445}
1446
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001447static void ca0106_midi_interrupt_disable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001448{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001449 snd_ca0106_intr_disable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001450}
1451
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001452static unsigned char ca0106_midi_read(struct snd_ca_midi *midi, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001453{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001454 return (unsigned char)snd_ca0106_ptr_read((struct snd_ca0106 *)(midi->dev_id),
1455 midi->port + idx, 0);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001456}
1457
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001458static void ca0106_midi_write(struct snd_ca_midi *midi, int data, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001459{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001460 snd_ca0106_ptr_write((struct snd_ca0106 *)(midi->dev_id), midi->port + idx, 0, data);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001461}
1462
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001463static struct snd_card *ca0106_dev_id_card(void *dev_id)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001464{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001465 return ((struct snd_ca0106 *)dev_id)->card;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001466}
1467
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001468static int ca0106_dev_id_port(void *dev_id)
1469{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001470 return ((struct snd_ca0106 *)dev_id)->port;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001471}
1472
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001473static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001474{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001475 struct snd_ca_midi *midi;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001476 char *name;
1477 int err;
1478
Takashi Iwai95a98262005-11-17 10:40:18 +01001479 if (channel == CA0106_MIDI_CHAN_B) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001480 name = "CA0106 MPU-401 (UART) B";
1481 midi = &chip->midi2;
1482 midi->tx_enable = INTE_MIDI_TX_B;
1483 midi->rx_enable = INTE_MIDI_RX_B;
1484 midi->ipr_tx = IPR_MIDI_TX_B;
1485 midi->ipr_rx = IPR_MIDI_RX_B;
1486 midi->port = MIDI_UART_B_DATA;
1487 } else {
1488 name = "CA0106 MPU-401 (UART)";
1489 midi = &chip->midi;
1490 midi->tx_enable = INTE_MIDI_TX_A;
1491 midi->rx_enable = INTE_MIDI_TX_B;
1492 midi->ipr_tx = IPR_MIDI_TX_A;
1493 midi->ipr_rx = IPR_MIDI_RX_A;
1494 midi->port = MIDI_UART_A_DATA;
1495 }
1496
1497 midi->reset = CA0106_MPU401_RESET;
1498 midi->enter_uart = CA0106_MPU401_ENTER_UART;
1499 midi->ack = CA0106_MPU401_ACK;
1500
1501 midi->input_avail = CA0106_MIDI_INPUT_AVAIL;
1502 midi->output_ready = CA0106_MIDI_OUTPUT_READY;
1503
1504 midi->channel = channel;
1505
1506 midi->interrupt_enable = ca0106_midi_interrupt_enable;
1507 midi->interrupt_disable = ca0106_midi_interrupt_disable;
1508
1509 midi->read = ca0106_midi_read;
1510 midi->write = ca0106_midi_write;
1511
1512 midi->get_dev_id_card = ca0106_dev_id_card;
1513 midi->get_dev_id_port = ca0106_dev_id_port;
1514
1515 midi->dev_id = chip;
1516
1517 if ((err = ca_midi_init(chip, midi, 0, name)) < 0)
1518 return err;
1519
1520 return 0;
1521}
1522
1523
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1525 const struct pci_device_id *pci_id)
1526{
1527 static int dev;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001528 struct snd_card *card;
1529 struct snd_ca0106 *chip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 int err;
1531
1532 if (dev >= SNDRV_CARDS)
1533 return -ENODEV;
1534 if (!enable[dev]) {
1535 dev++;
1536 return -ENOENT;
1537 }
1538
1539 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1540 if (card == NULL)
1541 return -ENOMEM;
1542
1543 if ((err = snd_ca0106_create(card, pci, &chip)) < 0) {
1544 snd_card_free(card);
1545 return err;
1546 }
1547
1548 if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
1549 snd_card_free(card);
1550 return err;
1551 }
1552 if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
1553 snd_card_free(card);
1554 return err;
1555 }
1556 if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
1557 snd_card_free(card);
1558 return err;
1559 }
1560 if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
1561 snd_card_free(card);
1562 return err;
1563 }
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001564 if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 if ((err = snd_ca0106_ac97(chip)) < 0) {
1566 snd_card_free(card);
1567 return err;
1568 }
1569 }
1570 if ((err = snd_ca0106_mixer(chip)) < 0) {
1571 snd_card_free(card);
1572 return err;
1573 }
1574
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001575 snd_printdd("ca0106: probe for MIDI channel A ...");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001576 if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
1577 snd_card_free(card);
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001578 snd_printdd(" failed, err=0x%x\n",err);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001579 return err;
1580 }
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001581 snd_printdd(" done.\n");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001582
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001583#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 snd_ca0106_proc_init(chip);
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001585#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 if ((err = snd_card_register(card)) < 0) {
1588 snd_card_free(card);
1589 return err;
1590 }
1591
1592 pci_set_drvdata(pci, card);
1593 dev++;
1594 return 0;
1595}
1596
1597static void __devexit snd_ca0106_remove(struct pci_dev *pci)
1598{
1599 snd_card_free(pci_get_drvdata(pci));
1600 pci_set_drvdata(pci, NULL);
1601}
1602
1603// PCI IDs
Takashi Iwaif40b6892006-07-05 16:51:05 +02001604static struct pci_device_id snd_ca0106_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
1606 { 0, }
1607};
1608MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
1609
1610// pci_driver definition
1611static struct pci_driver driver = {
1612 .name = "CA0106",
1613 .id_table = snd_ca0106_ids,
1614 .probe = snd_ca0106_probe,
1615 .remove = __devexit_p(snd_ca0106_remove),
1616};
1617
1618// initialization of the module
1619static int __init alsa_card_ca0106_init(void)
1620{
Takashi Iwai95a98262005-11-17 10:40:18 +01001621 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622}
1623
1624// clean up the module
1625static void __exit alsa_card_ca0106_exit(void)
1626{
1627 pci_unregister_driver(&driver);
1628}
1629
1630module_init(alsa_card_ca0106_init)
1631module_exit(alsa_card_ca0106_exit)