brintos

brintos / linux-shallow public Read only

0
0
Text · 31.4 KiB · ed34cc1 Raw
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, &reg);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, &reg);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