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