root/drivers/net/wireless/ath/carl9170/led.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. carl9170_led_set_state
  2. carl9170_led_init
  3. carl9170_led_update
  4. carl9170_led_set_brightness
  5. carl9170_led_register_led
  6. carl9170_led_unregister
  7. carl9170_led_register

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

/* [<][>][^][v][top][bottom][index][help] */