Changeset 772 for GPL/trunk/alsa-kernel/pci/emu10k1/io.c
- Timestamp:
- Apr 19, 2025, 8:08:37 PM (4 months ago)
- Location:
- GPL/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
GPL/trunk
- Property svn:mergeinfo changed
/GPL/branches/uniaud32-6.6-LTS (added) merged: 765,768-769 /GPL/branches/uniaud32-exp (added) merged: 735-741,743-744,748-751,753-760,762-764 /GPL/branches/uniaud32-next merged: 718-734
- Property svn:mergeinfo changed
-
GPL/trunk/alsa-kernel/pci/emu10k1/io.c
r679 r772 2 2 /* 3 3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 4 * Lee Revell <rlrevell@joe-job.com> 5 * James Courtier-Dutton <James@superbug.co.uk> 6 * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> 4 7 * Creative Labs, Inc. 8 * 5 9 * Routines for control of EMU10K1 chips 6 *7 * BUGS:8 * --9 *10 * TODO:11 * --12 10 */ 13 11 … … 19 17 #include "p17v.h" 20 18 19 static inline bool check_ptr_reg(struct snd_emu10k1 *emu, unsigned int reg) 20 { 21 if (snd_BUG_ON(!emu)) 22 return false; 23 if (snd_BUG_ON(reg & (emu->audigy ? (0xffff0000 & ~A_PTR_ADDRESS_MASK) 24 : (0xffff0000 & ~PTR_ADDRESS_MASK)))) 25 return false; 26 if (snd_BUG_ON(reg & 0x0000ffff & ~PTR_CHANNELNUM_MASK)) 27 return false; 28 return true; 29 } 30 21 31 unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn) 22 32 { … … 25 35 unsigned int mask; 26 36 27 mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; 28 regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); 37 regptr = (reg << 16) | chn; 38 if (!check_ptr_reg(emu, regptr)) 39 return 0; 40 41 spin_lock_irqsave(&emu->emu_lock, flags); 42 outl(regptr, emu->port + PTR); 43 val = inl(emu->port + DATA); 44 spin_unlock_irqrestore(&emu->emu_lock, flags); 29 45 30 46 if (reg & 0xff000000) { … … 33 49 size = (reg >> 24) & 0x3f; 34 50 offset = (reg >> 16) & 0x1f; 35 mask = ( (1 << size) - 1) << offset;51 mask = (1 << size) - 1; 36 52 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); 53 return (val >> offset) & mask; 54 } else { 48 55 return val; 49 56 } … … 58 65 unsigned int mask; 59 66 60 if (snd_BUG_ON(!emu)) 67 regptr = (reg << 16) | chn; 68 if (!check_ptr_reg(emu, regptr)) 61 69 return; 62 mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;63 regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);64 70 65 71 if (reg & 0xff000000) { … … 68 74 size = (reg >> 24) & 0x3f; 69 75 offset = (reg >> 16) & 0x1f; 70 mask = ((1 << size) - 1) << offset; 71 data = (data << offset) & mask; 76 mask = (1 << size) - 1; 77 if (snd_BUG_ON(data & ~mask)) 78 return; 79 mask <<= offset; 80 data <<= offset; 72 81 73 82 spin_lock_irqsave(&emu->emu_lock, flags); 74 83 outl(regptr, emu->port + PTR); 75 84 data |= inl(emu->port + DATA) & ~mask; 76 outl(data, emu->port + DATA);77 spin_unlock_irqrestore(&emu->emu_lock, flags);78 85 } else { 79 86 spin_lock_irqsave(&emu->emu_lock, flags); 80 87 outl(regptr, emu->port + PTR); 88 } 89 outl(data, emu->port + DATA); 90 spin_unlock_irqrestore(&emu->emu_lock, flags); 91 } 92 93 EXPORT_SYMBOL(snd_emu10k1_ptr_write); 94 95 void snd_emu10k1_ptr_write_multiple(struct snd_emu10k1 *emu, unsigned int chn, ...) 96 { 97 va_list va; 98 u32 addr_mask; 99 unsigned long flags; 100 101 if (snd_BUG_ON(!emu)) 102 return; 103 if (snd_BUG_ON(chn & ~PTR_CHANNELNUM_MASK)) 104 return; 105 addr_mask = ~((emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK) >> 16); 106 107 va_start(va, chn); 108 spin_lock_irqsave(&emu->emu_lock, flags); 109 for (;;) { 110 u32 data; 111 u32 reg = va_arg(va, u32); 112 if (reg == REGLIST_END) 113 break; 114 data = va_arg(va, u32); 115 if (snd_BUG_ON(reg & addr_mask)) // Only raw registers supported here 116 continue; 117 outl((reg << 16) | chn, emu->port + PTR); 81 118 outl(data, emu->port + DATA); 82 spin_unlock_irqrestore(&emu->emu_lock, flags); 83 } 84 } 85 86 EXPORT_SYMBOL(snd_emu10k1_ptr_write); 119 } 120 spin_unlock_irqrestore(&emu->emu_lock, flags); 121 va_end(va); 122 } 123 124 EXPORT_SYMBOL(snd_emu10k1_ptr_write_multiple); 87 125 88 126 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, … … 96 134 97 135 spin_lock_irqsave(&emu->emu_lock, flags); 98 outl(regptr, emu->port + 0x20 + PTR);99 val = inl(emu->port + 0x20 + DATA);136 outl(regptr, emu->port + PTR2); 137 val = inl(emu->port + DATA2); 100 138 spin_unlock_irqrestore(&emu->emu_lock, flags); 101 139 return val; … … 113 151 114 152 spin_lock_irqsave(&emu->emu_lock, flags); 115 outl(regptr, emu->port + 0x20 + PTR);116 outl(data, emu->port + 0x20 + DATA);153 outl(regptr, emu->port + PTR2); 154 outl(data, emu->port + DATA2); 117 155 spin_unlock_irqrestore(&emu->emu_lock, flags); 118 156 } … … 129 167 spin_lock(&emu->spi_lock); 130 168 if (emu->card_capabilities->ca0108_chip) 131 reg = 0x3c; /* PTR20, reg 0x3c */169 reg = P17V_SPI; 132 170 else { 133 171 /* For other chip types the SPI register … … 234 272 } 235 273 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; 274 static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32 value) 275 { 276 if (snd_BUG_ON(reg > 0x3f)) 277 return; 242 278 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); 279 if (snd_BUG_ON(value > 0x3f)) /* 0 to 0x3f are values */ 280 return; 281 outw(reg, emu->port + A_GPIO); 247 282 udelay(10); 248 out l(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */283 outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ 249 284 udelay(10); 250 out l(value, emu->port + A_IOCFG);285 outw(value, emu->port + A_GPIO); 251 286 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; 287 outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ 288 udelay(10); 289 } 290 291 void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value) 292 { 293 unsigned long flags; 294 295 spin_lock_irqsave(&emu->emu_lock, flags); 296 snd_emu1010_fpga_write_locked(emu, reg, value); 297 spin_unlock_irqrestore(&emu->emu_lock, flags); 298 } 299 300 static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *value) 301 { 302 // The higest input pin is used as the designated interrupt trigger, 303 // so it needs to be masked out. 304 // But note that any other input pin change will also cause an IRQ, 305 // so using this function often causes an IRQ as a side effect. 306 u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f; 307 if (snd_BUG_ON(reg > 0x3f)) 308 return; 263 309 reg += 0x40; /* 0x40 upwards are registers. */ 264 spin_lock_irqsave(&emu->emu_lock, flags); 265 outl(reg, emu->port + A_IOCFG); 310 outw(reg, emu->port + A_GPIO); 266 311 udelay(10); 267 out l(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */312 outw(reg | 0x80, emu->port + A_GPIO); /* High bit clocks the value into the fpga. */ 268 313 udelay(10); 269 *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f); 270 spin_unlock_irqrestore(&emu->emu_lock, flags); 271 272 return 0; 314 *value = ((inw(emu->port + A_GPIO) >> 8) & mask); 315 } 316 317 void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value) 318 { 319 unsigned long flags; 320 321 spin_lock_irqsave(&emu->emu_lock, flags); 322 snd_emu1010_fpga_read_locked(emu, reg, value); 323 spin_unlock_irqrestore(&emu->emu_lock, flags); 273 324 } 274 325 … … 276 327 * but one Source can feed any number of Destinations simultaneously. 277 328 */ 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; 329 void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src) 330 { 331 unsigned long flags; 332 333 if (snd_BUG_ON(dst & ~0x71f)) 334 return; 335 if (snd_BUG_ON(src & ~0x71f)) 336 return; 337 spin_lock_irqsave(&emu->emu_lock, flags); 338 snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8); 339 snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f); 340 snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCHI, src >> 8); 341 snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCLO, src & 0x1f); 342 spin_unlock_irqrestore(&emu->emu_lock, flags); 343 } 344 345 u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst) 346 { 347 unsigned long flags; 348 u32 hi, lo; 349 350 if (snd_BUG_ON(dst & ~0x71f)) 351 return 0; 352 spin_lock_irqsave(&emu->emu_lock, flags); 353 snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8); 354 snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f); 355 snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCHI, &hi); 356 snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCLO, &lo); 357 spin_unlock_irqrestore(&emu->emu_lock, flags); 358 return (hi << 8) | lo; 359 } 360 361 int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src) 362 { 363 u32 reg_lo, reg_hi, value, value2; 364 365 switch (src) { 366 case EMU_HANA_WCLOCK_HANA_SPDIF_IN: 367 snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &value); 368 if (value & EMU_HANA_SPDIF_MODE_RX_INVALID) 369 return 0; 370 reg_lo = EMU_HANA_WC_SPDIF_LO; 371 reg_hi = EMU_HANA_WC_SPDIF_HI; 372 break; 373 case EMU_HANA_WCLOCK_HANA_ADAT_IN: 374 reg_lo = EMU_HANA_WC_ADAT_LO; 375 reg_hi = EMU_HANA_WC_ADAT_HI; 376 break; 377 case EMU_HANA_WCLOCK_SYNC_BNC: 378 reg_lo = EMU_HANA_WC_BNC_LO; 379 reg_hi = EMU_HANA_WC_BNC_HI; 380 break; 381 case EMU_HANA_WCLOCK_2ND_HANA: 382 reg_lo = EMU_HANA2_WC_SPDIF_LO; 383 reg_hi = EMU_HANA2_WC_SPDIF_HI; 384 break; 385 default: 386 return 0; 387 } 388 snd_emu1010_fpga_read(emu, reg_hi, &value); 389 snd_emu1010_fpga_read(emu, reg_lo, &value2); 390 // FIXME: The /4 is valid for 0404b, but contradicts all other info. 391 return 0x1770000 / 4 / (((value << 5) | value2) + 1); 392 } 393 394 void snd_emu1010_update_clock(struct snd_emu10k1 *emu) 395 { 396 int clock; 397 u32 leds; 398 399 switch (emu->emu1010.wclock) { 400 case EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X: 401 clock = 44100; 402 leds = EMU_HANA_DOCK_LEDS_2_44K; 403 break; 404 case EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X: 405 clock = 48000; 406 leds = EMU_HANA_DOCK_LEDS_2_48K; 407 break; 408 default: 409 clock = snd_emu1010_get_raw_rate( 410 emu, emu->emu1010.wclock & EMU_HANA_WCLOCK_SRC_MASK); 411 // The raw rate reading is rather coarse (it cannot accurately 412 // represent 44.1 kHz) and fluctuates slightly. Luckily, the 413 // clock comes from digital inputs, which use standardized rates. 414 // So we round to the closest standard rate and ignore discrepancies. 415 if (clock < 46000) { 416 clock = 44100; 417 leds = EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_44K; 418 } else { 419 clock = 48000; 420 leds = EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_48K; 421 } 422 break; 423 } 424 emu->emu1010.word_clock = clock; 425 426 // FIXME: this should probably represent the AND of all currently 427 // used sources' lock status. But we don't know how to get that ... 428 leds |= EMU_HANA_DOCK_LEDS_2_LOCK; 429 430 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, leds); 286 431 } 287 432 … … 314 459 315 460 spin_lock_irqsave(&emu->emu_lock, flags); 316 /* voice interrupt */317 461 if (voicenum >= 32) { 318 462 outl(CLIEH << 16, emu->port + PTR); … … 334 478 335 479 spin_lock_irqsave(&emu->emu_lock, flags); 336 /* voice interrupt */337 480 if (voicenum >= 32) { 338 481 outl(CLIEH << 16, emu->port + PTR); … … 353 496 354 497 spin_lock_irqsave(&emu->emu_lock, flags); 355 /* voice interrupt */356 498 if (voicenum >= 32) { 357 499 outl(CLIPH << 16, emu->port + PTR); … … 371 513 372 514 spin_lock_irqsave(&emu->emu_lock, flags); 373 /* voice interrupt */374 515 if (voicenum >= 32) { 375 516 outl(HLIEH << 16, emu->port + PTR); … … 391 532 392 533 spin_lock_irqsave(&emu->emu_lock, flags); 393 /* voice interrupt */394 534 if (voicenum >= 32) { 395 535 outl(HLIEH << 16, emu->port + PTR); … … 410 550 411 551 spin_lock_irqsave(&emu->emu_lock, flags); 412 /* voice interrupt */413 552 if (voicenum >= 32) { 414 553 outl(HLIPH << 16, emu->port + PTR); … … 422 561 } 423 562 563 #if 0 424 564 void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum) 425 565 { … … 428 568 429 569 spin_lock_irqsave(&emu->emu_lock, flags); 430 /* voice interrupt */431 570 if (voicenum >= 32) { 432 571 outl(SOLEH << 16, emu->port + PTR); … … 448 587 449 588 spin_lock_irqsave(&emu->emu_lock, flags); 450 /* voice interrupt */451 589 if (voicenum >= 32) { 452 590 outl(SOLEH << 16, emu->port + PTR); … … 460 598 outl(sol, emu->port + DATA); 461 599 spin_unlock_irqrestore(&emu->emu_lock, flags); 600 } 601 #endif 602 603 void snd_emu10k1_voice_set_loop_stop_multiple(struct snd_emu10k1 *emu, u64 voices) 604 { 605 unsigned long flags; 606 607 spin_lock_irqsave(&emu->emu_lock, flags); 608 outl(SOLEL << 16, emu->port + PTR); 609 outl(inl(emu->port + DATA) | (u32)voices, emu->port + DATA); 610 outl(SOLEH << 16, emu->port + PTR); 611 outl(inl(emu->port + DATA) | (u32)(voices >> 32), emu->port + DATA); 612 spin_unlock_irqrestore(&emu->emu_lock, flags); 613 } 614 615 void snd_emu10k1_voice_clear_loop_stop_multiple(struct snd_emu10k1 *emu, u64 voices) 616 { 617 unsigned long flags; 618 619 spin_lock_irqsave(&emu->emu_lock, flags); 620 outl(SOLEL << 16, emu->port + PTR); 621 outl(inl(emu->port + DATA) & (u32)~voices, emu->port + DATA); 622 outl(SOLEH << 16, emu->port + PTR); 623 outl(inl(emu->port + DATA) & (u32)(~voices >> 32), emu->port + DATA); 624 spin_unlock_irqrestore(&emu->emu_lock, flags); 625 } 626 627 int snd_emu10k1_voice_clear_loop_stop_multiple_atomic(struct snd_emu10k1 *emu, u64 voices) 628 { 629 unsigned long flags; 630 u32 soll, solh; 631 int ret = -EIO; 632 633 spin_lock_irqsave(&emu->emu_lock, flags); 634 635 outl(SOLEL << 16, emu->port + PTR); 636 soll = inl(emu->port + DATA); 637 outl(SOLEH << 16, emu->port + PTR); 638 solh = inl(emu->port + DATA); 639 640 soll &= (u32)~voices; 641 solh &= (u32)(~voices >> 32); 642 643 for (int tries = 0; tries < 1000; tries++) { 644 const u32 quart = 1U << (REG_SIZE(WC_CURRENTCHANNEL) - 2); 645 // First we wait for the third quarter of the sample cycle ... 646 u32 wc = inl(emu->port + WC); 647 u32 cc = REG_VAL_GET(WC_CURRENTCHANNEL, wc); 648 if (cc >= quart * 2 && cc < quart * 3) { 649 // ... and release the low voices, while the high ones are serviced. 650 outl(SOLEL << 16, emu->port + PTR); 651 outl(soll, emu->port + DATA); 652 // Then we wait for the first quarter of the next sample cycle ... 653 for (; tries < 1000; tries++) { 654 cc = REG_VAL_GET(WC_CURRENTCHANNEL, inl(emu->port + WC)); 655 if (cc < quart) 656 goto good; 657 // We will block for 10+ us with interrupts disabled. This is 658 // not nice at all, but necessary for reasonable reliability. 659 udelay(1); 660 } 661 break; 662 good: 663 // ... and release the high voices, while the low ones are serviced. 664 outl(SOLEH << 16, emu->port + PTR); 665 outl(solh, emu->port + DATA); 666 // Finally we verify that nothing interfered in fact. 667 if (REG_VAL_GET(WC_SAMPLECOUNTER, inl(emu->port + WC)) == 668 ((REG_VAL_GET(WC_SAMPLECOUNTER, wc) + 1) & REG_MASK0(WC_SAMPLECOUNTER))) { 669 ret = 0; 670 } else { 671 ret = -EAGAIN; 672 } 673 break; 674 } 675 // Don't block for too long 676 spin_unlock_irqrestore(&emu->emu_lock, flags); 677 udelay(1); 678 spin_lock_irqsave(&emu->emu_lock, flags); 679 } 680 681 spin_unlock_irqrestore(&emu->emu_lock, flags); 682 return ret; 462 683 } 463 684 … … 504 725 spin_unlock_irqrestore(&emu->emu_lock, flags); 505 726 } 506 507 /*508 * convert rate to pitch509 */510 511 unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate)512 {513 static const 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, 0xfe8df530 };531 static const 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, 0x2f548 };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
Note:
See TracChangeset
for help on using the changeset viewer.