diff options
author | Christoph Pfister <christophpfister@bluemail.ch> | 2006-05-22 09:32:04 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-06-25 01:00:08 -0400 |
commit | da22d0e758bf011be5921421bf490ce69c387784 (patch) | |
tree | 87923892b62d43df67913d50ecb3424a8ee2facd | |
parent | 5c1208ba457a1668c81868060c08496a2d053be0 (diff) |
V4L/DVB (3988): Add math routines required by DVB demods
Signed-off-by: Christoph Pfister <christophpfister@bluemail.ch>
Signed-off-by: Manu Abraham <manu@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/dvb/dvb-core/Makefile | 6 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_math.c | 144 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_math.h | 58 |
3 files changed, 205 insertions, 3 deletions
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile index 7adb50c1e8eb..11054657fdb5 100644 --- a/drivers/media/dvb/dvb-core/Makefile +++ b/drivers/media/dvb/dvb-core/Makefile | |||
@@ -2,8 +2,8 @@ | |||
2 | # Makefile for the kernel DVB device drivers. | 2 | # Makefile for the kernel DVB device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ | 5 | dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ |
6 | dvb_ca_en50221.o dvb_frontend.o \ | 6 | dvb_ca_en50221.o dvb_frontend.o \ |
7 | dvb_net.o dvb_ringbuffer.o | 7 | dvb_net.o dvb_ringbuffer.o dvb_math.o |
8 | 8 | ||
9 | obj-$(CONFIG_DVB_CORE) += dvb-core.o | 9 | obj-$(CONFIG_DVB_CORE) += dvb-core.o |
diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c new file mode 100644 index 000000000000..db6d6b7f77a8 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_math.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * dvb-math provides some complex fixed-point math | ||
3 | * operations shared between the dvb related stuff | ||
4 | * | ||
5 | * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as | ||
9 | * published by the Free Software Foundation; either version 2.1 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/bitops.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <asm/bug.h> | ||
25 | #include "dvb_math.h" | ||
26 | |||
27 | const unsigned short logtable[256] = { | ||
28 | 0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7, | ||
29 | 0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508, | ||
30 | 0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6, | ||
31 | 0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37, | ||
32 | 0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f, | ||
33 | 0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41, | ||
34 | 0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1, | ||
35 | 0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142, | ||
36 | 0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68, | ||
37 | 0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355, | ||
38 | 0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c, | ||
39 | 0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490, | ||
40 | 0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3, | ||
41 | 0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507, | ||
42 | 0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe, | ||
43 | 0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca, | ||
44 | 0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c, | ||
45 | 0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7, | ||
46 | 0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c, | ||
47 | 0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c, | ||
48 | 0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a, | ||
49 | 0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065, | ||
50 | 0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730, | ||
51 | 0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc, | ||
52 | 0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469, | ||
53 | 0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9, | ||
54 | 0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c, | ||
55 | 0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765, | ||
56 | 0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83, | ||
57 | 0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387, | ||
58 | 0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973, | ||
59 | 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47 | ||
60 | }; | ||
61 | |||
62 | unsigned int intlog2(u32 value) | ||
63 | { | ||
64 | /** | ||
65 | * returns: log2(value) * 2^24 | ||
66 | * wrong result if value = 0 (log2(0) is undefined) | ||
67 | */ | ||
68 | unsigned int msb; | ||
69 | unsigned int logentry; | ||
70 | unsigned int significand; | ||
71 | unsigned int interpolation; | ||
72 | |||
73 | if (unlikely(value == 0)) { | ||
74 | WARN_ON(1); | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | /* first detect the msb (count begins at 0) */ | ||
79 | msb = fls(value) - 1; | ||
80 | |||
81 | /** | ||
82 | * now we use a logtable after the following method: | ||
83 | * | ||
84 | * log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24 | ||
85 | * where x = msb and therefore 1 <= y < 2 | ||
86 | * first y is determined by shifting the value left | ||
87 | * so that msb is bit 31 | ||
88 | * 0x00231f56 -> 0x8C7D5800 | ||
89 | * the result is y * 2^31 -> "significand" | ||
90 | * then the highest 9 bits are used for a table lookup | ||
91 | * the highest bit is discarded because it's always set | ||
92 | * the highest nine bits in our example are 100011000 | ||
93 | * so we would use the entry 0x18 | ||
94 | */ | ||
95 | significand = value << (31 - msb); | ||
96 | logentry = (significand >> 23) & 0xff; | ||
97 | |||
98 | /** | ||
99 | * last step we do is interpolation because of the | ||
100 | * limitations of the log table the error is that part of | ||
101 | * the significand which isn't used for lookup then we | ||
102 | * compute the ratio between the error and the next table entry | ||
103 | * and interpolate it between the log table entry used and the | ||
104 | * next one the biggest error possible is 0x7fffff | ||
105 | * (in our example it's 0x7D5800) | ||
106 | * needed value for next table entry is 0x800000 | ||
107 | * so the interpolation is | ||
108 | * (error / 0x800000) * (logtable_next - logtable_current) | ||
109 | * in the implementation the division is moved to the end for | ||
110 | * better accuracy there is also an overflow correction if | ||
111 | * logtable_next is 256 | ||
112 | */ | ||
113 | interpolation = ((significand & 0x7fffff) * | ||
114 | ((logtable[(logentry + 1) & 0xff] - | ||
115 | logtable[logentry]) & 0xffff)) >> 15; | ||
116 | |||
117 | /* now we return the result */ | ||
118 | return ((msb << 24) + (logtable[logentry] << 8) + interpolation); | ||
119 | } | ||
120 | EXPORT_SYMBOL(intlog2); | ||
121 | |||
122 | unsigned int intlog10(u32 value) | ||
123 | { | ||
124 | /** | ||
125 | * returns: log10(value) * 2^24 | ||
126 | * wrong result if value = 0 (log10(0) is undefined) | ||
127 | */ | ||
128 | u64 log; | ||
129 | |||
130 | if (unlikely(value == 0)) { | ||
131 | WARN_ON(1); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | log = intlog2(value); | ||
136 | |||
137 | /** | ||
138 | * we use the following method: | ||
139 | * log10(x) = log2(x) * log10(2) | ||
140 | */ | ||
141 | |||
142 | return (log * 646456993) >> 31; | ||
143 | } | ||
144 | EXPORT_SYMBOL(intlog10); | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h new file mode 100644 index 000000000000..aecc867e9404 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_math.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * dvb-math provides some complex fixed-point math | ||
3 | * operations shared between the dvb related stuff | ||
4 | * | ||
5 | * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as | ||
9 | * published by the Free Software Foundation; either version 2.1 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifndef __DVB_MATH_H | ||
23 | #define __DVB_MATH_H | ||
24 | |||
25 | #include <linux/types.h> | ||
26 | |||
27 | /** | ||
28 | * computes log2 of a value; the result is shifted left by 24 bits | ||
29 | * | ||
30 | * to use rational values you can use the following method: | ||
31 | * intlog2(value) = intlog2(value * 2^x) - x * 2^24 | ||
32 | * | ||
33 | * example: intlog2(8) will give 3 << 24 = 3 * 2^24 | ||
34 | * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24 | ||
35 | * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24 | ||
36 | * | ||
37 | * @param value The value (must be != 0) | ||
38 | * @return log2(value) * 2^24 | ||
39 | */ | ||
40 | extern unsigned int intlog2(u32 value); | ||
41 | |||
42 | /** | ||
43 | * computes log10 of a value; the result is shifted left by 24 bits | ||
44 | * | ||
45 | * to use rational values you can use the following method: | ||
46 | * intlog10(value) = intlog10(value * 10^x) - x * 2^24 | ||
47 | * | ||
48 | * example: intlog10(1000) will give 3 << 24 = 3 * 2^24 | ||
49 | * due to the implementation intlog10(1000) might be not exactly 3 * 2^24 | ||
50 | * | ||
51 | * look at intlog2 for similar examples | ||
52 | * | ||
53 | * @param value The value (must be != 0) | ||
54 | * @return log10(value) * 2^24 | ||
55 | */ | ||
56 | extern unsigned int intlog10(u32 value); | ||
57 | |||
58 | #endif | ||