diff options
author | Denis 'GNUtoo' Carikli <GNUtoo@no-log.org> | 2013-05-18 19:52:20 +0200 |
---|---|---|
committer | Denis 'GNUtoo' Carikli <GNUtoo@no-log.org> | 2013-05-19 14:04:41 +0200 |
commit | 9fc1b4c67b8715d9612ef9a772adbd3d4e89b666 (patch) | |
tree | 18c4dff5c8e5f08996a1c0989fb37e5f3370d7e0 | |
parent | 7d7b608c38e15e2072d5fcc7e9af3315028a2763 (diff) | |
download | kernel_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/Kconfig | 9 | ||||
-rw-r--r-- | drivers/misc/Makefile | 1 | ||||
-rwxr-xr-x | drivers/misc/gta04_jack.c | 168 | ||||
-rwxr-xr-x | include/linux/gta04_jack.h | 35 |
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(>a04_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(>a04_jack_driver); +} + +static void __exit gta04_jack_exit(void) +{ + platform_driver_unregister(>a04_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 |