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