]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[karo-tx-linux.git] / drivers / net / wireless / realtek / rtlwifi / rtl8821ae / led.c
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
31 static 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
40 void 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 not process\n");
64                 break;
65         }
66         pled->ledon = true;
67 }
68
69 void 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
101 void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
102 {
103         struct rtl_priv *rtlpriv = rtl_priv(hw);
104         struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
105         u8 ledcfg;
106
107         RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
108                  "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
109
110         ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
111
112         switch (pled->ledpin) {
113         case LED_PIN_GPIO0:
114                 break;
115         case LED_PIN_LED0:
116                 ledcfg &= 0xf0;
117                 if (pcipriv->ledctl.led_opendrain) {
118                         ledcfg &= 0x90; /* Set to software control. */
119                         rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3)));
120                         ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
121                         ledcfg &= 0xFE;
122                         rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg);
123                 } else {
124                         ledcfg &= ~BIT(6);
125                         rtl_write_byte(rtlpriv, REG_LEDCFG2,
126                                        (ledcfg | BIT(3) | BIT(5)));
127                 }
128                 break;
129         case LED_PIN_LED1:
130                 ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
131                 ledcfg &= 0x10; /* Set to software control. */
132                 rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3));
133                 break;
134         default:
135                 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
136                          "switch case not process\n");
137                 break;
138         }
139         pled->ledon = false;
140 }
141
142 void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
143 {
144         u16 ledreg = REG_LEDCFG1;
145         struct rtl_priv *rtlpriv = rtl_priv(hw);
146         struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
147
148         switch (pled->ledpin) {
149         case LED_PIN_LED0:
150                 ledreg = REG_LEDCFG1;
151                 break;
152
153         case LED_PIN_LED1:
154                 ledreg = REG_LEDCFG2;
155                 break;
156
157         case LED_PIN_GPIO0:
158         default:
159                 break;
160         }
161
162         RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
163                  "In SwLedOff,LedAddr:%X LEDPIN=%d\n",
164                  ledreg, pled->ledpin);
165         /*Open-drain arrangement for controlling the LED*/
166         if (pcipriv->ledctl.led_opendrain) {
167                 u8 ledcfg = rtl_read_byte(rtlpriv, ledreg);
168
169                 ledreg &= 0xd0; /* Set to software control.*/
170                 rtl_write_byte(rtlpriv, ledreg, (ledcfg | BIT(3)));
171
172                 /*Open-drain arrangement*/
173                 ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
174                 ledcfg &= 0xFE;/*Set GPIO[8] to input mode*/
175                 rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg);
176         } else {
177                 rtl_write_byte(rtlpriv, ledreg, 0x28);
178         }
179
180         pled->ledon = false;
181 }
182
183 void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw)
184 {
185         struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
186
187         _rtl8821ae_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0);
188         _rtl8821ae_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1);
189 }
190
191 static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw,
192                                       enum led_ctl_mode ledaction)
193 {
194         struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
195         struct rtl_led *pLed0 = &pcipriv->ledctl.sw_led0;
196         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
197
198         switch (ledaction) {
199         case LED_CTL_POWER_ON:
200         case LED_CTL_LINK:
201         case LED_CTL_NO_LINK:
202                 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
203                         rtl8812ae_sw_led_on(hw, pLed0);
204                 else
205                         rtl8821ae_sw_led_on(hw, pLed0);
206                 break;
207         case LED_CTL_POWER_OFF:
208                 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
209                         rtl8812ae_sw_led_off(hw, pLed0);
210                 else
211                         rtl8821ae_sw_led_off(hw, pLed0);
212                 break;
213         default:
214                 break;
215         }
216 }
217
218 void rtl8821ae_led_control(struct ieee80211_hw *hw,
219                            enum led_ctl_mode ledaction)
220 {
221         struct rtl_priv *rtlpriv = rtl_priv(hw);
222         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
223
224         if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
225             (ledaction == LED_CTL_TX ||
226              ledaction == LED_CTL_RX ||
227              ledaction == LED_CTL_SITE_SURVEY ||
228              ledaction == LED_CTL_LINK ||
229              ledaction == LED_CTL_NO_LINK ||
230              ledaction == LED_CTL_START_TO_LINK ||
231              ledaction == LED_CTL_POWER_ON)) {
232                 return;
233         }
234         RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n",
235                  ledaction);
236         _rtl8821ae_sw_led_control(hw, ledaction);
237 }