1063 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// mt6359-accdet.c -- ALSA SoC mt6359 accdet driver4//5// Copyright (C) 2021 MediaTek Inc.6// Author: Argus Lin <argus.lin@mediatek.com>7//8 9#include <linux/of.h>10#include <linux/input.h>11#include <linux/kthread.h>12#include <linux/io.h>13#include <linux/sched/clock.h>14#include <linux/workqueue.h>15#include <linux/timer.h>16#include <linux/delay.h>17#include <linux/module.h>18#include <linux/platform_device.h>19#include <linux/init.h>20#include <linux/irqdomain.h>21#include <linux/irq.h>22#include <linux/regmap.h>23#include <sound/soc.h>24#include <sound/jack.h>25#include <linux/mfd/mt6397/core.h>26 27#include "mt6359-accdet.h"28#include "mt6359.h"29 30/* global variable definitions */31#define REGISTER_VAL(x) ((x) - 1)32 33/* mt6359 accdet capability */34#define ACCDET_PMIC_EINT_IRQ BIT(0)35#define ACCDET_AP_GPIO_EINT BIT(1)36 37#define ACCDET_PMIC_EINT0 BIT(2)38#define ACCDET_PMIC_EINT1 BIT(3)39#define ACCDET_PMIC_BI_EINT BIT(4)40 41#define ACCDET_PMIC_GPIO_TRIG_EINT BIT(5)42#define ACCDET_PMIC_INVERTER_TRIG_EINT BIT(6)43#define ACCDET_PMIC_RSV_EINT BIT(7)44 45#define ACCDET_THREE_KEY BIT(8)46#define ACCDET_FOUR_KEY BIT(9)47#define ACCDET_TRI_KEY_CDD BIT(10)48#define ACCDET_RSV_KEY BIT(11)49 50#define ACCDET_ANALOG_FASTDISCHARGE BIT(12)51#define ACCDET_DIGITAL_FASTDISCHARGE BIT(13)52#define ACCDET_AD_FASTDISCHRAGE BIT(14)53 54static struct platform_driver mt6359_accdet_driver;55static const struct snd_soc_component_driver mt6359_accdet_soc_driver;56 57/* local function declaration */58static void accdet_set_debounce(struct mt6359_accdet *priv, int state,59 unsigned int debounce);60static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv);61static void config_digital_init_by_mode(struct mt6359_accdet *priv);62static void config_eint_init_by_mode(struct mt6359_accdet *priv);63static inline void mt6359_accdet_init(struct mt6359_accdet *priv);64static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv);65static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv);66static void mt6359_accdet_jack_report(struct mt6359_accdet *priv);67static void recover_eint_analog_setting(struct mt6359_accdet *priv);68static void recover_eint_digital_setting(struct mt6359_accdet *priv);69static void recover_eint_setting(struct mt6359_accdet *priv);70 71static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)72{73 if (priv->data->eint_detect_mode == 0x3 ||74 priv->data->eint_detect_mode == 0x4) {75 /* ESD switches off */76 regmap_update_bits(priv->regmap,77 RG_ACCDETSPARE_ADDR, 1 << 8, 0);78 }79 if (priv->data->eint_detect_mode == 0x4) {80 if (priv->caps & ACCDET_PMIC_EINT0) {81 /* enable RG_EINT0CONFIGACCDET */82 regmap_update_bits(priv->regmap,83 RG_EINT0CONFIGACCDET_ADDR,84 RG_EINT0CONFIGACCDET_MASK_SFT,85 BIT(RG_EINT0CONFIGACCDET_SFT));86 } else if (priv->caps & ACCDET_PMIC_EINT1) {87 /* enable RG_EINT1CONFIGACCDET */88 regmap_update_bits(priv->regmap,89 RG_EINT1CONFIGACCDET_ADDR,90 RG_EINT1CONFIGACCDET_MASK_SFT,91 BIT(RG_EINT1CONFIGACCDET_SFT));92 }93 if (priv->data->eint_use_ext_res == 0x3 ||94 priv->data->eint_use_ext_res == 0x4) {95 /*select 500k, use internal resistor */96 regmap_update_bits(priv->regmap,97 RG_EINT0HIRENB_ADDR,98 RG_EINT0HIRENB_MASK_SFT,99 BIT(RG_EINT0HIRENB_SFT));100 }101 }102 return 0;103}104 105static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv)106{107 if (priv->caps & ACCDET_PMIC_EINT0) {108 /* disable inverter */109 regmap_update_bits(priv->regmap,110 ACCDET_EINT0_INVERTER_SW_EN_ADDR,111 ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, 0);112 } else if (priv->caps & ACCDET_PMIC_EINT1) {113 /* disable inverter */114 regmap_update_bits(priv->regmap,115 ACCDET_EINT1_INVERTER_SW_EN_ADDR,116 ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, 0);117 }118 119 if (priv->data->eint_detect_mode == 0x4) {120 if (priv->caps & ACCDET_PMIC_EINT0) {121 /* set DA stable signal */122 regmap_update_bits(priv->regmap,123 ACCDET_DA_STABLE_ADDR,124 ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);125 } else if (priv->caps & ACCDET_PMIC_EINT1) {126 /* set DA stable signal */127 regmap_update_bits(priv->regmap,128 ACCDET_DA_STABLE_ADDR,129 ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);130 }131 }132 return 0;133}134 135static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv)136{137 if (priv->jd_sts == M_PLUG_IN) {138 /* adjust digital setting */139 adjust_eint_digital_setting(priv);140 /* adjust analog setting */141 adjust_eint_analog_setting(priv);142 } else if (priv->jd_sts == M_PLUG_OUT) {143 /* set debounce to 1ms */144 accdet_set_debounce(priv, eint_state000,145 priv->data->pwm_deb->eint_debounce0);146 } else {147 dev_dbg(priv->dev, "should not be here %s()\n", __func__);148 }149 150 return 0;151}152 153static void recover_eint_analog_setting(struct mt6359_accdet *priv)154{155 if (priv->data->eint_detect_mode == 0x3 ||156 priv->data->eint_detect_mode == 0x4) {157 /* ESD switches on */158 regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,159 1 << 8, 1 << 8);160 }161 if (priv->data->eint_detect_mode == 0x4) {162 if (priv->caps & ACCDET_PMIC_EINT0) {163 /* disable RG_EINT0CONFIGACCDET */164 regmap_update_bits(priv->regmap,165 RG_EINT0CONFIGACCDET_ADDR,166 RG_EINT0CONFIGACCDET_MASK_SFT, 0);167 } else if (priv->caps & ACCDET_PMIC_EINT1) {168 /* disable RG_EINT1CONFIGACCDET */169 regmap_update_bits(priv->regmap,170 RG_EINT1CONFIGACCDET_ADDR,171 RG_EINT1CONFIGACCDET_MASK_SFT, 0);172 }173 regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,174 RG_EINT0HIRENB_MASK_SFT, 0);175 }176}177 178static void recover_eint_digital_setting(struct mt6359_accdet *priv)179{180 if (priv->caps & ACCDET_PMIC_EINT0) {181 regmap_update_bits(priv->regmap,182 ACCDET_EINT0_M_SW_EN_ADDR,183 ACCDET_EINT0_M_SW_EN_MASK_SFT, 0);184 } else if (priv->caps & ACCDET_PMIC_EINT1) {185 regmap_update_bits(priv->regmap,186 ACCDET_EINT1_M_SW_EN_ADDR,187 ACCDET_EINT1_M_SW_EN_MASK_SFT, 0);188 }189 if (priv->data->eint_detect_mode == 0x4) {190 /* enable eint0cen */191 if (priv->caps & ACCDET_PMIC_EINT0) {192 /* enable eint0cen */193 regmap_update_bits(priv->regmap,194 ACCDET_DA_STABLE_ADDR,195 ACCDET_EINT0_CEN_STABLE_MASK_SFT,196 BIT(ACCDET_EINT0_CEN_STABLE_SFT));197 } else if (priv->caps & ACCDET_PMIC_EINT1) {198 /* enable eint1cen */199 regmap_update_bits(priv->regmap,200 ACCDET_DA_STABLE_ADDR,201 ACCDET_EINT1_CEN_STABLE_MASK_SFT,202 BIT(ACCDET_EINT1_CEN_STABLE_SFT));203 }204 }205 206 if (priv->data->eint_detect_mode != 0x1) {207 if (priv->caps & ACCDET_PMIC_EINT0) {208 /* enable inverter */209 regmap_update_bits(priv->regmap,210 ACCDET_EINT0_INVERTER_SW_EN_ADDR,211 ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,212 BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));213 } else if (priv->caps & ACCDET_PMIC_EINT1) {214 /* enable inverter */215 regmap_update_bits(priv->regmap,216 ACCDET_EINT1_INVERTER_SW_EN_ADDR,217 ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,218 BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));219 }220 }221}222 223static void recover_eint_setting(struct mt6359_accdet *priv)224{225 if (priv->jd_sts == M_PLUG_OUT) {226 recover_eint_analog_setting(priv);227 recover_eint_digital_setting(priv);228 }229}230 231static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)232{233 int ret;234 unsigned int value = 0;235 236 regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,237 ACCDET_IRQ_CLR_MASK_SFT, BIT(ACCDET_IRQ_CLR_SFT));238 usleep_range(200, 300);239 ret = regmap_read_poll_timeout(priv->regmap,240 ACCDET_IRQ_ADDR,241 value,242 (value & ACCDET_IRQ_MASK_SFT) == 0,243 0,244 1000);245 if (ret)246 dev_warn(priv->dev, "%s(), ret %d\n", __func__, ret);247 /* clear accdet int, modify for fix interrupt trigger twice error */248 regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,249 ACCDET_IRQ_CLR_MASK_SFT, 0);250 regmap_update_bits(priv->regmap, RG_INT_STATUS_ACCDET_ADDR,251 RG_INT_STATUS_ACCDET_MASK_SFT,252 BIT(RG_INT_STATUS_ACCDET_SFT));253 254 /* recover accdet debounce0,3 */255 accdet_set_debounce(priv, accdet_state000,256 priv->data->pwm_deb->debounce0);257 accdet_set_debounce(priv, accdet_state001,258 priv->data->pwm_deb->debounce1);259 accdet_set_debounce(priv, accdet_state011,260 priv->data->pwm_deb->debounce3);261 262 priv->jack_type = 0;263 priv->btn_type = 0;264 priv->accdet_status = 0x3;265 mt6359_accdet_jack_report(priv);266}267 268static void accdet_set_debounce(struct mt6359_accdet *priv, int state,269 unsigned int debounce)270{271 switch (state) {272 case accdet_state000:273 regmap_write(priv->regmap, ACCDET_DEBOUNCE0_ADDR, debounce);274 break;275 case accdet_state001:276 regmap_write(priv->regmap, ACCDET_DEBOUNCE1_ADDR, debounce);277 break;278 case accdet_state010:279 regmap_write(priv->regmap, ACCDET_DEBOUNCE2_ADDR, debounce);280 break;281 case accdet_state011:282 regmap_write(priv->regmap, ACCDET_DEBOUNCE3_ADDR, debounce);283 break;284 case accdet_auxadc:285 regmap_write(priv->regmap,286 ACCDET_CONNECT_AUXADC_TIME_DIG_ADDR, debounce);287 break;288 case eint_state000:289 regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE0_ADDR,290 0xF << ACCDET_EINT_DEBOUNCE0_SFT,291 debounce << ACCDET_EINT_DEBOUNCE0_SFT);292 break;293 case eint_state001:294 regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE1_ADDR,295 0xF << ACCDET_EINT_DEBOUNCE1_SFT,296 debounce << ACCDET_EINT_DEBOUNCE1_SFT);297 break;298 case eint_state010:299 regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE2_ADDR,300 0xF << ACCDET_EINT_DEBOUNCE2_SFT,301 debounce << ACCDET_EINT_DEBOUNCE2_SFT);302 break;303 case eint_state011:304 regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE3_ADDR,305 0xF << ACCDET_EINT_DEBOUNCE3_SFT,306 debounce << ACCDET_EINT_DEBOUNCE3_SFT);307 break;308 case eint_inverter_state000:309 regmap_write(priv->regmap, ACCDET_EINT_INVERTER_DEBOUNCE_ADDR,310 debounce);311 break;312 default:313 dev_warn(priv->dev, "Error: %s error state (%d)\n", __func__,314 state);315 break;316 }317}318 319static void mt6359_accdet_jack_report(struct mt6359_accdet *priv)320{321 int report = 0;322 323 if (!priv->jack)324 return;325 326 report = priv->jack_type | priv->btn_type;327 snd_soc_jack_report(priv->jack, report, MT6359_ACCDET_JACK_MASK);328}329 330static unsigned int check_button(struct mt6359_accdet *priv, unsigned int v)331{332 if (priv->caps & ACCDET_FOUR_KEY) {333 if (v < priv->data->four_key.down &&334 v >= priv->data->four_key.up)335 priv->btn_type = SND_JACK_BTN_1;336 if (v < priv->data->four_key.up &&337 v >= priv->data->four_key.voice)338 priv->btn_type = SND_JACK_BTN_2;339 if (v < priv->data->four_key.voice &&340 v >= priv->data->four_key.mid)341 priv->btn_type = SND_JACK_BTN_3;342 if (v < priv->data->four_key.mid)343 priv->btn_type = SND_JACK_BTN_0;344 } else {345 if (v < priv->data->three_key.down &&346 v >= priv->data->three_key.up)347 priv->btn_type = SND_JACK_BTN_1;348 if (v < priv->data->three_key.up &&349 v >= priv->data->three_key.mid)350 priv->btn_type = SND_JACK_BTN_2;351 if (v < priv->data->three_key.mid)352 priv->btn_type = SND_JACK_BTN_0;353 }354 return 0;355}356 357static void is_key_pressed(struct mt6359_accdet *priv, bool pressed)358{359 priv->btn_type = priv->jack_type & ~MT6359_ACCDET_BTN_MASK;360 361 if (pressed)362 check_button(priv, priv->cali_voltage);363}364 365static inline void check_jack_btn_type(struct mt6359_accdet *priv)366{367 unsigned int val = 0;368 369 regmap_read(priv->regmap, ACCDET_MEM_IN_ADDR, &val);370 371 priv->accdet_status =372 (val >> ACCDET_STATE_MEM_IN_OFFSET) & ACCDET_STATE_AB_MASK;373 374 switch (priv->accdet_status) {375 case 0:376 if (priv->jack_type == SND_JACK_HEADSET)377 is_key_pressed(priv, true);378 else379 priv->jack_type = SND_JACK_HEADPHONE;380 break;381 case 1:382 if (priv->jack_type == SND_JACK_HEADSET) {383 is_key_pressed(priv, false);384 } else {385 priv->jack_type = SND_JACK_HEADSET;386 accdet_set_debounce(priv, eint_state011, 0x1);387 }388 break;389 case 3:390 default:391 priv->jack_type = 0;392 break;393 }394}395 396static void mt6359_accdet_work(struct work_struct *work)397{398 struct mt6359_accdet *priv =399 container_of(work, struct mt6359_accdet, accdet_work);400 401 mutex_lock(&priv->res_lock);402 priv->pre_accdet_status = priv->accdet_status;403 check_jack_btn_type(priv);404 405 if (priv->jack_plugged &&406 priv->pre_accdet_status != priv->accdet_status)407 mt6359_accdet_jack_report(priv);408 mutex_unlock(&priv->res_lock);409}410 411static void mt6359_accdet_jd_work(struct work_struct *work)412{413 int ret;414 unsigned int value = 0;415 416 struct mt6359_accdet *priv =417 container_of(work, struct mt6359_accdet, jd_work);418 419 mutex_lock(&priv->res_lock);420 if (priv->jd_sts == M_PLUG_IN) {421 priv->jack_plugged = true;422 423 /* set and clear initial bit every eint interrupt */424 regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR,425 ACCDET_SEQ_INIT_MASK_SFT,426 BIT(ACCDET_SEQ_INIT_SFT));427 regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR,428 ACCDET_SEQ_INIT_MASK_SFT, 0);429 ret = regmap_read_poll_timeout(priv->regmap,430 ACCDET_SEQ_INIT_ADDR,431 value,432 (value & ACCDET_SEQ_INIT_MASK_SFT) == 0,433 0,434 1000);435 if (ret)436 dev_err(priv->dev, "%s(), ret %d\n", __func__, ret);437 438 /* enable ACCDET unit */439 regmap_update_bits(priv->regmap, ACCDET_SW_EN_ADDR,440 ACCDET_SW_EN_MASK_SFT, BIT(ACCDET_SW_EN_SFT));441 } else if (priv->jd_sts == M_PLUG_OUT) {442 priv->jack_plugged = false;443 444 accdet_set_debounce(priv, accdet_state011,445 priv->data->pwm_deb->debounce3);446 regmap_update_bits(priv->regmap, ACCDET_SW_EN_ADDR,447 ACCDET_SW_EN_MASK_SFT, 0);448 mt6359_accdet_recover_jd_setting(priv);449 }450 451 if (priv->caps & ACCDET_PMIC_EINT_IRQ)452 recover_eint_setting(priv);453 mutex_unlock(&priv->res_lock);454}455 456static irqreturn_t mt6359_accdet_irq(int irq, void *data)457{458 struct mt6359_accdet *priv = data;459 unsigned int irq_val = 0, val = 0, value = 0;460 int ret;461 462 mutex_lock(&priv->res_lock);463 regmap_read(priv->regmap, ACCDET_IRQ_ADDR, &irq_val);464 465 if (irq_val & ACCDET_IRQ_MASK_SFT) {466 regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,467 ACCDET_IRQ_CLR_MASK_SFT,468 BIT(ACCDET_IRQ_CLR_SFT));469 ret = regmap_read_poll_timeout(priv->regmap,470 ACCDET_IRQ_ADDR,471 value,472 (value & ACCDET_IRQ_MASK_SFT) == 0,473 0,474 1000);475 if (ret) {476 dev_err(priv->dev, "%s(), ret %d\n", __func__, ret);477 mutex_unlock(&priv->res_lock);478 return IRQ_NONE;479 }480 regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,481 ACCDET_IRQ_CLR_MASK_SFT, 0);482 regmap_update_bits(priv->regmap, RG_INT_STATUS_ACCDET_ADDR,483 RG_INT_STATUS_ACCDET_MASK_SFT,484 BIT(RG_INT_STATUS_ACCDET_SFT));485 486 queue_work(priv->accdet_workqueue, &priv->accdet_work);487 } else {488 if (irq_val & ACCDET_EINT0_IRQ_MASK_SFT) {489 regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,490 ACCDET_EINT0_IRQ_CLR_MASK_SFT,491 BIT(ACCDET_EINT0_IRQ_CLR_SFT));492 ret = regmap_read_poll_timeout(priv->regmap,493 ACCDET_IRQ_ADDR,494 value,495 (value & ACCDET_EINT0_IRQ_MASK_SFT) == 0,496 0,497 1000);498 if (ret) {499 dev_err(priv->dev, "%s(), ret %d\n", __func__,500 ret);501 mutex_unlock(&priv->res_lock);502 return IRQ_NONE;503 }504 regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,505 ACCDET_EINT0_IRQ_CLR_MASK_SFT, 0);506 regmap_update_bits(priv->regmap,507 RG_INT_STATUS_ACCDET_ADDR,508 RG_INT_STATUS_ACCDET_EINT0_MASK_SFT,509 BIT(RG_INT_STATUS_ACCDET_EINT0_SFT));510 }511 if (irq_val & ACCDET_EINT1_IRQ_MASK_SFT) {512 regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,513 ACCDET_EINT1_IRQ_CLR_MASK_SFT,514 BIT(ACCDET_EINT1_IRQ_CLR_SFT));515 ret = regmap_read_poll_timeout(priv->regmap,516 ACCDET_IRQ_ADDR,517 value,518 (value & ACCDET_EINT1_IRQ_MASK_SFT) == 0,519 0,520 1000);521 if (ret) {522 dev_err(priv->dev, "%s(), ret %d\n", __func__,523 ret);524 mutex_unlock(&priv->res_lock);525 return IRQ_NONE;526 }527 regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,528 ACCDET_EINT1_IRQ_CLR_MASK_SFT, 0);529 regmap_update_bits(priv->regmap,530 RG_INT_STATUS_ACCDET_ADDR,531 RG_INT_STATUS_ACCDET_EINT1_MASK_SFT,532 BIT(RG_INT_STATUS_ACCDET_EINT1_SFT));533 }534 /* get jack detection status */535 regmap_read(priv->regmap, ACCDET_EINT0_MEM_IN_ADDR, &val);536 priv->jd_sts = ((val >> ACCDET_EINT0_MEM_IN_SFT) &537 ACCDET_EINT0_MEM_IN_MASK);538 /* adjust eint digital/analog setting */539 mt6359_accdet_jd_setting(priv);540 541 queue_work(priv->jd_workqueue, &priv->jd_work);542 }543 mutex_unlock(&priv->res_lock);544 545 return IRQ_HANDLED;546}547 548static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)549{550 int ret;551 struct device *dev = priv->dev;552 struct device_node *node = NULL;553 int pwm_deb[15] = {0};554 unsigned int tmp = 0;555 556 node = of_get_child_by_name(dev->parent->of_node, "accdet");557 if (!node)558 return -EINVAL;559 560 ret = of_property_read_u32(node, "mediatek,mic-vol",561 &priv->data->mic_vol);562 if (ret)563 priv->data->mic_vol = 8;564 565 ret = of_property_read_u32(node, "mediatek,plugout-debounce",566 &priv->data->plugout_deb);567 if (ret)568 priv->data->plugout_deb = 1;569 570 ret = of_property_read_u32(node, "mediatek,mic-mode",571 &priv->data->mic_mode);572 if (ret)573 priv->data->mic_mode = 2;574 575 ret = of_property_read_u32_array(node, "mediatek,pwm-deb-setting",576 pwm_deb, ARRAY_SIZE(pwm_deb));577 /* debounce8(auxadc debounce) is default, needn't get from dts */578 if (!ret)579 memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb));580 581 ret = of_property_read_u32(node, "mediatek,eint-level-pol",582 &priv->data->eint_pol);583 if (ret)584 priv->data->eint_pol = 8;585 586 ret = of_property_read_u32(node, "mediatek,eint-use-ap", &tmp);587 if (ret)588 tmp = 0;589 if (tmp == 0)590 priv->caps |= ACCDET_PMIC_EINT_IRQ;591 else if (tmp == 1)592 priv->caps |= ACCDET_AP_GPIO_EINT;593 594 ret = of_property_read_u32(node, "mediatek,eint-detect-mode",595 &priv->data->eint_detect_mode);596 if (ret) {597 /* eint detection mode equals to EINT HW Mode */598 priv->data->eint_detect_mode = 0x4;599 }600 601 ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);602 if (ret)603 tmp = 0;604 if (tmp == 0)605 priv->caps |= ACCDET_PMIC_EINT0;606 else if (tmp == 1)607 priv->caps |= ACCDET_PMIC_EINT1;608 else if (tmp == 2)609 priv->caps |= ACCDET_PMIC_BI_EINT;610 611 ret = of_property_read_u32(node, "mediatek,eint-trig-mode",612 &tmp);613 if (ret)614 tmp = 0;615 if (tmp == 0)616 priv->caps |= ACCDET_PMIC_GPIO_TRIG_EINT;617 else if (tmp == 1)618 priv->caps |= ACCDET_PMIC_INVERTER_TRIG_EINT;619 620 ret = of_property_read_u32(node, "mediatek,eint-use-ext-res",621 &priv->data->eint_use_ext_res);622 if (ret) {623 /* eint use internal resister */624 priv->data->eint_use_ext_res = 0x0;625 }626 627 ret = of_property_read_u32(node, "mediatek,eint-comp-vth",628 &priv->data->eint_comp_vth);629 if (ret)630 priv->data->eint_comp_vth = 0x0;631 632 ret = of_property_read_u32(node, "mediatek,key-mode", &tmp);633 if (ret)634 tmp = 0;635 if (tmp == 0) {636 int three_key[4];637 638 priv->caps |= ACCDET_THREE_KEY;639 ret = of_property_read_u32_array(node,640 "mediatek,three-key-thr",641 three_key,642 ARRAY_SIZE(three_key));643 if (!ret)644 memcpy(&priv->data->three_key, three_key + 1,645 sizeof(struct three_key_threshold));646 } else if (tmp == 1) {647 int four_key[5];648 649 priv->caps |= ACCDET_FOUR_KEY;650 ret = of_property_read_u32_array(node,651 "mediatek,four-key-thr",652 four_key,653 ARRAY_SIZE(four_key));654 if (!ret) {655 memcpy(&priv->data->four_key, four_key + 1,656 sizeof(struct four_key_threshold));657 } else {658 dev_warn(priv->dev,659 "accdet no 4-key-thrsh dts, use efuse\n");660 }661 } else if (tmp == 2) {662 int three_key[4];663 664 priv->caps |= ACCDET_TRI_KEY_CDD;665 ret = of_property_read_u32_array(node,666 "mediatek,tri-key-cdd-thr",667 three_key,668 ARRAY_SIZE(three_key));669 if (!ret)670 memcpy(&priv->data->three_key, three_key + 1,671 sizeof(struct three_key_threshold));672 }673 674 of_node_put(node);675 dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);676 677 return 0;678}679 680static void config_digital_init_by_mode(struct mt6359_accdet *priv)681{682 /* enable eint cmpmem pwm */683 regmap_write(priv->regmap, ACCDET_EINT_CMPMEN_PWM_THRESH_ADDR,684 (priv->data->pwm_deb->eint_pwm_width << 4 |685 priv->data->pwm_deb->eint_pwm_thresh));686 /* DA signal stable */687 if (priv->caps & ACCDET_PMIC_EINT0) {688 regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,689 ACCDET_EINT0_STABLE_VAL);690 } else if (priv->caps & ACCDET_PMIC_EINT1) {691 regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,692 ACCDET_EINT1_STABLE_VAL);693 }694 /* after receive n+1 number, interrupt issued. */695 regmap_update_bits(priv->regmap, ACCDET_EINT_M_PLUG_IN_NUM_ADDR,696 ACCDET_EINT_M_PLUG_IN_NUM_MASK_SFT,697 BIT(ACCDET_EINT_M_PLUG_IN_NUM_SFT));698 /* setting HW mode, enable digital fast discharge699 * if use EINT0 & EINT1 detection, please modify700 * ACCDET_HWMODE_EN_ADDR[2:1]701 */702 regmap_write(priv->regmap, ACCDET_HWMODE_EN_ADDR, 0x100);703 704 regmap_update_bits(priv->regmap, ACCDET_EINT_M_DETECT_EN_ADDR,705 ACCDET_EINT_M_DETECT_EN_MASK_SFT, 0);706 707 /* enable PWM */708 regmap_write(priv->regmap, ACCDET_CMP_PWM_EN_ADDR, 0x67);709 /* enable inverter detection */710 if (priv->data->eint_detect_mode == 0x1) {711 /* disable inverter detection */712 if (priv->caps & ACCDET_PMIC_EINT0) {713 regmap_update_bits(priv->regmap,714 ACCDET_EINT0_INVERTER_SW_EN_ADDR,715 ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,716 0);717 } else if (priv->caps & ACCDET_PMIC_EINT1) {718 regmap_update_bits(priv->regmap,719 ACCDET_EINT1_INVERTER_SW_EN_ADDR,720 ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,721 0);722 }723 } else {724 if (priv->caps & ACCDET_PMIC_EINT0) {725 regmap_update_bits(priv->regmap,726 ACCDET_EINT0_INVERTER_SW_EN_ADDR,727 ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,728 BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));729 } else if (priv->caps & ACCDET_PMIC_EINT1) {730 regmap_update_bits(priv->regmap,731 ACCDET_EINT1_INVERTER_SW_EN_ADDR,732 ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,733 BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));734 }735 }736}737 738static void config_eint_init_by_mode(struct mt6359_accdet *priv)739{740 unsigned int val = 0;741 742 if (priv->caps & ACCDET_PMIC_EINT0) {743 regmap_update_bits(priv->regmap, RG_EINT0EN_ADDR,744 RG_EINT0EN_MASK_SFT, BIT(RG_EINT0EN_SFT));745 } else if (priv->caps & ACCDET_PMIC_EINT1) {746 regmap_update_bits(priv->regmap, RG_EINT1EN_ADDR,747 RG_EINT1EN_MASK_SFT, BIT(RG_EINT1EN_SFT));748 }749 /* ESD switches on */750 regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,751 1 << 8, 1 << 8);752 /* before playback, set NCP pull low before nagative voltage */753 regmap_update_bits(priv->regmap, RG_NCP_PDDIS_EN_ADDR,754 RG_NCP_PDDIS_EN_MASK_SFT, BIT(RG_NCP_PDDIS_EN_SFT));755 756 if (priv->data->eint_detect_mode == 0x1 ||757 priv->data->eint_detect_mode == 0x2 ||758 priv->data->eint_detect_mode == 0x3) {759 if (priv->data->eint_use_ext_res == 0x1) {760 if (priv->caps & ACCDET_PMIC_EINT0) {761 regmap_update_bits(priv->regmap,762 RG_EINT0CONFIGACCDET_ADDR,763 RG_EINT0CONFIGACCDET_MASK_SFT,764 0);765 } else if (priv->caps & ACCDET_PMIC_EINT1) {766 regmap_update_bits(priv->regmap,767 RG_EINT1CONFIGACCDET_ADDR,768 RG_EINT1CONFIGACCDET_MASK_SFT,769 0);770 }771 } else {772 if (priv->caps & ACCDET_PMIC_EINT0) {773 regmap_update_bits(priv->regmap,774 RG_EINT0CONFIGACCDET_ADDR,775 RG_EINT0CONFIGACCDET_MASK_SFT,776 BIT(RG_EINT0CONFIGACCDET_SFT));777 } else if (priv->caps & ACCDET_PMIC_EINT1) {778 regmap_update_bits(priv->regmap,779 RG_EINT1CONFIGACCDET_ADDR,780 RG_EINT1CONFIGACCDET_MASK_SFT,781 BIT(RG_EINT1CONFIGACCDET_SFT));782 }783 }784 }785 786 if (priv->data->eint_detect_mode != 0x1) {787 /* current detect set 0.25uA */788 regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,789 0x3 << RG_ACCDETSPARE_SFT,790 0x3 << RG_ACCDETSPARE_SFT);791 }792 regmap_write(priv->regmap, RG_EINTCOMPVTH_ADDR,793 val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT);794}795 796static void mt6359_accdet_init(struct mt6359_accdet *priv)797{798 unsigned int reg = 0;799 800 regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR,801 ACCDET_SEQ_INIT_MASK_SFT, BIT(ACCDET_SEQ_INIT_SFT));802 mdelay(2);803 regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR,804 ACCDET_SEQ_INIT_MASK_SFT, 0);805 mdelay(1);806 /* init the debounce time (debounce/32768)sec */807 accdet_set_debounce(priv, accdet_state000,808 priv->data->pwm_deb->debounce0);809 accdet_set_debounce(priv, accdet_state001,810 priv->data->pwm_deb->debounce1);811 accdet_set_debounce(priv, accdet_state011,812 priv->data->pwm_deb->debounce3);813 accdet_set_debounce(priv, accdet_auxadc,814 priv->data->pwm_deb->debounce4);815 816 accdet_set_debounce(priv, eint_state000,817 priv->data->pwm_deb->eint_debounce0);818 accdet_set_debounce(priv, eint_state001,819 priv->data->pwm_deb->eint_debounce1);820 accdet_set_debounce(priv, eint_state011,821 priv->data->pwm_deb->eint_debounce3);822 accdet_set_debounce(priv, eint_inverter_state000,823 priv->data->pwm_deb->eint_inverter_debounce);824 825 regmap_update_bits(priv->regmap, RG_ACCDET_RST_ADDR,826 RG_ACCDET_RST_MASK_SFT, BIT(RG_ACCDET_RST_SFT));827 regmap_update_bits(priv->regmap, RG_ACCDET_RST_ADDR,828 RG_ACCDET_RST_MASK_SFT, 0);829 830 /* clear high micbias1 voltage setting */831 regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,832 0x3 << RG_AUDMICBIAS1HVEN_SFT, 0);833 regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,834 0x7 << RG_AUDMICBIAS1VREF_SFT, 0);835 836 /* init pwm frequency, duty & rise/falling delay */837 regmap_write(priv->regmap, ACCDET_PWM_WIDTH_ADDR,838 REGISTER_VAL(priv->data->pwm_deb->pwm_width));839 regmap_write(priv->regmap, ACCDET_PWM_THRESH_ADDR,840 REGISTER_VAL(priv->data->pwm_deb->pwm_thresh));841 regmap_write(priv->regmap, ACCDET_RISE_DELAY_ADDR,842 (priv->data->pwm_deb->fall_delay << 15 |843 priv->data->pwm_deb->rise_delay));844 845 regmap_read(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, ®);846 if (priv->data->mic_vol <= 7) {847 /* micbias1 <= 2.7V */848 regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,849 reg | (priv->data->mic_vol << RG_AUDMICBIAS1VREF_SFT) |850 RG_AUDMICBIAS1LOWPEN_MASK_SFT);851 } else if (priv->data->mic_vol == 8) {852 /* micbias1 = 2.8v */853 regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,854 reg | (3 << RG_AUDMICBIAS1HVEN_SFT) |855 RG_AUDMICBIAS1LOWPEN_MASK_SFT);856 } else if (priv->data->mic_vol == 9) {857 /* micbias1 = 2.85v */858 regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,859 reg | (1 << RG_AUDMICBIAS1HVEN_SFT) |860 RG_AUDMICBIAS1LOWPEN_MASK_SFT);861 }862 /* mic mode setting */863 regmap_read(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, ®);864 if (priv->data->mic_mode == HEADSET_MODE_1) {865 /* ACC mode*/866 regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,867 reg | RG_ACCDET_MODE_ANA11_MODE1);868 /* enable analog fast discharge */869 regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,870 RG_ANALOGFDEN_MASK_SFT,871 BIT(RG_ANALOGFDEN_SFT));872 regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,873 0x3 << 11, 0x3 << 11);874 } else if (priv->data->mic_mode == HEADSET_MODE_2) {875 /* DCC mode Low cost mode without internal bias */876 regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,877 reg | RG_ACCDET_MODE_ANA11_MODE2);878 /* enable analog fast discharge */879 regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,880 0x3 << RG_ANALOGFDEN_SFT,881 0x3 << RG_ANALOGFDEN_SFT);882 } else if (priv->data->mic_mode == HEADSET_MODE_6) {883 /* DCC mode Low cost mode with internal bias,884 * bit8 = 1 to use internal bias885 */886 regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,887 reg | RG_ACCDET_MODE_ANA11_MODE6);888 regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,889 RG_AUDMICBIAS1DCSW1PEN_MASK_SFT,890 BIT(RG_AUDMICBIAS1DCSW1PEN_SFT));891 /* enable analog fast discharge */892 regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,893 0x3 << RG_ANALOGFDEN_SFT,894 0x3 << RG_ANALOGFDEN_SFT);895 }896 897 if (priv->caps & ACCDET_PMIC_EINT_IRQ) {898 config_eint_init_by_mode(priv);899 config_digital_init_by_mode(priv);900 }901}902 903int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component,904 struct snd_soc_jack *jack)905{906 struct mt6359_accdet *priv =907 snd_soc_component_get_drvdata(component);908 909 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);910 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEDOWN);911 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);912 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);913 914 priv->jack = jack;915 916 mt6359_accdet_jack_report(priv);917 918 return 0;919}920EXPORT_SYMBOL_GPL(mt6359_accdet_enable_jack_detect);921 922static int mt6359_accdet_probe(struct platform_device *pdev)923{924 struct mt6359_accdet *priv;925 struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);926 int ret;927 928 dev_dbg(&pdev->dev, "%s(), dev name %s\n",929 __func__, dev_name(&pdev->dev));930 931 priv = devm_kzalloc(&pdev->dev, sizeof(struct mt6359_accdet),932 GFP_KERNEL);933 if (!priv)934 return -ENOMEM;935 936 priv->data = devm_kzalloc(&pdev->dev, sizeof(struct dts_data),937 GFP_KERNEL);938 if (!priv->data)939 return -ENOMEM;940 941 priv->data->pwm_deb = devm_kzalloc(&pdev->dev,942 sizeof(struct pwm_deb_settings),943 GFP_KERNEL);944 if (!priv->data->pwm_deb)945 return -ENOMEM;946 947 priv->regmap = mt6397->regmap;948 if (IS_ERR(priv->regmap)) {949 ret = PTR_ERR(priv->regmap);950 dev_err(&pdev->dev, "Failed to allocate register map: %d\n",951 ret);952 return ret;953 }954 priv->dev = &pdev->dev;955 956 ret = mt6359_accdet_parse_dt(priv);957 if (ret) {958 dev_err(&pdev->dev, "Failed to parse dts\n");959 return ret;960 }961 mutex_init(&priv->res_lock);962 963 priv->accdet_irq = platform_get_irq(pdev, 0);964 if (priv->accdet_irq >= 0) {965 ret = devm_request_threaded_irq(&pdev->dev, priv->accdet_irq,966 NULL, mt6359_accdet_irq,967 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,968 "ACCDET_IRQ", priv);969 if (ret) {970 dev_err(&pdev->dev,971 "Failed to request IRQ: (%d)\n", ret);972 return ret;973 }974 }975 976 if (priv->caps & ACCDET_PMIC_EINT0) {977 priv->accdet_eint0 = platform_get_irq(pdev, 1);978 if (priv->accdet_eint0 >= 0) {979 ret = devm_request_threaded_irq(&pdev->dev,980 priv->accdet_eint0,981 NULL, mt6359_accdet_irq,982 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,983 "ACCDET_EINT0", priv);984 if (ret) {985 dev_err(&pdev->dev,986 "Failed to request eint0 IRQ (%d)\n",987 ret);988 return ret;989 }990 }991 } else if (priv->caps & ACCDET_PMIC_EINT1) {992 priv->accdet_eint1 = platform_get_irq(pdev, 2);993 if (priv->accdet_eint1 >= 0) {994 ret = devm_request_threaded_irq(&pdev->dev,995 priv->accdet_eint1,996 NULL, mt6359_accdet_irq,997 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,998 "ACCDET_EINT1", priv);999 if (ret) {1000 dev_err(&pdev->dev,1001 "Failed to request eint1 IRQ (%d)\n",1002 ret);1003 return ret;1004 }1005 }1006 }1007 1008 priv->accdet_workqueue = create_singlethread_workqueue("accdet");1009 INIT_WORK(&priv->accdet_work, mt6359_accdet_work);1010 if (!priv->accdet_workqueue) {1011 dev_err(&pdev->dev, "Failed to create accdet workqueue\n");1012 ret = -1;1013 goto err_accdet_wq;1014 }1015 1016 priv->jd_workqueue = create_singlethread_workqueue("mt6359_accdet_jd");1017 INIT_WORK(&priv->jd_work, mt6359_accdet_jd_work);1018 if (!priv->jd_workqueue) {1019 dev_err(&pdev->dev, "Failed to create jack detect workqueue\n");1020 ret = -1;1021 goto err_eint_wq;1022 }1023 1024 platform_set_drvdata(pdev, priv);1025 ret = devm_snd_soc_register_component(&pdev->dev,1026 &mt6359_accdet_soc_driver,1027 NULL, 0);1028 if (ret) {1029 dev_err(&pdev->dev, "Failed to register component\n");1030 return ret;1031 }1032 1033 priv->jd_sts = M_PLUG_OUT;1034 priv->jack_type = 0;1035 priv->btn_type = 0;1036 priv->accdet_status = 0x3;1037 mt6359_accdet_init(priv);1038 1039 mt6359_accdet_jack_report(priv);1040 1041 return 0;1042 1043err_eint_wq:1044 destroy_workqueue(priv->accdet_workqueue);1045err_accdet_wq:1046 dev_err(&pdev->dev, "%s error. now exit.!\n", __func__);1047 return ret;1048}1049 1050static struct platform_driver mt6359_accdet_driver = {1051 .driver = {1052 .name = "pmic-codec-accdet",1053 },1054 .probe = mt6359_accdet_probe,1055};1056 1057module_platform_driver(mt6359_accdet_driver)1058 1059/* Module information */1060MODULE_DESCRIPTION("MT6359 ALSA SoC codec jack driver");1061MODULE_AUTHOR("Argus Lin <argus.lin@mediatek.com>");1062MODULE_LICENSE("GPL v2");1063