diff options
author | Ulrich Kunitz <kune@deine-taler.de> | 2006-09-12 21:42:38 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-09-25 16:52:17 -0400 |
commit | 583afd1e4f25c87000c85ad7d03f5299fd4155dc (patch) | |
tree | e5ceeee697091a1b9a654ae3e6411cd4674a47c2 /drivers/net/wireless/zd1211rw/zd_chip.c | |
parent | bc5f06a8aaa29a79c9da2cedb5b9779b8081289c (diff) |
[PATCH] zd1211rw: Add LED support
This patch includes a big cleanup of the existing unused LED code,
and adds support for controlling the LED.
The link LED will blink if the device is not associated. The LED
switches between 2 seconds on and 1 second off. If the device is
associated the LED is switched on.
The link LED also indicates packet TX. I do a little bit more led
resetting than the vendor driver, but the device works now as
expected for single LED and double LED devices.
Signed-off-by: Ulrich Kunitz <kune@deine-taler.de>
Signed-off-by: Daniel Drake <dsd@gentoo.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/zd1211rw/zd_chip.c')
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_chip.c | 117 |
1 files changed, 48 insertions, 69 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index c213a2e56e55..aa661b2b76c7 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -325,13 +325,22 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type) | |||
325 | chip->patch_cr157 = (value >> 13) & 0x1; | 325 | chip->patch_cr157 = (value >> 13) & 0x1; |
326 | chip->patch_6m_band_edge = (value >> 21) & 0x1; | 326 | chip->patch_6m_band_edge = (value >> 21) & 0x1; |
327 | chip->new_phy_layout = (value >> 31) & 0x1; | 327 | chip->new_phy_layout = (value >> 31) & 0x1; |
328 | chip->link_led = ((value >> 4) & 1) ? LED1 : LED2; | ||
329 | chip->supports_tx_led = 1; | ||
330 | if (value & (1 << 24)) { /* LED scenario */ | ||
331 | if (value & (1 << 29)) | ||
332 | chip->supports_tx_led = 0; | ||
333 | } | ||
328 | 334 | ||
329 | dev_dbg_f(zd_chip_dev(chip), | 335 | dev_dbg_f(zd_chip_dev(chip), |
330 | "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " | 336 | "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " |
331 | "patch 6M %d new PHY %d\n", | 337 | "patch 6M %d new PHY %d link LED%d tx led %d\n", |
332 | zd_rf_name(*rf_type), *rf_type, | 338 | zd_rf_name(*rf_type), *rf_type, |
333 | chip->pa_type, chip->patch_cck_gain, | 339 | chip->pa_type, chip->patch_cck_gain, |
334 | chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout); | 340 | chip->patch_cr157, chip->patch_6m_band_edge, |
341 | chip->new_phy_layout, | ||
342 | chip->link_led == LED1 ? 1 : 2, | ||
343 | chip->supports_tx_led); | ||
335 | return 0; | 344 | return 0; |
336 | error: | 345 | error: |
337 | *rf_type = 0; | 346 | *rf_type = 0; |
@@ -1289,89 +1298,60 @@ u8 zd_chip_get_channel(struct zd_chip *chip) | |||
1289 | return channel; | 1298 | return channel; |
1290 | } | 1299 | } |
1291 | 1300 | ||
1292 | static u16 led_mask(int led) | 1301 | int zd_chip_control_leds(struct zd_chip *chip, enum led_status status) |
1293 | { | ||
1294 | switch (led) { | ||
1295 | case 1: | ||
1296 | return LED1; | ||
1297 | case 2: | ||
1298 | return LED2; | ||
1299 | default: | ||
1300 | return 0; | ||
1301 | } | ||
1302 | } | ||
1303 | |||
1304 | static int read_led_reg(struct zd_chip *chip, u16 *status) | ||
1305 | { | ||
1306 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
1307 | return zd_ioread16_locked(chip, status, CR_LED); | ||
1308 | } | ||
1309 | |||
1310 | static int write_led_reg(struct zd_chip *chip, u16 status) | ||
1311 | { | 1302 | { |
1312 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | 1303 | static const zd_addr_t a[] = { |
1313 | return zd_iowrite16_locked(chip, status, CR_LED); | 1304 | FW_LINK_STATUS, |
1314 | } | 1305 | CR_LED, |
1306 | }; | ||
1315 | 1307 | ||
1316 | int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status) | 1308 | int r; |
1317 | { | 1309 | u16 v[ARRAY_SIZE(a)]; |
1318 | int r, ret; | 1310 | struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = { |
1319 | u16 mask = led_mask(led); | 1311 | [0] = { FW_LINK_STATUS }, |
1320 | u16 reg; | 1312 | [1] = { CR_LED }, |
1313 | }; | ||
1314 | u16 other_led; | ||
1321 | 1315 | ||
1322 | if (!mask) | ||
1323 | return -EINVAL; | ||
1324 | mutex_lock(&chip->mutex); | 1316 | mutex_lock(&chip->mutex); |
1325 | r = read_led_reg(chip, ®); | 1317 | r = zd_ioread16v_locked(chip, v, (const zd_addr_t *)a, ARRAY_SIZE(a)); |
1326 | if (r) | 1318 | if (r) |
1327 | return r; | 1319 | goto out; |
1320 | |||
1321 | other_led = chip->link_led == LED1 ? LED2 : LED1; | ||
1322 | |||
1328 | switch (status) { | 1323 | switch (status) { |
1329 | case LED_STATUS: | ||
1330 | return (reg & mask) ? LED_ON : LED_OFF; | ||
1331 | case LED_OFF: | 1324 | case LED_OFF: |
1332 | reg &= ~mask; | 1325 | ioreqs[0].value = FW_LINK_OFF; |
1333 | ret = LED_OFF; | 1326 | ioreqs[1].value = v[1] & ~(LED1|LED2); |
1334 | break; | 1327 | break; |
1335 | case LED_FLIP: | 1328 | case LED_SCANNING: |
1336 | reg ^= mask; | 1329 | ioreqs[0].value = FW_LINK_OFF; |
1337 | ret = (reg&mask) ? LED_ON : LED_OFF; | 1330 | ioreqs[1].value = v[1] & ~other_led; |
1331 | if (get_seconds() % 3 == 0) { | ||
1332 | ioreqs[1].value &= ~chip->link_led; | ||
1333 | } else { | ||
1334 | ioreqs[1].value |= chip->link_led; | ||
1335 | } | ||
1338 | break; | 1336 | break; |
1339 | case LED_ON: | 1337 | case LED_ASSOCIATED: |
1340 | reg |= mask; | 1338 | ioreqs[0].value = FW_LINK_TX; |
1341 | ret = LED_ON; | 1339 | ioreqs[1].value = v[1] & ~other_led; |
1340 | ioreqs[1].value |= chip->link_led; | ||
1342 | break; | 1341 | break; |
1343 | default: | 1342 | default: |
1344 | return -EINVAL; | 1343 | r = -EINVAL; |
1345 | } | ||
1346 | r = write_led_reg(chip, reg); | ||
1347 | if (r) { | ||
1348 | ret = r; | ||
1349 | goto out; | 1344 | goto out; |
1350 | } | 1345 | } |
1351 | out: | ||
1352 | mutex_unlock(&chip->mutex); | ||
1353 | return r; | ||
1354 | } | ||
1355 | 1346 | ||
1356 | int zd_chip_led_flip(struct zd_chip *chip, int led, | 1347 | if (v[0] != ioreqs[0].value || v[1] != ioreqs[1].value) { |
1357 | const unsigned int *phases_msecs, unsigned int count) | 1348 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); |
1358 | { | 1349 | if (r) |
1359 | int i, r; | ||
1360 | enum led_status status; | ||
1361 | |||
1362 | r = zd_chip_led_status(chip, led, LED_STATUS); | ||
1363 | if (r) | ||
1364 | return r; | ||
1365 | status = r; | ||
1366 | for (i = 0; i < count; i++) { | ||
1367 | r = zd_chip_led_status(chip, led, LED_FLIP); | ||
1368 | if (r < 0) | ||
1369 | goto out; | 1350 | goto out; |
1370 | msleep(phases_msecs[i]); | ||
1371 | } | 1351 | } |
1372 | 1352 | r = 0; | |
1373 | out: | 1353 | out: |
1374 | zd_chip_led_status(chip, led, status); | 1354 | mutex_unlock(&chip->mutex); |
1375 | return r; | 1355 | return r; |
1376 | } | 1356 | } |
1377 | 1357 | ||
@@ -1673,4 +1653,3 @@ int zd_rfwritev_cr_locked(struct zd_chip *chip, | |||
1673 | 1653 | ||
1674 | return 0; | 1654 | return 0; |
1675 | } | 1655 | } |
1676 | |||