linux/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2010  Realtek Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * The full GNU General Public License is included in this distribution in the
  15 * file called LICENSE.
  16 *
  17 * Contact Information:
  18 * wlanfae <wlanfae@realtek.com>
  19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20 * Hsinchu 300, Taiwan.
  21 *
  22 * Larry Finger <Larry.Finger@lwfinger.net>
  23 *
  24 *****************************************************************************/
  25
  26#include "../wifi.h"
  27#include "../pci.h"
  28#include "reg.h"
  29#include "led.h"
  30
  31static void _rtl8821ae_init_led(struct ieee80211_hw *hw,
  32                                struct rtl_led *pled,
  33                                enum rtl_led_pin ledpin)
  34{
  35        pled->hw = hw;
  36        pled->ledpin = ledpin;
  37        pled->ledon = false;
  38}
  39
  40void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
  41{
  42        u8 ledcfg;
  43        struct rtl_priv *rtlpriv = rtl_priv(hw);
  44
  45        RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
  46                 "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
  47
  48        switch (pled->ledpin) {
  49        case LED_PIN_GPIO0:
  50                break;
  51        case LED_PIN_LED0:
  52                ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
  53                ledcfg &= ~BIT(6);
  54                rtl_write_byte(rtlpriv,
  55                               REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5));
  56                break;
  57        case LED_PIN_LED1:
  58                ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
  59                rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
  60                break;
  61        default:
  62                RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
  63                         "switch case %#x not processed\n", pled->ledpin);
  64                break;
  65        }
  66        pled->ledon = true;
  67}
  68
  69void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
  70{
  71        u16     ledreg = REG_LEDCFG1;
  72        u8      ledcfg = 0;
  73        struct rtl_priv *rtlpriv = rtl_priv(hw);
  74
  75        switch (pled->ledpin) {
  76        case LED_PIN_LED0:
  77                ledreg = REG_LEDCFG1;
  78                break;
  79
  80        case LED_PIN_LED1:
  81                ledreg = REG_LEDCFG2;
  82                break;
  83
  84        case LED_PIN_GPIO0:
  85        default:
  86                break;
  87        }
  88
  89        RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
  90                 "In SwLedOn, LedAddr:%X LEDPIN=%d\n",
  91                 ledreg, pled->ledpin);
  92
  93        ledcfg =  rtl_read_byte(rtlpriv, ledreg);
  94        ledcfg |= BIT(5); /*Set 0x4c[21]*/
  95        ledcfg &= ~(BIT(7) | BIT(6) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
  96                /*Clear 0x4c[23:22] and 0x4c[19:16]*/
  97        rtl_write_byte(rtlpriv, ledreg, ledcfg); /*SW control led0 on.*/
  98        pled->ledon = true;
  99}
 100
 101void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 102{
 103        struct rtl_priv *rtlpriv = rtl_priv(hw);
 104        u8 ledcfg;
 105
 106        RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
 107                 "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
 108
 109        ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
 110
 111        switch (pled->ledpin) {
 112        case LED_PIN_GPIO0:
 113                break;
 114        case LED_PIN_LED0:
 115                ledcfg &= 0xf0;
 116                if (rtlpriv->ledctl.led_opendrain) {
 117                        ledcfg &= 0x90; /* Set to software control. */
 118                        rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3)));
 119                        ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
 120                        ledcfg &= 0xFE;
 121                        rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg);
 122                } else {
 123                        ledcfg &= ~BIT(6);
 124                        rtl_write_byte(rtlpriv, REG_LEDCFG2,
 125                                       (ledcfg | BIT(3) | BIT(5)));
 126                }
 127                break;
 128        case LED_PIN_LED1:
 129                ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
 130                ledcfg &= 0x10; /* Set to software control. */
 131                rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3));
 132                break;
 133        default:
 134                RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
 135                         "switch case %#x not processed\n", pled->ledpin);
 136                break;
 137        }
 138        pled->ledon = false;
 139}
 140
 141void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 142{
 143        u16 ledreg = REG_LEDCFG1;
 144        struct rtl_priv *rtlpriv = rtl_priv(hw);
 145
 146        switch (pled->ledpin) {
 147        case LED_PIN_LED0:
 148                ledreg = REG_LEDCFG1;
 149                break;
 150
 151        case LED_PIN_LED1:
 152                ledreg = REG_LEDCFG2;
 153                break;
 154
 155        case LED_PIN_GPIO0:
 156        default:
 157                break;
 158        }
 159
 160        RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
 161                 "In SwLedOff,LedAddr:%X LEDPIN=%d\n",
 162                 ledreg, pled->ledpin);
 163        /*Open-drain arrangement for controlling the LED*/
 164        if (rtlpriv->ledctl.led_opendrain) {
 165                u8 ledcfg = rtl_read_byte(rtlpriv, ledreg);
 166
 167                ledreg &= 0xd0; /* Set to software control.*/
 168                rtl_write_byte(rtlpriv, ledreg, (ledcfg | BIT(3)));
 169
 170                /*Open-drain arrangement*/
 171                ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
 172                ledcfg &= 0xFE;/*Set GPIO[8] to input mode*/
 173                rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg);
 174        } else {
 175                rtl_write_byte(rtlpriv, ledreg, 0x28);
 176        }
 177
 178        pled->ledon = false;
 179}
 180
 181void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw)
 182{
 183        struct rtl_priv *rtlpriv = rtl_priv(hw);
 184
 185        _rtl8821ae_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
 186        _rtl8821ae_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
 187}
 188
 189static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw,
 190                                      enum led_ctl_mode ledaction)
 191{
 192        struct rtl_priv *rtlpriv = rtl_priv(hw);
 193        struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
 194        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 195
 196        switch (ledaction) {
 197        case LED_CTL_POWER_ON:
 198        case LED_CTL_LINK:
 199        case LED_CTL_NO_LINK:
 200                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 201                        rtl8812ae_sw_led_on(hw, pled0);
 202                else
 203                        rtl8821ae_sw_led_on(hw, pled0);
 204                break;
 205        case LED_CTL_POWER_OFF:
 206                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 207                        rtl8812ae_sw_led_off(hw, pled0);
 208                else
 209                        rtl8821ae_sw_led_off(hw, pled0);
 210                break;
 211        default:
 212                break;
 213        }
 214}
 215
 216void rtl8821ae_led_control(struct ieee80211_hw *hw,
 217                           enum led_ctl_mode ledaction)
 218{
 219        struct rtl_priv *rtlpriv = rtl_priv(hw);
 220        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 221
 222        if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
 223            (ledaction == LED_CTL_TX ||
 224             ledaction == LED_CTL_RX ||
 225             ledaction == LED_CTL_SITE_SURVEY ||
 226             ledaction == LED_CTL_LINK ||
 227             ledaction == LED_CTL_NO_LINK ||
 228             ledaction == LED_CTL_START_TO_LINK ||
 229             ledaction == LED_CTL_POWER_ON)) {
 230                return;
 231        }
 232        RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n",
 233                 ledaction);
 234        _rtl8821ae_sw_led_control(hw, ledaction);
 235}
 236