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 + PTR2); 99 val = inl(emu->port + DATA2); 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 + PTR2); 116 outl(data, emu->port + DATA2); 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 = P17V_SPI; 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 void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value) 237 { 238 unsigned long flags; 239 240 if (snd_BUG_ON(reg > 0x3f)) 241 return; 242 reg += 0x40; /* 0x40 upwards are registers. */ 243 if (snd_BUG_ON(value > 0x3f)) /* 0 to 0x3f are values */ 244 return; 245 spin_lock_irqsave(&emu->emu_lock, flags); 246 outw(reg, emu->port + A_GPIO); 247 udelay(10); 248 outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ 249 udelay(10); 250 outw(value, emu->port + A_GPIO); 251 udelay(10); 252 outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ 253 spin_unlock_irqrestore(&emu->emu_lock, flags); 254 } 255 256 void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value) 257 { 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; 261 unsigned long flags; 262 if (snd_BUG_ON(reg > 0x3f)) 263 return; 264 reg += 0x40; /* 0x40 upwards are registers. */ 265 spin_lock_irqsave(&emu->emu_lock, flags); 266 outw(reg, emu->port + A_GPIO); 267 udelay(10); 268 outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ 269 udelay(10); 270 *value = ((inw(emu->port + A_GPIO) >> 8) & mask); 271 spin_unlock_irqrestore(&emu->emu_lock, flags); 272 } 273 274 /* Each Destination has one and only one Source, 275 * but one Source can feed any number of Destinations simultaneously. 276 */ 277 void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src) 278 { 279 if (snd_BUG_ON(dst & ~0x71f)) 280 return; 281 if (snd_BUG_ON(src & ~0x71f)) 282 return; 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); 287 } 288 289 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) 290 { 291 unsigned long flags; 292 unsigned int enable; 293 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); 298 } 299 300 void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb) 301 { 302 unsigned long flags; 303 unsigned int enable; 304 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); 309 } 310 311 void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum) 312 { 313 unsigned long flags; 314 unsigned int val; 315 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); 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 if (voicenum >= 32) { 337 outl(CLIEH << 16, emu->port + PTR); 338 val = inl(emu->port + DATA); 339 val &= ~(1 << (voicenum - 32)); 340 } else { 341 outl(CLIEL << 16, emu->port + PTR); 342 val = inl(emu->port + DATA); 343 val &= ~(1 << voicenum); 344 } 345 outl(val, emu->port + DATA); 346 spin_unlock_irqrestore(&emu->emu_lock, flags); 347 } 348 349 void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) 350 { 351 unsigned long flags; 352 353 spin_lock_irqsave(&emu->emu_lock, flags); 354 if (voicenum >= 32) { 355 outl(CLIPH << 16, emu->port + PTR); 356 voicenum = 1 << (voicenum - 32); 357 } else { 358 outl(CLIPL << 16, emu->port + PTR); 359 voicenum = 1 << voicenum; 360 } 361 outl(voicenum, emu->port + DATA); 362 spin_unlock_irqrestore(&emu->emu_lock, flags); 363 } 364 365 void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum) 366 { 367 unsigned long flags; 368 unsigned int val; 369 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); 375 } else { 376 outl(HLIEL << 16, emu->port + PTR); 377 val = inl(emu->port + DATA); 378 val |= 1 << voicenum; 379 } 380 outl(val, emu->port + DATA); 381 spin_unlock_irqrestore(&emu->emu_lock, flags); 382 } 383 384 void snd_emu10k1_voice_half_loop_intr_disable(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 if (voicenum >= 32) { 391 outl(HLIEH << 16, emu->port + PTR); 392 val = inl(emu->port + DATA); 393 val &= ~(1 << (voicenum - 32)); 394 } else { 395 outl(HLIEL << 16, emu->port + PTR); 396 val = inl(emu->port + DATA); 397 val &= ~(1 << voicenum); 398 } 399 outl(val, emu->port + DATA); 400 spin_unlock_irqrestore(&emu->emu_lock, flags); 401 } 402 403 void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) 404 { 405 unsigned long flags; 406 407 spin_lock_irqsave(&emu->emu_lock, flags); 408 if (voicenum >= 32) { 409 outl(HLIPH << 16, emu->port + PTR); 410 voicenum = 1 << (voicenum - 32); 411 } else { 412 outl(HLIPL << 16, emu->port + PTR); 413 voicenum = 1 << voicenum; 414 } 415 outl(voicenum, emu->port + DATA); 416 spin_unlock_irqrestore(&emu->emu_lock, flags); 417 } 418 419 void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum) 420 { 421 unsigned long flags; 422 unsigned int sol; 423 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); 429 } else { 430 outl(SOLEL << 16, emu->port + PTR); 431 sol = inl(emu->port + DATA); 432 sol |= 1 << voicenum; 433 } 434 outl(sol, emu->port + DATA); 435 spin_unlock_irqrestore(&emu->emu_lock, flags); 436 } 437 438 void snd_emu10k1_voice_clear_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 if (voicenum >= 32) { 445 outl(SOLEH << 16, emu->port + PTR); 446 sol = inl(emu->port + DATA); 447 sol &= ~(1 << (voicenum - 32)); 448 } else { 449 outl(SOLEL << 16, emu->port + PTR); 450 sol = inl(emu->port + DATA); 451 sol &= ~(1 << voicenum); 452 } 453 outl(sol, emu->port + DATA); 454 spin_unlock_irqrestore(&emu->emu_lock, flags); 455 } 456 457 void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait) 458 { 459 volatile unsigned count; 460 unsigned int newtime = 0, curtime; 461 462 curtime = inl(emu->port + WC) >> 6; 463 while (wait-- > 0) { 464 count = 0; 465 while (count++ < 16384) { 466 newtime = inl(emu->port + WC) >> 6; 467 if (newtime != curtime) 468 break; 469 } 470 if (count > 16384) 471 break; 472 curtime = newtime; 473 } 474 } 475 476 unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg) 477 { 478 struct snd_emu10k1 *emu = ac97->private_data; 479 unsigned long flags; 480 unsigned short val; 481 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); 486 return val; 487 } 488 489 void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data) 490 { 491 struct snd_emu10k1 *emu = ac97->private_data; 492 unsigned long flags; 493 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); 498 } 499 500 /* 501 * convert rate to pitch 502 */ 503 504 unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate) 505 { 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 523 }; 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 541 }; 542 int i; 543 544 if (rate == 0) 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)]); 553 } 554 rate <<= 1; 555 } 556 557 return 0; /* Should never reach this point */ 558 } 559 560