1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Routines for control of EMU10K1 chips
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>
21 unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
24 unsigned int regptr, val;
27 mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
28 regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
30 if (reg & 0xff000000) {
31 unsigned char size, offset;
33 size = (reg >> 24) & 0x3f;
34 offset = (reg >> 16) & 0x1f;
35 mask = ((1 << size) - 1) << offset;
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);
42 return (val & mask) >> offset;
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);
52 EXPORT_SYMBOL(snd_emu10k1_ptr_read);
54 void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)
62 mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
63 regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
65 if (reg & 0xff000000) {
66 unsigned char size, offset;
68 size = (reg >> 24) & 0x3f;
69 offset = (reg >> 16) & 0x1f;
70 mask = ((1 << size) - 1) << offset;
71 data = (data << offset) & mask;
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);
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);
86 EXPORT_SYMBOL(snd_emu10k1_ptr_write);
88 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu,
93 unsigned int regptr, val;
95 regptr = (reg << 16) | chn;
97 spin_lock_irqsave(&emu->emu_lock, flags);
98 outl(regptr, emu->port + PTR2);
99 val = inl(emu->port + DATA2);
100 spin_unlock_irqrestore(&emu->emu_lock, flags);
104 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu,
112 regptr = (reg << 16) | chn;
114 spin_lock_irqsave(&emu->emu_lock, flags);
115 outl(regptr, emu->port + PTR2);
116 outl(data, emu->port + DATA2);
117 spin_unlock_irqrestore(&emu->emu_lock, flags);
120 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
123 unsigned int reset, set;
124 unsigned int reg, tmp;
128 /* This function is not re-entrant, so protect against it. */
129 spin_lock(&emu->spi_lock);
130 if (emu->card_capabilities->ca0108_chip)
133 /* For other chip types the SPI register
134 * is currently unknown. */
139 /* Only 16bit values allowed */
144 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
145 reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
146 set = reset | 0x10000; /* Set xxx1xxxx */
147 snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
148 tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* write post */
149 snd_emu10k1_ptr20_write(emu, reg, 0, set | data);
151 /* Wait for status bit to return to 0 */
152 for (n = 0; n < 100; n++) {
154 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
155 if (!(tmp & 0x10000)) {
165 snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
166 tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */
169 spin_unlock(&emu->spi_lock);
173 /* The ADC does not support i2c read, so only write is implemented */
174 int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
184 if ((reg > 0x7f) || (value > 0x1ff)) {
185 dev_err(emu->card->dev, "i2c_write: invalid values.\n");
189 /* This function is not re-entrant, so protect against it. */
190 spin_lock(&emu->i2c_lock);
192 tmp = reg << 25 | value << 16;
194 /* This controls the I2C connected to the WM8775 ADC Codec */
195 snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
196 tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */
198 for (retry = 0; retry < 10; retry++) {
199 /* Send the data to i2c */
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);
204 /* Wait till the transaction ends */
207 status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
209 if ((status & I2C_A_ADC_START) == 0)
212 if (timeout > 1000) {
213 dev_warn(emu->card->dev,
214 "emu10k1:I2C:timeout status=0x%x\n",
219 //Read back and see if the transaction is successful
220 if ((status & I2C_A_ADC_ABORT) == 0)
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",
232 spin_unlock(&emu->i2c_lock);
236 void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
240 if (snd_BUG_ON(reg > 0x3f))
242 reg += 0x40; /* 0x40 upwards are registers. */
243 if (snd_BUG_ON(value > 0x3f)) /* 0 to 0x3f are values */
245 spin_lock_irqsave(&emu->emu_lock, flags);
246 outw(reg, emu->port + A_GPIO);
248 outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */
250 outw(value, emu->port + A_GPIO);
252 outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */
253 spin_unlock_irqrestore(&emu->emu_lock, flags);
256 void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
258 // The higest input pin is used as the designated interrupt trigger,
259 // so it needs to be masked out.
260 u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f;
262 if (snd_BUG_ON(reg > 0x3f))
264 reg += 0x40; /* 0x40 upwards are registers. */
265 spin_lock_irqsave(&emu->emu_lock, flags);
266 outw(reg, emu->port + A_GPIO);
268 outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */
270 *value = ((inw(emu->port + A_GPIO) >> 8) & mask);
271 spin_unlock_irqrestore(&emu->emu_lock, flags);
274 /* Each Destination has one and only one Source,
275 * but one Source can feed any number of Destinations simultaneously.
277 void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src)
279 if (snd_BUG_ON(dst & ~0x71f))
281 if (snd_BUG_ON(src & ~0x71f))
283 snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
284 snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
285 snd_emu1010_fpga_write(emu, EMU_HANA_SRCHI, src >> 8);
286 snd_emu1010_fpga_write(emu, EMU_HANA_SRCLO, src & 0x1f);
289 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
294 spin_lock_irqsave(&emu->emu_lock, flags);
295 enable = inl(emu->port + INTE) | intrenb;
296 outl(enable, emu->port + INTE);
297 spin_unlock_irqrestore(&emu->emu_lock, flags);
300 void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
305 spin_lock_irqsave(&emu->emu_lock, flags);
306 enable = inl(emu->port + INTE) & ~intrenb;
307 outl(enable, emu->port + INTE);
308 spin_unlock_irqrestore(&emu->emu_lock, flags);
311 void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
316 spin_lock_irqsave(&emu->emu_lock, flags);
317 if (voicenum >= 32) {
318 outl(CLIEH << 16, emu->port + PTR);
319 val = inl(emu->port + DATA);
320 val |= 1 << (voicenum - 32);
322 outl(CLIEL << 16, emu->port + PTR);
323 val = inl(emu->port + DATA);
324 val |= 1 << voicenum;
326 outl(val, emu->port + DATA);
327 spin_unlock_irqrestore(&emu->emu_lock, flags);
330 void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
335 spin_lock_irqsave(&emu->emu_lock, flags);
336 if (voicenum >= 32) {
337 outl(CLIEH << 16, emu->port + PTR);
338 val = inl(emu->port + DATA);
339 val &= ~(1 << (voicenum - 32));
341 outl(CLIEL << 16, emu->port + PTR);
342 val = inl(emu->port + DATA);
343 val &= ~(1 << voicenum);
345 outl(val, emu->port + DATA);
346 spin_unlock_irqrestore(&emu->emu_lock, flags);
349 void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
353 spin_lock_irqsave(&emu->emu_lock, flags);
354 if (voicenum >= 32) {
355 outl(CLIPH << 16, emu->port + PTR);
356 voicenum = 1 << (voicenum - 32);
358 outl(CLIPL << 16, emu->port + PTR);
359 voicenum = 1 << voicenum;
361 outl(voicenum, emu->port + DATA);
362 spin_unlock_irqrestore(&emu->emu_lock, flags);
365 void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
370 spin_lock_irqsave(&emu->emu_lock, flags);
371 if (voicenum >= 32) {
372 outl(HLIEH << 16, emu->port + PTR);
373 val = inl(emu->port + DATA);
374 val |= 1 << (voicenum - 32);
376 outl(HLIEL << 16, emu->port + PTR);
377 val = inl(emu->port + DATA);
378 val |= 1 << voicenum;
380 outl(val, emu->port + DATA);
381 spin_unlock_irqrestore(&emu->emu_lock, flags);
384 void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
389 spin_lock_irqsave(&emu->emu_lock, flags);
390 if (voicenum >= 32) {
391 outl(HLIEH << 16, emu->port + PTR);
392 val = inl(emu->port + DATA);
393 val &= ~(1 << (voicenum - 32));
395 outl(HLIEL << 16, emu->port + PTR);
396 val = inl(emu->port + DATA);
397 val &= ~(1 << voicenum);
399 outl(val, emu->port + DATA);
400 spin_unlock_irqrestore(&emu->emu_lock, flags);
403 void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
407 spin_lock_irqsave(&emu->emu_lock, flags);
408 if (voicenum >= 32) {
409 outl(HLIPH << 16, emu->port + PTR);
410 voicenum = 1 << (voicenum - 32);
412 outl(HLIPL << 16, emu->port + PTR);
413 voicenum = 1 << voicenum;
415 outl(voicenum, emu->port + DATA);
416 spin_unlock_irqrestore(&emu->emu_lock, flags);
419 void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
424 spin_lock_irqsave(&emu->emu_lock, flags);
425 if (voicenum >= 32) {
426 outl(SOLEH << 16, emu->port + PTR);
427 sol = inl(emu->port + DATA);
428 sol |= 1 << (voicenum - 32);
430 outl(SOLEL << 16, emu->port + PTR);
431 sol = inl(emu->port + DATA);
432 sol |= 1 << voicenum;
434 outl(sol, emu->port + DATA);
435 spin_unlock_irqrestore(&emu->emu_lock, flags);
438 void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
443 spin_lock_irqsave(&emu->emu_lock, flags);
444 if (voicenum >= 32) {
445 outl(SOLEH << 16, emu->port + PTR);
446 sol = inl(emu->port + DATA);
447 sol &= ~(1 << (voicenum - 32));
449 outl(SOLEL << 16, emu->port + PTR);
450 sol = inl(emu->port + DATA);
451 sol &= ~(1 << voicenum);
453 outl(sol, emu->port + DATA);
454 spin_unlock_irqrestore(&emu->emu_lock, flags);
457 void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait)
459 volatile unsigned count;
460 unsigned int newtime = 0, curtime;
462 curtime = inl(emu->port + WC) >> 6;
465 while (count++ < 16384) {
466 newtime = inl(emu->port + WC) >> 6;
467 if (newtime != curtime)
476 unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
478 struct snd_emu10k1 *emu = ac97->private_data;
482 spin_lock_irqsave(&emu->emu_lock, flags);
483 outb(reg, emu->port + AC97ADDRESS);
484 val = inw(emu->port + AC97DATA);
485 spin_unlock_irqrestore(&emu->emu_lock, flags);
489 void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data)
491 struct snd_emu10k1 *emu = ac97->private_data;
494 spin_lock_irqsave(&emu->emu_lock, flags);
495 outb(reg, emu->port + AC97ADDRESS);
496 outw(data, emu->port + AC97DATA);
497 spin_unlock_irqrestore(&emu->emu_lock, flags);
501 * convert rate to pitch
504 unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate)
506 static const u32 logMagTable[128] = {
507 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
508 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
509 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
510 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
511 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
512 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
513 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
514 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
515 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
516 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
517 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
518 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
519 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
520 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
521 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
522 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
524 static const char logSlopeTable[128] = {
525 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
526 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
527 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
528 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
529 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
530 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
531 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
532 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
533 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
534 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
535 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
536 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
537 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
538 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
539 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
540 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
545 return 0; /* Bail out if no leading "1" */
546 rate *= 11185; /* Scale 48000 to 0x20002380 */
547 for (i = 31; i > 0; i--) {
548 if (rate & 0x80000000) { /* Detect leading "1" */
549 return (((unsigned int) (i - 15) << 20) +
550 logMagTable[0x7f & (rate >> 24)] +
551 (0x7f & (rate >> 17)) *
552 logSlopeTable[0x7f & (rate >> 24)]);
557 return 0; /* Should never reach this point */