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