summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristoffer KARLSSON <kristoffer.karlsson@stericsson.com>2011-12-16 14:55:33 +0100
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:03:38 +0200
commit22f6fcb4ace2e99058078a8d5e2c1db3a29eac4d (patch)
tree94774cfd537fc052dada39132a6b36c395fc7048
parentb0fe67b7a7cd0645c43bbca20ea31c8db049db8f (diff)
input: ab8500-accdet: Add unsupported hs detection
This patch adds support for detection of headsets with gnd and mic pins switched. ST-Ericsson Linux next: NA ST-Ericsson ID: 361921 ST-Ericsson FOSS-OUT ID: Trivial Depends-On: I01171aa4ce57a25237986cdf2f0ca4e01660fb28 Change-Id: I1e20586940121f4d7da5b3e8b6e132527303076d Signed-off-by: Kristoffer KARLSSON <kristoffer.karlsson@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42939 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
-rw-r--r--arch/arm/mach-ux500/include/mach/abx500-accdet.h8
-rw-r--r--drivers/input/misc/ab5500-accdet.c9
-rw-r--r--drivers/input/misc/ab8500-accdet.c46
-rw-r--r--drivers/input/misc/abx500-accdet.c81
4 files changed, 133 insertions, 11 deletions
diff --git a/arch/arm/mach-ux500/include/mach/abx500-accdet.h b/arch/arm/mach-ux500/include/mach/abx500-accdet.h
index 04082b824ae..cdd78cd7d0c 100644
--- a/arch/arm/mach-ux500/include/mach/abx500-accdet.h
+++ b/arch/arm/mach-ux500/include/mach/abx500-accdet.h
@@ -119,6 +119,7 @@ struct abx500_accdet_platform_data {
* detect the actual type. In this mode, possible button events are reported.
* @JACK_TYPE_HEADPHONE Headphone type of accessory (spkrs only) connected
* @JACK_TYPE_HEADSET Headset type of accessory (mic+spkrs) connected
+ * @JACK_TYPE_UNSUPPORTED_HEADSET Unsupported headset of type accessory connected
* @JACK_TYPE_CARKIT Carkit type of accessory connected
* @JACK_TYPE_OPENCABLE Open cable connected
* @JACK_TYPE_CVIDEO CVideo type of accessory connected.
@@ -129,6 +130,7 @@ enum accessory_jack_type {
JACK_TYPE_CONNECTED,
JACK_TYPE_HEADPHONE,
JACK_TYPE_HEADSET,
+ JACK_TYPE_UNSUPPORTED_HEADSET,
JACK_TYPE_CARKIT,
JACK_TYPE_OPENCABLE,
JACK_TYPE_CVIDEO
@@ -225,6 +227,8 @@ struct accessory_regu_descriptor {
* making the decision or can cached voltage be used instead.
* @minvol minimum voltage (mV) for decision
* @maxvol maximum voltage (mV) for decision
+ * @alt_minvol minimum alternative voltage (mV) for decision
+ * @alt_maxvol maximum alternative voltage (mV) for decision
*/
struct accessory_detect_task {
const char *typename;
@@ -233,6 +237,8 @@ struct accessory_detect_task {
int meas_mv;
int minvol;
int maxvol;
+ int alt_minvol;
+ int alt_maxvol;
};
/**
@@ -271,6 +277,7 @@ struct accessory_detect_task {
* @config_accdetect1_hw: Callback for configuring accdet1 comparator.
* @detect_plugged_in: Callback to detect type of accessory connected.
* @meas_voltage_stable: Callback to read present accdet voltage.
+ * @meas_alt_voltage_stable: Callback to read present alt accdet voltage.
* @config_hw_test_basic_carkit: Callback to configure hw for carkit
* detect.
* @turn_of_accdet_comparator: Call back to turn off comparators.
@@ -319,6 +326,7 @@ struct abx500_ad {
void (*config_accdetect1_hw)(struct abx500_ad *, int);
int (*detect_plugged_in)(struct abx500_ad *);
int (*meas_voltage_stable)(struct abx500_ad *);
+ int (*meas_alt_voltage_stable)(struct abx500_ad *);
void (*config_hw_test_basic_carkit)(struct abx500_ad *, int);
void (*turn_off_accdet_comparator)(struct platform_device *pdev);
void (*turn_on_accdet_comparator)(struct platform_device *pdev);
diff --git a/drivers/input/misc/ab5500-accdet.c b/drivers/input/misc/ab5500-accdet.c
index 828ff29cb1e..280af8ac8be 100644
--- a/drivers/input/misc/ab5500-accdet.c
+++ b/drivers/input/misc/ab5500-accdet.c
@@ -187,6 +187,14 @@ static int ab5500_meas_voltage_stable(struct abx500_ad *dd)
}
/*
+ * not implemented
+ */
+static int ab5500_meas_alt_voltage_stable(struct abx500_ad *dd)
+{
+ return -1;
+}
+
+/*
* configures HW so that it is possible to make decision whether
* accessory is connected or not.
*/
@@ -262,6 +270,7 @@ struct abx500_ad ab5500_accessory_det_callbacks = {
.config_accdetect1_hw = ab5500_config_accdetect1_hw,
.detect_plugged_in = ab5500_detect_plugged_in,
.meas_voltage_stable = ab5500_meas_voltage_stable,
+ .meas_alt_voltage_stable = ab5500_meas_alt_voltage_stable,
.config_hw_test_basic_carkit = ab5500_config_hw_test_basic_carkit,
.turn_off_accdet_comparator = ab5500_turn_off_accdet_comparator,
.turn_on_accdet_comparator = ab5500_turn_on_accdet_comparator,
diff --git a/drivers/input/misc/ab8500-accdet.c b/drivers/input/misc/ab8500-accdet.c
index 2d9c740bc17..0fe60364d54 100644
--- a/drivers/input/misc/ab8500-accdet.c
+++ b/drivers/input/misc/ab8500-accdet.c
@@ -21,6 +21,9 @@
#include <linux/gpio.h>
#include <linux/err.h>
#include <mach/abx500-accdet.h>
+#ifdef CONFIG_SND_SOC_UX500_AB8500
+#include <sound/ux500_ab8500_ext.h>
+#endif
#define MAX_DET_COUNT 10
#define MAX_VOLT_DIFF 30
@@ -228,8 +231,38 @@ static int ab8500_detect_plugged_in(struct abx500_ad *dd)
return value & BIT_ITSOURCE5_ACCDET1 ? 0 : 1;
}
+#ifdef CONFIG_SND_SOC_UX500_AB8500
+
/*
- * mic_line_voltage_stable - measures a relative stable voltage from spec. input
+ * meas_voltage_stable - measures relative stable voltage from spec. input
+ */
+static int ab8500_meas_voltage_stable(struct abx500_ad *dd)
+{
+ int ret, mv;
+
+ ret = ux500_ab8500_audio_gpadc_measure((struct ab8500_gpadc *)dd->gpadc,
+ ACC_DETECT2, false, &mv);
+
+ return (ret < 0) ? ret : mv;
+}
+
+/*
+ * meas_alt_voltage_stable - measures relative stable voltage from spec. input
+ */
+static int ab8500_meas_alt_voltage_stable(struct abx500_ad *dd)
+{
+ int ret, mv;
+
+ ret = ux500_ab8500_audio_gpadc_measure((struct ab8500_gpadc *)dd->gpadc,
+ ACC_DETECT2, true, &mv);
+
+ return (ret < 0) ? ret : mv;
+}
+
+#else
+
+/*
+ * meas_voltage_stable - measures relative stable voltage from spec. input
*/
static int ab8500_meas_voltage_stable(struct abx500_ad *dd)
{
@@ -251,6 +284,16 @@ static int ab8500_meas_voltage_stable(struct abx500_ad *dd)
}
/*
+ * not implemented for non soc setups
+ */
+static int ab8500_meas_alt_voltage_stable(struct abx500_ad *dd)
+{
+ return -1;
+}
+
+#endif
+
+/*
* configures HW so that it is possible to make decision whether
* accessory is connected or not.
*/
@@ -392,6 +435,7 @@ struct abx500_ad ab8500_accessory_det_callbacks = {
.config_accdetect1_hw = ab8500_config_accdetect1_hw,
.detect_plugged_in = ab8500_detect_plugged_in,
.meas_voltage_stable = ab8500_meas_voltage_stable,
+ .meas_alt_voltage_stable = ab8500_meas_alt_voltage_stable,
.config_hw_test_basic_carkit = ab8500_config_hw_test_basic_carkit,
.turn_off_accdet_comparator = ab8500_turn_off_accdet_comparator,
.turn_on_accdet_comparator = ab8500_turn_on_accdet_comparator,
diff --git a/drivers/input/misc/abx500-accdet.c b/drivers/input/misc/abx500-accdet.c
index 92aa69d1176..d716a1d8870 100644
--- a/drivers/input/misc/abx500-accdet.c
+++ b/drivers/input/misc/abx500-accdet.c
@@ -49,6 +49,10 @@
#define ACCESSORY_DET_VOL_DONTCARE -1
#define ACCESSORY_HEADPHONE_DET_VOL_MIN 0
#define ACCESSORY_HEADPHONE_DET_VOL_MAX 40
+#define ACCESSORY_U_HEADSET_DET_VOL_MIN 47
+#define ACCESSORY_U_HEADSET_DET_VOL_MAX 732
+#define ACCESSORY_U_HEADSET_ALT_DET_VOL_MIN 25
+#define ACCESSORY_U_HEADSET_ALT_DET_VOL_MAX 50
#define ACCESSORY_CVIDEO_DET_VOL_MIN 41
#define ACCESSORY_CVIDEO_DET_VOL_MAX 105
#define ACCESSORY_CARKIT_DET_VOL_MIN 1100
@@ -87,7 +91,9 @@ static struct accessory_detect_task detect_ops[] = {
.meas_mv = 1,
.req_det_count = 1,
.minvol = ACCESSORY_DET_VOL_DONTCARE,
- .maxvol = ACCESSORY_DET_VOL_DONTCARE
+ .maxvol = ACCESSORY_DET_VOL_DONTCARE,
+ .alt_minvol = ACCESSORY_DET_VOL_DONTCARE,
+ .alt_maxvol = ACCESSORY_DET_VOL_DONTCARE
},
{
.type = JACK_TYPE_HEADPHONE,
@@ -95,7 +101,19 @@ static struct accessory_detect_task detect_ops[] = {
.meas_mv = 1,
.req_det_count = 1,
.minvol = ACCESSORY_HEADPHONE_DET_VOL_MIN,
- .maxvol = ACCESSORY_HEADPHONE_DET_VOL_MAX
+ .maxvol = ACCESSORY_HEADPHONE_DET_VOL_MAX,
+ .alt_minvol = ACCESSORY_DET_VOL_DONTCARE,
+ .alt_maxvol = ACCESSORY_DET_VOL_DONTCARE
+ },
+ {
+ .type = JACK_TYPE_UNSUPPORTED_HEADSET,
+ .typename = "UNSUPPORTED HEADSET",
+ .meas_mv = 1,
+ .req_det_count = 2,
+ .minvol = ACCESSORY_U_HEADSET_DET_VOL_MIN,
+ .maxvol = ACCESSORY_U_HEADSET_DET_VOL_MAX,
+ .alt_minvol = ACCESSORY_U_HEADSET_ALT_DET_VOL_MIN,
+ .alt_maxvol = ACCESSORY_U_HEADSET_ALT_DET_VOL_MAX
},
{
.type = JACK_TYPE_CVIDEO,
@@ -103,7 +121,9 @@ static struct accessory_detect_task detect_ops[] = {
.meas_mv = 0,
.req_det_count = 4,
.minvol = ACCESSORY_CVIDEO_DET_VOL_MIN,
- .maxvol = ACCESSORY_CVIDEO_DET_VOL_MAX
+ .maxvol = ACCESSORY_CVIDEO_DET_VOL_MAX,
+ .alt_minvol = ACCESSORY_DET_VOL_DONTCARE,
+ .alt_maxvol = ACCESSORY_DET_VOL_DONTCARE
},
{
.type = JACK_TYPE_OPENCABLE,
@@ -111,7 +131,9 @@ static struct accessory_detect_task detect_ops[] = {
.meas_mv = 0,
.req_det_count = 4,
.minvol = ACCESSORY_OPENCABLE_DET_VOL_MIN,
- .maxvol = ACCESSORY_OPENCABLE_DET_VOL_MAX
+ .maxvol = ACCESSORY_OPENCABLE_DET_VOL_MAX,
+ .alt_minvol = ACCESSORY_DET_VOL_DONTCARE,
+ .alt_maxvol = ACCESSORY_DET_VOL_DONTCARE
},
{
.type = JACK_TYPE_CARKIT,
@@ -119,7 +141,9 @@ static struct accessory_detect_task detect_ops[] = {
.meas_mv = 1,
.req_det_count = 1,
.minvol = ACCESSORY_CARKIT_DET_VOL_MIN,
- .maxvol = ACCESSORY_CARKIT_DET_VOL_MAX
+ .maxvol = ACCESSORY_CARKIT_DET_VOL_MAX,
+ .alt_minvol = ACCESSORY_DET_VOL_DONTCARE,
+ .alt_maxvol = ACCESSORY_DET_VOL_DONTCARE
},
{
.type = JACK_TYPE_HEADSET,
@@ -127,7 +151,9 @@ static struct accessory_detect_task detect_ops[] = {
.meas_mv = 0,
.req_det_count = 2,
.minvol = ACCESSORY_HEADSET_DET_VOL_MIN,
- .maxvol = ACCESSORY_HEADSET_DET_VOL_MAX
+ .maxvol = ACCESSORY_HEADSET_DET_VOL_MAX,
+ .alt_minvol = ACCESSORY_DET_VOL_DONTCARE,
+ .alt_maxvol = ACCESSORY_DET_VOL_DONTCARE
},
{
.type = JACK_TYPE_CONNECTED,
@@ -135,7 +161,9 @@ static struct accessory_detect_task detect_ops[] = {
.meas_mv = 0,
.req_det_count = 4,
.minvol = ACCESSORY_DET_VOL_DONTCARE,
- .maxvol = ACCESSORY_DET_VOL_DONTCARE
+ .maxvol = ACCESSORY_DET_VOL_DONTCARE,
+ .alt_minvol = ACCESSORY_DET_VOL_DONTCARE,
+ .alt_maxvol = ACCESSORY_DET_VOL_DONTCARE
}
};
@@ -288,6 +316,10 @@ void report_jack_status(struct abx500_ad *dd)
dev_info(&dd->pdev->dev, "Accessory: %s\n",
accessory_str(dd->jack_type));
+ /* Never report unsupported headset */
+ if (dd->jack_type == JACK_TYPE_UNSUPPORTED_HEADSET)
+ goto out;
+
if (dd->jack_type != JACK_TYPE_DISCONNECTED &&
dd->jack_type != JACK_TYPE_UNSPECIFIED)
value |= SND_JACK_MECHANICAL;
@@ -488,14 +520,28 @@ irqreturn_t button_release_irq_handler(int irq, void *_userdata)
* voltage might be re-measured or previously measured voltage is reused.
*/
static int mic_vol_in_range(struct abx500_ad *dd,
- int lo, int hi, int force_read)
+ int lo, int hi, int alt_lo, int alt_hi, int force_read)
{
static int mv = MIN_MIC_POWER;
+ static int alt_mv = MIN_MIC_POWER;
- if (mv == -100 || force_read)
+ if (mv == MIN_MIC_POWER || force_read)
mv = dd->meas_voltage_stable(dd);
- return (mv >= lo && mv <= hi) ? 1 : 0;
+ if (mv < lo || mv > hi)
+ return 0;
+
+ if (ACCESSORY_DET_VOL_DONTCARE == alt_lo &&
+ ACCESSORY_DET_VOL_DONTCARE == alt_hi)
+ return 1;
+
+ if (alt_mv == MIN_MIC_POWER || force_read)
+ alt_mv = dd->meas_alt_voltage_stable(dd);
+
+ if (alt_mv < alt_lo || alt_mv > alt_hi)
+ return 0;
+
+ return 1;
}
/*
@@ -519,10 +565,13 @@ static int detect_hw(struct abx500_ad *dd,
case JACK_TYPE_HEADPHONE:
case JACK_TYPE_CVIDEO:
case JACK_TYPE_HEADSET:
+ case JACK_TYPE_UNSUPPORTED_HEADSET:
case JACK_TYPE_OPENCABLE:
status = mic_vol_in_range(dd,
task->minvol,
task->maxvol,
+ task->alt_minvol,
+ task->alt_maxvol,
task->meas_mv);
break;
default:
@@ -675,6 +724,18 @@ static void config_accdetect(struct abx500_ad *dd)
release_irq(dd, BUTTON_RELEASE_IRQ);
break;
+ case JACK_TYPE_UNSUPPORTED_HEADSET:
+ dd->config_accdetect1_hw(dd, 1);
+ dd->config_accdetect2_hw(dd, 1);
+
+ release_irq(dd, PLUG_IRQ);
+ claim_irq(dd, UNPLUG_IRQ);
+ release_irq(dd, BUTTON_PRESS_IRQ);
+ release_irq(dd, BUTTON_RELEASE_IRQ);
+ if (dd->set_av_switch)
+ dd->set_av_switch(dd, NOT_SET);
+ break;
+
case JACK_TYPE_CONNECTED:
case JACK_TYPE_HEADSET:
case JACK_TYPE_CARKIT: