0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include "b43legacy.h"
0017 #include "leds.h"
0018 #include "rfkill.h"
0019
0020
0021 static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
0022 bool activelow)
0023 {
0024 struct b43legacy_wl *wl = dev->wl;
0025 unsigned long flags;
0026 u16 ctl;
0027
0028 spin_lock_irqsave(&wl->leds_lock, flags);
0029 ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
0030 if (activelow)
0031 ctl &= ~(1 << led_index);
0032 else
0033 ctl |= (1 << led_index);
0034 b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
0035 spin_unlock_irqrestore(&wl->leds_lock, flags);
0036 }
0037
0038 static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index,
0039 bool activelow)
0040 {
0041 struct b43legacy_wl *wl = dev->wl;
0042 unsigned long flags;
0043 u16 ctl;
0044
0045 spin_lock_irqsave(&wl->leds_lock, flags);
0046 ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
0047 if (activelow)
0048 ctl |= (1 << led_index);
0049 else
0050 ctl &= ~(1 << led_index);
0051 b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
0052 spin_unlock_irqrestore(&wl->leds_lock, flags);
0053 }
0054
0055
0056 static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
0057 enum led_brightness brightness)
0058 {
0059 struct b43legacy_led *led = container_of(led_dev, struct b43legacy_led,
0060 led_dev);
0061 struct b43legacy_wldev *dev = led->dev;
0062 bool radio_enabled;
0063
0064
0065
0066
0067 radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
0068
0069 if (brightness == LED_OFF || !radio_enabled)
0070 b43legacy_led_turn_off(dev, led->index, led->activelow);
0071 else
0072 b43legacy_led_turn_on(dev, led->index, led->activelow);
0073 }
0074
0075 static int b43legacy_register_led(struct b43legacy_wldev *dev,
0076 struct b43legacy_led *led,
0077 const char *name,
0078 const char *default_trigger,
0079 u8 led_index, bool activelow)
0080 {
0081 int err;
0082
0083 b43legacy_led_turn_off(dev, led_index, activelow);
0084 if (led->dev)
0085 return -EEXIST;
0086 if (!default_trigger)
0087 return -EINVAL;
0088 led->dev = dev;
0089 led->index = led_index;
0090 led->activelow = activelow;
0091 strlcpy(led->name, name, sizeof(led->name));
0092
0093 led->led_dev.name = led->name;
0094 led->led_dev.default_trigger = default_trigger;
0095 led->led_dev.brightness_set = b43legacy_led_brightness_set;
0096
0097 err = led_classdev_register(dev->dev->dev, &led->led_dev);
0098 if (err) {
0099 b43legacywarn(dev->wl, "LEDs: Failed to register %s\n", name);
0100 led->dev = NULL;
0101 return err;
0102 }
0103 return 0;
0104 }
0105
0106 static void b43legacy_unregister_led(struct b43legacy_led *led)
0107 {
0108 if (!led->dev)
0109 return;
0110 led_classdev_unregister(&led->led_dev);
0111 b43legacy_led_turn_off(led->dev, led->index, led->activelow);
0112 led->dev = NULL;
0113 }
0114
0115 static void b43legacy_map_led(struct b43legacy_wldev *dev,
0116 u8 led_index,
0117 enum b43legacy_led_behaviour behaviour,
0118 bool activelow)
0119 {
0120 struct ieee80211_hw *hw = dev->wl->hw;
0121 char name[B43legacy_LED_MAX_NAME_LEN + 1];
0122
0123
0124
0125 switch (behaviour) {
0126 case B43legacy_LED_INACTIVE:
0127 break;
0128 case B43legacy_LED_OFF:
0129 b43legacy_led_turn_off(dev, led_index, activelow);
0130 break;
0131 case B43legacy_LED_ON:
0132 b43legacy_led_turn_on(dev, led_index, activelow);
0133 break;
0134 case B43legacy_LED_ACTIVITY:
0135 case B43legacy_LED_TRANSFER:
0136 case B43legacy_LED_APTRANSFER:
0137 snprintf(name, sizeof(name),
0138 "b43legacy-%s::tx", wiphy_name(hw->wiphy));
0139 b43legacy_register_led(dev, &dev->led_tx, name,
0140 ieee80211_get_tx_led_name(hw),
0141 led_index, activelow);
0142 snprintf(name, sizeof(name),
0143 "b43legacy-%s::rx", wiphy_name(hw->wiphy));
0144 b43legacy_register_led(dev, &dev->led_rx, name,
0145 ieee80211_get_rx_led_name(hw),
0146 led_index, activelow);
0147 break;
0148 case B43legacy_LED_RADIO_ALL:
0149 case B43legacy_LED_RADIO_A:
0150 case B43legacy_LED_RADIO_B:
0151 case B43legacy_LED_MODE_BG:
0152 snprintf(name, sizeof(name),
0153 "b43legacy-%s::radio", wiphy_name(hw->wiphy));
0154 b43legacy_register_led(dev, &dev->led_radio, name,
0155 ieee80211_get_radio_led_name(hw),
0156 led_index, activelow);
0157
0158 if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev))
0159 b43legacy_led_turn_on(dev, led_index, activelow);
0160 break;
0161 case B43legacy_LED_WEIRD:
0162 case B43legacy_LED_ASSOC:
0163 snprintf(name, sizeof(name),
0164 "b43legacy-%s::assoc", wiphy_name(hw->wiphy));
0165 b43legacy_register_led(dev, &dev->led_assoc, name,
0166 ieee80211_get_assoc_led_name(hw),
0167 led_index, activelow);
0168 break;
0169 default:
0170 b43legacywarn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
0171 behaviour);
0172 break;
0173 }
0174 }
0175
0176 void b43legacy_leds_init(struct b43legacy_wldev *dev)
0177 {
0178 struct ssb_bus *bus = dev->dev->bus;
0179 u8 sprom[4];
0180 int i;
0181 enum b43legacy_led_behaviour behaviour;
0182 bool activelow;
0183
0184 sprom[0] = bus->sprom.gpio0;
0185 sprom[1] = bus->sprom.gpio1;
0186 sprom[2] = bus->sprom.gpio2;
0187 sprom[3] = bus->sprom.gpio3;
0188
0189 for (i = 0; i < 4; i++) {
0190 if (sprom[i] == 0xFF) {
0191
0192
0193 activelow = false;
0194 switch (i) {
0195 case 0:
0196 behaviour = B43legacy_LED_ACTIVITY;
0197 activelow = true;
0198 if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
0199 behaviour = B43legacy_LED_RADIO_ALL;
0200 break;
0201 case 1:
0202 behaviour = B43legacy_LED_RADIO_B;
0203 if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
0204 behaviour = B43legacy_LED_ASSOC;
0205 break;
0206 case 2:
0207 behaviour = B43legacy_LED_RADIO_A;
0208 break;
0209 case 3:
0210 behaviour = B43legacy_LED_OFF;
0211 break;
0212 default:
0213 B43legacy_WARN_ON(1);
0214 return;
0215 }
0216 } else {
0217 behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
0218 activelow = !!(sprom[i] & B43legacy_LED_ACTIVELOW);
0219 }
0220 b43legacy_map_led(dev, i, behaviour, activelow);
0221 }
0222 }
0223
0224 void b43legacy_leds_exit(struct b43legacy_wldev *dev)
0225 {
0226 b43legacy_unregister_led(&dev->led_tx);
0227 b43legacy_unregister_led(&dev->led_rx);
0228 b43legacy_unregister_led(&dev->led_assoc);
0229 b43legacy_unregister_led(&dev->led_radio);
0230 }