mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
cap1106: implement controling by state change of RMNET interface
1. If kconfig CAP_SENSOR_RMNET_CTL is checked, cap1106 will be disabled if and only if all of the rmnet_usb network interfaces turn off. 2. cap1106 is disabled by default now. Bug: 9148999 Change-Id: I9e9fa65265e5972f31a607487cb86942bb6384dc Signed-off-by: Raphanus Lo <raphanus_lo@asus.com>
This commit is contained in:
parent
e69941931c
commit
ad49c7f9fe
4 changed files with 125 additions and 1 deletions
|
@ -306,6 +306,7 @@ CONFIG_BATTERY_ASUS_BQ27541=y
|
|||
CONFIG_SENSORS_PM8XXX_ADC=y
|
||||
CONFIG_SENSORS_EPM_ADC=y
|
||||
CONFIG_SENSORS_CAP1106=y
|
||||
CONFIG_CAP_SENSOR_RMNET_CTL=y
|
||||
CONFIG_THERMAL=y
|
||||
CONFIG_THERMAL_TSENS8960=y
|
||||
CONFIG_THERMAL_PM8XXX=y
|
||||
|
|
|
@ -1435,6 +1435,13 @@ config SENSORS_CAP1106
|
|||
To compile this driver as a module, choose m here. The module will
|
||||
be called cap1106.
|
||||
|
||||
config CAP_SENSOR_RMNET_CTL
|
||||
bool "RMNET-controled SMSC CAP1106"
|
||||
depends on MSM_RMNET_USB && SENSORS_CAP1106
|
||||
help
|
||||
Enable/disable SMSC 1106 cap sensor by state change of RMNET-related
|
||||
network interface.
|
||||
|
||||
if ACPI
|
||||
|
||||
comment "ACPI drivers"
|
||||
|
|
|
@ -20,10 +20,15 @@
|
|||
#include <linux/switch.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <linux/i2c/cap1106.h>
|
||||
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
extern bool rmnet_netdev_cmp(struct net_device *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Debug Utility
|
||||
*/
|
||||
|
@ -54,6 +59,9 @@ struct cap1106_data {
|
|||
int det_gpio;
|
||||
char *det_gpio_name;
|
||||
const unsigned char *init_table;
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
struct notifier_block netdev_obs;
|
||||
#endif
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(cap_mtx);
|
||||
|
@ -63,7 +71,11 @@ static int is_wood_sensitivity = 0;
|
|||
static int ac2 = 0; // Accumulated Count Ch2
|
||||
static int ac6 = 0; // Accumulated Count Ch6
|
||||
static int ac_limit = 10;
|
||||
static int force_enable = 1;
|
||||
static int force_enable = 0;
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
static int rmnet_ctl = 1;
|
||||
static int rmnet_if_up = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function Declaration
|
||||
|
@ -82,6 +94,9 @@ static void cap1106_work_function(struct work_struct *work);
|
|||
static int cap1106_init_sensor(struct i2c_client *client);
|
||||
static int cap1106_config_irq(struct i2c_client *client);
|
||||
static void cap1106_enable_sensor(struct i2c_client *client, int enable);
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
static void rmnet_state_changed(struct i2c_client *client);
|
||||
#endif
|
||||
static ssize_t show_attrs_handler(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf);
|
||||
static ssize_t store_attrs_handler(struct device *dev,
|
||||
|
@ -125,6 +140,9 @@ DEVICE_ATTR(sensor_onoff, 0644, show_attrs_handler, store_attrs_handler);
|
|||
DEVICE_ATTR(sensor_recal, 0644, show_attrs_handler, store_attrs_handler);
|
||||
DEVICE_ATTR(sensor_app2mdm_sar, 0644, NULL, store_attrs_handler);
|
||||
DEVICE_ATTR(sensor_main, 0644, show_attrs_handler, NULL);
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
DEVICE_ATTR(sensor_rmnetctl, 0644, show_attrs_handler, store_attrs_handler);
|
||||
#endif
|
||||
|
||||
static struct attribute *cap1106_attr_deb[] = {
|
||||
&dev_attr_obj_detect.attr, // 1
|
||||
|
@ -141,6 +159,9 @@ static struct attribute *cap1106_attr_deb[] = {
|
|||
&dev_attr_sensor_recal.attr, // 12
|
||||
&dev_attr_sensor_app2mdm_sar.attr, // 13
|
||||
&dev_attr_sensor_main.attr, // 14
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
&dev_attr_sensor_rmnetctl.attr, // 15
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -186,6 +207,10 @@ static ssize_t show_attrs_handler(struct device *dev,
|
|||
cap1106_read_reg(client, 0x26) == 0x0 ? "OK\n" : "FAIL\n");
|
||||
} else if (!strcmp(attr_name, dev_attr_sensor_main.attr.name)) {
|
||||
ret = sprintf(buf, "%02X\n", cap1106_read_reg(client, 0x00));
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
} else if (!strcmp(attr_name, dev_attr_sensor_rmnetctl.attr.name)) {
|
||||
ret = sprintf(buf, "%d\n", rmnet_ctl);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if (!strcmp(attr_name, dev_attr_sensor_main.attr.name)) {
|
||||
|
@ -234,19 +259,35 @@ static ssize_t store_attrs_handler(struct device *dev,
|
|||
} else if (!strcmp(attr_name, dev_attr_sensor_onoff.attr.name)) {
|
||||
if (value == 0) {
|
||||
force_enable = 0;
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
rmnet_ctl = 0;
|
||||
#endif
|
||||
cap1106_enable_sensor(client, 0);
|
||||
}
|
||||
} else if (!strcmp(attr_name, dev_attr_sensor_recal.attr.name)) {
|
||||
cap1106_write_reg(client, 0x26, 0x22);
|
||||
} else if (!strcmp(attr_name, dev_attr_sensor_app2mdm_sar.attr.name)) {
|
||||
gpio_set_value(data->sar_gpio, value);
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
} else if (!strcmp(attr_name, dev_attr_sensor_rmnetctl.attr.name)) {
|
||||
rmnet_ctl = value;
|
||||
rmnet_state_changed(client);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if (!strcmp(attr_name, dev_attr_sensor_onoff.attr.name)) {
|
||||
if (value == 1) {
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
rmnet_ctl = 0;
|
||||
#endif
|
||||
force_enable = 1;
|
||||
cap1106_enable_sensor(client, 1);
|
||||
}
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
} else if (!strcmp(attr_name, dev_attr_sensor_rmnetctl.attr.name)) {
|
||||
rmnet_ctl = value;
|
||||
rmnet_state_changed(client);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
mutex_unlock(&cap_mtx);
|
||||
|
@ -270,6 +311,47 @@ static ssize_t print_cap_state(struct switch_dev *sdev, char *buf)
|
|||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
static int netdev_changed_event(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)ptr;
|
||||
struct cap1106_data *data = container_of(this, struct cap1106_data, netdev_obs);
|
||||
int before_if_up = rmnet_if_up;
|
||||
|
||||
CAP_DEBUG("+\n");
|
||||
if (!rmnet_netdev_cmp(dev))
|
||||
goto done;
|
||||
|
||||
mutex_lock(&cap_mtx);
|
||||
switch (event) {
|
||||
case NETDEV_UP:
|
||||
++rmnet_if_up;
|
||||
CAP_DEBUG("netdev %s is up, rmnet_if_up=%d\n", dev->name, rmnet_if_up);
|
||||
break;
|
||||
|
||||
case NETDEV_DOWN:
|
||||
--rmnet_if_up;
|
||||
CAP_DEBUG("netdev %s is down, rmnet_if_up=%d\n", dev->name, rmnet_if_up);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (rmnet_if_up < 0) {
|
||||
CAP_ERROR("rmnet_if_up is negative! Unbalanced netdev state change?\n");
|
||||
rmnet_if_up = 0;
|
||||
}
|
||||
if (before_if_up != rmnet_if_up)
|
||||
rmnet_state_changed(data->client);
|
||||
mutex_unlock(&cap_mtx);
|
||||
|
||||
done:
|
||||
CAP_DEBUG("-\n");
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
#endif
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void cap1106_enable_sensor(struct i2c_client *client, int enable)
|
||||
|
@ -302,6 +384,16 @@ static void cap1106_enable_sensor(struct i2c_client *client, int enable)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
static void rmnet_state_changed(struct i2c_client *client)
|
||||
{
|
||||
if (force_enable || (rmnet_ctl && rmnet_if_up > 0))
|
||||
cap1106_enable_sensor(client, 1);
|
||||
else
|
||||
cap1106_enable_sensor(client, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static s32 cap1106_read_reg(struct i2c_client *client, u8 command)
|
||||
{
|
||||
return i2c_smbus_read_byte_data(client, command);
|
||||
|
@ -579,6 +671,11 @@ static int __devinit cap1106_probe(struct i2c_client *client,
|
|||
queue_delayed_work(data->cap_wq, &data->checking_work,
|
||||
msecs_to_jiffies(1000));
|
||||
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
data->netdev_obs.notifier_call = netdev_changed_event;
|
||||
register_netdevice_notifier(&data->netdev_obs);
|
||||
#endif
|
||||
|
||||
pivate_data = data;
|
||||
|
||||
CAP_INFO("OK\n");
|
||||
|
@ -601,6 +698,9 @@ static int __devexit cap1106_remove(struct i2c_client *client)
|
|||
{
|
||||
struct cap1106_data *data = i2c_get_clientdata(client);
|
||||
CAP_DEBUG("+\n");
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
unregister_netdevice_notifier(&data->netdev_obs);
|
||||
#endif
|
||||
switch_dev_unregister(&cap_sdev);
|
||||
sysfs_remove_group(&client->dev.kobj, &data->attrs);
|
||||
free_irq(client->irq, client);
|
||||
|
|
|
@ -95,6 +95,22 @@ module_param(no_rmnet_insts_per_dev, uint, S_IRUGO | S_IWUSR);
|
|||
static int rmnet_data_start(void);
|
||||
static bool rmnet_data_init;
|
||||
|
||||
#if defined(CONFIG_CAP_SENSOR_RMNET_CTL)
|
||||
bool rmnet_netdev_cmp(struct net_device *dev)
|
||||
{
|
||||
int i;
|
||||
const char *rmnet_name;
|
||||
|
||||
for (i = 0; i < 2; ++i) {
|
||||
rmnet_name = rmnet_names[i];
|
||||
if (0 == strncmp(dev->name, rmnet_name, strlen(rmnet_name)-2))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(rmnet_netdev_cmp);
|
||||
#endif
|
||||
|
||||
static int rmnet_init(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
Loading…
Reference in a new issue