This source file includes following definitions.
- snd_emu10k1_ptr_read
- snd_emu10k1_ptr_write
- snd_emu10k1_ptr20_read
- snd_emu10k1_ptr20_write
- snd_emu10k1_spi_write
- snd_emu10k1_i2c_write
- snd_emu1010_fpga_write
- snd_emu1010_fpga_read
- snd_emu1010_fpga_link_dst_src_write
- snd_emu10k1_intr_enable
- snd_emu10k1_intr_disable
- snd_emu10k1_voice_intr_enable
- snd_emu10k1_voice_intr_disable
- snd_emu10k1_voice_intr_ack
- snd_emu10k1_voice_half_loop_intr_enable
- snd_emu10k1_voice_half_loop_intr_disable
- snd_emu10k1_voice_half_loop_intr_ack
- snd_emu10k1_voice_set_loop_stop
- snd_emu10k1_voice_clear_loop_stop
- snd_emu10k1_wait
- snd_emu10k1_ac97_read
- snd_emu10k1_ac97_write
- snd_emu10k1_rate_to_pitch
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <linux/time.h>
15 #include <sound/core.h>
16 #include <sound/emu10k1.h>
17 #include <linux/delay.h>
18 #include <linux/export.h>
19 #include "p17v.h"
20
21 unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
22 {
23 unsigned long flags;
24 unsigned int regptr, val;
25 unsigned int mask;
26
27 mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
28 regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
29
30 if (reg & 0xff000000) {
31 unsigned char size, offset;
32
33 size = (reg >> 24) & 0x3f;
34 offset = (reg >> 16) & 0x1f;
35 mask = ((1 << size) - 1) << offset;
36
37 spin_lock_irqsave(&emu->emu_lock, flags);
38 outl(regptr, emu->port + PTR);
39 val = inl(emu->port + DATA);
40 spin_unlock_irqrestore(&emu->emu_lock, flags);
41
42 return (val & mask) >> offset;
43 } else {
44 spin_lock_irqsave(&emu->emu_lock, flags);
45 outl(regptr, emu->port + PTR);
46 val = inl(emu->port + DATA);
47 spin_unlock_irqrestore(&emu->emu_lock, flags);
48 return val;
49 }
50 }
51
52 EXPORT_SYMBOL(snd_emu10k1_ptr_read);
53
54 void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)
55 {
56 unsigned int regptr;
57 unsigned long flags;
58 unsigned int mask;
59
60 if (snd_BUG_ON(!emu))
61 return;
62 mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
63 regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
64
65 if (reg & 0xff000000) {
66 unsigned char size, offset;
67
68 size = (reg >> 24) & 0x3f;
69 offset = (reg >> 16) & 0x1f;
70 mask = ((1 << size) - 1) << offset;
71 data = (data << offset) & mask;
72
73 spin_lock_irqsave(&emu->emu_lock, flags);
74 outl(regptr, emu->port + PTR);
75 data |= inl(emu->port + DATA) & ~mask;
76 outl(data, emu->port + DATA);
77 spin_unlock_irqrestore(&emu->emu_lock, flags);
78 } else {
79 spin_lock_irqsave(&emu->emu_lock, flags);
80 outl(regptr, emu->port + PTR);
81 outl(data, emu->port + DATA);
82 spin_unlock_irqrestore(&emu->emu_lock, flags);
83 }
84 }
85
86 EXPORT_SYMBOL(snd_emu10k1_ptr_write);
87
88 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu,
89 unsigned int reg,
90 unsigned int chn)
91 {
92 unsigned long flags;
93 unsigned int regptr, val;
94
95 regptr = (reg << 16) | chn;
96
97 spin_lock_irqsave(&emu->emu_lock, flags);
98 outl(regptr, emu->port + 0x20 + PTR);
99 val = inl(emu->port + 0x20 + DATA);
100 spin_unlock_irqrestore(&emu->emu_lock, flags);
101 return val;
102 }
103
104 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu,
105 unsigned int reg,
106 unsigned int chn,
107 unsigned int data)
108 {
109 unsigned int regptr;
110 unsigned long flags;
111
112 regptr = (reg << 16) | chn;
113
114 spin_lock_irqsave(&emu->emu_lock, flags);
115 outl(regptr, emu->port + 0x20 + PTR);
116 outl(data, emu->port + 0x20 + DATA);
117 spin_unlock_irqrestore(&emu->emu_lock, flags);
118 }
119
120 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
121 unsigned int data)
122 {
123 unsigned int reset, set;
124 unsigned int reg, tmp;
125 int n, result;
126 int err = 0;
127
128
129 spin_lock(&emu->spi_lock);
130 if (emu->card_capabilities->ca0108_chip)
131 reg = 0x3c;
132 else {
133
134
135 err = 1;
136 goto spi_write_exit;
137 }
138 if (data > 0xffff) {
139
140 err = 1;
141 goto spi_write_exit;
142 }
143
144 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
145 reset = (tmp & ~0x3ffff) | 0x20000;
146 set = reset | 0x10000;
147 snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
148 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
149 snd_emu10k1_ptr20_write(emu, reg, 0, set | data);
150 result = 1;
151
152 for (n = 0; n < 100; n++) {
153 udelay(10);
154 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
155 if (!(tmp & 0x10000)) {
156 result = 0;
157 break;
158 }
159 }
160 if (result) {
161
162 err = 1;
163 goto spi_write_exit;
164 }
165 snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
166 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
167 err = 0;
168 spi_write_exit:
169 spin_unlock(&emu->spi_lock);
170 return err;
171 }
172
173
174 int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
175 u32 reg,
176 u32 value)
177 {
178 u32 tmp;
179 int timeout = 0;
180 int status;
181 int retry;
182 int err = 0;
183
184 if ((reg > 0x7f) || (value > 0x1ff)) {
185 dev_err(emu->card->dev, "i2c_write: invalid values.\n");
186 return -EINVAL;
187 }
188
189
190 spin_lock(&emu->i2c_lock);
191
192 tmp = reg << 25 | value << 16;
193
194
195 snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
196 tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0);
197
198 for (retry = 0; retry < 10; retry++) {
199
200 tmp = 0;
201 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
202 snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);
203
204
205 while (1) {
206 mdelay(1);
207 status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
208 timeout++;
209 if ((status & I2C_A_ADC_START) == 0)
210 break;
211
212 if (timeout > 1000) {
213 dev_warn(emu->card->dev,
214 "emu10k1:I2C:timeout status=0x%x\n",
215 status);
216 break;
217 }
218 }
219
220 if ((status & I2C_A_ADC_ABORT) == 0)
221 break;
222 }
223
224 if (retry == 10) {
225 dev_err(emu->card->dev, "Writing to ADC failed!\n");
226 dev_err(emu->card->dev, "status=0x%x, reg=%d, value=%d\n",
227 status, reg, value);
228
229 err = -EINVAL;
230 }
231
232 spin_unlock(&emu->i2c_lock);
233 return err;
234 }
235
236 int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value)
237 {
238 unsigned long flags;
239
240 if (reg > 0x3f)
241 return 1;
242 reg += 0x40;
243 if (value > 0x3f)
244 return 1;
245 spin_lock_irqsave(&emu->emu_lock, flags);
246 outl(reg, emu->port + A_IOCFG);
247 udelay(10);
248 outl(reg | 0x80, emu->port + A_IOCFG);
249 udelay(10);
250 outl(value, emu->port + A_IOCFG);
251 udelay(10);
252 outl(value | 0x80 , emu->port + A_IOCFG);
253 spin_unlock_irqrestore(&emu->emu_lock, flags);
254
255 return 0;
256 }
257
258 int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value)
259 {
260 unsigned long flags;
261 if (reg > 0x3f)
262 return 1;
263 reg += 0x40;
264 spin_lock_irqsave(&emu->emu_lock, flags);
265 outl(reg, emu->port + A_IOCFG);
266 udelay(10);
267 outl(reg | 0x80, emu->port + A_IOCFG);
268 udelay(10);
269 *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f);
270 spin_unlock_irqrestore(&emu->emu_lock, flags);
271
272 return 0;
273 }
274
275
276
277
278 int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src)
279 {
280 snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
281 snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
282 snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) );
283 snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) );
284
285 return 0;
286 }
287
288 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
289 {
290 unsigned long flags;
291 unsigned int enable;
292
293 spin_lock_irqsave(&emu->emu_lock, flags);
294 enable = inl(emu->port + INTE) | intrenb;
295 outl(enable, emu->port + INTE);
296 spin_unlock_irqrestore(&emu->emu_lock, flags);
297 }
298
299 void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
300 {
301 unsigned long flags;
302 unsigned int enable;
303
304 spin_lock_irqsave(&emu->emu_lock, flags);
305 enable = inl(emu->port + INTE) & ~intrenb;
306 outl(enable, emu->port + INTE);
307 spin_unlock_irqrestore(&emu->emu_lock, flags);
308 }
309
310 void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
311 {
312 unsigned long flags;
313 unsigned int val;
314
315 spin_lock_irqsave(&emu->emu_lock, flags);
316
317 if (voicenum >= 32) {
318 outl(CLIEH << 16, emu->port + PTR);
319 val = inl(emu->port + DATA);
320 val |= 1 << (voicenum - 32);
321 } else {
322 outl(CLIEL << 16, emu->port + PTR);
323 val = inl(emu->port + DATA);
324 val |= 1 << voicenum;
325 }
326 outl(val, emu->port + DATA);
327 spin_unlock_irqrestore(&emu->emu_lock, flags);
328 }
329
330 void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
331 {
332 unsigned long flags;
333 unsigned int val;
334
335 spin_lock_irqsave(&emu->emu_lock, flags);
336
337 if (voicenum >= 32) {
338 outl(CLIEH << 16, emu->port + PTR);
339 val = inl(emu->port + DATA);
340 val &= ~(1 << (voicenum - 32));
341 } else {
342 outl(CLIEL << 16, emu->port + PTR);
343 val = inl(emu->port + DATA);
344 val &= ~(1 << voicenum);
345 }
346 outl(val, emu->port + DATA);
347 spin_unlock_irqrestore(&emu->emu_lock, flags);
348 }
349
350 void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
351 {
352 unsigned long flags;
353
354 spin_lock_irqsave(&emu->emu_lock, flags);
355
356 if (voicenum >= 32) {
357 outl(CLIPH << 16, emu->port + PTR);
358 voicenum = 1 << (voicenum - 32);
359 } else {
360 outl(CLIPL << 16, emu->port + PTR);
361 voicenum = 1 << voicenum;
362 }
363 outl(voicenum, emu->port + DATA);
364 spin_unlock_irqrestore(&emu->emu_lock, flags);
365 }
366
367 void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
368 {
369 unsigned long flags;
370 unsigned int val;
371
372 spin_lock_irqsave(&emu->emu_lock, flags);
373
374 if (voicenum >= 32) {
375 outl(HLIEH << 16, emu->port + PTR);
376 val = inl(emu->port + DATA);
377 val |= 1 << (voicenum - 32);
378 } else {
379 outl(HLIEL << 16, emu->port + PTR);
380 val = inl(emu->port + DATA);
381 val |= 1 << voicenum;
382 }
383 outl(val, emu->port + DATA);
384 spin_unlock_irqrestore(&emu->emu_lock, flags);
385 }
386
387 void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
388 {
389 unsigned long flags;
390 unsigned int val;
391
392 spin_lock_irqsave(&emu->emu_lock, flags);
393
394 if (voicenum >= 32) {
395 outl(HLIEH << 16, emu->port + PTR);
396 val = inl(emu->port + DATA);
397 val &= ~(1 << (voicenum - 32));
398 } else {
399 outl(HLIEL << 16, emu->port + PTR);
400 val = inl(emu->port + DATA);
401 val &= ~(1 << voicenum);
402 }
403 outl(val, emu->port + DATA);
404 spin_unlock_irqrestore(&emu->emu_lock, flags);
405 }
406
407 void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
408 {
409 unsigned long flags;
410
411 spin_lock_irqsave(&emu->emu_lock, flags);
412
413 if (voicenum >= 32) {
414 outl(HLIPH << 16, emu->port + PTR);
415 voicenum = 1 << (voicenum - 32);
416 } else {
417 outl(HLIPL << 16, emu->port + PTR);
418 voicenum = 1 << voicenum;
419 }
420 outl(voicenum, emu->port + DATA);
421 spin_unlock_irqrestore(&emu->emu_lock, flags);
422 }
423
424 void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
425 {
426 unsigned long flags;
427 unsigned int sol;
428
429 spin_lock_irqsave(&emu->emu_lock, flags);
430
431 if (voicenum >= 32) {
432 outl(SOLEH << 16, emu->port + PTR);
433 sol = inl(emu->port + DATA);
434 sol |= 1 << (voicenum - 32);
435 } else {
436 outl(SOLEL << 16, emu->port + PTR);
437 sol = inl(emu->port + DATA);
438 sol |= 1 << voicenum;
439 }
440 outl(sol, emu->port + DATA);
441 spin_unlock_irqrestore(&emu->emu_lock, flags);
442 }
443
444 void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
445 {
446 unsigned long flags;
447 unsigned int sol;
448
449 spin_lock_irqsave(&emu->emu_lock, flags);
450
451 if (voicenum >= 32) {
452 outl(SOLEH << 16, emu->port + PTR);
453 sol = inl(emu->port + DATA);
454 sol &= ~(1 << (voicenum - 32));
455 } else {
456 outl(SOLEL << 16, emu->port + PTR);
457 sol = inl(emu->port + DATA);
458 sol &= ~(1 << voicenum);
459 }
460 outl(sol, emu->port + DATA);
461 spin_unlock_irqrestore(&emu->emu_lock, flags);
462 }
463
464 void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait)
465 {
466 volatile unsigned count;
467 unsigned int newtime = 0, curtime;
468
469 curtime = inl(emu->port + WC) >> 6;
470 while (wait-- > 0) {
471 count = 0;
472 while (count++ < 16384) {
473 newtime = inl(emu->port + WC) >> 6;
474 if (newtime != curtime)
475 break;
476 }
477 if (count > 16384)
478 break;
479 curtime = newtime;
480 }
481 }
482
483 unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
484 {
485 struct snd_emu10k1 *emu = ac97->private_data;
486 unsigned long flags;
487 unsigned short val;
488
489 spin_lock_irqsave(&emu->emu_lock, flags);
490 outb(reg, emu->port + AC97ADDRESS);
491 val = inw(emu->port + AC97DATA);
492 spin_unlock_irqrestore(&emu->emu_lock, flags);
493 return val;
494 }
495
496 void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data)
497 {
498 struct snd_emu10k1 *emu = ac97->private_data;
499 unsigned long flags;
500
501 spin_lock_irqsave(&emu->emu_lock, flags);
502 outb(reg, emu->port + AC97ADDRESS);
503 outw(data, emu->port + AC97DATA);
504 spin_unlock_irqrestore(&emu->emu_lock, flags);
505 }
506
507
508
509
510
511 unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate)
512 {
513 static u32 logMagTable[128] = {
514 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
515 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
516 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
517 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
518 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
519 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
520 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
521 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
522 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
523 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
524 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
525 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
526 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
527 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
528 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
529 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
530 };
531 static char logSlopeTable[128] = {
532 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
533 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
534 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
535 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
536 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
537 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
538 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
539 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
540 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
541 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
542 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
543 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
544 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
545 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
546 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
547 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
548 };
549 int i;
550
551 if (rate == 0)
552 return 0;
553 rate *= 11185;
554 for (i = 31; i > 0; i--) {
555 if (rate & 0x80000000) {
556 return (((unsigned int) (i - 15) << 20) +
557 logMagTable[0x7f & (rate >> 24)] +
558 (0x7f & (rate >> 17)) *
559 logSlopeTable[0x7f & (rate >> 24)]);
560 }
561 rate <<= 1;
562 }
563
564 return 0;
565 }
566