diff options
Diffstat (limited to 'drivers/net/wireless/b43/phy_a.c')
-rw-r--r-- | drivers/net/wireless/b43/phy_a.c | 130 |
1 files changed, 115 insertions, 15 deletions
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c index 4d7d59e30960..0f1a84c9de61 100644 --- a/drivers/net/wireless/b43/phy_a.c +++ b/drivers/net/wireless/b43/phy_a.c | |||
@@ -58,6 +58,25 @@ static inline u16 freq_r3A_value(u16 frequency) | |||
58 | return value; | 58 | return value; |
59 | } | 59 | } |
60 | 60 | ||
61 | #if 0 | ||
62 | /* This function converts a TSSI value to dBm in Q5.2 */ | ||
63 | static s8 b43_aphy_estimate_power_out(struct b43_wldev *dev, s8 tssi) | ||
64 | { | ||
65 | struct b43_phy *phy = &dev->phy; | ||
66 | struct b43_phy_a *aphy = phy->a; | ||
67 | s8 dbm = 0; | ||
68 | s32 tmp; | ||
69 | |||
70 | tmp = (aphy->tgt_idle_tssi - aphy->cur_idle_tssi + tssi); | ||
71 | tmp += 0x80; | ||
72 | tmp = clamp_val(tmp, 0x00, 0xFF); | ||
73 | dbm = aphy->tssi2dbm[tmp]; | ||
74 | //TODO: There's a FIXME on the specs | ||
75 | |||
76 | return dbm; | ||
77 | } | ||
78 | #endif | ||
79 | |||
61 | void b43_radio_set_tx_iq(struct b43_wldev *dev) | 80 | void b43_radio_set_tx_iq(struct b43_wldev *dev) |
62 | { | 81 | { |
63 | static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; | 82 | static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; |
@@ -326,43 +345,106 @@ void b43_phy_inita(struct b43_wldev *dev) | |||
326 | } | 345 | } |
327 | } | 346 | } |
328 | 347 | ||
348 | /* Initialise the TSSI->dBm lookup table */ | ||
349 | static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev) | ||
350 | { | ||
351 | struct b43_phy *phy = &dev->phy; | ||
352 | struct b43_phy_a *aphy = phy->a; | ||
353 | s16 pab0, pab1, pab2; | ||
354 | |||
355 | pab0 = (s16) (dev->dev->bus->sprom.pa1b0); | ||
356 | pab1 = (s16) (dev->dev->bus->sprom.pa1b1); | ||
357 | pab2 = (s16) (dev->dev->bus->sprom.pa1b2); | ||
358 | |||
359 | if (pab0 != 0 && pab1 != 0 && pab2 != 0 && | ||
360 | pab0 != -1 && pab1 != -1 && pab2 != -1) { | ||
361 | /* The pabX values are set in SPROM. Use them. */ | ||
362 | if ((s8) dev->dev->bus->sprom.itssi_a != 0 && | ||
363 | (s8) dev->dev->bus->sprom.itssi_a != -1) | ||
364 | aphy->tgt_idle_tssi = | ||
365 | (s8) (dev->dev->bus->sprom.itssi_a); | ||
366 | else | ||
367 | aphy->tgt_idle_tssi = 62; | ||
368 | aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, | ||
369 | pab1, pab2); | ||
370 | if (!aphy->tssi2dbm) | ||
371 | return -ENOMEM; | ||
372 | } else { | ||
373 | /* pabX values not set in SPROM, | ||
374 | * but APHY needs a generated table. */ | ||
375 | aphy->tssi2dbm = NULL; | ||
376 | b43err(dev->wl, "Could not generate tssi2dBm " | ||
377 | "table (wrong SPROM info)!\n"); | ||
378 | return -ENODEV; | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
329 | static int b43_aphy_op_allocate(struct b43_wldev *dev) | 384 | static int b43_aphy_op_allocate(struct b43_wldev *dev) |
330 | { | 385 | { |
331 | struct b43_phy_a *aphy; | 386 | struct b43_phy_a *aphy; |
387 | int err; | ||
332 | 388 | ||
333 | aphy = kzalloc(sizeof(*aphy), GFP_KERNEL); | 389 | aphy = kzalloc(sizeof(*aphy), GFP_KERNEL); |
334 | if (!aphy) | 390 | if (!aphy) |
335 | return -ENOMEM; | 391 | return -ENOMEM; |
336 | dev->phy.a = aphy; | 392 | dev->phy.a = aphy; |
337 | 393 | ||
338 | //TODO init struct b43_phy_a | 394 | err = b43_aphy_init_tssi2dbm_table(dev); |
395 | if (err) | ||
396 | goto err_free_aphy; | ||
339 | 397 | ||
340 | return 0; | 398 | return 0; |
399 | |||
400 | err_free_aphy: | ||
401 | kfree(aphy); | ||
402 | dev->phy.a = NULL; | ||
403 | |||
404 | return err; | ||
341 | } | 405 | } |
342 | 406 | ||
343 | static int b43_aphy_op_init(struct b43_wldev *dev) | 407 | static void b43_aphy_op_prepare_structs(struct b43_wldev *dev) |
344 | { | 408 | { |
345 | struct b43_phy_a *aphy = dev->phy.a; | 409 | struct b43_phy *phy = &dev->phy; |
410 | struct b43_phy_a *aphy = phy->a; | ||
411 | const void *tssi2dbm; | ||
412 | int tgt_idle_tssi; | ||
346 | 413 | ||
347 | b43_phy_inita(dev); | 414 | /* tssi2dbm table is constant, so it is initialized at alloc time. |
348 | aphy->initialised = 1; | 415 | * Save a copy of the pointer. */ |
416 | tssi2dbm = aphy->tssi2dbm; | ||
417 | tgt_idle_tssi = aphy->tgt_idle_tssi; | ||
418 | |||
419 | /* Zero out the whole PHY structure. */ | ||
420 | memset(aphy, 0, sizeof(*aphy)); | ||
421 | |||
422 | aphy->tssi2dbm = tssi2dbm; | ||
423 | aphy->tgt_idle_tssi = tgt_idle_tssi; | ||
424 | |||
425 | //TODO init struct b43_phy_a | ||
349 | 426 | ||
350 | return 0; | ||
351 | } | 427 | } |
352 | 428 | ||
353 | static void b43_aphy_op_exit(struct b43_wldev *dev) | 429 | static void b43_aphy_op_free(struct b43_wldev *dev) |
354 | { | 430 | { |
355 | struct b43_phy_a *aphy = dev->phy.a; | 431 | struct b43_phy *phy = &dev->phy; |
432 | struct b43_phy_a *aphy = phy->a; | ||
433 | |||
434 | kfree(aphy->tssi2dbm); | ||
435 | aphy->tssi2dbm = NULL; | ||
356 | 436 | ||
357 | if (aphy->initialised) { | ||
358 | //TODO | ||
359 | aphy->initialised = 0; | ||
360 | } | ||
361 | //TODO | ||
362 | kfree(aphy); | 437 | kfree(aphy); |
363 | dev->phy.a = NULL; | 438 | dev->phy.a = NULL; |
364 | } | 439 | } |
365 | 440 | ||
441 | static int b43_aphy_op_init(struct b43_wldev *dev) | ||
442 | { | ||
443 | b43_phy_inita(dev); | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
366 | static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset) | 448 | static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset) |
367 | { | 449 | { |
368 | /* OFDM registers are base-registers for the A-PHY. */ | 450 | /* OFDM registers are base-registers for the A-PHY. */ |
@@ -430,7 +512,23 @@ static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev) | |||
430 | 512 | ||
431 | static void b43_aphy_op_software_rfkill(struct b43_wldev *dev, | 513 | static void b43_aphy_op_software_rfkill(struct b43_wldev *dev, |
432 | enum rfkill_state state) | 514 | enum rfkill_state state) |
433 | {//TODO | 515 | { |
516 | struct b43_phy *phy = &dev->phy; | ||
517 | |||
518 | if (state == RFKILL_STATE_UNBLOCKED) { | ||
519 | if (phy->radio_on) | ||
520 | return; | ||
521 | b43_radio_write16(dev, 0x0004, 0x00C0); | ||
522 | b43_radio_write16(dev, 0x0005, 0x0008); | ||
523 | b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) & 0xFFF7); | ||
524 | b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) & 0xFFF7); | ||
525 | b43_radio_init2060(dev); | ||
526 | } else { | ||
527 | b43_radio_write16(dev, 0x0004, 0x00FF); | ||
528 | b43_radio_write16(dev, 0x0005, 0x00FB); | ||
529 | b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) | 0x0008); | ||
530 | b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008); | ||
531 | } | ||
434 | } | 532 | } |
435 | 533 | ||
436 | static int b43_aphy_op_switch_channel(struct b43_wldev *dev, | 534 | static int b43_aphy_op_switch_channel(struct b43_wldev *dev, |
@@ -525,14 +623,16 @@ static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev) | |||
525 | 623 | ||
526 | const struct b43_phy_operations b43_phyops_a = { | 624 | const struct b43_phy_operations b43_phyops_a = { |
527 | .allocate = b43_aphy_op_allocate, | 625 | .allocate = b43_aphy_op_allocate, |
626 | .free = b43_aphy_op_free, | ||
627 | .prepare_structs = b43_aphy_op_prepare_structs, | ||
528 | .init = b43_aphy_op_init, | 628 | .init = b43_aphy_op_init, |
529 | .exit = b43_aphy_op_exit, | ||
530 | .phy_read = b43_aphy_op_read, | 629 | .phy_read = b43_aphy_op_read, |
531 | .phy_write = b43_aphy_op_write, | 630 | .phy_write = b43_aphy_op_write, |
532 | .radio_read = b43_aphy_op_radio_read, | 631 | .radio_read = b43_aphy_op_radio_read, |
533 | .radio_write = b43_aphy_op_radio_write, | 632 | .radio_write = b43_aphy_op_radio_write, |
534 | .supports_hwpctl = b43_aphy_op_supports_hwpctl, | 633 | .supports_hwpctl = b43_aphy_op_supports_hwpctl, |
535 | .software_rfkill = b43_aphy_op_software_rfkill, | 634 | .software_rfkill = b43_aphy_op_software_rfkill, |
635 | .switch_analog = b43_phyop_switch_analog_generic, | ||
536 | .switch_channel = b43_aphy_op_switch_channel, | 636 | .switch_channel = b43_aphy_op_switch_channel, |
537 | .get_default_chan = b43_aphy_op_get_default_chan, | 637 | .get_default_chan = b43_aphy_op_get_default_chan, |
538 | .set_rx_antenna = b43_aphy_op_set_rx_antenna, | 638 | .set_rx_antenna = b43_aphy_op_set_rx_antenna, |