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 | ||
516304b0 JP |
42 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
43 | ||
0ed4548f BC |
44 | #include <linux/pci.h> |
45 | #include "ath5k.h" | |
0ed4548f | 46 | |
e4bbf2f5 | 47 | #define ATH_SDEVICE(subv, subd) \ |
cdb02dc6 BC |
48 | .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ |
49 | .subvendor = (subv), .subdevice = (subd) | |
50 | ||
e4bbf2f5 | 51 | #define ATH_LED(pin, polarity) .driver_data = (((pin) << 8) | (polarity)) |
cdb02dc6 BC |
52 | #define ATH_PIN(data) ((data) >> 8) |
53 | #define ATH_POLARITY(data) ((data) & 0xff) | |
54 | ||
55 | /* Devices we match on for LED config info (typically laptops) */ | |
9baa3c34 | 56 | static const struct pci_device_id ath5k_led_devices[] = { |
cdb02dc6 BC |
57 | /* AR5211 */ |
58 | { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, | |
59 | /* HP Compaq nc6xx, nc4000, nx6000 */ | |
60 | { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, | |
61 | /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ | |
22e5b085 | 62 | { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, |
77c8258f KYL |
63 | /* Acer Aspire One AO531h AO751h (keng-yu.lin@canonical.com) */ |
64 | { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe00d), ATH_LED(3, 0) }, | |
22e5b085 BC |
65 | /* Acer Ferrari 5000 (russ.dill@gmail.com) */ |
66 | { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, | |
cdb02dc6 | 67 | /* E-machines E510 (tuliom@gmail.com) */ |
22e5b085 | 68 | { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, |
1e93bd4a BC |
69 | /* BenQ Joybook R55v (nowymarluk@wp.pl) */ |
70 | { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0100), ATH_LED(1, 0) }, | |
af83debf TMQMF |
71 | /* Acer Extensa 5620z (nekoreeve@gmail.com) */ |
72 | { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, | |
6a362bb1 BC |
73 | /* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */ |
74 | { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) }, | |
84379cba PL |
75 | /* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */ |
76 | { ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) }, | |
6f9797ae BC |
77 | /* HP Compaq CQ60-206US (ddreggors@jumptv.com) */ |
78 | { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, | |
09c9bae2 MC |
79 | /* HP Compaq C700 (nitrousnrg@gmail.com) */ |
80 | { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, | |
47db3a67 LV |
81 | /* LiteOn AR5BXB63 (magooz@salug.it) */ |
82 | { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) }, | |
84379cba PL |
83 | /* IBM-specific AR5212 (all others) */ |
84 | { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, | |
6a213afd SO |
85 | /* Dell Vostro A860 (shahar@shahar-or.co.il) */ |
86 | { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0112), ATH_LED(3, 0) }, | |
cdb02dc6 BC |
87 | { } |
88 | }; | |
89 | ||
e0d687bd | 90 | void ath5k_led_enable(struct ath5k_hw *ah) |
0ed4548f | 91 | { |
e0d687bd PR |
92 | if (test_bit(ATH_STAT_LEDSOFT, ah->status)) { |
93 | ath5k_hw_set_gpio_output(ah, ah->led_pin); | |
94 | ath5k_led_off(ah); | |
0ed4548f BC |
95 | } |
96 | } | |
97 | ||
e0d687bd | 98 | static void ath5k_led_on(struct ath5k_hw *ah) |
0ed4548f | 99 | { |
e0d687bd | 100 | if (!test_bit(ATH_STAT_LEDSOFT, ah->status)) |
0ed4548f | 101 | return; |
e0d687bd | 102 | ath5k_hw_set_gpio(ah, ah->led_pin, ah->led_on); |
0ed4548f BC |
103 | } |
104 | ||
e0d687bd | 105 | void ath5k_led_off(struct ath5k_hw *ah) |
0ed4548f | 106 | { |
e0d687bd | 107 | if (!test_bit(ATH_STAT_LEDSOFT, ah->status)) |
0ed4548f | 108 | return; |
e0d687bd | 109 | ath5k_hw_set_gpio(ah, ah->led_pin, !ah->led_on); |
0ed4548f BC |
110 | } |
111 | ||
112 | static void | |
113 | ath5k_led_brightness_set(struct led_classdev *led_dev, | |
114 | enum led_brightness brightness) | |
115 | { | |
116 | struct ath5k_led *led = container_of(led_dev, struct ath5k_led, | |
117 | led_dev); | |
118 | ||
119 | if (brightness == LED_OFF) | |
e0d687bd | 120 | ath5k_led_off(led->ah); |
0ed4548f | 121 | else |
e0d687bd | 122 | ath5k_led_on(led->ah); |
0ed4548f BC |
123 | } |
124 | ||
125 | static int | |
e0d687bd | 126 | ath5k_register_led(struct ath5k_hw *ah, struct ath5k_led *led, |
0ed4548f BC |
127 | const char *name, char *trigger) |
128 | { | |
129 | int err; | |
130 | ||
e0d687bd | 131 | led->ah = ah; |
0ed4548f | 132 | strncpy(led->name, name, sizeof(led->name)); |
daf9669b | 133 | led->name[sizeof(led->name)-1] = 0; |
0ed4548f BC |
134 | led->led_dev.name = led->name; |
135 | led->led_dev.default_trigger = trigger; | |
136 | led->led_dev.brightness_set = ath5k_led_brightness_set; | |
137 | ||
e0d687bd | 138 | err = led_classdev_register(ah->dev, &led->led_dev); |
0ed4548f | 139 | if (err) { |
e0d687bd PR |
140 | ATH5K_WARN(ah, "could not register LED %s\n", name); |
141 | led->ah = NULL; | |
0ed4548f BC |
142 | } |
143 | return err; | |
144 | } | |
145 | ||
146 | static void | |
147 | ath5k_unregister_led(struct ath5k_led *led) | |
148 | { | |
e0d687bd | 149 | if (!led->ah) |
0ed4548f BC |
150 | return; |
151 | led_classdev_unregister(&led->led_dev); | |
e0d687bd PR |
152 | ath5k_led_off(led->ah); |
153 | led->ah = NULL; | |
0ed4548f BC |
154 | } |
155 | ||
e0d687bd | 156 | void ath5k_unregister_leds(struct ath5k_hw *ah) |
0ed4548f | 157 | { |
e0d687bd PR |
158 | ath5k_unregister_led(&ah->rx_led); |
159 | ath5k_unregister_led(&ah->tx_led); | |
0ed4548f BC |
160 | } |
161 | ||
e829cf96 | 162 | int ath5k_init_leds(struct ath5k_hw *ah) |
0ed4548f BC |
163 | { |
164 | int ret = 0; | |
e0d687bd | 165 | struct ieee80211_hw *hw = ah->hw; |
e0d687bd | 166 | struct pci_dev *pdev = ah->pdev; |
0ed4548f | 167 | char name[ATH5K_LED_MAX_NAME_LEN + 1]; |
cdb02dc6 | 168 | const struct pci_device_id *match; |
0ed4548f | 169 | |
e0d687bd | 170 | if (!ah->pdev) |
8efa5d7d FF |
171 | return 0; |
172 | ||
cdb02dc6 BC |
173 | match = pci_match_id(&ath5k_led_devices[0], pdev); |
174 | if (match) { | |
e0d687bd PR |
175 | __set_bit(ATH_STAT_LEDSOFT, ah->status); |
176 | ah->led_pin = ATH_PIN(match->driver_data); | |
177 | ah->led_on = ATH_POLARITY(match->driver_data); | |
0ed4548f BC |
178 | } |
179 | ||
e0d687bd | 180 | if (!test_bit(ATH_STAT_LEDSOFT, ah->status)) |
0ed4548f BC |
181 | goto out; |
182 | ||
e0d687bd | 183 | ath5k_led_enable(ah); |
0ed4548f BC |
184 | |
185 | snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); | |
e0d687bd | 186 | ret = ath5k_register_led(ah, &ah->rx_led, name, |
0ed4548f BC |
187 | ieee80211_get_rx_led_name(hw)); |
188 | if (ret) | |
189 | goto out; | |
190 | ||
191 | snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); | |
e0d687bd | 192 | ret = ath5k_register_led(ah, &ah->tx_led, name, |
0ed4548f BC |
193 | ieee80211_get_tx_led_name(hw)); |
194 | out: | |
195 | return ret; | |
196 | } | |
197 |