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
30struct 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
42static 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
56static 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
70static const u32 b43_lcntab_0x0b[] = {
71	0x000141f8, 0x000021f8, 0x000021fb, 0x000041fb,
72	0x0001fedb, 0x0000217b, 0x00002133, 0x000040eb,
73	0x0001fea3, 0x0000024b,
74};
75
76static 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
84static 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
124static 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
134static 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
148static 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
154static 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
167static 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
194static 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
219static 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
248static 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
269static 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
316static 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
452static 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
470u32 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
500void 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
538void 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
568void 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)
616static 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
634static 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 */
661static 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 */
678static 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 */
689static 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 */
698void 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) == IEEE80211_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