~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2010 Broadcom Corporation
 
3
 *
 
4
 * Permission to use, copy, modify, and/or distribute this software for any
 
5
 * purpose with or without fee is hereby granted, provided that the above
 
6
 * copyright notice and this permission notice appear in all copies.
 
7
 *
 
8
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 
9
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 
10
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 
11
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
12
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 
13
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 
14
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
15
 */
 
16
 
 
17
#include <linux/types.h>
 
18
 
 
19
#include "wlc_phy_qmath.h"
 
20
 
 
21
/*
 
22
Description: This function make 16 bit unsigned multiplication. To fit the output into
 
23
16 bits the 32 bit multiplication result is right shifted by 16 bits.
 
24
*/
 
25
u16 qm_mulu16(u16 op1, u16 op2)
 
26
{
 
27
        return (u16) (((u32) op1 * (u32) op2) >> 16);
 
28
}
 
29
 
 
30
/*
 
31
Description: This function make 16 bit multiplication and return the result in 16 bits.
 
32
To fit the multiplication result into 16 bits the multiplication result is right shifted by
 
33
15 bits. Right shifting 15 bits instead of 16 bits is done to remove the extra sign bit formed
 
34
due to the multiplication.
 
35
When both the 16bit inputs are 0x8000 then the output is saturated to 0x7fffffff.
 
36
*/
 
37
s16 qm_muls16(s16 op1, s16 op2)
 
38
{
 
39
        s32 result;
 
40
        if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000) {
 
41
                result = 0x7fffffff;
 
42
        } else {
 
43
                result = ((s32) (op1) * (s32) (op2));
 
44
        }
 
45
        return (s16) (result >> 15);
 
46
}
 
47
 
 
48
/*
 
49
Description: This function add two 32 bit numbers and return the 32bit result.
 
50
If the result overflow 32 bits, the output will be saturated to 32bits.
 
51
*/
 
52
s32 qm_add32(s32 op1, s32 op2)
 
53
{
 
54
        s32 result;
 
55
        result = op1 + op2;
 
56
        if (op1 < 0 && op2 < 0 && result > 0) {
 
57
                result = 0x80000000;
 
58
        } else if (op1 > 0 && op2 > 0 && result < 0) {
 
59
                result = 0x7fffffff;
 
60
        }
 
61
        return result;
 
62
}
 
63
 
 
64
/*
 
65
Description: This function add two 16 bit numbers and return the 16bit result.
 
66
If the result overflow 16 bits, the output will be saturated to 16bits.
 
67
*/
 
68
s16 qm_add16(s16 op1, s16 op2)
 
69
{
 
70
        s16 result;
 
71
        s32 temp = (s32) op1 + (s32) op2;
 
72
        if (temp > (s32) 0x7fff) {
 
73
                result = (s16) 0x7fff;
 
74
        } else if (temp < (s32) 0xffff8000) {
 
75
                result = (s16) 0xffff8000;
 
76
        } else {
 
77
                result = (s16) temp;
 
78
        }
 
79
        return result;
 
80
}
 
81
 
 
82
/*
 
83
Description: This function make 16 bit subtraction and return the 16bit result.
 
84
If the result overflow 16 bits, the output will be saturated to 16bits.
 
85
*/
 
86
s16 qm_sub16(s16 op1, s16 op2)
 
87
{
 
88
        s16 result;
 
89
        s32 temp = (s32) op1 - (s32) op2;
 
90
        if (temp > (s32) 0x7fff) {
 
91
                result = (s16) 0x7fff;
 
92
        } else if (temp < (s32) 0xffff8000) {
 
93
                result = (s16) 0xffff8000;
 
94
        } else {
 
95
                result = (s16) temp;
 
96
        }
 
97
        return result;
 
98
}
 
99
 
 
100
/*
 
101
Description: This function make a 32 bit saturated left shift when the specified shift
 
102
is +ve. This function will make a 32 bit right shift when the specified shift is -ve.
 
103
This function return the result after shifting operation.
 
104
*/
 
105
s32 qm_shl32(s32 op, int shift)
 
106
{
 
107
        int i;
 
108
        s32 result;
 
109
        result = op;
 
110
        if (shift > 31)
 
111
                shift = 31;
 
112
        else if (shift < -31)
 
113
                shift = -31;
 
114
        if (shift >= 0) {
 
115
                for (i = 0; i < shift; i++) {
 
116
                        result = qm_add32(result, result);
 
117
                }
 
118
        } else {
 
119
                result = result >> (-shift);
 
120
        }
 
121
        return result;
 
122
}
 
123
 
 
124
/*
 
125
Description: This function make a 16 bit saturated left shift when the specified shift
 
126
is +ve. This function will make a 16 bit right shift when the specified shift is -ve.
 
127
This function return the result after shifting operation.
 
128
*/
 
129
s16 qm_shl16(s16 op, int shift)
 
130
{
 
131
        int i;
 
132
        s16 result;
 
133
        result = op;
 
134
        if (shift > 15)
 
135
                shift = 15;
 
136
        else if (shift < -15)
 
137
                shift = -15;
 
138
        if (shift > 0) {
 
139
                for (i = 0; i < shift; i++) {
 
140
                        result = qm_add16(result, result);
 
141
                }
 
142
        } else {
 
143
                result = result >> (-shift);
 
144
        }
 
145
        return result;
 
146
}
 
147
 
 
148
/*
 
149
Description: This function make a 16 bit right shift when shift is +ve.
 
150
This function make a 16 bit saturated left shift when shift is -ve. This function
 
151
return the result of the shift operation.
 
152
*/
 
153
s16 qm_shr16(s16 op, int shift)
 
154
{
 
155
        return qm_shl16(op, -shift);
 
156
}
 
157
 
 
158
/*
 
159
Description: This function return the number of redundant sign bits in a 32 bit number.
 
160
Example: qm_norm32(0x00000080) = 23
 
161
*/
 
162
s16 qm_norm32(s32 op)
 
163
{
 
164
        u16 u16extraSignBits;
 
165
        if (op == 0) {
 
166
                return 31;
 
167
        } else {
 
168
                u16extraSignBits = 0;
 
169
                while ((op >> 31) == (op >> 30)) {
 
170
                        u16extraSignBits++;
 
171
                        op = op << 1;
 
172
                }
 
173
        }
 
174
        return u16extraSignBits;
 
175
}
 
176
 
 
177
/* This table is log2(1+(i/32)) where i=[0:1:31], in q.15 format */
 
178
static const s16 log_table[] = {
 
179
        0,
 
180
        1455,
 
181
        2866,
 
182
        4236,
 
183
        5568,
 
184
        6863,
 
185
        8124,
 
186
        9352,
 
187
        10549,
 
188
        11716,
 
189
        12855,
 
190
        13968,
 
191
        15055,
 
192
        16117,
 
193
        17156,
 
194
        18173,
 
195
        19168,
 
196
        20143,
 
197
        21098,
 
198
        22034,
 
199
        22952,
 
200
        23852,
 
201
        24736,
 
202
        25604,
 
203
        26455,
 
204
        27292,
 
205
        28114,
 
206
        28922,
 
207
        29717,
 
208
        30498,
 
209
        31267,
 
210
        32024
 
211
};
 
212
 
 
213
#define LOG_TABLE_SIZE 32       /* log_table size */
 
214
#define LOG2_LOG_TABLE_SIZE 5   /* log2(log_table size) */
 
215
#define Q_LOG_TABLE 15          /* qformat of log_table */
 
216
#define LOG10_2         19728   /* log10(2) in q.16 */
 
217
 
 
218
/*
 
219
Description:
 
220
This routine takes the input number N and its q format qN and compute
 
221
the log10(N). This routine first normalizes the input no N.     Then N is in mag*(2^x) format.
 
222
mag is any number in the range 2^30-(2^31 - 1). Then log2(mag * 2^x) = log2(mag) + x is computed.
 
223
From that log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed.
 
224
This routine looks the log2 value in the table considering LOG2_LOG_TABLE_SIZE+1 MSBs.
 
225
As the MSB is always 1, only next LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup.
 
226
Next 16 MSBs are used for interpolation.
 
227
Inputs:
 
228
N - number to which log10 has to be found.
 
229
qN - q format of N
 
230
log10N - address where log10(N) will be written.
 
231
qLog10N - address where log10N qformat will be written.
 
232
Note/Problem:
 
233
For accurate results input should be in normalized or near normalized form.
 
234
*/
 
235
void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
 
236
{
 
237
        s16 s16norm, s16tableIndex, s16errorApproximation;
 
238
        u16 u16offset;
 
239
        s32 s32log;
 
240
 
 
241
        /* normalize the N. */
 
242
        s16norm = qm_norm32(N);
 
243
        N = N << s16norm;
 
244
 
 
245
        /* The qformat of N after normalization.
 
246
         * -30 is added to treat the no as between 1.0 to 2.0
 
247
         * i.e. after adding the -30 to the qformat the decimal point will be
 
248
         * just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e.
 
249
         * at the right side of 30th bit.
 
250
         */
 
251
        qN = qN + s16norm - 30;
 
252
 
 
253
        /* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the MSB */
 
254
        s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE)));
 
255
 
 
256
        /* remove the MSB. the MSB is always 1 after normalization. */
 
257
        s16tableIndex =
 
258
            s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
 
259
 
 
260
        /* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */
 
261
        N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1);
 
262
 
 
263
        /* take the offset as the 16 MSBS after table index.
 
264
         */
 
265
        u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
 
266
 
 
267
        /* look the log value in the table. */
 
268
        s32log = log_table[s16tableIndex];      /* q.15 format */
 
269
 
 
270
        /* interpolate using the offset. */
 
271
        s16errorApproximation = (s16) qm_mulu16(u16offset, (u16) (log_table[s16tableIndex + 1] - log_table[s16tableIndex]));    /* q.15 */
 
272
 
 
273
        s32log = qm_add16((s16) s32log, s16errorApproximation); /* q.15 format */
 
274
 
 
275
        /* adjust for the qformat of the N as
 
276
         * log2(mag * 2^x) = log2(mag) + x
 
277
         */
 
278
        s32log = qm_add32(s32log, ((s32) -qN) << 15);   /* q.15 format */
 
279
 
 
280
        /* normalize the result. */
 
281
        s16norm = qm_norm32(s32log);
 
282
 
 
283
        /* bring all the important bits into lower 16 bits */
 
284
        s32log = qm_shl32(s32log, s16norm - 16);        /* q.15+s16norm-16 format */
 
285
 
 
286
        /* compute the log10(N) by multiplying log2(N) with log10(2).
 
287
         * as log10(mag * 2^x) = log2(mag * 2^x) * log10(2)
 
288
         * log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16)
 
289
         */
 
290
        *log10N = qm_muls16((s16) s32log, (s16) LOG10_2);
 
291
 
 
292
        /* write the q format of the result. */
 
293
        *qLog10N = 15 + s16norm - 16 + 1;
 
294
 
 
295
        return;
 
296
}