Commit | Line | Data |
---|---|---|
66101de1 PM |
1 | /* |
2 | * phy_302_calibration.c | |
3 | * | |
4 | * Copyright (C) 2002, 2005 Winbond Electronics Corp. | |
5 | * | |
6 | * modification history | |
7 | * --------------------------------------------------------------------------- | |
8 | * 0.01.001, 2003-04-16, Kevin created | |
9 | * | |
10 | */ | |
11 | ||
12 | /****************** INCLUDE FILES SECTION ***********************************/ | |
7e797abf | 13 | #include "sysdef.h" |
66101de1 | 14 | #include "phy_calibration.h" |
72ca8819 PE |
15 | #include "wbhal_s.h" |
16 | #include "wb35reg_f.h" | |
17 | #include "core.h" | |
66101de1 PM |
18 | |
19 | ||
20 | /****************** DEBUG CONSTANT AND MACRO SECTION ************************/ | |
21 | ||
22 | /****************** LOCAL CONSTANT AND MACRO SECTION ************************/ | |
23 | #define LOOP_TIMES 20 | |
3a4d1b90 | 24 | #define US 1000/* MICROSECOND*/ |
66101de1 PM |
25 | |
26 | #define AG_CONST 0.6072529350 | |
27 | #define FIXED(X) ((s32)((X) * 32768.0)) | |
28 | #define DEG2RAD(X) 0.017453 * (X) | |
29 | ||
3a4d1b90 TT |
30 | static const s32 Angles[] = { |
31 | FIXED(DEG2RAD(45.0)), FIXED(DEG2RAD(26.565)), FIXED(DEG2RAD(14.0362)), | |
32 | FIXED(DEG2RAD(7.12502)), FIXED(DEG2RAD(3.57633)), FIXED(DEG2RAD(1.78991)), | |
33 | FIXED(DEG2RAD(0.895174)), FIXED(DEG2RAD(0.447614)), FIXED(DEG2RAD(0.223811)), | |
34 | FIXED(DEG2RAD(0.111906)), FIXED(DEG2RAD(0.055953)), FIXED(DEG2RAD(0.027977)) | |
66101de1 PM |
35 | }; |
36 | ||
2e04bb7b | 37 | /****************** LOCAL FUNCTION DECLARATION SECTION **********************/ |
3a4d1b90 TT |
38 | |
39 | /* | |
40 | * void _phy_rf_write_delay(struct hw_data *phw_data); | |
41 | * void phy_init_rf(struct hw_data *phw_data); | |
42 | */ | |
66101de1 PM |
43 | |
44 | /****************** FUNCTION DEFINITION SECTION *****************************/ | |
45 | ||
46 | s32 _s13_to_s32(u32 data) | |
47 | { | |
48 | u32 val; | |
49 | ||
50 | val = (data & 0x0FFF); | |
51 | ||
52 | if ((data & BIT(12)) != 0) | |
66101de1 | 53 | val |= 0xFFFFF000; |
66101de1 PM |
54 | |
55 | return ((s32) val); | |
56 | } | |
57 | ||
58 | u32 _s32_to_s13(s32 data) | |
59 | { | |
60 | u32 val; | |
61 | ||
62 | if (data > 4095) | |
66101de1 | 63 | data = 4095; |
66101de1 | 64 | else if (data < -4096) |
66101de1 | 65 | data = -4096; |
66101de1 PM |
66 | |
67 | val = data & 0x1FFF; | |
68 | ||
69 | return val; | |
70 | } | |
71 | ||
72 | /****************************************************************************/ | |
73 | s32 _s4_to_s32(u32 data) | |
74 | { | |
75 | s32 val; | |
76 | ||
77 | val = (data & 0x0007); | |
78 | ||
79 | if ((data & BIT(3)) != 0) | |
66101de1 | 80 | val |= 0xFFFFFFF8; |
66101de1 PM |
81 | |
82 | return val; | |
83 | } | |
84 | ||
85 | u32 _s32_to_s4(s32 data) | |
86 | { | |
87 | u32 val; | |
88 | ||
89 | if (data > 7) | |
66101de1 | 90 | data = 7; |
66101de1 | 91 | else if (data < -8) |
66101de1 | 92 | data = -8; |
66101de1 PM |
93 | |
94 | val = data & 0x000F; | |
95 | ||
96 | return val; | |
97 | } | |
98 | ||
99 | /****************************************************************************/ | |
100 | s32 _s5_to_s32(u32 data) | |
101 | { | |
102 | s32 val; | |
103 | ||
104 | val = (data & 0x000F); | |
105 | ||
106 | if ((data & BIT(4)) != 0) | |
66101de1 | 107 | val |= 0xFFFFFFF0; |
66101de1 PM |
108 | |
109 | return val; | |
110 | } | |
111 | ||
112 | u32 _s32_to_s5(s32 data) | |
113 | { | |
114 | u32 val; | |
115 | ||
116 | if (data > 15) | |
66101de1 | 117 | data = 15; |
66101de1 | 118 | else if (data < -16) |
66101de1 | 119 | data = -16; |
66101de1 PM |
120 | |
121 | val = data & 0x001F; | |
122 | ||
123 | return val; | |
124 | } | |
125 | ||
126 | /****************************************************************************/ | |
127 | s32 _s6_to_s32(u32 data) | |
128 | { | |
129 | s32 val; | |
130 | ||
131 | val = (data & 0x001F); | |
132 | ||
133 | if ((data & BIT(5)) != 0) | |
66101de1 | 134 | val |= 0xFFFFFFE0; |
66101de1 PM |
135 | |
136 | return val; | |
137 | } | |
138 | ||
139 | u32 _s32_to_s6(s32 data) | |
140 | { | |
141 | u32 val; | |
142 | ||
143 | if (data > 31) | |
66101de1 | 144 | data = 31; |
66101de1 | 145 | else if (data < -32) |
66101de1 | 146 | data = -32; |
66101de1 PM |
147 | |
148 | val = data & 0x003F; | |
149 | ||
150 | return val; | |
151 | } | |
152 | ||
153 | /****************************************************************************/ | |
154 | s32 _s9_to_s32(u32 data) | |
155 | { | |
156 | s32 val; | |
157 | ||
158 | val = data & 0x00FF; | |
159 | ||
160 | if ((data & BIT(8)) != 0) | |
66101de1 | 161 | val |= 0xFFFFFF00; |
66101de1 PM |
162 | |
163 | return val; | |
164 | } | |
165 | ||
166 | u32 _s32_to_s9(s32 data) | |
167 | { | |
168 | u32 val; | |
169 | ||
170 | if (data > 255) | |
66101de1 | 171 | data = 255; |
66101de1 | 172 | else if (data < -256) |
66101de1 | 173 | data = -256; |
66101de1 PM |
174 | |
175 | val = data & 0x01FF; | |
176 | ||
177 | return val; | |
178 | } | |
179 | ||
180 | /****************************************************************************/ | |
181 | s32 _floor(s32 n) | |
182 | { | |
183 | if (n > 0) | |
3a4d1b90 | 184 | n += 5; |
66101de1 | 185 | else |
66101de1 | 186 | n -= 5; |
66101de1 PM |
187 | |
188 | return (n/10); | |
189 | } | |
190 | ||
191 | /****************************************************************************/ | |
3a4d1b90 TT |
192 | /* |
193 | * The following code is sqare-root function. | |
194 | * sqsum is the input and the output is sq_rt; | |
195 | * The maximum of sqsum = 2^27 -1; | |
196 | */ | |
66101de1 PM |
197 | u32 _sqrt(u32 sqsum) |
198 | { | |
199 | u32 sq_rt; | |
200 | ||
201 | int g0, g1, g2, g3, g4; | |
202 | int seed; | |
203 | int next; | |
204 | int step; | |
205 | ||
206 | g4 = sqsum / 100000000; | |
3a4d1b90 TT |
207 | g3 = (sqsum - g4*100000000) / 1000000; |
208 | g2 = (sqsum - g4*100000000 - g3*1000000) / 10000; | |
209 | g1 = (sqsum - g4*100000000 - g3*1000000 - g2*10000) / 100; | |
66101de1 PM |
210 | g0 = (sqsum - g4*100000000 - g3*1000000 - g2*10000 - g1*100); |
211 | ||
212 | next = g4; | |
213 | step = 0; | |
214 | seed = 0; | |
3a4d1b90 TT |
215 | while (((seed+1)*(step+1)) <= next) { |
216 | step++; | |
217 | seed++; | |
66101de1 PM |
218 | } |
219 | ||
220 | sq_rt = seed * 10000; | |
221 | next = (next-(seed*step))*100 + g3; | |
222 | ||
223 | step = 0; | |
224 | seed = 2 * seed * 10; | |
3a4d1b90 | 225 | while (((seed+1)*(step+1)) <= next) { |
66101de1 | 226 | step++; |
3a4d1b90 | 227 | seed++; |
66101de1 PM |
228 | } |
229 | ||
230 | sq_rt = sq_rt + step * 1000; | |
231 | next = (next - seed * step) * 100 + g2; | |
232 | seed = (seed + step) * 10; | |
233 | step = 0; | |
3a4d1b90 | 234 | while (((seed+1)*(step+1)) <= next) { |
66101de1 | 235 | step++; |
3a4d1b90 | 236 | seed++; |
66101de1 PM |
237 | } |
238 | ||
239 | sq_rt = sq_rt + step * 100; | |
240 | next = (next - seed * step) * 100 + g1; | |
241 | seed = (seed + step) * 10; | |
242 | step = 0; | |
243 | ||
3a4d1b90 | 244 | while (((seed+1)*(step+1)) <= next) { |
66101de1 | 245 | step++; |
3a4d1b90 | 246 | seed++; |
66101de1 PM |
247 | } |
248 | ||
249 | sq_rt = sq_rt + step * 10; | |
3a4d1b90 | 250 | next = (next - seed * step) * 100 + g0; |
66101de1 PM |
251 | seed = (seed + step) * 10; |
252 | step = 0; | |
253 | ||
3a4d1b90 | 254 | while (((seed+1)*(step+1)) <= next) { |
66101de1 | 255 | step++; |
3a4d1b90 | 256 | seed++; |
66101de1 PM |
257 | } |
258 | ||
259 | sq_rt = sq_rt + step; | |
260 | ||
261 | return sq_rt; | |
262 | } | |
263 | ||
264 | /****************************************************************************/ | |
265 | void _sin_cos(s32 angle, s32 *sin, s32 *cos) | |
266 | { | |
20dbe695 | 267 | s32 X, Y, TargetAngle, CurrAngle; |
66101de1 PM |
268 | unsigned Step; |
269 | ||
3a4d1b90 TT |
270 | X = FIXED(AG_CONST); /* AG_CONST * cos(0) */ |
271 | Y = 0; /* AG_CONST * sin(0) */ | |
272 | TargetAngle = abs(angle); | |
273 | CurrAngle = 0; | |
66101de1 | 274 | |
3a4d1b90 | 275 | for (Step = 0; Step < 12; Step++) { |
20dbe695 | 276 | s32 NewX; |
66101de1 | 277 | |
3a4d1b90 TT |
278 | if (TargetAngle > CurrAngle) { |
279 | NewX = X - (Y >> Step); | |
280 | Y = (X >> Step) + Y; | |
281 | X = NewX; | |
66101de1 | 282 | CurrAngle += Angles[Step]; |
3a4d1b90 TT |
283 | } else { |
284 | NewX = X + (Y >> Step); | |
285 | Y = -(X >> Step) + Y; | |
286 | X = NewX; | |
66101de1 PM |
287 | CurrAngle -= Angles[Step]; |
288 | } | |
289 | } | |
290 | ||
3a4d1b90 | 291 | if (angle > 0) { |
66101de1 PM |
292 | *cos = X; |
293 | *sin = Y; | |
3a4d1b90 | 294 | } else { |
66101de1 PM |
295 | *cos = X; |
296 | *sin = -Y; | |
297 | } | |
298 | } | |
299 | ||
dd68e1b4 PE |
300 | static unsigned char hal_get_dxx_reg(struct hw_data *pHwData, u16 number, u32 * pValue) |
301 | { | |
302 | if (number < 0x1000) | |
303 | number += 0x1000; | |
304 | return Wb35Reg_ReadSync(pHwData, number, pValue); | |
305 | } | |
3a4d1b90 | 306 | #define hw_get_dxx_reg(_A, _B, _C) hal_get_dxx_reg(_A, _B, (u32 *)_C) |
dd68e1b4 PE |
307 | |
308 | static unsigned char hal_set_dxx_reg(struct hw_data *pHwData, u16 number, u32 value) | |
309 | { | |
310 | unsigned char ret; | |
311 | ||
312 | if (number < 0x1000) | |
313 | number += 0x1000; | |
314 | ret = Wb35Reg_WriteSync(pHwData, number, value); | |
315 | return ret; | |
316 | } | |
3a4d1b90 | 317 | #define hw_set_dxx_reg(_A, _B, _C) hal_set_dxx_reg(_A, _B, (u32)_C) |
dd68e1b4 | 318 | |
66101de1 | 319 | |
8e41b4b6 | 320 | void _reset_rx_cal(struct hw_data *phw_data) |
66101de1 PM |
321 | { |
322 | u32 val; | |
323 | ||
324 | hw_get_dxx_reg(phw_data, 0x54, &val); | |
325 | ||
3a4d1b90 | 326 | if (phw_data->revision == 0x2002) /* 1st-cut */ |
66101de1 | 327 | val &= 0xFFFF0000; |
3a4d1b90 | 328 | else /* 2nd-cut */ |
66101de1 | 329 | val &= 0x000003FF; |
66101de1 PM |
330 | |
331 | hw_set_dxx_reg(phw_data, 0x54, val); | |
332 | } | |
333 | ||
334 | ||
3a4d1b90 TT |
335 | /**************for winbond calibration*********/ |
336 | ||
337 | ||
66101de1 | 338 | |
3a4d1b90 | 339 | /**********************************************/ |
8e41b4b6 | 340 | void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequency) |
66101de1 PM |
341 | { |
342 | u32 reg_agc_ctrl3; | |
343 | u32 reg_a_acq_ctrl; | |
344 | u32 reg_b_acq_ctrl; | |
345 | u32 val; | |
346 | ||
347 | PHY_DEBUG(("[CAL] -> [1]_rxadc_dc_offset_cancellation()\n")); | |
348 | phy_init_rf(phw_data); | |
349 | ||
3a4d1b90 TT |
350 | /* set calibration channel */ |
351 | if ((RF_WB_242 == phw_data->phy_type) || | |
352 | (RF_WB_242_1 == phw_data->phy_type)) /* 20060619.5 Add */{ | |
353 | if ((frequency >= 2412) && (frequency <= 2484)) { | |
354 | /* w89rf242 change frequency to 2390Mhz */ | |
66101de1 PM |
355 | PHY_DEBUG(("[CAL] W89RF242/11G/Channel=2390Mhz\n")); |
356 | phy_set_rf_data(phw_data, 3, (3<<24)|0x025586); | |
357 | ||
358 | } | |
3a4d1b90 | 359 | } else { |
66101de1 PM |
360 | |
361 | } | |
362 | ||
3a4d1b90 | 363 | /* reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel */ |
66101de1 PM |
364 | hw_get_dxx_reg(phw_data, 0x5C, &val); |
365 | val &= ~(0x03FF); | |
366 | hw_set_dxx_reg(phw_data, 0x5C, val); | |
367 | ||
3a4d1b90 | 368 | /* reset the TX and RX IQ calibration data */ |
66101de1 PM |
369 | hw_set_dxx_reg(phw_data, 0x3C, 0); |
370 | hw_set_dxx_reg(phw_data, 0x54, 0); | |
371 | ||
3a4d1b90 | 372 | hw_set_dxx_reg(phw_data, 0x58, 0x30303030); /* IQ_Alpha Changed */ |
66101de1 | 373 | |
3a4d1b90 | 374 | /* a. Disable AGC */ |
66101de1 PM |
375 | hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, ®_agc_ctrl3); |
376 | reg_agc_ctrl3 &= ~BIT(2); | |
377 | reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX); | |
378 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3); | |
379 | ||
380 | hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val); | |
381 | val |= MASK_AGC_FIX_GAIN; | |
382 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val); | |
383 | ||
3a4d1b90 | 384 | /* b. Turn off BB RX */ |
66101de1 PM |
385 | hw_get_dxx_reg(phw_data, REG_A_ACQ_CTRL, ®_a_acq_ctrl); |
386 | reg_a_acq_ctrl |= MASK_AMER_OFF_REG; | |
387 | hw_set_dxx_reg(phw_data, REG_A_ACQ_CTRL, reg_a_acq_ctrl); | |
388 | ||
389 | hw_get_dxx_reg(phw_data, REG_B_ACQ_CTRL, ®_b_acq_ctrl); | |
390 | reg_b_acq_ctrl |= MASK_BMER_OFF_REG; | |
391 | hw_set_dxx_reg(phw_data, REG_B_ACQ_CTRL, reg_b_acq_ctrl); | |
392 | ||
3a4d1b90 TT |
393 | /* c. Make sure MAC is in receiving mode |
394 | * d. Turn ON ADC calibration | |
395 | * - ADC calibrator is triggered by this signal rising from 0 to 1 */ | |
66101de1 PM |
396 | hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val); |
397 | val &= ~MASK_ADC_DC_CAL_STR; | |
398 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val); | |
399 | ||
400 | val |= MASK_ADC_DC_CAL_STR; | |
401 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val); | |
66101de1 | 402 | |
3a4d1b90 | 403 | /* e. The result are shown in "adc_dc_cal_i[8:0] and adc_dc_cal_q[8:0]" */ |
66101de1 PM |
404 | #ifdef _DEBUG |
405 | hw_get_dxx_reg(phw_data, REG_OFFSET_READ, &val); | |
406 | PHY_DEBUG(("[CAL] REG_OFFSET_READ = 0x%08X\n", val)); | |
407 | ||
408 | PHY_DEBUG(("[CAL] ** adc_dc_cal_i = %d (0x%04X)\n", | |
409 | _s9_to_s32(val&0x000001FF), val&0x000001FF)); | |
410 | PHY_DEBUG(("[CAL] ** adc_dc_cal_q = %d (0x%04X)\n", | |
411 | _s9_to_s32((val&0x0003FE00)>>9), (val&0x0003FE00)>>9)); | |
412 | #endif | |
413 | ||
414 | hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val); | |
415 | val &= ~MASK_ADC_DC_CAL_STR; | |
416 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, val); | |
417 | ||
3a4d1b90 TT |
418 | /* f. Turn on BB RX */ |
419 | /* hw_get_dxx_reg(phw_data, REG_A_ACQ_CTRL, ®_a_acq_ctrl); */ | |
66101de1 PM |
420 | reg_a_acq_ctrl &= ~MASK_AMER_OFF_REG; |
421 | hw_set_dxx_reg(phw_data, REG_A_ACQ_CTRL, reg_a_acq_ctrl); | |
422 | ||
3a4d1b90 | 423 | /* hw_get_dxx_reg(phw_data, REG_B_ACQ_CTRL, ®_b_acq_ctrl); */ |
66101de1 PM |
424 | reg_b_acq_ctrl &= ~MASK_BMER_OFF_REG; |
425 | hw_set_dxx_reg(phw_data, REG_B_ACQ_CTRL, reg_b_acq_ctrl); | |
426 | ||
3a4d1b90 TT |
427 | /* g. Enable AGC */ |
428 | /* hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val); */ | |
66101de1 PM |
429 | reg_agc_ctrl3 |= BIT(2); |
430 | reg_agc_ctrl3 &= ~(MASK_LNA_FIX_GAIN|MASK_AGC_FIX); | |
431 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3); | |
432 | } | |
433 | ||
3a4d1b90 | 434 | /****************************************************************/ |
8e41b4b6 | 435 | void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) |
66101de1 PM |
436 | { |
437 | u32 reg_agc_ctrl3; | |
438 | u32 reg_mode_ctrl; | |
439 | u32 reg_dc_cancel; | |
440 | s32 iqcal_image_i; | |
441 | s32 iqcal_image_q; | |
442 | u32 sqsum; | |
443 | s32 mag_0; | |
444 | s32 mag_1; | |
445 | s32 fix_cancel_dc_i = 0; | |
446 | u32 val; | |
447 | int loop; | |
448 | ||
449 | PHY_DEBUG(("[CAL] -> [2]_txidac_dc_offset_cancellation()\n")); | |
450 | ||
3a4d1b90 | 451 | /* a. Set to "TX calibration mode" */ |
66101de1 | 452 | |
3a4d1b90 | 453 | /* 0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits */ |
66101de1 | 454 | phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2); |
3a4d1b90 | 455 | /* 0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit */ |
66101de1 | 456 | phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6); |
3a4d1b90 | 457 | /* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */ |
66101de1 | 458 | phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A); |
3a4d1b90 | 459 | /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ |
66101de1 | 460 | phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C); |
3a4d1b90 | 461 | /* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */ |
66101de1 PM |
462 | phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); |
463 | ||
3a4d1b90 | 464 | hw_set_dxx_reg(phw_data, 0x58, 0x30303030); /* IQ_Alpha Changed */ |
66101de1 | 465 | |
3a4d1b90 | 466 | /* a. Disable AGC */ |
66101de1 PM |
467 | hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, ®_agc_ctrl3); |
468 | reg_agc_ctrl3 &= ~BIT(2); | |
469 | reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX); | |
470 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3); | |
471 | ||
472 | hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val); | |
473 | val |= MASK_AGC_FIX_GAIN; | |
474 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val); | |
475 | ||
3a4d1b90 | 476 | /* b. set iqcal_mode[1:0] to 0x2 and set iqcal_tone[3:2] to 0 */ |
66101de1 PM |
477 | hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); |
478 | ||
479 | PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl)); | |
480 | reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); | |
481 | ||
3a4d1b90 TT |
482 | /* mode=2, tone=0 */ |
483 | /* reg_mode_ctrl |= (MASK_CALIB_START|2); */ | |
66101de1 | 484 | |
3a4d1b90 TT |
485 | /* mode=2, tone=1 */ |
486 | /* reg_mode_ctrl |= (MASK_CALIB_START|2|(1<<2)); */ | |
66101de1 | 487 | |
3a4d1b90 | 488 | /* mode=2, tone=2 */ |
66101de1 PM |
489 | reg_mode_ctrl |= (MASK_CALIB_START|2|(2<<2)); |
490 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
491 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
66101de1 PM |
492 | |
493 | hw_get_dxx_reg(phw_data, 0x5C, ®_dc_cancel); | |
494 | PHY_DEBUG(("[CAL] DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel)); | |
495 | ||
3a4d1b90 | 496 | for (loop = 0; loop < LOOP_TIMES; loop++) { |
66101de1 PM |
497 | PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop)); |
498 | ||
3a4d1b90 | 499 | /* c. reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel */ |
66101de1 PM |
500 | reg_dc_cancel &= ~(0x03FF); |
501 | PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); | |
502 | hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); | |
66101de1 PM |
503 | |
504 | hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val); | |
505 | PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val)); | |
506 | ||
507 | iqcal_image_i = _s13_to_s32(val & 0x00001FFF); | |
508 | iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13); | |
509 | sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q; | |
510 | mag_0 = (s32) _sqrt(sqsum); | |
511 | PHY_DEBUG(("[CAL] mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n", | |
512 | mag_0, iqcal_image_i, iqcal_image_q)); | |
513 | ||
3a4d1b90 | 514 | /* d. */ |
66101de1 PM |
515 | reg_dc_cancel |= (1 << CANCEL_DC_I_SHIFT); |
516 | PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); | |
517 | hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); | |
66101de1 PM |
518 | |
519 | hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val); | |
520 | PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val)); | |
521 | ||
522 | iqcal_image_i = _s13_to_s32(val & 0x00001FFF); | |
523 | iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13); | |
524 | sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q; | |
525 | mag_1 = (s32) _sqrt(sqsum); | |
526 | PHY_DEBUG(("[CAL] mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n", | |
527 | mag_1, iqcal_image_i, iqcal_image_q)); | |
528 | ||
3a4d1b90 | 529 | /* e. Calculate the correct DC offset cancellation value for I */ |
66101de1 | 530 | if (mag_0 != mag_1) |
66101de1 | 531 | fix_cancel_dc_i = (mag_0*10000) / (mag_0*10000 - mag_1*10000); |
3a4d1b90 | 532 | else { |
66101de1 | 533 | if (mag_0 == mag_1) |
66101de1 | 534 | PHY_DEBUG(("[CAL] ***** mag_0 = mag_1 !!\n")); |
66101de1 PM |
535 | fix_cancel_dc_i = 0; |
536 | } | |
537 | ||
538 | PHY_DEBUG(("[CAL] ** fix_cancel_dc_i = %d (0x%04X)\n", | |
539 | fix_cancel_dc_i, _s32_to_s5(fix_cancel_dc_i))); | |
540 | ||
541 | if ((abs(mag_1-mag_0)*6) > mag_0) | |
66101de1 | 542 | break; |
66101de1 PM |
543 | } |
544 | ||
3a4d1b90 | 545 | if (loop >= 19) |
66101de1 PM |
546 | fix_cancel_dc_i = 0; |
547 | ||
548 | reg_dc_cancel &= ~(0x03FF); | |
549 | reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_i) << CANCEL_DC_I_SHIFT); | |
550 | hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); | |
551 | PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); | |
552 | ||
3a4d1b90 | 553 | /* g. */ |
66101de1 PM |
554 | reg_mode_ctrl &= ~MASK_CALIB_START; |
555 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
556 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
66101de1 PM |
557 | } |
558 | ||
3a4d1b90 | 559 | /*****************************************************/ |
8e41b4b6 | 560 | void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) |
66101de1 PM |
561 | { |
562 | u32 reg_agc_ctrl3; | |
563 | u32 reg_mode_ctrl; | |
564 | u32 reg_dc_cancel; | |
565 | s32 iqcal_image_i; | |
566 | s32 iqcal_image_q; | |
567 | u32 sqsum; | |
568 | s32 mag_0; | |
569 | s32 mag_1; | |
570 | s32 fix_cancel_dc_q = 0; | |
571 | u32 val; | |
572 | int loop; | |
573 | ||
574 | PHY_DEBUG(("[CAL] -> [3]_txqdac_dc_offset_cacellation()\n")); | |
3a4d1b90 | 575 | /*0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits */ |
66101de1 | 576 | phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2); |
3a4d1b90 | 577 | /* 0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit */ |
66101de1 | 578 | phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6); |
3a4d1b90 | 579 | /* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */ |
66101de1 | 580 | phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A); |
3a4d1b90 | 581 | /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ |
66101de1 | 582 | phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C); |
3a4d1b90 | 583 | /* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */ |
66101de1 PM |
584 | phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); |
585 | ||
3a4d1b90 | 586 | hw_set_dxx_reg(phw_data, 0x58, 0x30303030); /* IQ_Alpha Changed */ |
66101de1 | 587 | |
3a4d1b90 | 588 | /* a. Disable AGC */ |
66101de1 PM |
589 | hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, ®_agc_ctrl3); |
590 | reg_agc_ctrl3 &= ~BIT(2); | |
591 | reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX); | |
592 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3); | |
593 | ||
594 | hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val); | |
595 | val |= MASK_AGC_FIX_GAIN; | |
596 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val); | |
597 | ||
3a4d1b90 | 598 | /* a. set iqcal_mode[1:0] to 0x3 and set iqcal_tone[3:2] to 0 */ |
66101de1 PM |
599 | hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); |
600 | PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl)); | |
601 | ||
3a4d1b90 | 602 | /* reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); */ |
66101de1 PM |
603 | reg_mode_ctrl &= ~(MASK_IQCAL_MODE); |
604 | reg_mode_ctrl |= (MASK_CALIB_START|3); | |
605 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
606 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
66101de1 PM |
607 | |
608 | hw_get_dxx_reg(phw_data, 0x5C, ®_dc_cancel); | |
609 | PHY_DEBUG(("[CAL] DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel)); | |
610 | ||
3a4d1b90 | 611 | for (loop = 0; loop < LOOP_TIMES; loop++) { |
66101de1 PM |
612 | PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop)); |
613 | ||
3a4d1b90 | 614 | /* b. reset cancel_dc_q[4:0] in register DC_Cancel */ |
66101de1 PM |
615 | reg_dc_cancel &= ~(0x001F); |
616 | PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); | |
617 | hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); | |
66101de1 PM |
618 | |
619 | hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val); | |
620 | PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val)); | |
66101de1 PM |
621 | |
622 | iqcal_image_i = _s13_to_s32(val & 0x00001FFF); | |
623 | iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13); | |
624 | sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q; | |
625 | mag_0 = _sqrt(sqsum); | |
626 | PHY_DEBUG(("[CAL] mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n", | |
627 | mag_0, iqcal_image_i, iqcal_image_q)); | |
628 | ||
3a4d1b90 | 629 | /* c. */ |
66101de1 PM |
630 | reg_dc_cancel |= (1 << CANCEL_DC_Q_SHIFT); |
631 | PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); | |
632 | hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); | |
66101de1 PM |
633 | |
634 | hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val); | |
635 | PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val)); | |
66101de1 PM |
636 | |
637 | iqcal_image_i = _s13_to_s32(val & 0x00001FFF); | |
638 | iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13); | |
639 | sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q; | |
640 | mag_1 = _sqrt(sqsum); | |
641 | PHY_DEBUG(("[CAL] mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n", | |
642 | mag_1, iqcal_image_i, iqcal_image_q)); | |
643 | ||
3a4d1b90 | 644 | /* d. Calculate the correct DC offset cancellation value for I */ |
66101de1 | 645 | if (mag_0 != mag_1) |
66101de1 | 646 | fix_cancel_dc_q = (mag_0*10000) / (mag_0*10000 - mag_1*10000); |
3a4d1b90 | 647 | else { |
66101de1 | 648 | if (mag_0 == mag_1) |
66101de1 | 649 | PHY_DEBUG(("[CAL] ***** mag_0 = mag_1 !!\n")); |
66101de1 PM |
650 | fix_cancel_dc_q = 0; |
651 | } | |
652 | ||
653 | PHY_DEBUG(("[CAL] ** fix_cancel_dc_q = %d (0x%04X)\n", | |
654 | fix_cancel_dc_q, _s32_to_s5(fix_cancel_dc_q))); | |
655 | ||
656 | if ((abs(mag_1-mag_0)*6) > mag_0) | |
66101de1 | 657 | break; |
66101de1 PM |
658 | } |
659 | ||
3a4d1b90 | 660 | if (loop >= 19) |
66101de1 PM |
661 | fix_cancel_dc_q = 0; |
662 | ||
663 | reg_dc_cancel &= ~(0x001F); | |
664 | reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_q) << CANCEL_DC_Q_SHIFT); | |
665 | hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel); | |
666 | PHY_DEBUG(("[CAL] DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel)); | |
667 | ||
668 | ||
3a4d1b90 | 669 | /* f. */ |
66101de1 PM |
670 | reg_mode_ctrl &= ~MASK_CALIB_START; |
671 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
672 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
66101de1 PM |
673 | } |
674 | ||
3a4d1b90 | 675 | /* 20060612.1.a 20060718.1 Modify */ |
8e41b4b6 | 676 | u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, |
66101de1 PM |
677 | s32 a_2_threshold, |
678 | s32 b_2_threshold) | |
679 | { | |
680 | u32 reg_mode_ctrl; | |
681 | s32 iq_mag_0_tx; | |
682 | s32 iqcal_tone_i0; | |
683 | s32 iqcal_tone_q0; | |
684 | s32 iqcal_tone_i; | |
685 | s32 iqcal_tone_q; | |
686 | u32 sqsum; | |
687 | s32 rot_i_b; | |
688 | s32 rot_q_b; | |
689 | s32 tx_cal_flt_b[4]; | |
690 | s32 tx_cal[4]; | |
691 | s32 tx_cal_reg[4]; | |
692 | s32 a_2, b_2; | |
693 | s32 sin_b, sin_2b; | |
694 | s32 cos_b, cos_2b; | |
695 | s32 divisor; | |
696 | s32 temp1, temp2; | |
697 | u32 val; | |
698 | u16 loop; | |
3a4d1b90 | 699 | s32 iqcal_tone_i_avg, iqcal_tone_q_avg; |
66101de1 PM |
700 | u8 verify_count; |
701 | int capture_time; | |
702 | ||
703 | PHY_DEBUG(("[CAL] -> _tx_iq_calibration_loop()\n")); | |
704 | PHY_DEBUG(("[CAL] ** a_2_threshold = %d\n", a_2_threshold)); | |
705 | PHY_DEBUG(("[CAL] ** b_2_threshold = %d\n", b_2_threshold)); | |
706 | ||
707 | verify_count = 0; | |
708 | ||
709 | hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); | |
710 | PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl)); | |
711 | ||
712 | loop = LOOP_TIMES; | |
713 | ||
3a4d1b90 | 714 | while (loop > 0) { |
66101de1 PM |
715 | PHY_DEBUG(("[CAL] [%d.] <_tx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1))); |
716 | ||
3a4d1b90 TT |
717 | iqcal_tone_i_avg = 0; |
718 | iqcal_tone_q_avg = 0; | |
719 | if (!hw_set_dxx_reg(phw_data, 0x3C, 0x00)) /* 20060718.1 modify */ | |
66101de1 | 720 | return 0; |
3a4d1b90 TT |
721 | for (capture_time = 0; capture_time < 10; capture_time++) { |
722 | /* | |
723 | * a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to | |
724 | * enable "IQ alibration Mode II" | |
725 | */ | |
66101de1 PM |
726 | reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); |
727 | reg_mode_ctrl &= ~MASK_IQCAL_MODE; | |
728 | reg_mode_ctrl |= (MASK_CALIB_START|0x02); | |
729 | reg_mode_ctrl |= (MASK_CALIB_START|0x02|2<<2); | |
730 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
731 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
66101de1 | 732 | |
3a4d1b90 | 733 | /* b. */ |
66101de1 PM |
734 | hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val); |
735 | PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val)); | |
66101de1 PM |
736 | |
737 | iqcal_tone_i0 = _s13_to_s32(val & 0x00001FFF); | |
738 | iqcal_tone_q0 = _s13_to_s32((val & 0x03FFE000) >> 13); | |
739 | PHY_DEBUG(("[CAL] ** iqcal_tone_i0=%d, iqcal_tone_q0=%d\n", | |
740 | iqcal_tone_i0, iqcal_tone_q0)); | |
741 | ||
742 | sqsum = iqcal_tone_i0*iqcal_tone_i0 + | |
743 | iqcal_tone_q0*iqcal_tone_q0; | |
744 | iq_mag_0_tx = (s32) _sqrt(sqsum); | |
745 | PHY_DEBUG(("[CAL] ** iq_mag_0_tx=%d\n", iq_mag_0_tx)); | |
746 | ||
3a4d1b90 | 747 | /* c. Set "calib_start" to 0x0 */ |
66101de1 PM |
748 | reg_mode_ctrl &= ~MASK_CALIB_START; |
749 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
750 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
66101de1 | 751 | |
3a4d1b90 TT |
752 | /* |
753 | * d. Set iqcal_mode[1:0] to 0x3 and set "calib_start" to 0x1 to | |
754 | * enable "IQ alibration Mode II" | |
755 | */ | |
756 | /* hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val); */ | |
66101de1 PM |
757 | hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); |
758 | reg_mode_ctrl &= ~MASK_IQCAL_MODE; | |
759 | reg_mode_ctrl |= (MASK_CALIB_START|0x03); | |
760 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
761 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
66101de1 | 762 | |
3a4d1b90 | 763 | /* e. */ |
66101de1 PM |
764 | hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val); |
765 | PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val)); | |
66101de1 PM |
766 | |
767 | iqcal_tone_i = _s13_to_s32(val & 0x00001FFF); | |
768 | iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13); | |
769 | PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n", | |
770 | iqcal_tone_i, iqcal_tone_q)); | |
3a4d1b90 | 771 | if (capture_time == 0) |
66101de1 | 772 | continue; |
3a4d1b90 TT |
773 | else { |
774 | iqcal_tone_i_avg = (iqcal_tone_i_avg*(capture_time-1) + iqcal_tone_i)/capture_time; | |
775 | iqcal_tone_q_avg = (iqcal_tone_q_avg*(capture_time-1) + iqcal_tone_q)/capture_time; | |
66101de1 PM |
776 | } |
777 | } | |
778 | ||
779 | iqcal_tone_i = iqcal_tone_i_avg; | |
780 | iqcal_tone_q = iqcal_tone_q_avg; | |
781 | ||
782 | ||
783 | rot_i_b = (iqcal_tone_i * iqcal_tone_i0 + | |
784 | iqcal_tone_q * iqcal_tone_q0) / 1024; | |
785 | rot_q_b = (iqcal_tone_i * iqcal_tone_q0 * (-1) + | |
786 | iqcal_tone_q * iqcal_tone_i0) / 1024; | |
787 | PHY_DEBUG(("[CAL] ** rot_i_b = %d, rot_q_b = %d\n", | |
788 | rot_i_b, rot_q_b)); | |
789 | ||
3a4d1b90 | 790 | /* f. */ |
66101de1 PM |
791 | divisor = ((iq_mag_0_tx * iq_mag_0_tx * 2)/1024 - rot_i_b) * 2; |
792 | ||
3a4d1b90 | 793 | if (divisor == 0) { |
66101de1 PM |
794 | PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> ERROR *******\n")); |
795 | PHY_DEBUG(("[CAL] ** divisor=0 to calculate EPS and THETA !!\n")); | |
796 | PHY_DEBUG(("[CAL] ******************************************\n")); | |
797 | break; | |
798 | } | |
799 | ||
800 | a_2 = (rot_i_b * 32768) / divisor; | |
801 | b_2 = (rot_q_b * (-32768)) / divisor; | |
802 | PHY_DEBUG(("[CAL] ***** EPSILON/2 = %d\n", a_2)); | |
803 | PHY_DEBUG(("[CAL] ***** THETA/2 = %d\n", b_2)); | |
804 | ||
805 | phw_data->iq_rsdl_gain_tx_d2 = a_2; | |
806 | phw_data->iq_rsdl_phase_tx_d2 = b_2; | |
807 | ||
3a4d1b90 TT |
808 | /* if ((abs(a_2) < 150) && (abs(b_2) < 100)) */ |
809 | /* if ((abs(a_2) < 200) && (abs(b_2) < 200)) */ | |
810 | if ((abs(a_2) < a_2_threshold) && (abs(b_2) < b_2_threshold)) { | |
66101de1 PM |
811 | verify_count++; |
812 | ||
813 | PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *************\n")); | |
814 | PHY_DEBUG(("[CAL] ** VERIFY OK # %d !!\n", verify_count)); | |
815 | PHY_DEBUG(("[CAL] ******************************************\n")); | |
816 | ||
3a4d1b90 | 817 | if (verify_count > 2) { |
66101de1 PM |
818 | PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n")); |
819 | PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION (EPS,THETA) OK !!\n")); | |
820 | PHY_DEBUG(("[CAL] **************************************\n")); | |
821 | return 0; | |
822 | } | |
823 | ||
824 | continue; | |
3a4d1b90 | 825 | } else |
66101de1 | 826 | verify_count = 0; |
66101de1 PM |
827 | |
828 | _sin_cos(b_2, &sin_b, &cos_b); | |
829 | _sin_cos(b_2*2, &sin_2b, &cos_2b); | |
830 | PHY_DEBUG(("[CAL] ** sin(b/2)=%d, cos(b/2)=%d\n", sin_b, cos_b)); | |
831 | PHY_DEBUG(("[CAL] ** sin(b)=%d, cos(b)=%d\n", sin_2b, cos_2b)); | |
832 | ||
3a4d1b90 | 833 | if (cos_2b == 0) { |
66101de1 PM |
834 | PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> ERROR *******\n")); |
835 | PHY_DEBUG(("[CAL] ** cos(b)=0 !!\n")); | |
836 | PHY_DEBUG(("[CAL] ******************************************\n")); | |
837 | break; | |
838 | } | |
839 | ||
3a4d1b90 | 840 | /* 1280 * 32768 = 41943040 */ |
66101de1 PM |
841 | temp1 = (41943040/cos_2b)*cos_b; |
842 | ||
3a4d1b90 TT |
843 | /* temp2 = (41943040/cos_2b)*sin_b*(-1); */ |
844 | if (phw_data->revision == 0x2002) /* 1st-cut */ | |
66101de1 | 845 | temp2 = (41943040/cos_2b)*sin_b*(-1); |
3a4d1b90 | 846 | else /* 2nd-cut */ |
66101de1 | 847 | temp2 = (41943040*4/cos_2b)*sin_b*(-1); |
66101de1 PM |
848 | |
849 | tx_cal_flt_b[0] = _floor(temp1/(32768+a_2)); | |
850 | tx_cal_flt_b[1] = _floor(temp2/(32768+a_2)); | |
851 | tx_cal_flt_b[2] = _floor(temp2/(32768-a_2)); | |
852 | tx_cal_flt_b[3] = _floor(temp1/(32768-a_2)); | |
853 | PHY_DEBUG(("[CAL] ** tx_cal_flt_b[0] = %d\n", tx_cal_flt_b[0])); | |
854 | PHY_DEBUG(("[CAL] tx_cal_flt_b[1] = %d\n", tx_cal_flt_b[1])); | |
855 | PHY_DEBUG(("[CAL] tx_cal_flt_b[2] = %d\n", tx_cal_flt_b[2])); | |
856 | PHY_DEBUG(("[CAL] tx_cal_flt_b[3] = %d\n", tx_cal_flt_b[3])); | |
857 | ||
858 | tx_cal[2] = tx_cal_flt_b[2]; | |
3a4d1b90 | 859 | tx_cal[2] = tx_cal[2] + 3; |
66101de1 PM |
860 | tx_cal[1] = tx_cal[2]; |
861 | tx_cal[3] = tx_cal_flt_b[3] - 128; | |
3a4d1b90 | 862 | tx_cal[0] = -tx_cal[3] + 1; |
66101de1 PM |
863 | |
864 | PHY_DEBUG(("[CAL] tx_cal[0] = %d\n", tx_cal[0])); | |
865 | PHY_DEBUG(("[CAL] tx_cal[1] = %d\n", tx_cal[1])); | |
866 | PHY_DEBUG(("[CAL] tx_cal[2] = %d\n", tx_cal[2])); | |
867 | PHY_DEBUG(("[CAL] tx_cal[3] = %d\n", tx_cal[3])); | |
868 | ||
3a4d1b90 TT |
869 | /* if ((tx_cal[0] == 0) && (tx_cal[1] == 0) && |
870 | (tx_cal[2] == 0) && (tx_cal[3] == 0)) | |
871 | { */ | |
872 | /* PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *************\n")); | |
873 | * PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION COMPLETE !!\n")); | |
874 | * PHY_DEBUG(("[CAL] ******************************************\n")); | |
875 | * return 0; | |
876 | } */ | |
877 | ||
878 | /* g. */ | |
879 | if (phw_data->revision == 0x2002) /* 1st-cut */{ | |
66101de1 PM |
880 | hw_get_dxx_reg(phw_data, 0x54, &val); |
881 | PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val)); | |
882 | tx_cal_reg[0] = _s4_to_s32((val & 0xF0000000) >> 28); | |
883 | tx_cal_reg[1] = _s4_to_s32((val & 0x0F000000) >> 24); | |
884 | tx_cal_reg[2] = _s4_to_s32((val & 0x00F00000) >> 20); | |
885 | tx_cal_reg[3] = _s4_to_s32((val & 0x000F0000) >> 16); | |
3a4d1b90 | 886 | } else /* 2nd-cut */{ |
66101de1 PM |
887 | hw_get_dxx_reg(phw_data, 0x3C, &val); |
888 | PHY_DEBUG(("[CAL] ** 0x3C = 0x%08X\n", val)); | |
889 | tx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27); | |
890 | tx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21); | |
891 | tx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15); | |
892 | tx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10); | |
893 | ||
894 | } | |
895 | ||
896 | PHY_DEBUG(("[CAL] ** tx_cal_reg[0] = %d\n", tx_cal_reg[0])); | |
897 | PHY_DEBUG(("[CAL] tx_cal_reg[1] = %d\n", tx_cal_reg[1])); | |
898 | PHY_DEBUG(("[CAL] tx_cal_reg[2] = %d\n", tx_cal_reg[2])); | |
899 | PHY_DEBUG(("[CAL] tx_cal_reg[3] = %d\n", tx_cal_reg[3])); | |
900 | ||
3a4d1b90 TT |
901 | if (phw_data->revision == 0x2002) /* 1st-cut */{ |
902 | if (((tx_cal_reg[0] == 7) || (tx_cal_reg[0] == (-8))) && | |
903 | ((tx_cal_reg[3] == 7) || (tx_cal_reg[3] == (-8)))) { | |
66101de1 PM |
904 | PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n")); |
905 | PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION SATUATION !!\n")); | |
906 | PHY_DEBUG(("[CAL] **************************************\n")); | |
907 | break; | |
908 | } | |
3a4d1b90 TT |
909 | } else /* 2nd-cut */{ |
910 | if (((tx_cal_reg[0] == 31) || (tx_cal_reg[0] == (-32))) && | |
911 | ((tx_cal_reg[3] == 31) || (tx_cal_reg[3] == (-32)))) { | |
66101de1 PM |
912 | PHY_DEBUG(("[CAL] ** <_tx_iq_calibration_loop> *********\n")); |
913 | PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION SATUATION !!\n")); | |
914 | PHY_DEBUG(("[CAL] **************************************\n")); | |
915 | break; | |
916 | } | |
917 | } | |
918 | ||
919 | tx_cal[0] = tx_cal[0] + tx_cal_reg[0]; | |
920 | tx_cal[1] = tx_cal[1] + tx_cal_reg[1]; | |
921 | tx_cal[2] = tx_cal[2] + tx_cal_reg[2]; | |
922 | tx_cal[3] = tx_cal[3] + tx_cal_reg[3]; | |
923 | PHY_DEBUG(("[CAL] ** apply tx_cal[0] = %d\n", tx_cal[0])); | |
924 | PHY_DEBUG(("[CAL] apply tx_cal[1] = %d\n", tx_cal[1])); | |
925 | PHY_DEBUG(("[CAL] apply tx_cal[2] = %d\n", tx_cal[2])); | |
926 | PHY_DEBUG(("[CAL] apply tx_cal[3] = %d\n", tx_cal[3])); | |
927 | ||
3a4d1b90 | 928 | if (phw_data->revision == 0x2002) /* 1st-cut */{ |
66101de1 PM |
929 | val &= 0x0000FFFF; |
930 | val |= ((_s32_to_s4(tx_cal[0]) << 28)| | |
931 | (_s32_to_s4(tx_cal[1]) << 24)| | |
932 | (_s32_to_s4(tx_cal[2]) << 20)| | |
933 | (_s32_to_s4(tx_cal[3]) << 16)); | |
934 | hw_set_dxx_reg(phw_data, 0x54, val); | |
935 | PHY_DEBUG(("[CAL] ** CALIB_DATA = 0x%08X\n", val)); | |
936 | return 0; | |
3a4d1b90 | 937 | } else /* 2nd-cut */{ |
66101de1 PM |
938 | val &= 0x000003FF; |
939 | val |= ((_s32_to_s5(tx_cal[0]) << 27)| | |
940 | (_s32_to_s6(tx_cal[1]) << 21)| | |
941 | (_s32_to_s6(tx_cal[2]) << 15)| | |
942 | (_s32_to_s5(tx_cal[3]) << 10)); | |
943 | hw_set_dxx_reg(phw_data, 0x3C, val); | |
944 | PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION = 0x%08X\n", val)); | |
945 | return 0; | |
946 | } | |
947 | ||
3a4d1b90 | 948 | /* i. Set "calib_start" to 0x0 */ |
66101de1 PM |
949 | reg_mode_ctrl &= ~MASK_CALIB_START; |
950 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
951 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
952 | ||
953 | loop--; | |
954 | } | |
955 | ||
956 | return 1; | |
957 | } | |
958 | ||
8e41b4b6 | 959 | void _tx_iq_calibration_winbond(struct hw_data *phw_data) |
66101de1 PM |
960 | { |
961 | u32 reg_agc_ctrl3; | |
962 | #ifdef _DEBUG | |
963 | s32 tx_cal_reg[4]; | |
964 | ||
965 | #endif | |
966 | u32 reg_mode_ctrl; | |
967 | u32 val; | |
968 | u8 result; | |
969 | ||
970 | PHY_DEBUG(("[CAL] -> [4]_tx_iq_calibration()\n")); | |
971 | ||
3a4d1b90 | 972 | /* 0x01 0xEE3FC2 ; 3B8FF ; Calibration (6a). enable TX IQ calibration loop circuits */ |
66101de1 | 973 | phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2); |
3a4d1b90 TT |
974 | /* 0x0B 0x1905D6 ; 06417 ; Calibration (6b). enable TX I/Q cal loop squaring circuit */ |
975 | phy_set_rf_data(phw_data, 11, (11<<24)|0x19BDD6); /* 20060612.1.a 0x1905D6); */ | |
976 | /* 0x05 0x24C60A ; 09318 ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */ | |
977 | phy_set_rf_data(phw_data, 5, (5<<24)|0x24C60A); /* 0x24C60A (high temperature) */ | |
978 | /* 0x06 0x06880C ; 01A20 ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */ | |
979 | phy_set_rf_data(phw_data, 6, (6<<24)|0x34880C); /* 20060612.1.a 0x06890C); */ | |
980 | /* 0x00 0xFDF1C0 ; 3F7C7 ; Calibration (6e). turn on IQ imbalance/Test mode */ | |
66101de1 | 981 | phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0); |
3a4d1b90 TT |
982 | /* ; [BB-chip]: Calibration (6f).Send test pattern */ |
983 | /* ; [BB-chip]: Calibration (6g). Search RXGCL optimal value */ | |
984 | /* ; [BB-chip]: Calibration (6h). Caculate TX-path IQ imbalance and setting TX path IQ compensation table */ | |
985 | /* phy_set_rf_data(phw_data, 3, (3<<24)|0x025586); */ | |
66101de1 | 986 | |
3a4d1b90 TT |
987 | msleep(30); /* 20060612.1.a 30ms delay. Add the follow 2 lines */ |
988 | /* To adjust TXVGA to fit iq_mag_0 range from 1250 ~ 1750 */ | |
989 | adjust_TXVGA_for_iq_mag(phw_data); | |
66101de1 | 990 | |
3a4d1b90 | 991 | /* a. Disable AGC */ |
66101de1 PM |
992 | hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, ®_agc_ctrl3); |
993 | reg_agc_ctrl3 &= ~BIT(2); | |
994 | reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX); | |
995 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3); | |
996 | ||
997 | hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val); | |
998 | val |= MASK_AGC_FIX_GAIN; | |
999 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val); | |
1000 | ||
1001 | result = _tx_iq_calibration_loop_winbond(phw_data, 150, 100); | |
1002 | ||
3a4d1b90 TT |
1003 | if (result > 0) { |
1004 | if (phw_data->revision == 0x2002) /* 1st-cut */{ | |
66101de1 PM |
1005 | hw_get_dxx_reg(phw_data, 0x54, &val); |
1006 | val &= 0x0000FFFF; | |
1007 | hw_set_dxx_reg(phw_data, 0x54, val); | |
3a4d1b90 | 1008 | } else /* 2nd-cut*/{ |
66101de1 PM |
1009 | hw_get_dxx_reg(phw_data, 0x3C, &val); |
1010 | val &= 0x000003FF; | |
1011 | hw_set_dxx_reg(phw_data, 0x3C, val); | |
1012 | } | |
1013 | ||
1014 | result = _tx_iq_calibration_loop_winbond(phw_data, 300, 200); | |
1015 | ||
3a4d1b90 TT |
1016 | if (result > 0) { |
1017 | if (phw_data->revision == 0x2002) /* 1st-cut */{ | |
66101de1 PM |
1018 | hw_get_dxx_reg(phw_data, 0x54, &val); |
1019 | val &= 0x0000FFFF; | |
1020 | hw_set_dxx_reg(phw_data, 0x54, val); | |
3a4d1b90 | 1021 | } else /* 2nd-cut*/{ |
66101de1 PM |
1022 | hw_get_dxx_reg(phw_data, 0x3C, &val); |
1023 | val &= 0x000003FF; | |
1024 | hw_set_dxx_reg(phw_data, 0x3C, val); | |
1025 | } | |
1026 | ||
1027 | result = _tx_iq_calibration_loop_winbond(phw_data, 500, 400); | |
3a4d1b90 TT |
1028 | if (result > 0) { |
1029 | if (phw_data->revision == 0x2002) /* 1st-cut */{ | |
66101de1 PM |
1030 | hw_get_dxx_reg(phw_data, 0x54, &val); |
1031 | val &= 0x0000FFFF; | |
1032 | hw_set_dxx_reg(phw_data, 0x54, val); | |
3a4d1b90 | 1033 | } else /* 2nd-cut */{ |
66101de1 PM |
1034 | hw_get_dxx_reg(phw_data, 0x3C, &val); |
1035 | val &= 0x000003FF; | |
1036 | hw_set_dxx_reg(phw_data, 0x3C, val); | |
1037 | } | |
1038 | ||
1039 | ||
1040 | result = _tx_iq_calibration_loop_winbond(phw_data, 700, 500); | |
1041 | ||
3a4d1b90 | 1042 | if (result > 0) { |
66101de1 PM |
1043 | PHY_DEBUG(("[CAL] ** <_tx_iq_calibration> **************\n")); |
1044 | PHY_DEBUG(("[CAL] ** TX_IQ_CALIBRATION FAILURE !!\n")); | |
1045 | PHY_DEBUG(("[CAL] **************************************\n")); | |
1046 | ||
3a4d1b90 | 1047 | if (phw_data->revision == 0x2002) /* 1st-cut */{ |
66101de1 PM |
1048 | hw_get_dxx_reg(phw_data, 0x54, &val); |
1049 | val &= 0x0000FFFF; | |
1050 | hw_set_dxx_reg(phw_data, 0x54, val); | |
3a4d1b90 | 1051 | } else /* 2nd-cut */{ |
66101de1 PM |
1052 | hw_get_dxx_reg(phw_data, 0x3C, &val); |
1053 | val &= 0x000003FF; | |
1054 | hw_set_dxx_reg(phw_data, 0x3C, val); | |
1055 | } | |
1056 | } | |
1057 | } | |
1058 | } | |
1059 | } | |
1060 | ||
3a4d1b90 | 1061 | /* i. Set "calib_start" to 0x0 */ |
66101de1 PM |
1062 | hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); |
1063 | reg_mode_ctrl &= ~MASK_CALIB_START; | |
1064 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
1065 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
1066 | ||
3a4d1b90 TT |
1067 | /* g. Enable AGC */ |
1068 | /* hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &val); */ | |
66101de1 PM |
1069 | reg_agc_ctrl3 |= BIT(2); |
1070 | reg_agc_ctrl3 &= ~(MASK_LNA_FIX_GAIN|MASK_AGC_FIX); | |
1071 | hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3); | |
1072 | ||
1073 | #ifdef _DEBUG | |
3a4d1b90 | 1074 | if (phw_data->revision == 0x2002) /* 1st-cut */{ |
66101de1 PM |
1075 | hw_get_dxx_reg(phw_data, 0x54, &val); |
1076 | PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val)); | |
1077 | tx_cal_reg[0] = _s4_to_s32((val & 0xF0000000) >> 28); | |
1078 | tx_cal_reg[1] = _s4_to_s32((val & 0x0F000000) >> 24); | |
1079 | tx_cal_reg[2] = _s4_to_s32((val & 0x00F00000) >> 20); | |
1080 | tx_cal_reg[3] = _s4_to_s32((val & 0x000F0000) >> 16); | |
3a4d1b90 | 1081 | } else /* 2nd-cut */ { |
66101de1 PM |
1082 | hw_get_dxx_reg(phw_data, 0x3C, &val); |
1083 | PHY_DEBUG(("[CAL] ** 0x3C = 0x%08X\n", val)); | |
1084 | tx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27); | |
1085 | tx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21); | |
1086 | tx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15); | |
1087 | tx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10); | |
1088 | ||
1089 | } | |
1090 | ||
1091 | PHY_DEBUG(("[CAL] ** tx_cal_reg[0] = %d\n", tx_cal_reg[0])); | |
1092 | PHY_DEBUG(("[CAL] tx_cal_reg[1] = %d\n", tx_cal_reg[1])); | |
1093 | PHY_DEBUG(("[CAL] tx_cal_reg[2] = %d\n", tx_cal_reg[2])); | |
1094 | PHY_DEBUG(("[CAL] tx_cal_reg[3] = %d\n", tx_cal_reg[3])); | |
1095 | #endif | |
1096 | ||
1097 | ||
3a4d1b90 TT |
1098 | /* |
1099 | * for test - BEN | |
1100 | * RF Control Override | |
1101 | */ | |
66101de1 PM |
1102 | } |
1103 | ||
3a4d1b90 | 1104 | /*****************************************************/ |
8e41b4b6 | 1105 | u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 frequency) |
66101de1 PM |
1106 | { |
1107 | u32 reg_mode_ctrl; | |
1108 | s32 iqcal_tone_i; | |
1109 | s32 iqcal_tone_q; | |
1110 | s32 iqcal_image_i; | |
1111 | s32 iqcal_image_q; | |
1112 | s32 rot_tone_i_b; | |
1113 | s32 rot_tone_q_b; | |
1114 | s32 rot_image_i_b; | |
1115 | s32 rot_image_q_b; | |
1116 | s32 rx_cal_flt_b[4]; | |
1117 | s32 rx_cal[4]; | |
1118 | s32 rx_cal_reg[4]; | |
1119 | s32 a_2, b_2; | |
1120 | s32 sin_b, sin_2b; | |
1121 | s32 cos_b, cos_2b; | |
1122 | s32 temp1, temp2; | |
1123 | u32 val; | |
1124 | u16 loop; | |
1125 | ||
1126 | u32 pwr_tone; | |
1127 | u32 pwr_image; | |
1128 | u8 verify_count; | |
1129 | ||
3a4d1b90 TT |
1130 | s32 iqcal_tone_i_avg, iqcal_tone_q_avg; |
1131 | s32 iqcal_image_i_avg, iqcal_image_q_avg; | |
1132 | u16 capture_time; | |
66101de1 PM |
1133 | |
1134 | PHY_DEBUG(("[CAL] -> [5]_rx_iq_calibration_loop()\n")); | |
1135 | PHY_DEBUG(("[CAL] ** factor = %d\n", factor)); | |
1136 | ||
3a4d1b90 | 1137 | hw_set_dxx_reg(phw_data, 0x58, 0x44444444); /* IQ_Alpha */ |
66101de1 | 1138 | |
3a4d1b90 | 1139 | /* b. */ |
66101de1 PM |
1140 | |
1141 | hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); | |
1142 | PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl)); | |
1143 | ||
1144 | verify_count = 0; | |
1145 | ||
3a4d1b90 TT |
1146 | /* for (loop = 0; loop < 1; loop++) */ |
1147 | /* for (loop = 0; loop < LOOP_TIMES; loop++) */ | |
66101de1 | 1148 | loop = LOOP_TIMES; |
3a4d1b90 | 1149 | while (loop > 0) { |
66101de1 | 1150 | PHY_DEBUG(("[CAL] [%d.] <_rx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1))); |
3a4d1b90 TT |
1151 | iqcal_tone_i_avg = 0; |
1152 | iqcal_tone_q_avg = 0; | |
1153 | iqcal_image_i_avg = 0; | |
1154 | iqcal_image_q_avg = 0; | |
1155 | capture_time = 0; | |
1156 | ||
1157 | for (capture_time = 0; capture_time < 10; capture_time++) { | |
1158 | /* i. Set "calib_start" to 0x0 */ | |
66101de1 | 1159 | reg_mode_ctrl &= ~MASK_CALIB_START; |
3a4d1b90 | 1160 | if (!hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl))/*20060718.1 modify */ |
66101de1 PM |
1161 | return 0; |
1162 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
66101de1 PM |
1163 | |
1164 | reg_mode_ctrl &= ~MASK_IQCAL_MODE; | |
1165 | reg_mode_ctrl |= (MASK_CALIB_START|0x1); | |
1166 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
1167 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
66101de1 | 1168 | |
3a4d1b90 | 1169 | /* c. */ |
66101de1 PM |
1170 | hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val); |
1171 | PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val)); | |
1172 | ||
1173 | iqcal_tone_i = _s13_to_s32(val & 0x00001FFF); | |
1174 | iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13); | |
1175 | PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n", | |
1176 | iqcal_tone_i, iqcal_tone_q)); | |
1177 | ||
1178 | hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val); | |
1179 | PHY_DEBUG(("[CAL] CALIB_READ2 = 0x%08X\n", val)); | |
1180 | ||
1181 | iqcal_image_i = _s13_to_s32(val & 0x00001FFF); | |
1182 | iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13); | |
1183 | PHY_DEBUG(("[CAL] ** iqcal_image_i = %d, iqcal_image_q = %d\n", | |
1184 | iqcal_image_i, iqcal_image_q)); | |
3a4d1b90 | 1185 | if (capture_time == 0) |
66101de1 | 1186 | continue; |
3a4d1b90 TT |
1187 | else { |
1188 | iqcal_image_i_avg = (iqcal_image_i_avg*(capture_time-1) + iqcal_image_i)/capture_time; | |
1189 | iqcal_image_q_avg = (iqcal_image_q_avg*(capture_time-1) + iqcal_image_q)/capture_time; | |
1190 | iqcal_tone_i_avg = (iqcal_tone_i_avg*(capture_time-1) + iqcal_tone_i)/capture_time; | |
1191 | iqcal_tone_q_avg = (iqcal_tone_q_avg*(capture_time-1) + iqcal_tone_q)/capture_time; | |
66101de1 PM |
1192 | } |
1193 | } | |
1194 | ||
1195 | ||
1196 | iqcal_image_i = iqcal_image_i_avg; | |
1197 | iqcal_image_q = iqcal_image_q_avg; | |
1198 | iqcal_tone_i = iqcal_tone_i_avg; | |
1199 | iqcal_tone_q = iqcal_tone_q_avg; | |
1200 | ||
3a4d1b90 | 1201 | /* d. */ |
66101de1 PM |
1202 | rot_tone_i_b = (iqcal_tone_i * iqcal_tone_i + |
1203 | iqcal_tone_q * iqcal_tone_q) / 1024; | |
1204 | rot_tone_q_b = (iqcal_tone_i * iqcal_tone_q * (-1) + | |
1205 | iqcal_tone_q * iqcal_tone_i) / 1024; | |
1206 | rot_image_i_b = (iqcal_image_i * iqcal_tone_i - | |
1207 | iqcal_image_q * iqcal_tone_q) / 1024; | |
1208 | rot_image_q_b = (iqcal_image_i * iqcal_tone_q + | |
1209 | iqcal_image_q * iqcal_tone_i) / 1024; | |
1210 | ||
1211 | PHY_DEBUG(("[CAL] ** rot_tone_i_b = %d\n", rot_tone_i_b)); | |
1212 | PHY_DEBUG(("[CAL] ** rot_tone_q_b = %d\n", rot_tone_q_b)); | |
1213 | PHY_DEBUG(("[CAL] ** rot_image_i_b = %d\n", rot_image_i_b)); | |
1214 | PHY_DEBUG(("[CAL] ** rot_image_q_b = %d\n", rot_image_q_b)); | |
1215 | ||
3a4d1b90 TT |
1216 | /* f. */ |
1217 | if (rot_tone_i_b == 0) { | |
66101de1 PM |
1218 | PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> ERROR *******\n")); |
1219 | PHY_DEBUG(("[CAL] ** rot_tone_i_b=0 to calculate EPS and THETA !!\n")); | |
1220 | PHY_DEBUG(("[CAL] ******************************************\n")); | |
1221 | break; | |
1222 | } | |
1223 | ||
1224 | a_2 = (rot_image_i_b * 32768) / rot_tone_i_b - | |
1225 | phw_data->iq_rsdl_gain_tx_d2; | |
1226 | b_2 = (rot_image_q_b * 32768) / rot_tone_i_b - | |
1227 | phw_data->iq_rsdl_phase_tx_d2; | |
1228 | ||
1229 | PHY_DEBUG(("[CAL] ** iq_rsdl_gain_tx_d2 = %d\n", phw_data->iq_rsdl_gain_tx_d2)); | |
1230 | PHY_DEBUG(("[CAL] ** iq_rsdl_phase_tx_d2= %d\n", phw_data->iq_rsdl_phase_tx_d2)); | |
1231 | PHY_DEBUG(("[CAL] ***** EPSILON/2 = %d\n", a_2)); | |
1232 | PHY_DEBUG(("[CAL] ***** THETA/2 = %d\n", b_2)); | |
1233 | ||
1234 | _sin_cos(b_2, &sin_b, &cos_b); | |
1235 | _sin_cos(b_2*2, &sin_2b, &cos_2b); | |
1236 | PHY_DEBUG(("[CAL] ** sin(b/2)=%d, cos(b/2)=%d\n", sin_b, cos_b)); | |
1237 | PHY_DEBUG(("[CAL] ** sin(b)=%d, cos(b)=%d\n", sin_2b, cos_2b)); | |
1238 | ||
3a4d1b90 | 1239 | if (cos_2b == 0) { |
66101de1 PM |
1240 | PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> ERROR *******\n")); |
1241 | PHY_DEBUG(("[CAL] ** cos(b)=0 !!\n")); | |
1242 | PHY_DEBUG(("[CAL] ******************************************\n")); | |
1243 | break; | |
1244 | } | |
1245 | ||
3a4d1b90 | 1246 | /* 1280 * 32768 = 41943040 */ |
66101de1 PM |
1247 | temp1 = (41943040/cos_2b)*cos_b; |
1248 | ||
3a4d1b90 TT |
1249 | /* temp2 = (41943040/cos_2b)*sin_b*(-1); */ |
1250 | if (phw_data->revision == 0x2002)/* 1st-cut */ | |
66101de1 | 1251 | temp2 = (41943040/cos_2b)*sin_b*(-1); |
3a4d1b90 | 1252 | else/* 2nd-cut */ |
66101de1 | 1253 | temp2 = (41943040*4/cos_2b)*sin_b*(-1); |
66101de1 PM |
1254 | |
1255 | rx_cal_flt_b[0] = _floor(temp1/(32768+a_2)); | |
1256 | rx_cal_flt_b[1] = _floor(temp2/(32768-a_2)); | |
1257 | rx_cal_flt_b[2] = _floor(temp2/(32768+a_2)); | |
1258 | rx_cal_flt_b[3] = _floor(temp1/(32768-a_2)); | |
1259 | ||
1260 | PHY_DEBUG(("[CAL] ** rx_cal_flt_b[0] = %d\n", rx_cal_flt_b[0])); | |
1261 | PHY_DEBUG(("[CAL] rx_cal_flt_b[1] = %d\n", rx_cal_flt_b[1])); | |
1262 | PHY_DEBUG(("[CAL] rx_cal_flt_b[2] = %d\n", rx_cal_flt_b[2])); | |
1263 | PHY_DEBUG(("[CAL] rx_cal_flt_b[3] = %d\n", rx_cal_flt_b[3])); | |
1264 | ||
1265 | rx_cal[0] = rx_cal_flt_b[0] - 128; | |
1266 | rx_cal[1] = rx_cal_flt_b[1]; | |
1267 | rx_cal[2] = rx_cal_flt_b[2]; | |
1268 | rx_cal[3] = rx_cal_flt_b[3] - 128; | |
1269 | PHY_DEBUG(("[CAL] ** rx_cal[0] = %d\n", rx_cal[0])); | |
1270 | PHY_DEBUG(("[CAL] rx_cal[1] = %d\n", rx_cal[1])); | |
1271 | PHY_DEBUG(("[CAL] rx_cal[2] = %d\n", rx_cal[2])); | |
1272 | PHY_DEBUG(("[CAL] rx_cal[3] = %d\n", rx_cal[3])); | |
1273 | ||
3a4d1b90 | 1274 | /* e. */ |
66101de1 PM |
1275 | pwr_tone = (iqcal_tone_i*iqcal_tone_i + iqcal_tone_q*iqcal_tone_q); |
1276 | pwr_image = (iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q)*factor; | |
1277 | ||
1278 | PHY_DEBUG(("[CAL] ** pwr_tone = %d\n", pwr_tone)); | |
1279 | PHY_DEBUG(("[CAL] ** pwr_image = %d\n", pwr_image)); | |
1280 | ||
3a4d1b90 | 1281 | if (pwr_tone > pwr_image) { |
66101de1 PM |
1282 | verify_count++; |
1283 | ||
1284 | PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *************\n")); | |
1285 | PHY_DEBUG(("[CAL] ** VERIFY OK # %d !!\n", verify_count)); | |
1286 | PHY_DEBUG(("[CAL] ******************************************\n")); | |
1287 | ||
3a4d1b90 | 1288 | if (verify_count > 2) { |
66101de1 PM |
1289 | PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n")); |
1290 | PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION OK !!\n")); | |
1291 | PHY_DEBUG(("[CAL] **************************************\n")); | |
1292 | return 0; | |
1293 | } | |
1294 | ||
1295 | continue; | |
1296 | } | |
3a4d1b90 | 1297 | /* g. */ |
66101de1 PM |
1298 | hw_get_dxx_reg(phw_data, 0x54, &val); |
1299 | PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val)); | |
1300 | ||
3a4d1b90 | 1301 | if (phw_data->revision == 0x2002) /* 1st-cut */{ |
66101de1 PM |
1302 | rx_cal_reg[0] = _s4_to_s32((val & 0x0000F000) >> 12); |
1303 | rx_cal_reg[1] = _s4_to_s32((val & 0x00000F00) >> 8); | |
1304 | rx_cal_reg[2] = _s4_to_s32((val & 0x000000F0) >> 4); | |
1305 | rx_cal_reg[3] = _s4_to_s32((val & 0x0000000F)); | |
3a4d1b90 | 1306 | } else /* 2nd-cut */{ |
66101de1 PM |
1307 | rx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27); |
1308 | rx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21); | |
1309 | rx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15); | |
1310 | rx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10); | |
1311 | } | |
1312 | ||
1313 | PHY_DEBUG(("[CAL] ** rx_cal_reg[0] = %d\n", rx_cal_reg[0])); | |
1314 | PHY_DEBUG(("[CAL] rx_cal_reg[1] = %d\n", rx_cal_reg[1])); | |
1315 | PHY_DEBUG(("[CAL] rx_cal_reg[2] = %d\n", rx_cal_reg[2])); | |
1316 | PHY_DEBUG(("[CAL] rx_cal_reg[3] = %d\n", rx_cal_reg[3])); | |
1317 | ||
3a4d1b90 TT |
1318 | if (phw_data->revision == 0x2002) /* 1st-cut */{ |
1319 | if (((rx_cal_reg[0] == 7) || (rx_cal_reg[0] == (-8))) && | |
1320 | ((rx_cal_reg[3] == 7) || (rx_cal_reg[3] == (-8)))) { | |
66101de1 PM |
1321 | PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n")); |
1322 | PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION SATUATION !!\n")); | |
1323 | PHY_DEBUG(("[CAL] **************************************\n")); | |
1324 | break; | |
1325 | } | |
3a4d1b90 TT |
1326 | } else /* 2nd-cut */{ |
1327 | if (((rx_cal_reg[0] == 31) || (rx_cal_reg[0] == (-32))) && | |
1328 | ((rx_cal_reg[3] == 31) || (rx_cal_reg[3] == (-32)))) { | |
66101de1 PM |
1329 | PHY_DEBUG(("[CAL] ** <_rx_iq_calibration_loop> *********\n")); |
1330 | PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION SATUATION !!\n")); | |
1331 | PHY_DEBUG(("[CAL] **************************************\n")); | |
1332 | break; | |
1333 | } | |
1334 | } | |
1335 | ||
1336 | rx_cal[0] = rx_cal[0] + rx_cal_reg[0]; | |
1337 | rx_cal[1] = rx_cal[1] + rx_cal_reg[1]; | |
1338 | rx_cal[2] = rx_cal[2] + rx_cal_reg[2]; | |
1339 | rx_cal[3] = rx_cal[3] + rx_cal_reg[3]; | |
1340 | PHY_DEBUG(("[CAL] ** apply rx_cal[0] = %d\n", rx_cal[0])); | |
1341 | PHY_DEBUG(("[CAL] apply rx_cal[1] = %d\n", rx_cal[1])); | |
1342 | PHY_DEBUG(("[CAL] apply rx_cal[2] = %d\n", rx_cal[2])); | |
1343 | PHY_DEBUG(("[CAL] apply rx_cal[3] = %d\n", rx_cal[3])); | |
1344 | ||
1345 | hw_get_dxx_reg(phw_data, 0x54, &val); | |
3a4d1b90 | 1346 | if (phw_data->revision == 0x2002) /* 1st-cut */{ |
66101de1 PM |
1347 | val &= 0x0000FFFF; |
1348 | val |= ((_s32_to_s4(rx_cal[0]) << 12)| | |
1349 | (_s32_to_s4(rx_cal[1]) << 8)| | |
1350 | (_s32_to_s4(rx_cal[2]) << 4)| | |
1351 | (_s32_to_s4(rx_cal[3]))); | |
1352 | hw_set_dxx_reg(phw_data, 0x54, val); | |
3a4d1b90 | 1353 | } else /* 2nd-cut */{ |
66101de1 PM |
1354 | val &= 0x000003FF; |
1355 | val |= ((_s32_to_s5(rx_cal[0]) << 27)| | |
1356 | (_s32_to_s6(rx_cal[1]) << 21)| | |
1357 | (_s32_to_s6(rx_cal[2]) << 15)| | |
1358 | (_s32_to_s5(rx_cal[3]) << 10)); | |
1359 | hw_set_dxx_reg(phw_data, 0x54, val); | |
1360 | ||
3a4d1b90 | 1361 | if (loop == 3) |
66101de1 PM |
1362 | return 0; |
1363 | } | |
1364 | PHY_DEBUG(("[CAL] ** CALIB_DATA = 0x%08X\n", val)); | |
1365 | ||
1366 | loop--; | |
1367 | } | |
1368 | ||
1369 | return 1; | |
1370 | } | |
1371 | ||
3a4d1b90 | 1372 | /*************************************************/ |
66101de1 | 1373 | |
3a4d1b90 | 1374 | /***************************************************************/ |
8e41b4b6 | 1375 | void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency) |
66101de1 | 1376 | { |
3a4d1b90 | 1377 | /* figo 20050523 marked this flag for can't compile for relesase */ |
66101de1 PM |
1378 | #ifdef _DEBUG |
1379 | s32 rx_cal_reg[4]; | |
1380 | u32 val; | |
1381 | #endif | |
1382 | ||
1383 | u8 result; | |
1384 | ||
1385 | PHY_DEBUG(("[CAL] -> [5]_rx_iq_calibration()\n")); | |
3a4d1b90 TT |
1386 | /* a. Set RFIC to "RX calibration mode" */ |
1387 | /* ; ----- Calibration (7). RX path IQ imbalance calibration loop */ | |
1388 | /* 0x01 0xFFBFC2 ; 3FEFF ; Calibration (7a). enable RX IQ calibration loop circuits */ | |
66101de1 | 1389 | phy_set_rf_data(phw_data, 1, (1<<24)|0xEFBFC2); |
3a4d1b90 | 1390 | /* 0x0B 0x1A01D6 ; 06817 ; Calibration (7b). enable RX I/Q cal loop SW1 circuits */ |
66101de1 | 1391 | phy_set_rf_data(phw_data, 11, (11<<24)|0x1A05D6); |
3a4d1b90 TT |
1392 | /* 0x05 0x24848A ; 09212 ; Calibration (7c). setting TX-VGA gain (TXGCH) to 2 --> to be optimized */ |
1393 | phy_set_rf_data(phw_data, 5, (5<<24) | phw_data->txvga_setting_for_cal); | |
1394 | /* 0x06 0x06840C ; 01A10 ; Calibration (7d). RXGCH=00; RXGCL=010 000 (RXVGA) --> to be optimized */ | |
66101de1 | 1395 | phy_set_rf_data(phw_data, 6, (6<<24)|0x06834C); |
3a4d1b90 | 1396 | /* 0x00 0xFFF1C0 ; 3F7C7 ; Calibration (7e). turn on IQ imbalance/Test mode */ |
66101de1 PM |
1397 | phy_set_rf_data(phw_data, 0, (0<<24)|0xFFF1C0); |
1398 | ||
3a4d1b90 TT |
1399 | /* ; [BB-chip]: Calibration (7f). Send test pattern */ |
1400 | /* ; [BB-chip]: Calibration (7g). Search RXGCL optimal value */ | |
1401 | /* ; [BB-chip]: Calibration (7h). Caculate RX-path IQ imbalance and setting RX path IQ compensation table */ | |
66101de1 PM |
1402 | |
1403 | result = _rx_iq_calibration_loop_winbond(phw_data, 12589, frequency); | |
1404 | ||
3a4d1b90 | 1405 | if (result > 0) { |
66101de1 PM |
1406 | _reset_rx_cal(phw_data); |
1407 | result = _rx_iq_calibration_loop_winbond(phw_data, 7943, frequency); | |
1408 | ||
3a4d1b90 | 1409 | if (result > 0) { |
66101de1 PM |
1410 | _reset_rx_cal(phw_data); |
1411 | result = _rx_iq_calibration_loop_winbond(phw_data, 5011, frequency); | |
1412 | ||
3a4d1b90 | 1413 | if (result > 0) { |
66101de1 PM |
1414 | PHY_DEBUG(("[CAL] ** <_rx_iq_calibration> **************\n")); |
1415 | PHY_DEBUG(("[CAL] ** RX_IQ_CALIBRATION FAILURE !!\n")); | |
1416 | PHY_DEBUG(("[CAL] **************************************\n")); | |
1417 | _reset_rx_cal(phw_data); | |
1418 | } | |
1419 | } | |
1420 | } | |
1421 | ||
1422 | #ifdef _DEBUG | |
1423 | hw_get_dxx_reg(phw_data, 0x54, &val); | |
1424 | PHY_DEBUG(("[CAL] ** 0x54 = 0x%08X\n", val)); | |
1425 | ||
3a4d1b90 | 1426 | if (phw_data->revision == 0x2002) /* 1st-cut */{ |
66101de1 PM |
1427 | rx_cal_reg[0] = _s4_to_s32((val & 0x0000F000) >> 12); |
1428 | rx_cal_reg[1] = _s4_to_s32((val & 0x00000F00) >> 8); | |
1429 | rx_cal_reg[2] = _s4_to_s32((val & 0x000000F0) >> 4); | |
1430 | rx_cal_reg[3] = _s4_to_s32((val & 0x0000000F)); | |
3a4d1b90 | 1431 | } else /* 2nd-cut */{ |
66101de1 PM |
1432 | rx_cal_reg[0] = _s5_to_s32((val & 0xF8000000) >> 27); |
1433 | rx_cal_reg[1] = _s6_to_s32((val & 0x07E00000) >> 21); | |
1434 | rx_cal_reg[2] = _s6_to_s32((val & 0x001F8000) >> 15); | |
1435 | rx_cal_reg[3] = _s5_to_s32((val & 0x00007C00) >> 10); | |
1436 | } | |
1437 | ||
1438 | PHY_DEBUG(("[CAL] ** rx_cal_reg[0] = %d\n", rx_cal_reg[0])); | |
1439 | PHY_DEBUG(("[CAL] rx_cal_reg[1] = %d\n", rx_cal_reg[1])); | |
1440 | PHY_DEBUG(("[CAL] rx_cal_reg[2] = %d\n", rx_cal_reg[2])); | |
1441 | PHY_DEBUG(("[CAL] rx_cal_reg[3] = %d\n", rx_cal_reg[3])); | |
1442 | #endif | |
1443 | ||
1444 | } | |
1445 | ||
3a4d1b90 | 1446 | /*******************************************************/ |
8e41b4b6 | 1447 | void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency) |
66101de1 PM |
1448 | { |
1449 | u32 reg_mode_ctrl; | |
1450 | u32 iq_alpha; | |
1451 | ||
1452 | PHY_DEBUG(("[CAL] -> phy_calibration_winbond()\n")); | |
1453 | ||
66101de1 PM |
1454 | hw_get_dxx_reg(phw_data, 0x58, &iq_alpha); |
1455 | ||
66101de1 | 1456 | _rxadc_dc_offset_cancellation_winbond(phw_data, frequency); |
3a4d1b90 TT |
1457 | /* _txidac_dc_offset_cancellation_winbond(phw_data); */ |
1458 | /* _txqdac_dc_offset_cacellation_winbond(phw_data); */ | |
66101de1 PM |
1459 | |
1460 | _tx_iq_calibration_winbond(phw_data); | |
1461 | _rx_iq_calibration_winbond(phw_data, frequency); | |
1462 | ||
3a4d1b90 | 1463 | /*********************************************************************/ |
66101de1 | 1464 | hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl); |
3a4d1b90 | 1465 | reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE|MASK_CALIB_START); /* set when finish */ |
66101de1 PM |
1466 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); |
1467 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
1468 | ||
3a4d1b90 | 1469 | /* i. Set RFIC to "Normal mode" */ |
66101de1 PM |
1470 | hw_set_dxx_reg(phw_data, 0x58, iq_alpha); |
1471 | ||
3a4d1b90 | 1472 | /*********************************************************************/ |
66101de1 PM |
1473 | phy_init_rf(phw_data); |
1474 | ||
1475 | } | |
1476 | ||
3a4d1b90 TT |
1477 | /******************/ |
1478 | void phy_set_rf_data(struct hw_data *pHwData, u32 index, u32 value) | |
66101de1 | 1479 | { |
2e04bb7b | 1480 | u32 ltmp = 0; |
3a4d1b90 TT |
1481 | |
1482 | switch (pHwData->phy_type) { | |
1483 | case RF_MAXIM_2825: | |
1484 | case RF_MAXIM_V1: /* 11g Winbond 2nd BB(with Phy board (v1) + Maxim 331) */ | |
1485 | ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18); | |
1486 | break; | |
1487 | ||
1488 | case RF_MAXIM_2827: | |
1489 | ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18); | |
1490 | break; | |
1491 | ||
1492 | case RF_MAXIM_2828: | |
1493 | ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18); | |
1494 | break; | |
1495 | ||
1496 | case RF_MAXIM_2829: | |
1497 | ltmp = (1 << 31) | (0 << 30) | (18 << 24) | BitReverse(value, 18); | |
1498 | break; | |
1499 | ||
1500 | case RF_AIROHA_2230: | |
1501 | case RF_AIROHA_2230S: /* 20060420 Add this */ | |
1502 | ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse(value, 20); | |
1503 | break; | |
1504 | ||
1505 | case RF_AIROHA_7230: | |
1506 | ltmp = (1 << 31) | (0 << 30) | (24 << 24) | (value&0xffffff); | |
1507 | break; | |
1508 | ||
1509 | case RF_WB_242: | |
1510 | case RF_WB_242_1:/* 20060619.5 Add */ | |
1511 | ltmp = (1 << 31) | (0 << 30) | (24 << 24) | BitReverse(value, 24); | |
1512 | break; | |
1513 | } | |
66101de1 | 1514 | |
3a4d1b90 | 1515 | Wb35Reg_WriteSync(pHwData, 0x0864, ltmp); |
66101de1 PM |
1516 | } |
1517 | ||
3a4d1b90 | 1518 | /* 20060717 modify as Bruce's mail */ |
8e41b4b6 | 1519 | unsigned char adjust_TXVGA_for_iq_mag(struct hw_data *phw_data) |
66101de1 PM |
1520 | { |
1521 | int init_txvga = 0; | |
1522 | u32 reg_mode_ctrl; | |
1523 | u32 val; | |
1524 | s32 iqcal_tone_i0; | |
1525 | s32 iqcal_tone_q0; | |
1526 | u32 sqsum; | |
1527 | s32 iq_mag_0_tx; | |
3a4d1b90 TT |
1528 | u8 reg_state; |
1529 | int current_txvga; | |
66101de1 PM |
1530 | |
1531 | ||
1532 | reg_state = 0; | |
3a4d1b90 TT |
1533 | for (init_txvga = 0; init_txvga < 10; init_txvga++) { |
1534 | current_txvga = (0x24C40A|(init_txvga<<6)); | |
1535 | phy_set_rf_data(phw_data, 5, ((5<<24)|current_txvga)); | |
66101de1 PM |
1536 | phw_data->txvga_setting_for_cal = current_txvga; |
1537 | ||
3a4d1b90 | 1538 | msleep(30);/* 20060612.1.a */ |
66101de1 | 1539 | |
3a4d1b90 | 1540 | if (!hw_get_dxx_reg(phw_data, REG_MODE_CTRL, ®_mode_ctrl))/* 20060718.1 modify */ |
279b6ccc | 1541 | return false; |
66101de1 PM |
1542 | |
1543 | PHY_DEBUG(("[CAL] MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl)); | |
1544 | ||
3a4d1b90 TT |
1545 | /* |
1546 | * a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to | |
1547 | * enable "IQ alibration Mode II" | |
1548 | */ | |
66101de1 PM |
1549 | reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); |
1550 | reg_mode_ctrl &= ~MASK_IQCAL_MODE; | |
1551 | reg_mode_ctrl |= (MASK_CALIB_START|0x02); | |
1552 | reg_mode_ctrl |= (MASK_CALIB_START|0x02|2<<2); | |
1553 | hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl); | |
1554 | PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl)); | |
1555 | ||
3a4d1b90 | 1556 | udelay(1);/* 20060612.1.a */ |
66101de1 | 1557 | |
3a4d1b90 | 1558 | udelay(300);/* 20060612.1.a */ |
66101de1 | 1559 | |
3a4d1b90 | 1560 | /* b. */ |
66101de1 PM |
1561 | hw_get_dxx_reg(phw_data, REG_CALIB_READ1, &val); |
1562 | ||
1563 | PHY_DEBUG(("[CAL] CALIB_READ1 = 0x%08X\n", val)); | |
3a4d1b90 | 1564 | udelay(300);/* 20060612.1.a */ |
66101de1 PM |
1565 | |
1566 | iqcal_tone_i0 = _s13_to_s32(val & 0x00001FFF); | |
1567 | iqcal_tone_q0 = _s13_to_s32((val & 0x03FFE000) >> 13); | |
1568 | PHY_DEBUG(("[CAL] ** iqcal_tone_i0=%d, iqcal_tone_q0=%d\n", | |
1569 | iqcal_tone_i0, iqcal_tone_q0)); | |
1570 | ||
1571 | sqsum = iqcal_tone_i0*iqcal_tone_i0 + iqcal_tone_q0*iqcal_tone_q0; | |
1572 | iq_mag_0_tx = (s32) _sqrt(sqsum); | |
1573 | PHY_DEBUG(("[CAL] ** auto_adjust_txvga_for_iq_mag_0_tx=%d\n", iq_mag_0_tx)); | |
1574 | ||
3a4d1b90 | 1575 | if (iq_mag_0_tx >= 700 && iq_mag_0_tx <= 1750) |
66101de1 | 1576 | break; |
3a4d1b90 TT |
1577 | else if (iq_mag_0_tx > 1750) { |
1578 | init_txvga = -2; | |
66101de1 | 1579 | continue; |
3a4d1b90 | 1580 | } else |
66101de1 PM |
1581 | continue; |
1582 | ||
1583 | } | |
1584 | ||
3a4d1b90 | 1585 | if (iq_mag_0_tx >= 700 && iq_mag_0_tx <= 1750) |
279b6ccc | 1586 | return true; |
66101de1 | 1587 | else |
279b6ccc | 1588 | return false; |
66101de1 | 1589 | } |