Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * Atheros AR9170 driver
  3  *
  4  * LED handling
  5  *
  6  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
  7  *
  8  * This program is free software; you can redistribute it and/or modify
  9  * it under the terms of the GNU General Public License as published by
 10  * the Free Software Foundation; either version 2 of the License, or
 11  * (at your option) any later version.
 12  *
 13  * This program is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16  * GNU General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU General Public License
 19  * along with this program; see the file COPYING.  If not, see
 20  * http://www.gnu.org/licenses/.
 21  *
 22  * This file incorporates work covered by the following copyright and
 23  * permission notice:
 24  *    Copyright (c) 2007-2008 Atheros Communications, Inc.
 25  *
 26  *    Permission to use, copy, modify, and/or distribute this software for any
 27  *    purpose with or without fee is hereby granted, provided that the above
 28  *    copyright notice and this permission notice appear in all copies.
 29  *
 30  *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 31  *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 32  *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 33  *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 34  *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 35  *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 36  *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 37  */
 38 
 39 #include "ar9170.h"
 40 #include "cmd.h"
 41 
 42 int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state)
 43 {
 44         return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state);
 45 }
 46 
 47 int ar9170_init_leds(struct ar9170 *ar)
 48 {
 49         int err;
 50 
 51         /* disable LEDs */
 52         /* GPIO [0/1 mode: output, 2/3: input] */
 53         err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3);
 54         if (err)
 55                 goto out;
 56 
 57         /* GPIO 0/1 value: off */
 58         err = ar9170_set_leds_state(ar, 0);
 59 
 60 out:
 61         return err;
 62 }
 63 
 64 #ifdef CONFIG_AR9170_LEDS
 65 static void ar9170_update_leds(struct work_struct *work)
 66 {
 67         struct ar9170 *ar = container_of(work, struct ar9170, led_work.work);
 68         int i, tmp, blink_delay = 1000;
 69         u32 led_val = 0;
 70         bool rerun = false;
 71 
 72         if (unlikely(!IS_ACCEPTING_CMD(ar)))
 73                 return ;
 74 
 75         mutex_lock(&ar->mutex);
 76         for (i = 0; i < AR9170_NUM_LEDS; i++)
 77                 if (ar->leds[i].registered && ar->leds[i].toggled) {
 78                         led_val |= 1 << i;
 79 
 80                         tmp = 70 + 200 / (ar->leds[i].toggled);
 81                         if (tmp < blink_delay)
 82                                 blink_delay = tmp;
 83 
 84                         if (ar->leds[i].toggled > 1)
 85                                 ar->leds[i].toggled = 0;
 86 
 87                         rerun = true;
 88                 }
 89 
 90         ar9170_set_leds_state(ar, led_val);
 91         mutex_unlock(&ar->mutex);
 92 
 93         if (rerun)
 94                 queue_delayed_work(ar->hw->workqueue, &ar->led_work,
 95                                    msecs_to_jiffies(blink_delay));
 96 }
 97 
 98 static void ar9170_led_brightness_set(struct led_classdev *led,
 99                                       enum led_brightness brightness)
100 {
101         struct ar9170_led *arl = container_of(led, struct ar9170_led, l);
102         struct ar9170 *ar = arl->ar;
103 
104         if (unlikely(!arl->registered))
105                 return ;
106 
107         if (arl->last_state != !!brightness) {
108                 arl->toggled++;
109                 arl->last_state = !!brightness;
110         }
111 
112         if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
113                 queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10);
114 }
115 
116 static int ar9170_register_led(struct ar9170 *ar, int i, char *name,
117                                char *trigger)
118 {
119         int err;
120 
121         snprintf(ar->leds[i].name, sizeof(ar->leds[i].name),
122                  "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name);
123 
124         ar->leds[i].ar = ar;
125         ar->leds[i].l.name = ar->leds[i].name;
126         ar->leds[i].l.brightness_set = ar9170_led_brightness_set;
127         ar->leds[i].l.brightness = 0;
128         ar->leds[i].l.default_trigger = trigger;
129 
130         err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
131                                     &ar->leds[i].l);
132         if (err)
133                 printk(KERN_ERR "%s: failed to register %s LED (%d).\n",
134                        wiphy_name(ar->hw->wiphy), ar->leds[i].name, err);
135         else
136                 ar->leds[i].registered = true;
137 
138         return err;
139 }
140 
141 void ar9170_unregister_leds(struct ar9170 *ar)
142 {
143         int i;
144 
145         for (i = 0; i < AR9170_NUM_LEDS; i++)
146                 if (ar->leds[i].registered) {
147                         led_classdev_unregister(&ar->leds[i].l);
148                         ar->leds[i].registered = false;
149                         ar->leds[i].toggled = 0;
150                 }
151 
152         cancel_delayed_work_sync(&ar->led_work);
153 }
154 
155 int ar9170_register_leds(struct ar9170 *ar)
156 {
157         int err;
158 
159         INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds);
160 
161         err = ar9170_register_led(ar, 0, "tx",
162                                   ieee80211_get_tx_led_name(ar->hw));
163         if (err)
164                 goto fail;
165 
166         err = ar9170_register_led(ar, 1, "assoc",
167                                  ieee80211_get_assoc_led_name(ar->hw));
168         if (err)
169                 goto fail;
170 
171         return 0;
172 
173 fail:
174         ar9170_unregister_leds(ar);
175         return err;
176 }
177 
178 #endif /* CONFIG_AR9170_LEDS */
179 
  This page was automatically generated by the LXR engine.