1// SPDX-License-Identifier: GPL-2.0
2/* Copyright(c) 2009-2013  Realtek Corporation.*/
3
4#include "../wifi.h"
5#include "../pci.h"
6#include "reg.h"
7#include "led.h"
8
9static void _rtl88ee_init_led(struct ieee80211_hw *hw,
10			      struct rtl_led *pled, enum rtl_led_pin ledpin)
11{
12	pled->hw = hw;
13	pled->ledpin = ledpin;
14	pled->ledon = false;
15}
16
17void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
18{
19	u8 ledcfg;
20	struct rtl_priv *rtlpriv = rtl_priv(hw);
21
22	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
23		"LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
24
25	switch (pled->ledpin) {
26	case LED_PIN_GPIO0:
27		break;
28	case LED_PIN_LED0:
29		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
30		rtl_write_byte(rtlpriv,
31			       REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6));
32		break;
33	case LED_PIN_LED1:
34		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
35		rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
36		break;
37	default:
38		rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
39			"switch case %#x not processed\n", pled->ledpin);
40		break;
41	}
42	pled->ledon = true;
43}
44
45void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
46{
47	struct rtl_priv *rtlpriv = rtl_priv(hw);
48	u8 ledcfg;
49
50	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
51		"LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
52
53	switch (pled->ledpin) {
54	case LED_PIN_GPIO0:
55		break;
56	case LED_PIN_LED0:
57		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
58		ledcfg &= 0xf0;
59		if (rtlpriv->ledctl.led_opendrain) {
60			rtl_write_byte(rtlpriv, REG_LEDCFG2,
61				       (ledcfg | BIT(3) | BIT(5) | BIT(6)));
62			ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
63			rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG,
64				       (ledcfg & 0xFE));
65		} else
66			rtl_write_byte(rtlpriv, REG_LEDCFG2,
67				       (ledcfg | BIT(3) | BIT(5) | BIT(6)));
68		break;
69	case LED_PIN_LED1:
70		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
71		ledcfg &= 0x10;
72		rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3)));
73		break;
74	default:
75		rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
76			"switch case %#x not processed\n", pled->ledpin);
77		break;
78	}
79	pled->ledon = false;
80}
81
82void rtl88ee_init_sw_leds(struct ieee80211_hw *hw)
83{
84	struct rtl_priv *rtlpriv = rtl_priv(hw);
85
86	_rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
87	_rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
88}
89
90static void _rtl88ee_sw_led_control(struct ieee80211_hw *hw,
91				    enum led_ctl_mode ledaction)
92{
93	struct rtl_priv *rtlpriv = rtl_priv(hw);
94	struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
95
96	switch (ledaction) {
97	case LED_CTL_POWER_ON:
98	case LED_CTL_LINK:
99	case LED_CTL_NO_LINK:
100		rtl88ee_sw_led_on(hw, pled0);
101		break;
102	case LED_CTL_POWER_OFF:
103		rtl88ee_sw_led_off(hw, pled0);
104		break;
105	default:
106		break;
107	}
108}
109
110void rtl88ee_led_control(struct ieee80211_hw *hw,
111			enum led_ctl_mode ledaction)
112{
113	struct rtl_priv *rtlpriv = rtl_priv(hw);
114	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
115
116	if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
117	    (ledaction == LED_CTL_TX ||
118	     ledaction == LED_CTL_RX ||
119	     ledaction == LED_CTL_SITE_SURVEY ||
120	     ledaction == LED_CTL_LINK ||
121	     ledaction == LED_CTL_NO_LINK ||
122	     ledaction == LED_CTL_START_TO_LINK ||
123	     ledaction == LED_CTL_POWER_ON)) {
124		return;
125	}
126	rtl_dbg(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n",
127		ledaction);
128	_rtl88ee_sw_led_control(hw, ledaction);
129}
130