1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066 |
- // SPDX-License-Identifier: GPL-2.0
- //
- // mt6359-accdet.c -- ALSA SoC mt6359 accdet driver
- //
- // Copyright (C) 2021 MediaTek Inc.
- // Author: Argus Lin <[email protected]>
- //
- #include <linux/of_gpio.h>
- #include <linux/of.h>
- #include <linux/of_irq.h>
- #include <linux/of_device.h>
- #include <linux/of_address.h>
- #include <linux/input.h>
- #include <linux/kthread.h>
- #include <linux/io.h>
- #include <linux/sched/clock.h>
- #include <linux/workqueue.h>
- #include <linux/timer.h>
- #include <linux/delay.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/init.h>
- #include <linux/irqdomain.h>
- #include <linux/irq.h>
- #include <linux/regmap.h>
- #include <sound/soc.h>
- #include <sound/jack.h>
- #include <linux/mfd/mt6397/core.h>
- #include "mt6359-accdet.h"
- #include "mt6359.h"
- /* global variable definitions */
- #define REGISTER_VAL(x) ((x) - 1)
- /* mt6359 accdet capability */
- #define ACCDET_PMIC_EINT_IRQ BIT(0)
- #define ACCDET_AP_GPIO_EINT BIT(1)
- #define ACCDET_PMIC_EINT0 BIT(2)
- #define ACCDET_PMIC_EINT1 BIT(3)
- #define ACCDET_PMIC_BI_EINT BIT(4)
- #define ACCDET_PMIC_GPIO_TRIG_EINT BIT(5)
- #define ACCDET_PMIC_INVERTER_TRIG_EINT BIT(6)
- #define ACCDET_PMIC_RSV_EINT BIT(7)
- #define ACCDET_THREE_KEY BIT(8)
- #define ACCDET_FOUR_KEY BIT(9)
- #define ACCDET_TRI_KEY_CDD BIT(10)
- #define ACCDET_RSV_KEY BIT(11)
- #define ACCDET_ANALOG_FASTDISCHARGE BIT(12)
- #define ACCDET_DIGITAL_FASTDISCHARGE BIT(13)
- #define ACCDET_AD_FASTDISCHRAGE BIT(14)
- static struct platform_driver mt6359_accdet_driver;
- static const struct snd_soc_component_driver mt6359_accdet_soc_driver;
- /* local function declaration */
- static void accdet_set_debounce(struct mt6359_accdet *priv, int state,
- unsigned int debounce);
- static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv);
- static void config_digital_init_by_mode(struct mt6359_accdet *priv);
- static void config_eint_init_by_mode(struct mt6359_accdet *priv);
- static inline void mt6359_accdet_init(struct mt6359_accdet *priv);
- static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv);
- static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv);
- static void mt6359_accdet_jack_report(struct mt6359_accdet *priv);
- static void recover_eint_analog_setting(struct mt6359_accdet *priv);
- static void recover_eint_digital_setting(struct mt6359_accdet *priv);
- static void recover_eint_setting(struct mt6359_accdet *priv);
- static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv)
- {
- if (priv->data->eint_detect_mode == 0x3 ||
- priv->data->eint_detect_mode == 0x4) {
- /* ESD switches off */
- regmap_update_bits(priv->regmap,
- RG_ACCDETSPARE_ADDR, 1 << 8, 0);
- }
- if (priv->data->eint_detect_mode == 0x4) {
- if (priv->caps & ACCDET_PMIC_EINT0) {
- /* enable RG_EINT0CONFIGACCDET */
- regmap_update_bits(priv->regmap,
- RG_EINT0CONFIGACCDET_ADDR,
- RG_EINT0CONFIGACCDET_MASK_SFT,
- BIT(RG_EINT0CONFIGACCDET_SFT));
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- /* enable RG_EINT1CONFIGACCDET */
- regmap_update_bits(priv->regmap,
- RG_EINT1CONFIGACCDET_ADDR,
- RG_EINT1CONFIGACCDET_MASK_SFT,
- BIT(RG_EINT1CONFIGACCDET_SFT));
- }
- if (priv->data->eint_use_ext_res == 0x3 ||
- priv->data->eint_use_ext_res == 0x4) {
- /*select 500k, use internal resistor */
- regmap_update_bits(priv->regmap,
- RG_EINT0HIRENB_ADDR,
- RG_EINT0HIRENB_MASK_SFT,
- BIT(RG_EINT0HIRENB_SFT));
- }
- }
- return 0;
- }
- static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv)
- {
- if (priv->caps & ACCDET_PMIC_EINT0) {
- /* disable inverter */
- regmap_update_bits(priv->regmap,
- ACCDET_EINT0_INVERTER_SW_EN_ADDR,
- ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, 0);
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- /* disable inverter */
- regmap_update_bits(priv->regmap,
- ACCDET_EINT1_INVERTER_SW_EN_ADDR,
- ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, 0);
- }
- if (priv->data->eint_detect_mode == 0x4) {
- if (priv->caps & ACCDET_PMIC_EINT0) {
- /* set DA stable signal */
- regmap_update_bits(priv->regmap,
- ACCDET_DA_STABLE_ADDR,
- ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0);
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- /* set DA stable signal */
- regmap_update_bits(priv->regmap,
- ACCDET_DA_STABLE_ADDR,
- ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0);
- }
- }
- return 0;
- }
- static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv)
- {
- if (priv->jd_sts == M_PLUG_IN) {
- /* adjust digital setting */
- adjust_eint_digital_setting(priv);
- /* adjust analog setting */
- adjust_eint_analog_setting(priv);
- } else if (priv->jd_sts == M_PLUG_OUT) {
- /* set debounce to 1ms */
- accdet_set_debounce(priv, eint_state000,
- priv->data->pwm_deb->eint_debounce0);
- } else {
- dev_dbg(priv->dev, "should not be here %s()\n", __func__);
- }
- return 0;
- }
- static void recover_eint_analog_setting(struct mt6359_accdet *priv)
- {
- if (priv->data->eint_detect_mode == 0x3 ||
- priv->data->eint_detect_mode == 0x4) {
- /* ESD switches on */
- regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
- 1 << 8, 1 << 8);
- }
- if (priv->data->eint_detect_mode == 0x4) {
- if (priv->caps & ACCDET_PMIC_EINT0) {
- /* disable RG_EINT0CONFIGACCDET */
- regmap_update_bits(priv->regmap,
- RG_EINT0CONFIGACCDET_ADDR,
- RG_EINT0CONFIGACCDET_MASK_SFT, 0);
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- /* disable RG_EINT1CONFIGACCDET */
- regmap_update_bits(priv->regmap,
- RG_EINT1CONFIGACCDET_ADDR,
- RG_EINT1CONFIGACCDET_MASK_SFT, 0);
- }
- regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR,
- RG_EINT0HIRENB_MASK_SFT, 0);
- }
- }
- static void recover_eint_digital_setting(struct mt6359_accdet *priv)
- {
- if (priv->caps & ACCDET_PMIC_EINT0) {
- regmap_update_bits(priv->regmap,
- ACCDET_EINT0_M_SW_EN_ADDR,
- ACCDET_EINT0_M_SW_EN_MASK_SFT, 0);
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- regmap_update_bits(priv->regmap,
- ACCDET_EINT1_M_SW_EN_ADDR,
- ACCDET_EINT1_M_SW_EN_MASK_SFT, 0);
- }
- if (priv->data->eint_detect_mode == 0x4) {
- /* enable eint0cen */
- if (priv->caps & ACCDET_PMIC_EINT0) {
- /* enable eint0cen */
- regmap_update_bits(priv->regmap,
- ACCDET_DA_STABLE_ADDR,
- ACCDET_EINT0_CEN_STABLE_MASK_SFT,
- BIT(ACCDET_EINT0_CEN_STABLE_SFT));
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- /* enable eint1cen */
- regmap_update_bits(priv->regmap,
- ACCDET_DA_STABLE_ADDR,
- ACCDET_EINT1_CEN_STABLE_MASK_SFT,
- BIT(ACCDET_EINT1_CEN_STABLE_SFT));
- }
- }
- if (priv->data->eint_detect_mode != 0x1) {
- if (priv->caps & ACCDET_PMIC_EINT0) {
- /* enable inverter */
- regmap_update_bits(priv->regmap,
- ACCDET_EINT0_INVERTER_SW_EN_ADDR,
- ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
- BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- /* enable inverter */
- regmap_update_bits(priv->regmap,
- ACCDET_EINT1_INVERTER_SW_EN_ADDR,
- ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
- BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
- }
- }
- }
- static void recover_eint_setting(struct mt6359_accdet *priv)
- {
- if (priv->jd_sts == M_PLUG_OUT) {
- recover_eint_analog_setting(priv);
- recover_eint_digital_setting(priv);
- }
- }
- static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv)
- {
- int ret;
- unsigned int value = 0;
- regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
- ACCDET_IRQ_CLR_MASK_SFT, BIT(ACCDET_IRQ_CLR_SFT));
- usleep_range(200, 300);
- ret = regmap_read_poll_timeout(priv->regmap,
- ACCDET_IRQ_ADDR,
- value,
- (value & ACCDET_IRQ_MASK_SFT) == 0,
- 0,
- 1000);
- if (ret)
- dev_warn(priv->dev, "%s(), ret %d\n", __func__, ret);
- /* clear accdet int, modify for fix interrupt trigger twice error */
- regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
- ACCDET_IRQ_CLR_MASK_SFT, 0);
- regmap_update_bits(priv->regmap, RG_INT_STATUS_ACCDET_ADDR,
- RG_INT_STATUS_ACCDET_MASK_SFT,
- BIT(RG_INT_STATUS_ACCDET_SFT));
- /* recover accdet debounce0,3 */
- accdet_set_debounce(priv, accdet_state000,
- priv->data->pwm_deb->debounce0);
- accdet_set_debounce(priv, accdet_state001,
- priv->data->pwm_deb->debounce1);
- accdet_set_debounce(priv, accdet_state011,
- priv->data->pwm_deb->debounce3);
- priv->jack_type = 0;
- priv->btn_type = 0;
- priv->accdet_status = 0x3;
- mt6359_accdet_jack_report(priv);
- }
- static void accdet_set_debounce(struct mt6359_accdet *priv, int state,
- unsigned int debounce)
- {
- switch (state) {
- case accdet_state000:
- regmap_write(priv->regmap, ACCDET_DEBOUNCE0_ADDR, debounce);
- break;
- case accdet_state001:
- regmap_write(priv->regmap, ACCDET_DEBOUNCE1_ADDR, debounce);
- break;
- case accdet_state010:
- regmap_write(priv->regmap, ACCDET_DEBOUNCE2_ADDR, debounce);
- break;
- case accdet_state011:
- regmap_write(priv->regmap, ACCDET_DEBOUNCE3_ADDR, debounce);
- break;
- case accdet_auxadc:
- regmap_write(priv->regmap,
- ACCDET_CONNECT_AUXADC_TIME_DIG_ADDR, debounce);
- break;
- case eint_state000:
- regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE0_ADDR,
- 0xF << ACCDET_EINT_DEBOUNCE0_SFT,
- debounce << ACCDET_EINT_DEBOUNCE0_SFT);
- break;
- case eint_state001:
- regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE1_ADDR,
- 0xF << ACCDET_EINT_DEBOUNCE1_SFT,
- debounce << ACCDET_EINT_DEBOUNCE1_SFT);
- break;
- case eint_state010:
- regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE2_ADDR,
- 0xF << ACCDET_EINT_DEBOUNCE2_SFT,
- debounce << ACCDET_EINT_DEBOUNCE2_SFT);
- break;
- case eint_state011:
- regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE3_ADDR,
- 0xF << ACCDET_EINT_DEBOUNCE3_SFT,
- debounce << ACCDET_EINT_DEBOUNCE3_SFT);
- break;
- case eint_inverter_state000:
- regmap_write(priv->regmap, ACCDET_EINT_INVERTER_DEBOUNCE_ADDR,
- debounce);
- break;
- default:
- dev_warn(priv->dev, "Error: %s error state (%d)\n", __func__,
- state);
- break;
- }
- }
- static void mt6359_accdet_jack_report(struct mt6359_accdet *priv)
- {
- int report = 0;
- if (!priv->jack)
- return;
- report = priv->jack_type | priv->btn_type;
- snd_soc_jack_report(priv->jack, report, MT6359_ACCDET_JACK_MASK);
- }
- static unsigned int check_button(struct mt6359_accdet *priv, unsigned int v)
- {
- if (priv->caps & ACCDET_FOUR_KEY) {
- if (v < priv->data->four_key.down &&
- v >= priv->data->four_key.up)
- priv->btn_type = SND_JACK_BTN_1;
- if (v < priv->data->four_key.up &&
- v >= priv->data->four_key.voice)
- priv->btn_type = SND_JACK_BTN_2;
- if (v < priv->data->four_key.voice &&
- v >= priv->data->four_key.mid)
- priv->btn_type = SND_JACK_BTN_3;
- if (v < priv->data->four_key.mid)
- priv->btn_type = SND_JACK_BTN_0;
- } else {
- if (v < priv->data->three_key.down &&
- v >= priv->data->three_key.up)
- priv->btn_type = SND_JACK_BTN_1;
- if (v < priv->data->three_key.up &&
- v >= priv->data->three_key.mid)
- priv->btn_type = SND_JACK_BTN_2;
- if (v < priv->data->three_key.mid)
- priv->btn_type = SND_JACK_BTN_0;
- }
- return 0;
- }
- static void is_key_pressed(struct mt6359_accdet *priv, bool pressed)
- {
- priv->btn_type = priv->jack_type & ~MT6359_ACCDET_BTN_MASK;
- if (pressed)
- check_button(priv, priv->cali_voltage);
- }
- static inline void check_jack_btn_type(struct mt6359_accdet *priv)
- {
- unsigned int val = 0;
- regmap_read(priv->regmap, ACCDET_MEM_IN_ADDR, &val);
- priv->accdet_status =
- (val >> ACCDET_STATE_MEM_IN_OFFSET) & ACCDET_STATE_AB_MASK;
- switch (priv->accdet_status) {
- case 0:
- if (priv->jack_type == SND_JACK_HEADSET)
- is_key_pressed(priv, true);
- else
- priv->jack_type = SND_JACK_HEADPHONE;
- break;
- case 1:
- if (priv->jack_type == SND_JACK_HEADSET) {
- is_key_pressed(priv, false);
- } else {
- priv->jack_type = SND_JACK_HEADSET;
- accdet_set_debounce(priv, eint_state011, 0x1);
- }
- break;
- case 3:
- default:
- priv->jack_type = 0;
- break;
- }
- }
- static void mt6359_accdet_work(struct work_struct *work)
- {
- struct mt6359_accdet *priv =
- container_of(work, struct mt6359_accdet, accdet_work);
- mutex_lock(&priv->res_lock);
- priv->pre_accdet_status = priv->accdet_status;
- check_jack_btn_type(priv);
- if (priv->jack_plugged &&
- priv->pre_accdet_status != priv->accdet_status)
- mt6359_accdet_jack_report(priv);
- mutex_unlock(&priv->res_lock);
- }
- static void mt6359_accdet_jd_work(struct work_struct *work)
- {
- int ret;
- unsigned int value = 0;
- struct mt6359_accdet *priv =
- container_of(work, struct mt6359_accdet, jd_work);
- mutex_lock(&priv->res_lock);
- if (priv->jd_sts == M_PLUG_IN) {
- priv->jack_plugged = true;
- /* set and clear initial bit every eint interrupt */
- regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR,
- ACCDET_SEQ_INIT_MASK_SFT,
- BIT(ACCDET_SEQ_INIT_SFT));
- regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR,
- ACCDET_SEQ_INIT_MASK_SFT, 0);
- ret = regmap_read_poll_timeout(priv->regmap,
- ACCDET_SEQ_INIT_ADDR,
- value,
- (value & ACCDET_SEQ_INIT_MASK_SFT) == 0,
- 0,
- 1000);
- if (ret)
- dev_err(priv->dev, "%s(), ret %d\n", __func__, ret);
- /* enable ACCDET unit */
- regmap_update_bits(priv->regmap, ACCDET_SW_EN_ADDR,
- ACCDET_SW_EN_MASK_SFT, BIT(ACCDET_SW_EN_SFT));
- } else if (priv->jd_sts == M_PLUG_OUT) {
- priv->jack_plugged = false;
- accdet_set_debounce(priv, accdet_state011,
- priv->data->pwm_deb->debounce3);
- regmap_update_bits(priv->regmap, ACCDET_SW_EN_ADDR,
- ACCDET_SW_EN_MASK_SFT, 0);
- mt6359_accdet_recover_jd_setting(priv);
- }
- if (priv->caps & ACCDET_PMIC_EINT_IRQ)
- recover_eint_setting(priv);
- mutex_unlock(&priv->res_lock);
- }
- static irqreturn_t mt6359_accdet_irq(int irq, void *data)
- {
- struct mt6359_accdet *priv = data;
- unsigned int irq_val = 0, val = 0, value = 0;
- int ret;
- mutex_lock(&priv->res_lock);
- regmap_read(priv->regmap, ACCDET_IRQ_ADDR, &irq_val);
- if (irq_val & ACCDET_IRQ_MASK_SFT) {
- regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
- ACCDET_IRQ_CLR_MASK_SFT,
- BIT(ACCDET_IRQ_CLR_SFT));
- ret = regmap_read_poll_timeout(priv->regmap,
- ACCDET_IRQ_ADDR,
- value,
- (value & ACCDET_IRQ_MASK_SFT) == 0,
- 0,
- 1000);
- if (ret) {
- dev_err(priv->dev, "%s(), ret %d\n", __func__, ret);
- mutex_unlock(&priv->res_lock);
- return IRQ_NONE;
- }
- regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
- ACCDET_IRQ_CLR_MASK_SFT, 0);
- regmap_update_bits(priv->regmap, RG_INT_STATUS_ACCDET_ADDR,
- RG_INT_STATUS_ACCDET_MASK_SFT,
- BIT(RG_INT_STATUS_ACCDET_SFT));
- queue_work(priv->accdet_workqueue, &priv->accdet_work);
- } else {
- if (irq_val & ACCDET_EINT0_IRQ_MASK_SFT) {
- regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
- ACCDET_EINT0_IRQ_CLR_MASK_SFT,
- BIT(ACCDET_EINT0_IRQ_CLR_SFT));
- ret = regmap_read_poll_timeout(priv->regmap,
- ACCDET_IRQ_ADDR,
- value,
- (value & ACCDET_EINT0_IRQ_MASK_SFT) == 0,
- 0,
- 1000);
- if (ret) {
- dev_err(priv->dev, "%s(), ret %d\n", __func__,
- ret);
- mutex_unlock(&priv->res_lock);
- return IRQ_NONE;
- }
- regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
- ACCDET_EINT0_IRQ_CLR_MASK_SFT, 0);
- regmap_update_bits(priv->regmap,
- RG_INT_STATUS_ACCDET_ADDR,
- RG_INT_STATUS_ACCDET_EINT0_MASK_SFT,
- BIT(RG_INT_STATUS_ACCDET_EINT0_SFT));
- }
- if (irq_val & ACCDET_EINT1_IRQ_MASK_SFT) {
- regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
- ACCDET_EINT1_IRQ_CLR_MASK_SFT,
- BIT(ACCDET_EINT1_IRQ_CLR_SFT));
- ret = regmap_read_poll_timeout(priv->regmap,
- ACCDET_IRQ_ADDR,
- value,
- (value & ACCDET_EINT1_IRQ_MASK_SFT) == 0,
- 0,
- 1000);
- if (ret) {
- dev_err(priv->dev, "%s(), ret %d\n", __func__,
- ret);
- mutex_unlock(&priv->res_lock);
- return IRQ_NONE;
- }
- regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR,
- ACCDET_EINT1_IRQ_CLR_MASK_SFT, 0);
- regmap_update_bits(priv->regmap,
- RG_INT_STATUS_ACCDET_ADDR,
- RG_INT_STATUS_ACCDET_EINT1_MASK_SFT,
- BIT(RG_INT_STATUS_ACCDET_EINT1_SFT));
- }
- /* get jack detection status */
- regmap_read(priv->regmap, ACCDET_EINT0_MEM_IN_ADDR, &val);
- priv->jd_sts = ((val >> ACCDET_EINT0_MEM_IN_SFT) &
- ACCDET_EINT0_MEM_IN_MASK);
- /* adjust eint digital/analog setting */
- mt6359_accdet_jd_setting(priv);
- queue_work(priv->jd_workqueue, &priv->jd_work);
- }
- mutex_unlock(&priv->res_lock);
- return IRQ_HANDLED;
- }
- static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv)
- {
- int ret;
- struct device *dev = priv->dev;
- struct device_node *node = NULL;
- int pwm_deb[15] = {0};
- unsigned int tmp = 0;
- node = of_get_child_by_name(dev->parent->of_node, "accdet");
- if (!node)
- return -EINVAL;
- ret = of_property_read_u32(node, "mediatek,mic-vol",
- &priv->data->mic_vol);
- if (ret)
- priv->data->mic_vol = 8;
- ret = of_property_read_u32(node, "mediatek,plugout-debounce",
- &priv->data->plugout_deb);
- if (ret)
- priv->data->plugout_deb = 1;
- ret = of_property_read_u32(node, "mediatek,mic-mode",
- &priv->data->mic_mode);
- if (ret)
- priv->data->mic_mode = 2;
- ret = of_property_read_u32_array(node, "mediatek,pwm-deb-setting",
- pwm_deb, ARRAY_SIZE(pwm_deb));
- /* debounce8(auxadc debounce) is default, needn't get from dts */
- if (!ret)
- memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb));
- ret = of_property_read_u32(node, "mediatek,eint-level-pol",
- &priv->data->eint_pol);
- if (ret)
- priv->data->eint_pol = 8;
- ret = of_property_read_u32(node, "mediatek,eint-use-ap", &tmp);
- if (ret)
- tmp = 0;
- if (tmp == 0)
- priv->caps |= ACCDET_PMIC_EINT_IRQ;
- else if (tmp == 1)
- priv->caps |= ACCDET_AP_GPIO_EINT;
- ret = of_property_read_u32(node, "mediatek,eint-detect-mode",
- &priv->data->eint_detect_mode);
- if (ret) {
- /* eint detection mode equals to EINT HW Mode */
- priv->data->eint_detect_mode = 0x4;
- }
- ret = of_property_read_u32(node, "mediatek,eint-num", &tmp);
- if (ret)
- tmp = 0;
- if (tmp == 0)
- priv->caps |= ACCDET_PMIC_EINT0;
- else if (tmp == 1)
- priv->caps |= ACCDET_PMIC_EINT1;
- else if (tmp == 2)
- priv->caps |= ACCDET_PMIC_BI_EINT;
- ret = of_property_read_u32(node, "mediatek,eint-trig-mode",
- &tmp);
- if (ret)
- tmp = 0;
- if (tmp == 0)
- priv->caps |= ACCDET_PMIC_GPIO_TRIG_EINT;
- else if (tmp == 1)
- priv->caps |= ACCDET_PMIC_INVERTER_TRIG_EINT;
- ret = of_property_read_u32(node, "mediatek,eint-use-ext-res",
- &priv->data->eint_use_ext_res);
- if (ret) {
- /* eint use internal resister */
- priv->data->eint_use_ext_res = 0x0;
- }
- ret = of_property_read_u32(node, "mediatek,eint-comp-vth",
- &priv->data->eint_comp_vth);
- if (ret)
- priv->data->eint_comp_vth = 0x0;
- ret = of_property_read_u32(node, "mediatek,key-mode", &tmp);
- if (ret)
- tmp = 0;
- if (tmp == 0) {
- int three_key[4];
- priv->caps |= ACCDET_THREE_KEY;
- ret = of_property_read_u32_array(node,
- "mediatek,three-key-thr",
- three_key,
- ARRAY_SIZE(three_key));
- if (!ret)
- memcpy(&priv->data->three_key, three_key + 1,
- sizeof(struct three_key_threshold));
- } else if (tmp == 1) {
- int four_key[5];
- priv->caps |= ACCDET_FOUR_KEY;
- ret = of_property_read_u32_array(node,
- "mediatek,four-key-thr",
- four_key,
- ARRAY_SIZE(four_key));
- if (!ret) {
- memcpy(&priv->data->four_key, four_key + 1,
- sizeof(struct four_key_threshold));
- } else {
- dev_warn(priv->dev,
- "accdet no 4-key-thrsh dts, use efuse\n");
- }
- } else if (tmp == 2) {
- int three_key[4];
- priv->caps |= ACCDET_TRI_KEY_CDD;
- ret = of_property_read_u32_array(node,
- "mediatek,tri-key-cdd-thr",
- three_key,
- ARRAY_SIZE(three_key));
- if (!ret)
- memcpy(&priv->data->three_key, three_key + 1,
- sizeof(struct three_key_threshold));
- }
- of_node_put(node);
- dev_warn(priv->dev, "accdet caps=%x\n", priv->caps);
- return 0;
- }
- static void config_digital_init_by_mode(struct mt6359_accdet *priv)
- {
- /* enable eint cmpmem pwm */
- regmap_write(priv->regmap, ACCDET_EINT_CMPMEN_PWM_THRESH_ADDR,
- (priv->data->pwm_deb->eint_pwm_width << 4 |
- priv->data->pwm_deb->eint_pwm_thresh));
- /* DA signal stable */
- if (priv->caps & ACCDET_PMIC_EINT0) {
- regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
- ACCDET_EINT0_STABLE_VAL);
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR,
- ACCDET_EINT1_STABLE_VAL);
- }
- /* after receive n+1 number, interrupt issued. */
- regmap_update_bits(priv->regmap, ACCDET_EINT_M_PLUG_IN_NUM_ADDR,
- ACCDET_EINT_M_PLUG_IN_NUM_MASK_SFT,
- BIT(ACCDET_EINT_M_PLUG_IN_NUM_SFT));
- /* setting HW mode, enable digital fast discharge
- * if use EINT0 & EINT1 detection, please modify
- * ACCDET_HWMODE_EN_ADDR[2:1]
- */
- regmap_write(priv->regmap, ACCDET_HWMODE_EN_ADDR, 0x100);
- regmap_update_bits(priv->regmap, ACCDET_EINT_M_DETECT_EN_ADDR,
- ACCDET_EINT_M_DETECT_EN_MASK_SFT, 0);
- /* enable PWM */
- regmap_write(priv->regmap, ACCDET_CMP_PWM_EN_ADDR, 0x67);
- /* enable inverter detection */
- if (priv->data->eint_detect_mode == 0x1) {
- /* disable inverter detection */
- if (priv->caps & ACCDET_PMIC_EINT0) {
- regmap_update_bits(priv->regmap,
- ACCDET_EINT0_INVERTER_SW_EN_ADDR,
- ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
- 0);
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- regmap_update_bits(priv->regmap,
- ACCDET_EINT1_INVERTER_SW_EN_ADDR,
- ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
- 0);
- }
- } else {
- if (priv->caps & ACCDET_PMIC_EINT0) {
- regmap_update_bits(priv->regmap,
- ACCDET_EINT0_INVERTER_SW_EN_ADDR,
- ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT,
- BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT));
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- regmap_update_bits(priv->regmap,
- ACCDET_EINT1_INVERTER_SW_EN_ADDR,
- ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT,
- BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT));
- }
- }
- }
- static void config_eint_init_by_mode(struct mt6359_accdet *priv)
- {
- unsigned int val = 0;
- if (priv->caps & ACCDET_PMIC_EINT0) {
- regmap_update_bits(priv->regmap, RG_EINT0EN_ADDR,
- RG_EINT0EN_MASK_SFT, BIT(RG_EINT0EN_SFT));
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- regmap_update_bits(priv->regmap, RG_EINT1EN_ADDR,
- RG_EINT1EN_MASK_SFT, BIT(RG_EINT1EN_SFT));
- }
- /* ESD switches on */
- regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
- 1 << 8, 1 << 8);
- /* before playback, set NCP pull low before nagative voltage */
- regmap_update_bits(priv->regmap, RG_NCP_PDDIS_EN_ADDR,
- RG_NCP_PDDIS_EN_MASK_SFT, BIT(RG_NCP_PDDIS_EN_SFT));
- if (priv->data->eint_detect_mode == 0x1 ||
- priv->data->eint_detect_mode == 0x2 ||
- priv->data->eint_detect_mode == 0x3) {
- if (priv->data->eint_use_ext_res == 0x1) {
- if (priv->caps & ACCDET_PMIC_EINT0) {
- regmap_update_bits(priv->regmap,
- RG_EINT0CONFIGACCDET_ADDR,
- RG_EINT0CONFIGACCDET_MASK_SFT,
- 0);
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- regmap_update_bits(priv->regmap,
- RG_EINT1CONFIGACCDET_ADDR,
- RG_EINT1CONFIGACCDET_MASK_SFT,
- 0);
- }
- } else {
- if (priv->caps & ACCDET_PMIC_EINT0) {
- regmap_update_bits(priv->regmap,
- RG_EINT0CONFIGACCDET_ADDR,
- RG_EINT0CONFIGACCDET_MASK_SFT,
- BIT(RG_EINT0CONFIGACCDET_SFT));
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- regmap_update_bits(priv->regmap,
- RG_EINT1CONFIGACCDET_ADDR,
- RG_EINT1CONFIGACCDET_MASK_SFT,
- BIT(RG_EINT1CONFIGACCDET_SFT));
- }
- }
- }
- if (priv->data->eint_detect_mode != 0x1) {
- /* current detect set 0.25uA */
- regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
- 0x3 << RG_ACCDETSPARE_SFT,
- 0x3 << RG_ACCDETSPARE_SFT);
- }
- regmap_write(priv->regmap, RG_EINTCOMPVTH_ADDR,
- val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT);
- }
- static void mt6359_accdet_init(struct mt6359_accdet *priv)
- {
- unsigned int reg = 0;
- regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR,
- ACCDET_SEQ_INIT_MASK_SFT, BIT(ACCDET_SEQ_INIT_SFT));
- mdelay(2);
- regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR,
- ACCDET_SEQ_INIT_MASK_SFT, 0);
- mdelay(1);
- /* init the debounce time (debounce/32768)sec */
- accdet_set_debounce(priv, accdet_state000,
- priv->data->pwm_deb->debounce0);
- accdet_set_debounce(priv, accdet_state001,
- priv->data->pwm_deb->debounce1);
- accdet_set_debounce(priv, accdet_state011,
- priv->data->pwm_deb->debounce3);
- accdet_set_debounce(priv, accdet_auxadc,
- priv->data->pwm_deb->debounce4);
- accdet_set_debounce(priv, eint_state000,
- priv->data->pwm_deb->eint_debounce0);
- accdet_set_debounce(priv, eint_state001,
- priv->data->pwm_deb->eint_debounce1);
- accdet_set_debounce(priv, eint_state011,
- priv->data->pwm_deb->eint_debounce3);
- accdet_set_debounce(priv, eint_inverter_state000,
- priv->data->pwm_deb->eint_inverter_debounce);
- regmap_update_bits(priv->regmap, RG_ACCDET_RST_ADDR,
- RG_ACCDET_RST_MASK_SFT, BIT(RG_ACCDET_RST_SFT));
- regmap_update_bits(priv->regmap, RG_ACCDET_RST_ADDR,
- RG_ACCDET_RST_MASK_SFT, 0);
- /* clear high micbias1 voltage setting */
- regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
- 0x3 << RG_AUDMICBIAS1HVEN_SFT, 0);
- regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
- 0x7 << RG_AUDMICBIAS1VREF_SFT, 0);
- /* init pwm frequency, duty & rise/falling delay */
- regmap_write(priv->regmap, ACCDET_PWM_WIDTH_ADDR,
- REGISTER_VAL(priv->data->pwm_deb->pwm_width));
- regmap_write(priv->regmap, ACCDET_PWM_THRESH_ADDR,
- REGISTER_VAL(priv->data->pwm_deb->pwm_thresh));
- regmap_write(priv->regmap, ACCDET_RISE_DELAY_ADDR,
- (priv->data->pwm_deb->fall_delay << 15 |
- priv->data->pwm_deb->rise_delay));
- regmap_read(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, ®);
- if (priv->data->mic_vol <= 7) {
- /* micbias1 <= 2.7V */
- regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
- reg | (priv->data->mic_vol << RG_AUDMICBIAS1VREF_SFT) |
- RG_AUDMICBIAS1LOWPEN_MASK_SFT);
- } else if (priv->data->mic_vol == 8) {
- /* micbias1 = 2.8v */
- regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
- reg | (3 << RG_AUDMICBIAS1HVEN_SFT) |
- RG_AUDMICBIAS1LOWPEN_MASK_SFT);
- } else if (priv->data->mic_vol == 9) {
- /* micbias1 = 2.85v */
- regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
- reg | (1 << RG_AUDMICBIAS1HVEN_SFT) |
- RG_AUDMICBIAS1LOWPEN_MASK_SFT);
- }
- /* mic mode setting */
- regmap_read(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, ®);
- if (priv->data->mic_mode == HEADSET_MODE_1) {
- /* ACC mode*/
- regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
- reg | RG_ACCDET_MODE_ANA11_MODE1);
- /* enable analog fast discharge */
- regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
- RG_ANALOGFDEN_MASK_SFT,
- BIT(RG_ANALOGFDEN_SFT));
- regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR,
- 0x3 << 11, 0x3 << 11);
- } else if (priv->data->mic_mode == HEADSET_MODE_2) {
- /* DCC mode Low cost mode without internal bias */
- regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
- reg | RG_ACCDET_MODE_ANA11_MODE2);
- /* enable analog fast discharge */
- regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
- 0x3 << RG_ANALOGFDEN_SFT,
- 0x3 << RG_ANALOGFDEN_SFT);
- } else if (priv->data->mic_mode == HEADSET_MODE_6) {
- /* DCC mode Low cost mode with internal bias,
- * bit8 = 1 to use internal bias
- */
- regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR,
- reg | RG_ACCDET_MODE_ANA11_MODE6);
- regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR,
- RG_AUDMICBIAS1DCSW1PEN_MASK_SFT,
- BIT(RG_AUDMICBIAS1DCSW1PEN_SFT));
- /* enable analog fast discharge */
- regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR,
- 0x3 << RG_ANALOGFDEN_SFT,
- 0x3 << RG_ANALOGFDEN_SFT);
- }
- if (priv->caps & ACCDET_PMIC_EINT_IRQ) {
- config_eint_init_by_mode(priv);
- config_digital_init_by_mode(priv);
- }
- }
- int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component,
- struct snd_soc_jack *jack)
- {
- struct mt6359_accdet *priv =
- snd_soc_component_get_drvdata(component);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEDOWN);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
- snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
- priv->jack = jack;
- mt6359_accdet_jack_report(priv);
- return 0;
- }
- EXPORT_SYMBOL_GPL(mt6359_accdet_enable_jack_detect);
- static int mt6359_accdet_probe(struct platform_device *pdev)
- {
- struct mt6359_accdet *priv;
- struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
- int ret;
- dev_dbg(&pdev->dev, "%s(), dev name %s\n",
- __func__, dev_name(&pdev->dev));
- priv = devm_kzalloc(&pdev->dev, sizeof(struct mt6359_accdet),
- GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- priv->data = devm_kzalloc(&pdev->dev, sizeof(struct dts_data),
- GFP_KERNEL);
- if (!priv->data)
- return -ENOMEM;
- priv->data->pwm_deb = devm_kzalloc(&pdev->dev,
- sizeof(struct pwm_deb_settings),
- GFP_KERNEL);
- if (!priv->data->pwm_deb)
- return -ENOMEM;
- priv->regmap = mt6397->regmap;
- if (IS_ERR(priv->regmap)) {
- ret = PTR_ERR(priv->regmap);
- dev_err(&pdev->dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
- priv->dev = &pdev->dev;
- ret = mt6359_accdet_parse_dt(priv);
- if (ret) {
- dev_err(&pdev->dev, "Failed to parse dts\n");
- return ret;
- }
- mutex_init(&priv->res_lock);
- priv->accdet_irq = platform_get_irq(pdev, 0);
- if (priv->accdet_irq >= 0) {
- ret = devm_request_threaded_irq(&pdev->dev, priv->accdet_irq,
- NULL, mt6359_accdet_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- "ACCDET_IRQ", priv);
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to request IRQ: (%d)\n", ret);
- return ret;
- }
- }
- if (priv->caps & ACCDET_PMIC_EINT0) {
- priv->accdet_eint0 = platform_get_irq(pdev, 1);
- if (priv->accdet_eint0 >= 0) {
- ret = devm_request_threaded_irq(&pdev->dev,
- priv->accdet_eint0,
- NULL, mt6359_accdet_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- "ACCDET_EINT0", priv);
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to request eint0 IRQ (%d)\n",
- ret);
- return ret;
- }
- }
- } else if (priv->caps & ACCDET_PMIC_EINT1) {
- priv->accdet_eint1 = platform_get_irq(pdev, 2);
- if (priv->accdet_eint1 >= 0) {
- ret = devm_request_threaded_irq(&pdev->dev,
- priv->accdet_eint1,
- NULL, mt6359_accdet_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- "ACCDET_EINT1", priv);
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to request eint1 IRQ (%d)\n",
- ret);
- return ret;
- }
- }
- }
- priv->accdet_workqueue = create_singlethread_workqueue("accdet");
- INIT_WORK(&priv->accdet_work, mt6359_accdet_work);
- if (!priv->accdet_workqueue) {
- dev_err(&pdev->dev, "Failed to create accdet workqueue\n");
- ret = -1;
- goto err_accdet_wq;
- }
- priv->jd_workqueue = create_singlethread_workqueue("mt6359_accdet_jd");
- INIT_WORK(&priv->jd_work, mt6359_accdet_jd_work);
- if (!priv->jd_workqueue) {
- dev_err(&pdev->dev, "Failed to create jack detect workqueue\n");
- ret = -1;
- goto err_eint_wq;
- }
- platform_set_drvdata(pdev, priv);
- ret = devm_snd_soc_register_component(&pdev->dev,
- &mt6359_accdet_soc_driver,
- NULL, 0);
- if (ret) {
- dev_err(&pdev->dev, "Failed to register component\n");
- return ret;
- }
- priv->jd_sts = M_PLUG_OUT;
- priv->jack_type = 0;
- priv->btn_type = 0;
- priv->accdet_status = 0x3;
- mt6359_accdet_init(priv);
- mt6359_accdet_jack_report(priv);
- return 0;
- err_eint_wq:
- destroy_workqueue(priv->accdet_workqueue);
- err_accdet_wq:
- dev_err(&pdev->dev, "%s error. now exit.!\n", __func__);
- return ret;
- }
- static struct platform_driver mt6359_accdet_driver = {
- .driver = {
- .name = "pmic-codec-accdet",
- },
- .probe = mt6359_accdet_probe,
- };
- module_platform_driver(mt6359_accdet_driver)
- /* Module information */
- MODULE_DESCRIPTION("MT6359 ALSA SoC codec jack driver");
- MODULE_AUTHOR("Argus Lin <[email protected]>");
- MODULE_LICENSE("GPL v2");
|