OVer-Current-Detection (OVCD) for the micbias current is used to detect if an inserted jack is a headset or headphones (mic shorted to ground).
Some boards may need different values for the OVCD threshold because of a resistor on the board in serial with or parallel to the jack mic contact.
This commit adds support for the sofar unset OVCD scale-factor register values and adds support for specifying both the current threshold and the scale-factor to pdata and this commets sets these values only once from rt5651_set_jack() instead of setting them every time we do jack-detection.
This commit sets the new pdata values for this to 2000uA with a scale-factor of 0.75 for the KIANO SlimNote 14.2 device, which is the only rt5652 using device on which jack-detection is currently enabled.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- include/sound/rt5651.h | 29 +++++++++++++++++++++++++++- sound/soc/codecs/rt5651.c | 27 +++++++++++++++++--------- sound/soc/codecs/rt5651.h | 10 ++++++++++ sound/soc/intel/boards/bytcr_rt5651.c | 36 +++++++++++++++++++++++++++++------ 4 files changed, 86 insertions(+), 16 deletions(-)
diff --git a/include/sound/rt5651.h b/include/sound/rt5651.h index 18b79a761f10..7b000406589c 100644 --- a/include/sound/rt5651.h +++ b/include/sound/rt5651.h @@ -18,12 +18,39 @@ enum rt5651_jd_src { RT5651_JD2, };
+/* These mirror the RT5651_MIC1_OVTH_*UA consts and MUST be in the same order */ +enum rt5651_ovth_curr { + RT5651_OVTH_600UA, + RT5651_OVTH_1500UA, + RT5651_OVTH_2000UA, +}; + +/* These mirror the RT5651_MIC_OVCD_SF* consts and MUST be in the same order */ +enum rt5651_ovcd_sf { + RT5651_OVCD_SF_0P5, + RT5651_OVCD_SF_0P75, + RT5651_OVCD_SF_1P0, + RT5651_OVCD_SF_1P5, +}; + +/* + * Note testing on various boards has shown that good defaults for ovth_curr + * and ovth_sf are 2000UA and 0.75. For an effective threshold of 1500UA, + * this seems to be more reliable then 1500UA and 1.0. Some boards may need + * different values because of a resistor on the board in serial with or + * parallel to the jack mic contact. + */ struct rt5651_platform_data { /* IN2 can optionally be differential */ bool in2_diff; - + /* Configure GPIO2 as DMIC1 SCL */ bool dmic_en; + /* Jack detect source or JD_NULL to disable jack-detect */ enum rt5651_jd_src jd_src; + /* Jack micbias overcurrent detect current threshold */ + enum rt5651_ovth_curr ovth_curr; + /* Jack micbias overcurrent detect current scale-factor */ + enum rt5651_ovcd_sf ovth_sf; };
#endif diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 4b0509f7e001..1e20cdb8b569 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1575,6 +1575,7 @@ static int rt5651_set_jack(struct snd_soc_codec *codec, regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1, RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
+ /* Select jack detect source */ switch (rt5651->pdata.jd_src) { case RT5651_JD1_1: regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2, @@ -1607,11 +1608,25 @@ static int rt5651_set_jack(struct snd_soc_codec *codec, break; }
+ /* Enable jack detect power */ regmap_update_bits(rt5651->regmap, RT5651_PWR_ANLG2, RT5651_PWR_JD_M, RT5651_PWR_JD_M);
+ /* + * Set OVCD threshold current and scale-factor from pdata. + */ + regmap_write(rt5651->regmap, RT5651_PR_BASE + RT5651_BIAS_CUR4, 0xa800 | + (rt5651->pdata.ovth_sf << RT5651_MIC_OVCD_SF_SFT)); + regmap_update_bits(rt5651->regmap, RT5651_MICBIAS, - 0x38, 0x38); + RT5651_MIC1_OVCD_MASK | + RT5651_MIC1_OVTH_MASK | + RT5651_PWR_CLK12M_MASK | + RT5651_PWR_MB_MASK, + RT5651_MIC1_OVCD_DIS | + (rt5651->pdata.ovth_curr << RT5651_MIC1_OVTH_SFT) | + RT5651_PWR_MB_PU | + RT5651_PWR_CLK12M_PU);
ret = devm_request_threaded_irq(codec->dev, rt5651->irq, NULL, rt5651_irq, @@ -1795,14 +1810,8 @@ static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert) snd_soc_dapm_mutex_unlock(dapm);
snd_soc_update_bits(codec, RT5651_MICBIAS, - RT5651_MIC1_OVCD_MASK | - RT5651_MIC1_OVTH_MASK | - RT5651_PWR_CLK12M_MASK | - RT5651_PWR_MB_MASK, - RT5651_MIC1_OVCD_EN | - RT5651_MIC1_OVTH_600UA | - RT5651_PWR_MB_PU | - RT5651_PWR_CLK12M_PU); + RT5651_MIC1_OVCD_MASK, + RT5651_MIC1_OVCD_EN); msleep(100); if (snd_soc_read(codec, RT5651_IRQ_CTRL2) & RT5651_MB1_OC_CLR) jack_type = SND_JACK_HEADPHONE; diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h index 151ac92f6bad..96168a1e87c1 100644 --- a/sound/soc/codecs/rt5651.h +++ b/sound/soc/codecs/rt5651.h @@ -138,6 +138,7 @@ /* Index of Codec Private Register definition */ #define RT5651_BIAS_CUR1 0x12 #define RT5651_BIAS_CUR3 0x14 +#define RT5651_BIAS_CUR4 0x15 #define RT5651_CLSD_INT_REG1 0x1c #define RT5651_CHPUMP_INT_REG1 0x24 #define RT5651_MAMP_INT_REG2 0x37 @@ -1966,6 +1967,15 @@ #define RT5651_D_GATE_EN_SFT 0
/* Codec Private Register definition */ + +/* MIC Over current threshold scale factor (0x15) */ +#define RT5651_MIC_OVCD_SF_MASK (0x3 << 8) +#define RT5651_MIC_OVCD_SF_SFT 8 +#define RT5651_MIC_OVCD_SF_0P5 (0x0 << 8) +#define RT5651_MIC_OVCD_SF_0P75 (0x1 << 8) +#define RT5651_MIC_OVCD_SF_1P0 (0x2 << 8) +#define RT5651_MIC_OVCD_SF_1P5 (0x3 << 8) + /* 3D Speaker Control (0x63) */ #define RT5651_3D_SPK_MASK (0x1 << 15) #define RT5651_3D_SPK_SFT 15 diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 8ef5b5500fb7..a6cc0bc85db8 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -49,11 +49,26 @@ enum { BYT_RT5651_JD2 = (RT5651_JD2 << 4), };
-#define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(3, 0)) -#define BYT_RT5651_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4) -#define BYT_RT5651_DMIC_EN BIT(16) -#define BYT_RT5651_MCLK_EN BIT(17) -#define BYT_RT5651_MCLK_25MHZ BIT(18) +enum { + BYT_RT5651_OVTH_600UA = (RT5651_OVTH_600UA << 8), + BYT_RT5651_OVTH_1500UA = (RT5651_OVTH_1500UA << 8), + BYT_RT5651_OVTH_2000UA = (RT5651_OVTH_2000UA << 8), +}; + +enum { + BYT_RT5651_OVCD_SF_0P5 = (RT5651_OVCD_SF_0P5 << 12), + BYT_RT5651_OVCD_SF_0P75 = (RT5651_OVCD_SF_0P75 << 12), + BYT_RT5651_OVCD_SF_1P0 = (RT5651_OVCD_SF_1P0 << 12), + BYT_RT5651_OVCD_SF_1P5 = (RT5651_OVCD_SF_1P5 << 12), +}; + +#define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(3, 0)) +#define BYT_RT5651_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4) +#define BYT_RT5651_OVTH(quirk) (((quirk) & GENMASK(11, 8)) >> 8) +#define BYT_RT5651_OVCD_SF(quirk) (((quirk) & GENMASK(15, 12)) >> 12) +#define BYT_RT5651_DMIC_EN BIT(16) +#define BYT_RT5651_MCLK_EN BIT(17) +#define BYT_RT5651_MCLK_25MHZ BIT(18)
struct byt_rt5651_private { struct clk *mclk; @@ -73,9 +88,14 @@ static void log_quirks(struct device *dev) dev_info(dev, "quirk IN2_MAP enabled"); if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN3_MAP) dev_info(dev, "quirk IN3_MAP enabled"); - if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) + if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) { dev_info(dev, "quirk jack-detect src %ld\n", BYT_RT5651_JDSRC(byt_rt5651_quirk)); + dev_info(dev, "quirk ovth_curr %ld\n", + BYT_RT5651_OVTH(byt_rt5651_quirk)); + dev_info(dev, "quirk ovth_sf %ld\n", + BYT_RT5651_OVCD_SF(byt_rt5651_quirk)); + } if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN) dev_info(dev, "quirk DMIC enabled"); if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) @@ -299,6 +319,8 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = { }, .driver_data = (void *)(BYT_RT5651_MCLK_EN | BYT_RT5651_JD1_1 | + BYT_RT5651_OVTH_2000UA | + BYT_RT5651_OVCD_SF_0P75 | BYT_RT5651_IN1_IN2_MAP), }, {} @@ -373,6 +395,8 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) }
pdata.jd_src = BYT_RT5651_JDSRC(byt_rt5651_quirk); + pdata.ovth_curr = BYT_RT5651_OVTH(byt_rt5651_quirk); + pdata.ovth_sf = BYT_RT5651_OVCD_SF(byt_rt5651_quirk); if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN) pdata.dmic_en = true; rt5651_set_pdata(codec, &pdata);