1 /*
2 
3   Broadcom B43 wireless driver
4   IEEE 802.11n LCN-PHY data tables
5 
6   Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
7 
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12 
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   along with this program; see the file COPYING.  If not, write to
20   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
21   Boston, MA 02110-1301, USA.
22 
23 */
24 
25 #include "b43.h"
26 #include "tables_phy_lcn.h"
27 #include "phy_common.h"
28 #include "phy_lcn.h"
29 
30 struct b43_lcntab_tx_gain_tbl_entry {
31 	u8 gm;
32 	u8 pga;
33 	u8 pad;
34 	u8 dac;
35 	u8 bb_mult;
36 };
37 
38 /**************************************************
39  * Static tables.
40  **************************************************/
41 
42 static const u16 b43_lcntab_0x02[] = {
43 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
44 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
45 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
46 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
47 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
48 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
49 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
50 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
51 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
52 	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
53 	0x014d, 0x014d, 0x014d, 0x014d,
54 };
55 
56 static const u16 b43_lcntab_0x01[] = {
57 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
58 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
59 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
60 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
61 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
62 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
63 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
64 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
65 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
66 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
67 	0x0000, 0x0000, 0x0000, 0x0000,
68 };
69 
70 static const u32 b43_lcntab_0x0b[] = {
71 	0x000141f8, 0x000021f8, 0x000021fb, 0x000041fb,
72 	0x0001fedb, 0x0000217b, 0x00002133, 0x000040eb,
73 	0x0001fea3, 0x0000024b,
74 };
75 
76 static const u32 b43_lcntab_0x0c[] = {
77 	0x00100001, 0x00200010, 0x00300001, 0x00400010,
78 	0x00500022, 0x00600122, 0x00700222, 0x00800322,
79 	0x00900422, 0x00a00522, 0x00b00622, 0x00c00722,
80 	0x00d00822, 0x00f00922, 0x00100a22, 0x00200b22,
81 	0x00300c22, 0x00400d22, 0x00500e22, 0x00600f22,
82 };
83 
84 static const u32 b43_lcntab_0x0d[] = {
85 	0x00000000, 0x00000000, 0x10000000, 0x00000000,
86 	0x20000000, 0x00000000, 0x30000000, 0x00000000,
87 	0x40000000, 0x00000000, 0x50000000, 0x00000000,
88 	0x60000000, 0x00000000, 0x70000000, 0x00000000,
89 	0x80000000, 0x00000000, 0x90000000, 0x00000008,
90 	0xa0000000, 0x00000008, 0xb0000000, 0x00000008,
91 	0xc0000000, 0x00000008, 0xd0000000, 0x00000008,
92 	0xe0000000, 0x00000008, 0xf0000000, 0x00000008,
93 	0x00000000, 0x00000009, 0x10000000, 0x00000009,
94 	0x20000000, 0x00000019, 0x30000000, 0x00000019,
95 	0x40000000, 0x00000019, 0x50000000, 0x00000019,
96 	0x60000000, 0x00000019, 0x70000000, 0x00000019,
97 	0x80000000, 0x00000019, 0x90000000, 0x00000019,
98 	0xa0000000, 0x00000019, 0xb0000000, 0x00000019,
99 	0xc0000000, 0x00000019, 0xd0000000, 0x00000019,
100 	0xe0000000, 0x00000019, 0xf0000000, 0x00000019,
101 	0x00000000, 0x0000001a, 0x10000000, 0x0000001a,
102 	0x20000000, 0x0000001a, 0x30000000, 0x0000001a,
103 	0x40000000, 0x0000001a, 0x50000000, 0x00000002,
104 	0x60000000, 0x00000002, 0x70000000, 0x00000002,
105 	0x80000000, 0x00000002, 0x90000000, 0x00000002,
106 	0xa0000000, 0x00000002, 0xb0000000, 0x00000002,
107 	0xc0000000, 0x0000000a, 0xd0000000, 0x0000000a,
108 	0xe0000000, 0x0000000a, 0xf0000000, 0x0000000a,
109 	0x00000000, 0x0000000b, 0x10000000, 0x0000000b,
110 	0x20000000, 0x0000000b, 0x30000000, 0x0000000b,
111 	0x40000000, 0x0000000b, 0x50000000, 0x0000001b,
112 	0x60000000, 0x0000001b, 0x70000000, 0x0000001b,
113 	0x80000000, 0x0000001b, 0x90000000, 0x0000001b,
114 	0xa0000000, 0x0000001b, 0xb0000000, 0x0000001b,
115 	0xc0000000, 0x0000001b, 0xd0000000, 0x0000001b,
116 	0xe0000000, 0x0000001b, 0xf0000000, 0x0000001b,
117 	0x00000000, 0x0000001c, 0x10000000, 0x0000001c,
118 	0x20000000, 0x0000001c, 0x30000000, 0x0000001c,
119 	0x40000000, 0x0000001c, 0x50000000, 0x0000001c,
120 	0x60000000, 0x0000001c, 0x70000000, 0x0000001c,
121 	0x80000000, 0x0000001c, 0x90000000, 0x0000001c,
122 };
123 
124 static const u16 b43_lcntab_0x0e[] = {
125 	0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406,
126 	0x0407, 0x0408, 0x0409, 0x040a, 0x058b, 0x058c,
127 	0x058d, 0x058e, 0x058f, 0x0090, 0x0091, 0x0092,
128 	0x0193, 0x0194, 0x0195, 0x0196, 0x0197, 0x0198,
129 	0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e,
130 	0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a4,
131 	0x01a5, 0x0000,
132 };
133 
134 static const u16 b43_lcntab_0x0f[] = {
135 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
136 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
137 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
138 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
139 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
140 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
141 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
142 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
143 	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
144 	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
145 	0x000a, 0x0009, 0x0006, 0x0005,
146 };
147 
148 static const u16 b43_lcntab_0x10[] = {
149 	0x005f, 0x0036, 0x0029, 0x001f, 0x005f, 0x0036,
150 	0x0029, 0x001f, 0x005f, 0x0036, 0x0029, 0x001f,
151 	0x005f, 0x0036, 0x0029, 0x001f,
152 };
153 
154 static const u16 b43_lcntab_0x11[] = {
155 	0x0009, 0x000f, 0x0014, 0x0018, 0x00fe, 0x0007,
156 	0x000b, 0x000f, 0x00fb, 0x00fe, 0x0001, 0x0005,
157 	0x0008, 0x000b, 0x000e, 0x0011, 0x0014, 0x0017,
158 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
159 	0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f,
160 	0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
161 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003,
162 	0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015,
163 	0x0018, 0x001b, 0x0000, 0x0000, 0x0000, 0x0000,
164 	0x0000, 0x0000, 0x0003, 0x00eb, 0x0000, 0x0000,
165 };
166 
167 static const u32 b43_lcntab_0x12[] = {
168 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
169 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
170 	0x00000004, 0x00000000, 0x00000004, 0x00000008,
171 	0x00000001, 0x00000005, 0x00000009, 0x0000000d,
172 	0x0000004d, 0x0000008d, 0x0000000d, 0x0000004d,
173 	0x0000008d, 0x000000cd, 0x0000004f, 0x0000008f,
174 	0x000000cf, 0x000000d3, 0x00000113, 0x00000513,
175 	0x00000913, 0x00000953, 0x00000d53, 0x00001153,
176 	0x00001193, 0x00005193, 0x00009193, 0x0000d193,
177 	0x00011193, 0x00000000, 0x00000000, 0x00000000,
178 	0x00000000, 0x00000000, 0x00000000, 0x00000004,
179 	0x00000000, 0x00000004, 0x00000008, 0x00000001,
180 	0x00000005, 0x00000009, 0x0000000d, 0x0000004d,
181 	0x0000008d, 0x0000000d, 0x0000004d, 0x0000008d,
182 	0x000000cd, 0x0000004f, 0x0000008f, 0x000000cf,
183 	0x000000d3, 0x00000113, 0x00000513, 0x00000913,
184 	0x00000953, 0x00000d53, 0x00001153, 0x00005153,
185 	0x00009153, 0x0000d153, 0x00011153, 0x00015153,
186 	0x00019153, 0x0001d153, 0x00000000, 0x00000000,
187 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
188 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
189 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
190 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
191 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
192 };
193 
194 static const u16 b43_lcntab_0x14[] = {
195 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
196 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
197 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
198 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
199 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
200 	0x0002, 0x0003, 0x0001, 0x0003, 0x0002, 0x0001,
201 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
202 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
203 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
204 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
205 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
206 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
207 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
208 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
209 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
210 	0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003,
211 	0x0001, 0x0003, 0x0002, 0x0001, 0x0001, 0x0001,
212 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
213 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
214 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
215 	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
216 	0x0001, 0x0001,
217 };
218 
219 static const u16 b43_lcntab_0x17[] = {
220 	0x001a, 0x0034, 0x004e, 0x0068, 0x009c, 0x00d0,
221 	0x00ea, 0x0104, 0x0034, 0x0068, 0x009c, 0x00d0,
222 	0x0138, 0x01a0, 0x01d4, 0x0208, 0x004e, 0x009c,
223 	0x00ea, 0x0138, 0x01d4, 0x0270, 0x02be, 0x030c,
224 	0x0068, 0x00d0, 0x0138, 0x01a0, 0x0270, 0x0340,
225 	0x03a8, 0x0410, 0x0018, 0x009c, 0x00d0, 0x0104,
226 	0x00ea, 0x0138, 0x0186, 0x00d0, 0x0104, 0x0104,
227 	0x0138, 0x016c, 0x016c, 0x01a0, 0x0138, 0x0186,
228 	0x0186, 0x01d4, 0x0222, 0x0222, 0x0270, 0x0104,
229 	0x0138, 0x016c, 0x0138, 0x016c, 0x01a0, 0x01d4,
230 	0x01a0, 0x01d4, 0x0208, 0x0208, 0x023c, 0x0186,
231 	0x01d4, 0x0222, 0x01d4, 0x0222, 0x0270, 0x02be,
232 	0x0270, 0x02be, 0x030c, 0x030c, 0x035a, 0x0036,
233 	0x006c, 0x00a2, 0x00d8, 0x0144, 0x01b0, 0x01e6,
234 	0x021c, 0x006c, 0x00d8, 0x0144, 0x01b0, 0x0288,
235 	0x0360, 0x03cc, 0x0438, 0x00a2, 0x0144, 0x01e6,
236 	0x0288, 0x03cc, 0x0510, 0x05b2, 0x0654, 0x00d8,
237 	0x01b0, 0x0288, 0x0360, 0x0510, 0x06c0, 0x0798,
238 	0x0870, 0x0018, 0x0144, 0x01b0, 0x021c, 0x01e6,
239 	0x0288, 0x032a, 0x01b0, 0x021c, 0x021c, 0x0288,
240 	0x02f4, 0x02f4, 0x0360, 0x0288, 0x032a, 0x032a,
241 	0x03cc, 0x046e, 0x046e, 0x0510, 0x021c, 0x0288,
242 	0x02f4, 0x0288, 0x02f4, 0x0360, 0x03cc, 0x0360,
243 	0x03cc, 0x0438, 0x0438, 0x04a4, 0x032a, 0x03cc,
244 	0x046e, 0x03cc, 0x046e, 0x0510, 0x05b2, 0x0510,
245 	0x05b2, 0x0654, 0x0654, 0x06f6,
246 };
247 
248 static const u16 b43_lcntab_0x00[] = {
249 	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00,
250 	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005,
251 	0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
252 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
253 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
254 	0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
255 	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003,
256 	0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007,
257 	0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
258 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
259 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
260 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
261 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
262 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
263 	0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
264 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
265 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
266 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
267 };
268 
269 static const u32 b43_lcntab_0x18[] = {
270 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
271 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
272 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
273 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
274 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
275 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
276 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
277 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
278 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
279 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
280 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
281 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
282 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
283 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
284 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
285 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
286 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
287 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
288 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
289 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
290 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
291 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
292 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
293 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
294 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
295 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
296 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
297 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
298 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
299 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
300 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
301 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
302 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
303 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
304 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
305 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
306 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
307 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
308 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
309 	0x00080000, 0x00080000, 0x00080000, 0x00080000,
310 };
311 
312 /**************************************************
313  * TX gain.
314  **************************************************/
315 
316 static const struct b43_lcntab_tx_gain_tbl_entry
317 	b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
318 	{ 0x03, 0x00, 0x1f, 0x0, 0x48 },
319 	{ 0x03, 0x00, 0x1f, 0x0, 0x46 },
320 	{ 0x03, 0x00, 0x1f, 0x0, 0x44 },
321 	{ 0x03, 0x00, 0x1e, 0x0, 0x43 },
322 	{ 0x03, 0x00, 0x1d, 0x0, 0x44 },
323 	{ 0x03, 0x00, 0x1c, 0x0, 0x44 },
324 	{ 0x03, 0x00, 0x1b, 0x0, 0x45 },
325 	{ 0x03, 0x00, 0x1a, 0x0, 0x46 },
326 	{ 0x03, 0x00, 0x19, 0x0, 0x46 },
327 	{ 0x03, 0x00, 0x18, 0x0, 0x47 },
328 	{ 0x03, 0x00, 0x17, 0x0, 0x48 },
329 	{ 0x03, 0x00, 0x17, 0x0, 0x46 },
330 	{ 0x03, 0x00, 0x16, 0x0, 0x47 },
331 	{ 0x03, 0x00, 0x15, 0x0, 0x48 },
332 	{ 0x03, 0x00, 0x15, 0x0, 0x46 },
333 	{ 0x03, 0x00, 0x15, 0x0, 0x44 },
334 	{ 0x03, 0x00, 0x15, 0x0, 0x42 },
335 	{ 0x03, 0x00, 0x15, 0x0, 0x40 },
336 	{ 0x03, 0x00, 0x15, 0x0, 0x3f },
337 	{ 0x03, 0x00, 0x14, 0x0, 0x40 },
338 	{ 0x03, 0x00, 0x13, 0x0, 0x41 },
339 	{ 0x03, 0x00, 0x13, 0x0, 0x40 },
340 	{ 0x03, 0x00, 0x12, 0x0, 0x41 },
341 	{ 0x03, 0x00, 0x12, 0x0, 0x40 },
342 	{ 0x03, 0x00, 0x11, 0x0, 0x41 },
343 	{ 0x03, 0x00, 0x11, 0x0, 0x40 },
344 	{ 0x03, 0x00, 0x10, 0x0, 0x41 },
345 	{ 0x03, 0x00, 0x10, 0x0, 0x40 },
346 	{ 0x03, 0x00, 0x10, 0x0, 0x3e },
347 	{ 0x03, 0x00, 0x10, 0x0, 0x3c },
348 	{ 0x03, 0x00, 0x10, 0x0, 0x3a },
349 	{ 0x03, 0x00, 0x0f, 0x0, 0x3d },
350 	{ 0x03, 0x00, 0x0f, 0x0, 0x3b },
351 	{ 0x03, 0x00, 0x0e, 0x0, 0x3d },
352 	{ 0x03, 0x00, 0x0e, 0x0, 0x3c },
353 	{ 0x03, 0x00, 0x0e, 0x0, 0x3a },
354 	{ 0x03, 0x00, 0x0d, 0x0, 0x3c },
355 	{ 0x03, 0x00, 0x0d, 0x0, 0x3b },
356 	{ 0x03, 0x00, 0x0c, 0x0, 0x3e },
357 	{ 0x03, 0x00, 0x0c, 0x0, 0x3c },
358 	{ 0x03, 0x00, 0x0c, 0x0, 0x3a },
359 	{ 0x03, 0x00, 0x0b, 0x0, 0x3e },
360 	{ 0x03, 0x00, 0x0b, 0x0, 0x3c },
361 	{ 0x03, 0x00, 0x0b, 0x0, 0x3b },
362 	{ 0x03, 0x00, 0x0b, 0x0, 0x39 },
363 	{ 0x03, 0x00, 0x0a, 0x0, 0x3d },
364 	{ 0x03, 0x00, 0x0a, 0x0, 0x3b },
365 	{ 0x03, 0x00, 0x0a, 0x0, 0x39 },
366 	{ 0x03, 0x00, 0x09, 0x0, 0x3e },
367 	{ 0x03, 0x00, 0x09, 0x0, 0x3c },
368 	{ 0x03, 0x00, 0x09, 0x0, 0x3a },
369 	{ 0x03, 0x00, 0x09, 0x0, 0x39 },
370 	{ 0x03, 0x00, 0x08, 0x0, 0x3e },
371 	{ 0x03, 0x00, 0x08, 0x0, 0x3c },
372 	{ 0x03, 0x00, 0x08, 0x0, 0x3a },
373 	{ 0x03, 0x00, 0x08, 0x0, 0x39 },
374 	{ 0x03, 0x00, 0x08, 0x0, 0x37 },
375 	{ 0x03, 0x00, 0x07, 0x0, 0x3d },
376 	{ 0x03, 0x00, 0x07, 0x0, 0x3c },
377 	{ 0x03, 0x00, 0x07, 0x0, 0x3a },
378 	{ 0x03, 0x00, 0x07, 0x0, 0x38 },
379 	{ 0x03, 0x00, 0x07, 0x0, 0x37 },
380 	{ 0x03, 0x00, 0x06, 0x0, 0x3e },
381 	{ 0x03, 0x00, 0x06, 0x0, 0x3c },
382 	{ 0x03, 0x00, 0x06, 0x0, 0x3a },
383 	{ 0x03, 0x00, 0x06, 0x0, 0x39 },
384 	{ 0x03, 0x00, 0x06, 0x0, 0x37 },
385 	{ 0x03, 0x00, 0x06, 0x0, 0x36 },
386 	{ 0x03, 0x00, 0x06, 0x0, 0x34 },
387 	{ 0x03, 0x00, 0x05, 0x0, 0x3d },
388 	{ 0x03, 0x00, 0x05, 0x0, 0x3b },
389 	{ 0x03, 0x00, 0x05, 0x0, 0x39 },
390 	{ 0x03, 0x00, 0x05, 0x0, 0x38 },
391 	{ 0x03, 0x00, 0x05, 0x0, 0x36 },
392 	{ 0x03, 0x00, 0x05, 0x0, 0x35 },
393 	{ 0x03, 0x00, 0x05, 0x0, 0x33 },
394 	{ 0x03, 0x00, 0x04, 0x0, 0x3e },
395 	{ 0x03, 0x00, 0x04, 0x0, 0x3c },
396 	{ 0x03, 0x00, 0x04, 0x0, 0x3a },
397 	{ 0x03, 0x00, 0x04, 0x0, 0x39 },
398 	{ 0x03, 0x00, 0x04, 0x0, 0x37 },
399 	{ 0x03, 0x00, 0x04, 0x0, 0x36 },
400 	{ 0x03, 0x00, 0x04, 0x0, 0x34 },
401 	{ 0x03, 0x00, 0x04, 0x0, 0x33 },
402 	{ 0x03, 0x00, 0x04, 0x0, 0x31 },
403 	{ 0x03, 0x00, 0x04, 0x0, 0x30 },
404 	{ 0x03, 0x00, 0x04, 0x0, 0x2e },
405 	{ 0x03, 0x00, 0x03, 0x0, 0x3c },
406 	{ 0x03, 0x00, 0x03, 0x0, 0x3a },
407 	{ 0x03, 0x00, 0x03, 0x0, 0x39 },
408 	{ 0x03, 0x00, 0x03, 0x0, 0x37 },
409 	{ 0x03, 0x00, 0x03, 0x0, 0x36 },
410 	{ 0x03, 0x00, 0x03, 0x0, 0x34 },
411 	{ 0x03, 0x00, 0x03, 0x0, 0x33 },
412 	{ 0x03, 0x00, 0x03, 0x0, 0x31 },
413 	{ 0x03, 0x00, 0x03, 0x0, 0x30 },
414 	{ 0x03, 0x00, 0x03, 0x0, 0x2e },
415 	{ 0x03, 0x00, 0x03, 0x0, 0x2d },
416 	{ 0x03, 0x00, 0x03, 0x0, 0x2c },
417 	{ 0x03, 0x00, 0x03, 0x0, 0x2b },
418 	{ 0x03, 0x00, 0x03, 0x0, 0x29 },
419 	{ 0x03, 0x00, 0x02, 0x0, 0x3d },
420 	{ 0x03, 0x00, 0x02, 0x0, 0x3b },
421 	{ 0x03, 0x00, 0x02, 0x0, 0x39 },
422 	{ 0x03, 0x00, 0x02, 0x0, 0x38 },
423 	{ 0x03, 0x00, 0x02, 0x0, 0x36 },
424 	{ 0x03, 0x00, 0x02, 0x0, 0x35 },
425 	{ 0x03, 0x00, 0x02, 0x0, 0x33 },
426 	{ 0x03, 0x00, 0x02, 0x0, 0x32 },
427 	{ 0x03, 0x00, 0x02, 0x0, 0x30 },
428 	{ 0x03, 0x00, 0x02, 0x0, 0x2f },
429 	{ 0x03, 0x00, 0x02, 0x0, 0x2e },
430 	{ 0x03, 0x00, 0x02, 0x0, 0x2c },
431 	{ 0x03, 0x00, 0x02, 0x0, 0x2b },
432 	{ 0x03, 0x00, 0x02, 0x0, 0x2a },
433 	{ 0x03, 0x00, 0x02, 0x0, 0x29 },
434 	{ 0x03, 0x00, 0x02, 0x0, 0x27 },
435 	{ 0x03, 0x00, 0x02, 0x0, 0x26 },
436 	{ 0x03, 0x00, 0x02, 0x0, 0x25 },
437 	{ 0x03, 0x00, 0x02, 0x0, 0x24 },
438 	{ 0x03, 0x00, 0x02, 0x0, 0x23 },
439 	{ 0x03, 0x00, 0x02, 0x0, 0x22 },
440 	{ 0x03, 0x00, 0x02, 0x0, 0x21 },
441 	{ 0x03, 0x00, 0x02, 0x0, 0x20 },
442 	{ 0x03, 0x00, 0x01, 0x0, 0x3f },
443 	{ 0x03, 0x00, 0x01, 0x0, 0x3d },
444 	{ 0x03, 0x00, 0x01, 0x0, 0x3b },
445 	{ 0x03, 0x00, 0x01, 0x0, 0x39 },
446 };
447 
448 /**************************************************
449  * SW control.
450  **************************************************/
451 
452 static const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
453 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
454 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
455 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
456 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
457 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
458 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
459 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
460 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
461 	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
462 	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
463 	0x0002, 0x0008, 0x0004, 0x0001,
464 };
465 
466 /**************************************************
467  * R/W ops.
468  **************************************************/
469 
470 u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset)
471 {
472 	u32 type, value;
473 
474 	type = offset & B43_LCNTAB_TYPEMASK;
475 	offset &= ~B43_LCNTAB_TYPEMASK;
476 	B43_WARN_ON(offset > 0xFFFF);
477 
478 	switch (type) {
479 	case B43_LCNTAB_8BIT:
480 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
481 		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO) & 0xFF;
482 		break;
483 	case B43_LCNTAB_16BIT:
484 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
485 		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
486 		break;
487 	case B43_LCNTAB_32BIT:
488 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
489 		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
490 		value |= (b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI) << 16);
491 		break;
492 	default:
493 		B43_WARN_ON(1);
494 		value = 0;
495 	}
496 
497 	return value;
498 }
499 
500 void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
501 			  unsigned int nr_elements, void *_data)
502 {
503 	u32 type;
504 	u8 *data = _data;
505 	unsigned int i;
506 
507 	type = offset & B43_LCNTAB_TYPEMASK;
508 	offset &= ~B43_LCNTAB_TYPEMASK;
509 	B43_WARN_ON(offset > 0xFFFF);
510 
511 	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
512 
513 	for (i = 0; i < nr_elements; i++) {
514 		switch (type) {
515 		case B43_LCNTAB_8BIT:
516 			*data = b43_phy_read(dev,
517 					     B43_PHY_LCN_TABLE_DATALO) & 0xFF;
518 			data++;
519 			break;
520 		case B43_LCNTAB_16BIT:
521 			*((u16 *)data) = b43_phy_read(dev,
522 						      B43_PHY_LCN_TABLE_DATALO);
523 			data += 2;
524 			break;
525 		case B43_LCNTAB_32BIT:
526 			*((u32 *)data) = b43_phy_read(dev,
527 						B43_PHY_LCN_TABLE_DATALO);
528 			*((u32 *)data) |= (b43_phy_read(dev,
529 					   B43_PHY_LCN_TABLE_DATAHI) << 16);
530 			data += 4;
531 			break;
532 		default:
533 			B43_WARN_ON(1);
534 		}
535 	}
536 }
537 
538 void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value)
539 {
540 	u32 type;
541 
542 	type = offset & B43_LCNTAB_TYPEMASK;
543 	offset &= 0xFFFF;
544 
545 	switch (type) {
546 	case B43_LCNTAB_8BIT:
547 		B43_WARN_ON(value & ~0xFF);
548 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
549 		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
550 		break;
551 	case B43_LCNTAB_16BIT:
552 		B43_WARN_ON(value & ~0xFFFF);
553 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
554 		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
555 		break;
556 	case B43_LCNTAB_32BIT:
557 		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
558 		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, value >> 16);
559 		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value & 0xFFFF);
560 		break;
561 	default:
562 		B43_WARN_ON(1);
563 	}
564 
565 	return;
566 }
567 
568 void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
569 			   unsigned int nr_elements, const void *_data)
570 {
571 	u32 type, value;
572 	const u8 *data = _data;
573 	unsigned int i;
574 
575 	type = offset & B43_LCNTAB_TYPEMASK;
576 	offset &= ~B43_LCNTAB_TYPEMASK;
577 	B43_WARN_ON(offset > 0xFFFF);
578 
579 	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
580 
581 	for (i = 0; i < nr_elements; i++) {
582 		switch (type) {
583 		case B43_LCNTAB_8BIT:
584 			value = *data;
585 			data++;
586 			B43_WARN_ON(value & ~0xFF);
587 			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
588 			break;
589 		case B43_LCNTAB_16BIT:
590 			value = *((u16 *)data);
591 			data += 2;
592 			B43_WARN_ON(value & ~0xFFFF);
593 			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
594 			break;
595 		case B43_LCNTAB_32BIT:
596 			value = *((u32 *)data);
597 			data += 4;
598 			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI,
599 				      value >> 16);
600 			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO,
601 				      value & 0xFFFF);
602 			break;
603 		default:
604 			B43_WARN_ON(1);
605 		}
606 	}
607 }
608 
609 /**************************************************
610  * Tables ops.
611  **************************************************/
612 
613 #define lcntab_upload(dev, offset, data) do { \
614 		b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
615 	} while (0)
616 static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev)
617 {
618 	lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02);
619 	lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01);
620 	lcntab_upload(dev, B43_LCNTAB32(0x0b, 0), b43_lcntab_0x0b);
621 	lcntab_upload(dev, B43_LCNTAB32(0x0c, 0), b43_lcntab_0x0c);
622 	lcntab_upload(dev, B43_LCNTAB32(0x0d, 0), b43_lcntab_0x0d);
623 	lcntab_upload(dev, B43_LCNTAB16(0x0e, 0), b43_lcntab_0x0e);
624 	lcntab_upload(dev, B43_LCNTAB16(0x0f, 0), b43_lcntab_0x0f);
625 	lcntab_upload(dev, B43_LCNTAB16(0x10, 0), b43_lcntab_0x10);
626 	lcntab_upload(dev, B43_LCNTAB16(0x11, 0), b43_lcntab_0x11);
627 	lcntab_upload(dev, B43_LCNTAB32(0x12, 0), b43_lcntab_0x12);
628 	lcntab_upload(dev, B43_LCNTAB16(0x14, 0), b43_lcntab_0x14);
629 	lcntab_upload(dev, B43_LCNTAB16(0x17, 0), b43_lcntab_0x17);
630 	lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00);
631 	lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);
632 }
633 
634 static void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
635 			const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
636 {
637 	u32 i;
638 	u32 val;
639 
640 	u16 pa_gain = 0x70;
641 	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM)
642 		pa_gain = 0x10;
643 
644 	for (i = 0; i < B43_LCNTAB_TX_GAIN_SIZE; i++) {
645 		val = ((pa_gain << 24) |
646 		       (gain_table[i].pad << 16) |
647 		       (gain_table[i].pga << 8) |
648 			gain_table[i].gm);
649 		b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0xc0 + i), val);
650 
651 		/* brcmsmac doesn't maskset, we follow newer wl here */
652 		val = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
653 		val &= 0x000fffff;
654 		val |= ((gain_table[i].dac << 28) |
655 			(gain_table[i].bb_mult << 20));
656 		b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x140 + i), val);
657 	}
658 }
659 
660 /* wlc_lcnphy_load_rfpower */
661 static void b43_phy_lcn_load_rfpower(struct b43_wldev *dev)
662 {
663 	u32 bbmult, rfgain;
664 	u8 i;
665 
666 	for (i = 0; i < 128; i++) {
667 		bbmult = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
668 		bbmult >>= 20;
669 		rfgain = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0xc0 + i));
670 
671 		/* TODO: calculate value for 0x240 + i table offset
672 		 * b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), val);
673 		 */
674 	}
675 }
676 
677 /* Not implemented in brcmsmac, noticed in wl in MMIO dump */
678 static void b43_phy_lcn_rewrite_rfpower_table(struct b43_wldev *dev)
679 {
680 	int i;
681 	u32 tmp;
682 	for (i = 0; i < 128; i++) {
683 		tmp = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x240 + i));
684 		b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), tmp);
685 	}
686 }
687 
688 /* wlc_lcnphy_clear_papd_comptable */
689 static void b43_phy_lcn_clean_papd_comp_table(struct b43_wldev *dev)
690 {
691 	u8 i;
692 
693 	for (i = 0; i < 0x80; i++)
694 		b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
695 }
696 
697 /* wlc_lcnphy_tbl_init */
698 void b43_phy_lcn_tables_init(struct b43_wldev *dev)
699 {
700 	struct ssb_sprom *sprom = dev->dev->bus_sprom;
701 
702 	b43_phy_lcn_upload_static_tables(dev);
703 
704 	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
705 		if (sprom->boardflags_lo & B43_BFL_FEM)
706 			b43_phy_lcn_load_tx_gain_tab(dev,
707 				b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0);
708 		else
709 			b43err(dev->wl,
710 			       "TX gain table unknown for this card\n");
711 	}
712 
713 	if (sprom->boardflags_lo & B43_BFL_FEM &&
714 	    !(sprom->boardflags_hi & B43_BFH_FEM_BT))
715 		b43_lcntab_write_bulk(dev, B43_LCNTAB16(0xf, 0),
716 			ARRAY_SIZE(b43_lcntab_sw_ctl_4313_epa_rev0),
717 			b43_lcntab_sw_ctl_4313_epa_rev0);
718 	else
719 		b43err(dev->wl, "SW ctl table is unknown for this card\n");
720 
721 	b43_phy_lcn_load_rfpower(dev);
722 	b43_phy_lcn_rewrite_rfpower_table(dev);
723 	b43_phy_lcn_clean_papd_comp_table(dev);
724 }
725