Misc: import Jack Monitoring Interface from samsung
authorvivian, zhang <vivian.zhang@intel.com>
Thu, 13 Jun 2013 01:45:28 +0000 (09:45 +0800)
committerYin Kangkai <kangkai.yin@linux.intel.com>
Thu, 26 Dec 2013 14:33:48 +0000 (22:33 +0800)
Jack monitor framework monitors jack events (e.g. earjack, usb) and then
export through /sys.

Both sound and usb driver has some dependency on this framework.

(FIXME: we should isolate this jack monitor framework, independent of sound or
usb patches)

For the sound driver, it is used to set jack status: earjack_online,
earkey_online; these status are required for earjack type detecting in
avsystem project.

Signed-off-by: Vivian Zhang <vivian.zhang@intel.com>
Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
[Port to support CTP platform, and add FIXME]
Signed-off-by: Yin Kangkai <kangkai.yin@intel.com>
arch/x86/configs/i386_tizen_defconfig
arch/x86/platform/intel-mid/device_libs/platform_ctp_audio.c
arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/jack.c [new file with mode: 0644]
include/linux/jack.h [new file with mode: 0644]

index d499cc3..038d051 100644 (file)
@@ -1034,6 +1034,7 @@ CONFIG_UID_STAT=y
 CONFIG_MID_I2S_DEV=m
 CONFIG_A1026=y
 CONFIG_EMMC_IPANIC=y
+CONFIG_JACK_MON=y
 CONFIG_SCU_LOGGING=y
 CONFIG_UUID=y
 CONFIG_ZTE_PROP_BRIDGE=y
index 1a5641f..2d7e256 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/sfi.h>
 #include <linux/platform_device.h>
+#include <linux/jack.h>
 #include <asm/intel-mid.h>
 #include <asm/intel_mid_remoteproc.h>
 #include <asm/platform_sst_audio.h>
@@ -27,6 +28,19 @@ static struct ctp_audio_platform_data ctp_audio_pdata = {
        .spid = &spid,
 };
 
+#ifdef CONFIG_JACK_MON
+static struct jack_platform_data jack_data = {
+       .usb_online             = -1,
+       .charger_online         = -1,
+       .hdmi_online            = -1,
+       .earjack_online         = 0,
+       .earkey_online          = 0,
+       .ums_online             = -1,
+       .cdrom_online           = -1,
+       .jig_online             = -1,
+};
+#endif
+
 void *ctp_audio_platform_data(void *info)
 {
        struct platform_device *pdev;
@@ -39,6 +53,28 @@ void *ctp_audio_platform_data(void *info)
        if (ret < 0)
                return NULL;
 
+#ifdef CONFIG_JACK_MON
+       pdev = platform_device_alloc("jack", -1);
+       if (!pdev) {
+               pr_err("failed to allocate jack platform device\n");
+               return NULL;
+       }
+
+       ret = platform_device_add_data(pdev, &jack_data, sizeof(jack_data));
+       if (ret) {
+               pr_err("failed to add platform data to jack platform device\n");
+               platform_device_put(pdev);
+               return NULL;
+       }
+
+       ret = platform_device_add(pdev);
+       if (ret) {
+               pr_err("failed to add jack platform device\n");
+               platform_device_put(pdev);
+               return NULL;
+       }
+#endif
+
        pdev = platform_device_alloc("compress-sst", -1);
        if (!pdev) {
                pr_err("failed to allocate compress-sst platform device\n");
index 58b1189..0c0f304 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/sfi.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/intel_msic.h>
+#include <linux/jack.h>
 #include <asm/platform_sst_audio.h>
 #include <asm/intel-mid.h>
 #include <asm/intel_mid_remoteproc.h>
@@ -41,6 +42,19 @@ static struct msic_audio_platform_data msic_audio_pdata = {
        .spid = &spid,
 };
 
+#ifdef CONFIG_JACK_MON
+static struct jack_platform_data jack_data = {
+       .usb_online             = -1,
+       .charger_online         = -1,
+       .hdmi_online            = -1,
+       .earjack_online         = 0,
+       .earkey_online          = 0,
+       .ums_online             = -1,
+       .cdrom_online           = -1,
+       .jig_online             = -1,
+};
+#endif
+
 void *msic_audio_platform_data(void *info)
 {
        int i;
@@ -51,6 +65,26 @@ void *msic_audio_platform_data(void *info)
        if (add_sst_platform_device() < 0)
                return NULL;
 
+#ifdef CONFIG_JACK_MON
+       pdev = platform_device_alloc("jack", -1);
+       if (!pdev) {
+               pr_err("failed to allocate jack platform device\n");
+               return NULL;
+       }
+
+       if (platform_device_add_data(pdev, &jack_data, sizeof(jack_data))) {
+               pr_err("failed to add platform data to jack platform device\n");
+               platform_device_put(pdev);
+               return NULL;
+       }
+
+       if (platform_device_add(pdev)) {
+               pr_err("failed to add jack platform device\n");
+               platform_device_put(pdev);
+               return NULL;
+       }
+#endif
+
        pdev = platform_device_alloc("hdmi-audio", -1);
        if (!pdev) {
                pr_err("failed to allocate hdmi-audio platform device\n");
index d734d34..d200943 100644 (file)
@@ -558,6 +558,12 @@ config EMMC_IPANIC
         Driver which handles kernel panics and attempts to write
         critical debugging data to EMMC.
 
+config JACK_MON
+       tristate "Jacks Monitoring Driver"
+       default m
+       help
+         Jacks Monitoring Driver
+
 config SCU_LOGGING
        tristate "Intel SCU fabric debug driver"
        default n
index d7ac066..9d8bc6b 100644 (file)
@@ -43,6 +43,7 @@ obj-y                         += cb710/
 obj-$(CONFIG_SPEAR13XX_PCIE_GADGET)    += spear13xx_pcie_gadget.o
 obj-$(CONFIG_VMWARE_BALLOON)   += vmw_balloon.o
 obj-$(CONFIG_ARM_CHARLCD)      += arm-charlcd.o
+obj-$(CONFIG_JACK_MON)         += jack.o
 obj-$(CONFIG_PCH_PHUB)         += pch_phub.o
 obj-y                          += ti-st/
 obj-$(CONFIG_BCM_BT_LPM)       += bcm-lpm/
diff --git a/drivers/misc/jack.c b/drivers/misc/jack.c
new file mode 100644 (file)
index 0000000..08a5636
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *  Jack Monitoring Interface
+ *
+ *  Copyright (C) 2009 Samsung Electronics
+ *  Minkyu Kang <mk7.kang@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/jack.h>
+#include <linux/slab.h>
+
+struct jack_data {
+       struct jack_platform_data       *pdata;
+};
+
+static struct platform_device *jack_dev;
+
+static void jack_set_data(struct jack_platform_data *pdata,
+               const char *name, int value)
+{
+       if (!strcmp(name, "usb"))
+               pdata->usb_online = value;
+       else if (!strcmp(name, "charger"))
+               pdata->charger_online = value;
+       else if (!strcmp(name, "hdmi"))
+               pdata->hdmi_online = value;
+       else if (!strcmp(name, "earjack"))
+               pdata->earjack_online = value;
+       else if (!strcmp(name, "earkey"))
+               pdata->earkey_online = value;
+       else if (!strcmp(name, "ums"))
+               pdata->ums_online = value;
+       else if (!strcmp(name, "cdrom"))
+               pdata->cdrom_online = value;
+       else if (!strcmp(name, "jig"))
+               pdata->jig_online = value;
+       else if (!strcmp(name, "host"))
+               pdata->host_online = value;
+}
+
+int jack_get_data(const char *name)
+{
+       struct jack_data *jack = platform_get_drvdata(jack_dev);
+
+       if (!strcmp(name, "usb"))
+               return jack->pdata->usb_online;
+       else if (!strcmp(name, "charger"))
+               return jack->pdata->charger_online;
+       else if (!strcmp(name, "hdmi"))
+               return jack->pdata->hdmi_online;
+       else if (!strcmp(name, "earjack"))
+               return jack->pdata->earjack_online;
+       else if (!strcmp(name, "earkey"))
+               return jack->pdata->earkey_online;
+       else if (!strcmp(name, "ums"))
+               return jack->pdata->ums_online;
+       else if (!strcmp(name, "cdrom"))
+               return jack->pdata->cdrom_online;
+       else if (!strcmp(name, "jig"))
+               return jack->pdata->jig_online;
+       else if (!strcmp(name, "host"))
+               return jack->pdata->host_online;
+
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(jack_get_data);
+
+void jack_event_handler(const char *name, int value)
+{
+       if (jack_dev) {
+               struct jack_data *jack = platform_get_drvdata(jack_dev);
+               char env_str[16];
+               char *envp[] = { env_str, NULL };
+
+               jack_set_data(jack->pdata, name, value);
+
+               sprintf(env_str, "CHGDET=%s", name);
+               dev_info(&jack_dev->dev, "jack event %s\n", env_str);
+               kobject_uevent_env(&jack_dev->dev.kobj, KOBJ_CHANGE, envp);
+       } else
+               printk(KERN_ERR "failed to set jack event\n");
+}
+EXPORT_SYMBOL_GPL(jack_event_handler);
+
+#define JACK_OUTPUT(name)                                              \
+static ssize_t jack_show_##name(struct device *dev,                    \
+               struct device_attribute *attr, char *buf)               \
+{                                                                      \
+       struct jack_data *chip = dev_get_drvdata(dev);                  \
+       return sprintf(buf, "%d\n", chip->pdata->name);                 \
+}                                                                      \
+static DEVICE_ATTR(name, S_IRUGO, jack_show_##name, NULL);
+
+JACK_OUTPUT(usb_online);
+JACK_OUTPUT(charger_online);
+JACK_OUTPUT(hdmi_online);
+JACK_OUTPUT(earjack_online);
+JACK_OUTPUT(earkey_online);
+JACK_OUTPUT(jig_online);
+JACK_OUTPUT(host_online);
+
+static int jack_device_init(struct jack_data *jack)
+{
+       struct jack_platform_data *pdata = jack->pdata;
+       int ret;
+
+       if (pdata->usb_online != -1)
+               ret = device_create_file(&jack_dev->dev,
+                               &dev_attr_usb_online);
+       if (pdata->charger_online != -1)
+               ret = device_create_file(&jack_dev->dev,
+                               &dev_attr_charger_online);
+       if (pdata->hdmi_online != -1)
+               ret = device_create_file(&jack_dev->dev,
+                               &dev_attr_hdmi_online);
+       if (pdata->earjack_online != -1)
+               ret = device_create_file(&jack_dev->dev,
+                               &dev_attr_earjack_online);
+       if (pdata->earkey_online != -1)
+               ret = device_create_file(&jack_dev->dev,
+                               &dev_attr_earkey_online);
+       if (pdata->jig_online != -1)
+               ret = device_create_file(&jack_dev->dev,
+                               &dev_attr_jig_online);
+       if (pdata->host_online != -1)
+               ret = device_create_file(&jack_dev->dev,
+                               &dev_attr_host_online);
+
+       return 0;
+}
+
+static int __devinit jack_probe(struct platform_device *pdev)
+{
+       struct jack_platform_data *pdata = pdev->dev.platform_data;
+       struct jack_data *jack;
+
+       jack = kzalloc(sizeof(struct jack_data), GFP_KERNEL);
+       if (!jack) {
+               dev_err(&pdev->dev, "failed to allocate driver data\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, jack);
+       jack_dev = pdev;
+       jack->pdata = pdata;
+
+       jack_device_init(jack);
+
+       return 0;
+}
+
+static int __devexit jack_remove(struct platform_device *pdev)
+{
+       struct jack_data *jack = platform_get_drvdata(pdev);
+
+       if (jack->pdata->usb_online != -1)
+               device_remove_file(&jack_dev->dev, &dev_attr_usb_online);
+       if (jack->pdata->charger_online != -1)
+               device_remove_file(&jack_dev->dev, &dev_attr_charger_online);
+       if (jack->pdata->hdmi_online != -1)
+               device_remove_file(&jack_dev->dev, &dev_attr_hdmi_online);
+       if (jack->pdata->earjack_online != -1)
+               device_remove_file(&jack_dev->dev, &dev_attr_earjack_online);
+       if (jack->pdata->earkey_online != -1)
+               device_remove_file(&jack_dev->dev, &dev_attr_earkey_online);
+       if (jack->pdata->jig_online != -1)
+               device_remove_file(&jack_dev->dev, &dev_attr_jig_online);
+       if (jack->pdata->host_online != -1)
+               device_remove_file(&jack_dev->dev, &dev_attr_host_online);
+
+
+       kfree(jack);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver jack_driver = {
+       .probe          = jack_probe,
+       .remove         = __devexit_p(jack_remove),
+       .driver         = {
+               .name   = "jack",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init jack_init(void)
+{
+       return platform_driver_register(&jack_driver);
+}
+module_init(jack_init);
+
+static void __exit jack_exit(void)
+{
+       platform_driver_unregister(&jack_driver);
+}
+module_exit(jack_exit);
+
+MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
+MODULE_DESCRIPTION("Jack Monitoring Interface");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/jack.h b/include/linux/jack.h
new file mode 100644 (file)
index 0000000..9593cd7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (C) 2009 Samsung Electronics
+ *  Minkyu Kang <mk7.kang@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __JACK_H_
+#define __JACK_H_
+
+struct jack_platform_data {
+       int usb_online;
+       int charger_online;
+       int hdmi_online;
+       int earjack_online;
+       int earkey_online;
+       int ums_online;
+       int cdrom_online;
+       int jig_online;
+       int host_online;
+};
+
+int jack_get_data(const char *name);
+void jack_event_handler(const char *name, int value);
+
+#endif