aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtl818x/rtl8187/leds.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-12-20 15:16:53 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-22 13:45:32 -0500
commit3cfeb0c33f5cbcc6dde371392877ef3101b8f805 (patch)
tree017c47fa83ee62682e20d7ff90de1e4c17331194 /drivers/net/wireless/rtl818x/rtl8187/leds.c
parent3d986b25b5faa50ba6afd94f60f270b6c3061e5e (diff)
rtl818x: move rtl8180 and rtl8187 to separate subdirectories
These drivers share one header file, but nothing else. Worse, both drivers use the rtl8225 part with different register settings. The results has been some ugly naming -- let's simplify that. Signed-off-by: John W. Linville <linville@tuxdriver.com> Acked-by: Hin-Tak Leung <htl10@users.sourceforge.net> Acked-by: Larry Finger <Larry.Finger@lwfinger.net> Acked-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
Diffstat (limited to 'drivers/net/wireless/rtl818x/rtl8187/leds.c')
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/leds.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c
new file mode 100644
index 000000000000..2e0de2f5f0f9
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c
@@ -0,0 +1,245 @@
1/*
2 * Linux LED driver for RTL8187
3 *
4 * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
5 *
6 * Based on the LED handling in the r8187 driver, which is:
7 * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
8 *
9 * Thanks to Realtek for their support!
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#ifdef CONFIG_RTL8187_LEDS
17
18#include <net/mac80211.h>
19#include <linux/usb.h>
20#include <linux/eeprom_93cx6.h>
21
22#include "rtl8187.h"
23#include "leds.h"
24
25static void led_turn_on(struct work_struct *work)
26{
27 /* As this routine does read/write operations on the hardware, it must
28 * be run from a work queue.
29 */
30 u8 reg;
31 struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
32 led_on.work);
33 struct rtl8187_led *led = &priv->led_tx;
34
35 /* Don't change the LED, when the device is down. */
36 if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
37 return ;
38
39 /* Skip if the LED is not registered. */
40 if (!led->dev)
41 return;
42 mutex_lock(&priv->conf_mutex);
43 switch (led->ledpin) {
44 case LED_PIN_GPIO0:
45 rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
46 rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00);
47 break;
48 case LED_PIN_LED0:
49 reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4);
50 rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
51 break;
52 case LED_PIN_LED1:
53 reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5);
54 rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
55 break;
56 case LED_PIN_HW:
57 default:
58 break;
59 }
60 mutex_unlock(&priv->conf_mutex);
61}
62
63static void led_turn_off(struct work_struct *work)
64{
65 /* As this routine does read/write operations on the hardware, it must
66 * be run from a work queue.
67 */
68 u8 reg;
69 struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
70 led_off.work);
71 struct rtl8187_led *led = &priv->led_tx;
72
73 /* Don't change the LED, when the device is down. */
74 if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
75 return ;
76
77 /* Skip if the LED is not registered. */
78 if (!led->dev)
79 return;
80 mutex_lock(&priv->conf_mutex);
81 switch (led->ledpin) {
82 case LED_PIN_GPIO0:
83 rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
84 rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01);
85 break;
86 case LED_PIN_LED0:
87 reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4);
88 rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
89 break;
90 case LED_PIN_LED1:
91 reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5);
92 rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
93 break;
94 case LED_PIN_HW:
95 default:
96 break;
97 }
98 mutex_unlock(&priv->conf_mutex);
99}
100
101/* Callback from the LED subsystem. */
102static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
103 enum led_brightness brightness)
104{
105 struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led,
106 led_dev);
107 struct ieee80211_hw *hw = led->dev;
108 struct rtl8187_priv *priv;
109 static bool radio_on;
110
111 if (!hw)
112 return;
113 priv = hw->priv;
114 if (led->is_radio) {
115 if (brightness == LED_FULL) {
116 ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
117 radio_on = true;
118 } else if (radio_on) {
119 radio_on = false;
120 cancel_delayed_work_sync(&priv->led_on);
121 ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
122 }
123 } else if (radio_on) {
124 if (brightness == LED_OFF) {
125 ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
126 /* The LED is off for 1/20 sec - it just blinks. */
127 ieee80211_queue_delayed_work(hw, &priv->led_on,
128 HZ / 20);
129 } else
130 ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
131 }
132}
133
134static int rtl8187_register_led(struct ieee80211_hw *dev,
135 struct rtl8187_led *led, const char *name,
136 const char *default_trigger, u8 ledpin,
137 bool is_radio)
138{
139 int err;
140 struct rtl8187_priv *priv = dev->priv;
141
142 if (led->dev)
143 return -EEXIST;
144 if (!default_trigger)
145 return -EINVAL;
146 led->dev = dev;
147 led->ledpin = ledpin;
148 led->is_radio = is_radio;
149 strncpy(led->name, name, sizeof(led->name));
150
151 led->led_dev.name = led->name;
152 led->led_dev.default_trigger = default_trigger;
153 led->led_dev.brightness_set = rtl8187_led_brightness_set;
154
155 err = led_classdev_register(&priv->udev->dev, &led->led_dev);
156 if (err) {
157 printk(KERN_INFO "LEDs: Failed to register %s\n", name);
158 led->dev = NULL;
159 return err;
160 }
161 return 0;
162}
163
164static void rtl8187_unregister_led(struct rtl8187_led *led)
165{
166 struct ieee80211_hw *hw = led->dev;
167 struct rtl8187_priv *priv = hw->priv;
168
169 led_classdev_unregister(&led->led_dev);
170 flush_delayed_work(&priv->led_off);
171 led->dev = NULL;
172}
173
174void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
175{
176 struct rtl8187_priv *priv = dev->priv;
177 char name[RTL8187_LED_MAX_NAME_LEN + 1];
178 u8 ledpin;
179 int err;
180
181 /* According to the vendor driver, the LED operation depends on the
182 * customer ID encoded in the EEPROM
183 */
184 printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid);
185 switch (custid) {
186 case EEPROM_CID_RSVD0:
187 case EEPROM_CID_RSVD1:
188 case EEPROM_CID_SERCOMM_PS:
189 case EEPROM_CID_QMI:
190 case EEPROM_CID_DELL:
191 case EEPROM_CID_TOSHIBA:
192 ledpin = LED_PIN_GPIO0;
193 break;
194 case EEPROM_CID_ALPHA0:
195 ledpin = LED_PIN_LED0;
196 break;
197 case EEPROM_CID_HW:
198 ledpin = LED_PIN_HW;
199 break;
200 default:
201 ledpin = LED_PIN_GPIO0;
202 }
203
204 INIT_DELAYED_WORK(&priv->led_on, led_turn_on);
205 INIT_DELAYED_WORK(&priv->led_off, led_turn_off);
206
207 snprintf(name, sizeof(name),
208 "rtl8187-%s::radio", wiphy_name(dev->wiphy));
209 err = rtl8187_register_led(dev, &priv->led_radio, name,
210 ieee80211_get_radio_led_name(dev), ledpin, true);
211 if (err)
212 return;
213
214 snprintf(name, sizeof(name),
215 "rtl8187-%s::tx", wiphy_name(dev->wiphy));
216 err = rtl8187_register_led(dev, &priv->led_tx, name,
217 ieee80211_get_tx_led_name(dev), ledpin, false);
218 if (err)
219 goto err_tx;
220
221 snprintf(name, sizeof(name),
222 "rtl8187-%s::rx", wiphy_name(dev->wiphy));
223 err = rtl8187_register_led(dev, &priv->led_rx, name,
224 ieee80211_get_rx_led_name(dev), ledpin, false);
225 if (!err)
226 return;
227
228 /* registration of RX LED failed - unregister */
229 rtl8187_unregister_led(&priv->led_tx);
230err_tx:
231 rtl8187_unregister_led(&priv->led_radio);
232}
233
234void rtl8187_leds_exit(struct ieee80211_hw *dev)
235{
236 struct rtl8187_priv *priv = dev->priv;
237
238 rtl8187_unregister_led(&priv->led_radio);
239 rtl8187_unregister_led(&priv->led_rx);
240 rtl8187_unregister_led(&priv->led_tx);
241 cancel_delayed_work_sync(&priv->led_off);
242 cancel_delayed_work_sync(&priv->led_on);
243}
244#endif /* def CONFIG_RTL8187_LEDS */
245