a3f1de7e5feefb2cf6a9b0555b52f1e48bc30866
[muen/linux.git] / sound / pci / emu10k1 / io.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4  *                   Creative Labs, Inc.
5  *  Routines for control of EMU10K1 chips
6  *
7  *  BUGS:
8  *    --
9  *
10  *  TODO:
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         /* This function is not re-entrant, so protect against it. */
129         spin_lock(&emu->spi_lock);
130         if (emu->card_capabilities->ca0108_chip)
131                 reg = 0x3c; /* PTR20, reg 0x3c */
132         else {
133                 /* For other chip types the SPI register
134                  * is currently unknown. */
135                 err = 1;
136                 goto spi_write_exit;
137         }
138         if (data > 0xffff) {
139                 /* Only 16bit values allowed */
140                 err = 1;
141                 goto spi_write_exit;
142         }
143
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);
150         result = 1;
151         /* Wait for status bit to return to 0 */
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                 /* Timed out */
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); /* Write post */
167         err = 0;
168 spi_write_exit:
169         spin_unlock(&emu->spi_lock);
170         return err;
171 }
172
173 /* The ADC does not support i2c read, so only write is implemented */
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         /* This function is not re-entrant, so protect against it. */
190         spin_lock(&emu->i2c_lock);
191
192         tmp = reg << 25 | value << 16;
193
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 */
197
198         for (retry = 0; retry < 10; retry++) {
199                 /* Send the data to i2c */
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                 /* Wait till the transaction ends */
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                 //Read back and see if the transaction is successful
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                 /* dump_stack(); */
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; /* 0x40 upwards are registers. */
243         if (value > 0x3f) /* 0 to 0x3f are values */
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);  /* High bit clocks the value into the fpga. */
249         udelay(10);
250         outl(value, emu->port + A_IOCFG);
251         udelay(10);
252         outl(value | 0x80 , emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
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; /* 0x40 upwards are registers. */
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);  /* High bit clocks the value into the fpga. */
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 /* Each Destination has one and only one Source,
276  * but one Source can feed any number of Destinations simultaneously.
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         /* voice interrupt */
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         /* voice interrupt */
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         /* voice interrupt */
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         /* voice interrupt */
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         /* voice interrupt */
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         /* voice interrupt */
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         /* voice interrupt */
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         /* voice interrupt */
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  *  convert rate to pitch
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;       /* Bail out if no leading "1" */
553         rate *= 11185;          /* Scale 48000 to 0x20002380 */
554         for (i = 31; i > 0; i--) {
555                 if (rate & 0x80000000) {        /* Detect leading "1" */
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;               /* Should never reach this point */
565 }
566