123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #ifndef __WCD9XXX_MBHC_H__
- #define __WCD9XXX_MBHC_H__
- #include "wcd9xxx-resmgr.h"
- #include "wcdcal-hwdep.h"
- #define WCD9XXX_CFILT_FAST_MODE 0x00
- #define WCD9XXX_CFILT_SLOW_MODE 0x40
- #define WCD9XXX_CFILT_EXT_PRCHG_EN 0x30
- #define WCD9XXX_CFILT_EXT_PRCHG_DSBL 0x00
- #define WCD9XXX_USLEEP_RANGE_MARGIN_US 100
- struct mbhc_micbias_regs {
- u16 cfilt_val;
- u16 cfilt_ctl;
- u16 mbhc_reg;
- u16 int_rbias;
- u16 ctl_reg;
- u8 cfilt_sel;
- };
- enum mbhc_v_index {
- MBHC_V_IDX_CFILT,
- MBHC_V_IDX_VDDIO,
- MBHC_V_IDX_NUM,
- };
- enum mbhc_cal_type {
- MBHC_CAL_MCLK,
- MBHC_CAL_RCO,
- MBHC_CAL_NUM,
- };
- enum mbhc_impedance_detect_stages {
- PRE_MEAS,
- POST_MEAS,
- PA_DISABLE,
- };
- /* Data used by MBHC */
- struct mbhc_internal_cal_data {
- u16 dce_z;
- u16 dce_nsc_cs_z;
- u16 dce_mb;
- u16 sta_z;
- u16 sta_mb;
- u32 t_sta_dce;
- u32 t_dce;
- u32 t_sta;
- u32 micb_mv;
- u16 v_ins_hu[MBHC_V_IDX_NUM];
- u16 v_ins_h[MBHC_V_IDX_NUM];
- u16 v_b1_hu[MBHC_V_IDX_NUM];
- u16 v_b1_h[MBHC_V_IDX_NUM];
- u16 v_brh[MBHC_V_IDX_NUM];
- u16 v_brl;
- u16 v_no_mic;
- s16 v_inval_ins_low;
- s16 v_inval_ins_high;
- u16 v_cs_ins_h;
- };
- enum wcd9xxx_mbhc_plug_type {
- PLUG_TYPE_INVALID = -1,
- PLUG_TYPE_NONE,
- PLUG_TYPE_HEADSET,
- PLUG_TYPE_HEADPHONE,
- PLUG_TYPE_HIGH_HPH,
- PLUG_TYPE_GND_MIC_SWAP,
- PLUG_TYPE_ANC_HEADPHONE,
- };
- enum wcd9xxx_mbhc_micbias_type {
- MBHC_PRIMARY_MIC_MB,
- MBHC_ANC_MIC_MB,
- };
- enum wcd9xxx_micbias_num {
- MBHC_MICBIAS_INVALID = -1,
- MBHC_MICBIAS1,
- MBHC_MICBIAS2,
- MBHC_MICBIAS3,
- MBHC_MICBIAS4,
- };
- enum hw_jack_type {
- FOUR_POLE_JACK = 0,
- FIVE_POLE_JACK,
- SIX_POLE_JACK,
- };
- enum wcd9xx_mbhc_micbias_enable_bits {
- MBHC_MICBIAS_ENABLE_THRESHOLD_HEADSET,
- MBHC_MICBIAS_ENABLE_REGULAR_HEADSET,
- };
- enum wcd9xx_mbhc_cs_enable_bits {
- MBHC_CS_ENABLE_POLLING,
- MBHC_CS_ENABLE_INSERTION,
- MBHC_CS_ENABLE_REMOVAL,
- MBHC_CS_ENABLE_DET_ANC,
- };
- enum wcd9xxx_mbhc_state {
- MBHC_STATE_NONE = -1,
- MBHC_STATE_POTENTIAL,
- MBHC_STATE_POTENTIAL_RECOVERY,
- MBHC_STATE_RELEASE,
- };
- enum wcd9xxx_mbhc_btn_det_mem {
- MBHC_BTN_DET_V_BTN_LOW,
- MBHC_BTN_DET_V_BTN_HIGH,
- MBHC_BTN_DET_N_READY,
- MBHC_BTN_DET_N_CIC,
- MBHC_BTN_DET_GAIN
- };
- enum wcd9xxx_mbhc_clk_freq {
- TAIKO_MCLK_12P2MHZ = 0,
- TAIKO_MCLK_9P6MHZ,
- TAIKO_NUM_CLK_FREQS,
- };
- enum wcd9xxx_mbhc_event_state {
- MBHC_EVENT_PA_HPHL,
- MBHC_EVENT_PA_HPHR,
- MBHC_EVENT_PRE_TX_1_3_ON,
- MBHC_EVENT_POST_TX_1_3_OFF,
- };
- struct wcd9xxx_mbhc_general_cfg {
- u8 t_ldoh;
- u8 t_bg_fast_settle;
- u8 t_shutdown_plug_rem;
- u8 mbhc_nsa;
- u8 mbhc_navg;
- u8 v_micbias_l;
- u8 v_micbias;
- u8 mbhc_reserved;
- u16 settle_wait;
- u16 t_micbias_rampup;
- u16 t_micbias_rampdown;
- u16 t_supply_bringup;
- } __packed;
- struct wcd9xxx_mbhc_plug_detect_cfg {
- u32 mic_current;
- u32 hph_current;
- u16 t_mic_pid;
- u16 t_ins_complete;
- u16 t_ins_retry;
- u16 v_removal_delta;
- u8 micbias_slow_ramp;
- u8 reserved0;
- u8 reserved1;
- u8 reserved2;
- } __packed;
- struct wcd9xxx_mbhc_plug_type_cfg {
- u8 av_detect;
- u8 mono_detect;
- u8 num_ins_tries;
- u8 reserved0;
- s16 v_no_mic;
- s16 v_av_min;
- s16 v_av_max;
- s16 v_hs_min;
- s16 v_hs_max;
- u16 reserved1;
- } __packed;
- struct wcd9xxx_mbhc_btn_detect_cfg {
- s8 c[8];
- u8 nc;
- u8 n_meas;
- u8 mbhc_nsc;
- u8 n_btn_meas;
- u8 n_btn_con;
- u8 num_btn;
- u8 reserved0;
- u8 reserved1;
- u16 t_poll;
- u16 t_bounce_wait;
- u16 t_rel_timeout;
- s16 v_btn_press_delta_sta;
- s16 v_btn_press_delta_cic;
- u16 t_btn0_timeout;
- s16 _v_btn_low[0]; /* v_btn_low[num_btn] */
- s16 _v_btn_high[0]; /* v_btn_high[num_btn] */
- u8 _n_ready[TAIKO_NUM_CLK_FREQS];
- u8 _n_cic[TAIKO_NUM_CLK_FREQS];
- u8 _gain[TAIKO_NUM_CLK_FREQS];
- } __packed;
- struct wcd9xxx_mbhc_imped_detect_cfg {
- u8 _hs_imped_detect;
- u8 _n_rload;
- u8 _hph_keep_on;
- u8 _repeat_rload_calc;
- u16 _t_dac_ramp_time;
- u16 _rhph_high;
- u16 _rhph_low;
- u16 _rload[0]; /* rload[n_rload] */
- u16 _alpha[0]; /* alpha[n_rload] */
- u16 _beta[3];
- } __packed;
- struct wcd9xxx_mbhc_config {
- bool read_fw_bin;
- /*
- * void* calibration contains:
- * struct wcd9xxx_mbhc_general_cfg generic;
- * struct wcd9xxx_mbhc_plug_detect_cfg plug_det;
- * struct wcd9xxx_mbhc_plug_type_cfg plug_type;
- * struct wcd9xxx_mbhc_btn_detect_cfg btn_det;
- * struct wcd9xxx_mbhc_imped_detect_cfg imped_det;
- * Note: various size depends on btn_det->num_btn
- */
- void *calibration;
- enum wcd9xxx_micbias_num micbias;
- enum wcd9xxx_micbias_num anc_micbias;
- int (*mclk_cb_fn) (struct snd_soc_codec*, int, bool);
- unsigned int mclk_rate;
- unsigned int gpio;
- unsigned int gpio_irq;
- int gpio_level_insert;
- bool insert_detect; /* codec has own MBHC_INSERT_DETECT */
- bool detect_extn_cable;
- /* bit mask of enum wcd9xx_mbhc_micbias_enable_bits */
- unsigned long micbias_enable_flags;
- /* swap_gnd_mic returns true if extern GND/MIC swap switch toggled */
- bool (*swap_gnd_mic) (struct snd_soc_codec *);
- unsigned long cs_enable_flags;
- bool use_int_rbias;
- bool do_recalibration;
- bool use_vddio_meas;
- bool enable_anc_mic_detect;
- enum hw_jack_type hw_jack_type;
- };
- struct wcd9xxx_cfilt_mode {
- u8 reg_mode_val;
- u8 cur_mode_val;
- u8 reg_mask;
- };
- struct wcd9xxx_mbhc_intr {
- int poll_plug_rem;
- int shortavg_complete;
- int potential_button_press;
- int button_release;
- int dce_est_complete;
- int insertion;
- int hph_left_ocp;
- int hph_right_ocp;
- int hs_jack_switch;
- };
- struct wcd9xxx_mbhc_cb {
- void (*enable_mux_bias_block) (struct snd_soc_codec *);
- void (*cfilt_fast_mode) (struct snd_soc_codec *, struct wcd9xxx_mbhc *);
- void (*codec_specific_cal) (struct snd_soc_codec *,
- struct wcd9xxx_mbhc *);
- struct wcd9xxx_cfilt_mode (*switch_cfilt_mode) (struct wcd9xxx_mbhc *,
- bool);
- void (*select_cfilt) (struct snd_soc_codec *, struct wcd9xxx_mbhc *);
- enum wcd9xxx_cdc_type (*get_cdc_type) (void);
- void (*enable_clock_gate) (struct snd_soc_codec *, bool);
- int (*setup_zdet) (struct wcd9xxx_mbhc *,
- enum mbhc_impedance_detect_stages stage);
- void (*compute_impedance) (s16 *, s16 *, uint32_t *, uint32_t *);
- void (*enable_mbhc_txfe) (struct snd_soc_codec *, bool);
- int (*enable_mb_source) (struct snd_soc_codec *, bool, bool);
- void (*setup_int_rbias) (struct snd_soc_codec *, bool);
- void (*pull_mb_to_vddio) (struct snd_soc_codec *, bool);
- struct firmware_cal * (*get_hwdep_fw_cal) (struct snd_soc_codec *,
- enum wcd_cal_type);
- };
- struct wcd9xxx_mbhc {
- bool polling_active;
- /* Delayed work to report long button press */
- struct delayed_work mbhc_btn_dwork;
- int buttons_pressed;
- enum wcd9xxx_mbhc_state mbhc_state;
- struct wcd9xxx_mbhc_config *mbhc_cfg;
- const struct wcd9xxx_mbhc_cb *mbhc_cb;
- struct mbhc_internal_cal_data mbhc_data;
- struct mbhc_micbias_regs mbhc_bias_regs;
- struct mbhc_micbias_regs mbhc_anc_bias_regs;
- bool mbhc_micbias_switched;
- u32 hph_status; /* track headhpone status */
- u8 hphlocp_cnt; /* headphone left ocp retry */
- u8 hphrocp_cnt; /* headphone right ocp retry */
- /* Work to perform MBHC Firmware Read */
- struct delayed_work mbhc_firmware_dwork;
- const struct firmware *mbhc_fw;
- struct delayed_work mbhc_insert_dwork;
- struct firmware_cal *mbhc_cal;
- u8 current_plug;
- struct work_struct correct_plug_swch;
- /*
- * Work to perform polling on microphone voltage
- * in order to correct plug type once plug type
- * is detected as headphone
- */
- struct work_struct correct_plug_noswch;
- bool hs_detect_work_stop;
- bool lpi_enabled; /* low power insertion detection */
- bool in_swch_irq_handler;
- struct wcd9xxx_resmgr *resmgr;
- struct snd_soc_codec *codec;
- bool no_mic_headset_override;
- /* track PA/DAC state to sync with userspace */
- unsigned long hph_pa_dac_state;
- /*
- * save codec's state with resmgr event notification
- * bit flags of enum wcd9xxx_mbhc_event_state
- */
- unsigned long event_state;
- unsigned long mbhc_last_resume; /* in jiffies */
- bool insert_detect_level_insert;
- struct snd_soc_jack headset_jack;
- struct snd_soc_jack button_jack;
- struct notifier_block nblock;
- bool micbias_enable;
- int (*micbias_enable_cb) (struct snd_soc_codec*, bool,
- enum wcd9xxx_micbias_num);
- bool impedance_detect;
- /* impedance of hphl and hphr */
- uint32_t zl, zr;
- u32 rco_clk_rate;
- bool update_z;
- u8 scaling_mux_in;
- /* Holds codec specific interrupt mapping */
- const struct wcd9xxx_mbhc_intr *intr_ids;
- #ifdef CONFIG_DEBUG_FS
- struct dentry *debugfs_poke;
- struct dentry *debugfs_mbhc;
- #endif
- struct mutex mbhc_lock;
- };
- #define WCD9XXX_MBHC_CAL_SIZE(buttons, rload) ( \
- sizeof(enum wcd9xxx_micbias_num) + \
- sizeof(struct wcd9xxx_mbhc_general_cfg) + \
- sizeof(struct wcd9xxx_mbhc_plug_detect_cfg) + \
- ((sizeof(s16) + sizeof(s16)) * buttons) + \
- sizeof(struct wcd9xxx_mbhc_plug_type_cfg) + \
- sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
- sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
- ((sizeof(u16) + sizeof(u16)) * rload) \
- )
- #define WCD9XXX_MBHC_CAL_GENERAL_PTR(cali) ( \
- (struct wcd9xxx_mbhc_general_cfg *) cali)
- #define WCD9XXX_MBHC_CAL_PLUG_DET_PTR(cali) ( \
- (struct wcd9xxx_mbhc_plug_detect_cfg *) \
- &(WCD9XXX_MBHC_CAL_GENERAL_PTR(cali)[1]))
- #define WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(cali) ( \
- (struct wcd9xxx_mbhc_plug_type_cfg *) \
- &(WCD9XXX_MBHC_CAL_PLUG_DET_PTR(cali)[1]))
- #define WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali) ( \
- (struct wcd9xxx_mbhc_btn_detect_cfg *) \
- &(WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(cali)[1]))
- #define WCD9XXX_MBHC_CAL_IMPED_DET_PTR(cali) ( \
- (struct wcd9xxx_mbhc_imped_detect_cfg *) \
- (((void *)&WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)[1]) + \
- (WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->num_btn * \
- (sizeof(WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_low[0]) + \
- sizeof(WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_high[0])))) \
- )
- /* minimum size of calibration data assuming there is only one button and
- * one rload.
- */
- #define WCD9XXX_MBHC_CAL_MIN_SIZE ( \
- sizeof(struct wcd9xxx_mbhc_general_cfg) + \
- sizeof(struct wcd9xxx_mbhc_plug_detect_cfg) + \
- sizeof(struct wcd9xxx_mbhc_plug_type_cfg) + \
- sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
- sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
- (sizeof(u16) * 2) \
- )
- #define WCD9XXX_MBHC_CAL_BTN_SZ(cfg_ptr) ( \
- sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
- (cfg_ptr->num_btn * (sizeof(cfg_ptr->_v_btn_low[0]) + \
- sizeof(cfg_ptr->_v_btn_high[0]))))
- #define WCD9XXX_MBHC_CAL_IMPED_MIN_SZ ( \
- sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + sizeof(u16) * 2)
- #define WCD9XXX_MBHC_CAL_IMPED_SZ(cfg_ptr) ( \
- sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
- (cfg_ptr->_n_rload * \
- (sizeof(cfg_ptr->_rload[0]) + sizeof(cfg_ptr->_alpha[0]))))
- int wcd9xxx_mbhc_start(struct wcd9xxx_mbhc *mbhc,
- struct wcd9xxx_mbhc_config *mbhc_cfg);
- void wcd9xxx_mbhc_stop(struct wcd9xxx_mbhc *mbhc);
- int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
- struct snd_soc_codec *codec,
- int (*micbias_enable_cb) (struct snd_soc_codec*, bool,
- enum wcd9xxx_micbias_num),
- const struct wcd9xxx_mbhc_cb *mbhc_cb,
- const struct wcd9xxx_mbhc_intr *mbhc_cdc_intr_ids,
- int rco_clk_rate,
- bool impedance_det_en);
- void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc);
- void *wcd9xxx_mbhc_cal_btn_det_mp(
- const struct wcd9xxx_mbhc_btn_detect_cfg *btn_det,
- const enum wcd9xxx_mbhc_btn_det_mem mem);
- int wcd9xxx_mbhc_get_impedance(struct wcd9xxx_mbhc *mbhc, uint32_t *zl,
- uint32_t *zr);
- #endif /* __WCD9XXX_MBHC_H__ */
|