2021-03-10 21:33:06 +08:00
// SPDX-License-Identifier: GPL-2.0
//
// mt6359-accdet.c -- ALSA SoC mt6359 accdet driver
//
// Copyright (C) 2021 MediaTek Inc.
// Author: Argus Lin <argus.lin@mediatek.com>
//
# include <linux/of.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 )
{
2021-08-04 14:24:55 -05:00
int ret ;
2021-03-10 21:33:06 +08:00
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 )
{
2021-04-26 16:46:58 -05:00
int ret ;
2021-03-10 21:33:06 +08:00
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 ;
2021-08-04 14:24:55 -05:00
int ret ;
2021-03-10 21:33:06 +08:00
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 )
{
2021-08-04 14:24:55 -05:00
int ret ;
2021-03-10 21:33:06 +08:00
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 ) ) ;
}
2022-07-13 18:20:13 +08:00
of_node_put ( node ) ;
2021-03-10 21:33:06 +08:00
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 , & reg ) ;
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 , & reg ) ;
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 ) ;
2021-08-04 14:24:55 -05:00
int ret ;
2021-03-10 21:33:06 +08:00
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 ) ;
2022-08-11 14:01:26 +03:00
if ( priv - > accdet_irq > = 0 ) {
2021-03-10 21:33:06 +08:00
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 ) ;
2022-08-11 14:01:26 +03:00
if ( priv - > accdet_eint0 > = 0 ) {
2021-03-10 21:33:06 +08:00
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 ) ;
2022-08-11 14:01:26 +03:00
if ( priv - > accdet_eint1 > = 0 ) {
2021-03-10 21:33:06 +08:00
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 ) {
2021-03-30 09:47:10 +01:00
dev_err ( & pdev - > dev , " Failed to create jack detect workqueue \n " ) ;
2021-03-10 21:33:06 +08:00
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 ,
} ;
2021-05-31 14:12:03 +09:00
module_platform_driver ( mt6359_accdet_driver )
2021-03-10 21:33:06 +08:00
/* Module information */
MODULE_DESCRIPTION ( " MT6359 ALSA SoC codec jack driver " ) ;
MODULE_AUTHOR ( " Argus Lin <argus.lin@mediatek.com> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;