1cfa9a966SJiaxin Yu // SPDX-License-Identifier: GPL-2.0
2cfa9a966SJiaxin Yu //
3cfa9a966SJiaxin Yu // mt8186-afe-gpio.c  --  Mediatek 8186 afe gpio ctrl
4cfa9a966SJiaxin Yu //
5cfa9a966SJiaxin Yu // Copyright (c) 2022 MediaTek Inc.
6cfa9a966SJiaxin Yu // Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
7cfa9a966SJiaxin Yu 
8cfa9a966SJiaxin Yu #include <linux/gpio.h>
9cfa9a966SJiaxin Yu #include <linux/pinctrl/consumer.h>
10cfa9a966SJiaxin Yu 
11cfa9a966SJiaxin Yu #include "mt8186-afe-common.h"
12cfa9a966SJiaxin Yu #include "mt8186-afe-gpio.h"
13cfa9a966SJiaxin Yu 
14*672029caSTom Rix static struct pinctrl *aud_pinctrl;
15cfa9a966SJiaxin Yu 
16cfa9a966SJiaxin Yu enum mt8186_afe_gpio {
17cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_CLK_MOSI_OFF,
18cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_CLK_MOSI_ON,
19cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_CLK_MISO_OFF,
20cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_CLK_MISO_ON,
21cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_DAT_MISO_OFF,
22cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_DAT_MISO_ON,
23cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_DAT_MOSI_OFF,
24cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_DAT_MOSI_ON,
25cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_I2S0_OFF,
26cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_I2S0_ON,
27cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_I2S1_OFF,
28cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_I2S1_ON,
29cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_I2S2_OFF,
30cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_I2S2_ON,
31cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_I2S3_OFF,
32cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_I2S3_ON,
33cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_TDM_OFF,
34cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_TDM_ON,
35cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_PCM_OFF,
36cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_PCM_ON,
37cfa9a966SJiaxin Yu 	MT8186_AFE_GPIO_GPIO_NUM
38cfa9a966SJiaxin Yu };
39cfa9a966SJiaxin Yu 
40cfa9a966SJiaxin Yu struct audio_gpio_attr {
41cfa9a966SJiaxin Yu 	const char *name;
42cfa9a966SJiaxin Yu 	bool gpio_prepare;
43cfa9a966SJiaxin Yu 	struct pinctrl_state *gpioctrl;
44cfa9a966SJiaxin Yu };
45cfa9a966SJiaxin Yu 
46cfa9a966SJiaxin Yu static struct audio_gpio_attr aud_gpios[MT8186_AFE_GPIO_GPIO_NUM] = {
47cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_CLK_MOSI_OFF] = {"aud_clk_mosi_off", false, NULL},
48cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_CLK_MOSI_ON] = {"aud_clk_mosi_on", false, NULL},
49cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_CLK_MISO_OFF] = {"aud_clk_miso_off", false, NULL},
50cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_CLK_MISO_ON] = {"aud_clk_miso_on", false, NULL},
51cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_DAT_MISO_OFF] = {"aud_dat_miso_off", false, NULL},
52cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_DAT_MISO_ON] = {"aud_dat_miso_on", false, NULL},
53cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_DAT_MOSI_OFF] = {"aud_dat_mosi_off", false, NULL},
54cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_DAT_MOSI_ON] = {"aud_dat_mosi_on", false, NULL},
55cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_I2S0_OFF] = {"aud_gpio_i2s0_off", false, NULL},
56cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_I2S0_ON] = {"aud_gpio_i2s0_on", false, NULL},
57cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_I2S1_OFF] = {"aud_gpio_i2s1_off", false, NULL},
58cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_I2S1_ON] = {"aud_gpio_i2s1_on", false, NULL},
59cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_I2S2_OFF] = {"aud_gpio_i2s2_off", false, NULL},
60cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_I2S2_ON] = {"aud_gpio_i2s2_on", false, NULL},
61cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_I2S3_OFF] = {"aud_gpio_i2s3_off", false, NULL},
62cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_I2S3_ON] = {"aud_gpio_i2s3_on", false, NULL},
63cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_TDM_OFF] = {"aud_gpio_tdm_off", false, NULL},
64cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_TDM_ON] = {"aud_gpio_tdm_on", false, NULL},
65cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_PCM_OFF] = {"aud_gpio_pcm_off", false, NULL},
66cfa9a966SJiaxin Yu 	[MT8186_AFE_GPIO_PCM_ON] = {"aud_gpio_pcm_on", false, NULL},
67cfa9a966SJiaxin Yu };
68cfa9a966SJiaxin Yu 
69cfa9a966SJiaxin Yu static DEFINE_MUTEX(gpio_request_mutex);
70cfa9a966SJiaxin Yu 
mt8186_afe_gpio_init(struct device * dev)71cfa9a966SJiaxin Yu int mt8186_afe_gpio_init(struct device *dev)
72cfa9a966SJiaxin Yu {
73cfa9a966SJiaxin Yu 	int i, j, ret;
74cfa9a966SJiaxin Yu 
75cfa9a966SJiaxin Yu 	aud_pinctrl = devm_pinctrl_get(dev);
76cfa9a966SJiaxin Yu 	if (IS_ERR(aud_pinctrl)) {
77cfa9a966SJiaxin Yu 		ret = PTR_ERR(aud_pinctrl);
78cfa9a966SJiaxin Yu 		dev_err(dev, "%s(), ret %d, cannot get aud_pinctrl!\n",
79cfa9a966SJiaxin Yu 			__func__, ret);
80cfa9a966SJiaxin Yu 		return ret;
81cfa9a966SJiaxin Yu 	}
82cfa9a966SJiaxin Yu 
83cfa9a966SJiaxin Yu 	for (i = 0; i < ARRAY_SIZE(aud_gpios); i++) {
84cfa9a966SJiaxin Yu 		aud_gpios[i].gpioctrl = pinctrl_lookup_state(aud_pinctrl,
85cfa9a966SJiaxin Yu 							     aud_gpios[i].name);
86cfa9a966SJiaxin Yu 		if (IS_ERR(aud_gpios[i].gpioctrl)) {
87cfa9a966SJiaxin Yu 			ret = PTR_ERR(aud_gpios[i].gpioctrl);
883af24372SAllen-KH Cheng 			dev_dbg(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n",
89cfa9a966SJiaxin Yu 				 __func__, aud_gpios[i].name, ret);
90cfa9a966SJiaxin Yu 		} else {
91cfa9a966SJiaxin Yu 			aud_gpios[i].gpio_prepare = true;
92cfa9a966SJiaxin Yu 		}
93cfa9a966SJiaxin Yu 	}
94cfa9a966SJiaxin Yu 
95cfa9a966SJiaxin Yu 	/* gpio status init */
96cfa9a966SJiaxin Yu 	for (i = MT8186_DAI_ADDA; i <= MT8186_DAI_TDM_IN; i++) {
97cfa9a966SJiaxin Yu 		for (j = 0; j <= 1; j++)
98cfa9a966SJiaxin Yu 			mt8186_afe_gpio_request(dev, false, i, j);
99cfa9a966SJiaxin Yu 	}
100cfa9a966SJiaxin Yu 
101cfa9a966SJiaxin Yu 	return 0;
102cfa9a966SJiaxin Yu }
103cfa9a966SJiaxin Yu EXPORT_SYMBOL_GPL(mt8186_afe_gpio_init);
104cfa9a966SJiaxin Yu 
mt8186_afe_gpio_select(struct device * dev,enum mt8186_afe_gpio type)105cfa9a966SJiaxin Yu static int mt8186_afe_gpio_select(struct device *dev,
106cfa9a966SJiaxin Yu 				  enum mt8186_afe_gpio type)
107cfa9a966SJiaxin Yu {
108cfa9a966SJiaxin Yu 	int ret = 0;
109cfa9a966SJiaxin Yu 
110cfa9a966SJiaxin Yu 	if (type < 0 || type >= MT8186_AFE_GPIO_GPIO_NUM) {
1113af24372SAllen-KH Cheng 		dev_dbg(dev, "%s(), error, invalid gpio type %d\n",
112cfa9a966SJiaxin Yu 			__func__, type);
113cfa9a966SJiaxin Yu 		return -EINVAL;
114cfa9a966SJiaxin Yu 	}
115cfa9a966SJiaxin Yu 
116cfa9a966SJiaxin Yu 	if (!aud_gpios[type].gpio_prepare) {
1173af24372SAllen-KH Cheng 		dev_dbg(dev, "%s(), error, gpio type %d not prepared\n",
118cfa9a966SJiaxin Yu 			__func__, type);
119cfa9a966SJiaxin Yu 		return -EIO;
120cfa9a966SJiaxin Yu 	}
121cfa9a966SJiaxin Yu 
122cfa9a966SJiaxin Yu 	ret = pinctrl_select_state(aud_pinctrl,
123cfa9a966SJiaxin Yu 				   aud_gpios[type].gpioctrl);
124cfa9a966SJiaxin Yu 	if (ret) {
1253af24372SAllen-KH Cheng 		dev_dbg(dev, "%s(), error, can not set gpio type %d\n",
126cfa9a966SJiaxin Yu 			__func__, type);
127cfa9a966SJiaxin Yu 		return ret;
128cfa9a966SJiaxin Yu 	}
129cfa9a966SJiaxin Yu 
130cfa9a966SJiaxin Yu 	return 0;
131cfa9a966SJiaxin Yu }
132cfa9a966SJiaxin Yu 
mt8186_afe_gpio_adda_dl(struct device * dev,bool enable)133cfa9a966SJiaxin Yu static int mt8186_afe_gpio_adda_dl(struct device *dev, bool enable)
134cfa9a966SJiaxin Yu {
135cfa9a966SJiaxin Yu 	int ret;
136cfa9a966SJiaxin Yu 
137cfa9a966SJiaxin Yu 	if (enable) {
138cfa9a966SJiaxin Yu 		ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_ON);
139cfa9a966SJiaxin Yu 		if (ret) {
1403af24372SAllen-KH Cheng 			dev_dbg(dev, "%s(), MOSI CLK ON select fail!\n", __func__);
141cfa9a966SJiaxin Yu 			return ret;
142cfa9a966SJiaxin Yu 		}
143cfa9a966SJiaxin Yu 
144cfa9a966SJiaxin Yu 		ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_ON);
145cfa9a966SJiaxin Yu 		if (ret) {
1463af24372SAllen-KH Cheng 			dev_dbg(dev, "%s(), MOSI DAT ON select fail!\n", __func__);
147cfa9a966SJiaxin Yu 			return ret;
148cfa9a966SJiaxin Yu 		}
149cfa9a966SJiaxin Yu 	} else {
150cfa9a966SJiaxin Yu 		ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_OFF);
151cfa9a966SJiaxin Yu 		if (ret) {
1523af24372SAllen-KH Cheng 			dev_dbg(dev, "%s(), MOSI DAT OFF select fail!\n", __func__);
153cfa9a966SJiaxin Yu 			return ret;
154cfa9a966SJiaxin Yu 		}
155cfa9a966SJiaxin Yu 
156cfa9a966SJiaxin Yu 		ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_OFF);
157cfa9a966SJiaxin Yu 		if (ret) {
1583af24372SAllen-KH Cheng 			dev_dbg(dev, "%s(), MOSI CLK ON select fail!\n", __func__);
159cfa9a966SJiaxin Yu 			return ret;
160cfa9a966SJiaxin Yu 		}
161cfa9a966SJiaxin Yu 	}
162cfa9a966SJiaxin Yu 
163cfa9a966SJiaxin Yu 	return 0;
164cfa9a966SJiaxin Yu }
165cfa9a966SJiaxin Yu 
mt8186_afe_gpio_adda_ul(struct device * dev,bool enable)166cfa9a966SJiaxin Yu static int mt8186_afe_gpio_adda_ul(struct device *dev, bool enable)
167cfa9a966SJiaxin Yu {
168cfa9a966SJiaxin Yu 	int ret;
169cfa9a966SJiaxin Yu 
170cfa9a966SJiaxin Yu 	if (enable) {
171cfa9a966SJiaxin Yu 		ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_ON);
172cfa9a966SJiaxin Yu 		if (ret) {
1733af24372SAllen-KH Cheng 			dev_dbg(dev, "%s(), MISO CLK ON select fail!\n", __func__);
174cfa9a966SJiaxin Yu 			return ret;
175cfa9a966SJiaxin Yu 		}
176cfa9a966SJiaxin Yu 
177cfa9a966SJiaxin Yu 		ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_ON);
178cfa9a966SJiaxin Yu 		if (ret) {
1793af24372SAllen-KH Cheng 			dev_dbg(dev, "%s(), MISO DAT ON select fail!\n", __func__);
180cfa9a966SJiaxin Yu 			return ret;
181cfa9a966SJiaxin Yu 		}
182cfa9a966SJiaxin Yu 	} else {
183cfa9a966SJiaxin Yu 		ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_OFF);
184cfa9a966SJiaxin Yu 		if (ret) {
1853af24372SAllen-KH Cheng 			dev_dbg(dev, "%s(), MISO DAT OFF select fail!\n", __func__);
186cfa9a966SJiaxin Yu 			return ret;
187cfa9a966SJiaxin Yu 		}
188cfa9a966SJiaxin Yu 
189cfa9a966SJiaxin Yu 		ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_OFF);
190cfa9a966SJiaxin Yu 		if (ret) {
1913af24372SAllen-KH Cheng 			dev_dbg(dev, "%s(), MISO CLK OFF select fail!\n", __func__);
192cfa9a966SJiaxin Yu 			return ret;
193cfa9a966SJiaxin Yu 		}
194cfa9a966SJiaxin Yu 	}
195cfa9a966SJiaxin Yu 
196cfa9a966SJiaxin Yu 	return 0;
197cfa9a966SJiaxin Yu }
198cfa9a966SJiaxin Yu 
mt8186_afe_gpio_request(struct device * dev,bool enable,int dai,int uplink)199cfa9a966SJiaxin Yu int mt8186_afe_gpio_request(struct device *dev, bool enable,
200cfa9a966SJiaxin Yu 			    int dai, int uplink)
201cfa9a966SJiaxin Yu {
202cfa9a966SJiaxin Yu 	enum mt8186_afe_gpio sel;
203cfa9a966SJiaxin Yu 	int ret = -EINVAL;
204cfa9a966SJiaxin Yu 
205cfa9a966SJiaxin Yu 	mutex_lock(&gpio_request_mutex);
206cfa9a966SJiaxin Yu 
207cfa9a966SJiaxin Yu 	switch (dai) {
208cfa9a966SJiaxin Yu 	case MT8186_DAI_ADDA:
209cfa9a966SJiaxin Yu 		if (uplink)
210cfa9a966SJiaxin Yu 			ret = mt8186_afe_gpio_adda_ul(dev, enable);
211cfa9a966SJiaxin Yu 		else
212cfa9a966SJiaxin Yu 			ret = mt8186_afe_gpio_adda_dl(dev, enable);
213cfa9a966SJiaxin Yu 		goto unlock;
214cfa9a966SJiaxin Yu 	case MT8186_DAI_I2S_0:
215cfa9a966SJiaxin Yu 		sel = enable ? MT8186_AFE_GPIO_I2S0_ON : MT8186_AFE_GPIO_I2S0_OFF;
216cfa9a966SJiaxin Yu 		break;
217cfa9a966SJiaxin Yu 	case MT8186_DAI_I2S_1:
218cfa9a966SJiaxin Yu 		sel = enable ? MT8186_AFE_GPIO_I2S1_ON : MT8186_AFE_GPIO_I2S1_OFF;
219cfa9a966SJiaxin Yu 		break;
220cfa9a966SJiaxin Yu 	case MT8186_DAI_I2S_2:
221cfa9a966SJiaxin Yu 		sel = enable ? MT8186_AFE_GPIO_I2S2_ON : MT8186_AFE_GPIO_I2S2_OFF;
222cfa9a966SJiaxin Yu 		break;
223cfa9a966SJiaxin Yu 	case MT8186_DAI_I2S_3:
224cfa9a966SJiaxin Yu 		sel = enable ? MT8186_AFE_GPIO_I2S3_ON : MT8186_AFE_GPIO_I2S3_OFF;
225cfa9a966SJiaxin Yu 		break;
226cfa9a966SJiaxin Yu 	case MT8186_DAI_TDM_IN:
227cfa9a966SJiaxin Yu 		sel = enable ? MT8186_AFE_GPIO_TDM_ON : MT8186_AFE_GPIO_TDM_OFF;
228cfa9a966SJiaxin Yu 		break;
229cfa9a966SJiaxin Yu 	case MT8186_DAI_PCM:
230cfa9a966SJiaxin Yu 		sel = enable ? MT8186_AFE_GPIO_PCM_ON : MT8186_AFE_GPIO_PCM_OFF;
231cfa9a966SJiaxin Yu 		break;
232cfa9a966SJiaxin Yu 	default:
2333af24372SAllen-KH Cheng 		dev_dbg(dev, "%s(), invalid dai %d\n", __func__, dai);
234cfa9a966SJiaxin Yu 		goto unlock;
235cfa9a966SJiaxin Yu 	}
236cfa9a966SJiaxin Yu 
237cfa9a966SJiaxin Yu 	ret = mt8186_afe_gpio_select(dev, sel);
238cfa9a966SJiaxin Yu 
239cfa9a966SJiaxin Yu unlock:
240cfa9a966SJiaxin Yu 	mutex_unlock(&gpio_request_mutex);
241cfa9a966SJiaxin Yu 
242cfa9a966SJiaxin Yu 	return ret;
243cfa9a966SJiaxin Yu }
244