243 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// mt8186-afe-gpio.c -- Mediatek 8186 afe gpio ctrl4//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 13static struct pinctrl *aud_pinctrl;14 15enum 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_NUM37};38 39struct audio_gpio_attr {40 const char *name;41 bool gpio_prepare;42 struct pinctrl_state *gpioctrl;43};44 45static 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 68static DEFINE_MUTEX(gpio_request_mutex);69 70int 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}102EXPORT_SYMBOL_GPL(mt8186_afe_gpio_init);103 104static 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 132static 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 165static 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 198int 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 else211 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 238unlock:239 mutex_unlock(&gpio_request_mutex);240 241 return ret;242}243