@@ -15,6 +15,7 @@
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/tlv.h>
+#include <sound/jack.h>
/* Register 512 CPCAP_REG_VAUDIOC --- Audio Regulator and Bias Voltage
*/ #define CPCAP_BIT_AUDIO_LOW_PWR 6
@@ -252,8 +253,14 @@ enum cpcap_dai {
};
struct cpcap_audio {
+ struct device *dev;
struct snd_soc_component *component;
struct regmap *regmap;
+ struct snd_soc_jack *hp_jack;
+
+ struct delayed_work jack_detect_work;
+
+ int hp_irq;
u16 vendor;
@@ -603,6 +610,21 @@ static int cpcap_input_left_mux_put_enum(struct
snd_kcontrol *kcontrol, return 0;
}
+static struct snd_soc_jack_pin headset_jack_pins[] = {
+ {
+ .pin = "Headset Right Playback Route",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "Headset Left Playback Route",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "Headphones",
+ .mask = SND_JACK_HEADPHONE,
+ }
+};
+
static const struct snd_kcontrol_new cpcap_input_left_mux =
SOC_DAPM_ENUM_EXT("Input Left", cpcap_input_left_mux_enum,
cpcap_input_left_mux_get_enum,
@@ -1561,8 +1583,6 @@ static int cpcap_dai_mux(struct cpcap_audio
*cpcap, bool swap_dai_configuration) u16 voice_mask =
BIT(CPCAP_BIT_DIG_AUD_IN); int err;
-
-
if (!swap_dai_configuration) {
/* Codec on DAI0, HiFi on DAI1 */
voice_val = 0;
@@ -1586,6 +1606,44 @@ static int cpcap_dai_mux(struct cpcap_audio
*cpcap, bool swap_dai_configuration) return 0;
}
+static irqreturn_t cpcap_hp_irq_thread(int irq, void *arg)
+{
+ struct cpcap_audio *cpcap = arg;
+ int val = -1;
+ bool plugged;
+
+ regmap_read(cpcap->regmap, CPCAP_REG_INTS1, &val);
+ plugged = val & (1<<9);
+
+ if (!cpcap->component) {
+ dev_warn(cpcap->dev, "%s called before component is
ready.", __func__);
+ return IRQ_HANDLED;
+ }
+
+ if (!cpcap->hp_jack) {
+ dev_warn(cpcap->dev, "%s called before jack is
ready.", __func__);
+ return IRQ_HANDLED;
+ }
+
+ snd_soc_jack_report(cpcap->hp_jack, plugged ? 0 :
SND_JACK_HEADPHONE, SND_JACK_HEADPHONE); +
+ return IRQ_HANDLED;
+}
+
+static int cpcap_set_jack_detect(struct snd_soc_component *component,
+ struct snd_soc_jack *hp_jack, void *data)
+{
+ struct cpcap_audio *cpcap =
snd_soc_component_get_drvdata(component); +
+ if (!cpcap->hp_jack) {
+ dev_info(cpcap->dev, "registering jack");
+ cpcap->hp_jack = hp_jack;
+ snd_soc_jack_add_pins(hp_jack,
ARRAY_SIZE(headset_jack_pins), headset_jack_pins);
+ }
+
+ return 0;
+}
+