@@ -1022,19 +1022,71 @@ static int wcd_mbhc_get_plug_from_adc(struct wcd_mbhc *mbhc, int adc_result)
10221022 return plug_type ;
10231023}
10241024
1025+ static int wcd_mbhc_get_spl_hs_thres (struct wcd_mbhc * mbhc )
1026+ {
1027+ int hs_threshold , micbias_mv ;
1028+
1029+ micbias_mv = wcd_mbhc_get_micbias (mbhc );
1030+ if (mbhc -> cfg -> hs_thr && mbhc -> cfg -> micb_mv != WCD_MBHC_ADC_MICBIAS_MV ) {
1031+ if (mbhc -> cfg -> micb_mv == micbias_mv )
1032+ hs_threshold = mbhc -> cfg -> hs_thr ;
1033+ else
1034+ hs_threshold = (mbhc -> cfg -> hs_thr * micbias_mv ) / mbhc -> cfg -> micb_mv ;
1035+ } else {
1036+ hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * micbias_mv ) /
1037+ WCD_MBHC_ADC_MICBIAS_MV );
1038+ }
1039+ return hs_threshold ;
1040+ }
1041+
1042+ static bool wcd_mbhc_check_for_spl_headset (struct wcd_mbhc * mbhc )
1043+ {
1044+ bool is_spl_hs = false;
1045+ int output_mv , hs_threshold , hph_threshold ;
1046+
1047+ if (!mbhc -> mbhc_cb -> mbhc_micb_ctrl_thr_mic )
1048+ return false;
1049+
1050+ /* Bump up MIC_BIAS2 to 2.7V */
1051+ mbhc -> mbhc_cb -> mbhc_micb_ctrl_thr_mic (mbhc -> component , MIC_BIAS_2 , true);
1052+ usleep_range (10000 , 10100 );
1053+
1054+ output_mv = wcd_measure_adc_once (mbhc , MUX_CTL_IN2P );
1055+ hs_threshold = wcd_mbhc_get_spl_hs_thres (mbhc );
1056+ hph_threshold = wcd_mbhc_adc_get_hph_thres (mbhc );
1057+
1058+ if (output_mv > hs_threshold || output_mv < hph_threshold ) {
1059+ if (mbhc -> force_linein == true)
1060+ is_spl_hs = false;
1061+ } else {
1062+ is_spl_hs = true;
1063+ }
1064+
1065+ /* Back MIC_BIAS2 to 1.8v if the type is not special headset */
1066+ if (!is_spl_hs ) {
1067+ mbhc -> mbhc_cb -> mbhc_micb_ctrl_thr_mic (mbhc -> component , MIC_BIAS_2 , false);
1068+ /* Add 10ms delay for micbias to settle */
1069+ usleep_range (10000 , 10100 );
1070+ }
1071+
1072+ return is_spl_hs ;
1073+ }
1074+
10251075static void wcd_correct_swch_plug (struct work_struct * work )
10261076{
10271077 struct wcd_mbhc * mbhc ;
10281078 struct snd_soc_component * component ;
10291079 enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID ;
10301080 unsigned long timeout ;
10311081 int pt_gnd_mic_swap_cnt = 0 ;
1032- int output_mv , cross_conn , hs_threshold , try = 0 ;
1082+ int output_mv , cross_conn , hs_threshold , try = 0 , micbias_mv ;
1083+ bool is_spl_hs = false;
10331084 bool is_pa_on ;
10341085
10351086 mbhc = container_of (work , struct wcd_mbhc , correct_plug_swch );
10361087 component = mbhc -> component ;
10371088
1089+ micbias_mv = wcd_mbhc_get_micbias (mbhc );
10381090 hs_threshold = wcd_mbhc_adc_get_hs_thres (mbhc );
10391091
10401092 /* Mask ADC COMPLETE interrupt */
@@ -1097,6 +1149,16 @@ static void wcd_correct_swch_plug(struct work_struct *work)
10971149 plug_type = wcd_mbhc_get_plug_from_adc (mbhc , output_mv );
10981150 is_pa_on = wcd_mbhc_read_field (mbhc , WCD_MBHC_HPH_PA_EN );
10991151
1152+ if ((output_mv > hs_threshold ) && (!is_spl_hs )) {
1153+ is_spl_hs = wcd_mbhc_check_for_spl_headset (mbhc );
1154+ output_mv = wcd_measure_adc_once (mbhc , MUX_CTL_IN2P );
1155+
1156+ if (is_spl_hs ) {
1157+ hs_threshold = (hs_threshold * wcd_mbhc_get_micbias (mbhc )) /
1158+ micbias_mv ;
1159+ }
1160+ }
1161+
11001162 if ((output_mv <= hs_threshold ) && !is_pa_on ) {
11011163 /* Check for cross connection*/
11021164 cross_conn = wcd_check_cross_conn (mbhc );
@@ -1122,14 +1184,19 @@ static void wcd_correct_swch_plug(struct work_struct *work)
11221184 }
11231185 }
11241186
1125- if (output_mv > hs_threshold ) /* cable is extension cable */
1187+ /* cable is extension cable */
1188+ if (output_mv > hs_threshold || mbhc -> force_linein == true)
11261189 plug_type = MBHC_PLUG_TYPE_HIGH_HPH ;
11271190 }
11281191
11291192 wcd_mbhc_bcs_enable (mbhc , plug_type , true);
11301193
1131- if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH )
1132- wcd_mbhc_write_field (mbhc , WCD_MBHC_ELECT_ISRC_EN , 1 );
1194+ if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH ) {
1195+ if (is_spl_hs )
1196+ plug_type = MBHC_PLUG_TYPE_HEADSET ;
1197+ else
1198+ wcd_mbhc_write_field (mbhc , WCD_MBHC_ELECT_ISRC_EN , 1 );
1199+ }
11331200
11341201 wcd_mbhc_write_field (mbhc , WCD_MBHC_ADC_MODE , 0 );
11351202 wcd_mbhc_write_field (mbhc , WCD_MBHC_ADC_EN , 0 );
0 commit comments