summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/rt5659.c
diff options
context:
space:
mode:
authoroder_chiou@realtek.com <oder_chiou@realtek.com>2018-02-05 11:29:56 +0100
committerMark Brown <broonie@kernel.org>2018-02-12 10:31:26 +0100
commit041e74b71491acadad74b275e8b05add165d92b4 (patch)
tree0673de6d19eb63b72140ab44f1ccda72e0fea28f /sound/soc/codecs/rt5659.c
parentLinux 4.16-rc1 (diff)
downloadlinux-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.c118
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