aboutsummaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/tlv320aic3x.c31
-rw-r--r--sound/soc/codecs/tlv320aic3x.h46
2 files changed, 74 insertions, 3 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 0f4067bdd4a..341e1adc916 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1018,14 +1018,41 @@ int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
}
EXPORT_SYMBOL_GPL(aic3x_get_gpio);
+void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
+ int headset_debounce, int button_debounce)
+{
+ u8 val;
+
+ val = ((detect & AIC3X_HEADSET_DETECT_MASK)
+ << AIC3X_HEADSET_DETECT_SHIFT) |
+ ((headset_debounce & AIC3X_HEADSET_DEBOUNCE_MASK)
+ << AIC3X_HEADSET_DEBOUNCE_SHIFT) |
+ ((button_debounce & AIC3X_BUTTON_DEBOUNCE_MASK)
+ << AIC3X_BUTTON_DEBOUNCE_SHIFT);
+
+ if (detect & AIC3X_HEADSET_DETECT_MASK)
+ val |= AIC3X_HEADSET_DETECT_ENABLED;
+
+ aic3x_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
+}
+EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
+
int aic3x_headset_detected(struct snd_soc_codec *codec)
{
u8 val;
- aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val);
- return (val >> 2) & 1;
+ aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
+ return (val >> 4) & 1;
}
EXPORT_SYMBOL_GPL(aic3x_headset_detected);
+int aic3x_button_pressed(struct snd_soc_codec *codec)
+{
+ u8 val;
+ aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
+ return (val >> 5) & 1;
+}
+EXPORT_SYMBOL_GPL(aic3x_button_pressed);
+
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 7e982acf399..73e35b6ec92 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -39,7 +39,9 @@
#define AIC3X_OVRF_STATUS_AND_PLLR_REG 11
/* Audio codec digital filter control register */
#define AIC3X_CODEC_DFILT_CTRL 12
-
+/* Headset/button press detection register */
+#define AIC3X_HEADSET_DETECT_CTRL_A 13
+#define AIC3X_HEADSET_DETECT_CTRL_B 14
/* ADC PGA Gain control registers */
#define LADC_VOL 15
#define RADC_VOL 16
@@ -233,7 +235,49 @@ enum {
void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
+
+/* headset detection / button API */
+
+/* The AIC3x supports detection of stereo headsets (GND + left + right signal)
+ * and cellular headsets (GND + speaker output + microphone input).
+ * It is recommended to enable MIC bias for this function to work properly.
+ * For more information, please refer to the datasheet. */
+enum {
+ AIC3X_HEADSET_DETECT_OFF = 0,
+ AIC3X_HEADSET_DETECT_STEREO = 1,
+ AIC3X_HEADSET_DETECT_CELLULAR = 2,
+ AIC3X_HEADSET_DETECT_BOTH = 3
+};
+
+enum {
+ AIC3X_HEADSET_DEBOUNCE_16MS = 0,
+ AIC3X_HEADSET_DEBOUNCE_32MS = 1,
+ AIC3X_HEADSET_DEBOUNCE_64MS = 2,
+ AIC3X_HEADSET_DEBOUNCE_128MS = 3,
+ AIC3X_HEADSET_DEBOUNCE_256MS = 4,
+ AIC3X_HEADSET_DEBOUNCE_512MS = 5
+};
+
+enum {
+ AIC3X_BUTTON_DEBOUNCE_0MS = 0,
+ AIC3X_BUTTON_DEBOUNCE_8MS = 1,
+ AIC3X_BUTTON_DEBOUNCE_16MS = 2,
+ AIC3X_BUTTON_DEBOUNCE_32MS = 3
+};
+
+#define AIC3X_HEADSET_DETECT_ENABLED 0x80
+#define AIC3X_HEADSET_DETECT_SHIFT 5
+#define AIC3X_HEADSET_DETECT_MASK 3
+#define AIC3X_HEADSET_DEBOUNCE_SHIFT 2
+#define AIC3X_HEADSET_DEBOUNCE_MASK 7
+#define AIC3X_BUTTON_DEBOUNCE_SHIFT 0
+#define AIC3X_BUTTON_DEBOUNCE_MASK 3
+
+/* see the enums above for valid parameters to this function */
+void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
+ int headset_debounce, int button_debounce);
int aic3x_headset_detected(struct snd_soc_codec *codec);
+int aic3x_button_pressed(struct snd_soc_codec *codec);
struct aic3x_setup_data {
int i2c_bus;