From 2b45454c4d5f4b3467eceb10e41bb26fccbbcb94 Mon Sep 17 00:00:00 2001 From: "vivian, zhang" Date: Mon, 25 Jun 2012 12:09:17 +0800 Subject: [PATCH] Sound: import Jack Monitoring Interface from samsung 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 Signed-off-by: Markus Lehtonen --- arch/x86/configs/tizen_bb_defconfig | 1 + .../intel-mid/device_libs/platform_msic_audio.c | 36 ++++ drivers/misc/Kconfig | 6 + drivers/misc/Makefile | 1 + drivers/misc/jack.c | 209 +++++++++++++++++++++ include/linux/jack.h | 28 +++ sound/soc/mid-x86/mfld_machine.c | 46 +++++ 7 files changed, 327 insertions(+) create mode 100644 drivers/misc/jack.c create mode 100644 include/linux/jack.h diff --git a/arch/x86/configs/tizen_bb_defconfig b/arch/x86/configs/tizen_bb_defconfig index eac2ed2..f65fd11 100644 --- a/arch/x86/configs/tizen_bb_defconfig +++ b/arch/x86/configs/tizen_bb_defconfig @@ -2210,6 +2210,7 @@ CONFIG_SND_SST_PLATFORM=y # CONFIG_SND_MFLD_COMMS_MACHINE is not set CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_JACK_MON=y CONFIG_SND_SOC_SN95031=y # CONFIG_SOUND_PRIME is not set CONFIG_HID_SUPPORT=y diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c index a7319a3..b1f0006 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "platform_ipc.h" #include "platform_msic_audio.h" @@ -53,6 +54,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 ret; @@ -106,6 +120,28 @@ void *msic_audio_platform_data(void *info) 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 + if (strncmp(entry->name, "msic_audio", 16) == 0) handle_ipc_irq_res(entry->irq, ipc_msic_audio_res); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index dd00161..40612b3 100755 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -563,6 +563,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 diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 571ffd1..96abca6 100755 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -45,6 +45,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_AB8500_PWM) += ab8500-pwm.o diff --git a/drivers/misc/jack.c b/drivers/misc/jack.c new file mode 100644 index 0000000..08a56365 --- /dev/null +++ b/drivers/misc/jack.c @@ -0,0 +1,209 @@ +/* + * Jack Monitoring Interface + * + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * 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 +#include +#include +#include +#include +#include + +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 "); +MODULE_DESCRIPTION("Jack Monitoring Interface"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/jack.h b/include/linux/jack.h new file mode 100644 index 0000000..9593cd7 --- /dev/null +++ b/include/linux/jack.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * 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 diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 05a7cd3..ada89a0 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,12 @@ #define MFLD_JACK_DEBOUNCE_TIME 250 /* mS */ #define MFLD_GPIO_HEADSET_DET_PIN 77 +#ifdef CONFIG_JACK_MON +#define JACK_UEVENT_NAME "earjack" +#define JACK_KEY_UEVENT_NAME "earkey" +#define SND_JACK_NONE 0x00 +#endif + /* jack detection voltage zones */ static struct snd_soc_jack_zone mfld_zones[] = { {MFLD_MV_START, MFLD_MV_AM_HS, SND_JACK_HEADPHONE}, @@ -71,6 +78,42 @@ static void mfld_jack_disable_mic_bias(struct snd_soc_codec *codec) mutex_unlock(&codec->mutex); } +static void mfld_jack_status_set(int jack) +{ + if (jack < SND_JACK_BTN_0) { + /* JACK */ + switch (jack) { + case SND_JACK_NONE: + pr_debug("Jack is detached\n"); + break; + case SND_JACK_HEADPHONE: + pr_debug("Jack is Earjack3\n"); + break; + case SND_JACK_HEADSET: + pr_debug("Jack is Earjack4\n"); + break; + default: + pr_debug("Jack is unknown\n"); + return; + } + jack_event_handler(JACK_UEVENT_NAME, jack); + } else { + /* JACK Key */ + switch (jack) { + case SND_JACK_BTN_0: + pr_debug("EAR_SEND_END is pressed\n"); + break; + case SND_JACK_BTN_1: + case SND_JACK_BTN_2: + default: + pr_debug("The key is unknown\n"); + return; + } + jack_event_handler(JACK_KEY_UEVENT_NAME, jack); + } +} + + static int mfld_get_headset_state(struct snd_soc_jack *jack) { int micbias, jack_type, hs_gpio = 1; @@ -193,6 +236,9 @@ void mfld_jack_wq(struct work_struct *work) pr_err("Invalid intr_id:0x%x\n", intr_id); return; } +#ifdef CONFIG_JACK_MON + mfld_jack_status_set(status); +#endif mfld_jack_report(jack, status); } -- 2.7.4