Commit | Line | Data |
---|---|---|
0ed4548f BC |
1 | /* |
2 | * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting | |
3 | * Copyright (c) 2004-2005 Atheros Communications, Inc. | |
4 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | |
5 | * Copyright (c) 2009 Bob Copeland <me@bobcopeland.com> | |
6 | * | |
7 | * All rights reserved. | |
8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer, | |
14 | * without modification. | |
15 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | |
16 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | |
17 | * redistribution must be conditioned upon including a substantially | |
18 | * similar Disclaimer requirement for further binary redistribution. | |
19 | * 3. Neither the names of the above-listed copyright holders nor the names | |
20 | * of any contributors may be used to endorse or promote products derived | |
21 | * from this software without specific prior written permission. | |
22 | * | |
23 | * Alternatively, this software may be distributed under the terms of the | |
24 | * GNU General Public License ("GPL") version 2 as published by the Free | |
25 | * Software Foundation. | |
26 | * | |
27 | * NO WARRANTY | |
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
29 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
30 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | |
31 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |
32 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | |
33 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
34 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
35 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | |
36 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
37 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
38 | * THE POSSIBILITY OF SUCH DAMAGES. | |
39 | * | |
40 | */ | |
41 | ||
42 | #include <linux/pci.h> | |
43 | #include "ath5k.h" | |
0ed4548f | 44 | |
e4bbf2f5 | 45 | #define ATH_SDEVICE(subv, subd) \ |
cdb02dc6 BC |
46 | .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ |
47 | .subvendor = (subv), .subdevice = (subd) | |
48 | ||
e4bbf2f5 | 49 | #define ATH_LED(pin, polarity) .driver_data = (((pin) << 8) | (polarity)) |
cdb02dc6 BC |
50 | #define ATH_PIN(data) ((data) >> 8) |
51 | #define ATH_POLARITY(data) ((data) & 0xff) | |
52 | ||
53 | /* Devices we match on for LED config info (typically laptops) */ | |
25380d80 | 54 | static DEFINE_PCI_DEVICE_TABLE(ath5k_led_devices) = { |
cdb02dc6 BC |
55 | /* AR5211 */ |
56 | { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, | |
57 | /* HP Compaq nc6xx, nc4000, nx6000 */ | |
58 | { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, | |
59 | /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ | |
22e5b085 | 60 | { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, |
77c8258f KYL |
61 | /* Acer Aspire One AO531h AO751h (keng-yu.lin@canonical.com) */ |
62 | { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe00d), ATH_LED(3, 0) }, | |
22e5b085 BC |
63 | /* Acer Ferrari 5000 (russ.dill@gmail.com) */ |
64 | { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, | |
cdb02dc6 | 65 | /* E-machines E510 (tuliom@gmail.com) */ |
22e5b085 | 66 | { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, |
1e93bd4a BC |
67 | /* BenQ Joybook R55v (nowymarluk@wp.pl) */ |
68 | { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0100), ATH_LED(1, 0) }, | |
af83debf TMQMF |
69 | /* Acer Extensa 5620z (nekoreeve@gmail.com) */ |
70 | { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, | |
6a362bb1 BC |
71 | /* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */ |
72 | { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) }, | |
84379cba PL |
73 | /* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */ |
74 | { ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) }, | |
6f9797ae BC |
75 | /* HP Compaq CQ60-206US (ddreggors@jumptv.com) */ |
76 | { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, | |
09c9bae2 MC |
77 | /* HP Compaq C700 (nitrousnrg@gmail.com) */ |
78 | { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, | |
47db3a67 LV |
79 | /* LiteOn AR5BXB63 (magooz@salug.it) */ |
80 | { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) }, | |
84379cba PL |
81 | /* IBM-specific AR5212 (all others) */ |
82 | { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, | |
6a213afd SO |
83 | /* Dell Vostro A860 (shahar@shahar-or.co.il) */ |
84 | { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0112), ATH_LED(3, 0) }, | |
cdb02dc6 BC |
85 | { } |
86 | }; | |
87 | ||
e0d687bd | 88 | void ath5k_led_enable(struct ath5k_hw *ah) |
0ed4548f | 89 | { |
e0d687bd PR |
90 | if (test_bit(ATH_STAT_LEDSOFT, ah->status)) { |
91 | ath5k_hw_set_gpio_output(ah, ah->led_pin); | |
92 | ath5k_led_off(ah); | |
0ed4548f BC |
93 | } |
94 | } | |
95 | ||
e0d687bd | 96 | static void ath5k_led_on(struct ath5k_hw *ah) |
0ed4548f | 97 | { |
e0d687bd | 98 | if (!test_bit(ATH_STAT_LEDSOFT, ah->status)) |
0ed4548f | 99 | return; |
e0d687bd | 100 | ath5k_hw_set_gpio(ah, ah->led_pin, ah->led_on); |
0ed4548f BC |
101 | } |
102 | ||
e0d687bd | 103 | void ath5k_led_off(struct ath5k_hw *ah) |
0ed4548f | 104 | { |
e0d687bd | 105 | if (!test_bit(ATH_STAT_LEDSOFT, ah->status)) |
0ed4548f | 106 | return; |
e0d687bd | 107 | ath5k_hw_set_gpio(ah, ah->led_pin, !ah->led_on); |
0ed4548f BC |
108 | } |
109 | ||
110 | static void | |
111 | ath5k_led_brightness_set(struct led_classdev *led_dev, | |
112 | enum led_brightness brightness) | |
113 | { | |
114 | struct ath5k_led *led = container_of(led_dev, struct ath5k_led, | |
115 | led_dev); | |
116 | ||
117 | if (brightness == LED_OFF) | |
e0d687bd | 118 | ath5k_led_off(led->ah); |
0ed4548f | 119 | else |
e0d687bd | 120 | ath5k_led_on(led->ah); |
0ed4548f BC |
121 | } |
122 | ||
123 | static int | |
e0d687bd | 124 | ath5k_register_led(struct ath5k_hw *ah, struct ath5k_led *led, |
0ed4548f BC |
125 | const char *name, char *trigger) |
126 | { | |
127 | int err; | |
128 | ||
e0d687bd | 129 | led->ah = ah; |
0ed4548f BC |
130 | strncpy(led->name, name, sizeof(led->name)); |
131 | led->led_dev.name = led->name; | |
132 | led->led_dev.default_trigger = trigger; | |
133 | led->led_dev.brightness_set = ath5k_led_brightness_set; | |
134 | ||
e0d687bd | 135 | err = led_classdev_register(ah->dev, &led->led_dev); |
0ed4548f | 136 | if (err) { |
e0d687bd PR |
137 | ATH5K_WARN(ah, "could not register LED %s\n", name); |
138 | led->ah = NULL; | |
0ed4548f BC |
139 | } |
140 | return err; | |
141 | } | |
142 | ||
143 | static void | |
144 | ath5k_unregister_led(struct ath5k_led *led) | |
145 | { | |
e0d687bd | 146 | if (!led->ah) |
0ed4548f BC |
147 | return; |
148 | led_classdev_unregister(&led->led_dev); | |
e0d687bd PR |
149 | ath5k_led_off(led->ah); |
150 | led->ah = NULL; | |
0ed4548f BC |
151 | } |
152 | ||
e0d687bd | 153 | void ath5k_unregister_leds(struct ath5k_hw *ah) |
0ed4548f | 154 | { |
e0d687bd PR |
155 | ath5k_unregister_led(&ah->rx_led); |
156 | ath5k_unregister_led(&ah->tx_led); | |
0ed4548f BC |
157 | } |
158 | ||
e0d687bd | 159 | int __devinit ath5k_init_leds(struct ath5k_hw *ah) |
0ed4548f BC |
160 | { |
161 | int ret = 0; | |
e0d687bd | 162 | struct ieee80211_hw *hw = ah->hw; |
a0b907ee | 163 | #ifndef CONFIG_ATHEROS_AR231X |
e0d687bd | 164 | struct pci_dev *pdev = ah->pdev; |
a0b907ee | 165 | #endif |
0ed4548f | 166 | char name[ATH5K_LED_MAX_NAME_LEN + 1]; |
cdb02dc6 | 167 | const struct pci_device_id *match; |
0ed4548f | 168 | |
e0d687bd | 169 | if (!ah->pdev) |
8efa5d7d FF |
170 | return 0; |
171 | ||
a0b907ee FF |
172 | #ifdef CONFIG_ATHEROS_AR231X |
173 | match = NULL; | |
174 | #else | |
cdb02dc6 | 175 | match = pci_match_id(&ath5k_led_devices[0], pdev); |
a0b907ee | 176 | #endif |
cdb02dc6 | 177 | if (match) { |
e0d687bd PR |
178 | __set_bit(ATH_STAT_LEDSOFT, ah->status); |
179 | ah->led_pin = ATH_PIN(match->driver_data); | |
180 | ah->led_on = ATH_POLARITY(match->driver_data); | |
0ed4548f BC |
181 | } |
182 | ||
e0d687bd | 183 | if (!test_bit(ATH_STAT_LEDSOFT, ah->status)) |
0ed4548f BC |
184 | goto out; |
185 | ||
e0d687bd | 186 | ath5k_led_enable(ah); |
0ed4548f BC |
187 | |
188 | snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); | |
e0d687bd | 189 | ret = ath5k_register_led(ah, &ah->rx_led, name, |
0ed4548f BC |
190 | ieee80211_get_rx_led_name(hw)); |
191 | if (ret) | |
192 | goto out; | |
193 | ||
194 | snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); | |
e0d687bd | 195 | ret = ath5k_register_led(ah, &ah->tx_led, name, |
0ed4548f BC |
196 | ieee80211_get_tx_led_name(hw)); |
197 | out: | |
198 | return ret; | |
199 | } | |
200 |