0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #include "carl9170.h"
0041 #include "cmd.h"
0042
0043 int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state)
0044 {
0045 return carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_DATA, led_state);
0046 }
0047
0048 int carl9170_led_init(struct ar9170 *ar)
0049 {
0050 int err;
0051
0052
0053
0054 err = carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3);
0055 if (err)
0056 goto out;
0057
0058
0059 err = carl9170_led_set_state(ar, 0);
0060
0061 out:
0062 return err;
0063 }
0064
0065 #ifdef CONFIG_CARL9170_LEDS
0066 static void carl9170_led_update(struct work_struct *work)
0067 {
0068 struct ar9170 *ar = container_of(work, struct ar9170, led_work.work);
0069 int i, tmp = 300, blink_delay = 1000;
0070 u32 led_val = 0;
0071 bool rerun = false;
0072
0073 if (!IS_ACCEPTING_CMD(ar))
0074 return;
0075
0076 mutex_lock(&ar->mutex);
0077 for (i = 0; i < AR9170_NUM_LEDS; i++) {
0078 if (ar->leds[i].registered) {
0079 if (ar->leds[i].last_state ||
0080 ar->leds[i].toggled) {
0081
0082 if (ar->leds[i].toggled)
0083 tmp = 70 + 200 / (ar->leds[i].toggled);
0084
0085 if (tmp < blink_delay)
0086 blink_delay = tmp;
0087
0088 led_val |= 1 << i;
0089 ar->leds[i].toggled = 0;
0090 rerun = true;
0091 }
0092 }
0093 }
0094
0095 carl9170_led_set_state(ar, led_val);
0096 mutex_unlock(&ar->mutex);
0097
0098 if (!rerun)
0099 return;
0100
0101 ieee80211_queue_delayed_work(ar->hw,
0102 &ar->led_work,
0103 msecs_to_jiffies(blink_delay));
0104 }
0105
0106 static void carl9170_led_set_brightness(struct led_classdev *led,
0107 enum led_brightness brightness)
0108 {
0109 struct carl9170_led *arl = container_of(led, struct carl9170_led, l);
0110 struct ar9170 *ar = arl->ar;
0111
0112 if (!arl->registered)
0113 return;
0114
0115 if (arl->last_state != !!brightness) {
0116 arl->toggled++;
0117 arl->last_state = !!brightness;
0118 }
0119
0120 if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
0121 ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ / 10);
0122 }
0123
0124 static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name,
0125 const char *trigger)
0126 {
0127 int err;
0128
0129 snprintf(ar->leds[i].name, sizeof(ar->leds[i].name),
0130 "carl9170-%s::%s", wiphy_name(ar->hw->wiphy), name);
0131
0132 ar->leds[i].ar = ar;
0133 ar->leds[i].l.name = ar->leds[i].name;
0134 ar->leds[i].l.brightness_set = carl9170_led_set_brightness;
0135 ar->leds[i].l.brightness = 0;
0136 ar->leds[i].l.default_trigger = trigger;
0137
0138 err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
0139 &ar->leds[i].l);
0140 if (err) {
0141 wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n",
0142 ar->leds[i].name, err);
0143 } else {
0144 ar->leds[i].registered = true;
0145 }
0146
0147 return err;
0148 }
0149
0150 void carl9170_led_unregister(struct ar9170 *ar)
0151 {
0152 int i;
0153
0154 for (i = 0; i < AR9170_NUM_LEDS; i++)
0155 if (ar->leds[i].registered) {
0156 led_classdev_unregister(&ar->leds[i].l);
0157 ar->leds[i].registered = false;
0158 ar->leds[i].toggled = 0;
0159 }
0160
0161 cancel_delayed_work_sync(&ar->led_work);
0162 }
0163
0164 int carl9170_led_register(struct ar9170 *ar)
0165 {
0166 int err;
0167
0168 INIT_DELAYED_WORK(&ar->led_work, carl9170_led_update);
0169
0170 err = carl9170_led_register_led(ar, 0, "tx",
0171 ieee80211_get_tx_led_name(ar->hw));
0172 if (err)
0173 goto fail;
0174
0175 if (ar->features & CARL9170_ONE_LED)
0176 return 0;
0177
0178 err = carl9170_led_register_led(ar, 1, "assoc",
0179 ieee80211_get_assoc_led_name(ar->hw));
0180 if (err)
0181 goto fail;
0182
0183 return 0;
0184
0185 fail:
0186 carl9170_led_unregister(ar);
0187 return err;
0188 }
0189
0190 #endif