ASoC: cs42l42: Implement Manual Type detection as fallback
Some headsets are not detected correctly by Automatic Type Detection on cs42l42. Instead, Manual Type Detection can be used to give a more accurate value. Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com> Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com> Link: https://lore.kernel.org/r/20210916102750.9212-2-vitalyr@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
bde4f08cff
commit
1245181449
@ -1046,11 +1046,83 @@ static struct snd_soc_dai_driver cs42l42_dai = {
|
||||
.ops = &cs42l42_ops,
|
||||
};
|
||||
|
||||
static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||
{
|
||||
unsigned int hs_det_status;
|
||||
unsigned int hs_det_comp;
|
||||
unsigned int hs_det_sw;
|
||||
|
||||
/* Set hs detect to manual, active mode */
|
||||
regmap_update_bits(cs42l42->regmap,
|
||||
CS42L42_HSDET_CTL2,
|
||||
CS42L42_HSDET_CTRL_MASK |
|
||||
CS42L42_HSDET_SET_MASK |
|
||||
CS42L42_HSBIAS_REF_MASK |
|
||||
CS42L42_HSDET_AUTO_TIME_MASK,
|
||||
(1 << CS42L42_HSDET_CTRL_SHIFT) |
|
||||
(0 << CS42L42_HSDET_SET_SHIFT) |
|
||||
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
||||
(0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
|
||||
|
||||
/* Open the SW_HSB_HS3 switch and close SW_HSB_HS4 for a Type 1 headset. */
|
||||
regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, CS42L42_HSDET_SW_COMP1);
|
||||
|
||||
regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
|
||||
|
||||
hs_det_comp = (hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
|
||||
CS42L42_HSDET_COMP1_OUT_SHIFT;
|
||||
|
||||
/* Close the SW_HSB_HS3 switch for a Type 2 headset. */
|
||||
regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, CS42L42_HSDET_SW_COMP2);
|
||||
|
||||
regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
|
||||
|
||||
hs_det_comp |= ((hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
|
||||
CS42L42_HSDET_COMP2_OUT_SHIFT) << 1;
|
||||
|
||||
switch (hs_det_comp) {
|
||||
case CS42L42_HSDET_COMP_TYPE1:
|
||||
cs42l42->hs_type = CS42L42_PLUG_CTIA;
|
||||
hs_det_sw = CS42L42_HSDET_SW_TYPE1;
|
||||
break;
|
||||
case CS42L42_HSDET_COMP_TYPE2:
|
||||
cs42l42->hs_type = CS42L42_PLUG_OMTP;
|
||||
hs_det_sw = CS42L42_HSDET_SW_TYPE2;
|
||||
break;
|
||||
case CS42L42_HSDET_COMP_TYPE3:
|
||||
cs42l42->hs_type = CS42L42_PLUG_HEADPHONE;
|
||||
hs_det_sw = CS42L42_HSDET_SW_TYPE3;
|
||||
break;
|
||||
default:
|
||||
cs42l42->hs_type = CS42L42_PLUG_INVALID;
|
||||
hs_det_sw = CS42L42_HSDET_SW_TYPE4;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set Switches */
|
||||
regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, hs_det_sw);
|
||||
|
||||
/* Set HSDET mode to Manual—Disabled */
|
||||
regmap_update_bits(cs42l42->regmap,
|
||||
CS42L42_HSDET_CTL2,
|
||||
CS42L42_HSDET_CTRL_MASK |
|
||||
CS42L42_HSDET_SET_MASK |
|
||||
CS42L42_HSBIAS_REF_MASK |
|
||||
CS42L42_HSDET_AUTO_TIME_MASK,
|
||||
(0 << CS42L42_HSDET_CTRL_SHIFT) |
|
||||
(0 << CS42L42_HSDET_SET_SHIFT) |
|
||||
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
||||
(0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
|
||||
}
|
||||
|
||||
static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||
{
|
||||
unsigned int hs_det_status;
|
||||
unsigned int int_status;
|
||||
|
||||
/* Read and save the hs detection result */
|
||||
regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
|
||||
|
||||
/* Mask the auto detect interrupt */
|
||||
regmap_update_bits(cs42l42->regmap,
|
||||
CS42L42_CODEC_INT_MASK,
|
||||
@ -1059,24 +1131,32 @@ static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||
(1 << CS42L42_PDN_DONE_SHIFT) |
|
||||
(1 << CS42L42_HSDET_AUTO_DONE_SHIFT));
|
||||
|
||||
/* Set hs detect to automatic, disabled mode */
|
||||
regmap_update_bits(cs42l42->regmap,
|
||||
CS42L42_HSDET_CTL2,
|
||||
CS42L42_HSDET_CTRL_MASK |
|
||||
CS42L42_HSDET_SET_MASK |
|
||||
CS42L42_HSBIAS_REF_MASK |
|
||||
CS42L42_HSDET_AUTO_TIME_MASK,
|
||||
(2 << CS42L42_HSDET_CTRL_SHIFT) |
|
||||
(2 << CS42L42_HSDET_SET_SHIFT) |
|
||||
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
||||
(3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
|
||||
|
||||
/* Read and save the hs detection result */
|
||||
regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
|
||||
|
||||
cs42l42->hs_type = (hs_det_status & CS42L42_HSDET_TYPE_MASK) >>
|
||||
CS42L42_HSDET_TYPE_SHIFT;
|
||||
|
||||
/* Run Manual detection if auto detect has not found a headset.
|
||||
* We Re-Run with Manual Detection if the original detection was invalid or headphones,
|
||||
* to ensure that a headset mic is detected in all cases.
|
||||
*/
|
||||
if (cs42l42->hs_type == CS42L42_PLUG_INVALID ||
|
||||
cs42l42->hs_type == CS42L42_PLUG_HEADPHONE) {
|
||||
dev_dbg(cs42l42->component->dev, "Running Manual Detection Fallback\n");
|
||||
cs42l42_manual_hs_type_detect(cs42l42);
|
||||
} else {
|
||||
/* Set hs detect to automatic, disabled mode */
|
||||
regmap_update_bits(cs42l42->regmap,
|
||||
CS42L42_HSDET_CTL2,
|
||||
CS42L42_HSDET_CTRL_MASK |
|
||||
CS42L42_HSDET_SET_MASK |
|
||||
CS42L42_HSBIAS_REF_MASK |
|
||||
CS42L42_HSDET_AUTO_TIME_MASK,
|
||||
(2 << CS42L42_HSDET_CTRL_SHIFT) |
|
||||
(2 << CS42L42_HSDET_SET_SHIFT) |
|
||||
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
||||
(3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
|
||||
}
|
||||
|
||||
/* Set up button detection */
|
||||
if ((cs42l42->hs_type == CS42L42_PLUG_CTIA) ||
|
||||
(cs42l42->hs_type == CS42L42_PLUG_OMTP)) {
|
||||
|
@ -228,6 +228,60 @@
|
||||
#define CS42L42_PLUG_HEADPHONE 2
|
||||
#define CS42L42_PLUG_INVALID 3
|
||||
|
||||
#define CS42L42_HSDET_SW_COMP1 ((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_HS3_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
|
||||
(0 << CS42L42_SW_REF_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_REF_HS3_SHIFT))
|
||||
#define CS42L42_HSDET_SW_COMP2 ((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_HS3_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
|
||||
(1 << CS42L42_SW_REF_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_REF_HS3_SHIFT))
|
||||
#define CS42L42_HSDET_SW_TYPE1 ((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_HS3_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
|
||||
(0 << CS42L42_SW_REF_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_REF_HS3_SHIFT))
|
||||
#define CS42L42_HSDET_SW_TYPE2 ((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_HS3_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
|
||||
(1 << CS42L42_SW_REF_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_REF_HS3_SHIFT))
|
||||
#define CS42L42_HSDET_SW_TYPE3 ((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_HS3_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
|
||||
(1 << CS42L42_SW_REF_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_REF_HS3_SHIFT))
|
||||
#define CS42L42_HSDET_SW_TYPE4 ((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_HS4_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_HS3_SHIFT) | \
|
||||
(0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
|
||||
(0 << CS42L42_SW_REF_HS4_SHIFT) | \
|
||||
(1 << CS42L42_SW_REF_HS3_SHIFT))
|
||||
|
||||
#define CS42L42_HSDET_COMP_TYPE1 1
|
||||
#define CS42L42_HSDET_COMP_TYPE2 2
|
||||
#define CS42L42_HSDET_COMP_TYPE3 0
|
||||
#define CS42L42_HSDET_COMP_TYPE4 3
|
||||
|
||||
#define CS42L42_HS_CLAMP_DISABLE (CS42L42_PAGE_11 + 0x29)
|
||||
#define CS42L42_HS_CLAMP_DISABLE_SHIFT 0
|
||||
#define CS42L42_HS_CLAMP_DISABLE_MASK (1 << CS42L42_HS_CLAMP_DISABLE_SHIFT)
|
||||
|
Loading…
Reference in New Issue
Block a user