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