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