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