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