blob: cc36b748d9a5984081dbfcf8162369ef0f26bb43 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Creative Labs, Inc.
4 * Routines for control of EMU10K1 chips
5 *
6 * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
7 * Added support for Audigy 2 Value.
8 *
9 *
10 * BUGS:
11 * --
12 *
13 * TODO:
14 * --
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32#include <sound/driver.h>
33#include <linux/delay.h>
34#include <linux/init.h>
35#include <linux/interrupt.h>
36#include <linux/pci.h>
37#include <linux/slab.h>
38#include <linux/vmalloc.h>
39
40#include <sound/core.h>
41#include <sound/emu10k1.h>
42#include "p16v.h"
James Courtier-Duttone2b15f82005-11-11 23:39:05 +010043#include "tina2.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Linus Torvalds1da177e2005-04-16 15:20:36 -070045/*************************************************************************
46 * EMU10K1 init / done
47 *************************************************************************/
48
Takashi Iwaieb4698f2005-11-17 14:50:13 +010049void snd_emu10k1_voice_init(struct snd_emu10k1 * emu, int ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050{
51 snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0);
52 snd_emu10k1_ptr_write(emu, IP, ch, 0);
53 snd_emu10k1_ptr_write(emu, VTFT, ch, 0xffff);
54 snd_emu10k1_ptr_write(emu, CVCF, ch, 0xffff);
55 snd_emu10k1_ptr_write(emu, PTRX, ch, 0);
56 snd_emu10k1_ptr_write(emu, CPF, ch, 0);
57 snd_emu10k1_ptr_write(emu, CCR, ch, 0);
58
59 snd_emu10k1_ptr_write(emu, PSST, ch, 0);
60 snd_emu10k1_ptr_write(emu, DSL, ch, 0x10);
61 snd_emu10k1_ptr_write(emu, CCCA, ch, 0);
62 snd_emu10k1_ptr_write(emu, Z1, ch, 0);
63 snd_emu10k1_ptr_write(emu, Z2, ch, 0);
64 snd_emu10k1_ptr_write(emu, FXRT, ch, 0x32100000);
65
66 snd_emu10k1_ptr_write(emu, ATKHLDM, ch, 0);
67 snd_emu10k1_ptr_write(emu, DCYSUSM, ch, 0);
68 snd_emu10k1_ptr_write(emu, IFATN, ch, 0xffff);
69 snd_emu10k1_ptr_write(emu, PEFE, ch, 0);
70 snd_emu10k1_ptr_write(emu, FMMOD, ch, 0);
71 snd_emu10k1_ptr_write(emu, TREMFRQ, ch, 24); /* 1 Hz */
72 snd_emu10k1_ptr_write(emu, FM2FRQ2, ch, 24); /* 1 Hz */
73 snd_emu10k1_ptr_write(emu, TEMPENV, ch, 0);
74
75 /*** these are last so OFF prevents writing ***/
76 snd_emu10k1_ptr_write(emu, LFOVAL2, ch, 0);
77 snd_emu10k1_ptr_write(emu, LFOVAL1, ch, 0);
78 snd_emu10k1_ptr_write(emu, ATKHLDV, ch, 0);
79 snd_emu10k1_ptr_write(emu, ENVVOL, ch, 0);
80 snd_emu10k1_ptr_write(emu, ENVVAL, ch, 0);
81
82 /* Audigy extra stuffs */
83 if (emu->audigy) {
84 snd_emu10k1_ptr_write(emu, 0x4c, ch, 0); /* ?? */
85 snd_emu10k1_ptr_write(emu, 0x4d, ch, 0); /* ?? */
86 snd_emu10k1_ptr_write(emu, 0x4e, ch, 0); /* ?? */
87 snd_emu10k1_ptr_write(emu, 0x4f, ch, 0); /* ?? */
88 snd_emu10k1_ptr_write(emu, A_FXRT1, ch, 0x03020100);
89 snd_emu10k1_ptr_write(emu, A_FXRT2, ch, 0x3f3f3f3f);
90 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, ch, 0);
91 }
92}
93
Takashi Iwai09668b42005-11-17 16:14:10 +010094static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
Linus Torvalds1da177e2005-04-16 15:20:36 -070095{
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 unsigned int silent_page;
Takashi Iwai09668b42005-11-17 16:14:10 +010097 int ch;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
99 /* disable audio and lock cache */
Takashi Iwai09668b42005-11-17 16:14:10 +0100100 outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
101 emu->port + HCFG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103 /* reset recording buffers */
104 snd_emu10k1_ptr_write(emu, MICBS, 0, ADCBS_BUFSIZE_NONE);
105 snd_emu10k1_ptr_write(emu, MICBA, 0, 0);
106 snd_emu10k1_ptr_write(emu, FXBS, 0, ADCBS_BUFSIZE_NONE);
107 snd_emu10k1_ptr_write(emu, FXBA, 0, 0);
108 snd_emu10k1_ptr_write(emu, ADCBS, 0, ADCBS_BUFSIZE_NONE);
109 snd_emu10k1_ptr_write(emu, ADCBA, 0, 0);
110
111 /* disable channel interrupt */
112 outl(0, emu->port + INTE);
113 snd_emu10k1_ptr_write(emu, CLIEL, 0, 0);
114 snd_emu10k1_ptr_write(emu, CLIEH, 0, 0);
115 snd_emu10k1_ptr_write(emu, SOLEL, 0, 0);
116 snd_emu10k1_ptr_write(emu, SOLEH, 0, 0);
117
118 if (emu->audigy){
119 /* set SPDIF bypass mode */
120 snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT);
121 /* enable rear left + rear right AC97 slots */
Takashi Iwai09668b42005-11-17 16:14:10 +0100122 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_REAR_RIGHT |
123 AC97SLOT_REAR_LEFT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 }
125
126 /* init envelope engine */
Takashi Iwai09668b42005-11-17 16:14:10 +0100127 for (ch = 0; ch < NUM_G; ch++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 snd_emu10k1_voice_init(emu, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Takashi Iwai09668b42005-11-17 16:14:10 +0100130 snd_emu10k1_ptr_write(emu, SPCS0, 0, emu->spdif_bits[0]);
131 snd_emu10k1_ptr_write(emu, SPCS1, 0, emu->spdif_bits[1]);
132 snd_emu10k1_ptr_write(emu, SPCS2, 0, emu->spdif_bits[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Lee Revell2b637da2005-03-30 13:51:18 +0200134 if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 /* Hacks for Alice3 to work independent of haP16V driver */
136 u32 tmp;
137
138 //Setup SRCMulti_I2S SamplingRate
139 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
140 tmp &= 0xfffff1ff;
141 tmp |= (0x2<<9);
142 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
143
144 /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
145 snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14);
146 /* Setup SRCMulti Input Audio Enable */
147 /* Use 0xFFFFFFFF to enable P16V sounds. */
148 snd_emu10k1_ptr20_write(emu, SRCMULTI_ENABLE, 0, 0xFFFFFFFF);
149
150 /* Enabled Phased (8-channel) P16V playback */
151 outl(0x0201, emu->port + HCFG2);
152 /* Set playback routing. */
James Courtier-Duttonfd9a98e2005-04-10 15:43:35 +0200153 snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 }
James Courtier-Duttone0474e52005-07-02 16:33:34 +0200155 if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 /* Hacks for Alice3 to work independent of haP16V driver */
157 u32 tmp;
158
Takashi Iwai09668b42005-11-17 16:14:10 +0100159 snd_printk(KERN_INFO "Audigy2 value: Special config.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 //Setup SRCMulti_I2S SamplingRate
161 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
162 tmp &= 0xfffff1ff;
163 tmp |= (0x2<<9);
164 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
165
166 /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
167 outl(0x600000, emu->port + 0x20);
168 outl(0x14, emu->port + 0x24);
169
170 /* Setup SRCMulti Input Audio Enable */
171 outl(0x7b0000, emu->port + 0x20);
172 outl(0xFF000000, emu->port + 0x24);
173
174 /* Setup SPDIF Out Audio Enable */
175 /* The Audigy 2 Value has a separate SPDIF out,
176 * so no need for a mixer switch
177 */
178 outl(0x7a0000, emu->port + 0x20);
179 outl(0xFF000000, emu->port + 0x24);
180 tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */
181 outl(tmp, emu->port + A_IOCFG);
182 }
183
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
185 snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */
186 snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
187
188 silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK;
189 for (ch = 0; ch < NUM_G; ch++) {
190 snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page);
191 snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
192 }
193
194 /*
195 * Hokay, setup HCFG
196 * Mute Disable Audio = 0
197 * Lock Tank Memory = 1
198 * Lock Sound Memory = 0
199 * Auto Mute = 1
200 */
201 if (emu->audigy) {
202 if (emu->revision == 4) /* audigy2 */
203 outl(HCFG_AUDIOENABLE |
204 HCFG_AC3ENABLE_CDSPDIF |
205 HCFG_AC3ENABLE_GPSPDIF |
206 HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
207 else
208 outl(HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
James Courtier-Duttone0474e52005-07-02 16:33:34 +0200209 /* FIXME: Remove all these emu->model and replace it with a card recognition parameter,
210 * e.g. card_capabilities->joystick */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 } else if (emu->model == 0x20 ||
212 emu->model == 0xc400 ||
213 (emu->model == 0x21 && emu->revision < 6))
214 outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE, emu->port + HCFG);
215 else
216 // With on-chip joystick
217 outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
218
219 if (enable_ir) { /* enable IR for SB Live */
220 if (emu->audigy) {
221 unsigned int reg = inl(emu->port + A_IOCFG);
222 outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
223 udelay(500);
224 outl(reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
225 udelay(100);
226 outl(reg, emu->port + A_IOCFG);
227 } else {
228 unsigned int reg = inl(emu->port + HCFG);
229 outl(reg | HCFG_GPOUT2, emu->port + HCFG);
230 udelay(500);
231 outl(reg | HCFG_GPOUT1 | HCFG_GPOUT2, emu->port + HCFG);
232 udelay(100);
233 outl(reg, emu->port + HCFG);
234 }
235 }
236
237 if (emu->audigy) { /* enable analog output */
238 unsigned int reg = inl(emu->port + A_IOCFG);
239 outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
240 }
241
Takashi Iwai09668b42005-11-17 16:14:10 +0100242 return 0;
243}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
Takashi Iwai09668b42005-11-17 16:14:10 +0100245static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
246{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 /*
248 * Enable the audio bit
249 */
250 outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG);
251
252 /* Enable analog/digital outs on audigy */
253 if (emu->audigy) {
254 outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
255
James Courtier-Duttone0474e52005-07-02 16:33:34 +0200256 if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 /* Unmute Analog now. Set GPO6 to 1 for Apollo.
258 * This has to be done after init ALice3 I2SOut beyond 48KHz.
259 * So, sequence is important. */
260 outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG);
James Courtier-Duttone0474e52005-07-02 16:33:34 +0200261 } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 /* Unmute Analog now. */
263 outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG);
264 } else {
265 /* Disable routing from AC97 line out to Front speakers */
266 outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG);
267 }
268 }
269
270#if 0
271 {
272 unsigned int tmp;
273 /* FIXME: the following routine disables LiveDrive-II !! */
274 // TOSLink detection
275 emu->tos_link = 0;
276 tmp = inl(emu->port + HCFG);
277 if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
278 outl(tmp|0x800, emu->port + HCFG);
279 udelay(50);
280 if (tmp != (inl(emu->port + HCFG) & ~0x800)) {
281 emu->tos_link = 1;
282 outl(tmp, emu->port + HCFG);
283 }
284 }
285 }
286#endif
287
288 snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289}
290
Takashi Iwai09668b42005-11-17 16:14:10 +0100291int snd_emu10k1_done(struct snd_emu10k1 * emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292{
293 int ch;
294
295 outl(0, emu->port + INTE);
296
297 /*
298 * Shutdown the chip
299 */
300 for (ch = 0; ch < NUM_G; ch++)
301 snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0);
302 for (ch = 0; ch < NUM_G; ch++) {
303 snd_emu10k1_ptr_write(emu, VTFT, ch, 0);
304 snd_emu10k1_ptr_write(emu, CVCF, ch, 0);
305 snd_emu10k1_ptr_write(emu, PTRX, ch, 0);
306 snd_emu10k1_ptr_write(emu, CPF, ch, 0);
307 }
308
309 /* reset recording buffers */
310 snd_emu10k1_ptr_write(emu, MICBS, 0, 0);
311 snd_emu10k1_ptr_write(emu, MICBA, 0, 0);
312 snd_emu10k1_ptr_write(emu, FXBS, 0, 0);
313 snd_emu10k1_ptr_write(emu, FXBA, 0, 0);
314 snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
315 snd_emu10k1_ptr_write(emu, ADCBS, 0, ADCBS_BUFSIZE_NONE);
316 snd_emu10k1_ptr_write(emu, ADCBA, 0, 0);
317 snd_emu10k1_ptr_write(emu, TCBS, 0, TCBS_BUFFSIZE_16K);
318 snd_emu10k1_ptr_write(emu, TCB, 0, 0);
319 if (emu->audigy)
320 snd_emu10k1_ptr_write(emu, A_DBG, 0, A_DBG_SINGLE_STEP);
321 else
322 snd_emu10k1_ptr_write(emu, DBG, 0, EMU10K1_DBG_SINGLE_STEP);
323
324 /* disable channel interrupt */
325 snd_emu10k1_ptr_write(emu, CLIEL, 0, 0);
326 snd_emu10k1_ptr_write(emu, CLIEH, 0, 0);
327 snd_emu10k1_ptr_write(emu, SOLEL, 0, 0);
328 snd_emu10k1_ptr_write(emu, SOLEH, 0, 0);
329
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 /* disable audio and lock cache */
331 outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, emu->port + HCFG);
332 snd_emu10k1_ptr_write(emu, PTB, 0, 0);
333
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 return 0;
335}
336
337/*************************************************************************
338 * ECARD functional implementation
339 *************************************************************************/
340
341/* In A1 Silicon, these bits are in the HC register */
342#define HOOKN_BIT (1L << 12)
343#define HANDN_BIT (1L << 11)
344#define PULSEN_BIT (1L << 10)
345
346#define EC_GDI1 (1 << 13)
347#define EC_GDI0 (1 << 14)
348
349#define EC_NUM_CONTROL_BITS 20
350
351#define EC_AC3_DATA_SELN 0x0001L
352#define EC_EE_DATA_SEL 0x0002L
353#define EC_EE_CNTRL_SELN 0x0004L
354#define EC_EECLK 0x0008L
355#define EC_EECS 0x0010L
356#define EC_EESDO 0x0020L
357#define EC_TRIM_CSN 0x0040L
358#define EC_TRIM_SCLK 0x0080L
359#define EC_TRIM_SDATA 0x0100L
360#define EC_TRIM_MUTEN 0x0200L
361#define EC_ADCCAL 0x0400L
362#define EC_ADCRSTN 0x0800L
363#define EC_DACCAL 0x1000L
364#define EC_DACMUTEN 0x2000L
365#define EC_LEDN 0x4000L
366
367#define EC_SPDIF0_SEL_SHIFT 15
368#define EC_SPDIF1_SEL_SHIFT 17
369#define EC_SPDIF0_SEL_MASK (0x3L << EC_SPDIF0_SEL_SHIFT)
370#define EC_SPDIF1_SEL_MASK (0x7L << EC_SPDIF1_SEL_SHIFT)
371#define EC_SPDIF0_SELECT(_x) (((_x) << EC_SPDIF0_SEL_SHIFT) & EC_SPDIF0_SEL_MASK)
372#define EC_SPDIF1_SELECT(_x) (((_x) << EC_SPDIF1_SEL_SHIFT) & EC_SPDIF1_SEL_MASK)
373#define EC_CURRENT_PROM_VERSION 0x01 /* Self-explanatory. This should
374 * be incremented any time the EEPROM's
375 * format is changed. */
376
377#define EC_EEPROM_SIZE 0x40 /* ECARD EEPROM has 64 16-bit words */
378
379/* Addresses for special values stored in to EEPROM */
380#define EC_PROM_VERSION_ADDR 0x20 /* Address of the current prom version */
381#define EC_BOARDREV0_ADDR 0x21 /* LSW of board rev */
382#define EC_BOARDREV1_ADDR 0x22 /* MSW of board rev */
383
384#define EC_LAST_PROMFILE_ADDR 0x2f
385
386#define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The
387 * can be up to 30 characters in length
388 * and is stored as a NULL-terminated
389 * ASCII string. Any unused bytes must be
390 * filled with zeros */
391#define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */
392
393
394/* Most of this stuff is pretty self-evident. According to the hardware
395 * dudes, we need to leave the ADCCAL bit low in order to avoid a DC
396 * offset problem. Weird.
397 */
398#define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | \
399 EC_TRIM_CSN)
400
401
402#define EC_DEFAULT_ADC_GAIN 0xC4C4
403#define EC_DEFAULT_SPDIF0_SEL 0x0
404#define EC_DEFAULT_SPDIF1_SEL 0x4
405
406/**************************************************************************
407 * @func Clock bits into the Ecard's control latch. The Ecard uses a
408 * control latch will is loaded bit-serially by toggling the Modem control
409 * lines from function 2 on the E8010. This function hides these details
410 * and presents the illusion that we are actually writing to a distinct
411 * register.
412 */
413
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100414static void snd_emu10k1_ecard_write(struct snd_emu10k1 * emu, unsigned int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415{
416 unsigned short count;
417 unsigned int data;
418 unsigned long hc_port;
419 unsigned int hc_value;
420
421 hc_port = emu->port + HCFG;
422 hc_value = inl(hc_port) & ~(HOOKN_BIT | HANDN_BIT | PULSEN_BIT);
423 outl(hc_value, hc_port);
424
425 for (count = 0; count < EC_NUM_CONTROL_BITS; count++) {
426
427 /* Set up the value */
428 data = ((value & 0x1) ? PULSEN_BIT : 0);
429 value >>= 1;
430
431 outl(hc_value | data, hc_port);
432
433 /* Clock the shift register */
434 outl(hc_value | data | HANDN_BIT, hc_port);
435 outl(hc_value | data, hc_port);
436 }
437
438 /* Latch the bits */
439 outl(hc_value | HOOKN_BIT, hc_port);
440 outl(hc_value, hc_port);
441}
442
443/**************************************************************************
444 * @func Set the gain of the ECARD's CS3310 Trim/gain controller. The
445 * trim value consists of a 16bit value which is composed of two
446 * 8 bit gain/trim values, one for the left channel and one for the
447 * right channel. The following table maps from the Gain/Attenuation
448 * value in decibels into the corresponding bit pattern for a single
449 * channel.
450 */
451
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100452static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 unsigned short gain)
454{
455 unsigned int bit;
456
457 /* Enable writing to the TRIM registers */
458 snd_emu10k1_ecard_write(emu, emu->ecard_ctrl & ~EC_TRIM_CSN);
459
460 /* Do it again to insure that we meet hold time requirements */
461 snd_emu10k1_ecard_write(emu, emu->ecard_ctrl & ~EC_TRIM_CSN);
462
463 for (bit = (1 << 15); bit; bit >>= 1) {
464 unsigned int value;
465
466 value = emu->ecard_ctrl & ~(EC_TRIM_CSN | EC_TRIM_SDATA);
467
468 if (gain & bit)
469 value |= EC_TRIM_SDATA;
470
471 /* Clock the bit */
472 snd_emu10k1_ecard_write(emu, value);
473 snd_emu10k1_ecard_write(emu, value | EC_TRIM_SCLK);
474 snd_emu10k1_ecard_write(emu, value);
475 }
476
477 snd_emu10k1_ecard_write(emu, emu->ecard_ctrl);
478}
479
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100480static int __devinit snd_emu10k1_ecard_init(struct snd_emu10k1 * emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481{
482 unsigned int hc_value;
483
484 /* Set up the initial settings */
485 emu->ecard_ctrl = EC_RAW_RUN_MODE |
486 EC_SPDIF0_SELECT(EC_DEFAULT_SPDIF0_SEL) |
487 EC_SPDIF1_SELECT(EC_DEFAULT_SPDIF1_SEL);
488
489 /* Step 0: Set the codec type in the hardware control register
490 * and enable audio output */
491 hc_value = inl(emu->port + HCFG);
492 outl(hc_value | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S, emu->port + HCFG);
493 inl(emu->port + HCFG);
494
495 /* Step 1: Turn off the led and deassert TRIM_CS */
496 snd_emu10k1_ecard_write(emu, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
497
498 /* Step 2: Calibrate the ADC and DAC */
499 snd_emu10k1_ecard_write(emu, EC_DACCAL | EC_LEDN | EC_TRIM_CSN);
500
501 /* Step 3: Wait for awhile; XXX We can't get away with this
502 * under a real operating system; we'll need to block and wait that
503 * way. */
504 snd_emu10k1_wait(emu, 48000);
505
506 /* Step 4: Switch off the DAC and ADC calibration. Note
507 * That ADC_CAL is actually an inverted signal, so we assert
508 * it here to stop calibration. */
509 snd_emu10k1_ecard_write(emu, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
510
511 /* Step 4: Switch into run mode */
512 snd_emu10k1_ecard_write(emu, emu->ecard_ctrl);
513
514 /* Step 5: Set the analog input gain */
515 snd_emu10k1_ecard_setadcgain(emu, EC_DEFAULT_ADC_GAIN);
516
517 return 0;
518}
519
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100520static int __devinit snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu)
James Courtier-Duttond83c6712005-10-31 10:27:41 +0000521{
522 unsigned long special_port;
523 unsigned int value;
524
525 /* Special initialisation routine
526 * before the rest of the IO-Ports become active.
527 */
528 special_port = emu->port + 0x38;
529 value = inl(special_port);
530 outl(0x00d00000, special_port);
531 value = inl(special_port);
532 outl(0x00d00001, special_port);
533 value = inl(special_port);
534 outl(0x00d0005f, special_port);
535 value = inl(special_port);
536 outl(0x00d0007f, special_port);
537 value = inl(special_port);
538 outl(0x0090007f, special_port);
539 value = inl(special_port);
540
James Courtier-Duttone2b15f82005-11-11 23:39:05 +0100541 snd_emu10k1_ptr20_write(emu, TINA2_VOLUME, 0, 0xfefefefe); /* Defaults to 0x30303030 */
James Courtier-Duttond83c6712005-10-31 10:27:41 +0000542 return 0;
543}
544
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545/*
546 * Create the EMU10K1 instance
547 */
548
Takashi Iwai09668b42005-11-17 16:14:10 +0100549#ifdef CONFIG_PM
550static int alloc_pm_buffer(struct snd_emu10k1 *emu);
551static void free_pm_buffer(struct snd_emu10k1 *emu);
552#endif
553
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100554static int snd_emu10k1_free(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
556 if (emu->port) { /* avoid access to already used hardware */
557 snd_emu10k1_fx8010_tram_setup(emu, 0);
558 snd_emu10k1_done(emu);
Takashi Iwai09668b42005-11-17 16:14:10 +0100559 /* remove reserved page */
560 if (emu->reserved_page) {
561 snd_emu10k1_synth_free(emu, (struct snd_util_memblk *)emu->reserved_page);
562 emu->reserved_page = NULL;
563 }
564 snd_emu10k1_free_efx(emu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 }
566 if (emu->memhdr)
567 snd_util_memhdr_free(emu->memhdr);
568 if (emu->silent_page.area)
569 snd_dma_free_pages(&emu->silent_page);
570 if (emu->ptb_pages.area)
571 snd_dma_free_pages(&emu->ptb_pages);
572 vfree(emu->page_ptr_table);
573 vfree(emu->page_addr_table);
Takashi Iwai09668b42005-11-17 16:14:10 +0100574#ifdef CONFIG_PM
575 free_pm_buffer(emu);
576#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 if (emu->irq >= 0)
578 free_irq(emu->irq, (void *)emu);
579 if (emu->port)
580 pci_release_regions(emu->pci);
Lee Revell2b637da2005-03-30 13:51:18 +0200581 if (emu->card_capabilities->ca0151_chip) /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 snd_p16v_free(emu);
Takashi Iwai09668b42005-11-17 16:14:10 +0100583 pci_disable_device(emu->pci);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 kfree(emu);
585 return 0;
586}
587
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100588static int snd_emu10k1_dev_free(struct snd_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100590 struct snd_emu10k1 *emu = device->device_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 return snd_emu10k1_free(emu);
592}
593
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100594static struct snd_emu_chip_details emu_chip_details[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
James Courtier-Dutton88dc0e52005-07-03 12:54:29 +0200596 /* Tested by James@superbug.co.uk 3rd July 2005 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
598 .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200599 .id = "Audigy2",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 .emu10k2_chip = 1,
601 .ca0108_chip = 1,
Peter Zubaj26689072005-04-01 11:15:07 +0200602 .spk71 = 1,
603 .ac97_chip = 1} ,
James Courtier-Duttond83c6712005-10-31 10:27:41 +0000604 /* Audigy 2 ZS Notebook Cardbus card.*/
605 /* Tested by James@superbug.co.uk 30th October 2005 */
606 /* Not working yet, but progressing. */
607 {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
608 .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
609 .id = "Audigy2",
610 .emu10k2_chip = 1,
611 .ca0108_chip = 1,
612 .ca_cardbus_chip = 1,
613 .spk71 = 1} ,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 {.vendor = 0x1102, .device = 0x0008,
615 .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200616 .id = "Audigy2",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 .emu10k2_chip = 1,
Peter Zubaj26689072005-04-01 11:15:07 +0200618 .ca0108_chip = 1,
619 .ac97_chip = 1} ,
James Courtier-Dutton7c1d5492005-07-10 11:50:36 +0200620 /* Tested by James@superbug.co.uk 8th July 2005. No sound available yet. */
621 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
622 .driver = "Audigy2", .name = "E-mu 1212m [4001]",
623 .id = "EMU1212m",
624 .emu10k2_chip = 1,
625 .ca0102_chip = 1,
626 .ecard = 1} ,
James Courtier-Dutton88dc0e52005-07-03 12:54:29 +0200627 /* Tested by James@superbug.co.uk 3rd July 2005 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
629 .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200630 .id = "Audigy2",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 .emu10k2_chip = 1,
632 .ca0102_chip = 1,
633 .ca0151_chip = 1,
634 .spk71 = 1,
635 .spdif_bug = 1,
636 .ac97_chip = 1} ,
Lee Revellf6f8bb62005-11-07 14:59:19 +0100637 /* Tested by shane-alsa@cm.nu 5th Nov 2005 */
638 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102,
639 .driver = "Audigy2", .name = "Audigy 2 [2006]",
640 .id = "Audigy2",
641 .emu10k2_chip = 1,
642 .ca0102_chip = 1,
643 .ca0151_chip = 1,
644 .spk71 = 1,
645 .spdif_bug = 1,
646 .ac97_chip = 1} ,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
648 .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200649 .id = "Audigy2",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 .emu10k2_chip = 1,
651 .ca0102_chip = 1,
652 .ca0151_chip = 1,
653 .spk71 = 1,
654 .spdif_bug = 1,
655 .ac97_chip = 1} ,
656 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
657 .driver = "Audigy2", .name = "Audigy 2 ZS [2001]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200658 .id = "Audigy2",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 .emu10k2_chip = 1,
660 .ca0102_chip = 1,
661 .ca0151_chip = 1,
662 .spk71 = 1,
663 .spdif_bug = 1,
664 .ac97_chip = 1} ,
665 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
666 .driver = "Audigy2", .name = "Audigy 2 [SB0240]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200667 .id = "Audigy2",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 .emu10k2_chip = 1,
669 .ca0102_chip = 1,
670 .ca0151_chip = 1,
671 .spk71 = 1,
672 .spdif_bug = 1,
673 .ac97_chip = 1} ,
674 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
675 .driver = "Audigy2", .name = "Audigy 2 EX [1005]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200676 .id = "Audigy2",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 .emu10k2_chip = 1,
678 .ca0102_chip = 1,
679 .ca0151_chip = 1,
Lee Revell2f020aa2005-11-07 14:54:24 +0100680 .spk71 = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 .spdif_bug = 1} ,
682 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
683 .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200684 .id = "Audigy2",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 .emu10k2_chip = 1,
686 .ca0102_chip = 1,
687 .ca0151_chip = 1,
688 .spk71 = 1,
689 .spdif_bug = 1,
690 .ac97_chip = 1} ,
Takashi Iwaibdaed502005-04-07 15:48:42 +0200691 {.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
692 .driver = "Audigy2", .name = "Audigy 2 [Unknown]",
693 .id = "Audigy2",
694 .emu10k2_chip = 1,
695 .ca0102_chip = 1,
696 .ca0151_chip = 1,
697 .spdif_bug = 1,
698 .ac97_chip = 1} ,
Peter Zubaj26689072005-04-01 11:15:07 +0200699 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102,
700 .driver = "Audigy", .name = "Audigy 1 [SB0090]",
701 .id = "Audigy",
702 .emu10k2_chip = 1,
703 .ca0102_chip = 1,
704 .ac97_chip = 1} ,
James Courtier-Duttonae3a72d2005-07-06 22:36:18 +0200705 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102,
706 .driver = "Audigy", .name = "Audigy 1 ES [SB0160]",
707 .id = "Audigy",
708 .emu10k2_chip = 1,
709 .ca0102_chip = 1,
710 .spdif_bug = 1,
711 .ac97_chip = 1} ,
Arnaud Patarda6c17ec2005-05-27 12:31:34 +0200712 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102,
713 .driver = "Audigy", .name = "Audigy 1 [SB0090]",
714 .id = "Audigy",
715 .emu10k2_chip = 1,
716 .ca0102_chip = 1,
717 .ac97_chip = 1} ,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 {.vendor = 0x1102, .device = 0x0004,
Takashi Iwaibdaed502005-04-07 15:48:42 +0200719 .driver = "Audigy", .name = "Audigy 1 [Unknown]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200720 .id = "Audigy",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 .emu10k2_chip = 1,
722 .ca0102_chip = 1,
Peter Zubaj26689072005-04-01 11:15:07 +0200723 .ac97_chip = 1} ,
James Courtier-Duttona6f61922005-07-03 12:32:40 +0200724 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102,
725 .driver = "EMU10K1", .name = "SBLive! [SB0105]",
James Courtier-Dutton2b6b22f2005-06-18 13:50:22 +0200726 .id = "Live",
727 .emu10k1_chip = 1,
728 .ac97_chip = 1,
729 .sblive51 = 1} ,
730 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102,
731 .driver = "EMU10K1", .name = "SBLive! Value [SB0103]",
732 .id = "Live",
733 .emu10k1_chip = 1,
734 .ac97_chip = 1,
735 .sblive51 = 1} ,
James Courtier-Duttona6f61922005-07-03 12:32:40 +0200736 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102,
737 .driver = "EMU10K1", .name = "SBLive! Value [SB0101]",
738 .id = "Live",
739 .emu10k1_chip = 1,
740 .ac97_chip = 1,
741 .sblive51 = 1} ,
Lee Revellc6c0b842005-08-29 17:42:00 +0200742 /* Tested by Thomas Zehetbauer 27th Aug 2005 */
743 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80651102,
744 .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]",
745 .id = "Live",
746 .emu10k1_chip = 1,
747 .ac97_chip = 1,
748 .sblive51 = 1} ,
James Courtier-Duttona6f61922005-07-03 12:32:40 +0200749 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
750 .driver = "EMU10K1", .name = "SB Live 5.1",
751 .id = "Live",
752 .emu10k1_chip = 1,
753 .ac97_chip = 1,
754 .sblive51 = 1} ,
James Courtier-Duttonafe0f1f2005-09-10 10:24:10 +0200755 /* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */
James Courtier-Duttona6f61922005-07-03 12:32:40 +0200756 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
Takashi Iwaif12aa402005-09-30 16:56:59 +0200757 .driver = "EMU10K1", .name = "SBLive 5.1 [SB0060]",
James Courtier-Duttona6f61922005-07-03 12:32:40 +0200758 .id = "Live",
759 .emu10k1_chip = 1,
Takashi Iwaif12aa402005-09-30 16:56:59 +0200760 .ac97_chip = 2, /* ac97 is optional; both SBLive 5.1 and platinum
761 * share the same IDs!
762 */
James Courtier-Duttona6f61922005-07-03 12:32:40 +0200763 .sblive51 = 1} ,
764 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
765 .driver = "EMU10K1", .name = "SBLive! Value [CT4850]",
766 .id = "Live",
767 .emu10k1_chip = 1,
768 .ac97_chip = 1,
769 .sblive51 = 1} ,
770 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
771 .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]",
772 .id = "Live",
773 .emu10k1_chip = 1,
774 .ac97_chip = 1} ,
775 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102,
776 .driver = "EMU10K1", .name = "SBLive! Value [CT4871]",
777 .id = "Live",
778 .emu10k1_chip = 1,
779 .ac97_chip = 1,
780 .sblive51 = 1} ,
781 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102,
782 .driver = "EMU10K1", .name = "SBLive! Value [CT4831]",
783 .id = "Live",
784 .emu10k1_chip = 1,
785 .ac97_chip = 1,
786 .sblive51 = 1} ,
787 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102,
788 .driver = "EMU10K1", .name = "SBLive! Value [CT4870]",
789 .id = "Live",
790 .emu10k1_chip = 1,
791 .ac97_chip = 1,
792 .sblive51 = 1} ,
James Courtier-Dutton88dc0e52005-07-03 12:54:29 +0200793 /* Tested by James@superbug.co.uk 3rd July 2005 */
James Courtier-Duttona6f61922005-07-03 12:32:40 +0200794 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102,
795 .driver = "EMU10K1", .name = "SBLive! Value [CT4832]",
796 .id = "Live",
797 .emu10k1_chip = 1,
798 .ac97_chip = 1,
799 .sblive51 = 1} ,
800 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102,
801 .driver = "EMU10K1", .name = "SBLive! Value [CT4830]",
802 .id = "Live",
803 .emu10k1_chip = 1,
804 .ac97_chip = 1,
805 .sblive51 = 1} ,
806 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102,
807 .driver = "EMU10K1", .name = "SB PCI512 [CT4790]",
808 .id = "Live",
809 .emu10k1_chip = 1,
810 .ac97_chip = 1,
811 .sblive51 = 1} ,
812 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102,
813 .driver = "EMU10K1", .name = "SBLive! Value [CT4780]",
814 .id = "Live",
815 .emu10k1_chip = 1,
816 .ac97_chip = 1,
817 .sblive51 = 1} ,
818 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
819 .driver = "EMU10K1", .name = "E-mu APS [4001]",
820 .id = "APS",
821 .emu10k1_chip = 1,
822 .ecard = 1} ,
823 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102,
824 .driver = "EMU10K1", .name = "SBLive! [CT4620]",
825 .id = "Live",
826 .emu10k1_chip = 1,
827 .ac97_chip = 1,
828 .sblive51 = 1} ,
829 {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102,
830 .driver = "EMU10K1", .name = "SBLive! Value [CT4670]",
James Courtier-Dutton2b6b22f2005-06-18 13:50:22 +0200831 .id = "Live",
832 .emu10k1_chip = 1,
833 .ac97_chip = 1,
834 .sblive51 = 1} ,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 {.vendor = 0x1102, .device = 0x0002,
836 .driver = "EMU10K1", .name = "SB Live [Unknown]",
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200837 .id = "Live",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 .emu10k1_chip = 1,
Lee Revell2b637da2005-03-30 13:51:18 +0200839 .ac97_chip = 1,
840 .sblive51 = 1} ,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 { } /* terminator */
842};
843
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100844int __devinit snd_emu10k1_create(struct snd_card *card,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 struct pci_dev * pci,
846 unsigned short extin_mask,
847 unsigned short extout_mask,
848 long max_cache_bytes,
849 int enable_ir,
James Courtier-Duttone66bc8b2005-07-06 22:21:51 +0200850 uint subsystem,
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100851 struct snd_emu10k1 ** remu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100853 struct snd_emu10k1 *emu;
Takashi Iwai09668b42005-11-17 16:14:10 +0100854 int idx, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 int is_audigy;
856 unsigned char revision;
Takashi Iwai09668b42005-11-17 16:14:10 +0100857 unsigned int silent_page;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100858 const struct snd_emu_chip_details *c;
859 static struct snd_device_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 .dev_free = snd_emu10k1_dev_free,
861 };
862
863 *remu = NULL;
864
865 /* enable PCI device */
866 if ((err = pci_enable_device(pci)) < 0)
867 return err;
868
Takashi Iwaie560d8d2005-09-09 14:21:46 +0200869 emu = kzalloc(sizeof(*emu), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 if (emu == NULL) {
871 pci_disable_device(pci);
872 return -ENOMEM;
873 }
874 emu->card = card;
875 spin_lock_init(&emu->reg_lock);
876 spin_lock_init(&emu->emu_lock);
877 spin_lock_init(&emu->voice_lock);
878 spin_lock_init(&emu->synth_lock);
879 spin_lock_init(&emu->memblk_lock);
880 init_MUTEX(&emu->ptb_lock);
881 init_MUTEX(&emu->fx8010.lock);
882 INIT_LIST_HEAD(&emu->mapped_link_head);
883 INIT_LIST_HEAD(&emu->mapped_order_link_head);
884 emu->pci = pci;
885 emu->irq = -1;
886 emu->synth = NULL;
887 emu->get_synth_voice = NULL;
888 /* read revision & serial */
889 pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
890 emu->revision = revision;
891 pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
892 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
894
895 for (c = emu_chip_details; c->vendor; c++) {
896 if (c->vendor == pci->vendor && c->device == pci->device) {
James Courtier-Duttone66bc8b2005-07-06 22:21:51 +0200897 if (subsystem) {
898 if (c->subsystem && (c->subsystem == subsystem) ) {
899 break;
900 } else continue;
901 } else {
902 if (c->subsystem && (c->subsystem != emu->serial) )
903 continue;
904 if (c->revision && c->revision != emu->revision)
905 continue;
906 }
Takashi Iwaibdaed502005-04-07 15:48:42 +0200907 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 }
909 }
910 if (c->vendor == 0) {
911 snd_printk(KERN_ERR "emu10k1: Card not recognised\n");
912 kfree(emu);
913 pci_disable_device(pci);
914 return -ENOENT;
915 }
916 emu->card_capabilities = c;
James Courtier-Duttone66bc8b2005-07-06 22:21:51 +0200917 if (c->subsystem && !subsystem)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 snd_printdd("Sound card name=%s\n", c->name);
James Courtier-Duttone66bc8b2005-07-06 22:21:51 +0200919 else if (subsystem)
920 snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x. Forced to subsytem=0x%x\n",
921 c->name, pci->vendor, pci->device, emu->serial, c->subsystem);
922 else
923 snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x.\n",
924 c->name, pci->vendor, pci->device, emu->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
Takashi Iwai85a655d2005-03-30 14:40:25 +0200926 if (!*card->id && c->id) {
927 int i, n = 0;
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200928 strlcpy(card->id, c->id, sizeof(card->id));
Takashi Iwai85a655d2005-03-30 14:40:25 +0200929 for (;;) {
930 for (i = 0; i < snd_ecards_limit; i++) {
931 if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id))
932 break;
933 }
934 if (i >= snd_ecards_limit)
935 break;
936 n++;
937 if (n >= SNDRV_CARDS)
938 break;
939 snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n);
940 }
941 }
Takashi Iwaiaec72e02005-03-30 14:22:25 +0200942
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 is_audigy = emu->audigy = c->emu10k2_chip;
944
945 /* set the DMA transfer mask */
946 emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
947 if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
948 pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
949 snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
950 kfree(emu);
951 pci_disable_device(pci);
952 return -ENXIO;
953 }
954 if (is_audigy)
955 emu->gpr_base = A_FXGPREGBASE;
956 else
957 emu->gpr_base = FXGPREGBASE;
958
959 if ((err = pci_request_regions(pci, "EMU10K1")) < 0) {
960 kfree(emu);
961 pci_disable_device(pci);
962 return err;
963 }
964 emu->port = pci_resource_start(pci, 0);
965
966 if (request_irq(pci->irq, snd_emu10k1_interrupt, SA_INTERRUPT|SA_SHIRQ, "EMU10K1", (void *)emu)) {
Takashi Iwai09668b42005-11-17 16:14:10 +0100967 err = -EBUSY;
968 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 }
970 emu->irq = pci->irq;
971
972 emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
973 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
974 32 * 1024, &emu->ptb_pages) < 0) {
Takashi Iwai09668b42005-11-17 16:14:10 +0100975 err = -ENOMEM;
976 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 }
978
979 emu->page_ptr_table = (void **)vmalloc(emu->max_cache_pages * sizeof(void*));
980 emu->page_addr_table = (unsigned long*)vmalloc(emu->max_cache_pages * sizeof(unsigned long));
981 if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) {
Takashi Iwai09668b42005-11-17 16:14:10 +0100982 err = -ENOMEM;
983 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 }
985
986 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
987 EMUPAGESIZE, &emu->silent_page) < 0) {
Takashi Iwai09668b42005-11-17 16:14:10 +0100988 err = -ENOMEM;
989 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 }
991 emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE);
992 if (emu->memhdr == NULL) {
Takashi Iwai09668b42005-11-17 16:14:10 +0100993 err = -ENOMEM;
994 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 }
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100996 emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) -
997 sizeof(struct snd_util_memblk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
999 pci_set_master(pci);
1000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 emu->fx8010.fxbus_mask = 0x303f;
1002 if (extin_mask == 0)
1003 extin_mask = 0x3fcf;
1004 if (extout_mask == 0)
1005 extout_mask = 0x7fff;
1006 emu->fx8010.extin_mask = extin_mask;
1007 emu->fx8010.extout_mask = extout_mask;
Takashi Iwai09668b42005-11-17 16:14:10 +01001008 emu->enable_ir = enable_ir;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009
Lee Revell2b637da2005-03-30 13:51:18 +02001010 if (emu->card_capabilities->ecard) {
Takashi Iwai09668b42005-11-17 16:14:10 +01001011 if ((err = snd_emu10k1_ecard_init(emu)) < 0)
1012 goto error;
James Courtier-Duttond83c6712005-10-31 10:27:41 +00001013 } else if (emu->card_capabilities->ca_cardbus_chip) {
Takashi Iwai09668b42005-11-17 16:14:10 +01001014 if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
1015 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 } else {
1017 /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
1018 does not support this, it shouldn't do any harm */
1019 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
1020 }
1021
Takashi Iwai09668b42005-11-17 16:14:10 +01001022 /* initialize TRAM setup */
1023 emu->fx8010.itram_size = (16 * 1024)/2;
1024 emu->fx8010.etram_pages.area = NULL;
1025 emu->fx8010.etram_pages.bytes = 0;
1026
1027 /*
1028 * Init to 0x02109204 :
1029 * Clock accuracy = 0 (1000ppm)
1030 * Sample Rate = 2 (48kHz)
1031 * Audio Channel = 1 (Left of 2)
1032 * Source Number = 0 (Unspecified)
1033 * Generation Status = 1 (Original for Cat Code 12)
1034 * Cat Code = 12 (Digital Signal Mixer)
1035 * Mode = 0 (Mode 0)
1036 * Emphasis = 0 (None)
1037 * CP = 1 (Copyright unasserted)
1038 * AN = 0 (Audio data)
1039 * P = 0 (Consumer)
1040 */
1041 emu->spdif_bits[0] = emu->spdif_bits[1] =
1042 emu->spdif_bits[2] = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
1043 SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
1044 SPCS_GENERATIONSTATUS | 0x00001200 |
1045 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
1046
1047 emu->reserved_page = (struct snd_emu10k1_memblk *)
1048 snd_emu10k1_synth_alloc(emu, 4096);
1049 if (emu->reserved_page)
1050 emu->reserved_page->map_locked = 1;
1051
1052 /* Clear silent pages and set up pointers */
1053 memset(emu->silent_page.area, 0, PAGE_SIZE);
1054 silent_page = emu->silent_page.addr << 1;
1055 for (idx = 0; idx < MAXPAGES; idx++)
1056 ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
1057
1058 /* set up voice indices */
1059 for (idx = 0; idx < NUM_G; idx++) {
1060 emu->voices[idx].emu = emu;
1061 emu->voices[idx].number = idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063
Takashi Iwai09668b42005-11-17 16:14:10 +01001064 if ((err = snd_emu10k1_init(emu, enable_ir, 0)) < 0)
1065 goto error;
1066#ifdef CONFIG_PM
1067 if ((err = alloc_pm_buffer(emu)) < 0)
1068 goto error;
1069#endif
1070
1071 /* Initialize the effect engine */
1072 if ((err = snd_emu10k1_init_efx(emu)) < 0)
1073 goto error;
1074 snd_emu10k1_audio_enable(emu);
1075
1076 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops)) < 0)
1077 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
1079 snd_emu10k1_proc_init(emu);
1080
1081 snd_card_set_dev(card, &pci->dev);
1082 *remu = emu;
1083 return 0;
Takashi Iwai09668b42005-11-17 16:14:10 +01001084
1085 error:
1086 snd_emu10k1_free(emu);
1087 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088}
1089
Takashi Iwai09668b42005-11-17 16:14:10 +01001090#ifdef CONFIG_PM
1091static unsigned char saved_regs[] = {
1092 CPF, PTRX, CVCF, VTFT, Z1, Z2, PSST, DSL, CCCA, CCR, CLP,
1093 FXRT, MAPA, MAPB, ENVVOL, ATKHLDV, DCYSUSV, LFOVAL1, ENVVAL,
1094 ATKHLDM, DCYSUSM, LFOVAL2, IP, IFATN, PEFE, FMMOD, TREMFRQ, FM2FRQ2,
1095 TEMPENV, ADCCR, FXWC, MICBA, ADCBA, FXBA,
1096 MICBS, ADCBS, FXBS, CDCS, GPSCS, SPCS0, SPCS1, SPCS2,
1097 SPBYPASS, AC97SLOT, CDSRCS, GPSRCS, ZVSRCS, MICIDX, ADCIDX, FXIDX,
1098 0xff /* end */
1099};
1100static unsigned char saved_regs_audigy[] = {
1101 A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_SAMPLE_RATE,
1102 A_FXRT2, A_SENDAMOUNTS, A_FXRT1,
1103 0xff /* end */
1104};
1105
1106static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu)
1107{
1108 int size;
1109
1110 size = ARRAY_SIZE(saved_regs);
1111 if (emu->audigy)
1112 size += ARRAY_SIZE(saved_regs_audigy);
1113 emu->saved_ptr = vmalloc(4 * NUM_G * size);
1114 if (! emu->saved_ptr)
1115 return -ENOMEM;
1116 if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0)
1117 return -ENOMEM;
1118 if (emu->card_capabilities->ca0151_chip &&
1119 snd_p16v_alloc_pm_buffer(emu) < 0)
1120 return -ENOMEM;
1121 return 0;
1122}
1123
1124static void free_pm_buffer(struct snd_emu10k1 *emu)
1125{
1126 vfree(emu->saved_ptr);
1127 snd_emu10k1_efx_free_pm_buffer(emu);
1128 if (emu->card_capabilities->ca0151_chip)
1129 snd_p16v_free_pm_buffer(emu);
1130}
1131
1132void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu)
1133{
1134 int i;
1135 unsigned char *reg;
1136 unsigned int *val;
1137
1138 val = emu->saved_ptr;
1139 for (reg = saved_regs; *reg != 0xff; reg++)
1140 for (i = 0; i < NUM_G; i++, val++)
1141 *val = snd_emu10k1_ptr_read(emu, *reg, i);
1142 if (emu->audigy) {
1143 for (reg = saved_regs_audigy; *reg != 0xff; reg++)
1144 for (i = 0; i < NUM_G; i++, val++)
1145 *val = snd_emu10k1_ptr_read(emu, *reg, i);
1146 }
1147 if (emu->audigy)
1148 emu->saved_a_iocfg = inl(emu->port + A_IOCFG);
1149 emu->saved_hcfg = inl(emu->port + HCFG);
1150}
1151
1152void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
1153{
1154 if (emu->card_capabilities->ecard)
1155 snd_emu10k1_ecard_init(emu);
1156 else
1157 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
1158 snd_emu10k1_init(emu, emu->enable_ir, 1);
1159}
1160
1161void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu)
1162{
1163 int i;
1164 unsigned char *reg;
1165 unsigned int *val;
1166
1167 snd_emu10k1_audio_enable(emu);
1168
1169 /* resore for spdif */
1170 if (emu->audigy)
1171 outl(emu->port + A_IOCFG, emu->saved_a_iocfg);
1172 outl(emu->port + HCFG, emu->saved_hcfg);
1173
1174 val = emu->saved_ptr;
1175 for (reg = saved_regs; *reg != 0xff; reg++)
1176 for (i = 0; i < NUM_G; i++, val++)
1177 snd_emu10k1_ptr_write(emu, *reg, i, *val);
1178 if (emu->audigy) {
1179 for (reg = saved_regs_audigy; *reg != 0xff; reg++)
1180 for (i = 0; i < NUM_G; i++, val++)
1181 snd_emu10k1_ptr_write(emu, *reg, i, *val);
1182 }
1183}
1184#endif
1185
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186/* memory.c */
1187EXPORT_SYMBOL(snd_emu10k1_synth_alloc);
1188EXPORT_SYMBOL(snd_emu10k1_synth_free);
1189EXPORT_SYMBOL(snd_emu10k1_synth_bzero);
1190EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user);
1191EXPORT_SYMBOL(snd_emu10k1_memblk_map);
1192/* voice.c */
1193EXPORT_SYMBOL(snd_emu10k1_voice_alloc);
1194EXPORT_SYMBOL(snd_emu10k1_voice_free);
1195/* io.c */
1196EXPORT_SYMBOL(snd_emu10k1_ptr_read);
1197EXPORT_SYMBOL(snd_emu10k1_ptr_write);