blob: fd8bfebfbd541a846a20c908182406e0ce098437 [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
189 * ADC: WM8768GEDS
190 * DAC: WM8775EDS
191 */
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 */
198 { .serial = 0x10091462,
199 .name = "MSI K8N Diamond MB [SB0438]",
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200200 .gpio_type = 1,
201 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100202 /* Shuttle XPC SD31P which has an onboard Creative Labs
203 * Sound Blaster Live! 24-bit EAX
James Courtier-Dutton1b059622005-08-12 23:50:13 +0200204 * high-definition 7.1 audio processor".
205 * Added using info from andrewvegan in alsa bug #1298
206 */
207 { .serial = 0x30381297,
208 .name = "Shuttle XPC SD31P [SD31P]",
209 .gpio_type = 1,
210 .i2c_adc = 1 } ,
James Courtier-Duttonbe3cd572006-01-09 21:20:56 +0100211 /* Shuttle XPC SD11G5 which has an onboard Creative Labs
212 * Sound Blaster Live! 24-bit EAX
213 * high-definition 7.1 audio processor".
214 * Fixes ALSA bug#1600
215 */
216 { .serial = 0x30411297,
217 .name = "Shuttle XPC SD11G5 [SD11G5]",
218 .gpio_type = 1,
219 .i2c_adc = 1 } ,
James Courtier-Dutton1baa7052005-05-21 22:35:58 +0200220 { .serial = 0,
221 .name = "AudigyLS [Unknown]" }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222};
223
224/* hardware definition */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100225static struct snd_pcm_hardware snd_ca0106_playback_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 .info = (SNDRV_PCM_INFO_MMAP |
227 SNDRV_PCM_INFO_INTERLEAVED |
228 SNDRV_PCM_INFO_BLOCK_TRANSFER |
229 SNDRV_PCM_INFO_MMAP_VALID),
230 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100231 .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
232 SNDRV_PCM_RATE_192000),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 .rate_min = 48000,
234 .rate_max = 192000,
235 .channels_min = 2, //1,
236 .channels_max = 2, //6,
237 .buffer_bytes_max = ((65536 - 64) * 8),
238 .period_bytes_min = 64,
239 .period_bytes_max = (65536 - 64),
240 .periods_min = 2,
241 .periods_max = 8,
242 .fifo_size = 0,
243};
244
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100245static struct snd_pcm_hardware snd_ca0106_capture_hw = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 .info = (SNDRV_PCM_INFO_MMAP |
247 SNDRV_PCM_INFO_INTERLEAVED |
248 SNDRV_PCM_INFO_BLOCK_TRANSFER |
249 SNDRV_PCM_INFO_MMAP_VALID),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200250 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
Takashi Iwai95a98262005-11-17 10:40:18 +0100251 .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
252 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200253 .rate_min = 44100,
254 .rate_max = 192000,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 .channels_min = 2,
256 .channels_max = 2,
257 .buffer_bytes_max = ((65536 - 64) * 8),
258 .period_bytes_min = 64,
259 .period_bytes_max = (65536 - 64),
260 .periods_min = 2,
261 .periods_max = 2,
262 .fifo_size = 0,
263};
264
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100265unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 unsigned int reg,
267 unsigned int chn)
268{
269 unsigned long flags;
270 unsigned int regptr, val;
271
272 regptr = (reg << 16) | chn;
273
274 spin_lock_irqsave(&emu->emu_lock, flags);
275 outl(regptr, emu->port + PTR);
276 val = inl(emu->port + DATA);
277 spin_unlock_irqrestore(&emu->emu_lock, flags);
278 return val;
279}
280
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100281void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 unsigned int reg,
283 unsigned int chn,
284 unsigned int data)
285{
286 unsigned int regptr;
287 unsigned long flags;
288
289 regptr = (reg << 16) | chn;
290
291 spin_lock_irqsave(&emu->emu_lock, flags);
292 outl(regptr, emu->port + PTR);
293 outl(data, emu->port + DATA);
294 spin_unlock_irqrestore(&emu->emu_lock, flags);
295}
296
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100297int snd_ca0106_spi_write(struct snd_ca0106 * emu,
298 unsigned int data)
James Courtier-Duttona5875152005-12-20 22:30:49 +0100299{
James Courtier-Duttonaad90952005-12-21 22:26:26 +0100300 unsigned int reset, set;
301 unsigned int reg, tmp;
302 int n, result;
303 reg = SPI;
304 if (data > 0xffff) /* Only 16bit values allowed */
305 return 1;
306 tmp = snd_ca0106_ptr_read(emu, reg, 0);
307 reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
308 set = reset | 0x10000; /* Set xxx1xxxx */
309 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
310 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* write post */
311 snd_ca0106_ptr_write(emu, reg, 0, set | data);
312 result = 1;
313 /* Wait for status bit to return to 0 */
314 for (n = 0; n < 100; n++) {
315 udelay(10);
316 tmp = snd_ca0106_ptr_read(emu, reg, 0);
317 if (!(tmp & 0x10000)) {
318 result = 0;
319 break;
320 }
321 }
322 if (result) /* Timed out */
323 return 1;
324 snd_ca0106_ptr_write(emu, reg, 0, reset | data);
325 tmp = snd_ca0106_ptr_read(emu, reg, 0); /* Write post */
James Courtier-Duttona5875152005-12-20 22:30:49 +0100326 return 0;
327}
328
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100329int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200330 u32 reg,
331 u32 value)
332{
333 u32 tmp;
Takashi Iwai95a98262005-11-17 10:40:18 +0100334 int timeout = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200335 int status;
336 int retry;
Takashi Iwai95a98262005-11-17 10:40:18 +0100337 if ((reg > 0x7f) || (value > 0x1ff)) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200338 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200339 return -EINVAL;
340 }
341
342 tmp = reg << 25 | value << 16;
James Courtier-Dutton8fabab12005-05-28 16:35:49 +0200343 /* Not sure what this I2C channel controls. */
344 /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
345
346 /* This controls the I2C connected to the WM8775 ADC Codec */
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200347 snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
348
Takashi Iwai95a98262005-11-17 10:40:18 +0100349 for (retry = 0; retry < 10; retry++) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200350 /* Send the data to i2c */
351 tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
352 tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
353 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
354 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
355
356 /* Wait till the transaction ends */
Takashi Iwai95a98262005-11-17 10:40:18 +0100357 while (1) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200358 status = snd_ca0106_ptr_read(emu, I2C_A, 0);
359 //snd_printk("I2C:status=0x%x\n", status);
360 timeout++;
Takashi Iwai95a98262005-11-17 10:40:18 +0100361 if ((status & I2C_A_ADC_START) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200362 break;
363
Takashi Iwai95a98262005-11-17 10:40:18 +0100364 if (timeout > 1000)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200365 break;
366 }
367 //Read back and see if the transaction is successful
Takashi Iwai95a98262005-11-17 10:40:18 +0100368 if ((status & I2C_A_ADC_ABORT) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200369 break;
370 }
371
Takashi Iwai95a98262005-11-17 10:40:18 +0100372 if (retry == 10) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200373 snd_printk(KERN_ERR "Writing to ADC failed!\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200374 return -EINVAL;
375 }
376
377 return 0;
378}
379
380
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100381static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382{
383 unsigned long flags;
384 unsigned int enable;
385
386 spin_lock_irqsave(&emu->emu_lock, flags);
387 enable = inl(emu->port + INTE) | intrenb;
388 outl(enable, emu->port + INTE);
389 spin_unlock_irqrestore(&emu->emu_lock, flags);
390}
391
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100392static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +0200393{
394 unsigned long flags;
395 unsigned int enable;
396
397 spin_lock_irqsave(&emu->emu_lock, flags);
398 enable = inl(emu->port + INTE) & ~intrenb;
399 outl(enable, emu->port + INTE);
400 spin_unlock_irqrestore(&emu->emu_lock, flags);
401}
402
403
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100404static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
Jesper Juhl4d572772005-05-30 17:30:32 +0200406 kfree(runtime->private_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407}
408
409/* open_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100410static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
411 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100413 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
414 struct snd_ca0106_channel *channel = &(chip->playback_channels[channel_id]);
415 struct snd_ca0106_pcm *epcm;
416 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 int err;
418
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200419 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
421 if (epcm == NULL)
422 return -ENOMEM;
423 epcm->emu = chip;
424 epcm->substream = substream;
425 epcm->channel_id=channel_id;
426
427 runtime->private_data = epcm;
428 runtime->private_free = snd_ca0106_pcm_free_substream;
429
430 runtime->hw = snd_ca0106_playback_hw;
431
432 channel->emu = chip;
433 channel->number = channel_id;
434
Takashi Iwai95a98262005-11-17 10:40:18 +0100435 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
437 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwai95a98262005-11-17 10:40:18 +0100438 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
440 return err;
441 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
442 return err;
443 return 0;
444}
445
446/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100447static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100449 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
450 struct snd_pcm_runtime *runtime = substream->runtime;
451 struct snd_ca0106_pcm *epcm = runtime->private_data;
452 chip->playback_channels[epcm->channel_id].use = 0;
453 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 return 0;
455}
456
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100457static int snd_ca0106_pcm_open_playback_front(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458{
459 return snd_ca0106_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
460}
461
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100462static int snd_ca0106_pcm_open_playback_center_lfe(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463{
464 return snd_ca0106_pcm_open_playback_channel(substream, PCM_CENTER_LFE_CHANNEL);
465}
466
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100467static int snd_ca0106_pcm_open_playback_unknown(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{
469 return snd_ca0106_pcm_open_playback_channel(substream, PCM_UNKNOWN_CHANNEL);
470}
471
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100472static int snd_ca0106_pcm_open_playback_rear(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473{
474 return snd_ca0106_pcm_open_playback_channel(substream, PCM_REAR_CHANNEL);
475}
476
477/* open_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100478static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substream,
479 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100481 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
482 struct snd_ca0106_channel *channel = &(chip->capture_channels[channel_id]);
483 struct snd_ca0106_pcm *epcm;
484 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 int err;
486
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200487 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 if (epcm == NULL) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200489 snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 return -ENOMEM;
491 }
492 epcm->emu = chip;
493 epcm->substream = substream;
494 epcm->channel_id=channel_id;
495
496 runtime->private_data = epcm;
497 runtime->private_free = snd_ca0106_pcm_free_substream;
498
499 runtime->hw = snd_ca0106_capture_hw;
500
501 channel->emu = chip;
502 channel->number = channel_id;
503
Takashi Iwai95a98262005-11-17 10:40:18 +0100504 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
506 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100507 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
509 return err;
510 //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
511 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
512 return err;
513 return 0;
514}
515
516/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100517static int snd_ca0106_pcm_close_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100519 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
520 struct snd_pcm_runtime *runtime = substream->runtime;
521 struct snd_ca0106_pcm *epcm = runtime->private_data;
522 chip->capture_channels[epcm->channel_id].use = 0;
523 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 return 0;
525}
526
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100527static int snd_ca0106_pcm_open_0_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528{
529 return snd_ca0106_pcm_open_capture_channel(substream, 0);
530}
531
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100532static int snd_ca0106_pcm_open_1_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533{
534 return snd_ca0106_pcm_open_capture_channel(substream, 1);
535}
536
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100537static int snd_ca0106_pcm_open_2_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538{
539 return snd_ca0106_pcm_open_capture_channel(substream, 2);
540}
541
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100542static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
544 return snd_ca0106_pcm_open_capture_channel(substream, 3);
545}
546
547/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100548static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream,
549 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550{
551 return snd_pcm_lib_malloc_pages(substream,
552 params_buffer_bytes(hw_params));
553}
554
555/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100556static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557{
558 return snd_pcm_lib_free_pages(substream);
559}
560
561/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100562static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream,
563 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564{
565 return snd_pcm_lib_malloc_pages(substream,
566 params_buffer_bytes(hw_params));
567}
568
569/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100570static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
572 return snd_pcm_lib_free_pages(substream);
573}
574
575/* prepare playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100576static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100578 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
579 struct snd_pcm_runtime *runtime = substream->runtime;
580 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 int channel = epcm->channel_id;
582 u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
583 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
584 u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
585 u32 hcfg_set = 0x00000000;
586 u32 hcfg;
587 u32 reg40_mask = 0x30000 << (channel<<1);
588 u32 reg40_set = 0;
589 u32 reg40;
590 /* FIXME: Depending on mixer selection of SPDIF out or not, select the spdif rate or the DAC rate. */
591 u32 reg71_mask = 0x03030000 ; /* Global. Set SPDIF rate. We only support 44100 to spdif, not to DAC. */
592 u32 reg71_set = 0;
593 u32 reg71;
594 int i;
595
596 //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));
597 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
598 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
599 /* Rate can be set per channel. */
600 /* reg40 control host to fifo */
601 /* reg71 controls DAC rate. */
602 switch (runtime->rate) {
603 case 44100:
604 reg40_set = 0x10000 << (channel<<1);
605 reg71_set = 0x01010000;
606 break;
607 case 48000:
608 reg40_set = 0;
609 reg71_set = 0;
610 break;
611 case 96000:
612 reg40_set = 0x20000 << (channel<<1);
613 reg71_set = 0x02020000;
614 break;
615 case 192000:
616 reg40_set = 0x30000 << (channel<<1);
617 reg71_set = 0x03030000;
618 break;
619 default:
620 reg40_set = 0;
621 reg71_set = 0;
622 break;
623 }
624 /* Format is a global setting */
625 /* FIXME: Only let the first channel accessed set this. */
626 switch (runtime->format) {
627 case SNDRV_PCM_FORMAT_S16_LE:
628 hcfg_set = 0;
629 break;
630 case SNDRV_PCM_FORMAT_S32_LE:
631 hcfg_set = HCFG_PLAYBACK_S32_LE;
632 break;
633 default:
634 hcfg_set = 0;
635 break;
636 }
637 hcfg = inl(emu->port + HCFG) ;
638 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
639 outl(hcfg, emu->port + HCFG);
640 reg40 = snd_ca0106_ptr_read(emu, 0x40, 0);
641 reg40 = (reg40 & ~reg40_mask) | reg40_set;
642 snd_ca0106_ptr_write(emu, 0x40, 0, reg40);
643 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
644 reg71 = (reg71 & ~reg71_mask) | reg71_set;
645 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
646
647 /* FIXME: Check emu->buffer.size before actually writing to it. */
648 for(i=0; i < runtime->periods; i++) {
Takashi Iwai95a98262005-11-17 10:40:18 +0100649 table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
650 table_base[i*2+1] = period_size_bytes << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 }
652
653 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
654 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
655 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
656 snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
657 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
658 /* FIXME test what 0 bytes does. */
659 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
660 snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
661 snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
662 snd_ca0106_ptr_write(emu, 0x08, channel, 0);
663 snd_ca0106_ptr_write(emu, PLAYBACK_MUTE, 0x0, 0x0); /* Unmute output */
664#if 0
665 snd_ca0106_ptr_write(emu, SPCS0, 0,
666 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
667 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
668 SPCS_GENERATIONSTATUS | 0x00001200 |
669 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
670 }
671#endif
672
673 return 0;
674}
675
676/* prepare capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100677static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100679 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
680 struct snd_pcm_runtime *runtime = substream->runtime;
681 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 int channel = epcm->channel_id;
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200683 u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
684 u32 hcfg_set = 0x00000000;
685 u32 hcfg;
686 u32 over_sampling=0x2;
687 u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
688 u32 reg71_set = 0;
689 u32 reg71;
690
691 //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));
692 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
693 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
694 /* reg71 controls ADC rate. */
695 switch (runtime->rate) {
696 case 44100:
697 reg71_set = 0x00004000;
698 break;
699 case 48000:
700 reg71_set = 0;
701 break;
702 case 96000:
703 reg71_set = 0x00008000;
704 over_sampling=0xa;
705 break;
706 case 192000:
707 reg71_set = 0x0000c000;
708 over_sampling=0xa;
709 break;
710 default:
711 reg71_set = 0;
712 break;
713 }
714 /* Format is a global setting */
715 /* FIXME: Only let the first channel accessed set this. */
716 switch (runtime->format) {
717 case SNDRV_PCM_FORMAT_S16_LE:
718 hcfg_set = 0;
719 break;
720 case SNDRV_PCM_FORMAT_S32_LE:
721 hcfg_set = HCFG_CAPTURE_S32_LE;
722 break;
723 default:
724 hcfg_set = 0;
725 break;
726 }
727 hcfg = inl(emu->port + HCFG) ;
728 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
729 outl(hcfg, emu->port + HCFG);
730 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
731 reg71 = (reg71 & ~reg71_mask) | reg71_set;
732 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
733 if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
734 snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
735 }
736
737
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 //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));
739 snd_ca0106_ptr_write(emu, 0x13, channel, 0);
740 snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
741 snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
742 snd_ca0106_ptr_write(emu, CAPTURE_POINTER, channel, 0);
743
744 return 0;
745}
746
747/* trigger_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100748static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 int cmd)
750{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100751 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
752 struct snd_pcm_runtime *runtime;
753 struct snd_ca0106_pcm *epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 int channel;
755 int result = 0;
756 struct list_head *pos;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100757 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 u32 basic = 0;
759 u32 extended = 0;
760 int running=0;
761
762 switch (cmd) {
763 case SNDRV_PCM_TRIGGER_START:
764 running=1;
765 break;
766 case SNDRV_PCM_TRIGGER_STOP:
767 default:
768 running=0;
769 break;
770 }
771 snd_pcm_group_for_each(pos, substream) {
772 s = snd_pcm_group_substream_entry(pos);
773 runtime = s->runtime;
774 epcm = runtime->private_data;
775 channel = epcm->channel_id;
776 //snd_printk("channel=%d\n",channel);
777 epcm->running = running;
778 basic |= (0x1<<channel);
779 extended |= (0x10<<channel);
780 snd_pcm_trigger_done(s, substream);
781 }
782 //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
783
784 switch (cmd) {
785 case SNDRV_PCM_TRIGGER_START:
786 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
787 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
788 break;
789 case SNDRV_PCM_TRIGGER_STOP:
790 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
791 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
792 break;
793 default:
794 result = -EINVAL;
795 break;
796 }
797 return result;
798}
799
800/* trigger_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100801static int snd_ca0106_pcm_trigger_capture(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 int cmd)
803{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100804 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
805 struct snd_pcm_runtime *runtime = substream->runtime;
806 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 int channel = epcm->channel_id;
808 int result = 0;
809
810 switch (cmd) {
811 case SNDRV_PCM_TRIGGER_START:
812 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
813 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
814 epcm->running = 1;
815 break;
816 case SNDRV_PCM_TRIGGER_STOP:
817 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
818 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
819 epcm->running = 0;
820 break;
821 default:
822 result = -EINVAL;
823 break;
824 }
825 return result;
826}
827
828/* pointer_playback callback */
829static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100830snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100832 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
833 struct snd_pcm_runtime *runtime = substream->runtime;
834 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
836 int channel = epcm->channel_id;
837
838 if (!epcm->running)
839 return 0;
840
841 ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
842 ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
843 ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
844 if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
845 ptr2 = bytes_to_frames(runtime, ptr1);
846 ptr2+= (ptr4 >> 3) * runtime->period_size;
847 ptr=ptr2;
848 if (ptr >= runtime->buffer_size)
849 ptr -= runtime->buffer_size;
850 //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);
851
852 return ptr;
853}
854
855/* pointer_capture callback */
856static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100857snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100859 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
860 struct snd_pcm_runtime *runtime = substream->runtime;
861 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
863 int channel = channel=epcm->channel_id;
864
865 if (!epcm->running)
866 return 0;
867
868 ptr1 = snd_ca0106_ptr_read(emu, CAPTURE_POINTER, channel);
869 ptr2 = bytes_to_frames(runtime, ptr1);
870 ptr=ptr2;
871 if (ptr >= runtime->buffer_size)
872 ptr -= runtime->buffer_size;
873 //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);
874
875 return ptr;
876}
877
878/* operators */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100879static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 .open = snd_ca0106_pcm_open_playback_front,
881 .close = snd_ca0106_pcm_close_playback,
882 .ioctl = snd_pcm_lib_ioctl,
883 .hw_params = snd_ca0106_pcm_hw_params_playback,
884 .hw_free = snd_ca0106_pcm_hw_free_playback,
885 .prepare = snd_ca0106_pcm_prepare_playback,
886 .trigger = snd_ca0106_pcm_trigger_playback,
887 .pointer = snd_ca0106_pcm_pointer_playback,
888};
889
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100890static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 .open = snd_ca0106_pcm_open_0_capture,
892 .close = snd_ca0106_pcm_close_capture,
893 .ioctl = snd_pcm_lib_ioctl,
894 .hw_params = snd_ca0106_pcm_hw_params_capture,
895 .hw_free = snd_ca0106_pcm_hw_free_capture,
896 .prepare = snd_ca0106_pcm_prepare_capture,
897 .trigger = snd_ca0106_pcm_trigger_capture,
898 .pointer = snd_ca0106_pcm_pointer_capture,
899};
900
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100901static struct snd_pcm_ops snd_ca0106_capture_1_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 .open = snd_ca0106_pcm_open_1_capture,
903 .close = snd_ca0106_pcm_close_capture,
904 .ioctl = snd_pcm_lib_ioctl,
905 .hw_params = snd_ca0106_pcm_hw_params_capture,
906 .hw_free = snd_ca0106_pcm_hw_free_capture,
907 .prepare = snd_ca0106_pcm_prepare_capture,
908 .trigger = snd_ca0106_pcm_trigger_capture,
909 .pointer = snd_ca0106_pcm_pointer_capture,
910};
911
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100912static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 .open = snd_ca0106_pcm_open_2_capture,
914 .close = snd_ca0106_pcm_close_capture,
915 .ioctl = snd_pcm_lib_ioctl,
916 .hw_params = snd_ca0106_pcm_hw_params_capture,
917 .hw_free = snd_ca0106_pcm_hw_free_capture,
918 .prepare = snd_ca0106_pcm_prepare_capture,
919 .trigger = snd_ca0106_pcm_trigger_capture,
920 .pointer = snd_ca0106_pcm_pointer_capture,
921};
922
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100923static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 .open = snd_ca0106_pcm_open_3_capture,
925 .close = snd_ca0106_pcm_close_capture,
926 .ioctl = snd_pcm_lib_ioctl,
927 .hw_params = snd_ca0106_pcm_hw_params_capture,
928 .hw_free = snd_ca0106_pcm_hw_free_capture,
929 .prepare = snd_ca0106_pcm_prepare_capture,
930 .trigger = snd_ca0106_pcm_trigger_capture,
931 .pointer = snd_ca0106_pcm_pointer_capture,
932};
933
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100934static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 .open = snd_ca0106_pcm_open_playback_center_lfe,
936 .close = snd_ca0106_pcm_close_playback,
937 .ioctl = snd_pcm_lib_ioctl,
938 .hw_params = snd_ca0106_pcm_hw_params_playback,
939 .hw_free = snd_ca0106_pcm_hw_free_playback,
940 .prepare = snd_ca0106_pcm_prepare_playback,
941 .trigger = snd_ca0106_pcm_trigger_playback,
942 .pointer = snd_ca0106_pcm_pointer_playback,
943};
944
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100945static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 .open = snd_ca0106_pcm_open_playback_unknown,
947 .close = snd_ca0106_pcm_close_playback,
948 .ioctl = snd_pcm_lib_ioctl,
949 .hw_params = snd_ca0106_pcm_hw_params_playback,
950 .hw_free = snd_ca0106_pcm_hw_free_playback,
951 .prepare = snd_ca0106_pcm_prepare_playback,
952 .trigger = snd_ca0106_pcm_trigger_playback,
953 .pointer = snd_ca0106_pcm_pointer_playback,
954};
955
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100956static struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 .open = snd_ca0106_pcm_open_playback_rear,
958 .close = snd_ca0106_pcm_close_playback,
959 .ioctl = snd_pcm_lib_ioctl,
960 .hw_params = snd_ca0106_pcm_hw_params_playback,
961 .hw_free = snd_ca0106_pcm_hw_free_playback,
962 .prepare = snd_ca0106_pcm_prepare_playback,
963 .trigger = snd_ca0106_pcm_trigger_playback,
964 .pointer = snd_ca0106_pcm_pointer_playback,
965};
966
967
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100968static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 unsigned short reg)
970{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100971 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 unsigned long flags;
973 unsigned short val;
974
975 spin_lock_irqsave(&emu->emu_lock, flags);
976 outb(reg, emu->port + AC97ADDRESS);
977 val = inw(emu->port + AC97DATA);
978 spin_unlock_irqrestore(&emu->emu_lock, flags);
979 return val;
980}
981
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100982static void snd_ca0106_ac97_write(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 unsigned short reg, unsigned short val)
984{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100985 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 unsigned long flags;
987
988 spin_lock_irqsave(&emu->emu_lock, flags);
989 outb(reg, emu->port + AC97ADDRESS);
990 outw(val, emu->port + AC97DATA);
991 spin_unlock_irqrestore(&emu->emu_lock, flags);
992}
993
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100994static int snd_ca0106_ac97(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100996 struct snd_ac97_bus *pbus;
997 struct snd_ac97_template ac97;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 int err;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100999 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 .write = snd_ca0106_ac97_write,
1001 .read = snd_ca0106_ac97_read,
1002 };
1003
1004 if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
1005 return err;
1006 pbus->no_vra = 1; /* we don't need VRA */
1007
1008 memset(&ac97, 0, sizeof(ac97));
1009 ac97.private_data = chip;
Takashi Iwai36c4dc42005-03-24 17:48:30 +01001010 ac97.scaps = AC97_SCAP_NO_SPDIF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
1012}
1013
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001014static int snd_ca0106_free(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015{
1016 if (chip->res_port != NULL) { /* avoid access to already used hardware */
1017 // disable interrupts
1018 snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
1019 outl(0, chip->port + INTE);
1020 snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
1021 udelay(1000);
1022 // disable audio
1023 //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
1024 outl(0, chip->port + HCFG);
1025 /* FIXME: We need to stop and DMA transfers here.
1026 * But as I am not sure how yet, we cannot from the dma pages.
1027 * So we can fix: snd-malloc: Memory leak? pages not freed = 8
1028 */
1029 }
1030 // release the data
1031#if 1
1032 if (chip->buffer.area)
1033 snd_dma_free_pages(&chip->buffer);
1034#endif
1035
1036 // release the i/o port
Takashi Iwaib1d57762005-10-10 11:56:31 +02001037 release_and_free_resource(chip->res_port);
1038
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 // release the irq
1040 if (chip->irq >= 0)
1041 free_irq(chip->irq, (void *)chip);
1042 pci_disable_device(chip->pci);
1043 kfree(chip);
1044 return 0;
1045}
1046
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001047static int snd_ca0106_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001049 struct snd_ca0106 *chip = device->device_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 return snd_ca0106_free(chip);
1051}
1052
1053static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
1054 struct pt_regs *regs)
1055{
1056 unsigned int status;
1057
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001058 struct snd_ca0106 *chip = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 int i;
1060 int mask;
1061 unsigned int stat76;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001062 struct snd_ca0106_channel *pchannel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 status = inl(chip->port + IPR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 if (! status)
1066 return IRQ_NONE;
1067
1068 stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0);
1069 //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76);
1070 //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0));
1071 mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
1072 for(i = 0; i < 4; i++) {
1073 pchannel = &(chip->playback_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001074 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075/* FIXME: Select the correct substream for period elapsed */
1076 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001077 snd_pcm_period_elapsed(pchannel->epcm->substream);
1078 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 }
1080 }
1081 //printk(KERN_INFO "channel=%p\n",pchannel);
1082 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1083 mask <<= 1;
1084 }
1085 mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */
1086 for(i = 0; i < 4; i++) {
1087 pchannel = &(chip->capture_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001088 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089/* FIXME: Select the correct substream for period elapsed */
1090 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001091 snd_pcm_period_elapsed(pchannel->epcm->substream);
1092 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 }
1094 }
1095 //printk(KERN_INFO "channel=%p\n",pchannel);
1096 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1097 mask <<= 1;
1098 }
1099
1100 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001101
1102 if (chip->midi.dev_id &&
Takashi Iwai95a98262005-11-17 10:40:18 +01001103 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001104 if (chip->midi.interrupt)
1105 chip->midi.interrupt(&chip->midi, status);
1106 else
1107 chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable);
1108 }
1109
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 // acknowledge the interrupt if necessary
1111 outl(status, chip->port+IPR);
1112
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 return IRQ_HANDLED;
1114}
1115
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001116static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001118 struct snd_pcm *pcm;
1119 struct snd_pcm_substream *substream;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 int err;
1121
1122 if (rpcm)
1123 *rpcm = NULL;
1124 if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
1125 return err;
1126
1127 pcm->private_data = emu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
1129 switch (device) {
1130 case 0:
1131 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops);
1132 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops);
1133 break;
1134 case 1:
1135 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops);
1136 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops);
1137 break;
1138 case 2:
1139 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops);
1140 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops);
1141 break;
1142 case 3:
1143 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops);
1144 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops);
1145 break;
1146 }
1147
1148 pcm->info_flags = 0;
1149 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
1150 strcpy(pcm->name, "CA0106");
1151 emu->pcm = pcm;
1152
1153 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1154 substream;
1155 substream = substream->next) {
1156 if ((err = snd_pcm_lib_preallocate_pages(substream,
1157 SNDRV_DMA_TYPE_DEV,
1158 snd_dma_pci_data(emu->pci),
1159 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
1160 return err;
1161 }
1162
1163 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1164 substream;
1165 substream = substream->next) {
1166 if ((err = snd_pcm_lib_preallocate_pages(substream,
1167 SNDRV_DMA_TYPE_DEV,
1168 snd_dma_pci_data(emu->pci),
1169 64*1024, 64*1024)) < 0)
1170 return err;
1171 }
1172
1173 if (rpcm)
1174 *rpcm = pcm;
1175
1176 return 0;
1177}
1178
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001179static unsigned int spi_dac_init[] = {
1180 0x00ff,
1181 0x02ff,
1182 0x0400,
1183 0x0520,
1184 0x0600,
1185 0x08ff,
1186 0x0aff,
1187 0x0cff,
1188 0x0eff,
1189 0x10ff,
1190 0x1200,
1191 0x1400,
1192 0x1480,
1193 0x1800,
1194 0x1aff,
1195 0x1cff,
1196 0x1e00,
1197 0x0530,
1198 0x0602,
1199 0x0622,
1200 0x1400,
1201};
1202
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001203static int __devinit snd_ca0106_create(struct snd_card *card,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 struct pci_dev *pci,
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001205 struct snd_ca0106 **rchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001207 struct snd_ca0106 *chip;
1208 struct snd_ca0106_details *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 int err;
1210 int ch;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001211 static struct snd_device_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 .dev_free = snd_ca0106_dev_free,
1213 };
1214
1215 *rchip = NULL;
1216
1217 if ((err = pci_enable_device(pci)) < 0)
1218 return err;
Tobias Klauser299676b2005-05-29 15:21:02 +02001219 if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
1220 pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 printk(KERN_ERR "error to set 32bit mask DMA\n");
1222 pci_disable_device(pci);
1223 return -ENXIO;
1224 }
1225
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001226 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 if (chip == NULL) {
1228 pci_disable_device(pci);
1229 return -ENOMEM;
1230 }
1231
1232 chip->card = card;
1233 chip->pci = pci;
1234 chip->irq = -1;
1235
1236 spin_lock_init(&chip->emu_lock);
1237
1238 chip->port = pci_resource_start(pci, 0);
1239 if ((chip->res_port = request_region(chip->port, 0x20,
1240 "snd_ca0106")) == NULL) {
1241 snd_ca0106_free(chip);
1242 printk(KERN_ERR "cannot allocate the port\n");
1243 return -EBUSY;
1244 }
1245
1246 if (request_irq(pci->irq, snd_ca0106_interrupt,
1247 SA_INTERRUPT|SA_SHIRQ, "snd_ca0106",
1248 (void *)chip)) {
1249 snd_ca0106_free(chip);
1250 printk(KERN_ERR "cannot grab irq\n");
1251 return -EBUSY;
1252 }
1253 chip->irq = pci->irq;
1254
1255 /* This stores the periods table. */
1256 if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
1257 snd_ca0106_free(chip);
1258 return -ENOMEM;
1259 }
1260
1261 pci_set_master(pci);
1262 /* read revision & serial */
1263 pci_read_config_byte(pci, PCI_REVISION_ID, (char *)&chip->revision);
1264 pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
1265 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
1266#if 1
1267 printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
1268 chip->revision, chip->serial);
1269#endif
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001270 strcpy(card->driver, "CA0106");
1271 strcpy(card->shortname, "CA0106");
1272
Takashi Iwai95a98262005-11-17 10:40:18 +01001273 for (c = ca0106_chip_details; c->serial; c++) {
1274 if (c->serial == chip->serial)
1275 break;
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001276 }
1277 chip->details = c;
1278 sprintf(card->longname, "%s at 0x%lx irq %i",
1279 c->name, chip->port, chip->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
1281 outl(0, chip->port + INTE);
1282
1283 /*
1284 * Init to 0x02109204 :
1285 * Clock accuracy = 0 (1000ppm)
1286 * Sample Rate = 2 (48kHz)
1287 * Audio Channel = 1 (Left of 2)
1288 * Source Number = 0 (Unspecified)
1289 * Generation Status = 1 (Original for Cat Code 12)
1290 * Cat Code = 12 (Digital Signal Mixer)
1291 * Mode = 0 (Mode 0)
1292 * Emphasis = 0 (None)
1293 * CP = 1 (Copyright unasserted)
1294 * AN = 0 (Audio data)
1295 * P = 0 (Consumer)
1296 */
1297 snd_ca0106_ptr_write(chip, SPCS0, 0,
1298 chip->spdif_bits[0] =
1299 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1300 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1301 SPCS_GENERATIONSTATUS | 0x00001200 |
1302 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1303 /* Only SPCS1 has been tested */
1304 snd_ca0106_ptr_write(chip, SPCS1, 0,
1305 chip->spdif_bits[1] =
1306 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1307 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1308 SPCS_GENERATIONSTATUS | 0x00001200 |
1309 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1310 snd_ca0106_ptr_write(chip, SPCS2, 0,
1311 chip->spdif_bits[2] =
1312 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1313 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1314 SPCS_GENERATIONSTATUS | 0x00001200 |
1315 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1316 snd_ca0106_ptr_write(chip, SPCS3, 0,
1317 chip->spdif_bits[3] =
1318 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1319 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1320 SPCS_GENERATIONSTATUS | 0x00001200 |
1321 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1322
1323 snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
1324 snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
1325
1326 /* Write 0x8000 to AC97_REC_GAIN to mute it. */
1327 outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
1328 outw(0x8000, chip->port + AC97DATA);
1329#if 0
1330 snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
1331 snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
1332 snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
1333 snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
1334#endif
1335
1336 //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
1337 /* Analog or Digital output */
1338 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
James Courtier-Dutton8f55fbb2005-05-21 16:45:58 +02001339 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 -07001340 chip->spdif_enable = 0; /* Set digital SPDIF output off */
1341 chip->capture_source = 3; /* Set CAPTURE_SOURCE */
1342 //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
1343 //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
1344
1345 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
1346 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
1347 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
1348 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
1349 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
1350 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
1351 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
1352 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
1353 for(ch = 0; ch < 4; ch++) {
1354 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
1355 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
1356 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
1357 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
1358 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
1359 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
1360 }
1361 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
1362 chip->capture_source = 3; /* Set CAPTURE_SOURCE */
1363
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001364 if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1366 outl(0x0, chip->port+GPIO);
1367 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
James Courtier-Duttonc82bf822005-06-04 15:03:06 +02001368 outl(0x005f5301, chip->port+GPIO); /* Analog */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 } else {
1370 outl(0x0, chip->port+GPIO);
1371 outl(0x005f03a3, chip->port+GPIO); /* Analog */
1372 //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
1373 }
1374 snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
1375
1376 //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
1377 //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
1378 //outl(0x00000009, chip->port+HCFG);
1379 outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
1380
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001381 if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
1382 snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
1383 }
James Courtier-Duttona5875152005-12-20 22:30:49 +01001384 if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001385 int size, n;
1386
1387 size = ARRAY_SIZE(spi_dac_init);
1388 for (n=0; n < size; n++)
1389 snd_ca0106_spi_write(chip, spi_dac_init[n]);
James Courtier-Duttona5875152005-12-20 22:30:49 +01001390 }
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
1393 chip, &ops)) < 0) {
1394 snd_ca0106_free(chip);
1395 return err;
1396 }
1397 *rchip = chip;
1398 return 0;
1399}
1400
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001401
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001402static void ca0106_midi_interrupt_enable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001403{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001404 snd_ca0106_intr_enable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001405}
1406
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001407static void ca0106_midi_interrupt_disable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001408{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001409 snd_ca0106_intr_disable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001410}
1411
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001412static unsigned char ca0106_midi_read(struct snd_ca_midi *midi, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001413{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001414 return (unsigned char)snd_ca0106_ptr_read((struct snd_ca0106 *)(midi->dev_id),
1415 midi->port + idx, 0);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001416}
1417
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001418static void ca0106_midi_write(struct snd_ca_midi *midi, int data, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001419{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001420 snd_ca0106_ptr_write((struct snd_ca0106 *)(midi->dev_id), midi->port + idx, 0, data);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001421}
1422
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001423static struct snd_card *ca0106_dev_id_card(void *dev_id)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001424{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001425 return ((struct snd_ca0106 *)dev_id)->card;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001426}
1427
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001428static int ca0106_dev_id_port(void *dev_id)
1429{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001430 return ((struct snd_ca0106 *)dev_id)->port;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001431}
1432
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001433static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001434{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001435 struct snd_ca_midi *midi;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001436 char *name;
1437 int err;
1438
Takashi Iwai95a98262005-11-17 10:40:18 +01001439 if (channel == CA0106_MIDI_CHAN_B) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001440 name = "CA0106 MPU-401 (UART) B";
1441 midi = &chip->midi2;
1442 midi->tx_enable = INTE_MIDI_TX_B;
1443 midi->rx_enable = INTE_MIDI_RX_B;
1444 midi->ipr_tx = IPR_MIDI_TX_B;
1445 midi->ipr_rx = IPR_MIDI_RX_B;
1446 midi->port = MIDI_UART_B_DATA;
1447 } else {
1448 name = "CA0106 MPU-401 (UART)";
1449 midi = &chip->midi;
1450 midi->tx_enable = INTE_MIDI_TX_A;
1451 midi->rx_enable = INTE_MIDI_TX_B;
1452 midi->ipr_tx = IPR_MIDI_TX_A;
1453 midi->ipr_rx = IPR_MIDI_RX_A;
1454 midi->port = MIDI_UART_A_DATA;
1455 }
1456
1457 midi->reset = CA0106_MPU401_RESET;
1458 midi->enter_uart = CA0106_MPU401_ENTER_UART;
1459 midi->ack = CA0106_MPU401_ACK;
1460
1461 midi->input_avail = CA0106_MIDI_INPUT_AVAIL;
1462 midi->output_ready = CA0106_MIDI_OUTPUT_READY;
1463
1464 midi->channel = channel;
1465
1466 midi->interrupt_enable = ca0106_midi_interrupt_enable;
1467 midi->interrupt_disable = ca0106_midi_interrupt_disable;
1468
1469 midi->read = ca0106_midi_read;
1470 midi->write = ca0106_midi_write;
1471
1472 midi->get_dev_id_card = ca0106_dev_id_card;
1473 midi->get_dev_id_port = ca0106_dev_id_port;
1474
1475 midi->dev_id = chip;
1476
1477 if ((err = ca_midi_init(chip, midi, 0, name)) < 0)
1478 return err;
1479
1480 return 0;
1481}
1482
1483
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1485 const struct pci_device_id *pci_id)
1486{
1487 static int dev;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001488 struct snd_card *card;
1489 struct snd_ca0106 *chip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 int err;
1491
1492 if (dev >= SNDRV_CARDS)
1493 return -ENODEV;
1494 if (!enable[dev]) {
1495 dev++;
1496 return -ENOENT;
1497 }
1498
1499 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1500 if (card == NULL)
1501 return -ENOMEM;
1502
1503 if ((err = snd_ca0106_create(card, pci, &chip)) < 0) {
1504 snd_card_free(card);
1505 return err;
1506 }
1507
1508 if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
1509 snd_card_free(card);
1510 return err;
1511 }
1512 if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
1513 snd_card_free(card);
1514 return err;
1515 }
1516 if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
1517 snd_card_free(card);
1518 return err;
1519 }
1520 if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
1521 snd_card_free(card);
1522 return err;
1523 }
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001524 if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 if ((err = snd_ca0106_ac97(chip)) < 0) {
1526 snd_card_free(card);
1527 return err;
1528 }
1529 }
1530 if ((err = snd_ca0106_mixer(chip)) < 0) {
1531 snd_card_free(card);
1532 return err;
1533 }
1534
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001535 snd_printdd("ca0106: probe for MIDI channel A ...");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001536 if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
1537 snd_card_free(card);
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001538 snd_printdd(" failed, err=0x%x\n",err);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001539 return err;
1540 }
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001541 snd_printdd(" done.\n");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001542
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001543#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 snd_ca0106_proc_init(chip);
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001545#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 if ((err = snd_card_register(card)) < 0) {
1548 snd_card_free(card);
1549 return err;
1550 }
1551
1552 pci_set_drvdata(pci, card);
1553 dev++;
1554 return 0;
1555}
1556
1557static void __devexit snd_ca0106_remove(struct pci_dev *pci)
1558{
1559 snd_card_free(pci_get_drvdata(pci));
1560 pci_set_drvdata(pci, NULL);
1561}
1562
1563// PCI IDs
Henrik Kretzschmar396c9b92006-04-24 15:59:04 +02001564static struct pci_device_id snd_ca0106_ids[] __devinitdata = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
1566 { 0, }
1567};
1568MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
1569
1570// pci_driver definition
1571static struct pci_driver driver = {
1572 .name = "CA0106",
1573 .id_table = snd_ca0106_ids,
1574 .probe = snd_ca0106_probe,
1575 .remove = __devexit_p(snd_ca0106_remove),
1576};
1577
1578// initialization of the module
1579static int __init alsa_card_ca0106_init(void)
1580{
Takashi Iwai95a98262005-11-17 10:40:18 +01001581 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582}
1583
1584// clean up the module
1585static void __exit alsa_card_ca0106_exit(void)
1586{
1587 pci_unregister_driver(&driver);
1588}
1589
1590module_init(alsa_card_ca0106_init)
1591module_exit(alsa_card_ca0106_exit)