aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/phy_a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43/phy_a.c')
-rw-r--r--drivers/net/wireless/b43/phy_a.c130
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 */
63static 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
61void b43_radio_set_tx_iq(struct b43_wldev *dev) 80void 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 */
349static 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
329static int b43_aphy_op_allocate(struct b43_wldev *dev) 384static 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
400err_free_aphy:
401 kfree(aphy);
402 dev->phy.a = NULL;
403
404 return err;
341} 405}
342 406
343static int b43_aphy_op_init(struct b43_wldev *dev) 407static 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
353static void b43_aphy_op_exit(struct b43_wldev *dev) 429static 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
441static int b43_aphy_op_init(struct b43_wldev *dev)
442{
443 b43_phy_inita(dev);
444
445 return 0;
446}
447
366static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset) 448static 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
431static void b43_aphy_op_software_rfkill(struct b43_wldev *dev, 513static 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
436static int b43_aphy_op_switch_channel(struct b43_wldev *dev, 534static 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
526const struct b43_phy_operations b43_phyops_a = { 624const 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,