1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2010  Realtek Corporation.*/
3 
4 #include "../wifi.h"
5 #include "../pci.h"
6 #include "reg.h"
7 #include "led.h"
8 
9 void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
10 {
11 	u8 ledcfg;
12 	struct rtl_priv *rtlpriv = rtl_priv(hw);
13 
14 	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
15 		"LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
16 
17 	switch (pin) {
18 	case LED_PIN_GPIO0:
19 		break;
20 	case LED_PIN_LED0:
21 		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
22 		ledcfg &= ~BIT(6);
23 		rtl_write_byte(rtlpriv,
24 			       REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5));
25 		break;
26 	case LED_PIN_LED1:
27 		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
28 		rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
29 		break;
30 	default:
31 		rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
32 			"switch case %#x not processed\n", pin);
33 		break;
34 	}
35 }
36 
37 void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
38 {
39 	u16	ledreg = REG_LEDCFG1;
40 	u8	ledcfg = 0;
41 	struct rtl_priv *rtlpriv = rtl_priv(hw);
42 
43 	switch (pin) {
44 	case LED_PIN_LED0:
45 		ledreg = REG_LEDCFG1;
46 		break;
47 
48 	case LED_PIN_LED1:
49 		ledreg = REG_LEDCFG2;
50 		break;
51 
52 	case LED_PIN_GPIO0:
53 	default:
54 		break;
55 	}
56 
57 	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
58 		"In SwLedOn, LedAddr:%X LEDPIN=%d\n",
59 		ledreg, pin);
60 
61 	ledcfg =  rtl_read_byte(rtlpriv, ledreg);
62 	ledcfg |= BIT(5); /*Set 0x4c[21]*/
63 	ledcfg &= ~(BIT(7) | BIT(6) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
64 		/*Clear 0x4c[23:22] and 0x4c[19:16]*/
65 	rtl_write_byte(rtlpriv, ledreg, ledcfg); /*SW control led0 on.*/
66 }
67 
68 void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
69 {
70 	struct rtl_priv *rtlpriv = rtl_priv(hw);
71 	u8 ledcfg;
72 
73 	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
74 		"LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
75 
76 	ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
77 
78 	switch (pin) {
79 	case LED_PIN_GPIO0:
80 		break;
81 	case LED_PIN_LED0:
82 		ledcfg &= 0xf0;
83 		if (rtlpriv->ledctl.led_opendrain) {
84 			ledcfg &= 0x90; /* Set to software control. */
85 			rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3)));
86 			ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
87 			ledcfg &= 0xFE;
88 			rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg);
89 		} else {
90 			ledcfg &= ~BIT(6);
91 			rtl_write_byte(rtlpriv, REG_LEDCFG2,
92 				       (ledcfg | BIT(3) | BIT(5)));
93 		}
94 		break;
95 	case LED_PIN_LED1:
96 		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
97 		ledcfg &= 0x10; /* Set to software control. */
98 		rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3));
99 		break;
100 	default:
101 		rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
102 			"switch case %#x not processed\n", pin);
103 		break;
104 	}
105 }
106 
107 void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
108 {
109 	u16 ledreg = REG_LEDCFG1;
110 	struct rtl_priv *rtlpriv = rtl_priv(hw);
111 
112 	switch (pin) {
113 	case LED_PIN_LED0:
114 		ledreg = REG_LEDCFG1;
115 		break;
116 
117 	case LED_PIN_LED1:
118 		ledreg = REG_LEDCFG2;
119 		break;
120 
121 	case LED_PIN_GPIO0:
122 	default:
123 		break;
124 	}
125 
126 	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
127 		"In SwLedOff,LedAddr:%X LEDPIN=%d\n",
128 		ledreg, pin);
129 	/*Open-drain arrangement for controlling the LED*/
130 	if (rtlpriv->ledctl.led_opendrain) {
131 		u8 ledcfg = rtl_read_byte(rtlpriv, ledreg);
132 
133 		ledreg &= 0xd0; /* Set to software control.*/
134 		rtl_write_byte(rtlpriv, ledreg, (ledcfg | BIT(3)));
135 
136 		/*Open-drain arrangement*/
137 		ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
138 		ledcfg &= 0xFE;/*Set GPIO[8] to input mode*/
139 		rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg);
140 	} else {
141 		rtl_write_byte(rtlpriv, ledreg, 0x28);
142 	}
143 }
144 
145 static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw,
146 				      enum led_ctl_mode ledaction)
147 {
148 	struct rtl_priv *rtlpriv = rtl_priv(hw);
149 	enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
150 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
151 
152 	switch (ledaction) {
153 	case LED_CTL_POWER_ON:
154 	case LED_CTL_LINK:
155 	case LED_CTL_NO_LINK:
156 		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
157 			rtl8812ae_sw_led_on(hw, pin0);
158 		else
159 			rtl8821ae_sw_led_on(hw, pin0);
160 		break;
161 	case LED_CTL_POWER_OFF:
162 		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
163 			rtl8812ae_sw_led_off(hw, pin0);
164 		else
165 			rtl8821ae_sw_led_off(hw, pin0);
166 		break;
167 	default:
168 		break;
169 	}
170 }
171 
172 void rtl8821ae_led_control(struct ieee80211_hw *hw,
173 			   enum led_ctl_mode ledaction)
174 {
175 	struct rtl_priv *rtlpriv = rtl_priv(hw);
176 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
177 
178 	if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
179 	    (ledaction == LED_CTL_TX ||
180 	     ledaction == LED_CTL_RX ||
181 	     ledaction == LED_CTL_SITE_SURVEY ||
182 	     ledaction == LED_CTL_LINK ||
183 	     ledaction == LED_CTL_NO_LINK ||
184 	     ledaction == LED_CTL_START_TO_LINK ||
185 	     ledaction == LED_CTL_POWER_ON)) {
186 		return;
187 	}
188 	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n",
189 		ledaction);
190 	_rtl8821ae_sw_led_control(hw, ledaction);
191 }
192