mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-09-21 03:43:03 +00:00
fc9499e55a
* Package version: T713XXU2BQCO Change-Id: I293d9e7f2df458c512d59b7a06f8ca6add610c99
154 lines
3.9 KiB
C
154 lines
3.9 KiB
C
/*
|
|
* Copyright (C) 2013 Samsung Electronics Co, Ltd.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <linux/err.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/switch.h>
|
|
#include <linux/extcon.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/power_supply.h>
|
|
#include <linux/regulator/machine.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/pm_runtime.h>
|
|
|
|
struct muic_cable {
|
|
struct work_struct work;
|
|
struct delayed_work cable_init;
|
|
struct notifier_block nb;
|
|
struct extcon_specific_cable_nb extcon_nb;
|
|
struct extcon_dev *edev;
|
|
enum extcon_cable_name cable_type;
|
|
int cable_state;
|
|
};
|
|
|
|
static struct switch_dev switch_dock = {
|
|
.name = "dock",
|
|
};
|
|
|
|
extern struct class *sec_class;
|
|
|
|
struct device *switch_dev;
|
|
EXPORT_SYMBOL(switch_dev);
|
|
static struct muic_cable support_cable_list[] = {
|
|
{ .cable_type = EXTCON_DESKDOCK, },
|
|
{ .cable_type = EXTCON_CARDOCK, },
|
|
{ .cable_type = EXTCON_AUDIODOCK, },
|
|
{ .cable_type = EXTCON_SMARTDOCK, },
|
|
#if defined(CONFIG_MUIC_SUPPORT_HMT_DETECTION)
|
|
{ .cable_type = EXTCON_HMT, },
|
|
#endif
|
|
};
|
|
|
|
static void muic_cable_event_worker(struct work_struct *work)
|
|
{
|
|
struct muic_cable *cable =
|
|
container_of(work, struct muic_cable, work);
|
|
|
|
pr_info("%s: '%s' is %s\n", __func__,
|
|
extcon_cable_name[cable->cable_type],
|
|
cable->cable_state ? "attached" : "detached");
|
|
|
|
switch (cable->cable_type) {
|
|
case EXTCON_DESKDOCK:
|
|
switch_set_state(&switch_dock, cable->cable_state ? 1 : 0);
|
|
break;
|
|
case EXTCON_CARDOCK:
|
|
switch_set_state(&switch_dock, cable->cable_state ? 2 : 0);
|
|
break;
|
|
case EXTCON_AUDIODOCK:
|
|
switch_set_state(&switch_dock, cable->cable_state ? 7 : 0);
|
|
break;
|
|
case EXTCON_SMARTDOCK:
|
|
switch_set_state(&switch_dock, cable->cable_state ? 8 : 0);
|
|
break;
|
|
#if defined(CONFIG_MUIC_SUPPORT_HMT_DETECTION)
|
|
case EXTCON_HMT:
|
|
switch_set_state(&switch_dock, cable->cable_state ? 11 : 0);
|
|
break;
|
|
#endif
|
|
default:
|
|
pr_err("%s: invalid cable value (%d, %d)\n", __func__,
|
|
cable->cable_type, cable->cable_state);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static int muic_cable_notifier(struct notifier_block *nb,
|
|
unsigned long stat, void *ptr)
|
|
{
|
|
struct muic_cable *cable =
|
|
container_of(nb, struct muic_cable, nb);
|
|
|
|
cable->cable_state = stat;
|
|
schedule_work(&cable->work);
|
|
|
|
return NOTIFY_DONE;
|
|
}
|
|
|
|
|
|
static int muic_init_cable_notify(void)
|
|
{
|
|
int i, ret;
|
|
struct muic_cable *cable = NULL;
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(support_cable_list); i++) {
|
|
cable = &support_cable_list[i];
|
|
INIT_WORK(&cable->work, muic_cable_event_worker);
|
|
cable->nb.notifier_call = muic_cable_notifier;
|
|
|
|
ret = extcon_register_interest(&cable->extcon_nb,
|
|
EXTCON_DEV_NAME,
|
|
extcon_cable_name[cable->cable_type],
|
|
&cable->nb);
|
|
if (ret)
|
|
pr_err("%s: fail to register extcon notifier(%s, %d)\n",
|
|
__func__, extcon_cable_name[cable->cable_type],
|
|
ret);
|
|
|
|
cable->edev = cable->extcon_nb.edev;
|
|
if (!cable->edev)
|
|
pr_err("%s: fail to get extcon device\n", __func__);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static __init int muic_init_switch(void)
|
|
{
|
|
int ret;
|
|
|
|
pr_info("register extcon notifier for JIG and docks\n");
|
|
switch_dev = device_create(sec_class, NULL, 0, NULL, "switch");
|
|
if (IS_ERR(switch_dev)) {
|
|
pr_err("(%s): failed to created device (switch_dev)!\n",
|
|
__func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
ret = switch_dev_register(&switch_dock);
|
|
if (ret < 0) {
|
|
pr_err("Failed to register dock switch. %d\n",
|
|
ret);
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
device_initcall(muic_init_switch);
|
|
late_initcall(muic_init_cable_notify);
|