~ubuntu-branches/ubuntu/maverick/linux-backports-modules-2.6.32/maverick

« back to all changes in this revision

Viewing changes to updates/compat-wireless-2.6/drivers/net/wireless/b43legacy/leds.c

  • Committer: Bazaar Package Importer
  • Author(s): Andy Whitcroft, Andy Whitcroft
  • Date: 2010-02-04 23:15:51 UTC
  • Revision ID: james.westby@ubuntu.com-20100204231551-vjz5pkvxclukjxm1
Tags: 2.6.32-12.1
[ Andy Whitcroft ]

* initial LBM for lucid
* drop generated files
* printchanges -- rebase tree does not have stable tags use changelog
* printenv -- add revisions to printenv output
* formally rename compat-wireless to linux-backports-modules-wireless
* Update to compat-wireless-2.6.33-rc5
* update nouveau to mainline 2.6.33-rc4
* add new LBM package for nouveau
* nouveau -- fix major numbers and proc entry names
* fix up firmware installs for -wireless
* clean up UPDATE-NOVEAU
* update Nouveau to v2.6.33-rc6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
  Broadcom B43 wireless driver
 
4
  LED control
 
5
 
 
6
  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
 
7
  Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
 
8
  Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
 
9
  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
 
10
  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
11
 
 
12
  This program is free software; you can redistribute it and/or modify
 
13
  it under the terms of the GNU General Public License as published by
 
14
  the Free Software Foundation; either version 2 of the License, or
 
15
  (at your option) any later version.
 
16
 
 
17
  This program is distributed in the hope that it will be useful,
 
18
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
  GNU General Public License for more details.
 
21
 
 
22
  You should have received a copy of the GNU General Public License
 
23
  along with this program; see the file COPYING.  If not, write to
 
24
  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
 
25
  Boston, MA 02110-1301, USA.
 
26
 
 
27
*/
 
28
 
 
29
#include "b43legacy.h"
 
30
#include "leds.h"
 
31
#include "rfkill.h"
 
32
 
 
33
 
 
34
static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
 
35
                            bool activelow)
 
36
{
 
37
        struct b43legacy_wl *wl = dev->wl;
 
38
        unsigned long flags;
 
39
        u16 ctl;
 
40
 
 
41
        spin_lock_irqsave(&wl->leds_lock, flags);
 
42
        ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
 
43
        if (activelow)
 
44
                ctl &= ~(1 << led_index);
 
45
        else
 
46
                ctl |= (1 << led_index);
 
47
        b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
 
48
        spin_unlock_irqrestore(&wl->leds_lock, flags);
 
49
}
 
50
 
 
51
static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index,
 
52
                             bool activelow)
 
53
{
 
54
        struct b43legacy_wl *wl = dev->wl;
 
55
        unsigned long flags;
 
56
        u16 ctl;
 
57
 
 
58
        spin_lock_irqsave(&wl->leds_lock, flags);
 
59
        ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
 
60
        if (activelow)
 
61
                ctl |= (1 << led_index);
 
62
        else
 
63
                ctl &= ~(1 << led_index);
 
64
        b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
 
65
        spin_unlock_irqrestore(&wl->leds_lock, flags);
 
66
}
 
67
 
 
68
/* Callback from the LED subsystem. */
 
69
static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
 
70
                                   enum led_brightness brightness)
 
71
{
 
72
        struct b43legacy_led *led = container_of(led_dev, struct b43legacy_led,
 
73
                                    led_dev);
 
74
        struct b43legacy_wldev *dev = led->dev;
 
75
        bool radio_enabled;
 
76
 
 
77
        /* Checking the radio-enabled status here is slightly racy,
 
78
         * but we want to avoid the locking overhead and we don't care
 
79
         * whether the LED has the wrong state for a second. */
 
80
        radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
 
81
 
 
82
        if (brightness == LED_OFF || !radio_enabled)
 
83
                b43legacy_led_turn_off(dev, led->index, led->activelow);
 
84
        else
 
85
                b43legacy_led_turn_on(dev, led->index, led->activelow);
 
86
}
 
87
 
 
88
static int b43legacy_register_led(struct b43legacy_wldev *dev,
 
89
                                  struct b43legacy_led *led,
 
90
                                  const char *name,
 
91
                                  const char *default_trigger,
 
92
                                  u8 led_index, bool activelow)
 
93
{
 
94
        int err;
 
95
 
 
96
        b43legacy_led_turn_off(dev, led_index, activelow);
 
97
        if (led->dev)
 
98
                return -EEXIST;
 
99
        if (!default_trigger)
 
100
                return -EINVAL;
 
101
        led->dev = dev;
 
102
        led->index = led_index;
 
103
        led->activelow = activelow;
 
104
        strncpy(led->name, name, sizeof(led->name));
 
105
 
 
106
        led->led_dev.name = led->name;
 
107
        led->led_dev.default_trigger = default_trigger;
 
108
        led->led_dev.brightness_set = b43legacy_led_brightness_set;
 
109
 
 
110
        err = led_classdev_register(dev->dev->dev, &led->led_dev);
 
111
        if (err) {
 
112
                b43legacywarn(dev->wl, "LEDs: Failed to register %s\n", name);
 
113
                led->dev = NULL;
 
114
                return err;
 
115
        }
 
116
        return 0;
 
117
}
 
118
 
 
119
static void b43legacy_unregister_led(struct b43legacy_led *led)
 
120
{
 
121
        if (!led->dev)
 
122
                return;
 
123
        led_classdev_unregister(&led->led_dev);
 
124
        b43legacy_led_turn_off(led->dev, led->index, led->activelow);
 
125
        led->dev = NULL;
 
126
}
 
127
 
 
128
static void b43legacy_map_led(struct b43legacy_wldev *dev,
 
129
                        u8 led_index,
 
130
                        enum b43legacy_led_behaviour behaviour,
 
131
                        bool activelow)
 
132
{
 
133
        struct ieee80211_hw *hw = dev->wl->hw;
 
134
        char name[B43legacy_LED_MAX_NAME_LEN + 1];
 
135
 
 
136
        /* Map the b43 specific LED behaviour value to the
 
137
         * generic LED triggers. */
 
138
        switch (behaviour) {
 
139
        case B43legacy_LED_INACTIVE:
 
140
                break;
 
141
        case B43legacy_LED_OFF:
 
142
                b43legacy_led_turn_off(dev, led_index, activelow);
 
143
                break;
 
144
        case B43legacy_LED_ON:
 
145
                b43legacy_led_turn_on(dev, led_index, activelow);
 
146
                break;
 
147
        case B43legacy_LED_ACTIVITY:
 
148
        case B43legacy_LED_TRANSFER:
 
149
        case B43legacy_LED_APTRANSFER:
 
150
                snprintf(name, sizeof(name),
 
151
                         "b43legacy-%s::tx", wiphy_name(hw->wiphy));
 
152
                b43legacy_register_led(dev, &dev->led_tx, name,
 
153
                                 ieee80211_get_tx_led_name(hw),
 
154
                                 led_index, activelow);
 
155
                snprintf(name, sizeof(name),
 
156
                         "b43legacy-%s::rx", wiphy_name(hw->wiphy));
 
157
                b43legacy_register_led(dev, &dev->led_rx, name,
 
158
                                 ieee80211_get_rx_led_name(hw),
 
159
                                 led_index, activelow);
 
160
                break;
 
161
        case B43legacy_LED_RADIO_ALL:
 
162
        case B43legacy_LED_RADIO_A:
 
163
        case B43legacy_LED_RADIO_B:
 
164
        case B43legacy_LED_MODE_BG:
 
165
                snprintf(name, sizeof(name),
 
166
                         "b43legacy-%s::radio", wiphy_name(hw->wiphy));
 
167
                b43legacy_register_led(dev, &dev->led_radio, name,
 
168
                                 ieee80211_get_radio_led_name(hw),
 
169
                                 led_index, activelow);
 
170
                /* Sync the RF-kill LED state with radio and switch states. */
 
171
                if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev))
 
172
                        b43legacy_led_turn_on(dev, led_index, activelow);
 
173
                break;
 
174
        case B43legacy_LED_WEIRD:
 
175
        case B43legacy_LED_ASSOC:
 
176
                snprintf(name, sizeof(name),
 
177
                         "b43legacy-%s::assoc", wiphy_name(hw->wiphy));
 
178
                b43legacy_register_led(dev, &dev->led_assoc, name,
 
179
                                 ieee80211_get_assoc_led_name(hw),
 
180
                                 led_index, activelow);
 
181
                break;
 
182
        default:
 
183
                b43legacywarn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
 
184
                        behaviour);
 
185
                break;
 
186
        }
 
187
}
 
188
 
 
189
void b43legacy_leds_init(struct b43legacy_wldev *dev)
 
190
{
 
191
        struct ssb_bus *bus = dev->dev->bus;
 
192
        u8 sprom[4];
 
193
        int i;
 
194
        enum b43legacy_led_behaviour behaviour;
 
195
        bool activelow;
 
196
 
 
197
        sprom[0] = bus->sprom.gpio0;
 
198
        sprom[1] = bus->sprom.gpio1;
 
199
        sprom[2] = bus->sprom.gpio2;
 
200
        sprom[3] = bus->sprom.gpio3;
 
201
 
 
202
        for (i = 0; i < 4; i++) {
 
203
                if (sprom[i] == 0xFF) {
 
204
                        /* There is no LED information in the SPROM
 
205
                         * for this LED. Hardcode it here. */
 
206
                        activelow = 0;
 
207
                        switch (i) {
 
208
                        case 0:
 
209
                                behaviour = B43legacy_LED_ACTIVITY;
 
210
                                activelow = 1;
 
211
                                if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
 
212
                                        behaviour = B43legacy_LED_RADIO_ALL;
 
213
                                break;
 
214
                        case 1:
 
215
                                behaviour = B43legacy_LED_RADIO_B;
 
216
                                if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
 
217
                                        behaviour = B43legacy_LED_ASSOC;
 
218
                                break;
 
219
                        case 2:
 
220
                                behaviour = B43legacy_LED_RADIO_A;
 
221
                                break;
 
222
                        case 3:
 
223
                                behaviour = B43legacy_LED_OFF;
 
224
                                break;
 
225
                        default:
 
226
                                B43legacy_WARN_ON(1);
 
227
                                return;
 
228
                        }
 
229
                } else {
 
230
                        behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
 
231
                        activelow = !!(sprom[i] & B43legacy_LED_ACTIVELOW);
 
232
                }
 
233
                b43legacy_map_led(dev, i, behaviour, activelow);
 
234
        }
 
235
}
 
236
 
 
237
void b43legacy_leds_exit(struct b43legacy_wldev *dev)
 
238
{
 
239
        b43legacy_unregister_led(&dev->led_tx);
 
240
        b43legacy_unregister_led(&dev->led_rx);
 
241
        b43legacy_unregister_led(&dev->led_assoc);
 
242
        b43legacy_unregister_led(&dev->led_radio);
 
243
}