~ubuntu-branches/ubuntu/trusty/linux-backports-modules-3.2.0/trusty

« back to all changes in this revision

Viewing changes to updates/cw-3.3/drivers/net/wireless/rtl818x/rtl8187/leds.c

  • Committer: Package Import Robot
  • Author(s): Leann Ogasawara
  • Date: 2012-02-15 08:42:08 UTC
  • Revision ID: package-import@ubuntu.com-20120215084208-2gcs2zosufz014pi
Tags: 3.2.0-18.1
* Open Precise LBM
* Add compat-wireless v3.3
* Consolidated amd64 server flavour into generic
* Remove lpia control file
* Update Vcs-Git to ubuntu-preicse-lbm

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
25
static 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
 
 
63
static 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. */
 
102
static 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
 
 
134
static 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
 
 
164
static 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
 
 
174
void 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);
 
230
err_tx:
 
231
        rtl8187_unregister_led(&priv->led_radio);
 
232
}
 
233
 
 
234
void 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