diff options
author | Michael Buesch <mb@bu3sch.de> | 2009-02-04 13:55:22 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-11 11:44:23 -0500 |
commit | ce1a9ee33a5864f3d199baa1d3e154a1f9a6f3dd (patch) | |
tree | 2fc0e301b7d81a401b7114608134413897c4296a /drivers/net/wireless/b43/phy_lp.c | |
parent | 7a9470806053f765ecf7f3932acb4c95c204ad4b (diff) |
b43: Add parts of LP-PHY TX power control
This adds the initial parts of the LP-PHY TX power control.
This also adds helper functions for bulk access of LP tables.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43/phy_lp.c')
-rw-r--r-- | drivers/net/wireless/b43/phy_lp.c | 177 |
1 files changed, 175 insertions, 2 deletions
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 94d9e8b215e3..58e319d6b1ed 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -23,6 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "b43.h" | 25 | #include "b43.h" |
26 | #include "main.h" | ||
26 | #include "phy_lp.h" | 27 | #include "phy_lp.h" |
27 | #include "phy_common.h" | 28 | #include "phy_common.h" |
28 | #include "tables_lpphy.h" | 29 | #include "tables_lpphy.h" |
@@ -267,13 +268,185 @@ static void lpphy_radio_init(struct b43_wldev *dev) | |||
267 | } | 268 | } |
268 | } | 269 | } |
269 | 270 | ||
271 | /* Read the TX power control mode from hardware. */ | ||
272 | static void lpphy_read_tx_pctl_mode_from_hardware(struct b43_wldev *dev) | ||
273 | { | ||
274 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
275 | u16 ctl; | ||
276 | |||
277 | ctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD); | ||
278 | switch (ctl & B43_LPPHY_TX_PWR_CTL_CMD_MODE) { | ||
279 | case B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF: | ||
280 | lpphy->txpctl_mode = B43_LPPHY_TXPCTL_OFF; | ||
281 | break; | ||
282 | case B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW: | ||
283 | lpphy->txpctl_mode = B43_LPPHY_TXPCTL_SW; | ||
284 | break; | ||
285 | case B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW: | ||
286 | lpphy->txpctl_mode = B43_LPPHY_TXPCTL_HW; | ||
287 | break; | ||
288 | default: | ||
289 | lpphy->txpctl_mode = B43_LPPHY_TXPCTL_UNKNOWN; | ||
290 | B43_WARN_ON(1); | ||
291 | break; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | /* Set the TX power control mode in hardware. */ | ||
296 | static void lpphy_write_tx_pctl_mode_to_hardware(struct b43_wldev *dev) | ||
297 | { | ||
298 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
299 | u16 ctl; | ||
300 | |||
301 | switch (lpphy->txpctl_mode) { | ||
302 | case B43_LPPHY_TXPCTL_OFF: | ||
303 | ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF; | ||
304 | break; | ||
305 | case B43_LPPHY_TXPCTL_HW: | ||
306 | ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW; | ||
307 | break; | ||
308 | case B43_LPPHY_TXPCTL_SW: | ||
309 | ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW; | ||
310 | break; | ||
311 | default: | ||
312 | ctl = 0; | ||
313 | B43_WARN_ON(1); | ||
314 | } | ||
315 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, | ||
316 | (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, ctl); | ||
317 | } | ||
318 | |||
319 | static void lpphy_set_tx_power_control(struct b43_wldev *dev, | ||
320 | enum b43_lpphy_txpctl_mode mode) | ||
321 | { | ||
322 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
323 | enum b43_lpphy_txpctl_mode oldmode; | ||
324 | |||
325 | oldmode = lpphy->txpctl_mode; | ||
326 | lpphy_read_tx_pctl_mode_from_hardware(dev); | ||
327 | if (lpphy->txpctl_mode == mode) | ||
328 | return; | ||
329 | lpphy->txpctl_mode = mode; | ||
330 | |||
331 | if (oldmode == B43_LPPHY_TXPCTL_HW) { | ||
332 | //TODO Update TX Power NPT | ||
333 | //TODO Clear all TX Power offsets | ||
334 | } else { | ||
335 | if (mode == B43_LPPHY_TXPCTL_HW) { | ||
336 | //TODO Recalculate target TX power | ||
337 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, | ||
338 | 0xFF80, lpphy->tssi_idx); | ||
339 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, | ||
340 | 0x8FFF, ((u16)lpphy->tssi_npt << 16)); | ||
341 | //TODO Set "TSSI Transmit Count" variable to total transmitted frame count | ||
342 | //TODO Disable TX gain override | ||
343 | lpphy->tx_pwr_idx_over = -1; | ||
344 | } | ||
345 | } | ||
346 | if (dev->phy.rev >= 2) { | ||
347 | if (mode == B43_LPPHY_TXPCTL_HW) | ||
348 | b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0x2); | ||
349 | else | ||
350 | b43_phy_maskset(dev, B43_PHY_OFDM(0xD0), 0xFD, 0); | ||
351 | } | ||
352 | lpphy_write_tx_pctl_mode_to_hardware(dev); | ||
353 | } | ||
354 | |||
355 | static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index) | ||
356 | { | ||
357 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
358 | |||
359 | lpphy->tx_pwr_idx_over = index; | ||
360 | if (lpphy->txpctl_mode != B43_LPPHY_TXPCTL_OFF) | ||
361 | lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_SW); | ||
362 | |||
363 | //TODO | ||
364 | } | ||
365 | |||
366 | static void lpphy_btcoex_override(struct b43_wldev *dev) | ||
367 | { | ||
368 | b43_write16(dev, B43_MMIO_BTCOEX_CTL, 0x3); | ||
369 | b43_write16(dev, B43_MMIO_BTCOEX_TXCTL, 0xFF); | ||
370 | } | ||
371 | |||
372 | static void lpphy_pr41573_workaround(struct b43_wldev *dev) | ||
373 | { | ||
374 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
375 | u32 *saved_tab; | ||
376 | const unsigned int saved_tab_size = 256; | ||
377 | enum b43_lpphy_txpctl_mode txpctl_mode; | ||
378 | s8 tx_pwr_idx_over; | ||
379 | u16 tssi_npt, tssi_idx; | ||
380 | |||
381 | saved_tab = kcalloc(saved_tab_size, sizeof(saved_tab[0]), GFP_KERNEL); | ||
382 | if (!saved_tab) { | ||
383 | b43err(dev->wl, "PR41573 failed. Out of memory!\n"); | ||
384 | return; | ||
385 | } | ||
386 | |||
387 | lpphy_read_tx_pctl_mode_from_hardware(dev); | ||
388 | txpctl_mode = lpphy->txpctl_mode; | ||
389 | tx_pwr_idx_over = lpphy->tx_pwr_idx_over; | ||
390 | tssi_npt = lpphy->tssi_npt; | ||
391 | tssi_idx = lpphy->tssi_idx; | ||
392 | |||
393 | if (dev->phy.rev < 2) { | ||
394 | b43_lptab_read_bulk(dev, B43_LPTAB32(10, 0x140), | ||
395 | saved_tab_size, saved_tab); | ||
396 | } else { | ||
397 | b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140), | ||
398 | saved_tab_size, saved_tab); | ||
399 | } | ||
400 | //TODO | ||
401 | |||
402 | kfree(saved_tab); | ||
403 | } | ||
404 | |||
405 | static void lpphy_calibration(struct b43_wldev *dev) | ||
406 | { | ||
407 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
408 | enum b43_lpphy_txpctl_mode saved_pctl_mode; | ||
409 | |||
410 | b43_mac_suspend(dev); | ||
411 | |||
412 | lpphy_btcoex_override(dev); | ||
413 | lpphy_read_tx_pctl_mode_from_hardware(dev); | ||
414 | saved_pctl_mode = lpphy->txpctl_mode; | ||
415 | lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); | ||
416 | //TODO Perform transmit power table I/Q LO calibration | ||
417 | if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF)) | ||
418 | lpphy_pr41573_workaround(dev); | ||
419 | //TODO If a full calibration has not been performed on this channel yet, perform PAPD TX-power calibration | ||
420 | lpphy_set_tx_power_control(dev, saved_pctl_mode); | ||
421 | //TODO Perform I/Q calibration with a single control value set | ||
422 | |||
423 | b43_mac_enable(dev); | ||
424 | } | ||
425 | |||
426 | /* Initialize TX power control */ | ||
427 | static void lpphy_tx_pctl_init(struct b43_wldev *dev) | ||
428 | { | ||
429 | if (0/*FIXME HWPCTL capable */) { | ||
430 | //TODO | ||
431 | } else { /* This device is only software TX power control capable. */ | ||
432 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
433 | //TODO | ||
434 | } else { | ||
435 | //TODO | ||
436 | } | ||
437 | //TODO set BB multiplier to 0x0096 | ||
438 | } | ||
439 | } | ||
440 | |||
270 | static int b43_lpphy_op_init(struct b43_wldev *dev) | 441 | static int b43_lpphy_op_init(struct b43_wldev *dev) |
271 | { | 442 | { |
272 | /* TODO: band SPROM */ | 443 | /* TODO: band SPROM */ |
273 | lpphy_baseband_init(dev); | 444 | lpphy_baseband_init(dev); |
274 | lpphy_radio_init(dev); | 445 | lpphy_radio_init(dev); |
275 | 446 | //TODO calibrate RC | |
276 | //TODO | 447 | //TODO set channel |
448 | lpphy_tx_pctl_init(dev); | ||
449 | //TODO full calib | ||
277 | 450 | ||
278 | return 0; | 451 | return 0; |
279 | } | 452 | } |