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