Linux Audio

Check our new training course

Loading...
v3.1
  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
 43int 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
 48int 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
 61out:
 62	return err;
 63}
 64
 65#ifdef CONFIG_CARL9170_LEDS
 66static 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
106static 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
124static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name,
125				     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
150void 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
164int 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
185fail:
186	carl9170_led_unregister(ar);
187	return err;
188}
189
190#endif /* CONFIG_CARL9170_LEDS */
v6.13.7
  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
 43int 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
 48int 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
 61out:
 62	return err;
 63}
 64
 65#ifdef CONFIG_CARL9170_LEDS
 66static 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
106static 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
124static 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
150void 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
164int 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
185fail:
186	carl9170_led_unregister(ar);
187	return err;
188}
189
190#endif /* CONFIG_CARL9170_LEDS */