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