diff options
author | oder_chiou@realtek.com <oder_chiou@realtek.com> | 2018-02-05 11:29:56 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-02-12 10:31:26 +0100 |
commit | 041e74b71491acadad74b275e8b05add165d92b4 (patch) | |
tree | 0673de6d19eb63b72140ab44f1ccda72e0fea28f /sound/soc/codecs/rt5659.c | |
parent | Linux 4.16-rc1 (diff) | |
download | linux-041e74b71491acadad74b275e8b05add165d92b4.tar.xz linux-041e74b71491acadad74b275e8b05add165d92b4.zip |
ASoC: rt5659: Add the support of Intel HDA Header
The patch adds the support of Intel HDA Header.
Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/rt5659.c')
-rw-r--r-- | sound/soc/codecs/rt5659.c | 118 |
1 files changed, 114 insertions, 4 deletions
diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 07e7757417bc..dbc7dbfe8c6f 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -1461,6 +1461,61 @@ static void rt5659_jack_detect_work(struct work_struct *work) SND_JACK_BTN_2 | SND_JACK_BTN_3); } +static void rt5659_jack_detect_intel_hd_header(struct work_struct *work) +{ + struct rt5659_priv *rt5659 = + container_of(work, struct rt5659_priv, jack_detect_work.work); + unsigned int value; + bool hp_flag, mic_flag; + + if (!rt5659->hs_jack) + return; + + /* headphone jack */ + regmap_read(rt5659->regmap, RT5659_GPIO_STA, &value); + hp_flag = (!(value & 0x8)) ? true : false; + + if (hp_flag != rt5659->hda_hp_plugged) { + rt5659->hda_hp_plugged = hp_flag; + + if (hp_flag) { + regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_1, + 0x10, 0x0); + rt5659->jack_type |= SND_JACK_HEADPHONE; + } else { + regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_1, + 0x10, 0x10); + rt5659->jack_type = rt5659->jack_type & + (~SND_JACK_HEADPHONE); + } + + snd_soc_jack_report(rt5659->hs_jack, rt5659->jack_type, + SND_JACK_HEADPHONE); + } + + /* mic jack */ + regmap_read(rt5659->regmap, RT5659_4BTN_IL_CMD_1, &value); + regmap_write(rt5659->regmap, RT5659_4BTN_IL_CMD_1, value); + mic_flag = (value & 0x2000) ? true : false; + + if (mic_flag != rt5659->hda_mic_plugged) { + rt5659->hda_mic_plugged = mic_flag; + if (mic_flag) { + regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2, + 0x2, 0x2); + rt5659->jack_type |= SND_JACK_MICROPHONE; + } else { + regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2, + 0x2, 0x0); + rt5659->jack_type = rt5659->jack_type + & (~SND_JACK_MICROPHONE); + } + + snd_soc_jack_report(rt5659->hs_jack, rt5659->jack_type, + SND_JACK_MICROPHONE); + } +} + static const struct snd_kcontrol_new rt5659_snd_controls[] = { /* Speaker Output Volume */ SOC_DOUBLE_TLV("Speaker Playback Volume", RT5659_SPO_VOL, @@ -3990,6 +4045,54 @@ static void rt5659_calibrate(struct rt5659_priv *rt5659) regmap_write(rt5659->regmap, RT5659_HP_CHARGE_PUMP_1, 0x0c16); } +void rt5659_intel_hd_header_probe_setup(struct rt5659_priv *rt5659) +{ + int value; + + regmap_read(rt5659->regmap, RT5659_GPIO_STA, &value); + if (!(value & 0x8)) { + rt5659->hda_hp_plugged = true; + regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_1, + 0x10, 0x0); + } else { + regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_1, + 0x10, 0x10); + } + + regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_1, + RT5659_PWR_VREF2 | RT5659_PWR_MB, + RT5659_PWR_VREF2 | RT5659_PWR_MB); + msleep(20); + regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_1, + RT5659_PWR_FV2, RT5659_PWR_FV2); + + regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_3, RT5659_PWR_LDO2, + RT5659_PWR_LDO2); + regmap_update_bits(rt5659->regmap, RT5659_PWR_ANLG_2, RT5659_PWR_MB1, + RT5659_PWR_MB1); + regmap_update_bits(rt5659->regmap, RT5659_PWR_VOL, RT5659_PWR_MIC_DET, + RT5659_PWR_MIC_DET); + msleep(20); + + regmap_update_bits(rt5659->regmap, RT5659_4BTN_IL_CMD_2, + RT5659_4BTN_IL_MASK, RT5659_4BTN_IL_EN); + regmap_read(rt5659->regmap, RT5659_4BTN_IL_CMD_1, &value); + regmap_write(rt5659->regmap, RT5659_4BTN_IL_CMD_1, value); + regmap_read(rt5659->regmap, RT5659_4BTN_IL_CMD_1, &value); + + if (value & 0x2000) { + rt5659->hda_mic_plugged = true; + regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2, + 0x2, 0x2); + } else { + regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2, + 0x2, 0x0); + } + + regmap_update_bits(rt5659->regmap, RT5659_IRQ_CTRL_2, + RT5659_IL_IRQ_MASK, RT5659_IL_IRQ_EN); +} + static int rt5659_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -4174,16 +4277,23 @@ static int rt5659_i2c_probe(struct i2c_client *i2c, RT5659_PWR_MB, RT5659_PWR_MB); regmap_write(rt5659->regmap, RT5659_PWR_ANLG_2, 0x0001); regmap_write(rt5659->regmap, RT5659_IRQ_CTRL_2, 0x0040); + INIT_DELAYED_WORK(&rt5659->jack_detect_work, + rt5659_jack_detect_work); break; - case RT5659_JD_NULL: + case RT5659_JD_HDA_HEADER: + regmap_write(rt5659->regmap, RT5659_GPIO_CTRL_3, 0x8000); + regmap_write(rt5659->regmap, RT5659_RC_CLK_CTRL, 0x0900); + regmap_write(rt5659->regmap, RT5659_EJD_CTRL_1, 0x70c0); + regmap_write(rt5659->regmap, RT5659_JD_CTRL_1, 0x2000); + regmap_write(rt5659->regmap, RT5659_IRQ_CTRL_1, 0x0040); + INIT_DELAYED_WORK(&rt5659->jack_detect_work, + rt5659_jack_detect_intel_hd_header); + rt5659_intel_hd_header_probe_setup(rt5659); break; default: - dev_warn(&i2c->dev, "Currently, support JD3 only\n"); break; } - INIT_DELAYED_WORK(&rt5659->jack_detect_work, rt5659_jack_detect_work); - if (i2c->irq) { ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, rt5659_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |