0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0043
0044 #include <linux/pci.h>
0045 #include "ath5k.h"
0046
0047 #define ATH_SDEVICE(subv, subd) \
0048 .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
0049 .subvendor = (subv), .subdevice = (subd)
0050
0051 #define ATH_LED(pin, polarity) .driver_data = (((pin) << 8) | (polarity))
0052 #define ATH_PIN(data) ((data) >> 8)
0053 #define ATH_POLARITY(data) ((data) & 0xff)
0054
0055
0056 static const struct pci_device_id ath5k_led_devices[] = {
0057
0058 { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
0059
0060 { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) },
0061
0062 { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) },
0063
0064 { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe00d), ATH_LED(3, 0) },
0065
0066 { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) },
0067
0068 { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) },
0069
0070 { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0100), ATH_LED(1, 0) },
0071
0072 { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) },
0073
0074 { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) },
0075
0076 { ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) },
0077
0078 { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) },
0079
0080 { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 0) },
0081
0082 { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) },
0083
0084 { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
0085
0086 { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0112), ATH_LED(3, 0) },
0087 { }
0088 };
0089
0090 void ath5k_led_enable(struct ath5k_hw *ah)
0091 {
0092 if (IS_ENABLED(CONFIG_MAC80211_LEDS) &&
0093 test_bit(ATH_STAT_LEDSOFT, ah->status)) {
0094 ath5k_hw_set_gpio_output(ah, ah->led_pin);
0095 ath5k_led_off(ah);
0096 }
0097 }
0098
0099 static void ath5k_led_on(struct ath5k_hw *ah)
0100 {
0101 if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
0102 return;
0103 ath5k_hw_set_gpio(ah, ah->led_pin, ah->led_on);
0104 }
0105
0106 void ath5k_led_off(struct ath5k_hw *ah)
0107 {
0108 if (!IS_ENABLED(CONFIG_MAC80211_LEDS) ||
0109 !test_bit(ATH_STAT_LEDSOFT, ah->status))
0110 return;
0111 ath5k_hw_set_gpio(ah, ah->led_pin, !ah->led_on);
0112 }
0113
0114 static void
0115 ath5k_led_brightness_set(struct led_classdev *led_dev,
0116 enum led_brightness brightness)
0117 {
0118 struct ath5k_led *led = container_of(led_dev, struct ath5k_led,
0119 led_dev);
0120
0121 if (brightness == LED_OFF)
0122 ath5k_led_off(led->ah);
0123 else
0124 ath5k_led_on(led->ah);
0125 }
0126
0127 static int
0128 ath5k_register_led(struct ath5k_hw *ah, struct ath5k_led *led,
0129 const char *name, const char *trigger)
0130 {
0131 int err;
0132
0133 led->ah = ah;
0134 strncpy(led->name, name, sizeof(led->name));
0135 led->name[sizeof(led->name)-1] = 0;
0136 led->led_dev.name = led->name;
0137 led->led_dev.default_trigger = trigger;
0138 led->led_dev.brightness_set = ath5k_led_brightness_set;
0139
0140 err = led_classdev_register(ah->dev, &led->led_dev);
0141 if (err) {
0142 ATH5K_WARN(ah, "could not register LED %s\n", name);
0143 led->ah = NULL;
0144 }
0145 return err;
0146 }
0147
0148 static void
0149 ath5k_unregister_led(struct ath5k_led *led)
0150 {
0151 if (!IS_ENABLED(CONFIG_MAC80211_LEDS) || !led->ah)
0152 return;
0153 led_classdev_unregister(&led->led_dev);
0154 ath5k_led_off(led->ah);
0155 led->ah = NULL;
0156 }
0157
0158 void ath5k_unregister_leds(struct ath5k_hw *ah)
0159 {
0160 ath5k_unregister_led(&ah->rx_led);
0161 ath5k_unregister_led(&ah->tx_led);
0162 }
0163
0164 int ath5k_init_leds(struct ath5k_hw *ah)
0165 {
0166 int ret = 0;
0167 struct ieee80211_hw *hw = ah->hw;
0168 #ifndef CONFIG_ATH5K_AHB
0169 struct pci_dev *pdev = ah->pdev;
0170 #endif
0171 char name[ATH5K_LED_MAX_NAME_LEN + 1];
0172 const struct pci_device_id *match;
0173
0174 if (!IS_ENABLED(CONFIG_MAC80211_LEDS) || !ah->pdev)
0175 return 0;
0176
0177 #ifdef CONFIG_ATH5K_AHB
0178 match = NULL;
0179 #else
0180 match = pci_match_id(&ath5k_led_devices[0], pdev);
0181 #endif
0182 if (match) {
0183 __set_bit(ATH_STAT_LEDSOFT, ah->status);
0184 ah->led_pin = ATH_PIN(match->driver_data);
0185 ah->led_on = ATH_POLARITY(match->driver_data);
0186 }
0187
0188 if (!test_bit(ATH_STAT_LEDSOFT, ah->status))
0189 goto out;
0190
0191 ath5k_led_enable(ah);
0192
0193 snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy));
0194 ret = ath5k_register_led(ah, &ah->rx_led, name,
0195 ieee80211_get_rx_led_name(hw));
0196 if (ret)
0197 goto out;
0198
0199 snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy));
0200 ret = ath5k_register_led(ah, &ah->tx_led, name,
0201 ieee80211_get_tx_led_name(hw));
0202 out:
0203 return ret;
0204 }
0205