blob: 3762f58384e0e86a890f1045b2ff06e3844d9837 [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
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100329/* The ADC does not support i2c read, so only write is implemented */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100330int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200331 u32 reg,
332 u32 value)
333{
334 u32 tmp;
Takashi Iwai95a98262005-11-17 10:40:18 +0100335 int timeout = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200336 int status;
337 int retry;
Takashi Iwai95a98262005-11-17 10:40:18 +0100338 if ((reg > 0x7f) || (value > 0x1ff)) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200339 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200340 return -EINVAL;
341 }
342
343 tmp = reg << 25 | value << 16;
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100344 // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
James Courtier-Dutton8fabab12005-05-28 16:35:49 +0200345 /* Not sure what this I2C channel controls. */
346 /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
347
348 /* This controls the I2C connected to the WM8775 ADC Codec */
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200349 snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
350
Takashi Iwai95a98262005-11-17 10:40:18 +0100351 for (retry = 0; retry < 10; retry++) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200352 /* Send the data to i2c */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +0100353 //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
354 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
355 tmp = 0;
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200356 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
357 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
358
359 /* Wait till the transaction ends */
Takashi Iwai95a98262005-11-17 10:40:18 +0100360 while (1) {
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200361 status = snd_ca0106_ptr_read(emu, I2C_A, 0);
362 //snd_printk("I2C:status=0x%x\n", status);
363 timeout++;
Takashi Iwai95a98262005-11-17 10:40:18 +0100364 if ((status & I2C_A_ADC_START) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200365 break;
366
Takashi Iwai95a98262005-11-17 10:40:18 +0100367 if (timeout > 1000)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200368 break;
369 }
370 //Read back and see if the transaction is successful
Takashi Iwai95a98262005-11-17 10:40:18 +0100371 if ((status & I2C_A_ADC_ABORT) == 0)
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200372 break;
373 }
374
Takashi Iwai95a98262005-11-17 10:40:18 +0100375 if (retry == 10) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200376 snd_printk(KERN_ERR "Writing to ADC failed!\n");
James Courtier-Dutton7199acd2005-05-27 22:07:23 +0200377 return -EINVAL;
378 }
379
380 return 0;
381}
382
383
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100384static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385{
386 unsigned long flags;
387 unsigned int enable;
388
389 spin_lock_irqsave(&emu->emu_lock, flags);
390 enable = inl(emu->port + INTE) | intrenb;
391 outl(enable, emu->port + INTE);
392 spin_unlock_irqrestore(&emu->emu_lock, flags);
393}
394
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100395static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +0200396{
397 unsigned long flags;
398 unsigned int enable;
399
400 spin_lock_irqsave(&emu->emu_lock, flags);
401 enable = inl(emu->port + INTE) & ~intrenb;
402 outl(enable, emu->port + INTE);
403 spin_unlock_irqrestore(&emu->emu_lock, flags);
404}
405
406
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100407static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
Jesper Juhl4d572772005-05-30 17:30:32 +0200409 kfree(runtime->private_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410}
411
412/* open_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100413static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
414 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100416 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
417 struct snd_ca0106_channel *channel = &(chip->playback_channels[channel_id]);
418 struct snd_ca0106_pcm *epcm;
419 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 int err;
421
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200422 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
424 if (epcm == NULL)
425 return -ENOMEM;
426 epcm->emu = chip;
427 epcm->substream = substream;
428 epcm->channel_id=channel_id;
429
430 runtime->private_data = epcm;
431 runtime->private_free = snd_ca0106_pcm_free_substream;
432
433 runtime->hw = snd_ca0106_playback_hw;
434
435 channel->emu = chip;
436 channel->number = channel_id;
437
Takashi Iwai95a98262005-11-17 10:40:18 +0100438 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
440 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwai95a98262005-11-17 10:40:18 +0100441 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
443 return err;
444 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
445 return err;
446 return 0;
447}
448
449/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100450static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100452 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
453 struct snd_pcm_runtime *runtime = substream->runtime;
454 struct snd_ca0106_pcm *epcm = runtime->private_data;
455 chip->playback_channels[epcm->channel_id].use = 0;
456 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 return 0;
458}
459
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100460static int snd_ca0106_pcm_open_playback_front(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
462 return snd_ca0106_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
463}
464
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100465static int snd_ca0106_pcm_open_playback_center_lfe(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
467 return snd_ca0106_pcm_open_playback_channel(substream, PCM_CENTER_LFE_CHANNEL);
468}
469
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100470static int snd_ca0106_pcm_open_playback_unknown(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471{
472 return snd_ca0106_pcm_open_playback_channel(substream, PCM_UNKNOWN_CHANNEL);
473}
474
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100475static int snd_ca0106_pcm_open_playback_rear(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476{
477 return snd_ca0106_pcm_open_playback_channel(substream, PCM_REAR_CHANNEL);
478}
479
480/* open_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100481static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substream,
482 int channel_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100484 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
485 struct snd_ca0106_channel *channel = &(chip->capture_channels[channel_id]);
486 struct snd_ca0106_pcm *epcm;
487 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 int err;
489
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200490 epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 if (epcm == NULL) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200492 snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 return -ENOMEM;
494 }
495 epcm->emu = chip;
496 epcm->substream = substream;
497 epcm->channel_id=channel_id;
498
499 runtime->private_data = epcm;
500 runtime->private_free = snd_ca0106_pcm_free_substream;
501
502 runtime->hw = snd_ca0106_capture_hw;
503
504 channel->emu = chip;
505 channel->number = channel_id;
506
Takashi Iwai95a98262005-11-17 10:40:18 +0100507 channel->use = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
509 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100510 channel->epcm = epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
512 return err;
513 //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
514 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
515 return err;
516 return 0;
517}
518
519/* close callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100520static int snd_ca0106_pcm_close_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100522 struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
523 struct snd_pcm_runtime *runtime = substream->runtime;
524 struct snd_ca0106_pcm *epcm = runtime->private_data;
525 chip->capture_channels[epcm->channel_id].use = 0;
526 /* FIXME: maybe zero others */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 return 0;
528}
529
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100530static int snd_ca0106_pcm_open_0_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531{
532 return snd_ca0106_pcm_open_capture_channel(substream, 0);
533}
534
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100535static int snd_ca0106_pcm_open_1_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536{
537 return snd_ca0106_pcm_open_capture_channel(substream, 1);
538}
539
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100540static int snd_ca0106_pcm_open_2_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541{
542 return snd_ca0106_pcm_open_capture_channel(substream, 2);
543}
544
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100545static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546{
547 return snd_ca0106_pcm_open_capture_channel(substream, 3);
548}
549
550/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100551static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream,
552 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553{
554 return snd_pcm_lib_malloc_pages(substream,
555 params_buffer_bytes(hw_params));
556}
557
558/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100559static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
561 return snd_pcm_lib_free_pages(substream);
562}
563
564/* hw_params callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100565static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream,
566 struct snd_pcm_hw_params *hw_params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567{
568 return snd_pcm_lib_malloc_pages(substream,
569 params_buffer_bytes(hw_params));
570}
571
572/* hw_free callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100573static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574{
575 return snd_pcm_lib_free_pages(substream);
576}
577
578/* prepare playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100579static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100581 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
582 struct snd_pcm_runtime *runtime = substream->runtime;
583 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 int channel = epcm->channel_id;
585 u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
586 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
587 u32 hcfg_mask = HCFG_PLAYBACK_S32_LE;
588 u32 hcfg_set = 0x00000000;
589 u32 hcfg;
590 u32 reg40_mask = 0x30000 << (channel<<1);
591 u32 reg40_set = 0;
592 u32 reg40;
593 /* FIXME: Depending on mixer selection of SPDIF out or not, select the spdif rate or the DAC rate. */
594 u32 reg71_mask = 0x03030000 ; /* Global. Set SPDIF rate. We only support 44100 to spdif, not to DAC. */
595 u32 reg71_set = 0;
596 u32 reg71;
597 int i;
598
599 //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));
600 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
601 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
602 /* Rate can be set per channel. */
603 /* reg40 control host to fifo */
604 /* reg71 controls DAC rate. */
605 switch (runtime->rate) {
606 case 44100:
607 reg40_set = 0x10000 << (channel<<1);
608 reg71_set = 0x01010000;
609 break;
610 case 48000:
611 reg40_set = 0;
612 reg71_set = 0;
613 break;
614 case 96000:
615 reg40_set = 0x20000 << (channel<<1);
616 reg71_set = 0x02020000;
617 break;
618 case 192000:
619 reg40_set = 0x30000 << (channel<<1);
620 reg71_set = 0x03030000;
621 break;
622 default:
623 reg40_set = 0;
624 reg71_set = 0;
625 break;
626 }
627 /* Format is a global setting */
628 /* FIXME: Only let the first channel accessed set this. */
629 switch (runtime->format) {
630 case SNDRV_PCM_FORMAT_S16_LE:
631 hcfg_set = 0;
632 break;
633 case SNDRV_PCM_FORMAT_S32_LE:
634 hcfg_set = HCFG_PLAYBACK_S32_LE;
635 break;
636 default:
637 hcfg_set = 0;
638 break;
639 }
640 hcfg = inl(emu->port + HCFG) ;
641 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
642 outl(hcfg, emu->port + HCFG);
643 reg40 = snd_ca0106_ptr_read(emu, 0x40, 0);
644 reg40 = (reg40 & ~reg40_mask) | reg40_set;
645 snd_ca0106_ptr_write(emu, 0x40, 0, reg40);
646 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
647 reg71 = (reg71 & ~reg71_mask) | reg71_set;
648 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
649
650 /* FIXME: Check emu->buffer.size before actually writing to it. */
651 for(i=0; i < runtime->periods; i++) {
Takashi Iwai95a98262005-11-17 10:40:18 +0100652 table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
653 table_base[i*2+1] = period_size_bytes << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 }
655
656 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
657 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
658 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
659 snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
660 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
661 /* FIXME test what 0 bytes does. */
662 snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
663 snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
664 snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
665 snd_ca0106_ptr_write(emu, 0x08, channel, 0);
666 snd_ca0106_ptr_write(emu, PLAYBACK_MUTE, 0x0, 0x0); /* Unmute output */
667#if 0
668 snd_ca0106_ptr_write(emu, SPCS0, 0,
669 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
670 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
671 SPCS_GENERATIONSTATUS | 0x00001200 |
672 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
673 }
674#endif
675
676 return 0;
677}
678
679/* prepare capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100680static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100682 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
683 struct snd_pcm_runtime *runtime = substream->runtime;
684 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 int channel = epcm->channel_id;
James Courtier-Dutton883130b2005-05-28 13:28:21 +0200686 u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
687 u32 hcfg_set = 0x00000000;
688 u32 hcfg;
689 u32 over_sampling=0x2;
690 u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
691 u32 reg71_set = 0;
692 u32 reg71;
693
694 //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));
695 //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
696 //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
697 /* reg71 controls ADC rate. */
698 switch (runtime->rate) {
699 case 44100:
700 reg71_set = 0x00004000;
701 break;
702 case 48000:
703 reg71_set = 0;
704 break;
705 case 96000:
706 reg71_set = 0x00008000;
707 over_sampling=0xa;
708 break;
709 case 192000:
710 reg71_set = 0x0000c000;
711 over_sampling=0xa;
712 break;
713 default:
714 reg71_set = 0;
715 break;
716 }
717 /* Format is a global setting */
718 /* FIXME: Only let the first channel accessed set this. */
719 switch (runtime->format) {
720 case SNDRV_PCM_FORMAT_S16_LE:
721 hcfg_set = 0;
722 break;
723 case SNDRV_PCM_FORMAT_S32_LE:
724 hcfg_set = HCFG_CAPTURE_S32_LE;
725 break;
726 default:
727 hcfg_set = 0;
728 break;
729 }
730 hcfg = inl(emu->port + HCFG) ;
731 hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
732 outl(hcfg, emu->port + HCFG);
733 reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
734 reg71 = (reg71 & ~reg71_mask) | reg71_set;
735 snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
736 if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
737 snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
738 }
739
740
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 //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));
742 snd_ca0106_ptr_write(emu, 0x13, channel, 0);
743 snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
744 snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
745 snd_ca0106_ptr_write(emu, CAPTURE_POINTER, channel, 0);
746
747 return 0;
748}
749
750/* trigger_playback callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100751static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 int cmd)
753{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100754 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
755 struct snd_pcm_runtime *runtime;
756 struct snd_ca0106_pcm *epcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 int channel;
758 int result = 0;
759 struct list_head *pos;
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100760 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 u32 basic = 0;
762 u32 extended = 0;
763 int running=0;
764
765 switch (cmd) {
766 case SNDRV_PCM_TRIGGER_START:
767 running=1;
768 break;
769 case SNDRV_PCM_TRIGGER_STOP:
770 default:
771 running=0;
772 break;
773 }
774 snd_pcm_group_for_each(pos, substream) {
775 s = snd_pcm_group_substream_entry(pos);
776 runtime = s->runtime;
777 epcm = runtime->private_data;
778 channel = epcm->channel_id;
779 //snd_printk("channel=%d\n",channel);
780 epcm->running = running;
781 basic |= (0x1<<channel);
782 extended |= (0x10<<channel);
783 snd_pcm_trigger_done(s, substream);
784 }
785 //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
786
787 switch (cmd) {
788 case SNDRV_PCM_TRIGGER_START:
789 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
790 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
791 break;
792 case SNDRV_PCM_TRIGGER_STOP:
793 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
794 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
795 break;
796 default:
797 result = -EINVAL;
798 break;
799 }
800 return result;
801}
802
803/* trigger_capture callback */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100804static int snd_ca0106_pcm_trigger_capture(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 int cmd)
806{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100807 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
808 struct snd_pcm_runtime *runtime = substream->runtime;
809 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 int channel = epcm->channel_id;
811 int result = 0;
812
813 switch (cmd) {
814 case SNDRV_PCM_TRIGGER_START:
815 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
816 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
817 epcm->running = 1;
818 break;
819 case SNDRV_PCM_TRIGGER_STOP:
820 snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
821 snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
822 epcm->running = 0;
823 break;
824 default:
825 result = -EINVAL;
826 break;
827 }
828 return result;
829}
830
831/* pointer_playback callback */
832static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100833snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100835 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
836 struct snd_pcm_runtime *runtime = substream->runtime;
837 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
839 int channel = epcm->channel_id;
840
841 if (!epcm->running)
842 return 0;
843
844 ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
845 ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
846 ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
847 if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
848 ptr2 = bytes_to_frames(runtime, ptr1);
849 ptr2+= (ptr4 >> 3) * runtime->period_size;
850 ptr=ptr2;
851 if (ptr >= runtime->buffer_size)
852 ptr -= runtime->buffer_size;
853 //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);
854
855 return ptr;
856}
857
858/* pointer_capture callback */
859static snd_pcm_uframes_t
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100860snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100862 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
863 struct snd_pcm_runtime *runtime = substream->runtime;
864 struct snd_ca0106_pcm *epcm = runtime->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
866 int channel = channel=epcm->channel_id;
867
868 if (!epcm->running)
869 return 0;
870
871 ptr1 = snd_ca0106_ptr_read(emu, CAPTURE_POINTER, channel);
872 ptr2 = bytes_to_frames(runtime, ptr1);
873 ptr=ptr2;
874 if (ptr >= runtime->buffer_size)
875 ptr -= runtime->buffer_size;
876 //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);
877
878 return ptr;
879}
880
881/* operators */
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100882static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 .open = snd_ca0106_pcm_open_playback_front,
884 .close = snd_ca0106_pcm_close_playback,
885 .ioctl = snd_pcm_lib_ioctl,
886 .hw_params = snd_ca0106_pcm_hw_params_playback,
887 .hw_free = snd_ca0106_pcm_hw_free_playback,
888 .prepare = snd_ca0106_pcm_prepare_playback,
889 .trigger = snd_ca0106_pcm_trigger_playback,
890 .pointer = snd_ca0106_pcm_pointer_playback,
891};
892
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100893static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 .open = snd_ca0106_pcm_open_0_capture,
895 .close = snd_ca0106_pcm_close_capture,
896 .ioctl = snd_pcm_lib_ioctl,
897 .hw_params = snd_ca0106_pcm_hw_params_capture,
898 .hw_free = snd_ca0106_pcm_hw_free_capture,
899 .prepare = snd_ca0106_pcm_prepare_capture,
900 .trigger = snd_ca0106_pcm_trigger_capture,
901 .pointer = snd_ca0106_pcm_pointer_capture,
902};
903
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100904static struct snd_pcm_ops snd_ca0106_capture_1_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 .open = snd_ca0106_pcm_open_1_capture,
906 .close = snd_ca0106_pcm_close_capture,
907 .ioctl = snd_pcm_lib_ioctl,
908 .hw_params = snd_ca0106_pcm_hw_params_capture,
909 .hw_free = snd_ca0106_pcm_hw_free_capture,
910 .prepare = snd_ca0106_pcm_prepare_capture,
911 .trigger = snd_ca0106_pcm_trigger_capture,
912 .pointer = snd_ca0106_pcm_pointer_capture,
913};
914
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100915static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 .open = snd_ca0106_pcm_open_2_capture,
917 .close = snd_ca0106_pcm_close_capture,
918 .ioctl = snd_pcm_lib_ioctl,
919 .hw_params = snd_ca0106_pcm_hw_params_capture,
920 .hw_free = snd_ca0106_pcm_hw_free_capture,
921 .prepare = snd_ca0106_pcm_prepare_capture,
922 .trigger = snd_ca0106_pcm_trigger_capture,
923 .pointer = snd_ca0106_pcm_pointer_capture,
924};
925
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100926static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 .open = snd_ca0106_pcm_open_3_capture,
928 .close = snd_ca0106_pcm_close_capture,
929 .ioctl = snd_pcm_lib_ioctl,
930 .hw_params = snd_ca0106_pcm_hw_params_capture,
931 .hw_free = snd_ca0106_pcm_hw_free_capture,
932 .prepare = snd_ca0106_pcm_prepare_capture,
933 .trigger = snd_ca0106_pcm_trigger_capture,
934 .pointer = snd_ca0106_pcm_pointer_capture,
935};
936
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100937static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 .open = snd_ca0106_pcm_open_playback_center_lfe,
939 .close = snd_ca0106_pcm_close_playback,
940 .ioctl = snd_pcm_lib_ioctl,
941 .hw_params = snd_ca0106_pcm_hw_params_playback,
942 .hw_free = snd_ca0106_pcm_hw_free_playback,
943 .prepare = snd_ca0106_pcm_prepare_playback,
944 .trigger = snd_ca0106_pcm_trigger_playback,
945 .pointer = snd_ca0106_pcm_pointer_playback,
946};
947
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100948static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 .open = snd_ca0106_pcm_open_playback_unknown,
950 .close = snd_ca0106_pcm_close_playback,
951 .ioctl = snd_pcm_lib_ioctl,
952 .hw_params = snd_ca0106_pcm_hw_params_playback,
953 .hw_free = snd_ca0106_pcm_hw_free_playback,
954 .prepare = snd_ca0106_pcm_prepare_playback,
955 .trigger = snd_ca0106_pcm_trigger_playback,
956 .pointer = snd_ca0106_pcm_pointer_playback,
957};
958
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100959static struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 .open = snd_ca0106_pcm_open_playback_rear,
961 .close = snd_ca0106_pcm_close_playback,
962 .ioctl = snd_pcm_lib_ioctl,
963 .hw_params = snd_ca0106_pcm_hw_params_playback,
964 .hw_free = snd_ca0106_pcm_hw_free_playback,
965 .prepare = snd_ca0106_pcm_prepare_playback,
966 .trigger = snd_ca0106_pcm_trigger_playback,
967 .pointer = snd_ca0106_pcm_pointer_playback,
968};
969
970
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100971static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 unsigned short reg)
973{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100974 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 unsigned long flags;
976 unsigned short val;
977
978 spin_lock_irqsave(&emu->emu_lock, flags);
979 outb(reg, emu->port + AC97ADDRESS);
980 val = inw(emu->port + AC97DATA);
981 spin_unlock_irqrestore(&emu->emu_lock, flags);
982 return val;
983}
984
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100985static void snd_ca0106_ac97_write(struct snd_ac97 *ac97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 unsigned short reg, unsigned short val)
987{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100988 struct snd_ca0106 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 unsigned long flags;
990
991 spin_lock_irqsave(&emu->emu_lock, flags);
992 outb(reg, emu->port + AC97ADDRESS);
993 outw(val, emu->port + AC97DATA);
994 spin_unlock_irqrestore(&emu->emu_lock, flags);
995}
996
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100997static int snd_ca0106_ac97(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998{
Takashi Iwaie4a3d142005-11-17 14:55:40 +0100999 struct snd_ac97_bus *pbus;
1000 struct snd_ac97_template ac97;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 int err;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001002 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 .write = snd_ca0106_ac97_write,
1004 .read = snd_ca0106_ac97_read,
1005 };
1006
1007 if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
1008 return err;
1009 pbus->no_vra = 1; /* we don't need VRA */
1010
1011 memset(&ac97, 0, sizeof(ac97));
1012 ac97.private_data = chip;
Takashi Iwai36c4dc42005-03-24 17:48:30 +01001013 ac97.scaps = AC97_SCAP_NO_SPDIF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
1015}
1016
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001017static int snd_ca0106_free(struct snd_ca0106 *chip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018{
1019 if (chip->res_port != NULL) { /* avoid access to already used hardware */
1020 // disable interrupts
1021 snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
1022 outl(0, chip->port + INTE);
1023 snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
1024 udelay(1000);
1025 // disable audio
1026 //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
1027 outl(0, chip->port + HCFG);
1028 /* FIXME: We need to stop and DMA transfers here.
1029 * But as I am not sure how yet, we cannot from the dma pages.
1030 * So we can fix: snd-malloc: Memory leak? pages not freed = 8
1031 */
1032 }
1033 // release the data
1034#if 1
1035 if (chip->buffer.area)
1036 snd_dma_free_pages(&chip->buffer);
1037#endif
1038
1039 // release the i/o port
Takashi Iwaib1d57762005-10-10 11:56:31 +02001040 release_and_free_resource(chip->res_port);
1041
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 // release the irq
1043 if (chip->irq >= 0)
1044 free_irq(chip->irq, (void *)chip);
1045 pci_disable_device(chip->pci);
1046 kfree(chip);
1047 return 0;
1048}
1049
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001050static int snd_ca0106_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001052 struct snd_ca0106 *chip = device->device_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 return snd_ca0106_free(chip);
1054}
1055
1056static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
1057 struct pt_regs *regs)
1058{
1059 unsigned int status;
1060
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001061 struct snd_ca0106 *chip = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 int i;
1063 int mask;
1064 unsigned int stat76;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001065 struct snd_ca0106_channel *pchannel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 status = inl(chip->port + IPR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 if (! status)
1069 return IRQ_NONE;
1070
1071 stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0);
1072 //snd_printk("interrupt status = 0x%08x, stat76=0x%08x\n", status, stat76);
1073 //snd_printk("ptr=0x%08x\n",snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0));
1074 mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
1075 for(i = 0; i < 4; i++) {
1076 pchannel = &(chip->playback_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001077 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078/* FIXME: Select the correct substream for period elapsed */
1079 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001080 snd_pcm_period_elapsed(pchannel->epcm->substream);
1081 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 }
1083 }
1084 //printk(KERN_INFO "channel=%p\n",pchannel);
1085 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1086 mask <<= 1;
1087 }
1088 mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */
1089 for(i = 0; i < 4; i++) {
1090 pchannel = &(chip->capture_channels[i]);
Takashi Iwai95a98262005-11-17 10:40:18 +01001091 if (stat76 & mask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092/* FIXME: Select the correct substream for period elapsed */
1093 if(pchannel->use) {
Takashi Iwai95a98262005-11-17 10:40:18 +01001094 snd_pcm_period_elapsed(pchannel->epcm->substream);
1095 //printk(KERN_INFO "interrupt [%d] used\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 }
1097 }
1098 //printk(KERN_INFO "channel=%p\n",pchannel);
1099 //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number);
1100 mask <<= 1;
1101 }
1102
1103 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001104
1105 if (chip->midi.dev_id &&
Takashi Iwai95a98262005-11-17 10:40:18 +01001106 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001107 if (chip->midi.interrupt)
1108 chip->midi.interrupt(&chip->midi, status);
1109 else
1110 chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable);
1111 }
1112
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 // acknowledge the interrupt if necessary
1114 outl(status, chip->port+IPR);
1115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 return IRQ_HANDLED;
1117}
1118
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001119static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001121 struct snd_pcm *pcm;
1122 struct snd_pcm_substream *substream;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 int err;
1124
1125 if (rpcm)
1126 *rpcm = NULL;
1127 if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
1128 return err;
1129
1130 pcm->private_data = emu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
1132 switch (device) {
1133 case 0:
1134 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops);
1135 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops);
1136 break;
1137 case 1:
1138 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops);
1139 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops);
1140 break;
1141 case 2:
1142 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops);
1143 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops);
1144 break;
1145 case 3:
1146 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops);
1147 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops);
1148 break;
1149 }
1150
1151 pcm->info_flags = 0;
1152 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
1153 strcpy(pcm->name, "CA0106");
1154 emu->pcm = pcm;
1155
1156 for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1157 substream;
1158 substream = substream->next) {
1159 if ((err = snd_pcm_lib_preallocate_pages(substream,
1160 SNDRV_DMA_TYPE_DEV,
1161 snd_dma_pci_data(emu->pci),
1162 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
1163 return err;
1164 }
1165
1166 for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1167 substream;
1168 substream = substream->next) {
1169 if ((err = snd_pcm_lib_preallocate_pages(substream,
1170 SNDRV_DMA_TYPE_DEV,
1171 snd_dma_pci_data(emu->pci),
1172 64*1024, 64*1024)) < 0)
1173 return err;
1174 }
1175
1176 if (rpcm)
1177 *rpcm = pcm;
1178
1179 return 0;
1180}
1181
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001182static unsigned int spi_dac_init[] = {
1183 0x00ff,
1184 0x02ff,
1185 0x0400,
1186 0x0520,
1187 0x0600,
1188 0x08ff,
1189 0x0aff,
1190 0x0cff,
1191 0x0eff,
1192 0x10ff,
1193 0x1200,
1194 0x1400,
1195 0x1480,
1196 0x1800,
1197 0x1aff,
1198 0x1cff,
1199 0x1e00,
1200 0x0530,
1201 0x0602,
1202 0x0622,
1203 0x1400,
1204};
1205
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001206static unsigned int i2c_adc_init[][2] = {
1207 { 0x17, 0x00 }, /* Reset */
1208 { 0x07, 0x00 }, /* Timeout */
1209 { 0x0b, 0x22 }, /* Interface control */
1210 { 0x0c, 0x22 }, /* Master mode control */
1211 { 0x0d, 0x08 }, /* Powerdown control */
1212 { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
1213 { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */
1214 { 0x10, 0x7b }, /* ALC Control 1 */
1215 { 0x11, 0x00 }, /* ALC Control 2 */
1216 { 0x12, 0x32 }, /* ALC Control 3 */
1217 { 0x13, 0x00 }, /* Noise gate control */
1218 { 0x14, 0xa6 }, /* Limiter control */
1219 { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
1220};
1221
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001222static int __devinit snd_ca0106_create(struct snd_card *card,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 struct pci_dev *pci,
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001224 struct snd_ca0106 **rchip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001226 struct snd_ca0106 *chip;
1227 struct snd_ca0106_details *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 int err;
1229 int ch;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001230 static struct snd_device_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 .dev_free = snd_ca0106_dev_free,
1232 };
1233
1234 *rchip = NULL;
1235
1236 if ((err = pci_enable_device(pci)) < 0)
1237 return err;
Tobias Klauser299676b2005-05-29 15:21:02 +02001238 if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
1239 pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 printk(KERN_ERR "error to set 32bit mask DMA\n");
1241 pci_disable_device(pci);
1242 return -ENXIO;
1243 }
1244
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001245 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 if (chip == NULL) {
1247 pci_disable_device(pci);
1248 return -ENOMEM;
1249 }
1250
1251 chip->card = card;
1252 chip->pci = pci;
1253 chip->irq = -1;
1254
1255 spin_lock_init(&chip->emu_lock);
1256
1257 chip->port = pci_resource_start(pci, 0);
1258 if ((chip->res_port = request_region(chip->port, 0x20,
1259 "snd_ca0106")) == NULL) {
1260 snd_ca0106_free(chip);
1261 printk(KERN_ERR "cannot allocate the port\n");
1262 return -EBUSY;
1263 }
1264
1265 if (request_irq(pci->irq, snd_ca0106_interrupt,
1266 SA_INTERRUPT|SA_SHIRQ, "snd_ca0106",
1267 (void *)chip)) {
1268 snd_ca0106_free(chip);
1269 printk(KERN_ERR "cannot grab irq\n");
1270 return -EBUSY;
1271 }
1272 chip->irq = pci->irq;
1273
1274 /* This stores the periods table. */
1275 if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
1276 snd_ca0106_free(chip);
1277 return -ENOMEM;
1278 }
1279
1280 pci_set_master(pci);
1281 /* read revision & serial */
1282 pci_read_config_byte(pci, PCI_REVISION_ID, (char *)&chip->revision);
1283 pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
1284 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
1285#if 1
1286 printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
1287 chip->revision, chip->serial);
1288#endif
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001289 strcpy(card->driver, "CA0106");
1290 strcpy(card->shortname, "CA0106");
1291
Takashi Iwai95a98262005-11-17 10:40:18 +01001292 for (c = ca0106_chip_details; c->serial; c++) {
1293 if (c->serial == chip->serial)
1294 break;
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001295 }
1296 chip->details = c;
1297 sprintf(card->longname, "%s at 0x%lx irq %i",
1298 c->name, chip->port, chip->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299
1300 outl(0, chip->port + INTE);
1301
1302 /*
1303 * Init to 0x02109204 :
1304 * Clock accuracy = 0 (1000ppm)
1305 * Sample Rate = 2 (48kHz)
1306 * Audio Channel = 1 (Left of 2)
1307 * Source Number = 0 (Unspecified)
1308 * Generation Status = 1 (Original for Cat Code 12)
1309 * Cat Code = 12 (Digital Signal Mixer)
1310 * Mode = 0 (Mode 0)
1311 * Emphasis = 0 (None)
1312 * CP = 1 (Copyright unasserted)
1313 * AN = 0 (Audio data)
1314 * P = 0 (Consumer)
1315 */
1316 snd_ca0106_ptr_write(chip, SPCS0, 0,
1317 chip->spdif_bits[0] =
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 /* Only SPCS1 has been tested */
1323 snd_ca0106_ptr_write(chip, SPCS1, 0,
1324 chip->spdif_bits[1] =
1325 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1326 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1327 SPCS_GENERATIONSTATUS | 0x00001200 |
1328 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1329 snd_ca0106_ptr_write(chip, SPCS2, 0,
1330 chip->spdif_bits[2] =
1331 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1332 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1333 SPCS_GENERATIONSTATUS | 0x00001200 |
1334 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1335 snd_ca0106_ptr_write(chip, SPCS3, 0,
1336 chip->spdif_bits[3] =
1337 SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1338 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1339 SPCS_GENERATIONSTATUS | 0x00001200 |
1340 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
1341
1342 snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
1343 snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
1344
1345 /* Write 0x8000 to AC97_REC_GAIN to mute it. */
1346 outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
1347 outw(0x8000, chip->port + AC97DATA);
1348#if 0
1349 snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
1350 snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
1351 snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
1352 snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
1353#endif
1354
1355 //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
1356 /* Analog or Digital output */
1357 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
James Courtier-Dutton8f55fbb2005-05-21 16:45:58 +02001358 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 -07001359 chip->spdif_enable = 0; /* Set digital SPDIF output off */
1360 chip->capture_source = 3; /* Set CAPTURE_SOURCE */
1361 //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
1362 //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
1363
1364 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
1365 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
1366 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
1367 snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
1368 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
1369 snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
1370 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
1371 snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
1372 for(ch = 0; ch < 4; ch++) {
1373 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
1374 snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
1375 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
1376 //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
1377 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
1378 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
1379 }
1380 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
1381 chip->capture_source = 3; /* Set CAPTURE_SOURCE */
1382
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001383 if (chip->details->gpio_type == 2) { /* The SB0410 and SB0413 use GPIO differently. */
1384 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1385 outl(0x0, chip->port+GPIO);
1386 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
1387 outl(0x005f5301, chip->port+GPIO); /* Analog */
1388 } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
1390 outl(0x0, chip->port+GPIO);
1391 //outl(0x00f0e000, chip->port+GPIO); /* Analog */
James Courtier-Duttonc82bf822005-06-04 15:03:06 +02001392 outl(0x005f5301, chip->port+GPIO); /* Analog */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 } else {
1394 outl(0x0, chip->port+GPIO);
1395 outl(0x005f03a3, chip->port+GPIO); /* Analog */
1396 //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
1397 }
1398 snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
1399
1400 //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
1401 //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
1402 //outl(0x00000009, chip->port+HCFG);
1403 outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
1404
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001405 if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
James Courtier-Dutton6129daa2006-04-09 13:01:34 +01001406 int size, n;
1407
1408 size = ARRAY_SIZE(i2c_adc_init);
1409 //snd_printk("I2C:array size=0x%x\n", size);
1410 for (n=0; n < size; n++) {
1411 snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
1412 }
1413 for (n=0; n < 4; n++) {
1414 chip->i2c_capture_volume[n][0]= 0xcf;
1415 chip->i2c_capture_volume[n][1]= 0xcf;
1416 }
1417 chip->i2c_capture_source=2; /* Line in */
1418 //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 +02001419 }
James Courtier-Duttona5875152005-12-20 22:30:49 +01001420 if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
James Courtier-Duttonaad90952005-12-21 22:26:26 +01001421 int size, n;
1422
1423 size = ARRAY_SIZE(spi_dac_init);
1424 for (n=0; n < size; n++)
1425 snd_ca0106_spi_write(chip, spi_dac_init[n]);
James Courtier-Duttona5875152005-12-20 22:30:49 +01001426 }
James Courtier-Dutton7199acd2005-05-27 22:07:23 +02001427
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
1429 chip, &ops)) < 0) {
1430 snd_ca0106_free(chip);
1431 return err;
1432 }
1433 *rchip = chip;
1434 return 0;
1435}
1436
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001437
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001438static void ca0106_midi_interrupt_enable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001439{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001440 snd_ca0106_intr_enable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001441}
1442
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001443static void ca0106_midi_interrupt_disable(struct snd_ca_midi *midi, int intr)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001444{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001445 snd_ca0106_intr_disable((struct snd_ca0106 *)(midi->dev_id), intr);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001446}
1447
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001448static unsigned char ca0106_midi_read(struct snd_ca_midi *midi, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001449{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001450 return (unsigned char)snd_ca0106_ptr_read((struct snd_ca0106 *)(midi->dev_id),
1451 midi->port + idx, 0);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001452}
1453
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001454static void ca0106_midi_write(struct snd_ca_midi *midi, int data, int idx)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001455{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001456 snd_ca0106_ptr_write((struct snd_ca0106 *)(midi->dev_id), midi->port + idx, 0, data);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001457}
1458
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001459static struct snd_card *ca0106_dev_id_card(void *dev_id)
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001460{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001461 return ((struct snd_ca0106 *)dev_id)->card;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001462}
1463
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001464static int ca0106_dev_id_port(void *dev_id)
1465{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001466 return ((struct snd_ca0106 *)dev_id)->port;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001467}
1468
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001469static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001470{
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001471 struct snd_ca_midi *midi;
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001472 char *name;
1473 int err;
1474
Takashi Iwai95a98262005-11-17 10:40:18 +01001475 if (channel == CA0106_MIDI_CHAN_B) {
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001476 name = "CA0106 MPU-401 (UART) B";
1477 midi = &chip->midi2;
1478 midi->tx_enable = INTE_MIDI_TX_B;
1479 midi->rx_enable = INTE_MIDI_RX_B;
1480 midi->ipr_tx = IPR_MIDI_TX_B;
1481 midi->ipr_rx = IPR_MIDI_RX_B;
1482 midi->port = MIDI_UART_B_DATA;
1483 } else {
1484 name = "CA0106 MPU-401 (UART)";
1485 midi = &chip->midi;
1486 midi->tx_enable = INTE_MIDI_TX_A;
1487 midi->rx_enable = INTE_MIDI_TX_B;
1488 midi->ipr_tx = IPR_MIDI_TX_A;
1489 midi->ipr_rx = IPR_MIDI_RX_A;
1490 midi->port = MIDI_UART_A_DATA;
1491 }
1492
1493 midi->reset = CA0106_MPU401_RESET;
1494 midi->enter_uart = CA0106_MPU401_ENTER_UART;
1495 midi->ack = CA0106_MPU401_ACK;
1496
1497 midi->input_avail = CA0106_MIDI_INPUT_AVAIL;
1498 midi->output_ready = CA0106_MIDI_OUTPUT_READY;
1499
1500 midi->channel = channel;
1501
1502 midi->interrupt_enable = ca0106_midi_interrupt_enable;
1503 midi->interrupt_disable = ca0106_midi_interrupt_disable;
1504
1505 midi->read = ca0106_midi_read;
1506 midi->write = ca0106_midi_write;
1507
1508 midi->get_dev_id_card = ca0106_dev_id_card;
1509 midi->get_dev_id_port = ca0106_dev_id_port;
1510
1511 midi->dev_id = chip;
1512
1513 if ((err = ca_midi_init(chip, midi, 0, name)) < 0)
1514 return err;
1515
1516 return 0;
1517}
1518
1519
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1521 const struct pci_device_id *pci_id)
1522{
1523 static int dev;
Takashi Iwaie4a3d142005-11-17 14:55:40 +01001524 struct snd_card *card;
1525 struct snd_ca0106 *chip;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 int err;
1527
1528 if (dev >= SNDRV_CARDS)
1529 return -ENODEV;
1530 if (!enable[dev]) {
1531 dev++;
1532 return -ENOENT;
1533 }
1534
1535 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1536 if (card == NULL)
1537 return -ENOMEM;
1538
1539 if ((err = snd_ca0106_create(card, pci, &chip)) < 0) {
1540 snd_card_free(card);
1541 return err;
1542 }
1543
1544 if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
1545 snd_card_free(card);
1546 return err;
1547 }
1548 if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
1549 snd_card_free(card);
1550 return err;
1551 }
1552 if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
1553 snd_card_free(card);
1554 return err;
1555 }
1556 if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
1557 snd_card_free(card);
1558 return err;
1559 }
James Courtier-Dutton1baa7052005-05-21 22:35:58 +02001560 if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 if ((err = snd_ca0106_ac97(chip)) < 0) {
1562 snd_card_free(card);
1563 return err;
1564 }
1565 }
1566 if ((err = snd_ca0106_mixer(chip)) < 0) {
1567 snd_card_free(card);
1568 return err;
1569 }
1570
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001571 snd_printdd("ca0106: probe for MIDI channel A ...");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001572 if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
1573 snd_card_free(card);
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001574 snd_printdd(" failed, err=0x%x\n",err);
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001575 return err;
1576 }
James Courtier-Dutton7cf47832005-10-22 11:45:55 +02001577 snd_printdd(" done.\n");
James Courtier-Dutton8a5afd22005-10-20 22:57:51 +02001578
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001579#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 snd_ca0106_proc_init(chip);
Takashi Iwaiadf1b3d2005-12-01 10:49:58 +01001581#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 if ((err = snd_card_register(card)) < 0) {
1584 snd_card_free(card);
1585 return err;
1586 }
1587
1588 pci_set_drvdata(pci, card);
1589 dev++;
1590 return 0;
1591}
1592
1593static void __devexit snd_ca0106_remove(struct pci_dev *pci)
1594{
1595 snd_card_free(pci_get_drvdata(pci));
1596 pci_set_drvdata(pci, NULL);
1597}
1598
1599// PCI IDs
Henrik Kretzschmar396c9b92006-04-24 15:59:04 +02001600static struct pci_device_id snd_ca0106_ids[] __devinitdata = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
1602 { 0, }
1603};
1604MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
1605
1606// pci_driver definition
1607static struct pci_driver driver = {
1608 .name = "CA0106",
1609 .id_table = snd_ca0106_ids,
1610 .probe = snd_ca0106_probe,
1611 .remove = __devexit_p(snd_ca0106_remove),
1612};
1613
1614// initialization of the module
1615static int __init alsa_card_ca0106_init(void)
1616{
Takashi Iwai95a98262005-11-17 10:40:18 +01001617 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618}
1619
1620// clean up the module
1621static void __exit alsa_card_ca0106_exit(void)
1622{
1623 pci_unregister_driver(&driver);
1624}
1625
1626module_init(alsa_card_ca0106_init)
1627module_exit(alsa_card_ca0106_exit)