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

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

Merge "sensors: add enable and poll_delay handle for kxtj9 sensor drver"

parents c6658c2c 4e1f8730
Loading
Loading
Loading
Loading
+78 −45
Original line number Diff line number Diff line
@@ -87,9 +87,13 @@ static struct sensors_classdev sensors_cdev = {
	.max_range = "19.6",
	.resolution = "0.01",
	.sensor_power = "0.2",
	.min_delay = 2000,
	.min_delay = 2000,	/* microsecond */
	.fifo_reserved_event_count = 0,
	.fifo_max_event_count = 0,
	.enabled = 0,
	.delay_msec = 200,	/* millisecond */
	.sensors_enable = NULL,
	.sensors_poll_delay = NULL,
};

static const struct {
@@ -121,6 +125,7 @@ struct kxtj9_data {
	bool	power_enabled;
	struct regulator *vdd;
	struct regulator *vio;
	struct sensors_classdev cdev;
};

static int kxtj9_i2c_read(struct kxtj9_data *tj9, u8 addr, u8 *data, int len)
@@ -489,6 +494,36 @@ static int kxtj9_setup_input_device(struct kxtj9_data *tj9)
	return 0;
}

static int kxtj9_enable_set(struct sensors_classdev *sensors_cdev,
					unsigned int enabled)
{
	struct kxtj9_data *tj9 = container_of(sensors_cdev,
					struct kxtj9_data, cdev);
	struct input_dev *input_dev = tj9->input_dev;

	mutex_lock(&input_dev->mutex);

	if (enabled == 0) {
		disable_irq(tj9->client->irq);
		kxtj9_disable(tj9);
		tj9->enable = false;
	} else if (enabled == 1) {
		if (!kxtj9_enable(tj9)) {
			enable_irq(tj9->client->irq);
			tj9->enable = true;
		}
	} else {
		dev_err(&tj9->client->dev,
			"Invalid value of input, input=%d\n", enabled);
		mutex_unlock(&input_dev->mutex);
		return -EINVAL;
	}

	mutex_unlock(&input_dev->mutex);

	return 0;
}

static ssize_t kxtj9_enable_show(struct device *dev,
				struct device_attribute *attr, char *buf)
{
@@ -504,31 +539,16 @@ static ssize_t kxtj9_enable_store(struct device *dev,
{
	struct i2c_client *client = to_i2c_client(dev);
	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
	struct input_dev *input_dev = tj9->input_dev;
	unsigned long data;
	int error;

	error = kstrtoul(buf, 10, &data);
	if (error)
	if (error < 0)
		return error;
	mutex_lock(&input_dev->mutex);

	if (data == 0) {
		disable_irq(client->irq);
		kxtj9_disable(tj9);
		tj9->enable = false;
	} else if (data == 1) {
		if (!kxtj9_enable(tj9)) {
			enable_irq(client->irq);
			tj9->enable = true;
		}
	} else {
		dev_err(&tj9->client->dev,
			"Invalid value of input, input=%ld\n", data);
	}

	mutex_unlock(&input_dev->mutex);

	error = kxtj9_enable_set(&tj9->cdev, data);
	if (error < 0)
		return error;
	return count;
}

@@ -545,6 +565,29 @@ static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR|S_IWGRP,
 * will be responsible for retrieving data from the input node at the desired
 * interval.
 */
static int kxtj9_poll_delay_set(struct sensors_classdev *sensors_cdev,
					unsigned int delay_msec)
{
	struct kxtj9_data *tj9 = container_of(sensors_cdev,
					struct kxtj9_data, cdev);
	struct input_dev *input_dev = tj9->input_dev;

	/* Lock the device to prevent races with open/close (and itself) */
	mutex_lock(&input_dev->mutex);

	if (tj9->enable)
		disable_irq(tj9->client->irq);

	tj9->last_poll_interval = max(delay_msec, tj9->pdata.min_interval);

	if (tj9->enable) {
		kxtj9_update_odr(tj9, tj9->last_poll_interval);
		enable_irq(tj9->client->irq);
	}
	mutex_unlock(&input_dev->mutex);

	return 0;
}

/* Returns currently selected poll interval (in ms) */
static ssize_t kxtj9_get_poll_delay(struct device *dev,
@@ -563,7 +606,6 @@ static ssize_t kxtj9_set_poll_delay(struct device *dev,
{
	struct i2c_client *client = to_i2c_client(dev);
	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
	struct input_dev *input_dev = tj9->input_dev;
	unsigned int interval;
	int error;

@@ -571,24 +613,9 @@ static ssize_t kxtj9_set_poll_delay(struct device *dev,
	if (error < 0)
		return error;

	/* Lock the device to prevent races with open/close (and itself) */
	mutex_lock(&input_dev->mutex);

	if (tj9->enable)
		disable_irq(client->irq);

	/*
	 * Set current interval to the greater of the minimum interval or
	 * the requested interval
	 */
	tj9->last_poll_interval = max(interval, tj9->pdata.min_interval);

	if (tj9->enable) {
		kxtj9_update_odr(tj9, tj9->last_poll_interval);
		enable_irq(client->irq);
	}
	mutex_unlock(&input_dev->mutex);

	error = kxtj9_poll_delay_set(&tj9->cdev, interval);
	if (error < 0)
		return error;
	return count;
}

@@ -605,7 +632,6 @@ static struct attribute_group kxtj9_attribute_group = {
	.attrs = kxtj9_attributes
};


#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
static void kxtj9_poll(struct input_polled_dev *dev)
{
@@ -861,6 +887,18 @@ static int kxtj9_probe(struct i2c_client *client,
	tj9->ctrl_reg1 = tj9->pdata.res_ctl | tj9->pdata.g_range;
	tj9->last_poll_interval = tj9->pdata.init_interval;

	tj9->cdev = sensors_cdev;
	/* The min_delay is used by userspace and the unit is microsecond. */
	tj9->cdev.min_delay = tj9->pdata.min_interval * 1000;
	tj9->cdev.delay_msec = tj9->pdata.init_interval;
	tj9->cdev.sensors_enable = kxtj9_enable_set;
	tj9->cdev.sensors_poll_delay = kxtj9_poll_delay_set;
	err = sensors_classdev_register(&client->dev, &tj9->cdev);
	if (err) {
		dev_err(&client->dev, "class device create failed: %d\n", err);
		goto err_power_off;
	}

	if (client->irq) {
		/* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */
		tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL;
@@ -892,11 +930,6 @@ static int kxtj9_probe(struct i2c_client *client,
			goto err_power_off;
	}

	err = sensors_classdev_register(&client->dev, &sensors_cdev);
	if (err) {
		dev_err(&client->dev, "class device create failed: %d\n", err);
		goto err_free_irq;
	}

	dev_dbg(&client->dev, "%s: kxtj9_probe OK.\n", __func__);
	kxtj9_device_power_off(tj9);