Ignore:
Timestamp:
Apr 19, 2025, 8:08:37 PM (4 months ago)
Author:
David Azarewicz
Message:

Merge in changes from 6.6-LTS branch.
Fixed additional 25+ problems.

Location:
GPL/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • GPL/trunk

  • GPL/trunk/alsa-kernel/pci/emu10k1/io.c

    r679 r772  
    22/*
    33 *  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>
    47 *                   Creative Labs, Inc.
     8 *
    59 *  Routines for control of EMU10K1 chips
    6  *
    7  *  BUGS:
    8  *    --
    9  *
    10  *  TODO:
    11  *    --
    1210 */
    1311
     
    1917#include "p17v.h"
    2018
     19static 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
    2131unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
    2232{
     
    2535        unsigned int mask;
    2636
    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);
    2945
    3046        if (reg & 0xff000000) {
     
    3349                size = (reg >> 24) & 0x3f;
    3450                offset = (reg >> 16) & 0x1f;
    35                 mask = ((1 << size) - 1) << offset;
     51                mask = (1 << size) - 1;
    3652               
    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 {
    4855                return val;
    4956        }
     
    5865        unsigned int mask;
    5966
    60         if (snd_BUG_ON(!emu))
     67        regptr = (reg << 16) | chn;
     68        if (!check_ptr_reg(emu, regptr))
    6169                return;
    62         mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
    63         regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
    6470
    6571        if (reg & 0xff000000) {
     
    6874                size = (reg >> 24) & 0x3f;
    6975                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;
    7281
    7382                spin_lock_irqsave(&emu->emu_lock, flags);
    7483                outl(regptr, emu->port + PTR);
    7584                data |= inl(emu->port + DATA) & ~mask;
    76                 outl(data, emu->port + DATA);
    77                 spin_unlock_irqrestore(&emu->emu_lock, flags);         
    7885        } else {
    7986                spin_lock_irqsave(&emu->emu_lock, flags);
    8087                outl(regptr, emu->port + PTR);
     88        }
     89        outl(data, emu->port + DATA);
     90        spin_unlock_irqrestore(&emu->emu_lock, flags);
     91}
     92
     93EXPORT_SYMBOL(snd_emu10k1_ptr_write);
     94
     95void 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);
    81118                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
     124EXPORT_SYMBOL(snd_emu10k1_ptr_write_multiple);
    87125
    88126unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu,
     
    96134
    97135        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);
    100138        spin_unlock_irqrestore(&emu->emu_lock, flags);
    101139        return val;
     
    113151
    114152        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);
    117155        spin_unlock_irqrestore(&emu->emu_lock, flags);
    118156}
     
    129167        spin_lock(&emu->spi_lock);
    130168        if (emu->card_capabilities->ca0108_chip)
    131                 reg = 0x3c; /* PTR20, reg 0x3c */
     169                reg = P17V_SPI;
    132170        else {
    133171                /* For other chip types the SPI register
     
    234272}
    235273
    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;
     274static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32 value)
     275{
     276        if (snd_BUG_ON(reg > 0x3f))
     277                return;
    242278        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);
    247282        udelay(10);
    248         outl(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. */
    249284        udelay(10);
    250         outl(value, emu->port + A_IOCFG);
     285        outw(value, emu->port + A_GPIO);
    251286        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
     291void 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
     300static 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;
    263309        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);
    266311        udelay(10);
    267         outl(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. */
    268313        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
     317void 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);
    273324}
    274325
     
    276327 * but one Source can feed any number of Destinations simultaneously.
    277328 */
    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;
     329void 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
     345u32 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
     361int 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
     394void 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);
    286431}
    287432
     
    314459
    315460        spin_lock_irqsave(&emu->emu_lock, flags);
    316         /* voice interrupt */
    317461        if (voicenum >= 32) {
    318462                outl(CLIEH << 16, emu->port + PTR);
     
    334478
    335479        spin_lock_irqsave(&emu->emu_lock, flags);
    336         /* voice interrupt */
    337480        if (voicenum >= 32) {
    338481                outl(CLIEH << 16, emu->port + PTR);
     
    353496
    354497        spin_lock_irqsave(&emu->emu_lock, flags);
    355         /* voice interrupt */
    356498        if (voicenum >= 32) {
    357499                outl(CLIPH << 16, emu->port + PTR);
     
    371513
    372514        spin_lock_irqsave(&emu->emu_lock, flags);
    373         /* voice interrupt */
    374515        if (voicenum >= 32) {
    375516                outl(HLIEH << 16, emu->port + PTR);
     
    391532
    392533        spin_lock_irqsave(&emu->emu_lock, flags);
    393         /* voice interrupt */
    394534        if (voicenum >= 32) {
    395535                outl(HLIEH << 16, emu->port + PTR);
     
    410550
    411551        spin_lock_irqsave(&emu->emu_lock, flags);
    412         /* voice interrupt */
    413552        if (voicenum >= 32) {
    414553                outl(HLIPH << 16, emu->port + PTR);
     
    422561}
    423562
     563#if 0
    424564void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
    425565{
     
    428568
    429569        spin_lock_irqsave(&emu->emu_lock, flags);
    430         /* voice interrupt */
    431570        if (voicenum >= 32) {
    432571                outl(SOLEH << 16, emu->port + PTR);
     
    448587
    449588        spin_lock_irqsave(&emu->emu_lock, flags);
    450         /* voice interrupt */
    451589        if (voicenum >= 32) {
    452590                outl(SOLEH << 16, emu->port + PTR);
     
    460598        outl(sol, emu->port + DATA);
    461599        spin_unlock_irqrestore(&emu->emu_lock, flags);
     600}
     601#endif
     602
     603void 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
     615void 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
     627int 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;
    462683}
    463684
     
    504725        spin_unlock_irqrestore(&emu->emu_lock, flags);
    505726}
    506 
    507 /*
    508  *  convert rate to pitch
    509  */
    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, 0xfe8df
    530         };
    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, 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 
Note: See TracChangeset for help on using the changeset viewer.