Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72cee73d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "input: sensors: use work queue for mma8x5x data polling"

parents f018ed1f ca23a3a8
Loading
Loading
Loading
Loading
+74 −96
Original line number Diff line number Diff line
@@ -26,8 +26,8 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input-polldev.h>
#include <linux/sensors.h>
#include <linux/input.h>
#include <linux/regulator/consumer.h>
#include <linux/of_gpio.h>
#include <linux/irq.h>
@@ -44,8 +44,6 @@
#define POLL_INTERVAL_MAX	10000
#define POLL_INTERVAL		100 /* msecs */

/* if sensor is standby ,set POLL_STOP_TIME to slow down the poll */
#define POLL_STOP_TIME		10000
#define INPUT_FUZZ			32
#define INPUT_FLAT			32
#define INPUT_DATA_DIVIDER	16
@@ -189,7 +187,7 @@ struct mma8x5x_data_axis {
};
struct mma8x5x_data {
	struct i2c_client *client;
	struct input_polled_dev *poll_dev;
	struct delayed_work dwork;
	struct input_dev *idev;
	struct mutex data_lock;
	struct sensors_classdev cdev;
@@ -229,7 +227,6 @@ static int mma8x5x_position_setting[8][3][3] = {
	{{ 0,  1,  0}, { 1,  0,	0}, {0, 0,  -1} },
	{{ 1,  0,  0}, { 0, -1,	0}, {0, 0,  -1} },
};
static struct mma8x5x_data *drv_data;
static int mma8x5x_config_regulator(struct i2c_client *client, bool on)
{
	int rc = 0, i;
@@ -487,32 +484,27 @@ static int mma8x5x_read_data(struct i2c_client *client,

static void mma8x5x_report_data(struct mma8x5x_data *pdata)
{
	struct input_polled_dev *poll_dev = pdata->poll_dev;
	struct mma8x5x_data_axis data;

	mutex_lock(&pdata->data_lock);
	if ((pdata->active & MMA_STATE_MASK) == MMA_STANDBY) {
		poll_dev->poll_interval = POLL_STOP_TIME;
		/* if standby ,set as 10s to slow the poll. */
		goto out;
	} else {
		if (poll_dev->poll_interval == POLL_STOP_TIME)
			poll_dev->poll_interval = pdata->poll_delay;
	}
	if (mma8x5x_read_data(pdata->client, &data) != 0)
		goto out;
	mma8x5x_data_convert(pdata, &data);
	input_report_abs(poll_dev->input, ABS_X, data.x);
	input_report_abs(poll_dev->input, ABS_Y, data.y);
	input_report_abs(poll_dev->input, ABS_Z, data.z);
	input_sync(poll_dev->input);
	input_report_abs(pdata->idev, ABS_X, data.x);
	input_report_abs(pdata->idev, ABS_Y, data.y);
	input_report_abs(pdata->idev, ABS_Z, data.z);
	input_sync(pdata->idev);
out:
	mutex_unlock(&pdata->data_lock);
}

static void mma8x5x_dev_poll(struct input_polled_dev *dev)
static void mma8x5x_dev_poll(struct work_struct *work)
{
	struct mma8x5x_data *pdata = (struct mma8x5x_data *)dev->private;
	struct mma8x5x_data *pdata = container_of((struct delayed_work *)work,
				struct mma8x5x_data, dwork);
	mma8x5x_report_data(pdata);
	schedule_delayed_work(&pdata->dwork,
				msecs_to_jiffies(pdata->poll_delay));
}

static irqreturn_t mma8x5x_interrupt(int vec, void *data)
@@ -577,12 +569,18 @@ static int mma8x5x_enable_set(struct sensors_classdev *sensors_cdev,
				dev_err(&client->dev, "change device state failed!");
				goto err_failed;
			}

			schedule_delayed_work(&pdata->dwork,
				msecs_to_jiffies(pdata->poll_delay));

			pdata->active = MMA_ACTIVED;
			dev_dbg(&client->dev, "%s:mma enable setting active.\n",
					__func__);
		}
	} else if (enable == 0) {
		if (pdata->active == MMA_ACTIVED) {
			cancel_delayed_work_sync(&pdata->dwork);

			val = i2c_smbus_read_byte_data(client,
					MMA8X5X_CTRL_REG1);
			if (val < 0) {
@@ -616,7 +614,7 @@ err_failed:
static ssize_t mma8x5x_enable_show(struct device *dev,
				   struct device_attribute *attr, char *buf)
{
	struct mma8x5x_data *pdata = drv_data;
	struct mma8x5x_data *pdata = dev_get_drvdata(dev);
	struct i2c_client *client;
	u8 val;
	int enable;
@@ -641,7 +639,7 @@ static ssize_t mma8x5x_enable_store(struct device *dev,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	struct mma8x5x_data *pdata = drv_data;
	struct mma8x5x_data *pdata = dev_get_drvdata(dev);
	struct i2c_client *client;
	int ret;
	unsigned long enable;
@@ -663,7 +661,7 @@ static ssize_t mma8x5x_enable_store(struct device *dev,
static ssize_t mma8x5x_position_show(struct device *dev,
				   struct device_attribute *attr, char *buf)
{
	struct mma8x5x_data *pdata = drv_data;
	struct mma8x5x_data *pdata = dev_get_drvdata(dev);
	int position = 0;

	if (!pdata) {
@@ -680,7 +678,7 @@ static ssize_t mma8x5x_position_store(struct device *dev,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	struct mma8x5x_data *pdata = drv_data;
	struct mma8x5x_data *pdata = dev_get_drvdata(dev);
	int position;
	int ret;

@@ -714,7 +712,6 @@ static int mma8x5x_poll_delay_set(struct sensors_classdev *sensors_cdev,
	} else {
		mutex_lock(&pdata->data_lock);
		pdata->poll_delay = delay_ms;
		pdata->poll_dev->poll_interval = pdata->poll_delay;
		mutex_unlock(&pdata->data_lock);
	}

@@ -724,7 +721,7 @@ static int mma8x5x_poll_delay_set(struct sensors_classdev *sensors_cdev,
static ssize_t mma8x5x_poll_delay_show(struct device *dev,
				   struct device_attribute *attr, char *buf)
{
	struct mma8x5x_data *pdata = drv_data;
	struct mma8x5x_data *pdata = dev_get_drvdata(dev);

	if (!pdata) {
		dev_err(dev, "Invalid driver private data!");
@@ -738,7 +735,7 @@ static ssize_t mma8x5x_poll_delay_store(struct device *dev,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	struct mma8x5x_data *pdata = drv_data;
	struct mma8x5x_data *pdata = dev_get_drvdata(dev);
	int delay;
	int ret;

@@ -825,7 +822,6 @@ static int mma8x5x_probe(struct i2c_client *client,
	struct input_dev *idev;
	struct mma8x5x_data *pdata;
	struct i2c_adapter *adapter;
	struct input_polled_dev *poll_dev;
	adapter = to_i2c_adapter(client->dev.parent);
	/* power on the device */
	result = mma8x5x_config_regulator(client, 1);
@@ -836,7 +832,7 @@ static int mma8x5x_probe(struct i2c_client *client,
					 I2C_FUNC_SMBUS_BYTE |
					 I2C_FUNC_SMBUS_BYTE_DATA);
	if (!result)
		goto err_out;
		goto err_check_id;

	chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);

@@ -846,14 +842,14 @@ static int mma8x5x_probe(struct i2c_client *client,
			chip_id, MMA8451_ID, MMA8452_ID, MMA8453_ID,
			MMA8652_ID, MMA8653_ID);
		result = -EINVAL;
		goto err_out;
		goto err_check_id;
	}
	/* set the private data */
	pdata = kzalloc(sizeof(struct mma8x5x_data), GFP_KERNEL);
	if (!pdata) {
		result = -ENOMEM;
		dev_err(&client->dev, "alloc data memory error!\n");
		goto err_out;
		goto err_check_id;
	}

	if (client->dev.of_node) {
@@ -867,12 +863,10 @@ static int mma8x5x_probe(struct i2c_client *client,
	}

	/* Initialize the MMA8X5X chip */
	drv_data = pdata;
	pdata->client = client;
	pdata->chip_id = chip_id;
	pdata->mode = MODE_2G;
	pdata->poll_delay = POLL_STOP_TIME;
	pdata->poll_dev = NULL;
	pdata->poll_delay = POLL_INTERVAL;

	mutex_init(&pdata->data_lock);
	i2c_set_clientdata(client, pdata);
@@ -894,29 +888,9 @@ static int mma8x5x_probe(struct i2c_client *client,
			if (result) {
				dev_err(&client->dev,
					"set_direction for irq gpio failed\n");
				goto err_set_direction;
			}
		}
		idev = input_allocate_device();
		if (!idev) {
			result = -ENOMEM;
			dev_err(&client->dev, "alloc input device failed!\n");
			goto err_alloc_poll_device;
				goto err_set_gpio_direction;
			}
		input_set_drvdata(idev, pdata);
		idev->name = ACCEL_INPUT_DEV_NAME;
		idev->uniq = mma8x5x_id2name(pdata->chip_id);
		idev->id.bustype = BUS_I2C;
		idev->evbit[0] = BIT_MASK(EV_ABS);
		input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
		input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
		input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
		result = input_register_device(idev);
		if (result) {
			dev_err(&client->dev, "register input device failed!\n");
			goto err_register_device;
		}
		pdata->idev = idev;
		device_init_wakeup(&client->dev, true);
		enable_irq_wake(client->irq);
		result = request_threaded_irq(client->irq, NULL,
@@ -930,21 +904,15 @@ static int mma8x5x_probe(struct i2c_client *client,
		}
		mma8x5x_device_int_init(client);
	} else {
		/* create the input poll device */
		poll_dev = input_allocate_polled_device();
		if (!poll_dev) {
		INIT_DELAYED_WORK(&pdata->dwork, mma8x5x_dev_poll);
	}
	idev = input_allocate_device();
	if (!idev) {
		result = -ENOMEM;
			dev_err(&client->dev, "alloc poll device failed!\n");
		dev_err(&client->dev, "alloc input device failed!\n");
		goto err_alloc_poll_device;
	}
		pdata->poll_dev = poll_dev;
		pdata->idev = NULL;
		poll_dev->poll = mma8x5x_dev_poll;
		poll_dev->poll_interval = POLL_STOP_TIME;
		poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
		poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
		poll_dev->private = pdata;
		idev = poll_dev->input;
	input_set_drvdata(idev, pdata);
	idev->name = ACCEL_INPUT_DEV_NAME;
	idev->uniq = mma8x5x_id2name(pdata->chip_id);
	idev->id.bustype = BUS_I2C;
@@ -952,12 +920,13 @@ static int mma8x5x_probe(struct i2c_client *client,
	input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
	input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
	input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
		result = input_register_polled_device(pdata->poll_dev);
	result = input_register_device(idev);
	if (result) {
			dev_err(&client->dev, "register poll device failed!\n");
		dev_err(&client->dev, "register input device failed!\n");
		goto err_register_device;
	}
	}
	pdata->idev = idev;

	result = sysfs_create_group(&idev->dev.kobj, &mma8x5x_attr_group);
	if (result) {
		dev_err(&client->dev, "create device file failed!\n");
@@ -983,23 +952,20 @@ static int mma8x5x_probe(struct i2c_client *client,
err_create_class_sysfs:
	sysfs_remove_group(&idev->dev.kobj, &mma8x5x_attr_group);
err_create_sysfs:
	input_unregister_polled_device(pdata->poll_dev);
err_register_irq:
	if (pdata->use_int)
		device_init_wakeup(&client->dev, false);
	input_unregister_device(idev);
err_register_device:
	if (pdata->use_int)
	input_free_device(idev);
	else
		input_free_polled_device(pdata->poll_dev);
err_alloc_poll_device:
err_set_direction:
err_register_irq:
	if (pdata->use_int)
		device_init_wakeup(&client->dev, false);
err_set_gpio_direction:
	if (gpio_is_valid(pdata->int_pin) && pdata->use_int)
		gpio_free(pdata->int_pin);
err_request_gpio:
err_parse_dt:
	kfree(pdata);
err_out:
err_check_id:
	mma8x5x_config_regulator(client, 0);
err_power_on:
	return result;
@@ -1007,14 +973,22 @@ err_power_on:
static int mma8x5x_remove(struct i2c_client *client)
{
	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
	struct input_polled_dev *poll_dev;
	struct input_dev *idev;

	mma8x5x_device_stop(client);
	if (pdata) {
		poll_dev = pdata->poll_dev;
		input_unregister_polled_device(poll_dev);
		input_free_polled_device(poll_dev);
		idev = pdata->idev;
		sysfs_remove_group(&idev->dev.kobj, &mma8x5x_attr_group);
		if (pdata->use_int) {
			device_init_wakeup(&client->dev, false);
			if (gpio_is_valid(pdata->int_pin))
				gpio_free(pdata->int_pin);
		}
		input_unregister_device(idev);
		input_free_device(idev);
		kfree(pdata);
	}
	mma8x5x_config_regulator(client, 0);
	return 0;
}

@@ -1026,8 +1000,10 @@ static int mma8x5x_suspend(struct device *dev)

	if (pdata->use_int && pdata->active == MMA_ACTIVED)
		return 0;
	if (pdata->active == MMA_ACTIVED)
	if (pdata->active == MMA_ACTIVED) {
		mma8x5x_device_stop(client);
		cancel_delayed_work_sync(&pdata->dwork);
	}
	if (pdata->active & MMA_SHUTTEDDOWN)
		return 0;
	if (!mma8x5x_config_regulator(client, 0))
@@ -1058,6 +1034,8 @@ static int mma8x5x_resume(struct device *dev)
	if (pdata->active == MMA_ACTIVED) {
		val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
		i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val|0x01);
		schedule_delayed_work(&pdata->dwork,
				msecs_to_jiffies(pdata->poll_delay));
	}

	return 0;