aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis 'GNUtoo' Carikli <GNUtoo@no-log.org>2013-05-18 19:52:20 +0200
committerDenis 'GNUtoo' Carikli <GNUtoo@no-log.org>2013-05-19 14:04:41 +0200
commit9fc1b4c67b8715d9612ef9a772adbd3d4e89b666 (patch)
tree18c4dff5c8e5f08996a1c0989fb37e5f3370d7e0
parent7d7b608c38e15e2072d5fcc7e9af3315028a2763 (diff)
downloadkernel_goldelico_gta04-9fc1b4c67b8715d9612ef9a772adbd3d4e89b666.zip
kernel_goldelico_gta04-9fc1b4c67b8715d9612ef9a772adbd3d4e89b666.tar.gz
kernel_goldelico_gta04-9fc1b4c67b8715d9612ef9a772adbd3d4e89b666.tar.bz2
Add Android ear jack driver based on the tuna SEC Jack driver.
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
-rw-r--r--drivers/misc/Kconfig9
-rw-r--r--drivers/misc/Makefile1
-rwxr-xr-xdrivers/misc/gta04_jack.c168
-rwxr-xr-xinclude/linux/gta04_jack.h35
4 files changed, 213 insertions, 0 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 051bfe9..5d2dd49 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -313,6 +313,15 @@ config SGI_GRU_DEBUG
This option enables addition debugging code for the SGI GRU driver. If
you are unsure, say N.
+config ANDROID_JACK
+ bool "Ear jack driver for Android devices"
+ depends on INPUT
+ default n
+ ---help---
+ This is an ear jack driver for Android devices.
+
+ If unsure, say N.
+
config APDS9802ALS
tristate "Medfield Avago APDS9802 ALS Sensor module"
depends on I2C
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 606b27f..36c106b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_SENSORS_BH1780) += bh1780gli.o
obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
+obj-$(CONFIG_ANDROID_JACK) += gta04_jack.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
diff --git a/drivers/misc/gta04_jack.c b/drivers/misc/gta04_jack.c
new file mode 100755
index 0000000..1c2d960
--- /dev/null
+++ b/drivers/misc/gta04_jack.c
@@ -0,0 +1,168 @@
+/* drivers/misc/gta04_jack.c
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/module.h>
+#include <linux/gta04_jack.h>
+#include <linux/switch.h>
+#include <linux/i2c/twl4030-madc.h>
+#include <linux/gta04_jack.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+
+/* with some modifications like moving all the gpio structs inside
+ * the platform data and getting the name for the switch and
+ * gpio_event from the platform data, the driver could support more than
+ * one headset jack, but currently user space is looking only for
+ * one key file and switch for a headset so it'd be overkill and
+ * untestable so we limit to one instantiation for now.
+ */
+static atomic_t instantiated = ATOMIC_INIT(0);
+static int jack_present;
+struct input_handler gta04_jack_input_handler;
+struct delayed_work jack_work;
+
+/* sysfs name HeadsetObserver.java looks for to track headset state
+ */
+struct switch_dev switch_jack_detection = {
+ .name = "h2w",
+};
+
+static void gta04_audio_jack_work(struct work_struct *work)
+{
+ long val;
+ long delay = msecs_to_jiffies(500);
+ int jackbits = 0;
+
+ /* choose delay *before* checking presence so we still get
+ * one long delay on first insertion to help with debounce.
+ */
+ if (jack_present)
+ delay = msecs_to_jiffies(50);
+
+ val = twl4030_get_madc_conversion(7);
+ printk("[%s] twl4030_get_madc_conversion's val = %d\n",__func__, val);
+ if (val < 0)
+ goto out;
+ /* On my device:
+ * open circuit = around 20
+ * short circuit = around 800
+ * microphone = around 830-840 !!!
+ */
+ if (val < 100) {
+ /* open circuit */
+ jackbits = SEC_JACK_NO_DEVICE;
+ jack_present = 0;
+ /* debounce */
+ delay = msecs_to_jiffies(500);
+ } else if (val < 820) {
+ /* short */
+ if (jack_present == 0) {
+ /* Inserted headset with no mic */
+ jack_present = SEC_HEADSET_3POLE;
+ jackbits = jack_present;
+ } else if (jack_present & SEC_HEADSET_4POLE) {
+ /* mic shorter == button press */
+ /* TODO: jackbits = ? ; */
+#if 0
+ input_report_key(hi->input_dev, btn_zones[i].code, 1);
+ input_sync(hi->input_dev);
+#endif
+ } else {
+ /* headphones still present */
+ jackbits = jack_present;
+ }
+ } else {
+ /* There is a microphone there */
+ jack_present = SEC_HEADSET_4POLE;
+ jackbits = jack_present;
+ }
+#if 0
+ snd_soc_jack_report(&jack.hs_jack, jackbits,
+ SND_JACK_HEADSET | SND_JACK_BTN_0);
+#endif
+
+ switch_set_state(&switch_jack_detection, jackbits);
+
+out:
+ schedule_delayed_work(&jack_work, delay);
+}
+
+static int gta04_jack_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ printk("%s: PROBE\n", __func__);
+
+ if (atomic_xchg(&instantiated, 1)) {
+ pr_err("%s : already instantiated, can only have one\n",
+ __func__);
+ return -ENODEV;
+ }
+#if 0 //TODO
+ gta04_jack_input_handler.filter = sec_jack_buttons_filter;
+ gta04_jack_input_handler.connect = sec_jack_buttons_connect;
+ gta04_jack_input_handler.disconnect = sec_jack_buttons_disconnect;
+ gta04_jack_input_handler.name = "sec_jack_buttons";
+ gta04_jack_input_handler.id_table = &hi->ids;
+ gta04_jack_input_handler.private = hi;
+
+ ret = input_register_handler(&gta04_jack_input_handler);
+ if (ret) {
+ pr_err("%s : Failed to register_handler\n", __func__);
+ return ret;
+ }
+#endif
+ INIT_DELAYED_WORK(&jack_work, gta04_audio_jack_work);
+
+ schedule_delayed_work(&jack_work, msecs_to_jiffies(100));
+
+ ret = switch_dev_register(&switch_jack_detection);
+
+ printk("%s: PROBE DONE with ret=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int gta04_jack_remove(struct platform_device *pdev)
+{
+
+ atomic_set(&instantiated, 0);
+
+ return 0;
+}
+
+static struct platform_driver gta04_jack_driver = {
+ .probe = gta04_jack_probe,
+ .remove = gta04_jack_remove,
+ .driver = {
+ .name = "gta04_jack",
+ .owner = THIS_MODULE,
+ },
+};
+static int __init gta04_jack_init(void)
+{
+ return platform_driver_register(&gta04_jack_driver);
+}
+
+static void __exit gta04_jack_exit(void)
+{
+ platform_driver_unregister(&gta04_jack_driver);
+}
+
+module_init(gta04_jack_init);
+module_exit(gta04_jack_exit);
+
+MODULE_AUTHOR("GNUtoo@no-log.org");
+MODULE_DESCRIPTION("GTA04 Ear-Jack detection driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/gta04_jack.h b/include/linux/gta04_jack.h
new file mode 100755
index 0000000..89a0d84
--- /dev/null
+++ b/include/linux/gta04_jack.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 Samsung Electronics, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM_ARCH_GTA04_HEADSET_H
+#define __ASM_ARCH_GTA04_HEADSET_H
+
+#ifdef __KERNEL__
+
+enum {
+ SEC_JACK_NO_DEVICE = 0x0,
+ SEC_HEADSET_4POLE = 0x01 << 0,
+ SEC_HEADSET_3POLE = 0x01 << 1,
+ SEC_TTY_DEVICE = 0x01 << 2,
+ SEC_FM_HEADSET = 0x01 << 3,
+ SEC_FM_SPEAKER = 0x01 << 4,
+ SEC_TVOUT_DEVICE = 0x01 << 5,
+ SEC_EXTRA_DOCK_SPEAKER = 0x01 << 6,
+ SEC_EXTRA_CAR_DOCK_SPEAKER = 0x01 << 7,
+ SEC_UNKNOWN_DEVICE = 0x01 << 8,
+};
+
+#endif
+
+#endif